<commit_before>;(function ($, window, document, undefined) {
  'use strict';

  Foundation.libs.tooltip = {
    name : 'tooltip',

    version : '5.0.0',

    settings : {
      additional_inheritable_classes : [],
      tooltip_class : '.tooltip',
      append_to: 'body',
      touch_close_text: 'Tap To Close',
      disable_for_touch: false,
      tip_template : function (selector, content) {
        return '' + content + '';
      }
    },

    cache : {},

    init : function (scope, method, options) {
      this.bindings(method, options);
    },

    events : function () {
      var self = this;

      $(this.scope)
        .off('.tooltip')
        .on('mouseenter.fndtn.tooltip mouseleave.fndtn.tooltip touchstart.fndtn.tooltip',
          '[data-tooltip]', function (e) {
          var $this = $(this),
              settings = $.extend({}, self.settings, self.data_options($this)),
              is_touch = false;

          if ($this.hasClass('open')) {
            if(Modernizr.touch && /touchstart/i.test(e.type)) { e.preventDefault(); }
            self.hide($this);
          }
          else
          {
            if(settings.disable_for_touch && Modernizr.touch && /touchstart/i.test(e.type))
            {
              return;
            }
            else if(!settings.disable_for_touch && Modernizr.touch && /touchstart/i.test(e.type))
            {
              e.preventDefault();
              $('.tooltip.open').hide();
              is_touch = true;
            }
            self.showOrCreateTip($this, is_touch);
          }
        });
    },

    showOrCreateTip : function ($target, is_touch) {
      var $tip = this.getTip($target);

      if ($tip && $tip.length > 0) {
        return this.show($target);
      }

      return this.create($target, is_touch);
    },

    getTip : function ($target) {
      var selector = this.selector($target),
          tip = null;

      if (selector) {
        var settings = $.extend({}, this.settings, this.data_options($('[data-tooltip="' + selector + '"]'))),
        tip = $('[data-selector="' + selector + '"]' + settings.tooltip_class);
      }

      return (typeof tip === 'object') ? tip : false;
    },

    selector : function ($target) {
      var id = $target.attr('id'),
          dataSelector = $target.attr('data-tooltip') || $target.attr('data-selector');

      if ((id && id.length < 1 || !id) && typeof dataSelector != 'string') {
        dataSelector = 'tooltip' + Math.random().toString(36).substring(7);
        $target.attr('data-selector', dataSelector);
      }

      return (id && id.length > 0) ? id : dataSelector;
    },

    create : function ($target, is_touch) {
      var self = this,
          settings = $.extend({}, this.settings, this.data_options($target)),
          tip_template = this.settings.tip_template;

      if(typeof settings.tip_template === 'string' && window.hasOwnProperty(settings.tip_template))
      {
        tip_template = window[settings.tip_template];
      }

      var $tip = $(tip_template(this.selector($target), $('

').html($target.attr('title')).html())),
          classes = this.inheritable_classes($target);

      $tip.addClass(classes).appendTo(settings.append_to);
      if (is_touch) {
        $tip.append(''+settings.touch_close_text+'');
        $tip.on('touchstart.fndtn.tooltip', function(e) {
          self.hide($target);
        });
      }
      $target.removeAttr('title').attr('title','');
      this.show($target);
    },

    reposition : function (target, tip, classes) {
      var width, nub, nubHeight, nubWidth, column, objPos;

      tip.css('visibility', 'hidden').show();

      width = target.data('width');
      nub = tip.children('.nub');
      nubHeight = nub.outerHeight();
      nubWidth = nub.outerHeight();

      tip.css({'width' : (width) ? width : 'auto'});

      objPos = function (obj, top, right, bottom, left, width) {
        return obj.css({
          'top' : (top) ? top : 'auto',
          'bottom' : (bottom) ? bottom : 'auto',
          'left' : (left) ? left : 'auto',
          'right' : (right) ? right : 'auto',
        }).end();
      };

      objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', target.offset().left);

      if (this.small()) {
        objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', 12.5, $(this.scope).width());
        tip.addClass('tip-override');
        objPos(nub, -nubHeight, 'auto', 'auto', target.offset().left);
      } else {
        var left = target.offset().left;
        if (Foundation.rtl) {
          left = target.offset().left + target.offset().width - tip.outerWidth();
        }
        objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', left);
        tip.removeClass('tip-override');
        if (classes && classes.indexOf('tip-top') > -1) {
          objPos(tip, (target.offset().top - tip.outerHeight()), 'auto', 'auto', left)
            .removeClass('tip-override');
        } else if (classes && classes.indexOf('tip-left') > -1) {
          objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left - tip.outerWidth() - nubHeight))
            .removeClass('tip-override');
        } else if (classes && classes.indexOf('tip-right') > -1) {
          objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left + target.outerWidth() + nubHeight))
            .removeClass('tip-override');
        }
      }

      tip.css('visibility', 'visible').hide();
    },

    small : function () {
      return matchMedia(Foundation.media_queries.small).matches;
    },

    inheritable_classes : function ($target) {
      var settings = $.extend({}, this.settings, this.data_options($target)),
          inheritables = ['tip-top', 'tip-left', 'tip-bottom', 'tip-right', 'noradius'].concat(settings.additional_inheritable_classes),
          classes = $target.attr('class'),
          filtered = classes ? $.map(classes.split(' '), function (el, i) {
            if ($.inArray(el, inheritables) !== -1) {
              return el;
            }
          }).join(' ') : '';

      return $.trim(filtered);
    },

    show : function ($target) {
      var $tip = this.getTip($target);

      this.reposition($target, $tip, $target.attr('class'));
      $target.addClass('open');
      $tip.fadeIn(150);
    },

    hide : function ($target) {
      var $tip = this.getTip($target);

      $target.removeClass('open');
      $tip.fadeOut(150);
    },

    // deprecate reload
    reload : function () {
      var $self = $(this);

      return ($self.data('fndtn-tooltips')) ? $self.foundationTooltips('destroy').foundationTooltips('init') : $self.foundationTooltips('init');
    },

    off : function () {
      var self = this;
      $(this.scope).off('.fndtn.tooltip');
      $('[data-tooltip]').each(function (i) {
        $(this).attr('title', $(this).text());
        self.getTip($(this)).remove();
      });
    },

    reflow : function () {}
  };
}(jQuery, this, this.document));
<commit_msg>Clean up the code a bit. Should allow you to switch to a mouse based input type even if you opened it using touchstart. Clicking on the data-tooltip element via touchstart will now close it so you don't have to click on the tooltip itself<commit_after>;(function ($, window, document, undefined) {
  'use strict';

  Foundation.libs.tooltip = {
    name : 'tooltip',

    version : '5.0.0',

    settings : {
      additional_inheritable_classes : [],
      tooltip_class : '.tooltip',
      append_to: 'body',
      touch_close_text: 'Tap To Close',
      disable_for_touch: false,
      tip_template : function (selector, content) {
        return '' + content + '';
      }
    },

    cache : {},

    init : function (scope, method, options) {
      this.bindings(method, options);
    },

    events : function () {
      var self = this;

      $(this.scope)
        .off('.tooltip')
        .on('mouseenter.fndtn.tooltip touchstart.fndtn.tooltip',
            '[data-tooltip]:not(".open")', function (e) {
          var $this = $(this),
              settings = $.extend({}, self.settings, self.data_options($this)),
              is_touch = /touchstart/i.test(e.type);

            if(settings.disable_for_touch && is_touch) {
              return;
            }
            else if(!settings.disable_for_touch && self.is_touch) {
              e.preventDefault();
            }

            // Close all tooltips so they don't overlap
            $('.open[data-tooltip]').each(function() {
                self.hide($(this));
            });

            if(is_touch) {
              $this.data('tooltip-open-event-type', 'touch');
            } else {
              $this.data('tooltip-open-event-type', 'mouse');
            }

            self.showOrCreateTip($this);
        })
        .on('mouseleave.fndtn.tooltip touchstart.fndtn.tooltip', '.open[data-tooltip]', function (e) {
          if($(this).data('tooltip-open-event-type') == 'touch' && e.type == 'mouseleave') {
            return;
          }
          self.hide($(this));
        });
    },

    showOrCreateTip : function ($target) {
      var $tip = this.getTip($target);

      if ($tip && $tip.length > 0) {
        return this.show($target);
      }

      return this.create($target);
    },

    getTip : function ($target) {
      var selector = this.selector($target),
          tip = null;

      if (selector) {
        var settings = $.extend({}, this.settings, this.data_options($('[data-tooltip="' + selector + '"]'))),
        tip = $('[data-selector="' + selector + '"]' + settings.tooltip_class);
      }

      return (typeof tip === 'object') ? tip : false;
    },

    selector : function ($target) {
      var id = $target.attr('id'),
          dataSelector = $target.attr('data-tooltip') || $target.attr('data-selector');

      if ((id && id.length < 1 || !id) && typeof dataSelector != 'string') {
        dataSelector = 'tooltip' + Math.random().toString(36).substring(7);
        $target.attr('data-selector', dataSelector);
      }

      return (id && id.length > 0) ? id : dataSelector;
    },

    create : function ($target) {
      var self = this,
          settings = $.extend({}, this.settings, this.data_options($target)),
          tip_template = this.settings.tip_template;

      if(typeof settings.tip_template === 'string' && window.hasOwnProperty(settings.tip_template))
      {
        tip_template = window[settings.tip_template];
      }

      var $tip = $(tip_template(this.selector($target), $('

').html($target.attr('title')).html())),
          classes = this.inheritable_classes($target);

      $tip.addClass(classes).appendTo(settings.append_to);
      if ($target.data('tooltip-open-event-type') == 'touch') {
        $tip.append(''+settings.touch_close_text+'');
        $tip.on('click.fndtn.tooltip touchstart.fndtn.tooltip', function(e) {
          self.hide($target);
        });
      }
      $target.removeAttr('title').attr('title','');
      this.show($target);
    },

    reposition : function (target, tip, classes) {
      var width, nub, nubHeight, nubWidth, column, objPos;

      tip.css('visibility', 'hidden').show();

      width = target.data('width');
      nub = tip.children('.nub');
      nubHeight = nub.outerHeight();
      nubWidth = nub.outerHeight();

      tip.css({'width' : (width) ? width : 'auto'});

      objPos = function (obj, top, right, bottom, left, width) {
        return obj.css({
          'top' : (top) ? top : 'auto',
          'bottom' : (bottom) ? bottom : 'auto',
          'left' : (left) ? left : 'auto',
          'right' : (right) ? right : 'auto',
        }).end();
      };

      objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', target.offset().left);

      if (this.small()) {
        objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', 12.5, $(this.scope).width());
        tip.addClass('tip-override');
        objPos(nub, -nubHeight, 'auto', 'auto', target.offset().left);
      } else {
        var left = target.offset().left;
        if (Foundation.rtl) {
          left = target.offset().left + target.offset().width - tip.outerWidth();
        }
        objPos(tip, (target.offset().top + target.outerHeight() + 10), 'auto', 'auto', left);
        tip.removeClass('tip-override');
        if (classes && classes.indexOf('tip-top') > -1) {
          objPos(tip, (target.offset().top - tip.outerHeight()), 'auto', 'auto', left)
            .removeClass('tip-override');
        } else if (classes && classes.indexOf('tip-left') > -1) {
          objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left - tip.outerWidth() - nubHeight))
            .removeClass('tip-override');
        } else if (classes && classes.indexOf('tip-right') > -1) {
          objPos(tip, (target.offset().top + (target.outerHeight() / 2) - (tip.outerHeight() / 2)), 'auto', 'auto', (target.offset().left + target.outerWidth() + nubHeight))
            .removeClass('tip-override');
        }
      }

      tip.css('visibility', 'visible').hide();
    },

    small : function () {
      return matchMedia(Foundation.media_queries.small).matches;
    },

    inheritable_classes : function ($target) {
      var settings = $.extend({}, this.settings, this.data_options($target)),
          inheritables = ['tip-top', 'tip-left', 'tip-bottom', 'tip-right', 'noradius'].concat(settings.additional_inheritable_classes),
          classes = $target.attr('class'),
          filtered = classes ? $.map(classes.split(' '), function (el, i) {
            if ($.inArray(el, inheritables) !== -1) {
              return el;
            }
          }).join(' ') : '';

      return $.trim(filtered);
    },

    show : function ($target) {
      var $tip = this.getTip($target);

      this.reposition($target, $tip, $target.attr('class'));
      $target.addClass('open');
      $tip.fadeIn(150);
    },

    hide : function ($target) {
      var $tip = this.getTip($target);

      $target.removeClass('open');
      $tip.fadeOut(150);
    },

    // deprecate reload
    reload : function () {
      var $self = $(this);

      return ($self.data('fndtn-tooltips')) ? $self.foundationTooltips('destroy').foundationTooltips('init') : $self.foundationTooltips('init');
    },

    off : function () {
      var self = this;
      $(this.scope).off('.fndtn.tooltip');
      $('[data-tooltip]').each(function (i) {
        $(this).attr('title', $(this).text());
        self.getTip($(this)).remove();
      });
    },

    reflow : function () {}
  };
}(jQuery, this, this.document));
<|endoftext|>


<commit_before>/**
 * jquery.clever-infinite-scroll.js
 * Working with jQuery 2.1.4
 *
 * Twitter: @watarutwt
 * GitHub: @wataruoguchi
 */
/* global define, require, history, window, document, location  */
(function(root, factory) {
  "use strict";
  if (typeof define === "function" && define.amd) {
    define(["jquery"], factory);
  } else if (typeof exports === "object") {
    factory(require("jquery"));
  } else {
    factory(root.jQuery);
  }
})(this, function($) {
  "use strict";
  /**
   * Elements it reffers. Each page must has those selectors.
   * The structure must be same as article1.html
   * #contentsWrapper, .content, #next
   */
  $.fn.cleverInfiniteScroll = function(options) {
    /**
     * Settings
     */
    var windowHeight = (typeof window.outerHeight !== "undefined") ? Math.max(window.outerHeight, $(window).height()) : $(window).height(),
      defaults = {
        contentsWrapperSelector: "#contentsWrapper",
        contentSelector: ".content",
        nextSelector: "#next",
        loadImage: "",
        offset: windowHeight,
      },
      settings = $.extend(defaults, options);

    /**
     * Private methods
     */
    var generateHiddenSpans = function(_title, _path) {
        return "" + _title + "" + _path + "";
      },
      setTitleAndHistory = function(_title, _path) {
        // Set history
        history.pushState(null, _title, _path);
        // Set title
        $("title").html(_title);
      },
      changeTitleAndURL = function(_value) {
        // value is an element of a content user is seeing
        // Get title and path of the article page from hidden span elements
        var title = $(_value).children(".hidden-title:first").text(),
          path = $(_value).children(".hidden-url:first").text();
        if ($("title").text() !== title) {
          // If it has changed
          $(settings.contentSelector).removeClass("active");
          $(_value).addClass("active");
          setTitleAndHistory(title, path);
        }
      };

    /**
     * Initialize
     */
    // Get current page's title and URL.
    var title = $("title").text(),
      path = $(location).attr("href"),
      documentHeight = $(document).height(),
      threshold = settings.offset,
      $contents = $(settings.contentSelector);
    // Set hidden span elements and history
    $(settings.contentSelector + ":last").append(generateHiddenSpans(title, path));
    $(settings.contentSelector).addClass("active");
    setTitleAndHistory(title, path);

    /**
     * scroll
     */
    var lastScroll = 0,
      currentScroll;
    $(window).scroll(function() {
      // Detect where you are
      window.clearTimeout($.data("this", "scrollTimer"));
      $.data(this, "scrollTimer", window.setTimeout(function() {
        // Get current scroll position
        currentScroll = $(window).scrollTop();

        // Detect whether it's scrolling up or down by comparing current scroll location and last scroll location
        if (currentScroll > lastScroll) {
          // If it's scrolling down
          $contents.each(function(key, value) {
            if ($(value).offset().top + $(value).height() > currentScroll) {
              // Change title and URL
              changeTitleAndURL(value);
              // Quit each loop
              return false;
            }
          });
        } else if (currentScroll < lastScroll) {
          // If it's scrolling up
          $contents.each(function(key, value) {
            if ($(value).offset().top + $(value).height() - windowHeight / 2 > currentScroll) {
              // Change title and URL
              changeTitleAndURL(value);
              // Quit each loop
              return false;
            }
          });
        } else {
          // When currentScroll == lastScroll, it does not do anything because it has not been scrolled.
        }
        // Renew last scroll position
        lastScroll = currentScroll;
      }, 200));

      if ($(window).scrollTop() + windowHeight + threshold >= documentHeight) {
        // If scrolling close to the bottom

        // Getting URL from settings.nextSelector
        var $url = [$(settings.nextSelector).attr("href")];
        $(settings.nextSelector).remove();
        if ($url[0] !== undefined) {
          // If the page has link, call ajax
          if (settings.loadImage !== "") {
            $(settings.contentsWrapperSelector).append("");
          }
          $.ajax({
            url: $url[0],
            dataType: "html",
            success: function(res) {
              // Get title and URL
              title = $(res).filter("title").text();
              path = $url[0];
              // Set hidden span elements and history
              $(settings.contentsWrapperSelector).append($(res).find(settings.contentSelector).append(generateHiddenSpans(title, path)));
              if ($(res).find(settings.contentSelector).find(settings.nextSelector).length === 0) {
                //If there is no nextSelector in the contentSelector, get next Slecter from response and append it.
                $(settings.contentsWrapperSelector).append($(res).find(settings.nextSelector));
              }
              documentHeight = $(document).height();
              $contents = $(settings.contentSelector);
              $("#cis-load-img").remove();
            }
          });
        }
      }
    }); //scroll

    return (this);
  }; //$.fn.cleverInfiniteScroll
});
<commit_msg>Replace pushState with replaceState - so it does not keep the history wataruoguchi/clever-infinite-scroll/issues/6<commit_after>/**
 * jquery.clever-infinite-scroll.js
 * Working with jQuery 2.1.4
 *
 * Twitter: @watarutwt
 * GitHub: @wataruoguchi
 */
/* global define, require, history, window, document, location  */
(function(root, factory) {
  "use strict";
  if (typeof define === "function" && define.amd) {
    define(["jquery"], factory);
  } else if (typeof exports === "object") {
    factory(require("jquery"));
  } else {
    factory(root.jQuery);
  }
})(this, function($) {
  "use strict";
  /**
   * Elements it reffers. Each page must has those selectors.
   * The structure must be same as article1.html
   * #contentsWrapper, .content, #next
   */
  $.fn.cleverInfiniteScroll = function(options) {
    /**
     * Settings
     */
    var windowHeight = (typeof window.outerHeight !== "undefined") ? Math.max(window.outerHeight, $(window).height()) : $(window).height(),
      defaults = {
        contentsWrapperSelector: "#contentsWrapper",
        contentSelector: ".content",
        nextSelector: "#next",
        loadImage: "",
        offset: windowHeight,
      },
      settings = $.extend(defaults, options);

    /**
     * Private methods
     */
    var generateHiddenSpans = function(_title, _path) {
        return "" + _title + "" + _path + "";
      },
      setTitleAndHistory = function(_title, _path) {
        // Set history
        history.replaceState(null, _title, _path);
        // Set title
        $("title").html(_title);
      },
      changeTitleAndURL = function(_value) {
        // value is an element of a content user is seeing
        // Get title and path of the article page from hidden span elements
        var title = $(_value).children(".hidden-title:first").text(),
          path = $(_value).children(".hidden-url:first").text();
        if ($("title").text() !== title) {
          // If it has changed
          $(settings.contentSelector).removeClass("active");
          $(_value).addClass("active");
          setTitleAndHistory(title, path);
        }
      };

    /**
     * Initialize
     */
    // Get current page's title and URL.
    var title = $("title").text(),
      path = $(location).attr("href"),
      documentHeight = $(document).height(),
      threshold = settings.offset,
      $contents = $(settings.contentSelector);
    // Set hidden span elements and history
    $(settings.contentSelector + ":last").append(generateHiddenSpans(title, path));
    $(settings.contentSelector).addClass("active");
    setTitleAndHistory(title, path);

    /**
     * scroll
     */
    var lastScroll = 0,
      currentScroll;
    $(window).scroll(function() {
      // Detect where you are
      window.clearTimeout($.data("this", "scrollTimer"));
      $.data(this, "scrollTimer", window.setTimeout(function() {
        // Get current scroll position
        currentScroll = $(window).scrollTop();

        // Detect whether it's scrolling up or down by comparing current scroll location and last scroll location
        if (currentScroll > lastScroll) {
          // If it's scrolling down
          $contents.each(function(key, value) {
            if ($(value).offset().top + $(value).height() > currentScroll) {
              // Change title and URL
              changeTitleAndURL(value);
              // Quit each loop
              return false;
            }
          });
        } else if (currentScroll < lastScroll) {
          // If it's scrolling up
          $contents.each(function(key, value) {
            if ($(value).offset().top + $(value).height() - windowHeight / 2 > currentScroll) {
              // Change title and URL
              changeTitleAndURL(value);
              // Quit each loop
              return false;
            }
          });
        } else {
          // When currentScroll == lastScroll, it does not do anything because it has not been scrolled.
        }
        // Renew last scroll position
        lastScroll = currentScroll;
      }, 200));

      if ($(window).scrollTop() + windowHeight + threshold >= documentHeight) {
        // If scrolling close to the bottom

        // Getting URL from settings.nextSelector
        var $url = [$(settings.nextSelector).attr("href")];
        $(settings.nextSelector).remove();
        if ($url[0] !== undefined) {
          // If the page has link, call ajax
          if (settings.loadImage !== "") {
            $(settings.contentsWrapperSelector).append("");
          }
          $.ajax({
            url: $url[0],
            dataType: "html",
            success: function(res) {
              // Get title and URL
              title = $(res).filter("title").text();
              path = $url[0];
              // Set hidden span elements and history
              $(settings.contentsWrapperSelector).append($(res).find(settings.contentSelector).append(generateHiddenSpans(title, path)));
              if ($(res).find(settings.contentSelector).find(settings.nextSelector).length === 0) {
                //If there is no nextSelector in the contentSelector, get next Slecter from response and append it.
                $(settings.contentsWrapperSelector).append($(res).find(settings.nextSelector));
              }
              documentHeight = $(document).height();
              $contents = $(settings.contentSelector);
              $("#cis-load-img").remove();
            }
          });
        }
      }
    }); //scroll

    return (this);
  }; //$.fn.cleverInfiniteScroll
});
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import setUpGames from '../actions/setup-games'
import setGameId from '../actions/set-current-game'
import Paper from 'material-ui/Paper'
import RaisedButton from 'material-ui/RaisedButton'
import FlatButton from 'material-ui/FlatButton'
import saveGame from '../actions/update-game'
import Board from '../components/Board'

import './Game.sass'

const PLAYER_COLORS = ['#0f0', '#00f']

class Game extends Component {
  componentWillMount() {
    this.props.setGameId(this.props.routeParams.gameId)
    this.props.setUpGames()
  }

  isPlayer() {
    const { game, currentUser } = this.props
    return game.players.filter((player) =>
      player.userId === currentUser._id).length > 0
  }

  canJoin() {
    if (this.isPlayer()) { return false }
    const { game } = this.props
    return game.players.length < 3
  }

  joinGame() {
    const { game, saveGame, currentUser } = this.props
    saveGame(game, { players: game.players.concat({
      userId: currentUser._id,
      name: currentUser.name,
      playerTurn: game.players.length,
      color: PLAYER_COLORS[game.players.length],
    })})
  }

  currentPlayer(){
    const { game, currentUser } = this.props
    const { players } = this.props.game
    // check if there actually are there are players...
    if( !!!players ) { return }
    // filter out the current player and return it
    return players.filter((player) => player.userId === currentUser._id)[0]
  }

  otherPlayer(){
    const { game, currentUser } = this.props
    const { players } = this.props.game
    // check if there actually are there are players...
    if( !!!players ) { return }
    // check if there are two players
    if( players.length < 2 ) { return }
    // filter out the other player and return it
    return players.filter((player) => player.userId != currentUser._id)[0]
  }

  notYouTurn(){
    const currentPlayer = this.currentPlayer()
    const otherPlayer = this.otherPlayer()
    const { turn } = this.props.game
    // check if there is another player
    if ( !otherPlayer ) { return false }
    // if turn is not playerTurn return true
    if (turn != currentPlayer.playerTurn) { return true }
  }

  gameNotOver(){
    const { players } = this.props.game
    const playerOneScore = players[0].boxes.length
    const playerTwoScore = players[1].boxes.length
    if (playerOneScore + playerTwoScore < 9){return true}
    return false
  }

  waitForOtherPlayer(){
    const otherPlayer = this.otherPlayer()
    // check if there is another player
    if ( !otherPlayer ) { return true }
  }

  render() {
    const { game } = this.props
    const { winner } = this.props.game
    const otherPlayer = this.otherPlayer()
    if (!!!game._id) { return null }

    if (this.canJoin()) {
      return (
        <Paper zDepth={3} className="join-game">

Join this Game?

Join { game.players.map((player) => player.name).join(' and ') } in this game.

          <RaisedButton label="Join" primary={true} onClick={ this.joinGame.bind(this) } />
          <Link to="/"><FlatButton label="Back to the Lobby" /></Link>
        </Paper>
      )
    } // end if() return

    return(

        {/*
Is player: { this.isPlayer() ? 'Yes' : 'No' }

Can join: { this.canJoin() ? 'Yes' : 'No' }
 */}

{ game.players.map((player) =>
{player.name}: SCORE = {player.boxes.length}
) }

 Winner: { winner }

        <Board />

        { (( this.notYouTurn.bind(this)() ) && this.gameNotOver.bind(this)() ) ?

Be patient, it's not your turn! { otherPlayer.name } is still thinking...

Or getting coffee...

          : null }

        { ( this.waitForOtherPlayer.bind(this)() )  ?

Nobody else here to play with... Please wait, or invite a friend!

          : null }

 // end div className="game"
    ) // end return
  } // end render
} // end component

Game.propTypes = {
  game: PropTypes.object.isRequired,
  currentUser: PropTypes.object.isRequired,
}

const mapStateToProps = (state) => {
  return {
    game: state.games.reduce((currentGame, nextGame) => {
      return nextGame._id === state.currentGame ? nextGame : currentGame
    }, {}),
    currentUser: state.currentUser,
  }
}

export default connect(mapStateToProps, { setUpGames, setGameId, saveGame })(Game)
<commit_msg>Fix missing key that caused errors in the console<commit_after>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import setUpGames from '../actions/setup-games'
import setGameId from '../actions/set-current-game'
import Paper from 'material-ui/Paper'
import RaisedButton from 'material-ui/RaisedButton'
import FlatButton from 'material-ui/FlatButton'
import saveGame from '../actions/update-game'
import Board from '../components/Board'

import './Game.sass'

const PLAYER_COLORS = ['#0f0', '#00f']

class Game extends Component {
  componentWillMount() {
    this.props.setGameId(this.props.routeParams.gameId)
    this.props.setUpGames()
  }

  isPlayer() {
    const { game, currentUser } = this.props
    return game.players.filter((player) =>
      player.userId === currentUser._id).length > 0
  }

  canJoin() {
    if (this.isPlayer()) { return false }
    const { game } = this.props
    return game.players.length < 3
  }

  joinGame() {
    const { game, saveGame, currentUser } = this.props
    saveGame(game, { players: game.players.concat({
      userId: currentUser._id,
      name: currentUser.name,
      playerTurn: game.players.length,
      color: PLAYER_COLORS[game.players.length],
    })})
  }

  currentPlayer(){
    const { game, currentUser } = this.props
    const { players } = this.props.game
    // check if there actually are there are players...
    if( !!!players ) { return }
    // filter out the current player and return it
    return players.filter((player) => player.userId === currentUser._id)[0]
  }

  otherPlayer(){
    const { game, currentUser } = this.props
    const { players } = this.props.game
    // check if there actually are there are players...
    if( !!!players ) { return }
    // check if there are two players
    if( players.length < 2 ) { return }
    // filter out the other player and return it
    return players.filter((player) => player.userId != currentUser._id)[0]
  }

  notYouTurn(){
    const currentPlayer = this.currentPlayer()
    const otherPlayer = this.otherPlayer()
    const { turn } = this.props.game
    // check if there is another player
    if ( !otherPlayer ) { return false }
    // if turn is not playerTurn return true
    if (turn != currentPlayer.playerTurn) { return true }
  }

  gameNotOver(){
    const { players } = this.props.game
    const playerOneScore = players[0].boxes.length
    const playerTwoScore = players[1].boxes.length
    if (playerOneScore + playerTwoScore < 9){return true}
    return false
  }

  waitForOtherPlayer(){
    const otherPlayer = this.otherPlayer()
    // check if there is another player
    if ( !otherPlayer ) { return true }
  }

  render() {
    const { game } = this.props
    const { winner } = this.props.game
    const otherPlayer = this.otherPlayer()
    if (!!!game._id) { return null }

    if (this.canJoin()) {
      return (
        <Paper zDepth={3} className="join-game">

Join this Game?

Join { game.players.map((player) => player.name).join(' and ') } in this game.

          <RaisedButton label="Join" primary={true} onClick={ this.joinGame.bind(this) } />
          <Link to="/"><FlatButton label="Back to the Lobby" /></Link>
        </Paper>
      )
    } // end if() return

    return(

        {/*
Is player: { this.isPlayer() ? 'Yes' : 'No' }

Can join: { this.canJoin() ? 'Yes' : 'No' }
 */}

{ game.players.map((player) =>
{player.name}: SCORE = {player.boxes.length}
) }

 Winner: { winner }

        <Board />

        { (( this.notYouTurn.bind(this)() ) && this.gameNotOver.bind(this)() ) ?

Be patient, it's not your turn! { otherPlayer.name } is still thinking...

Or getting coffee...

          : null }

        { ( this.waitForOtherPlayer.bind(this)() )  ?

Nobody else here to play with... Please wait, or invite a friend!

          : null }

 // end div className="game"
    ) // end return
  } // end render
} // end component

Game.propTypes = {
  game: PropTypes.object.isRequired,
  currentUser: PropTypes.object.isRequired,
}

const mapStateToProps = (state) => {
  return {
    game: state.games.reduce((currentGame, nextGame) => {
      return nextGame._id === state.currentGame ? nextGame : currentGame
    }, {}),
    currentUser: state.currentUser,
  }
}

export default connect(mapStateToProps, { setUpGames, setGameId, saveGame })(Game)
<|endoftext|>


<commit_before>function initLoadedPage_meslek_tetkik_islemleri() {
    loadCheckBoxList('lstTetkikler', 'idTetkik', 'tetkik', 'tetkikler');
        firebase.database().ref('Meslektetkikler').once('value').then(function (snapshot) {
            var rows = [];
            snapshot.forEach(function (element) {
                var cleanelement = JSON.parse(JSON.stringify(element));
                cleanelement['id'] = rows.length + 1;
                rows.push(cleanelement);
            });
        });
        $("#drpMeslek").change(function () {
            var meslekId=$("#drpMeslek").val();
            firebase.database().ref('Meslektetkikler').once('value').startAt(meslekId).endAt(meslekId).then(function (snapshot) {
                if(snapshot==null){
                    return;
                }
                $("#chkitem"+snapshot.val().idTetkik).setAttribute("checked", "checked");
                // $("#drpUygulamaTuru select").val(snapshot.val().uygulamaTuru);
                // $("#drpUygulamaTuru select[value='"+snapshot.val().uygulamaTuru +"']").attr("selected",true);
                //  $("#drpMeslek").val(snapsh  ot.val().uygulamaTuru ).find("option[value=" + snapshot.val().uygulamaTuru +"]").attr('selected', true);
                $('#myModal').modal('show');
            });
        });
        LoadDrop('drpMeslek','idMeslek','meslek','meslekler','');
        setHeader("Mesleğe Göre Tetkik Belirleme İşlemleri");
    }

function setEditTetkikMeslek(id) {

}

function kaydetMeslekTetkikBilgisi() {
    var d = new Date();
    var n = d.getTime()

    var meslek = $("#drpMeslek").val();
    var idMeslekTetkik = meslek.replace(/[^\x00-\x7F]/g, "") + n;

    $('#mt_TetkikListe input:checked').each(function() {
    var veri = {
        "idMeslekTetkik": idMeslekTetkik,
        "tetkik": this.value,
        "meslek":meslek,
        "kayitEden": firebase.auth().currentUser.providerData[0]["email"]
    }

    kaydetVeritabani("Meslektetkikler", idMeslekTetkik, veri);
});
    // clearAllFieldsTetkik()

}

function clearAllFieldsTetkik() {
    $("#hdnId").val('');
    $("#txtTetkik").val("");
    $("#txtFiyat").val('');
    $("#drpUygulamaTuru select").val("Seçiniz");
    $("#drpUygulamaTuru").val("Seçiniz").find("option[value=0]").attr('selected', true);
}<commit_msg>sdfsf<commit_after>function initLoadedPage_meslek_tetkik_islemleri() {
    loadCheckBoxList('lstTetkikler', 'idTetkik', 'tetkik', 'tetkikler');
        firebase.database().ref('Meslektetkikler').once('value').then(function (snapshot) {
            var rows = [];
            snapshot.forEach(function (element) {
                var cleanelement = JSON.parse(JSON.stringify(element));
                cleanelement['id'] = rows.length + 1;
                rows.push(cleanelement);
            });
        });
        $("#drpMeslek").change(function () {
            var meslekId=$("#drpMeslek").val();
            firebase.database().ref.equalTo('Meslektetkikler').once('value').then(function (snapshot) {
                if(snapshot==null){
                    return;
                }
                $("#chkitem"+snapshot.val().idTetkik).setAttribute("checked", "checked");
                // $("#drpUygulamaTuru select").val(snapshot.val().uygulamaTuru);
                // $("#drpUygulamaTuru select[value='"+snapshot.val().uygulamaTuru +"']").attr("selected",true);
                //  $("#drpMeslek").val(snapsh  ot.val().uygulamaTuru ).find("option[value=" + snapshot.val().uygulamaTuru +"]").attr('selected', true);
                $('#myModal').modal('show');
            });
        });
        LoadDrop('drpMeslek','idMeslek','meslek','meslekler','');
        setHeader("Mesleğe Göre Tetkik Belirleme İşlemleri");
    }

function setEditTetkikMeslek(id) {

}

function kaydetMeslekTetkikBilgisi() {
    var d = new Date();
    var n = d.getTime()

    var meslek = $("#drpMeslek").val();
    var idMeslekTetkik = meslek.replace(/[^\x00-\x7F]/g, "") + n;

    $('#mt_TetkikListe input:checked').each(function() {
    var veri = {
        "idMeslekTetkik": idMeslekTetkik,
        "tetkik": this.value,
        "meslek":meslek,
        "kayitEden": firebase.auth().currentUser.providerData[0]["email"]
    }

    kaydetVeritabani("Meslektetkikler", idMeslekTetkik, veri);
});
    // clearAllFieldsTetkik()

}

function clearAllFieldsTetkik() {
    $("#hdnId").val('');
    $("#txtTetkik").val("");
    $("#txtFiyat").val('');
    $("#drpUygulamaTuru select").val("Seçiniz");
    $("#drpUygulamaTuru").val("Seçiniz").find("option[value=0]").attr('selected', true);
}<|endoftext|>


<commit_before>/**
 *  Copyright (C) 2017 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

(function () {
	"use strict";

	angular.module("3drepo")
		.service("ViewerService", ViewerService);

	ViewerService.$inject = [
		"ClientConfigService", "$q", "APIService", "DialogService",
		"EventService"
	];

	function ViewerService(
		ClientConfigService, $q, APIService, DialogService, EventService
	) {

		var viewer;
		var currentModel = {
			model : null,
			promise : null
		};

		var initialised = $q.defer();

		var service = {
			pin : {
				pinDropMode : false
			},
			initViewer : initViewer,
			getViewer : getViewer,
			loadViewerModel : loadViewerModel,
			currentModel : currentModel,
			initialised : initialised,
			reset : reset,
			fetchModelProperties : fetchModelProperties,
			activateMeasure: activateMeasure,
			disableMeasure: disableMeasure,
			getScreenshot: getScreenshot,
			goToExtent: goToExtent,
			setNavMode: setNavMode,
			getModelInfo: getModelInfo,
			setMultiSelectMode: setMultiSelectMode,
			switchObjectVisibility: switchObjectVisibility,
			handleUnityError: handleUnityError,
			handleEvent: handleEvent,
			highlightObjects: highlightObjects,
			getObjectsStatus: getObjectsStatus,
			clearClippingPlanes: clearClippingPlanes,
			addPin: addPin,
			removePin: removePin,
			getCurrentViewpoint: getCurrentViewpoint,
			clearHighlights: clearHighlights
		};

		return service;

		///////////////

		// TODO: More EventService to be removed, but these functions broadcast
		// across multiple watchers

		function handleEvent(event, account, model) {

			initialised.promise.then(function() {

				switch(event.type) {

				case EventService.EVENT.MODEL_SETTINGS_READY:
					if (event.value.account === account && event.value.model === model) {
						viewer.updateSettings(event.value.settings);
						//mapTile && mapTile.updateSettings(event.value.settings);
					}
					break;

				case EventService.EVENT.VIEWER.CLICK_PIN:
					viewer.clickPin(event.value.id);
					break;

				case EventService.EVENT.VIEWER.CHANGE_PIN_COLOUR:
					viewer.changePinColours(
						event.value.id,
						event.value.colours
					);
					break;

				case EventService.EVENT.VIEWER.UPDATE_CLIPPING_PLANES:
					viewer.updateClippingPlanes(
						event.value.clippingPlanes, event.value.fromClipPanel,
						event.value.account, event.value.model
					);
					break;

				case EventService.EVENT.VIEWER.BACKGROUND_SELECTED:
					viewer.clearHighlights();
					break;

				case EventService.EVENT.VIEWER.SET_CAMERA:
					currentModel.promise.then(function(){
						viewer.setCamera(
							event.value.position,
							event.value.view_dir,
							event.value.up,
							event.value.look_at,
							angular.isDefined(event.value.animate) ? event.value.animate : true,
							event.value.rollerCoasterMode,
							event.value.account,
							event.value.model
						);
					}).catch(function(error){
						handleUnityError("Setting the camera errored because model failed to load: " + error);
					});
					break;

				}

			});

		}

		function clearHighlights() {
			viewer.clearHighlights();
		}

		function getCurrentViewpoint(params) {
			// Note the Info suffix
			viewer.getCurrentViewpointInfo(
				params.account,
				params.model,
				params.promise
			);
		}

		function addPin(params) {
			initialised.promise.then(function(){
				viewer.addPin(
					params.account,
					params.model,
					params.id,
					params.pickedPos,
					params.pickedNorm,
					params.colours,
					params.viewpoint
				);
			});
		}

		function removePin(params) {
			initialised.promise.then(function(){
				viewer.removePin(
					params.id
				);
			});
		}

		function clearClippingPlanes() {
			viewer.clearClippingPlanes();
		}

		function getObjectsStatus(params) {
			viewer.getObjectsStatus(
				params.account,
				params.model,
				params.promise
			);
		}

		function highlightObjects(params) {

			viewer.highlightObjects(
				params.account,
				params.model,
				params.id ? [params.id] : params.ids,
				params.zoom,
				params.colour,
				params.multi
			);
		}

		function setMultiSelectMode(value) {
			viewer.setMultiSelectMode(value);
		}

		function switchObjectVisibility(account, model, ids, visibility){
			viewer.switchObjectVisibility(account, model, ids, visibility);
		}

		function handleUnityError(message) {

			DialogService.html("Unity Error", message, true)
				.then(function() {
					if (event.value.reload) {
						location.reload();
					}
				}, function() {
					console.error("Unity errorered and user canceled reload", message);
				});

		}

		function getModelInfo(account, model) {

			var url = account + "/" + model + ".json";

			return APIService.get(url);
		}

		function reset() {
			if (viewer) {
				disableMeasure();
				viewer.reset();
			}
		}

		function getViewer(name, element, eventCallback, errCallback) {
			if (!viewer) {
				viewer = new Viewer(
					name,
					element,
					eventCallback,
					errCallback
				);
			}

			return viewer;
		}

		function getScreenshot(promise) {
			if (promise) {
				viewer.getScreenshot(promise);
			}
		}

		function goToExtent() {
			viewer.goToExtent();
		}

		function setNavMode(mode) {
			viewer.setNavMode(mode);
		}

		function unityInserted() {
			if (!viewer) {
				return false;
			} else {
				return viewer.unityScriptInserted;
			}

		}

		function initViewer() {

			if (unityInserted()) {
				return callInit();
			} else {
				return viewer.insertUnityLoader()
					.then(callInit)
					.catch(function(error){
						console.error("Error inserting Unity script: ", error);
					});
			}

		}

		function activateMeasure() {
			viewer.setMeasureMode(true);
		}

		function disableMeasure() {
			viewer.setMeasureMode(false);
		}

		function callInit() {

			return viewer
				.init({
					showAll : true,
					getAPI: {
						hostNames:  ClientConfigService.apiUrls["all"]
					}
				})
				.catch(function(error){
					console.error("Error creating Viewer Directive: ", error);
				});

		}

		function loadViewerModel(account, model, branch, revision) {

			if (!account || !model) {
				console.error("Account, model, branch or revision was not defined!", account, model, branch, revision);
			} else {
				currentModel.promise = viewer.loadModel(
					account,
					model,
					branch,
					revision
				)
					.then(function(){
						// Set the current model in the viewer
						currentModel.model = model;
						initialised.resolve();
						fetchModelProperties(account, model, branch, revision);
					})
					.catch(function(error){
						console.error("Error loading model: ", error);
					});
			}

		}

		function fetchModelProperties(account, model, branch, revision) {

			if (account && model) {

				if(!branch) {
					branch = !revision ? "master" : "";
				}

				if(!revision || branch === "master") {
					//revision is master/head
					revision = branch + "/head";
				}

				var url = account + "/" + model + "/revision/" + revision + "/modelProperties.json";

				APIService.get(url)
					.then(function(response) {
						if (response.data && response.data.status) {
							if (response.data.status === "NOT_FOUND") {
								console.error("Model properties was not found from API");
							}
						}

						if (response.data && response.data.properties) {
							viewer.applyModelProperties(account, model, response.data.properties);
						} else {
							var message = "No data properties returned. This was the response:";
							console.error(message, response);
						}
					})
					.catch(function(error){
						console.error("Model properties failed to fetch", error);
					});

			} else {
				console.error("Account and model were not set correctly " +
				"for model property fetching: ", account, model);
			}

		}

	}
}());
<commit_msg>ISSUE #556 - Actually fix extent button<commit_after>/**
 *  Copyright (C) 2017 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

(function () {
	"use strict";

	angular.module("3drepo")
		.service("ViewerService", ViewerService);

	ViewerService.$inject = [
		"ClientConfigService", "$q", "APIService", "DialogService",
		"EventService"
	];

	function ViewerService(
		ClientConfigService, $q, APIService, DialogService, EventService
	) {

		var viewer;
		var currentModel = {
			model : null,
			promise : null
		};

		var initialised = $q.defer();

		var service = {
			pin : {
				pinDropMode : false
			},
			initViewer : initViewer,
			getViewer : getViewer,
			loadViewerModel : loadViewerModel,
			currentModel : currentModel,
			initialised : initialised,
			reset : reset,
			fetchModelProperties : fetchModelProperties,
			activateMeasure: activateMeasure,
			disableMeasure: disableMeasure,
			getScreenshot: getScreenshot,
			goToExtent: goToExtent,
			setNavMode: setNavMode,
			getModelInfo: getModelInfo,
			setMultiSelectMode: setMultiSelectMode,
			switchObjectVisibility: switchObjectVisibility,
			handleUnityError: handleUnityError,
			handleEvent: handleEvent,
			highlightObjects: highlightObjects,
			getObjectsStatus: getObjectsStatus,
			clearClippingPlanes: clearClippingPlanes,
			addPin: addPin,
			removePin: removePin,
			getCurrentViewpoint: getCurrentViewpoint,
			clearHighlights: clearHighlights
		};

		return service;

		///////////////

		// TODO: More EventService to be removed, but these functions broadcast
		// across multiple watchers

		function handleEvent(event, account, model) {

			initialised.promise.then(function() {

				switch(event.type) {

				case EventService.EVENT.MODEL_SETTINGS_READY:
					if (event.value.account === account && event.value.model === model) {
						viewer.updateSettings(event.value.settings);
						//mapTile && mapTile.updateSettings(event.value.settings);
					}
					break;

				case EventService.EVENT.VIEWER.CLICK_PIN:
					viewer.clickPin(event.value.id);
					break;

				case EventService.EVENT.VIEWER.CHANGE_PIN_COLOUR:
					viewer.changePinColours(
						event.value.id,
						event.value.colours
					);
					break;

				case EventService.EVENT.VIEWER.UPDATE_CLIPPING_PLANES:
					viewer.updateClippingPlanes(
						event.value.clippingPlanes, event.value.fromClipPanel,
						event.value.account, event.value.model
					);
					break;

				case EventService.EVENT.VIEWER.BACKGROUND_SELECTED:
					viewer.clearHighlights();
					break;

				case EventService.EVENT.VIEWER.SET_CAMERA:
					currentModel.promise.then(function(){
						viewer.setCamera(
							event.value.position,
							event.value.view_dir,
							event.value.up,
							event.value.look_at,
							angular.isDefined(event.value.animate) ? event.value.animate : true,
							event.value.rollerCoasterMode,
							event.value.account,
							event.value.model
						);
					}).catch(function(error){
						handleUnityError("Setting the camera errored because model failed to load: " + error);
					});
					break;

				}

			});

		}

		function clearHighlights() {
			viewer.clearHighlights();
		}

		function getCurrentViewpoint(params) {
			// Note the Info suffix
			viewer.getCurrentViewpointInfo(
				params.account,
				params.model,
				params.promise
			);
		}

		function addPin(params) {
			initialised.promise.then(function(){
				viewer.addPin(
					params.account,
					params.model,
					params.id,
					params.pickedPos,
					params.pickedNorm,
					params.colours,
					params.viewpoint
				);
			});
		}

		function removePin(params) {
			initialised.promise.then(function(){
				viewer.removePin(
					params.id
				);
			});
		}

		function clearClippingPlanes() {
			viewer.clearClippingPlanes();
		}

		function getObjectsStatus(params) {
			viewer.getObjectsStatus(
				params.account,
				params.model,
				params.promise
			);
		}

		function highlightObjects(params) {

			viewer.highlightObjects(
				params.account,
				params.model,
				params.id ? [params.id] : params.ids,
				params.zoom,
				params.colour,
				params.multi
			);
		}

		function setMultiSelectMode(value) {
			viewer.setMultiSelectMode(value);
		}

		function switchObjectVisibility(account, model, ids, visibility){
			viewer.switchObjectVisibility(account, model, ids, visibility);
		}

		function handleUnityError(message) {

			DialogService.html("Unity Error", message, true)
				.then(function() {
					if (event.value.reload) {
						location.reload();
					}
				}, function() {
					console.error("Unity errorered and user canceled reload", message);
				});

		}

		function getModelInfo(account, model) {

			var url = account + "/" + model + ".json";

			return APIService.get(url);
		}

		function reset() {
			if (viewer) {
				disableMeasure();
				viewer.reset();
			}
		}

		function getViewer(name, element, eventCallback, errCallback) {
			if (!viewer) {
				viewer = new Viewer(
					name,
					element,
					eventCallback,
					errCallback
				);
			}

			return viewer;
		}

		function getScreenshot(promise) {
			if (promise) {
				viewer.getScreenshot(promise);
			}
		}

		function goToExtent() {
			viewer.showAll();
		}

		function setNavMode(mode) {
			viewer.setNavMode(mode);
		}

		function unityInserted() {
			if (!viewer) {
				return false;
			} else {
				return viewer.unityScriptInserted;
			}

		}

		function initViewer() {

			if (unityInserted()) {
				return callInit();
			} else {
				return viewer.insertUnityLoader()
					.then(callInit)
					.catch(function(error){
						console.error("Error inserting Unity script: ", error);
					});
			}

		}

		function activateMeasure() {
			viewer.setMeasureMode(true);
		}

		function disableMeasure() {
			viewer.setMeasureMode(false);
		}

		function callInit() {

			return viewer
				.init({
					showAll : true,
					getAPI: {
						hostNames:  ClientConfigService.apiUrls["all"]
					}
				})
				.catch(function(error){
					console.error("Error creating Viewer Directive: ", error);
				});

		}

		function loadViewerModel(account, model, branch, revision) {

			if (!account || !model) {
				console.error("Account, model, branch or revision was not defined!", account, model, branch, revision);
			} else {
				currentModel.promise = viewer.loadModel(
					account,
					model,
					branch,
					revision
				)
					.then(function(){
						// Set the current model in the viewer
						currentModel.model = model;
						initialised.resolve();
						fetchModelProperties(account, model, branch, revision);
					})
					.catch(function(error){
						console.error("Error loading model: ", error);
					});
			}

		}

		function fetchModelProperties(account, model, branch, revision) {

			if (account && model) {

				if(!branch) {
					branch = !revision ? "master" : "";
				}

				if(!revision || branch === "master") {
					//revision is master/head
					revision = branch + "/head";
				}

				var url = account + "/" + model + "/revision/" + revision + "/modelProperties.json";

				APIService.get(url)
					.then(function(response) {
						if (response.data && response.data.status) {
							if (response.data.status === "NOT_FOUND") {
								console.error("Model properties was not found from API");
							}
						}

						if (response.data && response.data.properties) {
							viewer.applyModelProperties(account, model, response.data.properties);
						} else {
							var message = "No data properties returned. This was the response:";
							console.error(message, response);
						}
					})
					.catch(function(error){
						console.error("Model properties failed to fetch", error);
					});

			} else {
				console.error("Account and model were not set correctly " +
				"for model property fetching: ", account, model);
			}

		}

	}
}());
<|endoftext|>


<commit_before>/**
	Johannes Mainusch
	20130329
	instanciate an Energy Object and calculate consumption
*/

function energyObject () {
	var objref=this,
		gotDataEvent = "gotData";

	this.summaryTableDiv = "summaryTableDiv1234";
	this.meterPlotDiv = "meterPlotDiv1234";
	$('body').append ('

');
	$('body').append ('

');

	this.setDomain = function (URL) { this.domain = URL; return this; };
	this.setURL = function (URL) { this.URL = URL; return this; };
	this.setTitle = function (title) { this.title = title; return this; };
	this.setMyData = function (d) { this.myData = d; return this; };
	this.setMeterPlotDiv = function (d) { this.meterPlotDiv = d; return this; }
	this.setSummaryTableDiv = function (d) { this.summaryTableDiv = d; return this; }

	this.listenOnGotDataEvent = function () {
		$(objref).on (gotDataEvent, this.GotDataEventCallback);
		return objref;
	};

	this.GotDataEventCallback = function (event) {
		console.log( 'gotData!!!, #datapoints=' , event);
		this.calculate (this.myData);
		this.tableSummary(this.myData);
		plotN (this.myData, this.meterPlotDiv, this.title);

		this.listenOnWebSocket ();

		return this;
	};

	this.getData = function (nolines) {
		$.ajax ({
			url: this.URL+'/get?'+'nolines='+nolines,
			cache : false,
			dataType: 'jsonp',
			crossDomain: true,
			success:
				function (data) { // this little closure will preserve the object reference of this (energyObject)
					console.log ("got called back with data ...", data[data.length-1] );
					objref.setMyData( data );
					$(objref).trigger( gotDataEvent, [data]);
					return objref;
				}
		});
		return this;
	};

	this.listenOnWebSocket = function () {
		console.log('in listenOnWebSocket', this.domain);
		var socket = io.connect(this.domain);
	  		socket.on('got new data', function (d) {
	    		console.log('WebSocket speaks:',  d);
	    		//socket.emit('my other event', { my: 'data' });
				// pop the first array entry and put the new data on the end
				objref.myData.push(d);
				objref.myData.shift();
				objref.tableSummary(objref.myData);
				plotN (objref.myData, objref.meterPlotDiv, objref.title);
	  		});
		return this;
	};

	// render some calculation on the data
	this.calculate = function (data) {
		var t1=data[0].timestamp,
		    t2=data[data.length-1].timestamp,
			tdiff = t2 - t1;
		console.log ("in calculate, myobj.mydata.length:" + data.length);
		console.log ("in calculate, mydata:" + new Date (data[0].timestamp));
		console.log ("in calculate, mydata:" + new Date (data[data.length-1].timestamp) );
		console.log ("in calculate, tdiff[s]=" + tdiff/1000);
		console.log ("in calculate, KW/h per day=" + (data.length/75) * (86400*1000)/tdiff );
		console.log ("in calculate, KW/h per year=" + 365*(data.length/75) * (86400*1000)/tdiff );
		return this;
	};

	// render some calculation on the data
	this.tableSummary = function (data) {
		console.log ("in tableSummary..." + data[0].timestamp );
		var t1=data[0].timestamp,
		    t2=data[data.length-1].timestamp,
			tdiff = t2 - t1;
		$('#'+this.summaryTableDiv)
			//.appendTo('body')
			.html('
');
		$('#summaryTable').append( $('
')
				.append( $('').append('selected entries: ') )
				.append( $('').append(data.length + ", last at: "+new Date (data[data.length-1].timestamp)) )
			)
			.append( $('
')
				.append( $('').append('measuring time: ') )
				.append( $('').append(  Math.round( tdiff/(100*60*60*24) )/10 +" Tage	" ) )
			)
			.append( $('
')
				.append( $('').append('KW/h per day: ') )
				.append( $('').append( Math.round( 100*(data.length/75) * (86400*1000)/tdiff) /100) )
			)
			.append( $('
')
				.append( $('').append('KW/h per year: ') )
				.append( $('').append( Math.round( 10*365*(data.length/75) * (86400*1000)/tdiff) /10 ) )
			);

	};

	return this;
}

<commit_msg>Update getEnergyObject.js<commit_after>/**
	Johannes Mainusch
	20130329
	instanciate an Energy Object and calculate consumption
*/

function energyObject () {
	var objref = this,
	    gotDataEvent = "gotData";

	this.summaryTableDiv = "summaryTableDiv1234";
	this.meterPlotDiv = "meterPlotDiv1234";
	$('body').append ('

');

	this.setDomain = function (URL) { this.domain = URL; return this; };
	this.setURL = function (URL) { this.URL = URL; return this; };
	this.setTitle = function (title) { this.title = title; return this; };
	this.setMyData = function (d) { this.myData = d; return this; };
	this.setMeterPlotDiv = function (d) { this.meterPlotDiv = d; return this; }
	this.setSummaryTableDiv = function (d) { this.summaryTableDiv = d; return this; }

	this.listenOnGotDataEvent = function () {
		$(objref).on (gotDataEvent, this.GotDataEventCallback);
		return objref;
	};

	this.GotDataEventCallback = function (event) {
		console.log( 'gotData!!!, #datapoints=' , event);
		this.calculate (this.myData);
		this.tableSummary(this.myData);
		plotN (this.myData, this.meterPlotDiv, this.title);

		this.listenOnWebSocket ();

		return this;
	};

	this.getData = function (nolines) {
		$.ajax ({
			url: this.URL+'/get?'+'nolines='+nolines,
			cache : false,
			dataType: 'jsonp',
			crossDomain: true,
			success:
				function (data) { // this little closure will preserve the object reference of this (energyObject)
					console.log ("got called back with data ...", data[data.length-1] );
					objref.setMyData( data );
					$(objref).trigger( gotDataEvent, [data]);
					return objref;
				}
		});
		return this;
	};

	this.listenOnWebSocket = function () {
		console.log('in listenOnWebSocket', this.domain);
		var socket = io.connect(this.domain);
	  		socket.on('got new data', function (d) {
	    		console.log('WebSocket speaks:',  d);
	    		//socket.emit('my other event', { my: 'data' });
				// pop the first array entry and put the new data on the end
				objref.myData.push(d);
				objref.myData.shift();
				objref.tableSummary(objref.myData);
				plotN (objref.myData, objref.meterPlotDiv, objref.title);
	  		});
		return this;
	};

	// render some calculation on the data
	this.calculate = function (data) {
		var t1=data[0].timestamp,
		    t2=data[data.length-1].timestamp,
			tdiff = t2 - t1;
		console.log ("in calculate, myobj.mydata.length:" + data.length);
		console.log ("in calculate, mydata:" + new Date (data[0].timestamp));
		console.log ("in calculate, mydata:" + new Date (data[data.length-1].timestamp) );
		console.log ("in calculate, tdiff[s]=" + tdiff/1000);
		console.log ("in calculate, KW/h per day=" + (data.length/75) * (86400*1000)/tdiff );
		console.log ("in calculate, KW/h per year=" + 365*(data.length/75) * (86400*1000)/tdiff );
		return this;
	};

	// render some calculation on the data
	this.tableSummary = function (data) {
		console.log ("in tableSummary..." + data[0].timestamp );
		var t1=data[0].timestamp,
		    t2=data[data.length-1].timestamp,
			tdiff = t2 - t1;
		$('#'+this.summaryTableDiv)
			//.appendTo('body')
			.html('
');
		$('#summaryTable').append( $('
')
				.append( $('').append('selected entries: ') )
				.append( $('').append(data.length + ", last at: "+new Date (data[data.length-1].timestamp)) )
			)
			.append( $('
')
				.append( $('').append('measuring time: ') )
				.append( $('').append(  Math.round( tdiff/(100*60*60*24) )/10 +" Tage	" ) )
			)
			.append( $('
')
				.append( $('').append('KW/h per day: ') )
				.append( $('').append( Math.round( 100*(data.length/75) * (86400*1000)/tdiff) /100) )
			)
			.append( $('
')
				.append( $('').append('KW/h per year: ') )
				.append( $('').append( Math.round( 10*365*(data.length/75) * (86400*1000)/tdiff) /10 ) )
			);

	};

	return this;
}

<|endoftext|>


<commit_before>/**
 * Dialog for member selections
 */
var DrillthroughModal = Modal.extend({
    type: "drillthrough",

    buttons: [
        { text: "Ok", method: "ok" },
        { text: "Cancel", method: "close" }
    ],

    events: {
        'click .collapsed': 'select',
        'click .expand': 'select',
        'click .folder_collapsed': 'select',
        'click .folder_expanded': 'select',

        'click .dialog_footer a:' : 'call',
        'click .parent_dimension input' : 'select_dimension',
        'click .measure_tree input' : 'select_measure'
    },

    initialize: function(args) {
        // Initialize properties
        _.extend(this, args);
        this.options.title = args.title;
        this.query = args.workspace.query;

        this.position = args.position;
        this.action = args.action;
        Saiku.ui.unblock();
        _.bindAll(this, "ok", "drilled");

        // Resize when rendered
        this.bind('open', this.post_render);
        this.render();
               // Load template
       $(this.el).find('.dialog_body')
          .html(_.template($("#template-drillthrough").html())(this));
        // Show dialog
        $(this.el).find('.maxrows').val(this.maxrows);

        var schema = this.query.get('schema');
        var key = this.query.get('connection') + "/" +
                this.query.get('catalog') + "/"
                + ((schema == "" || schema == null) ? "null" : schema)
                + "/" + this.query.get('cube');

        var dimensions = Saiku.session.sessionworkspace.dimensions[key].get('data');
        var measures = Saiku.session.sessionworkspace.measures[key].get('data');

        var container = $("#template-drillthrough-list").html();
        var templ_dim =_.template($("#template-drillthrough-dimensions").html())({dimensions: dimensions});
        var templ_measure =_.template($("#template-drillthrough-measures").html())({measures: measures});

        $(container).appendTo($(this.el).find('.dialog_body'));
        $(this.el).find('.sidebar').height(($("body").height() / 2) + ($("body").height() / 6) );
        $(this.el).find('.sidebar').width(380);

        $(this.el).find('.dimension_tree').html('').append($(templ_dim));
        $(this.el).find('.measure_tree').html('').append($(templ_measure));

    },

    select: function(event) {
        var $target = $(event.target).hasClass('root')
            ? $(event.target) : $(event.target).parent().find('span');
        if ($target.hasClass('root')) {
            $target.find('a').toggleClass('folder_collapsed').toggleClass('folder_expand');
            $target.toggleClass('collapsed').toggleClass('expand');
            $target.parents('li').find('ul').children('li').toggle();
        }

        return false;
    },

    select_dimension: function(event) {
        var $target = $(event.target);
        var checked = $target.is(':checked');
        $target.parent().find('input').attr('checked', checked);
    },

    select_measure: function(event) {
        var $target = $(event.target);
        var checked = $target.is(':checked');
        if(checked) {
            $target.parent().siblings().find('input').attr('checked', false);
        }
    },

    post_render: function(args) {
        $(args.modal.el).parents('.ui-dialog').css({ width: "150px" });
    },

    ok: function() {
        // Notify user that updates are in progress
        var $loading = $("
Drilling through...
");
        $(this.el).find('.dialog_body').children().hide();
        $(this.el).find('.dialog_body').prepend($loading);
        var selections = ""
        $(this.el).find('.check_level:checked').each( function(index) {
            if (index > 0) {
                selections += ", ";
            }
            selections += $(this).val();
        });

        var maxrows = $(this.el).find('.maxrows').val();
        var params = "?maxrows=" + maxrows;
        params = params + (typeof this.position !== "undefined" ? "&position=" + this.position : "" );
        params += "&returns=" + selections;
        if (this.action == "export") {
            var location = Settings.REST_URL +
                Saiku.session.username + "/query/" +
                this.query.id + "/drillthrough/export/csv" + params;
            this.close();
            window.open(location);
        } else if (this.action == "table") {
            Saiku.ui.block("Executing drillthrough...");
            this.query.action.get("/drillthrough", { data: { position: this.position, maxrows: maxrows , returns: selections}, success: this.drilled } );
            this.close();
        }

        return false;
    },

    drilled: function(model, response) {
        var table = new Table({ workspace: this.workspace });
        table.render({ data: response }, true);

        Saiku.ui.unblock();
        var html = '

' + $(table.el).html() + '

';
        this.remove();
        table.remove();
        $.fancybox(html
            ,
            {
            'autoDimensions'    : false,
            'autoScale'         : false,
            'height'            :  ($("body").height() - 100),
            'width'             :  ($("body").width() - 100),
            'transitionIn'      : 'none',
            'transitionOut'     : 'none'
            }
        ).resize();

    },

    finished: function() {
        $(this.el).dialog('destroy').remove();
        this.query.run();
    }
});<commit_msg>fix fancy box issue<commit_after>/**
 * Dialog for member selections
 */
var DrillthroughModal = Modal.extend({
    type: "drillthrough",

    buttons: [
        { text: "Ok", method: "ok" },
        { text: "Cancel", method: "close" }
    ],

    events: {
        'click .collapsed': 'select',
        'click .expand': 'select',
        'click .folder_collapsed': 'select',
        'click .folder_expanded': 'select',

        'click .dialog_footer a:' : 'call',
        'click .parent_dimension input' : 'select_dimension',
        'click .measure_tree input' : 'select_measure'
    },

    initialize: function(args) {
        // Initialize properties
        _.extend(this, args);
        this.options.title = args.title;
        this.query = args.workspace.query;

        this.position = args.position;
        this.action = args.action;
        Saiku.ui.unblock();
        _.bindAll(this, "ok", "drilled");

        // Resize when rendered
        this.bind('open', this.post_render);
        this.render();
               // Load template
       $(this.el).find('.dialog_body')
          .html(_.template($("#template-drillthrough").html())(this));
        // Show dialog
        $(this.el).find('.maxrows').val(this.maxrows);

        var schema = this.query.get('schema');
        var key = this.query.get('connection') + "/" +
                this.query.get('catalog') + "/"
                + ((schema == "" || schema == null) ? "null" : schema)
                + "/" + this.query.get('cube');

        var dimensions = Saiku.session.sessionworkspace.dimensions[key].get('data');
        var measures = Saiku.session.sessionworkspace.measures[key].get('data');

        var container = $("#template-drillthrough-list").html();
        var templ_dim =_.template($("#template-drillthrough-dimensions").html())({dimensions: dimensions});
        var templ_measure =_.template($("#template-drillthrough-measures").html())({measures: measures});

        $(container).appendTo($(this.el).find('.dialog_body'));
        $(this.el).find('.sidebar').height(($("body").height() / 2) + ($("body").height() / 6) );
        $(this.el).find('.sidebar').width(380);

        $(this.el).find('.dimension_tree').html('').append($(templ_dim));
        $(this.el).find('.measure_tree').html('').append($(templ_measure));

    },

    select: function(event) {
        var $target = $(event.target).hasClass('root')
            ? $(event.target) : $(event.target).parent().find('span');
        if ($target.hasClass('root')) {
            $target.find('a').toggleClass('folder_collapsed').toggleClass('folder_expand');
            $target.toggleClass('collapsed').toggleClass('expand');
            $target.parents('li').find('ul').children('li').toggle();
        }

        return false;
    },

    select_dimension: function(event) {
        var $target = $(event.target);
        var checked = $target.is(':checked');
        $target.parent().find('input').attr('checked', checked);
    },

    select_measure: function(event) {
        var $target = $(event.target);
        var checked = $target.is(':checked');
        if(checked) {
            $target.parent().siblings().find('input').attr('checked', false);
        }
    },

    post_render: function(args) {
        $(args.modal.el).parents('.ui-dialog').css({ width: "150px" });
    },

    ok: function() {
        // Notify user that updates are in progress
        var $loading = $("
Drilling through...
");
        $(this.el).find('.dialog_body').children().hide();
        $(this.el).find('.dialog_body').prepend($loading);
        var selections = ""
        $(this.el).find('.check_level:checked').each( function(index) {
            if (index > 0) {
                selections += ", ";
            }
            selections += $(this).val();
        });

        var maxrows = $(this.el).find('.maxrows').val();
        var params = "?maxrows=" + maxrows;
        params = params + (typeof this.position !== "undefined" ? "&position=" + this.position : "" );
        params += "&returns=" + selections;
        if (this.action == "export") {
            var location = Settings.REST_URL +
                Saiku.session.username + "/query/" +
                this.query.id + "/drillthrough/export/csv" + params;
            this.close();
            window.open(location);
        } else if (this.action == "table") {
            Saiku.ui.block("Executing drillthrough...");
            this.query.action.get("/drillthrough", { data: { position: this.position, maxrows: maxrows , returns: selections}, success: this.drilled } );
            this.close();
        }

        return false;
    },

    drilled: function(model, response) {
        var table = new Table({ workspace: this.workspace });
        table.render({ data: response }, true);

        Saiku.ui.unblock();
        var html = '

' + $(table.el).html() + '

';
        this.remove();
        table.remove();
        $.fancybox(html
            ,
            {
            'autoDimensions'    : false,
            'autoScale'         : false,
            'height'            :  ($("body").height() - 100),
            'width'             :  ($("body").width() - 100),
            'transitionIn'      : 'none',
            'transitionOut'     : 'none'
            }
        );

    },

    finished: function() {
        $(this.el).dialog('destroy').remove();
        this.query.run();
    }
});<|endoftext|>


<commit_before>import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';
import '@polymer/iron-collapse/iron-collapse.js';
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/iron-icons/social-icons.js';
import '@polymer/paper-badge/paper-badge.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-tooltip/paper-tooltip.js';
import '../debug.js';

import {ReduxMixin} from './redux/store';
import {actions as channelsActions} from './redux/server_info/channels';
import {actions as statsActions} from './redux/server_info/server_stats';
import {actions as currentActions} from './redux/current_actions';

class ServerInfo extends PolymerElement {

    static get template() {
        return html`

            Uptime [[serverStats.uptime]]

            Unique users remembered
            <paper-badge label="[[serverStats.remembered_user_count]]"></paper-badge>

            Unique users connected
            <paper-badge label="[[serverStats.unique_user_count]]"></paper-badge>

            Total connections
            <paper-badge label="[[serverStats.total_connections]]"></paper-badge>

            Total channels
            <paper-badge label="[[serverStats.total_channels]]"></paper-badge>

            Messages since start
            <paper-badge label="[[serverStats.total_unique_messages]]"></paper-badge>

            All frames sent
            <paper-badge label="[[serverStats.total_messages]]"></paper-badge>

        <template is="dom-repeat" items="[[channels]]">
            <paper-card heading="channel: [[item.name]]">

Long name: [[item.long_name]]

last active: [[item.last_active]]

Total connections: [[item.total_connections]]

Total users: [[item.total_users]]

Config

                    <app-debug data="[[item.settings]]"></app-debug>

                    <iron-collapse class$="channel-history-[[index]]">

                            Message history:
                            <template is="dom-repeat" items="[[item.history]]">
                                <app-debug data="[[item]]"></app-debug>

        </template>

        </iron-collapse>

        <iron-collapse class$="channel-users-[[index]]">

                Connected users:
                <template is="dom-repeat" items="[[item.users]]">

[[item]]

                </template>

        </iron-collapse>

            <paper-button toggles raised on-tap="toggleHistory" data-channel$="[[item.name]]" data-index$="[[index]]">
                <iron-icon icon="icons:history"></iron-icon>History</paper-button>
            <paper-tooltip position="top" animation-delay="0">Shows this channels history</paper-tooltip>

            <paper-button toggles raised on-tap="toggleUsers" data-channel$="[[item.name]]" data-index$="[[index]]">
                <iron-icon icon="social:people-outline"></iron-icon>Users</paper-button>
            <paper-tooltip position="top" animation-delay="0">Shows currently connected users</paper-tooltip>

        </paper-card>
        `;
    }

    static get is() {
        return 'server-info';
    }

    static get properties() {
        return {
            channels: {
                type: Array
            },
            serverStats: {
                type: Object
            }
        };
    }

    toggleHistory(event) {
        let index = event.currentTarget.dataset['index'];
        if (index !== undefined) {
            this.shadowRoot.querySelector('.channel-history-' + index).toggle();
        }
    }

    toggleUsers(event) {
        let index = event.currentTarget.dataset['index'];
        if (index !== undefined) {
            this.shadowRoot.querySelector('.channel-users-' + index).toggle();
        }
    }
}

customElements.define(ServerInfo.is, ServerInfo);
<commit_msg>front: server info now uses lit-html for rendering<commit_after>import {LitElement, html} from '@polymer/lit-element';
import { repeat } from 'lit-html/lib/repeat.js';
import '@polymer/iron-collapse/iron-collapse.js';
import '@polymer/iron-icons/iron-icons.js';
import '@polymer/iron-icons/social-icons.js';
import '@polymer/paper-badge/paper-badge.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-tooltip/paper-tooltip.js';
import '../debug.js';

import {ReduxMixin} from './redux/store';
import {actions as channelsActions} from './redux/server_info/channels';
import {actions as statsActions} from './redux/server_info/server_stats';
import {actions as currentActions} from './redux/current_actions';

class ServerInfo extends LitElement {

    _render({channels, serverStats}) {
        return html`

            Uptime ${serverStats.uptime}

            Unique users remembered
            <paper-badge label="${serverStats.remembered_user_count}"></paper-badge>

            Unique users connected
            <paper-badge label="${serverStats.unique_user_count}"></paper-badge>

            Total connections
            <paper-badge label="${serverStats.total_connections}"></paper-badge>

            Total channels
            <paper-badge label="${serverStats.total_channels}"></paper-badge>

            Messages since start
            <paper-badge label="${serverStats.total_unique_messages}"></paper-badge>

            All frames sent
            <paper-badge label="${serverStats.total_messages}"></paper-badge>

            ${repeat(channels, (channel) => channel.name, (channel, index) => html`
            <paper-card heading="channel: ${channel.name}" class$="channel-${channel.id}">

                ${index}

Long name: ${channel.long_name}

last active: ${channel.last_active}

Total connections: ${channel.total_connections}

Total users: ${channel.total_users}

Config

                    <app-debug data="${channel.settings}"></app-debug>

                    <iron-collapse class$="channel-history-${channel.id}">

                            Message history:
                            ${channel.history.map((item) => html`
                            <app-debug data="${item}"></app-debug>
                            `)}

                    </iron-collapse>

                    <iron-collapse class$="channel-users-${channel.id}">

                            Connected users:
                            ${channel.users.map((item) => html`

${item}

                            `)}

                    </iron-collapse>

                <paper-button raised toggles on-tap=${(e) => this.toggleHistory(channel.id)}">
                    <iron-icon icon="icons:history"></iron-icon>History</paper-button>
                <paper-tooltip position="top" animation-delay="0">Shows this channels history</paper-tooltip>

                <paper-button raised toggles on-tap=${(e) => this.toggleUsers(channel.id)}">
                    <iron-icon icon="social:people-outline"></iron-icon>Users</paper-button>
                <paper-tooltip position="top" animation-delay="0">Shows currently connected users</paper-tooltip>

            </paper-card>
            `)}

        `;
    }

    static get is() {
        return 'server-info';
    }

    static get properties() {
        return {
            channels: {
                type: Array
            },
            serverStats: {
                type: Object
            }
        };
    }

    toggleHistory(index) {
        if (index !== undefined) {
            this.shadowRoot.querySelector('.channel-history-' + index).toggle();
        }
    }

    toggleUsers(index) {
        if (index !== undefined) {
            this.shadowRoot.querySelector('.channel-users-' + index).toggle();
        }
    }
}

customElements.define(ServerInfo.is, ServerInfo);
<|endoftext|>