<commit_before>import {_} from 'lodash';
import Runner from '../../core/actions/runner.js';
import GetContributionVersion from './get_contribution_version';
import json2csv from 'json2csv';

import {default as magicVersions} from '../configs/magic_versions';
import {default as magicDataModels} from '../configs/data_models/data_models';

export default class extends Runner {

  constructor({LocalState}) {
    super('EXPORT_CONTRIBUTION', {LocalState});
    this.VersionGetter = new GetContributionVersion({LocalState});
  }

  toText(json) {

    let text = '';
    // Retrieve the data model version used in the json
    const version = this.VersionGetter.getVersion(json);
    if (!version) return text;

    // Retrieve the data model
    const model = magicDataModels[version];

    for (let newTableName in json) {//this gets the string name of the property 'table'
      let newTableObject = model.tables[newTableName];
      if(!newTableObject)
      {
        this._appendError(`table ${newTableName} is not defined in magic data model version ${version}`);
        continue;
      }

      //Test to make sure the column names are valid for a given model
      let columnErrorTracker = {};//keep track of invalid columns we have seen
      for (let jsonRowIdx in json[newTableName]) {
        let jsonColumnNames = Object.getOwnPropertyNames(json[newTableName][jsonRowIdx]);
        for (let jsonColumnNameIdx in jsonColumnNames) {
          let modelColumn = model.tables[newTableName].columns[jsonColumnNames[jsonColumnNameIdx]];
          if (!modelColumn || modelColumn == undefined) {
            if (!columnErrorTracker[jsonColumnNames[jsonColumnNameIdx]] ) {
              this._appendError(`column ${jsonColumnNames[jsonColumnNameIdx]} in table ${newTableName} is not defined in magic data model version ${version}`);
              //Keeping track of column we have seen for this table. I really only care about the property here, not the value.
              columnErrorTracker[jsonColumnNames[jsonColumnNameIdx]] = 'placeholder';
            }
            continue;
        }
      }
        // TODO: use the model to build up text string here

        // Text should be a valid MagIC tab delimited text file with the tables and columns in the order defined in the data model.

        // For each table in json, make a list of all of the columns used in the rows in the json table,
        // and sort them using the "position" property of the data model columns.
        // Start by making a list of tables in json, and sort them using the "position" property of the data model tables.
        //console.log(`JSON BEFORE: ${JSON.stringify(json)}`)
        var jsonAscendingOrder = _.sortBy( json, 'position' );

        //console.log(`JSON AFTER : ${JSON.stringify(jsonAscendingOrder)}`);
        for(var tableName in jsonAscendingOrder)
        {
          //console.log(`Table: ${tableName}`);

        }

        /*for (var table in json) {
          if (!table.hasOwnProperty(table)) {
            //The current property is not a direct property of p
            continue;
          }*/

          //Do your logic with the property here

        // Then loop through the used tables in data model order,
        //   print the table header (note: "tab delimited\ttable_name" format)
        //   loop through the used columns for that table in data model order,
        //     print the column headers
        //   loop through the rows in that table in the order in the json,
        //     loop through the used columns for that table in data model order,
        //       print the column value for that row
        //         note: arrays turn into :val1:val2 string,
        //               any string in an array that contains a ":" gets double quotes around it
        //   and print the table separator if there is another table.
      }
    }
    return text;

      //let tsv = '';
      /*json2csv({ data: json, del: '\t', doubleQuotes: ''}, function(err, tsv) {
        if (err) console.log(err);
         console.log(tsv);
        callBack(tsv);
      });*/

  }
}
<commit_msg>Cleaning up an import that might break without importing the right package<commit_after>import {_} from 'lodash';
import Runner from '../../core/actions/runner.js';
import GetContributionVersion from './get_contribution_version';
//import json2csv from 'json2csv';

import {default as magicVersions} from '../configs/magic_versions';
import {default as magicDataModels} from '../configs/data_models/data_models';

export default class extends Runner {

  constructor({LocalState}) {
    super('EXPORT_CONTRIBUTION', {LocalState});
    this.VersionGetter = new GetContributionVersion({LocalState});
  }

  toText(json) {

    let text = '';
    // Retrieve the data model version used in the json
    const version = this.VersionGetter.getVersion(json);
    if (!version) return text;

    // Retrieve the data model
    const model = magicDataModels[version];

    for (let newTableName in json) {//this gets the string name of the property 'table'
      let newTableObject = model.tables[newTableName];
      if(!newTableObject)
      {
        this._appendError(`table ${newTableName} is not defined in magic data model version ${version}`);
        continue;
      }

      //Test to make sure the column names are valid for a given model
      let columnErrorTracker = {};//keep track of invalid columns we have seen
      for (let jsonRowIdx in json[newTableName]) {
        let jsonColumnNames = Object.getOwnPropertyNames(json[newTableName][jsonRowIdx]);
        for (let jsonColumnNameIdx in jsonColumnNames) {
          let modelColumn = model.tables[newTableName].columns[jsonColumnNames[jsonColumnNameIdx]];
          if (!modelColumn || modelColumn == undefined) {
            if (!columnErrorTracker[jsonColumnNames[jsonColumnNameIdx]] ) {
              this._appendError(`column ${jsonColumnNames[jsonColumnNameIdx]} in table ${newTableName} is not defined in magic data model version ${version}`);
              //Keeping track of column we have seen for this table. I really only care about the property here, not the value.
              columnErrorTracker[jsonColumnNames[jsonColumnNameIdx]] = 'placeholder';
            }
            continue;
        }
      }
        // TODO: use the model to build up text string here

        // Text should be a valid MagIC tab delimited text file with the tables and columns in the order defined in the data model.

        // For each table in json, make a list of all of the columns used in the rows in the json table,
        // and sort them using the "position" property of the data model columns.
        // Start by making a list of tables in json, and sort them using the "position" property of the data model tables.
        //console.log(`JSON BEFORE: ${JSON.stringify(json)}`)
        var jsonAscendingOrder = _.sortBy( json, 'position' );

        //console.log(`JSON AFTER : ${JSON.stringify(jsonAscendingOrder)}`);
        for(var tableName in jsonAscendingOrder)
        {
          //console.log(`Table: ${tableName}`);

        }

        /*for (var table in json) {
          if (!table.hasOwnProperty(table)) {
            //The current property is not a direct property of p
            continue;
          }*/

          //Do your logic with the property here

        // Then loop through the used tables in data model order,
        //   print the table header (note: "tab delimited\ttable_name" format)
        //   loop through the used columns for that table in data model order,
        //     print the column headers
        //   loop through the rows in that table in the order in the json,
        //     loop through the used columns for that table in data model order,
        //       print the column value for that row
        //         note: arrays turn into :val1:val2 string,
        //               any string in an array that contains a ":" gets double quotes around it
        //   and print the table separator if there is another table.
      }
    }
    return text;

      //let tsv = '';
      /*json2csv({ data: json, del: '\t', doubleQuotes: ''}, function(err, tsv) {
        if (err) console.log(err);
         console.log(tsv);
        callBack(tsv);
      });*/

  }
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import update from 'react-addons-update';

import Place from '../Place/Place';
import Nav from '../Nav/Nav';

export default class Main extends Component {
  constructor(props) {
    super(props);

    this.state = {
      search: {
        zip: '04038',
        category: 'restaurants'
      },
      place: {}
    }

    console.log(this.state);
  }

  handleChange(event){
    let newState = update(this.state, {
      search: {
        $merge: {
          [event.target.name]: event.target.value
        }
      }
    })

    console.log(this.state);
    this.setState(newState);
  }

  findPlaces() {
  fetch(`http://localhost:8000/restaurants/zip/${this.state.search.zip}/restaurant`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json'
        }
      })
      .then(r => r.json()
        .then((places) => {
          const randomIndex = Math.floor(Math.random() * places.length);
          console.log(randomIndex);
          const place = places[randomIndex]
          console.log(place)
          this.setState({ place })
        })
      )
      .catch((err) => console.log(err));
  }

  render() {
    return(

        <input maxLength='5' type="text" name="zip" onChange={this.handleChange.bind(this)} value={this.state.search.zip} placeholder="ZIP"/>
        <button type="radio" name="category" value="restaurant" onClick={this.handleChange.bind(this)}  checked></button>
        <button type="radio" name="category" value="bar" onClick={this.handleChange.bind(this)}></button>
        <button onClick={this.findPlaces.bind(this)}>FIND</button>
        <Place place={this.state.place} />

    )
  }
}
<commit_msg>small change to main.js<commit_after>import React, { Component } from 'react';
import update from 'react-addons-update';

import Place from '../Place/Place';
import Nav from '../Nav/Nav';

export default class Main extends Component {
  constructor(props) {
    super(props);

    this.state = {
      search: {
        zip: '04038',
        category: 'restaurants'
      },
      place: {}
    }

    console.log(this.state);
  }

  handleChange(event){
    let newState = update(this.state, {
      search: {
        $merge: {
          [event.target.name]: event.target.value
        }
      }
    })

    console.log(this.state);
    this.setState(newState);
  }

  findPlaces() {
  fetch(`http://localhost:8000/restaurants/zip/${this.state.search.zip}/restaurant`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json'
        }
      })
      .then(r => r.json()
        .then((places) => {
          const randomIndex = Math.floor(Math.random() * places.length);
          console.log(randomIndex);
          const place = places[randomIndex]
          console.log(place)
          this.setState({ place })
        })
      )
      .catch((err) => console.log(err));
  }

  render() {
    return(

        <input maxLength='5' type="text" name="zip" onChange={this.handleChange.bind(this)} value={this.state.search.zip} placeholder="ZIP"/>
        <button type="radio" name="category" value="restaurant" onClick={this.handleChange.bind(this)}  checked></button>
        <button type="radio" name="category" value="bar" onClick={this.handleChange.bind(this)}></button>
        <button onClick={this.findPlaces.bind(this)}>FIND</button>

        <Place place={this.state.place} />

    )
  }
}
<|endoftext|>


<commit_before>/* @flow */
//jshint ignore:start

var https: any/* flow https defs seem broken */ = require('https');
var querystring = require('querystring');

import aeu from './auto-encode-uri';

class ConnHelper {
  _authKey: string;

  constructor(authKey: string) {
    this._authKey = authKey;
  }

  _getRequestOptions(method: string, path: string, headers: Object={}, encoding: ?string='utf8'): Object {
    return {
      method, headers, encoding,
      host: 'mailfoogae.appspot.com',
      path: '/api/v1/' + path,
      auth: this._authKey
    };
  }

  _parseResponse(response: https.IncomingMessage): Promise {
    return new Promise((resolve, reject) => {
      var strs: string[] = [];
      response.on('data', (chunk: string) => {
        strs.push(chunk);
      });
      response.on('end', () => {
        try {
          var str = strs.join('');
          if (response.statusCode === 200) {
            resolve(JSON.parse(str));
          } else {
            var json;
            var errorMessage = `Response code ${response.statusCode}`;
            try {
              json = JSON.parse(str);
              if (json && json.error) {
                errorMessage = json.error;
              }
            } catch(err) {}
            reject(Object.assign((new Error(errorMessage): Object), {
              str, json,
              statusCode: response.statusCode,
              headers: response.headers
            }));
          }
        } catch(err) {
          reject(err);
        }
      });
    });
  }

  _plainResponse(response: https.IncomingMessage): Promise<Buffer> {
    return new Promise((resolve, reject) => {
      var chunks: Buffer[] = [];
      response.on('data', (chunk: Buffer) => {
        chunks.push(chunk);
      });
      response.on('end', () => {
        try {
          var buf = Buffer.concat(chunks);
          if (response.statusCode === 200) {
            resolve(buf);
          } else {
            var errorMessage = `Response code ${response.statusCode}`;
            reject(Object.assign((new Error(errorMessage): Object), {
              buf,
              statusCode: response.statusCode,
              headers: response.headers
            }));
          }
        } catch(err) {
          reject(err);
        }
      });
    });
  }

  get(path: string): Promise {
    return new Promise((resolve, reject) => {
      var opts = this._getRequestOptions('GET', path);
      var request = https.request(opts, res => {
        resolve(this._parseResponse(res));
      });
      request.on('error', reject);
      request.end();
    });
  }

  getNoParse(path: string): Promise<Buffer> {
    return new Promise((resolve, reject) => {
      var opts = this._getRequestOptions('GET', path, undefined, null);
      var request = https.request(opts, res => {
        resolve(this._plainResponse(res));
      });
      request.on('error', reject);
      request.end();
    });
  }

  put(path: string, data: Object): Promise<Object> {
    return new Promise((resolve, reject) => {
      var dstr = querystring.stringify(data);
      var opts = this._getRequestOptions('PUT', path + "?" + dstr);
      var request = https.request(opts, res => {
        resolve(this._parseResponse(res));
      });
      request.on('error', reject);
      request.end();
    });
  }

  delete(path: string): Promise {
    return new Promise((resolve, reject) => {
      var opts = this._getRequestOptions('DELETE', path);
      var request = https.request(opts, res => {
        resolve(this._parseResponse(res));
      });
      request.on('error', reject);
      request.end();
    });
  }

  post(path: string, data: any): Promise<Object> {
    return new Promise((resolve, reject) => {
      var buf = new Buffer(JSON.stringify(data));
      var opts = this._getRequestOptions('POST', path, {
        'Content-Type': 'application/json',
        'Content-Length': buf.length
      });
      var request = https.request(opts, res => {
        resolve(this._parseResponse(res));
      });
      request.write(buf);
      request.on('error', reject);
      request.end();
    });
  }
}

class Me {
  _s: Streak;
  _c: ConnHelper;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
  }
  get() {
    return this._c.get('users/me');
  }
}

class Pipelines {
  _s: Streak;
  _c: ConnHelper;
  Stages: PipelineStages;
  Fields: PipelineFields;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
    this.Stages = new PipelineStages(s, c);
    this.Fields = new PipelineFields(s, c);
  }
  getAll() {
    return this._c.get('pipelines');
  }
  getOne(key: string) {
    return this._c.get(aeu `pipelines/${key}`);
  }
  getBoxes(key: string) {
    return this._c.get(aeu `pipelines/${key}/boxes`);
  }
  getBoxesInStage (key: string, stageKey: string) {
    return this._c.get(aeu `pipelines/${key}/boxes?stageKey=${stageKey}`);
  }
  create(data: Object) {
    return this._c.put('pipelines', data);
  }
  delete(key: string) {
    return this._c.delete(aeu `pipelines/${key}`);
  }
  update(data: Object) {
    return this._c.post(aeu `pipelines/${data.key}`, data);
  }
  getFeed(key: string, detailLevel: ?string) {
    var qs = "";
    if (detailLevel) {
      qs += '?' + querystring.stringify({detailLevel});
    }
    return this._c.get(aeu `pipelines/${key}/newsfeed` + qs);
  }
}

class PipelineStages {
  _s: Streak;
  _c: ConnHelper;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
  }
  getAll(pipeKey: string) {
    return this._c.get(aeu `pipelines/${pipeKey}/stages`);
  }
  getOne(pipeKey: string, key: string) {
    return this._c.get(aeu `pipelines/${pipeKey}/stages/${key}`);
  }
  create(pipeKey: string, data: Object) {
    return this._c.put(aeu `pipelines/${pipeKey}/stages`, data);
  }
  delete(pipeKey: string, key: string) {
    return this._c.delete(aeu `pipelines/${pipeKey}/stages/${key}`);
  }
  update(pipeKey: string, data: Object) {
    return this._c.post(aeu `pipelines/${pipeKey}/stages/${data.key}`, data);
  }
}

class PipelineFields {
  _s: Streak;
  _c: ConnHelper;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
  }
  getAll(pipeKey: string) {
    return this._c.get(aeu `pipelines/${pipeKey}/fields`);
  }
  getOne(pipeKey: string, key: string) {
    return this._c.get(aeu `pipelines/${pipeKey}/fields/${key}`);
  }
  create(pipeKey: string, data: Object) {
    return this._c.put(aeu `pipelines/${pipeKey}/fields`, data);
  }
  delete(pipeKey: string, key: string) {
    return this._c.delete(aeu `pipelines/${pipeKey}/fields/${key}`);
  }
  update(pipeKey: string, data: Object) {
    return this._c.post(aeu `pipelines/${pipeKey}/fields/${data.key}`, data);
  }
}

class Boxes {
  _s: Streak;
  _c: ConnHelper;
  Fields: BoxFields;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
    this.Fields = new BoxFields(s, c);
  }
  getAll() {
    return this._c.get('boxes');
  }
  getForPipeline(key: string) {
    return this._s.Pipelines.getBoxes(key);
  }
  getOne(key: string) {
    return this._c.get(aeu `boxes/${key}`);
  }
  create(pipeKey, data) {
    return this._c.put(aeu `pipelines/${pipeKey}/boxes`, data);
  }
  delete(key: string) {
    return this._c.delete(aeu `boxes/${key}`);
  }
  update(data: Object) {
    return this._c.post(aeu `boxes/${data.key}`, data);
  }
  getFields(key: string) {
    return this._c.get(aeu `boxes/${key}/fields`);
  }
  getReminders(key: string) {
    return this._c.get(aeu `boxes/${key}/reminders`);
  }
  getComments(key: string) {
    return this._c.get(aeu `boxes/${key}/comments`);
  }
  createComment(key: string, data) {
    return this._c.put(aeu `boxes/${key}/comments`, data);
  }
  getFiles(key: string) {
    return this._c.get(aeu `boxes/${key}/files`);
  }
  getFeed(key: string, detailLevel: ?string) {
    var qs = "";
    if (detailLevel) {
      qs += '?' + querystring.stringify({detailLevel});
    }
    return this._c.get(aeu `boxes/${key}/newsfeed` + qs);
  }
}

class BoxFields {
  _s: Streak;
  _c: ConnHelper;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
  }
  getForBox(key: string) {
    return this._s.Boxes.getFields(key);
  }
  getOne(boxKey: string, key: string) {
    return this._c.get(aeu `boxes/${boxKey}/fields/${key}`);
  }
  update(boxKey: string, data: Object) {
    return this._c.post(aeu `boxes/${boxKey}/fields/${data.key}`, data);
  }
}

class Files {
  _s: Streak;
  _c: ConnHelper;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
  }
  getForBox(key: string) {
    return this._s.Boxes.getFiles(key);
  }
  getOne(key: string) {
    return this._c.get(aeu `files/${key}`);
  }
  getContents(key: string) {
    return this._c.getNoParse(aeu `files/${key}/contents`);
  }
}

export class Streak {
  _c: ConnHelper;
  Me: Me;
  Pipelines: Object;
  Boxes: Object;
  Files: Object;

  constructor(authKey: string) {
    this._c = new ConnHelper(authKey);
    this.Me = new Me(this, this._c);
    this.Pipelines = new Pipelines(this, this._c);
    this.Boxes = new Boxes(this, this._c);
    this.Files = new Files(this, this._c);
  }

  search(query: string): Promise {
    return this._c.get(aeu `search?query=${query}`);
  }
}
<commit_msg>Fix posting unicode text. Fixed some unhandled errors.<commit_after>/* @flow */
//jshint ignore:start

var https: any/* flow https defs seem broken */ = require('https');
var querystring = require('querystring');

import aeu from './auto-encode-uri';

class ConnHelper {
  _authKey: string;

  constructor(authKey: string) {
    this._authKey = authKey;
  }

  _getRequestOptions(method: string, path: string, headers: Object={}, encoding: ?string='utf8'): Object {
    return {
      method, headers, encoding,
      host: 'mailfoogae.appspot.com',
      path: '/api/v1/' + path,
      auth: this._authKey
    };
  }

  _parseResponse(response: https.IncomingMessage): Promise {
    return new Promise((resolve, reject) => {
      var strs: string[] = [];
      response.on('data', (chunk: string) => {
        strs.push(chunk);
      });
      response.on('end', () => {
        try {
          var str = strs.join('');
          if (response.statusCode === 200) {
            resolve(JSON.parse(str));
          } else {
            var json;
            var errorMessage = `Response code ${response.statusCode}`;
            try {
              json = JSON.parse(str);
              if (json && json.error) {
                errorMessage = json.error;
              }
            } catch(err) {}
            reject(Object.assign((new Error(errorMessage): Object), {
              str, json,
              statusCode: response.statusCode,
              headers: response.headers
            }));
          }
        } catch(err) {
          reject(err);
        }
      });
      response.on('error', reject);
    });
  }

  _plainResponse(response: https.IncomingMessage): Promise<Buffer> {
    return new Promise((resolve, reject) => {
      var chunks: Buffer[] = [];
      response.on('data', (chunk: Buffer) => {
        chunks.push(chunk);
      });
      response.on('end', () => {
        try {
          var buf = Buffer.concat(chunks);
          if (response.statusCode === 200) {
            resolve(buf);
          } else {
            var errorMessage = `Response code ${response.statusCode}`;
            reject(Object.assign((new Error(errorMessage): Object), {
              buf,
              statusCode: response.statusCode,
              headers: response.headers
            }));
          }
        } catch(err) {
          reject(err);
        }
      });
      response.on('error', reject);
    });
  }

  get(path: string): Promise {
    return new Promise((resolve, reject) => {
      var opts = this._getRequestOptions('GET', path);
      var request = https.request(opts, res => {
        resolve(this._parseResponse(res));
      });
      request.on('error', reject);
      request.end();
    });
  }

  getNoParse(path: string): Promise<Buffer> {
    return new Promise((resolve, reject) => {
      var opts = this._getRequestOptions('GET', path, undefined, null);
      var request = https.request(opts, res => {
        resolve(this._plainResponse(res));
      });
      request.on('error', reject);
      request.end();
    });
  }

  put(path: string, data: Object): Promise<Object> {
    return new Promise((resolve, reject) => {
      var dstr = querystring.stringify(data);
      var opts = this._getRequestOptions('PUT', path + "?" + dstr);
      var request = https.request(opts, res => {
        resolve(this._parseResponse(res));
      });
      request.on('error', reject);
      request.end();
    });
  }

  delete(path: string): Promise {
    return new Promise((resolve, reject) => {
      var opts = this._getRequestOptions('DELETE', path);
      var request = https.request(opts, res => {
        resolve(this._parseResponse(res));
      });
      request.on('error', reject);
      request.end();
    });
  }

  post(path: string, data: any): Promise<Object> {
    return new Promise((resolve, reject) => {
      var send = querystring.stringify({json:JSON.stringify(data)});
      var opts = this._getRequestOptions('POST', path, {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': send.length
      });
      var request = https.request(opts, res => {
        resolve(this._parseResponse(res));
      });
      request.write(send);
      request.on('error', reject);
      request.end();
    });
  }
}

class Me {
  _s: Streak;
  _c: ConnHelper;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
  }
  get() {
    return this._c.get('users/me');
  }
}

class Pipelines {
  _s: Streak;
  _c: ConnHelper;
  Stages: PipelineStages;
  Fields: PipelineFields;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
    this.Stages = new PipelineStages(s, c);
    this.Fields = new PipelineFields(s, c);
  }
  getAll() {
    return this._c.get('pipelines');
  }
  getOne(key: string) {
    return this._c.get(aeu `pipelines/${key}`);
  }
  getBoxes(key: string) {
    return this._c.get(aeu `pipelines/${key}/boxes`);
  }
  getBoxesInStage (key: string, stageKey: string) {
    return this._c.get(aeu `pipelines/${key}/boxes?stageKey=${stageKey}`);
  }
  create(data: Object) {
    return this._c.put('pipelines', data);
  }
  delete(key: string) {
    return this._c.delete(aeu `pipelines/${key}`);
  }
  update(data: Object) {
    return this._c.post(aeu `pipelines/${data.key}`, data);
  }
  getFeed(key: string, detailLevel: ?string) {
    var qs = "";
    if (detailLevel) {
      qs += '?' + querystring.stringify({detailLevel});
    }
    return this._c.get(aeu `pipelines/${key}/newsfeed` + qs);
  }
}

class PipelineStages {
  _s: Streak;
  _c: ConnHelper;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
  }
  getAll(pipeKey: string) {
    return this._c.get(aeu `pipelines/${pipeKey}/stages`);
  }
  getOne(pipeKey: string, key: string) {
    return this._c.get(aeu `pipelines/${pipeKey}/stages/${key}`);
  }
  create(pipeKey: string, data: Object) {
    return this._c.put(aeu `pipelines/${pipeKey}/stages`, data);
  }
  delete(pipeKey: string, key: string) {
    return this._c.delete(aeu `pipelines/${pipeKey}/stages/${key}`);
  }
  update(pipeKey: string, data: Object) {
    return this._c.post(aeu `pipelines/${pipeKey}/stages/${data.key}`, data);
  }
}

class PipelineFields {
  _s: Streak;
  _c: ConnHelper;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
  }
  getAll(pipeKey: string) {
    return this._c.get(aeu `pipelines/${pipeKey}/fields`);
  }
  getOne(pipeKey: string, key: string) {
    return this._c.get(aeu `pipelines/${pipeKey}/fields/${key}`);
  }
  create(pipeKey: string, data: Object) {
    return this._c.put(aeu `pipelines/${pipeKey}/fields`, data);
  }
  delete(pipeKey: string, key: string) {
    return this._c.delete(aeu `pipelines/${pipeKey}/fields/${key}`);
  }
  update(pipeKey: string, data: Object) {
    return this._c.post(aeu `pipelines/${pipeKey}/fields/${data.key}`, data);
  }
}

class Boxes {
  _s: Streak;
  _c: ConnHelper;
  Fields: BoxFields;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
    this.Fields = new BoxFields(s, c);
  }
  getAll() {
    return this._c.get('boxes');
  }
  getForPipeline(key: string) {
    return this._s.Pipelines.getBoxes(key);
  }
  getOne(key: string) {
    return this._c.get(aeu `boxes/${key}`);
  }
  create(pipeKey, data) {
    return this._c.put(aeu `pipelines/${pipeKey}/boxes`, data);
  }
  delete(key: string) {
    return this._c.delete(aeu `boxes/${key}`);
  }
  update(data: Object) {
    return this._c.post(aeu `boxes/${data.key}`, data);
  }
  getFields(key: string) {
    return this._c.get(aeu `boxes/${key}/fields`);
  }
  getReminders(key: string) {
    return this._c.get(aeu `boxes/${key}/reminders`);
  }
  getComments(key: string) {
    return this._c.get(aeu `boxes/${key}/comments`);
  }
  createComment(key: string, data) {
    return this._c.put(aeu `boxes/${key}/comments`, data);
  }
  getFiles(key: string) {
    return this._c.get(aeu `boxes/${key}/files`);
  }
  getFeed(key: string, detailLevel: ?string) {
    var qs = "";
    if (detailLevel) {
      qs += '?' + querystring.stringify({detailLevel});
    }
    return this._c.get(aeu `boxes/${key}/newsfeed` + qs);
  }
}

class BoxFields {
  _s: Streak;
  _c: ConnHelper;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
  }
  getForBox(key: string) {
    return this._s.Boxes.getFields(key);
  }
  getOne(boxKey: string, key: string) {
    return this._c.get(aeu `boxes/${boxKey}/fields/${key}`);
  }
  update(boxKey: string, data: Object) {
    return this._c.post(aeu `boxes/${boxKey}/fields/${data.key}`, data);
  }
}

class Files {
  _s: Streak;
  _c: ConnHelper;
  constructor(s: Streak, c: ConnHelper) {
    this._s = s;
    this._c = c;
  }
  getForBox(key: string) {
    return this._s.Boxes.getFiles(key);
  }
  getOne(key: string) {
    return this._c.get(aeu `files/${key}`);
  }
  getContents(key: string) {
    return this._c.getNoParse(aeu `files/${key}/contents`);
  }
}

export class Streak {
  _c: ConnHelper;
  Me: Me;
  Pipelines: Object;
  Boxes: Object;
  Files: Object;

  constructor(authKey: string) {
    this._c = new ConnHelper(authKey);
    this.Me = new Me(this, this._c);
    this.Pipelines = new Pipelines(this, this._c);
    this.Boxes = new Boxes(this, this._c);
    this.Files = new Files(this, this._c);
  }

  search(query: string): Promise {
    return this._c.get(aeu `search?query=${query}`);
  }
}
<|endoftext|>


<commit_before>import React from "react";
import PropTypes from "prop-types";
import { map, sortBy } from "lodash-es";
import { ListGroup, Panel } from "react-bootstrap";

import { Icon, ListGroupItem } from "../../../base/index";

export default function APIPermissions ({ style, userPermissions, keyPermissions, onChange }) {

    const permissions = map(keyPermissions, (value, key) => ({name: key, allowed: value}));

    const rowComponents = map(sortBy(permissions, "name"), permission => {
        const disabled = !userPermissions[permission.name];

        return (
            <ListGroupItem
                key={permission.name}
                onClick={disabled ? null : () => onChange(permission.name, !permission.allowed)}
                disabled={disabled}
            >
                {permission.name}
                <Icon name={`checkbox-${permission.allowed ? "checked" : "unchecked"}`} pullRight />
            </ListGroupItem>
        );
    });

    return (
        <Panel style={style}>
            <Panel.Body>
                <ListGroup>
                    {rowComponents}
                </ListGroup>
            </Panel.Body>
        </Panel>
    );
}

APIPermissions.propTypes = {
    userPermissions: PropTypes.object.isRequired,
    keyPermissions: PropTypes.object.isRequired,
    onChange: PropTypes.func.isRequired,
    style: PropTypes.object
};
<commit_msg>Add checkbox to API permissions<commit_after>import React from "react";
import PropTypes from "prop-types";
import { map, sortBy } from "lodash-es";
import { ListGroup, Panel } from "react-bootstrap";

import { ListGroupItem, Checkbox } from "../../../base/index";

export default function APIPermissions ({ style, userPermissions, keyPermissions, onChange }) {

    const permissions = map(keyPermissions, (value, key) => ({name: key, allowed: value}));

    const rowComponents = map(sortBy(permissions, "name"), permission => {
        const disabled = !userPermissions[permission.name];

        return (
            <ListGroupItem
                key={permission.name}
                onClick={disabled ? null : () => onChange(permission.name, !permission.allowed)}
                disabled={disabled}
            >
                {permission.name}
                <Checkbox
                    checked={permission.allowed}
                    pullRight
                />
            </ListGroupItem>
        );
    });

    return (
        <Panel style={style}>
            <Panel.Body>
                <ListGroup>
                    {rowComponents}
                </ListGroup>
            </Panel.Body>
        </Panel>
    );
}

APIPermissions.propTypes = {
    userPermissions: PropTypes.object.isRequired,
    keyPermissions: PropTypes.object.isRequired,
    onChange: PropTypes.func.isRequired,
    style: PropTypes.object
};
<|endoftext|>


<commit_before>import React, { Component } from "react"
import { dayNames, shortDayNames } from "./../utils/Strings"
import { withStyles, createStyleSheet } from "material-ui/styles"
import Typography from "material-ui/Typography"
import PropTypes from "prop-types"
import Paper from "material-ui/Paper"
import Toolbar from "material-ui/Toolbar"
import { getWeeksOfMonth, getDaysInMonth } from "./../utils/DateHelper"
import DayCard from "./DayCard"
import { getEvents } from "./../api/api"

const styleSheet = createStyleSheet("MonthView", theme => ({
  root: {
    display: "flex",
    position: "relative",
    height: "550px"
  },
  dayDiv: {
    position: "relative",
    width: "20%"
  },
  dayTitleBar: {
    position: "relative",
    height: "50px",
    backgroundColor: "#004987",
    color: "#FFFFFF",
    fontWeight: "bold"
  },
  monthDiv: {
    width: "80%",
    height: "100%",
    overflow: "hidden"
  },
  monthTitleBar: {
    position: "relative",
    height: "50px"
  },
  table: {
    width: "100%",
    borderTop: "hidden",
    borderLeft: "hidden",
    borderRight: "hidden",
    borderCollapse: "collapse",
    height: "100%"
  },
  tableHead: {
    border: "1px solid rgba(0, 0, 0, 0.075)",
    color: "#000000",
    opacity: 0.7,
    textAlign: "center",
    fontWeight: "bold",
    borderTop: "hidden",
    height: "20%"
  },
  tableBody: {
    backgroundColor: "rgb(255,243,233)",
    color: "#000000",
    textAlign: "left",
    verticalAlign: "top"
  }
}))

class MonthView extends Component {
  constructor() {
    super()
    this.state = {
      width: window.outerWidth,
      currentDay: null,
      events: null
    }
    this.monthDayCounter = 1
  }

  componentDidMount() {
    getEvents().then(events => {
      this.setState({ events })
    })
  }

  componentWillMount() {
    window.addEventListener("resize", this.changeView)
  }

  changeView = () => {
    this.setState({ width: window.outerWidth })
  }

  toWeekName() {
    let date = new Date()
    let day = date.getDay()
    for (let i = 0; i < 7; ++i) {
      if (day === i) {
        if (this.state.width < 746) {
          day = shortDayNames[i]
        } else day = dayNames[i]
      }
    }
    return day
  }

  getMonthRows = () => {
    let first = new Date(
      this.props.currentDateRange.year,
      this.props.currentDateRange.month,
      1
    )
    let wks = getWeeksOfMonth(first)
    let rows = []

    for (let i = 0; i < wks; i++) {
      rows.push(
{this.getDays(i)}
)
    }
    this.monthDayCounter = 1
    return rows
  }

  getDays = wk => {
    let days = []
    let numDays = getDaysInMonth(
      this.props.currentDateRange.year,
      this.props.currentDateRange.month
    ).getDate()

    let first = new Date(
      this.props.currentDateRange.year,
      this.props.currentDateRange.month,
      1
    )

    let today = new Date()
    for (let i = 0; i < 7; i++) {
      if (this.monthDayCounter > numDays) {
        days.push(

        )
      } else if (
        this.monthDayCounter === 1 &&
        wk === 0 &&
        first.getDay() !== i
      ) {
        days.push(

        )
      } else {
        if (
          this.props.currentDateRange.year === today.getFullYear() &&
          this.props.currentDateRange.month === today.getMonth() &&
          this.monthDayCounter === today.getDate()
        ) {
          days.push(

              <Typography
                type="body1"
                component="div"
                style={{ fontWeight: "600" }}
              >
                {this.monthDayCounter}
              </Typography>

          )
        } else {
          days.push(

              <Typography type="body1" component="div">
                {this.monthDayCounter}
              </Typography>

          )
        }
        this.monthDayCounter++
      }
    }
    return days
  }

  weekDays() {
    let weekDaysRow = []

    for (let i = 0; i < 7; ++i) {
      weekDaysRow.push(

          <Typography type="body1" component="div" style={{ fontWeight: 600 }}>
            {shortDayNames[i]}
          </Typography>

      )
    }
    return weekDaysRow
  }

  render() {
    if (this.state.events === null) {
      return

    } else {
      const classes = this.props.classes
      return (
        <Paper className={classes.root}>

            <Toolbar className={classes.dayTitleBar}>
              <Typography type="h1">
                {this.toWeekName()}
              </Typography>
            </Toolbar>
            <DayCard events={this.state.events} />

                  {this.weekDays()}

                {this.getMonthRows()}

        </Paper>
      )
    }
  }
}

MonthView.propTypes = {
  classes: PropTypes.object.isRequired
}

export default withStyles(styleSheet)(MonthView)
<commit_msg>"change selecting days method"<commit_after>import React, { Component } from "react"
import { dayNames, shortDayNames } from "./../utils/Strings"
import { withStyles, createStyleSheet } from "material-ui/styles"
import Typography from "material-ui/Typography"
import PropTypes from "prop-types"
import Paper from "material-ui/Paper"
import Toolbar from "material-ui/Toolbar"
import { getWeeksOfMonth, getDaysInMonth } from "./../utils/DateHelper"
import DayCard from "./DayCard"
import { getEvents } from "./../api/api"

const styleSheet = createStyleSheet("MonthView", theme => ({
  root: {
    display: "flex",
    position: "relative",
    height: "550px"
  },
  dayDiv: {
    position: "relative",
    width: "20%"
  },
  dayTitleBar: {
    position: "relative",
    height: "50px",
    backgroundColor: "#004987",
    color: "#FFFFFF",
    fontWeight: "bold"
  },
  monthDiv: {
    width: "80%",
    height: "100%",
    overflow: "hidden"
  },
  monthTitleBar: {
    position: "relative",
    height: "50px"
  },
  table: {
    width: "100%",
    borderTop: "hidden",
    borderLeft: "hidden",
    borderRight: "hidden",
    borderCollapse: "collapse",
    height: "100%"
  },
  tableHead: {
    border: "1px solid rgba(0, 0, 0, 0.075)",
    color: "#000000",
    opacity: 0.7,
    textAlign: "center",
    fontWeight: "bold",
    borderTop: "hidden",
    height: "20%"
  },
  tableBody: {
    backgroundColor: "rgb(255,243,233)",
    color: "#000000",
    textAlign: "left",
    verticalAlign: "top"
  }
}))

class MonthView extends Component {
  constructor() {
    super()
    this.state = {
      selectedDay: new Date().getDate(),
      selectedWeekDay: new Date().getDay(),
    }
    this.monthDayCounter = 1
  }

  handleSelect(day, weekDay){
   this.setState({selectedDay: day, selectedWeekDay: weekDay})
  }

  toWeekName() {
    let today = new Date()
    let first = new Date(
      this.props.currentDateRange.year,
      this.props.currentDateRange.month,
      1
    )
    let dateObj = this.props.currentDateRange
    let day = this.props.currentDateRange.day
    let todayWeekDay =  today.getDay()
    let month = this.props.currentDateRange.month
    let year = this.props.currentDateRange.year
if ( year === today.getFullYear() &&
     month === today.getMonth() &&
     day === today.getDate() ){
    for( let i = 0; i < 7; ++i){
      if( todayWeekDay === i ){
        todayWeekDay=dayNames[i]
      }
    } return todayWeekDay + " " + today.getDate()
  }
if ( year === today.getFullYear() &&
     month === today.getMonth() &&
     day !== today.getDate() ){
       todayWeekDay=day.getDay()
       for( let i = 0; i < 7; ++i){
      if( todayWeekDay === i ){
        todayWeekDay=dayNames[i]
      }
    }
      return todayWeekDay + " " + day
  }else{
    today = first.getDate()
    todayWeekDay = first.getDay()
    for( let i = 0; i < 7; ++i){
      if( todayWeekDay === i ){
        todayWeekDay=dayNames[i]
      }
  }return todayWeekDay + " " + today
}
}

  getMonthRows = () => {
    let first = new Date(
      this.props.currentDateRange.year,
      this.props.currentDateRange.month,
      1
    )
    let wks = getWeeksOfMonth(first)
    let rows = []

    for (let i = 0; i < wks; i++) {
      rows.push(
{this.getDays(i)}
)
    }
    this.monthDayCounter = 1
    return rows
  }

  getDays = wk => {
    let days = []
    let numDays = getDaysInMonth(
      this.props.currentDateRange.year,
      this.props.currentDateRange.month
    ).getDate()

    let first = new Date(
      this.props.currentDateRange.year,
      this.props.currentDateRange.month,
      1
    )

    let today = new Date()
    for (let i = 0; i < 7; i++) {
      if (this.monthDayCounter > numDays) {
        days.push(

        )
      } else if (
        this.monthDayCounter === 1 &&
        wk === 0 &&
        first.getDay() !== i
      ) {
        days.push(

        )
      } else {
        if (
          this.props.currentDateRange.year === today.getFullYear() &&
          this.props.currentDateRange.month === today.getMonth() &&
          this.monthDayCounter === today.getDate()
        ) {
          let dateObj = this.props.currentDateRange
          let selectWeekDay = dayNames[i]
          days.push(
             this.props.changeDateRange(dateObj)}
               style={{
                fontSize: "15px",
                fontWeight: "bold",
                color: "#000000",
                border: "1px solid white",
                padding: "10px",
                backgroundColor: "rgba(86,162,234, 0.5)"
              }}
            >
              <Typography
                type="body1"
                component="div"
                style={{ fontWeight: "600" }}
              >
                {this.monthDayCounter}
              </Typography>

          )
        } else {
          let dateObj = this.props.currentDateRange
          let selectWeekDay = dayNames[i]
          days.push(
             this.props.changeDateRange(dateObj)}
              style={{
                fontSize: "15px",
                border: "1px solid white",
                padding: "10px"
              }}
            >
              <Typography type="body1" component="div">
                {this.monthDayCounter}
              </Typography>

          )
        }
        this.monthDayCounter++
      }
    }
    return days
  }

  weekDays() {
    let weekDaysRow = []

    for (let i = 0; i < 7; ++i) {
      weekDaysRow.push(

          <Typography type="body1" component="div" style={{ fontWeight: 600 }}>
            {shortDayNames[i]}
          </Typography>

      )
    }
    return weekDaysRow
  }

  render() {
    if (this.props.calendar === null) {
      return

    } else {
      const classes = this.props.classes
      return (
        <Paper className={classes.root}>

            <Toolbar className={classes.dayTitleBar}>
              <Typography type="h1">
                {this.toWeekName()}
              </Typography>
            </Toolbar>

            {console.log(this.props.currentDateRange)}

                  {this.weekDays()}

                {this.getMonthRows()}

        </Paper>
      )
    }
  }
}

MonthView.propTypes = {
  classes: PropTypes.object.isRequired
}

export default withStyles(styleSheet)(MonthView)
<|endoftext|>


<commit_before>var React         = require('react');
var joinClasses   = require('classnames');

var Autocomplete = React.createClass({

  propTypes: {
    options: React.PropTypes.any,
    search: React.PropTypes.func,
    resultRenderer: React.PropTypes.oneOfType([
      React.PropTypes.component,
      React.PropTypes.func
    ]),
    value: React.PropTypes.object,
    onChange: React.PropTypes.func,
    onError: React.PropTypes.func,
    onFocus: React.PropTypes.func
  },

  getDefaultProps: function() {
    return {search: searchArray};
  },

  getInitialState: function() {
    var searchTerm = this.props.searchTerm ?
      this.props.searchTerm :
      this.props.value ?
      this.props.value.title :
      '';
    return {
      results: [],
      showResults: false,
      showResultsInProgress: false,
      searchTerm: searchTerm,
      focusedValue: null
    };
  },

  getResultIdentifier : function(result){
    if(this.props.resultIdentifier === undefined){
      return result.id;
    }else{
      return result[this.props.resultIdentifier];
    }
  },

  render: function() {
    var className = joinClasses(
      this.props.className,
      'react-autocomplete-Autocomplete',
      this.state.showResults ?
        'react-autocomplete-Autocomplete--resultsShown' :
        undefined
    );
    var style = {
      position: 'relative',
      outline: 'none'
    };
    return (
      <div
        tabIndex="1"
        className={className}
        onFocus={this.onFocus}
        onBlur={this.onBlur}
        style={style}>
        <input
          ref="search"
          className="react-autocomplete-Autocomplete__search"
          style={{width: '100%'}}
          onClick={this.showAllResults}
          onChange={this.onQueryChange}
          onFocus={this.onSearchInputFocus}
          onBlur={this.onQueryBlur}
          onKeyDown={this.onQueryKeyDown}
          value={this.state.searchTerm}
          />
        <Results
          className="react-autocomplete-Autocomplete__results"
          onSelect={this.onValueChange}
          onFocus={this.onValueFocus}
          results={this.state.results}
          focusedValue={this.state.focusedValue}
          show={this.state.showResults}
          renderer={this.props.resultRenderer}
          label={this.props.label}
          resultIdentifier={this.props.resultIdentifier}
          />
      </div>
    );
  },

  componentWillReceiveProps: function(nextProps) {
    var searchTerm = nextProps.searchTerm ?
      nextProps.searchTerm :
      nextProps.value ?
      nextProps.value.title :
      '';
    this.setState({searchTerm: searchTerm});
  },

  componentWillMount: function() {
    this.blurTimer = null;
  },

  /**
    * Show results for a search term value.
    *
    * This method doesn't update search term value itself.
    *
    * @param {Search} searchTerm
    */
  showResults: function(searchTerm) {
    this.setState({showResultsInProgress: true});
    this.props.search(
      this.props.options,
      searchTerm.trim(),
      this.onSearchComplete
    );
  },

  showAllResults: function() {
    if (!this.state.showResultsInProgress && !this.state.showResults) {
      this.showResults('');
    }
  },

  onValueChange: function(value) {
    var state = {
      value: value,
      showResults: false
    };

    if (value) {
      state.searchTerm = value.title;
    }

    this.setState(state);

    if (this.props.onChange) {
      this.props.onChange(value);
    }
  },

  onSearchComplete: function(err, results) {
    if (err) {
      if (this.props.onError) {
        this.props.onError(err);
      } else {
        throw err;
      }
    }

    this.setState({
      showResultsInProgress: false,
      showResults: true,
      results: results
    });
  },

  onValueFocus: function(value) {
    this.setState({focusedValue: value});
  },

  onQueryChange: function(e) {
    var searchTerm = e.target.value;
    this.setState({
      searchTerm: searchTerm,
      focusedValue: null
    });
    this.showResults(searchTerm);
  },

  onFocus: function() {
    if (this.blurTimer) {
      clearTimeout(this.blurTimer);
      this.blurTimer = null;
    }
    this.refs.search.getDOMNode().focus();
  },

  onSearchInputFocus: function() {
    if (this.props.onFocus) {
      this.props.onFocus();
    }

    this.showAllResults();
  },

  onBlur: function() {
    // wrap in setTimeout so we can catch a click on results
    this.blurTimer = setTimeout(() => {
      if (this.isMounted()) {
        this.setState({showResults: false});
      }
    }, 100);
  },

  onQueryKeyDown: function(e) {

    if (e.key === 'Enter') {
      e.preventDefault();
      if (this.state.focusedValue) {
        this.onValueChange(this.state.focusedValue);
      }

    } else if (e.key === 'ArrowUp' && this.state.showResults) {
      e.preventDefault();
      var prevIdx = Math.max(
        this.focusedValueIndex() - 1,
        0
      );
      this.setState({
        focusedValue: this.state.results[prevIdx]
      });

    } else if (e.key === 'ArrowDown') {
      e.preventDefault();
      if (this.state.showResults) {
        var nextIdx = Math.min(
          this.focusedValueIndex() + (this.state.showResults ? 1 : 0),
          this.state.results.length - 1
        );
        this.setState({
          showResults: true,
          focusedValue: this.state.results[nextIdx]
        });
      } else {
        this.showAllResults();
      }
    }
  },

  focusedValueIndex: function() {
    if (!this.state.focusedValue) {
      return -1;
    }
    for (var i = 0, len = this.state.results.length; i < len; i++) {
      if (this.getResultIdentifier(this.state.results[i]) === this.getResultIdentifier(this.state.focusedValue)) {
        return i;
      }
    }
    return -1;
  }
});

var Results = React.createClass({

  getResultIdentifier : function(result){
    if(this.props.resultIdentifier === undefined){
      if(!result.id){
        throw ("id property not found on result. You must specify a resultIdentifier and pass as props to autocomplete component");
      }
      return result.id;
    }else{
      return result[this.props.resultIdentifier];
    }
  },

  render: function() {
    var style = {
      display: this.props.show ? 'block' : 'none',
      position: 'absolute',
      listStyleType: 'none'
    };
    var {className, ...props} = this.props;

    return (
      <ul {...props} style={style} className={className + " react-autocomplete-Results"}>
        {this.props.results.map(this.renderResult)}
      </ul>
    );
  },

  renderResult: function(result) {
    var focused = this.props.focusedValue && this.getResultIdentifier(this.props.focusedValue) === this.getResultIdentifier(result);
    var Renderer = this.props.renderer || Result;
    return (<Renderer
      ref={focused ? "focused" : undefined}
      key={this.getResultIdentifier(result)}
      result={result}
      focused={focused}
      onMouseEnter={this.onMouseEnterResult}
      onClick={this.props.onSelect}
      label={this.props.label}/>)
  },

  componentDidUpdate: function() {
    this.scrollToFocused();
  },

  componentDidMount: function() {
    this.scrollToFocused();
  },

  componentWillMount: function() {
    this.ignoreFocus = false;
  },

  scrollToFocused: function() {
    var focused = this.refs && this.refs.focused;
    if (focused) {
      var containerNode = this.getDOMNode();
      var scroll = containerNode.scrollTop;
      var height = containerNode.offsetHeight;

      var node = focused.getDOMNode();
      var top = node.offsetTop;
      var bottom = top + node.offsetHeight;

      // we update ignoreFocus to true if we change the scroll position so
      // the mouseover event triggered because of that won't have an
      // effect
      if (top < scroll) {
        this.ignoreFocus = true;
        containerNode.scrollTop = top;
      } else if (bottom - scroll > height) {
        this.ignoreFocus = true;
        containerNode.scrollTop = bottom - height;
      }
    }
  },

  onMouseEnterResult: function(e, result) {
    // check if we need to prevent the next onFocus event because it was
    // probably caused by a mouseover due to scroll position change
    if (this.ignoreFocus) {
      this.ignoreFocus = false;
    } else {
      // we need to make sure focused node is visible
      // for some reason mouse events fire on visible nodes due to
      // box-shadow
      var containerNode = this.getDOMNode();
      var scroll = containerNode.scrollTop;
      var height = containerNode.offsetHeight;

      var node = e.target;
      var top = node.offsetTop;
      var bottom = top + node.offsetHeight;

      if (bottom > scroll && top < scroll + height) {
        this.props.onFocus(result);
      }
    }
  }
});

var Result = React.createClass({

  getDefaultProps : function(){
    return {
      label : function(result){
        return result.title;
      }
    }
  },

  getLabel : function(result){
    if(typeof this.props.label === 'function'){
      return this.props.label(result);
    }else if(typeof this.props.label === 'string'){
      return result[this.props.label];
    }
  },

  render: function() {
    var className = joinClasses({
      'react-autocomplete-Result': true,
      'react-autocomplete-Result--active': this.props.focused
    });

    return (
      <li
        style={{listStyleType: 'none'}}
        className={className}
        onClick={this.onClick}
        onMouseEnter={this.onMouseEnter}>
        <a>{this.getLabel(this.props.result)}</a>
      </li>
    );
  },

  onClick: function() {
    this.props.onClick(this.props.result);
  },

  onMouseEnter: function(e) {
    if (this.props.onMouseEnter) {
      this.props.onMouseEnter(e, this.props.result);
    }
  },

  shouldComponentUpdate: function(nextProps) {
    return (nextProps.result.id !== this.props.result.id ||
            nextProps.focused !== this.props.focused);
  }
});

/**
* Search options using specified search term treating options as an array
* of candidates.
*
* @param {Array.<Object>} options
* @param {String} searchTerm
* @param {Callback} cb
*/
function searchArray(options, searchTerm, cb) {
  if (!options) {
    return cb(null, []);
  }

  searchTerm = new RegExp(searchTerm, 'i');

  var results = [];

  for (var i = 0, len = options.length; i < len; i++) {
    if (searchTerm.exec(options[i].title)) {
      results.push(options[i]);
    }
  }

  cb(null, results);
}

module.exports = Autocomplete;
<commit_msg>Throw error instead of string<commit_after>var React         = require('react');
var joinClasses   = require('classnames');

var Autocomplete = React.createClass({

  propTypes: {
    options: React.PropTypes.any,
    search: React.PropTypes.func,
    resultRenderer: React.PropTypes.oneOfType([
      React.PropTypes.component,
      React.PropTypes.func
    ]),
    value: React.PropTypes.object,
    onChange: React.PropTypes.func,
    onError: React.PropTypes.func,
    onFocus: React.PropTypes.func
  },

  getDefaultProps: function() {
    return {search: searchArray};
  },

  getInitialState: function() {
    var searchTerm = this.props.searchTerm ?
      this.props.searchTerm :
      this.props.value ?
      this.props.value.title :
      '';
    return {
      results: [],
      showResults: false,
      showResultsInProgress: false,
      searchTerm: searchTerm,
      focusedValue: null
    };
  },

  getResultIdentifier : function(result){
    if(this.props.resultIdentifier === undefined){
      return result.id;
    }else{
      return result[this.props.resultIdentifier];
    }
  },

  render: function() {
    var className = joinClasses(
      this.props.className,
      'react-autocomplete-Autocomplete',
      this.state.showResults ?
        'react-autocomplete-Autocomplete--resultsShown' :
        undefined
    );
    var style = {
      position: 'relative',
      outline: 'none'
    };
    return (
      <div
        tabIndex="1"
        className={className}
        onFocus={this.onFocus}
        onBlur={this.onBlur}
        style={style}>
        <input
          ref="search"
          className="react-autocomplete-Autocomplete__search"
          style={{width: '100%'}}
          onClick={this.showAllResults}
          onChange={this.onQueryChange}
          onFocus={this.onSearchInputFocus}
          onBlur={this.onQueryBlur}
          onKeyDown={this.onQueryKeyDown}
          value={this.state.searchTerm}
          />
        <Results
          className="react-autocomplete-Autocomplete__results"
          onSelect={this.onValueChange}
          onFocus={this.onValueFocus}
          results={this.state.results}
          focusedValue={this.state.focusedValue}
          show={this.state.showResults}
          renderer={this.props.resultRenderer}
          label={this.props.label}
          resultIdentifier={this.props.resultIdentifier}
          />
      </div>
    );
  },

  componentWillReceiveProps: function(nextProps) {
    var searchTerm = nextProps.searchTerm ?
      nextProps.searchTerm :
      nextProps.value ?
      nextProps.value.title :
      '';
    this.setState({searchTerm: searchTerm});
  },

  componentWillMount: function() {
    this.blurTimer = null;
  },

  /**
    * Show results for a search term value.
    *
    * This method doesn't update search term value itself.
    *
    * @param {Search} searchTerm
    */
  showResults: function(searchTerm) {
    this.setState({showResultsInProgress: true});
    this.props.search(
      this.props.options,
      searchTerm.trim(),
      this.onSearchComplete
    );
  },

  showAllResults: function() {
    if (!this.state.showResultsInProgress && !this.state.showResults) {
      this.showResults('');
    }
  },

  onValueChange: function(value) {
    var state = {
      value: value,
      showResults: false
    };

    if (value) {
      state.searchTerm = value.title;
    }

    this.setState(state);

    if (this.props.onChange) {
      this.props.onChange(value);
    }
  },

  onSearchComplete: function(err, results) {
    if (err) {
      if (this.props.onError) {
        this.props.onError(err);
      } else {
        throw err;
      }
    }

    this.setState({
      showResultsInProgress: false,
      showResults: true,
      results: results
    });
  },

  onValueFocus: function(value) {
    this.setState({focusedValue: value});
  },

  onQueryChange: function(e) {
    var searchTerm = e.target.value;
    this.setState({
      searchTerm: searchTerm,
      focusedValue: null
    });
    this.showResults(searchTerm);
  },

  onFocus: function() {
    if (this.blurTimer) {
      clearTimeout(this.blurTimer);
      this.blurTimer = null;
    }
    this.refs.search.getDOMNode().focus();
  },

  onSearchInputFocus: function() {
    if (this.props.onFocus) {
      this.props.onFocus();
    }

    this.showAllResults();
  },

  onBlur: function() {
    // wrap in setTimeout so we can catch a click on results
    this.blurTimer = setTimeout(() => {
      if (this.isMounted()) {
        this.setState({showResults: false});
      }
    }, 100);
  },

  onQueryKeyDown: function(e) {

    if (e.key === 'Enter') {
      e.preventDefault();
      if (this.state.focusedValue) {
        this.onValueChange(this.state.focusedValue);
      }

    } else if (e.key === 'ArrowUp' && this.state.showResults) {
      e.preventDefault();
      var prevIdx = Math.max(
        this.focusedValueIndex() - 1,
        0
      );
      this.setState({
        focusedValue: this.state.results[prevIdx]
      });

    } else if (e.key === 'ArrowDown') {
      e.preventDefault();
      if (this.state.showResults) {
        var nextIdx = Math.min(
          this.focusedValueIndex() + (this.state.showResults ? 1 : 0),
          this.state.results.length - 1
        );
        this.setState({
          showResults: true,
          focusedValue: this.state.results[nextIdx]
        });
      } else {
        this.showAllResults();
      }
    }
  },

  focusedValueIndex: function() {
    if (!this.state.focusedValue) {
      return -1;
    }
    for (var i = 0, len = this.state.results.length; i < len; i++) {
      if (this.getResultIdentifier(this.state.results[i]) === this.getResultIdentifier(this.state.focusedValue)) {
        return i;
      }
    }
    return -1;
  }
});

var Results = React.createClass({

  getResultIdentifier : function(result){
    if(this.props.resultIdentifier === undefined){
      if(!result.id){
        throw Error("id property not found on result. You must specify a resultIdentifier and pass as props to autocomplete component");
      }
      return result.id;
    }else{
      return result[this.props.resultIdentifier];
    }
  },

  render: function() {
    var style = {
      display: this.props.show ? 'block' : 'none',
      position: 'absolute',
      listStyleType: 'none'
    };
    var {className, ...props} = this.props;

    return (
      <ul {...props} style={style} className={className + " react-autocomplete-Results"}>
        {this.props.results.map(this.renderResult)}
      </ul>
    );
  },

  renderResult: function(result) {
    var focused = this.props.focusedValue && this.getResultIdentifier(this.props.focusedValue) === this.getResultIdentifier(result);
    var Renderer = this.props.renderer || Result;
    return (<Renderer
      ref={focused ? "focused" : undefined}
      key={this.getResultIdentifier(result)}
      result={result}
      focused={focused}
      onMouseEnter={this.onMouseEnterResult}
      onClick={this.props.onSelect}
      label={this.props.label}/>)
  },

  componentDidUpdate: function() {
    this.scrollToFocused();
  },

  componentDidMount: function() {
    this.scrollToFocused();
  },

  componentWillMount: function() {
    this.ignoreFocus = false;
  },

  scrollToFocused: function() {
    var focused = this.refs && this.refs.focused;
    if (focused) {
      var containerNode = this.getDOMNode();
      var scroll = containerNode.scrollTop;
      var height = containerNode.offsetHeight;

      var node = focused.getDOMNode();
      var top = node.offsetTop;
      var bottom = top + node.offsetHeight;

      // we update ignoreFocus to true if we change the scroll position so
      // the mouseover event triggered because of that won't have an
      // effect
      if (top < scroll) {
        this.ignoreFocus = true;
        containerNode.scrollTop = top;
      } else if (bottom - scroll > height) {
        this.ignoreFocus = true;
        containerNode.scrollTop = bottom - height;
      }
    }
  },

  onMouseEnterResult: function(e, result) {
    // check if we need to prevent the next onFocus event because it was
    // probably caused by a mouseover due to scroll position change
    if (this.ignoreFocus) {
      this.ignoreFocus = false;
    } else {
      // we need to make sure focused node is visible
      // for some reason mouse events fire on visible nodes due to
      // box-shadow
      var containerNode = this.getDOMNode();
      var scroll = containerNode.scrollTop;
      var height = containerNode.offsetHeight;

      var node = e.target;
      var top = node.offsetTop;
      var bottom = top + node.offsetHeight;

      if (bottom > scroll && top < scroll + height) {
        this.props.onFocus(result);
      }
    }
  }
});

var Result = React.createClass({

  getDefaultProps : function(){
    return {
      label : function(result){
        return result.title;
      }
    }
  },

  getLabel : function(result){
    if(typeof this.props.label === 'function'){
      return this.props.label(result);
    }else if(typeof this.props.label === 'string'){
      return result[this.props.label];
    }
  },

  render: function() {
    var className = joinClasses({
      'react-autocomplete-Result': true,
      'react-autocomplete-Result--active': this.props.focused
    });

    return (
      <li
        style={{listStyleType: 'none'}}
        className={className}
        onClick={this.onClick}
        onMouseEnter={this.onMouseEnter}>
        <a>{this.getLabel(this.props.result)}</a>
      </li>
    );
  },

  onClick: function() {
    this.props.onClick(this.props.result);
  },

  onMouseEnter: function(e) {
    if (this.props.onMouseEnter) {
      this.props.onMouseEnter(e, this.props.result);
    }
  },

  shouldComponentUpdate: function(nextProps) {
    return (nextProps.result.id !== this.props.result.id ||
            nextProps.focused !== this.props.focused);
  }
});

/**
* Search options using specified search term treating options as an array
* of candidates.
*
* @param {Array.<Object>} options
* @param {String} searchTerm
* @param {Callback} cb
*/
function searchArray(options, searchTerm, cb) {
  if (!options) {
    return cb(null, []);
  }

  searchTerm = new RegExp(searchTerm, 'i');

  var results = [];

  for (var i = 0, len = options.length; i < len; i++) {
    if (searchTerm.exec(options[i].title)) {
      results.push(options[i]);
    }
  }

  cb(null, results);
}

module.exports = Autocomplete;
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'

export default Object.assign({}, PropTypes, {
  color: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.func
  ]),
  ellipsizeMode: PropTypes.oneOf(['head', 'middle', 'tail', 'clip']),
  opacity: PropTypes.number,
  palette: PropTypes.oneOf(['primary', 'primaryDark', 'primaryLight', 'accent', 'accentDark', 'accentLight', 'warn', 'warnDark', 'warnLight', 'background', 'backgroundDark', 'backgroundLight']),
  style: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.arrayOf(PropTypes.object)
  ]),
  text: PropTypes.oneOfType([
    PropTypes.element,
    PropTypes.string
  ]),
  textSubType: PropTypes.oneOf(['primary', 'secondary', 'hint']),
  textType: PropTypes.oneOf(['button', 'caption', 'body1', 'body2', 'subhead1', 'subhead2', 'title', 'headline', 'display1', 'display2', 'display3', 'display4']),
  view: PropTypes.oneOfType([
    PropTypes.element,
    PropTypes.func
  ]),
  imageRadius: PropTypes.oneOfType([
    PropTypes.number,
    PropTypes.oneOf(['auto', 'none'])
  ]),
  imageResizeMode: PropTypes.oneOf(['cover', 'contain', 'stretch', 'center']),
  imageScaleType: PropTypes.oneOf(['width', 'height', 'none']),
  imageSource: PropTypes.oneOfType([
    PropTypes.number,
    PropTypes.shape({
      uri: PropTypes.string
    }),
    PropTypes.string,
  ])
})
<commit_msg>Updated PropTypes<commit_after>import PropTypes from 'prop-types'

export default Object.assign({}, PropTypes, {
  color: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.func
  ]),
  ellipsizeMode: PropTypes.oneOf(['head', 'middle', 'tail', 'clip']),
  imageRadius: PropTypes.oneOfType([
    PropTypes.number,
    PropTypes.oneOf(['auto', 'none'])
  ]),
  imageResizeMode: PropTypes.oneOf(['cover', 'contain', 'stretch', 'center']),
  imageScaleType: PropTypes.oneOf(['width', 'height', 'none']),
  imageSource: PropTypes.oneOfType([
    PropTypes.number,
    PropTypes.shape({
      uri: PropTypes.string
    }),
    PropTypes.string,
  ]),
  opacity: PropTypes.number,
  palette: PropTypes.oneOf(['primary', 'primaryDark', 'primaryLight', 'accent', 'accentDark', 'accentLight', 'warn', 'warnDark', 'warnLight', 'background', 'backgroundDark', 'backgroundLight']),
  style: PropTypes.oneOfType([
    PropTypes.object,
    PropTypes.arrayOf(PropTypes.object)
  ]),
  text: PropTypes.oneOfType([
    PropTypes.element,
    PropTypes.string
  ]),
  textSubType: PropTypes.oneOf(['primary', 'secondary', 'hint']),
  textType: PropTypes.oneOf(['button', 'caption', 'body1', 'body2', 'subhead1', 'subhead2', 'title', 'headline', 'display1', 'display2', 'display3', 'display4']),
  view: PropTypes.oneOfType([
    PropTypes.element,
    PropTypes.func
  ])
})
<|endoftext|>


<commit_before>var core        = require('./core'),
    deprecation = require('./deprecation');

// plugins:
core.extras         = require('./extras');
core.filters        = require('./filters');
core.interaction    = require('./interaction');
core.loaders        = require('./loaders');
core.spine          = require('./spine');
core.text           = require('./text');

module.exports = core;
<commit_msg>Removed the namespaces<commit_after>var core = require('./core'),
	math = core.math,
	// plugins:
	extras         = require('./extras'),
	filters        = require('./filters'),
	interaction    = require('./interaction'),
	loaders        = require('./loaders'),
	spine          = require('./spine'),
	text           = require('./text'),
    deprecation    = require('./deprecation');

var modules = [];

modules.push(math);
modules.push(extras);
modules.push(filters);
modules.push(interaction);
modules.push(loaders);
modules.push(spine);
modules.push(text);

for (var i = 0; i < modules.length; i++) {

	// Adds the module to the core, so you can do
	// PIXI.Text instead of PIXI.text.Text
	bundleUp(core,modules[i]);
};

function bundleUp(object1,object2){

    for(var keys in object2){
        object1[keys] = object2[keys];
    }
}

module.exports = core;
<|endoftext|>


<commit_before>
import ReadOnlyObjectStore from "../object-store/ReadOnlyObjectStore"
import ReadOnlyCursor from "../object-store/ReadOnlyCursor"

/**
 * Private field symbols.
 */
const FIELDS = Object.freeze({
  transaction: Symbol("transaction"),
  transactionFactory: Symbol("transactionFactory"),
  objectStores: Symbol("objectStores"),
  completeListeners: Symbol("completeListeners"),
  abortListeners: Symbol("abortListeners"),
  errorListeners: Symbol("errorListeners")
})

/**
 * A transaction with only a read-only access to the selected object stores.
 */
export default class ReadOnlyTransaction {
  /**
   * Initializes the read-only transaction.
   *
   * @param {IDBTransaction} transaction The IndexedDB native transaction.
   * @param {function(string): ReadOnlyTransaction} transactionFactory The
   *        factory function that creates a new read-only transaction with
   *        access only the to the object store specified by the provided
   *        argument every time the function is invoked.
   */
  constructor(transaction, transactionFactory) {
    /**
     * The native IndexedDB transaction object.
     *
     * @type {IDBTransaction}
     */
    this[FIELDS.transaction] = transaction

    /**
     * The factory function that creates a new read-only transaction with
     * access only the to the object store specified by the provided argument
     * every time the function is invoked.
     *
     * @type {function(string): ReadOnlyTransaction}
     */
    this[FIELDS.transactionFactory] = transactionFactory

    /**
     * Cache of created object store instances. The keys are the names of the
     * object stores.
     *
     * @type {Map<string, ReadOnlyObjectStore>}
     */
    this[FIELDS.objectStores] = new Map()

    /**
     * Event listeners for the {@code complete} event.
     *
     * @type {Set<function()>}
     */
    this[FIELDS.completeListeners] = new Set()

    /**
     * Event listeners for the {@code abort} event.
     *
     * @type {Set<function()>}
     */
    this[FIELDS.abortListeners] = new Set()

    /**
     * Event listeners of the {@code error} event.
     *
     * @type {Set<function(Error)>}
     */
    this[FIELDS.errorListeners] = new Set()

    /**
     * A promise that resolves when the transaction is completed, and rejects
     * when it is aborted on encounters an unexpected error.
     *
     * @type {Promise<undefined>}
     */
    this.completionPromise = new Promise((resolve, reject) => {
      this.addCompleteListener(resolve)
      this.addAbortListener(() => {
        reject(new Error("The transaction has been aborted"))
      })
      this.addErrorListener(reject)
    })

    transaction.oncomplete = () => {
      executeEventListeners(this[FIELDS.completeListeners])
    }

    transaction.onabort = () => {
      executeEventListeners(this[FIELDS.abortListeners])
    }

    transaction.onerror = () => {
      executeEventListeners(this[FIELDS.errorListeners], transaction.error)
    }

    this.addErrorListener((error) => {
      if (this[FIELDS.errorListeners].size < 2) {
        console.error("Encountered an uncaptured transaction-level error " +
            "while no error listeners were registered", error);
      }
    })

    if (this.constructor === ReadOnlyTransaction) {
      Object.freeze(this)
    }
  }

  /**
   * Registers the provided listener to be executed when the transaction is
   * completed.
   *
   * The order in which the event listeners will be executed is undefined and
   * should not be relied upon.
   *
   * @param {function()} listener The listener to register.
   */
  addCompleteListener(listener) {
    this[FIELDS.completeListeners].add(listener)
  }

  /**
   * Registers the provided listener to be executed when the transaction is
   * aborted by calling the {@codelink abort()} method, or due to an error.
   *
   * The order in which the event listeners will be executed is undefined and
   * should not be relied upon.
   *
   * @param {function()} listener The listener to register.
   */
  addAbortListener(listener) {
    this[FIELDS.abortListeners].add(listener)
  }

  /**
   * Registers the provided listener to be executed when an error is
   * encountered during the manipulation of the database from this transaction,
   * and the error was not somehow captured during the processing of the
   * operation that caused the error.
   *
   * The order in which the event listeners will be executed is undefined and
   * should not be relied upon.
   *
   * @param {function(Error)} listener The listener to register.
   */
  addErrorListener(listener) {
    this[FIELDS.errorListeners].add(listener)
  }

  /**
   * Aborts this transaction. Calling this method will lead to the execution of
   * the abort listeners registered on this transaction.
   */
  abort() {
    this[FIELDS.transaction].abort()
  }

  /**
   * Returns the read-only object store of the specified name. The method
   * returns the same object store if called repeatedly with the same argument.
   *
   * @param {string} objectStoreName The name of the object store to retrieve.
   * @return {ReadOnlyObjectStore} The object store.
   */
  getObjectStore(objectStoreName) {
    if (this[FIELDS.objectStores].has(objectStoreName)) {
      return this[FIELDS.objectStores].get(objectStoreName)
    }

    let transactionFactory = () => {
      return this[FIELDS.transactionFactory].getObjectStore(objectStoreName)
    }

    let idbObjectStore = this[FIELDS.transaction].objectStore(objectStoreName)
    let objectStore = new ReadOnlyObjectStore(
      idbObjectStore,
      ReadOnlyCursor,
      transactionFactory
    )
    this[FIELDS.objectStores].set(objectStoreName, objectStore)

    return objectStore
  }
}

/**
 * Executes the provided event listeners with the provided parameters. Any
 * errors thrown by the executed event listeners will be caught and logged to
 * the console, and then the remaining event listeners will be executed.
 *
 * @param {function(...*)[]} listeners The event listeners to execute.
 * @param {...*} parameters The parameters to pass to the event listeners as
 *        arguments.
 */
function executeEventListeners(listeners, ...parameters) {
  listeners.forEach((listener) => {
    try {
      listener.apply(null, parameters)
    } catch (error) {
      console.error("An event listener threw an error", error)
    }
  })
}
<commit_msg>fixed usage of transaction factory<commit_after>
import ReadOnlyObjectStore from "../object-store/ReadOnlyObjectStore"
import ReadOnlyCursor from "../object-store/ReadOnlyCursor"

/**
 * Private field symbols.
 */
const FIELDS = Object.freeze({
  transaction: Symbol("transaction"),
  transactionFactory: Symbol("transactionFactory"),
  objectStores: Symbol("objectStores"),
  completeListeners: Symbol("completeListeners"),
  abortListeners: Symbol("abortListeners"),
  errorListeners: Symbol("errorListeners")
})

/**
 * A transaction with only a read-only access to the selected object stores.
 */
export default class ReadOnlyTransaction {
  /**
   * Initializes the read-only transaction.
   *
   * @param {IDBTransaction} transaction The IndexedDB native transaction.
   * @param {function(string): ReadOnlyTransaction} transactionFactory The
   *        factory function that creates a new read-only transaction with
   *        access only the to the object store specified by the provided
   *        argument every time the function is invoked.
   */
  constructor(transaction, transactionFactory) {
    /**
     * The native IndexedDB transaction object.
     *
     * @type {IDBTransaction}
     */
    this[FIELDS.transaction] = transaction

    /**
     * The factory function that creates a new read-only transaction with
     * access only the to the object store specified by the provided argument
     * every time the function is invoked.
     *
     * @type {function(string): ReadOnlyTransaction}
     */
    this[FIELDS.transactionFactory] = transactionFactory

    /**
     * Cache of created object store instances. The keys are the names of the
     * object stores.
     *
     * @type {Map<string, ReadOnlyObjectStore>}
     */
    this[FIELDS.objectStores] = new Map()

    /**
     * Event listeners for the {@code complete} event.
     *
     * @type {Set<function()>}
     */
    this[FIELDS.completeListeners] = new Set()

    /**
     * Event listeners for the {@code abort} event.
     *
     * @type {Set<function()>}
     */
    this[FIELDS.abortListeners] = new Set()

    /**
     * Event listeners of the {@code error} event.
     *
     * @type {Set<function(Error)>}
     */
    this[FIELDS.errorListeners] = new Set()

    /**
     * A promise that resolves when the transaction is completed, and rejects
     * when it is aborted on encounters an unexpected error.
     *
     * @type {Promise<undefined>}
     */
    this.completionPromise = new Promise((resolve, reject) => {
      this.addCompleteListener(resolve)
      this.addAbortListener(() => {
        reject(new Error("The transaction has been aborted"))
      })
      this.addErrorListener(reject)
    })

    transaction.oncomplete = () => {
      executeEventListeners(this[FIELDS.completeListeners])
    }

    transaction.onabort = () => {
      executeEventListeners(this[FIELDS.abortListeners])
    }

    transaction.onerror = () => {
      executeEventListeners(this[FIELDS.errorListeners], transaction.error)
    }

    this.addErrorListener((error) => {
      if (this[FIELDS.errorListeners].size < 2) {
        console.error("Encountered an uncaptured transaction-level error " +
            "while no error listeners were registered", error);
      }
    })

    if (this.constructor === ReadOnlyTransaction) {
      Object.freeze(this)
    }
  }

  /**
   * Registers the provided listener to be executed when the transaction is
   * completed.
   *
   * The order in which the event listeners will be executed is undefined and
   * should not be relied upon.
   *
   * @param {function()} listener The listener to register.
   */
  addCompleteListener(listener) {
    this[FIELDS.completeListeners].add(listener)
  }

  /**
   * Registers the provided listener to be executed when the transaction is
   * aborted by calling the {@codelink abort()} method, or due to an error.
   *
   * The order in which the event listeners will be executed is undefined and
   * should not be relied upon.
   *
   * @param {function()} listener The listener to register.
   */
  addAbortListener(listener) {
    this[FIELDS.abortListeners].add(listener)
  }

  /**
   * Registers the provided listener to be executed when an error is
   * encountered during the manipulation of the database from this transaction,
   * and the error was not somehow captured during the processing of the
   * operation that caused the error.
   *
   * The order in which the event listeners will be executed is undefined and
   * should not be relied upon.
   *
   * @param {function(Error)} listener The listener to register.
   */
  addErrorListener(listener) {
    this[FIELDS.errorListeners].add(listener)
  }

  /**
   * Aborts this transaction. Calling this method will lead to the execution of
   * the abort listeners registered on this transaction.
   */
  abort() {
    this[FIELDS.transaction].abort()
  }

  /**
   * Returns the read-only object store of the specified name. The method
   * returns the same object store if called repeatedly with the same argument.
   *
   * @param {string} objectStoreName The name of the object store to retrieve.
   * @return {ReadOnlyObjectStore} The object store.
   */
  getObjectStore(objectStoreName) {
    if (this[FIELDS.objectStores].has(objectStoreName)) {
      return this[FIELDS.objectStores].get(objectStoreName)
    }

    let transactionFactory = () => {
      return this[FIELDS.transactionFactory](objectStoreName)
    }

    let idbObjectStore = this[FIELDS.transaction].objectStore(objectStoreName)
    let objectStore = new ReadOnlyObjectStore(
      idbObjectStore,
      ReadOnlyCursor,
      transactionFactory
    )
    this[FIELDS.objectStores].set(objectStoreName, objectStore)

    return objectStore
  }
}

/**
 * Executes the provided event listeners with the provided parameters. Any
 * errors thrown by the executed event listeners will be caught and logged to
 * the console, and then the remaining event listeners will be executed.
 *
 * @param {function(...*)[]} listeners The event listeners to execute.
 * @param {...*} parameters The parameters to pass to the event listeners as
 *        arguments.
 */
function executeEventListeners(listeners, ...parameters) {
  listeners.forEach((listener) => {
    try {
      listener.apply(null, parameters)
    } catch (error) {
      console.error("An event listener threw an error", error)
    }
  })
}
<|endoftext|>


<commit_before>'use strict';

import _ from 'lodash';
import rest from './lib/rest-client';

var cronofy = function(config){
  this.accountInformation = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/account', details.options, details.callback);
  }

  this.authorizeWithServiceAccount = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpPost('/v1/service_account_authorizations', details.options, details.callback);
  }

  this.availability = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpPost('/v1/availability', details.options, details.callback);
  }

  this.createEvent = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpPost('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
  }

  this.createNotificationChannel = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpPost('/v1/channels', details.options, details.callback);
  }

  this.deleteEvent = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpDelete('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
  }

  this.deleteExternalEvent = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpDelete('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
  }

  this.deleteNotificationChannel = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpDelete('/v1/channels/' + details.options.channel_id, details.options, details.callback, ['access_token', 'channel_id']);
  }

  this.elevatedPermissions = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpPost('/v1/permissions', details.options, details.callback);
  }

  this.freeBusy = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/free_busy', details.options, details.callback);
  }

  this.listCalendars = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/calendars', details.options, details.callback);
  }

  this.listNotificationChannels = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/channels', details.options, details.callback);
  }

  this.profileInformation = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/profiles', details.options, details.callback);
  }

  this.readEvents = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/events', details.options, details.callback);
  }

  this.refreshAccessToken = function(){
    var details = parseArguments(arguments, ["client_id", "client_secret", "refresh_token"]);

    details.options.grant_type = "refresh_token";

    return httpPost('/oauth/token', details.options, function(token){
      config.access_token = token.access_token;
      config.refresh_token = token.refresh_token;

      details.callback(token);
    });
  }

  this.requestAccessToken = function(){
    var details = parseArguments(arguments, ["client_id", "client_secret", "refresh_token"]);

    details.options.grant_type = "authorization_code";

    return httpPost('/oauth/token', details.options, function(token){
      config.access_token = token.access_token;
      config.refresh_token = token.refresh_token;

      details.callback(token);
    })
  }

  this.revokeAuthorization = function(){
    var details = parseArguments(arguments, ["client_id", "client_secret", "refresh_token"]);

    return httpPost('/oauth/token/revoke', details.options, function(){
      delete config.access_token;
      delete config.refresh_token;

      console.log(config);

      details.callback();
    })
  }

  var urls = {
    api: 'http://local' + (config.dataCenter ? '-' + config.dataCenter : '') + '.cronofy.com'
  };

  var httpGet = function(path, options, callback, optionsToOmit){
    return httpCall('GET', path, options, callback, optionsToOmit);
  }

  var httpPost = function(path, options, callback, optionsToOmit){
    return httpCall('POST', path, options, callback, optionsToOmit);
  }

  var httpDelete = function(path, options, callback, optionsToOmit){
    return httpCall('DELETE', path, options, callback, optionsToOmit);
  }

  var httpCall = function(method, path, options, callback, optionsToOmit){
    var settings = {
      method: method,
      path: urls.api + path,
      headers: {
        Authorization: 'Bearer ' + options.access_token,
        'Content-Type': 'application/json'
      },
      entity: _.omit(options, optionsToOmit || ['access_token'])
    };

    return new Promise(function(resolve, reject){
      callback = callback || resolve;

      rest(settings).then(function(result){
        if(result['entity']) {
          callback(result['entity']);
        } else {
          callback();
        }
      });
    });
  }

  var parseArguments = function(args, configDefaults){
    var parsed = {options: {}, callback: null};

    if(args.length == 2){
      parsed.options = args[0];
      parsed.callback = args[1];
    } else {
      switch(typeof args[0]){
        case "object":
          parsed.options = args[0];
          break;
        case "function":
          parsed.callback = args[0];
          break;
      }
    }

    for(var i = 0; i < configDefaults.length; i++){
      var key = configDefaults[i];

      parsed.options[key] = parsed.options[key] || config[key];
    }

    return parsed;
  }
}

export default cronofy;
<commit_msg>Handle promise errors<commit_after>'use strict';

import _ from 'lodash';
import rest from './lib/rest-client';

var tap = function(func){
  return function(value){
    func.apply(null, arguments);
    return value;
  }
}

var cronofy = function(config){
  this.accountInformation = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/account', details.options, details.callback);
  }

  this.authorizeWithServiceAccount = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpPost('/v1/service_account_authorizations', details.options, details.callback);
  }

  this.availability = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpPost('/v1/availability', details.options, details.callback);
  }

  this.createEvent = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpPost('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
  }

  this.createNotificationChannel = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpPost('/v1/channels', details.options, details.callback);
  }

  this.deleteEvent = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpDelete('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
  }

  this.deleteExternalEvent = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpDelete('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
  }

  this.deleteNotificationChannel = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpDelete('/v1/channels/' + details.options.channel_id, details.options, details.callback, ['access_token', 'channel_id']);
  }

  this.elevatedPermissions = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpPost('/v1/permissions', details.options, details.callback);
  }

  this.freeBusy = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/free_busy', details.options, details.callback);
  }

  this.listCalendars = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/calendars', details.options, details.callback);
  }

  this.listNotificationChannels = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/channels', details.options, details.callback);
  }

  this.profileInformation = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/profiles', details.options, details.callback);
  }

  this.readEvents = function(){
    var details = parseArguments(arguments, ["access_token"]);

    return httpGet('/v1/events', details.options, details.callback);
  }

  this.refreshAccessToken = function(){
    var details = parseArguments(arguments, ["client_id", "client_secret", "refresh_token"]);

    details.options.grant_type = "refresh_token";

    return httpPost('/oauth/token', details.options).then(tap(function(token){
      config.access_token = token.access_token;
      config.refresh_token = token.refresh_token;

      if(details.callback){
        details.callback(null, token);
      }
    }), details.callback);
  }

  this.requestAccessToken = function(){
    var details = parseArguments(arguments, ["client_id", "client_secret", "refresh_token"]);

    details.options.grant_type = "authorization_code";

    return httpPost('/oauth/token', details.options).then(tap(function(token){
      config.access_token = token.access_token;
      config.refresh_token = token.refresh_token;

      if(details.callback){
        details.callback(null, token);
      }
    }), details.callback);
  }

  this.revokeAuthorization = function(){
    var details = parseArguments(arguments, ["client_id", "client_secret", "refresh_token"]);

    return httpPost('/oauth/token/revoke', details.options).then(tap(function(){
      delete config.access_token;
      delete config.refresh_token;

      if(details.callback){
        details.callback();
      }
    }), details.callback);
  }

  var urls = {
    api: 'http://local' + (config.dataCenter ? '-' + config.dataCenter : '') + '.cronofy.com'
  };

  var httpGet = function(path, options, callback, optionsToOmit){
    return httpCall('GET', path, options, callback, optionsToOmit);
  }

  var httpPost = function(path, options, callback, optionsToOmit){
    return httpCall('POST', path, options, callback, optionsToOmit);
  }

  var httpDelete = function(path, options, callback, optionsToOmit){
    return httpCall('DELETE', path, options, callback, optionsToOmit);
  }

  var httpCall = function(method, path, options, callback, optionsToOmit){
    var settings = {
      method: method,
      path: urls.api + path,
      headers: {
        Authorization: 'Bearer ' + options.access_token,
        'Content-Type': 'application/json'
      },
      entity: _.omit(options, optionsToOmit || ['access_token'])
    };

    return new Promise(function(resolve, reject){
      rest(settings).then(function(result){
        if(callback){
          callback(null, result['entity']);
        } else {
          resolve(result['entity']);
        }
      }, function(err){
        if(callback){
          callback(err);
        } else {
          reject(err);
        }
      });
    });
  }

  var parseArguments = function(args, configDefaults){
    var parsed = {options: {}, callback: null};

    if(args.length == 2){
      parsed.options = args[0];
      parsed.callback = args[1];
    } else {
      switch(typeof args[0]){
        case "object":
          parsed.options = args[0];
          break;
        case "function":
          parsed.callback = args[0];
          break;
      }
    }

    for(var i = 0; i < configDefaults.length; i++){
      var key = configDefaults[i];

      parsed.options[key] = parsed.options[key] || config[key];
    }

    return parsed;
  }
}

export default cronofy;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import csjs from 'csjs';
import insertStyle, { removeStyle, getStyle } from './insert-style';

const cache = new Map();

export default function withStyles(css) {
  return DecoratedComponent =>
    class WithStyleDecorator extends Component {
      static displayName = `csjs(${DecoratedComponent.displayName
                            || DecoratedComponent.name || 'Component'})`

      componentWillMount() {
        let refs = cache.get(DecoratedComponent);
        if (!refs) {
          this.elm = insertStyle(csjs.getCss(css));
          cache.set(DecoratedComponent, { style: this.elm, count: 1 });
        } else {
          this.elm = refs.style;
          refs.count++;
        }
      }

      componentWillUpdate() {
        if (process.env.NODE_ENV !== 'production') {
            // Support React Hot Loader
          const cssText = csjs.getCss(css);
          if (getStyle(this.elm) !== cssText) {
            this.elm = insertStyle(cssText, { element: this.elm });
          }
        }
      }

      componentWillUnmount() {
        let refs = cache.get(DecoratedComponent);
        refs.count--;
        if (refs.count === 0) {
            cache.delete(DecoratedComponent)
            removeStyle(this.elm);
            this.elm = null;
        }
      }

      render() {
        return <DecoratedComponent classes={css} {...this.props} />;
      }
    };
}
<commit_msg>cleanup<commit_after>import React, { Component } from 'react';
import csjs from 'csjs';
import insertStyle, { removeStyle, getStyle } from './insert-style';

const cache = new Map();

export default function withStyles(css) {
  return DecoratedComponent =>
    class WithStyleDecorator extends Component {
      static displayName = `csjs(${DecoratedComponent.displayName
                            || DecoratedComponent.name || 'Component'})`

      componentWillMount() {
        let refs = cache.get(DecoratedComponent);
        if (!refs) {
          this.elm = insertStyle(csjs.getCss(css));
          cache.set(DecoratedComponent, { style: this.elm, count: 1 });
        } else {
          this.elm = refs.style;
          refs.count++;
        }
      }

      componentWillUpdate() {
        if (process.env.NODE_ENV !== 'production') {
            // Support React Hot Loader
          const cssText = csjs.getCss(css);
          if (getStyle(this.elm) !== cssText) {
            this.elm = insertStyle(cssText, { element: this.elm });
          }
        }
      }

      componentWillUnmount() {
        let refs = cache.get(DecoratedComponent);
        if (--refs.count === 0) {
            cache.delete(DecoratedComponent)
            removeStyle(this.elm);
            this.elm = null;
        }
      }

      render() {
        return <DecoratedComponent classes={css} {...this.props} />;
      }
    };
}
<|endoftext|>