<commit_before>'use strict';

const Backendless = require('backendless');

const isPersistable = value =>
  value instanceof PersistenceItem ||
  value instanceof Backendless.GeoPoint;

const isArrayOfPersistable = value => {
  if (!Array.isArray(value) || value.length === 0) {
    return false;
  }

  for (let i = 0; i < value.length; i++) {
    if (!isPersistable(value[i])) {
      return false;
    }
  }

  return true;
};

const trimRelations = item => {
  const result = {};

  Object.keys(item).forEach(key => {
    const value = item[key];

    if (!isPersistable(value) && !isArrayOfPersistable(value)) {
      result[key] = value;
    }
  });

  return result;
};

const SYSTEM_PROPS = ['objectId', 'ownerId', 'objectId', 'created', 'updated', '___class', '___jsonclass'];

const queryToBuilder = query => {
  if (query instanceof Backendless.DataQueryBuilder) {
    return query;
  }

  if (typeof query === 'string') {
    return Backendless.DataQueryBuilder.create().setWhereClause(query);
  }

  const result = Backendless.DataQueryBuilder.create();

  if (query) {
    const { condition, properties, options } = query;

    condition && (result.setWhereClause(condition));
    properties && (result.setProperties(properties));

    if (options) {
      options.pageSize && (result.setPageSize(options.pageSize));
      options.offset && (result.setOffset(options.offset));
      options.relations && (result.setRelated(options.relations));
      options.sortBy && (result.setSortBy(options.sortBy));
    }
  }

  return result;
};

/**
 * @typedef {Object} PersistenceIten
 * @property {String} ownerId
 * @property {String} objectId
 * @property {Number} created
 * @property {Number} updated
 */
class PersistenceItem {
  constructor(args) {
    this.___class = this.constructor.name;

    if (typeof args === 'string') {
      args = { objectId: args };
    }

    Object.assign(this, args);
  }

  /**
   * @param {String[]} [relations]
   * @param {String[]} [properties]
   * @returns {Promise.<PersistenceItem>}
   */
  fetch(relations, properties) {
    return this.constructor.findById(this.objectId, relations, properties);
  }

  /**
   * @returns {Promise}
   */
  save() {
    const payload = trimRelations(this);

    const hasCustomProps = !!Object.keys(payload).find(key =>
      payload[key] !== undefined && !SYSTEM_PROPS.includes(key));

    if (!payload.objectId || hasCustomProps) {
      return this.dataStore.save(payload).then(saved => Object.assign(this, saved));
    }

    return Promise.resolve(this);
  }

  /**
   * @param {{stale: String[]}} [options]
   * @returns {Promise.<PersistenceItem>}
   */
  saveWithRelations(options = {}) {
    const { stale = [] } = options;

    const staleForChild = key => {
      const prefix = `${key}.`;

      return stale
        .filter(s => s.startsWith(prefix))
        .map(s => s.substr(prefix.length));
    };

    return this.save().then(saved => {
      const saveItem = (item, itemStale) => {
        if (item instanceof PersistenceItem) {
          return item.saveWithRelations({ stale: itemStale });
        }

        if (item instanceof Backendless.GeoPoint) {
          return Backendless.Geo.savePoint(item);
        }

        return item;
      };

      const processField = (name, value) => {
        const setRelation = relation => {
          saved[name] = relation;

          return saved.setRelation(name, relation);
        };

        if (isPersistable(value)) {
          return Promise.resolve()
            .then(() => stale.includes(name) ? value : saveItem(value, staleForChild(name)))
            .then(setRelation);
        }

        if (isArrayOfPersistable(value)) {
          return Promise.resolve()
            .then(() => stale.includes(name) ? value : Promise.all(value.map(item => saveItem(item, staleForChild(name))))) // eslint-disable-line
            .then(setRelation);
        }
      };

      return Promise.all(Object.keys(this).map(key => processField(key, this[key])))
        .then(() => saved);
    });
  }

  /**
   * Returns a new class instance with objectId and filtered set of properties
   *
   * @param {...String} propsToInclude - properties to include in the response
   * @returns {PersistenceItem}
   */
  ref(...propsToInclude) {
    const result = new this.constructor({ objectId: this.objectId });

    if (propsToInclude) {
      propsToInclude.forEach(propName => {
        result[propName] = this[propName];
      });
    }

    return result;
  }

  /**
   * @returns {Promise}
   */
  remove() {
    return this.dataStore.remove(this);
  }

  /**
   * @param {String} columnName - A name of the column identifying the relation
   * @param {PersistenceItem|PersistenceItem[]|String} childrenOrWhereClause
   * @returns {Promise}
   */
  setRelation(columnName, childrenOrWhereClause) {
    if (isPersistable(childrenOrWhereClause)) {
      childrenOrWhereClause = [childrenOrWhereClause];
    }

    return this.dataStore.setRelation(this, columnName, childrenOrWhereClause);
  }

  /**
   * @param {String} columnName - A name of the column identifying the relation
   * @param {PersistenceItem|PersistenceItem[]|String} childrenOrWhereClause
   * @returns {Promise}
   */
  addRelation(columnName, childrenOrWhereClause) {
    if (isPersistable(childrenOrWhereClause)) {
      childrenOrWhereClause = [childrenOrWhereClause];
    }

    return this.dataStore.addRelation(this, columnName, childrenOrWhereClause);
  }

  /**
   * @param {String} columnName - A name of the column identifying the relation
   * @param {PersistenceItem|PersistenceItem[]|String} childrenOrWhereClause
   * @returns {Promise}
   */
  deleteRelation(columnName, childrenOrWhereClause) {
    if (isPersistable(childrenOrWhereClause)) {
      childrenOrWhereClause = [childrenOrWhereClause];
    }

    return this.dataStore.deleteRelation(this, columnName, childrenOrWhereClause);
  }

  /**
   * @private
   */
  get dataStore() {
    return Backendless.Persistence.of(this.constructor);
  }

  /**
   * @private
   */
  static get dataStore() {
    return Backendless.Persistence.of(this);
  }

  /**
   * @param {String} condition
   * @returns {Promise}
   */
  static count(condition) {
    return this.dataStore.getObjectCount(condition);
  }

  /**
   * @param {Object} obj
   * @returns {Promise.<PersistenceItem>}
   */
  static save(obj) {
    return new this(obj).save();
  }

  /**
   * @param {Object} obj
   * @param {Object} [opts]
   * @returns {Promise.<PersistenceItem>}
   */
  static saveWithRelations(obj, opts) {
    return new this(obj).saveWithRelations(opts);
  }

  /**
   * @param {Backendless.DataQuery|Object|String} query
   * @returns {Promise.<PersistenceItem[]>}
   */
  static find(query) {
    return this.dataStore.find(queryToBuilder(query));
  }

  /**
   * @param {String} objectId
   * @param {String[]} [relations]
   * @param {String[]} [properties]
   * @returns {Promise.<PersistenceItem>}
   */
  static findById(objectId, relations, properties) {
    if (!objectId) {
      return Promise.reject(new Error('objectId is not defined'));
    }

    return this.dataStore.findById(objectId, {
      options: { relations },
      properties
    });
  }

  /**
   * @returns {Promise}
   */
  static findFirst() {
    return this.dataStore.findFirst();
  }

  /**
   * @returns {Promise}
   */
  static findLast() {
    return this.dataStore.findLast();
  }

  /**
   * @param {Object|String} obj An object or objectId for deletion
   * @returns {Promise}
   */
  static remove(obj) {
    return this.dataStore.remove(obj);
  }

  /**
   * @param {Object} changes
   * @param {String} whereClause
   * @returns {Promise}
   */
  static bulkUpdate(changes, whereClause) {
    return this.dataStore.bulkUpdate(changes, whereClause);
  }

  /**
   * @param {String|Array<Object|String>} whereClause whereClause or an array of objects/objectIds for deletion
   * @returns {Promise}
   */
  static bulkDelete(whereClause) {
    return this.dataStore.bulkDelete(whereClause);
  }
}

module.exports = PersistenceItem;<commit_msg>feat (api) add deletable option to PersistenceItem.saveWithRelations<commit_after>'use strict';

const Backendless = require('backendless');

const isPersistable = value =>
  value instanceof PersistenceItem ||
  value instanceof Backendless.GeoPoint;

const isArray = value => Array.isArray(value);

const isEmptyArray = value => isArray(value) && value.length === 0;

const isArrayOfPersistable = value => {
  if (!isArray(value) || value.length === 0) {
    return false;
  }

  for (let i = 0; i < value.length; i++) {
    if (!isPersistable(value[i])) {
      return false;
    }
  }

  return true;
};

const trimRelations = item => {
  const result = {};

  Object.keys(item).forEach(key => {
    const value = item[key];

    if (isPersistable(value) || isArray(value)) {
      return;
    }

    result[key] = value;
  });

  return result;
};

const SYSTEM_PROPS = ['objectId', 'ownerId', 'objectId', 'created', 'updated', '___class', '___jsonclass'];

const queryToBuilder = query => {
  if (query instanceof Backendless.DataQueryBuilder) {
    return query;
  }

  if (typeof query === 'string') {
    return Backendless.DataQueryBuilder.create().setWhereClause(query);
  }

  const result = Backendless.DataQueryBuilder.create();

  if (query) {
    const { condition, properties, options } = query;

    condition && (result.setWhereClause(condition));
    properties && (result.setProperties(properties));

    if (options) {
      options.pageSize && (result.setPageSize(options.pageSize));
      options.offset && (result.setOffset(options.offset));
      options.relations && (result.setRelated(options.relations));
      options.sortBy && (result.setSortBy(options.sortBy));
    }
  }

  return result;
};

/**
 * @typedef {Object} PersistenceIten
 * @property {String} ownerId
 * @property {String} objectId
 * @property {Number} created
 * @property {Number} updated
 */
class PersistenceItem {
  constructor(args) {
    this.___class = this.constructor.name;

    if (typeof args === 'string') {
      args = { objectId: args };
    }

    Object.assign(this, args);
  }

  /**
   * @param {String[]} [relations]
   * @param {String[]} [properties]
   * @returns {Promise.<PersistenceItem>}
   */
  fetch(relations, properties) {
    return this.constructor.findById(this.objectId, relations, properties);
  }

  /**
   * @returns {Promise}
   */
  save() {
    const payload = trimRelations(this);

    const hasCustomProps = !!Object.keys(payload).find(key =>
      payload[key] !== undefined && !SYSTEM_PROPS.includes(key));

    if (!payload.objectId || hasCustomProps) {
      return this.dataStore.save(payload).then(saved => Object.assign(this, saved));
    }

    return Promise.resolve(this);
  }

  /**
   * @param {{stale: String[]}} [options]
   * @returns {Promise.<PersistenceItem>}
   */
  saveWithRelations(options = {}) {
    const { stale = [], deletable = [] } = options;

    const childPath = (key, path) => {
      const prefix = `${key}.`;

      return path
        .filter(s => s.startsWith(prefix))
        .map(s => s.substr(prefix.length));
    };

    return this.save().then(saved => {
      // eslint-disable-next-line no-shadow
      const saveItem = (item, stale, deletable) => {
        if (item instanceof PersistenceItem) {
          return item.saveWithRelations({ stale, deletable });
        }

        if (item instanceof Backendless.GeoPoint) {
          return Backendless.Geo.savePoint(item);
        }

        return item;
      };

      const processField = (name, value) => {
        const setRelation = relation => {
          saved[name] = relation;

          return saved.setRelation(name, relation);
        };

        if (isPersistable(value)) {
          return Promise.resolve()
            .then(() => {
              return stale.includes(name)
                ? value
                : saveItem(value, childPath(name, stale), childPath(name, deletable));
            })
            .then(setRelation);
        }

        if (isArrayOfPersistable(value)) {
          return Promise.resolve()
            .then(() => {
              return stale.includes(name)
                ? value
                : Promise.all(value.map(item => saveItem(item, childPath(name, stale), childPath(name, deletable))));
            })
            .then(setRelation);
        }

        if (deletable.includes(name) && (isEmptyArray(value) || value === null)) {
          return saved.deleteRelation(name, 'objectId is not null');
        }
      };

      return Promise.all(Object.keys(this).map(key => processField(key, this[key])))
        .then(() => saved);
    });
  }

  /**
   * Returns a new class instance with objectId and filtered set of properties
   *
   * @param {...String} propsToInclude - properties to include in the response
   * @returns {PersistenceItem}
   */
  ref(...propsToInclude) {
    const result = new this.constructor({ objectId: this.objectId });

    if (propsToInclude) {
      propsToInclude.forEach(propName => {
        result[propName] = this[propName];
      });
    }

    return result;
  }

  /**
   * @returns {Promise}
   */
  remove() {
    return this.dataStore.remove(this);
  }

  /**
   * @param {String} columnName - A name of the column identifying the relation
   * @param {PersistenceItem|PersistenceItem[]|String} childrenOrWhereClause
   * @returns {Promise}
   */
  setRelation(columnName, childrenOrWhereClause) {
    if (isPersistable(childrenOrWhereClause)) {
      childrenOrWhereClause = [childrenOrWhereClause];
    }

    return this.dataStore.setRelation(this, columnName, childrenOrWhereClause);
  }

  /**
   * @param {String} columnName - A name of the column identifying the relation
   * @param {PersistenceItem|PersistenceItem[]|String} childrenOrWhereClause
   * @returns {Promise}
   */
  addRelation(columnName, childrenOrWhereClause) {
    if (isPersistable(childrenOrWhereClause)) {
      childrenOrWhereClause = [childrenOrWhereClause];
    }

    return this.dataStore.addRelation(this, columnName, childrenOrWhereClause);
  }

  /**
   * @param {String} columnName - A name of the column identifying the relation
   * @param {PersistenceItem|PersistenceItem[]|String} childrenOrWhereClause
   * @returns {Promise}
   */
  deleteRelation(columnName, childrenOrWhereClause) {
    if (isPersistable(childrenOrWhereClause)) {
      childrenOrWhereClause = [childrenOrWhereClause];
    }

    return this.dataStore.deleteRelation(this, columnName, childrenOrWhereClause);
  }

  /**
   * @private
   */
  get dataStore() {
    return Backendless.Persistence.of(this.constructor);
  }

  /**
   * @private
   */
  static get dataStore() {
    return Backendless.Persistence.of(this);
  }

  /**
   * @param {String} condition
   * @returns {Promise}
   */
  static count(condition) {
    return this.dataStore.getObjectCount(condition);
  }

  /**
   * @param {Object} obj
   * @returns {Promise.<PersistenceItem>}
   */
  static save(obj) {
    return new this(obj).save();
  }

  /**
   * @param {Object} obj
   * @param {Object} [opts]
   * @returns {Promise.<PersistenceItem>}
   */
  static saveWithRelations(obj, opts) {
    return new this(obj).saveWithRelations(opts);
  }

  /**
   * @param {Backendless.DataQuery|Object|String} query
   * @returns {Promise.<PersistenceItem[]>}
   */
  static find(query) {
    return this.dataStore.find(queryToBuilder(query));
  }

  /**
   * @param {String} objectId
   * @param {String[]} [relations]
   * @param {String[]} [properties]
   * @returns {Promise.<PersistenceItem>}
   */
  static findById(objectId, relations, properties) {
    if (!objectId) {
      return Promise.reject(new Error('objectId is not defined'));
    }

    return this.dataStore.findById(objectId, {
      options: { relations },
      properties
    });
  }

  /**
   * @returns {Promise}
   */
  static findFirst() {
    return this.dataStore.findFirst();
  }

  /**
   * @returns {Promise}
   */
  static findLast() {
    return this.dataStore.findLast();
  }

  /**
   * @param {Object|String} obj An object or objectId for deletion
   * @returns {Promise}
   */
  static remove(obj) {
    return this.dataStore.remove(obj);
  }

  /**
   * @param {Object} changes
   * @param {String} whereClause
   * @returns {Promise}
   */
  static bulkUpdate(changes, whereClause) {
    return this.dataStore.bulkUpdate(changes, whereClause);
  }

  /**
   * @param {String|Array<Object|String>} whereClause whereClause or an array of objects/objectIds for deletion
   * @returns {Promise}
   */
  static bulkDelete(whereClause) {
    return this.dataStore.bulkDelete(whereClause);
  }
}

module.exports = PersistenceItem;<|endoftext|>


<commit_before>/** @license MIT License (c) copyright B Cavalier & J Hann */

/**
 * wire/dom/render plugin
 * wire plugin that provides a factory for dom nodes via a simple html
 * template.
 *
 * wire is part of the cujo.js family of libraries (http://cujojs.com/)
 *
 * Licensed under the MIT License at:
 * http://www.opensource.org/licenses/mit-license.php
 */

define(['when', '../domReady'], function(when, domReady) {

	var parentTypes, parseTemplateRx, getFirstTagNameRx, undef;

	parentTypes = {
		'td': 'tr',
		'tr': 'tbody',
		'tbody': 'table',
		'li': 'ul'
		// TODO: finish this list
	};

	parseTemplateRx = /\$\{([^}]*)\}/g;
	getFirstTagNameRx = /<\s*(\w+)/;

	/**
	 * Constructs a DOM node and child nodes from a template string.
	 * Information contained in a hashmap is merged into the template
	 * via tokens (${name}) before rendering into DOM nodes.
	 * Nothing is done with the css parameter at this time.
	 * @param template {String}
	 * @param hashmap {Object}
	 * @param optRefNode {DOMNode}
	 * @param optCss {Object}
	 * @returns {DOMNode}
	 */
	function render (template, hashmap, optRefNode, optCss) {
		var node, parentType;

		// replace tokens (before attempting to find top tag name)
		template = replaceTokens(template, hashmap);

		// get parent tag type
		parentType = getParentTagName(template);

		node = createTemplatedNode(template, parentType);

		if (optRefNode) {
			node = safeReplaceNode(node, optRefNode);
		}

		return node;
	}

	render.wire$plugin = function (ready, destroyed, options) {
		return {
			factories: {
				render: domRenderFactory
			}
		};
	};

	return render;

	/**
	 * Creates rendered dom trees for the "render" factory.
	 * @param resolver
	 * @param spec
	 * @param wire
	 */
	function domRenderFactory(resolver, spec, wire) {
		var parentRef, options;

		options = spec.render;

		domReady(function() {

			var futureTemplate, futureMixin, futureRoot, futureCss;

			// get args from spec
			futureTemplate = options.template ? wire(options.template) : '';
			if (options.mixin) {
				futureMixin = wire(options.mixin);
			}
			if (options.at) {
				futureRoot = wire(options.at);
			}
			if (options.css) {
				futureCss = wire(options.css);
			}

			when.all([futureTemplate, futureMixin, futureRoot, futureCss], function (args) {
				return render.apply(undef, args);
			}).then(resolver.resolve, resolver.reject);

		});
	}

	/**
	 * Finds the first html element in a string, extracts its tag name,
	 * and looks up the natural parent element tag name for this element.
	 * @param template {String}
	 * @returns {String} the parent tag name, or 'div' if none was found.
	 */
	function getParentTagName (template) {
		var matches;
		// TODO: throw if no element was ever found
		matches = template.match(getFirstTagNameRx);
		return parentTypes[matches && matches[1]] || 'div';
	}

	/**
	 * Creates a node from a text template.
	 * @private
	 * @param template
	 * @param parentTagName
	 * @returns {DOMNode} the root node created from the template
	 */
	function createTemplatedNode (template, parentTagName) {
		var parent = document.createElement(parentTagName);
		parent.innerHTML = template;
		// just return first node (templates that use nodelists are tricky)
		return parent.childNodes[0];
	}

	/**
	 * Replaces a dom node, while preserving important attributes
	 * of the original.
	 * @private
	 * @param oldNode {DOMNode}
	 * @param newNode {DOMNode}
	 * @returns {DOMNode} newNode
	 */
	function safeReplaceNode (newNode, oldNode) {
		var i, attr, newClassesRx, parent;
		for (i = 0; i < oldNode.attributes.length; i++) {
			attr = oldNode.attributes[i];
			if ('class' == attr.name) {
				// merge css classes
				newClassesRx = new RegExp(newNode.className.replace(' ', '|'));
				newNode.className = oldNode.className.replace(newClassesRx, '') + ' ' + newNode.className;
			}
			else if (!newNode.hasAttribute(attr.name)) {
				newNode.setAttribute(attr.name, oldNode.getAttribute(attr.name));
			}
		}
		parent = oldNode.parentNode;
		if (parent) {
			parent.replaceChild(newNode, oldNode);
		}
		return newNode;
	}

	/**
	 * Replaces simple tokens in a string.  Tokens are in the format ${key}.
	 * Tokens are replaced by values looked up in an associated hashmap.
	 * If a token's key is not found in the hashmap, an empty string is
	 * inserted instead.
	 * @private
	 * @param template
	 * @param hashmap {Object} the names of the properties of this object
	 * are used as keys. The values replace the token in the string.
	 * @param transform {Function} callback that can
	 * @returns {String}
	 */
	function replaceTokens (template, hashmap, transform) {
		if (!transform) transform = blankIfMissing;
		return template.replace(parseTemplateRx, function (m, token) {
			return transform(hashmap && hashmap[token]);
		});
	}

	function blankIfMissing (val) { return val || ''; }

});<commit_msg>Adding proxy for DOM nodes<commit_after>/** @license MIT License (c) copyright B Cavalier & J Hann */

/**
 * wire/dom/render plugin
 * wire plugin that provides a factory for dom nodes via a simple html
 * template.
 *
 * wire is part of the cujo.js family of libraries (http://cujojs.com/)
 *
 * Licensed under the MIT License at:
 * http://www.opensource.org/licenses/mit-license.php
 */

define(['when', '../domReady'], function(when, domReady) {

	var parentTypes, parseTemplateRx, getFirstTagNameRx, undef;

	parentTypes = {
		'td': 'tr',
		'tr': 'tbody',
		'tbody': 'table',
		'li': 'ul'
		// TODO: finish this list
	};

	parseTemplateRx = /\$\{([^}]*)\}/g;
	getFirstTagNameRx = /<\s*(\w+)/;

	/**
	 * Constructs a DOM node and child nodes from a template string.
	 * Information contained in a hashmap is merged into the template
	 * via tokens (${name}) before rendering into DOM nodes.
	 * Nothing is done with the css parameter at this time.
	 * @param template {String}
	 * @param hashmap {Object}
	 * @param optRefNode {DOMNode}
	 * @param optCss {Object}
	 * @returns {DOMNode}
	 */
	function render (template, hashmap, optRefNode, optCss) {
		var node, parentType;

		// replace tokens (before attempting to find top tag name)
		template = replaceTokens(template, hashmap);

		// get parent tag type
		parentType = getParentTagName(template);

		node = createTemplatedNode(template, parentType);

		if (optRefNode) {
			node = safeReplaceNode(node, optRefNode);
		}

		return node;
	}

	render.wire$plugin = function (ready, destroyed, options) {
		return {
			factories: {
				render: domRenderFactory
			},
			proxies: [
				nodeProxy
			]
		};
	};

	return render;

	/**
	 * Creates rendered dom trees for the "render" factory.
	 * @param resolver
	 * @param spec
	 * @param wire
	 */
	function domRenderFactory(resolver, spec, wire) {
		var parentRef, options;

		options = spec.render;

		domReady(function() {

			var futureTemplate, futureMixin, futureRoot, futureCss;

			// get args from spec
			futureTemplate = options.template ? wire(options.template) : '';
			if (options.mixin) {
				futureMixin = wire(options.mixin);
			}
			if (options.at) {
				futureRoot = wire(options.at);
			}
			if (options.css) {
				futureCss = wire(options.css);
			}

			when.all([futureTemplate, futureMixin, futureRoot, futureCss], function (args) {
				return render.apply(undef, args);
			}).then(resolver.resolve, resolver.reject);

		});
	}

	/**
	 * Finds the first html element in a string, extracts its tag name,
	 * and looks up the natural parent element tag name for this element.
	 * @param template {String}
	 * @returns {String} the parent tag name, or 'div' if none was found.
	 */
	function getParentTagName (template) {
		var matches;
		// TODO: throw if no element was ever found
		matches = template.match(getFirstTagNameRx);
		return parentTypes[matches && matches[1]] || 'div';
	}

	/**
	 * Creates a node from a text template.
	 * @private
	 * @param template
	 * @param parentTagName
	 * @returns {DOMNode} the root node created from the template
	 */
	function createTemplatedNode (template, parentTagName) {
		var parent = document.createElement(parentTagName);
		parent.innerHTML = template;
		// just return first node (templates that use nodelists are tricky)
		return parent.childNodes[0];
	}

	/**
	 * Replaces a dom node, while preserving important attributes
	 * of the original.
	 * @private
	 * @param oldNode {DOMNode}
	 * @param newNode {DOMNode}
	 * @returns {DOMNode} newNode
	 */
	function safeReplaceNode (newNode, oldNode) {
		var i, attr, newClassesRx, parent;
		for (i = 0; i < oldNode.attributes.length; i++) {
			attr = oldNode.attributes[i];
			if ('class' == attr.name) {
				// merge css classes
				newClassesRx = new RegExp(newNode.className.replace(' ', '|'));
				newNode.className = oldNode.className.replace(newClassesRx, '') + ' ' + newNode.className;
			}
			else if (!newNode.hasAttribute(attr.name)) {
				newNode.setAttribute(attr.name, oldNode.getAttribute(attr.name));
			}
		}
		parent = oldNode.parentNode;
		if (parent) {
			parent.replaceChild(newNode, oldNode);
		}
		return newNode;
	}

	/**
	 * Replaces simple tokens in a string.  Tokens are in the format ${key}.
	 * Tokens are replaced by values looked up in an associated hashmap.
	 * If a token's key is not found in the hashmap, an empty string is
	 * inserted instead.
	 * @private
	 * @param template
	 * @param hashmap {Object} the names of the properties of this object
	 * are used as keys. The values replace the token in the string.
	 * @param transform {Function} callback that can
	 * @returns {String}
	 */
	function replaceTokens (template, hashmap, transform) {
		if (!transform) transform = blankIfMissing;
		return template.replace(parseTemplateRx, function (m, token) {
			return transform(hashmap && hashmap[token]);
		});
	}

	function nodeProxy(node) {
		if(!node.tagName || !node.setAttribute || !node.getAttribute) return;

		return {
			get: function() { /** TODO */ },
			set: function() { /** TODO */ },
			invoke: function() { /** TODO */ },
			destroy: function() {
				var parent = node.parentNode;
				if(parent) parent.removeChild(node);
			}
		};
	}

	function blankIfMissing (val) { return val || ''; }

});<|endoftext|>


<commit_before>
var fs = require('fs');
var path = require('path');

module.exports = function() {};

module.exports.pitch = function(remainingRequest) {
  this.cacheable && this.cacheable();
  var cb = this.async();

  var templatePath = __dirname + '/lib/template.js';
  this.addDependency(templatePath);

  var resource = this.resourcePath;
  var ext = path.extname(resource);
  var name = path.basename(resource, ext)
  var dirname = path.dirname(resource);

  var req = remainingRequest.split('!');
  req.pop();

  var loadingComponent = dirname + '/' + name + '.loading' + ext;
  var LOADING = fs.existsSync(loadingComponent) ?
        'loading = require(' + JSON.stringify('!!' + req.join('!') + '!' + loadingComponent) + '),\n' +
        'loading = loading["default"] || loading':
        '';

  if (LOADING) this.addDependency(loadingComponent);

  fs.readFile(templatePath, 'utf8', function(err, template) {
    if (err) return cb(err);

    cb(null,
       template
         .replace(/__REQUEST__/g, JSON.stringify('!!' + remainingRequest))
         .replace(/__PROXY__/g, JSON.stringify(require.resolve('./lib/lazy-load.js')))
         .replace(/__LOADING_COMPONENT__/g, LOADING)
    );
  });
};
<commit_msg>expose force-load query param<commit_after>
var fs = require('fs');
var path = require('path');

module.exports = function() {};

module.exports.pitch = function(remainingRequest) {
  if (~(this.resourceQuery || '').indexOf('force-load')) return 'module.exports = require(' + JSON.stringify('!!' + remainingRequest) + ');';
  this.cacheable && this.cacheable();
  var cb = this.async();

  var templatePath = __dirname + '/lib/template.js';
  this.addDependency(templatePath);

  var resource = this.resourcePath;
  var ext = path.extname(resource);
  var name = path.basename(resource, ext)
  var dirname = path.dirname(resource);

  var req = remainingRequest.split('!');
  req.pop();

  var loadingComponent = dirname + '/' + name + '.loading' + ext;
  var LOADING = fs.existsSync(loadingComponent) ?
        'loading = require(' + JSON.stringify('!!' + req.join('!') + '!' + loadingComponent) + '),\n' +
        'loading = loading["default"] || loading':
        '';

  if (LOADING) this.addDependency(loadingComponent);

  fs.readFile(templatePath, 'utf8', function(err, template) {
    if (err) return cb(err);

    cb(null,
       template
         .replace(/__REQUEST__/g, JSON.stringify('!!' + remainingRequest))
         .replace(/__PROXY__/g, JSON.stringify(require.resolve('./lib/lazy-load.js')))
         .replace(/__LOADING_COMPONENT__/g, LOADING)
    );
  });
};
<|endoftext|>


<commit_before>hqDefine("report/js/tableau", function () {
    var initialPageData = hqImport("hqwebapp/js/initial_page_data"),
        self = {};

    self.initViz = function() {
        var containerDiv = document.getElementById("vizContainer");
        var url = _.template("https://<%- validate_hostname %>/<% if (is_server) { %>trusted/<%- ticket %>/<% } %><%- view_url %>")({
            validate_hostname: initialPageData.get("validate_hostname"),
            is_server: initialPageData.get("server_type") === "server",
            ticket: initialPageData.get("ticket"),
            view_url: initialPageData.get("view_url"),
        });

        var options = {
            hideTabs: true,
            width: "800px",
            height: "700px",
        };

        var viz = new tableau.Viz(containerDiv, url, options);
    };

    $(document).ready(function() {
        self.initViz();
    });

    return 1;
});
<commit_msg>Removed static dimensions<commit_after>hqDefine("report/js/tableau", function () {
    var initialPageData = hqImport("hqwebapp/js/initial_page_data"),
        self = {};

    self.initViz = function() {
        var containerDiv = document.getElementById("vizContainer");
        var url = _.template("https://<%- validate_hostname %>/<% if (is_server) { %>trusted/<%- ticket %>/<% } %><%- view_url %>")({
            validate_hostname: initialPageData.get("validate_hostname"),
            is_server: initialPageData.get("server_type") === "server",
            ticket: initialPageData.get("ticket"),
            view_url: initialPageData.get("view_url"),
        });

        new tableau.Viz(containerDiv, url, {
            hideTabs: true,
        });
    };

    $(document).ready(function() {
        self.initViz();
    });

    return 1;
});
<|endoftext|>


<commit_before>
import React from 'react';
import {Redirect, Switch, Route} from 'react-router-dom';
import {connect} from 'react-redux'
import {getPattern, getPatternUsedPatterns, getVariantFromPattern, getUsed} from './selectors';
import {toggleInfo} from './actions';
import PatternInfo from './components/PatternInfo';
import RenderFrame from './components/RenderFrame';
import {VariantNotFound} from './components/NotFound';
import VariantSelector from './components/VariantSelector';
import PatternProblems from './components/PatternProblems';
import PatternTopBar from './components/PatternTopBar';
import {OpenButton, ViewInfoButton, InfoCloseButton} from './components/Buttons';

import './PatternPage.css';

const PatternOuterPage = (props) => {
    const {pattern, match} = props;

    return (
        <Route path={`${match.url}/variant/:vid`} children={({match: variantMatch}) => {
            const variant = variantMatch ? getVariantFromPattern(pattern, variantMatch.params.vid) : null;
            return <PatternInnerPage base={match.url} variant={variant} {...props} />
        }}/>
    )
}

const PatternInnerPage = ({pattern, variant, showingInfo, match, toggleInfo, base, history}) => {
    const changeVariant = (e) => history.push(`${base}/variant/${e.target.value}`);
    const variants = pattern ? pattern.variants : [];
    const selector = variants.length ? <VariantSelector onChange={changeVariant} value={variant ? variant.id : ''} variants={variants} /> : null;
    const problems = pattern && pattern.problems.length ? <PatternProblems className="Content" problems={pattern.problems} /> : null;
    const actions = (

            {variant &&
<OpenButton href={variant.source} />
}

<ViewInfoButton onClick={toggleInfo} />

    );
    var info;
    if(pattern) {
        info = <ConnectedPatternInfo className={showingInfo ? 'showing' : 'hiding'} pattern={pattern} variant={variant} controls={<InfoCloseButton onClick={toggleInfo} />} />
    }
    else {
        info = null;
    }
    return (

            <PatternTopBar actions={actions} selector={selector} title={pattern ? pattern.name : 'Loading...'} />
            {problems}
            <Switch>
                <Route path={`${match.path}`} exact render={({match}) => {
                    if(pattern && pattern.variants.length) {
                        return <Redirect to={`${match.url}/variant/${pattern.variants[0].id}`}/>
                    }
                    return <VariantNotFound text={'There are no variants for this pattern.'} />
                }}/>
                {/* Then try to match on the exact variant. */}
                {pattern && pattern.variants.map(variant => {
                    return <Route key={variant.id} path={`${match.path}/variant/${variant.id}`} render={(p) => {
                        return <RenderFrame src={variant.rendered} />
                    }} />
                })}
                <Route component={VariantNotFound} />
            </Switch>
            {info}

    )
}

const iMapStateToProps = (state, ownProps) => {
    return {
        used: getPatternUsedPatterns(ownProps.pattern, state.patterns)
    }
}
const ConnectedPatternInfo = connect(iMapStateToProps)(PatternInfo);

const mapStateToProps = (state, ownProps) => {
    return {
        pattern: getPattern(state, ownProps),
        showingInfo: state.info,
        used: getUsed(state, ownProps)
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        toggleInfo: () => dispatch(toggleInfo()),
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(PatternOuterPage);<commit_msg>Show rendered instead of source when opening in a new window<commit_after>
import React from 'react';
import {Redirect, Switch, Route} from 'react-router-dom';
import {connect} from 'react-redux'
import {getPattern, getPatternUsedPatterns, getVariantFromPattern, getUsed} from './selectors';
import {toggleInfo} from './actions';
import PatternInfo from './components/PatternInfo';
import RenderFrame from './components/RenderFrame';
import {VariantNotFound} from './components/NotFound';
import VariantSelector from './components/VariantSelector';
import PatternProblems from './components/PatternProblems';
import PatternTopBar from './components/PatternTopBar';
import {OpenButton, ViewInfoButton, InfoCloseButton} from './components/Buttons';

import './PatternPage.css';

const PatternOuterPage = (props) => {
    const {pattern, match} = props;

    return (
        <Route path={`${match.url}/variant/:vid`} children={({match: variantMatch}) => {
            const variant = variantMatch ? getVariantFromPattern(pattern, variantMatch.params.vid) : null;
            return <PatternInnerPage base={match.url} variant={variant} {...props} />
        }}/>
    )
}

const PatternInnerPage = ({pattern, variant, showingInfo, match, toggleInfo, base, history}) => {
    const changeVariant = (e) => history.push(`${base}/variant/${e.target.value}`);
    const variants = pattern ? pattern.variants : [];
    const selector = variants.length ? <VariantSelector onChange={changeVariant} value={variant ? variant.id : ''} variants={variants} /> : null;
    const problems = pattern && pattern.problems.length ? <PatternProblems className="Content" problems={pattern.problems} /> : null;
    const actions = (

            {variant &&
<OpenButton href={variant.rendered} />
}

<ViewInfoButton onClick={toggleInfo} />

    );
    var info;
    if(pattern) {
        info = <ConnectedPatternInfo className={showingInfo ? 'showing' : 'hiding'} pattern={pattern} variant={variant} controls={<InfoCloseButton onClick={toggleInfo} />} />
    }
    else {
        info = null;
    }
    return (

            <PatternTopBar actions={actions} selector={selector} title={pattern ? pattern.name : 'Loading...'} />
            {problems}
            <Switch>
                <Route path={`${match.path}`} exact render={({match}) => {
                    if(pattern && pattern.variants.length) {
                        return <Redirect to={`${match.url}/variant/${pattern.variants[0].id}`}/>
                    }
                    return <VariantNotFound text={'There are no variants for this pattern.'} />
                }}/>
                {/* Then try to match on the exact variant. */}
                {pattern && pattern.variants.map(variant => {
                    return <Route key={variant.id} path={`${match.path}/variant/${variant.id}`} render={(p) => {
                        return <RenderFrame src={variant.rendered} />
                    }} />
                })}
                <Route component={VariantNotFound} />
            </Switch>
            {info}

    )
}

const iMapStateToProps = (state, ownProps) => {
    return {
        used: getPatternUsedPatterns(ownProps.pattern, state.patterns)
    }
}
const ConnectedPatternInfo = connect(iMapStateToProps)(PatternInfo);

const mapStateToProps = (state, ownProps) => {
    return {
        pattern: getPattern(state, ownProps),
        showingInfo: state.info,
        used: getUsed(state, ownProps)
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
        toggleInfo: () => dispatch(toggleInfo()),
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(PatternOuterPage);<|endoftext|>


<commit_before>var TCM = TCM || {};

(function($) {

    TCM.addLoadingCSS = function(container) {
        var vertHeight = (parseInt(container.css('height'), 10) - parseInt(container.css('line-height'), 10)) / 2 + 'px',
            style = '';
        $('head').append(style);
    };

    TCM.addLoading = function(trigger, context) {
        $(context).find(trigger).click(function() {
            var container = $(this).closest(context).addClass('loading');
            TCM.addLoadingCSS(container);
        });
    };

    var filtering = function() {
        var button = $('#filter .visual .content button[type="submit"]').hide(),
            input = $('#filter .visual .filter-group input[type="checkbox"]').each(function() {
                $(this).data('originallyChecked', $(this).is(':checked'));
            }),
            textbox = $('#filter .textual #text-filter'),
            typedText = textbox.val(),
            suggestionList = $('#filter .textual .suggest').hide(),
            keywordGroups = $('#filter .visual .filter-group.keyword'),
            notKeywordGroups = $('#filter .visual .filter-group:not(.keyword)'),
            selected,
            updateButton = function() {
                if (input.filter(function() {
                    return $(this).data('state') === 'changed';
                }).length) {
                    button.fadeIn('fast');
                } else {
                    button.fadeOut('fast');
                }
            };

        input.live('change', function() {
            if ($(this).data('originallyChecked') !== $(this).is(':checked')) {
                $(this).data('state', 'changed');
            } else {
                $(this).data('state', null);
            }
            updateButton();
        });

        textbox.keyup(function(event) {
            if ($(this).val() !== typedText) {
                typedText = $(this).val();
                suggestionList.empty();
                if ($(this).val().length) {
                    var relevantFilters = notKeywordGroups.find('input[type="checkbox"]:not(:checked)').parent('li').filter(function() {
                            return $(this).children('label').html().toLowerCase().indexOf(typedText.toLowerCase()) !== -1;
                        });
                    relevantFilters.each(function() {
                        var typedIndex = $(this).children('label').html().toLowerCase().indexOf(typedText.toLowerCase()),
                            preText = $(this).children('label').html().substring(0, typedIndex),
                            postText = $(this).children('label').html().substring(typedIndex + typedText.length),
                            type = $(this).children('input').attr('name'),
                            id = $(this).children('input').attr('id'),
                            newHTML = '
' + preText + '' + typedText + '' + postText + ' [' + type + ']
';
                        suggestionList.append(newHTML);
                    });
                    keywordGroups.each(function() {
                        var type = $(this).children('h5').html(),
                            name = $(this).data('name'),
                            keywordHTML = '
' + typedText + ' [' + type + ']
';
                        if (!$(this).find('input[type="checkbox"][value="' + typedText + '"]:checked').length) {
                            suggestionList.append(keywordHTML);
                        }
                    });
                    suggestionList.find('li:first-child a').addClass('selected');
                }
            }
        }).keydown(function(event) {
            if (event.keyCode === 38) {
                event.preventDefault();
                if (!suggestionList.find('.selected').parent().is(':first-child')) {
                    suggestionList.find('.selected').removeClass('selected').parent().prev().children('a').addClass('selected');
                }
                return false;
            }
            if (event.keyCode === 40) {
                event.preventDefault();
                if (!suggestionList.find('.selected').parent().is(':last-child')) {
                    suggestionList.find('.selected').removeClass('selected').parent().next().children('a').addClass('selected');
                }
                return false;
            }
            if (event.keyCode === 13) {
                event.preventDefault();
                suggestionList.find('.selected').click();
                suggestionList.show();
                return false;
            }
            if (event.keyCode === 9) {
                var thisFilterName = input.filter('#' + suggestionList.find('.selected').data('id')).siblings('label').html();
                if (thisFilterName) {
                    event.preventDefault();
                    textbox.val(thisFilterName);
                    return false;
                }
            }
        });

        textbox.focus(function() {
            suggestionList.show();
            textbox.data('clicked', false);
        }).blur(function() {
            function hideList() {
                if (textbox.data('clicked') !== true) {
                    suggestionList.hide();
                }
            }
            window.setTimeout(hideList, 150);
        });

        suggestionList.hover(function() {
            selected = $(this).find('.selected').removeClass('selected');
        }, function() {
            selected.addClass('selected');
        });

        suggestionList.find('a').live('mousedown', function() {
            textbox.data('clicked', true);
        }).live('click', function() {
            if ($(this).data('class') === 'keyword') {
                var name = $(this).data('name'),
                    thisGroup = keywordGroups.filter(function() {
                        return $(this).data('name') === name;
                    }),
                    existingKeyword = thisGroup.find('input[type="checkbox"][value="' + typedText + '"][name="' + name + '"]'),
                    index = thisGroup.find('li').length + 1,
                    newHTML =
                        '
' +
                            '<input type="checkbox" name="' + name + '" value="' + typedText + '" id="id-' + name + '-' + index + '" checked="checked" data-state="changed" data-originallyChecked="false">' +
                            '' + typedText + '' +
                        '
';
                if (existingKeyword.length) {
                    existingKeyword.attr('checked', 'checked');
                    if (existingKeyword.data('originallyChecked') !== existingKeyword.is(':checked')) {
                        existingKeyword.data('state', 'changed');
                    }
                } else {
                    thisGroup.removeClass('empty').children('ul').append(newHTML);
                    input = input.add('#id-' + name + '-' + index);
                }
            } else {
                var thisFilter = input.filter('#' + $(this).data('id')).attr('checked', 'checked');
                if (thisFilter.data('originallyChecked') !== thisFilter.is(':checked')) {
                    thisFilter.data('state', 'changed');
                }
            }
            updateButton();
            textbox.data('clicked', false).val(null);
            typedText = null;
            suggestionList.empty().hide();
            return false;
        });
    };

    $(function() {
        filtering();
        $('input[placeholder], textarea[placeholder]').placeholder();
        $('input:not([type=radio], [type=checkbox]), textarea').blur(
            function() {
                $(this).addClass('hadfocus');
            }
        );
        $('#filter .toggle a').click(
            function() {
                $('#filter .visual').toggleClass('compact').toggleClass('expanded');
                return false;
            }
        );
        if ($('html').hasClass('no-details')) {
            $('details').html5accordion('summary');
        }
        $('.details:not(html)').html5accordion('.summary');
        $('.subnav .findertoggle').click(function() {
            $(this).add('.subnav .finder').toggleClass('expanded').toggleClass('compact');
            return false;
        });
        $('.subnav').html5finder( {
            loading: true,
            horizontalScroll: true,
            scrollContainer: '.finder.expanded',
            headerSelector: 'header.listordering',
            sectionSelector: '.col',
            sectionContentSelector: '.colcontent',
            sectionClasses: [
                'products',
                'cycles',
                'runs',
                'cases',
                'results'
            ],
            sectionItemSelectors: [
                'input[name="product"]',
                'input[name="cycle"]',
                'input[name="run"]',
                'input[name="case"]',
                'input[name="result"]'
            ]
        });
        $('.selectruns').html5finder( {
            loading: true,
            headerSelector: '.listordering',
            sectionSelector: '.col',
            sectionContentSelector: '.colcontent',
            sectionClasses: [
                'products',
                'cycles',
                'runs'
            ],
            sectionItemSelectors: [
                'input[name="product"]',
                'input[name="testcycle"]',
                'input[name="testrun"]'
            ],
            callback: function() {
                $('.selectruns + .environment').slideUp('fast');
            },
            lastChildCallback: function(choice) {
                var environments = $('.selectruns + .environment').css('min-height', '169px').addClass('loading').slideDown('fast'),
                    ajaxUrl = $(choice).data("sub-url");
                TCM.addLoadingCSS(environments);
                $.get(ajaxUrl, function(data) {
                    environments.html(data);
                    $('.loadingCSS').detach();
                    $('.loading').removeClass('loading');
                });
            }
        });
        $('.selectruns + .environment.empty').hide();
    });

    $(window).load(function() {
        $('#listcontent .items .summary .title').ellipsis(true);
    });

})(jQuery);
<commit_msg>js2-mode doesn't like a function that only sometimes returns a value.<commit_after>var TCM = TCM || {};

(function($) {

    TCM.addLoadingCSS = function(container) {
        var vertHeight = (parseInt(container.css('height'), 10) - parseInt(container.css('line-height'), 10)) / 2 + 'px',
            style = '';
        $('head').append(style);
    };

    TCM.addLoading = function(trigger, context) {
        $(context).find(trigger).click(function() {
            var container = $(this).closest(context).addClass('loading');
            TCM.addLoadingCSS(container);
        });
    };

    var filtering = function() {
        var button = $('#filter .visual .content button[type="submit"]').hide(),
            input = $('#filter .visual .filter-group input[type="checkbox"]').each(function() {
                $(this).data('originallyChecked', $(this).is(':checked'));
            }),
            textbox = $('#filter .textual #text-filter'),
            typedText = textbox.val(),
            suggestionList = $('#filter .textual .suggest').hide(),
            keywordGroups = $('#filter .visual .filter-group.keyword'),
            notKeywordGroups = $('#filter .visual .filter-group:not(.keyword)'),
            selected,
            updateButton = function() {
                if (input.filter(function() {
                    return $(this).data('state') === 'changed';
                }).length) {
                    button.fadeIn('fast');
                } else {
                    button.fadeOut('fast');
                }
            };

        input.live('change', function() {
            if ($(this).data('originallyChecked') !== $(this).is(':checked')) {
                $(this).data('state', 'changed');
            } else {
                $(this).data('state', null);
            }
            updateButton();
        });

        textbox.keyup(function(event) {
            if ($(this).val() !== typedText) {
                typedText = $(this).val();
                suggestionList.empty();
                if ($(this).val().length) {
                    var relevantFilters = notKeywordGroups.find('input[type="checkbox"]:not(:checked)').parent('li').filter(function() {
                            return $(this).children('label').html().toLowerCase().indexOf(typedText.toLowerCase()) !== -1;
                        });
                    relevantFilters.each(function() {
                        var typedIndex = $(this).children('label').html().toLowerCase().indexOf(typedText.toLowerCase()),
                            preText = $(this).children('label').html().substring(0, typedIndex),
                            postText = $(this).children('label').html().substring(typedIndex + typedText.length),
                            type = $(this).children('input').attr('name'),
                            id = $(this).children('input').attr('id'),
                            newHTML = '
' + preText + '' + typedText + '' + postText + ' [' + type + ']
';
                        suggestionList.append(newHTML);
                    });
                    keywordGroups.each(function() {
                        var type = $(this).children('h5').html(),
                            name = $(this).data('name'),
                            keywordHTML = '
' + typedText + ' [' + type + ']
';
                        if (!$(this).find('input[type="checkbox"][value="' + typedText + '"]:checked').length) {
                            suggestionList.append(keywordHTML);
                        }
                    });
                    suggestionList.find('li:first-child a').addClass('selected');
                }
            }
        }).keydown(function(event) {
            if (event.keyCode === 38) {
                event.preventDefault();
                if (!suggestionList.find('.selected').parent().is(':first-child')) {
                    suggestionList.find('.selected').removeClass('selected').parent().prev().children('a').addClass('selected');
                }
                return false;
            }
            if (event.keyCode === 40) {
                event.preventDefault();
                if (!suggestionList.find('.selected').parent().is(':last-child')) {
                    suggestionList.find('.selected').removeClass('selected').parent().next().children('a').addClass('selected');
                }
                return false;
            }
            if (event.keyCode === 13) {
                event.preventDefault();
                suggestionList.find('.selected').click();
                suggestionList.show();
                return false;
            }
            if (event.keyCode === 9) {
                var thisFilterName = input.filter('#' + suggestionList.find('.selected').data('id')).siblings('label').html();
                if (thisFilterName) {
                    event.preventDefault();
                    textbox.val(thisFilterName);
                    return false;
                }
            }
            return true;
        });

        textbox.focus(function() {
            suggestionList.show();
            textbox.data('clicked', false);
        }).blur(function() {
            function hideList() {
                if (textbox.data('clicked') !== true) {
                    suggestionList.hide();
                }
            }
            window.setTimeout(hideList, 150);
        });

        suggestionList.hover(function() {
            selected = $(this).find('.selected').removeClass('selected');
        }, function() {
            selected.addClass('selected');
        });

        suggestionList.find('a').live('mousedown', function() {
            textbox.data('clicked', true);
        }).live('click', function() {
            if ($(this).data('class') === 'keyword') {
                var name = $(this).data('name'),
                    thisGroup = keywordGroups.filter(function() {
                        return $(this).data('name') === name;
                    }),
                    existingKeyword = thisGroup.find('input[type="checkbox"][value="' + typedText + '"][name="' + name + '"]'),
                    index = thisGroup.find('li').length + 1,
                    newHTML =
                        '
' +
                            '<input type="checkbox" name="' + name + '" value="' + typedText + '" id="id-' + name + '-' + index + '" checked="checked" data-state="changed" data-originallyChecked="false">' +
                            '' + typedText + '' +
                        '
';
                if (existingKeyword.length) {
                    existingKeyword.attr('checked', 'checked');
                    if (existingKeyword.data('originallyChecked') !== existingKeyword.is(':checked')) {
                        existingKeyword.data('state', 'changed');
                    }
                } else {
                    thisGroup.removeClass('empty').children('ul').append(newHTML);
                    input = input.add('#id-' + name + '-' + index);
                }
            } else {
                var thisFilter = input.filter('#' + $(this).data('id')).attr('checked', 'checked');
                if (thisFilter.data('originallyChecked') !== thisFilter.is(':checked')) {
                    thisFilter.data('state', 'changed');
                }
            }
            updateButton();
            textbox.data('clicked', false).val(null);
            typedText = null;
            suggestionList.empty().hide();
            return false;
        });
    };

    $(function() {
        filtering();
        $('input[placeholder], textarea[placeholder]').placeholder();
        $('input:not([type=radio], [type=checkbox]), textarea').blur(
            function() {
                $(this).addClass('hadfocus');
            }
        );
        $('#filter .toggle a').click(
            function() {
                $('#filter .visual').toggleClass('compact').toggleClass('expanded');
                return false;
            }
        );
        if ($('html').hasClass('no-details')) {
            $('details').html5accordion('summary');
        }
        $('.details:not(html)').html5accordion('.summary');
        $('.subnav .findertoggle').click(function() {
            $(this).add('.subnav .finder').toggleClass('expanded').toggleClass('compact');
            return false;
        });
        $('.subnav').html5finder( {
            loading: true,
            horizontalScroll: true,
            scrollContainer: '.finder.expanded',
            headerSelector: 'header.listordering',
            sectionSelector: '.col',
            sectionContentSelector: '.colcontent',
            sectionClasses: [
                'products',
                'cycles',
                'runs',
                'cases',
                'results'
            ],
            sectionItemSelectors: [
                'input[name="product"]',
                'input[name="cycle"]',
                'input[name="run"]',
                'input[name="case"]',
                'input[name="result"]'
            ]
        });
        $('.selectruns').html5finder( {
            loading: true,
            headerSelector: '.listordering',
            sectionSelector: '.col',
            sectionContentSelector: '.colcontent',
            sectionClasses: [
                'products',
                'cycles',
                'runs'
            ],
            sectionItemSelectors: [
                'input[name="product"]',
                'input[name="testcycle"]',
                'input[name="testrun"]'
            ],
            callback: function() {
                $('.selectruns + .environment').slideUp('fast');
            },
            lastChildCallback: function(choice) {
                var environments = $('.selectruns + .environment').css('min-height', '169px').addClass('loading').slideDown('fast'),
                    ajaxUrl = $(choice).data("sub-url");
                TCM.addLoadingCSS(environments);
                $.get(ajaxUrl, function(data) {
                    environments.html(data);
                    $('.loadingCSS').detach();
                    $('.loading').removeClass('loading');
                });
            }
        });
        $('.selectruns + .environment.empty').hide();
    });

    $(window).load(function() {
        $('#listcontent .items .summary .title').ellipsis(true);
    });

})(jQuery);
<|endoftext|>


<commit_before>'use strict';

module.exports = function(config) {
  return {
    afterParse: function(sql, values, plugin, callback){
      var params = plugin.params;
      var dialect = plugin.ctx.dialect;
      if (params.length === 0 || !params[0]) {
        return callback(sql, values);
      }
      var limit = params[0];
      if (!limit.offset) {
        limit.offset = 0;
      }
      var condition = '';
      if (dialect === 'mysql' || dialect === 'postgres' || dialect === 'sqlite') {
        callback((sql + (limit.rows ? (' LIMIT ' + limit.rows) : '') + ' OFFSET ' + limit.offset), values);
      } else if (dialect === 'oracle') {
        condition = '';
        if (limit.rows) {
          condition = 'WHERE rownum <= ' + limit.rows;
        }
        callback('SELECT * FROM ( SELECT tmp_table.*, rownum, row_id FROM ( ' + sql + ' ) tmp_table ' + condition + ' ) WHERE row_id > ' + limit.offset, values);
      } else if (dialect === 'mssql') {
        // MSSQL Server 2012
        condition = '';
        if (limit.rows) {
          condition = 'FETCH NEXT ' + limit.rows + ' ROWS ONLY';
        }
        callback(sql + ' OFFSET ' + limit.offset + ' ROWS ' + condition, values);
      } else {
        callback(sql, values);
      }
    }
  };
});
<commit_msg>fix syntax error<commit_after>'use strict';

module.exports = function(config) {
  return {
    afterParse: function(sql, values, plugin, callback) {
      var params = plugin.params;
      var dialect = plugin.ctx.dialect;
      if (params.length === 0 || !params[0]) {
        return callback(sql, values);
      }
      var limit = params[0];
      if (!limit.offset) {
        limit.offset = 0;
      }
      var condition = '';
      if (dialect === 'mysql' || dialect === 'postgres' || dialect === 'sqlite') {
        condition = '';
        callback((sql + (limit.rows ? (' LIMIT ' + limit.rows) : '') + ' OFFSET ' + limit.offset), values);
      } else if (dialect === 'oracle') {
        condition = '';
        if (limit.rows) {
          condition = 'WHERE rownum <= ' + limit.rows;
        }
        callback('SELECT * FROM ( SELECT tmp_table.*, rownum, row_id FROM ( ' + sql + ' ) tmp_table ' + condition + ' ) WHERE row_id > ' + limit.offset, values);
      } else if (dialect === 'mssql') {
        // MSSQL Server 2012
        condition = '';
        if (limit.rows) {
          condition = 'FETCH NEXT ' + limit.rows + ' ROWS ONLY';
        }
        callback(sql + ' OFFSET ' + limit.offset + ' ROWS ' + condition, values);
      } else {
        callback(sql, values);
      }
    }
  };
};
<|endoftext|>


<commit_before>var util = require('util');
var dgram = require('dgram');
var EventEmitter = require('events').EventEmitter;
var Netmask = require('netmask').Netmask;

module.exports = UDPServiceDiscovery;

function UDPServiceDiscovery(opts) {

    if (!(this instanceof UDPServiceDiscovery)) {
        return new UDPServiceDiscovery(opts);
    }

    this.emit('statusChanged', this.status);
    this.status = "INITIALIZING";

    opts = opts || {};

    this.broadcasterPort = typeof opts.port === 'undefined' ? 12345 : opts.port;
    this.broadcasterAddress = typeof opts.address === 'undefined' ? null : opts.address;
    this.announceInterval = typeof opts.announceInterval === 'undefined' ? 1000 : opts.announceInterval;

    this.serviceListenFor = null;
    this.serviceListenOnce = false;

    // Setup UDP socket
    this.socket = dgram.createSocket('udp4');

    // Setup message handler
    this.socket.on('message', ((data) => {
        var announcedService = JSONObjFromString(data);

        if (announcedService) {
            if (this.serviceListenFor) {
                var match = false;

                Object.keys(this.serviceListenFor).forEach(((key) => {
                    if (this.serviceListenFor[key] === announcedService[key]) {
                        match = true;
                    } else {
                        match = false;
                    }
                }));

                if (match) {
                    this.emit('discovery', announcedService);

                    if (this.serviceListenOnce) {
                        this.close();
                    }
                } else {
                    // no match
                }
            } else {
                this.emit('discovery', announcedService);

                if (this.serviceListenOnce) {
                    this.close();
                }
            }
        }
    }));

    this.socket.on('error', ((e) => {
        if (e.code === 'EADDRINUSE') {
            setTimeout(this.tryBinding, 210);
            console.log('[UDPServiceDiscovery] Retrying to open port');
        } else {
            console.log('[UDPServiceDiscovery] Err: ' + e);
        }
    }));

    this.socket.on('listening', (() => {
        this.socket.setBroadcast(true);

        // self.socket.setMulticastLoopback(true);
        // self.socket.addMembership(state.address, state.host);

        var address = this.socket.address();
        console.log('Listening on ' + address.address + ':' + address.port);
    }));

    this.socket.on('close', (() => {
        console.log('closing socket');
    }));
}

// name, ip, port, json object
// json object
UDPServiceDiscovery.prototype.broadcast = function broadcast() {
    var service = {host: null};
    var netmask;
    var host;
    var broadcastAddress;
    var announceMessage;

    switch (arguments.length) {
        case 4:
            if (typeof arguments[3] === 'string') {
                service = JSONObjFromString(arguments[3]);
            } else {
                service = arguments[3];
            }
        case 3:
            service.port = arguments[2];
        case 2:
            service.host = arguments[1];
            service.name = arguments[0];
            break;
        case 1:
            service = JSONObjFromString(arguments[0]);
            break;
    }

    announceMessage = new Buffer(JSON.stringify(service));

    announce = (() => {
        var mask = getLocalIPAndNetmask();
        if (mask.length > 0 && mask[0].length > 0) {
            netmask = mask[0][1];
            host = mask[0][0];
            broadcastAddress = getBroadcastAddress(host, netmask);

            if (host !== service.host) {
                service.host = host;
                announceMessage = new Buffer(JSON.stringify(service));
                this.emit('statusChanged', this.status);
            }

            if (host) {
                this.socket.send(announceMessage, 0, announceMessage.length, this.broadcasterPort, broadcastAddress, ((err, bytes) => {
                    if (err) {
                        console.log("UDP - Error announcing!", err);
                        throw err;
                    } else {
                        if (this.status !== 'BROADCASTING') {
                            this.status = "BROADCASTING";
                            this.emit('statusChanged', this.status);
                        }
                    }
                }));
            }
        } else {
            // Not connected
            this.status = "NOT_CONNECTED";
            this.emit('statusChanged', this.status);
        }
    });

    // announce once per second
    setInterval(announce, this.announceInterval);
};

UDPServiceDiscovery.prototype.listen = function listen(listenFor) {
    this.serviceListenOnce = false;

    if (listenFor) {
        if (typeof listenFor === 'string' && !JSONObjFromString(listenFor)) {
            this.serviceListenFor = {};
            this.serviceListenFor.name = listenFor;
        } else {
            if (typeof listenFor === 'string') {
                this.serviceListenFor = JSONObjFromString(listenFor);
            } else {
                this.serviceListenFor = listenFor;
            }
        }
    }

    this.tryBinding();
};

UDPServiceDiscovery.prototype.listenOnce = function listenOnce(listenFor) {
    this.serviceListenOnce = true;
    if (listenFor) {
        if (typeof listenFor === 'string' && !JSONObjFromString(listenFor)) {
            this.serviceListenFor = {};
            this.serviceListenFor.name = listenFor;
        } else {
            if (typeof listenFor === 'string') {
                this.serviceListenFor = JSONObjFromString(listenFor);
            } else {
                this.serviceListenFor = listenFor;
            }
        }
    }

    this.tryBinding();
};

UDPServiceDiscovery.prototype.tryBinding = function tryBinding() {
    this.socket.bind(this.broadcasterPort, this.broadcasterAddress);
};

UDPServiceDiscovery.prototype.close = function close() {
    this.socket.close();
};

util.inherits(UDPServiceDiscovery, EventEmitter);

function JSONObjFromString(jsonString) {
    try {
        var o = JSON.parse(jsonString);

        // Handle non-exception-throwing cases:
        // Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
        // but... JSON.parse(null) returns null, and typeof null === "object",
        // so we must check for that, too. Thankfully, null is falsey, so this suffices:
        if (o && typeof o === 'object') {
            return o;
        }
    } catch (err) {
    }
    return null;
}

function getLocalIPAndNetmask() {
    var networkInterfaces = require('os').networkInterfaces();
    var matches = [];

    Object.keys(networkInterfaces).forEach(function (item) {
        networkInterfaces[item].forEach(function (address) {
            if (address.internal === false && address.family === 'IPv4') {
                matches.push([address.address, address.netmask]);
            }
        });
    });

    return matches;
}

function getBroadcastAddress(ip, netmask) {
    console.log(ip, netmask);
    var block = new Netmask(ip + "/" + netmask);

    return block.broadcast;
}
<commit_msg>cleaned unnecessary brackets<commit_after>var util = require('util');
var dgram = require('dgram');
var EventEmitter = require('events').EventEmitter;
var Netmask = require('netmask').Netmask;

module.exports = UDPServiceDiscovery;

function UDPServiceDiscovery(opts) {

    if (!(this instanceof UDPServiceDiscovery)) {
        return new UDPServiceDiscovery(opts);
    }

    this.emit('statusChanged', this.status);
    this.status = "INITIALIZING";

    opts = opts || {};

    this.broadcasterPort = typeof opts.port === 'undefined' ? 12345 : opts.port;
    this.broadcasterAddress = typeof opts.address === 'undefined' ? null : opts.address;
    this.announceInterval = typeof opts.announceInterval === 'undefined' ? 1000 : opts.announceInterval;

    this.serviceListenFor = null;
    this.serviceListenOnce = false;

    // Setup UDP socket
    this.socket = dgram.createSocket('udp4');

    // Setup message handler
    this.socket.on('message', ((data) => {
        var announcedService = JSONObjFromString(data);

        if (announcedService) {
            if (this.serviceListenFor) {
                var match = false;

                Object.keys(this.serviceListenFor).forEach(key => {
                    if (this.serviceListenFor[key] === announcedService[key]) {
                        match = true;
                    } else {
                        match = false;
                    }
                });

                if (match) {
                    this.emit('discovery', announcedService);

                    if (this.serviceListenOnce) {
                        this.close();
                    }
                } else {
                    // no match
                }
            } else {
                this.emit('discovery', announcedService);

                if (this.serviceListenOnce) {
                    this.close();
                }
            }
        }
    }));

    this.socket.on('error', e => {
        if (e.code === 'EADDRINUSE') {
            setTimeout(this.tryBinding, 210);
            console.log('[UDPServiceDiscovery] Retrying to open port.');
        } else {
            console.log('[UDPServiceDiscovery] Err: ' + e);
        }
    });

    this.socket.on('listening', () => {
        this.socket.setBroadcast(true);

        // self.socket.setMulticastLoopback(true);
        // self.socket.addMembership(state.address, state.host);

        var address = this.socket.address();
        console.log('Listening on ' + address.address + ':' + address.port);
    });

    this.socket.on('close', () => {
        console.log('Closing socket.');
    });
}

// name, ip, port, json object
// json object
UDPServiceDiscovery.prototype.broadcast = function broadcast() {
    var service = {host: null};
    var netmask;
    var host;
    var broadcastAddress;
    var announceMessage;

    switch (arguments.length) {
        case 4:
            if (typeof arguments[3] === 'string') {
                service = JSONObjFromString(arguments[3]);
            } else {
                service = arguments[3];
            }
        case 3:
            service.port = arguments[2];
        case 2:
            service.host = arguments[1];
            service.name = arguments[0];
            break;
        case 1:
            service = JSONObjFromString(arguments[0]);
            break;
    }

    announceMessage = new Buffer(JSON.stringify(service));

    announce = (() => {
        var mask = getLocalIPAndNetmask();
        if (mask.length > 0 && mask[0].length > 0) {
            netmask = mask[0][1];
            host = mask[0][0];
            broadcastAddress = getBroadcastAddress(host, netmask);

            if (host !== service.host) {
                service.host = host;
                announceMessage = new Buffer(JSON.stringify(service));
                this.emit('statusChanged', this.status);
            }

            if (host) {
                this.socket.send(announceMessage, 0, announceMessage.length, this.broadcasterPort, broadcastAddress, ((err, bytes) => {
                    if (err) {
                        console.log("UDP - Error announcing!", err);
                        throw err;
                    } else {
                        if (this.status !== 'BROADCASTING') {
                            this.status = "BROADCASTING";
                            this.emit('statusChanged', this.status);
                        }
                    }
                }));
            }
        } else {
            // Not connected
            this.status = "NOT_CONNECTED";
            this.emit('statusChanged', this.status);
        }
    });

    // announce once per second
    setInterval(announce, this.announceInterval);
};

UDPServiceDiscovery.prototype.listen = function listen(listenFor) {
    this.serviceListenOnce = false;

    if (listenFor) {
        if (typeof listenFor === 'string' && !JSONObjFromString(listenFor)) {
            this.serviceListenFor = {};
            this.serviceListenFor.name = listenFor;
        } else {
            if (typeof listenFor === 'string') {
                this.serviceListenFor = JSONObjFromString(listenFor);
            } else {
                this.serviceListenFor = listenFor;
            }
        }
    }

    this.tryBinding();
};

UDPServiceDiscovery.prototype.listenOnce = function listenOnce(listenFor) {
    this.serviceListenOnce = true;
    if (listenFor) {
        if (typeof listenFor === 'string' && !JSONObjFromString(listenFor)) {
            this.serviceListenFor = {};
            this.serviceListenFor.name = listenFor;
        } else {
            if (typeof listenFor === 'string') {
                this.serviceListenFor = JSONObjFromString(listenFor);
            } else {
                this.serviceListenFor = listenFor;
            }
        }
    }

    this.tryBinding();
};

UDPServiceDiscovery.prototype.tryBinding = function tryBinding() {
    this.socket.bind(this.broadcasterPort, this.broadcasterAddress);
};

UDPServiceDiscovery.prototype.close = function close() {
    this.socket.close();
};

util.inherits(UDPServiceDiscovery, EventEmitter);

function JSONObjFromString(jsonString) {
    try {
        var o = JSON.parse(jsonString);

        // Handle non-exception-throwing cases:
        // Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
        // but... JSON.parse(null) returns null, and typeof null === "object",
        // so we must check for that, too. Thankfully, null is falsey, so this suffices:
        if (o && typeof o === 'object') {
            return o;
        }
    } catch (err) {
    }
    return null;
}

function getLocalIPAndNetmask() {
    var networkInterfaces = require('os').networkInterfaces();
    var matches = [];

    Object.keys(networkInterfaces).forEach(function (item) {
        networkInterfaces[item].forEach(function (address) {
            if (address.internal === false && address.family === 'IPv4') {
                matches.push([address.address, address.netmask]);
            }
        });
    });

    return matches;
}

function getBroadcastAddress(ip, netmask) {
    console.log(ip, netmask);
    var block = new Netmask(ip + "/" + netmask);

    return block.broadcast;
}
<|endoftext|>


<commit_before>var ffi = require('ffi')
  , ref = require('ref');

if(process.platform == 'win32') {
    var ulongPtr = ref.refType(ref.types.uint64);
    var DiskApi = ffi.Library('kernel32', {
        'GetDiskFreeSpaceExA': [ 'int', [ 'string', ulongPtr, ulongPtr, ulongPtr ] ]
    })

    exports.check = function(drive, callback) {
        var freeBytesPtr = ref.alloc(ref.types.uint64)
          , totalBytesPtr = ref.alloc(ref.types.uint64);
        var returnCode = DiskApi.GetDiskFreeSpaceExA(drive, freeBytesPtr, totalBytesPtr, ref.NULL_POINTER);
        if(!returnCode) {
            callback(returnCode, undefined);
        } else {
            callback(undefined, {
                free: freeBytesPtr.deref(),
                total: totalBytesPtr.deref()
            });
        }
    }
} else if(process.platform == 'linux' ||
          process.platform == 'freebsd' ||
          process.platform == 'darwin' ||
          process.platform == 'sunos' ) {

    var Struct = require('ref-struct')
      , ArrayType = require('ref-array');

    var fsblkcnt_t = ref.types.ulong
      , fsfilcnt_t = ref.types.ulong
      , ulong = ref.types.ulong
      , char = ref.types.char;

    var statvfs_t = Struct({
        'f_bsize': ulong,                       /* fundamental file system block size */
        'f_frsize': ulong,                      /* fragment size */
        'f_blocks': fsblkcnt_t,                 /* total blocks of f_frsize on fs */
        'f_bfree': fsblkcnt_t,                  /* total free blocks of f_frsize */
        'f_bavail': fsblkcnt_t,                 /* free blocks avail to non-superuser */
        'f_files': fsfilcnt_t,                  /* total file nodes (inodes) */
        'f_ffree': fsfilcnt_t,                  /* total free file nodes */
        'f_favail': fsfilcnt_t,                 /* free nodes avail to non-superuser */
        'f_fsid': ulong,                        /* file system id (dev for now) */
        'f_basetype': ArrayType(char, 16),      /* target fs type name, null-terminated */
        'f_flag': ulong,                        /* bit-mask of flags */
        'f_namemax': ulong,                     /* maximum file name length */
        'f_fstr': ArrayType(char, 32),          /* filesystem-specific string */
        'f_filler': ArrayType(ulong, 16)        /* reserved for future expansion */
    });

    // Do we depend on libc being loaded in the Node procces?
    var DiskApi = ffi.Library(null, {
        'statvfs': [ 'int', [ 'string', ref.refType(statvfs_t) ] ]
    })

    exports.check = function(drive, callback) {
        var statvfs = new statvfs_t();
        var returnCode = DiskApi.statvfs(drive, statvfs.ref());

        if(returnCode) {
            callback(returnCode, undefined);
        } else {
            callback(undefined, {
                free: statvfs.f_bfree * statvfs.f_frsize,
                total: statvfs.f_blocks * statvfs.f_frsize
            });
        }
    }
}
<commit_msg>Wrap the appropriate type in statvfs<commit_after>var ffi = require('ffi')
  , ref = require('ref');

if(process.platform == 'win32') {
    var ulongPtr = ref.refType(ref.types.uint64);
    var DiskApi = ffi.Library('kernel32', {
        'GetDiskFreeSpaceExA': [ 'int', [ 'string', ulongPtr, ulongPtr, ulongPtr ] ]
    })

    exports.check = function(drive, callback) {
        var freeBytesPtr = ref.alloc(ref.types.uint64)
          , totalBytesPtr = ref.alloc(ref.types.uint64);
        var returnCode = DiskApi.GetDiskFreeSpaceExA(drive, freeBytesPtr, totalBytesPtr, ref.NULL_POINTER);
        if(!returnCode) {
            callback(returnCode, undefined);
        } else {
            callback(undefined, {
                free: freeBytesPtr.deref(),
                total: totalBytesPtr.deref()
            });
        }
    }
} else if(process.platform == 'linux' ||
          process.platform == 'freebsd' ||
          process.platform == 'darwin' ||
          process.platform == 'sunos' ) {

    var Struct = require('ref-struct')
      , ArrayType = require('ref-array');

    var fsblkcnt_t = (process.platform == 'darwin') ? ref.types.uint : ref.types.ulong
      , fsfilcnt_t = (process.platform == 'darwin') ? ref.types.uint : ref.types.ulong
      , ulong = ref.types.ulong
      , char = ref.types.char;

    var statvfs_t = Struct({
        'f_bsize': ulong,                       /* fundamental file system block size */
        'f_frsize': ulong,                      /* fragment size */
        'f_blocks': fsblkcnt_t,                 /* total blocks of f_frsize on fs */
        'f_bfree': fsblkcnt_t,                  /* total free blocks of f_frsize */
        'f_bavail': fsblkcnt_t,                 /* free blocks avail to non-superuser */
        'f_files': fsfilcnt_t,                  /* total file nodes (inodes) */
        'f_ffree': fsfilcnt_t,                  /* total free file nodes */
        'f_favail': fsfilcnt_t,                 /* free nodes avail to non-superuser */
        'f_fsid': ulong,                        /* file system id (dev for now) */
        'f_basetype': ArrayType(char, 16),      /* target fs type name, null-terminated */
        'f_flag': ulong,                        /* bit-mask of flags */
        'f_namemax': ulong,                     /* maximum file name length */
        'f_fstr': ArrayType(char, 32),          /* filesystem-specific string */
        'f_filler': ArrayType(ulong, 16)        /* reserved for future expansion */
    });

    // Do we depend on libc being loaded in the Node procces?
    var DiskApi = ffi.Library(null, {
        'statvfs': [ 'int', [ 'string', ref.refType(statvfs_t) ] ]
    })

    exports.check = function(drive, callback) {
        var statvfs = new statvfs_t();
        var returnCode = DiskApi.statvfs(drive, statvfs.ref());

        if(returnCode) {
            callback(returnCode, undefined);
        } else {
            callback(undefined, {
                free: statvfs.f_bfree * statvfs.f_frsize,
                total: statvfs.f_blocks * statvfs.f_frsize
            });
        }
    }
}
<|endoftext|>


<commit_before>"use strict";

var http = require('http');
var fs = require('fs');
var crypto = require('crypto');
var constants = require('constants');
var assert = require('assert');
var MongoClient = require('mongodb').MongoClient;
var ObjectId = require('mongodb').ObjectID;

var url = 'mongodb://localhost:27017/thesis';

var insertDocument = function(db, gestures, callback) {
    db.collection('gestures').insertMany(gestures, function(err, result) {
        assert.equal(err, null);
        console.log("Inserted a document into the gestures collection.");
        callback(result);
    });
};

var server = http.createServer( function(req, res) {

    console.dir(req.param);

    if (req.method == 'POST') {
        console.log("POST");
        let body = '';
        req.on('data', function (data) {
            body += data;
            // console.log("Partial body: " + body);
        });
        req.on('end', function () {
            // console.log("Body: " + body);
            let payload = JSON.parse(body);
            if (process.env.PRIVATE_KEY_PATH === undefined) {
                console.error("Set PRIVATE_KEY_PATH to valid path to RSA PEM key");
            }

            let privateKeyString = fs.readFileSync(process.env.PRIVATE_KEY_PATH, { encoding: 'utf8' });
            let privateKey = {
                "key": privateKeyString,
                "padding": constants.RSA_PKCS1_PADDING
            };
            let sessionKey = crypto.privateDecrypt(privateKey, new Buffer(payload.session_key, 'base64'));
            let decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, new Buffer(payload.iv, 'base64'));
            let decdata = decipher.update(new Buffer(payload.data, 'base64'));
            decdata += decipher.final();

            let ts = Date.now();
            let gestures = JSON.parse(decdata.toString('utf-8'));

            for (var i = 0; i < gestures.length; i++) {
                gestures[i].timestamp = new Date(gestures[i].timestamp);
                gestures[i].deviceId = payload.device_id;
            };

            MongoClient.connect(url, function(err, db) {
                assert.equal(null, err);
                insertDocument(db, gestures, function() {
                    db.close();
                });
            });
        });
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('post received');
    }
    else
    {
        console.log("GET");
        // var html = '<form method="post" action="http://localhost:3000">Name: <input type="text" name="name" /><input type="submit" value="Submit" /></form>';
        var html = fs.readFileSync('index.html');
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end(html);
    }

});

var port = 9002;
var host = '0.0.0.0';
server.listen(port, host);
console.log('Listening at http://' + host + ':' + port);
<commit_msg>Store device_name in DB.<commit_after>"use strict";

var http = require('http');
var fs = require('fs');
var crypto = require('crypto');
var constants = require('constants');
var assert = require('assert');
var MongoClient = require('mongodb').MongoClient;
var ObjectId = require('mongodb').ObjectID;

var url = 'mongodb://localhost:27017/thesis';

var insertDocument = function(db, gestures, callback) {
    db.collection('gestures').insertMany(gestures, function(err, result) {
        assert.equal(err, null);
        console.log("Inserted a document into the gestures collection.");
        callback(result);
    });
};

var server = http.createServer( function(req, res) {

    console.dir(req.param);

    if (req.method == 'POST') {
        console.log("POST");
        let body = '';
        req.on('data', function (data) {
            body += data;
            // console.log("Partial body: " + body);
        });
        req.on('end', function () {
            // console.log("Body: " + body);
            let payload = JSON.parse(body);
            if (process.env.PRIVATE_KEY_PATH === undefined) {
                console.error("Set PRIVATE_KEY_PATH to valid path to RSA PEM key");
            }

            let privateKeyString = fs.readFileSync(process.env.PRIVATE_KEY_PATH, { encoding: 'utf8' });
            let privateKey = {
                "key": privateKeyString,
                "padding": constants.RSA_PKCS1_PADDING
            };
            let sessionKey = crypto.privateDecrypt(privateKey, new Buffer(payload.session_key, 'base64'));
            let decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, new Buffer(payload.iv, 'base64'));
            let decdata = decipher.update(new Buffer(payload.data, 'base64'));
            decdata += decipher.final();

            let ts = Date.now();
            let gestures = JSON.parse(decdata.toString('utf-8'));

            for (var i = 0; i < gestures.length; i++) {
                gestures[i].timestamp = new Date(gestures[i].timestamp);
                gestures[i].deviceId = payload.device_id;
                gestures[i].deviceName = payload.device_name;
            };

            MongoClient.connect(url, function(err, db) {
                assert.equal(null, err);
                insertDocument(db, gestures, function() {
                    db.close();
                });
            });
        });
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('post received');
    }
    else
    {
        console.log("GET");
        // var html = '<form method="post" action="http://localhost:3000">Name: <input type="text" name="name" /><input type="submit" value="Submit" /></form>';
        var html = fs.readFileSync('index.html');
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end(html);
    }

});

var port = 9002;
var host = '0.0.0.0';
server.listen(port, host);
console.log('Listening at http://' + host + ':' + port);
<|endoftext|>