<commit_before>var ZoomLevelMapper = require('./ZoomLevelMapper.js').ZoomLevelMapper;

exports.ArcGISController = function() {
    "use strict";

    this.LODCache = {};

    var self = this;
    setInterval(function clearOldCacheItems() {
        for(var cacheKey in self.LODCache) {
            var cacheItem = self.LODCache[cacheKey];
            if(cacheItem == null || cacheItem.lastTouch < Date.now() - 300000) {
                delete self.LODCache[cacheKey];
            }
        }
    }, 60000);
};

exports.ArcGISController.prototype.getZoomLevelMapper = function (url, callback) {
    if(this.LODCache[url] == null) {
        var zoomLevelMapper = new ZoomLevelMapper(url);
        zoomLevelMapper.init(function(err) {
            if(err) {
                return callback(err);
            }
            return callback(undefined, zoomLevelMapper);
        });
    } else {
        return callback(undefined, this.LODCache[url]);
    }
}

exports.ArcGISController.prototype.getRedirectUrl = function (req, res) {
    "use strict";

    var parseUrl = /[/]?(.*(?=[\/]arcgis[\/]?))/i,
        parseZ = /z\/([0-9]+)/i,
        parseY = /y\/([0-9]+)/i,
        parseX = /x\/([0-9]+)/i;

    var url = req.url.match(parseUrl)[1],
        z = req.url.match(parseZ)[1],
        y = req.url.match(parseY)[1],
        x = req.url.match(parseX)[1];

    if(!isInt(z) || !isInt(x) || !isInt(y)) {
        res.status(500).send("X/Y/Z need to be integers");
        return;
    }

    this.getZoomLevelMapper(url, function(err, zoomLevelMapper) {
        if(err) {
            res.status(500).send(err.message);
            return;
        }

        z = zoomLevelMapper.getCorrectZoomLevel(z);

        if(z == null) {
            res.status(404).send("The requested LOD is not defined");
            return;
        }

        var redirectUrl = req.protocol + "://" + url + "/tile/"+z+"/"+y+"/"+x;
        res.redirect(redirectUrl);
    });
};

function isInt(n) {
    return n % 1 === 0;
}<commit_msg>adding an error message<commit_after>var ZoomLevelMapper = require('./ZoomLevelMapper.js').ZoomLevelMapper;

exports.ArcGISController = function() {
    "use strict";

    this.LODCache = {};

    var self = this;
    setInterval(function clearOldCacheItems() {
        for(var cacheKey in self.LODCache) {
            var cacheItem = self.LODCache[cacheKey];
            if(cacheItem == null || cacheItem.lastTouch < Date.now() - 300000) {
                delete self.LODCache[cacheKey];
            }
        }
    }, 60000);
};

exports.ArcGISController.prototype.getZoomLevelMapper = function (url, callback) {
    if(this.LODCache[url] == null) {
        var zoomLevelMapper = new ZoomLevelMapper(url);
        zoomLevelMapper.init(function(err) {
            if(err) {
                return callback(err);
            }
            return callback(undefined, zoomLevelMapper);
        });
    } else {
        return callback(undefined, this.LODCache[url]);
    }
}

exports.ArcGISController.prototype.getRedirectUrl = function (req, res) {
    "use strict";

    try {
        console.log(req.url);

        var parseUrl = /[/]?(.*(?=[\/]arcgis[\/]?))/i,
            parseZ = /z\/([0-9]+)/i,
            parseY = /y\/([0-9]+)/i,
            parseX = /x\/([0-9]+)/i;

        var url = req.url.match(parseUrl)[1],
            z = req.url.match(parseZ)[1],
            y = req.url.match(parseY)[1],
            x = req.url.match(parseX)[1];

        if(!isInt(z) || !isInt(x) || !isInt(y)) {
            res.status(500).send("X/Y/Z need to be integers");
            return;
        }

        this.getZoomLevelMapper(url, function(err, zoomLevelMapper) {
            if(err) {
                res.status(500).send(err.message);
                return;
            }

            z = zoomLevelMapper.getCorrectZoomLevel(z);

            if(z == null) {
                res.status(404).send("The requested LOD is not defined");
                return;
            }

            var redirectUrl = req.protocol + "://" + url + "/tile/"+z+"/"+y+"/"+x;
            res.redirect(redirectUrl);
        });
    } catch (ex) {
        console.log(ex);
        res.status(500).send("Bad request");
    }
};

function isInt(n) {
    return n % 1 === 0;
}<|endoftext|>


<commit_before>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2006-2009 Sprout Systems, Inc. and contributors.
//            Portions ©2008-2009 Apple Inc. All rights reserved.
// License:   Licened under MIT license (see license.js)
// ==========================================================================

/**
  @class

  SelectButtonView has a functionality similar to that of SelectField

  Clicking the SelectButtonView button displays a menu pane with a
  list of items. The selected item will be displayed on the button.
  User has the option of enabling checkbox for the selected menu item.

  @extends SC.ButtonView
  @version 1.0
  @author Mohammed Ashik
*/
sc_require('views/button');

SC.SelectButtonView = SC.ButtonView.extend(
/** @scope SC.SelectButtonView.prototype */ {

  /**
    An array of items that will be form the menu you want to show.

    @property
    @type {Array}
  */
  objects: [],

  /**
    Binding default for an array of objects

    @property
    @default SC.Binding.multiple()
  */
  objectsBindingDefault: SC.Binding.multiple(),

  /**
    If you set this to a non-null value, then the name shown for each
    menu item will be pulled from the object using the named property.
    if this is null, the collection objects themselves will be used.

    @property
    @type {String}
    @default: null
  */
  nameKey: null,

  /**
    If you set this to a non-null value, then the value of this key will
    be used to sort the objects.  If this is not set, then nameKey will
    be used.

    @property
    @type: {String}
    @default: null
  */
  sortKey: null,

  /**
     Set this to a non-null value to use a key from the passed set of objects
     as the value for the options popup.  If you don't set this, then the
     objects themselves will be used as the value.

     @property
     @type {String}
     @default null
  */
  valueKey: null,

  /**
     Key used to extract icons from the objects array
  */
  iconKey: null,

  /**
    If true, the empty name will be localized.

    @property
    @type {Boolean}
    @default YES
  */
  localize: YES,

  /**
    if true, it means that no sorting will occur, objects will appear
    in the same order as in the array

    @property
    @type {Boolean}
    @default YES
  */
  disableSort: YES,

  /**

    @property
    @default ['select-button']
  */
  classNames: ['select-button'],

  /**
    Menu item list

    @property
    @type:{Array}
  */
  itemList: [],

  /**
    Current selected menu item

    @property
    @default null
  */
  currentSelItem: null,

  /**
    Property to set the index of the selected menu item. This in turn
    is used to calculate the preferMatrix.

    @property
    @type {Number}
    @default null
  */
  itemIdx: null,

  /**
     Current Value of the selectButton

     @property
     @default null
  */
  value: null ,

  /**
    if this property is set to 'YES', a checbox is shown next to the
    selected menu item.

    @private
    @default YES
  */
  checkboxEnabled: YES,

  /**
    Set this property to YES to display separtor before the last item

    @private
    @default NO
  */
  hasSeparator: NO,

  /**
    Default value of the select button.
     This will be the first item from the menu item list.

    @private
  */
  _defaultVal: null,

  /**
    Default title of the select button.
     This will be the title corresponding to the _defaultVal.

    @private
  */
  _defaultTitle: null,

  /**
    Default icon of the select button.
     This will be the icon corresponding to the _defaultVal.

    @private
  */
  _defaultIcon: null,

  /**
    @private

    The button theme will be popup
  */
  theme: 'popup',

  /**
    Render method gets triggered when these properties change

    @property
    @type{SC.Array}
  */
  displayProperties: ['icon', 'value','controlSize'],

  /**
    Prefer matrix to position the select button menu such that the
    selected item for the menu item will appear aligned to the
    the button. The value at the second index(0) changes based on the
    postion(index) of the menu item in the menu pane.

    @property
    @type {Array}
    @default null

  */
  preferMatrix: null,

  /**
    Width of the sprite image that gets applied due to the theme.
     This has to be accounted for while calculating the actual
     width of the button

    @property
    @type {Number}
    @default 28
  */
  SELECT_BUTTON_SPRITE_WIDTH: 28,

  /**
    Property to set the menu item height. This in turn is used for
    the calculation of prefMatrix.

    @property
    @type {Number}
    @default 20
  */
  CUSTOM_MENU_ITEM_HEIGHT: 20,

  /**
    Binds the button's selection state to the menu's visibility.

    @private
  */
  isSelectedBinding: '*menu.isVisibleInWindow',

  /**
    If this property is set to 'YES', the menu pane will be positioned
    below the anchor.

    @private
    @default NO
  */
  isDefaultPosition: NO,

  /**
    lastMenuWidth is the width of the last menu which was created from
    the objects of this select button.

    @private
  */
  lastMenuWidth: null,

  /**
    customView used to draw the menu
  */
  customView: null,

  /**
    This is a property for enabling/disabling ellipsis

    @private
    @default YES
  */
  needsEllipsis: YES,

  /**
    Left Alignment based on the size of the button

    @private
  */
  leftAlign: function() {
    var val = 0 ;
    var controlSize = this.get('controlSize') ;
    if(controlSize === SC.SMALL_CONTROL_SIZE) val = -14 ;
    if(controlSize === SC.REGULAR_CONTROL_SIZE) val = -16 ;
    return val;
  }.property('controlSize'),

  /**
    override this method to implement your own sorting of the menu. By
    default, menu items are sorted using the value shown or the sortKey

    @param{SC.Array} objects the unsorted array of objects to display.
    @returns sorted array of objects
  */
  sortObjects: function(objects) {
    if(!this.get('disableSort')){
      var nameKey = this.get('sortKey') || this.get('nameKey') ;
      objects = objects.sort(function(a,b) {
        if (nameKey) {
          a = a.get ? a.get(nameKey) : a[nameKey] ;
          b = b.get ? b.get(nameKey) : b[nameKey] ;
        }
        return (a<b) ? -1 : ((a>b) ? 1 : 0) ;
      }) ;
    }
    return objects ;
  },

  /**
    render method

    @private
  */
  render: function(context,firstTime) {
    sc_super();
    var layoutWidth = this.layout.width ;
    if(firstTime && layoutWidth) {
      this.adjust({ width: layoutWidth - this.SELECT_BUTTON_SPRITE_WIDTH }) ;
    }

    var objects = this.get('objects') ;
    objects = this.sortObjects(objects) ;
    var len = objects.length ;

    //Get the namekey, iconKey and valueKey set by the user
    var nameKey = this.get('nameKey') ;
    var iconKey = this.get('iconKey') ;
    var valueKey = this.get('valueKey') ;
    var checkboxEnabled = this.get('checkboxEnabled') ;

    //get the current selected value
    var currentSelectedVal = this.get('value') ;

    // get the localization flag.
    var shouldLocalize = this.get('localize') ;

    // get the hasSeparator flag
    var hasSeparator = this.get('hasSeparator') ;

    //itemList array to set the menu items
    var itemList = [] ;

    //to set the 'checkbox' property of menu items
    var isChecked = YES ;

    //index for finding the first item in the list
    var idx = 0 ;

    objects.forEach(function(object) {
    if (object) {

      //Get the name value. If value key is not specified convert obj
      //to string
      var name = nameKey ? (object.get ?
        object.get(nameKey) : object[nameKey]) : object.toString() ;

      // localize name if specified.
      name = shouldLocalize? name.loc() : name ;

      //Get the icon value
      var icon = iconKey ? (object.get ?
        object.get(iconKey) : object[iconKey]) : null ;
      if (SC.none(object[iconKey])) icon = null ;

      // get the value using the valueKey or the object
      var value = (valueKey) ? (object.get ?
        object.get(valueKey) : object[valueKey]) : object ;

      if (!SC.none(currentSelectedVal) && !SC.none(value)){
        if( currentSelectedVal === value ) {
          this.set('title', name) ;
          this.set('icon', icon) ;
        }
      }

      //Check if the item is currentSelectedItem or not
      if(value === this.value) {

        //set the itemIdx - To change the prefMatrix accordingly.
        this.set('itemIdx', idx) ;
        isChecked = !checkboxEnabled ? NO : YES ;
      }
      else {
        isChecked = NO ;
      }

      //Set the first item from the list as default selected item
      if (idx === 0) {
        this._defaultVal = value ;
        this._defaultTitle = name ;
        this._defaultIcon = icon ;
      }

      var item = SC.Object.create({
        title: name,
        icon: icon,
        value: value,
        isEnabled: YES,
        checkbox: isChecked,
        action: this.displaySelectedItem
      }) ;

      //Set the items in the itemList array
      itemList.push(item);
    }

    idx += 1 ;

    // display the separator if specified by the user
    if (hasSeparator && idx === (len-1)) {
      var separator = SC.Object.create({
        separator: YES
      }) ;
      itemList.push(separator);
    }

    this.set('itemList', itemList) ;
    }, this ) ;

    if(firstTime) {
      var value = this.get('value') ;
      if(SC.none(value)) {
        this.set('value', this._defaultVal) ;
        this.set('title', this._defaultTitle) ;
        this.set('icon', this._defaultIcon) ;
      }
    }

    //Set the preference matrix for the menu pane
    this.changeSelectButtonPreferMatrix(this.itemIdx) ;

  },

  /**
    Button action handler

    @private
    @param {DOMMouseEvent} evt mouseup event that triggered the action
  */
  _action: function( evt )
  {
    var buttonLabel = this.$('.sc-button-label')[0] ;
    var menuWidth = this.get('layer').offsetWidth ; // Get the length of the text on the button in pixels
    var scrollWidth = buttonLabel.scrollWidth ;
    var lastMenuWidth = this.get('lastMenuWidth') ;
    if(scrollWidth) {
       var offsetWidth = buttonLabel.offsetWidth ; // Get the original width of the label in the button
       if(scrollWidth && offsetWidth) {
          menuWidth = menuWidth + scrollWidth - offsetWidth ; //Add the difference of the offset Height and the scrollHeight to the menu width
       }
    }
    if (!lastMenuWidth || (menuWidth > lastMenuWidth)) {
      lastMenuWidth = menuWidth ;
    }
    this.set('lastMenuWidth',lastMenuWidth) ;
    var currSel = this.get('currentSelItem') ;
    var itemList = this.get('itemList') ;
    var menuControlSize = this.get('controlSize') ;

    // get the user defined custom view
    var customView = this.get('customView') ;
    var customMenuView = customView ? customView : SC.MenuItemView ;

    var menu  = SC.MenuPane.create({

      /**
        Class name - select-button-item
      */
      classNames: ['select-button'],

      /**
        The menu items are set from the itemList property of SelectButton

        @property
      */
      items: itemList,

      /**
        Example view which will be used to create the Menu Items

        @default SC.MenuItemView
        @type SC.View
      */
      exampleView: customMenuView,

      /**
        This property enables all the items and makes them selectable.

        @property
      */
      isEnabled: YES,

      preferType: SC.PICKER_MENU,
      itemHeightKey: 'height',
      layout: { width: lastMenuWidth },
      controlSize: menuControlSize,
      itemWidth: lastMenuWidth,
      contentView: SC.View.extend({
      })
    }) ;

    // no menu to toggle... bail...
    if (!menu) return NO ;
    menu.popup(this, this.preferMatrix) ;
    menu.set('currentSelectedMenuItem', currSel) ;
    return YES ;
  },

  /**
     Action method for the select button menu items

  */
  displaySelectedItem: function() {
    //Get MenuPane, currentSelectedMenuItem & menuItemView
    // Get the main parent view to show the menus
    var menuView = this.parentMenu() ;
    var currSel = menuView.get('currentSelectedMenuItem') ;
    var itemViews = menuView.menuItemViews ;
    var title,val ;

    //  Fetch the index of the current selected item
    var itemIdx = 0 ;
    if (currSel && itemViews) {
      itemIdx = itemViews.indexOf(currSel) ;
    }

    // Get the select button View
    var button = menuView.get('anchor') ;

    // set the value and title
    var object = menuView.get('items') ;
    var len = object.length ;
    var found = null ;

    while (!found && (--len >= 0)) {
      title = !SC.none(object[len].title) ? object[len].title: object.toString() ;
      val =  !SC.none(object[len].value) ? object[len].value: title ;

      if (title === this.get('value') && (itemIdx === len)) {
        found = object ;
        button.set('value', val) ;
        button.set('title', title) ;
      }
    }

    // set the icon, currentSelectedItem and itemIdx
    button.set('icon', this.get('icon')).set('currentSelItem', currSel).
      set('itemIdx', itemIdx) ;
  },

  /**
     Set the "top" attribute in the prefer matrix property which will
     position menu such that the selected item in the menu will be
     place aligned to the item on the button when menu is opened.
  */
  changeSelectButtonPreferMatrix: function() {
    var preferMatrixAttributeTop = 0 ;
    var itemIdx = this.get('itemIdx') ;
    var leftAlign = this.get('leftAlign') ;
    var defPreferMatrix ;
    var tempPreferMatrix ;

    if(this.get('isDefaultPosition')) {
      defPreferMatrix = [leftAlign, 4, 3] ;
      this.set('preferMatrix', defPreferMatrix) ;
    }
    else {
      if(itemIdx) {
        preferMatrixAttributeTop = itemIdx * this.CUSTOM_MENU_ITEM_HEIGHT ;
      }
      tempPreferMatrix = [leftAlign, -preferMatrixAttributeTop, 2] ;
      this.set('preferMatrix', tempPreferMatrix) ;
    }
  },

  /**
    @private

    Holding down the button should display the menu pane.
  */
  mouseDown: function(evt) {
    if (!this.get('isEnabled')) return YES ; // handled event, but do nothing
    this.set('isActive', YES);
    this._isMouseDown = YES;
    this.becomeFirstResponder() ;
    this._action() ;
    return YES ;
  },

  /**
    @private

    Handle Key event - Down arrow key
  */
  keyDown: function(event) {
    if ( this.interpretKeyEvents(event) ) {
      return YES;
    }
    else {
      arguments.callee.base.apply(this,arguments);
    }
  },

  /**
    @private

    Pressing the Up or Down arrow key should display the menu pane
  */
  interpretKeyEvents: function(event) {
    if (event) {
      if ((event.keyCode === 38 || event.keyCode === 40)) {
        this._action() ;
      }
      else if (event.keyCode === 27) {
        this.resignFirstResponder() ;
      }
    }
    return arguments.callee.base.apply(this,arguments);
  }

}) ;

<commit_msg>Bug fix<commit_after>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2006-2009 Sprout Systems, Inc. and contributors.
//            Portions ©2008-2009 Apple Inc. All rights reserved.
// License:   Licened under MIT license (see license.js)
// ==========================================================================

/**
  @class

  SelectButtonView has a functionality similar to that of SelectField

  Clicking the SelectButtonView button displays a menu pane with a
  list of items. The selected item will be displayed on the button.
  User has the option of enabling checkbox for the selected menu item.

  @extends SC.ButtonView
  @version 1.0
  @author Mohammed Ashik
*/
sc_require('views/button');

SC.SelectButtonView = SC.ButtonView.extend(
/** @scope SC.SelectButtonView.prototype */ {

  /**
    An array of items that will be form the menu you want to show.

    @property
    @type {Array}
  */
  objects: [],

  /**
    Binding default for an array of objects

    @property
    @default SC.Binding.multiple()
  */
  objectsBindingDefault: SC.Binding.multiple(),

  /**
    If you set this to a non-null value, then the name shown for each
    menu item will be pulled from the object using the named property.
    if this is null, the collection objects themselves will be used.

    @property
    @type {String}
    @default: null
  */
  nameKey: null,

  /**
    If you set this to a non-null value, then the value of this key will
    be used to sort the objects.  If this is not set, then nameKey will
    be used.

    @property
    @type: {String}
    @default: null
  */
  sortKey: null,

  /**
     Set this to a non-null value to use a key from the passed set of objects
     as the value for the options popup.  If you don't set this, then the
     objects themselves will be used as the value.

     @property
     @type {String}
     @default null
  */
  valueKey: null,

  /**
     Key used to extract icons from the objects array
  */
  iconKey: null,

  /**
    If true, the empty name will be localized.

    @property
    @type {Boolean}
    @default YES
  */
  localize: YES,

  /**
    if true, it means that no sorting will occur, objects will appear
    in the same order as in the array

    @property
    @type {Boolean}
    @default YES
  */
  disableSort: YES,

  /**

    @property
    @default ['select-button']
  */
  classNames: ['select-button'],

  /**
    Menu item list

    @property
    @type:{Array}
  */
  itemList: [],

  /**
    Current selected menu item

    @property
    @default null
  */
  currentSelItem: null,

  /**
    Property to set the index of the selected menu item. This in turn
    is used to calculate the preferMatrix.

    @property
    @type {Number}
    @default null
  */
  itemIdx: null,

  /**
     Current Value of the selectButton

     @property
     @default null
  */
  value: null ,

  /**
    if this property is set to 'YES', a checbox is shown next to the
    selected menu item.

    @private
    @default YES
  */
  checkboxEnabled: YES,

  /**
    Set this property to YES to display separtor before the last item

    @private
    @default NO
  */
  hasSeparator: NO,

  /**
    Default value of the select button.
     This will be the first item from the menu item list.

    @private
  */
  _defaultVal: null,

  /**
    Default title of the select button.
     This will be the title corresponding to the _defaultVal.

    @private
  */
  _defaultTitle: null,

  /**
    Default icon of the select button.
     This will be the icon corresponding to the _defaultVal.

    @private
  */
  _defaultIcon: null,

  /**
    @private

    The button theme will be popup
  */
  theme: 'popup',

  /**
    Render method gets triggered when these properties change

    @property
    @type{SC.Array}
  */
  displayProperties: ['icon', 'value','controlSize'],

  /**
    Prefer matrix to position the select button menu such that the
    selected item for the menu item will appear aligned to the
    the button. The value at the second index(0) changes based on the
    postion(index) of the menu item in the menu pane.

    @property
    @type {Array}
    @default null

  */
  preferMatrix: null,

  /**
    Width of the sprite image that gets applied due to the theme.
     This has to be accounted for while calculating the actual
     width of the button

    @property
    @type {Number}
    @default 28
  */
  SELECT_BUTTON_SPRITE_WIDTH: 28,

  /**
    Property to set the menu item height. This in turn is used for
    the calculation of prefMatrix.

    @property
    @type {Number}
    @default 20
  */
  CUSTOM_MENU_ITEM_HEIGHT: 20,

  /**
    Binds the button's selection state to the menu's visibility.

    @private
  */
  isSelectedBinding: '*menu.isVisibleInWindow',

  /**
    If this property is set to 'YES', the menu pane will be positioned
    below the anchor.

    @private
    @default NO
  */
  isDefaultPosition: NO,

  /**
    lastMenuWidth is the width of the last menu which was created from
    the objects of this select button.

    @private
  */
  lastMenuWidth: null,

  /**
    customView used to draw the menu
  */
  customView: null,

  /**
    This is a property for enabling/disabling ellipsis

    @private
    @default YES
  */
  needsEllipsis: YES,

  /**
    Left Alignment based on the size of the button

    @private
  */
  leftAlign: function() {
    var val = 0 ;
    var controlSize = this.get('controlSize') ;
    if(controlSize === SC.SMALL_CONTROL_SIZE) val = -14 ;
    if(controlSize === SC.REGULAR_CONTROL_SIZE) val = -16 ;
    return val;
  }.property('controlSize'),

  /**
    override this method to implement your own sorting of the menu. By
    default, menu items are sorted using the value shown or the sortKey

    @param{SC.Array} objects the unsorted array of objects to display.
    @returns sorted array of objects
  */
  sortObjects: function(objects) {
    if(!this.get('disableSort')){
      var nameKey = this.get('sortKey') || this.get('nameKey') ;
      objects = objects.sort(function(a,b) {
        if (nameKey) {
          a = a.get ? a.get(nameKey) : a[nameKey] ;
          b = b.get ? b.get(nameKey) : b[nameKey] ;
        }
        return (a<b) ? -1 : ((a>b) ? 1 : 0) ;
      }) ;
    }
    return objects ;
  },

  /**
    render method

    @private
  */
  render: function(context,firstTime) {
    sc_super();
    var layoutWidth = this.layout.width ;
    if(firstTime && layoutWidth) {
      this.adjust({ width: layoutWidth - this.SELECT_BUTTON_SPRITE_WIDTH }) ;
    }

    var objects = this.get('objects') ;
    objects = this.sortObjects(objects) ;
    var len = objects.length ;

    //Get the namekey, iconKey and valueKey set by the user
    var nameKey = this.get('nameKey') ;
    var iconKey = this.get('iconKey') ;
    var valueKey = this.get('valueKey') ;
    var checkboxEnabled = this.get('checkboxEnabled') ;

    //get the current selected value
    var currentSelectedVal = this.get('value') ;

    // get the localization flag.
    var shouldLocalize = this.get('localize') ;

    // get the hasSeparator flag
    var hasSeparator = this.get('hasSeparator') ;

    //itemList array to set the menu items
    var itemList = [] ;

    //to set the 'checkbox' property of menu items
    var isChecked = YES ;

    //index for finding the first item in the list
    var idx = 0 ;

    objects.forEach(function(object) {
    if (object) {

      //Get the name value. If value key is not specified convert obj
      //to string
      var name = nameKey ? (object.get ?
        object.get(nameKey) : object[nameKey]) : object.toString() ;

      // localize name if specified.
      name = shouldLocalize? name.loc() : name ;

      //Get the icon value
      var icon = iconKey ? (object.get ?
        object.get(iconKey) : object[iconKey]) : null ;
      if (SC.none(object[iconKey])) icon = null ;

      // get the value using the valueKey or the object
      var value = (valueKey) ? (object.get ?
        object.get(valueKey) : object[valueKey]) : object ;

      if (!SC.none(currentSelectedVal) && !SC.none(value)){
        if( currentSelectedVal === value ) {
          this.set('title', name) ;
          this.set('icon', icon) ;
        }
      }

      //Check if the item is currentSelectedItem or not
      if(value === this.get('value')) {

        //set the itemIdx - To change the prefMatrix accordingly.
        this.set('itemIdx', idx) ;
        isChecked = !checkboxEnabled ? NO : YES ;
      }
      else {
        isChecked = NO ;
      }

      //Set the first item from the list as default selected item
      if (idx === 0) {
        this._defaultVal = value ;
        this._defaultTitle = name ;
        this._defaultIcon = icon ;
      }

      var item = SC.Object.create({
        title: name,
        icon: icon,
        value: value,
        isEnabled: YES,
        checkbox: isChecked,
        action: this.displaySelectedItem
      }) ;

      //Set the items in the itemList array
      itemList.push(item);
    }

    idx += 1 ;

    // display the separator if specified by the user
    if (hasSeparator && idx === (len-1)) {
      var separator = SC.Object.create({
        separator: YES
      }) ;
      itemList.push(separator);
    }

    this.set('itemList', itemList) ;
    }, this ) ;

    if(firstTime) {
      var value = this.get('value') ;
      if(SC.none(value)) {
        this.set('value', this._defaultVal) ;
        this.set('title', this._defaultTitle) ;
        this.set('icon', this._defaultIcon) ;
      }
    }

    //Set the preference matrix for the menu pane
    this.changeSelectButtonPreferMatrix(this.itemIdx) ;

  },

  /**
    Button action handler

    @private
    @param {DOMMouseEvent} evt mouseup event that triggered the action
  */
  _action: function( evt )
  {
    var buttonLabel = this.$('.sc-button-label')[0] ;
    var menuWidth = this.get('layer').offsetWidth ; // Get the length of the text on the button in pixels
    var scrollWidth = buttonLabel.scrollWidth ;
    var lastMenuWidth = this.get('lastMenuWidth') ;
    if(scrollWidth) {
       var offsetWidth = buttonLabel.offsetWidth ; // Get the original width of the label in the button
       if(scrollWidth && offsetWidth) {
          menuWidth = menuWidth + scrollWidth - offsetWidth ; //Add the difference of the offset Height and the scrollHeight to the menu width
       }
    }
    if (!lastMenuWidth || (menuWidth > lastMenuWidth)) {
      lastMenuWidth = menuWidth ;
    }
    this.set('lastMenuWidth',lastMenuWidth) ;
    var currSel = this.get('currentSelItem') ;
    var itemList = this.get('itemList') ;
    var menuControlSize = this.get('controlSize') ;

    // get the user defined custom view
    var customView = this.get('customView') ;
    var customMenuView = customView ? customView : SC.MenuItemView ;

    var menu  = SC.MenuPane.create({

      /**
        Class name - select-button-item
      */
      classNames: ['select-button'],

      /**
        The menu items are set from the itemList property of SelectButton

        @property
      */
      items: itemList,

      /**
        Example view which will be used to create the Menu Items

        @default SC.MenuItemView
        @type SC.View
      */
      exampleView: customMenuView,

      /**
        This property enables all the items and makes them selectable.

        @property
      */
      isEnabled: YES,

      preferType: SC.PICKER_MENU,
      itemHeightKey: 'height',
      layout: { width: lastMenuWidth },
      controlSize: menuControlSize,
      itemWidth: lastMenuWidth,
      contentView: SC.View.extend({
      })
    }) ;

    // no menu to toggle... bail...
    if (!menu) return NO ;
    menu.popup(this, this.preferMatrix) ;
    menu.set('currentSelectedMenuItem', currSel) ;
    return YES ;
  },

  /**
     Action method for the select button menu items

  */
  displaySelectedItem: function() {
    //Get MenuPane, currentSelectedMenuItem & menuItemView
    // Get the main parent view to show the menus
    var menuView = this.parentMenu() ;
    var currSel = menuView.get('currentSelectedMenuItem') ;
    var itemViews = menuView.menuItemViews ;
    var title,val ;

    //  Fetch the index of the current selected item
    var itemIdx = 0 ;
    if (currSel && itemViews) {
      itemIdx = itemViews.indexOf(currSel) ;
    }

    // Get the select button View
    var button = menuView.get('anchor') ;

    // set the value and title
    var object = menuView.get('items') ;
    var len = object.length ;
    var found = null ;

    while (!found && (--len >= 0)) {
      title = !SC.none(object[len].title) ? object[len].title: object.toString() ;
      val =  !SC.none(object[len].value) ? object[len].value: title ;

      if (title === this.get('value') && (itemIdx === len)) {
        found = object ;
        button.set('value', val) ;
        button.set('title', title) ;
      }
    }

    // set the icon, currentSelectedItem and itemIdx
    button.set('icon', this.get('icon')).set('currentSelItem', currSel).
      set('itemIdx', itemIdx) ;
  },

  /**
     Set the "top" attribute in the prefer matrix property which will
     position menu such that the selected item in the menu will be
     place aligned to the item on the button when menu is opened.
  */
  changeSelectButtonPreferMatrix: function() {
    var preferMatrixAttributeTop = 0 ;
    var itemIdx = this.get('itemIdx') ;
    var leftAlign = this.get('leftAlign') ;
    var defPreferMatrix ;
    var tempPreferMatrix ;

    if(this.get('isDefaultPosition')) {
      defPreferMatrix = [leftAlign, 4, 3] ;
      this.set('preferMatrix', defPreferMatrix) ;
    }
    else {
      if(itemIdx) {
        preferMatrixAttributeTop = itemIdx * this.CUSTOM_MENU_ITEM_HEIGHT ;
      }
      tempPreferMatrix = [leftAlign, -preferMatrixAttributeTop, 2] ;
      this.set('preferMatrix', tempPreferMatrix) ;
    }
  },

  /**
    @private

    Holding down the button should display the menu pane.
  */
  mouseDown: function(evt) {
    if (!this.get('isEnabled')) return YES ; // handled event, but do nothing
    this.set('isActive', YES);
    this._isMouseDown = YES;
    this.becomeFirstResponder() ;
    this._action() ;
    return YES ;
  },

  /**
    @private

    Handle Key event - Down arrow key
  */
  keyDown: function(event) {
    if ( this.interpretKeyEvents(event) ) {
      return YES;
    }
    else {
      arguments.callee.base.apply(this,arguments);
    }
  },

  /**
    @private

    Pressing the Up or Down arrow key should display the menu pane
  */
  interpretKeyEvents: function(event) {
    if (event) {
      if ((event.keyCode === 38 || event.keyCode === 40)) {
        this._action() ;
      }
      else if (event.keyCode === 27) {
        this.resignFirstResponder() ;
      }
    }
    return arguments.callee.base.apply(this,arguments);
  }

}) ;

<|endoftext|>


<commit_before>
//************************************************************
// Data for table
//************************************************************

var europa = [
        ['Sweden','581','581','59.31','59','6'],
        ['Luxembourg','46.8','33.4','58.63','111','21'],
        ['Norway','258','581','50.20','97','9'],
        ['Monaco','108','1.08','28.89','163','-'],
        ['United Kingdom','1211','1211','18.77','46','7'],
        ['France','1035','1035','15.64','43','5'],
        ['Denmark','71.8','71.80','12.73','48','7'],
        ['Germany','1003','1003','12.21','48','9'],
        ['Sweden','581','581','59.31','59','6'],
        ['Switzerland','100','100','12.21','59','6'],
        ['Finland','107','46.4','8.49','50','10'],
        ['Netherlands','134','134','7.94','52','10'],
        ['Belgium','66.9','66.9','6.18','48','9'],
        ['Italy','334','268','4.54','35','7'],
        ['Austria','34.8','34.8','4.09','51','8'],
        ['Spain','161','161','3.46','30','6'],
        ['Iceland','1','0.50','1.55','52','6'],
        ['Liechtenstein','<0.1','<0.1','1.48','135','1'],
        ['Estonia','1.30','1.3','0.99','20','14'],
        ['Poland','0.11','0.11','<0.01','4','2'],
        ['Romania','0.10','0.10','0.01','10','4'],
        ['Czech Republic','5.32','5.32','0.57','20','10'],
        ['Hungary','4.30','4.30','0.43','14','5'],
        ['Latvia','0.47','0.47','0.24','16','4'],
        ['Lithuania','0.10','0.10','59.31','59','6'],
        ['Bulgaria','0.10','0.10','0.02','8','7'],
        ['Ireland','2.70','-','0','53','8'],
        ['Portugal','2.68','-','0','22','5'],
        ['Cyprus','0.50','-','0','27','7']
];

var developed_countries = [
        ['Japan','1500','1500','11.80','36','9'],
        ['Australia','187','187','7.92','62','17'],
        ['Canada','277','277','7.79','50','14'],
        ['Republic of Korea','100','100','1.99','28','12']
];

var developing_countries = [
        ['Panama','1','1','0.25','12','3'],
        ['Peru','6','-','0','2'],
        ['Vietnam','0.10','-','0','2','2'],
        ['Indonesia','0.25','0.25','<0.01','4','2'],
        ['Colombia','6','0.30','<0.01','8','2'],
        ['New Zealand','2.56','2.56','0.57','20','10'],
        ['Mexico','10','10','0.08','10','4'],
        ['Mongolia','<0.1','-','0','4','7'],
        ['Chile','0.30','0.30','0.02','15','5']
];

var dataSet = [
		['United States','$3000','$3000'],
        ['China','$46.8','$33.4'],
        ['Europe','$5852','$5500'],
        ['Developed countries','$2064','$2064'],
        ['Developing countries','$26.31','$14.41']
];<commit_msg>Delete dataset_table.js<commit_after><|endoftext|>


<commit_before>var inherits = require('util').inherits

var request = require('request')
var _ = require('lodash')
var Q = require('q')
var cclib = require('cc-wallet-core').cclib
var OperationalTx = require('cc-wallet-core').tx.OperationalTx
var RawTx = require('cc-wallet-core').tx.RawTx

var PaymentModel = require('./PaymentModel')
var cwpp = require('./cwpp')
var errors = require('./errors')

/**
 * @class CWPPPaymentModel
 * @extends PaymentModel
 *
 * @param {WalletEngine} walletEngine
 * @param {string} paymentURI
 */
function CWPPPaymentModel(walletEngine, paymentURI) {
  PaymentModel.call(this)

  this.walletEngine = walletEngine
  this.paymentURI = paymentURI
  this.state = 'non-initialized'
  this.payreq = null
}

inherits(CWPPPaymentModel, PaymentModel)

/**
 * @callback CWPPPaymentModel~initializeCallback
 * @param {?Error} error
 */

/**
 * @param {CWPPPaymentModel~initializeCallback} cb
 * @throws {Error}
 */
CWPPPaymentModel.prototype.initialize = function (cb) {
  var self = this

  var requestOpts = {
    method: 'GET',
    uri: cwpp.requestURL(self.paymentURI),
    json: true
  }

  Q.nfcall(request, requestOpts).spread(function (response, body) {
    if (response.statusCode !== 200) {
      throw new errors.RequestError('CWPPPaymentModel: ' + response.statusMessage)
    }

    if (!cwpp.hashMessage(body) === cwpp.getURIHash(self.paymentURI)) {
      throw new errors.PaymentError('PaymentRequest hash mismatch')
    }

    self.payreq = body

    if (self.payreq.acceptedMethods['cinputs'] !== true) {
      throw new errors.PaymentError('incompatible payment method. upgrade required?')
    }

    var assetId = self.payreq.assetId
    self.assetModel = self.walletEngine.getAssetModelById(assetId)
    if (!self.assetModel) {
      throw new errors.AssetNotRecognizedError('CWPPPaymentModel.initialize')
    }

    // TODO this is hackish, move this to AssetDefinition
    var colorAddress = assetId + '@' + self.payreq.address

    self.recipients = [{
      address: colorAddress,
      amount: self.payreq.value && self.assetModel.getAssetDefinition().formatValue(self.payreq.value)
    }]
    self.state = 'fresh'

  }).done(function () { cb(null) }, function (error) { cb(error) })
}

/**
 * @throws {NotImplementedError}
 */
CWPPPaymentModel.prototype.addRecipient = function () {
  throw new errors.NotImplementedError('CWPPPaymentModel.addRecipient')
}

/**
 * @callback CWPPPaymentModel~selectCoinsCallback
 * @param {?Error} error
 * @param {external:cc-wallet-core.Coin~RawCoin[]} cinputs
 * @param {?{address: string, value: number}} change
 * @param {external:cc-wallet-core.cclib.ColorDefinition} colordef
 */

/**
 * @param {CWPPPaymentModel~selectCoinsCallback} cb
 */
CWPPPaymentModel.prototype.selectCoins = function (cb) {
  var self = this

  var assetdef = self.assetModel.getAssetDefinition()
  var colordef = assetdef.getColorSet().getColorDefinitions()[0]
  var neededColorValue = new cclib.ColorValue(colordef, self.payreq.value)

  var opTx = new OperationalTx(self.walletEngine.getWallet())
  opTx.selectCoins(neededColorValue, null, function (error, coins, colorValue) {
    if (error) {
      return cb(error)
    }

    var cinputs = coins.map(function (coin) { return coin.toRawCoin() })
    var change = null
    if (colorValue.getValue() > self.payreq.value) {
      change = {
        address: opTx.getChangeAddress(colordef),
        value: colorValue.getValue() - self.payreq.value
      }
    }

    cb(null, cinputs, change, colordef)
  })
}

/**
 * @param {RawTx} rawTx
 * @param {external:cc-wallet-core.Coin~RawCoin[]} cinputs
 * @param {?{address: string, value: number}} change
 * @param {external:cc-wallet-core.cclib.ColorDefinition} colordef
 * @return {Q.Promise}
 */
CWPPPaymentModel.prototype._checkRawTx = function (rawTx, cinputs, change, colordef) {
  var self = this
  var wallet = self.walletEngine.getWallet()

  return Q.fcall(function () {
    // check inputs
    var tx = rawTx.toTransaction(true)
    var txInputs = _.zipObject(tx.ins.map(function (input, index) {
      var txId = Array.prototype.reverse.call(new Buffer(input.hash)).toString('hex')
      return [txId + input.index, index]
    }))
    var indexes = _.chain(txInputs)
      .keys()
      .difference(cinputs.map(function (input) {
        return input.txId + input.outIndex
      }))
      .map(function (key) { return txInputs[key] })
      .value()

    if (indexes.length === 0) {
      return
    }

    return Q.ninvoke(rawTx, 'getInputAddresses', wallet, indexes).then(function (txAddresses) {
      if (_.intersection(txAddresses, wallet.getAllAddresses()).length > 0) {
        throw new errors.CWPPWrongTxError('Wrong inputs')
      }
    })

  }).then(function () {
    // check outputs
    var assetdef = self.assetModel.getAssetDefinition()
    var fromBase58Check = cclib.bitcoin.Address.fromBase58Check

    var value = self.payreq.value
    if (self.payreq.fee && self.payreq.fee > 0) {
      value -= self.payreq.fee
    }

    var targets = [{address: self.payreq.address,
                    value: value}]
    if (change !== null) {
      targets.push({
        address: change.address,
        value: change.value
      })
    }

    var colorTargets = targets.map(function (recipient) {
      var script = fromBase58Check(recipient.address).toOutputScript().toHex()
      var amount = recipient.value
      var colorValue = new cclib.ColorValue(colordef, amount)
      return new cclib.ColorTarget(script, colorValue)
    })

    return Q.ninvoke(rawTx, 'satisfiesTargets', wallet, colorTargets, true).then(function (isSatisfied) {
      if (!isSatisfied) {
        throw new errors.CWPPWrongTxError('Wrong outputs')
      }
    })
  })
}

/**
 * @callback CWPPPaymentModel~sendCallback
 * @param {?Error} error
 */

/**
 * @param {CWPPPaymentModel~sendCallback} cb
 */
CWPPPaymentModel.prototype.send = function (cb) {
  var self = this

  if (self.readOnly) {
    return cb(new errors.PaymentAlreadyCommitedError())
  }

  if (self.state !== 'fresh') {
    return cb(new errors.PaymentWasNotProperlyInitializedError())
  }

  if (self.recipients.length === 0) {
    return cb(new errors.ZeroArrayLengthError('CWPPPaymentModel.send: recipients list is empty'))
  }

  if (self.seed === null) {
    return cb(new errors.MnemonicIsUndefinedError('CWPPPaymentModel.send'))
  }

  self.readOnly = true
  self.status = 'sending'

  /**
   * @param {Object} message
   * @return {Q.Promise<Object>}
   */
  function cwppProcess(message) {
    var requestOpts = {
      method: 'POST',
      uri: cwpp.processURL(self.paymentURI),
      body: JSON.stringify(message),
      json: true
    }
    return Q.nfcall(request, requestOpts).spread(function (response, body) {
      if (response.statusCode !== 200) {
        var error = response.statusMessage
        if (_.isObject(body) && !_.isUndefined(body.error)) {
          error = body.error
        }

        throw new errors.RequestError('CWPPPaymentModel: ' + error)
      }

      return body
    })
  }

  var wallet = self.walletEngine.getWallet()
  console.log('CWPP: selectCoins')
  Q.ninvoke(self, 'selectCoins').spread(function (cinputs, change, colordef) {
    // service build transaction
    console.log('CWPP: sending inputs')
    var msg = cwpp.make_cinputs_proc_req_1(colordef.getDesc(), cinputs, change)
    return cwppProcess(msg).then(function (response) {
      console.log('CWPP: check tx')
      var rawTx = RawTx.fromHex(response.tx_data)
      // check inputs and outputs
      return self._checkRawTx(rawTx, cinputs, change, colordef).then(function () {
        return rawTx
      })

    }).then(function (rawTx) {
      console.log('CWPP: sign tx')
      // we signing transaction
      var tx = rawTx.toTransaction(true)
      var txInputs = _.zipObject(tx.ins.map(function (input, index) {
        var txId = Array.prototype.reverse.call(new Buffer(input.hash)).toString('hex')
        return [txId + input.index, index]
      }))
      var indexes = _.chain(cinputs)
        .map(function (input) { return txInputs[input.txId + input.outIndex] })
        .value()

      var opts = {seedHex: self.seed, signingOnly: indexes}
      return Q.ninvoke(wallet, 'transformTx', rawTx, 'partially-signed', opts)
    })

  }).then(function (tx) {
    console.log('CWPP: sending partially-signed transaction')
    // service signing transaction
    var msg = cwpp.make_cinputs_proc_req_2(tx.toHex(true))
    return cwppProcess(msg)

  }).then(function (response) {
    console.log('CWPP: sending fully signed transaction to the network')
    // build transaction and send
    var tx = RawTx.fromHex(response.tx_data).toTransaction()
    self.txId = tx.getId()
    return Q.ninvoke(wallet, 'sendTx', tx)
  }).done(
    function () {
      self.status = 'send'
      cb(null, self.txId)
    },
    function (error) {
      self.status = 'failed'
      cb(error)
    }
  )
}

module.exports = CWPPPaymentModel
<commit_msg>jslint fixces CWPPPaymentModel<commit_after>var inherits = require('util').inherits

var request = require('request')
var _ = require('lodash')
var Q = require('q')
var cclib = require('cc-wallet-core').cclib
var OperationalTx = require('cc-wallet-core').tx.OperationalTx
var RawTx = require('cc-wallet-core').tx.RawTx

var PaymentModel = require('./PaymentModel')
var cwpp = require('./cwpp')
var errors = require('./errors')

/**
 * @class CWPPPaymentModel
 * @extends PaymentModel
 *
 * @param {WalletEngine} walletEngine
 * @param {string} paymentURI
 */
function CWPPPaymentModel(walletEngine, paymentURI) {
  PaymentModel.call(this)

  this.walletEngine = walletEngine
  this.paymentURI = paymentURI
  this.state = 'non-initialized'
  this.payreq = null
}

inherits(CWPPPaymentModel, PaymentModel)

/**
 * @callback CWPPPaymentModel~initializeCallback
 * @param {?Error} error
 */

/**
 * @param {CWPPPaymentModel~initializeCallback} cb
 * @throws {Error}
 */
CWPPPaymentModel.prototype.initialize = function (cb) {
  var self = this

  var requestOpts = {
    method: 'GET',
    uri: cwpp.requestURL(self.paymentURI),
    json: true
  }

  Q.nfcall(request, requestOpts).spread(function (response, body) {
    if (response.statusCode !== 200) {
      throw new errors.RequestError('CWPPPaymentModel: ' + response.statusMessage)
    }

    if (cwpp.hashMessage(body) !== cwpp.getURIHash(self.paymentURI)) {
      throw new errors.PaymentError('PaymentRequest hash mismatch')
    }

    self.payreq = body

    if (self.payreq.acceptedMethods.cinputs !== true) {
      throw new errors.PaymentError('incompatible payment method. upgrade required?')
    }

    var assetId = self.payreq.assetId
    self.assetModel = self.walletEngine.getAssetModelById(assetId)
    if (!self.assetModel) {
      throw new errors.AssetNotRecognizedError('CWPPPaymentModel.initialize')
    }

    // TODO this is hackish, move this to AssetDefinition
    var colorAddress = assetId + '@' + self.payreq.address

    self.recipients = [{
      address: colorAddress,
      amount: self.payreq.value && self.assetModel.getAssetDefinition().formatValue(self.payreq.value)
    }]
    self.state = 'fresh'

  }).done(function () { cb(null) }, function (error) { cb(error) })
}

/**
 * @throws {NotImplementedError}
 */
CWPPPaymentModel.prototype.addRecipient = function () {
  throw new errors.NotImplementedError('CWPPPaymentModel.addRecipient')
}

/**
 * @callback CWPPPaymentModel~selectCoinsCallback
 * @param {?Error} error
 * @param {external:cc-wallet-core.Coin~RawCoin[]} cinputs
 * @param {?{address: string, value: number}} change
 * @param {external:cc-wallet-core.cclib.ColorDefinition} colordef
 */

/**
 * @param {CWPPPaymentModel~selectCoinsCallback} cb
 */
CWPPPaymentModel.prototype.selectCoins = function (cb) {
  var self = this

  var assetdef = self.assetModel.getAssetDefinition()
  var colordef = assetdef.getColorSet().getColorDefinitions()[0]
  var neededColorValue = new cclib.ColorValue(colordef, self.payreq.value)

  var opTx = new OperationalTx(self.walletEngine.getWallet())
  opTx.selectCoins(neededColorValue, null, function (error, coins, colorValue) {
    if (error) {
      return cb(error)
    }

    var cinputs = coins.map(function (coin) { return coin.toRawCoin() })
    var change = null
    if (colorValue.getValue() > self.payreq.value) {
      change = {
        address: opTx.getChangeAddress(colordef),
        value: colorValue.getValue() - self.payreq.value
      }
    }

    cb(null, cinputs, change, colordef)
  })
}

/**
 * @param {RawTx} rawTx
 * @param {external:cc-wallet-core.Coin~RawCoin[]} cinputs
 * @param {?{address: string, value: number}} change
 * @param {external:cc-wallet-core.cclib.ColorDefinition} colordef
 * @return {Q.Promise}
 */
CWPPPaymentModel.prototype._checkRawTx = function (rawTx, cinputs, change, colordef) {
  var self = this
  var wallet = self.walletEngine.getWallet()

  return Q.fcall(function () {
    // check inputs
    var tx = rawTx.toTransaction(true)
    var txInputs = _.zipObject(tx.ins.map(function (input, index) {
      var txId = Array.prototype.reverse.call(new Buffer(input.hash)).toString('hex')
      return [txId + input.index, index]
    }))
    var indexes = _.chain(txInputs)
      .keys()
      .difference(cinputs.map(function (input) {
        return input.txId + input.outIndex
      }))
      .map(function (key) { return txInputs[key] })
      .value()

    if (indexes.length === 0) {
      return
    }

    return Q.ninvoke(rawTx, 'getInputAddresses', wallet, indexes).then(function (txAddresses) {
      if (_.intersection(txAddresses, wallet.getAllAddresses()).length > 0) {
        throw new errors.CWPPWrongTxError('Wrong inputs')
      }
    })

  }).then(function () {
    // check outputs
    var fromBase58Check = cclib.bitcoin.Address.fromBase58Check

    var value = self.payreq.value
    if (self.payreq.fee && self.payreq.fee > 0) {
      value -= self.payreq.fee
    }

    var targets = [{address: self.payreq.address,
                    value: value}]
    if (change !== null) {
      targets.push({
        address: change.address,
        value: change.value
      })
    }

    var colorTargets = targets.map(function (recipient) {
      var script = fromBase58Check(recipient.address).toOutputScript().toHex()
      var amount = recipient.value
      var colorValue = new cclib.ColorValue(colordef, amount)
      return new cclib.ColorTarget(script, colorValue)
    })

    return Q.ninvoke(rawTx, 'satisfiesTargets', wallet, colorTargets, true).then(function (isSatisfied) {
      if (!isSatisfied) {
        throw new errors.CWPPWrongTxError('Wrong outputs')
      }
    })
  })
}

/**
 * @callback CWPPPaymentModel~sendCallback
 * @param {?Error} error
 */

/**
 * @param {CWPPPaymentModel~sendCallback} cb
 */
CWPPPaymentModel.prototype.send = function (cb) {
  var self = this

  if (self.readOnly) {
    return cb(new errors.PaymentAlreadyCommitedError())
  }

  if (self.state !== 'fresh') {
    return cb(new errors.PaymentWasNotProperlyInitializedError())
  }

  if (self.recipients.length === 0) {
    return cb(new errors.ZeroArrayLengthError('CWPPPaymentModel.send: recipients list is empty'))
  }

  if (self.seed === null) {
    return cb(new errors.MnemonicIsUndefinedError('CWPPPaymentModel.send'))
  }

  self.readOnly = true
  self.status = 'sending'

  /**
   * @param {Object} message
   * @return {Q.Promise<Object>}
   */
  function cwppProcess(message) {
    var requestOpts = {
      method: 'POST',
      uri: cwpp.processURL(self.paymentURI),
      body: JSON.stringify(message),
      json: true
    }
    return Q.nfcall(request, requestOpts).spread(function (response, body) {
      if (response.statusCode !== 200) {
        var error = response.statusMessage
        if (_.isObject(body) && !_.isUndefined(body.error)) {
          error = body.error
        }

        throw new errors.RequestError('CWPPPaymentModel: ' + error)
      }

      return body
    })
  }

  var wallet = self.walletEngine.getWallet()
  console.log('CWPP: selectCoins')
  Q.ninvoke(self, 'selectCoins').spread(function (cinputs, change, colordef) {
    // service build transaction
    console.log('CWPP: sending inputs')
    var msg = cwpp.make_cinputs_proc_req_1(colordef.getDesc(), cinputs, change)
    return cwppProcess(msg).then(function (response) {
      console.log('CWPP: check tx')
      var rawTx = RawTx.fromHex(response.tx_data)
      // check inputs and outputs
      return self._checkRawTx(rawTx, cinputs, change, colordef).then(function () {
        return rawTx
      })

    }).then(function (rawTx) {
      console.log('CWPP: sign tx')
      // we signing transaction
      var tx = rawTx.toTransaction(true)
      var txInputs = _.zipObject(tx.ins.map(function (input, index) {
        var txId = Array.prototype.reverse.call(new Buffer(input.hash)).toString('hex')
        return [txId + input.index, index]
      }))
      var indexes = _.chain(cinputs)
        .map(function (input) { return txInputs[input.txId + input.outIndex] })
        .value()

      var opts = {seedHex: self.seed, signingOnly: indexes}
      return Q.ninvoke(wallet, 'transformTx', rawTx, 'partially-signed', opts)
    })

  }).then(function (tx) {
    console.log('CWPP: sending partially-signed transaction')
    // service signing transaction
    var msg = cwpp.make_cinputs_proc_req_2(tx.toHex(true))
    return cwppProcess(msg)

  }).then(function (response) {
    console.log('CWPP: sending fully signed transaction to the network')
    // build transaction and send
    var tx = RawTx.fromHex(response.tx_data).toTransaction()
    self.txId = tx.getId()
    return Q.ninvoke(wallet, 'sendTx', tx)
  }).done(
    function () {
      self.status = 'send'
      cb(null, self.txId)
    },
    function (error) {
      self.status = 'failed'
      cb(error)
    }
  )
}

module.exports = CWPPPaymentModel
<|endoftext|>


<commit_before>var path = require('path');
var pkg = require('../../package.json');

/**
 * Configuration class containing all properties to be used throughout the build
 */
var Config = function() {
  this.debugMode = false;
  this.sassExtension = "scss";
  this.buildSass = false;
  this.copyRightMessage = "Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.";
	var distPath = 'dist';
	var srcPath = 'src';
	this.paths = {
		distComponents: distPath + '/components',
    distSass: distPath + '/sass',
		distCSS: distPath + '/css',
		distSamples: distPath + '/samples',
		distSampleComponents: distPath + '/samples/' +  '/Components',
		distJS: distPath + '/js',
		distPackages: distPath + '/packages',
		bundlePath: distPath + '/bundles',
		srcPath: srcPath,
		srcSamples: srcPath + '/samples',
    srcSass: srcPath + '/sass',
		componentsPath : 'src/components',
		templatePath : srcPath + '/templates'
	};
	this.port =  process.env.PORT || 2020;
	this.projectURL =  "http://localhost";
	this.projectDirectory =  path.resolve(__dirname, '../../' + this.paths.distSamples);
	this.servePaths = [
        {
            'urlPath': '/css',
            'folderPath': '../css'
        }
    ];
	this.nugetConfig = {
		id: "OfficeUIFabric",
		title: "Office UI Fabric",
		version: pkg.version,
		authors: "Microsoft Corporation",
		owners: "Microsoft Corporation",
		description: "Fabric is a responsive, mobile-first, front-end framework, designed to make it quick and simple for you to create web experiences using the Office Design Language. It’s easy to get up and running with Fabric—whether you’re creating a new Office experience from scratch or adding new features to an existing one.",
		summary: "The front-end framework for building experiences for Office and Office 365.",
		language: "en-us",
		projectUrl: "https://github.com/OfficeDev/Office-UI-Fabric",
		licenseUrl: "https://github.com/OfficeDev/Office-UI-Fabric/blob/master/LICENSE",
		copyright: "Copyright (c) Microsoft Corporation",
		requireLicenseAcceptance: true,
		tags: "Microsoft UI Fabric CSS",
		outputDir: this.paths.distPackages
	};
	this.nugetPaths = [
		{src: this.paths.distCSS, dest: "/content/"},
		{src: this.paths.distSass, dest: "/content/sass/"},
		{src: this.paths.distJS, dest: "/scripts/"}
	];
  this.componentSamplesUpdate = "Components Samples updated successfully! Yay!";
  this.componentSamplesFinished = ' Component Samples build was successful! Yay!';
  //JS Files to be ignored in the JS Linter for Components
  //NOTE: Only use this for third party files, do not add any Fabric JS files to this.
  this.ignoreComponentJSLinting = [{
        src: this.paths.componentsPath + '/DatePicker/PickaDate.js',
        dist: this.paths.distSampleComponents + '/DatePicker/'
  }];
  //Errors
  this.genericBuildError = "Hmm, something went wrong in the build... Here is the error dump";
	this.bundlesConfig = {
		"bundles": [
				{
					"name": "fabric-full",
					"description": "A bundle containing all of Fabric's core and Component CSS.",
					"excludes": [],
					"options": {
						// Log helpful messages about the bundles being built.
						"verbose": true,

						// Log warnings about the bundles being built.
						"logWarnings": false
					}
				},
				{
					"name": "custom-bundle",
					"description": "A custom bundle including a handful of modules.",
					"includes": [
						"_Fabric.Color.Variables",
						"_Fabric.Color.Mixins",
						"_Fabric.Typography.Variables",
						"_Fabric.Typography",
						"_Fabric.Typography.Fonts",
						"_Fabric.Typography.Languageoverrides",
						"_Fabric.Utilities",
						"Button",
						"PersonaCard"
					],
					"options": {
						"verbose": true,
						"logWarnings": false
					}
				}
			]
	}
};

module.exports = new Config();<commit_msg>Whitespace adjustments in Config.json<commit_after>var path = require('path');
var pkg = require('../../package.json');

/**
 * Configuration class containing all properties to be used throughout the build
 */
var Config = function() {
  this.debugMode = false;
  this.sassExtension = "scss";
  this.buildSass = false;
  this.copyRightMessage = "Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information.";
  var distPath = 'dist';
  var srcPath = 'src';
  this.paths = {
    distComponents: distPath + '/components',
    distSass: distPath + '/sass',
    distCSS: distPath + '/css',
    distSamples: distPath + '/samples',
    distSampleComponents: distPath + '/samples/' +  '/Components',
    distJS: distPath + '/js',
    distPackages: distPath + '/packages',
    bundlePath: distPath + '/bundles',
    srcPath: srcPath,
    srcSamples: srcPath + '/samples',
    srcSass: srcPath + '/sass',
    componentsPath : 'src/components',
    templatePath : srcPath + '/templates'
  };
  this.port =  process.env.PORT || 2020;
  this.projectURL =  "http://localhost";
  this.projectDirectory =  path.resolve(__dirname, '../../' + this.paths.distSamples);
  this.servePaths = [
        {
            'urlPath': '/css',
            'folderPath': '../css'
        }
    ];
  this.nugetConfig = {
    id: "OfficeUIFabric",
    title: "Office UI Fabric",
    version: pkg.version,
    authors: "Microsoft Corporation",
    owners: "Microsoft Corporation",
    description: "Fabric is a responsive, mobile-first, front-end framework, designed to make it quick and simple for you to create web experiences using the Office Design Language. It’s easy to get up and running with Fabric—whether you’re creating a new Office experience from scratch or adding new features to an existing one.",
    summary: "The front-end framework for building experiences for Office and Office 365.",
    language: "en-us",
    projectUrl: "https://github.com/OfficeDev/Office-UI-Fabric",
    licenseUrl: "https://github.com/OfficeDev/Office-UI-Fabric/blob/master/LICENSE",
    copyright: "Copyright (c) Microsoft Corporation",
    requireLicenseAcceptance: true,
    tags: "Microsoft UI Fabric CSS",
    outputDir: this.paths.distPackages
  };
  this.nugetPaths = [
    {src: this.paths.distCSS, dest: "/content/"},
    {src: this.paths.distSass, dest: "/content/sass/"},
    {src: this.paths.distJS, dest: "/scripts/"}
  ];
  this.componentSamplesUpdate = "Components Samples updated successfully! Yay!";
  this.componentSamplesFinished = ' Component Samples build was successful! Yay!';
  //JS Files to be ignored in the JS Linter for Components
  //NOTE: Only use this for third party files, do not add any Fabric JS files to this.
  this.ignoreComponentJSLinting = [{
        src: this.paths.componentsPath + '/DatePicker/PickaDate.js',
        dist: this.paths.distSampleComponents + '/DatePicker/'
  }];
  //Errors
  this.genericBuildError = "Hmm, something went wrong in the build... Here is the error dump";
  this.bundlesConfig = {
    "bundles": [
        {
          "name": "fabric-full",
          "description": "A bundle containing all of Fabric's core and Component CSS.",
          "excludes": [],
          "options": {
            // Log helpful messages about the bundles being built.
            "verbose": true,

            // Log warnings about the bundles being built.
            "logWarnings": false
          }
        },
        {
          "name": "custom-bundle",
          "description": "A custom bundle including a handful of modules.",
          "includes": [
            "_Fabric.Color.Variables",
            "_Fabric.Color.Mixins",
            "_Fabric.Typography.Variables",
            "_Fabric.Typography",
            "_Fabric.Typography.Fonts",
            "_Fabric.Typography.Languageoverrides",
            "_Fabric.Utilities",
            "Button",
            "PersonaCard"
          ],
          "options": {
            "verbose": true,
            "logWarnings": false
          }
        }
      ]
  }
};

module.exports = new Config();<|endoftext|>


<commit_before>var gulp = require('gulp');
var markdown = require('gulp-markdown');
var gutil = require('gulp-util');
var config = require('./../config');

gulp.task('markdown', function () {

	if (config.global.tasks.markdown) {
		return gulp.src(config.global.docs + '/_src/**/*.md')
			.pipe(markdown(config.markdown))
			.pipe();
	} else {
		gutil.log(gutil.colors.yellow('markdown disabled'));
	}
});
<commit_msg>added wrapper for markdown task<commit_after>var gulp = require('gulp');
var markdown = require('gulp-markdown');
var wrap = require('gulp-wrap');
var gutil = require('gulp-util');
var config = require('./../config');

gulp.task('markdown', function () {

    if (config.global.tasks.markdown) {
        return gulp.src('./readme.md')
            .pipe(markdown(config.markdown))
            .pipe(wrap({ src: config.global.docs + '/resources/wraps/markdown.tpl.html' }))
            .pipe(gulp.dest(config.global.docs));
    } else {
        gutil.log(gutil.colors.yellow('markdown disabled'));
    }
});
<|endoftext|>


<commit_before>
angular.module('frontendApp').factory('GeoFiles', ['$http', '$q', '$cacheFactory', function($http, $q, $cacheFactory) {
  /*
   * Service that wraps the fetching and preparing of TopoJSON / GeoJSON files
   */

  // TODO: Actually should use a resource here, and use the built in caching provided by $http

  var svc = {};
  svc._cache = $cacheFactory('GeoFiles');

  svc.getAreas = function() {
    var deferred = $q.defer();
    var cacheResult = svc._cache.get('areas');

    if (_.isUndefined(cacheResult)) {
      $http.get("scripts/geo/ca_polygon.topo.json").success(function(data, status) {
        var geo_data = topojson.feature(data, data.objects['ca_polygon.geo']);
        svc._cache.put('areas', geo_data);
        deferred.resolve(geo_data)
      });
    } else {
      deferred.resolve(cacheResult);
    }

    return deferred.promise;
  };

  svc.getDistricts = function() {
    var deferred = $q.defer();
    var cacheResult = svc._cache.get('districts');

    if (_.isUndefined(cacheResult)) {
      $http.get("scripts/geo/dc_polygon.topo.json").success(function(data, status) {
        var geo_data = topojson.feature(data, data.objects['dc_polygon.geo']);
        svc._cache.put('districts', geo_data);
        deferred.resolve(geo_data)
      });
    } else {
      deferred.resolve(cacheResult);
    }

    return deferred.promise;
  };

  return svc;
}]);<commit_msg>Use HTTP cache in GeoFiles<commit_after>
angular.module('frontendApp').factory('GeoFiles', ['$http', '$q', '$cacheFactory', function($http, $q, $cacheFactory) {
  /*
   * Service that wraps the fetching and preparing of TopoJSON / GeoJSON files
   */

  var svc = {};

  svc.getAreas = function() {
    var deferred = $q.defer();

    $http.get("scripts/geo/ca_polygon.topo.json", {cache: true}).success(function(data, status) {
      var geo_data = topojson.feature(data, data.objects['ca_polygon.geo']);
      deferred.resolve(geo_data)
    });

    return deferred.promise;
  };

  svc.getDistricts = function() {
    var deferred = $q.defer();

    $http.get("scripts/geo/dc_polygon.topo.json", {cache: true}).success(function(data, status) {
      var geo_data = topojson.feature(data, data.objects['dc_polygon.geo']);
      deferred.resolve(geo_data)
    });

    return deferred.promise;
  };

  return svc;
}]);<|endoftext|>


<commit_before>/* eslint-disable jsx-a11y/anchor-is-valid */
import React from 'react';
import { useQuery } from '@apollo/react-hooks';
import { thousandify } from './../../utils/thousandifyUtil';
import { getDate } from './../../utils/getDateUtil';
import { statsGlobalQuery } from './../../graphql/queries';
import Wrapper from '../layout/Wrapper';

// const HeroIconUsers = () => (
//   <svg
//     className="h-6 w-6 text-white"
//     xmlns="http://www.w3.org/2000/svg"
//     fill="none"
//     viewBox="0 0 24 24"
//     stroke="currentColor"
//     aria-hidden="true"
//   >
//     {/*  */}
//     <path
//       strokeLinecap="round"
//       strokeLinejoin="round"
//       strokeWidth="2"
//       d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"
//     />
//   </svg>
// );

// const HeroIconMailOpen = () => (
//   <svg
//     className="h-6 w-6 text-white"
//     xmlns="http://www.w3.org/2000/svg"
//     fill="none"
//     viewBox="0 0 24 24"
//     stroke="currentColor"
//     aria-hidden="true"
//   >
//     {/*  */}
//     <path
//       strokeLinecap="round"
//       strokeLinejoin="round"
//       strokeWidth="2"
//       d="M3 19v-8.93a2 2 0 01.89-1.664l7-4.666a2 2 0 012.22 0l7 4.666A2 2 0 0121 10.07V19M3 19a2 2 0 002 2h14a2 2 0 002-2M3 19l6.75-4.5M21 19l-6.75-4.5M3 10l6.75 4.5M21 10l-6.75 4.5m0 0l-1.14.76a2 2 0 01-2.22 0l-1.14-.76"
//     />
//   </svg>
// );

const HeroIconCursorClick = () => (
  <svg
    className="h-6 w-6 text-white"
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 24 24"
    stroke="currentColor"
    aria-hidden="true"
  >
    {/*  */}
    <path
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth="2"
      d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
    />
  </svg>
);

const StatsItem = ({ icon, heading, stat, statIncreasedBy, statDecreasedBy }) => (

{icon}

{heading}

{stat}

            {statIncreasedBy && (

                <svg
                  className="self-center flex-shrink-0 h-5 w-5 text-green-500"
                  fill="currentColor"
                  viewBox="0 0 20 20"
                  aria-hidden="true"
                >
                  <path
                    fillRule="evenodd"
                    d="M5.293 9.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L11 7.414V15a1 1 0 11-2 0V7.414L6.707 9.707a1 1 0 01-1.414 0z"
                    clipRule="evenodd"
                  />
                </svg>
                Increased by
                {statIncreasedBy}

            )}
            {statDecreasedBy && (

                <svg
                  className="self-center flex-shrink-0 h-5 w-5 text-red-500"
                  fill="currentColor"
                  viewBox="0 0 20 20"
                  aria-hidden="true"
                >
                  <path
                    fillRule="evenodd"
                    d="M14.707 10.293a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 111.414-1.414L9 12.586V5a1 1 0 012 0v7.586l2.293-2.293a1 1 0 011.414 0z"
                    clipRule="evenodd"
                  />
                </svg>
                Decreased by
                {statDecreasedBy}

            )}

    {/*

          {' '}
          View all {heading} stats

 */}

);

const DatesFromUntil = ({ from, until }) => (

    {getDate(from)} - {getDate(until)}

);

const HomePage = () => {
  const {
    data: {
      statsGlobal,
      statsGlobal: {
        commitDateFirst,
        commitDateLast,
        commits,
        commitsImpactGtThousand,
        commitsOnWeekend,
        commitsPerContributorAverage,
        // commitsPerDay,
        commitsPerDayAverage,
        // commitsPerMonthDay,
        // commitsPerMonthNr,
        // commitsPerYear,
        commitsWithoutFileChanges,
        commitsWithoutImpact,
        contributors,
        // contributorsList,
        daysActive,
        daysSinceFirstCommit,
        daysSinceLastCommit,
        fileChanges,
        lines,
        repositories,
        // repositoriesList,
        staleness,
        // weekdays,
      } = {},
    } = {},
  } = useQuery(statsGlobalQuery);
  return (
    <Wrapper pageType="home">

Global Stats

        <DatesFromUntil from={commitDateFirst} until={commitDateLast} />

      {statsGlobal && (
        <>

            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Commits"
              stat={thousandify(commits)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Commits impact > thousand"
              stat={thousandify(commitsImpactGtThousand)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Commits on weekends"
              stat={thousandify(commitsOnWeekend)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Average commits / contributor"
              stat={commitsPerContributorAverage.toFixed(2)}
            />
            {/* <StatsItem
              icon={<HeroIconCursorClick />}
              heading="commitsPerDay"
              stat={commitsPerDay}
            /> */}
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Average commits / day"
              stat={commitsPerDayAverage.toFixed(2)}
            />
            {/* <StatsItem
              icon={<HeroIconCursorClick />}
              heading="commitsPerMonthDay"
              stat={commitsPerMonthDay}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="commitsPerMonthNr"
              stat={commitsPerMonthNr}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="commitsPerYear"
              stat={commitsPerYear}
            /> */}
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Commits without file changes"
              stat={thousandify(commitsWithoutFileChanges)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Commits without impact"
              stat={thousandify(commitsWithoutImpact)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Contributors"
              stat={thousandify(contributors)}
            />
            {/* <StatsItem
              icon={<HeroIconCursorClick />}
              heading="contributorsList"
              stat={contributorsList}
            /> */}
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Days between first and last commit"
              stat={thousandify(daysActive)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Days since first commit"
              stat={daysSinceFirstCommit}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Days since last commit"
              stat={daysSinceLastCommit}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="File changes"
              stat={thousandify(fileChanges)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Lines of code"
              stat={thousandify(lines)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Repositories"
              stat={thousandify(repositories)}
            />
            {/* <StatsItem
              icon={<HeroIconCursorClick />}
              heading="repositoriesList"
              stat={repositoriesList}
            /> */}
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Staleness"
              stat={staleness.toFixed(2)}
            />
            {/* <StatsItem icon={<HeroIconCursorClick />} heading="weekdays" stat={weekdays} /> */}

        </>
      )}
    </Wrapper>
  );
};
export default HomePage;
<commit_msg>:shower: Change order of what is shown on global stats page<commit_after>/* eslint-disable jsx-a11y/anchor-is-valid */
import React from 'react';
import { useQuery } from '@apollo/react-hooks';
import { thousandify } from './../../utils/thousandifyUtil';
import { getDate } from './../../utils/getDateUtil';
import { statsGlobalQuery } from './../../graphql/queries';
import Wrapper from '../layout/Wrapper';

const HeroIconUsers = () => (
  <svg
    className="h-6 w-6 text-white"
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 24 24"
    stroke="currentColor"
    aria-hidden="true"
  >
    {/*  */}
    <path
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth="2"
      d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"
    />
  </svg>
);

// const HeroIconMailOpen = () => (
//   <svg
//     className="h-6 w-6 text-white"
//     xmlns="http://www.w3.org/2000/svg"
//     fill="none"
//     viewBox="0 0 24 24"
//     stroke="currentColor"
//     aria-hidden="true"
//   >
//     {/*  */}
//     <path
//       strokeLinecap="round"
//       strokeLinejoin="round"
//       strokeWidth="2"
//       d="M3 19v-8.93a2 2 0 01.89-1.664l7-4.666a2 2 0 012.22 0l7 4.666A2 2 0 0121 10.07V19M3 19a2 2 0 002 2h14a2 2 0 002-2M3 19l6.75-4.5M21 19l-6.75-4.5M3 10l6.75 4.5M21 10l-6.75 4.5m0 0l-1.14.76a2 2 0 01-2.22 0l-1.14-.76"
//     />
//   </svg>
// );

const HeroIconCursorClick = () => (
  <svg
    className="h-6 w-6 text-white"
    xmlns="http://www.w3.org/2000/svg"
    fill="none"
    viewBox="0 0 24 24"
    stroke="currentColor"
    aria-hidden="true"
  >
    {/*  */}
    <path
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth="2"
      d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122"
    />
  </svg>
);

const StatsItem = ({ icon, heading, stat, statIncreasedBy, statDecreasedBy }) => (

{icon}

{heading}

{stat}

            {statIncreasedBy && (

                <svg
                  className="self-center flex-shrink-0 h-5 w-5 text-green-500"
                  fill="currentColor"
                  viewBox="0 0 20 20"
                  aria-hidden="true"
                >
                  <path
                    fillRule="evenodd"
                    d="M5.293 9.707a1 1 0 010-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 01-1.414 1.414L11 7.414V15a1 1 0 11-2 0V7.414L6.707 9.707a1 1 0 01-1.414 0z"
                    clipRule="evenodd"
                  />
                </svg>
                Increased by
                {statIncreasedBy}

            )}
            {statDecreasedBy && (

                <svg
                  className="self-center flex-shrink-0 h-5 w-5 text-red-500"
                  fill="currentColor"
                  viewBox="0 0 20 20"
                  aria-hidden="true"
                >
                  <path
                    fillRule="evenodd"
                    d="M14.707 10.293a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 111.414-1.414L9 12.586V5a1 1 0 012 0v7.586l2.293-2.293a1 1 0 011.414 0z"
                    clipRule="evenodd"
                  />
                </svg>
                Decreased by
                {statDecreasedBy}

            )}

    {/*

          {' '}
          View all {heading} stats

 */}

);

const DatesFromUntil = ({ from, until }) => (

    {getDate(from)} - {getDate(until)}

);

const HomePage = () => {
  const {
    data: {
      statsGlobal,
      statsGlobal: {
        commitDateFirst,
        commitDateLast,
        commits,
        commitsImpactGtThousand,
        commitsOnWeekend,
        commitsPerContributorAverage,
        // commitsPerDay,
        commitsPerDayAverage,
        // commitsPerMonthDay,
        // commitsPerMonthNr,
        // commitsPerYear,
        commitsWithoutFileChanges,
        commitsWithoutImpact,
        contributors,
        // contributorsList,
        daysActive,
        daysSinceFirstCommit,
        daysSinceLastCommit,
        fileChanges,
        lines,
        repositories,
        // repositoriesList,
        staleness,
        // weekdays,
      } = {},
    } = {},
  } = useQuery(statsGlobalQuery);
  return (
    <Wrapper pageType="home">

Global Stats

        <DatesFromUntil from={commitDateFirst} until={commitDateLast} />

      {statsGlobal && (
        <>

            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Repositories"
              stat={thousandify(repositories)}
            />
            <StatsItem
              icon={<HeroIconUsers />}
              heading="Contributors"
              stat={thousandify(contributors)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Commits"
              stat={thousandify(commits)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Commits impact > thousand"
              stat={thousandify(commitsImpactGtThousand)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Commits on weekends"
              stat={thousandify(commitsOnWeekend)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Average commits / contributor"
              stat={commitsPerContributorAverage.toFixed(2)}
            />
            {/* <StatsItem
              icon={<HeroIconCursorClick />}
              heading="commitsPerDay"
              stat={commitsPerDay}
            /> */}
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Average commits / day"
              stat={commitsPerDayAverage.toFixed(2)}
            />
            {/* <StatsItem
              icon={<HeroIconCursorClick />}
              heading="commitsPerMonthDay"
              stat={commitsPerMonthDay}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="commitsPerMonthNr"
              stat={commitsPerMonthNr}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="commitsPerYear"
              stat={commitsPerYear}
            /> */}
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Commits without file changes"
              stat={thousandify(commitsWithoutFileChanges)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Commits without impact"
              stat={thousandify(commitsWithoutImpact)}
            />
            {/* <StatsItem
              icon={<HeroIconCursorClick />}
              heading="contributorsList"
              stat={contributorsList}
            /> */}
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Days between first and last commit"
              stat={thousandify(daysActive)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Days since first commit"
              stat={thousandify(daysSinceFirstCommit)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Days since last commit"
              stat={thousandify(daysSinceLastCommit)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="File changes"
              stat={thousandify(fileChanges)}
            />
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Lines of code"
              stat={thousandify(lines)}
            />
            {/* <StatsItem
              icon={<HeroIconCursorClick />}
              heading="repositoriesList"
              stat={repositoriesList}
            /> */}
            <StatsItem
              icon={<HeroIconCursorClick />}
              heading="Staleness"
              stat={staleness.toFixed(2)}
            />
            {/* <StatsItem icon={<HeroIconCursorClick />} heading="weekdays" stat={weekdays} /> */}

        </>
      )}
    </Wrapper>
  );
};
export default HomePage;
<|endoftext|>


<commit_before>/**
 * [Chart.PieceLabel.js]{@link https://github.com/emn178/Chart.PieceLabel.js}
 *
 * @version 0.2.0
 * @author Chen, Yi-Cyuan [emn178@gmail.com]
 * @copyright Chen, Yi-Cyuan 2017
 * @license MIT
 */
(function () {
  function drawArcText(context, str, centerX, centerY, radius, startAngle, endAngle) {
    context.save();
    context.translate(centerX, centerY);
    startAngle += Math.PI / 2;
    endAngle += Math.PI / 2;
    var mertrics = context.measureText(str);
    startAngle += (endAngle - (mertrics.width / radius + startAngle)) / 2;
    context.rotate(startAngle);
    for (var i = 0; i < str.length; i++) {
      var char = str.charAt(i);
      mertrics = context.measureText(char);
      context.save();
      context.translate(0, -1 * radius);
      context.fillText(char, 0, 0);
      context.restore();
      context.rotate(mertrics.width / radius);
    }
    context.restore();
  }

  Chart.pluginService.register({
    afterDraw: function (chartInstance) {
      if (!chartInstance.options.pieceLabel) {
        return;
      }
      var ctx = chartInstance.chart.ctx,
        options = chartInstance.config.options,
        arcText = chartInstance.options.pieceLabel.arcText || false,
        format = chartInstance.options.pieceLabel.format,
        precision = chartInstance.options.pieceLabel.precision || 0,
        fontSize = chartInstance.options.pieceLabel.fontSize || options.defaultFontSize,
        fontColor = chartInstance.options.pieceLabel.fontColor || '#fff',
        fontStyle = chartInstance.options.pieceLabel.fontStyle || options.defaultFontStyle,
        fontFamily = chartInstance.options.pieceLabel.fontFamily || options.defaultFontFamily,
        hasTooltip = chartInstance.tooltip._active && chartInstance.tooltip._active.length;

      chartInstance.config.data.datasets.forEach(function (dataset, datasetIndex) {
        var meta = dataset._meta[Object.keys(dataset._meta)[0]];
        var totalPercentage = 0;
        for (var i = 0; i < meta.data.length; i++) {
          var element = meta.data[i],
            view = element._view;

          if (hasTooltip) {
            element.draw();
          }

          var text;
          switch (chartInstance.options.pieceLabel.mode) {
            case 'value':
              var value = dataset.data[i];
              if (format) {
                value = format(value);
              }
              text = value.toString();
              break;
            case 'label':
              text = chartInstance.config.data.labels[i];
              break;
            case 'percentage':
            default:
              var percentage = view.circumference / options.circumference * 100;
              percentage = parseFloat(percentage.toFixed(precision));
              totalPercentage += percentage;
              if (totalPercentage > 100) {
                percentage -= totalPercentage - 100;
              }
              text = percentage + '%';
              break;
          }
          ctx.save();
          ctx.beginPath();
          ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
          var mertrics = ctx.measureText(text);
          var tooltipPosition = element.tooltipPosition();
          var left = tooltipPosition.x - mertrics.width / 2,
            right = tooltipPosition.x + mertrics.width / 2,
            top = tooltipPosition.y - fontSize / 2,
            bottom = tooltipPosition.y + fontSize / 2;
          var inRange = element.inRange(left, top) && element.inRange(left, bottom) &&
            element.inRange(right, top) && element.inRange(right, bottom);
          if (inRange) {
            ctx.fillStyle = fontColor;
            if (arcText) {
              ctx.textBaseline = 'middle';
              drawArcText(ctx, text, view.x, view.y, (view.innerRadius + view.outerRadius) / 2, view.startAngle, view.endAngle);
            } else {
              ctx.textBaseline = 'top';
              ctx.textAlign = 'center';
              ctx.fillText(text, tooltipPosition.x, tooltipPosition.y - fontSize / 2);
            }
          }
          ctx.restore();
        }
      });

      if (hasTooltip) {
        chartInstance.tooltip.draw();
      }
    }
  });
})();
<commit_msg>Fix: Fix to show percentage if it goes above 100%<commit_after>/**
 * [Chart.PieceLabel.js]{@link https://github.com/emn178/Chart.PieceLabel.js}
 *
 * @version 0.2.0
 * @author Chen, Yi-Cyuan [emn178@gmail.com]
 * @copyright Chen, Yi-Cyuan 2017
 * @license MIT
 */
(function () {
  function drawArcText(context, str, centerX, centerY, radius, startAngle, endAngle) {
    context.save();
    context.translate(centerX, centerY);
    startAngle += Math.PI / 2;
    endAngle += Math.PI / 2;
    var mertrics = context.measureText(str);
    startAngle += (endAngle - (mertrics.width / radius + startAngle)) / 2;
    context.rotate(startAngle);
    for (var i = 0; i < str.length; i++) {
      var char = str.charAt(i);
      mertrics = context.measureText(char);
      context.save();
      context.translate(0, -1 * radius);
      context.fillText(char, 0, 0);
      context.restore();
      context.rotate(mertrics.width / radius);
    }
    context.restore();
  }

  Chart.pluginService.register({
    afterDraw: function (chartInstance) {
      if (!chartInstance.options.pieceLabel) {
        return;
      }
      var ctx = chartInstance.chart.ctx,
        options = chartInstance.config.options,
        arcText = chartInstance.options.pieceLabel.arcText || false,
        format = chartInstance.options.pieceLabel.format,
        precision = chartInstance.options.pieceLabel.precision || 0,
        fontSize = chartInstance.options.pieceLabel.fontSize || options.defaultFontSize,
        fontColor = chartInstance.options.pieceLabel.fontColor || '#fff',
        fontStyle = chartInstance.options.pieceLabel.fontStyle || options.defaultFontStyle,
        fontFamily = chartInstance.options.pieceLabel.fontFamily || options.defaultFontFamily,
        hasTooltip = chartInstance.tooltip._active && chartInstance.tooltip._active.length;

      chartInstance.config.data.datasets.forEach(function (dataset, datasetIndex) {
        var meta = dataset._meta[Object.keys(dataset._meta)[0]];
        var totalPercentage = 0;
        for (var i = 0; i < meta.data.length; i++) {
          var element = meta.data[i],
            view = element._view;

          if (hasTooltip) {
            element.draw();
          }

          var text;
          switch (chartInstance.options.pieceLabel.mode) {
            case 'value':
              var value = dataset.data[i];
              if (format) {
                value = format(value);
              }
              text = value.toString();
              break;
            case 'label':
              text = chartInstance.config.data.labels[i];
              break;
            case 'percentage':
            default:
              var percentage = view.circumference / options.circumference * 100;
              percentage = parseFloat(percentage.toFixed(precision));
              totalPercentage += percentage;
              if (totalPercentage > 100) {
                percentage -= totalPercentage - 100;
                // After adjusting the percentage, need to trim the numbers after decimal points again, otherwise it may not show
                // on chart due to very long number after decimal point.
                percentage = parseFloat(percentage.toFixed(precision));
              }
              text = percentage + '%';
              break;
          }
          ctx.save();
          ctx.beginPath();
          ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
          var mertrics = ctx.measureText(text);
          var tooltipPosition = element.tooltipPosition();
          var left = tooltipPosition.x - mertrics.width / 2,
            right = tooltipPosition.x + mertrics.width / 2,
            top = tooltipPosition.y - fontSize / 2,
            bottom = tooltipPosition.y + fontSize / 2;
          var inRange = element.inRange(left, top) && element.inRange(left, bottom) &&
            element.inRange(right, top) && element.inRange(right, bottom);
          if (inRange) {
            ctx.fillStyle = fontColor;
            if (arcText) {
              ctx.textBaseline = 'middle';
              drawArcText(ctx, text, view.x, view.y, (view.innerRadius + view.outerRadius) / 2, view.startAngle, view.endAngle);
            } else {
              ctx.textBaseline = 'top';
              ctx.textAlign = 'center';
              ctx.fillText(text, tooltipPosition.x, tooltipPosition.y - fontSize / 2);
            }
          }
          ctx.restore();
        }
      });

      if (hasTooltip) {
        chartInstance.tooltip.draw();
      }
    }
  });
})();
<|endoftext|>