<commit_before>import request from 'supertest'
import uuid from 'uuid'
import util from 'util'
import Promise from 'bluebird'
import appMock from './utils/app'
import projectFixture from './fixtures/project'
import userFixture from './fixtures/user'
import User from './models/user'
import Project from './models/project'
import {
  setup,
  teardown
} from './utils/db'

const app = appMock()
const user = Object.assign({}, userFixture, {id: uuid.v4()})
const project = Object.assign({}, projectFixture, {id: uuid.v4()})

describe('netiam', () => {
  describe('JSONAPI', () => {

    before(setup)
    after(teardown)

    it('should create project', done => {
      Project
        .create(project)
        .then(() => done())
        .catch(done)
    })

    it('should create users', done => {
      const users = []
      users.push(user)
      for (let i = 0; i < 10; i += 1) {
        const username = uuid.v4()
        users.push(Object.assign({}, userFixture, {
          email: `${username}@neti.am`,
          username: username
        }))
      }

      User
        .bulkCreate(users)
        .then(() => {
          return User.findAll()
        })
        .then(users => {
          return Promise.all(users.map(user => {
            return user.setProjects([project.id])
          }))
        })
        .then(() => {
          return User.findAll({
            include: [
              {
                model: Project,
                as: 'projects',
                included: ['id']
              }
            ]
          })
        })
        .then(() => done())
        .catch(done)
    })

    it('should fetch user', done => {
      request(app)
        .get(`/users/${user.id}?include=projects`)
        .set('Accept', 'application/json')
        .expect(200)
        .expect('Content-Type', /json/)
        .expect(res => {
          const json = res.body

          json.should.be.an.Object()
          json.should.have.properties(['data', 'included', 'links'])
          json.data.should.be.Object()
          json.data.should.have.properties([
            'id',
            'type',
            'attributes',
            'relationships',
            'links'
          ])
          json.data.relationships.should.be.Object()
          json.data.relationships.should.have.properties([
            'projects'
          ])

          json.included.should.be.Array()
          json.included.should.have.length(1)
          json.included[0].should.have.properties([
            'id',
            'type',
            'attributes',
            'links'
          ])
          json.included[0].type.should.eql('project')
          json.included[0].links.should.have.properties(['self'])
        })
        .end(err => {
          if (err) {
            return done(err)
          }
          done()
        })
    })

    it('should fetch users', done => {
      request(app)
        .get('/users?include=projects')
        .set('Accept', 'application/json')
        .expect(200)
        .expect('Content-Type', /json/)
        .expect(res => {
          const json = res.body

          json.should.be.an.Object()
          json.should.have.properties(['data', 'included', 'links'])
          json.data.should.be.Array()
          json.data.should.have.length(10)
          json.data[0].should.have.properties([
            'id',
            'type',
            'attributes',
            'relationships',
            'links'
          ])
          json.data[0].relationships.should.be.Object()
          json.data[0].relationships.should.have.properties([
            'projects'
          ])

          json.included.should.be.Array()
          json.included.should.have.length(1)
          json.included[0].should.have.properties([
            'id',
            'type',
            'attributes',
            'links'
          ])
          json.included[0].type.should.eql('project')
          json.included[0].links.should.have.properties(['self'])
        })
        .end(err => {
          if (err) {
            return done(err)
          }
          done()
        })
    })

  })
})
<commit_msg>tests: remove `util` import<commit_after>import request from 'supertest'
import uuid from 'uuid'
import Promise from 'bluebird'
import appMock from './utils/app'
import projectFixture from './fixtures/project'
import userFixture from './fixtures/user'
import User from './models/user'
import Project from './models/project'
import {
  setup,
  teardown
} from './utils/db'

const app = appMock()
const user = Object.assign({}, userFixture, {id: uuid.v4()})
const project = Object.assign({}, projectFixture, {id: uuid.v4()})

describe('netiam', () => {
  describe('JSONAPI', () => {

    before(setup)
    after(teardown)

    it('should create project', done => {
      Project
        .create(project)
        .then(() => done())
        .catch(done)
    })

    it('should create users', done => {
      const users = []
      users.push(user)
      for (let i = 0; i < 10; i += 1) {
        const username = uuid.v4()
        users.push(Object.assign({}, userFixture, {
          email: `${username}@neti.am`,
          username: username
        }))
      }

      User
        .bulkCreate(users)
        .then(() => {
          return User.findAll()
        })
        .then(users => {
          return Promise.all(users.map(user => {
            return user.setProjects([project.id])
          }))
        })
        .then(() => {
          return User.findAll({
            include: [
              {
                model: Project,
                as: 'projects',
                included: ['id']
              }
            ]
          })
        })
        .then(() => done())
        .catch(done)
    })

    it('should fetch user', done => {
      request(app)
        .get(`/users/${user.id}?include=projects`)
        .set('Accept', 'application/json')
        .expect(200)
        .expect('Content-Type', /json/)
        .expect(res => {
          const json = res.body

          json.should.be.an.Object()
          json.should.have.properties(['data', 'included', 'links'])
          json.data.should.be.Object()
          json.data.should.have.properties([
            'id',
            'type',
            'attributes',
            'relationships',
            'links'
          ])
          json.data.relationships.should.be.Object()
          json.data.relationships.should.have.properties([
            'projects'
          ])

          json.included.should.be.Array()
          json.included.should.have.length(1)
          json.included[0].should.have.properties([
            'id',
            'type',
            'attributes',
            'links'
          ])
          json.included[0].type.should.eql('project')
          json.included[0].links.should.have.properties(['self'])
        })
        .end(err => {
          if (err) {
            return done(err)
          }
          done()
        })
    })

    it('should fetch users', done => {
      request(app)
        .get('/users?include=projects')
        .set('Accept', 'application/json')
        .expect(200)
        .expect('Content-Type', /json/)
        .expect(res => {
          const json = res.body

          json.should.be.an.Object()
          json.should.have.properties(['data', 'included', 'links'])
          json.data.should.be.Array()
          json.data.should.have.length(10)
          json.data[0].should.have.properties([
            'id',
            'type',
            'attributes',
            'relationships',
            'links'
          ])
          json.data[0].relationships.should.be.Object()
          json.data[0].relationships.should.have.properties([
            'projects'
          ])

          json.included.should.be.Array()
          json.included.should.have.length(1)
          json.included[0].should.have.properties([
            'id',
            'type',
            'attributes',
            'links'
          ])
          json.included[0].type.should.eql('project')
          json.included[0].links.should.have.properties(['self'])
        })
        .end(err => {
          if (err) {
            return done(err)
          }
          done()
        })
    })

  })
})
<|endoftext|>


<commit_before>var logicControllers = angular.module('logicControllers', []);

logicControllers.controller("HomeCtrl", ["$scope", "$location", "$window", "testSvc",function ($scope, $location, $window, testSvc) {

}]);

logicControllers.controller("TruthTableCtrl", ["$scope", "$mdDialog", "$location", "sequentSvc",function ($scope, $mdDialog, $location, sequentSvc) {
    $scope.loading = false;
	$scope.sequent = "P, P→Q ⊢ Q";

    $scope.logicSymbol = function (ev) {
    	$scope.sequent += ev.currentTarget.value;
    	document.getElementById("sequent").focus();
    };

	$scope.checkSequent = function (ev) {
		var sequent = $scope.sequent.replace(/ /g,'');
		$scope.message = "";
		$scope.tableHeaders = [];
		$scope.tableValues = [];
		$scope.loading = true;

		sequentSvc.isValid(sequent)
        .then(function (isValid) {
    		showAlert(ev, isValid);
        }, function (error) {
            console.log(error);
        });

		sequentSvc.getTruthTable(sequent)
        .then(function (table) {
    		showTable(table);
        }, function (error) {
            console.log(error);
        });

		function showAlert(ev, valid) {
			if(valid === "true") {
			    $scope.message = "The sequent is valid.";
			    $scope.messageColor = "green";
	    	} else if(valid === "false"){
	    		$scope.message = "The sequent is invalid.";
	    		$scope.messageColor = "red";
	    	} else {
	    		$scope.message = "The sequent is not well formed."
	    		$scope.messageColor = "yellow";
	    	}
	    }

		function showTable(table) {
			var cols = [];
			for(var i = 0; i < table.headers.length; i++) {
				cols[i] = "";
			}
			for(var i = 0; i < table.mainConnectors.length; i++) {
				cols[table.mainConnectors[i]] = "background-color: #C5CAE9;";
			}
			$scope.loading = false;
			$scope.tableCols = cols;
			$scope.tableHeaders = table.headers;
			$scope.tableValues = table.values;
		}
	};
}]);

logicControllers.controller("ProofValidteCtrl", ["$scope", "$location", "$window", "testSvc",function ($scope, $location, $window, testSvc) {

}]);

logicControllers.controller("ProofSolveCtrl", ["$scope", "$location", "$window", "testSvc",function ($scope, $location, $window, testSvc) {

}]);
<commit_msg>Fixed loading gif issue<commit_after>var logicControllers = angular.module('logicControllers', []);

logicControllers.controller("HomeCtrl", ["$scope", "$location", "$window", "testSvc",function ($scope, $location, $window, testSvc) {

}]);

logicControllers.controller("TruthTableCtrl", ["$scope", "$mdDialog", "$location", "sequentSvc",function ($scope, $mdDialog, $location, sequentSvc) {
    $scope.loading = false;
	$scope.sequent = "P, P→Q ⊢ Q";

    $scope.logicSymbol = function (ev) {
    	$scope.sequent += ev.currentTarget.value;
    	document.getElementById("sequent").focus();
    };

	$scope.checkSequent = function (ev) {
		var sequent = $scope.sequent.replace(/ /g,'');
		$scope.message = "";
		$scope.tableHeaders = [];
		$scope.tableValues = [];
		$scope.loading = true;

		sequentSvc.isValid(sequent)
        .then(function (isValid) {
    		showAlert(ev, isValid);
        }, function (error) {
            console.log(error);
        });

		sequentSvc.getTruthTable(sequent)
        .then(function (table) {
    		showTable(table);
        }, function (error) {
        	$scope.loading = false;
            console.log(error);
        });

		function showAlert(ev, valid) {
			if(valid === "true") {
			    $scope.message = "The sequent is valid.";
			    $scope.messageColor = "green";
	    	} else if(valid === "false"){
	    		$scope.message = "The sequent is invalid.";
	    		$scope.messageColor = "red";
	    	} else {
	    		$scope.message = "The sequent is not well formed."
	    		$scope.messageColor = "yellow";
	    	}
	    }

		function showTable(table) {
			if(table) {
				var cols = [];
				for(var i = 0; i < table.headers.length; i++) {
					cols[i] = "";
				}
				for(var i = 0; i < table.mainConnectors.length; i++) {
					cols[table.mainConnectors[i]] = "background-color: #C5CAE9;";
				}
				$scope.loading = false;
				$scope.tableCols = cols;
				$scope.tableHeaders = table.headers;
				$scope.tableValues = table.values;
			}
		}
	};
}]);

logicControllers.controller("ProofValidteCtrl", ["$scope", "$location", "$window", "testSvc",function ($scope, $location, $window, testSvc) {

}]);

logicControllers.controller("ProofSolveCtrl", ["$scope", "$location", "$window", "testSvc",function ($scope, $location, $window, testSvc) {

}]);
<|endoftext|>


<commit_before>/**
  Defines the artist.graph model

  Exports the ArtistGraph object to draw a graph of related artists
  in a DOM element given a music artist and some optional options 8D
*/

var models;

function Promise() {
  this.callback = function() {};

  this.done = function(callback) {
    this.callback = callback;
  };
}

var ArtistGraph = function(config, element, artist, options) {
  this.DEFAULT_BRANCHING = 4;
  this.DEFAULT_DEPTH = 2;

  this.element = element;
  this.artist = artist;
  this.artist.nodeid = 1;
  this.branching = config.branching || this.DEFAULT_BRANCHING;
  this.depth = config.depth || this.DEFAULT_DEPTH;

  this.relatedArtists = [];
  this.extraEdges = [];

  // numbering for the id's of adjacent nodes
  this.index = 1;

  this.treemode = true;

  // data of the graph: should contain nodes and edges
  this.data = {
    nodes: [{
      id: this.index,
      label: this.artist.name,
      color: {
        background: '#666'
      }
    }],
    edges: []
  };
  // options for the rendering of the graph
  this.options = options;

  this.graph = new vis.Graph(this.element, this.data, this.options);
};

ArtistGraph.prototype = {
  updateGraph: function(config) {
    this.branching = config.branching || this.branching;
    this.depth = config.depth || this.depth;

    this.index = 1;

    this.extraEdges = [];
    this.data = {
      nodes: [{
        id: this.index,
        label: this.artist.name,
        color: {
          background: '#666'
        }
      }],
      edges: []
    };

    this.treemode = config.treemode;
  },

  buildGraph: function() {
    this.counter = 1;

    this.maxNodes = 0;
    for (var i = 0; i <= this.depth; ++i) {
      this.maxNodes += Math.pow(this.branching, i);
    }

    console.log('#### Stats for ' + this.artist.name);
    console.log('# iterations: ' + this.maxNodes);
    this.constructGraph(this.depth - 1, this.artist);
  },

  constructGraph: function(depth, rootArtist) {

    var forEachRelated = function(artist) {
      var duplicated = _.findWhere(this.data.nodes, {
        label: artist.name
      });

      if (duplicated) {
        var inverseEdgeExists = _.findWhere(this.data.edges, {
          from: duplicated.id,
          to: rootArtist.nodeid
        });
        var edgeExists = _.findWhere(this.data.edges, {
          to: duplicated.id,
          from: rootArtist.nodeid
        });

        if (!inverseEdgeExists && !edgeExists) {
          var extraEdge = {
            from: rootArtist.nodeid,
            to: duplicated.id,
            color: '#ddd'
          };

          this.extraEdges.push(extraEdge);
          if (!this.treemode)
            this.data.edges.push(extraEdge);
        }
      } else {
        var nodeid = ++this.index;

        this.data.nodes.push({
          id: nodeid,
          label: artist.name
        });

        this.data.edges.push({
          from: rootArtist.nodeid,
          to: nodeid
        });

        this.relatedArtists.push(artist);

        artist.nodeid = nodeid;
      }

      if (depth > 0)
        this.constructGraph(depth - 1, artist);

      if (++this.counter === this.maxNodes) {
        this.draw(true);
      }
    };

    var relatedSnapshotDone = function(snapshot) {
      var snapshotLoadAll = snapshot.loadAll(['name', 'uri']);

      snapshotLoadAll.each(this, forEachRelated);
    };

    var relatedDone = function(artist) {
      var promiseRelatedSnapshot = artist.related.snapshot(0, this.branching);
      promiseRelatedSnapshot.done(this, relatedSnapshotDone);
    };

    var promiseRelated = rootArtist.load('related');
    promiseRelated.done(this, relatedDone);
  },

  draw: function(debug) {
    this.graph.setData(this.data, {
      disableStart: true
    });
    this.graph.start();
    this.graph.zoomExtent();

    if (this.throbber)
      this.throbber.hide();

    if (debug) {
      console.log('# nodes: ' + this.data.nodes.length);
      console.log('# edges: ' + this.data.edges.length);
    }
  },

  redraw: function() {
    this.graph.redraw();
  }
};

ArtistGraph.prototype.constructor = ArtistGraph;

require(['$api/models'], function(_models) {
  models = _models;

  exports.ArtistGraph = ArtistGraph;
});<commit_msg>bugfix: treemode was being ignored.<commit_after>/**
  Defines the artist.graph model

  Exports the ArtistGraph object to draw a graph of related artists
  in a DOM element given a music artist and some optional options 8D
*/

var models;

function Promise() {
  this.callback = function() {};

  this.done = function(callback) {
    this.callback = callback;
  };
}

var ArtistGraph = function(config, element, artist, options) {
  this.DEFAULT_BRANCHING = 4;
  this.DEFAULT_DEPTH = 2;

  this.element = element;
  this.artist = artist;
  this.artist.nodeid = 1;
  this.branching = config.branching || this.DEFAULT_BRANCHING;
  this.depth = config.depth || this.DEFAULT_DEPTH;

  this.relatedArtists = [];
  this.extraEdges = [];

  // numbering for the id's of adjacent nodes
  this.index = 1;

  this.treemode = true;

  // data of the graph: should contain nodes and edges
  this.data = {
    nodes: [{
      id: this.index,
      label: this.artist.name,
      color: {
        background: '#666'
      }
    }],
    edges: []
  };
  // options for the rendering of the graph
  this.options = options;

  this.graph = new vis.Graph(this.element, this.data, this.options);
};

ArtistGraph.prototype = {
  updateGraph: function(config) {
    this.branching = config.branching || this.branching;
    this.depth = config.depth || this.depth;

    this.index = 1;

    this.extraEdges = [];
    this.data = {
      nodes: [{
        id: this.index,
        label: this.artist.name,
        color: {
          background: '#666'
        }
      }],
      edges: []
    };

    if (typeof config.treemode != 'undefined')
      this.treemode = config.treemode;
  },

  buildGraph: function() {
    this.counter = 1;

    this.maxNodes = 0;
    for (var i = 0; i <= this.depth; ++i) {
      this.maxNodes += Math.pow(this.branching, i);
    }

    console.log('#### Stats for ' + this.artist.name);
    console.log('# iterations: ' + this.maxNodes);
    this.constructGraph(this.depth - 1, this.artist);
  },

  constructGraph: function(depth, rootArtist) {

    var forEachRelated = function(artist) {
      var duplicated = _.findWhere(this.data.nodes, {
        label: artist.name
      });

      if (duplicated) {
        var inverseEdgeExists = _.findWhere(this.data.edges, {
          from: duplicated.id,
          to: rootArtist.nodeid
        });
        var edgeExists = _.findWhere(this.data.edges, {
          to: duplicated.id,
          from: rootArtist.nodeid
        });

        if (!inverseEdgeExists && !edgeExists) {
          var extraEdge = {
            from: rootArtist.nodeid,
            to: duplicated.id,
            color: '#ddd'
          };

          this.extraEdges.push(extraEdge);
          if (!this.treemode)
            this.data.edges.push(extraEdge);
        }
      } else {
        var nodeid = ++this.index;

        this.data.nodes.push({
          id: nodeid,
          label: artist.name
        });

        this.data.edges.push({
          from: rootArtist.nodeid,
          to: nodeid
        });

        this.relatedArtists.push(artist);

        artist.nodeid = nodeid;
      }

      if (depth > 0)
        this.constructGraph(depth - 1, artist);

      if (++this.counter === this.maxNodes) {
        this.draw(true);
      }
    };

    var relatedSnapshotDone = function(snapshot) {
      var snapshotLoadAll = snapshot.loadAll(['name', 'uri']);

      snapshotLoadAll.each(this, forEachRelated);
    };

    var relatedDone = function(artist) {
      var promiseRelatedSnapshot = artist.related.snapshot(0, this.branching);
      promiseRelatedSnapshot.done(this, relatedSnapshotDone);
    };

    var promiseRelated = rootArtist.load('related');
    promiseRelated.done(this, relatedDone);
  },

  draw: function(debug) {
    this.graph.setData(this.data, {
      disableStart: true
    });
    this.graph.start();
    this.graph.zoomExtent();

    if (this.throbber)
      this.throbber.hide();

    if (debug) {
      console.log('# nodes: ' + this.data.nodes.length);
      console.log('# edges: ' + this.data.edges.length);
    }
  },

  redraw: function() {
    this.graph.redraw();
  }
};

ArtistGraph.prototype.constructor = ArtistGraph;

require(['$api/models'], function(_models) {
  models = _models;

  exports.ArtistGraph = ArtistGraph;
});<|endoftext|>


<commit_before>function giveObjectOption(qs, ls, n){
    var option = {qs : qs, a: ls[0], b: ls[1], c: ls[2], d:[3], ans:ls[n-1]};
    return option;
}

function rounds(){
    var r1 = [giveObjectOption("Question1", "OptionA", "OptionB", "OptionC", "OptionD", 3)
    , giveObjectOption("Question2", "OptionA", "OptionB", "OptionC", "OptionD", 2)
    ]
}
<commit_msg>Add method for updating scores<commit_after>function giveObjectOption(qs, ls, n){
    var question = {qs : qs, a: ls[0], b: ls[1], c: ls[2], d:[3], ans:ls[n-1]};
    return question;
}

function rounds(){
    var r1 = [
    	giveObjectOption("Question1", "OptionA", "OptionB", "OptionC", "OptionD", 3),
    	giveObjectOption("Question2", "OptionA", "OptionB", "OptionC", "OptionD", 2)
    ]

    var r3 = [
    	giveObjectOption("Question1", "OptionA", "OptionB", "OptionC", "OptionD", 3),
    	giveObjectOption("Question2", "OptionA", "OptionB", "OptionC", "OptionD", 2)
    ]
}

function score_update(question, option_provided, team) {
	if (question.ans === option_provided) {
		team.score += 10;
	}
	else {
	 	team.score -= 5;
	}
}<|endoftext|>


<commit_before>'use strict';
exports.info = {
  desc: 'Book Club Commands.',
  usage: '[join | leave | set | done | notify | history | delete]',
  aliases: [],
};

const config = require('../../config');
const request = require('superagent');
const xml2jsParser = require('superagent-xml2jsparser');
const moment = require('moment');
const striptags = require('striptags');

exports.run = (client, msg, params = []) => new Promise((resolve, reject) => {
  // Not used in DMs
  if (msg.channel.type === 'dm') {
    client.utils.dmDenied(msg).then(resolve).catch(reject);
    return;
  }

  // Only used in the Armory Server
  if (msg.guild.id !== '84764735832068096' && msg.guild.id !== '140025699867164673') {
    msg.reply('That command is not available in this Guild.').then(resolve).catch(reject);
    return;
  }

  // Lowercase all parameters
  params = params.map(x => x.toLowerCase());

  // Does the bot have permission to change roles?
  if (!msg.guild.members.get(client.user.id).hasPermission('MANAGE_ROLES_OR_PERMISSIONS')) {
    reject('Bot lacking MANAGE_ROLES permission.');
    return;
  }
  const bcRole = msg.guild.roles.find('name', 'Book Club');
  const bcPresRole = msg.guild.roles.find('name', 'Book Club President');

  if (!bcRole || !bcPresRole) {
    reject('Unable to resolve Role for Book Club.');
    return;
  }

  const usersRoles = msg.member.roles.map(r => r.id);
  const inBookClub = usersRoles.indexOf(bcRole.id) !== -1;
  const isPres = usersRoles.indexOf(bcPresRole.id) !== -1;

  // Show the current book info if we have it
  if (params.length === 0) {
    postBook();
    return;
  }

  // User wants to join the book club
  if (params[0] === 'join') {
    if (inBookClub) {
      msg.reply('You are already in the Book Club and will receive notifications.').then(resolve).catch(reject);
      return;
    }
    msg.member.addRole(bcRole)
      .then(() => msg.reply('Welcome to the Armory Book Club! You will now receive notifications.'), () => {
        msg.reply('There was an error setting your Role.');
      })
      .then(resolve)
      .catch(reject);
    return;
  }

  // User wants to leave the book club
  if (params[0] === 'leave') {
    if (!inBookClub) {
      msg.reply('You were not in the Book Club.').then(resolve).catch(reject);
      return;
    }
    msg.member.removeRole(bcRole)
      .then(() => {
        msg.reply('Thanks for being a part of the Armory Book Club. You will no longer receive notifications.');
      }, () => {
        msg.reply('There was an error setting your Role.');
      })
      .then(resolve)
      .catch(reject);
    return;
  }

  // User wants to see the book club book history
  if (params[0] === 'history') {
    client.mongo.bookClub.find()
      .then(results => {
        if (results.length === 0) {
          msg.reply('There is no Book history yet. Please set a book.').then(resolve).catch(reject);
          return;
        }
        let n = 1;
        const sorted = results
          .sort((a, b) => b.date_added - a.date_added)
          .map(x => {
            const date = moment(x.date_added).format('M/D/YY');
            return `\`\`${n++}.\`\` **${x.book_data.title}** - *${x.book_data.author}* - ${date}` +
              `${x.active ? ' - (CURRENT)' : ''}`;
          });
        msg.channel.send(sorted.join('\n')).then(resolve).catch(reject);
      }).catch(reject);
    return;
  }

  function pres() {
    if (!isPres) {
      msg.reply('You have to be a Book Club President to run this command.').then(resolve).catch(reject);
      return false;
    } else {
      return true;
    }
  }

  // Book Club President want to notify all the members
  if (params[0] === 'notify') {
    if (pres()) {
      // Join the rest of the message in to a string
      const str = msg.content.replace(`${msg.prefix}bc notify`, '').trim();
      bcRole.setMentionable(true)
        .then(() => msg.delete())
        .then(() => msg.channel.send(`<@&${bcRole.id}>\n${str}`))
        .then(() => bcRole.setMentionable(false))
        .then(resolve)
        .catch(reject);
    }
    return;
  }

// Book Club President want to notify all the members
  if (params[0] === 'set') {
    if (pres()) {
      const book = params.splice(1, params.length - 1).join(' ');
      searchBook(book)
        .then(books => {
          books = books.GoodreadsResponse.search[0];
          if (books['total-results'] === 0) {
            msg.reply(`The search returned no results.`).then(resolve).catch(reject);
            return;
          }
          const set = books.results[0].work
            .filter(x => x.best_book[0].$.type === 'Book')
            .splice(0, 5)
            .map(x => {
              return {
                id: x.best_book[0].id[0]._,
                title: x.best_book[0].title[0],
                author: x.best_book[0].author[0].name[0],
                image: x.best_book[0].image_url[0],
                rating: x.average_rating[0],
                year: x.original_publication_year[0]._,
              };
            });
          let num = 1;
          const list = set.map(x => `\`\`${num++}.\`\` **${x.title}** - *${x.author}* - ` +
          `(${x.year}) - Rating: ${x.rating}`);
          msg.channel.send(`Please select a number from the following list within 15 seconds\n\n${list.join('\n')}`)
            .then(listMessage => {
              const collector = msg.channel.createMessageCollector(
                x => x.author.id === msg.author.id, { time: 15000 });
              collector.on('collect', m => {
                const numSel = parseInt(m.content);
                if (!isNaN(numSel) && numSel > 0 && numSel < 6) {
                  collector.stop();
                  // Deactivate all active books
                  client.mongo.bookClub.findOne({ active: true })
                    .then(oldBook => {
                      if (oldBook) {
                        oldBook.active = false;
                        return oldBook.save();
                      }
                      return null;
                    })
                    .then(() => {
                      // Get full book info including synapses
                      const ourSelectedBook = set[numSel - 1];
                      return showBook(ourSelectedBook.id);
                    })
                    .then(bookInfo => {
                      const ourSelectedBook = set[numSel - 1];
                      ourSelectedBook.description = bookInfo.GoodreadsResponse.book[0].description[0];
                      const entry = client.mongo.bookClub({
                        book_data: ourSelectedBook,
                        date_added: new Date(),
                        active: true,
                      });
                      return entry.save();
                    })
                    .then(() => listMessage.delete())
                    .then(() => m.delete())
                    .then(() => postBook())
                    .then(resolve)
                    .catch(reject);
                }
              });
              collector.on('end', (col, reason) => {
                if (reason === 'time') {
                  listMessage.delete().catch(reject);
                }
              });
            })
            .catch(reject);
        });
    }
    return;
  }

  // We are done reading the current book
  if (params[0] === 'done') {
    if (pres()) {
      client.mongo.bookClub.findOne({ active: true })
        .then(result => {
          if (result) {
            result.active = false;
            result.save()
              .then(() => msg.reply('The current book has been saved. Please set a new book.'))
              .then(resolve)
              .catch(reject);
          }
        });
    }
    return;
  }

  function postBook() {
    client.mongo.bookClub.findOne({ active: true })
      .then(result => {
        if (!result) {
          return msg.reply('There is no current book to read. Sorry');
        }
        const book = result.book_data;
        const title = `${book.title} - ${book.author} - ${book.year}`;
        const googleLink = `https://www.google.com/search?q=${encodeURIComponent(title)}`;
        const embed = new client.Discord.RichEmbed()
          .setAuthor(title, 'https://s3.amazonaws.com/DBKynd/armoryBot/bookIcon.png', googleLink)
          .setImage(book.image)
          .setDescription(parseDesc(book.description));
        return msg.channel.send('The current book is:\n', { embed });
      })
      .catch(reject);
  }

  // Book Club President want to delete a db entry
  if (params[0] === 'delete') {
    if (pres()) {
      const num = parseInt(params[1]);
      if (isNaN(num)) {
        msg.reply('Please enter a number of the book entry you would like to delete from the History list.')
          .then(resolve.catch(reject));
        return;
      }
      client.mongo.bookClub.find()
        .then(results => {
          if (num < 1 || num > results.length) {
            msg.reply('That is not an available book entry position.').then(resolve).catch(reject);
            return null;
          }
          const sorted = results.sort((a, b) => b.date_added - a.date_added);
          return sorted[num - 1].remove();
        })
        .then(() => {
          msg.reply(`Entry position ${num} removed successfully`).then(resolve).catch(reject);
        })
        .catch(reject);
    }
    return;
  }

});

function searchBook(query) {
  return new Promise((resolve, reject) => {
    const uri = `https://www.goodreads.com/search?key=${config.goodreads.key}&q=${encodeURIComponent(query)}`;
    request
      .get(uri)
      .accept('xml')
      .buffer()
      .parse(xml2jsParser)
      .end((err, res) => {
        if (err) return reject(err);
        return resolve(res.body);
      });
  });
}

function showBook(id) {
  return new Promise((resolve, reject) => {
    const uri = `https://www.goodreads.com/book/show?format=xml&key=${config.goodreads.key}&id=${id}`;
    request
      .get(uri)
      .accept('xml')
      .buffer()
      .parse(xml2jsParser)
      .end((err, res) => {
        if (err) return reject(err);
        return resolve(res.body);
      });
  });
}

function parseDesc(str) {
  str = str.replace(/<br \/><br \/>/gmi, '\n');
  return striptags(str);
}<commit_msg>add bc list command<commit_after>'use strict';
exports.info = {
  desc: 'Book Club Commands.',
  usage: '[join | leave | set | done | notify | history | delete]',
  aliases: [],
};

const config = require('../../config');
const request = require('superagent');
const xml2jsParser = require('superagent-xml2jsparser');
const moment = require('moment');
const striptags = require('striptags');

exports.run = (client, msg, params = []) => new Promise((resolve, reject) => {
  // Not used in DMs
  if (msg.channel.type === 'dm') {
    client.utils.dmDenied(msg).then(resolve).catch(reject);
    return;
  }

  // Only used in the Armory Server
  if (msg.guild.id !== '84764735832068096' && msg.guild.id !== '140025699867164673') {
    msg.reply('That command is not available in this Guild.').then(resolve).catch(reject);
    return;
  }

  // Lowercase all parameters
  params = params.map(x => x.toLowerCase());

  // Does the bot have permission to change roles?
  if (!msg.guild.members.get(client.user.id).hasPermission('MANAGE_ROLES_OR_PERMISSIONS')) {
    reject('Bot lacking MANAGE_ROLES permission.');
    return;
  }
  const bcRole = msg.guild.roles.find('name', 'Book Club');
  const bcPresRole = msg.guild.roles.find('name', 'Book Club President');

  if (!bcRole || !bcPresRole) {
    reject('Unable to resolve Role for Book Club.');
    return;
  }

  const usersRoles = msg.member.roles.map(r => r.id);
  const inBookClub = usersRoles.indexOf(bcRole.id) !== -1;
  const isPres = usersRoles.indexOf(bcPresRole.id) !== -1;

  // Show the current book info if we have it
  if (params.length === 0) {
    postBook();
    return;
  }

  // User wants to join the book club
  if (params[0] === 'join') {
    if (inBookClub) {
      msg.reply('You are already in the Book Club and will receive notifications.').then(resolve).catch(reject);
      return;
    }
    msg.member.addRole(bcRole)
      .then(() => msg.reply('Welcome to the Armory Book Club! You will now receive notifications.'), () => {
        msg.reply('There was an error setting your Role.');
      })
      .then(resolve)
      .catch(reject);
    return;
  }

  // User wants to leave the book club
  if (params[0] === 'leave') {
    if (!inBookClub) {
      msg.reply('You were not in the Book Club.').then(resolve).catch(reject);
      return;
    }
    msg.member.removeRole(bcRole)
      .then(() => {
        msg.reply('Thanks for being a part of the Armory Book Club. You will no longer receive notifications.');
      }, () => {
        msg.reply('There was an error setting your Role.');
      })
      .then(resolve)
      .catch(reject);
    return;
  }

  // User wants to see the book club book history
  if (params[0] === 'history') {
    client.mongo.bookClub.find()
      .then(results => {
        if (results.length === 0) {
          msg.reply('There is no Book history yet. Please set a book.').then(resolve).catch(reject);
          return;
        }
        let n = 1;
        const sorted = results
          .sort((a, b) => b.date_added - a.date_added)
          .map(x => {
            const date = moment(x.date_added).format('M/D/YY');
            return `\`\`${n++}.\`\` **${x.book_data.title}** - *${x.book_data.author}* - ${date}` +
              `${x.active ? ' - (CURRENT)' : ''}`;
          });
        msg.channel.send(sorted.join('\n')).then(resolve).catch(reject);
      }).catch(reject);
    return;
  }

  function pres() {
    if (!isPres) {
      msg.reply('You have to be a Book Club President to run this command.').then(resolve).catch(reject);
      return false;
    } else {
      return true;
    }
  }

  // Book Club President want to notify all the members
  if (params[0] === 'notify') {
    if (pres()) {
      // Join the rest of the message in to a string
      const str = msg.content.replace(`${msg.prefix}bc notify`, '').trim();
      bcRole.setMentionable(true)
        .then(() => msg.delete())
        .then(() => msg.channel.send(`<@&${bcRole.id}>\n${str}`))
        .then(() => bcRole.setMentionable(false))
        .then(resolve)
        .catch(reject);
    }
    return;
  }

  // Book Club President wants a list of all the bc members
  if (params[0] === 'list') {
    if (pres()) {
      // Get the list of BC members
      const list = msg.guild.members.filter(m => m.roles.has(bcRole.id));
      const names = list.map(m => m.user.tag);
      if (!names || names.length === 0) {
        msg.author.send('There are no Book Club members.').then(resolve).catch(reject);
        return;
      }
      msg.author.send(names, { code: 'text' }).then(resolve).catch(reject);
    }
    return;
  }

  // Book Club President want to set the current book
  if (params[0] === 'set') {
    if (pres()) {
      const book = params.splice(1, params.length - 1).join(' ');
      searchBook(book)
        .then(books => {
          books = books.GoodreadsResponse.search[0];
          if (books['total-results'] === 0) {
            msg.reply(`The search returned no results.`).then(resolve).catch(reject);
            return;
          }
          const set = books.results[0].work
            .filter(x => x.best_book[0].$.type === 'Book')
            .splice(0, 5)
            .map(x => {
              return {
                id: x.best_book[0].id[0]._,
                title: x.best_book[0].title[0],
                author: x.best_book[0].author[0].name[0],
                image: x.best_book[0].image_url[0],
                rating: x.average_rating[0],
                year: x.original_publication_year[0]._,
              };
            });
          let num = 1;
          const list = set.map(x => `\`\`${num++}.\`\` **${x.title}** - *${x.author}* - ` +
          `(${x.year}) - Rating: ${x.rating}`);
          msg.channel.send(`Please select a number from the following list within 15 seconds\n\n${list.join('\n')}`)
            .then(listMessage => {
              const collector = msg.channel.createMessageCollector(
                x => x.author.id === msg.author.id, { time: 15000 });
              collector.on('collect', m => {
                const numSel = parseInt(m.content);
                if (!isNaN(numSel) && numSel > 0 && numSel < 6) {
                  collector.stop();
                  // Deactivate all active books
                  client.mongo.bookClub.findOne({ active: true })
                    .then(oldBook => {
                      if (oldBook) {
                        oldBook.active = false;
                        return oldBook.save();
                      }
                      return null;
                    })
                    .then(() => {
                      // Get full book info including synapses
                      const ourSelectedBook = set[numSel - 1];
                      return showBook(ourSelectedBook.id);
                    })
                    .then(bookInfo => {
                      const ourSelectedBook = set[numSel - 1];
                      ourSelectedBook.description = bookInfo.GoodreadsResponse.book[0].description[0];
                      const entry = client.mongo.bookClub({
                        book_data: ourSelectedBook,
                        date_added: new Date(),
                        active: true,
                      });
                      return entry.save();
                    })
                    .then(() => listMessage.delete())
                    .then(() => m.delete())
                    .then(() => postBook())
                    .then(resolve)
                    .catch(reject);
                }
              });
              collector.on('end', (col, reason) => {
                if (reason === 'time') {
                  listMessage.delete().catch(reject);
                }
              });
            })
            .catch(reject);
        });
    }
    return;
  }

  // We are done reading the current book
  if (params[0] === 'done') {
    if (pres()) {
      client.mongo.bookClub.findOne({ active: true })
        .then(result => {
          if (result) {
            result.active = false;
            result.save()
              .then(() => msg.reply('The current book has been saved. Please set a new book.'))
              .then(resolve)
              .catch(reject);
          }
        });
    }
    return;
  }

  function postBook() {
    client.mongo.bookClub.findOne({ active: true })
      .then(result => {
        if (!result) {
          return msg.reply('There is no current book to read. Sorry');
        }
        const book = result.book_data;
        const title = `${book.title} - ${book.author} - ${book.year}`;
        const googleLink = `https://www.google.com/search?q=${encodeURIComponent(title)}`;
        const embed = new client.Discord.RichEmbed()
          .setAuthor(title, 'https://s3.amazonaws.com/DBKynd/armoryBot/bookIcon.png', googleLink)
          .setImage(book.image)
          .setDescription(parseDesc(book.description));
        return msg.channel.send('The current book is:\n', { embed });
      })
      .catch(reject);
  }

  // Book Club President want to delete a db entry
  if (params[0] === 'delete') {
    if (pres()) {
      const num = parseInt(params[1]);
      if (isNaN(num)) {
        msg.reply('Please enter a number of the book entry you would like to delete from the History list.')
          .then(resolve.catch(reject));
        return;
      }
      client.mongo.bookClub.find()
        .then(results => {
          if (num < 1 || num > results.length) {
            msg.reply('That is not an available book entry position.').then(resolve).catch(reject);
            return null;
          }
          const sorted = results.sort((a, b) => b.date_added - a.date_added);
          return sorted[num - 1].remove();
        })
        .then(() => {
          msg.reply(`Entry position ${num} removed successfully`).then(resolve).catch(reject);
        })
        .catch(reject);
    }
    return;
  }

});

function searchBook(query) {
  return new Promise((resolve, reject) => {
    const uri = `https://www.goodreads.com/search?key=${config.goodreads.key}&q=${encodeURIComponent(query)}`;
    request
      .get(uri)
      .accept('xml')
      .buffer()
      .parse(xml2jsParser)
      .end((err, res) => {
        if (err) return reject(err);
        return resolve(res.body);
      });
  });
}

function showBook(id) {
  return new Promise((resolve, reject) => {
    const uri = `https://www.goodreads.com/book/show?format=xml&key=${config.goodreads.key}&id=${id}`;
    request
      .get(uri)
      .accept('xml')
      .buffer()
      .parse(xml2jsParser)
      .end((err, res) => {
        if (err) return reject(err);
        return resolve(res.body);
      });
  });
}

function parseDesc(str) {
  str = str.replace(/<br \/><br \/>/gmi, '\n');
  return striptags(str);
}<|endoftext|>


<commit_before>/**
 * @overview Stations table interface
 * @module   stations
 * @requires rethinkdb
 */

'use strict';

const database = require('rethinkdb');
const LIMIT    = 30;

function connect() {
  return database.connect({ db: 'radio_api' });
}

function buildFilter(params) {
  let predicate;

  params.forEach((value, param) => {
    if (param !== 'geolocation') {
      predicate = predicate ? predicate.and(database.row(param).match(`(?i)${value}`)) : database.row(param).match(`(?i)${value}`);
    }
  });

  return predicate;
}

function unmarshal(cursor) {
  // Manually convert ReQL `@geolocation` to GeoJSON
  return cursor.toArray().map(station => {
    if ('doc' in station) {
      station = station.doc;
    }

    if (station.geolocation) {
      station.geolocation = {
        coordinates: station.geolocation.coordinates,
        type: station.geolocation.type
      };
    }

    return station;
  });
}

class Stations {
  /**
   * Fetches a set of all radio stations
   * @param   {Object} options        - Hashmap of fetch options
   * @param   {number} options.page   - Page number of stations to fetch
   * @param   {Map}    options.filter - Filtering options
   * @returns {Promise} Fetch operation
   */
  static fetch(options = { page: 1 }) {
    return connect()
      .then(connection => {
        let query = database.table('stations');
        let first;
        let last;

        if (options.filter) {
          const filter = buildFilter(options.filter);
          query = filter ? query.filter(filter) : query;
        }

        if (options.filter && options.filter.has('geolocation')) {
          const [longitude, latitude] = options.filter.get('geolocation').split(',');
          query = query.getNearest(database.point(+longitude, +latitude), { index: 'geolocation' });
        }

        if (options.sort) {
          query = query.orderBy(options.sort);
        }

        if (options.page > 1) {
          first = (options.page - 1) * LIMIT;
          last  = first + (LIMIT);
        } else {
          first = 0;
          last  = LIMIT;
        }

        return query
          .slice(first, last)
          .run(connection)
          .then(unmarshal);
      })
      .catch(err => (
        Promise.reject(new Error('Failed to execute `Stations::fetch`'))
      ));
  }
}

module.exports = Stations;
<commit_msg>Fixed persistence of database connection in `stations`<commit_after>/**
 * @overview Stations table interface
 * @module   stations
 * @requires rethinkdb
 */

'use strict';

const database = require('rethinkdb');
const LIMIT    = 30;

let connection;

function connect() {
  if (connection) {
    return Promise.resolve(connection);
  }

  return database.connect({ db: 'radio_api' }).then(res => {
    connection = res;
    return connection;
  });
}

function buildFilter(params) {
  let predicate;

  params.forEach((value, param) => {
    if (param !== 'geolocation') {
      predicate = predicate ? predicate.and(database.row(param).match(`(?i)${value}`)) : database.row(param).match(`(?i)${value}`);
    }
  });

  return predicate;
}

function unmarshal(cursor) {
  // Manually convert ReQL `@geolocation` to GeoJSON
  return cursor.toArray().map(station => {
    if ('doc' in station) {
      station = station.doc;
    }

    if (station.geolocation) {
      station.geolocation = {
        coordinates: station.geolocation.coordinates,
        type: station.geolocation.type
      };
    }

    return station;
  });
}

class Stations {
  /**
   * Fetches a set of all radio stations
   * @param   {Object} options        - Hashmap of fetch options
   * @param   {number} options.page   - Page number of stations to fetch
   * @param   {Map}    options.filter - Filtering options
   * @returns {Promise} Fetch operation
   */
  static fetch(options = { page: 1 }) {
    return connect()
      .then(connection => {
        let query = database.table('stations');
        let first;
        let last;

        if (options.filter) {
          const filter = buildFilter(options.filter);
          query = filter ? query.filter(filter) : query;
        }

        if (options.filter && options.filter.has('geolocation')) {
          const [longitude, latitude] = options.filter.get('geolocation').split(',');
          query = query.getNearest(database.point(+longitude, +latitude), { index: 'geolocation' });
        }

        if (options.sort) {
          query = query.orderBy(options.sort);
        }

        if (options.page > 1) {
          first = (options.page - 1) * LIMIT;
          last  = first + (LIMIT);
        } else {
          first = 0;
          last  = LIMIT;
        }

        return query
          .slice(first, last)
          .run(connection)
          .then(unmarshal);
      })
      .catch(err => (
        Promise.reject(new Error('Failed to execute `Stations::fetch`'))
      ));
  }
}

module.exports = Stations;
<|endoftext|>


<commit_before>$(document).ready(function() {
    // Facets stuff
    if ($(".facet-container").length > 0) {
        // hide() or show() the toggle containers on load
        $(".facet-container").hide();

        //Switch the "Open" and "Close" state per click then slide up/down (depending on open/close state)
        $("h4.trigger").click(function() {
            $(this).toggleClass("active").next().slideToggle("slow");
            return false; //Prevent the browser jump to the link anchor
        });

        //Check to see if there are any active facets that need to be toggled to open
        var toggles = $(document).find("h4.trigger");
        $.each(toggles, function() {
            if ($(this).hasClass("active")) {
                $(this).next().css("display", "block");
            }
        })
    }

    if ($(".facet-container input[type=checkbox]").length > 0) {
        $(".facet-container input[type=checkbox]").click(function() {
            window.location.href = $(this).val();
        })
    }

    // Scroll to first checked term
    $(".facet-container").each(function(i) {
        $this = $(this);
        $checked = $this.find("input:checked");
        if ($checked.length) {
            $this.animate({
                scrollTop: $checked.offset().top - $this.offset().top - $this.height() / 2
            }, 1);
        }
    });

    $(".ic_container").capslide({
        caption_color    : 'white',
        caption_bgcolor  : 'black',
        overlay_bgcolor  : 'black',
        border           : '',
        showcaption      : true
    });
});<commit_msg>new facet layout and functionality adjustments<commit_after>$(document).ready(function() {
    // Facets stuff
    if ($(".facet-container").length > 0) {
        // hide() or show() the toggle containers on load
        $(".facet-container").hide();

        //Switch the "Open" and "Close" state per click then slide up/down (depending on open/close state)
        $("h4.trigger").click(function() {
            $(this).toggleClass("active").next().slideToggle("slow");
            return false; //Prevent the browser jump to the link anchor
        });

        //Check to see if there are any active facets that need to be toggled to open
        var toggles = $(document).find("h4.trigger");
        $.each(toggles, function() {
            if ($(this).hasClass("active")) {
                $(this).next().css("display", "block").delay(2500).hide('slow');
                $(this).removeClass("active");

            }
        })
    }

    if ($(".facet-container input[type=checkbox]").length > 0) {
        $(".facet-container input[type=checkbox]").click(function() {
            window.location.href = $(this).val();
        })
    }

    // Scroll to first checked term
    $(".facet-container").each(
        function(i) {
            $this = $(this);
            $checked = $this.find("input:checked");
            if ($checked.length) {
                $this.animate({
                    scrollTop: $checked.offset().top - $this.offset().top - $this.height() / 2
                }, 1);
            }
    });

    $(".ic_container").capslide({
        caption_color    : 'white',
        caption_bgcolor  : 'black',
        overlay_bgcolor  : 'black',
        border           : '',
        showcaption      : true
    });
});<|endoftext|>


<commit_before>var assert = require('assert');
var fs = require('fs-extra');
var miaow = require('miaow');
var path = require('path');

var parse = require('../index');
describe('miaow-css-mini', function () {
  this.timeout(10e3);

  var log;

  var cwd = path.resolve(__dirname, './fixtures');
  var output = path.resolve(__dirname, './output');

  function doCompile(cb) {
    miaow.compile({
      cwd: cwd,
      output: output,
      pack: false,
      module: {
        tasks: [
          {
            test: /\.css$/,
            plugins: [{
              plugin: parse,
              option: {
                compatibility: 'ie7'
              }
            }]
          }
        ]
      }
    }, function (err) {
      if (err) {
        console.error(err.toString());
        throw err;
      }

      log = JSON.parse(fs.readFileSync(path.join(output, 'miaow.log.json')));
      cb();
    });
  }

  before(function (done) {
    fs.emptyDirSync(output);
    doCompile(done);
  });

  it('接口是否存在', function () {
    assert(!!parse);
  });

  it('压缩', function () {
    console.log(log.modules);
    assert.equal(log.modules['foo.css'].hash, '034cfd8f122bc6d61b9b8376e1e55cd1');
  });

  it('缓存', function (done) {
    var fooPath = path.join(output, 'foo.css');
    fs.writeFileSync(fooPath, '/* load cache */');

    doCompile(function () {
      assert.equal(fs.readFileSync(fooPath, {encoding: 'utf8'}), '/* load cache */');
      done();
    });
  });
});
<commit_msg>修改测试压缩成功与否的方法<commit_after>var assert = require('assert');
var fs = require('fs-extra');
var miaow = require('miaow');
var path = require('path');

var parse = require('../index');
describe('miaow-css-mini', function () {
  this.timeout(10e3);

  var log;

  var cwd = path.resolve(__dirname, './fixtures');
  var output = path.resolve(__dirname, './output');

  function doCompile(cb) {
    miaow.compile({
      cwd: cwd,
      output: output,
      pack: false,
      module: {
        tasks: [
          {
            test: /\.css$/,
            plugins: [{
              plugin: parse,
              option: {
                compatibility: 'ie7'
              }
            }]
          }
        ]
      }
    }, function (err) {
      if (err) {
        console.error(err.toString());
        throw err;
      }

      log = JSON.parse(fs.readFileSync(path.join(output, 'miaow.log.json')));
      cb();
    });
  }

  before(function (done) {
    fs.emptyDirSync(output);
    doCompile(done);
  });

  it('接口是否存在', function () {
    assert(!!parse);
  });

  it('压缩', function () {
    var stat = fs.statSync(path.join(output, 'foo.css'));
    assert.equal(stat.size, 56);
  });

  it('缓存', function (done) {
    var fooPath = path.join(output, 'foo.css');
    fs.writeFileSync(fooPath, '/* load cache */');

    doCompile(function () {
      assert.equal(fs.readFileSync(fooPath, {encoding: 'utf8'}), '/* load cache */');
      done();
    });
  });
});
<|endoftext|>


<commit_before>import { SYNC_RENDER, NO_RENDER, FORCE_RENDER, ASYNC_RENDER, ATTR_KEY } from '../constants';
import options from '../options';
import { extend } from '../util';
import { enqueueRender } from '../render-queue';
import { getNodeProps } from './index';
import { diff, mounts, diffLevel, flushMounts, recollectNodeTree, removeChildren } from './diff';
import { createComponent, collectComponent } from './component-recycler';
import { removeNode } from '../dom/index';

/**
 * Set a component's `props` and possibly re-render the component
 * @param {import('../component').Component} component The Component to set props on
 * @param {object} props The new props
 * @param {number} renderMode Render options - specifies how to re-render the component
 * @param {object} context The new context
 * @param {boolean} mountAll Whether or not to immediately mount all components
 */
export function setComponentProps(component, props, renderMode, context, mountAll) {
	if (component._disable) return;
	component._disable = true;

	if ((component.__ref = props.ref)) delete props.ref;
	if ((component.__key = props.key)) delete props.key;

	if (typeof component.constructor.getDerivedStateFromProps === 'undefined') {
		if (!component.base || mountAll) {
			if (component.componentWillMount) component.componentWillMount();
		}
		else if (component.componentWillReceiveProps) {
			component.componentWillReceiveProps(props, context);
		}
	}

	if (context && context!==component.context) {
		if (!component.prevContext) component.prevContext = component.context;
		component.context = context;
	}

	if (!component.prevProps) component.prevProps = component.props;
	component.props = props;

	component._disable = false;

	if (renderMode!==NO_RENDER) {
		if (renderMode===SYNC_RENDER || options.syncComponentUpdates!==false || !component.base) {
			renderComponent(component, SYNC_RENDER, mountAll);
		}
		else {
			enqueueRender(component);
		}
	}

	if (component.__ref) component.__ref(component);
}

/**
 * Render a Component, triggering necessary lifecycle events and taking
 * High-Order Components into account.
 * @param {import('../component').Component} component The component to render
 * @param {number} [renderMode] render mode, see constants.js for available options.
 * @param {boolean} [mountAll] Whether or not to immediately mount all components
 * @param {boolean} [isChild] ?
 * @private
 */
export function renderComponent(component, renderMode, mountAll, isChild) {
	if (component._disable) return;

	let props = component.props,
		state = component.state,
		context = component.context,
		previousProps = component.prevProps || props,
		previousState = component.prevState || state,
		previousContext = component.prevContext || context,
		isUpdate = component.base,
		nextBase = component.nextBase,
		initialBase = isUpdate || nextBase,
		initialChildComponent = component._component,
		skip = false,
		snapshot = previousContext,
		rendered, inst, cbase;

	if (component.constructor.getDerivedStateFromProps) {
		previousState = extend({}, previousState);
		component.state = extend(state, component.constructor.getDerivedStateFromProps(props, state));
	}

	// if updating
	if (isUpdate) {
		component.props = previousProps;
		component.state = previousState;
		component.context = previousContext;
		if (renderMode!==FORCE_RENDER
			&& component.shouldComponentUpdate
			&& component.shouldComponentUpdate(props, state, context) === false) {
			skip = true;
		}
		else if (component.componentWillUpdate) {
			component.componentWillUpdate(props, state, context);
		}
		component.props = props;
		component.state = state;
		component.context = context;
	}

	component.prevProps = component.prevState = component.prevContext = component.nextBase = null;
	component._dirty = false;

	if (!skip) {
		rendered = component.render(props, state, context);

		// context to pass to the child, can be updated via (grand-)parent component
		if (component.getChildContext) {
			context = extend(extend({}, context), component.getChildContext());
		}

		if (isUpdate && component.getSnapshotBeforeUpdate) {
			snapshot = component.getSnapshotBeforeUpdate(previousProps, previousState);
		}

		let childComponent = rendered && rendered.nodeName,
			toUnmount, base;

		if (typeof childComponent==='function') {
			// set up high order component link

			let childProps = getNodeProps(rendered);
			inst = initialChildComponent;

			if (inst && inst.constructor===childComponent && childProps.key==inst.__key) {
				setComponentProps(inst, childProps, SYNC_RENDER, context, false);
			}
			else {
				toUnmount = inst;

				component._component = inst = createComponent(childComponent, childProps, context);
				inst.nextBase = inst.nextBase || nextBase;
				inst._parentComponent = component;
				setComponentProps(inst, childProps, NO_RENDER, context, false);
				renderComponent(inst, SYNC_RENDER, mountAll, true);
			}

			base = inst.base;
		}
		else {
			cbase = initialBase;

			// destroy high order component link
			toUnmount = initialChildComponent;
			if (toUnmount) {
				cbase = component._component = null;
			}

			if (initialBase || renderMode===SYNC_RENDER) {
				if (cbase) cbase._component = null;
				base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, true);
			}
		}

		if (initialBase && base!==initialBase && inst!==initialChildComponent) {
			let baseParent = initialBase.parentNode;
			if (baseParent && base!==baseParent) {
				baseParent.replaceChild(base, initialBase);

				if (!toUnmount) {
					initialBase._component = null;
					recollectNodeTree(initialBase, false);
				}
			}
		}

		if (toUnmount) {
			unmountComponent(toUnmount);
		}

		component.base = base;
		if (base && !isChild) {
			let componentRef = component,
				t = component;
			while ((t=t._parentComponent)) {
				(componentRef = t).base = base;
			}
			base._component = componentRef;
			base._componentConstructor = componentRef.constructor;
		}
	}

	if (!isUpdate || mountAll) {
		mounts.unshift(component);
	}
	else if (!skip) {
		// Ensure that pending componentDidMount() hooks of child components
		// are called before the componentDidUpdate() hook in the parent.
		// Note: disabled as it causes duplicate hooks, see https://github.com/developit/preact/issues/750
		// flushMounts();

		if (component.componentDidUpdate) {
			component.componentDidUpdate(previousProps, previousState, snapshot);
		}
		if (options.afterUpdate) options.afterUpdate(component);
	}

	while (component._renderCallbacks.length) component._renderCallbacks.pop().call(component);

	if (!diffLevel && !isChild) flushMounts();
}

/**
 * Apply the Component referenced by a VNode to the DOM.
 * @param {import('../dom').PreactElement} dom The DOM node to mutate
 * @param {import('../vnode').VNode} vnode A Component-referencing VNode
 * @param {object} context The current context
 * @param {boolean} mountAll Whether or not to immediately mount all components
 * @returns {import('../dom').PreactElement} The created/mutated element
 * @private
 */
export function buildComponentFromVNode(dom, vnode, context, mountAll) {
	let c = dom && dom._component,
		originalComponent = c,
		oldDom = dom,
		isDirectOwner = c && dom._componentConstructor===vnode.nodeName,
		isOwner = isDirectOwner,
		props = getNodeProps(vnode);
	while (c && !isOwner && (c=c._parentComponent)) {
		isOwner = c.constructor===vnode.nodeName;
	}

	if (c && isOwner && (!mountAll || c._component)) {
		setComponentProps(c, props, ASYNC_RENDER, context, mountAll);
		dom = c.base;
	}
	else {
		if (originalComponent && !isDirectOwner) {
			unmountComponent(originalComponent);
			dom = oldDom = null;
		}

		c = createComponent(vnode.nodeName, props, context);
		if (dom && !c.nextBase) {
			c.nextBase = dom;
			// passing dom/oldDom as nextBase will recycle it if unused, so bypass recycling on L229:
			oldDom = null;
		}
		setComponentProps(c, props, SYNC_RENDER, context, mountAll);
		dom = c.base;

		if (oldDom && dom!==oldDom) {
			oldDom._component = null;
			recollectNodeTree(oldDom, false);
		}
	}

	return dom;
}

/**
 * Remove a component from the DOM and recycle it.
 * @param {import('../component').Component} component The Component instance to unmount
 * @private
 */
export function unmountComponent(component) {
	if (options.beforeUnmount) options.beforeUnmount(component);

	let base = component.base;

	component._disable = true;

	if (component.componentWillUnmount) component.componentWillUnmount();

	component.base = null;

	// recursively tear down & recollect high-order component children:
	let inner = component._component;
	if (inner) {
		unmountComponent(inner);
	}
	else if (base) {
		if (base[ATTR_KEY] && base[ATTR_KEY].ref) base[ATTR_KEY].ref(null);

		component.nextBase = base;

		removeNode(base);
		collectComponent(component);

		removeChildren(base);
	}

	if (component.__ref) component.__ref(null);
}
<commit_msg>Alternative implementations<commit_after>import { SYNC_RENDER, NO_RENDER, FORCE_RENDER, ASYNC_RENDER, ATTR_KEY } from '../constants';
import options from '../options';
import { extend } from '../util';
import { enqueueRender } from '../render-queue';
import { getNodeProps } from './index';
import { diff, mounts, diffLevel, flushMounts, recollectNodeTree, removeChildren } from './diff';
import { createComponent, collectComponent } from './component-recycler';
import { removeNode } from '../dom/index';

/**
 * Set a component's `props` and possibly re-render the component
 * @param {import('../component').Component} component The Component to set props on
 * @param {object} props The new props
 * @param {number} renderMode Render options - specifies how to re-render the component
 * @param {object} context The new context
 * @param {boolean} mountAll Whether or not to immediately mount all components
 */
export function setComponentProps(component, props, renderMode, context, mountAll) {
	if (component._disable) return;
	component._disable = true;

	// if ((component.__ref = props.ref)) delete props.ref;
	// if ((component.__key = props.key)) delete props.key;

	// component.__ref = props.ref;
	// component.__key = props.key;
	// if ('ref' in props) delete props.ref;
	// if ('key' in props) delete props.key;

	// if ('ref' in props) {
	// 	component.__ref = props.ref;
	// 	delete props.ref;
	// }
	// if ('key' in props) {
	// 	component.__key = props.key;
	// 	delete props.key;
	// }

	if (typeof component.constructor.getDerivedStateFromProps === 'undefined') {
		if (!component.base || mountAll) {
			if (component.componentWillMount) component.componentWillMount();
		}
		else if (component.componentWillReceiveProps) {
			component.componentWillReceiveProps(props, context);
		}
	}

	if (context && context!==component.context) {
		if (!component.prevContext) component.prevContext = component.context;
		component.context = context;
	}

	if (!component.prevProps) component.prevProps = component.props;
	component.props = props;

	component._disable = false;

	if (renderMode!==NO_RENDER) {
		if (renderMode===SYNC_RENDER || options.syncComponentUpdates!==false || !component.base) {
			renderComponent(component, SYNC_RENDER, mountAll);
		}
		else {
			enqueueRender(component);
		}
	}

	if (component.__ref) component.__ref(component);
}

/**
 * Render a Component, triggering necessary lifecycle events and taking
 * High-Order Components into account.
 * @param {import('../component').Component} component The component to render
 * @param {number} [renderMode] render mode, see constants.js for available options.
 * @param {boolean} [mountAll] Whether or not to immediately mount all components
 * @param {boolean} [isChild] ?
 * @private
 */
export function renderComponent(component, renderMode, mountAll, isChild) {
	if (component._disable) return;

	let props = component.props,
		state = component.state,
		context = component.context,
		previousProps = component.prevProps || props,
		previousState = component.prevState || state,
		previousContext = component.prevContext || context,
		isUpdate = component.base,
		nextBase = component.nextBase,
		initialBase = isUpdate || nextBase,
		initialChildComponent = component._component,
		skip = false,
		snapshot = previousContext,
		rendered, inst, cbase;

	if (component.constructor.getDerivedStateFromProps) {
		previousState = extend({}, previousState);
		component.state = extend(state, component.constructor.getDerivedStateFromProps(props, state));
	}

	// if updating
	if (isUpdate) {
		component.props = previousProps;
		component.state = previousState;
		component.context = previousContext;
		if (renderMode!==FORCE_RENDER
			&& component.shouldComponentUpdate
			&& component.shouldComponentUpdate(props, state, context) === false) {
			skip = true;
		}
		else if (component.componentWillUpdate) {
			component.componentWillUpdate(props, state, context);
		}
		component.props = props;
		component.state = state;
		component.context = context;
	}

	component.prevProps = component.prevState = component.prevContext = component.nextBase = null;
	component._dirty = false;

	if (!skip) {
		rendered = component.render(props, state, context);

		// context to pass to the child, can be updated via (grand-)parent component
		if (component.getChildContext) {
			context = extend(extend({}, context), component.getChildContext());
		}

		if (isUpdate && component.getSnapshotBeforeUpdate) {
			snapshot = component.getSnapshotBeforeUpdate(previousProps, previousState);
		}

		let childComponent = rendered && rendered.nodeName,
			toUnmount, base;

		if (typeof childComponent==='function') {
			// set up high order component link

			let childProps = getNodeProps(rendered);
			inst = initialChildComponent;

			if (inst && inst.constructor===childComponent && childProps.key==inst.__key) {
				setComponentProps(inst, childProps, SYNC_RENDER, context, false);
			}
			else {
				toUnmount = inst;

				component._component = inst = createComponent(childComponent, childProps, context);
				inst.nextBase = inst.nextBase || nextBase;
				inst._parentComponent = component;
				setComponentProps(inst, childProps, NO_RENDER, context, false);
				renderComponent(inst, SYNC_RENDER, mountAll, true);
			}

			base = inst.base;
		}
		else {
			cbase = initialBase;

			// destroy high order component link
			toUnmount = initialChildComponent;
			if (toUnmount) {
				cbase = component._component = null;
			}

			if (initialBase || renderMode===SYNC_RENDER) {
				if (cbase) cbase._component = null;
				base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, true);
			}
		}

		if (initialBase && base!==initialBase && inst!==initialChildComponent) {
			let baseParent = initialBase.parentNode;
			if (baseParent && base!==baseParent) {
				baseParent.replaceChild(base, initialBase);

				if (!toUnmount) {
					initialBase._component = null;
					recollectNodeTree(initialBase, false);
				}
			}
		}

		if (toUnmount) {
			unmountComponent(toUnmount);
		}

		component.base = base;
		if (base && !isChild) {
			let componentRef = component,
				t = component;
			while ((t=t._parentComponent)) {
				(componentRef = t).base = base;
			}
			base._component = componentRef;
			base._componentConstructor = componentRef.constructor;
		}
	}

	if (!isUpdate || mountAll) {
		mounts.unshift(component);
	}
	else if (!skip) {
		// Ensure that pending componentDidMount() hooks of child components
		// are called before the componentDidUpdate() hook in the parent.
		// Note: disabled as it causes duplicate hooks, see https://github.com/developit/preact/issues/750
		// flushMounts();

		if (component.componentDidUpdate) {
			component.componentDidUpdate(previousProps, previousState, snapshot);
		}
		if (options.afterUpdate) options.afterUpdate(component);
	}

	while (component._renderCallbacks.length) component._renderCallbacks.pop().call(component);

	if (!diffLevel && !isChild) flushMounts();
}

/**
 * Apply the Component referenced by a VNode to the DOM.
 * @param {import('../dom').PreactElement} dom The DOM node to mutate
 * @param {import('../vnode').VNode} vnode A Component-referencing VNode
 * @param {object} context The current context
 * @param {boolean} mountAll Whether or not to immediately mount all components
 * @returns {import('../dom').PreactElement} The created/mutated element
 * @private
 */
export function buildComponentFromVNode(dom, vnode, context, mountAll) {
	let c = dom && dom._component,
		originalComponent = c,
		oldDom = dom,
		isDirectOwner = c && dom._componentConstructor===vnode.nodeName,
		isOwner = isDirectOwner,
		props = getNodeProps(vnode);
	while (c && !isOwner && (c=c._parentComponent)) {
		isOwner = c.constructor===vnode.nodeName;
	}

	if (c && isOwner && (!mountAll || c._component)) {
		setComponentProps(c, props, ASYNC_RENDER, context, mountAll);
		dom = c.base;
	}
	else {
		if (originalComponent && !isDirectOwner) {
			unmountComponent(originalComponent);
			dom = oldDom = null;
		}

		c = createComponent(vnode.nodeName, props, context);
		if (dom && !c.nextBase) {
			c.nextBase = dom;
			// passing dom/oldDom as nextBase will recycle it if unused, so bypass recycling on L229:
			oldDom = null;
		}
		setComponentProps(c, props, SYNC_RENDER, context, mountAll);
		dom = c.base;

		if (oldDom && dom!==oldDom) {
			oldDom._component = null;
			recollectNodeTree(oldDom, false);
		}
	}

	return dom;
}

/**
 * Remove a component from the DOM and recycle it.
 * @param {import('../component').Component} component The Component instance to unmount
 * @private
 */
export function unmountComponent(component) {
	if (options.beforeUnmount) options.beforeUnmount(component);

	let base = component.base;

	component._disable = true;

	if (component.componentWillUnmount) component.componentWillUnmount();

	component.base = null;

	// recursively tear down & recollect high-order component children:
	let inner = component._component;
	if (inner) {
		unmountComponent(inner);
	}
	else if (base) {
		if (base[ATTR_KEY] && base[ATTR_KEY].ref) base[ATTR_KEY].ref(null);

		component.nextBase = base;

		removeNode(base);
		collectComponent(component);

		removeChildren(base);
	}

	if (component.__ref) component.__ref(null);
}
<|endoftext|>


<commit_before>// Include The 'require.async' Module
require("require.async")(require);

/**
 * Tokenizes an input string.
 *
 * @param {String} Input
 *
 * @return {Array}
 */
function tokenize (input) {
    return input
            .replace(/[^a-zA-Z ]+/g, "")
            .replace("/ {2,}/", " ")
            .toLowerCase()
            .split(" ");
}

/**
 * Performs sentiment analysis on the provided input "term".
 *
 * @param {String} Input term
 *
 * @return {Object}
 */
module.exports = function (term, callback) {

	// Include the AFINN Dictionary JSON asynchronously
	require.async("./AFINN.json", function(afinn) {

        // Split line term to letters only words array
        var words = tokenize(term || "");
        var score = 0;
        var rate;
        var i = 0;

        function calculate(word) {
            // Get the word rate from the AFINN dictionary
            rate = afinn[word];
            if (rate) {
                // Add current word rate to the final calculated sentiment score
                score += rate;
            }

            // Defer next turn execution (Etheration)
            setImmediate(function() {
                // Use callback for completion
                if (i === (words.length - 1)) {
                    callback(null, score);
                }
                else {
                    // Invoke next turn
                    calculate(words[++i]);
                }
            });
        }

        // Start calculating
        calculate(i);
	});
};
<commit_msg>Fix bug in sentiment calculation<commit_after>// Include The 'require.async' Module
require("require.async")(require);

/**
 * Tokenizes an input string.
 *
 * @param {String} Input
 *
 * @return {Array}
 */
function tokenize (input) {
    return input
            .replace(/[^a-zA-Z ]+/g, "")
            .replace("/ {2,}/", " ")
            .toLowerCase()
            .split(" ");
}

/**
 * Performs sentiment analysis on the provided input "term".
 *
 * @param {String} Input term
 *
 * @return {Object}
 */
module.exports = function (term, callback) {

	// Include the AFINN Dictionary JSON asynchronously
	require.async("./AFINN.json", function(afinn) {

        // Split line term to letters only words array
        var words = tokenize(term || "");
        var score = 0;
        var rate;
        var i = 0;

        function calculate(word) {
            // Get the word rate from the AFINN dictionary
            rate = afinn[word];
            if (rate) {
                // Add current word rate to the final calculated sentiment score
                score += rate;
            }

            // Defer next turn execution (Etheration)
            setImmediate(function() {
                // Use callback for completion
                if (i === (words.length - 1)) {
                    callback(null, score);
                }
                else {
                    // Invoke next turn
                    calculate(words[++i]);
                }
            });
        }

        // Start calculating
        calculate(words[i]);
	});
};
<|endoftext|>


<commit_before>/*global module: false, require: false, window: false */
'use strict';

var React = require('react');
var PureRenderMixin = require('./PureRenderMixin');
var DataTable = require('./DataTable');
require('react-data-components-bd2k/css/table-twbs.css');
var _ = require('underscore');
var {utils} = require('react-data-components-bd2k');

function buildHeader(onClick, title) {
	return (

			{title}
			 {ev.stopPropagation(); onClick(title); }}
				className='help glyphicon glyphicon-question-sign superscript'/>

	);
}

function renderClinVarLink(val) {
	return (
		 ev.stopPropagation()}
			href={"http://www.ncbi.nlm.nih.gov/clinvar/?term=" + val}>{val}
	);
}

function renderCell(val) {
	return {val};
}

var filterColumns = [
	{name: 'Gene', prop: 'Gene_symbol', values: ['BRCA1', 'BRCA2']},
//	{name: 'Exon', values: ['Any', 1, 2, 3, 4, 5]}, // XXX needs refgene to get exon count
	{name: 'Pathogenicity', prop: 'Clinical_significance', values: ['Pathogenic', 'Benign']}
];

// This callback is used to apply all active filters. We override the
// one in react-data-components.utils, which performs a union of all
// matches, with this one which does an intersection.
var applyFilters = (filters, filterValues, data) => {
	return _.filter(data, row => _.every(filterValues, utils.filterPass(filters, row)));
};

// react-data-components filters are an object with keys for each filter, and
// values being a object with props 'filter', and optional 'prop' if the filter
// applies to just one property. Here we have filters 'visibleSearch', which does
// a 'string contains' filter on the visible columns, plus filters for each column
// that has a filter UI control.
// {visibleSearch: {filter: ...}, 'Gene symbol': {prop: 'Gene symbol', filter: ...}}
function filters(columns) {
	var visible = _.object(_.map(columns, c => [c.prop, true]));
	var colFilters = _.object(_.map(filterColumns, c =>
		[c.prop, {
			filter: (fv, val) => _.isNull(fv) || fv === val,
			prop: c.prop
		}]
	));
	return _.extend({
		visibleSearch: {
			filter: (filterValue, value, key) => visible[key] &&
				value.toLowerCase().indexOf(filterValue.toLowerCase()) !== -1
		}
	}, colFilters);
}

var strPropCmpFn = prop => (a, b) => {
	var ap = a[prop],
		bp = b[prop];
	if (ap == null && bp == null || ap === bp) {
		return 0;
	}
	if (bp == null || bp < ap) {
		return 1;
	}
	return -1;
};

var posCmpFn = strPropCmpFn('Genomic_Coordinate');

function sortColumns(columns, {prop, order}, data) {
	var sortFn = _.findWhere(columns, {prop: prop}).sortFn || strPropCmpFn(prop),
		sorted = data.slice(0).sort(sortFn);
	if (order === 'descending') {
		sorted.reverse();
	}
	return sorted;
}

var columns = [
	{title: 'Gene', prop: 'Gene_symbol', render: renderCell},
	{title: 'HGVS cDNA', prop: 'HGVS_cDNA', sortFn: posCmpFn, render: renderCell},
	{title: 'HGVS protein', prop: 'HGVS_protein', sortFn: posCmpFn, render: renderCell},
	{title: 'BIC', prop: "BIC_Nomenclature", render: renderCell},
	{title: 'Abbrev AA Change', prop: "Abbrev_AA_change", render: renderCell},
	{title: 'Genomic Coordinate', prop: 'Genomic_Coordinate', render: renderCell},
	{title: 'Pathogenicity', prop: 'Clinical_significance', render: renderCell},
	{title: 'ClinVar Link', prop: 'ClinVarAccession', render: renderClinVarLink}
];

// Work-around to allow the user to select text in the table. The browser does not distinguish between
// click and drag: if mouseup and mousedown occur on the same element, a click event is fired even if
// the events occur at very different locations. That makes it hard to select text. This workaround
// defeats the click event if text has been selected.
//
// XXX getSelection().isCollapsed is not available on all platforms. On those platforms we
// will always return false (no selection), so the row click will fire. This makes it hard
// for the user to select text in the table. A better solution would be to add a polyfill for
// getSelection and isCollapsed. There are a few available, though they are much larger than
// what we require:
// https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#dom-range-and-selection
// We might want to write a minimal isCollapsed that will use whichever DOM method is available. We could
// also add feature detection, and modify the UI if the feature is not available. E.g. we could style the
// text areas to look clickable instead of selectable..
var hasSelection = () => !(window.getSelection && window.getSelection().isCollapsed);

var VariantTable = React.createClass({
	mixins: [PureRenderMixin],
	getData: function () {
		return this.refs.table.state.data;
	},
	render: function () {
		var {data, onHeaderClick, onRowClick, ...opts} = this.props;
		return (
			<DataTable
				ref='table'
				className='row-clickable'
				{...opts}
				buildRowOptions={r => ({title: 'click for details', onClick: () => hasSelection() ? null : onRowClick(r)})}
				buildHeader={title => buildHeader(onHeaderClick, title)}
				sort={(sb, d) => sortColumns(columns, sb, d)}
				filter={applyFilters}
				filters={filters(columns)}
				filterColumns={filterColumns}
				columns={columns}
				initialData={data}
				initialPageLength={20}
                initialSortBy={{prop: 'Abbrev_AA_change', order: 'descending'}}
                pageLengthOptions={[ 20, 50, 100 ]}
            />
		);
	}
});

module.exports = VariantTable;
<commit_msg>change table column names<commit_after>/*global module: false, require: false, window: false */
'use strict';

var React = require('react');
var PureRenderMixin = require('./PureRenderMixin');
var DataTable = require('./DataTable');
require('react-data-components-bd2k/css/table-twbs.css');
var _ = require('underscore');
var {utils} = require('react-data-components-bd2k');

function buildHeader(onClick, title) {
	return (

			{title}
			 {ev.stopPropagation(); onClick(title); }}
				className='help glyphicon glyphicon-question-sign superscript'/>

	);
}

function renderClinVarLink(val) {
	return (
		 ev.stopPropagation()}
			href={"http://www.ncbi.nlm.nih.gov/clinvar/?term=" + val}>{val}
	);
}

function renderCell(val) {
	return {val};
}

var filterColumns = [
	{name: 'Gene', prop: 'Gene_symbol', values: ['BRCA1', 'BRCA2']},
//	{name: 'Exon', values: ['Any', 1, 2, 3, 4, 5]}, // XXX needs refgene to get exon count
	{name: 'Pathogenicity', prop: 'Clinical_significance', values: ['Pathogenic', 'Benign']}
];

// This callback is used to apply all active filters. We override the
// one in react-data-components.utils, which performs a union of all
// matches, with this one which does an intersection.
var applyFilters = (filters, filterValues, data) => {
	return _.filter(data, row => _.every(filterValues, utils.filterPass(filters, row)));
};

// react-data-components filters are an object with keys for each filter, and
// values being a object with props 'filter', and optional 'prop' if the filter
// applies to just one property. Here we have filters 'visibleSearch', which does
// a 'string contains' filter on the visible columns, plus filters for each column
// that has a filter UI control.
// {visibleSearch: {filter: ...}, 'Gene symbol': {prop: 'Gene symbol', filter: ...}}
function filters(columns) {
	var visible = _.object(_.map(columns, c => [c.prop, true]));
	var colFilters = _.object(_.map(filterColumns, c =>
		[c.prop, {
			filter: (fv, val) => _.isNull(fv) || fv === val,
			prop: c.prop
		}]
	));
	return _.extend({
		visibleSearch: {
			filter: (filterValue, value, key) => visible[key] &&
				value.toLowerCase().indexOf(filterValue.toLowerCase()) !== -1
		}
	}, colFilters);
}

var strPropCmpFn = prop => (a, b) => {
	var ap = a[prop],
		bp = b[prop];
	if (ap == null && bp == null || ap === bp) {
		return 0;
	}
	if (bp == null || bp < ap) {
		return 1;
	}
	return -1;
};

var posCmpFn = strPropCmpFn('Genomic_Coordinate');

function sortColumns(columns, {prop, order}, data) {
	var sortFn = _.findWhere(columns, {prop: prop}).sortFn || strPropCmpFn(prop),
		sorted = data.slice(0).sort(sortFn);
	if (order === 'descending') {
		sorted.reverse();
	}
	return sorted;
}

var columns = [
	{title: 'Gene', prop: 'Gene_symbol', render: renderCell},
	{title: 'Genomic Coordinate', prop: 'Genomic_Coordinate', render: renderCell},
    {title: 'HGVS cDNA', prop: 'HGVS_cDNA', sortFn: posCmpFn, render: renderCell},
	{title: 'HGVS protein', prop: 'HGVS_protein', sortFn: posCmpFn, render: renderCell},
	{title: 'HGVS protein (Abbrev.)', prop: "Abbrev_AA_change", render: renderCell},
    {title: 'BIC nucleotide', prop: "BIC_Nomenclature", render: renderCell},
	{title: 'Pathogenicity', prop: 'Clinical_significance', render: renderCell}
];

// Work-around to allow the user to select text in the table. The browser does not distinguish between
// click and drag: if mouseup and mousedown occur on the same element, a click event is fired even if
// the events occur at very different locations. That makes it hard to select text. This workaround
// defeats the click event if text has been selected.
//
// XXX getSelection().isCollapsed is not available on all platforms. On those platforms we
// will always return false (no selection), so the row click will fire. This makes it hard
// for the user to select text in the table. A better solution would be to add a polyfill for
// getSelection and isCollapsed. There are a few available, though they are much larger than
// what we require:
// https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#dom-range-and-selection
// We might want to write a minimal isCollapsed that will use whichever DOM method is available. We could
// also add feature detection, and modify the UI if the feature is not available. E.g. we could style the
// text areas to look clickable instead of selectable..
var hasSelection = () => !(window.getSelection && window.getSelection().isCollapsed);

var VariantTable = React.createClass({
	mixins: [PureRenderMixin],
	getData: function () {
		return this.refs.table.state.data;
	},
	render: function () {
		var {data, onHeaderClick, onRowClick, ...opts} = this.props;
		return (
			<DataTable
				ref='table'
				className='row-clickable'
				{...opts}
				buildRowOptions={r => ({title: 'click for details', onClick: () => hasSelection() ? null : onRowClick(r)})}
				buildHeader={title => buildHeader(onHeaderClick, title)}
				sort={(sb, d) => sortColumns(columns, sb, d)}
				filter={applyFilters}
				filters={filters(columns)}
				filterColumns={filterColumns}
				columns={columns}
				initialData={data}
				initialPageLength={20}
                initialSortBy={{prop: 'Abbrev_AA_change', order: 'descending'}}
                pageLengthOptions={[ 20, 50, 100 ]}
            />
		);
	}
});

module.exports = VariantTable;
<|endoftext|>


<commit_before>(function() {
  'use strict';
  /**
   *  @ngdoc overview
   *  @name ui.grid.autoScroll
   *
   *  @description
   *
   * #ui.grid.autoScroll
   *
   *
   * This module provides auto scroll functionality to ui-grid
   *
   */
  var module = angular.module('ui.grid.autoScroll', ['ui.grid']);
  /**
   *  @ngdoc service
   *  @name ui.grid.autoScroll.service:uiGridAutoScrollService
   *
   *  @description Service for auto scroll features
   */
  module.service('uiGridAutoScrollService', ['uiGridConstants', '$timeout', function (uiGridConstants, $timeout) {

    var service = {

      /**
       * @ngdoc function
       * @name initializeGrid
       * @methodOf ui.grid.autoScroll.service:uiGridAutoScrollService
       * @description This method register events and methods into grid public API
       */

      initializeGrid: function(grid, $scope) {
        service.defaultGridOptions(grid.options);

        if (!grid.options.enableAutoScroll) {
          return;
        }

        grid.autoScroll = {prevScrollPercent: 1};
        grid.api.core.on.scrollEnd($scope, service.handleScroll);
        grid.registerDataChangeCallback(service.autoScroll, [uiGridConstants.dataChange.ROW]);
      },

      defaultGridOptions: function (gridOptions) {
        //default option to true unless it was explicitly set to false
        /**
         *  @ngdoc object
         *  @name ui.grid.autoScroll.api:GridOptions
         *
         *  @description GridOptions for auto scroll feature, these are available to be
         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
         */

        /**
         *  @ngdoc object
         *  @name enableAutoScroll
         *  @propertyOf  ui.grid.autoScroll.api:GridOptions
         *  @description Enable auto scrolling for this grid
         *
Defaults to true
         */
        gridOptions.enableAutoScroll = gridOptions.enableAutoScroll !== false;
      },

      /**
       * @ngdoc function
       * @name handleScroll
       * @methodOf ui.grid.autoScroll.service:uiGridAutoScrollService
       * @description Called whenever the grid scrolls, determines whether the gird should
       * scroll when new data is added
       * @param {object} args the args from the event
       */
      handleScroll:  function (args) {
        if (args.y) {
          args.grid.autoScroll.prevScrollPercent = args.y.percentage;
        }
      },

      /**
       * @ngdoc function
       * @name autoScroll
       * @methodOf ui.grid.autoScroll.service:uiGridAutoScrollService
       * @description Called whenever the new data is added, will scroll to the bottom
       * if the grid was previously at the bottom
       * @param {object} args the args from the event
       */
      autoScroll:  function (args) {
        // If autoScroll timer is running then cancel and scroll to the bottom
        if ($timeout.cancel(args.api.grid.autoScroll.scrollTimeout)) {
          args.api.core.scrollTo(args.api.grid.options.data[args.api.grid.options.data.length - 1]);
        }

        // Delay to allow new data items to be added to the grid before scrolling
        args.api.grid.autoScroll.scrollTimeout = $timeout(function () {
          if (args.api.grid.autoScroll.prevScrollPercent > 0.99) {
            args.api.core.scrollTo(args.api.grid.options.data[args.api.grid.options.data.length - 1]);
          }
        }, 50);
      }
    };
    return service;
  }]);

  /**
   *  @ngdoc directive
   *  @name ui.grid.autoScroll.directive:uiGridAutoScroll
   *  @element div
   *  @restrict A
   *
   *  @description Adds auto scroll to grid
   *
   *  @example
   <example module="app">
   <file name="app.js">
   var app = angular.module('app', ['ui.grid', 'ui.grid.autoScroll']);

   app.controller('MainCtrl', ['$scope', function ($scope) {
      var logCount = 1;

      $scope.gridOptions = {
        columnDefs: [
          {name: 'message'}
        ],
        data: []
      };

      var loadData = function(lines) {
        for (var i = 0; i < lines; i++) {
          $scope.gridOptions.data.push({'message': 'log message ' + logCount});
          logCount++;
        }
      };

      $scope.addData = function() {
        loadData(100);
      };

      loadData(30);

    }]);
   </file>
   <file name="index.html">

   <button ng-click="addData()">Add more</button>

   </file>
   </example>
   */

  module.directive('uiGridAutoScroll', ['uiGridAutoScrollService',
    function (uiGridAutoScrollService) {
      return {
        scope: false,
        require: '^uiGrid',
        compile: function($scope, $elm, $attr){
          return {
            pre: function($scope, $elm, $attr, uiGridCtrl) {
              uiGridAutoScrollService.initializeGrid(uiGridCtrl.grid, $scope);
            },
            post: function($scope, $elm, $attr) {
            }
          };
        }
      };
    }]);

})();
<commit_msg>more timeout fixes<commit_after>(function() {
  'use strict';
  /**
   *  @ngdoc overview
   *  @name ui.grid.autoScroll
   *
   *  @description
   *
   * #ui.grid.autoScroll
   *
   *
   * This module provides auto scroll functionality to ui-grid
   *
   */
  var module = angular.module('ui.grid.autoScroll', ['ui.grid']);
  /**
   *  @ngdoc service
   *  @name ui.grid.autoScroll.service:uiGridAutoScrollService
   *
   *  @description Service for auto scroll features
   */
  module.service('uiGridAutoScrollService', ['uiGridConstants', '$timeout', function (uiGridConstants, $timeout) {

    var service = {

      /**
       * @ngdoc function
       * @name initializeGrid
       * @methodOf ui.grid.autoScroll.service:uiGridAutoScrollService
       * @description This method register events and methods into grid public API
       */

      initializeGrid: function(grid, $scope) {
        service.defaultGridOptions(grid.options);

        if (!grid.options.enableAutoScroll) {
          return;
        }

        grid.autoScroll = {prevScrollPercent: 1};
        grid.api.core.on.scrollEnd($scope, service.handleScroll);
        grid.registerDataChangeCallback(service.autoScroll, [uiGridConstants.dataChange.ROW]);
      },

      defaultGridOptions: function (gridOptions) {
        //default option to true unless it was explicitly set to false
        /**
         *  @ngdoc object
         *  @name ui.grid.autoScroll.api:GridOptions
         *
         *  @description GridOptions for auto scroll feature, these are available to be
         *  set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
         */

        /**
         *  @ngdoc object
         *  @name enableAutoScroll
         *  @propertyOf  ui.grid.autoScroll.api:GridOptions
         *  @description Enable auto scrolling for this grid
         *
Defaults to true
         */
        gridOptions.enableAutoScroll = gridOptions.enableAutoScroll !== false;
      },

      /**
       * @ngdoc function
       * @name handleScroll
       * @methodOf ui.grid.autoScroll.service:uiGridAutoScrollService
       * @description Called whenever the grid scrolls, determines whether the gird should
       * scroll when new data is added
       * @param {object} args the args from the event
       */
      handleScroll:  function (args) {
        if (args.y) {
          args.grid.autoScroll.prevScrollPercent = args.y.percentage;
        }
      },

      /**
       * @ngdoc function
       * @name autoScroll
       * @methodOf ui.grid.autoScroll.service:uiGridAutoScrollService
       * @description Called whenever the new data is added, will scroll to the bottom
       * if the grid was previously at the bottom
       * @param {object} args the args from the event
       */
      autoScroll:  function (args) {
        // If autoScroll timer is running then cancel and scroll to the bottom
        if ($timeout.cancel(args.api.grid.autoScroll.scrollTimeout)) {
          args.api.core.scrollTo(args.api.grid.options.data[args.api.grid.options.data.length - 1]);
        }

        // Delay to allow new data items to be added to the grid before scrolling
        if (args.api.grid.autoScroll.prevScrollPercent > 0.99) {
          args.api.grid.autoScroll.scrollTimeout = $timeout(function () {
            args.api.core.scrollTo(args.api.grid.options.data[args.api.grid.options.data.length - 1]);
          }, 50);
        }
      }
    };
    return service;
  }]);

  /**
   *  @ngdoc directive
   *  @name ui.grid.autoScroll.directive:uiGridAutoScroll
   *  @element div
   *  @restrict A
   *
   *  @description Adds auto scroll to grid
   *
   *  @example
   <example module="app">
   <file name="app.js">
   var app = angular.module('app', ['ui.grid', 'ui.grid.autoScroll']);

   app.controller('MainCtrl', ['$scope', function ($scope) {
      var logCount = 1;

      $scope.gridOptions = {
        columnDefs: [
          {name: 'message'}
        ],
        data: []
      };

      var loadData = function(lines) {
        for (var i = 0; i < lines; i++) {
          $scope.gridOptions.data.push({'message': 'log message ' + logCount});
          logCount++;
        }
      };

      $scope.addData = function() {
        loadData(100);
      };

      loadData(30);

    }]);
   </file>
   <file name="index.html">

   <button ng-click="addData()">Add more</button>

   </file>
   </example>
   */

  module.directive('uiGridAutoScroll', ['uiGridAutoScrollService',
    function (uiGridAutoScrollService) {
      return {
        scope: false,
        require: '^uiGrid',
        compile: function($scope, $elm, $attr){
          return {
            pre: function($scope, $elm, $attr, uiGridCtrl) {
              uiGridAutoScrollService.initializeGrid(uiGridCtrl.grid, $scope);
            },
            post: function($scope, $elm, $attr) {
            }
          };
        }
      };
    }]);

})();
<|endoftext|>