<commit_before>/**********************************************************************
 Freeciv - Copyright (C) 2009 - Andreas Røsdal   andrearo@pvv.ntnu.no
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
***********************************************************************/

var error_shown = false;
var syncTimerId = -1;
var isWorking = false;

var clinet_last_send = 0;
var debug_client_speed_list = [];

var freeciv_version = "+Freeciv.Web.Devel-2.6-2014.Apr.02b";

var ws = null;
var civserverport = null;

/****************************************************************************
  Initialized the Network communication, by requesting a valid server port.
****************************************************************************/
function network_init()
{

  if (!"WebSocket" in window) {
    alert("WebSockets not supported");
    return;
  }

  var civclient_request_url = "/civclientlauncher";
  if ($.getUrlVar('action') != null) civclient_request_url += "?action=" + $.getUrlVar('action');
  if ($.getUrlVar('civserverport') != null) civclient_request_url += "&civserverport=" + $.getUrlVar('civserverport');

  $.ajax({
   type: 'POST',
   url: civclient_request_url,
   success: function(data, textStatus, request){
       civserverport = request.getResponseHeader('port');
       var connect_result = request.getResponseHeader('result');
       if (civserverport != null && connect_result == "success") {
         websocket_init();
         load_game_check();

       } else {
         show_dialog_message("Network error", "Invalid server port. Error: " + connect_result);
       }
   },
   error: function (request, textStatus, errorThrown) {
	show_dialog_message("Network error", "Unable to communicate with civclientlauncher servlet . Error: "
		+ textStatus + " " + errorThrown + " " + request.getResponseHeader('result'));
   }
  });

}

/****************************************************************************
  Initialized the WebSocket connection.
****************************************************************************/
function websocket_init()
{
  ws = new ReconnectingWebSocket("ws://" + window.location.hostname + "/civsocket");

  ws.onopen = function () {
    var login_message = {"type":4, "username" : username,
    "capability": freeciv_version, "version_label": "-dev",
    "major_version" : 2, "minor_version" : 5, "patch_version" : 99,
    "port": civserverport};
    ws.send(JSON.stringify(login_message));
  };

  ws.onmessage = function (event) {
     if (typeof client_handle_packet !== 'undefined') {
       client_handle_packet(jQuery.parseJSON(event.data));
     } else {
       console.error("Error, freeciv-web not compiled correctly. Please "
             + "run sync.sh in freeciv-proxy correctly.");
     }
  };

  ws.onclose = function (event) {
   console.debug("WebSocket connection closed, reconnecting: " + event.code + ", " + event.reason);
  };

  ws.onerror = function (evt) {
   show_dialog_message("Network error", "Unable to communicate with server using WebSockets. Error: " + evt);
   console.error("Unable to communicate with server using WebSockets. Error: " + evt);
  };
}

/****************************************************************************
  Stops network sync.
****************************************************************************/
function network_stop()
{
  ws.close();
  ws = null;
}

/****************************************************************************
  Sends a request to the server, with a JSON packet.
****************************************************************************/
function send_request(packet_payload)
{
  if (ws != null) {
    ws.send(packet_payload);
  }

  if (debug_active) {
    clinet_last_send = new Date().getTime();
  }
}

/****************************************************************************
...
****************************************************************************/
function clinet_debug_collect()
{
  var time_elapsed = new Date().getTime() - clinet_last_send;
  debug_client_speed_list.push(time_elapsed);
  clinet_last_send = new Date().getTime();
}
<commit_msg>Set reconnectInterval and debug logging level for connection errors.<commit_after>/**********************************************************************
 Freeciv - Copyright (C) 2009 - Andreas Røsdal   andrearo@pvv.ntnu.no
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
***********************************************************************/

var error_shown = false;
var syncTimerId = -1;
var isWorking = false;

var clinet_last_send = 0;
var debug_client_speed_list = [];

var freeciv_version = "+Freeciv.Web.Devel-2.6-2014.Apr.02b";

var ws = null;
var civserverport = null;

/****************************************************************************
  Initialized the Network communication, by requesting a valid server port.
****************************************************************************/
function network_init()
{

  if (!"WebSocket" in window) {
    alert("WebSockets not supported");
    return;
  }

  var civclient_request_url = "/civclientlauncher";
  if ($.getUrlVar('action') != null) civclient_request_url += "?action=" + $.getUrlVar('action');
  if ($.getUrlVar('civserverport') != null) civclient_request_url += "&civserverport=" + $.getUrlVar('civserverport');

  $.ajax({
   type: 'POST',
   url: civclient_request_url,
   success: function(data, textStatus, request){
       civserverport = request.getResponseHeader('port');
       var connect_result = request.getResponseHeader('result');
       if (civserverport != null && connect_result == "success") {
         websocket_init();
         load_game_check();

       } else {
         show_dialog_message("Network error", "Invalid server port. Error: " + connect_result);
       }
   },
   error: function (request, textStatus, errorThrown) {
	show_dialog_message("Network error", "Unable to communicate with civclientlauncher servlet . Error: "
		+ textStatus + " " + errorThrown + " " + request.getResponseHeader('result'));
   }
  });

}

/****************************************************************************
  Initialized the WebSocket connection.
****************************************************************************/
function websocket_init()
{
  ws = new ReconnectingWebSocket("ws://" + window.location.hostname + "/civsocket");
  ws.reconnectInterval = 10000;

  ws.onopen = function () {
    var login_message = {"type":4, "username" : username,
    "capability": freeciv_version, "version_label": "-dev",
    "major_version" : 2, "minor_version" : 5, "patch_version" : 99,
    "port": civserverport};
    ws.send(JSON.stringify(login_message));
  };

  ws.onmessage = function (event) {
     if (typeof client_handle_packet !== 'undefined') {
       client_handle_packet(jQuery.parseJSON(event.data));
     } else {
       console.error("Error, freeciv-web not compiled correctly. Please "
             + "run sync.sh in freeciv-proxy correctly.");
     }
  };

  ws.onclose = function (event) {
   console.debug("WebSocket connection closed, reconnecting: " + event.code + ", " + event.reason);
  };

  ws.onerror = function (evt) {
   show_dialog_message("Network error", "A problem occured with the WebSocket connection to the server. Error:" + evt);
   console.debug("Unable to communicate with server using WebSockets. Error: " + evt);
  };
}

/****************************************************************************
  Stops network sync.
****************************************************************************/
function network_stop()
{
  ws.close();
  ws = null;
}

/****************************************************************************
  Sends a request to the server, with a JSON packet.
****************************************************************************/
function send_request(packet_payload)
{
  if (ws != null) {
    ws.send(packet_payload);
  }

  if (debug_active) {
    clinet_last_send = new Date().getTime();
  }
}

/****************************************************************************
...
****************************************************************************/
function clinet_debug_collect()
{
  var time_elapsed = new Date().getTime() - clinet_last_send;
  debug_client_speed_list.push(time_elapsed);
  clinet_last_send = new Date().getTime();
}
<|endoftext|>


<commit_before>import { Session } from 'meteor/session';
import { Template } from 'meteor/templating';
import { $ } from 'meteor/jquery';
import { BigNumber } from 'meteor/ethereum:web3';
import { web3 } from 'meteor/makerotc:dapple';
import { formatError } from '/imports/utils/functions';

import Tokens from '/imports/api/tokens';
import { Offers, Status } from '/imports/api/offers';

import './offermodal.html';

// TODO: DELETE THIS, TESTING PURPOSE
window.Tokens = Tokens;

Template.offermodal.viewmodel({
  share: 'newOffer',
  volume: '',
  total: '',
  autorun() {
    if (Template.currentData().offer) {
      const buyHowMuch = web3.fromWei(new BigNumber(Template.currentData().offer.buyHowMuch)).toString(10);
      const sellHowMuch = web3.fromWei(new BigNumber(Template.currentData().offer.sellHowMuch)).toString(10);
      const baseCurrency = Session.get('baseCurrency');
      if (baseCurrency === Template.currentData().offer.buyWhichToken) {
        this.volume(buyHowMuch);
        this.total(sellHowMuch);
      } else {
        this.volume(sellHowMuch);
        this.total(buyHowMuch);
      }
    }
  },
  precision() {
    return Dapple.getTokenSpecs(Session.get('baseCurrency')).precision;
  },
  validAmount: true,
  type() {
    if (Template.currentData().offer) {
      return Template.currentData().offer.type();
    }
    return '';
  },
  buyCurrency() {
    return this.type() === 'bid' ? Session.get('quoteCurrency') : Session.get('baseCurrency');
  },
  sellCurrency() {
    return this.type() === 'bid' ? Session.get('baseCurrency') : Session.get('quoteCurrency');
  },
  quoteToken() {
    return Tokens.findOne(Session.get('quoteCurrency'));
  },
  baseToken() {
    return Tokens.findOne(Session.get('baseCurrency'));
  },
  hasBalance() {
    try {
      const token = Tokens.findOne(this.sellCurrency());
      const balance = new BigNumber(token.balance);
      return token && balance.gte(web3.toWei(new BigNumber(this.type() === 'bid' ? this.volume() : this.total())));
    } catch (e) {
      return false;
    }
  },
  hasAllowance() {
    try {
      const token = Tokens.findOne(this.sellCurrency());
      const allowance = new BigNumber(token.allowance);
      return token && allowance.gte(web3.toWei(new BigNumber(this.type() === 'bid' ? this.volume() : this.total())));
    } catch (e) {
      return false;
    }
  },
  hasAllowanceNewOrder() {
    try {
      const token = Tokens.findOne(this.offerType() === 'buy'
                                                      ? Session.get('quoteCurrency') : Session.get('baseCurrency'));
      const allowance = new BigNumber(token.allowance);

      return token && allowance.gte(web3.toWei(new BigNumber(this.offerType() === 'buy'
                                                                       ? this.offerAmount() : this.offerTotal())));
    } catch (e) {
      return false;
    }
  },
  hasVolume() {
    try {
      const volume = new BigNumber(Template.currentData().offer.volume(this.buyCurrency()));
      return volume.gte(web3.toWei(new BigNumber(this.type() === 'bid' ? this.total() : this.volume())));
    } catch (e) {
      return false;
    }
  },
  maxVolume() {
    let maxVolume = '0';
    try {
      const baseCurrency = Session.get('baseCurrency');
      const volume = new BigNumber(Template.currentData().offer.volume(baseCurrency));
      if (Template.currentData().offer.buyWhichToken === baseCurrency) {
        // Calculate max volume, since we want to sell MKR, we need to check how much MKR we can sell
        const token = Tokens.findOne(baseCurrency);
        if (token) {
          // Can at most sell balance, allowance, and offer's volume
          const balance = new BigNumber(token.balance);
          const allowance = new BigNumber(token.allowance);
          maxVolume = web3.fromWei(BigNumber.min(balance, allowance, volume)).toString(10);
        }
      } else {
        maxVolume = web3.fromWei(volume).toString(10);
      }
    } catch (e) {
      maxVolume = '0';
    }
    return maxVolume;
  },
  maxTotal() {
    let maxTotal = '0';
    try {
      const quoteCurrency = Session.get('quoteCurrency');
      const total = new BigNumber(Template.currentData().offer.volume(quoteCurrency));
      if (Template.currentData().offer.buyWhichToken === quoteCurrency) {
        // Calculate max total, since we want to buy MKR, we need to check how much of the currency is available
        const token = Tokens.findOne(quoteCurrency);
        if (token) {
          // Can at most buy balance, allowance, and offer's total
          const balance = new BigNumber(token.balance);
          const allowance = new BigNumber(token.allowance);
          maxTotal = web3.fromWei(BigNumber.min(balance, allowance, total)).toString(10);
        }
      } else {
        maxTotal = web3.fromWei(total).toString(10);
      }
    } catch (e) {
      maxTotal = '0';
    }
    return maxTotal;
  },
  calcVolume() {
    this.validAmount(true);
    if (this.precision() === 0 && this.total() % 1 !== 0) {
      this.validAmount(false);
      this.volume('0');
      return;
    }
    try {
      const baseCurrency = Session.get('baseCurrency');
      const total = new BigNumber(this.total());
      const buyHowMuch = new BigNumber(this.templateInstance.data.offer.buyHowMuch);
      const sellHowMuch = new BigNumber(this.templateInstance.data.offer.sellHowMuch);
      if (this.templateInstance.data.offer.buyWhichToken === baseCurrency) {
        this.volume(buyHowMuch.div(sellHowMuch).times(total).toString(10));
      } else {
        this.volume(sellHowMuch.div(buyHowMuch).times(total).toString(10));
      }
    } catch (e) {
      this.volume('0');
    }
  },
  calcTotal() {
    this.validAmount(true);
    if (this.precision() === 0 && this.volume() % 1 !== 0) {
      this.validAmount(false);
      this.total('0');
      return;
    }
    try {
      const baseCurrency = Session.get('baseCurrency');
      const volume = new BigNumber(this.volume());
      const buyHowMuch = new BigNumber(this.templateInstance.data.offer.buyHowMuch);
      const sellHowMuch = new BigNumber(this.templateInstance.data.offer.sellHowMuch);
      if (this.templateInstance.data.offer.buyWhichToken === baseCurrency) {
        this.total(sellHowMuch.div(buyHowMuch).times(volume).toString(10));
      } else {
        this.total(buyHowMuch.div(sellHowMuch).times(volume).toString(10));
      }
    } catch (e) {
      this.total('0');
    }
  },
  dismiss(event) {
    $(event.target).closest('.modal').modal('hide');
  },
  cancel() {
    const offerId = this.templateInstance.data.offer._id;
    Offers.cancelOffer(offerId);
  },
  canBuy() {
    try {
      if (Template.currentData().offer.status !== Status.CONFIRMED) {
        return false;
      }
      const volume = new BigNumber(this.volume());
      const total = new BigNumber(this.total());
      const marketOpen = Session.get('market_open');
      return marketOpen && !total.isNaN() && total.gt(0) && total.lte(new BigNumber(this.maxTotal()))
        && !volume.isNaN() && volume.gt(0) && volume.lte(new BigNumber(this.maxVolume()));
    } catch (e) {
      return false;
    }
  },
  buy() {
    const offerId = this.templateInstance.data.offer._id;
    const offer = Offers.findOne(offerId);

    if (this.templateInstance.data.offer.type() === 'bid') {
      Offers.buyOffer(offerId, 'sell', new BigNumber(this.total()), offer.sellWhichToken);
    } else {
      Offers.buyOffer(offerId, 'buy', new BigNumber(this.volume()), offer.sellWhichToken);
    }
  },
  maxNewOfferAmount() {
    let maxAmount = '0';
    if (this.offerType() === 'sell') {
      const token = Tokens.findOne(Session.get('baseCurrency'));
      if (token) {
        const balance = new BigNumber(token.balance);
        const allowance = new BigNumber(token.allowance);
        maxAmount = web3.fromWei(BigNumber.min(balance, allowance).toString(10));
      }
    } else {
      maxAmount = '9e999';
    }
    return maxAmount;
  },
  maxNewOfferTotal() {
    // Only allow change of total if price is well-defined
    try {
      const price = new BigNumber(this.offerPrice());
      if ((price.isNaN() || price.isZero() || price.isNegative())) {
        return '0';
      }
    } catch (e) {
      return '0';
    }
    // If price is well-defined, take minimum of balance and allowance of currency, if 'buy', otherwise Infinity
    let maxTotal = '0';
    if (this.offerType() === 'buy') {
      const token = Tokens.findOne(Session.get('quoteCurrency'));
      if (token) {
        const balance = new BigNumber(token.balance);
        const allowance = new BigNumber(token.allowance);
        maxTotal = web3.fromWei(BigNumber.min(balance, allowance).toString(10));
      }
    } else {
      maxTotal = '9e999';
    }
    return maxTotal;
  },
  canSubmit() {
    try {
      const type = this.offerType();
      const price = new BigNumber(this.offerPrice());
      const amount = new BigNumber(this.offerAmount());
      const maxAmount = new BigNumber(this.maxNewOfferAmount());
      const total = new BigNumber(this.offerTotal());
      const maxTotal = new BigNumber(this.maxNewOfferTotal());
      const marketOpen = Session.get('market_open');
      const validTokenPair = Session.get('quoteCurrency') !== Session.get('baseCurrency');
      return marketOpen && price.gt(0) && amount.gt(0) && total.gt(0) && validTokenPair &&
        (type !== 'buy' || total.lte(maxTotal)) && (type !== 'sell' || amount.lte(maxAmount));
    } catch (e) {
      return false;
    }
  },
  confirmOffer(event) {
    event.preventDefault();

    this.offerError('');
    let sellHowMuch;
    let sellWhichToken;
    let buyHowMuch;
    let buyWhichToken;
    if (this.offerType() === 'buy') {
      sellWhichToken = Session.get('quoteCurrency');
      sellHowMuch = this.offerTotal();
      buyWhichToken = Session.get('baseCurrency');
      buyHowMuch = this.offerAmount();
    } else {
      sellWhichToken = Session.get('baseCurrency');
      sellHowMuch = this.offerAmount();
      buyWhichToken = Session.get('quoteCurrency');
      buyHowMuch = this.offerTotal();
    }
    Offers.newOffer(sellHowMuch, sellWhichToken, buyHowMuch, buyWhichToken, (error) => {
      if (error != null) {
        this.offerError(formatError(error));
      }
    });
  },
});

Template.offermodal.events({
  'click button.btn-allowance-modal': (event) => {
    const refer = $(event.target).data('refer');
    const token = $(event.target).data('link');
    $(`#allowanceModal${token}`).data('refer', refer);
    $(`#allowanceModal${token}`).modal('show');
  },
});
<commit_msg>Fix issue with allowance<commit_after>import { Session } from 'meteor/session';
import { Template } from 'meteor/templating';
import { $ } from 'meteor/jquery';
import { BigNumber } from 'meteor/ethereum:web3';
import { web3 } from 'meteor/makerotc:dapple';
import { formatError } from '/imports/utils/functions';

import Tokens from '/imports/api/tokens';
import { Offers, Status } from '/imports/api/offers';

import './offermodal.html';

// TODO: DELETE THIS, TESTING PURPOSE
window.Tokens = Tokens;

Template.offermodal.viewmodel({
  share: 'newOffer',
  volume: '',
  total: '',
  autorun() {
    if (Template.currentData().offer) {
      const buyHowMuch = web3.fromWei(new BigNumber(Template.currentData().offer.buyHowMuch)).toString(10);
      const sellHowMuch = web3.fromWei(new BigNumber(Template.currentData().offer.sellHowMuch)).toString(10);
      const baseCurrency = Session.get('baseCurrency');
      if (baseCurrency === Template.currentData().offer.buyWhichToken) {
        this.volume(buyHowMuch);
        this.total(sellHowMuch);
      } else {
        this.volume(sellHowMuch);
        this.total(buyHowMuch);
      }
    }
  },
  precision() {
    return Dapple.getTokenSpecs(Session.get('baseCurrency')).precision;
  },
  validAmount: true,
  type() {
    if (Template.currentData().offer) {
      return Template.currentData().offer.type();
    }
    return '';
  },
  buyCurrency() {
    return this.type() === 'bid' ? Session.get('quoteCurrency') : Session.get('baseCurrency');
  },
  sellCurrency() {
    return this.type() === 'bid' ? Session.get('baseCurrency') : Session.get('quoteCurrency');
  },
  quoteToken() {
    return Tokens.findOne(Session.get('quoteCurrency'));
  },
  baseToken() {
    return Tokens.findOne(Session.get('baseCurrency'));
  },
  hasBalance() {
    try {
      const token = Tokens.findOne(this.sellCurrency());
      const balance = new BigNumber(token.balance);
      return token && balance.gte(web3.toWei(new BigNumber(this.type() === 'bid' ? this.volume() : this.total())));
    } catch (e) {
      return false;
    }
  },
  hasAllowance() {
    try {
      const token = Tokens.findOne(this.sellCurrency());
      const allowance = new BigNumber(token.allowance);
      return token && allowance.gte(web3.toWei(new BigNumber(this.type() === 'bid' ? this.volume() : this.total())));
    } catch (e) {
      return false;
    }
  },
  hasAllowanceNewOrder() {
    try {
      const token = Tokens.findOne(this.offerType() === 'buy'
                                                      ? Session.get('quoteCurrency') : Session.get('baseCurrency'));
      const allowance = new BigNumber(token.allowance);

      return token && allowance.gte(web3.toWei(new BigNumber(this.offerType() === 'buy'
                                                                       ? this.offerTotal() : this.offerAmount())));
    } catch (e) {
      return false;
    }
  },
  hasVolume() {
    try {
      const volume = new BigNumber(Template.currentData().offer.volume(this.buyCurrency()));
      return volume.gte(web3.toWei(new BigNumber(this.type() === 'bid' ? this.total() : this.volume())));
    } catch (e) {
      return false;
    }
  },
  maxVolume() {
    let maxVolume = '0';
    try {
      const baseCurrency = Session.get('baseCurrency');
      const volume = new BigNumber(Template.currentData().offer.volume(baseCurrency));
      if (Template.currentData().offer.buyWhichToken === baseCurrency) {
        // Calculate max volume, since we want to sell MKR, we need to check how much MKR we can sell
        const token = Tokens.findOne(baseCurrency);
        if (token) {
          // Can at most sell balance, allowance, and offer's volume
          const balance = new BigNumber(token.balance);
          const allowance = new BigNumber(token.allowance);
          maxVolume = web3.fromWei(BigNumber.min(balance, allowance, volume)).toString(10);
        }
      } else {
        maxVolume = web3.fromWei(volume).toString(10);
      }
    } catch (e) {
      maxVolume = '0';
    }
    return maxVolume;
  },
  maxTotal() {
    let maxTotal = '0';
    try {
      const quoteCurrency = Session.get('quoteCurrency');
      const total = new BigNumber(Template.currentData().offer.volume(quoteCurrency));
      if (Template.currentData().offer.buyWhichToken === quoteCurrency) {
        // Calculate max total, since we want to buy MKR, we need to check how much of the currency is available
        const token = Tokens.findOne(quoteCurrency);
        if (token) {
          // Can at most buy balance, allowance, and offer's total
          const balance = new BigNumber(token.balance);
          const allowance = new BigNumber(token.allowance);
          maxTotal = web3.fromWei(BigNumber.min(balance, allowance, total)).toString(10);
        }
      } else {
        maxTotal = web3.fromWei(total).toString(10);
      }
    } catch (e) {
      maxTotal = '0';
    }
    return maxTotal;
  },
  calcVolume() {
    this.validAmount(true);
    if (this.precision() === 0 && this.total() % 1 !== 0) {
      this.validAmount(false);
      this.volume('0');
      return;
    }
    try {
      const baseCurrency = Session.get('baseCurrency');
      const total = new BigNumber(this.total());
      const buyHowMuch = new BigNumber(this.templateInstance.data.offer.buyHowMuch);
      const sellHowMuch = new BigNumber(this.templateInstance.data.offer.sellHowMuch);
      if (this.templateInstance.data.offer.buyWhichToken === baseCurrency) {
        this.volume(buyHowMuch.div(sellHowMuch).times(total).toString(10));
      } else {
        this.volume(sellHowMuch.div(buyHowMuch).times(total).toString(10));
      }
    } catch (e) {
      this.volume('0');
    }
  },
  calcTotal() {
    this.validAmount(true);
    if (this.precision() === 0 && this.volume() % 1 !== 0) {
      this.validAmount(false);
      this.total('0');
      return;
    }
    try {
      const baseCurrency = Session.get('baseCurrency');
      const volume = new BigNumber(this.volume());
      const buyHowMuch = new BigNumber(this.templateInstance.data.offer.buyHowMuch);
      const sellHowMuch = new BigNumber(this.templateInstance.data.offer.sellHowMuch);
      if (this.templateInstance.data.offer.buyWhichToken === baseCurrency) {
        this.total(sellHowMuch.div(buyHowMuch).times(volume).toString(10));
      } else {
        this.total(buyHowMuch.div(sellHowMuch).times(volume).toString(10));
      }
    } catch (e) {
      this.total('0');
    }
  },
  dismiss(event) {
    $(event.target).closest('.modal').modal('hide');
  },
  cancel() {
    const offerId = this.templateInstance.data.offer._id;
    Offers.cancelOffer(offerId);
  },
  canBuy() {
    try {
      if (Template.currentData().offer.status !== Status.CONFIRMED) {
        return false;
      }
      const volume = new BigNumber(this.volume());
      const total = new BigNumber(this.total());
      const marketOpen = Session.get('market_open');
      return marketOpen && !total.isNaN() && total.gt(0) && total.lte(new BigNumber(this.maxTotal()))
        && !volume.isNaN() && volume.gt(0) && volume.lte(new BigNumber(this.maxVolume()));
    } catch (e) {
      return false;
    }
  },
  buy() {
    const offerId = this.templateInstance.data.offer._id;
    const offer = Offers.findOne(offerId);

    if (this.templateInstance.data.offer.type() === 'bid') {
      Offers.buyOffer(offerId, 'sell', new BigNumber(this.total()), offer.sellWhichToken);
    } else {
      Offers.buyOffer(offerId, 'buy', new BigNumber(this.volume()), offer.sellWhichToken);
    }
  },
  maxNewOfferAmount() {
    let maxAmount = '0';
    if (this.offerType() === 'sell') {
      const token = Tokens.findOne(Session.get('baseCurrency'));
      if (token) {
        const balance = new BigNumber(token.balance);
        const allowance = new BigNumber(token.allowance);
        maxAmount = web3.fromWei(BigNumber.min(balance, allowance).toString(10));
      }
    } else {
      maxAmount = '9e999';
    }
    return maxAmount;
  },
  maxNewOfferTotal() {
    // Only allow change of total if price is well-defined
    try {
      const price = new BigNumber(this.offerPrice());
      if ((price.isNaN() || price.isZero() || price.isNegative())) {
        return '0';
      }
    } catch (e) {
      return '0';
    }
    // If price is well-defined, take minimum of balance and allowance of currency, if 'buy', otherwise Infinity
    let maxTotal = '0';
    if (this.offerType() === 'buy') {
      const token = Tokens.findOne(Session.get('quoteCurrency'));
      if (token) {
        const balance = new BigNumber(token.balance);
        const allowance = new BigNumber(token.allowance);
        maxTotal = web3.fromWei(BigNumber.min(balance, allowance).toString(10));
      }
    } else {
      maxTotal = '9e999';
    }
    return maxTotal;
  },
  canSubmit() {
    try {
      const type = this.offerType();
      const price = new BigNumber(this.offerPrice());
      const amount = new BigNumber(this.offerAmount());
      const maxAmount = new BigNumber(this.maxNewOfferAmount());
      const total = new BigNumber(this.offerTotal());
      const maxTotal = new BigNumber(this.maxNewOfferTotal());
      const marketOpen = Session.get('market_open');
      const validTokenPair = Session.get('quoteCurrency') !== Session.get('baseCurrency');
      return marketOpen && price.gt(0) && amount.gt(0) && total.gt(0) && validTokenPair &&
        (type !== 'buy' || total.lte(maxTotal)) && (type !== 'sell' || amount.lte(maxAmount));
    } catch (e) {
      return false;
    }
  },
  confirmOffer(event) {
    event.preventDefault();

    this.offerError('');
    let sellHowMuch;
    let sellWhichToken;
    let buyHowMuch;
    let buyWhichToken;
    if (this.offerType() === 'buy') {
      sellWhichToken = Session.get('quoteCurrency');
      sellHowMuch = this.offerTotal();
      buyWhichToken = Session.get('baseCurrency');
      buyHowMuch = this.offerAmount();
    } else {
      sellWhichToken = Session.get('baseCurrency');
      sellHowMuch = this.offerAmount();
      buyWhichToken = Session.get('quoteCurrency');
      buyHowMuch = this.offerTotal();
    }
    Offers.newOffer(sellHowMuch, sellWhichToken, buyHowMuch, buyWhichToken, (error) => {
      if (error != null) {
        this.offerError(formatError(error));
      }
    });
  },
});

Template.offermodal.events({
  'click button.btn-allowance-modal': (event) => {
    const refer = $(event.target).data('refer');
    const token = $(event.target).data('link');
    $(`#allowanceModal${token}`).data('refer', refer);
    $(`#allowanceModal${token}`).modal('show');
  },
});
<|endoftext|>


<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2020
 */

import { UIDatabase } from '../database';
import { Sensor } from '../database/DataTypes';

export const TEMPERATURE_SYNC_ACTIONS = {
  SCAN_START: 'TemperatureSync/scanStart',
  SCAN_COMPLETE: 'TemperatureSync/scanComplete',
  SCAN_ERROR: 'TemperatureSync/scanError',
};

const scanStart = () => ({ type: TEMPERATURE_SYNC_ACTIONS.SCAN_START });
const scanComplete = () => ({ type: TEMPERATURE_SYNC_ACTIONS.SCAN_COMPLETE });
const scanError = () => ({ type: TEMPERATURE_SYNC_ACTIONS.SCAN_ERROR });

const updateSensors = sensorAdvertisements => dispatch => {
  const isArray = Object.isArray(sensorAdvertisements);

  if (!isArray) dispatch(scanError());
  if (isArray && !sensorAdvertisements.length) dispatch(scanError());

  if (isArray && sensorAdvertisements.length) {
    sensorAdvertisements.forEach(({ macAddress, batteryLevel }) => {
      UIDatabase.write(() => {
        UIDatabase.update('Sensor', {
          ...UIDatabase.get('Sensor', 'macAddress', macAddress),
          macAddress,
          batteryLevel,
        });
      });
    });
  }
};

const scanForSensors = () => async dispatch => {
  dispatch(scanStart());

  const sensorResult = await Sensor.startScan();
  const { success, data } = sensorResult;

  dispatch(updateSensors(data));

  if (success) dispatch(scanComplete());
};

export const TemperatureSyncActions = {
  scanForSensors,
};
<commit_msg>Add updates with correct syntax<commit_after>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2020
 */

import { generateUUID } from 'react-native-database';

import { UIDatabase } from '../database';
import { Sensor } from '../database/DataTypes';

export const TEMPERATURE_SYNC_ACTIONS = {
  SCAN_START: 'TemperatureSync/scanStart',
  SCAN_COMPLETE: 'TemperatureSync/scanComplete',
  SCAN_ERROR: 'TemperatureSync/scanError',
};

const scanStart = () => ({ type: TEMPERATURE_SYNC_ACTIONS.SCAN_START });
const scanComplete = () => ({ type: TEMPERATURE_SYNC_ACTIONS.SCAN_COMPLETE });
const scanError = () => ({ type: TEMPERATURE_SYNC_ACTIONS.SCAN_ERROR });

const updateSensors = sensorAdvertisements => dispatch => {
  const isArray = Array.isArray(sensorAdvertisements);

  if (!isArray) dispatch(scanError());
  if (isArray && !sensorAdvertisements.length) dispatch(scanError());

  if (isArray && sensorAdvertisements.length) {
    sensorAdvertisements.forEach(({ macAddress, batteryLevel }) => {
      UIDatabase.write(() => {
        UIDatabase.update('Sensor', {
          id: generateUUID(),
          ...UIDatabase.get('Sensor', 'macAddress', macAddress),
          macAddress,
          batteryLevel,
        });
      });
    });
  }
};

const scanForSensors = () => async dispatch => {
  dispatch(scanStart());

  const sensorResult = await Sensor.startScan();
  const { success, data } = sensorResult;

  dispatch(updateSensors(data));

  if (success) dispatch(scanComplete());
};

export const TemperatureSyncActions = {
  scanForSensors,
};
<|endoftext|>


<commit_before>'use strict';

var common = require('../../../server/common');

/**
 * Create an express server
 *
 * @param {Object} options
 *    - port port to listen to. Defaults to 0.
 *    - hostname hostname to bind to. Defaults to 0.0.0.0.
 *
 * @returns {Promise} Promise that resolves with the value of the server
 *                    process when it is listening.
 */
module.exports = function(options, debug) {
  options = options || {};

  var server = common.createHTTPServer(options);

  return common.whenListening(server, debug);
};
<commit_msg>Update Pizza server to use correct common API<commit_after>'use strict';

var common = require('../../../server/common');

/**
 * Create an express server
 *
 * @param {Object} options
 *    - port port to listen to. Defaults to 0.
 *    - hostname hostname to bind to. Defaults to 0.0.0.0.
 *
 * @returns {Promise} Promise that resolves with the value of the server
 *                    process when it is listening.
 */
module.exports = function(options, debug) {
  options = options || {};

  var app = common.createExpressServer(options);
  var server = app.listen(options.port || 0);

  return common.whenListening(server, debug);
};
<|endoftext|>


<commit_before>$(function() {
    window.chat = {
        init: function() {
            this.chatLog = $('.chat-history');
            this.chatLogList = this.chatLog.find('ul');
            this.userList = $('.people-list .list');
            this.sendButton = $('button');
            this.textArea = $('#message-to-send');
            this.sendButton.on('click', this.sendMessage.bind(this));
            this.textArea.on('keyup', this.sendMessageReturn.bind(this));
            this.responseTemplateContent = $('#message-response-template').html();
            this.userMessageTemplateContent = $("#message-template").html();
            this.userConnectedTemplate = $("#user-connected-template").html();
            this.loginForm = $('#login');
            this.loginForm.submit(this.performLogin.bind(this));
            this.typingIndicator = $('#typing');
            this.socket = io();
            this.socket
                .on('ready', this.socketReady.bind(this))
                .on('delete_message', this.deleteMessage.bind(this))
                .on('bot_is_typing', this.botIsTyping.bind(this))
                .on('add_reaction_to', this.addReactionTo.bind(this))
                .on('bot_said', this.processBotMessage.bind(this))
                .on('user_said', this.appendResponse.bind(this))
                .on('user_connected', this.userConnected.bind(this))
                .on('user_disconnected', this.userDisconnected.bind(this))
                .on('extra_metadata', this.extraMetadata.bind(this));
        },
        addUser: function(user) {
            if ($('[data-user-id="' + user.id + '"]').length === 0) {
                this.userList.append(Mustache.render(this.userConnectedTemplate, user));
            }
        },
        performLogin: function(e) {
            e.preventDefault();
            e.stopPropagation();
            this.socket.emit('identify', {
                name:       $('#name').val(),
                username:   $('#username').val()
            });
            return false;
        },
        sendMessageReturn: function(e) {
            if(e.keyCode === 13) {
                e.preventDefault();
                e.stopPropagation();
                this.sendMessage();
                return false;
            }
        },
        sendMessage: function() {
            var v = this.textArea.val().trim();
            if(v.length) {
                this.socket.emit('message', { text: v, ts: Date.now() });
                this.textArea.val('');
            }
        },
        scrollToBottom: function() {
            this.chatLog.scrollTop(this.chatLog[0].scrollHeight);
        },
        appendResponse: function(incomingMessage) {
            var context = {
                time: new Date().toLocaleTimeString().replace(/([\d]+:[\d]{2})(:[\d]{2})(.*)/, "$1$3"),
                ts: incomingMessage.ts,
                response: incomingMessage.text
            };
            var template;

            if(incomingMessage.user.id === this.userId) {
                context.from = 'You';
                template = this.userMessageTemplateContent;
            } else {
                context.from = incomingMessage.user.username;
                template = this.responseTemplateContent;
            }
            this.chatLogList.append(Mustache.render(template, context));
            this.scrollToBottom();
        },
        socketReady: function(msg) {
            this.userId = msg.id;
            $('.login').fadeOut(300, function() {
                this.textArea.focus();
            }.bind(this));
            msg.userList.forEach(this.addUser.bind(this));
        },
        deleteMessage: function(msg) {
            $('[data-ts="' + msg.ts + '"]').fadeOut(300, function() {
                $(this).remove();
            });
        },
        botIsTyping: function() {
            this.typingIndicator.fadeIn(300);
        },
        addReactionTo: function(msg) {
            console.log('addReactionTo', msg);
        },
        processBotMessage: function(msg) {
            this.typingIndicator.fadeOut(300);
            if(msg.to === 'channel' && !msg.channel) {
                this.appendResponse({
                    ts: msg.ts,
                    text: msg.message,
                    user: {
                        username: 'Giskard'
                    }
                });
            } else {
                console.log('processBotMessage', msg);
            }
            this.scrollToBottom();
        },
        userConnected: function(msg) {
            this.addUser(msg);
        },
        userDisconnected: function(msg) {
            $('[data-user-id="' + msg.id + '"]').remove();
        },
        extraMetadata: function(msg) {
            var _this = this;
            $('[data-ts="' + msg.ts + '"]').find('.message').append('
').find('img').load(function() {
                _this.scrollToBottom();
            });
        }
    };
    $('#typing').fadeOut(0);
    chat.init();
});
<commit_msg>Implement basic markdown engine, implement behaviour for bot messages on other channels<commit_after>$(function() {
    window.chat = {
        init: function() {
            this.chatLog = $('.chat-history');
            this.chatLogList = this.chatLog.find('ul');
            this.userList = $('.people-list .list');
            this.sendButton = $('button');
            this.textArea = $('#message-to-send');
            this.sendButton.on('click', this.sendMessage.bind(this));
            this.textArea.on('keyup', this.sendMessageReturn.bind(this));
            this.responseTemplateContent = $('#message-response-template').html();
            this.userMessageTemplateContent = $("#message-template").html();
            this.userConnectedTemplate = $("#user-connected-template").html();
            this.loginForm = $('#login');
            this.loginForm.submit(this.performLogin.bind(this));
            this.typingIndicator = $('#typing');
            this.socket = io();
            this.socket
                .on('ready', this.socketReady.bind(this))
                .on('delete_message', this.deleteMessage.bind(this))
                .on('bot_is_typing', this.botIsTyping.bind(this))
                .on('add_reaction_to', this.addReactionTo.bind(this))
                .on('bot_said', this.processBotMessage.bind(this))
                .on('user_said', this.appendResponse.bind(this))
                .on('user_connected', this.userConnected.bind(this))
                .on('user_disconnected', this.userDisconnected.bind(this))
                .on('extra_metadata', this.extraMetadata.bind(this));
        },
        addUser: function(user) {
            if ($('[data-user-id="' + user.id + '"]').length === 0) {
                this.userList.append(Mustache.render(this.userConnectedTemplate, user));
            }
        },
        performLogin: function(e) {
            e.preventDefault();
            e.stopPropagation();
            this.socket.emit('identify', {
                name:       $('#name').val(),
                username:   $('#username').val()
            });
            return false;
        },
        sendMessageReturn: function(e) {
            if(e.keyCode === 13) {
                e.preventDefault();
                e.stopPropagation();
                this.sendMessage();
                return false;
            }
        },
        sendMessage: function() {
            var v = this.textArea.val().trim();
            if(v.length) {
                this.socket.emit('message', { text: v, ts: Date.now() });
                this.textArea.val('');
            }
        },
        scrollToBottom: function() {
            this.chatLog.scrollTop(this.chatLog[0].scrollHeight);
        },
        appendResponse: function(incomingMessage) {
            var context = {
                time: new Date().toLocaleTimeString().replace(/([\d]+:[\d]{2})(:[\d]{2})(.*)/, "$1$3"),
                ts: incomingMessage.ts,
                response: this.formatText(incomingMessage.text),
                channel: incomingMessage.channel
            };
            var template;

            if(incomingMessage.user.id === this.userId) {
                context.from = 'You';
                template = this.userMessageTemplateContent;
            } else {
                context.from = incomingMessage.user.username;
                template = this.responseTemplateContent;
            }
            this.chatLogList.append(Mustache.render(template, context));
            this.scrollToBottom();
        },
        socketReady: function(msg) {
            this.userId = msg.id;
            $('.login').fadeOut(300, function() {
                this.textArea.focus();
            }.bind(this));
            msg.userList.forEach(this.addUser.bind(this));
        },
        deleteMessage: function(msg) {
            $('[data-ts="' + msg.ts + '"]').fadeOut(300, function() {
                $(this).remove();
            });
        },
        botIsTyping: function() {
            this.typingIndicator.fadeIn(300);
        },
        addReactionTo: function(msg) {
            console.log('addReactionTo', msg);
        },
        processBotMessage: function(msg) {
            this.typingIndicator.fadeOut(300);
            this.appendResponse({
                ts: msg.ts,
                text: msg.message,
                channel: msg.channel,
                user: {
                    username: 'Giskard'
                }
            });
            this.scrollToBottom();
        },
        userConnected: function(msg) {
            this.addUser(msg);
        },
        userDisconnected: function(msg) {
            $('[data-user-id="' + msg.id + '"]').remove();
        },
        extraMetadata: function(msg) {
            var _this = this;
            $('[data-ts="' + msg.ts + '"]').find('.message').append('
').find('img').load(function() {
                _this.scrollToBottom();
            });
        },
        formatText: function(txt) {
            txt = txt
                .replace(/>/g, '>')
                .replace(/</g, '<')
                .replace(/@([a-zA-Z1-9_]+)/g, function(s, m) {
                    return '@' + m + '';
                })
                .replace(/\*([^\n]+)\*/g, function(s, m) {
                    return '' + m + '';
                })
                .replace(/_([^\n]+)_/g, function(s, m) {
                    return '' + m + '';
                })
                .replace(/`([^`\n]+)`/g, function(s, m) {
                    return '' + m + '';
                })
                .split('\n');
            var result = [],
                inB = false,
                inC = false;
            txt.forEach(function(i) {
                if(i.indexOf('>') === 0 && !inB && !inC) {
                    result.push('
' + i.replace('>', '').trimLeft() + '
');
                    inB = true;
                } else if(i.indexOf('>') === -1 && inB && !inC) {
                    result.push('

');
                    result.push(i + '
');
                    inB = false;
                } else if(i === '```') {
                    inC = !inC;
                    if(inC) {
                        result.push('
');
                    } else {
                        result.push('
');
                    }
                } else {
                    if(inB && !inC) {
                        result.push(i.replace('>', '').trimLeft() + '
');
                    } else if(!inB && inC) {
                        result.push(i);
                    } else {
                        result.push(i + '
');
                    }
                }
            });

            return result.join('').replace(/

/g, '
');
        }
    };
    $('#typing').fadeOut(0);
    chat.init();
});
<|endoftext|>


<commit_before>osmtm = {};
osmtm.project = {};
osmtm.project.edit = {};
osmtm.project.edit.priority_areas = (function() {

  var lmap;
  var drawControl;
  var drawnItems;

  // creates the Leaflet map
  function createMap() {
    lmap = L.map('leaflet');
    // create the tile layer with correct attribution
    var osmUrl='http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png';
    var osmAttrib='Map data © OpenStreetMap contributors';
    var osm = new L.TileLayer(osmUrl, {attribution: osmAttrib});
    lmap.addLayer(osm);

    var layer = new L.geoJson(geometry, {
      style: {
        fillOpacity: 0.1,
        weight: 1.5
      }
    });
    lmap.addLayer(layer);
    lmap.fitBounds(layer.getBounds());
    lmap.zoomOut();

    var style = {
      color: 'red',
      weight: 1
    };
    drawnItems = new L.GeoJSON(null, {
      style: style
    });
    lmap.addLayer(drawnItems);
    drawnItems.addData(priority_areas);

    onChange(true);

    drawControl = new L.Control.Draw({
      position: 'topleft',
      draw: {
        rectangle: {
          title: 'Draw the area of interest'
        },
        circle: false,
        marker: false,
        polyline: false,
        polygon: {
          title: 'Draw the area of interest'
        }
      },
      edit: {
        featureGroup: drawnItems
      }
    });
    lmap.addControl(drawControl);

    lmap.on('draw:created', function(e) {
      var layer = e.layer;
      drawnItems.addLayer(layer);
      layer.setStyle(style);
      onChange();
    });
    lmap.on('draw:edited', function(e) {
      onChange();
    });
    lmap.on('draw:deleted', function(e) {
      onChange();
    });
  }

  function onChange(silent) {
    var val = '';
    if (drawnItems.getLayers().length) {
      var gj = drawnItems.toGeoJSON();
      val = JSON.stringify(gj);
    }
    $('#priority_areas').val(val);

    silent = !!silent;
    if (!silent) {
      $('#priority_areas').trigger('change');
    }
  }

  return {
    init: function() {
      createMap();

      $('#priority_areas').on('change', function() {
        $('input[type=submit]').removeAttr('disabled');
      });
    }
  };
})();

$(document).ready(function() {
  osmtm.project.edit.priority_areas.init();
});
<commit_msg>Removing obsolete file<commit_after><|endoftext|>


<commit_before>'use strict';

import _ from 'lodash';
import Reflux from 'reflux';
import UIActions from 'actions/UIActions';
import NetworkActions from 'actions/NetworkActions';
import ChannelActions from 'actions/ChannelActions';
import SocketActions from 'actions/SocketActions';
import NotificationActions from 'actions/NotificationActions';
import UserActions from 'actions/UserActions';
import ChannelStore from 'stores/ChannelStore';
import UserStore from 'stores/UserStore';

const messagesBatchSize = 8;

const MessageStore = Reflux.createStore({
  listenables: [UIActions, NetworkActions, SocketActions, ChannelActions],
  init: function() {
    this.socket = null;
    this.posts = {}; // simple cache for message contents
    this._reset();
    this.hasLoaded = false;

    // Listen for changes in channels
    this.unsubscribeFromChannelStore = ChannelStore.listen((channels) => {
      channels.forEach((channel) => {
        if(!this.messages[channel.name])
          this.messages[channel.name] = [];
      });
    });
  },
  _reset: function() {
    this.messages = {};
    this.contents = {};
    this._resetLoadingState();
  },
  _resetLoadingState: function() {
    this.hasLoaded = false;
    this.loading = false;
    this.canLoadMore = true;
  },
  getMessages: function(channel: string) {
    if(!this.messages[channel])
      this.loadMessages(channel, null, null, messagesBatchSize);

    return this.messages[channel] ? this.messages[channel] : [];
  },
  getOldestMessage: function(channel: string) {
    return this.messages[channel] && this.messages[channel].length > 0 ? this.messages[channel][0].key : null;
  },
  onSocketConnected: function(socket) {
    console.log("MessageStore connected");
    this.socket = socket;

    // Handle new messages
    this.socket.on('messages', (channel, message) => {
      console.log("--> new messages in #", channel, message);
      this.loadMessages(channel, null, null, messagesBatchSize);
    });

    // Handle DB loading state
    this.socket.on('db.load', (action, channel) => {
      if(action === 'sync') {
        this.hasLoaded = false;
        UIActions.startLoading(channel, "loadhistory", "Syncing...");
      }
      else if(action === 'query')
        UIActions.startLoading(channel, "query", "Loading...");
    });
    this.socket.on('db.loaded', (action, channel) => {
      if(action === 'sync') {
        this.hasLoaded = true;
        UIActions.stopLoading(channel, "loadhistory");
      }
      else if(action === 'query')
        UIActions.stopLoading(channel, "query");
    });
  },
  onSocketDisconnected: function() {
    this.socket.removeAllListeners('messages');
    this.socket = null;
    this._reset();
  },
  onDisconnect: function() {
    this._reset();
  },
  onJoinedChannel: function(channel) {
    // console.log("MessageStore - open #" + channel);
    if(!this.messages[channel]) this.messages[channel] = [];
    this._resetLoadingState();
  },
  onLeaveChannel: function(channel: string) {
    // console.log("MessageStore - close #" + channel);
    this._resetLoadingState();
    delete this.messages[channel];
  },
  onShowChannel: function(channel: string) {
    if(!this.messages[channel]) this.messages[channel] = [];
    this._resetLoadingState();
  },
  onLoadMoreMessages: function(channel: string) {
    if(!this.loading && this.canLoadMore) {
      console.log("MessageStore - load more messages from #" + channel);
      this.canLoadMore = false;
      this.loadMessages(channel, this.getOldestMessage(channel), null, messagesBatchSize);
    }
  },
  loadMessages: function(channel: string, olderThanHash: string, newerThanHash: string, amount: number) {
    if(!this.socket)
      return;

    console.log("--> channel.get: ", channel, olderThanHash, newerThanHash, amount);
    this.loading = true;
    UIActions.startLoading(channel, "loadmessages", "Loading messages...");
    this.socket.emit('channel.get', channel, olderThanHash, newerThanHash, amount, (c, messages) => {
      this._addMessages(channel, messages, olderThanHash !== null);
      this.loading = false;
      UIActions.stopLoading(channel, "loadmessages");
    });
  },
  _addMessages: function(channel: string, newMessages: Array, older: boolean) {
    console.log("<-- messages: ", channel, newMessages.length, newMessages);
    var unique = _.differenceWith(newMessages, this.messages[channel], _.isEqual);
    console.log("MessageStore - new messages count: ", unique.length);

    if(unique.length > 0) {
      // If we received more than 1 message, there are more messages to be loaded
      // if(unique.length > 1) {
      //   this.canLoadMore = true;
      // } else if(unique.length === 1 && this.messages[channel].length === 0 && older) {
      //   // Special case for a channel that has only one message
      //   ChannelActions.reachedChannelStart();
      // }
      this.canLoadMore = true;
      if(unique.length === 1 && this.messages[channel].length === 0 && older) {
        // Special case for a channel that has only one message
        ChannelActions.reachedChannelStart();
      }

      // Append the new messages either at the end (newer) or at the beginning (older)
      if(older)
        this.messages[channel] = unique.concat(this.messages[channel]);
      else
        this.messages[channel] = this.messages[channel].concat(unique);

      // Load message content
      unique.reverse().forEach((f) => this._loadPost(channel, f));

      NotificationActions.newMessage(channel);
      this.trigger(channel, this.messages[channel]);
    } else if(older) {
      ChannelActions.reachedChannelStart();
    } else if(!older && this.messages[channel].length === 0 && this.hasLoaded) {
      ChannelActions.reachedChannelStart();
    }
  },
  _loadPost: function(channel: string, message) {
    const hasMentions = (text: string, mention: string) => {
      return text.split(' ').map((word) => {
          const match = word.startsWith(mention)
                  || word.startsWith(mention + ":")
                  || word.startsWith("@" + mention)
                  || word.startsWith(mention + ",");
          return match;
      }).filter((f) => f === true).length > 0;
    };

    this.onLoadPost(message.value, (err, post) => {
      UserActions.addUser(post.meta.from);
      if(post && post.content) {
        if(hasMentions(post.content.toLowerCase(), UserStore.user.username.toLowerCase()))
          NotificationActions.mention(channel, post.content);
      }
    });
  },
  onLoadPost: function(hash: string, callback) {
    if(!this.posts[hash]) {
      this.socket.emit('post.get', hash, (err, data) => {
        this.posts[hash] = data;
        callback(err, data);
      });
    } else {
      callback(null, this.posts[hash]);
    }
  },
  onSendMessage: function(channel: string, text: string, callback) {
    console.log("--> send message:", text);
    UIActions.startLoading(channel, "send");
    this.socket.emit('message.send', channel, text, (err) => {
      if(err) {
        console.log("Couldn't send message:", err.toString());
        UIActions.raiseError(err.toString());
      }
      UIActions.stopLoading(channel, "send");
    });
  },
  onAddFile: function(channel: string, filePath: string) {
    console.log("--> add file:", filePath);
    UIActions.startLoading(channel);
    this.socket.emit('file.add', channel, filePath, (err) => {
      if(err) {
        console.log("Couldn't add file:", filePath, err.toString());
        UIActions.raiseError(err.toString());
      }
      UIActions.stopLoading(channel);
    });
  },
  onLoadDirectoryInfo: function(hash, cb) {
    console.log("--> get directory:", hash);
    if(hash) {
      this.socket.emit('directory.get', hash, (result) => {
        console.log("<-- directory:", result);
        if(result) {
          result = result.map((e) => {
            return {
              hash: e.Hash,
              size: e.Size,
              type: e.Type === 1 ? "directory" : "file",
              name: e.Name
            };
          });
        }
        cb(result);
      });
    } else {
      cb(null);
    }
  }
});

export default MessageStore;
<commit_msg>Sort messages by timestamp<commit_after>'use strict';

import _ from 'lodash';
import Reflux from 'reflux';
import UIActions from 'actions/UIActions';
import NetworkActions from 'actions/NetworkActions';
import ChannelActions from 'actions/ChannelActions';
import SocketActions from 'actions/SocketActions';
import NotificationActions from 'actions/NotificationActions';
import UserActions from 'actions/UserActions';
import ChannelStore from 'stores/ChannelStore';
import UserStore from 'stores/UserStore';

const messagesBatchSize = 8;

const MessageStore = Reflux.createStore({
  listenables: [UIActions, NetworkActions, SocketActions, ChannelActions],
  init: function() {
    this.socket = null;
    this.posts = {}; // simple cache for message contents
    this._reset();
    this.hasLoaded = false;

    // Listen for changes in channels
    this.unsubscribeFromChannelStore = ChannelStore.listen((channels) => {
      channels.forEach((channel) => {
        if(!this.messages[channel.name])
          this.messages[channel.name] = [];
      });
    });
  },
  _reset: function() {
    this.messages = {};
    this.contents = {};
    this._resetLoadingState();
  },
  _resetLoadingState: function() {
    this.hasLoaded = false;
    this.loading = false;
    this.canLoadMore = true;
  },
  getMessages: function(channel: string) {
    if(!this.messages[channel])
      this.loadMessages(channel, null, null, messagesBatchSize);

    return this.messages[channel] ? this.messages[channel] : [];
  },
  getOldestMessage: function(channel: string) {
    return this.messages[channel] && this.messages[channel].length > 0 ? this.messages[channel][0].key : null;
  },
  onSocketConnected: function(socket) {
    console.log("MessageStore connected");
    this.socket = socket;

    // Handle new messages
    this.socket.on('messages', (channel, message) => {
      console.log("--> new messages in #", channel, message);
      this.loadMessages(channel, null, null, messagesBatchSize);
    });

    // Handle DB loading state
    this.socket.on('db.load', (action, channel) => {
      if(action === 'sync') {
        this.hasLoaded = false;
        UIActions.startLoading(channel, "loadhistory", "Syncing...");
      }
      else if(action === 'query')
        UIActions.startLoading(channel, "query", "Loading...");
    });
    this.socket.on('db.loaded', (action, channel) => {
      if(action === 'sync') {
        this.hasLoaded = true;
        UIActions.stopLoading(channel, "loadhistory");
      }
      else if(action === 'query')
        UIActions.stopLoading(channel, "query");
    });
  },
  onSocketDisconnected: function() {
    this.socket.removeAllListeners('messages');
    this.socket = null;
    this._reset();
  },
  onDisconnect: function() {
    this._reset();
  },
  onJoinedChannel: function(channel) {
    // console.log("MessageStore - open #" + channel);
    if(!this.messages[channel]) this.messages[channel] = [];
    this._resetLoadingState();
  },
  onLeaveChannel: function(channel: string) {
    // console.log("MessageStore - close #" + channel);
    this._resetLoadingState();
    delete this.messages[channel];
  },
  onShowChannel: function(channel: string) {
    if(!this.messages[channel]) this.messages[channel] = [];
    this._resetLoadingState();
  },
  onLoadMoreMessages: function(channel: string) {
    if(!this.loading && this.canLoadMore) {
      console.log("MessageStore - load more messages from #" + channel);
      this.canLoadMore = false;
      this.loadMessages(channel, this.getOldestMessage(channel), null, messagesBatchSize);
    }
  },
  loadMessages: function(channel: string, olderThanHash: string, newerThanHash: string, amount: number) {
    if(!this.socket)
      return;

    console.log("--> channel.get: ", channel, olderThanHash, newerThanHash, amount);
    this.loading = true;
    UIActions.startLoading(channel, "loadmessages", "Loading messages...");
    this.socket.emit('channel.get', channel, olderThanHash, newerThanHash, amount, (c, messages) => {
      this._addMessages(channel, messages, olderThanHash !== null);
      this.loading = false;
      UIActions.stopLoading(channel, "loadmessages");
    });
  },
  _addMessages: function(channel: string, newMessages: Array, older: boolean) {
    console.log("<-- messages: ", channel, newMessages.length, newMessages);
    var unique = _.differenceWith(newMessages, this.messages[channel], _.isEqual);
    console.log("MessageStore - new messages count: ", unique.length);

    if(unique.length > 0) {
      // If we received more than 1 message, there are more messages to be loaded
      this.canLoadMore = true;
      if(unique.length === 1 && this.messages[channel].length === 0 && older) {
        // Special case for a channel that has only one message
        ChannelActions.reachedChannelStart();
      }

      // Append the new messages either at the end (newer) or at the beginning (older)
      if(older)
        this.messages[channel] = unique.concat(this.messages[channel]);
      else
        this.messages[channel] = this.messages[channel].concat(unique);

      // Load message content
      unique.reverse().forEach((f) => this._loadPost(channel, f));

      // Sort by timestamp
      this.messages[channel] = _.sortBy(this.messages[channel], (e) => e.meta.ts);

      NotificationActions.newMessage(channel);
      this.trigger(channel, this.messages[channel]);
    } else if(older) {
      ChannelActions.reachedChannelStart();
    } else if(!older && this.messages[channel].length === 0 && this.hasLoaded) {
      ChannelActions.reachedChannelStart();
    }
  },
  _loadPost: function(channel: string, message) {
    const hasMentions = (text: string, mention: string) => {
      return text.split(' ').map((word) => {
          const match = word.startsWith(mention)
                  || word.startsWith(mention + ":")
                  || word.startsWith("@" + mention)
                  || word.startsWith(mention + ",");
          return match;
      }).filter((f) => f === true).length > 0;
    };

    this.onLoadPost(message.value, (err, post) => {
      UserActions.addUser(post.meta.from);
      if(post && post.content) {
        if(hasMentions(post.content.toLowerCase(), UserStore.user.username.toLowerCase()))
          NotificationActions.mention(channel, post.content);
      }
    });
  },
  onLoadPost: function(hash: string, callback) {
    if(!this.posts[hash]) {
      this.socket.emit('post.get', hash, (err, data) => {
        this.posts[hash] = data;
        callback(err, data);
      });
    } else {
      callback(null, this.posts[hash]);
    }
  },
  onSendMessage: function(channel: string, text: string, callback) {
    console.log("--> send message:", text);
    UIActions.startLoading(channel, "send");
    this.socket.emit('message.send', channel, text, (err) => {
      if(err) {
        console.log("Couldn't send message:", err.toString());
        UIActions.raiseError(err.toString());
      }
      UIActions.stopLoading(channel, "send");
    });
  },
  onAddFile: function(channel: string, filePath: string) {
    console.log("--> add file:", filePath);
    UIActions.startLoading(channel);
    this.socket.emit('file.add', channel, filePath, (err) => {
      if(err) {
        console.log("Couldn't add file:", filePath, err.toString());
        UIActions.raiseError(err.toString());
      }
      UIActions.stopLoading(channel);
    });
  },
  onLoadDirectoryInfo: function(hash, cb) {
    console.log("--> get directory:", hash);
    if(hash) {
      this.socket.emit('directory.get', hash, (result) => {
        console.log("<-- directory:", result);
        if(result) {
          result = result.map((e) => {
            return {
              hash: e.Hash,
              size: e.Size,
              type: e.Type === 1 ? "directory" : "file",
              name: e.Name
            };
          });
        }
        cb(result);
      });
    } else {
      cb(null);
    }
  }
});

export default MessageStore;
<|endoftext|>


<commit_before>$(document).ready(function() {

    // Add an encodeGrid function to jQuery so it can be used
    // with the table element
    (function ($){
        $.fn.encodeGrid = function(){
            var data = "";
            var isLiving = function(element) {
                if ($(element).hasClass('live')) {
                    return "X";
                } else {
                    return " ";
                }
            }

            // Cycle through each row in the table
            $(this).find('tr').each(function() {
                // Map isLiving to the set of TD elements
                data += $.map($(this).find('td'), isLiving).join('') + '\n';
            });

            return data;
        }
    })(jQuery);

    function updateGrid() {

        var height = $('.height-box').val();
        var width = $('.width-box').val();
        var table = $('.life-table');

        table.empty();

        for (var i=0; i < height; i++)
        {
            table.append('

');
        }
        $('.life-table tr').each(function(rowNum) {
            for (var j=0; j < width; j++)
             {
            $(this).append('  	');
        }});
    }

    $('.height-box').change(updateGrid);
    $('.width-box').change(updateGrid);

    $('.play').click(function(){
        $.ajax({
            url: '/nextgen',
            type: 'POST',
                // This will be the encoded grid data used as POST data.
            data: $('.life-table').encodeGrid(),
            dataType: 'text'
        }).done(function(data) {
            $('.life-table').empty().append('
'+data+'
');
        });
    });

    $('td').live('click', function() {
        $(this).toggleClass('live');
    });

// end document ready
});
<commit_msg>Harness: return lowercase x when encoding grid rather than uppercase.<commit_after>$(document).ready(function() {

    // Add an encodeGrid function to jQuery so it can be used
    // with the table element
    (function ($){
        $.fn.encodeGrid = function(){
            var data = "";
            var isLiving = function(element) {
                if ($(element).hasClass('live')) {
                    return "x";
                } else {
                    return " ";
                }
            }

            // Cycle through each row in the table
            $(this).find('tr').each(function() {
                // Map isLiving to the set of TD elements
                data += $.map($(this).find('td'), isLiving).join('') + '\n';
            });

            return data;
        }
    })(jQuery);

    function updateGrid() {

        var height = $('.height-box').val();
        var width = $('.width-box').val();
        var table = $('.life-table');

        table.empty();

        for (var i=0; i < height; i++)
        {
            table.append('

');
        }
        $('.life-table tr').each(function(rowNum) {
            for (var j=0; j < width; j++)
             {
            $(this).append('  	');
        }});
    }

    $('.height-box').change(updateGrid);
    $('.width-box').change(updateGrid);

    $('.play').click(function(){
        $.ajax({
            url: '/nextgen',
            type: 'POST',
                // This will be the encoded grid data used as POST data.
            data: $('.life-table').encodeGrid(),
            dataType: 'text'
        }).done(function(data) {
            $('.life-table').empty().append('
'+data+'
');
        });
    });

    $('td').live('click', function() {
        $(this).toggleClass('live');
    });

// end document ready
});
<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular
    .module('fpl-toolbox')
    .controller('PlayersController', PlayersController);

  /** @ngInject */
  function PlayersController(plResource) {
    var pCtrl = this;
    pCtrl.players = [];
    pCtrl.gameweek = 0;
    pCtrl.teams = [];

    pCtrl.playersToShow = [];

    pCtrl.showFilters = true;
    pCtrl.orderPredicate = 'ppg_per_pound';
    pCtrl.orderReverse = true;

    pCtrl.playerFilters = {
      healthy: true,
      position: 1,
      maxCost: 15,
      minutes: 0,

      applyOrder: ['positionOnly', 'healthyOnly', 'minutesOnly', 'priceOnly', 'teamOnly'],

      healthyOnly: function(p) {
        return !this.healthy || p.status === 'a';
      },
      minutesOnly: function(p) {
        return p.minutes >= this.minutes;
      },
      positionOnly: function(p) {
        return this.position === 0 || p.element_type === this.position;
      },
      teamOnly: function(p) {
        return !pCtrl.teams || pCtrl.teams[p.team-1].selected;
      },
      priceOnly: function(p) {
        return p.cost <= this.maxCost;
      }
    };

    // functions
    pCtrl.orderPlayers = orderPlayers;
    pCtrl.filter = filter;
    pCtrl.resetFilters = resetFilters;
    pCtrl.selectAll = selectAll;
    pCtrl.selectNone = selectNone;

    init();

    function init() {
      plResource.init(function() {
        pCtrl.players = plResource.players;
        pCtrl.gameweek = plResource.gameweek;
        pCtrl.teams = _.sortBy(plResource.teams, 'team');
        _.forEach(pCtrl.teams, function(t) {
          t.selected = true;
        });

        _.forEach(pCtrl.players, function(p) {
          p.points_per_pound = (p.total_points / p.now_cost) * 10;
          p.ppg_per_pound = (p.points_per_game / p.now_cost) * 10;
          p.cost = p.now_cost / 10;
          p.selected_by_percent = parseFloat(p.selected_by_percent);
          p.points_per_game = parseFloat(p.points_per_game);
        });

        filter(); // apply initial filter
      });
    }

    function orderPlayers($event) {
      var el = angular.element($event.currentTarget);
      var colId =  el.data('js-table-th-order-id');

      pCtrl.orderReverse = pCtrl.orderPredicate !== colId || !pCtrl.orderReverse;
      pCtrl.orderPredicate = colId;

      el.parent().parent().children().children().children()
        .removeClass('glyphicon glyphicon-sort-by-order-alt glyphicon-sort-by-order'); // TODO: this is very bad, in order not to add jQ, all ordering directive needs refacto (use scope + parent.scope)
      angular.element(el.children()[1]).addClass('glyphicon')
        .addClass(pCtrl.orderReverse ? 'glyphicon-sort-by-order-alt' : 'glyphicon-sort-by-order');
    }

    function filter() {
      pCtrl.playersToShow = pCtrl.players;
      _.forEach(pCtrl.playerFilters.applyOrder, function(filterName) {
        if (typeof pCtrl.playerFilters[filterName] === 'function') {
          pCtrl.playersToShow = _.filter(pCtrl.playersToShow, pCtrl.playerFilters[filterName], pCtrl.playerFilters);
        }
      });
    }

    function resetFilters() {
      pCtrl.playerFilters.healthy = true;
      pCtrl.playerFilters.maxCost = 15;
      pCtrl.playerFilters.minutes = 0;
      selectAll();

      filter();
    }

    function selectAll() {
      _.forEach(pCtrl.teams, function(t) {
        t.selected = true;
      });
    }

    function selectNone() {
      _.forEach(pCtrl.teams, function(t) {
        t.selected = false;
      });
    }

  }
})();
<commit_msg>players select all none filter fix<commit_after>(function() {
  'use strict';

  angular
    .module('fpl-toolbox')
    .controller('PlayersController', PlayersController);

  /** @ngInject */
  function PlayersController(plResource) {
    var pCtrl = this;
    pCtrl.players = [];
    pCtrl.gameweek = 0;
    pCtrl.teams = [];

    pCtrl.playersToShow = [];

    pCtrl.showFilters = true;
    pCtrl.orderPredicate = 'ppg_per_pound';
    pCtrl.orderReverse = true;

    pCtrl.playerFilters = {
      healthy: true,
      position: 1,
      maxCost: 15,
      minutes: 0,

      applyOrder: ['positionOnly', 'healthyOnly', 'minutesOnly', 'priceOnly', 'teamOnly'],

      healthyOnly: function(p) {
        return !this.healthy || p.status === 'a';
      },
      minutesOnly: function(p) {
        return p.minutes >= this.minutes;
      },
      positionOnly: function(p) {
        return this.position === 0 || p.element_type === this.position;
      },
      teamOnly: function(p) {
        return !pCtrl.teams || pCtrl.teams[p.team-1].selected;
      },
      priceOnly: function(p) {
        return p.cost <= this.maxCost;
      }
    };

    // functions
    pCtrl.orderPlayers = orderPlayers;
    pCtrl.filter = filter;
    pCtrl.resetFilters = resetFilters;
    pCtrl.selectAll = selectAll;
    pCtrl.selectNone = selectNone;

    init();

    function init() {
      plResource.init(function() {
        pCtrl.players = plResource.players;
        pCtrl.gameweek = plResource.gameweek;
        pCtrl.teams = _.sortBy(plResource.teams, 'team');
        _.forEach(pCtrl.teams, function(t) {
          t.selected = true;
        });

        _.forEach(pCtrl.players, function(p) {
          p.points_per_pound = (p.total_points / p.now_cost) * 10;
          p.ppg_per_pound = (p.points_per_game / p.now_cost) * 10;
          p.cost = p.now_cost / 10;
          p.selected_by_percent = parseFloat(p.selected_by_percent);
          p.points_per_game = parseFloat(p.points_per_game);
        });

        filter(); // apply initial filter
      });
    }

    function orderPlayers($event) {
      var el = angular.element($event.currentTarget);
      var colId =  el.data('js-table-th-order-id');

      pCtrl.orderReverse = pCtrl.orderPredicate !== colId || !pCtrl.orderReverse;
      pCtrl.orderPredicate = colId;

      el.parent().parent().children().children().children()
        .removeClass('glyphicon glyphicon-sort-by-order-alt glyphicon-sort-by-order'); // TODO: this is very bad, in order not to add jQ, all ordering directive needs refacto (use scope + parent.scope)
      angular.element(el.children()[1]).addClass('glyphicon')
        .addClass(pCtrl.orderReverse ? 'glyphicon-sort-by-order-alt' : 'glyphicon-sort-by-order');
    }

    function filter() {
      pCtrl.playersToShow = pCtrl.players;
      _.forEach(pCtrl.playerFilters.applyOrder, function(filterName) {
        if (typeof pCtrl.playerFilters[filterName] === 'function') {
          pCtrl.playersToShow = _.filter(pCtrl.playersToShow, pCtrl.playerFilters[filterName], pCtrl.playerFilters);
        }
      });
    }

    function resetFilters() {
      pCtrl.playerFilters.healthy = true;
      pCtrl.playerFilters.maxCost = 15;
      pCtrl.playerFilters.minutes = 0;
      selectAll();

      filter();
    }

    function selectAll() {
      _.forEach(pCtrl.teams, function(t) {
        t.selected = true;
      });

      filter();
    }

    function selectNone() {
      _.forEach(pCtrl.teams, function(t) {
        t.selected = false;
      });

      filter();
    }

  }
})();
<|endoftext|>


<commit_before>Template['subscribe'].events({
  'submit .subscribe.form': function(e, tpl) {
		e.preventDefault();

    var params = {
          name: tpl.$('input[name=name]').val(),
          email: tpl.$('input[name=email]').val()
        };

    /*
    Meteor.call('submitSubscription', params, function(error) {
			if (error) {
				return console.log(error.reason);
			} else {
				console.log('method called ' + params);
			}
		});
    */

    Meteor.call('saveSubscription', params, function(error) {
      if (error) {
        return console.log(error.reason);
			} else {
				console.log('subscription saved ' + params);
			}
    });
	}
});
<commit_msg>updated packages, subscribe form reset on success<commit_after>Template['subscribe'].events({
  'submit .subscribe.form': function(e, tpl) {
		e.preventDefault();

    var $form = tpl.$('.subscribe.form'),
        params = {
          name: tpl.$('input[name=name]').val(),
          email: tpl.$('input[name=email]').val()
        };

    /* @TODO: tie in mailchimp http post into method
    Meteor.call('submitSubscription', params, function(error) {
			if (error) {
				return console.log(error.reason);
			} else {
				console.log('method called ' + params);
			}
		});
    */

    Meteor.call('saveSubscription', params, function(error) {
      if (error) {
        return console.log(error.reason);
			} else {
        $form[0].reset();
				console.log('subscription saved ' + params);
			}
    });
	}
});
<|endoftext|>


<commit_before>import React from 'react';
import { Microservices } from '../../../configs/microservices';
import { connectToStores } from 'fluxible-addons-react';
import {NavLink, navigateAction} from 'fluxible-router';
import UserProfileStore from '../../../stores/UserProfileStore';
import { timeSince } from '../../../common';
import updateUsergroup from '../../../actions/user/userprofile/updateUsergroup';
import saveUsergroup from '../../../actions/user/userprofile/saveUsergroup';

class UserGroupEdit extends React.Component {
    constructor(props){
        super(props);

        this.styles = {'backgroundColor': '#2185D0', 'color': 'white'};
    }

    componentWillReceiveProps(nextProps) {
        console.log('UserGroupEdit componentWillReceiveProps:', nextProps.UserProfileStore.saveUsergroupError, this.props.UserProfileStore.saveUsergroupError);
        if (nextProps.UserProfileStore.saveUsergroupError !== '' && this.props.UserProfileStore.saveUsergroupError === '') {
            swal({
                title: 'Error',
                text: 'Unknown error while saving.',
                type: 'error',
                confirmButtonText: 'Close',
                confirmButtonClass: 'negative ui button',
                allowEscapeKey: true,
                allowOutsideClick: true,
                buttonsStyling: false
            })
            .then(() => {
                return true;
            })
            .catch();
            return;
        }
    }

    componentDidMount() {
        $('#usergoup_edit_dropdown_usernames_remote')
            .dropdown({
                apiSettings: {
                    url: Microservices.user.uri + '/information/username/search/{query}'
                },
                saveRemoteData: false,
                action: (name, value, source) => {
                    // console.log('dropdown select', name, value, source);

                    $('#usergoup_edit_dropdown_usernames_remote').dropdown('clear');
                    $('#usergoup_edit_dropdown_usernames_remote').dropdown('hide');

                    let group = this.getGroup(this.props.UserProfileStore.currentUsergroup.members);
                    if (group.members === undefined || group.members === null)
                        group.members = [];

                    let data = JSON.parse(decodeURIComponent(value));
                    // console.log('trying to add', name, 'to', group.members, ' with ', data);
                    if (group.members.findIndex((member) => {
                        return member.userid === parseInt(data.userid);
                    }) === -1 && name !== this.props.UserProfileStore.username) {
                        group.members.push({
                            username: name,
                            userid: parseInt(data.userid),
                            joined: data.joined || undefined,
                            picture: data.picture
                        });
                    }

                    this.context.executeAction(updateUsergroup, {group: group, offline: true});

                    return true;
                }
            });
    }

    getGroup(members = undefined) {
        let group = {
            _id: this.props.UserProfileStore.currentUsergroup._id,
            name: this.refs.GroupName.value,
            description: this.refs.GroupDescription.value,
            members: members,
            timestamp: this.props.UserProfileStore.currentUsergroup.timestamp || '',
            creator: this.props.UserProfileStore.currentUsergroup.creator || this.props.UserProfileStore.userid
        };

        if (this.props.UserProfileStore.currentUsergroup._id)
            group.id = group._id;

        //TODO get members from list

        return group;
    }

    handleClickOnEditGroup(e) {
        e.preventDefault();
    }

    handleSave(e) {
        e.preventDefault();

        let group = this.getGroup(this.props.UserProfileStore.currentUsergroup.members);

        console.log('handleSave:', group);

        if (group.name === '') {
            swal({
                title: 'Error',
                text: 'At least you have to give the group a name.',
                type: 'error',
                confirmButtonText: 'Close',
                confirmButtonClass: 'negative ui button',
                allowEscapeKey: true,
                allowOutsideClick: true,
                buttonsStyling: false
            })
            .then(() => {
                return true;
            })
            .catch();
            return;
        }

        this.context.executeAction(saveUsergroup, group);
    }

    handleClickRemoveMember(member) {
        console.log('handleClickRemoveMember', member);

        let group = this.getGroup(this.props.UserProfileStore.currentUsergroup.members);

        group.members.pop(member);

        this.context.executeAction(updateUsergroup, {group: group, offline: true});
    }

    render() {
        const signUpLabelStyle = {width: '150px'};

        let userlist = [];
        let prefs = {
            name: this.props.UserProfileStore.currentUsergroup.name,
            desc: this.props.UserProfileStore.currentUsergroup.description
        };
        //change header and data depending on group should be created or edited
        let header = 'Create Group';
        if (this.props.UserProfileStore.currentUsergroup._id !== undefined) {
            header = 'Edit Group';
        }

        // console.log('render UserGroupEdit:', this.props.UserProfileStore.currentUsergroup.members);
        if (this.props.UserProfileStore.currentUsergroup.members !== undefined && this.props.UserProfileStore.currentUsergroup.members.length > 0) {
            this.props.UserProfileStore.currentUsergroup.members.forEach((member) => {
                let fct = () => {
                    this.handleClickRemoveMember(member);
                };
                let optionalText = (member.joined) ? ('Joined '+timeSince((new Date(member.joined)))+' ago') : '';
                userlist.push(
                  (

                              {member.username} ({member.userid})

{optionalText}

                  )
                );
            });
        }

        return (

{header}

                        <form className="ui form">

                                    Group Name

                                <input type="text" placeholder="Name" id="usergroupedit_input_GroupName" name="GroupName" ref="GroupName" aria-labelledby="GroupName" aria-required="true" defaultValue={prefs.name}  />

                                Description
                                <textarea rows="4" aria-labelledby="GroupDescription" id="usergroupedit_input_GroupDescription" name="GroupDescription" ref="GroupDescription" defaultValue={prefs.desc} ></textarea>

                                Add user
                                <select className="ui search dropdown" aria-labelledby="AddUserGr" id="usergroupedit_input_AddUserGr" name="AddUserGr" ref="AddUserGr" id="usergoup_edit_dropdown_usernames_remote">
                                </select>

                        </form>

                            <button className="ui blue labeled submit icon button" onClick={this.handleSave.bind(this)} >
                                Save group
                            </button>

                        {(this.props.UserProfileStore.saveUsergroupIsLoading === true) ?

Loading

 : ''}

Members

                            {userlist}

        );
    }
}

UserGroupEdit.contextTypes = {
    executeAction: React.PropTypes.func.isRequired
};

UserGroupEdit = connectToStores(UserGroupEdit, [UserProfileStore], (context, props) => {
    return {
        UserProfileStore: context.getStore(UserProfileStore).getState()
    };
});

export default UserGroupEdit;
<commit_msg>[SWIK-751_slow_internet_signin_form] Now reading more userdata from dropbox user search in group edit view.<commit_after>import React from 'react';
import { Microservices } from '../../../configs/microservices';
import { connectToStores } from 'fluxible-addons-react';
import {NavLink, navigateAction} from 'fluxible-router';
import UserProfileStore from '../../../stores/UserProfileStore';
import { timeSince } from '../../../common';
import updateUsergroup from '../../../actions/user/userprofile/updateUsergroup';
import saveUsergroup from '../../../actions/user/userprofile/saveUsergroup';

class UserGroupEdit extends React.Component {
    constructor(props){
        super(props);

        this.styles = {'backgroundColor': '#2185D0', 'color': 'white'};
    }

    componentWillReceiveProps(nextProps) {
        console.log('UserGroupEdit componentWillReceiveProps:', nextProps.UserProfileStore.saveUsergroupError, this.props.UserProfileStore.saveUsergroupError);
        if (nextProps.UserProfileStore.saveUsergroupError !== '' && this.props.UserProfileStore.saveUsergroupError === '') {
            swal({
                title: 'Error',
                text: 'Unknown error while saving.',
                type: 'error',
                confirmButtonText: 'Close',
                confirmButtonClass: 'negative ui button',
                allowEscapeKey: true,
                allowOutsideClick: true,
                buttonsStyling: false
            })
            .then(() => {
                return true;
            })
            .catch();
            return;
        }
    }

    componentDidMount() {
        $('#usergoup_edit_dropdown_usernames_remote')
            .dropdown({
                apiSettings: {
                    url: Microservices.user.uri + '/information/username/search/{query}'
                },
                saveRemoteData: false,
                action: (name, value, source) => {
                    // console.log('dropdown select', name, value, source);

                    $('#usergoup_edit_dropdown_usernames_remote').dropdown('clear');
                    $('#usergoup_edit_dropdown_usernames_remote').dropdown('hide');

                    let group = this.getGroup(this.props.UserProfileStore.currentUsergroup.members);
                    if (group.members === undefined || group.members === null)
                        group.members = [];

                    let data = JSON.parse(decodeURIComponent(value));
                    // console.log('trying to add', name, 'to', group.members, ' with ', data);
                    if (group.members.findIndex((member) => {
                        return member.userid === parseInt(data.userid);
                    }) === -1 && name !== this.props.UserProfileStore.username) {
                        group.members.push({
                            username: name,
                            userid: parseInt(data.userid),
                            joined: data.joined || undefined,
                            picture: data.picture,
                            surname: data.surname,
                            forename: data.forename,
                            organization: data.organization
                        });
                    }

                    this.context.executeAction(updateUsergroup, {group: group, offline: true});

                    return true;
                }
            });
    }

    getGroup(members = undefined) {
        let group = {
            _id: this.props.UserProfileStore.currentUsergroup._id,
            name: this.refs.GroupName.value,
            description: this.refs.GroupDescription.value,
            members: members,
            timestamp: this.props.UserProfileStore.currentUsergroup.timestamp || '',
            creator: this.props.UserProfileStore.currentUsergroup.creator || this.props.UserProfileStore.userid
        };

        if (this.props.UserProfileStore.currentUsergroup._id)
            group.id = group._id;

        //TODO get members from list

        return group;
    }

    handleClickOnEditGroup(e) {
        e.preventDefault();
    }

    handleSave(e) {
        e.preventDefault();

        let group = this.getGroup(this.props.UserProfileStore.currentUsergroup.members);

        console.log('handleSave:', group);

        if (group.name === '') {
            swal({
                title: 'Error',
                text: 'At least you have to give the group a name.',
                type: 'error',
                confirmButtonText: 'Close',
                confirmButtonClass: 'negative ui button',
                allowEscapeKey: true,
                allowOutsideClick: true,
                buttonsStyling: false
            })
            .then(() => {
                return true;
            })
            .catch();
            return;
        }

        this.context.executeAction(saveUsergroup, group);
    }

    handleClickRemoveMember(member) {
        console.log('handleClickRemoveMember', member);

        let group = this.getGroup(this.props.UserProfileStore.currentUsergroup.members);

        group.members.pop(member);

        this.context.executeAction(updateUsergroup, {group: group, offline: true});
    }

    render() {
        const signUpLabelStyle = {width: '150px'};

        let userlist = [];
        let prefs = {
            name: this.props.UserProfileStore.currentUsergroup.name,
            desc: this.props.UserProfileStore.currentUsergroup.description
        };
        //change header and data depending on group should be created or edited
        let header = 'Create Group';
        if (this.props.UserProfileStore.currentUsergroup._id !== undefined) {
            header = 'Edit Group';
        }

        // console.log('render UserGroupEdit:', this.props.UserProfileStore.currentUsergroup.members);
        if (this.props.UserProfileStore.currentUsergroup.members !== undefined && this.props.UserProfileStore.currentUsergroup.members.length > 0) {
            this.props.UserProfileStore.currentUsergroup.members.forEach((member) => {
                let fct = () => {
                    this.handleClickRemoveMember(member);
                };
                let optionalElement = (member.organization) ?  (

                    {member.organization}

                ) : '';
                let optionalText2 = (member.joined) ? ('Joined '+timeSince((new Date(member.joined)))+' ago') : '';
                userlist.push(
                  (

                              {member.surname} {member.forename} ({member.username})

{optionalElement}{optionalText2}

                  )
                );
            });
        }

        return (

{header}

                        <form className="ui form">

                                    Group Name

                                <input type="text" placeholder="Name" id="usergroupedit_input_GroupName" name="GroupName" ref="GroupName" aria-labelledby="GroupName" aria-required="true" defaultValue={prefs.name}  />

                                Description
                                <textarea rows="4" aria-labelledby="GroupDescription" id="usergroupedit_input_GroupDescription" name="GroupDescription" ref="GroupDescription" defaultValue={prefs.desc} ></textarea>

                                Add user
                                <select className="ui search dropdown" aria-labelledby="AddUserGr" id="usergroupedit_input_AddUserGr" name="AddUserGr" ref="AddUserGr" id="usergoup_edit_dropdown_usernames_remote">
                                </select>

                        </form>

                            <button className="ui blue labeled submit icon button" onClick={this.handleSave.bind(this)} >
                                Save group
                            </button>

                        {(this.props.UserProfileStore.saveUsergroupIsLoading === true) ?

Loading

 : ''}

Members

                            {userlist}

        );
    }
}

UserGroupEdit.contextTypes = {
    executeAction: React.PropTypes.func.isRequired
};

UserGroupEdit = connectToStores(UserGroupEdit, [UserProfileStore], (context, props) => {
    return {
        UserProfileStore: context.getStore(UserProfileStore).getState()
    };
});

export default UserGroupEdit;
<|endoftext|>


<commit_before>/** MIT License (c) copyright B Cavalier & J Hann */

/**
 * curl dojo 1.7 shim
 *
 * Licensed under the MIT License at:
 * 		http://www.opensource.org/licenses/mit-license.php
 */

/**
 * dojo 1.7 does some unique things with its loader.  This shim helps handle
 * those things.
 *
 * usage:
 *  curl({
 *  	preload: ['curl/shim/dojo17'],
 * 		package: { ... }
 *  }, ['dojo/parser'], function (parser) {
 *  	parser.parse();
 *  });
 *
 */
define(/*=='curl/shim/dojo17',==*/ ['curl/_privileged', './dojo16'], function (priv) {
	"use strict";

	var orig, dojoDetectorRx;

	orig = priv['core'].handleDepCycle;

	dojoDetectorRx = /^dojo\//;

	// in addition to expecting a require.ready function on the loader
	// (see dojo16 shim), dojo 1.7 has a wholly unnecessary dependency cycle
	// that the dojo loader resolves in a very janky way.

	priv['core'].handleDepCycle = function (defs, earlyExport, failure) {
		// don't resolve def since other modules that aren't in the
		// cycle (and aren't coded to handle a cycle) could be waiting
		// call earlyExport instead so that the currently waiting module
		// can have something to work with.  iiuc, this is roughly how the
		// dojo loader works.
		var parent = defs[0], dep = defs[1];
		if (dojoDetectorRx.test(dep.id)) {
			if (dep.ctx.useExports && (!parent || parent.ctx.useExports)) {
				earlyExport(dep.ctx.cjsVars.exports);
			}
			else {
				// wait until another time when the dep uses exports!
				// this could be using entirely different modules in the cycle.
			}
		}
		else {
			orig(defs, earlyExport, failure);
		}
	};

	return true;

});
<commit_msg>dojo17 shim is redundant with dojo16 shim<commit_after><|endoftext|>