<commit_before>Package.describe({
  name: 'jagi:astronomy-validators',
  version: '0.8.3',
  summary: 'Validators for Meteor Astronomy',
  git: 'https://github.com/jagi/meteor-astronomy-validators.git'
});

Package.onUse(function(api) {
  api.versionsFrom('1.1.0.2');

  api.use('jagi:astronomy@0.9.0');
  api.use('jagi:reactive-map@0.1.0');
  api.use('underscore');
  api.use('ui');

  api.imply('jagi:astronomy');

  // Module.
  api.addFiles('lib/module/global.js', ['client', 'server']);
  api.addFiles('lib/module/utils.js', ['client', 'server']);
  api.addFiles('lib/module/error.js', ['client', 'server']);
  api.addFiles('lib/module/validator.js', ['client', 'server']);
  api.addFiles('lib/module/init_module.js', ['client', 'server']);
  api.addFiles('lib/module/init_class.js', ['client', 'server']);
  api.addFiles('lib/module/init_instance.js', ['client', 'server']);
  api.addFiles('lib/module/module.js', ['client', 'server']);

  // Validators.
  api.addFiles('lib/validators/and.js', ['client', 'server']);
  api.addFiles('lib/validators/or.js', ['client', 'server']);

  api.addFiles('lib/validators/is_string.js', ['client', 'server']);
  api.addFiles('lib/validators/is_number.js', ['client', 'server']);
  api.addFiles('lib/validators/is_array.js', ['client', 'server']);
  api.addFiles('lib/validators/is_object.js', ['client', 'server']);
  api.addFiles('lib/validators/is_date.js', ['client', 'server']);
  api.addFiles('lib/validators/is_null.js', ['client', 'server']);
  api.addFiles('lib/validators/is_not_null.js', ['client', 'server']);
  api.addFiles('lib/validators/is_email.js', ['client', 'server']);

  api.addFiles('lib/validators/min_length.js', ['client', 'server']);
  api.addFiles('lib/validators/max_length.js', ['client', 'server']);
  api.addFiles('lib/validators/greater_than.js', ['client', 'server']);
  api.addFiles('lib/validators/greater_than_or_equal.js', ['client', 'server']);
  api.addFiles('lib/validators/less_than.js', ['client', 'server']);
  api.addFiles('lib/validators/less_than_or_equal.js', ['client', 'server']);
  api.addFiles('lib/validators/has_property.js', ['client', 'server']);

  api.addFiles('lib/validators/equal.js', ['client', 'server']);
  api.addFiles('lib/validators/equal_to.js', ['client', 'server']);
  api.addFiles('lib/validators/regexp.js', ['client', 'server']);
  api.addFiles('lib/validators/choice.js', ['client', 'server']);
  api.addFiles('lib/validators/unique.js', ['client', 'server']);

  api.export(['Validators'], ['client', 'server']);
});
<commit_msg>Update version to 0.8.4<commit_after>Package.describe({
  name: 'jagi:astronomy-validators',
  version: '0.8.4',
  summary: 'Validators for Meteor Astronomy',
  git: 'https://github.com/jagi/meteor-astronomy-validators.git'
});

Package.onUse(function(api) {
  api.versionsFrom('1.1.0.2');

  api.use('jagi:astronomy@0.9.0');
  api.use('jagi:reactive-map@0.1.0');
  api.use('underscore');
  api.use('ui');

  api.imply('jagi:astronomy');

  // Module.
  api.addFiles('lib/module/global.js', ['client', 'server']);
  api.addFiles('lib/module/utils.js', ['client', 'server']);
  api.addFiles('lib/module/error.js', ['client', 'server']);
  api.addFiles('lib/module/validator.js', ['client', 'server']);
  api.addFiles('lib/module/init_module.js', ['client', 'server']);
  api.addFiles('lib/module/init_class.js', ['client', 'server']);
  api.addFiles('lib/module/init_instance.js', ['client', 'server']);
  api.addFiles('lib/module/module.js', ['client', 'server']);

  // Validators.
  api.addFiles('lib/validators/and.js', ['client', 'server']);
  api.addFiles('lib/validators/or.js', ['client', 'server']);

  api.addFiles('lib/validators/is_string.js', ['client', 'server']);
  api.addFiles('lib/validators/is_number.js', ['client', 'server']);
  api.addFiles('lib/validators/is_array.js', ['client', 'server']);
  api.addFiles('lib/validators/is_object.js', ['client', 'server']);
  api.addFiles('lib/validators/is_date.js', ['client', 'server']);
  api.addFiles('lib/validators/is_null.js', ['client', 'server']);
  api.addFiles('lib/validators/is_not_null.js', ['client', 'server']);
  api.addFiles('lib/validators/is_email.js', ['client', 'server']);

  api.addFiles('lib/validators/min_length.js', ['client', 'server']);
  api.addFiles('lib/validators/max_length.js', ['client', 'server']);
  api.addFiles('lib/validators/greater_than.js', ['client', 'server']);
  api.addFiles('lib/validators/greater_than_or_equal.js', ['client', 'server']);
  api.addFiles('lib/validators/less_than.js', ['client', 'server']);
  api.addFiles('lib/validators/less_than_or_equal.js', ['client', 'server']);
  api.addFiles('lib/validators/has_property.js', ['client', 'server']);

  api.addFiles('lib/validators/equal.js', ['client', 'server']);
  api.addFiles('lib/validators/equal_to.js', ['client', 'server']);
  api.addFiles('lib/validators/regexp.js', ['client', 'server']);
  api.addFiles('lib/validators/choice.js', ['client', 'server']);
  api.addFiles('lib/validators/unique.js', ['client', 'server']);

  api.export(['Validators'], ['client', 'server']);
});
<|endoftext|>


<commit_before>Package.describe({
  summary: "Adds EJSON.minify and EJSON.maxify");

Package.on_use(function (api) {
  // TODO: remove underscore deps _.each (used once)
  api.use(['underscore', 'ejson'], ['client', 'server']);
  api.imply('ejson');

  api.add_files('ejson.minimax.js', ['client', 'server']);
});

Package.on_test(function (api) {
  api.use('ejson-minimax', ['client', 'server']);
  api.use('test-helpers', 'client');
  api.use(['tinytest', 'underscore', 'ejson']);

  api.add_files('ejson.minimax.tests.js', ['client', 'server']);

});
<commit_msg>Missed a curly brace<commit_after>Package.describe({
  summary: "Adds EJSON.minify and EJSON.maxify"});

Package.on_use(function (api) {
  // TODO: remove underscore deps _.each (used once)
  api.use(['underscore', 'ejson'], ['client', 'server']);
  api.imply('ejson');

  api.add_files('ejson.minimax.js', ['client', 'server']);
});

Package.on_test(function (api) {
  api.use('ejson-minimax', ['client', 'server']);
  api.use('test-helpers', 'client');
  api.use(['tinytest', 'underscore', 'ejson']);

  api.add_files('ejson.minimax.tests.js', ['client', 'server']);

});
<|endoftext|>


<commit_before>Template.ionTab.events({
  'click': function (event, template) {
    if (template.data.path) {
      Session.set('currentTab', template.data.path);
    }

    // If the tab's content is being rendered inside of a ionNavView
    // we don't want to slide it in when switching tabs
    IonNavigation.skipTransitions = true;
  }
});

Template.ionTab.helpers({
  url: function () {
    if (this.href) {
      return this.href;
    }

    if (this.path) {
      return Router.routes[this.path].path(Template.parentData(1));
    }
  },

  isActive: function () {
    if (this.path && this.path === Session.get('currentTab')) {
      return 'active';
    }
  },

  activeIcon: function () {
    if (this.iconOn) {
      return this.iconOn;
    } else {
      return this.icon;
    }
  },

  defaultIcon: function () {
    if (this.iconOff) {
      return this.iconOff;
    } else {
      return this.icon;
    }
  }
});
<commit_msg>active tab tied to route. fixes #18<commit_after>Template.ionTab.events({
  'click': function (event, template) {
    // If the tab's content is being rendered inside of a ionNavView
    // we don't want to slide it in when switching tabs
    IonNavigation.skipTransitions = true;
  }
});

Template.ionTab.helpers({
  url: function () {
    if (this.href) {
      return this.href;
    }

    if (this.path) {
      return Router.routes[this.path].path(Template.parentData(1));
    }
  },

  isActive: function () {
    // reactive data source
    var currentPath = Router.current().route.path();

    if(this.href && this.href === currentPath){
      return 'active';
    }

    if (this.path && Router.routes[this.path].path(Template.parentData(1)) === currentPath) {
      return 'active';
    }
  },

  activeIcon: function () {
    if (this.iconOn) {
      return this.iconOn;
    } else {
      return this.icon;
    }
  },

  defaultIcon: function () {
    if (this.iconOff) {
      return this.iconOff;
    } else {
      return this.icon;
    }
  }
});
<|endoftext|>


<commit_before>/* global Package */
Package.describe({
    name: 'socialize:messaging',
    summary: 'A social messaging package',
    version: '1.2.0',
    git: 'https://github.com/copleykj/socialize-messaging.git',
});

Package.onUse(function _(api) {
    api.versionsFrom('1.3');

    api.use([
        'check',
        'socialize:user-presence@1.0.1',
        'socialize:linkable-model@1.0.3',
        'reywood:publish-composite@1.6.0',
    ]);

    api.mainModule('server.js', 'server');
    api.mainModule('common.js', 'client');
});
<commit_msg>bump publish-composite<commit_after>/* global Package */
Package.describe({
    name: 'socialize:messaging',
    summary: 'A social messaging package',
    version: '1.2.0',
    git: 'https://github.com/copleykj/socialize-messaging.git',
});

Package.onUse(function _(api) {
    api.versionsFrom('1.3');

    api.use([
        'check',
        'socialize:user-presence@1.0.1',
        'socialize:linkable-model@1.0.3',
        'reywood:publish-composite@1.7.3',
    ]);

    api.mainModule('server.js', 'server');
    api.mainModule('common.js', 'client');
});
<|endoftext|>


<commit_before>Package.describe({
  name: 'thebakery:ipgeocoder',
  version: '0.1.0',
  // Brief, one-line summary of the package.
  summary: 'Geocode IP addresses using Maxmind IP database',
  // URL to the Git repository containing the source code for this package.
  git: 'https://github.com/thebakeryio/meteor-ipgeocoder',
  // By default, Meteor will default to using README.md for documentation.
  // To avoid submitting documentation, set this field to null.
  documentation: 'README.md'
});

Package.onUse(function(api) {
  api.versionsFrom('1.1.0.2');
  api.addFiles(['lib/patch.js', 'ipgeocoder.js'], 'server');

  api.export('IPGeocoder');
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.use('thebakery:ipgeocoder');
  api.addFiles('ipgeocoder-tests.js');
});

Npm.depends({
  'maxmind-db-reader': '0.1.1'
});<commit_msg>bump up the version<commit_after>Package.describe({
  name: 'thebakery:ipgeocoder',
  version: '0.1.1',
  // Brief, one-line summary of the package.
  summary: 'Geocode IP addresses using Maxmind IP database',
  // URL to the Git repository containing the source code for this package.
  git: 'https://github.com/thebakeryio/meteor-ipgeocoder',
  // By default, Meteor will default to using README.md for documentation.
  // To avoid submitting documentation, set this field to null.
  documentation: 'README.md'
});

Package.onUse(function(api) {
  api.versionsFrom('1.1.0.2');
  api.addFiles(['lib/patch.js', 'ipgeocoder.js'], 'server');

  api.export('IPGeocoder');
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.use('thebakery:ipgeocoder');
  api.addFiles('ipgeocoder-tests.js');
});

Npm.depends({
  'maxmind-db-reader': '0.1.1'
});<|endoftext|>


<commit_before>// package metadata file for Meteor.js

/* jshint strict:false */
/* global Package:true */

Package.describe({
  name: 'twbs:bootstrap',  // http://atmospherejs.com/twbs/bootstrap
  summary: 'The most popular front-end framework for developing responsive, mobile first projects on the web.',
  version: '3.3.5',
  git: 'https://github.com/twbs/bootstrap.git'
});

Package.onUse(function (api) {
  api.versionsFrom('METEOR@1.0');
  api.use('jquery', 'client');
  api.addFiles([
    'dist/fonts/glyphicons-halflings-regular.eot',
    'dist/fonts/glyphicons-halflings-regular.svg',
    'dist/fonts/glyphicons-halflings-regular.ttf',
    'dist/fonts/glyphicons-halflings-regular.woff',
    'dist/fonts/glyphicons-halflings-regular.woff2',
    'dist/css/bootstrap.css',
    'dist/js/bootstrap.js'
  ], 'client');
});
<commit_msg>Add support for Meteor 1.2<commit_after>// package metadata file for Meteor.js

/* jshint strict:false */
/* global Package:true */

Package.describe({
  name: 'twbs:bootstrap',  // http://atmospherejs.com/twbs/bootstrap
  summary: 'The most popular front-end framework for developing responsive, mobile first projects on the web.',
  version: '3.3.5',
  git: 'https://github.com/twbs/bootstrap.git'
});

Package.onUse(function (api) {
  api.versionsFrom('METEOR@1.0');
  api.use('jquery', 'client');
  api.addFiles([
    'dist/fonts/glyphicons-halflings-regular.eot',
    'dist/fonts/glyphicons-halflings-regular.svg',
    'dist/fonts/glyphicons-halflings-regular.ttf',
    'dist/fonts/glyphicons-halflings-regular.woff',
    'dist/fonts/glyphicons-halflings-regular.woff2'
  ], 'client', { isAsset: true });
  api.addFiles([
    'dist/css/bootstrap.css',
    'dist/js/bootstrap.js'
  ], 'client');
});
<|endoftext|>


<commit_before>Package.describe({
  name: 'mike:mocha',
  summary: "Run mocha tests in the browser",
  version: "0.6.0",
  debugOnly: true,
  git: "https://github.com/mad-eye/meteor-mocha-web"
});

Npm.depends({
  mocha: "1.17.1",
  mkdirp: "0.5.0"
});

Package.on_use(function (api, where) {
  api.use(['underscore@1.0.3'], ['client', 'server']);
  api.use(['velocity:core@0.6.0-rc.5'], "server");
  api.use(['velocity:html-reporter@0.5.0'], "client");
  api.use('practicalmeteor:chai@2.1.0_1');

  api.use(['templating@1.0.6'], "client");
  api.use(['velocity:shim@0.1.0'], ["client", "server"]);
  api.use(['mike:mocha-core@0.1.0'], ["client", "server"]);

  api.add_files(["reporter.js", "server.js"], "server");
  api.add_files(["client.html", "mocha.js", "reporter.js", "client.js"], "client");

  api.add_files(["sample-tests/client.js","sample-tests/server.js"], "server", {isAsset: true});
  api.export("MochaWeb", ["client", "server"]);
});
<commit_msg>version bump<commit_after>Package.describe({
  name: 'mike:mocha',
  summary: "Run mocha tests in the browser",
  version: "0.6.1",
  debugOnly: true,
  git: "https://github.com/mad-eye/meteor-mocha-web"
});

Npm.depends({
  mocha: "1.17.1",
  mkdirp: "0.5.0"
});

Package.on_use(function (api, where) {
  api.use(['underscore@1.0.3'], ['client', 'server']);
  api.use(['velocity:core@0.6.0-rc.5'], "server");
  api.use(['velocity:html-reporter@0.5.0'], "client");
  api.use('practicalmeteor:chai@2.1.0_1');

  api.use(['templating@1.0.6'], "client");
  api.use(['velocity:shim@0.1.0'], ["client", "server"]);
  api.use(['mike:mocha-core@0.1.0'], ["client", "server"]);

  api.add_files(["reporter.js", "server.js"], "server");
  api.add_files(["client.html", "mocha.js", "reporter.js", "client.js"], "client");

  api.add_files(["sample-tests/client.js","sample-tests/server.js"], "server", {isAsset: true});
  api.export("MochaWeb", ["client", "server"]);
});
<|endoftext|>


<commit_before>Package.describe({
    summary: "Meteor sign up and sign in templates core package.",
    version: "0.9.15",
    name: "splendido:accounts-templates-core",
    git: "https://github.com/splendido/accounts-templates-core.git",
});

Package.on_use(function(api) {
    api.versionsFrom("METEOR@0.9.2.2");

    api.use([
        "accounts-base",
        "check",
        "underscore",
        "iron:router",
    ], ["client", "server"]);

    api.use([
        "blaze",
        "reactive-dict",
        "sha",
    ], "client");

    api.imply([
        "accounts-base",
        "softwarerero:accounts-t9n@1.0.0",
        "iron:router@0.9.4",
    ], ["client", "server"]);

    api.imply([
        "templating",
    ], ["client"]);

    api.add_files([
        "lib/core.js",
        "lib/server.js",
        "lib/methods.js",
    ], ["server"]);

    api.add_files([
        "lib/utils.js",
        "lib/core.js",
        "lib/field.js",
        "lib/client.js",
        "lib/at_error.js",
        "lib/at_form.js",
        "lib/at_input.js",
        "lib/at_oauth.js",
        "lib/at_pwd_form.js",
        "lib/at_pwd_form_btn.js",
        "lib/at_pwd_link.js",
        "lib/at_result.js",
        "lib/at_sep.js",
        "lib/at_signin_link.js",
        "lib/at_signup_link.js",
        "lib/at_social.js",
        "lib/at_terms_link.js",
        "lib/at_title.js",
        "lib/methods.js",
    ], ["client"]);

    api.export([
        "AccountsTemplates",
    ], ["client", "server"]);
});

Package.on_test(function(api) {
    api.use("splendido:accounts-templates-core@0.9.15");
    api.use([
        //"softwarerero:accounts-t9n@1.0.0",
        //"iron:router@0.9.3",
    ], ["client", "server"]);

    api.use([
        'accounts-password',
        'tinytest',
        'test-helpers'
    ], ['client', 'server']);

    api.add_files([
        "tests/tests.js",
    ], ["client", "server"]);
});
<commit_msg>patch release - Bump to version 0.9.16<commit_after>Package.describe({
    summary: "Meteor sign up and sign in templates core package.",
    version: "0.9.16",
    name: "splendido:accounts-templates-core",
    git: "https://github.com/splendido/accounts-templates-core.git",
});

Package.on_use(function(api) {
    api.versionsFrom("METEOR@0.9.2.2");

    api.use([
        "accounts-base",
        "check",
        "underscore",
        "iron:router",
    ], ["client", "server"]);

    api.use([
        "blaze",
        "reactive-dict",
        "sha",
    ], "client");

    api.imply([
        "accounts-base",
        "softwarerero:accounts-t9n@1.0.0",
        "iron:router@0.9.4",
    ], ["client", "server"]);

    api.imply([
        "templating",
    ], ["client"]);

    api.add_files([
        "lib/core.js",
        "lib/server.js",
        "lib/methods.js",
    ], ["server"]);

    api.add_files([
        "lib/utils.js",
        "lib/core.js",
        "lib/field.js",
        "lib/client.js",
        "lib/at_error.js",
        "lib/at_form.js",
        "lib/at_input.js",
        "lib/at_oauth.js",
        "lib/at_pwd_form.js",
        "lib/at_pwd_form_btn.js",
        "lib/at_pwd_link.js",
        "lib/at_result.js",
        "lib/at_sep.js",
        "lib/at_signin_link.js",
        "lib/at_signup_link.js",
        "lib/at_social.js",
        "lib/at_terms_link.js",
        "lib/at_title.js",
        "lib/methods.js",
    ], ["client"]);

    api.export([
        "AccountsTemplates",
    ], ["client", "server"]);
});

Package.on_test(function(api) {
    api.use("splendido:accounts-templates-core@0.9.16");
    api.use([
        //"softwarerero:accounts-t9n@1.0.0",
        //"iron:router@0.9.3",
    ], ["client", "server"]);

    api.use([
        'accounts-password',
        'tinytest',
        'test-helpers'
    ], ['client', 'server']);

    api.add_files([
        "tests/tests.js",
    ], ["client", "server"]);
});
<|endoftext|>


<commit_before>Package.describe({
    "name": "kurounin:pagination",
    "summary": "Meteor pagination done right. Usable in ReactJS or Blaze templates.",
    "version": "1.0.13",
    "git": "https://github.com/Kurounin/Pagination.git"
});

Package.onUse(function (api) {
    api.versionsFrom("METEOR@1.2.1");
    api.use([
        "meteor-base",
        "check",
        "underscore",
        "mongo",
        "tmeasday:publish-counts@0.7.3"
    ]);

    api.addFiles([
        "server/pagination.js"
    ], "server");

    api.use([
        "reactive-var",
        "reactive-dict"
    ], "client");

    api.addFiles([
        "client/pagination.js"
    ], "client");
});<commit_msg>updated package.js to ES6<commit_after>Package.describe({
  name: 'kurounin:pagination',
  summary: 'Meteor pagination done right. Usable in ReactJS or Blaze templates.',
  version: '1.0.13',
  git: 'https://github.com/Kurounin/Pagination.git',
  documentation: 'README.md',
});

Package.onUse((api) => {
  api.versionsFrom('METEOR@1.2.1');
  api.use([
    'ecmascript',
    'meteor-base',
    'check',
    'underscore',
    'mongo',
    'tmeasday:publish-counts@0.7.3',
  ]);

  api.addFiles([
    'server/pagination.js',
  ], 'server');

  api.use([
    'reactive-var',
    'reactive-dict',
  ], 'client');

  api.addFiles([
    'client/pagination.js',
  ], 'client');
});
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { MENU } from '../identifiers.js';
import FontIcon from '../font_icon/FontIcon.js';

const factory = () => {
  class MenuItem extends Component {
    static propTypes = {
      caption: PropTypes.string,
      children: PropTypes.any,
      className: PropTypes.string,
      disabled: PropTypes.bool,
      icon: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.element,
      ]),
      onClick: PropTypes.func,
      selected: PropTypes.bool,
      shortcut: PropTypes.string,
      theme: PropTypes.shape({
        caption: PropTypes.string,
        disabled: PropTypes.string,
        icon: PropTypes.string,
        menuItem: PropTypes.string,
        selected: PropTypes.string,
        shortcut: PropTypes.string,
      }),
    };

    static defaultProps = {
      className: '',
      disabled: false,
      selected: false,
    };

    handleClick = (event) => {
      if (this.props.onClick && !this.props.disabled) {
        this.props.onClick(event, this);
      }
    };

    render () {
      const { icon, caption, children, shortcut, selected, disabled, theme, ...others } = this.props;
      const className = classnames(theme.menuItem, {
        [theme.selected]: selected,
        [theme.disabled]: disabled,
      }, this.props.className);

      return (

          {icon ? <FontIcon value={icon} className={theme.icon} /> : null}
          {caption}
          {shortcut ? {shortcut} : null}
          {children}

      );
    }
  }

  return MenuItem;
};

const MenuItem = factory();
export default themr(MENU)(MenuItem);
export { factory as menuItemFactory };
export { MenuItem };
<commit_msg>Readability +1<commit_after>import React, { Component, PropTypes } from 'react';
import classnames from 'classnames';
import { themr } from 'react-css-themr';
import { MENU } from '../identifiers.js';
import FontIcon from '../font_icon/FontIcon.js';

const factory = () => {
  class MenuItem extends Component {
    static propTypes = {
      caption: PropTypes.string,
      children: PropTypes.any,
      className: PropTypes.string,
      disabled: PropTypes.bool,
      icon: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.element,
      ]),
      onClick: PropTypes.func,
      selected: PropTypes.bool,
      shortcut: PropTypes.string,
      theme: PropTypes.shape({
        caption: PropTypes.string,
        disabled: PropTypes.string,
        icon: PropTypes.string,
        menuItem: PropTypes.string,
        selected: PropTypes.string,
        shortcut: PropTypes.string,
      }),
    };

    static defaultProps = {
      className: '',
      disabled: false,
      selected: false,
    };

    handleClick = (event) => {
      if (this.props.onClick && !this.props.disabled) {
        this.props.onClick(event, this);
      }
    };

    render () {
      const {
        icon,
        caption,
        children,
        shortcut,
        selected,
        disabled,
        theme,
        ...others
      } = this.props;

      const className = classnames(
        theme.menuItem,
        {
          [theme.selected]: selected,
          [theme.disabled]: disabled,
        },
        this.props.className
      );

      return (

          {icon ? <FontIcon value={icon} className={theme.icon} /> : null}
          {caption}
          {shortcut ? {shortcut} : null}
          {children}

      );
    }
  }

  return MenuItem;
};

const MenuItem = factory();
export default themr(MENU)(MenuItem);
export { factory as menuItemFactory };
export { MenuItem };
<|endoftext|>


<commit_before>var redis = require('redis');
var async = require('async');

var Stratum = require('stratum-pool');

module.exports = function(logger){

    var poolConfigs = JSON.parse(process.env.pools);

    Object.keys(poolConfigs).forEach(function(coin) {
        SetupForPool(logger, poolConfigs[coin]);
    });

};

function SetupForPool(logger, poolOptions){

    var coin = poolOptions.coin.name;

    var processingConfig = poolOptions.shareProcessing.internal;

    if (!processingConfig.enabled) return;

    var logSystem = 'Payments';
    var logComponent = coin;
    var paytxfee;

    var daemon = new Stratum.daemon.interface([processingConfig.daemon]);
    daemon.once('online', function(){
        logger.debug(logSystem, logComponent, 'Connected to daemon for payment processing');

        daemon.cmd('validateaddress', [poolOptions.address], function(result){
            if (!result[0].response || !result[0].response.ismine){
                logger.error(logSystem, logComponent, 'Daemon does not own pool address - payment processing can not be done with this daemon');
            }
        });
        daemon.cmd('getinfo', [], function(result){
            if (!result[0].response || !result[0].response.paytxfee){
                paytxfee = 0;
                logger.error(logSystem, logComponent, 'Daemon does not have paytxfee property on getinfo method results - payment processing could be broken with this daemon');
                return;
            }
            paytxfee = result[0].response.paytxfee;
        });
    }).once('connectionFailed', function(error){
        logger.error(logSystem, logComponent, 'Failed to connect to daemon for payment processing: ' + JSON.stringify(error));
    }).on('error', function(error){
        logger.error(logSystem, logComponent);
    }).init();

    var redisClient;

    var connectToRedis = function(){
        var reconnectTimeout;
        redisClient = redis.createClient(processingConfig.redis.port, processingConfig.redis.host);
        redisClient.on('ready', function(){
            clearTimeout(reconnectTimeout);
            logger.debug(logSystem, logComponent, 'Successfully connected to redis database');
        }).on('error', function(err){
                paymentLogger.error('redis', 'Redis client had an error: ' + JSON.stringify(err))
        }).on('end', function(){
            logger.error(logSystem, logComponent, 'Connection to redis database as been ended');
            logger.warning(logSystem, logComponent, 'Trying reconnection to redis in 3 seconds...');
            reconnectTimeout = setTimeout(function(){
                connectToRedis();
            }, 3000);
        });
    };
    connectToRedis();

    var processPayments = function(){
        async.waterfall([

            /* Call redis to get an array of rounds - which are coinbase transactions and block heights from submitted
               blocks. */
            function(callback){

                redisClient.smembers(coin + '_blocksPending', function(error, results){

                    if (error){
                        logger.error(logSystem, logComponent, 'Could get blocks from redis ' + JSON.stringify(error));
                        callback('Check finished - redis error for getting blocks');
                        return;
                    }
                    if (results.length === 0){
                        callback('Check finished - no pending blocks in redis');
                        return;
                    }

                    var rounds = results.map(function(r){
                        var details = r.split(':');
                        return {
                            category: details[0].category,
                            txHash: details[0],
                            height: details[1],
                            reward: details[2],
                            serialized: r
                        };
                    });

                    callback(null, rounds);
                });
            },

            /* Does a batch rpc call to daemon with all the transaction hashes to see if they are confirmed yet.
               It also adds the block reward amount to the round object - which the daemon gives also gives us. */
            function(rounds, callback){

                var batchRPCcommand = rounds.map(function(r){
                    return ['gettransaction', [r.txHash]];
                });

                daemon.batchCmd(batchRPCcommand, function(error, txDetails){

                    if (error || !txDetails){
                        callback('Check finished - daemon rpc error with batch gettransactions ' + JSON.stringify(error));
                        return;
                    }

                    txDetails = txDetails.filter(function(tx){
                        if (tx.error || !tx.result){
                            logger.error(logSystem, logComponent, 'error with requesting transaction from block daemon: ' + JSON.stringify(tx));
                            return false;
                        }
                        return true;
                    });

                    var magnitude;

                    rounds = rounds.filter(function(r){
                        var tx = txDetails.filter(function(tx){return tx.result.txid === r.txHash})[0];

                        if (!tx){
                            logger.error(logSystem, logComponent, 'daemon did not give us back a transaction that we asked for: ' + r.txHash);
                            return;
                        }

                        r.category = tx.result.details[0].category;

                        if (r.category === 'generate'){
                            r.amount = tx.result.amount;

                            var roundMagnitude = r.reward / r.amount;
                            if (!magnitude){
                                magnitude = roundMagnitude;

                                if (roundMagnitude % 10 !== 0)
                                    logger.error(logSystem, logComponent, 'Satosihis in coin is not divisible by 10 which is very odd');
                            }
                            else if (magnitude != roundMagnitude){
                                logger.error(logSystem, logComponent, 'Magnitude in a round was different than in another round. HUGE PROBLEM.');
                            }
                            return true;
                        }
                        else if (r.category === 'orphan')
                            return true;

                    });

                    if (rounds.length === 0){
                        callback('Check finished - no confirmed or orphaned blocks found');
                    }
                    else{
                        callback(null, rounds, magnitude);
                    }
                });
            },

            /* Does a batch redis call to get shares contributed to each round. Then calculates the reward
               amount owned to each miner for each round. */
            function(rounds, magnitude, callback){

                var shareLookups = rounds.map(function(r){
                    return ['hgetall', coin + '_shares:round' + r.height]
                });

                redisClient.multi(shareLookups).exec(function(error, allWorkerShares){
                    if (error){
                        callback('Check finished - redis error with multi get rounds share')
                        return;
                    }

                    var orphanMergeCommands = [];
                    var workerRewards = {};

                    rounds.forEach(function(round, i){
                        var workerShares = allWorkerShares[i];

                        if (round.category === 'orphan'){
                            Object.keys(workerShares).forEach(function(worker){
                                orphanMergeCommands.push(['hincrby', coin + '_shares:roundCurrent', worker, workerShares[worker]]);
                            });
                        }
                        else if (round.category === 'generate'){

                            var reward = round.reward * (1 - processingConfig.feePercent);

                            var totalShares = Object.keys(workerShares).reduce(function(p, c){
                                return p + parseInt(workerShares[c])
                            }, 0);

                            for (var worker in workerShares){
                                var percent = parseInt(workerShares[worker]) / totalShares;
                                var workerRewardTotal = Math.floor(reward * percent);
                                if (!(worker in workerRewards)) workerRewards[worker] = 0;
                                workerRewards[worker] += workerRewardTotal;
                            }
                        }
                    });

                    callback(null, rounds, magnitude, workerRewards, orphanMergeCommands);
                });
            },

            /* Does a batch call to redis to get worker existing balances from coin_balances*/
            function(rounds, magnitude, workerRewards, orphanMergeCommands, callback){

                var workers = Object.keys(workerRewards);

                redisClient.hmget([coin + '_balances'].concat(workers), function(error, results){
                    if (error && workers.length !== 0){
                        callback('Check finished - redis error with multi get balances ' + JSON.stringify(error));
                        return;
                    }

                    var workerBalances = {};

                    for (var i = 0; i < workers.length; i++){
                        workerBalances[workers[i]] = (parseInt(results[i]) || 0);
                    }

                    callback(null, rounds, magnitude, workerRewards, orphanMergeCommands, workerBalances);
                });

            },

            /* Calculate if any payments are ready to be sent and trigger them sending
             Get balance different for each address and pass it along as object of latest balances such as
             {worker1: balance1, worker2, balance2}
             when deciding the sent balance, it the difference should be -1*amount they had in db,
             if not sending the balance, the differnce should be +(the amount they earned this round)
             */
            function(rounds, magnitude, workerRewards, orphanMergeCommands, workerBalances, callback){

                //number of satoshis in a single coin unit - this can be different for coins so we calculate it :)

                daemon.cmd('getbalance', [''], function(results){

                    var totalBalance = results[0].response * magnitude;
                    var toBePaid = 0;
                    var workerPayments = {};

                    var balanceUpdateCommands = [];
                    var workerPayoutsCommand = [];

                    for (var worker in workerRewards){
                        workerPayments[worker] = ((workerPayments[worker] || 0) + workerRewards[worker]);
                    }
                    for (var worker in workerBalances){
                        workerPayments[worker] = ((workerPayments[worker] || 0) + workerBalances[worker]);
                    }

                    if (Object.keys(workerPayments).length > 0){
                        var coinPrecision = magnitude.toString().length - 1;
                        for (var worker in workerPayments){
                            if (workerPayments[worker] < processingConfig.minimumPayment * magnitude){
                                balanceUpdateCommands.push(['hincrby', coin + '_balances', worker, workerRewards[worker]]);
                                delete workerPayments[worker];
                            }
                            else{
                                if (workerBalances[worker] !== 0){
                                    balanceUpdateCommands.push(['hincrby', coin + '_balances', worker, -1 * workerBalances[worker]]);
                                }
                                var rewardInPrecision = (workerRewards[worker] / magnitude).toFixed(coinPrecision);
                                workerPayoutsCommand.push(['hincrbyfloat', coin + '_payouts', worker, rewardInPrecision]);
                                toBePaid += workerPayments[worker];
                            }
                        }

                    }

                    var feeAmountToBeCollected = parseFloat((toBePaid / (1 - processingConfig.feePercent) * processingConfig.feePercent).toFixed(coinPrecision));
                    var txFee = Object.keys(workerPayments).length * paytxfee;
                    var balanceLeftOver = totalBalance - toBePaid - feeAmountToBeCollected - txFee;
                    var minReserveSatoshis = processingConfig.minimumReserve * magnitude;
                    if (balanceLeftOver < minReserveSatoshis){

                        callback('Check finished - payments would wipe out minimum reserve, tried to pay out ' + toBePaid +
                            ' but only have ' + totalBalance + '. Left over balance would be ' + balanceLeftOver +
                            ', needs to be at least ' + minReserveSatoshis);
                        return;
                    }

                    var movePendingCommands = [];
                    var roundsToDelete = [];
                    rounds.forEach(function(r){
                        var destinationSet = r.category === 'orphan' ? '_blocksOrphaned' : '_blocksConfirmed';
                        movePendingCommands.push(['smove', coin + '_blocksPending', coin + destinationSet, r.serialized]);
                        roundsToDelete.push(coin + '_shares:round' + r.height)
                    });

                    var finalRedisCommands = [];

                    if (movePendingCommands.length > 0)
                        finalRedisCommands = finalRedisCommands.concat(movePendingCommands);

                    if (orphanMergeCommands.length > 0)
                        finalRedisCommands = finalRedisCommands.concat(orphanMergeCommands);

                    if (balanceUpdateCommands.length > 0)
                        finalRedisCommands = finalRedisCommands.concat(balanceUpdateCommands);

                    if (workerPayoutsCommand.length > 0)
                        finalRedisCommands = finalRedisCommands.concat(workerPayoutsCommand);

                    if (roundsToDelete.length > 0)
                        finalRedisCommands.push(['del'].concat(roundsToDelete));

                    if (toBePaid !== 0)
                        finalRedisCommands.push(['hincrbyfloat', coin + '_stats', 'totalPaid', (toBePaid / magnitude).toFixed(coinPrecision)]);

                    callback(null, magnitude, workerPayments, finalRedisCommands);

                });
            },

            function(magnitude, workerPayments, finalRedisCommands, callback){

                //This does the final all-or-nothing atom transaction if block deamon sent payments
                var finalizeRedisTx = function(){
                    redisClient.multi(finalRedisCommands).exec(function(error, results){
                        if (error){
                            callback('Check finished - error with final redis commands for cleaning up ' + JSON.stringify(error));
                            return;
                        }
                        callback(null, 'Payments processing performed an interval');
                    });
                };

                if (Object.keys(workerPayments).length === 0){
                    finalizeRedisTx();
                }
                else{

                    var coinPrecision = magnitude.toString().length - 1;
                    var addressAmounts = {};
                    var totalAmountUnits = 0;
                    for (var address in workerPayments){
                        var coinUnits = parseFloat((workerPayments[address] / magnitude).toFixed(coinPrecision));
                        addressAmounts[address] = coinUnits;
                        totalAmountUnits += coinUnits;
                    }

                    logger.debug(logSystem, logComponent, 'Payments about to be sent to: ' + JSON.stringify(addressAmounts));
                    daemon.cmd('sendmany', ['', addressAmounts], function(results){
                        if (results[0].error){
                            callback('Check finished - error with sendmany ' + JSON.stringify(results[0].error));
                            return;
                        }
                        finalizeRedisTx();
                        var totalWorkers = Object.keys(workerPayments).length;
                        logger.debug(logSystem, logComponent, 'Payments sent, a total of ' + totalAmountUnits +
                            ' was sent to ' + totalWorkers + ' miners');
                        var feeAmountUnits = parseFloat((totalAmountUnits / (1 - processingConfig.feePercent) * processingConfig.feePercent).toFixed(coinPrecision));
                        var txFee = totalWorkers * paytxfee;
                        var collectableFee = feeAmountUnits - txFee;
                        daemon.cmd('move', ['', processingConfig.feeCollectAccount, collectableFee], function(results){
                            if (results[0].error){
                                callback('Check finished - error with move ' + JSON.stringify(results[0].error));
                                return;
                            }
                            logger.debug(logSystem, logComponent, feeAmountUnits + ' collected as fee');
                        });
                    });
                }
            }
        ], function(error, result){
            if (error)
                logger.debug(logSystem, logComponent, error);

            else{
                logger.debug(logSystem, logComponent, result);
                withdrawalProfit();
            }
        });
    };

    var withdrawalProfit = function(){

        if (!processingConfig.feeWithdrawalThreshold) return;

        daemon.cmd('getbalance', [processingConfig.feeCollectAccount], function(results){

            var withdrawalAmount = results[0].response - paytxfee;

            if (withdrawalAmount < processingConfig.feeWithdrawalThreshold){
                logger.debug(logSystem, logComponent, 'Not enough profit to withdrawal yet');
            }
            else{

                var withdrawal = {};
                withdrawal[processingConfig.feeReceiveAddress] = withdrawalAmount;

                daemon.cmd('sendmany', [processingConfig.feeCollectAccount, withdrawal], function(results){
                    if (results[0].error){
                        logger.debug(logSystem, logComponent, 'Withdrawal profit finished - error with sendmany ' + JSON.stringify(results[0].error));
                        return;
                    }
                    logger.debug(logSystem, logComponent, 'Profit sent, a total of ' + withdrawalAmount +
                        ' was sent to ' + processingConfig.feeReceiveAddress);
                });
            }

        });

    };

    setInterval(processPayments, processingConfig.paymentInterval * 1000);
    setTimeout(processPayments, 100);

};<commit_msg>fix fee calculations and withdrawals once again<commit_after>var redis = require('redis');
var async = require('async');

var Stratum = require('stratum-pool');

module.exports = function(logger){

    var poolConfigs = JSON.parse(process.env.pools);

    Object.keys(poolConfigs).forEach(function(coin) {
        SetupForPool(logger, poolConfigs[coin]);
    });

};

function SetupForPool(logger, poolOptions){

    var coin = poolOptions.coin.name;

    var processingConfig = poolOptions.shareProcessing.internal;

    if (!processingConfig.enabled) return;

    var logSystem = 'Payments';
    var logComponent = coin;

    var daemon = new Stratum.daemon.interface([processingConfig.daemon]);
    daemon.once('online', function(){
        logger.debug(logSystem, logComponent, 'Connected to daemon for payment processing');

        daemon.cmd('validateaddress', [poolOptions.address], function(result){
            if (!result[0].response || !result[0].response.ismine){
                logger.error(logSystem, logComponent, 'Daemon does not own pool address - payment processing can not be done with this daemon');
            }
        });
    }).once('connectionFailed', function(error){
        logger.error(logSystem, logComponent, 'Failed to connect to daemon for payment processing: ' + JSON.stringify(error));
    }).on('error', function(error){
        logger.error(logSystem, logComponent);
    }).init();

    var redisClient;

    var connectToRedis = function(){
        var reconnectTimeout;
        redisClient = redis.createClient(processingConfig.redis.port, processingConfig.redis.host);
        redisClient.on('ready', function(){
            clearTimeout(reconnectTimeout);
            logger.debug(logSystem, logComponent, 'Successfully connected to redis database');
        }).on('error', function(err){
                paymentLogger.error('redis', 'Redis client had an error: ' + JSON.stringify(err))
        }).on('end', function(){
            logger.error(logSystem, logComponent, 'Connection to redis database as been ended');
            logger.warning(logSystem, logComponent, 'Trying reconnection to redis in 3 seconds...');
            reconnectTimeout = setTimeout(function(){
                connectToRedis();
            }, 3000);
        });
    };
    connectToRedis();

    var processPayments = function(){
        async.waterfall([

            /* Call redis to get an array of rounds - which are coinbase transactions and block heights from submitted
               blocks. */
            function(callback){

                redisClient.smembers(coin + '_blocksPending', function(error, results){

                    if (error){
                        logger.error(logSystem, logComponent, 'Could get blocks from redis ' + JSON.stringify(error));
                        callback('Check finished - redis error for getting blocks');
                        return;
                    }
                    if (results.length === 0){
                        callback('Check finished - no pending blocks in redis');
                        return;
                    }

                    var rounds = results.map(function(r){
                        var details = r.split(':');
                        return {
                            category: details[0].category,
                            txHash: details[0],
                            height: details[1],
                            reward: details[2],
                            serialized: r
                        };
                    });

                    callback(null, rounds);
                });
            },

            /* Does a batch rpc call to daemon with all the transaction hashes to see if they are confirmed yet.
               It also adds the block reward amount to the round object - which the daemon gives also gives us. */
            function(rounds, callback){

                var batchRPCcommand = rounds.map(function(r){
                    return ['gettransaction', [r.txHash]];
                });

                daemon.batchCmd(batchRPCcommand, function(error, txDetails){

                    if (error || !txDetails){
                        callback('Check finished - daemon rpc error with batch gettransactions ' + JSON.stringify(error));
                        return;
                    }

                    txDetails = txDetails.filter(function(tx){
                        if (tx.error || !tx.result){
                            logger.error(logSystem, logComponent, 'error with requesting transaction from block daemon: ' + JSON.stringify(tx));
                            return false;
                        }
                        return true;
                    });

                    var magnitude;

                    rounds = rounds.filter(function(r){
                        var tx = txDetails.filter(function(tx){return tx.result.txid === r.txHash})[0];

                        if (!tx){
                            logger.error(logSystem, logComponent, 'daemon did not give us back a transaction that we asked for: ' + r.txHash);
                            return;
                        }

                        r.category = tx.result.details[0].category;

                        if (r.category === 'generate'){
                            r.amount = tx.result.amount;

                            var roundMagnitude = r.reward / r.amount;
                            if (!magnitude){
                                magnitude = roundMagnitude;

                                if (roundMagnitude % 10 !== 0)
                                    logger.error(logSystem, logComponent, 'Satosihis in coin is not divisible by 10 which is very odd');
                            }
                            else if (magnitude != roundMagnitude){
                                logger.error(logSystem, logComponent, 'Magnitude in a round was different than in another round. HUGE PROBLEM.');
                            }
                            return true;
                        }
                        else if (r.category === 'orphan')
                            return true;

                    });

                    if (rounds.length === 0){
                        callback('Check finished - no confirmed or orphaned blocks found');
                    }
                    else{
                        callback(null, rounds, magnitude);
                    }
                });
            },

            /* Does a batch redis call to get shares contributed to each round. Then calculates the reward
               amount owned to each miner for each round. */
            function(rounds, magnitude, callback){

                var shareLookups = rounds.map(function(r){
                    return ['hgetall', coin + '_shares:round' + r.height]
                });

                redisClient.multi(shareLookups).exec(function(error, allWorkerShares){
                    if (error){
                        callback('Check finished - redis error with multi get rounds share')
                        return;
                    }

                    var orphanMergeCommands = [];
                    var workerRewards = {};

                    rounds.forEach(function(round, i){
                        var workerShares = allWorkerShares[i];

                        if (round.category === 'orphan'){
                            Object.keys(workerShares).forEach(function(worker){
                                orphanMergeCommands.push(['hincrby', coin + '_shares:roundCurrent', worker, workerShares[worker]]);
                            });
                        }
                        else if (round.category === 'generate'){

                            var reward = round.reward * (1 - processingConfig.feePercent);

                            var totalShares = Object.keys(workerShares).reduce(function(p, c){
                                return p + parseInt(workerShares[c])
                            }, 0);

                            for (var worker in workerShares){
                                var percent = parseInt(workerShares[worker]) / totalShares;
                                var workerRewardTotal = Math.floor(reward * percent);
                                if (!(worker in workerRewards)) workerRewards[worker] = 0;
                                workerRewards[worker] += workerRewardTotal;
                            }
                        }
                    });

                    callback(null, rounds, magnitude, workerRewards, orphanMergeCommands);
                });
            },

            /* Does a batch call to redis to get worker existing balances from coin_balances*/
            function(rounds, magnitude, workerRewards, orphanMergeCommands, callback){

                var workers = Object.keys(workerRewards);

                redisClient.hmget([coin + '_balances'].concat(workers), function(error, results){
                    if (error && workers.length !== 0){
                        callback('Check finished - redis error with multi get balances ' + JSON.stringify(error));
                        return;
                    }

                    var workerBalances = {};

                    for (var i = 0; i < workers.length; i++){
                        workerBalances[workers[i]] = (parseInt(results[i]) || 0);
                    }

                    callback(null, rounds, magnitude, workerRewards, orphanMergeCommands, workerBalances);
                });

            },

            /* Calculate if any payments are ready to be sent and trigger them sending
             Get balance different for each address and pass it along as object of latest balances such as
             {worker1: balance1, worker2, balance2}
             when deciding the sent balance, it the difference should be -1*amount they had in db,
             if not sending the balance, the differnce should be +(the amount they earned this round)
             */
            function(rounds, magnitude, workerRewards, orphanMergeCommands, workerBalances, callback){

                //number of satoshis in a single coin unit - this can be different for coins so we calculate it :)

                daemon.cmd('getbalance', [''], function(results){

                    var totalBalance = results[0].response * magnitude;
                    var toBePaid = 0;
                    var workerPayments = {};

                    var balanceUpdateCommands = [];
                    var workerPayoutsCommand = [];

                    for (var worker in workerRewards){
                        workerPayments[worker] = ((workerPayments[worker] || 0) + workerRewards[worker]);
                    }
                    for (var worker in workerBalances){
                        workerPayments[worker] = ((workerPayments[worker] || 0) + workerBalances[worker]);
                    }

                    if (Object.keys(workerPayments).length > 0){
                        var coinPrecision = magnitude.toString().length - 1;
                        for (var worker in workerPayments){
                            if (workerPayments[worker] < processingConfig.minimumPayment * magnitude){
                                balanceUpdateCommands.push(['hincrby', coin + '_balances', worker, workerRewards[worker]]);
                                delete workerPayments[worker];
                            }
                            else{
                                if (workerBalances[worker] !== 0){
                                    balanceUpdateCommands.push(['hincrby', coin + '_balances', worker, -1 * workerBalances[worker]]);
                                }
                                var rewardInPrecision = (workerRewards[worker] / magnitude).toFixed(coinPrecision);
                                workerPayoutsCommand.push(['hincrbyfloat', coin + '_payouts', worker, rewardInPrecision]);
                                toBePaid += workerPayments[worker];
                            }
                        }

                    }

                    // txfee included in feeAmountToBeCollected
                    var feeAmountToBeCollected = parseFloat((toBePaid / (1 - processingConfig.feePercent) * processingConfig.feePercent).toFixed(coinPrecision));
                    var balanceLeftOver = totalBalance - toBePaid - feeAmountToBeCollected;
                    var minReserveSatoshis = processingConfig.minimumReserve * magnitude;
                    if (balanceLeftOver < minReserveSatoshis){

                        callback('Check finished - payments would wipe out minimum reserve, tried to pay out ' + toBePaid +
                            ' and collect ' + feeAmountToBeCollected + ' as fees' +
                            ' but only have ' + totalBalance + '. Left over balance would be ' + balanceLeftOver +
                            ', needs to be at least ' + minReserveSatoshis);
                        return;
                    }

                    var movePendingCommands = [];
                    var roundsToDelete = [];
                    rounds.forEach(function(r){
                        var destinationSet = r.category === 'orphan' ? '_blocksOrphaned' : '_blocksConfirmed';
                        movePendingCommands.push(['smove', coin + '_blocksPending', coin + destinationSet, r.serialized]);
                        roundsToDelete.push(coin + '_shares:round' + r.height)
                    });

                    var finalRedisCommands = [];

                    if (movePendingCommands.length > 0)
                        finalRedisCommands = finalRedisCommands.concat(movePendingCommands);

                    if (orphanMergeCommands.length > 0)
                        finalRedisCommands = finalRedisCommands.concat(orphanMergeCommands);

                    if (balanceUpdateCommands.length > 0)
                        finalRedisCommands = finalRedisCommands.concat(balanceUpdateCommands);

                    if (workerPayoutsCommand.length > 0)
                        finalRedisCommands = finalRedisCommands.concat(workerPayoutsCommand);

                    if (roundsToDelete.length > 0)
                        finalRedisCommands.push(['del'].concat(roundsToDelete));

                    if (toBePaid !== 0)
                        finalRedisCommands.push(['hincrbyfloat', coin + '_stats', 'totalPaid', (toBePaid / magnitude).toFixed(coinPrecision)]);

                    callback(null, magnitude, results[0].response, workerPayments, finalRedisCommands);

                });
            },

            function(magnitude, balanceBefore, workerPayments, finalRedisCommands, callback){

                //This does the final all-or-nothing atom transaction if block deamon sent payments
                var finalizeRedisTx = function(){
                    redisClient.multi(finalRedisCommands).exec(function(error, results){
                        if (error){
                            callback('Check finished - error with final redis commands for cleaning up ' + JSON.stringify(error));
                            return;
                        }
                        callback(null, 'Payments processing performed an interval');
                    });
                };

                if (Object.keys(workerPayments).length === 0){
                    finalizeRedisTx();
                }
                else{

                    var coinPrecision = magnitude.toString().length - 1;
                    var addressAmounts = {};
                    var totalAmountUnits = 0;
                    for (var address in workerPayments){
                        var coinUnits = parseFloat((workerPayments[address] / magnitude).toFixed(coinPrecision));
                        addressAmounts[address] = coinUnits;
                        totalAmountUnits += coinUnits;
                    }

                    logger.debug(logSystem, logComponent, 'Payments about to be sent to: ' + JSON.stringify(addressAmounts));
                    daemon.cmd('sendmany', ['', addressAmounts], function(results){
                        if (results[0].error){
                            callback('Check finished - error with sendmany ' + JSON.stringify(results[0].error));
                            return;
                        }
                        finalizeRedisTx();
                        var totalWorkers = Object.keys(workerPayments).length;
                        logger.debug(logSystem, logComponent, 'Payments sent, a total of ' + totalAmountUnits + ' ' + poolOptions.coin.symbol +
                            ' was sent to ' + totalWorkers + ' miners');
                        setTimeout(function() { // not sure if we need some time to let daemon update the wallet balance
                            daemon.cmd('getbalance', [''], function(results){
                                var balanceDiff = balanceBefore - results[0].response;
                                var txFee = balanceDiff - totalAmountUnits;
                                var feeAmountUnits = parseFloat((totalAmountUnits / (1 - processingConfig.feePercent) * processingConfig.feePercent).toFixed(coinPrecision));
                                var poolFees = feeAmountUnits - txFee;
                                daemon.cmd('move', ['', processingConfig.feeCollectAccount, poolFees], function(results){
                                    if (results[0].error){
                                        callback('Check finished - error with move ' + JSON.stringify(results[0].error));
                                        return;
                                    }
                                    callback(null, poolFees + ' ' + poolOptions.coin.symbol + ' collected as pool fee');
                                });
                            });
                        }, 1000);
                    });
                }
            }
        ], function(error, result){
            if (error)
                logger.debug(logSystem, logComponent, error);

            else{
                logger.debug(logSystem, logComponent, result);
                // not sure if we need some time to let daemon update the wallet balance
                setTimeout(withdrawalProfit, 1000);
            }
        });
    };

    var withdrawalProfit = function(){

        if (!processingConfig.feeWithdrawalThreshold) return;

        logger.debug(logSystem, logComponent, 'Trying to withdrawal profit');
        daemon.cmd('getbalance', [processingConfig.feeCollectAccount], function(results){

            // We have to pay some tx fee here too but maybe we shoudn't really care about it too much as long as fee is less
            // then minimumReserve value. Because in this case even if feeCollectAccount account will have negative balance
            // total wallet balance will be positive and feeCollectAccount account will be refilled during next payment processing.
            // But to be as much accurate as we can we use getinfo command to retrieve minimum tx fee (paytxfee).
            daemon.cmd('getinfo', [], function(result){

                var paytxfee;
                if (!result[0].response || !result[0].response.paytxfee){
                    logger.error(logSystem, logComponent, 'Daemon does not have paytxfee property on getinfo method results - withdrawal processing could be broken with this daemon');
                    paytxfee = 0;
                } else {
                    paytxfee = result[0].response.paytxfee;
                }

                var withdrawalAmount = results[0].response - paytxfee;

                if (withdrawalAmount < processingConfig.feeWithdrawalThreshold){
                    logger.debug(logSystem, logComponent, 'Not enough profit to withdrawal yet');
                }
                else{

                    var withdrawal = {};
                    withdrawal[processingConfig.feeReceiveAddress] = withdrawalAmount;

                    daemon.cmd('sendmany', [processingConfig.feeCollectAccount, withdrawal], function(results){
                        if (results[0].error){
                            logger.debug(logSystem, logComponent, 'Withdrawal profit finished - error with sendmany ' + JSON.stringify(results[0].error));
                            return;
                        }
                        logger.debug(logSystem, logComponent, 'Profit sent, a total of ' + withdrawalAmount + ' ' + poolOptions.coin.symbol +
                            ' was sent to ' + processingConfig.feeReceiveAddress);
                    });
                }
            });

        });

    };

    setInterval(processPayments, processingConfig.paymentInterval * 1000);
    setTimeout(processPayments, 100);

};<|endoftext|>


<commit_before>Package.describe({
    name: 'gcampax:dropbox-oauth',
    summary: "Login service for dropbox accounts",
    version: '1.0.1',
    git: 'https://github.com/gcampax/meteor-dropbox-oauth'
});

Package.onUse(function(api) {
    api.versionsFrom('0.9.4');
    api.use('oauth', ['client', 'server']);
    api.use('oauth2', ['client', 'server']);
    api.use('http', ['client', 'server']);
    api.use('templating', 'client');
    api.use('service-configuration', ['client', 'server']);

    api.export('DropboxOAuth');

    api.addFiles(['dropbox_configure.html', 'dropbox_configure.js'], 'client');
    api.addFiles('dropbox_server.js', 'server');
    api.addFiles('dropbox_client.js', 'client');
});
<commit_msg>Use Meteor 1.2 dependancies<commit_after>Package.describe({
    name: 'gcampax:dropbox-oauth',
    summary: "Login service for dropbox accounts",
    version: '1.0.1',
    git: 'https://github.com/gcampax/meteor-dropbox-oauth'
});

Package.onUse(function(api) {
    api.versionsFrom('1.2');
    api.use('oauth', ['client', 'server']);
    api.use('oauth2', ['client', 'server']);
    api.use('http', ['client', 'server']);
    api.use('templating', 'client');
    api.use('service-configuration', ['client', 'server']);

    api.export('DropboxOAuth');

    api.addFiles(['dropbox_configure.html', 'dropbox_configure.js'], 'client');
    api.addFiles('dropbox_server.js', 'server');
    api.addFiles('dropbox_client.js', 'client');
});
<|endoftext|>


<commit_before>import React, { PureComponent } from 'react';
import ReactSelect from 'react-select';
import PropTypes from 'prop-types';
import omit from 'lodash.omit';
import { IconChevronDownSmallOutline, IconWarningBadgedSmallFilled } from '@teamleader/ui-icons';
import Box, { omitBoxProps, pickBoxProps } from '../box';
import { Button } from '../button';
import { TextSmall } from '../typography';
import { colors } from './constants';
import theme from './theme.css';
import cx from 'classnames';

class Select extends PureComponent {
  getClearIndicatorStyles = base => {
    const { inverse } = this.props;

    return {
      ...base,
      color: inverse ? colors.TEAL_LIGHTEST : colors.TEAL_DARK,
      '&:hover': {
        color: inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
      },
      cursor: 'pointer',
      svg: {
        height: '14px',
        width: '14px',
      },
    };
  };

  getControlStyles = (base, { isDisabled, isFocused }) => {
    const { inverse, size } = this.props;

    const commonStyles = {
      ...base,
      minHeight: size === 'small' ? '30px' : size === 'medium' ? '36px' : '48px',
    };

    if (inverse) {
      return {
        ...commonStyles,
        backgroundColor: isDisabled ? colors.TEAL_DARK : colors.TEAL,
        '&:hover': {
          borderColor: colors.TEAL_LIGHT,
        },
        borderColor: isFocused ? colors.TEAL_LIGHT : isDisabled ? colors.TEAL_DARK : colors.TEAL,
        boxShadow: isFocused ? `0 0 0 1px ${colors.TEAL_LIGHT}` : 'none',
      };
    }

    return {
      ...commonStyles,
      backgroundColor: isDisabled ? colors.NEUTRAL : colors.NEUTRAL_LIGHTEST,
      '&:hover': {
        borderColor: colors.NEUTRAL_DARKEST,
      },
      borderColor: isFocused ? colors.NEUTRAL_DARKEST : isDisabled ? colors.NEUTRAL : colors.NEUTRAL_DARK,
      boxShadow: isFocused ? `0 0 0 1px ${colors.NEUTRAL_DARKEST}` : 'none',
    };
  };

  getGroupStyles = base => {
    const { inverse } = this.props;

    return {
      ...base,
      borderBottomColor: inverse ? colors.TEAL_LIGHT : colors.NEUTRAL,
      borderBottomStyle: 'solid',
      borderBottomWidth: '1px',
      '&:last-child': {
        borderWidth: 0,
      },
    };
  };

  getGroupHeadingStyles = base => {
    const { inverse } = this.props;

    return {
      ...base,
      color: inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
      fontSize: '12px',
      fontWeight: '700',
      letterSpacing: '0.6px',
      padding: '0 6px',
    };
  };

  getIndicatorSeparatorStyles = (base, { isDisabled }) => {
    const commonStyles = {
      ...base,
      marginTop: 0,
      marginBottom: 0,
    };

    if (this.props.inverse) {
      return {
        ...commonStyles,
        backgroundColor: isDisabled ? colors.TEAL_DARK : colors.TEAL,
      };
    }

    return {
      ...commonStyles,
      backgroundColor: isDisabled ? colors.NEUTRAL : colors.NEUTRAL_DARK,
    };
  };

  getInput = base => {
    const { size, value } = this.props;

    return {
      ...base,
      marginLeft: value && value.length === 0 && size !== 'large' ? '6px' : '2px',
    };
  };

  getMenuStyles = base => ({
    ...base,
    backgroundColor: this.props.inverse ? colors.TEAL : colors.NEUTRAL_LIGHTEST,
  });

  getMultiValueStyles = base => {
    const { inverse } = this.props;

    return {
      ...base,
      borderColor: inverse ? colors.TEAL_DARK : colors.NEUTRAL,
      borderStyle: 'solid',
      borderWidth: '1px',
      borderRadius: '4px',
    };
  };

  getMultiValueLabelStyles = base => {
    const { inverse, size } = this.props;

    return {
      ...base,
      backgroundColor: inverse ? colors.TEAL_DARK : colors.NEUTRAL_LIGHT,
      borderRadius: 0,
      color: inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
      fontFamily: 'Inter-UI-Medium',
      fontSize: size === 'small' ? '12px' : '14px',
      lineHeight: size === 'small' ? '1' : '18px',
      padding: size === 'large' ? '9px' : '6px',
    };
  };

  getMultiValueRemoveStyles = base => {
    const { inverse } = this.props;

    return {
      ...base,
      backgroundColor: inverse ? colors.TEAL_DARK : colors.NEUTRAL_LIGHT,
      borderRadius: 0,
      color: inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
      '&:hover': {
        backgroundColor: inverse ? colors.TEAL_DARKEST : colors.NEUTRAL,
        color: inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
      },
      paddingLeft: '6px',
      paddingRight: '6px',
      transition: 'background-color .35s cubic-bezier(.4, 0, .2, 1)',
    };
  };

  getOptionStyles = (base, { isDisabled, isFocused, isSelected }) => {
    const commonStyles = {
      ...base,
      padding: '8px 12px',
    };

    if (this.props.inverse) {
      return {
        ...commonStyles,
        color: isDisabled ? colors.TEAL_LIGHT : isFocused ? colors.TEAL_DARK : colors.NEUTRAL_LIGHTEST,
        backgroundColor: isFocused ? colors.TEAL_LIGHT : isSelected ? colors.TEAL_DARK : colors.TEAL,
        '&:active': {
          backgroundColor: isDisabled ? colors.TEAL : colors.TEAL_DARK,
        },
      };
    }

    return {
      ...commonStyles,
      color: isDisabled ? colors.NEUTRAL_DARK : isSelected && !isFocused ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARK,
      backgroundColor: isFocused ? colors.NEUTRAL : isSelected ? colors.NEUTRAL_DARKEST : colors.NEUTRAL_LIGHTEST,
      '&:active': {
        backgroundColor: isDisabled ? colors.NEUTRAL_LIGHTEST : colors.NEUTRAL,
      },
    };
  };

  getPlaceholderStyles = (base, { isDisabled, isMulti }) => {
    const { inverse, size } = this.props;

    const commonStyles = {
      ...base,
      marginLeft: isMulti && size !== 'large' ? '6px' : '2px',
      marginRight: isMulti && size !== 'large' ? '6px' : '2px',
    };

    if (inverse) {
      return {
        ...commonStyles,
        color: isDisabled ? colors.TEAL : colors.TEAL_LIGHT,
      };
    }

    return {
      ...commonStyles,
      color: colors.NEUTRAL_DARKEST,
    };
  };

  getSingleValueStyles = base => ({
    ...base,
    color: this.props.inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
  });

  getValueContainerStyles = (base, { isMulti }) => {
    const { size } = this.props;

    return {
      ...base,
      padding: isMulti && size !== 'large' ? '0' : '0 4px',
    };
  };

  getStyles = () => ({
    clearIndicator: this.getClearIndicatorStyles,
    control: this.getControlStyles,
    group: this.getGroupStyles,
    groupHeading: this.getGroupHeadingStyles,
    indicatorSeparator: this.getIndicatorSeparatorStyles,
    input: this.getInput,
    menu: this.getMenuStyles,
    multiValue: this.getMultiValueStyles,
    multiValueLabel: this.getMultiValueLabelStyles,
    multiValueRemove: this.getMultiValueRemoveStyles,
    option: this.getOptionStyles,
    placeholder: this.getPlaceholderStyles,
    singleValue: this.getSingleValueStyles,
    valueContainer: this.getValueContainerStyles,
  });

  getDropDownIndicator = () => ({ isDisabled }) => {
    const { inverse, size } = this.props;

    return (
      <Button
        className={theme['dropdown-indicator']}
        disabled={isDisabled}
        icon={<IconChevronDownSmallOutline />}
        inverse={inverse}
        level={inverse ? 'outline' : 'secondary'}
        size={size}
      />
    );
  };

  renderHelpText() {
    const { helpText, inverse } = this.props;

    if (helpText) {
      return (
        <TextSmall color={inverse ? 'white' : 'neutral'} marginTop={1} soft>
          {helpText}
        </TextSmall>
      );
    }
  }

  renderValidationMessage() {
    return (
      <TextSmall className={theme['validation-text']} marginTop={2} display="flex">
        <Box element="span" className={theme['validation-icon']}>
          <IconWarningBadgedSmallFilled />
        </Box>
        <Box element="span" marginLeft={1}>
          {this.props.error}
        </Box>
      </TextSmall>
    );
  }

  render() {
    const { components, error, inverse, ...otherProps } = this.props;

    const boxProps = pickBoxProps(otherProps);
    const otherPropsWithoutBoxProps = omitBoxProps(otherProps);
    const restProps = omit(otherPropsWithoutBoxProps, ['size']);

    const wrapperClassnames = cx({
      [theme['has-error']]: error,
      [theme['is-inverse']]: inverse,
    });

    return (
      <Box className={wrapperClassnames} {...boxProps}>
        <ReactSelect
          className={theme['select']}
          components={{
            DropdownIndicator: this.getDropDownIndicator(),
            ...components,
          }}
          styles={this.getStyles()}
          {...restProps}
        />
        {error ? this.renderValidationMessage() : this.renderHelpText()}
      </Box>
    );
  }
}

Select.propTypes = {
  /** Override default components with your own. Pass an object with correct the key and its replacing component */
  components: PropTypes.object,
  /** The text string/element to use as error message below the input. */
  error: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
  /** The text string to use as help text below the input. */
  helpText: PropTypes.string,
  /** Boolean indicating whether the select should render as inverse. */
  inverse: PropTypes.bool,
  /** Size of the input element. */
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  /** Selected option value(s) */
  value: PropTypes.oneOfType([PropTypes.object, PropTypes.array, PropTypes.func]),
};

Select.defaultProps = {
  inverse: false,
  size: 'medium',
};

export default Select;
<commit_msg>Apply the correct input border color when an error occurred<commit_after>import React, { PureComponent } from 'react';
import ReactSelect from 'react-select';
import PropTypes from 'prop-types';
import omit from 'lodash.omit';
import { IconChevronDownSmallOutline, IconWarningBadgedSmallFilled } from '@teamleader/ui-icons';
import Box, { omitBoxProps, pickBoxProps } from '../box';
import { Button } from '../button';
import { TextSmall } from '../typography';
import { colors } from './constants';
import theme from './theme.css';
import cx from 'classnames';

class Select extends PureComponent {
  getClearIndicatorStyles = base => {
    const { inverse } = this.props;

    return {
      ...base,
      color: inverse ? colors.TEAL_LIGHTEST : colors.TEAL_DARK,
      '&:hover': {
        color: inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
      },
      cursor: 'pointer',
      svg: {
        height: '14px',
        width: '14px',
      },
    };
  };

  getControlStyles = (base, { isDisabled, isFocused }) => {
    const { error, inverse, size } = this.props;

    const commonStyles = {
      ...base,
      minHeight: size === 'small' ? '30px' : size === 'medium' ? '36px' : '48px',
    };

    if (inverse) {
      return {
        ...commonStyles,
        backgroundColor: isDisabled ? colors.TEAL_DARK : colors.TEAL,
        '&:hover': {
          borderColor: colors.TEAL_LIGHT,
        },
        borderColor: isFocused ? colors.TEAL_LIGHT : isDisabled ? colors.TEAL_DARK : colors.TEAL,
        boxShadow: isFocused ? `0 0 0 1px ${colors.TEAL_LIGHT}` : 'none',
      };
    }

    return {
      ...commonStyles,
      backgroundColor: isDisabled ? colors.NEUTRAL : colors.NEUTRAL_LIGHTEST,
      '&:hover': {
        borderColor: error ? colors.RUBY_DARK : colors.NEUTRAL_DARKEST,
      },
      borderColor: error
        ? colors.RUBY_DARK
        : isFocused
          ? colors.NEUTRAL_DARKEST
          : isDisabled
            ? colors.NEUTRAL
            : colors.NEUTRAL_DARK,
      boxShadow: error ? `0 0 0 1px ${colors.RUBY_DARK}` : isFocused ? `0 0 0 1px ${colors.NEUTRAL_DARKEST}` : 'none',
    };
  };

  getGroupStyles = base => {
    const { inverse } = this.props;

    return {
      ...base,
      borderBottomColor: inverse ? colors.TEAL_LIGHT : colors.NEUTRAL,
      borderBottomStyle: 'solid',
      borderBottomWidth: '1px',
      '&:last-child': {
        borderWidth: 0,
      },
    };
  };

  getGroupHeadingStyles = base => {
    const { inverse } = this.props;

    return {
      ...base,
      color: inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
      fontSize: '12px',
      fontWeight: '700',
      letterSpacing: '0.6px',
      padding: '0 6px',
    };
  };

  getIndicatorSeparatorStyles = (base, { isDisabled }) => {
    const commonStyles = {
      ...base,
      marginTop: 0,
      marginBottom: 0,
    };

    if (this.props.inverse) {
      return {
        ...commonStyles,
        backgroundColor: isDisabled ? colors.TEAL_DARK : colors.TEAL,
      };
    }

    return {
      ...commonStyles,
      backgroundColor: isDisabled ? colors.NEUTRAL : colors.NEUTRAL_DARK,
    };
  };

  getInput = base => {
    const { size, value } = this.props;

    return {
      ...base,
      marginLeft: value && value.length === 0 && size !== 'large' ? '6px' : '2px',
    };
  };

  getMenuStyles = base => ({
    ...base,
    backgroundColor: this.props.inverse ? colors.TEAL : colors.NEUTRAL_LIGHTEST,
  });

  getMultiValueStyles = base => {
    const { inverse } = this.props;

    return {
      ...base,
      borderColor: inverse ? colors.TEAL_DARK : colors.NEUTRAL,
      borderStyle: 'solid',
      borderWidth: '1px',
      borderRadius: '4px',
    };
  };

  getMultiValueLabelStyles = base => {
    const { inverse, size } = this.props;

    return {
      ...base,
      backgroundColor: inverse ? colors.TEAL_DARK : colors.NEUTRAL_LIGHT,
      borderRadius: 0,
      color: inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
      fontFamily: 'Inter-UI-Medium',
      fontSize: size === 'small' ? '12px' : '14px',
      lineHeight: size === 'small' ? '1' : '18px',
      padding: size === 'large' ? '9px' : '6px',
    };
  };

  getMultiValueRemoveStyles = base => {
    const { inverse } = this.props;

    return {
      ...base,
      backgroundColor: inverse ? colors.TEAL_DARK : colors.NEUTRAL_LIGHT,
      borderRadius: 0,
      color: inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
      '&:hover': {
        backgroundColor: inverse ? colors.TEAL_DARKEST : colors.NEUTRAL,
        color: inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
      },
      paddingLeft: '6px',
      paddingRight: '6px',
      transition: 'background-color .35s cubic-bezier(.4, 0, .2, 1)',
    };
  };

  getOptionStyles = (base, { isDisabled, isFocused, isSelected }) => {
    const commonStyles = {
      ...base,
      padding: '8px 12px',
    };

    if (this.props.inverse) {
      return {
        ...commonStyles,
        color: isDisabled ? colors.TEAL_LIGHT : isFocused ? colors.TEAL_DARK : colors.NEUTRAL_LIGHTEST,
        backgroundColor: isFocused ? colors.TEAL_LIGHT : isSelected ? colors.TEAL_DARK : colors.TEAL,
        '&:active': {
          backgroundColor: isDisabled ? colors.TEAL : colors.TEAL_DARK,
        },
      };
    }

    return {
      ...commonStyles,
      color: isDisabled ? colors.NEUTRAL_DARK : isSelected && !isFocused ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARK,
      backgroundColor: isFocused ? colors.NEUTRAL : isSelected ? colors.NEUTRAL_DARKEST : colors.NEUTRAL_LIGHTEST,
      '&:active': {
        backgroundColor: isDisabled ? colors.NEUTRAL_LIGHTEST : colors.NEUTRAL,
      },
    };
  };

  getPlaceholderStyles = (base, { isDisabled, isMulti }) => {
    const { inverse, size } = this.props;

    const commonStyles = {
      ...base,
      marginLeft: isMulti && size !== 'large' ? '6px' : '2px',
      marginRight: isMulti && size !== 'large' ? '6px' : '2px',
    };

    if (inverse) {
      return {
        ...commonStyles,
        color: isDisabled ? colors.TEAL : colors.TEAL_LIGHT,
      };
    }

    return {
      ...commonStyles,
      color: colors.NEUTRAL_DARKEST,
    };
  };

  getSingleValueStyles = base => ({
    ...base,
    color: this.props.inverse ? colors.NEUTRAL_LIGHTEST : colors.TEAL_DARKEST,
  });

  getValueContainerStyles = (base, { isMulti }) => {
    const { size } = this.props;

    return {
      ...base,
      padding: isMulti && size !== 'large' ? '0' : '0 4px',
    };
  };

  getStyles = () => ({
    clearIndicator: this.getClearIndicatorStyles,
    control: this.getControlStyles,
    group: this.getGroupStyles,
    groupHeading: this.getGroupHeadingStyles,
    indicatorSeparator: this.getIndicatorSeparatorStyles,
    input: this.getInput,
    menu: this.getMenuStyles,
    multiValue: this.getMultiValueStyles,
    multiValueLabel: this.getMultiValueLabelStyles,
    multiValueRemove: this.getMultiValueRemoveStyles,
    option: this.getOptionStyles,
    placeholder: this.getPlaceholderStyles,
    singleValue: this.getSingleValueStyles,
    valueContainer: this.getValueContainerStyles,
  });

  getDropDownIndicator = () => ({ isDisabled }) => {
    const { inverse, size } = this.props;

    return (
      <Button
        className={theme['dropdown-indicator']}
        disabled={isDisabled}
        icon={<IconChevronDownSmallOutline />}
        inverse={inverse}
        level={inverse ? 'outline' : 'secondary'}
        size={size}
      />
    );
  };

  renderHelpText() {
    const { helpText, inverse } = this.props;

    if (helpText) {
      return (
        <TextSmall color={inverse ? 'white' : 'neutral'} marginTop={1} soft>
          {helpText}
        </TextSmall>
      );
    }
  }

  renderValidationMessage() {
    return (
      <TextSmall className={theme['validation-text']} marginTop={2} display="flex">
        <Box element="span" className={theme['validation-icon']}>
          <IconWarningBadgedSmallFilled />
        </Box>
        <Box element="span" marginLeft={1}>
          {this.props.error}
        </Box>
      </TextSmall>
    );
  }

  render() {
    const { components, error, inverse, ...otherProps } = this.props;

    const boxProps = pickBoxProps(otherProps);
    const otherPropsWithoutBoxProps = omitBoxProps(otherProps);
    const restProps = omit(otherPropsWithoutBoxProps, ['size']);

    const wrapperClassnames = cx({
      [theme['has-error']]: error,
      [theme['is-inverse']]: inverse,
    });

    return (
      <Box className={wrapperClassnames} {...boxProps}>
        <ReactSelect
          className={theme['select']}
          components={{
            DropdownIndicator: this.getDropDownIndicator(),
            ...components,
          }}
          styles={this.getStyles()}
          {...restProps}
        />
        {error ? this.renderValidationMessage() : this.renderHelpText()}
      </Box>
    );
  }
}

Select.propTypes = {
  /** Override default components with your own. Pass an object with correct the key and its replacing component */
  components: PropTypes.object,
  /** The text string/element to use as error message below the input. */
  error: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
  /** The text string to use as help text below the input. */
  helpText: PropTypes.string,
  /** Boolean indicating whether the select should render as inverse. */
  inverse: PropTypes.bool,
  /** Size of the input element. */
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  /** Selected option value(s) */
  value: PropTypes.oneOfType([PropTypes.object, PropTypes.array, PropTypes.func]),
};

Select.defaultProps = {
  inverse: false,
  size: 'medium',
};

export default Select;
<|endoftext|>


<commit_before>Package.describe({
  name: 'ox2:temp-cordova',
  version: '0.1.0',
  // Brief, one-line summary of the package.
  summary: 'DO NOT USE',
  // URL to the Git repository containing the source code for this package.
  git: '',
  // By default, Meteor will default to using README.md for documentation.
  // To avoid submitting documentation, set this field to null.
  documentation: ''
});

var C = 'client';
var S = 'server';
var CS = [C, S];

Package.onUse(function(api) {
    api.versionsFrom('1.2.1');
    // Core
    api.use([
      'ecmascript'
    ]);
    // 3rd party
    api.use([

    ]);
    api.addFiles('lib/oo-temp-cordova.js', C);
});

Cordova.depends({
  "cordova-plugin-crosswalk-webview": "1.5.0",
  "phonegap-plugin-push": "1.5.3",
  "cordova-plugin-device": "1.1.1",
  "cordova-plugin-inappbrowser": "1.2.0",
  "cordova-plugin-splashscreen": "3.1.0",
  "org.cloudsky.cordovaplugins.zbar": "1.3.1",
});

Package.onTest(function(api) {
  api.use('ecmascript');
  api.use('tinytest');
  api.use('ox2:temp-cordova');
  api.addFiles('tests/package-tests.js');
});
<commit_msg>added camera plugin<commit_after>Package.describe({
  name: 'ox2:temp-cordova',
  version: '0.1.0',
  // Brief, one-line summary of the package.
  summary: 'DO NOT USE',
  // URL to the Git repository containing the source code for this package.
  git: '',
  // By default, Meteor will default to using README.md for documentation.
  // To avoid submitting documentation, set this field to null.
  documentation: ''
});

var C = 'client';
var S = 'server';
var CS = [C, S];

Package.onUse(function(api) {
    api.versionsFrom('1.2.1');
    // Core
    api.use([
      'ecmascript'
    ]);
    // 3rd party
    api.use([

    ]);
    api.addFiles('lib/oo-temp-cordova.js', C);
});

Cordova.depends({
  "cordova-plugin-crosswalk-webview": "1.5.0",
  "phonegap-plugin-push": "1.5.3",
  "cordova-plugin-device": "1.1.1",
  "cordova-plugin-inappbrowser": "1.2.0",
  "cordova-plugin-splashscreen": "3.1.0",
  "cordova-plugin-camera": "2.1.0",
  "org.cloudsky.cordovaplugins.zbar": "1.3.1",
});

Package.onTest(function(api) {
  api.use('ecmascript');
  api.use('tinytest');
  api.use('ox2:temp-cordova');
  api.addFiles('tests/package-tests.js');
});
<|endoftext|>


<commit_before>Package.describe({
  name: 'comerc:template-two-way-binding',
  version: '1.3.2',
  summary: 'Two-Way Binding for Blaze templates',
  git: 'https://github.com/comerc/meteor-template-two-way-binding',
  documentation: 'README.md'
});

Package.onUse(function (api) {
  // Have to stay on Meteor 1.2.1 to be compatible with all Meteor versions.
  api.versionsFrom('1.2.1');
  api.use([
    'templating',
    'blaze-html-templates',
    'aldeed:template-extension@4.0.0',
  ]);
  api.addFiles('template-two-way-binding.js', 'client');
  api.export('TemplateTwoWayBinding');
});
<commit_msg>Version 1.3.3<commit_after>Package.describe({
  name: 'comerc:template-two-way-binding',
  version: '1.3.3',
  summary: 'Two-Way Binding for Blaze templates',
  git: 'https://github.com/comerc/meteor-template-two-way-binding',
  documentation: 'README.md'
});

Package.onUse(function (api) {
  // Have to stay on Meteor 1.2.1 to be compatible with all Meteor versions.
  api.versionsFrom('1.3.2');
  api.use([
    'templating',
    'blaze-html-templates',
    'aldeed:template-extension@4.0.0', // TODO how to support METEOR@1.2.1
  ]);
  api.addFiles('template-two-way-binding.js', 'client');
  api.export('TemplateTwoWayBinding');
});
<|endoftext|>


<commit_before>Package.describe({
  name: "riffyn:autocomplete",
  summary: "Client/server autocompletion designed for Meteor's collections and reactivity",
  version: "0.4.10",
  git: "https://github.com/mizzao/meteor-autocomplete.git"
});

Package.onUse(function (api) {
  api.versionsFrom("0.9.4");

  api.use(['blaze', 'templating', 'jquery'], 'client');
  api.use(['coffeescript', 'underscore']); // both
  api.use(['mongo', 'ddp']);

  api.use("dandv:caret-position@2.1.0-3", 'client');

  // Our files
  api.addFiles([
    'autocomplete.css',
    'inputs.html',
    'autocomplete-client.coffee',
    'templates.coffee'
  ], 'client');

  api.addFiles([
    'autocomplete-server.coffee'
  ], 'server');

  api.export('Autocomplete', 'server');
  api.export('AutocompleteTest', {testOnly: true});
});

Package.onTest(function(api) {
  api.use("riffyn:autocomplete");

  api.use('coffeescript');
  api.use('mongo');
  api.use('tinytest');

  api.addFiles('tests/rule_tests.coffee', 'client');
  api.addFiles('tests/regex_tests.coffee', 'client');
  api.addFiles('tests/param_tests.coffee', 'client');
  api.addFiles('tests/security_tests.coffee');
});
<commit_msg>Bumped version number in the hope that will help track down problems in deployed version<commit_after>Package.describe({
  name: "riffyn:autocomplete",
  summary: "Client/server autocompletion designed for Meteor's collections and reactivity",
  version: "0.4.11",
  git: "https://github.com/mizzao/meteor-autocomplete.git"
});

Package.onUse(function (api) {
  api.versionsFrom("0.9.4");

  api.use(['blaze', 'templating', 'jquery'], 'client');
  api.use(['coffeescript', 'underscore']); // both
  api.use(['mongo', 'ddp']);

  api.use("dandv:caret-position@2.1.0-3", 'client');

  // Our files
  api.addFiles([
    'autocomplete.css',
    'inputs.html',
    'autocomplete-client.coffee',
    'templates.coffee'
  ], 'client');

  api.addFiles([
    'autocomplete-server.coffee'
  ], 'server');

  api.export('Autocomplete', 'server');
  api.export('AutocompleteTest', {testOnly: true});
});

Package.onTest(function(api) {
  api.use("riffyn:autocomplete");

  api.use('coffeescript');
  api.use('mongo');
  api.use('tinytest');

  api.addFiles('tests/rule_tests.coffee', 'client');
  api.addFiles('tests/regex_tests.coffee', 'client');
  api.addFiles('tests/param_tests.coffee', 'client');
  api.addFiles('tests/security_tests.coffee');
});
<|endoftext|>