<commit_before>//@author: Bohdan Mushkevych

conn = new Mongo('localhost:27017');
db = conn.getDB('scheduler');

// *** CLEAN ***
db.box_configuration.drop();

// *** CREATE ***
db.createCollection('box_configuration');
db.box_configuration.ensureIndex( { box_id : 1}, {unique: true} );

// *** Supervisor Settings ***
// Development environment
db.box_configuration.insert({'box_id': 'DEV',
    'process_list' : {
        'EventStreamGenerator' : {'state' : 'state_on', 'pid' : null},
        'SingleSessionWorker_00' : {'state' : 'state_on', 'pid' : null},
        'SiteHourlyAggregator' : {'state' : 'state_on', 'pid' : null},
        'SiteDailyAggregator' : {'state' : 'state_on', 'pid' : null},
        'GarbageCollectorWorker' : {'state' : 'state_on', 'pid' : null},
        'Scheduler' : {'state' : 'state_on', 'pid' : null}
    }});

db.box_configuration.insert({'box_id': 'QA',
    'process_list' : {
        'EventStreamGenerator' : {'state' : 'state_on', 'pid' : null},
        'SingleSessionWorker_00' : {'state' : 'state_on', 'pid' : null},
        'SiteHourlyAggregator' : {'state' : 'state_on', 'pid' : null},
        'SiteDailyAggregator' : {'state' : 'state_on', 'pid' : null},
        'SiteMonthlyAggregator' : {'state' : 'state_on', 'pid' : null},
        'SiteYearlyAggregator' : {'state' : 'state_on', 'pid' : null},
        'GarbageCollectorWorker' : {'state' : 'state_on', 'pid' : null},
        'Scheduler' : {'state' : 'state_on', 'pid' : null}
    }});
<commit_msg>Splitting mongo schema files<commit_after>//@author: Bohdan Mushkevych

conn = new Mongo('localhost:27017');
db = conn.getDB('scheduler');

// *** CLEAN ***
db.box_configuration.drop();

// *** CREATE ***
db.createCollection('box_configuration');
db.box_configuration.ensureIndex( { box_id : 1}, {unique: true} );

// *** Supervisor Settings ***
db.box_configuration.insert({'box_id': 'DEV',
    'process_list' : {
        'EventStreamGenerator' : {'state' : 'state_on', 'pid' : null},
        'SingleSessionWorker_00' : {'state' : 'state_on', 'pid' : null},
        'SiteHourlyAggregator' : {'state' : 'state_on', 'pid' : null},
        'SiteDailyAggregator' : {'state' : 'state_on', 'pid' : null},
        'GarbageCollectorWorker' : {'state' : 'state_on', 'pid' : null},
        'Scheduler' : {'state' : 'state_on', 'pid' : null}
    }});

db.box_configuration.insert({'box_id': 'QA',
    'process_list' : {
        'EventStreamGenerator' : {'state' : 'state_on', 'pid' : null},
        'SingleSessionWorker_00' : {'state' : 'state_on', 'pid' : null},
        'SiteHourlyAggregator' : {'state' : 'state_on', 'pid' : null},
        'SiteDailyAggregator' : {'state' : 'state_on', 'pid' : null},
        'SiteMonthlyAggregator' : {'state' : 'state_on', 'pid' : null},
        'SiteYearlyAggregator' : {'state' : 'state_on', 'pid' : null},
        'GarbageCollectorWorker' : {'state' : 'state_on', 'pid' : null},
        'Scheduler' : {'state' : 'state_on', 'pid' : null}
    }});
<|endoftext|>


<commit_before>export default {
    name: 'u-router-item',
    props: {
        href: String,
        to: [String, Object],
        replace: { type: Boolean, default: false },
        exact: { type: Boolean, default: false },
    },
    computed: {
        active() {
            if (this.to === undefined)
                return;

            if (!this.$router)
                return console.warn('[proto-ui] Cannot find vue router.');

            const current = this.$route;
            const location = this.$router.resolve(this.to).location;

            return this.exact ? location.path === current.path : current.path.startsWith(location.path);
        },
    },
    methods: {
        navigate() {
            if (this.href) {
                if (this.target === '_blank')
                    return window.open(this.href, this.target);
                else
                    return location.href = this.href;
            }

            if (this.to === undefined)
                return;

            if (!this.$router)
                return console.warn('[proto-ui] Cannot find vue router.');

            let cancel = false;
            this.$emit('before-navigate', {
                to: this.to,
                replace: this.replace,
                exact: this.exact,
                preventDefault: () => cancel = true,
            });
            if (cancel)
                return;

            const $router = this.$router;
            this.replace ? $router.replace(this.to) : $router.push(this.to);

            this.$emit('navigate', {
                to: this.to,
                replace: this.replace,
                exact: this.exact,
            });
        },
    },
};
<commit_msg>:bug: Add target prop<commit_after>export default {
    name: 'u-router-item',
    props: {
        href: String,
        target: { type: String, default: '_self' },
        to: [String, Object],
        replace: { type: Boolean, default: false },
        exact: { type: Boolean, default: false },
    },
    computed: {
        active() {
            if (this.to === undefined)
                return;

            if (!this.$router)
                return console.warn('[proto-ui] Cannot find vue router.');

            const current = this.$route;
            const location = this.$router.resolve(this.to).location;

            return this.exact ? location.path === current.path : current.path.startsWith(location.path);
        },
    },
    methods: {
        navigate() {
            if (this.href) {
                if (this.target === '_blank')
                    return window.open(this.href, this.target);
                else
                    return location.href = this.href;
            }

            if (this.to === undefined)
                return;

            if (!this.$router)
                return console.warn('[proto-ui] Cannot find vue router.');

            let cancel = false;
            this.$emit('before-navigate', {
                to: this.to,
                replace: this.replace,
                exact: this.exact,
                preventDefault: () => cancel = true,
            });
            if (cancel)
                return;

            const $router = this.$router;
            this.replace ? $router.replace(this.to) : $router.push(this.to);

            this.$emit('navigate', {
                to: this.to,
                replace: this.replace,
                exact: this.exact,
            });
        },
    },
};
<|endoftext|>


<commit_before>//==============================================================================
// RS_FollowerPassable.js
//==============================================================================

var Imported = Imported || {};
Imported.RS_FollowerPassable = true;

/*:
 * RS_FollowerPassable.js
 * @plugindesc If you are using this plugin, the player will be impossible
 * to pass other party members.
 *
 * @author biud436
 *
 * @param Enabled
 * @desc
 * @default true
 *
 * @param Separate Mode
 * @desc
 * @default false
 *
 * @help
 * =============================================================================
 * Plugin Command
 * =============================================================================
 *
 * FollowerPassable passable true
 * FollowerPassable SeparateMode true
 *
 * The following commands could use in separate mode only.
 *
 * FollowerPassable setOpacity index x
 * FollowerPassable setBlendMode index x
 * FollowerPassable setMoveSpeed index x
 * FollowerPassable setDirectionFix index x
 * FollowerPassable setTransparent index x
 *
 * =============================================================================
 * Change Log
 * =============================================================================
 * 2016.06.01 (v1.0.0) - First Release.
 * 2016.09.01 (v1.0.4) - Added Plugin Commands
 */

(function() {

  var parameters = PluginManager.parameters('RS_FollowerPassable');
  var passable = Boolean(parameters['Enabled'] === 'true');
  var isSeparate = Boolean(parameters['Separate Mode'] === 'true');

  var localKit = Object.assign(Object.create(
    {
      fpSendMessage: function (index, func, args) {
        var callFunc = $gamePlayer.followers().follower(index)[func];
        callFunc.apply(null, args);
      }
    }
  ));

  var KIT = new localKit();

  //============================================================================
  // Game_Player

  var alias_Game_Player_canPass = Game_Player.prototype.canPass;
  Game_Player.prototype.canPass = function(x, y, d) {
      var x2 = $gameMap.roundXWithDirection(x, d);
      var y2 = $gameMap.roundYWithDirection(y, d);
      if(this.isFollowerPassable(x2, y2) && passable) {
        return false;
      }
      return alias_Game_Player_canPass.call(this, x, y, d);
  }

  Game_Player.prototype.isFollowerPassable = function (x, y) {
      return this._followers.isFollowerPassable(x, y);
  };

  //============================================================================
  // Game_Follower

  var alias_Game_Follower_initialize = Game_Follower.prototype.initialize;
  Game_Follower.prototype.initialize = function(memberIndex) {
      alias_Game_Follower_initialize.call(this, memberIndex);
      this.setThrough(false);
  };

  Game_Follower.prototype.update = function() {
      Game_Character.prototype.update.call(this);
      if(!isSeparate) {
        this.setMoveSpeed($gamePlayer.realMoveSpeed());
        this.setOpacity($gamePlayer.opacity());
        this.setBlendMode($gamePlayer.blendMode());
        this.setWalkAnime($gamePlayer.hasWalkAnime());
        this.setStepAnime($gamePlayer.hasStepAnime());
        this.setDirectionFix($gamePlayer.isDirectionFixed());
        this.setTransparent($gamePlayer.isTransparent());
      }
  };

  //============================================================================
  // Game_Followers
  Game_Followers.prototype.isFollowerPassable = function(x, y) {
      var result = this._data.some(function(follower) {
        return follower.posNt(x, y);
      }, this);
      return result;
  };

  //============================================================================
  // Game_Interpreter
  var alias_Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function(command, args) {
    alias_Game_Interpreter_pluginCommand.call(this, command, args);
    if(command === "FollowerPassable") {
      switch (args[0]) {
        case 'enabled':
        case 'passable':
          passable = Boolean(args[1] === 'true');
          break;
        case 'SeparateMode':
          isSeparate = Boolean(args[1] === 'true');
          break;
        case 'setOpacity':
          var n = Number(args[2] || 255);
          KIT.fpSendMessage(Number(args[1] || 0), 'setOpacity', n.clamp(0, 255) );
          break;
        case 'setBlendMode':
          var type = Number(args[2] || 0);
          KIT.fpSendMessage(Number(args[1] || 0), 'setBlendMode', type.clamp(0, 3) );
          break;
        case 'setMoveSpeed':
          KIT.fpSendMessage(Number(args[1] || 0), 'setMoveSpeed', type.clamp(1, 6) );
          break;
        case 'setDirectionFix':
          KIT.fpSendMessage(Number(args[1] || 0), 'setDirectionFix', args[2] === 'true' );
          break;
        case 'setTransparent':
          KIT.fpSendMessage(Number(args[1] || 0), 'setTransparent', args[2] === 'true' );
          break;
      }
    }
  };

})();
<commit_msg>Fixed the bug<commit_after>//==============================================================================
// RS_FollowerPassable.js
//==============================================================================

var Imported = Imported || {};
Imported.RS_FollowerPassable = true;

/*:
 * RS_FollowerPassable.js
 * @plugindesc If you are using this plugin, the player will be impossible
 * to pass other party members.
 *
 * @author biud436
 *
 * @param Enabled
 * @desc
 * @default true
 *
 * @param Separate Mode
 * @desc
 * @default false
 *
 * @help
 * =============================================================================
 * Plugin Command
 * =============================================================================
 *
 * FollowerPassable passable true
 * FollowerPassable SeparateMode true
 *
 * The following commands could use in separate mode only.
 *
 * FollowerPassable setOpacity index x
 * FollowerPassable setBlendMode index x
 * FollowerPassable setMoveSpeed index x
 * FollowerPassable setDirectionFix index x
 * FollowerPassable setTransparent index x
 *
 * =============================================================================
 * Change Log
 * =============================================================================
 * 2016.06.01 (v1.0.0) - First Release.
 * 2016.09.01 (v1.0.4) - Added Plugin Commands
 * 2016.09.01 (v1.0.5) - Fixed the bug.
 */

(function() {

  var parameters = PluginManager.parameters('RS_FollowerPassable');
  var passable = Boolean(parameters['Enabled'] === 'true');
  var isSeparate = Boolean(parameters['Separate Mode'] === 'true');

  var KIT = Object.assign(Object.create({
      fpSendMessage: function (index, func, args) {
        var callFunc = $gamePlayer.followers().follower(index);
        callFunc[func].apply(callFunc, [args]);
      }
    }
  ));

  //============================================================================
  // Game_Player

  var alias_Game_Player_canPass = Game_Player.prototype.canPass;
  Game_Player.prototype.canPass = function(x, y, d) {
      var x2 = $gameMap.roundXWithDirection(x, d);
      var y2 = $gameMap.roundYWithDirection(y, d);
      if(this.isFollowerPassable(x2, y2) && passable) {
        return false;
      }
      return alias_Game_Player_canPass.call(this, x, y, d);
  }

  Game_Player.prototype.isFollowerPassable = function (x, y) {
      return this._followers.isFollowerPassable(x, y);
  };

  //============================================================================
  // Game_Follower

  var alias_Game_Follower_initialize = Game_Follower.prototype.initialize;
  Game_Follower.prototype.initialize = function(memberIndex) {
      alias_Game_Follower_initialize.call(this, memberIndex);
      this.setThrough(false);
  };

  Game_Follower.prototype.update = function() {
      Game_Character.prototype.update.call(this);
      if(!isSeparate) {
        this.setMoveSpeed($gamePlayer.realMoveSpeed());
        this.setOpacity($gamePlayer.opacity());
        this.setBlendMode($gamePlayer.blendMode());
        this.setWalkAnime($gamePlayer.hasWalkAnime());
        this.setStepAnime($gamePlayer.hasStepAnime());
        this.setDirectionFix($gamePlayer.isDirectionFixed());
        this.setTransparent($gamePlayer.isTransparent());
      }
  };

  //============================================================================
  // Game_Followers
  Game_Followers.prototype.isFollowerPassable = function(x, y) {
      var result = this._data.some(function(follower) {
        return follower.posNt(x, y);
      }, this);
      return result;
  };

  //============================================================================
  // Game_Interpreter
  var alias_Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function(command, args) {
    alias_Game_Interpreter_pluginCommand.call(this, command, args);
    if(command === "FollowerPassable") {
      switch (args[0]) {
        case 'enabled':
        case 'passable':
          passable = Boolean(args[1] === 'true');
          break;
        case 'SeparateMode':
          isSeparate = Boolean(args[1] === 'true');
          break;
        case 'setOpacity':
          var n = Number(args[2] || 255);
          KIT.fpSendMessage(Number(args[1] || 0), 'setOpacity', n.clamp(0, 255) );
          break;
        case 'setBlendMode':
          var type = Number(args[2] || 0);
          KIT.fpSendMessage(Number(args[1] || 0), 'setBlendMode', type.clamp(0, 3) );
          break;
        case 'setMoveSpeed':
          KIT.fpSendMessage(Number(args[1] || 0), 'setMoveSpeed', type.clamp(1, 6) );
          break;
        case 'setDirectionFix':
          KIT.fpSendMessage(Number(args[1] || 0), 'setDirectionFix', args[2] === 'true' );
          break;
        case 'setTransparent':
          KIT.fpSendMessage(Number(args[1] || 0), 'setTransparent', args[2] === 'true' );
          break;
      }
    }
  };

})();
<|endoftext|>


<commit_before>"use strict";

/**
 * @ngdoc function
 * @name ng311.controller.AlertMainCtrl
 * @description
 * Alert Main Controller
 */
angular
  .module("ng311")
  .controller("AlertMainCtrl", function ($scope, $uibModal, endpoints, Alert) {
    $scope.page = 1;
    $scope.limit = 10;
    $scope.search = {};
    $scope.channels = [];
    $scope.alert = { jurisdictions: [], methods: [], receivers: [] };

    $scope.jurisdictions = endpoints.jurisdictions.jurisdictions;
    $scope.methods = [
      { name: "SMS" },
      { name: "Email" },
      { name: "Push Notification" }
    ];

    $scope.priorities = [
      { name: "High", count: 100 },
      { name: "Normal", count: 100 },
      { name: "Low", count: 100 }
    ];

    $scope.statuses = [
      { name: "Sent", count: 100 },
      { name: "Failed", count: 100 },
      { name: "Delivered", count: 100 }
    ];

    $scope.methods = [
      { name: "SMS", count: 100 },
      { name: "Email", count: 100 },
      { name: "Push Notification", count: 100 }
    ];

    $scope.receivers = [
      { name: "Reporters" },
      { name: "Customers" },
      { name: "Subscribers" },
      { name: "Employees" }
    ];

    /**
     * Open model to compose
     *
     * @function
     * @name compose
     *
     * @version 0.1.0
     * @since 0.1.0
     */
    $scope.compose = function () {
      //open performance reports filter modal
      $scope.modal = $uibModal.open({
        templateUrl: "views/alerts/_partials/compose.html",
        scope: $scope,
        size: "lg"
      });

      //handle modal close and dismissed
      $scope.modal.result.then(
        function onClose(/*selectedItem*/) { },
        function onDismissed() { }
      );
    };

    /**
     * Send composed message
     *
     * @function
     * @name send
     *
     * @version 0.1.0
     * @since 0.1.0
     */
    $scope.send = function () {
      // TODO support Email and Push notification
      // normalize input
      // $scope.alert.methods = $scope.channels.map(function(method) {
      //   return method.toUpperCase();
      // });
      $scope.alert.methods = ["SMS"]; // fix SMS as the type of alert that will be sent

      var alert = new Alert($scope.alert);

      // save an alert
      alert
        .$save()
        .then(function (response) {
          console.log($scope.modal);
          $scope.modal.dismiss();
        })
        .catch(function (error) {
          console.log(error);
          // TODO handle errors
        });
    };

    /**
     * Load initial alerts on state activation
     *
     * @function
     * @name index
     *
     * @version 0.1.0
     * @since 0.1.0
     */
    $scope.find = function () {
      Alert.find({
        page: $scope.page,
        q: $scope.q
      }).then(function (results) {
        $scope.alerts = results.alerts.map(function (alert) {
          var areas = alert.jurisdictions.map(function (jurisdiction) {
            return jurisdiction.name;
          });

          return _.merge({}, alert, { areas: areas.toString() });
        });
        $scope.total = results.total;
      });
    };

    /**
     * Search Alert
     *
     * @function
     * @name onSearch
     *
     * @version 0.1.0
     * @since 0.1.0
     */
    $scope.onSearch = function () {
      if ($scope.alerts && $scope.search.q && $scope.search.q.length >= 2) {
        $scope.q = $scope.search.q;
        $scope.find();
      } else {
        $scope.q = undefined;
        $scope.find();
      }
    };

    /**
     * Determine whether to show pagination button
     *
     * @function
     * @name willPaginate
     *
     * @version 0.1.0
     * @since 0.1.0
     */
    $scope.willPaginate = function () {
      return $scope.total && $scope.total > $scope.limit;
    };

    // load alerts
    $scope.find();
  });
<commit_msg>add save message, error message plus reload on save<commit_after>"use strict";

/**
 * @ngdoc function
 * @name ng311.controller.AlertMainCtrl
 * @description
 * Alert Main Controller
 */
angular
  .module("ng311")
  .controller("AlertMainCtrl", function(
    $rootScope, $scope, $uibModal,
    endpoints, Alert
  ) {
    $scope.page = 1;
    $scope.limit = 10;
    $scope.search = {};
    $scope.channels = [];
    $scope.alert = { jurisdictions: [], methods: [], receivers: [] };

    $scope.jurisdictions = endpoints.jurisdictions.jurisdictions;
    $scope.methods = [
      { name: "SMS" },
      { name: "Email" },
      { name: "Push Notification" }
    ];

    $scope.priorities = [
      { name: "High", count: 100 },
      { name: "Normal", count: 100 },
      { name: "Low", count: 100 }
    ];

    $scope.statuses = [
      { name: "Sent", count: 100 },
      { name: "Failed", count: 100 },
      { name: "Delivered", count: 100 }
    ];

    $scope.methods = [
      { name: "SMS", count: 100 },
      { name: "Email", count: 100 },
      { name: "Push Notification", count: 100 }
    ];

    $scope.receivers = [
      { name: "Reporters" },
      { name: "Customers" },
      { name: "Subscribers" },
      { name: "Employees" }
    ];

    /**
     * Open model to compose
     *
     * @function
     * @name compose
     *
     * @version 0.1.0
     * @since 0.1.0
     */
    $scope.compose = function() {
      //open performance reports filter modal
      $scope.modal = $uibModal.open({
        templateUrl: "views/alerts/_partials/compose.html",
        scope: $scope,
        size: "lg"
      });

      //handle modal close and dismissed
      $scope.modal.result.then(
        function onClose( /*selectedItem*/ ) {},
        function onDismissed() {}
      );
    };

    /**
     * Send composed message
     *
     * @function
     * @name send
     *
     * @version 0.1.0
     * @since 0.1.0
     */
    $scope.send = function() {
      // TODO support Email and Push notification
      // normalize input
      // $scope.alert.methods = $scope.channels.map(function(method) {
      //   return method.toUpperCase();
      // });
      $scope.alert.methods = ["SMS"]; // fix SMS as the type of alert that will be sent

      var alert = new Alert($scope.alert);

      console.log($scope.alert);

      // save an alert
      alert
        .$save()
        .then(function( /*response*/ ) {

          $scope.modal.dismiss();

          //TODO avoid collision with alert.message
          var response = {};

          response.message =
            response.message || 'Alert Saved Successfully';

          $rootScope.$broadcast('appSuccess', response);

          $rootScope.$broadcast('app:alerts:reload');

        })
        .catch(function(error) {
          $rootScope.$broadcast('appError', error);
        });
    };

    /**
     * Load initial alerts on state activation
     *
     * @function
     * @name index
     *
     * @version 0.1.0
     * @since 0.1.0
     */
    $scope.find = function() {
      Alert.find({
        page: $scope.page,
        q: $scope.q
      }).then(function(results) {
        $scope.alerts = results.alerts.map(function(alert) {
          var areas = alert.jurisdictions.map(function(jurisdiction) {
            return jurisdiction.name;
          });

          return _.merge({}, alert, { areas: areas.toString() });
        });
        $scope.total = results.total;
      });
    };

    /**
     * Search Alert
     *
     * @function
     * @name onSearch
     *
     * @version 0.1.0
     * @since 0.1.0
     */
    $scope.onSearch = function() {
      if ($scope.alerts && $scope.search.q && $scope.search.q.length >= 2) {
        $scope.q = $scope.search.q;
        $scope.find();
      } else {
        $scope.q = undefined;
        $scope.find();
      }
    };

    /**
     * Determine whether to show pagination button
     *
     * @function
     * @name willPaginate
     *
     * @version 0.1.0
     * @since 0.1.0
     */
    $scope.willPaginate = function() {
      return $scope.total && $scope.total > $scope.limit;
    };

    // load alerts
    $scope.find();

    //listen for events
    $rootScope.$on('app:alerts:reload', function() {
      $scope.find();
    });

  });
<|endoftext|>


<commit_before>Controllers.controller("LineAuthorCtrl", ["$scope", function ($scope)
{
    if ($scope.user != null &&
        $scope.channel != null &&
        $scope.user.ranks[$scope.channel.name] != null)
    {
        $scope.rank = $scope.user.ranks[$scope.channel.name][0];
        if ($scope.rank === '%')
        {
            $scope.rank = '#';
        }
    } else
    {
        $scope.rank = '';
    }
}]);<commit_msg>Fixed ~/& for line authors<commit_after>Controllers.controller("LineAuthorCtrl", ["$scope", function ($scope)
{
    if ($scope.user != null &&
        $scope.channel != null &&
        $scope.user.ranks[$scope.channel.name] != null)
    {
        $scope.rank = $scope.user.ranks[$scope.channel.name][0];

        if ($scope.rank === '%')
        {
            $scope.rank = '#';
        }

        if ($scope.rank === '&' || $scope.rank === '~')
        {
            $scope.rank = '@';
        }
    } else
    {
        $scope.rank = '';
    }
}]);
<|endoftext|>


<commit_before>'use strict';

require('../app');
var angular = require('angular');

angular.module('deckApp')
  .factory('accountService', function(settings) {

    var detailsCache = {},
        credentialsCache = [];

    var credentialsEndpoint = Restangular.withConfig(function(RestangularConfigurer) {
      RestangularConfigurer.setBaseUrl(settings.credentialsUrl);
    });

    function listAccounts() {
      var deferred = $q.defer();
      if (credentialsCache.length) {
        deferred.resolve(credentialsCache);
      } else {
        credentialsEndpoint.all('credentials').getList().then(function(list) {
          credentialsCache = list;
          deferred.resolve(list);
        });
      }
      return deferred.promise;
    }

    function getAccountDetails(accountName) {
      var deferred = $q.defer();
      if (detailsCache[accountName]) {
        deferred.resolve(detailsCache[accountName]);
      } else {
        credentialsEndpoint.one('credentials', accountName).get().then(function(details) {
          detailsCache[accountName] = details;
          deferred.resolve(details);
        });
      }
      return deferred.promise;
    }

    function getRegionsForAccount(accountName) {
      return getAccountDetails(accountName).then(function(details) {
        return details ? details.regions : null;
      });
    }

    function challengeDestructiveActions(account) {
      return account && settings.accounts[account] && Boolean(settings.accounts[account].challengeDestructiveActions);
    }

    return {
      challengeDestructiveActions: challengeDestructiveActions,
      listAccounts: listAccounts,
      getAccountDetails: getAccountDetails,
      getRegionsForAccount: getRegionsForAccount
    };
  });
<commit_msg>inject accountService.js with dependencies<commit_after>'use strict';

require('../app');
var angular = require('angular');

angular.module('deckApp')
  .factory('accountService', function(settings, Restangular, $q) {

    var detailsCache = {},
        credentialsCache = [];

    var credentialsEndpoint = Restangular.withConfig(function(RestangularConfigurer) {
      RestangularConfigurer.setBaseUrl(settings.credentialsUrl);
    });

    function listAccounts() {
      var deferred = $q.defer();
      if (credentialsCache.length) {
        deferred.resolve(credentialsCache);
      } else {
        credentialsEndpoint.all('credentials').getList().then(function(list) {
          credentialsCache = list;
          deferred.resolve(list);
        });
      }
      return deferred.promise;
    }

    function getAccountDetails(accountName) {
      var deferred = $q.defer();
      if (detailsCache[accountName]) {
        deferred.resolve(detailsCache[accountName]);
      } else {
        credentialsEndpoint.one('credentials', accountName).get().then(function(details) {
          detailsCache[accountName] = details;
          deferred.resolve(details);
        });
      }
      return deferred.promise;
    }

    function getRegionsForAccount(accountName) {
      return getAccountDetails(accountName).then(function(details) {
        return details ? details.regions : null;
      });
    }

    function challengeDestructiveActions(account) {
      return account && settings.accounts[account] && Boolean(settings.accounts[account].challengeDestructiveActions);
    }

    return {
      challengeDestructiveActions: challengeDestructiveActions,
      listAccounts: listAccounts,
      getAccountDetails: getAccountDetails,
      getRegionsForAccount: getRegionsForAccount
    };
  });
<|endoftext|>


<commit_before>'use strict';

/**
 * ButtressJS - Realtime datastore for business software
 *
 * @file appointment.js
 * @description Appointment model definition.
 * @module Model
 * @exports model, schema, constants
 * @author Chris Bates-Keegan
 *
 */

const mongoose = require('mongoose');
const Model = require('../');
const Logging = require('../../logging');
const Shared = require('../shared');

/* ********************************************************************************
 *
 * LOCALS
 *
 **********************************************************************************/
let schema = new mongoose.Schema();
let ModelDef = null;

/* ********************************************************************************
 *
 * EMBEDDED DEPENDENCIES
 *
 **********************************************************************************/
Model.initModel('Contact');

/* ********************************************************************************
 *
 * CONSTANTS
 *
 **********************************************************************************/
let constants = {};

const outcomes = [
  'fail',
  'defer',
  'success'
];
const Outcomes = {
  FAIL: outcomes[0],
  DEFER: outcomes[1],
  SUCCESS: outcomes[2]
};

constants.Outcomes = Outcomes;

/* ********************************************************************************
 *
 * SCHEMA
 *
 **********************************************************************************/
schema.add({
  name: String,
  _app: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'App'
  },
  ownerId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  },
  assignedToId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  },
  companyId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Company'
  },
  contactId: String,
  locationId: String,
  approval: {
    status: {
      type: String,
      default: 'pending'
    },
    timestamp: {
      type: Date,
      default: Date.create
    },
    approverId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User'
    }
  },
  calendarEntryId: String,
  date: {
    type: Date
  },
  outcome: {
    type: String,
    enum: outcomes
  },
  reason: {
    type: String
  },
  metadata: [{key: String, value: String}],
  notes: [{
    userId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User'
    },
    text: String,
    timestamp: {
      type: Date,
      default: Date.create
    }
  }]
});

/* ********************************************************************************
 *
 * VIRTUALS
 *
 **********************************************************************************/
schema.virtual('details').get(function() {
  return {
    id: this._id,
    name: this.name,
    ownerId: this.ownerId && this.ownerId._id ? this.ownerId._id : this.ownerId,
    assignedToId: this.assignedToId && this.assignedToId._id ? this.assignedToId._id : this.assignedToId,
    companyId: this.companyId && this.companyId._id ? this.companyId._id : this.companyId,
    contactId: this.contactId,
    locationId: this.locationId,
    approval: this.approval,
    date: this.date,
    outcome: this.outcome,
    reason: this.reason,
    notes: this.notes.map(n => ({text: n.text, timestamp: n.timestamp, userId: n.userId}))
  };
});

/* ********************************************************************************
 *
 * STATICS
 *
 **********************************************************************************/
/**
 * @param {Object} body - body passed through from a POST request to be validated
 * @return {Object} - returns an object with validation context
 */
const __doValidation = body => {
  let res = {
    isValid: false,
    missing: [],
    invalid: []
  };

  if (!body.name) {
    res.missing.push('name');
    return res;
  }
  if (!body.ownerId) {
    res.missing.push('ownerId');
    return res;
  }
  if (!body.assignedToId) {
    res.missing.push('assignedToId');
    return res;
  }
  if (!body.companyId) {
    res.missing.push('companyId');
    return res;
  }
  if (!body.contactId) {
    res.missing.push('contactId');
    return res;
  }
  if (!body.date) {
    res.missing.push('date');
    return res;
  }

  res.isValid = true;
  return res;
};

schema.statics.validate = body => {
  if (body instanceof Array === false) {
    body = [body];
  }
  let validation = body.map(__doValidation).filter(v => v.isValid === false);

  return validation.length >= 1 ? validation[0] : {isValid: true};
};

/*
 * @param {Object} body - body passed through from a POST request
 * @return {Promise} - returns a promise that is fulfilled when the database request is completed
 */
const __add = body => {
  return prev => {
    Logging.logDebug(body);
    const cl = new ModelDef({
      _app: Model.authApp._id,
      name: body.name,
      date: Date.create(body.date),
      ownerId: body.ownerId,
      assignedToId: body.assignedToId,
      companyId: body.companyId,
      contactId: body.contactId,
      locationId: body.locationId
    });

    return cl.save()
      .then(cl => prev.concat([cl]));
  };
};

schema.statics.add = body => {
  if (body instanceof Array === false) {
    body = [body];
  }

  return body.reduce((promise, item) => {
    return promise
      .then(__add(item))
      .catch(Logging.Promise.logError());
  }, Promise.resolve([]));
};

/**
 * @return {Promise} - resolves to an array of Apps (native Mongoose objects)
 */
schema.statics.getAll = () => {
  Logging.log(`getAll: ${Model.authApp._id}`, Logging.Constants.LogLevel.DEBUG);
  return ModelDef.find({_app: Model.authApp._id});
};

schema.statics.rmAll = () => {
  return ModelDef.remove({});
};

/* ********************************************************************************
 *
 * UPDATE BY PATH
 *
 **********************************************************************************/

const PATH_CONTEXT = {
  '^outcome$': {type: 'scalar', values: [Outcomes.SUCCESS, Outcomes.DEFER, Outcomes.FAIL]},
  '^reason$': {type: 'scalar', values: []},
  '^contactId$': {type: 'scalar', values: []},
  '^locationId$': {type: 'scalar', values: []},
  '^date$': {type: 'scalar', values: []},
  '^approval$': {type: 'scalar', values: []},
  '^notes$': {type: 'vector-add', values: []},
  '^notes.([0-9]{1,3}).__remove__$': {type: 'vector-rm', values: ['']},
  '^notes.([0-9]{1,3}).text$': {type: 'scalar', values: []}
};

schema.statics.validateUpdate = Shared.validateUpdate(PATH_CONTEXT);
schema.methods.updateByPath = Shared.updateByPath(PATH_CONTEXT);

/* ********************************************************************************
 *
 * METHODS
 *
 **********************************************************************************/

/**
 * @return {Promise} - returns a promise that is fulfilled when the database request is completed
 */
schema.methods.rm = function() {
  return ModelDef.remove({_id: this._id});
};

/* ********************************************************************************
 *
 * METADATA
 *
 **********************************************************************************/

schema.methods.addOrUpdateMetadata = Shared.addOrUpdateMetadata;
schema.methods.findMetadata = Shared.findMetadata;
schema.methods.rmMetadata = Shared.rmMetadata;

/* ********************************************************************************
 *
 * EXPORTS
 *
 **********************************************************************************/
ModelDef = mongoose.model('Appointment', schema);

module.exports.constants = constants;
module.exports.schema = schema;
module.exports.model = ModelDef;
<commit_msg>- ADDED: assignedToId to appointment update by path rules<commit_after>'use strict';

/**
 * ButtressJS - Realtime datastore for business software
 *
 * @file appointment.js
 * @description Appointment model definition.
 * @module Model
 * @exports model, schema, constants
 * @author Chris Bates-Keegan
 *
 */

const mongoose = require('mongoose');
const Model = require('../');
const Logging = require('../../logging');
const Shared = require('../shared');

/* ********************************************************************************
 *
 * LOCALS
 *
 **********************************************************************************/
let schema = new mongoose.Schema();
let ModelDef = null;

/* ********************************************************************************
 *
 * EMBEDDED DEPENDENCIES
 *
 **********************************************************************************/
Model.initModel('Contact');

/* ********************************************************************************
 *
 * CONSTANTS
 *
 **********************************************************************************/
let constants = {};

const outcomes = [
  'fail',
  'defer',
  'success'
];
const Outcomes = {
  FAIL: outcomes[0],
  DEFER: outcomes[1],
  SUCCESS: outcomes[2]
};

constants.Outcomes = Outcomes;

/* ********************************************************************************
 *
 * SCHEMA
 *
 **********************************************************************************/
schema.add({
  name: String,
  _app: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'App'
  },
  ownerId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  },
  assignedToId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  },
  companyId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Company'
  },
  contactId: String,
  locationId: String,
  approval: {
    status: {
      type: String,
      default: 'pending'
    },
    timestamp: {
      type: Date,
      default: Date.create
    },
    approverId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User'
    }
  },
  calendarEntryId: String,
  date: {
    type: Date
  },
  outcome: {
    type: String,
    enum: outcomes
  },
  reason: {
    type: String
  },
  metadata: [{key: String, value: String}],
  notes: [{
    userId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User'
    },
    text: String,
    timestamp: {
      type: Date,
      default: Date.create
    }
  }]
});

/* ********************************************************************************
 *
 * VIRTUALS
 *
 **********************************************************************************/
schema.virtual('details').get(function() {
  return {
    id: this._id,
    name: this.name,
    ownerId: this.ownerId && this.ownerId._id ? this.ownerId._id : this.ownerId,
    assignedToId: this.assignedToId && this.assignedToId._id ? this.assignedToId._id : this.assignedToId,
    companyId: this.companyId && this.companyId._id ? this.companyId._id : this.companyId,
    contactId: this.contactId,
    locationId: this.locationId,
    approval: this.approval,
    date: this.date,
    outcome: this.outcome,
    reason: this.reason,
    notes: this.notes.map(n => ({text: n.text, timestamp: n.timestamp, userId: n.userId}))
  };
});

/* ********************************************************************************
 *
 * STATICS
 *
 **********************************************************************************/
/**
 * @param {Object} body - body passed through from a POST request to be validated
 * @return {Object} - returns an object with validation context
 */
const __doValidation = body => {
  let res = {
    isValid: false,
    missing: [],
    invalid: []
  };

  if (!body.name) {
    res.missing.push('name');
    return res;
  }
  if (!body.ownerId) {
    res.missing.push('ownerId');
    return res;
  }
  if (!body.assignedToId) {
    res.missing.push('assignedToId');
    return res;
  }
  if (!body.companyId) {
    res.missing.push('companyId');
    return res;
  }
  if (!body.contactId) {
    res.missing.push('contactId');
    return res;
  }
  if (!body.date) {
    res.missing.push('date');
    return res;
  }

  res.isValid = true;
  return res;
};

schema.statics.validate = body => {
  if (body instanceof Array === false) {
    body = [body];
  }
  let validation = body.map(__doValidation).filter(v => v.isValid === false);

  return validation.length >= 1 ? validation[0] : {isValid: true};
};

/*
 * @param {Object} body - body passed through from a POST request
 * @return {Promise} - returns a promise that is fulfilled when the database request is completed
 */
const __add = body => {
  return prev => {
    Logging.logDebug(body);
    const cl = new ModelDef({
      _app: Model.authApp._id,
      name: body.name,
      date: Date.create(body.date),
      ownerId: body.ownerId,
      assignedToId: body.assignedToId,
      companyId: body.companyId,
      contactId: body.contactId,
      locationId: body.locationId
    });

    return cl.save()
      .then(cl => prev.concat([cl]));
  };
};

schema.statics.add = body => {
  if (body instanceof Array === false) {
    body = [body];
  }

  return body.reduce((promise, item) => {
    return promise
      .then(__add(item))
      .catch(Logging.Promise.logError());
  }, Promise.resolve([]));
};

/**
 * @return {Promise} - resolves to an array of Apps (native Mongoose objects)
 */
schema.statics.getAll = () => {
  Logging.log(`getAll: ${Model.authApp._id}`, Logging.Constants.LogLevel.DEBUG);
  return ModelDef.find({_app: Model.authApp._id});
};

schema.statics.rmAll = () => {
  return ModelDef.remove({});
};

/* ********************************************************************************
 *
 * UPDATE BY PATH
 *
 **********************************************************************************/

const PATH_CONTEXT = {
  '^outcome$': {type: 'scalar', values: [Outcomes.SUCCESS, Outcomes.DEFER, Outcomes.FAIL]},
  '^reason$': {type: 'scalar', values: []},
  '^contactId$': {type: 'scalar', values: []},
  '^assignedToId$': {type: 'scalar', values: []},
  '^locationId$': {type: 'scalar', values: []},
  '^date$': {type: 'scalar', values: []},
  '^approval$': {type: 'scalar', values: []},
  '^notes$': {type: 'vector-add', values: []},
  '^notes.([0-9]{1,3}).__remove__$': {type: 'vector-rm', values: ['']},
  '^notes.([0-9]{1,3}).text$': {type: 'scalar', values: []}
};

schema.statics.validateUpdate = Shared.validateUpdate(PATH_CONTEXT);
schema.methods.updateByPath = Shared.updateByPath(PATH_CONTEXT);

/* ********************************************************************************
 *
 * METHODS
 *
 **********************************************************************************/

/**
 * @return {Promise} - returns a promise that is fulfilled when the database request is completed
 */
schema.methods.rm = function() {
  return ModelDef.remove({_id: this._id});
};

/* ********************************************************************************
 *
 * METADATA
 *
 **********************************************************************************/

schema.methods.addOrUpdateMetadata = Shared.addOrUpdateMetadata;
schema.methods.findMetadata = Shared.findMetadata;
schema.methods.rmMetadata = Shared.rmMetadata;

/* ********************************************************************************
 *
 * EXPORTS
 *
 **********************************************************************************/
ModelDef = mongoose.model('Appointment', schema);

module.exports.constants = constants;
module.exports.schema = schema;
module.exports.model = ModelDef;
<|endoftext|>


<commit_before>; (function () {
    var vueForm = {};
    vueForm.install = function (Vue) {

        function closest(elem, selector) {
            var matchesSelector = elem.matches || elem.webkitMatchesSelector || elem.mozMatchesSelector || elem.msMatchesSelector;
            while (elem) {
                if (matchesSelector.call(elem, selector)) {
                    return elem;
                } else {
                    elem = elem.parentElement;
                }
            }
            return null;
        }

        function removeClassWithPrefix(el, prefix) {
            var classes = el.className.split(" ").filter(function (c) {
                return c.lastIndexOf(prefix, 0) !== 0;
            });
            el.className = (classes.join(" ")).trim();
        }

        var emailRegExp = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i, // from angular
            urlRegExp = /^(http\:\/\/|https\:\/\/)(.{4,})$/,
            dirtyClass = 'vf-dirty',
            pristineClass = 'vf-pristine',
            validClass = 'vf-valid',
            invalidClass = 'vf-invalid',
            submittedClass = 'vf-submitted',
            attrs = [
                'type',
                'required',
                'pattern',
                'multiple',
                'minlength',
                'maxlength',
                'min',
                'max',
                'custom-validator'
            ],
            attrsWithValue = [
                'minlength',
                'maxlength',
                'min',
                'max',
                'pattern'
            ];

        var validators = {
            required: function (value) {
                if (Vue.util.isArray(value)) {
                    return !!value.length;
                }
                return !!value;
            },
            email: function (value, multiple) {
                return emailRegExp.test(value);
            },
            number: function (value) {
                return !isNaN(value);
            },
            url: function (value) {
                return urlRegExp.test(value);
            },
            minlength: function (value, length) {
                return value.length >= length;
            },
            maxlength: function (value, length) {
                return length >= value.length;
            },
            pattern: function (value, pattern) {
                var patternRegExp = new RegExp('^' + pattern + '$');
                return patternRegExp.test(value);
            },
            min: function (value, min) {
                return value >= min;
            },
            max: function (value, max) {
                return max >= value;
            }
        };

        // check if an attribute exists, static or binding.
        // if it is a binding, watch it and re-validate on change
        function checkAttribute($this, attribute) {
            var vueFormCtrl = $this._vueFormCtrl;
            var binding = Vue.util.getBindAttr($this.el, attribute);
            if (binding) {
                $this.vm.$watch(binding, function (value, oldValue) {
                    vueFormCtrl[attribute] = value;
                    if (attribute === 'type') {
                        delete vueFormCtrl.validators[oldValue];
                        vueFormCtrl.validators[value] = validators[value];
                    } else {
                        vueFormCtrl.validators[attribute] = validators[attribute];
                        if (value === false || typeof value === 'undefined') {
                            vueFormCtrl.validators[attribute] = false;
                        }
                    }
                    if ($this._vueForm) {
                        vueFormCtrl.validate($this._value);
                    } else {
                        // this is for when an input is inside a v-if
                        // and will not be inserted into the dom for
                        // some time
                        Vue.nextTick(function () {
                            Vue.nextTick(function () {
                                vueFormCtrl.validate($this._value);
                            });
                        });
                    }
                }, { immediate: true });
            }
            var staticAttr = $this.el.getAttribute(attribute);
            if (staticAttr !== null) {
                vueFormCtrl[attribute] = staticAttr || true;
                if (attribute === 'type') {
                    vueFormCtrl.validators[staticAttr] = validators[staticAttr];
                } else if (attribute === 'custom-validator') {
                    vueFormCtrl.validators[attribute] = $this.vm[staticAttr];
                } else {
                    vueFormCtrl.validators[attribute] = validators[attribute];
                }
            }

        }

        Vue.directive('form', {
            id: 'form',
            priority: 10001,
            bind: function () {
                var el = this.el,
                    formName = el.getAttribute('name'),
                    hook = el.getAttribute('hook'),
                    vm = this.vm,
                    self = this,
                    controls = {};

                el.noValidate = true;

                var state = this._state = {
                    $name: formName,
                    $dirty: false,
                    $pristine: true,
                    $valid: true,
                    $invalid: false,
                    $submitted: false,
                    $error: {}
                };

                // set inital state
                vm.$set(formName, state);
                Vue.util.addClass(el, pristineClass);
                Vue.util.addClass(el, validClass);

                var vueForm = this.el._vueForm = {
                    name: formName,
                    state: state,
                    addControl: function (ctrl) {
                        controls[ctrl.name] = ctrl;
                    },
                    removeControl: function (ctrl) {
                        this.removeError(ctrl.name);
                        delete controls[ctrl.name];
                        this.checkValidity();
                    },
                    setData: function (key, data) {
                        vm.$set(formName + '.' + key, data);
                    },
                    removeError: function (key) {
                        state.$error[key] = false;
                        delete state.$error[key];
                    },
                    checkValidity: function () {
                        var isValid = true;
                        Object.keys(controls).forEach(function (ctrl) {
                            if (controls[ctrl].state.$invalid) {
                                isValid = false;
                            }
                        });
                        this.setValidity(isValid);
                    },
                    setValidity: function (isValid) {
                        state.$valid = isValid;
                        state.$invalid = !isValid;
                        if (isValid) {
                            Vue.util.addClass(el, validClass);
                            Vue.util.removeClass(el, invalidClass);
                            removeClassWithPrefix(el, invalidClass + '-');
                        } else {
                            Vue.util.removeClass(el, validClass);
                            Vue.util.addClass(el, invalidClass);
                        }
                    },
                    setDirty: function () {
                        state.$dirty = true;
                        state.$pristine = false;
                        Vue.util.addClass(el, dirtyClass);
                        Vue.util.removeClass(el, pristineClass);
                    },
                    setPristine: function () {
                        state.$dirty = false;
                        state.$pristine = true;
                        Object.keys(controls).forEach(function (ctrl) {
                            controls[ctrl].setPristine();
                        });
                        vueForm.setSubmitted(false);
                        Vue.util.removeClass(el, dirtyClass);
                        Vue.util.addClass(el, pristineClass);
                    },
                    setSubmitted: function (isSubmitted) {
                        state.$submitted = isSubmitted;
                        if (isSubmitted) {
                            Vue.util.addClass(el, submittedClass);
                        } else {
                            Vue.util.removeClass(el, submittedClass);
                        }
                    }
                };

                if (hook) {
                    vm[hook](vueForm);
                }

                this._submitEvent = function () {
                    vueForm.setSubmitted(true);
                };
                Vue.util.on(el, 'submit', this._submitEvent);
            },
            update: function () {

            },
            unbind: function () {
                Vue.util.off(this.el, 'submit', this._submitEvent);
                delete this.el._vueForm;
            }
        });

        Vue.directive('formCtrl', {
            id: 'formCtrl',
            priority: 10000,
            bind: function () {
                var inputName = this.el.getAttribute('name'),
                    vModel = this.el.getAttribute('v-model'),
                    hook = this.el.getAttribute('hook'),
                    vm = this.vm,
                    el = this.el,
                    self = this,
                    vueForm;

                if (!inputName) {
                    console.warn('Name attribute must be populated');
                    return;
                }

                var state = self._state = {
                    $name: inputName,
                    $dirty: false,
                    $pristine: true,
                    $valid: true,
                    $invalid: false,
                    $error: {}
                };

                var vueFormCtrl = el._vueFormCtrl = self._vueFormCtrl = {
                    el: el,
                    name: inputName,
                    state: state,
                    setVadility: function (key, isValid) {
                        var vueForm = self._vueForm;

                        if (typeof key === 'boolean') {
                            // when key is boolean, we are setting
                            // overall field vadility
                            state.$valid = isValid;
                            state.$invalid = !isValid;

                            if (isValid) {
                                vueForm.removeError(inputName);
                                Vue.util.addClass(el, validClass);
                                Vue.util.removeClass(el, invalidClass);
                            } else {
                                Vue.util.removeClass(el, validClass);
                                Vue.util.addClass(el, invalidClass);
                            }
                            vueForm.checkValidity();
                            return;
                        }

                        if (isValid) {
                            vueForm.setData(inputName + '.$error.' + key, false);
                            delete state.$error[key];
                            removeClassWithPrefix(el, invalidClass + '-');
                        } else {
                            vueForm.setData(inputName + '.$error.' + key, true);
                            vueForm.setData('$error.' + inputName, state);
                            Vue.util.addClass(el, invalidClass + '-' + key);
                        }
                    },
                    setDirty: function () {
                        state.$dirty = true;
                        state.$pristine = false;
                        self._vueForm.setDirty();
                        Vue.util.addClass(el, dirtyClass);
                        Vue.util.removeClass(el, pristineClass);
                    },
                    setPristine: function () {
                        state.$dirty = false;
                        state.$pristine = true;
                        Vue.util.removeClass(el, dirtyClass);
                        Vue.util.addClass(el, pristineClass);
                    },
                    validators: {},
                    error: {},
                    validate: function (value) {
                        var isValid = true,
                            _this = this;

                        Object.keys(this.validators).forEach(function (validator) {
                            var args = [value];

                            if (_this.validators[validator] === false) {
                                _this.setVadility(validator, true);
                                return;
                            }

                            if (!_this.validators[validator]) {
                                return;
                            }

                            // if not the required validator and value is
                            // falsy but not a number, do not validate
                            if (validator !== 'required' && !value && typeof value !== 'number') {
                                _this.setVadility(validator, true);
                                return;
                            }

                            if (validator === 'email') {
                                args.push(_this.multiple);
                            } else if (attrsWithValue.indexOf(validator) !== -1) {
                                args.push(_this[validator]);
                            }

                            if (!_this.validators[validator].apply(this, args)) {
                                isValid = false;
                                _this.setVadility(validator, false);
                            } else {
                                _this.setVadility(validator, true);
                            }

                        });

                        _this.setVadility(true, isValid);

                        return isValid;
                    }
                };

                // add to validators depending on element attributes
                attrs.forEach(function (attr) {
                    checkAttribute(self, attr);
                });

                // find parent form
                var form;
                if (el.form) {
                    init(el.form._vueForm);
                } else {
                    // this is either a non form element node
                    // or a detached node (inside v-if)
                    form = closest(el, 'form[name]');
                    if (form && form._vueForm) {
                        init(form._vueForm);
                    } else {
                        // must be detached
                        Vue.nextTick(function () {
                            form = el.form || closest(el, 'form[name]');
                            init(form._vueForm);
                        });
                    }
                }

                function init(vueForm) {
                    if (!vueForm) {
                        return;
                    }
                    self._vueForm = vueForm;

                    // register the form control
                    vueForm.addControl(vueFormCtrl);

                    // set inital state
                    vueForm.setData(inputName, state);
                    Vue.util.addClass(el, pristineClass);
                    Vue.util.addClass(el, validClass);

                    var first = true;
                    if (vModel) {
                        self.vm.$watch(vModel, function (value, oldValue) {
                            if (!first) {
                                vueFormCtrl.setDirty();
                            }
                            first = false;
                            vueFormCtrl.validate(value);
                            self._value = value;
                        }, { immediate: true });
                    }

                };

                if (hook) {
                    vm[hook](vueFormCtrl);
                }

            },
            update: function (value, oldValue) {
                if (this._notfirst) {
                    this._vueFormCtrl.setDirty();
                }
                this._notfirst = true;
                this._vueFormCtrl.validate(value);
                this._value = value;
            },
            unbind: function () {
                this._vueForm.removeControl(this._vueFormCtrl);
                delete this.el._vueFormCtrl;
            }
        });

    }

    if (typeof exports == "object") {
        module.exports = vueForm;
    } else if (typeof define == "function" && define.amd) {
        define([], function () { return vueForm });
    } else if (window.Vue) {
        window.vueForm = vueForm;
        Vue.use(vueForm);
    }

})();<commit_msg>Prevent undefined in karam<commit_after>; (function () {
    var vueForm = {};
    vueForm.install = function (Vue) {

        function closest(elem, selector) {
            var matchesSelector = elem.matches || elem.webkitMatchesSelector || elem.mozMatchesSelector || elem.msMatchesSelector;
            while (elem) {
                if (matchesSelector.call(elem, selector)) {
                    return elem;
                } else {
                    elem = elem.parentElement;
                }
            }
            return null;
        }

        function removeClassWithPrefix(el, prefix) {
            var classes = el.className.split(" ").filter(function (c) {
                return c.lastIndexOf(prefix, 0) !== 0;
            });
            el.className = (classes.join(" ")).trim();
        }

        var emailRegExp = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i, // from angular
            urlRegExp = /^(http\:\/\/|https\:\/\/)(.{4,})$/,
            dirtyClass = 'vf-dirty',
            pristineClass = 'vf-pristine',
            validClass = 'vf-valid',
            invalidClass = 'vf-invalid',
            submittedClass = 'vf-submitted',
            attrs = [
                'type',
                'required',
                'pattern',
                'multiple',
                'minlength',
                'maxlength',
                'min',
                'max',
                'custom-validator'
            ],
            attrsWithValue = [
                'minlength',
                'maxlength',
                'min',
                'max',
                'pattern'
            ];

        var validators = {
            required: function (value) {
                if (Vue.util.isArray(value)) {
                    return !!value.length;
                }
                return !!value;
            },
            email: function (value, multiple) {
                return emailRegExp.test(value);
            },
            number: function (value) {
                return !isNaN(value);
            },
            url: function (value) {
                return urlRegExp.test(value);
            },
            minlength: function (value, length) {
                return value.length >= length;
            },
            maxlength: function (value, length) {
                return length >= value.length;
            },
            pattern: function (value, pattern) {
                var patternRegExp = new RegExp('^' + pattern + '$');
                return patternRegExp.test(value);
            },
            min: function (value, min) {
                return value >= min;
            },
            max: function (value, max) {
                return max >= value;
            }
        };

        // check if an attribute exists, static or binding.
        // if it is a binding, watch it and re-validate on change
        function checkAttribute($this, attribute) {
            var vueFormCtrl = $this._vueFormCtrl;
            var binding = Vue.util.getBindAttr($this.el, attribute);
            if (binding) {
                $this.vm.$watch(binding, function (value, oldValue) {
                    vueFormCtrl[attribute] = value;
                    if (attribute === 'type') {
                        delete vueFormCtrl.validators[oldValue];
                        vueFormCtrl.validators[value] = validators[value];
                    } else {
                        vueFormCtrl.validators[attribute] = validators[attribute];
                        if (value === false || typeof value === 'undefined') {
                            vueFormCtrl.validators[attribute] = false;
                        }
                    }
                    if ($this._vueForm) {
                        vueFormCtrl.validate($this._value);
                    } else {
                        // this is for when an input is inside a v-if
                        // and will not be inserted into the dom for
                        // some time
                        Vue.nextTick(function () {
                            Vue.nextTick(function () {
                                vueFormCtrl.validate($this._value);
                            });
                        });
                    }
                }, { immediate: true });
            }
            var staticAttr = $this.el.getAttribute(attribute);
            if (staticAttr !== null) {
                vueFormCtrl[attribute] = staticAttr || true;
                if (attribute === 'type') {
                    vueFormCtrl.validators[staticAttr] = validators[staticAttr];
                } else if (attribute === 'custom-validator') {
                    vueFormCtrl.validators[attribute] = $this.vm[staticAttr];
                } else {
                    vueFormCtrl.validators[attribute] = validators[attribute];
                }
            }

        }

        Vue.directive('form', {
            id: 'form',
            priority: 10001,
            bind: function () {
                var el = this.el,
                    formName = el.getAttribute('name'),
                    hook = el.getAttribute('hook'),
                    vm = this.vm,
                    self = this,
                    controls = {};

                el.noValidate = true;

                var state = this._state = {
                    $name: formName,
                    $dirty: false,
                    $pristine: true,
                    $valid: true,
                    $invalid: false,
                    $submitted: false,
                    $error: {}
                };

                // set inital state
                vm.$set(formName, state);
                Vue.util.addClass(el, pristineClass);
                Vue.util.addClass(el, validClass);

                var vueForm = this.el._vueForm = {
                    name: formName,
                    state: state,
                    addControl: function (ctrl) {
                        controls[ctrl.name] = ctrl;
                    },
                    removeControl: function (ctrl) {
                        this.removeError(ctrl.name);
                        delete controls[ctrl.name];
                        this.checkValidity();
                    },
                    setData: function (key, data) {
                        vm.$set(formName + '.' + key, data);
                    },
                    removeError: function (key) {
                        state.$error[key] = false;
                        delete state.$error[key];
                    },
                    checkValidity: function () {
                        var isValid = true;
                        Object.keys(controls).forEach(function (ctrl) {
                            if (controls[ctrl].state.$invalid) {
                                isValid = false;
                            }
                        });
                        this.setValidity(isValid);
                    },
                    setValidity: function (isValid) {
                        state.$valid = isValid;
                        state.$invalid = !isValid;
                        if (isValid) {
                            Vue.util.addClass(el, validClass);
                            Vue.util.removeClass(el, invalidClass);
                            removeClassWithPrefix(el, invalidClass + '-');
                        } else {
                            Vue.util.removeClass(el, validClass);
                            Vue.util.addClass(el, invalidClass);
                        }
                    },
                    setDirty: function () {
                        state.$dirty = true;
                        state.$pristine = false;
                        Vue.util.addClass(el, dirtyClass);
                        Vue.util.removeClass(el, pristineClass);
                    },
                    setPristine: function () {
                        state.$dirty = false;
                        state.$pristine = true;
                        Object.keys(controls).forEach(function (ctrl) {
                            controls[ctrl].setPristine();
                        });
                        vueForm.setSubmitted(false);
                        Vue.util.removeClass(el, dirtyClass);
                        Vue.util.addClass(el, pristineClass);
                    },
                    setSubmitted: function (isSubmitted) {
                        state.$submitted = isSubmitted;
                        if (isSubmitted) {
                            Vue.util.addClass(el, submittedClass);
                        } else {
                            Vue.util.removeClass(el, submittedClass);
                        }
                    }
                };

                if (hook) {
                    vm[hook](vueForm);
                }

                this._submitEvent = function () {
                    vueForm.setSubmitted(true);
                };
                Vue.util.on(el, 'submit', this._submitEvent);
            },
            update: function () {

            },
            unbind: function () {
                Vue.util.off(this.el, 'submit', this._submitEvent);
                delete this.el._vueForm;
            }
        });

        Vue.directive('formCtrl', {
            id: 'formCtrl',
            priority: 10000,
            bind: function () {
                var inputName = this.el.getAttribute('name'),
                    vModel = this.el.getAttribute('v-model'),
                    hook = this.el.getAttribute('hook'),
                    vm = this.vm,
                    el = this.el,
                    self = this,
                    vueForm;

                if (!inputName) {
                    console.warn('Name attribute must be populated');
                    return;
                }

                var state = self._state = {
                    $name: inputName,
                    $dirty: false,
                    $pristine: true,
                    $valid: true,
                    $invalid: false,
                    $error: {}
                };

                var vueFormCtrl = el._vueFormCtrl = self._vueFormCtrl = {
                    el: el,
                    name: inputName,
                    state: state,
                    setVadility: function (key, isValid) {
                        var vueForm = self._vueForm;

                        if (typeof key === 'boolean') {
                            // when key is boolean, we are setting
                            // overall field vadility
                            state.$valid = isValid;
                            state.$invalid = !isValid;

                            if (isValid) {
                                vueForm.removeError(inputName);
                                Vue.util.addClass(el, validClass);
                                Vue.util.removeClass(el, invalidClass);
                            } else {
                                Vue.util.removeClass(el, validClass);
                                Vue.util.addClass(el, invalidClass);
                            }
                            vueForm.checkValidity();
                            return;
                        }

                        if (isValid) {
                            vueForm.setData(inputName + '.$error.' + key, false);
                            delete state.$error[key];
                            removeClassWithPrefix(el, invalidClass + '-');
                        } else {
                            vueForm.setData(inputName + '.$error.' + key, true);
                            vueForm.setData('$error.' + inputName, state);
                            Vue.util.addClass(el, invalidClass + '-' + key);
                        }
                    },
                    setDirty: function () {
                        state.$dirty = true;
                        state.$pristine = false;
                        self._vueForm.setDirty();
                        Vue.util.addClass(el, dirtyClass);
                        Vue.util.removeClass(el, pristineClass);
                    },
                    setPristine: function () {
                        state.$dirty = false;
                        state.$pristine = true;
                        Vue.util.removeClass(el, dirtyClass);
                        Vue.util.addClass(el, pristineClass);
                    },
                    validators: {},
                    error: {},
                    validate: function (value) {
                        var isValid = true,
                            _this = this;

                        //console.log('value', value)

                        Object.keys(this.validators).forEach(function (validator) {
                            var args = [value];

                            if (_this.validators[validator] === false) {
                                _this.setVadility(validator, true);
                                return;
                            }

                            if (!_this.validators[validator]) {
                                return;
                            }

                            // if not the required validator and value is
                            // falsy but not a number, do not validate
                            if (validator !== 'required' && !value && typeof value !== 'number') {
                                _this.setVadility(validator, true);
                                return;
                            }

                            if (validator === 'email') {
                                args.push(_this.multiple);
                            } else if (attrsWithValue.indexOf(validator) !== -1) {
                                args.push(_this[validator]);
                            }

                            if (!_this.validators[validator].apply(this, args)) {
                                isValid = false;
                                _this.setVadility(validator, false);
                            } else {
                                _this.setVadility(validator, true);
                            }

                        });

                        _this.setVadility(true, isValid);

                        return isValid;
                    }
                };

                // add to validators depending on element attributes
                attrs.forEach(function (attr) {
                    checkAttribute(self, attr);
                });

                // find parent form
                var form;
                if (el.form) {
                    init(el.form._vueForm);
                } else {
                    // this is either a non form element node
                    // or a detached node (inside v-if)
                    form = closest(el, 'form[name]');
                    if (form && form._vueForm) {
                        init(form._vueForm);
                    } else {
                        // must be detached
                        Vue.nextTick(function () {
                            form = el.form || closest(el, 'form[name]');
                            init(form._vueForm);
                        });
                    }
                }

                function init(vueForm) {
                    if (!vueForm) {
                        return;
                    }
                    self._vueForm = vueForm;

                    // register the form control
                    vueForm.addControl(vueFormCtrl);

                    // set inital state
                    vueForm.setData(inputName, state);
                    Vue.util.addClass(el, pristineClass);
                    Vue.util.addClass(el, validClass);

                    var first = true;
                    if (vModel) {
                        self.vm.$watch(vModel, function (value, oldValue) {
                            if (!first) {
                                vueFormCtrl.setDirty();
                            }
                            first = false;
                            vueFormCtrl.validate(value);
                            self._value = value;
                        }, { immediate: true });
                    }

                };

                if (hook) {
                    vm[hook](vueFormCtrl);
                }

            },
            update: function (value, oldValue) {
                if(typeof value === 'undefined') {
                    return;
                }
                if (this._notfirst) {
                    this._vueFormCtrl.setDirty();
                }
                this._notfirst = true;
                this._vueFormCtrl.validate(value);
                this._value = value;
            },
            unbind: function () {
                this._vueForm.removeControl(this._vueFormCtrl);
                delete this.el._vueFormCtrl;
            }
        });

    }

    if (typeof exports == "object") {
        module.exports = vueForm;
    } else if (typeof define == "function" && define.amd) {
        define([], function () { return vueForm });
    } else if (window.Vue) {
        window.vueForm = vueForm;
        Vue.use(vueForm);
    }

})();<|endoftext|>


<commit_before>WatchMe = {
  initial: {
    diameter: 300
  }
};

WatchMe.padLeft = function (x, padCharacter, length) {
  var s = '' + x,
      parts = [];
  for (var i = s.length; i < length; ++i) {
    parts.push(padCharacter);
  }
  parts.push(s);
  return parts.join('');
};

WatchMe.update = function () {
  var date = new Date(),
      hour = date.getHours() % 12,
      minute = date.getMinutes(),
      second = date.getSeconds(),
      millisecond = date.getMilliseconds();

  // Textual time check.
  WatchMe.display.timeCheck.innerHTML = [ hour,
      WatchMe.padLeft(minute, '0', 2),
      WatchMe.padLeft(second, '0', 2) ].join(':');

  // Draw background graphics.
  var context = WatchMe.context.watch,
      radius = WatchMe.radius,
      center = { x: radius, y: radius };
      thickness = 1;
  context.clearRect(0, 0, 2 * radius, 2 * radius);
  context.lineWidth = thickness;

  var hourRadius = 0.20 * radius,
      hourDistance = radius - hourRadius,
      minuteRadius = 0.16 * radius,
      minuteDistance = hourDistance - hourRadius - minuteRadius,
      secondRadius = 0.12 * radius,
      secondDistance = minuteDistance - minuteRadius - secondRadius;

  var paintArc = function (value, hertz, handDistance, handRadius,
        edgeProportion, circleColor, arcColor) {
    var angle = -Math.PI / 2 + value * 2 * Math.PI / hertz;
    thickness = edgeProportion * 2 * handRadius;
    context.lineWidth = thickness;
    context.beginPath();
    context.strokeStyle = circleColor;
    context.arc(center.x, center.y, handDistance + handRadius - thickness / 2,
        0, 2 * Math.PI);
    context.stroke();
    context.beginPath();
    context.strokeStyle = arcColor;
    context.arc(center.x, center.y, handDistance + handRadius - thickness / 2,
        angle - Math.PI / hertz, angle + Math.PI / hertz);
    context.stroke();
    context.beginPath();
    context.lineWidth = 1;
    context.fillStyle = '#e8e8e8';
    var x = center.x + Math.cos(angle) * (handDistance - thickness / 2),
        y = center.y + Math.sin(angle) * (handDistance - thickness / 2);
    context.arc(x, y, handRadius - thickness / 2, 0, 2 * Math.PI);
    context.lineWidth = 1;
    context.fill();
  };
  paintArc(hour, 12, hourDistance, hourRadius, 0.105, '#f8f8f8', '#888');
  paintArc(minute, 60, minuteDistance, minuteRadius, 0.135, '#f4f4f4', '#666');
  paintArc(second, 60, secondDistance, secondRadius, 0.165, '#f4f4f4', '#444');

  window.requestAnimationFrame(WatchMe.update);
};

WatchMe.load = function () {
  WatchMe.display = {
    timeCheck: document.getElementById('timeCheck')
  };
  WatchMe.canvas = {
    watch: document.createElement('canvas')
  };
  var canvas = WatchMe.canvas.watch,
      diameter = WatchMe.diameter = WatchMe.initial.diameter,
      radius = WatchMe.radius = diameter / 2;
  document.getElementById('watchContainer').appendChild(canvas);
  canvas.width = diameter;
  canvas.height = diameter;
  WatchMe.context = {
    watch: canvas.getContext('2d')
  };
  window.requestAnimationFrame(WatchMe.update);
};

window.onload = WatchMe.load;
<commit_msg>Position text according to font height<commit_after>WatchMe = {
  initial: {
    diameter: 300
  }
};

WatchMe.padLeft = function (x, padCharacter, length) {
  var s = '' + x,
      parts = [];
  for (var i = s.length; i < length; ++i) {
    parts.push(padCharacter);
  }
  parts.push(s);
  return parts.join('');
};

WatchMe.update = function () {
  var date = new Date(),
      hour = date.getHours() % 12,
      minute = date.getMinutes(),
      second = date.getSeconds(),
      millisecond = date.getMilliseconds();

  // Textual time check.
  var hourText = hour + '',
      minuteText = WatchMe.padLeft(minute, '0', 2),
      secondText = WatchMe.padLeft(second, '0', 2);
  WatchMe.display.timeCheck.innerHTML =
      [ hourText, minuteText, secondText ].join(':');

  // Draw background graphics.
  var context = WatchMe.context.watch,
      radius = WatchMe.radius,
      center = { x: radius, y: radius };
      thickness = 1;
  context.clearRect(0, 0, 2 * radius, 2 * radius);
  context.lineWidth = thickness;

  var hourRadius = 0.20 * radius,
      hourDistance = radius - hourRadius,
      minuteRadius = 0.16 * radius,
      minuteDistance = hourDistance - hourRadius - minuteRadius,
      secondRadius = 0.12 * radius,
      secondDistance = minuteDistance - minuteRadius - secondRadius;

  var paintArc = function (value, valueText, hertz, handDistance, handRadius,
        edgeProportion, circleColor, arcColor) {
    var angle = -Math.PI / 2 + value * 2 * Math.PI / hertz;
    thickness = edgeProportion * 2 * handRadius;
    // Background circle.
    context.lineWidth = thickness;
    context.beginPath();
    context.strokeStyle = circleColor;
    context.arc(center.x, center.y, handDistance + handRadius - thickness / 2,
        0, 2 * Math.PI);
    context.stroke();
    // Foreground arc.
    context.beginPath();
    context.strokeStyle = arcColor;
    context.arc(center.x, center.y, handDistance + handRadius - thickness / 2,
        angle - Math.PI / hertz, angle + Math.PI / hertz);
    context.stroke();
    // Value position.
    context.beginPath();
    context.lineWidth = 1;
    context.fillStyle = '#e8e8e8';
    var x = center.x + Math.cos(angle) * (handDistance - thickness / 2),
        y = center.y + Math.sin(angle) * (handDistance - thickness / 2);
    context.arc(x, y, handRadius - thickness / 2, 0, 2 * Math.PI);
    context.lineWidth = 1;
    context.fill();
    // Value text.
    context.fillStyle = '#444';
    context.font = 2 * handRadius - thickness + 'px sans-serif';
    var width = context.measureText(valueText).width;
    context.fillText(valueText, x - width / 2, y + handRadius - thickness / 2);
  };
  paintArc(hour, hourText, 12, hourDistance, hourRadius,
      0.105, '#f4f4f4', '#888');
  paintArc(minute, minuteText, 60, minuteDistance, minuteRadius,
      0.135, '#f4f4f4', '#666');
  paintArc(second, secondText, 60, secondDistance, secondRadius,
      0.165, '#f4f4f4', '#444');

  window.requestAnimationFrame(WatchMe.update);
};

WatchMe.load = function () {
  WatchMe.display = {
    timeCheck: document.getElementById('timeCheck')
  };
  WatchMe.canvas = {
    watch: document.createElement('canvas')
  };
  var canvas = WatchMe.canvas.watch,
      diameter = WatchMe.diameter = WatchMe.initial.diameter,
      radius = WatchMe.radius = diameter / 2;
  document.getElementById('watchContainer').appendChild(canvas);
  canvas.width = diameter;
  canvas.height = diameter;
  WatchMe.context = {
    watch: canvas.getContext('2d')
  };
  window.requestAnimationFrame(WatchMe.update);
};

window.onload = WatchMe.load;
<|endoftext|>


<commit_before>const http = require('http');
const gpio = require('wpi-gpio');

gpio.BCM_GPIO = true;

http.get('http://10.0.0.70', (res, err) => {
  res.on('err', (err) => {
    console.log(err);
  });

  res.on('data', (data) => {
    let status = data.statusCode;
    if (status === 200) {
      console.log('Weeeeee.....')
    }
  })
  console.info(gpio);
})
<commit_msg>use strict, dontcha know...<commit_after>'use strict';

const http = require('http');
const gpio = require('wpi-gpio');

gpio.BCM_GPIO = true;

http.get('http://10.0.0.70', (res, err) => {
  res.on('err', (err) => {
    console.log(err);
  });

  res.on('data', (data) => {
    let status = data.statusCode;
    if (status === 200) {
      console.log('Weeeeee.....')
    }
  })
  console.info(gpio);
})
<|endoftext|>


<commit_before>var term = require('terminal-kit').terminal
var log = require('./logging')

var keyboard = {

  // Key map: kodi recognizes some keys differently than terminal-kit reports
  mapKeys: {
    '0': 'zero',
    '1': 'one',
    '2': 'two',
    '3': 'three',
    '4': 'four',
    '5': 'five',
    '6': 'six',
    '7': 'seven',
    '8': 'eight',
    '9': 'nine',
    '-': 'minus',
    '+': 'plus',
    '=': 'equals',
    '.': 'period',
    ',': 'comma',
    ' ': 'space',
    '\'': 'quote',
    '"': 'doublequote',
    '`': 'leftquote',
    '~': 'tilde',
    '_': 'underbar',
    '/': 'forwardslash',
    '\\': 'backslash',
    ';': 'semicolon',
    ':': 'colon',
    '[': 'opensquarebracket',
    ']': 'closesquarebracket',
    'page_up': 'pageup',
    'page_down': 'pagedown',
  },

  capture: function (ev_client) {
    this.ev_client = ev_client
    this.paused = false

    return new Promise( (resolve, reject) => {

      // Start grabbing key presses
      term.grabInput()

      term.on('key', (keyname, matches, data) => {
        if (this.paused) {
          return
        }
        log.debug('keypress:', keyname, data)

        // Exit key
        if (keyname === 'CTRL_C') {
          resolve(this.disconnect())
          return
        }

        this.sendKey(this._normalizeKeyName(keyname))
      })
    })
  },

  pauseCapture: function () {
    this.paused = true
    log.debug('pausing capture')
  },

  resumeCapture: function () {
    this.paused = false
    log.debug('resuming capture')
  },

  startTextEntry: function () {
    this.pauseCapture()

    term.bold.yellow('\nKodi is requesting text input\n')
    term.bold('Enter text to send: ')

    return new Promise( (resolve, reject) => {
      this._textInput = term.inputField( (error, input) => {
        term('\n')
        if (error) {
          log.error(error)
          reject(error)
        }
        else {
          resolve(input)
        }
        this.exitTextEntry()
      })
    })
  },

  exitTextEntry: function () {
    if (this._textInput) {
      this._textInput.abort()
      this._textInput = null
      this.resumeCapture()
    }
  },

  disconnect: function () {
    term.grabInput(false)
  },

  sendKey: function (key) {
    log.info('sending key:', key)

    this.ev_client.keyPress(key, (err, bytes) => {
      if (err.length) {
        log.error(err)
      }
    })
  },

  _normalizeKeyName: function (key) {
    key = key.toLowerCase()

    // Handle modifiers
    // TODO: ctrl & alt modifiers are not actually working.
    // I haven't figured out a way to send them properly to Kodi's event server
    ;['ctrl', 'alt'].forEach( (mod) => {
      key = key.replace(mod+'_', mod+'-')
    })

    var keys = key.split('-')
    keys[keys.length-1] = this._getMappedKey(keys[keys.length-1])
    return keys.join('-')
  },

  _getMappedKey: function (key) {
    return this.mapKeys[key] || key
  }
}

module.exports = keyboard
<commit_msg>Fix problem mapping '-' key<commit_after>var term = require('terminal-kit').terminal
var log = require('./logging')

var keyboard = {

  // Key map: kodi recognizes some keys differently than terminal-kit reports
  mapKeys: {
    '0': 'zero',
    '1': 'one',
    '2': 'two',
    '3': 'three',
    '4': 'four',
    '5': 'five',
    '6': 'six',
    '7': 'seven',
    '8': 'eight',
    '9': 'nine',
    '-': 'minus',
    '+': 'plus',
    '=': 'equals',
    '.': 'period',
    ',': 'comma',
    ' ': 'space',
    '\'': 'quote',
    '"': 'doublequote',
    '`': 'leftquote',
    '~': 'tilde',
    '_': 'underbar',
    '/': 'forwardslash',
    '\\': 'backslash',
    ';': 'semicolon',
    ':': 'colon',
    '[': 'opensquarebracket',
    ']': 'closesquarebracket',
    'page_up': 'pageup',
    'page_down': 'pagedown',
  },

  capture: function (ev_client) {
    this.ev_client = ev_client
    this.paused = false

    return new Promise( (resolve, reject) => {

      // Start grabbing key presses
      term.grabInput()

      term.on('key', (keyname, matches, data) => {
        if (this.paused) {
          return
        }
        log.debug('keypress:', keyname, data)

        // Exit key
        if (keyname === 'CTRL_C') {
          resolve(this.disconnect())
          return
        }

        this.sendKey(this._normalizeKeyName(keyname))
      })
    })
  },

  pauseCapture: function () {
    this.paused = true
    log.debug('pausing capture')
  },

  resumeCapture: function () {
    this.paused = false
    log.debug('resuming capture')
  },

  startTextEntry: function () {
    this.pauseCapture()

    term.bold.yellow('\nKodi is requesting text input\n')
    term.bold('Enter text to send: ')

    return new Promise( (resolve, reject) => {
      this._textInput = term.inputField( (error, input) => {
        term('\n')
        if (error) {
          log.error(error)
          reject(error)
        }
        else {
          resolve(input)
        }
        this.exitTextEntry()
      })
    })
  },

  exitTextEntry: function () {
    if (this._textInput) {
      this._textInput.abort()
      this._textInput = null
      this.resumeCapture()
    }
  },

  disconnect: function () {
    term.grabInput(false)
  },

  sendKey: function (key) {
    log.info('sending key:', key)

    this.ev_client.keyPress(key, (err, bytes) => {
      if (err.length) {
        log.error(err)
      }
    })
  },

  _normalizeKeyName: function (key) {
    key = key.toLowerCase()

    // Handle modifiers
    // TODO: ctrl & alt modifiers are not actually working.
    // I haven't figured out a way to send them properly to Kodi's event server
    var mods = ['ctrl', 'alt']
    mods.forEach( (mod) => {
      key = key.replace(mod+'_', mod+'__')
    })

    var keys = key.split('__')
    keys[keys.length-1] = this._getMappedKey(keys[keys.length-1])
    return keys.join('-')
  },

  _getMappedKey: function (key) {
    return this.mapKeys[key] || key
  }
}

module.exports = keyboard
<|endoftext|>