<commit_before>"use strict";
var assert = require('assert');

var Color = {
    White: 0,
    Black: 1
};

var Orientation = {
    Up: 0,
    Left: 1,
    Right: 2
};

var Ant = function() {

    var position = {x: 0, y: 0};
    var orientation = Orientation.Up;

    this.position = function() {
	return position;
    };

    this.orientation = function() {
	return orientation;
    };

    this.left = function() {

	var l = {};
	l[Orientation.Up] = Orientation.Left;
	l[Orientation.Left] =  Orientation.Down;
	l[Orientation.Down] =  Orientation.Right;
	l[Orientation.Right] =  Orientation.Up;

	orientation = l[orientation];
    };

    this.right = function() {

	var r = {};
	r[Orientation.Up] = Orientation.Right;
	r[Orientation.Left] =  Orientation.Up;
	r[Orientation.Down] =  Orientation.Left;
	r[Orientation.Right] =  Orientation.Down;

	orientation = r[orientation];
    };

    return this;
};

var makeAnt = function() {
    return new Ant();
};

var Square = function() {

    var color = Color.White;

    this.color = function() {
	return color;
    };

    this.flip = function() {
	color = (color == Color.White ? Color.Black : Color.White);
    };

    return this;
};

var makeSquare = function() {
    return new Square();
};

var eqPoint = function(p1,p2) {
    return p1.x === p2.x && p1.y === p2.y;
};

var Game = function() {
    var ant = makeAnt();

    var blackSquares = [];

    this.color = function(key) {
	for (var i=0;i<blackSquares.length;++i) {
	    if (eqPoint(blackSquares[i],key)) return Color.Black;
	}

	return Color.White;
    };

    this.ant = function() {
	return ant;
    };

    this.step = function() {
	if (this.color(ant.position()) === Color.White) {
	    blackSquares.push(ant.position());
	    ant.right();
	} else {
	    blackSquares.remove(ant.position());
	    ant.left();
	}
    };

    return this;
};

var makeGame = function() {
    return new Game();
};

describe('langton\'s ant', function() {

    describe('game', function() {
	it('exists', function() {
	    assert(makeGame());
	});

	it('records state', function() {
	    var game = makeGame();
	    assert.deepEqual({x: 0, y: 0}, game.ant().position());
	});

	it('steps ant orientation', function() {
	    var game = makeGame();
	    game.step();

	    assert.equal(Orientation.Right, game.ant().orientation());
	});

	it('flips square color', function() {
	    var game = makeGame();
	    assert.equal(Color.White, game.color({x: 0, y: 0}));

	    game.step();
	    assert.equal(Color.Black, game.color({x: 0, y: 0}));
	});
    });

    describe('ant', function() {
	it('exists', function() {
	    assert(makeAnt());
	});

	it('has a location', function() {
	    var ant = makeAnt();
	    assert.equal(0, ant.position().x);
	    assert.equal(0, ant.position().y);
	});

	it('orientation up', function() {
	    var ant = makeAnt();
	    assert.equal(Orientation.Up, ant.orientation());
	});

	it('turns left', function() {
	    var ant = makeAnt();
	    ant.left();
	    assert.equal(Orientation.Left, ant.orientation());

	    ant.left();
	    assert.equal(Orientation.Down, ant.orientation());

	    ant.left();
	    assert.equal(Orientation.Right, ant.orientation());

	    ant.left();
	    assert.equal(Orientation.Up, ant.orientation());
	});

	it('turns right', function() {
	    var ant = makeAnt();
	    ant.right();
	    assert.equal(Orientation.Right, ant.orientation());

	    ant.right();
	    assert.equal(Orientation.Down, ant.orientation());

	    ant.right();
	    assert.equal(Orientation.Left, ant.orientation());

	    ant.right();
	    assert.equal(Orientation.Up, ant.orientation());
	});
    });

    describe('square', function() {
	it('exists', function() {
	    assert(makeSquare());
	});

	it('initially white', function() {
	    assert.equal(Color.White, makeSquare().color());
	});

	it('flips', function() {
	    var sq = makeSquare();
	    sq.flip();
	    assert.equal(Color.Black, sq.color());
	});
    });
});
<commit_msg>remove unnecessary {}<commit_after>"use strict";
var assert = require('assert');

var Color = {
    White: 0,
    Black: 1
};

var Orientation = {
    Up: 0,
    Left: 1,
    Right: 2
};

var Ant = function() {

    var position = {x: 0, y: 0};
    var orientation = Orientation.Up;

    this.position = function() {
	return position;
    };

    this.orientation = function() {
	return orientation;
    };

    this.left = function() {

	var l = {};
	l[Orientation.Up] = Orientation.Left;
	l[Orientation.Left] =  Orientation.Down;
	l[Orientation.Down] =  Orientation.Right;
	l[Orientation.Right] =  Orientation.Up;

	orientation = l[orientation];
    };

    this.right = function() {

	var r = {};
	r[Orientation.Up] = Orientation.Right;
	r[Orientation.Left] =  Orientation.Up;
	r[Orientation.Down] =  Orientation.Left;
	r[Orientation.Right] =  Orientation.Down;

	orientation = r[orientation];
    };

    return this;
};

var makeAnt = function() {
    return new Ant();
};

var Square = function() {

    var color = Color.White;

    this.color = function() {
	return color;
    };

    this.flip = function() {
	color = (color == Color.White ? Color.Black : Color.White);
    };

    return this;
};

var makeSquare = function() {
    return new Square();
};

var eqPoint = function(p1,p2) {
    return p1.x === p2.x && p1.y === p2.y;
};

var Game = function() {
    var ant = makeAnt();

    var blackSquares = [];

    this.color = function(key) {
	for (var i=0;i<blackSquares.length;++i)
	    if (eqPoint(blackSquares[i],key)) return Color.Black;

	return Color.White;
    };

    this.ant = function() {
	return ant;
    };

    this.step = function() {
	if (this.color(ant.position()) === Color.White) {
	    blackSquares.push(ant.position());
	    ant.right();
	} else {
	    blackSquares.remove(ant.position());
	    ant.left();
	}
    };

    return this;
};

var makeGame = function() {
    return new Game();
};

describe('langton\'s ant', function() {

    describe('game', function() {
	it('exists', function() {
	    assert(makeGame());
	});

	it('records state', function() {
	    var game = makeGame();
	    assert.deepEqual({x: 0, y: 0}, game.ant().position());
	});

	it('steps ant orientation', function() {
	    var game = makeGame();
	    game.step();

	    assert.equal(Orientation.Right, game.ant().orientation());
	});

	it('flips square color', function() {
	    var game = makeGame();
	    assert.equal(Color.White, game.color({x: 0, y: 0}));

	    game.step();
	    assert.equal(Color.Black, game.color({x: 0, y: 0}));
	});
    });

    describe('ant', function() {
	it('exists', function() {
	    assert(makeAnt());
	});

	it('has a location', function() {
	    var ant = makeAnt();
	    assert.equal(0, ant.position().x);
	    assert.equal(0, ant.position().y);
	});

	it('orientation up', function() {
	    var ant = makeAnt();
	    assert.equal(Orientation.Up, ant.orientation());
	});

	it('turns left', function() {
	    var ant = makeAnt();
	    ant.left();
	    assert.equal(Orientation.Left, ant.orientation());

	    ant.left();
	    assert.equal(Orientation.Down, ant.orientation());

	    ant.left();
	    assert.equal(Orientation.Right, ant.orientation());

	    ant.left();
	    assert.equal(Orientation.Up, ant.orientation());
	});

	it('turns right', function() {
	    var ant = makeAnt();
	    ant.right();
	    assert.equal(Orientation.Right, ant.orientation());

	    ant.right();
	    assert.equal(Orientation.Down, ant.orientation());

	    ant.right();
	    assert.equal(Orientation.Left, ant.orientation());

	    ant.right();
	    assert.equal(Orientation.Up, ant.orientation());
	});
    });

    describe('square', function() {
	it('exists', function() {
	    assert(makeSquare());
	});

	it('initially white', function() {
	    assert.equal(Color.White, makeSquare().color());
	});

	it('flips', function() {
	    var sq = makeSquare();
	    sq.flip();
	    assert.equal(Color.Black, sq.color());
	});
    });
});
<|endoftext|>


<commit_before>var args = arguments[0] || {};

var data            = require('data'),
    eventData       = data.get('eventData');

$.formWindow.setTitle(eventData.form_label);
$.formWindow.setBackgroundColor(eventData.styles.background);

var formWebView = Titanium.UI.createWebView({
    url: eventData.form
});

$.formWindow.add(formWebView);<commit_msg>Fix ridiculous tabulation.<commit_after>var args = arguments[0] || {};

var data        = require('data'),
    eventData   = data.get('eventData');

$.formWindow.setTitle(eventData.form_label);
$.formWindow.setBackgroundColor(eventData.styles.background);

var formWebView = Titanium.UI.createWebView({
    url: eventData.form
});

$.formWindow.add(formWebView);<|endoftext|>


<commit_before>
(function (jQuery) {
	jQuery.extend({
		bindIframeLoadEvent: function(iframe, callback) {
			jQuery(iframe).bind('load', function () {
				// when we remove iframe from dom the request stops, but in IE load event fires
				if (!iframe.parentNode) {
					return;
				}
				// fixing Opera 10.53
				if (iframe.contentDocument && iframe.contentDocument.body && iframe.contentDocument.body.innerHTML == "false") {
					// In Opera event is fired second time when body.innerHTML changed from false
					// to server response approx. after 1 sec when we upload file with iframe
					return;
				}
				callback();
			});
		}
	});
})(jQuery);

(function (jQuery) {
	jQuery.fn.extend({
		center: function() {
			var jQueryWindow = jQuery(window);
			return this.each(function () {
				var jQueryThis = jQuery(this);
				var top = (jQueryWindow.height() - jQueryThis.outerHeight(true)) / 2 + jQueryWindow.scrollTop();
				top = top > 0 ? top : 0;
				var left = (jQueryWindow.width() - jQueryThis.outerWidth(true)) / 2 + jQueryWindow.scrollLeft();
				left = left > 0 ? left : 0;
				jQueryThis.css({ position: "absolute", margin: 0, top: top + "px", left: left + "px" });
				return jQueryThis;
			});
		}
	});
})(jQuery);
<commit_msg>refactoring<commit_after>
(function (jQuery) {
	jQuery.extend({
		bindIframeLoadEvent: function(iframe, callback) {
			jQuery(iframe).bind('load', function () {
				// when we remove iframe from dom the request stops, but in IE load event fires
				if (!iframe.parentNode) {
					return;
				}
				// fixing Opera 10.53
				if (iframe.contentDocument && iframe.contentDocument.body && iframe.contentDocument.body.innerHTML == "false") {
					// In Opera event is fired second time when body.innerHTML changed from false
					// to server response approx. after 1 sec when we upload file with iframe
					return;
				}
				callback();
			});
		}
	});
})(jQuery);

(function (jQuery) {
	jQuery.fn.extend({
		center: function() {
			var $window = jQuery(window);
			return this.each(function () {
				var $this = jQuery(this);
				var top = ($window.height() - $this.outerHeight(true)) / 2 + $window.scrollTop();
				top = top > 0 ? top : 0;
				var left = ($window.width() - $this.outerWidth(true)) / 2 + $window.scrollLeft();
				left = left > 0 ? left : 0;
				$this.css({ position: "absolute", margin: 0, top: top + "px", left: left + "px" });
				return $this;
			});
		}
	});
})(jQuery);

(function ($) {
    if (typeof __doPostBack === "function") {
        var __doPostBackOriginal = __doPostBack;
        __doPostBack = function (eventTarget, eventArgument) {
            $("form").trigger("onPostBack");
            __doPostBackOriginal(eventTarget, eventArgument);
        };
    }

    $.onPostBack = function (func) {
        $("form").on("onPostBack", function () { func(); });
    };
})(jQuery);
<|endoftext|>


<commit_before>// @flow

const LIMIT = 200

export default (displayName: string) => {
  let generatedClasses = {}
  let warningSeen = false

  return (className: string) => {
    if (!warningSeen) {
      generatedClasses[className] = true
      if (Object.keys(generatedClasses).length >= LIMIT) {
        // Unable to find latestRule in test environment.
        /* eslint-disable no-console, prefer-template */
        console.warn(`Over ${LIMIT} classes were generated for component ${displayName}. \n` +
          'Consider using the attrs property, together with a style object for frequently changed styles.\n' +
          'Example:\n' +
          '  const Component = styled.div.attrs({\n' +
          '    style: ({ background }) => {\n' +
          '      background,\n' +
          '    },\n' +
          '  })`width: 100%;`\n\n' +

          '  <Component />')
        warningSeen = true
        generatedClasses = {}
      }
    }
  }
}
<commit_msg>change 'attrs property' to attrs method' in warning<commit_after>// @flow

const LIMIT = 200

export default (displayName: string) => {
  let generatedClasses = {}
  let warningSeen = false

  return (className: string) => {
    if (!warningSeen) {
      generatedClasses[className] = true
      if (Object.keys(generatedClasses).length >= LIMIT) {
        // Unable to find latestRule in test environment.
        /* eslint-disable no-console, prefer-template */
        console.warn(`Over ${LIMIT} classes were generated for component ${displayName}. \n` +
          'Consider using the attrs method, together with a style object for frequently changed styles.\n' +
          'Example:\n' +
          '  const Component = styled.div.attrs({\n' +
          '    style: ({ background }) => {\n' +
          '      background,\n' +
          '    },\n' +
          '  })`width: 100%;`\n\n' +

          '  <Component />')
        warningSeen = true
        generatedClasses = {}
      }
    }
  }
}
<|endoftext|>


<commit_before>/**
 * This is the build script for both building
 *
 * Part I: Admin - the administrator panel
 * Part II: Stage - the front pages
 *
 * of our web application/site.
 */

var buildify = require('buildify'),
_ = require('underscore'),
cheerio = require('cheerio'), //as server side jquery
path = require('path');

/*-----------Config/Structure-------*/
/**
 * {} - create folder
 * 'string' - copy file or folder
 * true/false - read from task memory, minify or non-minify.
 */
var config = {
	distFolder: '../dist',
	clientBase: '../../',
	index: {
		admin : 'app/index.html'
	},
	structure : {
		admin: {
			scripts: {
				_try: {}, //autoload scripts
				modules: { //layouts/page wrapper
					active: {}, //view + interactions
					data: {}, //data model bound (grid + form)
					readonly: {}, //view only
					special: {} //non-view-able
				},
				vendor: {}, //3rd party libs
				widgets: {
					editor: {}, //form editors
					plugin: {}, //jquery plugins (as widgets)
					standard: {} //backbone view
				},
				core: { //core lib, tpl and application js are built then put here.
					'core.js': true, //!!Hardcoded path see - loadIndexHTML() below;
				},
				'config.js': 'app/scripts/config.js' //-non minified or copied
			},
			static: {
				menu: {
					'menu.json': 'app/static/menu/menu.json'
				},
				resources: 'app/static/resources'
			},
			themes: {
				_default: 'app/themes/_default'
			},
			'404.html': 'app/404.html',
			'index.html': true,
			'robots.txt': 'app/robots.txt'
		}
	}
};

/*-----------Util/Steps------------*/
//0. load index.html (replace lib, tpl and application js section - compress js libs into core.js)
function loadIndexHTML(target){
	return buildify().load(config.clientBase + config.index[target]).perform(function(content){
		//extract build sections.
		var $ = cheerio.load(content);
		var $script;
		var coreJS = buildify().load('EMPTY.js');
		$('script').each(function(index, el){
			$script = $(el);
			if($script.attr('non-core')) return;
			var srcPath = $script.attr('src');
			if(srcPath){
				//ref-ed js, concat
				coreJS.concat(config.clientBase + 'app/' + srcPath);
			}else {
				//in-line
				coreJS.perform(function(content){
					return content + ';' + $script.html() + ';';
				});
			}
			$script.remove();
		});

		$('body').append('<script src="scripts/core/core.js"></script>'); //Warning::Hard Coded Core Lib Path!
		content = $.html();

		return {
			'core.js': coreJS.uglify().getContent(),
			'index.html': content
		}
	});

}

//1. create structure with pre-processed package.
function createFolderStructure(target, package) {
	var structure = config.structure[target];
	var targets = [];
	var baseDir = path.join(config.distFolder, target);
	_.each(structure, function(content, key){
		targets.push({
			path: path.join(baseDir, key),
			content: content,
			key: key
		});
	});
	console.log(targets);
	//use iteration - bfs to create/copy/dump the files/folders
	//TBI
}

/*-----------Build Tasks-----------*/
buildify.task({
	name: 'admin',
	task: function(){
		var pack = loadIndexHTML('admin');
		createFolderStructure('admin', pack);
	}
});

buildify.task({
	name: 'stage',
	task: function(){

	}
});<commit_msg>Added folder/file create to build script<commit_after>/**
 * This is the build script for both building
 *
 * Part I: Admin - the administrator panel
 * Part II: Stage - the front pages
 *
 * of our web application/site.
 */

var buildify = require('buildify'),
_ = require('underscore'),
cheerio = require('cheerio'), //as server side jquery
path = require('path'),
mkdirp = require('mkdirp'),
ncp = require('ncp').ncp;

ncp.limit = 16;

/*-----------Config/Structure-------*/
/**
 * {} - create folder
 * 'string' - copy file or folder
 * true/false - read from task memory, minify or non-minify.
 */
var config = {
	distFolder: '../dist',
	clientBase: '../../',
	index: {
		admin : 'app/index.html'
	},
	structure : {
		admin: {
			scripts: {
				_try: {}, //autoload scripts
				modules: { //layouts/page wrapper
					active: {}, //view + interactions
					data: {}, //data model bound (grid + form)
					readonly: {}, //view only
					special: {} //non-view-able
				},
				vendor: {}, //3rd party libs
				widgets: {
					editor: {}, //form editors
					plugin: {}, //jquery plugins (as widgets)
					standard: {} //backbone view
				},
				core: { //core lib, tpl and application js are built then put here.
					'core.js': true, //!!Hardcoded path see - loadIndexHTML() below;
				},
				'config.js': 'app/scripts/config.js' //-non minified or copied
			},
			static: {
				menu: {
					'menu.json': 'app/static/menu/menu.json'
				},
				resources: 'app/static/resources'
			},
			themes: {
				_default: 'app/themes/_default'
			},
			'404.html': 'app/404.html',
			'index.html': true,
			'robots.txt': 'app/robots.txt'
		}
	}
};

/*-----------Util/Steps------------*/
//0. load index.html (replace lib, tpl and application js section - compress js libs into core.js)
function loadIndexHTML(target){
	return buildify().load(config.clientBase + config.index[target]).perform(function(content){
		//extract build sections.
		var $ = cheerio.load(content);
		var $script;
		var coreJS = buildify().load('EMPTY.js');
		$('script').each(function(index, el){
			$script = $(el);
			if($script.attr('non-core')) return;
			var srcPath = $script.attr('src');
			if(srcPath){
				//ref-ed js, concat
				coreJS.concat(config.clientBase + 'app/' + srcPath);
			}else {
				//in-line
				coreJS.perform(function(content){
					return content + ';' + $script.html() + ';';
				});
			}
			$script.remove();
		});

		$('body').append('<script src="scripts/core/core.js"></script>'); //Warning::Hard Coded Core Lib Path!
		content = $.html();

		return {
			'core.js': coreJS.uglify().getContent(),
			'index.html': content
		}
	});

}

//1. create structure with pre-processed package.
function createFolderStructure(target, package) {
	var structure = config.structure[target];
	var targets = [];
	var baseDir = path.join(config.distFolder, target);
	_.each(structure, function(content, key){
		targets.push({
			path: path.join(baseDir, key),
			content: content,
			key: key
		});
	});
	//use iteration - bfs to create/copy/dump the files/folders
	while(targets.length > 0) {
		var currentTarget = targets.shift();
		if(_.isString(currentTarget.content)){
			//path string - copy
			var srcPath = path.join(config.clientBase, currentTarget.content);
			ncp(srcPath, currentTarget.path, function(error){
				if(!error) console.log(srcPath, '==>', currentTarget.path, '[OK]');
				else console.log(srcPath, '==>', currentTarget.path, '[ERROR:', error, ']');
			});
		}else if(_.isBoolean(currentTarget.content)){
			//true/false - dump from cached package
			if(package[currentTarget.key]){
				buildify().setContent(package[currentTarget.key]).save(currentTarget.path);
			}
		}else if(_.isObject(currentTarget.content)){
			//{} and {...} create folder and keep the bfs going
			var folderPath = path.join(currentTarget.path, currentTarget.key);
			mkdirp(folderPath, function(error){
				if(!error) console.log(folderPath, '{+}', '[OK]');
				else console.log(folderPath, '{+}', '[ERROR:', error,']');
			});

			_.each(currentTarget.content, function(subContent, subKey){
				targets.push({
					path: path.join(folderPath, subKey),
					content: subContent,
					key: subKey
				});
			});
		}
	}
}

/*-----------Build Tasks-----------*/
buildify.task({
	name: 'admin',
	task: function(){
		var pack = loadIndexHTML('admin');
		mkdirp(config.distFolder, function(error){
			createFolderStructure('admin', pack);
		});
	}
});

buildify.task({
	name: 'stage',
	task: function(){

	}
});<|endoftext|>


<commit_before>// @flow

import Icon from '@conveyal/woonerf/components/icon'
import React, {Component} from 'react'

import { ListGroupItem, Row, Col, Button, Collapse, Glyphicon, Label } from 'react-bootstrap'
import { getFeed } from '../../common/util/modules'
import { getRouteNameAlerts } from '../../editor/util/gtfs'
import AgencySelector from './AgencySelector'
import ModeSelector from './ModeSelector'
import StopSelector from './StopSelector'
import RouteSelector from './RouteSelector'

import type {AlertEntity, Feed} from '../../types'

type Props = {
  activeFeeds: Array<Feed>,
  entity: AlertEntity,
  entityUpdated: (AlertEntity, string, any) => void,
  feeds: Array<Feed>,
  onDeleteEntityClick: any => void
}

type State = {
  active: boolean
}

export default class AffectedEntity extends Component<Props, State> {
  state = {
    active: false
  }

  _onRowClick = () => this.setState({active: !this.state.active})

  _onClickDeleteEntity = () => this.props.onDeleteEntityClick(this.props.entity)

  getEntitySummary (entity: AlertEntity) {
    const {feeds} = this.props
    const type = entity.type || 'AGENCY'
    const val = entity[type.toLowerCase()]
    let agencyName = ''
    if (entity.agency) {
      agencyName = entity.agency.name
    } else if (entity.stop) {
      // FIXME feed_id?
      const feed = getFeed(feeds, entity.stop.feed_id)
      agencyName = feed
        ? feed.name
        : 'Unknown agency'
    }
    const routeName = entity.route
      ? getRouteNameAlerts(entity.route)
      : entity.route_id
    const stopName = entity.stop
      ? `${entity.stop.stop_name} (${entity.stop.stop_id}) ${agencyName}`
      : entity.stop_id
    let summary = ''
    switch (type) {
      case 'AGENCY' :
        return (

            <Icon type='building' />{' '}
            {agencyName}

              Note: this selection will apply to all stops and routes for
              {agencyName}.

        )
      case 'STOP' :
        summary = stopName || '[no stop id]'
        if (routeName) {
          summary += ` for ${routeName}`
        }
        return <Icon type='map-marker' /> {summary}
      case 'ROUTE' :
        summary = routeName || '[no route id]'
        if (stopName) {
          summary += ` at ${stopName}`
        }
        return <Glyphicon glyph='option-horizontal' /> {summary}
      case 'MODE' :
        summary = val.name
        if (stopName) {
          summary += ` at ${stopName}`
        }
        return (

            {type}: {summary}

              Note: this selection will apply to all {val.name.toLowerCase()}{' '}
              routes{stopName && ` stopping at ${stopName}`}.

        )
    }
  }

  renderHeader (entity: AlertEntity) {
    return (
      <Row
        className='list-group-item-heading'
        onClick={this._onRowClick}
        style={{cursor: 'pointer'}}>
        <Col xs={10}>

            <Icon type={this.state.active ? 'caret-down' : 'caret-right'} />
            {this.getEntitySummary(entity)}

        </Col>
        <Col xs={2}>
          <Button
            bsSize='small'
            className='pull-right'
            style={{marginTop: '5px'}}
            onClick={this._onClickDeleteEntity}>
            <Icon type='remove' />
          </Button>
        </Col>
      </Row>
    )
  }

  renderEntity (entity: AlertEntity) {
    const {activeFeeds, entityUpdated, feeds} = this.props
    const indent = {
      paddingLeft: '30px'
    }
    const selectedFeeds = entity.agency ? [entity.agency] : activeFeeds
    const selectedRoute = entity.route
    const selectedStop = entity.stop
    switch (entity.type) {
      case 'AGENCY':
        return (

            Agency:
            <AgencySelector
              feeds={feeds}
              entityUpdated={entityUpdated}
              entity={entity} />

        )
      case 'MODE':
        return (

            Mode:
            <ModeSelector
              entityUpdated={entityUpdated}
              value={entity.type}
              entity={entity} />

              Refine by Agency:
              <AgencySelector
                feeds={feeds}
                entityUpdated={entityUpdated}
                entity={entity} />
              Refine by Stop:
              <StopSelector
                feeds={selectedFeeds}
                stop={entity.stop}
                entityUpdated={entityUpdated}
                entity={entity} />

        )
      case 'STOP':
        return (

            Stop:
            <StopSelector
              feeds={activeFeeds}
              stop={entity.stop}
              clearable={false}
              entityUpdated={entityUpdated}
              entity={entity} />

              Refine by Route:
              <RouteSelector
                feeds={selectedFeeds}
                minimumInput={0}
                filterByStop={selectedStop}
                route={entity.route}
                entityUpdated={entityUpdated}
                entity={entity} />

        )
      case 'ROUTE':
        return (

            Route:
            <RouteSelector
              feeds={activeFeeds}
              route={entity.route}
              clearable={false}
              entityUpdated={entityUpdated}
              entity={entity} />

              Refine by Stop:
              <StopSelector
                feeds={selectedFeeds}
                minimumInput={0}
                filterByRoute={selectedRoute}
                stop={entity.stop}
                entityUpdated={entityUpdated}
                entity={entity} />

        )
    }
  }

  render () {
    const {entity} = this.props
    const {type} = entity
    const bsStyle = (entity && (type === 'AGENCY' || type === 'MODE'))
      ? 'warning'
      : undefined
    return (
      <ListGroupItem bsStyle={bsStyle}>
        {this.renderHeader(entity)}
        <Collapse in={this.state.active}>
          {this.renderEntity(entity)}
        </Collapse>
      </ListGroupItem>
    )
  }
}
<commit_msg>refactor(alerts): prefer stop_code when rendering affected stop entity<commit_after>// @flow

import Icon from '@conveyal/woonerf/components/icon'
import React, {Component} from 'react'

import { ListGroupItem, Row, Col, Button, Collapse, Glyphicon, Label } from 'react-bootstrap'
import { getFeed } from '../../common/util/modules'
import { getRouteNameAlerts } from '../../editor/util/gtfs'
import AgencySelector from './AgencySelector'
import ModeSelector from './ModeSelector'
import StopSelector from './StopSelector'
import RouteSelector from './RouteSelector'

import type {AlertEntity, Feed} from '../../types'

type Props = {
  activeFeeds: Array<Feed>,
  entity: AlertEntity,
  entityUpdated: (AlertEntity, string, any) => void,
  feeds: Array<Feed>,
  onDeleteEntityClick: any => void
}

type State = {
  active: boolean
}

export default class AffectedEntity extends Component<Props, State> {
  state = {
    active: false
  }

  _onRowClick = () => this.setState({ active: !this.state.active })

  _onClickDeleteEntity = () => this.props.onDeleteEntityClick(this.props.entity)

  getEntitySummary (entity: AlertEntity) {
    const { feeds } = this.props
    const { stop } = entity
    const type = entity.type || 'AGENCY'
    const val = entity[type.toLowerCase()]
    let agencyName = ''
    let stopName = entity.stop_id
    if (entity.agency) {
      agencyName = entity.agency.name
    } else if (stop) {
      // FIXME feed_id?
      const feed = getFeed(feeds, stop.feed_id)
      agencyName = feed
        ? feed.name
        : 'Unknown agency'
    }
    const routeName = entity.route
      ? getRouteNameAlerts(entity.route)
      : entity.route_id
    if (stop) {
      const stopCode = stop.stop_code ? stop.stop_code : stop.stop_id
      stopName = `${stop.stop_name} (${stopCode}) ${agencyName}`
    }
    let summary = ''
    switch (type) {
      case 'AGENCY' :
        return (

            <Icon type='building' />{' '}
            {agencyName}

              Note: this selection will apply to all stops and routes for
              {agencyName}.

        )
      case 'STOP' :
        summary = stopName || '[no stop id]'
        if (routeName) {
          summary += ` for ${routeName}`
        }
        return <Icon type='map-marker' /> {summary}
      case 'ROUTE' :
        summary = routeName || '[no route id]'
        if (stopName) {
          summary += ` at ${stopName}`
        }
        return <Glyphicon glyph='option-horizontal' /> {summary}
      case 'MODE' :
        summary = val.name
        if (stopName) {
          summary += ` at ${stopName}`
        }
        return (

            {type}: {summary}

              Note: this selection will apply to all {val.name.toLowerCase()}{' '}
              routes{stopName && ` stopping at ${stopName}`}.

        )
    }
  }

  renderHeader (entity: AlertEntity) {
    return (
      <Row
        className='list-group-item-heading'
        onClick={this._onRowClick}
        style={{cursor: 'pointer'}}>
        <Col xs={10}>

            <Icon type={this.state.active ? 'caret-down' : 'caret-right'} />
            {this.getEntitySummary(entity)}

        </Col>
        <Col xs={2}>
          <Button
            bsSize='small'
            className='pull-right'
            style={{marginTop: '5px'}}
            onClick={this._onClickDeleteEntity}>
            <Icon type='remove' />
          </Button>
        </Col>
      </Row>
    )
  }

  renderEntity (entity: AlertEntity) {
    const {activeFeeds, entityUpdated, feeds} = this.props
    const indent = {
      paddingLeft: '30px'
    }
    const selectedFeeds = entity.agency ? [entity.agency] : activeFeeds
    const selectedRoute = entity.route
    const selectedStop = entity.stop
    switch (entity.type) {
      case 'AGENCY':
        return (

            Agency:
            <AgencySelector
              feeds={feeds}
              entityUpdated={entityUpdated}
              entity={entity} />

        )
      case 'MODE':
        return (

            Mode:
            <ModeSelector
              entityUpdated={entityUpdated}
              value={entity.type}
              entity={entity} />

              Refine by Agency:
              <AgencySelector
                feeds={feeds}
                entityUpdated={entityUpdated}
                entity={entity} />
              Refine by Stop:
              <StopSelector
                feeds={selectedFeeds}
                stop={entity.stop}
                entityUpdated={entityUpdated}
                entity={entity} />

        )
      case 'STOP':
        return (

            Stop:
            <StopSelector
              feeds={activeFeeds}
              stop={entity.stop}
              clearable={false}
              entityUpdated={entityUpdated}
              entity={entity} />

              Refine by Route:
              <RouteSelector
                feeds={selectedFeeds}
                minimumInput={0}
                filterByStop={selectedStop}
                route={entity.route}
                entityUpdated={entityUpdated}
                entity={entity} />

        )
      case 'ROUTE':
        return (

            Route:
            <RouteSelector
              feeds={activeFeeds}
              route={entity.route}
              clearable={false}
              entityUpdated={entityUpdated}
              entity={entity} />

              Refine by Stop:
              <StopSelector
                feeds={selectedFeeds}
                minimumInput={0}
                filterByRoute={selectedRoute}
                stop={entity.stop}
                entityUpdated={entityUpdated}
                entity={entity} />

        )
    }
  }

  render () {
    const {entity} = this.props
    const {type} = entity
    const bsStyle = (entity && (type === 'AGENCY' || type === 'MODE'))
      ? 'warning'
      : undefined
    return (
      <ListGroupItem bsStyle={bsStyle}>
        {this.renderHeader(entity)}
        <Collapse in={this.state.active}>
          {this.renderEntity(entity)}
        </Collapse>
      </ListGroupItem>
    )
  }
}
<|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')
const ncp = require('ncp').ncp
const mkdirp = require('mkdirp')
const rimraf = require('rimraf')

const version = JSON.parse(fs.readFileSync('package.json', 'utf-8')).version

const powerShellDir = path.join(process.env['USERPROFILE'], 'My Documents', 'WindowsPowerShell')
const moduleDir = path.join(powerShellDir, 'Modules', 'powershell-utils')

if (fs.existsSync(moduleDir)) {
    rimraf.sync(moduleDir)
}

const destinationDir = path.join(moduleDir, `${version}`)
mkdirp.sync(destinationDir)

ncp('src', destinationDir, function (err) {
    if (err) {
        throw err
    }

    const profilePath = path.join(powerShellDir, "profile.ps1")
    let content = fs.readFileSync(profilePath, "utf-8")
    const regex = /^Import-Module powershell-utils$/m

    if (!regex.test(content)) {
        fs.appendFileSync(profilePath, 'Import-Module powershell-utils')
    }
})
<commit_msg>Made sure a newline is added in profile.ps1<commit_after>const fs = require('fs')
const path = require('path')
const ncp = require('ncp').ncp
const mkdirp = require('mkdirp')
const rimraf = require('rimraf')

const version = JSON.parse(fs.readFileSync('package.json', 'utf-8')).version

const powerShellDir = path.join(process.env['USERPROFILE'], 'My Documents', 'WindowsPowerShell')
const moduleDir = path.join(powerShellDir, 'Modules', 'powershell-utils')

if (fs.existsSync(moduleDir)) {
    rimraf.sync(moduleDir)
}

const destinationDir = path.join(moduleDir, `${version}`)
mkdirp.sync(destinationDir)

ncp('src', destinationDir, function (err) {
    if (err) {
        throw err
    }

    const profilePath = path.join(powerShellDir, "profile.ps1")
    let content = fs.readFileSync(profilePath, "utf-8")
    const regex = /^Import-Module powershell-utils$/m

    if (!regex.test(content)) {
        fs.appendFileSync(profilePath, 'Import-Module powershell-utils\n')
    }
})
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */

const co = require('co');
const utils = require('lib/utils');
const mongoose = require('mongoose');
const Meme = mongoose.model('Meme');

/**
 * Get all memes.
 */

exports.getMemes = co.wrap(function* (ctx, next) {
  let memes;

  try {
    memes = yield Meme.find().exec();
    ctx.body = {
      memes: memes
    };
  } catch (err) {
    ctx.throw(err);
  }
});

/**
 * Get meme by id.
 */

exports.getMemeById = co.wrap(function* (ctx, next) {
  let id = ctx.params.id;
  ctx.assert(mongoose.Types.ObjectId.isValid(id), 404, 'Meme not found');

  try {
    let meme = yield Meme.findById(id).exec();
    ctx.assert(meme, 404, 'Meme not found');

    ctx.body = meme;
  } catch (err) {
    ctx.throw(err);
  }
});

/**
 * Create meme.
 */

exports.createMeme = co.wrap(function* (ctx, next) {
  let body = ctx.request.body;
  ctx.assert(body, 400, 'The body is empty');

  try {
    let data = JSON.parse(body);
    let meme = yield Meme.create(data);

    // set Location header
    ctx.set('Location', utils.generateResourceUrl('memes', meme.id));
    ctx.status = 201;
  } catch (err) {
    ctx.throw(err);
  }
});

/**
 * Update meme.
 */

exports.updateMeme = co.wrap(function* (ctx, next) {
  let id = ctx.params.id;
  ctx.assert(mongoose.Types.ObjectId.isValid(id), 404, 'Meme not found');

  let body = ctx.request.body;
  ctx.assert(body, 400, 'The body is empty');

  try {
    let data = JSON.parse(body);
    let meme = yield Meme.findByIdAndUpdate(id, data);

    ctx.status = 200;
  } catch (err) {
    ctx.throw(err);
  }
});
<commit_msg>minor error validation<commit_after>'use strict';

/**
 * Module dependencies.
 */

const co = require('co');
const utils = require('lib/utils');
const mongoose = require('mongoose');
const Meme = mongoose.model('Meme');

/**
 * Get all memes.
 */

exports.getMemes = co.wrap(function* (ctx, next) {
  let memes;

  try {
    memes = yield Meme.find().exec();
    ctx.body = {
      memes: memes
    };
  } catch (err) {
    ctx.throw(err);
  }
});

/**
 * Get meme by id.
 */

exports.getMemeById = co.wrap(function* (ctx, next) {
  let id = ctx.params.id;
  ctx.assert(mongoose.Types.ObjectId.isValid(id), 404, 'Meme not found');

  try {
    let meme = yield Meme.findById(id).exec();
    ctx.assert(meme, 404, 'Meme not found');

    ctx.body = meme;
  } catch (err) {
    ctx.throw(err);
  }
});

/**
 * Create meme.
 */

exports.createMeme = co.wrap(function* (ctx, next) {
  let body = ctx.request.body;
  ctx.assert(body, 400, 'The body is empty');

  try {
    let data = JSON.parse(body);
    let meme = yield Meme.create(data);

    // set Location header
    ctx.set('Location', utils.generateResourceUrl('memes', meme.id));
    ctx.status = 201;
  } catch (err) {
    ctx.throw(err);
  }
});

/**
 * Update meme.
 */

exports.updateMeme = co.wrap(function* (ctx, next) {
  let id = ctx.params.id;
  ctx.assert(mongoose.Types.ObjectId.isValid(id), 404, 'Meme not found');

  let body = ctx.request.body;
  ctx.assert(body, 400, 'The body is empty');

  try {
    let data = JSON.parse(body);
    let meme = yield Meme.findByIdAndUpdate(id, data);
    ctx.assert(meme, 404, 'Meme not found');

    ctx.status = 200;
  } catch (err) {
    ctx.throw(err);
  }
});
<|endoftext|>


<commit_before>function confirmIconPlugin(pluginConfig) {
	const defaultConfig = {
		confirmIcon: "<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='17' height='17' viewBox='0 0 17 17'> <g> </g> <path d='M15.418 1.774l-8.833 13.485-4.918-4.386 0.666-0.746 4.051 3.614 8.198-12.515 0.836 0.548z' fill='#000000' /> </svg>",
		confirmText: "OK ",
		showAlways: false
	};

	const config = Object.assign({}, defaultConfig, pluginConfig || {});

	return function(fp) {
		fp.confirmContainer = fp._createElement("div", "flatpickr-confirm", config.confirmText);
		fp.confirmContainer.innerHTML += config.confirmIcon;

		fp.confirmContainer.addEventListener("click", fp.close);

		const hooks = {
			onReady () {
				fp.calendarContainer.appendChild(fp.confirmContainer);
			}
		};

		if (config.showAlways)
			fp.confirmContainer.classList.add("visible");

		else
			hooks.onChange = function(dateObj, dateStr) {
				if(dateStr && !fp.config.inline)
					return fp.confirmContainer.classList.add("visible");
				fp.confirmContainer.classList.remove("visible");
			}

		return hooks;
	}
}

if (typeof module !== "undefined")
	module.exports = confirmIconPlugin;
<commit_msg>confirmDate: focus on confirm after amPM<commit_after>function confirmIconPlugin(pluginConfig) {
	const defaultConfig = {
		confirmIcon: "<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='17' height='17' viewBox='0 0 17 17'> <g> </g> <path d='M15.418 1.774l-8.833 13.485-4.918-4.386 0.666-0.746 4.051 3.614 8.198-12.515 0.836 0.548z' fill='#000000' /> </svg>",
		confirmText: "OK ",
		showAlways: false
	};

	const config = Object.assign({}, defaultConfig, pluginConfig || {});

	return function(fp) {
		fp.confirmContainer = fp._createElement("div", "flatpickr-confirm", config.confirmText);
		fp.confirmContainer.tabIndex = -1;
		fp.confirmContainer.innerHTML += config.confirmIcon;

		fp.confirmContainer.addEventListener("click", fp.close);

		const hooks = {
			onReady () {
				fp.calendarContainer.appendChild(fp.confirmContainer);
			}
		};

		if (config.showAlways)
			fp.confirmContainer.classList.add("visible");

		else
			hooks.onChange = function(dateObj, dateStr) {
				if(dateStr && !fp.config.inline)
					return fp.confirmContainer.classList.add("visible");
				fp.confirmContainer.classList.remove("visible");
			}

		hooks.onKeyDown = (_, __, ___, e) => {
			if (fp.config.enableTime && e.key === "Tab" && e.target === fp.amPM) {
				e.preventDefault();
				fp.confirmContainer.focus();
			}

			else if (e.key === "Enter" && e.target === fp.confirmContainer)
				fp.close();
		};

		return hooks;
	}
}

if (typeof module !== "undefined")
	module.exports = confirmIconPlugin;
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import { shortUrlType } from '../../short-urls/reducers/shortUrlsList';

/* eslint-disable padding-line-between-statements, newline-after-var */
export const GET_SHORT_URL_DETAIL_START = 'shlink/shortUrlDetail/GET_SHORT_URL_DETAIL_START';
export const GET_SHORT_URL_DETAIL_ERROR = 'shlink/shortUrlDetail/GET_SHORT_URL_DETAIL_ERROR';
export const GET_SHORT_URL_DETAIL = 'shlink/shortUrlDetail/GET_SHORT_URL_DETAIL';
/* eslint-enable padding-line-between-statements, newline-after-var */

export const shortUrlDetailType = PropTypes.shape({
  shortUrl: shortUrlType,
  loading: PropTypes.bool,
  error: PropTypes.bool,
});

const initialState = {
  shortUrl: {},
  loading: false,
  error: false,
};

export default function reducer(state = initialState, action) {
  switch (action.type) {
    case GET_SHORT_URL_DETAIL_START:
      return {
        ...state,
        loading: true,
      };
    case GET_SHORT_URL_DETAIL_ERROR:
      return {
        ...state,
        loading: false,
        error: true,
      };
    case GET_SHORT_URL_DETAIL:
      return {
        shortUrl: action.shortUrl,
        loading: false,
        error: false,
      };
    default:
      return state;
  }
}

export const getShortUrlDetail = (buildShlinkApiClient) => (shortCode) => async (dispatch, getState) => {
  dispatch({ type: GET_SHORT_URL_DETAIL_START });

  const { selectedServer } = getState();
  const shlinkApiClient = buildShlinkApiClient(selectedServer);

  try {
    const shortUrl = await shlinkApiClient.getShortUrl(shortCode);

    dispatch({ shortUrl, type: GET_SHORT_URL_DETAIL });
  } catch (e) {
    dispatch({ type: GET_SHORT_URL_DETAIL_ERROR });
  }
};
<commit_msg>Refactored shortUrlDetail reducer to take advantage of redux-actions<commit_after>import { handleActions } from 'redux-actions';
import PropTypes from 'prop-types';
import { shortUrlType } from '../../short-urls/reducers/shortUrlsList';

/* eslint-disable padding-line-between-statements */
export const GET_SHORT_URL_DETAIL_START = 'shlink/shortUrlDetail/GET_SHORT_URL_DETAIL_START';
export const GET_SHORT_URL_DETAIL_ERROR = 'shlink/shortUrlDetail/GET_SHORT_URL_DETAIL_ERROR';
export const GET_SHORT_URL_DETAIL = 'shlink/shortUrlDetail/GET_SHORT_URL_DETAIL';
/* eslint-enable padding-line-between-statements */

export const shortUrlDetailType = PropTypes.shape({
  shortUrl: shortUrlType,
  loading: PropTypes.bool,
  error: PropTypes.bool,
});

const initialState = {
  shortUrl: {},
  loading: false,
  error: false,
};

export default handleActions({
  [GET_SHORT_URL_DETAIL_START]: (state) => ({ ...state, loading: true }),
  [GET_SHORT_URL_DETAIL_ERROR]: (state) => ({ ...state, loading: false, error: true }),
  [GET_SHORT_URL_DETAIL]: (state, { shortUrl }) => ({ shortUrl, loading: false, error: false }),
}, initialState);

export const getShortUrlDetail = (buildShlinkApiClient) => (shortCode) => async (dispatch, getState) => {
  dispatch({ type: GET_SHORT_URL_DETAIL_START });

  const { selectedServer } = getState();
  const shlinkApiClient = buildShlinkApiClient(selectedServer);

  try {
    const shortUrl = await shlinkApiClient.getShortUrl(shortCode);

    dispatch({ shortUrl, type: GET_SHORT_URL_DETAIL });
  } catch (e) {
    dispatch({ type: GET_SHORT_URL_DETAIL_ERROR });
  }
};
<|endoftext|>


<commit_before>var sharedFunctions = require('./public/js/telemetryToSystemPower.js');
var PREFERENCES_NS = 'plugins';

class SystemEnvironment
{
    constructor(name, deps)
    {
      console.log('Controllerboard2x:SystemEnvironment plugin loaded');
    }
}

class SystemPower
{
    constructor(name, deps)
    {
      console.log('Controllerboard2x:SystemPower plugin loaded');

      this.config   = deps.config;
      this.cockpit  = deps.cockpit;
      var self      = this;

      deps.cockpit.on('plugin.systemPower.powerESCs', function (enable)
      {
        if (enable)
        {
          deps.globalEventLoop.emit('mcu.SendCommand', 'escp(1)');
        }
        else
        {
          deps.globalEventLoop.emit('mcu.SendCommand', 'escp(0)');
        }
      });
    }

    getSettingSchema()
    {
      // TODO:
      // If settings already exist, new defaults aren't available.
      // Do we have an idiomatic way for upgrading old settings so that
      // renamed properties/values and new ones replace them?

      var b = this.config.preferences.get(PREFERENCES_NS);

      return [{
        id:       'batteryDefinitions',
        title:    'Battery Formulas',
        category: 'power',
        type:     'object',

        properties:
        {
          batteries:
          {
            title:          "Batteries",
            type:           "array",
            uniqueItems:    true,
            propertyOrder:  1,

            items:
            {
              type:           "object",
              headerTemplate: "{{self.name}}",
              properties:
              {
                name:         { type: 'string', default: "New Battery" },
                minVoltage:   { type: 'number', default: 8 },
                maxVoltage:   { type: 'number', default: 12.6 }
              },
              required:
              [
                'name',
                'minVoltage',
                'maxVoltage'
              ]
            },
            default:
            [
              {
                name:       'TrustFire',
                minVoltage: 8,
                maxVoltage: 13
              },
              {
                name:       'LiFePO4 (OpenROV White)',
                minVoltage: 7,
                maxVoltage: 10
              },
              {
                name:       'High-Capacity NMC (OpenROV Blue)',
                minVoltage: 8,
                maxVoltage: 12.6
              }
            ]
          },
          selectedBattery:
          {
            title:      "Selected Battery",
            type:       'string',
            propertyOrder: 0,

            enumSource: "possible_batteries",
            enumValue: "{{item.name}}",
            watch:
            {
              "possible_batteries": "root.batteryDefinitions.batteries"
            },

            default:    "LiFePO4 (OpenROV White)"
          }
        },

        required:
        [
          'batteries',
          'selectedBattery'
        ]
      }];
    }
};

// Controller Board 2X Plugin
class Controllerboard2x
{
    constructor(name, deps)
    {
      console.log('Controllerboard2x plugin loaded');

      this.systempower        = new SystemPower(name, deps);
      this.systemenvironment  = new SystemEnvironment(name, deps);
    }

    getSettingSchema()
    {
      var item = this.systempower.getSettingSchema();
      return item;
    }
}

module.exports = function (name, deps)
{
  if( process.env.PRODUCTID == "trident" )
  {
      console.log( "Not supported on trident" );
      return {};
  }

  return new Controllerboard2x(name, deps);
};<commit_msg>Added minimum item count to battery definition list<commit_after>var sharedFunctions = require('./public/js/telemetryToSystemPower.js');
var PREFERENCES_NS = 'plugins';

class SystemEnvironment
{
    constructor(name, deps)
    {
      console.log('Controllerboard2x:SystemEnvironment plugin loaded');
    }
}

class SystemPower
{
    constructor(name, deps)
    {
      console.log('Controllerboard2x:SystemPower plugin loaded');

      this.config   = deps.config;
      this.cockpit  = deps.cockpit;
      var self      = this;

      deps.cockpit.on('plugin.systemPower.powerESCs', function (enable)
      {
        if (enable)
        {
          deps.globalEventLoop.emit('mcu.SendCommand', 'escp(1)');
        }
        else
        {
          deps.globalEventLoop.emit('mcu.SendCommand', 'escp(0)');
        }
      });
    }

    getSettingSchema()
    {
      // TODO:
      // If settings already exist, new defaults aren't available.
      // Do we have an idiomatic way for upgrading old settings so that
      // renamed properties/values and new ones replace them?

      var b = this.config.preferences.get(PREFERENCES_NS);

      return [{
        id:       'batteryDefinitions',
        title:    'Battery Formulas',
        category: 'power',
        type:     'object',

        properties:
        {
          batteries:
          {
            title:          "Batteries",
            type:           "array",
            minItems:       1,
            uniqueItems:    true,
            propertyOrder:  1,

            items:
            {
              type:           "object",
              headerTemplate: "{{self.name}}",
              properties:
              {
                name:         { type: 'string', default: "New Battery" },
                minVoltage:   { type: 'number', default: 8 },
                maxVoltage:   { type: 'number', default: 12.6 }
              },
              required:
              [
                'name',
                'minVoltage',
                'maxVoltage'
              ]
            },
            default:
            [
              {
                name:       'TrustFire',
                minVoltage: 8,
                maxVoltage: 13
              },
              {
                name:       'LiFePO4 (OpenROV White)',
                minVoltage: 7,
                maxVoltage: 10
              },
              {
                name:       'High-Capacity NMC (OpenROV Blue)',
                minVoltage: 8,
                maxVoltage: 12.6
              }
            ]
          },
          selectedBattery:
          {
            title:      "Selected Battery",
            type:       'string',
            propertyOrder: 0,

            enumSource: "possible_batteries",
            enumValue: "{{item.name}}",
            watch:
            {
              "possible_batteries": "root.batteryDefinitions.batteries"
            },

            default:    "LiFePO4 (OpenROV White)"
          }
        },

        required:
        [
          'batteries',
          'selectedBattery'
        ]
      }];
    }
};

// Controller Board 2X Plugin
class Controllerboard2x
{
    constructor(name, deps)
    {
      console.log('Controllerboard2x plugin loaded');

      this.systempower        = new SystemPower(name, deps);
      this.systemenvironment  = new SystemEnvironment(name, deps);
    }

    getSettingSchema()
    {
      var item = this.systempower.getSettingSchema();
      return item;
    }
}

module.exports = function (name, deps)
{
  if( process.env.PRODUCTID == "trident" )
  {
      console.log( "Not supported on trident" );
      return {};
  }

  return new Controllerboard2x(name, deps);
};<|endoftext|>


<commit_before>import { Fixed8 } from '../../utils'
import Coin from './Coin'

/**
 * @typedef AssetBalance
 * @property {Fixed8} balance - The total balance in this AssetBalance
 * @property {Coin[]} unspent - Unspent coins
 * @property {Coin[]} spent - Spent coins
 * @property {Coin[]} unconfirmed - Unconfirmed coins
 */
export default (assetBalanceObj = {}) => {
  const {
    balance,
    unspent,
    spent,
    unconfirmed
  } = assetBalanceObj

  return {
    balance: balance ? new Fixed8(balance) : new Fixed8(0),
    unspent: unspent ? unspent.map(coin => new Coin(coin)) : [],
    spent: spent ? spent.map(coin => new Coin(coin)) : [],
    unconfirmed: unconfirmed ? unconfirmed.map(coin => new Coin(coin)) : []
  }
}
<commit_msg>fix(wallet): remove new for Coin<commit_after>import { Fixed8 } from '../../utils'
import Coin from './Coin'

/**
 * @typedef AssetBalance
 * @property {Fixed8} balance - The total balance in this AssetBalance
 * @property {Coin[]} unspent - Unspent coins
 * @property {Coin[]} spent - Spent coins
 * @property {Coin[]} unconfirmed - Unconfirmed coins
 */
export default (assetBalanceObj = {}) => {
  const {
    balance,
    unspent,
    spent,
    unconfirmed
  } = assetBalanceObj

  return {
    balance: balance ? new Fixed8(balance) : new Fixed8(0),
    unspent: unspent ? unspent.map(coin => Coin(coin)) : [],
    spent: spent ? spent.map(coin => Coin(coin)) : [],
    unconfirmed: unconfirmed ? unconfirmed.map(coin => Coin(coin)) : []
  }
}
<|endoftext|>


<commit_before>'use strict';

var tmpl = require("../utilities/components-layout/tmpl.html");
var helpers = require('../utilities/handlebars/helpers.js');
var controlPanel = require('../components/controlPanel');
var lineGraph = require('../components/lineGraph');
var electronicPanelData = require('../utilities/data/electronicPanel.js');

module.exports = {
    init: function(el) {
        this.$el = $(el);
        var data = { title: "Electrical", primaryGraphName: "Solar Power Graph", secondaryGraphName: "Bus Voltage Graph" };
        var template = helpers.compile(tmpl);
        this.$el.html(template(data));
        this.loadControlPanel();
        this.loadGraphPanels();
    },
    loadControlPanel: function() {
        var data = electronicPanelData.data[0];
        controlPanel.init(data);
    },
    loadGraphPanels: function() {
        var SolarArrayGraphOptions = {
            xAxisId: 'Spacecraft_Time',
            xAxisName: 'Spacecraft Time',
            xAxisUnit: 'sec',
            yAxisId: 'SolArray_Pow',
            yAxisName: 'Solar Array Power',
            yAxisUnit: 'W',
            width: this.$el.find('.primaryGraph').width(),
            data: electronicPanelData.data,
            el: '.primaryGraph',
            limits : [
                {legend:"Critical High", value: 55, color: "red" },
                {legend:"Warning High", value: 50, color: "orange" },
                {legend:"Warning Low", value: 30, color: "orange" },
                {legend:"Critical Low", value: 25, color: "red" }
            ]
        };

        var BusVoltageGraphOptions = {
            xAxisId: 'Spacecraft_Time',
            xAxisName: 'Spacecraft Time',
            xAxisUnit: 'sec',
            yAxisId: 'Bus_Volt',
            yAxisName: 'Bus Voltage',
            yAxisUnit: 'V',
            width: this.$el.find('.secondaryGraph').width(),
            data: electronicPanelData.data,
            el: '.secondaryGraph',
            limits : [
                {legend:"", value: 33.28, color: "red" },
                {legend:"", value: 33.27, color: "orange" },
                {legend:"", value: 33.23, color: "orange" },
                {legend:"", value: 33.22, color: "red" }
            ]
        };

        lineGraph.init(SolarArrayGraphOptions);
        lineGraph.init(BusVoltageGraphOptions);
    }
};
<commit_msg>added the missing critical labels<commit_after>'use strict';

var tmpl = require("../utilities/components-layout/tmpl.html");
var helpers = require('../utilities/handlebars/helpers.js');
var controlPanel = require('../components/controlPanel');
var lineGraph = require('../components/lineGraph');
var electronicPanelData = require('../utilities/data/electronicPanel.js');

module.exports = {
    init: function(el) {
        this.$el = $(el);
        var data = { title: "Electrical", primaryGraphName: "Solar Power Graph", secondaryGraphName: "Bus Voltage Graph" };
        var template = helpers.compile(tmpl);
        this.$el.html(template(data));
        this.loadControlPanel();
        this.loadGraphPanels();
    },
    loadControlPanel: function() {
        var data = electronicPanelData.data[0];
        controlPanel.init(data);
    },
    loadGraphPanels: function() {
        var SolarArrayGraphOptions = {
            xAxisId: 'Spacecraft_Time',
            xAxisName: 'Spacecraft Time',
            xAxisUnit: 'sec',
            yAxisId: 'SolArray_Pow',
            yAxisName: 'Solar Array Power',
            yAxisUnit: 'W',
            width: this.$el.find('.primaryGraph').width(),
            data: electronicPanelData.data,
            el: '.primaryGraph',
            limits: [
                { legend: "Critical High", value: 55, color: "red" },
                { legend: "Warning High", value: 50, color: "orange" },
                { legend: "Warning Low", value: 30, color: "orange" },
                { legend: "Critical Low", value: 25, color: "red" }
            ]
        };

        var BusVoltageGraphOptions = {
            xAxisId: 'Spacecraft_Time',
            xAxisName: 'Spacecraft Time',
            xAxisUnit: 'sec',
            yAxisId: 'Bus_Volt',
            yAxisName: 'Bus Voltage',
            yAxisUnit: 'V',
            width: this.$el.find('.secondaryGraph').width(),
            data: electronicPanelData.data,
            el: '.secondaryGraph',
            limits: [
                { legend: "Critical High", value: 33.28, color: "red" },
                { legend: "Warning High", value: 33.27, color: "orange" },
                { legend: "Warning Low", value: 33.23, color: "orange" },
                { legend: "Critical Low", value: 33.22, color: "red" }
            ]
        };

        lineGraph.init(SolarArrayGraphOptions);
        lineGraph.init(BusVoltageGraphOptions);
    }
};
<|endoftext|>


<commit_before>var TradeOfferManager = require('../index.js');
var SteamID = require('steamid');

var ETradeOfferState = TradeOfferManager.ETradeOfferState;
var EOfferFilter = TradeOfferManager.EOfferFilter;

TradeOfferManager.prototype.createOffer = function(partner) {
	var offer = new TradeOffer(this, partner);
	offer.isOurOffer = true;
	offer.fromRealTimeTrade = false;
	return offer;
};

TradeOfferManager.prototype.getOffer = function(id, callback) {
	this._apiCall('GET', 'GetTradeOffer', 1, {"tradeofferid": id}, function(err, body) {
		if(err) {
			return callback(err);
		}

		if(!body.response || !body.response.offer) {
			return callback(new Error("Malformed API response"));
		}

		callback(null, createOfferFromData(this, body.response.offer));
	}.bind(this));
};

TradeOfferManager.prototype.getOffers = function(filter, historicalCutoff, callback) {
	if(typeof historicalCutoff === 'function') {
		callback = historicalCutoff;
		historicalCutoff = new Date(Date.now() + (31536000000));
	}

	var options = {
		"get_sent_offers": 1,
		"get_received_offers": 1,
		"get_descriptions": this._language ? 1 : 0,
		"language": this._language,
		"active_only": filter == EOfferFilter.ActiveOnly ? 1 : 0,
		"historical_only": filter == EOfferFilter.HistoricalOnly ? 1 : 0,
		"time_historical_cutoff": Math.floor(historicalCutoff.getTime())
	};

	var manager = this;
	this._apiCall('GET', 'GetTradeOffers', 1, options, function(err, body) {
		if(err) {
			return callback(err);
		}

		if(!body.response) {
			return callback(new Error("Malformed API response"));
		}

		var sent = (body.response.trade_offers_sent || []).map(function(data) {
			return createOfferFromData(manager, data);
		});

		var received = (body.response.trade_offers_received || []).map(function(data) {
			return createOfferFromData(manager, data);
		});

		callback(null, sent, received);
	});
};

function createOfferFromData(manager, data) {
	var offer = new TradeOffer(manager, new SteamID('[U:1:' + data.accountid_other + ']'));
	offer.id = data.tradeofferid;
	offer.message = data.message;
	offer.state = data.trade_offer_state;
	offer.itemsToGive = data.items_to_give || [];
	offer.itemsToReceive = data.items_to_receive || [];
	offer.isOurOffer = data.is_our_offer;
	offer.created = new Date(data.time_created * 1000),
	offer.updated = new Date(data.time_updated * 1000),
	offer.expires = new Date(data.expiration_time * 1000),
	offer.tradeID = data.tradeid || null;
	offer.fromRealTimeTrade = data.from_real_time_trade;

	return offer;
}

function TradeOffer(manager, partner) {
	if(partner instanceof SteamID) {
		this.partner = partner;
	} else {
		this.partner = new SteamID(partner);
	}

	this._manager = manager;

	this.id = null;
	this.message = null;
	this.state = ETradeOfferState.Invalid;
	this.itemsToGive = [];
	this.itemsToReceive = [];
	this.isOurOffer = null;
	this.created = null;
	this.updated = null;
	this.expires = null;
	this.tradeID = null;
	this.fromRealTimeTrade = null;
}

TradeOffer.prototype.loadPartnerInventory = function(appid, contextid, callback, data, start) {
	this._manager._request('https://steamcommunity.com/tradeoffer/' + (this.id ? this.id : 'new') + '/partnerinventory/', {
		"qs": {
			"sessionid": this._manager._community.getSessionID(),
			"partner": this.partner.toString(),
			"appid": appid,
			"contextid": contextid,
			"start": start
		},
		"headers": {
			"referer": "https://steamcommunity.com/tradeoffer/" + (this.id ? this.id : 'new') + "/?partner=" + this.partner.accountid
		},
		"json": true
	}, function(err, response, body) {
		if(err || response.statusCode != 200) {
			return callback(err || new Error("HTTP error " + response.statusCode));
		}

		if(!body || !body.rgInventory || !body.rgDescriptions || !body.rgCurrency) {
			return callback(new Error("Malformed response"));
		}

		data = (data || []).concat(mergeWithDescriptions(body.rgInventory, body.rgDescriptions, contextid)).concat(mergeWithDescriptions(body.rgCurrency, body.rgDescriptions, contextid));
		if(body.more) {
			this.loadPartnerInventory(appid, contextid, callback, data, body.more_start);
		} else {
			callback(null, data);
		}
	}.bind(this));
};

function mergeWithDescriptions(items, descriptions, contextid) {
	return Object.keys(items).map(function(id) {
		var item = items[id];
		var description = descriptions[item.classid + '_' + (item.instanceid || '0')];
		for (var key in description) {
			item[key] = description[key];
		}
		// add contextid because Steam is retarded
		item.contextid = contextid;
		return item;
	});
}

TradeOffer.prototype.send = function(message, token, callback) {
	if(this.id) {
		return makeAnError(new Error("This offer has already been sent"), callback);
	}

	message = message || '';

	if(typeof token !== 'string') {
		callback = token;
		token = null;
	}

	var offerdata = {
		"newversion": true,
		"version": 4,
		"me": {
			"assets": this.itemsToGive.map(function(item) {
				return {
					"appid": item.appid,
					"contextid": item.contextid,
					"amount": item.amount || 1,
					"assetid": item.assetid
				};
			}),
			"currency": [], // TODO
			"ready": false
		},
		"them": {
			"assets": this.itemsToReceive.map(function(item) {
				return {
					"appid": item.appid,
					"contextid": item.contextid,
					"amount": item.amount || 1,
					"assetid": item.assetid
				};
			}),
			"currency": [],
			"ready": false
		}
	};

	var params = {};
	if(token) {
		params.trade_offer_access_token = token;
	}

	this._request.post('https://steamcommunity.com/tradeoffer/new/send', {
		"headers": {
			"referer": "https://steamcommunity.com/tradeoffer/new/?partner=" + this.partner.accountid + (token ? "&token=" + token : '')
		},
		"json": true,
		"form": {
			"sessionid": this._community.getSessionID(),
			"serverid": 1,
			"partner": this.partner.toString(),
			"tradeoffermessage": message,
			"json_tradeoffer": JSON.stringify(offerdata),
			"captcha": '',
			"trade_offer_create_params": JSON.stringify(params)
		}
	}, function(err, response, body) {
		if(err || response.statusCode != 200) {
			return makeAnError(err || new Error("HTTP error " + response.statusCode), callback);
		}

		if(body && body.strError) {
			return makeAnError(new Error(body.strError));
		}

		if(body && body.tradeofferid) {
			this.id = body.tradeofferid;
			this.message = message;
			this.state = ETradeOfferState.Active;
			this.created = new Date();
			this.updated = new Date();
			this.expires = new Date(Date.now() + 1209600000);
		}

		if(body && body.needs_email_confirmation) {
			this.state = ETradeOfferState.EmailPending;
		}

		if(!callback) {
			return;
		}

		if(body && body.needs_email_confirmation) {
			callback(null, 'pending');
		} else if(body && body.tradeofferid) {
			callback(null, 'sent');
		} else {
			callback(new Error("Unknown response"));
		}
	}.bind(this));
};

TradeOffer.prototype.cancel = function(callback) {
	if(!this.id) {
		return makeAnError(new Error("Cannot cancel or decline an unsent offer"), callback);
	}

	if(this.state != ETradeOfferState.Active) {
		return makeAnError(new Error("Offer #" + this.id + " is not active, so it may not be cancelled or declined"), callback);
	}

	this._manager._apiCall('POST', this.isOurOffer ? 'CancelTradeOffer' : 'DeclineTradeOffer', 1, {"tradeofferid": this.id}, function(err, body) {
		if(err) {
			makeAnError(err, callback);
		}

		this.updated = new Date();

		if(callback) {
			callback();
		}
	}.bind(this));
};

TradeOffer.prototype.decline = function(callback) {
	// Alias of cancel
	this.cancel(callback);
};

TradeOffer.prototype.accept = function(callback) {
	if(!this.id) {
		return makeAnError(new Error("Cannot accept an unsent offer"), callback);
	}

	if(this.state != ETradeOfferState.Active) {
		return makeAnError(new Error("Offer #" + this.id + " is not active, so it may not be accepted"), callback);
	}

	if(this.isOurOffer) {
		return makeAnError(new Error("Cannot accept our own offer #" + this.id), callback);
	}

	this._request.post('https://steamcommunity.com/tradeoffer/' + this.id + '/accept', {
		"headers": {
			"referer": 'https://steamcommunity.com/tradeoffer/' + this.id + '/'
		},
		"json": true,
		"form": {
			"sessionid": this._community.getSessionID(),
			"serverid": 1,
			"tradeofferid": this.id,
			"partner": this.partner.toString(),
			"captcha": ""
		}
	}, function(err, response, body) {
		if(err || response.statusCode != 200) {
			return makeAnError(err || new Error("HTTP error " + response.statusCode), callback);
		}

		if(body && body.strError) {
			return makeAnError(new Error(body.strError), callback);
		}

		if(body && body.tradeid) {
			this.updated = new Date();
		}

		if(!callback) {
			return;
		}

		if(body && body.needs_email_confirmation) {
			callback(null, 'pending');
		} else if(body && body.tradeid) {
			this.state = ETradeOfferState.Accepted;
			this.tradeid = body.tradeid;
			callback(null, 'accepted');
		} else {
			callback(new Error("Unknown response"));
		}
	}.bind(this));
};

TradeOffer.prototype.getReceivedItems = function(callback) {
	if(!this.id) {
		return makeAnError(new Error("Cannot request received items on an unsent offer"), callback);
	}

	if(this.state != ETradeOfferState.Accepted) {
		return makeAnError(new Error("Offer #" + this.id + " is not accepted, cannot request received items"), callback);
	}

	if(!this.tradeID) {
		return makeAnError(new Error("Offer #" + this.id + " is accepted, but does not have a trade ID"), callback);
	}

	// TODO
};

function makeAnError(error, callback) {
	if(callback) {
		callback(error);
	}
}
<commit_msg>Gracefully handle invalid offer IDs<commit_after>var TradeOfferManager = require('../index.js');
var SteamID = require('steamid');

var ETradeOfferState = TradeOfferManager.ETradeOfferState;
var EOfferFilter = TradeOfferManager.EOfferFilter;

TradeOfferManager.prototype.createOffer = function(partner) {
	var offer = new TradeOffer(this, partner);
	offer.isOurOffer = true;
	offer.fromRealTimeTrade = false;
	return offer;
};

TradeOfferManager.prototype.getOffer = function(id, callback) {
	this._apiCall('GET', 'GetTradeOffer', 1, {"tradeofferid": id}, function(err, body) {
		if(err) {
			return callback(err);
		}

		if(!body.response) {
			return callback(new Error("Malformed API response"));
		}

		if(!body.response.offer) {
			return callback(new Error("No matching offer found"));
		}

		callback(null, createOfferFromData(this, body.response.offer));
	}.bind(this));
};

TradeOfferManager.prototype.getOffers = function(filter, historicalCutoff, callback) {
	if(typeof historicalCutoff === 'function') {
		callback = historicalCutoff;
		historicalCutoff = new Date(Date.now() + (31536000000));
	}

	var options = {
		"get_sent_offers": 1,
		"get_received_offers": 1,
		"get_descriptions": this._language ? 1 : 0,
		"language": this._language,
		"active_only": filter == EOfferFilter.ActiveOnly ? 1 : 0,
		"historical_only": filter == EOfferFilter.HistoricalOnly ? 1 : 0,
		"time_historical_cutoff": Math.floor(historicalCutoff.getTime())
	};

	var manager = this;
	this._apiCall('GET', 'GetTradeOffers', 1, options, function(err, body) {
		if(err) {
			return callback(err);
		}

		if(!body.response) {
			return callback(new Error("Malformed API response"));
		}

		var sent = (body.response.trade_offers_sent || []).map(function(data) {
			return createOfferFromData(manager, data);
		});

		var received = (body.response.trade_offers_received || []).map(function(data) {
			return createOfferFromData(manager, data);
		});

		callback(null, sent, received);
	});
};

function createOfferFromData(manager, data) {
	var offer = new TradeOffer(manager, new SteamID('[U:1:' + data.accountid_other + ']'));
	offer.id = data.tradeofferid;
	offer.message = data.message;
	offer.state = data.trade_offer_state;
	offer.itemsToGive = data.items_to_give || [];
	offer.itemsToReceive = data.items_to_receive || [];
	offer.isOurOffer = data.is_our_offer;
	offer.created = new Date(data.time_created * 1000),
	offer.updated = new Date(data.time_updated * 1000),
	offer.expires = new Date(data.expiration_time * 1000),
	offer.tradeID = data.tradeid || null;
	offer.fromRealTimeTrade = data.from_real_time_trade;

	return offer;
}

function TradeOffer(manager, partner) {
	if(partner instanceof SteamID) {
		this.partner = partner;
	} else {
		this.partner = new SteamID(partner);
	}

	this._manager = manager;

	this.id = null;
	this.message = null;
	this.state = ETradeOfferState.Invalid;
	this.itemsToGive = [];
	this.itemsToReceive = [];
	this.isOurOffer = null;
	this.created = null;
	this.updated = null;
	this.expires = null;
	this.tradeID = null;
	this.fromRealTimeTrade = null;
}

TradeOffer.prototype.loadPartnerInventory = function(appid, contextid, callback, data, start) {
	this._manager._request('https://steamcommunity.com/tradeoffer/' + (this.id ? this.id : 'new') + '/partnerinventory/', {
		"qs": {
			"sessionid": this._manager._community.getSessionID(),
			"partner": this.partner.toString(),
			"appid": appid,
			"contextid": contextid,
			"start": start
		},
		"headers": {
			"referer": "https://steamcommunity.com/tradeoffer/" + (this.id ? this.id : 'new') + "/?partner=" + this.partner.accountid
		},
		"json": true
	}, function(err, response, body) {
		if(err || response.statusCode != 200) {
			return callback(err || new Error("HTTP error " + response.statusCode));
		}

		if(!body || !body.rgInventory || !body.rgDescriptions || !body.rgCurrency) {
			return callback(new Error("Malformed response"));
		}

		data = (data || []).concat(mergeWithDescriptions(body.rgInventory, body.rgDescriptions, contextid)).concat(mergeWithDescriptions(body.rgCurrency, body.rgDescriptions, contextid));
		if(body.more) {
			this.loadPartnerInventory(appid, contextid, callback, data, body.more_start);
		} else {
			callback(null, data);
		}
	}.bind(this));
};

function mergeWithDescriptions(items, descriptions, contextid) {
	return Object.keys(items).map(function(id) {
		var item = items[id];
		var description = descriptions[item.classid + '_' + (item.instanceid || '0')];
		for (var key in description) {
			item[key] = description[key];
		}
		// add contextid because Steam is retarded
		item.contextid = contextid;
		return item;
	});
}

TradeOffer.prototype.send = function(message, token, callback) {
	if(this.id) {
		return makeAnError(new Error("This offer has already been sent"), callback);
	}

	message = message || '';

	if(typeof token !== 'string') {
		callback = token;
		token = null;
	}

	var offerdata = {
		"newversion": true,
		"version": 4,
		"me": {
			"assets": this.itemsToGive.map(function(item) {
				return {
					"appid": item.appid,
					"contextid": item.contextid,
					"amount": item.amount || 1,
					"assetid": item.assetid
				};
			}),
			"currency": [], // TODO
			"ready": false
		},
		"them": {
			"assets": this.itemsToReceive.map(function(item) {
				return {
					"appid": item.appid,
					"contextid": item.contextid,
					"amount": item.amount || 1,
					"assetid": item.assetid
				};
			}),
			"currency": [],
			"ready": false
		}
	};

	var params = {};
	if(token) {
		params.trade_offer_access_token = token;
	}

	this._request.post('https://steamcommunity.com/tradeoffer/new/send', {
		"headers": {
			"referer": "https://steamcommunity.com/tradeoffer/new/?partner=" + this.partner.accountid + (token ? "&token=" + token : '')
		},
		"json": true,
		"form": {
			"sessionid": this._community.getSessionID(),
			"serverid": 1,
			"partner": this.partner.toString(),
			"tradeoffermessage": message,
			"json_tradeoffer": JSON.stringify(offerdata),
			"captcha": '',
			"trade_offer_create_params": JSON.stringify(params)
		}
	}, function(err, response, body) {
		if(err || response.statusCode != 200) {
			return makeAnError(err || new Error("HTTP error " + response.statusCode), callback);
		}

		if(body && body.strError) {
			return makeAnError(new Error(body.strError));
		}

		if(body && body.tradeofferid) {
			this.id = body.tradeofferid;
			this.message = message;
			this.state = ETradeOfferState.Active;
			this.created = new Date();
			this.updated = new Date();
			this.expires = new Date(Date.now() + 1209600000);
		}

		if(body && body.needs_email_confirmation) {
			this.state = ETradeOfferState.EmailPending;
		}

		if(!callback) {
			return;
		}

		if(body && body.needs_email_confirmation) {
			callback(null, 'pending');
		} else if(body && body.tradeofferid) {
			callback(null, 'sent');
		} else {
			callback(new Error("Unknown response"));
		}
	}.bind(this));
};

TradeOffer.prototype.cancel = function(callback) {
	if(!this.id) {
		return makeAnError(new Error("Cannot cancel or decline an unsent offer"), callback);
	}

	if(this.state != ETradeOfferState.Active) {
		return makeAnError(new Error("Offer #" + this.id + " is not active, so it may not be cancelled or declined"), callback);
	}

	this._manager._apiCall('POST', this.isOurOffer ? 'CancelTradeOffer' : 'DeclineTradeOffer', 1, {"tradeofferid": this.id}, function(err, body) {
		if(err) {
			makeAnError(err, callback);
		}

		this.updated = new Date();

		if(callback) {
			callback();
		}
	}.bind(this));
};

TradeOffer.prototype.decline = function(callback) {
	// Alias of cancel
	this.cancel(callback);
};

TradeOffer.prototype.accept = function(callback) {
	if(!this.id) {
		return makeAnError(new Error("Cannot accept an unsent offer"), callback);
	}

	if(this.state != ETradeOfferState.Active) {
		return makeAnError(new Error("Offer #" + this.id + " is not active, so it may not be accepted"), callback);
	}

	if(this.isOurOffer) {
		return makeAnError(new Error("Cannot accept our own offer #" + this.id), callback);
	}

	this._request.post('https://steamcommunity.com/tradeoffer/' + this.id + '/accept', {
		"headers": {
			"referer": 'https://steamcommunity.com/tradeoffer/' + this.id + '/'
		},
		"json": true,
		"form": {
			"sessionid": this._community.getSessionID(),
			"serverid": 1,
			"tradeofferid": this.id,
			"partner": this.partner.toString(),
			"captcha": ""
		}
	}, function(err, response, body) {
		if(err || response.statusCode != 200) {
			return makeAnError(err || new Error("HTTP error " + response.statusCode), callback);
		}

		if(body && body.strError) {
			return makeAnError(new Error(body.strError), callback);
		}

		if(body && body.tradeid) {
			this.updated = new Date();
		}

		if(!callback) {
			return;
		}

		if(body && body.needs_email_confirmation) {
			callback(null, 'pending');
		} else if(body && body.tradeid) {
			this.state = ETradeOfferState.Accepted;
			this.tradeid = body.tradeid;
			callback(null, 'accepted');
		} else {
			callback(new Error("Unknown response"));
		}
	}.bind(this));
};

TradeOffer.prototype.getReceivedItems = function(callback) {
	if(!this.id) {
		return makeAnError(new Error("Cannot request received items on an unsent offer"), callback);
	}

	if(this.state != ETradeOfferState.Accepted) {
		return makeAnError(new Error("Offer #" + this.id + " is not accepted, cannot request received items"), callback);
	}

	if(!this.tradeID) {
		return makeAnError(new Error("Offer #" + this.id + " is accepted, but does not have a trade ID"), callback);
	}

	// TODO
};

function makeAnError(error, callback) {
	if(callback) {
		callback(error);
	}
}
<|endoftext|>