<commit_before>(function () {

  var BrickCardElementPrototype = Object.create(HTMLElement.prototype);

  BrickCardElementPrototype.createdCallback = function () {
    this.ns = {};
  };

  BrickCardElementPrototype.attachedCallback = function () {
    var deck = this.parentNode;
    if (deck.nodeName.toLowerCase() === 'brick-deck') {
      this.ns.deck = deck;
      if (this !== deck.selectedCard && this.selected) {
        deck.showCard(this, {'skipTransition':true});
      }
    }
  };

  BrickCardElementPrototype.detachedCallback = function () {
    var deck = this.ns.deck;
    if (deck) {
      if (this === deck.selectedCard) {
        deck.selectedCard = null;
        deck.removeAttribute('selected-index');
      }
      this.ns.deck = null;
    }
  };

  BrickCardElementPrototype.attributeChangedCallback = function (attr, oldVal, newVal) {
    if (attr in attrs) {
      attrs[attr].call(this, oldVal, newVal);
    }
  };

  // Attribute handlers
  var attrs = {
    'selected': function (oldVal, newVal) {
      var deck = this.ns.deck;
      if (!deck) { return; }
      // check for null because empty string is true
      // for our booleon attribute
      if (newVal !== null) {
        if (this !== deck.selectedCard) { deck.showCard(this); }
      } else {
        if (this === deck.selectedCard) { deck.hideCard(this); }
      }
    },
  };

  BrickCardElementPrototype.reveal = function() {
    this.dispatchEvent(new CustomEvent("reveal",{bubbles: true}));
  };

  // Property handlers
  Object.defineProperties(BrickCardElementPrototype, {
    'selected': {
      get : function () {
        return this.hasAttribute('selected');
      },
      set : function (newVal) {
        if (newVal) {
          this.setAttribute('selected','');
        } else {
          this.removeAttribute('selected');
        }
      }
    },
    'transitionType': {
      get: function() {
        return this.getAttribute("transition-type");
      },
      set: function(newVal) {
        this.setAttribute("transition-type", newVal);
      }
    }
  });

  // Register the element
  window.BrickCardElement = document.registerElement('brick-card', {
    prototype: BrickCardElementPrototype
  });

})();
;
/* global Platform */
(function () {

  var currentScript = document._currentScript || document.currentScript;

  var requestAnimationFrame = window.requestAnimationFrame ||
                              window.webkitRequestAnimationFrame ||
                              function (fn) { setTimeout(fn, 16); };

  function delegate(selector, handler) {
    return function(e) {
      var target = e.target;
      var delegateEl = e.currentTarget;
      var matches = delegateEl.querySelectorAll(selector);
      for (var el = target; el.parentNode && el !== delegateEl; el = el.parentNode) {
        for (var i = 0; i < matches.length; i++) {
          if (matches[i] === el) {
            handler.call(el, e);
            return;
          }
        }
      }
    };
  }

  var skipFrame = function(fn){
    requestAnimationFrame(function(){ requestAnimationFrame(fn); });
  };

  var sides = {
        next: ['nextElementSibling', 'firstElementChild'],
        previous: ['previousElementSibling', 'lastElementChild']
      };

  function indexOfCard(deck, card){
    return Array.prototype.indexOf.call(deck.children, card);
  }

  function getCard(deck, item){
    if (item && item.nodeName) {
      return item;
    } else {
      if (isNaN(item)) {
        return deck.querySelector(item);
      } else {
        return deck.children[item];
      }
    }
  }

  var card = document.createElement('brick-card');
  //ensure the children is a brick-card (or wraps it with one)
  function ensureIsCard(child){
    if(child.tagName !== 'BRICK-CARD'){
      var wrap = card.cloneNode();
      child.parentNode.replaceChild(wrap, child);
      wrap.appendChild(child);
    }
  }
  // check if a card is a card in a deck
  function checkCard(deck, card){
    return card &&
           deck === card.parentNode &&
           card.nodeName.toLowerCase() === 'brick-card';
  }

  function shuffle(deck, side, direction){
    var getters = sides[side];
    var selected = deck.selectedCard && deck.selectedCard[getters[0]];

    if (selected) {
      deck.showCard(selected, {'direction': direction});
    } else if (deck.loop || deck.selectedIndex === -1) {
      deck.showCard(deck[getters[1]], {'direction': direction});
    }
  }

  var BrickDeckElementPrototype = Object.create(HTMLElement.prototype);

  BrickDeckElementPrototype.createdCallback = function() {
    this.ns = {};
    var children = this.children, i, max;

    for(i=0, max=children.length; i<max; i++){
      ensureIsCard(children[i]);
    }

    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        var added = mutation.addedNodes || [];
        for(var i=0, max=added.length; i<max; i++){
          ensureIsCard(added[i]);
        }
      });
    });

    observer.observe(this, { childList: true });
  };

  BrickDeckElementPrototype.attachedCallback = function() {

    var importDoc = currentScript.ownerDocument;
    var template = importDoc.querySelector('#brick-deck-template');

    // fix styling for polyfill
    if (Platform.ShadowCSS) {
      var styles = template.content.querySelectorAll('style');
      for (var i = 0; i < styles.length; i++) {
        var style = styles[i];
        var cssText = Platform.ShadowCSS.shimStyle(style, 'brick-deck');
        Platform.ShadowCSS.addCssToDocument(cssText);
        style.remove();
      }
    }

    // create shadowRoot and append template to it.
    var shadowRoot = this.createShadowRoot();
    shadowRoot.appendChild(template.content.cloneNode(true));

    this.revealHandler = delegate('brick-card', function(e) {
      e.currentTarget.showCard(this);
    });
    this.addEventListener('reveal', this.revealHandler);
  };

  BrickDeckElementPrototype.detachedCallback = function() {
    this.removeEventListener('reveal', this.revealHandler);
  };

  BrickDeckElementPrototype.attributeChangedCallback = function (attr, oldVal, newVal) {
    if (attr in attrs) {
      attrs[attr].call(this, oldVal, newVal);
    }
  };

  var attrs = {
    'selected-index': function (oldVal, newVal) {
      var index = parseInt(newVal);
      if (!isNaN(index)  && this.cards[index] !== this.selectedCard) {
        this.showCard(index);
      }
    }
  };

  BrickDeckElementPrototype.nextCard = function(direction){
    shuffle(this, 'next', direction);
  };

  BrickDeckElementPrototype.previousCard = function(direction){
    shuffle(this, 'previous', direction);
  };

  BrickDeckElementPrototype.showCard = function(item, options){
    options = options || {};
    var direction = options.direction;
    var skipTransition = options.skipTransition;
    var card = getCard(this, item);
    if (!checkCard(this, card) || (card === this.selectedCard)) {
      return;
    }
    var selectedCard = this.ns.selectedCard;
    var currentIndex = indexOfCard(this, selectedCard);
    var nextIndex = indexOfCard(this, card);
    if (!direction) {
      direction = nextIndex > currentIndex ? 'forward' : 'reverse';
      // if looping is turned on, check if the other way round is shorter
      if (this.loop) {
        // the distance between two cards
        var dist = nextIndex - currentIndex;
        // the distance between two cards when skipping over the end of the deck
        var distLooped = this.cards.length - Math.max(nextIndex,currentIndex) + Math.min(nextIndex,currentIndex);
        // set the direction if the looped way is shorter
        if (Math.abs(distLooped) < Math.abs(dist)) {
          direction = nextIndex < currentIndex ? 'forward' : 'reverse';
        }
      }
    }
    // hide the old card
    if (selectedCard) { this.hideCard(selectedCard, direction); }
    this.ns.selectedCard = card;
    this.ns.selectedIndex = nextIndex;
    this.setAttribute("selected-index", nextIndex);
    if (!card.selected) { card.selected = true; }
    card.removeAttribute("hide"); // be safe
    var hasTransition = card.hasAttribute('transition-type') || this.hasAttribute('transition-type');
    if (!skipTransition && hasTransition) {
      // set attributes, set transitionend listener, skip a frame set transition attribute
      card.setAttribute('transition-direction', direction);
      var transitionendHandler = function() {
        card.dispatchEvent(new CustomEvent('show',{'bubbles': true}));
        card.removeEventListener('transitionend', transitionendHandler);
      };
      card.addEventListener('transitionend', transitionendHandler);
      skipFrame(function(){ card.setAttribute('transition', ''); });
    } else {
      card.dispatchEvent(new CustomEvent('show',{'bubbles': true}));
      if (hasTransition) {
        card.setAttribute('transition', '');
      }
    }
  };

  BrickDeckElementPrototype.hideCard = function(item, direction){
    var card = getCard(this, item);
    if (!checkCard(this, card) || (card !== this.selectedCard)) {
      return;
    }
    this.ns.selectedCard = null;
    if (card.selected) { card.selected = false; }
    var hasTransition = card.hasAttribute('transition-type') || this.hasAttribute('transition-type');
    if (hasTransition) {
      // set attributes, set transitionend listener, skip a frame set transition attribute
      var transitionendHandler = function() {
        card.removeAttribute('hide');
        card.removeAttribute('transition');
        card.removeAttribute('transition-direction');
        card.dispatchEvent(new CustomEvent('hide',{'bubbles': true}));
        card.removeEventListener('transitionend', transitionendHandler);
      };
      card.addEventListener('transitionend', transitionendHandler);
      skipFrame(function(){
        card.setAttribute('transition-direction', direction || 'reverse');
        card.setAttribute('hide', '');
      });
    } else {
      card.dispatchEvent(new CustomEvent('hide',{'bubbles': true}));
    }
  };

  // Property handlers
  Object.defineProperties(BrickDeckElementPrototype, {
    'loop': {
      get: function() {
        return this.hasAttribute('loop');
      },
      set: function(newVal) {
        if (newVal) {
          this.setAttribute('loop', newVal);
        } else {
          this.removeAttribute('loop');
        }
      }
    },
    'cards': {
      get: function () {
        var cardList = this.querySelectorAll("brick-card");
        return Array.prototype.slice.call(cardList);
      }
    },
    'selectedCard': {
      get: function() {
        return this.ns.selectedCard || null;
      }
    },
    'selectedIndex': {
      get: function() {
        return this.hasAttribute('selected-index') ? Number(this.getAttribute('selected-index')) : -1;
      },
      set: function(value) {
        var index = Number(value);
        var card = this.cards[index];
        if (card) {
          if (card !== this.ns.selectedCard) {
            this.showCard(card);
          }
        } else {
          this.removeAttribute('selected-index');
          if (this.ns.selectedCard) {
            this.hideCard(this.ns.selectedCard);
          }
        }
      }
    },
    'transitionType': {
      get: function() {
        return this.getAttribute('transition-type');
      },
      set: function(newVal) {
        this.setAttribute('transition-type', newVal);
      }
    }
  });

  // Register the element
  window.BrickDeckElement = document.registerElement('brick-deck', {
    prototype: BrickDeckElementPrototype
  });

})();
<commit_msg>update the dist file as well<commit_after>(function () {

  var BrickCardElementPrototype = Object.create(HTMLElement.prototype);

  BrickCardElementPrototype.createdCallback = function () {
    this.ns = {};
  };

  BrickCardElementPrototype.attachedCallback = function () {
    var deck = this.parentNode;
    if (deck.nodeName.toLowerCase() === 'brick-deck') {
      this.ns.deck = deck;
      if (this !== deck.selectedCard && this.selected) {
        deck.showCard(this, {'skipTransition':true});
      }
    }
  };

  BrickCardElementPrototype.detachedCallback = function () {
    var deck = this.ns.deck;
    if (deck) {
      if (this === deck.selectedCard) {
        deck.selectedCard = null;
        deck.removeAttribute('selected-index');
      }
      this.ns.deck = null;
    }
  };

  BrickCardElementPrototype.attributeChangedCallback = function (attr, oldVal, newVal) {
    if (attr in attrs) {
      attrs[attr].call(this, oldVal, newVal);
    }
  };

  // Attribute handlers
  var attrs = {
    'selected': function (oldVal, newVal) {
      var deck = this.ns.deck;
      if (!deck) { return; }
      // check for null because empty string is true
      // for our booleon attribute
      if (newVal !== null) {
        if (this !== deck.selectedCard) { deck.showCard(this); }
      } else {
        if (this === deck.selectedCard) { deck.hideCard(this); }
      }
    },
  };

  BrickCardElementPrototype.reveal = function() {
    this.dispatchEvent(new CustomEvent("reveal",{bubbles: true}));
  };

  // Property handlers
  Object.defineProperties(BrickCardElementPrototype, {
    'selected': {
      get : function () {
        return this.hasAttribute('selected');
      },
      set : function (newVal) {
        if (newVal) {
          this.setAttribute('selected','');
        } else {
          this.removeAttribute('selected');
        }
      }
    },
    'transitionType': {
      get: function() {
        return this.getAttribute("transition-type");
      },
      set: function(newVal) {
        this.setAttribute("transition-type", newVal);
      }
    }
  });

  // Register the element
  window.BrickCardElement = document.registerElement('brick-card', {
    prototype: BrickCardElementPrototype
  });

})();
;
/* global Platform */
(function () {

  var currentScript = document._currentScript || document.currentScript;

  var requestAnimationFrame = window.requestAnimationFrame ||
                              window.webkitRequestAnimationFrame ||
                              function (fn) { setTimeout(fn, 16); };

  function delegate(selector, handler) {
    return function(e) {
      var target = e.target;
      var delegateEl = e.currentTarget;
      var matches = delegateEl.querySelectorAll(selector);
      for (var el = target; el.parentNode && el !== delegateEl; el = el.parentNode) {
        for (var i = 0; i < matches.length; i++) {
          if (matches[i] === el) {
            handler.call(el, e);
            return;
          }
        }
      }
    };
  }

  var skipFrame = function(fn){
    requestAnimationFrame(function(){ requestAnimationFrame(fn); });
  };

  var sides = {
        next: ['nextElementSibling', 'firstElementChild'],
        previous: ['previousElementSibling', 'lastElementChild']
      };

  function indexOfCard(deck, card){
    return Array.prototype.indexOf.call(deck.children, card);
  }

  function getCard(deck, item){
    if (item && item.nodeName) {
      return item;
    } else {
      if (isNaN(item)) {
        return deck.querySelector(item);
      } else {
        return deck.children[item];
      }
    }
  }

  var card = document.createElement('brick-card');
  //ensure the children is a brick-card (or wraps it with one)
  function ensureIsCard(child){
    if(child.tagName !== 'BRICK-CARD'){
      var wrap = card.cloneNode(),
          attributes = ['selected', 'transition-type'],
          attribute;

      for(var i=0, max=attributes.length; i<max; i++){
        attribute = attributes[i];
        if(child.hasAttribute(attribute)){
          wrap.setAttribute(attribute, child.getAttribute(attribute));
        }
      }
      child.parentNode.replaceChild(wrap, child);
      wrap.appendChild(child);
    }
  }
  // check if a card is a card in a deck
  function checkCard(deck, card){
    return card &&
           deck === card.parentNode &&
           card.nodeName.toLowerCase() === 'brick-card';
  }

  function shuffle(deck, side, direction){
    var getters = sides[side];
    var selected = deck.selectedCard && deck.selectedCard[getters[0]];

    if (selected) {
      deck.showCard(selected, {'direction': direction});
    } else if (deck.loop || deck.selectedIndex === -1) {
      deck.showCard(deck[getters[1]], {'direction': direction});
    }
  }

  var BrickDeckElementPrototype = Object.create(HTMLElement.prototype);

  BrickDeckElementPrototype.createdCallback = function() {
    this.ns = {};
    var children = this.children, i, max;

    for(i=0, max=children.length; i<max; i++){
      ensureIsCard(children[i]);
    }

    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        var added = mutation.addedNodes || [];
        for(var i=0, max=added.length; i<max; i++){
          ensureIsCard(added[i]);
        }
      });
    });

    observer.observe(this, { childList: true });
  };

  BrickDeckElementPrototype.attachedCallback = function() {

    var importDoc = currentScript.ownerDocument;
    var template = importDoc.querySelector('#brick-deck-template');

    // fix styling for polyfill
    if (Platform.ShadowCSS) {
      var styles = template.content.querySelectorAll('style');
      for (var i = 0; i < styles.length; i++) {
        var style = styles[i];
        var cssText = Platform.ShadowCSS.shimStyle(style, 'brick-deck');
        Platform.ShadowCSS.addCssToDocument(cssText);
        style.remove();
      }
    }

    // create shadowRoot and append template to it.
    var shadowRoot = this.createShadowRoot();
    shadowRoot.appendChild(template.content.cloneNode(true));

    this.revealHandler = delegate('brick-card', function(e) {
      e.currentTarget.showCard(this);
    });
    this.addEventListener('reveal', this.revealHandler);
  };

  BrickDeckElementPrototype.detachedCallback = function() {
    this.removeEventListener('reveal', this.revealHandler);
  };

  BrickDeckElementPrototype.attributeChangedCallback = function (attr, oldVal, newVal) {
    if (attr in attrs) {
      attrs[attr].call(this, oldVal, newVal);
    }
  };

  var attrs = {
    'selected-index': function (oldVal, newVal) {
      var index = parseInt(newVal);
      if (!isNaN(index)  && this.cards[index] !== this.selectedCard) {
        this.showCard(index);
      }
    }
  };

  BrickDeckElementPrototype.nextCard = function(direction){
    shuffle(this, 'next', direction);
  };

  BrickDeckElementPrototype.previousCard = function(direction){
    shuffle(this, 'previous', direction);
  };

  BrickDeckElementPrototype.showCard = function(item, options){
    options = options || {};
    var direction = options.direction;
    var skipTransition = options.skipTransition;
    var card = getCard(this, item);
    if (!checkCard(this, card) || (card === this.selectedCard)) {
      return;
    }
    var selectedCard = this.ns.selectedCard;
    var currentIndex = indexOfCard(this, selectedCard);
    var nextIndex = indexOfCard(this, card);
    if (!direction) {
      direction = nextIndex > currentIndex ? 'forward' : 'reverse';
      // if looping is turned on, check if the other way round is shorter
      if (this.loop) {
        // the distance between two cards
        var dist = nextIndex - currentIndex;
        // the distance between two cards when skipping over the end of the deck
        var distLooped = this.cards.length - Math.max(nextIndex,currentIndex) + Math.min(nextIndex,currentIndex);
        // set the direction if the looped way is shorter
        if (Math.abs(distLooped) < Math.abs(dist)) {
          direction = nextIndex < currentIndex ? 'forward' : 'reverse';
        }
      }
    }
    // hide the old card
    if (selectedCard) { this.hideCard(selectedCard, direction); }
    this.ns.selectedCard = card;
    this.ns.selectedIndex = nextIndex;
    this.setAttribute("selected-index", nextIndex);
    if (!card.selected) { card.selected = true; }
    card.removeAttribute("hide"); // be safe
    var hasTransition = card.hasAttribute('transition-type') || this.hasAttribute('transition-type');
    if (!skipTransition && hasTransition) {
      // set attributes, set transitionend listener, skip a frame set transition attribute
      card.setAttribute('transition-direction', direction);
      var transitionendHandler = function() {
        card.dispatchEvent(new CustomEvent('show',{'bubbles': true}));
        card.removeEventListener('transitionend', transitionendHandler);
      };
      card.addEventListener('transitionend', transitionendHandler);
      skipFrame(function(){ card.setAttribute('transition', ''); });
    } else {
      card.dispatchEvent(new CustomEvent('show',{'bubbles': true}));
      if (hasTransition) {
        card.setAttribute('transition', '');
      }
    }
  };

  BrickDeckElementPrototype.hideCard = function(item, direction){
    var card = getCard(this, item);
    if (!checkCard(this, card) || (card !== this.selectedCard)) {
      return;
    }
    this.ns.selectedCard = null;
    if (card.selected) { card.selected = false; }
    var hasTransition = card.hasAttribute('transition-type') || this.hasAttribute('transition-type');
    if (hasTransition) {
      // set attributes, set transitionend listener, skip a frame set transition attribute
      var transitionendHandler = function() {
        card.removeAttribute('hide');
        card.removeAttribute('transition');
        card.removeAttribute('transition-direction');
        card.dispatchEvent(new CustomEvent('hide',{'bubbles': true}));
        card.removeEventListener('transitionend', transitionendHandler);
      };
      card.addEventListener('transitionend', transitionendHandler);
      skipFrame(function(){
        card.setAttribute('transition-direction', direction || 'reverse');
        card.setAttribute('hide', '');
      });
    } else {
      card.dispatchEvent(new CustomEvent('hide',{'bubbles': true}));
    }
  };

  // Property handlers
  Object.defineProperties(BrickDeckElementPrototype, {
    'loop': {
      get: function() {
        return this.hasAttribute('loop');
      },
      set: function(newVal) {
        if (newVal) {
          this.setAttribute('loop', newVal);
        } else {
          this.removeAttribute('loop');
        }
      }
    },
    'cards': {
      get: function () {
        var cardList = this.querySelectorAll("brick-card");
        return Array.prototype.slice.call(cardList);
      }
    },
    'selectedCard': {
      get: function() {
        return this.ns.selectedCard || null;
      }
    },
    'selectedIndex': {
      get: function() {
        return this.hasAttribute('selected-index') ? Number(this.getAttribute('selected-index')) : -1;
      },
      set: function(value) {
        var index = Number(value);
        var card = this.cards[index];
        if (card) {
          if (card !== this.ns.selectedCard) {
            this.showCard(card);
          }
        } else {
          this.removeAttribute('selected-index');
          if (this.ns.selectedCard) {
            this.hideCard(this.ns.selectedCard);
          }
        }
      }
    },
    'transitionType': {
      get: function() {
        return this.getAttribute('transition-type');
      },
      set: function(newVal) {
        this.setAttribute('transition-type', newVal);
      }
    }
  });

  // Register the element
  window.BrickDeckElement = document.registerElement('brick-deck', {
    prototype: BrickDeckElementPrototype
  });

})();
<|endoftext|>


<commit_before>import { combineReducers, createStore } from 'redux';
import count from './count';

const rootReducer = combineReducers({
  count,
});

export default createStore(rootReducer);
<commit_msg>Enable redux store debugger<commit_after>import { combineReducers, compose, createStore } from 'redux';
import count from './count';

const rootReducer = combineReducers({
  count,
});

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

export default createStore(rootReducer, composeEnhancers());
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var log = require('debug')('broadcast:db-api');

var Team = mongoose.model('Team');
var User = mongoose.model('User');

var async = require('async');

/**
 * Get all teams
 */
exports.allTeams = function allTeams (fn) {
  Team
  .find()
  .exec(function (err, teams) {
    if (err) return log(err), fn(err);

    if (!teams) return log('No teams found – returning null'), fn(null);

    return log('Found teams %s', teams.map(t => t.id)), fn(null, teams);
  });
}

/**
 * Add's `sender` to `reciever`'s accepts if `accepts`, else removes
 */
exports.modifyAccepts = function modifyAccepts (recieverDomain, senderDomain, accepts, fn) {
  Team
  .findOne({domain: recieverDomain})
  .exec(function (err, reciever) {
    if (err) return log(err), fn(err);

    Team
    .findOne({domain: senderDomain})
    .exec(function (err, sender) {
      if (err) return log(err), fn(err);

      if (accepts) {
        // add sender to reciever's accepts
        reciever.accepts.push(sender.id);
      } else {
        // if reciever currently accepts sender, remove sender from reciever's accepts
        if (reicever.accepts.indexOf(sender.id) > -1) {
          reciever.accepts.splice(sender.accepts.indexOf(sender.id), 1);
        }
      }

      reciever.save(function (err) {
        if (err) return log(err), fn(err);

        log('Successfully %s %s to %s\'s accepts', accepts ? 'added' : 'removed', senderDomain, recieverDomain);
        return fn(null, reciever);
      });
    });
  });
}

function promiseModifyAccepts (recieverDomain, senderDomain, accepts) {
  var promise = new Promise((resolve, reject) => {
    exports.modifyAccepts(recieverDomain, senderDomain, accepts, function (err, reciever) {
      if (err) return reject(err);

      return resolve(err);
    });
  });
  return promise;
}

/**
 * Add a new team with data in `team`
 */
exports.addTeam = function addTeam (team, fn) {
  team.accepts = [];

  exports.allTeams(function (err, teams) {
    if (err) return log(err), fn(err);

    teams.forEach(t => {
      team.accepts.push(t.id);
    });

    var newTeam = new Team(team);

    newTeam.save(function (err) {
      if (err) return log(err), fn(err);

      exports.allTeams(function (err, teams) {
        Promise
        .all( teams.map(t => promiseModifyAccepts(t.domain, newTeam.domain, true) )
        .then(teams => {
          return fn(null, newTeam);
        }).catch(err => {
          if (err) return log(err), fn(err);
        });
      });

    });
  });

}

/**
 * Get the teams that `outTeam` is allowed to send messages to
 */
exports.teamsFor = function (outTeamDomain, fn) {
  exports.allTeams(function (err, teams) {
    if (err) return fn(err);

    var outTeam = teams.filter(function (t) {
      return t.domain == outTeamDomain;
    })[0];

    if (outTeam) var outTeamId = outTeam.id;

    var teamsFor = teams.filter(function (t) {
      return t.accepts.indexOf(outTeamId) > -1;
    });

    log('%s is allowed to send to %s', outTeam.id, teamsFor.map(t => t.id));
    return fn(null, teamsFor);
  });
}

/**
 * Get a particular user
 */
exports.getUser = function getUser (username, fn) {
  User
  .findOne({username: username})
  .exec(function (err, user) {
    if (err) return log(err), fn(err);

    if (!user) return log('User with username %s not found', username), fn(null);

    return fn(null, user);
  });
}

/**
 * Get a particular user, creating one if it doesn't exist
 */
exports.ensureUser = function ensureUser (username, fn) {
  exports.getUser(function (err, user) {
    if (err) return log(err), fn(err);

    if (!user) {
      log('User with username %s not found, creating one...', username);
      var newUser = new User({username: username});
      newUser.save(function (err) {
        if (err) return log(err), fn(err);

        fn(null, newUser);
      });
    }

    return fn(null, user);
  });
}

/**
 * Makes user with username admin
 */
exports.makeUserAdmin = function (username, fn) {
  exports.ensureUser(username, function (err, user) {
    if (err) return fn(err); if (!user) fn(null);

    user.admin = true;
    user.save(function (err, user) {
      if (err) return log(err), fn(err);

      return log('Make %s admin', username), fn(null, user);
    });
  });
}

/**
 * Ban a particular user
 */
exports.modifySend = function (username, canSend, fn) {
  exports.ensureUser(username, function (err, user) {
    if (err) return fn(err); if (!user) fn(null);

    user.send = canSend;
    user.save(function (err, user) {
      if (err) return log(err), fn(err);

      return log('Make user %s\'s send privileges = %s', username, canSend), fn(null, user);
    });
  });
}

<commit_msg>miscounted parenthesis<commit_after>var mongoose = require('mongoose');
var log = require('debug')('broadcast:db-api');

var Team = mongoose.model('Team');
var User = mongoose.model('User');

var async = require('async');

/**
 * Get all teams
 */
exports.allTeams = function allTeams (fn) {
  Team
  .find()
  .exec(function (err, teams) {
    if (err) return log(err), fn(err);

    if (!teams) return log('No teams found – returning null'), fn(null);

    return log('Found teams %s', teams.map(t => t.id)), fn(null, teams);
  });
}

/**
 * Add's `sender` to `reciever`'s accepts if `accepts`, else removes
 */
exports.modifyAccepts = function modifyAccepts (recieverDomain, senderDomain, accepts, fn) {
  Team
  .findOne({domain: recieverDomain})
  .exec(function (err, reciever) {
    if (err) return log(err), fn(err);

    Team
    .findOne({domain: senderDomain})
    .exec(function (err, sender) {
      if (err) return log(err), fn(err);

      if (accepts) {
        // add sender to reciever's accepts
        reciever.accepts.push(sender.id);
      } else {
        // if reciever currently accepts sender, remove sender from reciever's accepts
        if (reicever.accepts.indexOf(sender.id) > -1) {
          reciever.accepts.splice(sender.accepts.indexOf(sender.id), 1);
        }
      }

      reciever.save(function (err) {
        if (err) return log(err), fn(err);

        log('Successfully %s %s to %s\'s accepts', accepts ? 'added' : 'removed', senderDomain, recieverDomain);
        return fn(null, reciever);
      });
    });
  });
}

function promiseModifyAccepts (recieverDomain, senderDomain, accepts) {
  var promise = new Promise((resolve, reject) => {
    exports.modifyAccepts(recieverDomain, senderDomain, accepts, function (err, reciever) {
      if (err) return reject(err);

      return resolve(err);
    });
  });
  return promise;
}

/**
 * Add a new team with data in `team`
 */
exports.addTeam = function addTeam (team, fn) {
  team.accepts = [];

  exports.allTeams(function (err, teams) {
    if (err) return log(err), fn(err);

    teams.forEach(t => {
      team.accepts.push(t.id);
    });

    var newTeam = new Team(team);

    newTeam.save(function (err) {
      if (err) return log(err), fn(err);

      exports.allTeams(function (err, teams) {
        Promise
        .all( teams.map(t => promiseModifyAccepts(t.domain, newTeam.domain, true) ))
        .then(teams => {
          return fn(null, newTeam);
        }).catch(err => {
          if (err) return log(err), fn(err);
        });
      });

    });
  });

}

/**
 * Get the teams that `outTeam` is allowed to send messages to
 */
exports.teamsFor = function (outTeamDomain, fn) {
  exports.allTeams(function (err, teams) {
    if (err) return fn(err);

    var outTeam = teams.filter(function (t) {
      return t.domain == outTeamDomain;
    })[0];

    if (outTeam) var outTeamId = outTeam.id;

    var teamsFor = teams.filter(function (t) {
      return t.accepts.indexOf(outTeamId) > -1;
    });

    log('%s is allowed to send to %s', outTeam.id, teamsFor.map(t => t.id));
    return fn(null, teamsFor);
  });
}

/**
 * Get a particular user
 */
exports.getUser = function getUser (username, fn) {
  User
  .findOne({username: username})
  .exec(function (err, user) {
    if (err) return log(err), fn(err);

    if (!user) return log('User with username %s not found', username), fn(null);

    return fn(null, user);
  });
}

/**
 * Get a particular user, creating one if it doesn't exist
 */
exports.ensureUser = function ensureUser (username, fn) {
  exports.getUser(function (err, user) {
    if (err) return log(err), fn(err);

    if (!user) {
      log('User with username %s not found, creating one...', username);
      var newUser = new User({username: username});
      newUser.save(function (err) {
        if (err) return log(err), fn(err);

        fn(null, newUser);
      });
    }

    return fn(null, user);
  });
}

/**
 * Makes user with username admin
 */
exports.makeUserAdmin = function (username, fn) {
  exports.ensureUser(username, function (err, user) {
    if (err) return fn(err); if (!user) fn(null);

    user.admin = true;
    user.save(function (err, user) {
      if (err) return log(err), fn(err);

      return log('Make %s admin', username), fn(null, user);
    });
  });
}

/**
 * Ban a particular user
 */
exports.modifySend = function (username, canSend, fn) {
  exports.ensureUser(username, function (err, user) {
    if (err) return fn(err); if (!user) fn(null);

    user.send = canSend;
    user.save(function (err, user) {
      if (err) return log(err), fn(err);

      return log('Make user %s\'s send privileges = %s', username, canSend), fn(null, user);
    });
  });
}

<|endoftext|>


<commit_before>(function() {

var nodes = {};

var links = {};

var config = {
    debug: false,
    layout: 'horizontal'
};

// ============================= HtmlRenderer ==================================
// =============================================================================

var HtmlRenderer = {

    'model/new': function(root, update) {

        if (root.classList) root.classList.add('rpd-model');

    },

    'node/add': function(root, update) {

        var node = update.node;

        var nodeBox = quickElm('div', 'rpd-node-box');
        var nodeElm = quickElm('div', 'rpd-node');
        var bodyElm = quickElm('div', 'rpd-body');

        var inletsElm = quickElm('ul', 'rpd-inlets');
        function addInlet(inletElm) {
            var holder = quickElm('li', 'rpd-inlet');
            holder.appendChild(inletElm);
            inletsElm.appendChild(holder);
        }
        var outletsElm = quickElm('ul', 'rpd-outlets');
        function addOutlet(outletElm) {
            var holder = quickElm('li', 'rpd-outlet');
            holder.appendChild(outletElm);
            outletsElm.appendChild(holder);
        }

        nodes[node.id] = { box: nodeBox, elm: nodeElm, body: bodyElm,
                           addInlet: addInlet, addOutlet: addOutlet,
                           inlets: {}, outlets: {},
                           inletsNum: 0, outletsNum: 0 };

        bodyElm.appendChild(inletsElm);
        bodyElm.appendChild(outletsElm);

        var titleElm = quickElm('div', 'rpd-title');
        titleElm.appendChild(quickElmVal('span', 'rpd-name', node.name));
        if (config.debug) titleElm.appendChild(quickElmVal('span', 'rpd-type', node.type));
        nodeElm.appendChild(titleElm);
        nodeElm.appendChild(bodyElm);

        if (nodeElm.classList) nodeElm.classList.add('rpd-'+node.type.replace('/','-'));

        applyNextNodeRect(node, nodeBox);

        nodeBox.appendChild(nodeElm);

        root.appendChild(nodeBox);

    },

    'node/remove': function(root, update) {},

    'inlet/add': function(root, update) {

        var inlet = update.inlet;

        var nodeData = nodes[inlet.node.id];
        var addInletF = nodeData.addInlet;

        var inletElm = quickElm('div', 'rpd-inlet');
        var valueElm = quickElm('span', 'rpd-value rpd-stale');
        inletElm.appendChild(valueElm);

        nodeData.inlets[inlet.id] = { elm: inletElm, valueElm: valueElm };

        inletElm.appendChild(quickElmVal('span', 'rpd-name', inlet.name));
        if (config.debug) inletElm.appendChild(quickElmVal('span', 'rpd-type', inlet.type));

        if (inletElm.classList) inletElm.classList.add('rpd-'+inlet.type.replace('/','-'));

        addInletF(inletElm);

        nodeData.inletsNum++;

    },

    'inlet/remove': function(root, update) {},

    'inlet/update': function(root, update) {

        var inlet = update.inlet;

        var nodeData = nodes[inlet.node.id];
        var inletData = nodeData.inlets[inlet.id];

        var valueElm = inletData.valueElm;
        valueElm.innerText = valueElm.textContent = update.value;
        valueUpdateEffect(inletData, valueElm);

    },

    'outlet/add': function(root, update) {

        var outlet = update.outlet;

        var nodeData = nodes[outlet.node.id];
        var addOutletF = nodeData.addOutlet;

        var outletElm = quickElm('div', 'rpd-outlet');
        var valueElm = quickElm('span', 'rpd-value rpd-stale');
        outletElm.appendChild(valueElm);

        nodeData.outlets[outlet.id] = { elm: outletElm, valueElm: valueElm };

        outletElm.appendChild(quickElmVal('span', 'rpd-name', outlet.name));
        if (config.debug) outletElm.appendChild(quickElmVal('span', 'rpd-type', outlet.type));

        if (outletElm.classList) outletElm.classList.add('rpd-'+outlet.type.replace('/','-'));

        addOutletF(outletElm);

        nodeData.outletsNum++;

    },

    'outlet/remove': function(root, update) {},

    'outlet/update': function(root, update) {

        var outlet = update.outlet;

        var nodeData = nodes[outlet.node.id];
        var outletData = nodeData.outlets[outlet.id];

        var valueElm = outletData.valueElm;
        valueElm.innerText = valueElm.textContent = update.value;
        valueUpdateEffect(outletData, valueElm);

    },

    'outlet/connect': function(root, update) {

        var link = update.link;
        var outlet = link.outlet;
        var inlet  = link.inlet;

        var outletElm = nodes[outlet.node.id].outlets[outlet.id].elm;
        var inletElm  = nodes[inlet.node.id].inlets[inlet.id].elm;

        var linkElm = createLink(outletElm, inletElm);

        links[link.id] = { elm: linkElm };

        root.appendChild(linkElm);

    },
    'link/adapt': function(root, update) {},
    'link/error': function(root, update) {}
};

// ================================ utils ======================================
// =============================================================================

function quickElm(type, cls) {
    var elm = document.createElement(type);
    if (cls) elm.className = cls;
    return elm;
}

function quickElmVal(type, cls, value) {
    var elm = document.createElement(type);
    elm.className = cls;
    elm.innerText = elm.textContent = value;
    return elm;
}

function valueUpdateEffect(storage, valueElm) {
    if (valueElm.classList) {
        valueElm.classList.remove("rpd-stale");
        valueElm.classList.add("rpd-fresh");
        if (storage.removeTimeout) clearTimeout(storage.removeTimeout);
        storage.removeTimeout = setTimeout(function() {
            valueElm.classList.remove("rpd-fresh");
            valueElm.classList.add("rpd-stale");
            storage.removeTimeout = null;
        }, 1000);
    }
}

function createLink(outletElm, inletElm) {
    var a = outletElm.getBoundingClientRect();
    var b = inletElm.getBoundingClientRect();

    var distance = Math.sqrt(((a.left - b.left) * (a.left - b.left)) +
                             ((a.top  - b.top ) * (a.top  - b.top )));
    var angle = Math.atan2(b.top - a.top, b.left - a.left);

    var linkElm = quickElm('span','rpd-link');
    linkElm.style.position = 'absolute';
    linkElm.style.width = Math.floor(distance) + 'px';
    linkElm.style.left = a.left + 'px';
    linkElm.style.top = a.top + 'px';
    linkElm.style.transformOrigin = 'left top';
    linkElm.style.transform = 'rotateZ(' + angle + 'rad)';
    return linkElm;
}

function rotateLink(root, degree) {
    // TODO:
}

var default_width = 100,
    default_height = 50,
    default_x_margin = 30;
    default_y_margin = 20,
    default_limits = [ 1000, 1000 ];

var node_rects = [];

function applyNextNodeRect(node, nodeElm, limits) {
    var width = node.def.minWidth || default_width,
        height = node.def.minHeight || default_height,
        limits = limits || default_limits;
    /*var w_sum = 0, h_sum = 0;
    for (var i = 0, il = node_rects.length; i < il; i++) {
        node_rects[i]
    } TODO */
    var new_rect;
    if (node_rects.length) {
        var last_rect = node_rects[node_rects.length-1];
        new_rect = [ last_rect[0], last_rect[1] + last_rect[3] + default_y_margin, width, height ];
    } else {
        new_rect = [ 0, 0, width, height ];
    }
    nodeElm.style.left = new_rect[0] + 'px';
    nodeElm.style.top = new_rect[1] + 'px';
    nodeElm.style.minWidth = new_rect[2] + 'px';
    nodeElm.style.minHeight = new_rect[3] + 'px';
    node_rects.push(new_rect);
}

// =========================== registration ====================================
// =============================================================================

Rpd.HtmlRenderer = HtmlRenderer;

Rpd.renderer('html', function(user_conf) {

    if (user_conf) {
        for (var prop in user_conf) {
            config[prop] = user_conf[prop];
        }
    }

    return function(root, update) {

        if (HtmlRenderer[update.type]) {
            HtmlRenderer[update.type](root, update);
        }

    }

});

})();
<commit_msg>planning quartz and pd layouts, instantiating HtmlRenderer<commit_after>(function() {

var default_config = {
    debug: false,
    layout: 'quartz'
};

// ============================= HtmlRenderer ==================================
// =============================================================================

function HtmlRenderer(user_config) {

    var nodes, links;

    var config = mergeConfig(user_config, default_config);

    return {

        'model/new': function(root, update) {

            nodes = {}; links = {};

            if (root.classList) {
                root.classList.add('rpd-model');
                if (config.layout) root.classList.add('rpd-layout-' + config.layout);
            }

        },

        'node/add': function(root, update) {

            var node = update.node;

            var nodeBox = quickElm('div', 'rpd-node-box');
            var nodeElm = quickElm('div', 'rpd-node');
            var bodyElm = quickElm('div', 'rpd-body');

            var inletsElm = quickElm('ul', 'rpd-inlets');
            function addInlet(inletElm) {
                var holder = quickElm('li', 'rpd-inlet');
                holder.appendChild(inletElm);
                inletsElm.appendChild(holder);
            }
            var outletsElm = quickElm('ul', 'rpd-outlets');
            function addOutlet(outletElm) {
                var holder = quickElm('li', 'rpd-outlet');
                holder.appendChild(outletElm);
                outletsElm.appendChild(holder);
            }

            nodes[node.id] = { box: nodeBox, elm: nodeElm, body: bodyElm,
                               addInlet: addInlet, addOutlet: addOutlet,
                               inlets: {}, outlets: {},
                               inletsNum: 0, outletsNum: 0 };

            var titleElm = quickElm('div', 'rpd-title');
            titleElm.appendChild(quickElmVal('span', 'rpd-name', node.name));
            if (config.debug) titleElm.appendChild(quickElmVal('span', 'rpd-type', node.type));

            if (!config.layout || (config.layout == 'quartz')) {

                bodyElm.appendChild(inletsElm);
                bodyElm.appendChild(outletsElm);

                nodeElm.appendChild(titleElm);
                nodeElm.appendChild(bodyElm);

            } else if (config.layout == 'pd') {

                nodeElm.appendChild(inletsElm);
                bodyElm.appendChild(titleElm);
                nodeElm.appendChild(bodyElm);
                nodeElm.appendChild(outletsElm);

            }

            if (nodeElm.classList) nodeElm.classList.add('rpd-'+node.type.replace('/','-'));

            applyNextNodeRect(node, nodeBox);

            nodeBox.appendChild(nodeElm);

            root.appendChild(nodeBox);

        },

        'node/remove': function(root, update) {},

        'inlet/add': function(root, update) {

            var inlet = update.inlet;

            var nodeData = nodes[inlet.node.id];
            var addInletF = nodeData.addInlet;

            var inletElm = quickElm('div', 'rpd-inlet');
            var valueElm = quickElm('span', 'rpd-value rpd-stale');
            inletElm.appendChild(valueElm);

            nodeData.inlets[inlet.id] = { elm: inletElm, valueElm: valueElm };

            inletElm.appendChild(quickElmVal('span', 'rpd-name', inlet.name));
            if (config.debug) inletElm.appendChild(quickElmVal('span', 'rpd-type', inlet.type));

            if (inletElm.classList) inletElm.classList.add('rpd-'+inlet.type.replace('/','-'));

            addInletF(inletElm);

            nodeData.inletsNum++;

        },

        'inlet/remove': function(root, update) {},

        'inlet/update': function(root, update) {

            var inlet = update.inlet;

            var nodeData = nodes[inlet.node.id];
            var inletData = nodeData.inlets[inlet.id];

            var valueElm = inletData.valueElm;
            valueElm.innerText = valueElm.textContent = update.value;
            valueUpdateEffect(inletData, valueElm);

        },

        'outlet/add': function(root, update) {

            var outlet = update.outlet;

            var nodeData = nodes[outlet.node.id];
            var addOutletF = nodeData.addOutlet;

            var outletElm = quickElm('div', 'rpd-outlet');
            var valueElm = quickElm('span', 'rpd-value rpd-stale');
            outletElm.appendChild(valueElm);

            nodeData.outlets[outlet.id] = { elm: outletElm, valueElm: valueElm };

            outletElm.appendChild(quickElmVal('span', 'rpd-name', outlet.name));
            if (config.debug) outletElm.appendChild(quickElmVal('span', 'rpd-type', outlet.type));

            if (outletElm.classList) outletElm.classList.add('rpd-'+outlet.type.replace('/','-'));

            addOutletF(outletElm);

            nodeData.outletsNum++;

        },

        'outlet/remove': function(root, update) {},

        'outlet/update': function(root, update) {

            var outlet = update.outlet;

            var nodeData = nodes[outlet.node.id];
            var outletData = nodeData.outlets[outlet.id];

            var valueElm = outletData.valueElm;
            valueElm.innerText = valueElm.textContent = update.value;
            valueUpdateEffect(outletData, valueElm);

        },

        'outlet/connect': function(root, update) {

            var link = update.link;
            var outlet = link.outlet;
            var inlet  = link.inlet;

            var outletElm = nodes[outlet.node.id].outlets[outlet.id].elm;
            var inletElm  = nodes[inlet.node.id].inlets[inlet.id].elm;

            var linkElm = createLink(outletElm, inletElm);

            links[link.id] = { elm: linkElm };

            root.appendChild(linkElm);

        },
        'link/adapt': function(root, update) {},
        'link/error': function(root, update) {}

    }; // return

} // function

// ================================ utils ======================================
// =============================================================================

function mergeConfig(user_conf, defaults) {
    if (user_conf) {
        var merged = {};
        for (var prop in defaults)  { merged[prop] = defaults[prop]; }
        for (var prop in user_conf) { merged[prop] = user_conf[prop]; }
        return merged;
    } else return defaults;
}

function quickElm(type, cls) {
    var elm = document.createElement(type);
    if (cls) elm.className = cls;
    return elm;
}

function quickElmVal(type, cls, value) {
    var elm = document.createElement(type);
    elm.className = cls;
    elm.innerText = elm.textContent = value;
    return elm;
}

function valueUpdateEffect(storage, valueElm) {
    if (valueElm.classList) {
        valueElm.classList.remove("rpd-stale");
        valueElm.classList.add("rpd-fresh");
        if (storage.removeTimeout) clearTimeout(storage.removeTimeout);
        storage.removeTimeout = setTimeout(function() {
            valueElm.classList.remove("rpd-fresh");
            valueElm.classList.add("rpd-stale");
            storage.removeTimeout = null;
        }, 1000);
    }
}

function createLink(outletElm, inletElm) {
    var a = outletElm.getBoundingClientRect();
    var b = inletElm.getBoundingClientRect();

    var distance = Math.sqrt(((a.left - b.left) * (a.left - b.left)) +
                             ((a.top  - b.top ) * (a.top  - b.top )));
    var angle = Math.atan2(b.top - a.top, b.left - a.left);

    var linkElm = quickElm('span','rpd-link');
    linkElm.style.position = 'absolute';
    linkElm.style.width = Math.floor(distance) + 'px';
    linkElm.style.left = a.left + 'px';
    linkElm.style.top = a.top + 'px';
    linkElm.style.transformOrigin = 'left top';
    linkElm.style.transform = 'rotateZ(' + angle + 'rad)';
    return linkElm;
}

function rotateLink(root, degree) {
    // TODO:
}

var default_width = 100,
    default_height = 50,
    default_x_margin = 30;
    default_y_margin = 20,
    default_limits = [ 1000, 1000 ];

var node_rects = [];

function applyNextNodeRect(node, nodeElm, limits) {
    var width = node.def.minWidth || default_width,
        height = node.def.minHeight || default_height,
        limits = limits || default_limits;
    /*var w_sum = 0, h_sum = 0;
    for (var i = 0, il = node_rects.length; i < il; i++) {
        node_rects[i]
    } TODO */
    var new_rect;
    if (node_rects.length) {
        var last_rect = node_rects[node_rects.length-1];
        new_rect = [ last_rect[0], last_rect[1] + last_rect[3] + default_y_margin, width, height ];
    } else {
        new_rect = [ 0, 0, width, height ];
    }
    nodeElm.style.left = new_rect[0] + 'px';
    nodeElm.style.top = new_rect[1] + 'px';
    nodeElm.style.minWidth = new_rect[2] + 'px';
    nodeElm.style.minHeight = new_rect[3] + 'px';
    node_rects.push(new_rect);
}

// =========================== registration ====================================
// =============================================================================

Rpd.HtmlRenderer = HtmlRenderer;

Rpd.renderer('html', function(user_conf) {

    var instance = HtmlRenderer(user_conf);

    return function(root, update) {

        if (instance[update.type]) {
            instance[update.type](root, update);
        }

    }

});

})();
<|endoftext|>


<commit_before>const React = require('react')
const e = React.createElement
const Component = React.Component
const bindActionCreators = require('redux').bindActionCreators
const connect = require('react-redux').connect
const LoadingActions = require('../actions/loading')
const nodegit = require('../utils/nodegit').nodegit
const hashHistory = require('react-router').hashHistory

const LIMIT = 250

class History extends Component {

	constructor(props) {
		super(props)

		this.state = {
			tree: [],
		}
	}

	componentDidMount() {
		this.refresh()
	}

	refresh() {
		this.props.actions.loading.IncrementLoadingJobs()
		const tree = []
		let commitsPool = []
		let nextIsRemote = false
		let nextIsLocal = false

		const processPool = () => {
			if (commitsPool.length === 0 || tree.length === LIMIT) { // @TODO: note to user that limit was reached
				return
			}
			let nextCommit = commitsPool.reduce((accumulator, current) => {
				if (accumulator.commit.timeMs() < current.commit.timeMs()) {
					return current
				}
				return accumulator
			})
			commitsPool = commitsPool.filter((commit) => {
				if (commit.commit.sha() === nextCommit.commit.sha()) {
					if (commit.branch === 'remote') {
						nextIsRemote = true
					} else if (commit.branch === 'local') {
						nextIsLocal = true
					}
					return false
				} else {
					return true
				}
			})
			if (nextIsRemote && nextIsLocal) {
				nextCommit.branch = 'common'
			}
			return nextCommit.commit.getParents()
				.then((parents) => {
					tree.push({
						branch: nextCommit.branch,
						message: nextCommit.commit.message().trim(),
						sha: nextCommit.commit.sha(),
						isMergeCommit: parents.length > 1,
					})
					commitsPool = commitsPool.concat(parents.map((commit) => {
						return {
							commit,
							branch: nextCommit.branch,
						}
					}))
					return processPool()
				})
		}

		let repo
		const getTopCommit = (reference, branch) => {
			return repo.getBranchCommit(reference)
				.then((commit) => commitsPool.push({
					commit,
					branch,
				}))
				.then(() => reference)
		}

		nodegit.Repository.open(this.props.projects.active.path)
			.then((r) => {
				repo = r
				return repo.getCurrentBranch()
			})
			.then((reference) => getTopCommit(reference, 'local'))
			.then((branch) => nodegit.Branch.upstream(branch))
			.then((reference) => getTopCommit(reference, 'remote'))
			.catch((error) => {
				console.error(error)
			})
			.then(() => processPool())
			.then(() => {
				this.setState(Object.assign({}, this.state, {
					tree,
				}))
			})
			.catch((error) => {
				console.error(error)
			})
			.then(() => {
				this.props.actions.loading.DecrementLoadingJobs()
			})
	}

	renderTree() {
		let lineRemote = false
		let lineLocal = false

		return (
			e(
				'div',
				{
					className: 'history-tree',
				},
				e(
					'div',
					{
						className: 'history-titles',
					},
					e(
						'h2',
						{
							className: 'history-title',
						},
						'Sdílené změny'
					),
					e(
						'h2',
						{
							className: 'history-title',
						},
						'Vaše nezazálohované změny'
					)
				),
				this.state.tree.map((node, i) => {
					const lineClasses = ['history-line']
					if (node.branch === 'common') {
						lineClasses.push('history-line-common')
					} else {
						if (node.branch === 'local') {
							lineLocal = true
						} else if (node.branch === 'remote') {
							lineRemote = true
						}
						if (lineRemote) {
							lineClasses.push('history-line-remote')
						}
						if (lineLocal) {
							lineClasses.push('history-line-local')
							if (this.state.tree[i+1] && this.state.tree[i+1].branch === 'common') {
								lineClasses.push('history-line-merge')
							}
						}
					}
					if (i === this.state.tree.length-1) {
						lineClasses.push('history-line-last')
					}
					const nodeClasses = ['history-node', `history-node-${node.branch}`]
					if (node.isMergeCommit) {
						nodeClasses.push('history-node-mergeCommit')
					}
					const message = node.message.split('\n')
					return e(
						'div',
						{
							key: i,
							className: nodeClasses.join(' '),
						},
						e(
							'div',
							{
								className: lineClasses.join(' '),
							},
							e(
								'span',
								{
									className: 'history-line-in',
								}
							)
						),
						e(
							'button',
							{
								className: 'history-node-in',
								onClick: () => {
									hashHistory.push(`/commitDetail/${node.sha}`)
								},
							},
							message[0] + (message.length > 1 ? '…' : '')
						)
					)
				})
			)
		)
	}

	render() {
		return (
			e(
				'div',
				null,
				e('h1', null, 'Historie'),
				this.renderTree()
			)
		)
	}

}

function mapStateToProps(state) {
	return {
		loading: state.loading,
		projects: state.projects,
	}
}

function mapDispatchToProps(dispatch) {
	return {
		actions: {
			loading: bindActionCreators(LoadingActions, dispatch),
		}
	}
}

module.exports = connect(mapStateToProps, mapDispatchToProps)(History)
<commit_msg>History: show titles only when local changes<commit_after>const React = require('react')
const e = React.createElement
const Component = React.Component
const bindActionCreators = require('redux').bindActionCreators
const connect = require('react-redux').connect
const LoadingActions = require('../actions/loading')
const nodegit = require('../utils/nodegit').nodegit
const hashHistory = require('react-router').hashHistory

const LIMIT = 250

class History extends Component {

	constructor(props) {
		super(props)

		this.state = {
			tree: [],
			countLocal: 0,
			countRemote: 0,
			countCommon: 0,
		}
	}

	componentDidMount() {
		this.refresh()
	}

	refresh() {
		this.props.actions.loading.IncrementLoadingJobs()
		const tree = []
		let commitsPool = []
		let nextIsRemote = false
		let nextIsLocal = false
		const count = {
			local: 0,
			remote: 0,
			common: 0,
		}

		const processPool = () => {
			if (commitsPool.length === 0 || tree.length === LIMIT) { // @TODO: note to user that limit was reached
				return
			}
			let nextCommit = commitsPool.reduce((accumulator, current) => {
				if (accumulator.commit.timeMs() < current.commit.timeMs()) {
					return current
				}
				return accumulator
			})
			commitsPool = commitsPool.filter((commit) => {
				if (commit.commit.sha() === nextCommit.commit.sha()) {
					if (commit.branch === 'remote') {
						nextIsRemote = true
					} else if (commit.branch === 'local') {
						nextIsLocal = true
					}
					return false
				} else {
					return true
				}
			})
			if (nextIsRemote && nextIsLocal) {
				nextCommit.branch = 'common'
			}
			count[nextCommit.branch]++
			return nextCommit.commit.getParents()
				.then((parents) => {
					tree.push({
						branch: nextCommit.branch,
						message: nextCommit.commit.message().trim(),
						sha: nextCommit.commit.sha(),
						isMergeCommit: parents.length > 1,
					})
					commitsPool = commitsPool.concat(parents.map((commit) => {
						return {
							commit,
							branch: nextCommit.branch,
						}
					}))
					return processPool()
				})
		}

		let repo
		const getTopCommit = (reference, branch) => {
			return repo.getBranchCommit(reference)
				.then((commit) => commitsPool.push({
					commit,
					branch,
				}))
				.then(() => reference)
		}

		nodegit.Repository.open(this.props.projects.active.path)
			.then((r) => {
				repo = r
				return repo.getCurrentBranch()
			})
			.then((reference) => getTopCommit(reference, 'local'))
			.then((branch) => nodegit.Branch.upstream(branch))
			.then((reference) => getTopCommit(reference, 'remote'))
			.catch((error) => {
				console.error(error)
			})
			.then(() => processPool())
			.then(() => {
				this.setState(Object.assign({}, this.state, {
					tree,
					countLocal: count.local,
					countRemote: count.remote,
					countCommon: count.common,
				}))
			})
			.catch((error) => {
				console.error(error)
			})
			.then(() => {
				this.props.actions.loading.DecrementLoadingJobs()
			})
	}

	renderTree() {
		let lineRemote = false
		let lineLocal = false

		return (
			e(
				'div',
				{
					className: 'history-tree',
				},
				this.state.countLocal === 0 ? null : e(
					'div',
					{
						className: 'history-titles',
					},
					e(
						'h2',
						{
							className: 'history-title',
						},
						'Sdílené změny'
					),
					e(
						'h2',
						{
							className: 'history-title',
						},
						'Vaše nezazálohované změny'
					)
				),
				this.state.tree.map((node, i) => {
					const lineClasses = ['history-line']
					if (node.branch === 'common') {
						lineClasses.push('history-line-common')
					} else {
						if (node.branch === 'local') {
							lineLocal = true
						} else if (node.branch === 'remote') {
							lineRemote = true
						}
						if (lineRemote) {
							lineClasses.push('history-line-remote')
						}
						if (lineLocal) {
							lineClasses.push('history-line-local')
							if (this.state.tree[i+1] && this.state.tree[i+1].branch === 'common') {
								lineClasses.push('history-line-merge')
							}
						}
					}
					if (i === this.state.tree.length-1) {
						lineClasses.push('history-line-last')
					}
					const nodeClasses = ['history-node', `history-node-${node.branch}`]
					if (node.isMergeCommit) {
						nodeClasses.push('history-node-mergeCommit')
					}
					const message = node.message.split('\n')
					return e(
						'div',
						{
							key: i,
							className: nodeClasses.join(' '),
						},
						e(
							'div',
							{
								className: lineClasses.join(' '),
							},
							e(
								'span',
								{
									className: 'history-line-in',
								}
							)
						),
						e(
							'button',
							{
								className: 'history-node-in',
								onClick: () => {
									hashHistory.push(`/commitDetail/${node.sha}`)
								},
							},
							message[0] + (message.length > 1 ? '…' : '')
						)
					)
				})
			)
		)
	}

	render() {
		return (
			e(
				'div',
				null,
				e('h1', null, 'Historie'),
				this.renderTree()
			)
		)
	}

}

function mapStateToProps(state) {
	return {
		loading: state.loading,
		projects: state.projects,
	}
}

function mapDispatchToProps(dispatch) {
	return {
		actions: {
			loading: bindActionCreators(LoadingActions, dispatch),
		}
	}
}

module.exports = connect(mapStateToProps, mapDispatchToProps)(History)
<|endoftext|>


<commit_before>require('./common');
const FileReceiver = require('./fileReceiver');
const { notify, findMetric, sendEvent } = require('./utils');
const bytes = require('bytes');
const Storage = require('./storage');
const storage = new Storage(localStorage);

const $ = require('jquery');
require('jquery-circle-progress');

const Raven = window.Raven;

$(document).ready(function() {
  //link back to homepage
  $('.send-new').attr('href', window.location.origin);

  $('.send-new').click(function() {
    sendEvent('recipient', 'restarted', {
      cd2: 'completed'
    });
  });

  $('.legal-links a, .social-links a, #dl-firefox').click(function(target) {
    const metric = findMetric(target.currentTarget.href);
    // record exited event by recipient
    sendEvent('recipient', 'exited', {
      cd3: metric
    });
  });

  const filename = $('#dl-filename').text();
  const bytelength = Number($('#dl-bytelength').text());
  const timeToExpiry = Number($('#dl-ttl').text());

  //initiate progress bar
  $('#dl-progress').circleProgress({
    value: 0.0,
    startAngle: -Math.PI / 2,
    fill: '#3B9DFF',
    size: 158,
    animation: { duration: 300 }
  });
  $('#download-btn').click(download);
  function download() {
    storage.totalDownloads += 1;

    const fileReceiver = new FileReceiver();
    const unexpiredFiles = storage.numFiles;

    fileReceiver.on('progress', progress => {
      window.onunload = function() {
        storage.referrer = 'cancelled-download';
        // record download-stopped (cancelled by tab close or reload)
        sendEvent('recipient', 'download-stopped', {
          cm1: bytelength,
          cm5: storage.totalUploads,
          cm6: unexpiredFiles,
          cm7: storage.totalDownloads,
          cd2: 'cancelled'
        });
      };

      $('#download-page-one').attr('hidden', true);
      $('#download-progress').removeAttr('hidden');
      const percent = progress[0] / progress[1];
      // update progress bar
      $('#dl-progress').circleProgress('value', percent);
      $('.percent-number').text(`${Math.floor(percent * 100)}`);
      $('.progress-text').text(
        `${filename} (${bytes(progress[0], {
          decimalPlaces: 1,
          fixedDecimals: true
        })} of ${bytes(progress[1], { decimalPlaces: 1 })})`
      );
    });

    let downloadEnd;
    fileReceiver.on('decrypting', isStillDecrypting => {
      // The file is being decrypted
      if (isStillDecrypting) {
        fileReceiver.removeAllListeners('progress');
        window.onunload = null;
        document.l10n.formatValue('decryptingFile').then(decryptingFile => {
          $('.progress-text').text(decryptingFile);
        });
      } else {
        downloadEnd = Date.now();
      }
    });

    fileReceiver.on('hashing', isStillHashing => {
      // The file is being hashed to make sure a malicious user hasn't tampered with it
      if (isStillHashing) {
        document.l10n.formatValue('verifyingFile').then(verifyingFile => {
          $('.progress-text').text(verifyingFile);
        });
      } else {
        $('.progress-text').text(' ');
        document.l10n
          .formatValues('downloadNotification', 'downloadFinish')
          .then(translated => {
            notify(translated[0]);
            $('.title').text(translated[1]);
          });
      }
    });

    const startTime = Date.now();

    // record download-started by recipient
    sendEvent('recipient', 'download-started', {
      cm1: bytelength,
      cm4: timeToExpiry,
      cm5: storage.totalUploads,
      cm6: unexpiredFiles,
      cm7: storage.totalDownloads
    });

    fileReceiver
      .download()
      .catch(err => {
        // record download-stopped (errored) by recipient
        sendEvent('recipient', 'download-stopped', {
          cm1: bytelength,
          cm5: storage.totalUploads,
          cm6: unexpiredFiles,
          cm7: storage.totalDownloads,
          cd2: 'errored',
          cd6: err
        });

        if (err.message === 'notfound') {
          location.reload();
        } else {
          document.l10n.formatValue('errorPageHeader').then(translated => {
            $('.title').text(translated);
          });
          $('#download-btn').attr('hidden', true);
          $('#expired-img').removeAttr('hidden');
        }
        throw err;
      })
      .then(([decrypted, fname]) => {
        const endTime = Date.now();
        const totalTime = endTime - startTime;
        const downloadTime = endTime - downloadEnd;
        const downloadSpeed = bytelength / (downloadTime / 1000);

        storage.referrer = 'completed-download';
        // record download-stopped (completed) by recipient
        sendEvent('recipient', 'download-stopped', {
          cm1: bytelength,
          cm2: totalTime,
          cm3: downloadSpeed,
          cm5: storage.totalUploads,
          cm6: unexpiredFiles,
          cm7: storage.totalDownloads,
          cd2: 'completed'
        });

        const dataView = new DataView(decrypted);
        const blob = new Blob([dataView]);
        const downloadUrl = URL.createObjectURL(blob);

        const a = document.createElement('a');
        a.href = downloadUrl;
        if (window.navigator.msSaveBlob) {
          // if we are in microsoft edge or IE
          window.navigator.msSaveBlob(blob, fname);
          return;
        }
        a.download = fname;
        document.body.appendChild(a);
        a.click();
      })
      .catch(err => {
        Raven.captureException(err);
        return Promise.reject(err);
      });
  }
});
<commit_msg>Prevent download button from being clicked multiple times<commit_after>require('./common');
const FileReceiver = require('./fileReceiver');
const { notify, findMetric, sendEvent } = require('./utils');
const bytes = require('bytes');
const Storage = require('./storage');
const storage = new Storage(localStorage);

const $ = require('jquery');
require('jquery-circle-progress');

const Raven = window.Raven;

$(document).ready(function() {
  //link back to homepage
  $('.send-new').attr('href', window.location.origin);

  $('.send-new').click(function() {
    sendEvent('recipient', 'restarted', {
      cd2: 'completed'
    });
  });

  $('.legal-links a, .social-links a, #dl-firefox').click(function(target) {
    const metric = findMetric(target.currentTarget.href);
    // record exited event by recipient
    sendEvent('recipient', 'exited', {
      cd3: metric
    });
  });

  const filename = $('#dl-filename').text();
  const bytelength = Number($('#dl-bytelength').text());
  const timeToExpiry = Number($('#dl-ttl').text());

  //initiate progress bar
  $('#dl-progress').circleProgress({
    value: 0.0,
    startAngle: -Math.PI / 2,
    fill: '#3B9DFF',
    size: 158,
    animation: { duration: 300 }
  });
  $('#download-btn').click(download);
  function download() {
    // Disable the download button to avoid accidental double clicks.
    $('#download-btn').attr('disabled', 'disabled');

    storage.totalDownloads += 1;

    const fileReceiver = new FileReceiver();
    const unexpiredFiles = storage.numFiles;

    fileReceiver.on('progress', progress => {
      window.onunload = function() {
        storage.referrer = 'cancelled-download';
        // record download-stopped (cancelled by tab close or reload)
        sendEvent('recipient', 'download-stopped', {
          cm1: bytelength,
          cm5: storage.totalUploads,
          cm6: unexpiredFiles,
          cm7: storage.totalDownloads,
          cd2: 'cancelled'
        });
      };

      $('#download-page-one').attr('hidden', true);
      $('#download-progress').removeAttr('hidden');
      const percent = progress[0] / progress[1];
      // update progress bar
      $('#dl-progress').circleProgress('value', percent);
      $('.percent-number').text(`${Math.floor(percent * 100)}`);
      $('.progress-text').text(
        `${filename} (${bytes(progress[0], {
          decimalPlaces: 1,
          fixedDecimals: true
        })} of ${bytes(progress[1], { decimalPlaces: 1 })})`
      );
    });

    let downloadEnd;
    fileReceiver.on('decrypting', isStillDecrypting => {
      // The file is being decrypted
      if (isStillDecrypting) {
        fileReceiver.removeAllListeners('progress');
        window.onunload = null;
        document.l10n.formatValue('decryptingFile').then(decryptingFile => {
          $('.progress-text').text(decryptingFile);
        });
      } else {
        downloadEnd = Date.now();
      }
    });

    fileReceiver.on('hashing', isStillHashing => {
      // The file is being hashed to make sure a malicious user hasn't tampered with it
      if (isStillHashing) {
        document.l10n.formatValue('verifyingFile').then(verifyingFile => {
          $('.progress-text').text(verifyingFile);
        });
      } else {
        $('.progress-text').text(' ');
        document.l10n
          .formatValues('downloadNotification', 'downloadFinish')
          .then(translated => {
            notify(translated[0]);
            $('.title').text(translated[1]);
          });
      }
    });

    const startTime = Date.now();

    // record download-started by recipient
    sendEvent('recipient', 'download-started', {
      cm1: bytelength,
      cm4: timeToExpiry,
      cm5: storage.totalUploads,
      cm6: unexpiredFiles,
      cm7: storage.totalDownloads
    });

    fileReceiver
      .download()
      .catch(err => {
        // record download-stopped (errored) by recipient
        sendEvent('recipient', 'download-stopped', {
          cm1: bytelength,
          cm5: storage.totalUploads,
          cm6: unexpiredFiles,
          cm7: storage.totalDownloads,
          cd2: 'errored',
          cd6: err
        });

        if (err.message === 'notfound') {
          location.reload();
        } else {
          document.l10n.formatValue('errorPageHeader').then(translated => {
            $('.title').text(translated);
          });
          $('#download-btn').attr('hidden', true);
          $('#expired-img').removeAttr('hidden');
        }
        throw err;
      })
      .then(([decrypted, fname]) => {
        const endTime = Date.now();
        const totalTime = endTime - startTime;
        const downloadTime = endTime - downloadEnd;
        const downloadSpeed = bytelength / (downloadTime / 1000);

        storage.referrer = 'completed-download';
        // record download-stopped (completed) by recipient
        sendEvent('recipient', 'download-stopped', {
          cm1: bytelength,
          cm2: totalTime,
          cm3: downloadSpeed,
          cm5: storage.totalUploads,
          cm6: unexpiredFiles,
          cm7: storage.totalDownloads,
          cd2: 'completed'
        });

        const dataView = new DataView(decrypted);
        const blob = new Blob([dataView]);
        const downloadUrl = URL.createObjectURL(blob);

        const a = document.createElement('a');
        a.href = downloadUrl;
        if (window.navigator.msSaveBlob) {
          // if we are in microsoft edge or IE
          window.navigator.msSaveBlob(blob, fname);
          return;
        }
        a.download = fname;
        document.body.appendChild(a);
        a.click();
      })
      .catch(err => {
        Raven.captureException(err);
        return Promise.reject(err);
      });
  }
});
<|endoftext|>


<commit_before><commit_msg>updated 添加按键重设置<commit_after><|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';

import {intersect, diff, withoutIdx} from 'utils/array';
import {parseInitialRecipeStrings, compareRecipes} from 'utils/recipe';
import {AddPartForm, AvailableRecipesList, AvailablePartBadge} from 'components';
import initialRecipeList from 'recipeLists/initial';

export default class App extends Component {
  state = {
    availableParts: [],
    recipes: parseInitialRecipeStrings(initialRecipeList)
  };

  calculateAvailableRecipes() {
    const {availableParts} = this.state;

    return this.state.recipes
      .map(recipe => Object.assign(recipe, {
        partsHave: intersect(recipe.parts, availableParts),
        partsLeft: diff(recipe.parts, availableParts)
      }))
      .sort(compareRecipes);
  }

  onAddAvailablePart(part) {
    this.setState({availableParts: this.state.availableParts.slice(0).concat([part])});
  }

  removeAvailablePart(index) {
    this.setState({availableParts: withoutIdx(this.state.availableParts, index)});
  }

  renderAvailablePartBadge(part, idx) {
    return <AvailablePartBadge key={idx} part={part} onRemove={() => this.removeAvailablePart(idx)}/>;
  }

  render() {
    return (

          <AddPartForm onAdd={::this.onAddAvailablePart} />

You're now having the following parts:

              {this.state.availableParts.map(::this.renderAvailablePartBadge)}

Available recipes:

            <AvailableRecipesList availableRecipes={::this.calculateAvailableRecipes()}/>

    )
  }
}
<commit_msg>searching through recipes regardless of case<commit_after>import React, {Component, PropTypes} from 'react';

import {intersect, diff, withoutIdx} from 'utils/array';
import {parseInitialRecipeStrings, compareRecipes} from 'utils/recipe';
import {AddPartForm, AvailableRecipesList, AvailablePartBadge} from 'components';
import initialRecipeList from 'recipeLists/initial';

export default class App extends Component {
  state = {
    availableParts: [],
    recipes: parseInitialRecipeStrings(initialRecipeList)
  };

  calculateAvailableRecipes() {
    const mapLowerCase = string => string.toLowerCase();
    const availableParts = this.state.availableParts.map(mapLowerCase);

    return this.state.recipes
      .map(recipe => ({
        ...recipe,
        partsHave: intersect(recipe.parts.map(mapLowerCase), availableParts),
        partsLeft: diff(recipe.parts.map(mapLowerCase), availableParts)
      }))
      .sort(compareRecipes);
  }

  onAddAvailablePart(part) {
    this.setState({availableParts: this.state.availableParts.slice(0).concat([part])});
  }

  removeAvailablePart(index) {
    this.setState({availableParts: withoutIdx(this.state.availableParts, index)});
  }

  renderAvailablePartBadge(part, idx) {
    return <AvailablePartBadge key={idx} part={part} onRemove={() => this.removeAvailablePart(idx)}/>;
  }

  render() {
    const {availableParts} = this.state;

    return (

                <AddPartForm onAdd={::this.onAddAvailablePart}/>

              {availableParts.map(::this.renderAvailablePartBadge)}

            <AvailableRecipesList availableRecipes={::this.calculateAvailableRecipes()}/>

    )
  }
}
<|endoftext|>


<commit_before><commit_msg>more langs<commit_after><|endoftext|>


<commit_before>import React, { Component } from 'react';
import Utils from '../utils';
import Task from '../task';
import colormap from 'colormap';
import { Handler, HandlerPopup } from './handler';
import classNames from 'classnames';

/* These are mostly for drawing */
const NUM_COLORS = 32;
const COLORS = colormap({
  colormap: 'rainbow-soft',   // pick a builtin colormap or add your own
  nshades: NUM_COLORS       // how many divisions
});
function hashCode(str) {
    var hash = 0;
    for (var i = 0; i < str.length; i++) {
        hash = ~~(((hash << 5) - hash) + str.charCodeAt(i));
    }
    return Math.abs(hash);
}
function getColor2(str) {
  return COLORS[hashCode(str) % NUM_COLORS];
}
function getColor(logEntry) {
  const hue = Task.getProjectColor(logEntry.project);
  return 'hsl(' + hue + ',100%,85%)';
}
function getStyle(logEntry) {
  const hue = Task.getProjectColor(logEntry.project);
}

/**
 * Show the work log
 * <Log log=[log entries] />
 */
export default class Log extends Component {

  constructor(props) {
      super(props);
      this.state = {
          edit: '',
          editStart: '',
          editEnd: ''
      };
  }

  shouldComponentUpdate(nextProps, nextState) {
    return (nextProps.log.length != this.props.log.length) ||
      (nextState.edit != this.state.edit);
  }

  getDuration(t1, t2) {
    try {
      return Math.floor((new Date(t2) - new Date(t1))/1000);
    }
    catch (e) {
      console.log(e);
      return 0;
    }
  }

  getLogEntryId(logEntry) {
    return logEntry.taskId + '.' + logEntry.startTime;
  }

  edit(logEntryId) {
    this.setState({
      edit: logEntryId
    });
  }

  render() {
    // 2017-02-24
    // 12:30 - 2:30 Documentation #21 35m (34%)
    // 2:30 - 4:00 Github Style 90m (100%)

    // group by day
    const days = [];
    const entriesByDay = {};
    let lastDay = -1;
    this.props.log.forEach( (logEntry, i) => {
      const day = Utils.getDay(logEntry.startTime);
      // create new day if necessary
      if (!entriesByDay[day]) {
        days.push(day);
        entriesByDay[day] = [];
      }
      entriesByDay[day].push(logEntry);
    });
    const rows = [];
    days.forEach((day) => {
      // append the day and its rows
      const dayEntries = entriesByDay[day];
      const dayStats = {
        numEntries: dayEntries.length,
        startTime: null,
        endTime: null,
        duration: 0,
        worked: 0
      };
      // Cumulative day stats
      dayEntries.forEach( (logEntry) => {
        if (!dayStats.startTime || dayStats.startTime > logEntry.startTime) {
          dayStats.startTime = logEntry.startTime;
        }
        if (!dayStats.endTime || dayStats.endTime < logEntry.endTime) {
          dayStats.endTime = logEntry.endTime;
        }
        dayStats.worked += logEntry.timeElapsed;
      });
      dayStats.duration = this.getDuration(dayStats.startTime, dayStats.endTime);
      rows.push((

          {day}

            {Utils.formatTimespan(dayStats.worked, true)}
             ({Utils.formatTimespan(dayStats.duration, true)})

      ));
      function chartHeight(duration) {
        return parseInt((duration*100)/dayStats.duration);
      }
      const chartRows = dayEntries.map( (logEntry, i) => {
        const start = chartHeight(this.getDuration(dayStats.startTime, logEntry.startTime));
        const height = Math.max(
          chartHeight(this.getDuration(logEntry.startTime, logEntry.endTime)),
          Math.min(2, 100-start));
        const style = {
          bottom: '' + start + '%',
          height: '' + height + '%',
          background: getColor(logEntry)
        };
        return (

        );
      });
      // The log entries
      const subrows = [];
      dayEntries.forEach( (logEntry, i) => {
        const label = logEntry.taskName || logEntry.task;
        const duration = this.getDuration(logEntry.startTime, logEntry.endTime);
        const utilization = Math.floor((logEntry.timeElapsed * 100) / duration);

        const style = {
          background: getColor(logEntry)
        };
        const logEntryId = this.getLogEntryId(logEntry);
        const editing = (logEntryId == this.state.edit);
        const edit = () => {
          console.log("Editing " + logEntryId);
          this.edit(logEntryId);
        };
        const className = classNames(
          'log-entry',
          { 'editing': editing }
        );
        subrows.push((

{chartRows[i]}

              {Utils.getTime(logEntry.startTime)} -
              {Utils.getTime(logEntry.endTime)}

            {label}

              {Utils.formatTimespan(logEntry.timeElapsed, true)}
              {Utils.formatTimespan(duration, true)}
              {utilization}%

        ));
      });

      rows.push((

          {subrows}

      ));

    });

    return (

        {rows}

    );
  }
}

class StatusPopup extends HandlerPopup {

    shouldComponentUpdate(nextProps, nextState) {
      return nextProps.log.length != this.props.log.length;
    }

    getDuration(t1, t2) {
      try {
        return Math.floor((new Date(t2) - new Date(t1))/1000);
      }
      catch (e) {
        console.log(e);
        return 0;
      }
    }

    render() {
      // group by day
      const days = [];
      const entriesByDay = {};
      let lastDay = -1;
      this.props.log.forEach( (logEntry, i) => {
        const day = Utils.getDay(logEntry.startTime);
        // create new day if necessary
        if (!entriesByDay[day]) {
          days.push(day);
          entriesByDay[day] = [];
        }
        entriesByDay[day].push(logEntry);
      });
      const rows = [];
      days.forEach((day) => {
        // append the day and its rows
        const dayEntries = entriesByDay[day];
        const dayStats = {
          numEntries: dayEntries.length,
          startTime: null,
          endTime: null,
          duration: 0,
          worked: 0
        };
        dayEntries.forEach( (logEntry) => {
          if (!dayStats.startTime || dayStats.startTime > logEntry.startTime) {
            dayStats.startTime = logEntry.startTime;
          }
          if (!dayStats.endTime || dayStats.endTime < logEntry.endTime) {
            dayStats.endTime = logEntry.endTime;
          }
          dayStats.worked += logEntry.timeElapsed;
        });
        dayStats.duration = this.getDuration(dayStats.startTime, dayStats.endTime);
        const colors = colormap({
          colormap: 'summer',   // pick a builtin colormap or add your own
          nshades: Math.max(dayStats.numEntries, 2)       // how many divisions
        });
        function chartHeight(duration) {
          return parseInt((duration*100)/dayStats.duration);
        }
        const chartRows = dayEntries.map( (logEntry, i) => {
          const start = chartHeight(this.getDuration(dayStats.startTime, logEntry.startTime));
          const height = Math.max(
            chartHeight(this.getDuration(logEntry.startTime, logEntry.endTime)),
            Math.min(2, 100-start));
          const style = {
            bottom: '' + start + '%',
            height: '' + height + '%',
            background: getColor(logEntry.taskId)
          };
          return (

          );
        });
        rows.push((

            {day}
            {Utils.formatTimespan(dayStats.duration)}
            {Utils.formatTimespan(dayStats.worked)}

        ));
        dayEntries.forEach( (logEntry, i) => {
          const label = logEntry.taskName || logEntry.task;
          const duration = this.getDuration(logEntry.startTime, logEntry.endTime);
          const utilization = Math.floor((logEntry.timeElapsed * 100) / duration);

          const firstCol = (i == 0) ? (

              {chartRows}

          ) : undefined;
          const style = {
            background: getColor(logEntry.taskId)
          };
          rows.push((

              {firstCol}

              {Utils.getTime(logEntry.startTime)}
              {Utils.getTime(logEntry.endTime)}
              {label}
              {Utils.formatTimespan(duration)}
              {Utils.formatTimespan(logEntry.timeElapsed)}
              {utilization}%

          ));
        });
      });

      return (

	Start	End	Task	Time	Work	Util

{rows}

      );
    }

  renderContents() {
    return this.props.messages.map( (message, i) => {
      return (

{message}

      );
    });
  }

}
<commit_msg>Show log with earliest entries the top within each day.<commit_after>import React, { Component } from 'react';
import Utils from '../utils';
import Task from '../task';
import colormap from 'colormap';
import { Handler, HandlerPopup } from './handler';
import classNames from 'classnames';

/* These are mostly for drawing */
const NUM_COLORS = 32;
const COLORS = colormap({
  colormap: 'rainbow-soft',   // pick a builtin colormap or add your own
  nshades: NUM_COLORS       // how many divisions
});
function hashCode(str) {
    var hash = 0;
    for (var i = 0; i < str.length; i++) {
        hash = ~~(((hash << 5) - hash) + str.charCodeAt(i));
    }
    return Math.abs(hash);
}
function getColor2(str) {
  return COLORS[hashCode(str) % NUM_COLORS];
}
function getColor(logEntry) {
  const hue = Task.getProjectColor(logEntry.project);
  return 'hsl(' + hue + ',100%,85%)';
}
function getStyle(logEntry) {
  const hue = Task.getProjectColor(logEntry.project);
}

/**
 * Show the work log
 * <Log log=[log entries] />
 */
export default class Log extends Component {

  constructor(props) {
      super(props);
      this.state = {
          edit: '',
          editStart: '',
          editEnd: ''
      };
  }

  shouldComponentUpdate(nextProps, nextState) {
    return (nextProps.log.length != this.props.log.length) ||
      (nextState.edit != this.state.edit);
  }

  getDuration(t1, t2) {
    try {
      return Math.floor((new Date(t2) - new Date(t1))/1000);
    }
    catch (e) {
      console.log(e);
      return 0;
    }
  }

  getLogEntryId(logEntry) {
    return logEntry.taskId + '.' + logEntry.startTime;
  }

  edit(logEntryId) {
    this.setState({
      edit: logEntryId
    });
  }

  render() {
    // 2017-02-24
    // 12:30 - 2:30 Documentation #21 35m (34%)
    // 2:30 - 4:00 Github Style 90m (100%)

    // group by day
    const days = [];
    const entriesByDay = {};
    let lastDay = -1;
    this.props.log.forEach( (logEntry, i) => {
      const day = Utils.getDay(logEntry.startTime);
      // create new day if necessary
      if (!entriesByDay[day]) {
        days.push(day);
        entriesByDay[day] = [];
      }
      entriesByDay[day].push(logEntry);
    });
    const rows = [];
    days.forEach((day) => {
      // append the day and its rows
      const dayEntries = entriesByDay[day];
      dayEntries.reverse();
      const dayStats = {
        numEntries: dayEntries.length,
        startTime: null,
        endTime: null,
        duration: 0,
        worked: 0
      };
      // Cumulative day stats
      dayEntries.forEach( (logEntry) => {
        if (!dayStats.startTime || dayStats.startTime > logEntry.startTime) {
          dayStats.startTime = logEntry.startTime;
        }
        if (!dayStats.endTime || dayStats.endTime < logEntry.endTime) {
          dayStats.endTime = logEntry.endTime;
        }
        dayStats.worked += logEntry.timeElapsed;
      });
      dayStats.duration = this.getDuration(dayStats.startTime, dayStats.endTime);
      rows.push((

          {day}

            {Utils.formatTimespan(dayStats.worked, true)}
             ({Utils.formatTimespan(dayStats.duration, true)})

      ));
      function chartHeight(duration) {
        return parseInt((duration*100)/dayStats.duration);
      }
      const chartRows = [];
      let lastOne = null;
      dayEntries.forEach( (logEntry, i) => {
        const start = chartHeight(this.getDuration(dayStats.startTime, logEntry.startTime));
        const height = Math.max(
          chartHeight(this.getDuration(logEntry.startTime, logEntry.endTime)),
          Math.min(2, 100-start));
        const style = {
          bottom: '' + start + '%',
          height: '' + height + '%',
          background: getColor(logEntry)
        };
        return (

        );
      });
      // The log entries
      const subrows = [];
      dayEntries.forEach( (logEntry, i) => {
        const label = logEntry.taskName || logEntry.task;
        const duration = this.getDuration(logEntry.startTime, logEntry.endTime);
        const utilization = Math.floor((logEntry.timeElapsed * 100) / duration);

        const style = {
          background: getColor(logEntry)
        };
        const logEntryId = this.getLogEntryId(logEntry);
        const editing = (logEntryId == this.state.edit);
        const edit = () => {
          console.log("Editing " + logEntryId);
          this.edit(logEntryId);
        };
        const className = classNames(
          'log-entry',
          { 'editing': editing }
        );
        subrows.push((

{chartRows[i]}

              {Utils.getTime(logEntry.startTime)} -
              {Utils.getTime(logEntry.endTime)}

            {label}

              {Utils.formatTimespan(logEntry.timeElapsed, true)}
              {Utils.formatTimespan(duration, true)}
              {utilization}%

        ));
      });

      rows.push((

          {subrows}

      ));

    });

    return (

        {rows}

    );
  }
}

/* Where is this used? */
class StatusPopup extends HandlerPopup {

    shouldComponentUpdate(nextProps, nextState) {
      return nextProps.log.length != this.props.log.length;
    }

    getDuration(t1, t2) {
      try {
        return Math.floor((new Date(t2) - new Date(t1))/1000);
      }
      catch (e) {
        console.log(e);
        return 0;
      }
    }

    render() {
      // group by day
      const days = [];
      const entriesByDay = {};
      let lastDay = -1;
      this.props.log.forEach( (logEntry, i) => {
        const day = Utils.getDay(logEntry.startTime);
        // create new day if necessary
        if (!entriesByDay[day]) {
          days.push(day);
          entriesByDay[day] = [];
        }
        entriesByDay[day].push(logEntry);
      });
      const rows = [];
      days.forEach((day) => {
        // append the day and its rows
        const dayEntries = entriesByDay[day];
        dayEntries.reverse();
        const dayStats = {
          numEntries: dayEntries.length,
          startTime: null,
          endTime: null,
          duration: 0,
          worked: 0
        };
        dayEntries.forEach( (logEntry) => {
          if (!dayStats.startTime || dayStats.startTime > logEntry.startTime) {
            dayStats.startTime = logEntry.startTime;
          }
          if (!dayStats.endTime || dayStats.endTime < logEntry.endTime) {
            dayStats.endTime = logEntry.endTime;
          }
          dayStats.worked += logEntry.timeElapsed;
        });
        dayStats.duration = this.getDuration(dayStats.startTime, dayStats.endTime);
        const colors = colormap({
          colormap: 'summer',   // pick a builtin colormap or add your own
          nshades: Math.max(dayStats.numEntries, 2)       // how many divisions
        });
        function chartHeight(duration) {
          return parseInt((duration*100)/dayStats.duration);
        }
        const chartRows = dayEntries.map( (logEntry, i) => {
          const start = chartHeight(this.getDuration(dayStats.startTime, logEntry.startTime));
          const height = Math.max(
            chartHeight(this.getDuration(logEntry.startTime, logEntry.endTime)),
            Math.min(2, 100-start));
          const style = {
            bottom: '' + start + '%',
            height: '' + height + '%',
            background: getColor(logEntry.taskId)
          };
          return (

          );
        });
        rows.push((

            {day}
            {Utils.formatTimespan(dayStats.duration)}
            {Utils.formatTimespan(dayStats.worked)}

        ));
        dayEntries.forEach( (logEntry, i) => {
          const label = logEntry.taskName || logEntry.task;
          const duration = this.getDuration(logEntry.startTime, logEntry.endTime);
          const utilization = Math.floor((logEntry.timeElapsed * 100) / duration);

          const firstCol = (i == 0) ? (

              {chartRows}

          ) : undefined;
          const style = {
            background: getColor(logEntry.taskId)
          };
          rows.push((

              {firstCol}

              {Utils.getTime(logEntry.startTime)}
              {Utils.getTime(logEntry.endTime)}
              {label}
              {Utils.formatTimespan(duration)}
              {Utils.formatTimespan(logEntry.timeElapsed)}
              {utilization}%

          ));
        });
      });

      return (

	Start	End	Task	Time	Work	Util

{rows}

      );
    }

  renderContents() {
    return this.props.messages.map( (message, i) => {
      return (

{message}

      );
    });
  }

}
<|endoftext|>


<commit_before>Application.Controllers.controller('projectSamplesCreate',
                                   ["$scope", "mcapi", "model.projects", "projectState", "$stateParams",
                                    "pubsub", "ui", "recent", projectSamplesCreate]);

function projectSamplesCreate($scope, mcapi, Projects, projectState, $stateParams, pubsub, ui, recent) {
    var stateID = $stateParams.id;

    $scope.onDrop = function(target, source) {
        if (source === "") {
            source = 0;
        }
        var sourceObject = $scope.events[source];
        // Remove the old item
        $scope.events.splice(source, 1);
        $scope.events.splice(target, 0, sourceObject);
    };

    function initializeState() {
        var state = projectState.get($scope.project.id, stateID);
        if (state) {
            $scope.doc = state;
        } else {
            $scope.doc = {
                name: '',
                notes: [],
                available: true,
                projects: [],
                properties: {'composition': {'value': [], 'unit': ''}},
                showComposition: false
            };

            $scope.doc.projects.push({'id': $scope.project.id, 'name': $scope.project.name});
            projectState.set($scope.project.id, stateID, $scope.doc);
        }

        $scope.bk = {
            selected_project: '',
            available: '',
            open: '',
            classification: '' ,
            element_name: '',
            element_value: ''
        };
    }

    $scope.create = function () {
        $scope.doc.path = $scope.doc.name;
        $scope.doc.project_id = $scope.project.id;
        mcapi('/objects/new')
            .arg('order_by=birthtime')
            .success(function () {
                Projects.getList(true).then(function (data) {
                    ui.setShowFiles($scope.project.id, true);
                    pubsub.send('update-tab-count.change');
                });
            }).post($scope.doc);
    };

    $scope.populateProjects = function () {
        $scope.doc.projects.push({'id': $scope.bk.selected_project.id, 'name': $scope.bk.selected_project.name});
    };

    $scope.cancel = function () {
        ui.setShowFiles($scope.project.id, true);
    };

    $scope.removeProjects = function (index) {
        $scope.doc.projects.splice(index, 1);
    };

    $scope.addComposition = function () {
        $scope.doc.properties.composition.value.push({'element': $scope.bk.element_name, 'value': $scope.bk.element_value});

    };
    $scope.removeComposition = function (i) {
        $scope.doc.properties.composition.value.splice(i, 1);
    };

    function init() {
        $scope.activeToolbarItem = "";
        initializeState();
        Projects.getList().then(function (projects) {
            $scope.projects = projects;
        });
        mcapi('/objects/elements')
            .success(function(data){
                $scope.elements = data;
            }).jsonp();

        $scope.events = [
            {
                name: "Heat Treatment A"
            },

            {
                name: "Heat Treatment B"
            },

            {
                name: "Cogged C"
            }
        ];
    }

    init();
}
<commit_msg>Remove projects.getList call after create. Instead append.<commit_after>Application.Controllers.controller('projectSamplesCreate',
                                   ["$scope", "mcapi", "model.projects", "projectState", "$stateParams",
                                    "pubsub", "ui", "recent", "project", projectSamplesCreate]);

function projectSamplesCreate($scope, mcapi, Projects, projectState, $stateParams, pubsub, ui, recent, project) {
    var stateID = $stateParams.id;

    $scope.onDrop = function(target, source) {
        if (source === "") {
            source = 0;
        }
        var sourceObject = $scope.events[source];
        // Remove the old item
        $scope.events.splice(source, 1);
        $scope.events.splice(target, 0, sourceObject);
    };

    function initializeState() {
        var state = projectState.get($scope.project.id, stateID);
        if (state) {
            $scope.doc = state;
        } else {
            $scope.doc = {
                name: '',
                notes: [],
                available: true,
                projects: [],
                properties: {'composition': {'value': [], 'unit': ''}},
                showComposition: false
            };

            $scope.doc.projects.push({'id': $scope.project.id, 'name': $scope.project.name});
            projectState.set($scope.project.id, stateID, $scope.doc);
        }

        $scope.bk = {
            selected_project: '',
            available: '',
            open: '',
            classification: '' ,
            element_name: '',
            element_value: ''
        };
    }

    $scope.create = function () {
        $scope.doc.path = $scope.doc.name;
        $scope.doc.project_id = $scope.project.id;
        mcapi('/objects/new')
            .success(function (sample) {
                project.samples.push(sample);
            }).post($scope.doc);
    };

    $scope.populateProjects = function () {
        $scope.doc.projects.push({'id': $scope.bk.selected_project.id, 'name': $scope.bk.selected_project.name});
    };

    $scope.cancel = function () {
        ui.setShowFiles($scope.project.id, true);
    };

    $scope.removeProjects = function (index) {
        $scope.doc.projects.splice(index, 1);
    };

    $scope.addComposition = function () {
        $scope.doc.properties.composition.value.push({'element': $scope.bk.element_name, 'value': $scope.bk.element_value});

    };
    $scope.removeComposition = function (i) {
        $scope.doc.properties.composition.value.splice(i, 1);
    };

    function init() {
        $scope.activeToolbarItem = "";
        initializeState();
        Projects.getList().then(function (projects) {
            $scope.projects = projects;
        });
        mcapi('/objects/elements')
            .success(function(data){
                $scope.elements = data;
            }).jsonp();

        // $scope.events = [
        //     {
        //         name: "Heat Treatment A"
        //     },

        //     {
        //         name: "Heat Treatment B"
        //     },

        //     {
        //         name: "Cogged C"
        //     }
        // ];
    }

    init();
}
<|endoftext|>