<commit_before>const r = require('../r');
const model = require('../../../shared/model');
const db = require('./db');

function* createNote(note, itemType, itemId) {
    let n = yield db.insert('notes', note);
    let n2i = new model.Note2Item(itemId, itemId, n.id);
    yield db.insert('note2item', n2i);
    return n;
}

function* updateNote(note) {
    note.mtime = r.now();
    return yield db.update('notes', note.id, note);
}

function* updateNotes(notes) {
    for (let note of notes) {
        note.mtime = r.now();
    }

    return yield db.updateAll('notes', notes);
}

function* deleteNote(noteId) {
    yield r.table('notes').get(noteId).delete();
    yield r.table('note2item').getAll(noteId, {index: 'note_id'}).delete();
}

function* getAllNotesForItem(itemId) {
    return yield r.table('note2item')
        .getAll(itemId, {index: 'item_id'}).without('item_id', 'item_type')
        .eqJoin('note_id', r.table('notes')).without({left: {note_id: true}}).zip();
}

function getAllNotesForItemRQL(itemId) {
    return r.table('note2item')
        .getAll(itemId, {index: 'item_id'}).without('item_id', 'item_type')
        .eqJoin('note_id', r.table('notes')).without({left: {note_id: true}}).zip();
}

function* getNote(noteId) {
    return yield r.table('notes').get(noteId);
}

module.exports = {
    createNote,
    updateNote,
    updateNotes,
    deleteNote,
    getAllNotesForItem,
    getAllNotesForItemRQL,
    getNote,
};<commit_msg>Item id rather than item type was being set in the database<commit_after>const r = require('../r');
const model = require('../../../shared/model');
const db = require('./db');

function* createNote(note, itemType, itemId) {
    let n = yield db.insert('notes', note);
    let n2i = new model.Note2Item(itemId, itemType, n.id);
    yield db.insert('note2item', n2i);
    return n;
}

function* updateNote(note) {
    note.mtime = r.now();
    return yield db.update('notes', note.id, note);
}

function* updateNotes(notes) {
    for (let note of notes) {
        note.mtime = r.now();
    }

    return yield db.updateAll('notes', notes);
}

function* deleteNote(noteId) {
    yield r.table('notes').get(noteId).delete();
    yield r.table('note2item').getAll(noteId, {index: 'note_id'}).delete();
}

function* getAllNotesForItem(itemId) {
    return yield r.table('note2item')
        .getAll(itemId, {index: 'item_id'}).without('item_id', 'item_type')
        .eqJoin('note_id', r.table('notes')).without({left: {note_id: true}}).zip();
}

function getAllNotesForItemRQL(itemId) {
    return r.table('note2item')
        .getAll(itemId, {index: 'item_id'}).without('item_id', 'item_type')
        .eqJoin('note_id', r.table('notes')).without({left: {note_id: true}}).zip();
}

function* getNote(noteId) {
    return yield r.table('notes').get(noteId);
}

module.exports = {
    createNote,
    updateNote,
    updateNotes,
    deleteNote,
    getAllNotesForItem,
    getAllNotesForItemRQL,
    getNote,
};<|endoftext|>


<commit_before>/**
 * Turf is a modular geospatial analysis engine written in JavaScript. It performs geospatial
 * processing tasks with GeoJSON data and can be run on a server or in a browser.
 *
 * @module turf
 * @summary Geospatial analysis for JavaScript
 */
export {default as isolines} from '@turf/isolines';
export {default as convex} from '@turf/convex';
export {default as within} from '@turf/within';
export {default as concave} from '@turf/concave';
export {default as difference} from '@turf/difference';
export {default as dissolve} from '@turf/dissolve';
export {default as collect} from '@turf/collect';
export {default as flip} from '@turf/flip';
export {default as simplify} from '@turf/simplify';
export {default as bezier} from '@turf/bezier';
export {default as tag} from '@turf/tag';
export {default as sample} from '@turf/sample';
export {default as envelope} from '@turf/envelope';
export {default as square} from '@turf/square';
export {default as circle} from '@turf/circle';
export {default as midpoint} from '@turf/midpoint';
export {default as buffer} from '@turf/buffer';
export {default as center} from '@turf/center';
export {default as centerOfMass} from '@turf/center-of-mass';
export {default as centroid} from '@turf/centroid';
export {default as combine} from '@turf/combine';
export {default as distance} from '@turf/distance';
export {default as explode} from '@turf/explode';
export {default as bbox} from '@turf/bbox';
export {default as tesselate} from '@turf/tesselate';
export {default as bboxPolygon} from '@turf/bbox-polygon';
export {default as inside} from '@turf/inside';
export {default as intersect} from '@turf/intersect';
export {default as nearest} from '@turf/nearest';
export {default as planepoint} from '@turf/planepoint';
export {default as random} from '@turf/random';
export {default as tin} from '@turf/tin';
export {default as union} from '@turf/union';
export {default as bearing} from '@turf/bearing';
export {default as destination} from '@turf/destination';
export {default as kinks} from '@turf/kinks';
export {default as pointOnSurface} from '@turf/point-on-surface';
export {default as area} from '@turf/area';
export {default as along} from '@turf/along';
export {default as lineDistance} from '@turf/line-distance';
export {default as lineSlice} from '@turf/line-slice';
export {default as lineSliceAlong} from '@turf/line-slice-along';
export {default as pointOnLine} from '@turf/point-on-line';
export {default as pointGrid} from '@turf/point-grid';
export {default as squareGrid} from '@turf/square-grid';
export {default as triangleGrid} from '@turf/triangle-grid';
export {default as hexGrid} from '@turf/hex-grid';
export {default as idw} from '@turf/idw';
export {default as truncate} from '@turf/truncate';
export {default as flatten} from '@turf/flatten';
export {default as lineIntersect} from '@turf/line-intersect';
export {default as mask} from '@turf/mask';
export {default as lineChunk} from '@turf/line-chunk';
export {default as unkinkPolygon} from '@turf/unkink-polygon';
export {default as greatCircle} from '@turf/great-circle';
export {default as lineSegment} from '@turf/line-segment';
export {default as lineSplit} from '@turf/line-split';
export {default as lineArc} from '@turf/line-arc';
export {default as polygonToLineString} from '@turf/polygon-to-linestring';
export {default as lineStringToPolygon} from '@turf/linestring-to-polygon';
export {default as bboxClip} from '@turf/bbox-clip';
export {default as lineOverlap} from '@turf/line-overlap';
export {default as sector} from '@turf/sector';
export {default as rhumbBearing} from '@turf/rhumb-bearing';
export {default as rhumbDistance} from '@turf/rhumb-distance';
export {default as rhumbDestination} from '@turf/rhumb-destination';
export {default as polygonTangents} from '@turf/polygon-tangents';
export {default as rewind} from '@turf/rewind';
export {default as isobands} from '@turf/isobands';
export {default as transformRotate} from '@turf/transform-rotate';
export {default as transformScale} from '@turf/transform-scale';
export {default as transformTranslate} from '@turf/transform-translate';
export {default as lineOffset} from '@turf/line-offset';
export {default as polygonize} from '@turf/polygonize';
export {default as booleanDisjoint} from '@turf/boolean-disjoint';
export {default as booleanContains} from '@turf/boolean-contains';
export {default as booleanCrosses} from '@turf/boolean-crosses';
export {default as booleanClockwise} from '@turf/boolean-clockwise';
export {default as booleanOverlap} from '@turf/boolean-overlap';
export {default as booleanPointOnLine} from '@turf/boolean-point-on-line';
export {default as booleanEqual} from '@turf/boolean-equal';
export {default as booleanWithin} from '@turf/boolean-within';
export {default as clone} from '@turf/clone';
export {default as cleanCoords} from '@turf/clean-coords';
export {default as interpolate} from '@turf/interpolate';
export {default as clustersDbscan} from '@turf/clusters-dbscan';
export {default as clustersKmeans} from '@turf/clusters-kmeans';
export {default as pointToLineDistance} from '@turf/point-to-line-distance';
export {default as booleanParallel} from '@turf/boolean-parallel';
export {default as nearestPointToLine} from '@turf/nearest-point-to-line';
export {
    toMercator,
    toWgs84
} from '@turf/projection';
import * as projection from '@turf/projection';
export { projection };
export {
    getCluster,
    clusterEach,
    clusterReduce
} from '@turf/clusters';
import * as clusters from '@turf/clusters';
export { clusters };
export {
    point,
    polygon,
    lineString,
    multiPoint,
    multiPolygon,
    multiLineString,
    feature,
    geometry,
    featureCollection,
    geometryCollection,
    radiansToDistance,
    distanceToRadians,
    distanceToDegrees,
    bearingToAngle,
    degrees2radians,
    radians2degrees,
    convertDistance,
    isNumber,
    round,
    convertArea
} from '@turf/helpers';
import * as helpers from '@turf/helpers';
export { helpers };
export {
    getCoord,
    getCoords,
    geojsonType,
    featureOf,
    collectionOf,
    containsNumber,
    getType,
    getGeom
} from '@turf/invariant';
import * as invariant from '@turf/invariant';
export { invariant };
export {
    coordEach,
    coordReduce,
    propEach,
    propReduce,
    featureEach,
    featureReduce,
    coordAll,
    geomEach,
    geomReduce,
    flattenEach,
    flattenReduce,
    segmentReduce,
    segmentEach,
    lineEach,
    lineReduce
} from '@turf/meta';
import * as meta from '@turf/meta';
export { meta };
<commit_msg>adds isObject to packages/turf/index.js<commit_after>/**
 * Turf is a modular geospatial analysis engine written in JavaScript. It performs geospatial
 * processing tasks with GeoJSON data and can be run on a server or in a browser.
 *
 * @module turf
 * @summary Geospatial analysis for JavaScript
 */
export {default as isolines} from '@turf/isolines';
export {default as convex} from '@turf/convex';
export {default as within} from '@turf/within';
export {default as concave} from '@turf/concave';
export {default as difference} from '@turf/difference';
export {default as dissolve} from '@turf/dissolve';
export {default as collect} from '@turf/collect';
export {default as flip} from '@turf/flip';
export {default as simplify} from '@turf/simplify';
export {default as bezier} from '@turf/bezier';
export {default as tag} from '@turf/tag';
export {default as sample} from '@turf/sample';
export {default as envelope} from '@turf/envelope';
export {default as square} from '@turf/square';
export {default as circle} from '@turf/circle';
export {default as midpoint} from '@turf/midpoint';
export {default as buffer} from '@turf/buffer';
export {default as center} from '@turf/center';
export {default as centerOfMass} from '@turf/center-of-mass';
export {default as centroid} from '@turf/centroid';
export {default as combine} from '@turf/combine';
export {default as distance} from '@turf/distance';
export {default as explode} from '@turf/explode';
export {default as bbox} from '@turf/bbox';
export {default as tesselate} from '@turf/tesselate';
export {default as bboxPolygon} from '@turf/bbox-polygon';
export {default as inside} from '@turf/inside';
export {default as intersect} from '@turf/intersect';
export {default as nearest} from '@turf/nearest';
export {default as planepoint} from '@turf/planepoint';
export {default as random} from '@turf/random';
export {default as tin} from '@turf/tin';
export {default as union} from '@turf/union';
export {default as bearing} from '@turf/bearing';
export {default as destination} from '@turf/destination';
export {default as kinks} from '@turf/kinks';
export {default as pointOnSurface} from '@turf/point-on-surface';
export {default as area} from '@turf/area';
export {default as along} from '@turf/along';
export {default as lineDistance} from '@turf/line-distance';
export {default as lineSlice} from '@turf/line-slice';
export {default as lineSliceAlong} from '@turf/line-slice-along';
export {default as pointOnLine} from '@turf/point-on-line';
export {default as pointGrid} from '@turf/point-grid';
export {default as squareGrid} from '@turf/square-grid';
export {default as triangleGrid} from '@turf/triangle-grid';
export {default as hexGrid} from '@turf/hex-grid';
export {default as idw} from '@turf/idw';
export {default as truncate} from '@turf/truncate';
export {default as flatten} from '@turf/flatten';
export {default as lineIntersect} from '@turf/line-intersect';
export {default as mask} from '@turf/mask';
export {default as lineChunk} from '@turf/line-chunk';
export {default as unkinkPolygon} from '@turf/unkink-polygon';
export {default as greatCircle} from '@turf/great-circle';
export {default as lineSegment} from '@turf/line-segment';
export {default as lineSplit} from '@turf/line-split';
export {default as lineArc} from '@turf/line-arc';
export {default as polygonToLineString} from '@turf/polygon-to-linestring';
export {default as lineStringToPolygon} from '@turf/linestring-to-polygon';
export {default as bboxClip} from '@turf/bbox-clip';
export {default as lineOverlap} from '@turf/line-overlap';
export {default as sector} from '@turf/sector';
export {default as rhumbBearing} from '@turf/rhumb-bearing';
export {default as rhumbDistance} from '@turf/rhumb-distance';
export {default as rhumbDestination} from '@turf/rhumb-destination';
export {default as polygonTangents} from '@turf/polygon-tangents';
export {default as rewind} from '@turf/rewind';
export {default as isobands} from '@turf/isobands';
export {default as transformRotate} from '@turf/transform-rotate';
export {default as transformScale} from '@turf/transform-scale';
export {default as transformTranslate} from '@turf/transform-translate';
export {default as lineOffset} from '@turf/line-offset';
export {default as polygonize} from '@turf/polygonize';
export {default as booleanDisjoint} from '@turf/boolean-disjoint';
export {default as booleanContains} from '@turf/boolean-contains';
export {default as booleanCrosses} from '@turf/boolean-crosses';
export {default as booleanClockwise} from '@turf/boolean-clockwise';
export {default as booleanOverlap} from '@turf/boolean-overlap';
export {default as booleanPointOnLine} from '@turf/boolean-point-on-line';
export {default as booleanEqual} from '@turf/boolean-equal';
export {default as booleanWithin} from '@turf/boolean-within';
export {default as clone} from '@turf/clone';
export {default as cleanCoords} from '@turf/clean-coords';
export {default as interpolate} from '@turf/interpolate';
export {default as clustersDbscan} from '@turf/clusters-dbscan';
export {default as clustersKmeans} from '@turf/clusters-kmeans';
export {default as pointToLineDistance} from '@turf/point-to-line-distance';
export {default as booleanParallel} from '@turf/boolean-parallel';
export {default as nearestPointToLine} from '@turf/nearest-point-to-line';
export {
    toMercator,
    toWgs84
} from '@turf/projection';
import * as projection from '@turf/projection';
export { projection };
export {
    getCluster,
    clusterEach,
    clusterReduce
} from '@turf/clusters';
import * as clusters from '@turf/clusters';
export { clusters };
export {
    point,
    polygon,
    lineString,
    multiPoint,
    multiPolygon,
    multiLineString,
    feature,
    geometry,
    featureCollection,
    geometryCollection,
    radiansToDistance,
    distanceToRadians,
    distanceToDegrees,
    bearingToAngle,
    degrees2radians,
    radians2degrees,
    convertDistance,
    isNumber,
    isObject,
    round,
    convertArea
} from '@turf/helpers';
import * as helpers from '@turf/helpers';
export { helpers };
export {
    getCoord,
    getCoords,
    geojsonType,
    featureOf,
    collectionOf,
    containsNumber,
    getType,
    getGeom
} from '@turf/invariant';
import * as invariant from '@turf/invariant';
export { invariant };
export {
    coordEach,
    coordReduce,
    propEach,
    propReduce,
    featureEach,
    featureReduce,
    coordAll,
    geomEach,
    geomReduce,
    flattenEach,
    flattenReduce,
    segmentReduce,
    segmentEach,
    lineEach,
    lineReduce
} from '@turf/meta';
import * as meta from '@turf/meta';
export { meta };
<|endoftext|>


<commit_before>'use strict';

var db = require('../../db')
  , serializeValue = require('dbjs/_setup/serialize/value')
  , mano = require('mano')
  , dbDriver = mano.dbDriver
  , deferred = require('deferred')
  , userStorage = dbDriver.getStorage('user')
  , User = require('../../model/user')(db);

module.exports = function (data) {
	var def = deferred(), email;
	try {
		email = User.prototype.getOwnDescriptor('email').type.validate(data.email);
		def.resolve(email);
	} catch (err) {
		def.reject(err);
	}

	return def.promise.then(function (email) {
		return userStorage.searchOne({
			key: 'email',
			value: serializeValue(email)
		}, function (foundRecord) {
			return foundRecord;
		}).then(function (foundRecord) {
			if (foundRecord) return;
			return mano.queryMemoryDb([], 'addUserByEmail', JSON.stringify(data));
		});
	});
};
<commit_msg>#1912 made the method return the id of the found user<commit_after>'use strict';

var db = require('../../db')
  , serializeValue = require('dbjs/_setup/serialize/value')
  , mano = require('mano')
  , dbDriver = mano.dbDriver
  , deferred = require('deferred')
  , userStorage = dbDriver.getStorage('user')
  , User = require('../../model/user')(db);

module.exports = function (data) {
	var def = deferred(), email;
	try {
		email = User.prototype.getOwnDescriptor('email').type.validate(data.email);
		def.resolve(email);
	} catch (err) {
		def.reject(err);
	}

	return def.promise.then(function (email) {
		return userStorage.searchOne({
			key: 'email',
			value: serializeValue(email)
		}, function (foundRecord) {
			return foundRecord.split('/')[0];
		}).then(function (foundId) {
			if (foundId) return foundId;
			return mano.queryMemoryDb([], 'addUser', JSON.stringify(data));
		});
	});
};
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A component handler interface using the revealing module design pattern.
 * More details on this design pattern here:
 * https://github.com/jasonmayes/mdl-component-design-pattern
 * @author Jason Mayes.
 */
/* exported componentHandler */
var componentHandler = (function() {
  'use strict';

  var registeredComponents_ = [];
  var createdComponents_ = [];
  var downgradeMethod_ = 'mdlDowngrade_';
  var componentConfigProperty_ = 'mdlComponentConfigInternal_';

  /**
   * Searches registered components for a class we are interested in using.
   * Optionally replaces a match with passed object if specified.
   * @param {string} name The name of a class we want to use.
   * @param {object} optReplace Optional object to replace match with.
   * @return {object | false}
   * @private
   */
  function findRegisteredClass_(name, optReplace) {
    for (var i = 0; i < registeredComponents_.length; i++) {
      if (registeredComponents_[i].className === name) {
        if (optReplace !== undefined) {
          registeredComponents_[i] = optReplace;
        }
        return registeredComponents_[i];
      }
    }
    return false;
  }

  /**
   * Searches existing DOM for elements of our component type and upgrades them
   * if they have not already been upgraded.
   * @param {string} jsClass the programatic name of the element class we need
   * to create a new instance of.
   * @param {string} cssClass the name of the CSS class elements of this type
   * will have.
   */
  function upgradeDomInternal(jsClass, cssClass) {
    if (jsClass === undefined && cssClass === undefined) {
      for (var i = 0; i < registeredComponents_.length; i++) {
        upgradeDomInternal(registeredComponents_[i].className,
            registeredComponents_[i].cssClass);
      }
    } else {
      if (cssClass === undefined) {
        var registeredClass = findRegisteredClass_(jsClass);
        if (registeredClass) {
          cssClass = registeredClass.cssClass;
        }
      }

      var elements = document.querySelectorAll('.' + cssClass);
      for (var n = 0; n < elements.length; n++) {
        upgradeElementInternal(elements[n], jsClass);
      }
    }
  }

  /**
   * Upgrades a specific element rather than all in the DOM.
   * @param {HTMLElement} element The element we wish to upgrade.
   * @param {string} jsClass The name of the class we want to upgrade
   * the element to.
   */
  function upgradeElementInternal(element, jsClass) {
    if (jsClass === undefined) {
      for (var i = 0; i < registeredComponents_.length; i++) {
        if (element.classList.contains(registeredComponents_[i].cssClass)) {
          upgradeElementInternal(element, registeredComponents_[i].className);
        }
      }
      return;
    }

    // Only upgrade elements that have not already been upgraded.
    var dataUpgraded = element.getAttribute('data-upgraded');

    if (dataUpgraded === null || dataUpgraded.indexOf(jsClass) === -1) {
      // Upgrade element.
      if (dataUpgraded === null) {
        dataUpgraded = '';
      }
      element.setAttribute('data-upgraded', dataUpgraded + ',' + jsClass);
      var registeredClass = findRegisteredClass_(jsClass);
      if (registeredClass) {
        // new
        var instance = new registeredClass.classConstructor(element);
        instance[componentConfigProperty_] = registeredClass;
        createdComponents_.push(instance);
        // Call any callbacks the user has registered with this component type.
        registeredClass.callbacks.forEach(function(callback) {
          callback(element);
        });

        if (registeredClass.widget) {
          // Assign per element instance for control over API
          element[jsClass] = instance;
        }
      } else {
        throw new Error(
          'Unable to find a registered component for the given class.');
      }

      var ev = document.createEvent('Events');
      ev.initEvent('mdl-componentupgraded', true, true);
      element.dispatchEvent(ev);
    }
  }

  /**
   * Registers a class for future use and attempts to upgrade existing DOM.
   * @param {object} config An object containing:
   * {constructor: Constructor, classAsString: string, cssClass: string}
   */
  function registerInternal(config) {
    var newConfig = {
      'classConstructor': config.constructor,
      'className': config.classAsString,
      'cssClass': config.cssClass,
      'widget': config.widget === undefined ? true : config.widget,
      'callbacks': []
    };

    registeredComponents_.forEach(function(item) {
      if (item.cssClass === newConfig.cssClass) {
        throw new Error('The provided cssClass has already been registered.');
      }
      if (item.className === newConfig.className) {
        throw new Error('The provided className has already been registered');
      }
    });

    if (config.constructor.prototype
        .hasOwnProperty(componentConfigProperty_)) {
      throw new Error(
        'MDL component classes must not have ' + componentConfigProperty_ +
          ' defined as a property.');
    }

    var found = findRegisteredClass_(config.classAsString, newConfig);

    if (!found) {
      registeredComponents_.push(newConfig);
    }
  }

  /**
   * Allows user to be alerted to any upgrades that are performed for a given
   * component type
   * @param {string} jsClass The class name of the MDL component we wish
   * to hook into for any upgrades performed.
   * @param {function} callback The function to call upon an upgrade. This
   * function should expect 1 parameter - the HTMLElement which got upgraded.
   */
  function registerUpgradedCallbackInternal(jsClass, callback) {
    var regClass = findRegisteredClass_(jsClass);
    if (regClass) {
      regClass.callbacks.push(callback);
    }
  }

  /**
   * Upgrades all registered components found in the current DOM. This is
   * automatically called on window load.
   */
  function upgradeAllRegisteredInternal() {
    for (var n = 0; n < registeredComponents_.length; n++) {
      upgradeDomInternal(registeredComponents_[n].className);
    }
  }

  /**
   * Finds a created component by a given DOM node.
   *
   * @param {!Element} node
   * @return {*}
   */
  function findCreatedComponentByNodeInternal(node) {
    for (var n = 0; n < createdComponents_.length; n++) {
      var component = createdComponents_[n];
      if (component.element_ === node) {
        return component;
      }
    }
  }

  /**
   * Check the component for the downgrade method.
   * Execute if found.
   * Remove component from createdComponents list.
   *
   * @param {*} component
   */
  function deconstructComponentInternal(component) {
    if (component &&
        component[componentConfigProperty_]
          .classConstructor.prototype
          .hasOwnProperty(downgradeMethod_)) {
      component[downgradeMethod_]();
      var componentIndex = createdComponents_.indexOf(component);
      createdComponents_.splice(componentIndex, 1);

      var upgrades = component.element_.dataset.upgraded.split(',');
      var componentPlace = upgrades.indexOf(
          component[componentConfigProperty_].classAsString);
      upgrades.splice(componentPlace, 1);
      component.element_.dataset.upgraded = upgrades.join(',');

      var ev = document.createEvent('Events');
      ev.initEvent('mdl-componentdowngraded', true, true);
      component.element_.dispatchEvent(ev);
    }
  }

  /**
   * Downgrade either a given node, an array of nodes, or a NodeList.
   *
   * @param {*} nodes
   */
  function downgradeNodesInternal(nodes) {
    var downgradeNode = function(node) {
      deconstructComponentInternal(findCreatedComponentByNodeInternal(node));
    };
    if (nodes instanceof Array || nodes instanceof NodeList) {
      for (var n = 0; n < nodes.length; n++) {
        downgradeNode(nodes[n]);
      }
    } else if (nodes instanceof Node) {
      downgradeNode(nodes);
    } else {
      throw new Error('Invalid argument provided to downgrade MDL nodes.');
    }
  }

  // Now return the functions that should be made public with their publicly
  // facing names...
  return {
    upgradeDom: upgradeDomInternal,
    upgradeElement: upgradeElementInternal,
    upgradeAllRegistered: upgradeAllRegisteredInternal,
    registerUpgradedCallback: registerUpgradedCallbackInternal,
    register: registerInternal,
    downgradeElements: downgradeNodesInternal
  };
})();

window.addEventListener('load', function() {
  'use strict';

  /**
   * Performs a "Cutting the mustard" test. If the browser supports the features
   * tested, adds a mdl-js class to the <html> element. It then upgrades all MDL
   * components requiring JavaScript.
   */
  if ('classList' in document.createElement('div') &&
      'querySelector' in document &&
      'addEventListener' in window && Array.prototype.forEach) {
    document.documentElement.classList.add('mdl-js');
    componentHandler.upgradeAllRegistered();
  } else {
    componentHandler.upgradeElement =
        componentHandler.register = function() {};
  }
});
<commit_msg>Improve upgradeElement CSS class detection<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * A component handler interface using the revealing module design pattern.
 * More details on this design pattern here:
 * https://github.com/jasonmayes/mdl-component-design-pattern
 * @author Jason Mayes.
 */
/* exported componentHandler */
var componentHandler = (function() {
  'use strict';

  var registeredComponents_ = [];
  var createdComponents_ = [];
  var downgradeMethod_ = 'mdlDowngrade_';
  var componentConfigProperty_ = 'mdlComponentConfigInternal_';

  /**
   * Searches registered components for a class we are interested in using.
   * Optionally replaces a match with passed object if specified.
   * @param {string} name The name of a class we want to use.
   * @param {object} optReplace Optional object to replace match with.
   * @return {object | false}
   * @private
   */
  function findRegisteredClass_(name, optReplace) {
    for (var i = 0; i < registeredComponents_.length; i++) {
      if (registeredComponents_[i].className === name) {
        if (optReplace !== undefined) {
          registeredComponents_[i] = optReplace;
        }
        return registeredComponents_[i];
      }
    }
    return false;
  }

  /**
   * Returns true if the given element has already been upgraded for the given
   * class.
   * @param {HTMLElement} element The element we want to check.
   * @param {string} jsClass The class to check for.
   * @return boolean
   * @private
   */
  function isElementUpgraded_(element, jsClass) {
    var dataUpgraded = element.getAttribute('data-upgraded');
    return dataUpgraded && dataUpgraded.indexOf(jsClass) !== -1;
  }

  /**
   * Searches existing DOM for elements of our component type and upgrades them
   * if they have not already been upgraded.
   * @param {string} jsClass the programatic name of the element class we need
   * to create a new instance of.
   * @param {string} cssClass the name of the CSS class elements of this type
   * will have.
   */
  function upgradeDomInternal(jsClass, cssClass) {
    if (jsClass === undefined && cssClass === undefined) {
      for (var i = 0; i < registeredComponents_.length; i++) {
        upgradeDomInternal(registeredComponents_[i].className,
            registeredComponents_[i].cssClass);
      }
    } else {
      if (cssClass === undefined) {
        var registeredClass = findRegisteredClass_(jsClass);
        if (registeredClass) {
          cssClass = registeredClass.cssClass;
        }
      }

      var elements = document.querySelectorAll('.' + cssClass);
      for (var n = 0; n < elements.length; n++) {
        upgradeElementInternal(elements[n], jsClass);
      }
    }
  }

  /**
   * Upgrades a specific element rather than all in the DOM.
   * @param {HTMLElement} element The element we wish to upgrade.
   * @param {string} optJsClass Optional name of the class we want to upgrade
   * the element to.
   */
  function upgradeElementInternal(element, optJsClass) {
    // Only upgrade elements that have not already been upgraded.
    var dataUpgraded = element.getAttribute('data-upgraded');

    var registeredClasses = [];
    // If jsClass is not provided scan the registered components to find the
    // ones matching the element's CSS classList.
    if (!optJsClass) {
      registeredClasses = registeredComponents_.filter(function(component) {
        return element.classList.contains(component.cssClass) &&
          !isElementUpgraded_(element, component.className);
      });
    } else if (!isElementUpgraded_(element, optJsClass)) {
      registeredClasses.push(findRegisteredClass_(optJsClass));
    }

    // Upgrade the element for each classes.
    for (var i = 0, l = registeredClasses.length; i < l; i++) {
      var registeredClass = registeredClasses[i];
      if (registeredClass) {
        // Mark element as upgraded.
        if (dataUpgraded === null) {
          dataUpgraded = '';
        }
        element.setAttribute('data-upgraded', dataUpgraded + ',' +
          registeredClass.className);
        var instance = new registeredClass.classConstructor(element);
        instance[componentConfigProperty_] = registeredClass;
        createdComponents_.push(instance);
        // Call any callbacks the user has registered with this component type.
        for (var j = 0, len = registeredClass.callbacks.length; j < len; i++) {
          registeredClass.callbacks[i](element);
        }

        if (registeredClass.widget) {
          // Assign per element instance for control over API
          element[registeredClass.className] = instance;
        }
      } else {
        throw new Error(
          'Unable to find a registered component for the given class.');
      }

      var ev = document.createEvent('Events');
      ev.initEvent('mdl-componentupgraded', true, true);
      element.dispatchEvent(ev);
    }
  }

  /**
   * Registers a class for future use and attempts to upgrade existing DOM.
   * @param {object} config An object containing:
   * {constructor: Constructor, classAsString: string, cssClass: string}
   */
  function registerInternal(config) {
    var newConfig = {
      'classConstructor': config.constructor,
      'className': config.classAsString,
      'cssClass': config.cssClass,
      'widget': config.widget === undefined ? true : config.widget,
      'callbacks': []
    };

    registeredComponents_.forEach(function(item) {
      if (item.cssClass === newConfig.cssClass) {
        throw new Error('The provided cssClass has already been registered.');
      }
      if (item.className === newConfig.className) {
        throw new Error('The provided className has already been registered');
      }
    });

    if (config.constructor.prototype
        .hasOwnProperty(componentConfigProperty_)) {
      throw new Error(
        'MDL component classes must not have ' + componentConfigProperty_ +
          ' defined as a property.');
    }

    var found = findRegisteredClass_(config.classAsString, newConfig);

    if (!found) {
      registeredComponents_.push(newConfig);
    }
  }

  /**
   * Allows user to be alerted to any upgrades that are performed for a given
   * component type
   * @param {string} jsClass The class name of the MDL component we wish
   * to hook into for any upgrades performed.
   * @param {function} callback The function to call upon an upgrade. This
   * function should expect 1 parameter - the HTMLElement which got upgraded.
   */
  function registerUpgradedCallbackInternal(jsClass, callback) {
    var regClass = findRegisteredClass_(jsClass);
    if (regClass) {
      regClass.callbacks.push(callback);
    }
  }

  /**
   * Upgrades all registered components found in the current DOM. This is
   * automatically called on window load.
   */
  function upgradeAllRegisteredInternal() {
    for (var n = 0; n < registeredComponents_.length; n++) {
      upgradeDomInternal(registeredComponents_[n].className);
    }
  }

  /**
   * Finds a created component by a given DOM node.
   *
   * @param {!Element} node
   * @return {*}
   */
  function findCreatedComponentByNodeInternal(node) {
    for (var n = 0; n < createdComponents_.length; n++) {
      var component = createdComponents_[n];
      if (component.element_ === node) {
        return component;
      }
    }
  }

  /**
   * Check the component for the downgrade method.
   * Execute if found.
   * Remove component from createdComponents list.
   *
   * @param {*} component
   */
  function deconstructComponentInternal(component) {
    if (component &&
        component[componentConfigProperty_]
          .classConstructor.prototype
          .hasOwnProperty(downgradeMethod_)) {
      component[downgradeMethod_]();
      var componentIndex = createdComponents_.indexOf(component);
      createdComponents_.splice(componentIndex, 1);

      var upgrades = component.element_.dataset.upgraded.split(',');
      var componentPlace = upgrades.indexOf(
          component[componentConfigProperty_].classAsString);
      upgrades.splice(componentPlace, 1);
      component.element_.dataset.upgraded = upgrades.join(',');

      var ev = document.createEvent('Events');
      ev.initEvent('mdl-componentdowngraded', true, true);
      component.element_.dispatchEvent(ev);
    }
  }

  /**
   * Downgrade either a given node, an array of nodes, or a NodeList.
   *
   * @param {*} nodes
   */
  function downgradeNodesInternal(nodes) {
    var downgradeNode = function(node) {
      deconstructComponentInternal(findCreatedComponentByNodeInternal(node));
    };
    if (nodes instanceof Array || nodes instanceof NodeList) {
      for (var n = 0; n < nodes.length; n++) {
        downgradeNode(nodes[n]);
      }
    } else if (nodes instanceof Node) {
      downgradeNode(nodes);
    } else {
      throw new Error('Invalid argument provided to downgrade MDL nodes.');
    }
  }

  // Now return the functions that should be made public with their publicly
  // facing names...
  return {
    upgradeDom: upgradeDomInternal,
    upgradeElement: upgradeElementInternal,
    upgradeAllRegistered: upgradeAllRegisteredInternal,
    registerUpgradedCallback: registerUpgradedCallbackInternal,
    register: registerInternal,
    downgradeElements: downgradeNodesInternal
  };
})();

window.addEventListener('load', function() {
  'use strict';

  /**
   * Performs a "Cutting the mustard" test. If the browser supports the features
   * tested, adds a mdl-js class to the <html> element. It then upgrades all MDL
   * components requiring JavaScript.
   */
  if ('classList' in document.createElement('div') &&
      'querySelector' in document &&
      'addEventListener' in window && Array.prototype.forEach) {
    document.documentElement.classList.add('mdl-js');
    componentHandler.upgradeAllRegistered();
  } else {
    componentHandler.upgradeElement =
        componentHandler.register = function() {};
  }
});
<|endoftext|>


<commit_before>/**
 * Created by opdah023 on 10/9/14.
 */
'use strict';
 //When we tested this function, it worked correctly with only two
 //parameters given, until we checked the final else case, in which
 // case it broke with only two parameters
angular.module('umm3601ursamajorApp')
    .filter('isntEmpty', function(){
        return function(input, title, altTitle){
            if(typeof(input) == "object"){
                if(input.length > 0){
                    return title + " " + input;
                }
            } else if (input !== "" && input !== null){
                return title + " " + input;
            } else {
                return altTitle;
            }
        }
    })

    .filter('fancyLimitTo', function(){
        return function(input, limit){
            return input.substring(0, limit) + "[...]";
        }
    })

    .controller('SublistCtrl', function ($scope, $http, socket, $modal, Modal, Auth, $window, $filter) {
        $scope.submissions = [];
        $scope.status = [];

        $scope.getCurrentUser = Auth.getCurrentUser;
        $scope.group = Auth.getCurrentUser().group;
        $scope.email = Auth.getCurrentUser().email;
        $scope.isReviewer = Auth.isReviewer;
        $scope.isAdmin = Auth.isAdmin;
        $scope.isCoChair = Auth.isCoChair;

        //--------------------- Filter Functions -----------------------

        $scope.filterData = {
            searchText: "",
            orderByPredicate: "",
            reviewGroupFilterSelection: "All",
            reviewGroupFilterOptions: [
                "All",
                "Unassigned",
                "Review Group 1",
                "Review Group 2",
                "Review Group 3",
                "Review Group 4"
            ],
            tabFilter: {isPresenter:false, isCoPresenter:false, isReviewer:false, isAdviser:false}
        };

        $scope.setReviewGroupSelection = function(str) {
            $scope.filterData.reviewGroupFilterSelection = str;
        };

        $scope.hasAdminPrivs = function(){
            return (($scope.getCurrentUser.role != null && $scope.getCurrentUser.role == "Admin") || $scope.isAdmin() || $scope.isCoChair());
        };

        $scope.isPresenter = function(submission) {
            if(submission == null) return false;
            return $scope.email === submission.presenterInfo.email;
        };

        $scope.isCoPresenter = function(submission) {
            if(submission == null) return false;
            return $scope.email === submission.copresenterOneInfo.email ||
                $scope.email === submission.copresenterTwoInfo.email;
        };

        $scope.isAdviser = function(submission) {
            if(submission == null) return false;
            return $scope.email === submission.adviserInfo.email;
        };

        $scope.isReviewerGroup = function(submission){
            if(submission == null) return false;
            return $scope.group === submission.group;
        };

        $scope.hasPermissions = function(submission) {
            if(submission == null) return false;
            if(!Auth.isLoggedIn){
                console.log("Not logged in!");
                return false;
            }

            if($scope.hasAdminPrivs()){
                return true;
            } else {
                console.log("Not admin, is logged in");
                return $scope.isPresenter(submission) ||
                       $scope.isCoPresenter(submission) ||
                       $scope.isAdviser(submission) ||
                       $scope.isReviewerGroup(submission)
            }
        };

        $scope.reviewGroupFilter = function(submission) {
            if($scope.filterData.reviewGroupFilterSelection === "All"){
                return true;
            } else if($scope.filterData.reviewGroupFilterSelection === "Unassigned"){
                return submission.group == 0;
            } else if($scope.filterData.reviewGroupFilterSelection === "Review Group 1"){
                return submission.group == 1;
            } else if($scope.filterData.reviewGroupFilterSelection === "Review Group 2"){
                return submission.group == 2;
            } else if($scope.filterData.reviewGroupFilterSelection === "Review Group 3"){
                return submission.group == 3;
            } else if($scope.filterData.reviewGroupFilterSelection === "Review Group 4"){
                return submission.group == 4;
            } else {
                return false;
            }
        };

        $scope.searchFilter = function(submission){
            var searchText = $scope.filterData.searchText.toLowerCase();
            return(
                (submission.presenterInfo.first.toLowerCase().indexOf(searchText) != -1) ||
                (submission.presenterInfo.last.toLowerCase().indexOf(searchText) != -1) ||
                (submission.copresenterOneInfo.first.toLowerCase().indexOf(searchText) != -1) ||
                (submission.copresenterOneInfo.last.toLowerCase().indexOf(searchText) != -1) ||
                (submission.copresenterTwoInfo.first.toLowerCase().indexOf(searchText) != -1) ||
                (submission.copresenterTwoInfo.last.toLowerCase().indexOf(searchText) != -1) ||
                (submission.adviserInfo.first.toLowerCase().indexOf(searchText) != -1) ||
                (submission.adviserInfo.last.toLowerCase().indexOf(searchText) != -1)
            )
        };

        $scope.isPresenterOnAnything = function(){
           return ($filter('filter')($scope.submissions, $scope.isPresenter).length > 0)
        };

        $scope.isCoPresenterOnAnything = function(){
            return ($filter('filter')($scope.submissions, $scope.isCoPresenter).length > 0)
        };

        $scope.isAdviserOfAnything = function(){
            return ($filter('filter')($scope.submissions, $scope.isAdviser).length > 0)
        };

        $scope.isReviewerOfAnything = function(){
            return ($filter('filter')($scope.submissions, $scope.isReviewerGroup).length > 0)
        };

        // --- Controlling the Tabs ---

        $scope.resetTabs = function(){
            for(var key in $scope.filterData.tabFilter) {
                if($scope.filterData.tabFilter.hasOwnProperty(key)){
                    $scope.filterData.tabFilter[key] = false;
                }
            }
        };

        $scope.showAllSubmissions = function(){
            $scope.resetTabs();
        };

        $scope.showMySubmissions = function(){
            $scope.resetTabs();
            $scope.filterData.tabFilter.isPresenter = true;
        };

        $scope.showMyCoSubmissions = function(){
            $scope.resetTabs();
            $scope.filterData.tabFilter.isCoPresenter = true;
        };

        $scope.showMyAdviserSubmissions = function(){
            $scope.resetTabs();
            $scope.filterData.tabFilter.isAdviser = true;
        };

        $scope.showMyReviewerSubmissions = function(){
            $scope.resetTabs();
            $scope.filterData.tabFilter.isReviewer = true;
        };

        $scope.tabFilters = function(submission){
          if($scope.filterData.tabFilter.isPresenter){
              return $scope.isPresenter(submission);
          }  else if ($scope.filterData.tabFilter.isCoPresenter) {
              return $scope.isCoPresenter(submission);
          } else if ($scope.filterData.tabFilter.isReviewer) {
                  return $scope.reviewGroupFilter(submission);
          } else if ($scope.filterData.tabFilter.isAdviser) {
              return $scope.isAdviser(submission);
          } else {
              console.log("no tab filters applied");
              return true;
          }
        };

        // ----------------------- Getting Data from Mongo ----------------------------

        $http.get('/api/submissions').success(function(submissions) {
            $scope.submissions = submissions;
            socket.syncUpdates('submission', $scope.submissions);
        });

        $http.get('/api/status').success(function(status) {
            $scope.status = status;
            socket.syncUpdates('status', $scope.status);
        });

        var sendGmail = function(opts){
            var str = 'http://mail.google.com/mail/?view=cm&fs=1'+
                '&to=' + opts.to +
                '&su=' + opts.subject +
                '&body=' + opts.message +
                '&ui=1';
            $window.open(str);
        };

        //----------------------------- Color Coding of submission list -----------------------------

        $scope.statusColorTab = function(status){
            switch(status){
                case "Awaiting Adviser Approval":
                    return {'border-left': '4px solid rgba(200, 30, 0, 1)'};
                    break;
                case "Reviewing in Process":
                    return {'border-left': '4px solid rgba(225, 225, 10, 1)'};
                    break;
                case "Revisions Needed":
                    return {'border-left': '4px solid rgba(20, 138, 255, 1)'};
                    break;
                case "Accepted":
                    return {'border-left': '4px solid rgba(71, 214, 0, 1)'};
                    break;
            }
        };

        $scope.statusColorBody = function(status){
            switch(status){
                case "Awaiting Adviser Approval":
                    return {'background-color': 'rgba(200, 30, 0, 1)'};
                    break;
                case "Reviewing in Process":
                    return {'background-color': 'rgba(225, 225, 10, 1)'};
                    break;
                case "Revisions Needed":
                    return {'background-color': 'rgba(20, 138, 255, 1)'};
                    break;
                case "Accepted":
                    return {'background-color': 'rgba(71, 214, 0, 1)'};
                    break;
            }
        };

        // ---------------------- Controlling selection of submission for detail view ---------------------------------

        $scope.selection = {selected: false, item: null};

        $scope.selectItem = function(itemIndex){
            var filteredSubmissions =
                $filter('filter')(
                    $filter('filter')(
                        $filter('filter')(
                            $filter('filter')(
                                $scope.submissions,
                                $scope.hasPermissions
                            ),
                            $scope.tabFilters
                        ),
                        $scope.reviewGroupFilter
                    ),
                    $scope.searchFilter
                );

            $scope.selection.selected = true;
            $scope.selection.item = filteredSubmissions[itemIndex];

            $scope.resetTemps();
        };

        $scope.resetSelection = function(){
            $scope.selection.selected = false;
            $scope.resetTemps();
        };

        $scope.deleteSubmissionConfirm = function(item){
            Modal.confirm.delete($scope.deleteSubmission)(item.title, item);
        };

        $scope.deleteSubmission = function(item){
            console.log("Deleting submission: " + item.title);
            $http.delete('/api/submissions/' + item._id);
            $scope.resetSelection();
        };

        // -------------------------- Editing of status ----------------------------------------------
        $scope.statusEdit = {
            editing: false,
            options: ["Reviewing in Process",
                "Revisions Needed",
                "Accepted"],
            subject:"URS submission update",
            body:[ ", Your URS submission has been approved by your adviser.",
                ", Your URS submission has been flagged for revisions, and is in need of changes.",
                ", Your URS submission has been approved, congratulations!"],
            temp: {strict: "", text: ""}
        };

        var stricts = [];
        var colors = [];
        var emailSubject = [];
        var emailBody = [];

        $scope.statusOptions = {
            editing: false,
            options: stricts,
            color: colors,
            subject: emailSubject,
            body: emailBody
        };

        $scope.statusGet = function(){
            for(x in $scope.status){
                stricts.add(x.strict)
                colors.add(x.color)
                emailSubject.add(x.emailSubject)
                emailBody.add(x.emailBody)
            }
        }

        $scope.resetTemps = function() {
            if($scope.selection.item != null){
                $scope.statusEdit.temp.strict = $scope.selection.item.status.strict;
                $scope.statusEdit.temp.text = $scope.selection.item.status.text;
            }
        };

        $scope.resetTemps();

        $scope.editStatus = function(){
            $scope.statusEdit.editing = !$scope.statusEdit.editing;
            $scope.resetTemps();
        };

        $scope.submitStatusEdit = function(){
            $http.patch('api/submissions/' + $scope.selection.item._id,
                {status: {strict: $scope.statusEdit.temp.strict, text: $scope.statusEdit.temp.text}}
            ).success(function(){
                    console.log("Successfully updated status of submission");
            });

            if($scope.selection.item.approval && $scope.statusEdit.temp.strict === "Awaiting Adviser Approval"){
                $http.patch('api/submissions/' + $scope.selection.item._id,
                    {approval: false}
                ).success(function(){
                    $scope.selection.item.approval = false;
                    console.log("Successfully updated approval of submission (un-approved)");
                });
            } else if(!$scope.selection.item.approval && $scope.statusEdit.temp.strict !== "Awaiting Adviser Approval"){
                $http.patch('api/submissions/' + $scope.selection.item._id,
                    {approval: true}
                ).success(function(){
                    $scope.selection.item.approval = true;
                    console.log("Successfully updated approval of submission (approved)");
                });
            }

            $scope.selection.item.status.strict = $scope.statusEdit.temp.strict;
            $scope.selection.item.status.text = $scope.statusEdit.temp.text;

        //--------------------------------------------- gmail stuff? ---------------------------------------

            sendGmail({
                to: $scope.selection.item.presenterInfo.email,
                subject: $scope.statusEdit.subject,
                message: $scope.selection.item.presenterInfo.first +
                    $scope.statusEdit.body[$scope.statusEdit.options.indexOf($scope.selection.item.status.strict)]
            });
            $scope.resetTemps();
            $scope.editStatus();
        };

        $scope.flagForResubmit = function(){
            $http.patch('api/submissions/' + $scope.selection.item._id,
                {resubmissionData: {comment: "flagged for resubmit", parentSubmission: "", resubmitFlag: true}}
            ).success(function(){
                    console.log("Successfully flagged submission for resubmit");
                });
        };

        $scope.approvalWordChange = function(approval){
             if(approval){
                 return "Yes";
                 }
             else{
                 return "No";
                 }
             };

        //--------------------------------------------- Tabs Stuff ---------------------------------------

    });<commit_msg>Bug fixing, refactoring status<commit_after>/**
 * Created by opdah023 on 10/9/14.
 */
'use strict';
 //When we tested this function, it worked correctly with only two
 //parameters given, until we checked the final else case, in which
 // case it broke with only two parameters
angular.module('umm3601ursamajorApp')
    .filter('isntEmpty', function(){
        return function(input, title, altTitle){
            if(typeof(input) == "object"){
                if(input.length > 0){
                    return title + " " + input;
                }
            } else if (input !== "" && input !== null){
                return title + " " + input;
            } else {
                return altTitle;
            }
        }
    })

    .filter('fancyLimitTo', function(){
        return function(input, limit){
            return input.substring(0, limit) + "[...]";
        }
    })

    .controller('SublistCtrl', function ($scope, $http, socket, $modal, Modal, Auth, $window, $filter) {
        $scope.submissions = [];
        $scope.status = [];

        $scope.getCurrentUser = Auth.getCurrentUser;
        $scope.group = Auth.getCurrentUser().group;
        $scope.email = Auth.getCurrentUser().email;
        $scope.isReviewer = Auth.isReviewer;
        $scope.isAdmin = Auth.isAdmin;
        $scope.isCoChair = Auth.isCoChair;

        //--------------------- Filter Functions -----------------------

        $scope.filterData = {
            searchText: "",
            orderByPredicate: "",
            reviewGroupFilterSelection: "All",
            reviewGroupFilterOptions: [
                "All",
                "Unassigned",
                "Review Group 1",
                "Review Group 2",
                "Review Group 3",
                "Review Group 4"
            ],
            tabFilter: {isPresenter:false, isCoPresenter:false, isReviewer:false, isAdviser:false}
        };

        $scope.setReviewGroupSelection = function(str) {
            $scope.filterData.reviewGroupFilterSelection = str;
        };

        $scope.hasAdminPrivs = function(){
            return (($scope.getCurrentUser.role != null && $scope.getCurrentUser.role == "Admin") || $scope.isAdmin() || $scope.isCoChair());
        };

        $scope.isPresenter = function(submission) {
            if(submission == null) return false;
            return $scope.email === submission.presenterInfo.email;
        };

        $scope.isCoPresenter = function(submission) {
            if(submission == null) return false;
            return $scope.email === submission.copresenterOneInfo.email ||
                $scope.email === submission.copresenterTwoInfo.email;
        };

        $scope.isAdviser = function(submission) {
            if(submission == null) return false;
            return $scope.email === submission.adviserInfo.email;
        };

        $scope.isReviewerGroup = function(submission){
            if(submission == null) return false;
            return $scope.group === submission.group;
        };

        $scope.hasPermissions = function(submission) {
            if(submission == null) return false;
            if(!Auth.isLoggedIn){
                console.log("Not logged in!");
                return false;
            }

            if($scope.hasAdminPrivs()){
                return true;
            } else {
                console.log("Not admin, is logged in");
                return $scope.isPresenter(submission) ||
                       $scope.isCoPresenter(submission) ||
                       $scope.isAdviser(submission) ||
                       $scope.isReviewerGroup(submission)
            }
        };

        $scope.reviewGroupFilter = function(submission) {
            if($scope.filterData.reviewGroupFilterSelection === "All"){
                return true;
            } else if($scope.filterData.reviewGroupFilterSelection === "Unassigned"){
                return submission.group == 0;
            } else if($scope.filterData.reviewGroupFilterSelection === "Review Group 1"){
                return submission.group == 1;
            } else if($scope.filterData.reviewGroupFilterSelection === "Review Group 2"){
                return submission.group == 2;
            } else if($scope.filterData.reviewGroupFilterSelection === "Review Group 3"){
                return submission.group == 3;
            } else if($scope.filterData.reviewGroupFilterSelection === "Review Group 4"){
                return submission.group == 4;
            } else {
                return false;
            }
        };

        $scope.searchFilter = function(submission){
            var searchText = $scope.filterData.searchText.toLowerCase();
            return(
                (submission.presenterInfo.first.toLowerCase().indexOf(searchText) != -1) ||
                (submission.presenterInfo.last.toLowerCase().indexOf(searchText) != -1) ||
                (submission.copresenterOneInfo.first.toLowerCase().indexOf(searchText) != -1) ||
                (submission.copresenterOneInfo.last.toLowerCase().indexOf(searchText) != -1) ||
                (submission.copresenterTwoInfo.first.toLowerCase().indexOf(searchText) != -1) ||
                (submission.copresenterTwoInfo.last.toLowerCase().indexOf(searchText) != -1) ||
                (submission.adviserInfo.first.toLowerCase().indexOf(searchText) != -1) ||
                (submission.adviserInfo.last.toLowerCase().indexOf(searchText) != -1)
            )
        };

        $scope.isPresenterOnAnything = function(){
           return ($filter('filter')($scope.submissions, $scope.isPresenter).length > 0)
        };

        $scope.isCoPresenterOnAnything = function(){
            return ($filter('filter')($scope.submissions, $scope.isCoPresenter).length > 0)
        };

        $scope.isAdviserOfAnything = function(){
            return ($filter('filter')($scope.submissions, $scope.isAdviser).length > 0)
        };

        $scope.isReviewerOfAnything = function(){
            return ($filter('filter')($scope.submissions, $scope.isReviewerGroup).length > 0)
        };

        // --- Controlling the Tabs ---

        $scope.resetTabs = function(){
            for(var key in $scope.filterData.tabFilter) {
                if($scope.filterData.tabFilter.hasOwnProperty(key)){
                    $scope.filterData.tabFilter[key] = false;
                }
            }
        };

        $scope.showAllSubmissions = function(){
            $scope.resetTabs();
        };

        $scope.showMySubmissions = function(){
            $scope.resetTabs();
            $scope.filterData.tabFilter.isPresenter = true;
        };

        $scope.showMyCoSubmissions = function(){
            $scope.resetTabs();
            $scope.filterData.tabFilter.isCoPresenter = true;
        };

        $scope.showMyAdviserSubmissions = function(){
            $scope.resetTabs();
            $scope.filterData.tabFilter.isAdviser = true;
        };

        $scope.showMyReviewerSubmissions = function(){
            $scope.resetTabs();
            $scope.filterData.tabFilter.isReviewer = true;
        };

        $scope.tabFilters = function(submission){
          if($scope.filterData.tabFilter.isPresenter){
              return $scope.isPresenter(submission);
          }  else if ($scope.filterData.tabFilter.isCoPresenter) {
              return $scope.isCoPresenter(submission);
          } else if ($scope.filterData.tabFilter.isReviewer) {
                  return $scope.reviewGroupFilter(submission);
          } else if ($scope.filterData.tabFilter.isAdviser) {
              return $scope.isAdviser(submission);
          } else {
              console.log("no tab filters applied");
              return true;
          }
        };

        // ----------------------- Getting Data from Mongo ----------------------------
        $scope.statusOptions = {
            editing: false,
            options: [],
            color: [],
            subject: [],
            body: [],
            temp: {strict: "", text: ""}
        };

        $scope.statusGet = function(){
            for(var x = 0; x<$scope.status.length; x++){
                $scope.statusOptions.options.push($scope.status[x].strict);
                $scope.statusOptions.color.push($scope.status[x].color);
                $scope.statusOptions.subject.push($scope.status[x].emailSubject);
                $scope.statusOptions.body.push($scope.status[x].emailBody);
            }
        };

        $http.get('/api/submissions').success(function(submissions) {
            $scope.submissions = submissions;
            socket.syncUpdates('submission', $scope.submissions);
        });

        $http.get('/api/statuss').success(function(status) {
            $scope.status = status;
            $scope.statusGet();
            socket.syncUpdates('status', $scope.status);
        });

        //*******Needs to be updated with new status system******
        var sendGmail = function(opts){
            var str = 'http://mail.google.com/mail/?view=cm&fs=1'+
                '&to=' + opts.to +
                '&su=' + opts.subject +
                '&body=' + opts.message +
                '&ui=1';
            $window.open(str);
        };

        //----------------------------- Color Coding of submission list -----------------------------

        $scope.statusColorTab = function(strict) {
            var index = $scope.statusOptions.options.indexOf(strict);
            if ($scope.statusOptions.color.length == 0 || index == -1) {
                return {'border-left': '4px solid rgba(0, 0, 0, 1)'};
            } else {
            return {'border-left': '4px solid rgba(' + $scope.statusOptions.color[index].red
                                               + ',' + $scope.statusOptions.color[index].green
                                               + ',' + $scope.statusOptions.color[index].blue +
                                                 ',' + $scope.statusOptions.color[index].alpha + ')'}
        }};

        $scope.statusColorBody = function(strict) {
            var index = $scope.statusOptions.options.indexOf(strict);
            if ($scope.statusOptions.color.length == 0 || index == -1) {
                return {'background-color': 'rgba(0, 0, 0, 1)'};
            } else {
                return {'background-color': 'rgba(' + $scope.statusOptions.color[index].red
                                                        + ',' + $scope.statusOptions.color[index].green
                                                        + ',' + $scope.statusOptions.color[index].blue +
                                                          ',' + $scope.statusOptions.color[index].alpha + ')'}
            }};

        // ---------------------- Controlling selection of submission for detail view ---------------------------------

        $scope.selection = {selected: false, item: null};

        $scope.selectItem = function(itemIndex){
            var filteredSubmissions =
                $filter('filter')(
                    $filter('filter')(
                        $filter('filter')(
                            $filter('filter')(
                                $scope.submissions,
                                $scope.hasPermissions
                            ),
                            $scope.tabFilters
                        ),
                        $scope.reviewGroupFilter
                    ),
                    $scope.searchFilter
                );

            $scope.selection.selected = true;
            $scope.selection.item = filteredSubmissions[itemIndex];

            $scope.resetTemps();
        };

        $scope.resetSelection = function(){
            $scope.selection.selected = false;
            $scope.resetTemps();
        };

        $scope.deleteSubmissionConfirm = function(item){
            Modal.confirm.delete($scope.deleteSubmission)(item.title, item);
        };

        $scope.deleteSubmission = function(item){
            console.log("Deleting submission: " + item.title);
            $http.delete('/api/submissions/' + item._id);
            $scope.resetSelection();
        };

        // -------------------------- Editing of status ----------------------------------------------
//        $scope.statusOptions = {
//            editing: false,
//            options: ["Reviewing in Process",
//                "Revisions Needed",
//                "Accepted"],
//            subject:"URS submission update",
//            body:[ ", Your URS submission has been approved by your adviser.",
//                ", Your URS submission has been flagged for revisions, and is in need of changes.",
//                ", Your URS submission has been approved, congratulations!"],
//            temp: {strict: "", text: ""}
//        };

        $scope.resetTemps = function() {
            if($scope.selection.item != null){
                $scope.statusOptions.temp.strict = $scope.selection.item.status.strict;
                $scope.statusOptions.temp.text = $scope.selection.item.status.text;
            }
        };

        $scope.resetTemps();

        $scope.editStatus = function(){
            $scope.statusOptions.editing = !$scope.statusOptions.editing;
            $scope.resetTemps();
        };

        $scope.submitStatusEdit = function(){
            $http.patch('api/submissions/' + $scope.selection.item._id,
                {status: {strict: $scope.statusOptions.temp.strict, text: $scope.statusOptions.temp.text}}
            ).success(function(){
                    console.log("Successfully updated status of submission");
            });

            if($scope.selection.item.approval && $scope.statusOptions.temp.strict === "Awaiting Adviser Approval"){
                $http.patch('api/submissions/' + $scope.selection.item._id,
                    {approval: false}
                ).success(function(){
                    $scope.selection.item.approval = false;
                    console.log("Successfully updated approval of submission (un-approved)");
                });
            } else if(!$scope.selection.item.approval && $scope.statusOptions.temp.strict !== "Awaiting Adviser Approval"){
                $http.patch('api/submissions/' + $scope.selection.item._id,
                    {approval: true}
                ).success(function(){
                    $scope.selection.item.approval = true;
                    console.log("Successfully updated approval of submission (approved)");
                });
            }

            $scope.selection.item.status.strict = $scope.statusOptions.temp.strict;
            $scope.selection.item.status.text = $scope.statusOptions.temp.text;

        //--------------------------------------------- gmail stuff? ---------------------------------------

            sendGmail({
                to: $scope.selection.item.presenterInfo.email,
                subject: $scope.statusOptions.subject,
                message: $scope.selection.item.presenterInfo.first +
                    $scope.statusOptions.body[$scope.statusOptions.options.indexOf($scope.selection.item.status.strict)]
            });
            $scope.resetTemps();
            $scope.editStatus();
        };

        $scope.flagForResubmit = function(){
            $http.patch('api/submissions/' + $scope.selection.item._id,
                {resubmissionData: {comment: "flagged for resubmit", parentSubmission: "", resubmitFlag: true}}
            ).success(function(){
                    console.log("Successfully flagged submission for resubmit");
                });
        };

        $scope.approvalWordChange = function(approval){
             if(approval){
                 return "Yes";
                 }
             else{
                 return "No";
                 }
             };

        //--------------------------------------------- Tabs Stuff ---------------------------------------

    });<|endoftext|>


<commit_before>import {decodeTobitAccessToken} from '../shared/utils/convert';
import {getAccessToken} from '../shared/utils/native-functions';
import Request from '../shared/utils/request';
import {loginTapp} from '../config';

let chaynsInfo,
    globalData;

export function loadLocation(locationId = 77783) {
    return new Promise((resolve) => {
        locationId = parseInt(locationId, 10);
        Request.get(`https://chaynssvc.tobit.com/v0.4/${locationId}/LocationSettings`)
            .then((res) => res.json())
            .then((data) => {
                data = data.data;

                data.design.color = `#${data.design.color}`;

                let accessToken = getAccessToken(),
                    payload = decodeTobitAccessToken(accessToken);

                chaynsInfo = {
                    Version: '4014',
                    BaseUrl: '/',
                    User: {
                        ID: payload && payload.TobitUserID ? payload.TobitUserID : 0,
                        FirstName: payload && payload.FirstName ? payload.FirstName : '',
                        LastName: payload && payload.LastName ? payload.LastName : '',
                        PersonID: payload && payload.PersonID ? payload.PersonID : '',
                        TobitAccessToken: accessToken,
                        UACGroups: []
                    },
                    LocationID: locationId,
                    SiteID: data.siteId,
                    LocationName: data.locatioName,
                    IsMobile: false,
                    IsFacebook: (document.referrer.indexOf('staticxx.facebook') > -1 || location.href.indexOf('fb=1') > -1),
                    Tapps: [],
                    LocationPersonID: data.locationPersonId,
                    Domain: window.location.host,
                    ColorMode: data.design.colorMode,
                    Color: data.design.color,
                    Webshadow: {
                        MenuPosition: 0
                    },
                    getGlobalData: () => globalData
                };

                globalData = {
                    AppUser: {
                        UACGroups: [],
                        FacebookAccessToken: '',
                        FacebookUserName: payload && payload.FirstName && payload.LastName ? `${payload.FirstName} ${payload.LastName}` : '',
                        FacebookID: payload && payload.FacebookUserID ? payload.FacebookUserID : '',
                        PersonID: payload && payload.PersonID ? payload.PersonID : '',
                        TobitUserID: payload && payload.TobitUserID ? payload.TobitUserID : 0,
                        TobitAccessToken: accessToken,
                        AdminMode: false
                    },
                    Device: {},
                    AppInfo: {
                        Version: 4014,
                        domain: location.host,
                        Tapps: [],
                        TappSelected: {},
                        FacebookAppID: data.facebookAppId,
                        FacebookPageID: data.facebookId,
                        Title: chaynsInfo.LocationName,
                        CurrentUrl: window.location.href,
                        SiteID: chaynsInfo.SiteID,
                        LocationID: chaynsInfo.LocationID,
                        IsColorSchemeDark: false,
                        colorMode: chaynsInfo.ColorMode,
                        color: chaynsInfo.Color,
                    }
                };
                window.ChaynsInfo = chaynsInfo;

                return Request.get(`https://chaynssvc.tobit.com/v0.4/${locationId}/Tapp?forWeb=true`)
                    .then(res => res.json())
                    .then((tapps) => {
                        chaynsInfo.Tapps = [];

                        for (let entry of tapps.data) {
                            if (entry.tapps && typeof entry.tapps === 'object') {
                                chaynsInfo.Tapps = chaynsInfo.Tapps.concat(entry.tapps);
                                continue;
                            }
                            chaynsInfo.Tapps.push(entry);
                        }

                        chaynsInfo.Tapps.push(loginTapp);
                        globalData.AppInfo.Tapps = chaynsInfo.Tapps;
                        resolve();
                    });
            })
            .catch((e) => console.error(e)); // loadLocation().then(resolve))
    })
}

export function setSelectedTapp(tapp) {
    if (tapp && typeof tapp === 'object') {
        globalData.AppInfo.TappSelected = {
            "Id": tapp.id,
            "InternalName": tapp.internalName,
            "ShowName": tapp.showName,
            "SortID": tapp.sortId,
            "ExclusiveMode": tapp.exclusiveMode,
            "LoadAsAjax": tapp.loadAsAjax,
            "Url": tapp.url,
            "Link": tapp.link,
            "SendAuthenticationHeader": tapp.sendAuthenticationHeader,
            "PostTobitAccessToken": tapp.postTobitAccessToken,
            "UserGroupIds": tapp.uacGroupIds || [],
            "HideFromMenu": tapp.hideFromMenu,
            "Mobile": tapp.mobile,
            "Desktop": tapp.desktop,
            "ShowOnlyInAdminMode": tapp.showOnlyInAdminMode,
            "Icon": tapp.icon,
            "FallbackTapp": tapp.fallbackTapp,
            "isExclusiveView": tapp.isExclusiveView
        };
    }
}<commit_msg>fixes when get tapps from csvc failed for loop crashes<commit_after>import {decodeTobitAccessToken} from '../shared/utils/convert';
import {getAccessToken} from '../shared/utils/native-functions';
import Request from '../shared/utils/request';
import {loginTapp} from '../config';

let chaynsInfo,
    globalData;

export function loadLocation(locationId = 77783) {
    return new Promise((resolve) => {
        locationId = parseInt(locationId, 10);
        Request.get(`https://chaynssvc.tobit.com/v0.4/${locationId}/LocationSettings`)
            .then((res) => res.json())
            .then((data) => {
                data = data.data;

                data.design.color = `#${data.design.color}`;

                let accessToken = getAccessToken(),
                    payload = decodeTobitAccessToken(accessToken);

                chaynsInfo = {
                    Version: '4014',
                    BaseUrl: '/',
                    User: {
                        ID: payload && payload.TobitUserID ? payload.TobitUserID : 0,
                        FirstName: payload && payload.FirstName ? payload.FirstName : '',
                        LastName: payload && payload.LastName ? payload.LastName : '',
                        PersonID: payload && payload.PersonID ? payload.PersonID : '',
                        TobitAccessToken: accessToken,
                        UACGroups: []
                    },
                    LocationID: locationId,
                    SiteID: data.siteId,
                    LocationName: data.locatioName,
                    IsMobile: false,
                    IsFacebook: (document.referrer.indexOf('staticxx.facebook') > -1 || location.href.indexOf('fb=1') > -1),
                    Tapps: [],
                    LocationPersonID: data.locationPersonId,
                    Domain: window.location.host,
                    ColorMode: data.design.colorMode,
                    Color: data.design.color,
                    Webshadow: {
                        MenuPosition: 0
                    },
                    getGlobalData: () => globalData
                };

                globalData = {
                    AppUser: {
                        UACGroups: [],
                        FacebookAccessToken: '',
                        FacebookUserName: payload && payload.FirstName && payload.LastName ? `${payload.FirstName} ${payload.LastName}` : '',
                        FacebookID: payload && payload.FacebookUserID ? payload.FacebookUserID : '',
                        PersonID: payload && payload.PersonID ? payload.PersonID : '',
                        TobitUserID: payload && payload.TobitUserID ? payload.TobitUserID : 0,
                        TobitAccessToken: accessToken,
                        AdminMode: false
                    },
                    Device: {},
                    AppInfo: {
                        Version: 4014,
                        domain: location.host,
                        Tapps: [],
                        TappSelected: {},
                        FacebookAppID: data.facebookAppId,
                        FacebookPageID: data.facebookId,
                        Title: chaynsInfo.LocationName,
                        CurrentUrl: window.location.href,
                        SiteID: chaynsInfo.SiteID,
                        LocationID: chaynsInfo.LocationID,
                        IsColorSchemeDark: false,
                        colorMode: chaynsInfo.ColorMode,
                        color: chaynsInfo.Color,
                    }
                };
                window.ChaynsInfo = chaynsInfo;

                return Request.get(`https://chaynssvc.tobit.com/v0.4/${locationId}/Tapp?forWeb=true`)
                    .then(res => res.json())
                    .then((tapps) => {
                        chaynsInfo.Tapps = [];
                        if (tapps && tapps.data) {
                            for (let entry of tapps.data) {
                                if (entry.tapps && typeof entry.tapps === 'object') {
                                    chaynsInfo.Tapps = chaynsInfo.Tapps.concat(entry.tapps);
                                    continue;
                                }
                                chaynsInfo.Tapps.push(entry);
                            }
                        }

                        chaynsInfo.Tapps.push(loginTapp);
                        globalData.AppInfo.Tapps = chaynsInfo.Tapps;
                        resolve();
                    });
            })
            .catch((e) => console.error(e)); // loadLocation().then(resolve))
    })
}

export function setSelectedTapp(tapp) {
    if (tapp && typeof tapp === 'object') {
        globalData.AppInfo.TappSelected = {
            "Id": tapp.id,
            "InternalName": tapp.internalName,
            "ShowName": tapp.showName,
            "SortID": tapp.sortId,
            "ExclusiveMode": tapp.exclusiveMode,
            "LoadAsAjax": tapp.loadAsAjax,
            "Url": tapp.url,
            "Link": tapp.link,
            "SendAuthenticationHeader": tapp.sendAuthenticationHeader,
            "PostTobitAccessToken": tapp.postTobitAccessToken,
            "UserGroupIds": tapp.uacGroupIds || [],
            "HideFromMenu": tapp.hideFromMenu,
            "Mobile": tapp.mobile,
            "Desktop": tapp.desktop,
            "ShowOnlyInAdminMode": tapp.showOnlyInAdminMode,
            "Icon": tapp.icon,
            "FallbackTapp": tapp.fallbackTapp,
            "isExclusiveView": tapp.isExclusiveView
        };
    }
}<|endoftext|>


<commit_before>var amqp = require('amqplib'),
    Bus = require('../bus'),
    Correlator = require('./correlator'),
    log = require('debug')('servicebus'),
    events = require('events'),
    extend = require('extend'),
    json = require('../formatters/json'),
    newId = require('node-uuid'),
    PubSubQueue = require('./pubsubqueue'),
    querystring = require('querystring'),
    Queue = require('./queue'),
    util = require('util');

function RabbitMQBus (options) {
  var self = this;

  options = options || {};
  options.url = options.url || process.env.RABBITMQ_URL || 'amqp://localhost';
  options.vhost = options.vhost || process.env.RABBITMQ_VHOST || '/';
  options.exchangeName = options.exchangeName || 'amq.topic';
  options.exchangeOptions = options.exchangeOptions || {};

  this.assertQueuesOnFirstSend = options.assertQueuesOnFirstSend || true;
  this.channels = [];
  this.correlator = new Correlator(options);
  this.delayOnStartup = options.delayOnStartup || 10;
  this.formatter = json;
  this.initialized = false;
  this.log = options.log || log;
  this.pubsubqueues = {};
  this.queues = {};
  this.queuesFile = options.queuesFile;

  var vhost = util.format('/%s', querystring.escape(options.vhost));
  var url = util.format('%s%s', options.url, vhost);

  self.log('connecting to rabbitmq on %s', url);

  amqp.connect(url).catch(function (err) {
    self.log('error connecting to rabbitmq: %s', err);
    self.emit('error', err);
  }).done(function (conn) {
    process.once('SIGINT', function() {
      self.log('closing channels and connection');
      self.channels.forEach(function (channel) {
        channel.close();
      });
      conn.close();
    });

    self.connection = conn;

    function channelError (err) {
      self.log('channel error with connection %s error: %s', options.url, err.toString());
      self.emit('error', err);
    }

    function done () {
      if (self.channels.length === (options.enableConfirms ? 3 : 2)) {
        self.initialized = true;
        self.log('connected to rabbitmq on %s', url);
        self.emit('ready');
      }
    }

    self.connection.createChannel().then(function (channel) {
      channel.on('error', channelError);
      self.sendChannel = channel;
      self.channels.push(channel);
      done();
    });

    self.connection.createChannel().then(function (channel) {
      channel.on('error', channelError);
      self.listenChannel = channel;
      self.channels.push(channel);
      done();
    });

    if (options.enableConfirms) {
      self.connection.createConfirmChannel().then(function (channel) {
        channel.on('error', channelError);
        self.confirmChannel = channel;
        if (options.prefetch) {
          self.confirmChannel.prefetch(options.prefetch);
        }
        self.channels.push(channel);
        done();
      });
    }

  }, function (err) {
    self.log('error connecting to rabbitmq: %s', err);
    self.emit('error', err);
  });

  Bus.call(this);
}

util.inherits(RabbitMQBus, Bus);

RabbitMQBus.prototype.listen = function listen (queueName, options, callback) {

  this.log('listen on queue %s', queueName);

  if (typeof options === "function") {
    callback = options;
    options = {};
  }

  if ( ! this.initialized) {
    return this.on('ready', listen.bind(this, queueName, options, callback));
  }

  this.setOptions(queueName, options);

  if (this.queues[options.queueName] === undefined) {
    this.log('creating queue %s', options.queueName);
    this.queues[options.queueName] = new Queue(options);
  }

  this.queues[options.queueName].listen(callback, options);

};

RabbitMQBus.prototype.unlisten = function unlisten (queueName, options) {
  if (this.queues[queueName] === undefined) {
    throw new Error('no queue currently listening at %s', queueName);
  } else {
    var result = this.queues[queueName].unlisten(options);
    delete this.queues[queueName];
    return result;
  }
};

RabbitMQBus.prototype.destroyListener = function removeListener (queueName) {
  if (this.queues[queueName] === undefined) {
    throw new Error('no queue currently listening at %s', queueName);
  } else {
    var q = this.queues[queueName];
    delete this.queues[queueName];
    return q.destroy();
  }
};

RabbitMQBus.prototype.setOptions = function (queueName, options) {
  if (typeof queueName === 'object') {
    options.queueName = queueName.queueName;
    options.routingKey = queueName.routingKey;
    queueName = queueName.queueName;
  } else {
    options.queueName = queueName;
  }

  extend(options, {
    assertQueue: this.assertQueuesOnFirstSend,
    bus: this,
    confirmChannel: this.confirmChannel,
    correlator: this.correlator,
    formatter: this.formatter,
    listenChannel: this.listenChannel,
    log: this.log,
    queuesFile: this.queuesFile,
    sendChannel: this.sendChannel
  });
};

RabbitMQBus.prototype.send = function send (queueName, message, options, cb) {
  options = options || {};

  if ( ! this.initialized) {
    return this.on('ready', send.bind(this, queueName, message, options, cb));
  }

  this.setOptions(queueName, options);

  var key = cb ? options.queueName + '.confirm' : options.queueName;

  if (this.queues[key] === undefined) {
    this.queues[key] = new Queue(options);
  }
  this.handleOutgoing(options.queueName, message, function (queueName, message) {
    this.queues[key].send(message, options, cb);
  }.bind(this));

};

RabbitMQBus.prototype.subscribe = function subscribe (queueName, options, callback) {
  var self = this;

  if (typeof options === "function") {
    callback = options;
    options = {};
  }

  var handle = null;
  function _unsubscribe (options) {
    handle.unsubscribe(options);
  }

  if ( ! this.initialized) {
    return this.on('ready', subscribe.bind(this, queueName, options, callback));
  }

  this.setOptions(queueName, options);

  if (this.pubsubqueues[options.queueName] === undefined) {
    this.log('creating pusubqueue %s', options.queueName);
    this.pubsubqueues[options.queueName] = new PubSubQueue(options);
  }

  handle = this.pubsubqueues[options.queueName].subscribe(options, callback);

  return {
    unsubscribe: _unsubscribe
  };

};

RabbitMQBus.prototype.publish = function publish (queueName, message, options, cb) {
  options = options || {};

  if ( ! this.initialized) {
    return this.on('ready', publish.bind(this, queueName, message, options, cb));
  }

  this.setOptions(queueName, options);

  var key = cb ? options.queueName + '.confirm' : options.queueName;

  if (this.pubsubqueues[key] === undefined) {
    this.pubsubqueues[key] = new PubSubQueue(options);
  }

  this.handleOutgoing(options.queueName, message, function (queueName, message) {
    this.pubsubqueues[key].publish(message, options, cb);
  }.bind(this));

};

module.exports.Bus = RabbitMQBus;
<commit_msg>check enableConfirms when determining queue name<commit_after>var amqp = require('amqplib'),
    Bus = require('../bus'),
    Correlator = require('./correlator'),
    log = require('debug')('servicebus'),
    events = require('events'),
    extend = require('extend'),
    json = require('../formatters/json'),
    newId = require('node-uuid'),
    PubSubQueue = require('./pubsubqueue'),
    querystring = require('querystring'),
    Queue = require('./queue'),
    util = require('util');

function RabbitMQBus (options) {
  var self = this;

  options = options || {};
  options.url = options.url || process.env.RABBITMQ_URL || 'amqp://localhost';
  options.vhost = options.vhost || process.env.RABBITMQ_VHOST || '/';
  options.exchangeName = options.exchangeName || 'amq.topic';
  options.exchangeOptions = options.exchangeOptions || {};

  this.assertQueuesOnFirstSend = options.assertQueuesOnFirstSend || true;
  this.channels = [];
  this.correlator = new Correlator(options);
  this.delayOnStartup = options.delayOnStartup || 10;
  this.formatter = json;
  this.initialized = false;
  this.log = options.log || log;
  this.pubsubqueues = {};
  this.queues = {};
  this.queuesFile = options.queuesFile;

  var vhost = util.format('/%s', querystring.escape(options.vhost));
  var url = util.format('%s%s', options.url, vhost);

  self.log('connecting to rabbitmq on %s', url);

  amqp.connect(url).catch(function (err) {
    self.log('error connecting to rabbitmq: %s', err);
    self.emit('error', err);
  }).done(function (conn) {
    process.once('SIGINT', function() {
      self.log('closing channels and connection');
      self.channels.forEach(function (channel) {
        channel.close();
      });
      conn.close();
    });

    self.connection = conn;

    function channelError (err) {
      self.log('channel error with connection %s error: %s', options.url, err.toString());
      self.emit('error', err);
    }

    function done () {
      if (self.channels.length === (options.enableConfirms ? 3 : 2)) {
        self.initialized = true;
        self.log('connected to rabbitmq on %s', url);
        self.emit('ready');
      }
    }

    self.connection.createChannel().then(function (channel) {
      channel.on('error', channelError);
      self.sendChannel = channel;
      self.channels.push(channel);
      done();
    });

    self.connection.createChannel().then(function (channel) {
      channel.on('error', channelError);
      self.listenChannel = channel;
      self.channels.push(channel);
      done();
    });

    if (options.enableConfirms) {
      self.connection.createConfirmChannel().then(function (channel) {
        channel.on('error', channelError);
        self.confirmChannel = channel;
        if (options.prefetch) {
          self.confirmChannel.prefetch(options.prefetch);
        }
        self.channels.push(channel);
        done();
      });
    }

  }, function (err) {
    self.log('error connecting to rabbitmq: %s', err);
    self.emit('error', err);
  });

  Bus.call(this);
}

util.inherits(RabbitMQBus, Bus);

RabbitMQBus.prototype.listen = function listen (queueName, options, callback) {

  this.log('listen on queue %s', queueName);

  if (typeof options === "function") {
    callback = options;
    options = {};
  }

  if ( ! this.initialized) {
    return this.on('ready', listen.bind(this, queueName, options, callback));
  }

  this.setOptions(queueName, options);

  if (this.queues[options.queueName] === undefined) {
    this.log('creating queue %s', options.queueName);
    this.queues[options.queueName] = new Queue(options);
  }

  this.queues[options.queueName].listen(callback, options);

};

RabbitMQBus.prototype.unlisten = function unlisten (queueName, options) {
  if (this.queues[queueName] === undefined) {
    throw new Error('no queue currently listening at %s', queueName);
  } else {
    var result = this.queues[queueName].unlisten(options);
    delete this.queues[queueName];
    return result;
  }
};

RabbitMQBus.prototype.destroyListener = function removeListener (queueName) {
  if (this.queues[queueName] === undefined) {
    throw new Error('no queue currently listening at %s', queueName);
  } else {
    var q = this.queues[queueName];
    delete this.queues[queueName];
    return q.destroy();
  }
};

RabbitMQBus.prototype.setOptions = function (queueName, options) {
  if (typeof queueName === 'object') {
    options.queueName = queueName.queueName;
    options.routingKey = queueName.routingKey;
    queueName = queueName.queueName;
  } else {
    options.queueName = queueName;
  }

  extend(options, {
    assertQueue: this.assertQueuesOnFirstSend,
    bus: this,
    confirmChannel: this.confirmChannel,
    correlator: this.correlator,
    formatter: this.formatter,
    listenChannel: this.listenChannel,
    log: this.log,
    queuesFile: this.queuesFile,
    sendChannel: this.sendChannel
  });
};

RabbitMQBus.prototype.send = function send (queueName, message, options, cb) {
  options = options || {};

  if ( ! this.initialized) {
    return this.on('ready', send.bind(this, queueName, message, options, cb));
  }

  this.setOptions(queueName, options);

  var key = options.enableConfirms && cb ? options.queueName + '.confirm' : options.queueName;

  if (this.queues[key] === undefined) {
    this.queues[key] = new Queue(options);
  }
  this.handleOutgoing(options.queueName, message, function (queueName, message) {
    this.queues[key].send(message, options, cb);
  }.bind(this));

};

RabbitMQBus.prototype.subscribe = function subscribe (queueName, options, callback) {
  var self = this;

  if (typeof options === "function") {
    callback = options;
    options = {};
  }

  var handle = null;
  function _unsubscribe (options) {
    handle.unsubscribe(options);
  }

  if ( ! this.initialized) {
    return this.on('ready', subscribe.bind(this, queueName, options, callback));
  }

  this.setOptions(queueName, options);

  if (this.pubsubqueues[options.queueName] === undefined) {
    this.log('creating pusubqueue %s', options.queueName);
    this.pubsubqueues[options.queueName] = new PubSubQueue(options);
  }

  handle = this.pubsubqueues[options.queueName].subscribe(options, callback);

  return {
    unsubscribe: _unsubscribe
  };

};

RabbitMQBus.prototype.publish = function publish (queueName, message, options, cb) {
  options = options || {};

  if ( ! this.initialized) {
    return this.on('ready', publish.bind(this, queueName, message, options, cb));
  }

  this.setOptions(queueName, options);

  var key = cb ? options.queueName + '.confirm' : options.queueName;

  if (this.pubsubqueues[key] === undefined) {
    this.pubsubqueues[key] = new PubSubQueue(options);
  }

  this.handleOutgoing(options.queueName, message, function (queueName, message) {
    this.pubsubqueues[key].publish(message, options, cb);
  }.bind(this));

};

module.exports.Bus = RabbitMQBus;
<|endoftext|>