<commit_before>/*
 * CommonJS-compatible mustache.js module
 *
 * See http://github.com/janl/mustache.js for more info.
 */

/*
  mustache.js — Logic-less templates in JavaScript

  See http://mustache.github.com/ for more info.
*/

var Mustache = function() {
  var regexCache = {};
  var Renderer = function() {};

  Renderer.prototype = {
    otag: "{{",
    ctag: "}}",
    pragmas: {},
    buffer: [],
    pragmas_implemented: {
      "IMPLICIT-ITERATOR": true
    },
    context: {},

    render: function(template, context, partials, in_recursion) {
      // reset buffer & set context
      if(!in_recursion) {
        this.context = context;
        this.buffer = []; // TODO: make this non-lazy
      }

      // fail fast
      if(!this.includes("", template)) {
        if(in_recursion) {
          return template;
        } else {
          this.send(template);
          return;
        }
      }

      // get the pragmas together
      template = this.render_pragmas(template);

      // render the template
      var html = this.render_section(template, context, partials);

      // render_section did not find any sections, we still need to render the tags
      if (html === false) {
        html = this.render_tags(template, context, partials, in_recursion);
      }

      if (in_recursion) {
        return html;
      } else {
        this.sendLines(html);
      }
    },

    /*
      Sends parsed lines
    */
    send: function(line) {
      if(line !== "") {
        this.buffer.push(line);
      }
    },

    sendLines: function(text) {
      if (text) {
        var lines = text.split("\n");
        for (var i = 0; i < lines.length; i++) {
          this.send(lines[i]);
        }
      }
    },

    /*
      Looks for %PRAGMAS
    */
    render_pragmas: function(template) {
      // no pragmas
      if(!this.includes("%", template)) {
        return template;
      }

      var that = this;
      var regex = this.getCachedRegex("render_pragmas", function(otag, ctag) {
        return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g");
      });

      return template.replace(regex, function(match, pragma, options) {
        if(!that.pragmas_implemented[pragma]) {
          throw({message:
            "This implementation of mustache doesn't understand the '" +
            pragma + "' pragma"});
        }
        that.pragmas[pragma] = {};
        if(options) {
          var opts = options.split("=");
          that.pragmas[pragma][opts[0]] = opts[1];
        }
        return "";
        // ignore unknown pragmas silently
      });
    },

    /*
      Tries to find a partial in the curent scope and render it
    */
    render_partial: function(name, context, partials) {
      name = this.trim(name);
      if(!partials || partials[name] === undefined) {
        throw({message: "unknown_partial '" + name + "'"});
      }
      if(typeof(context[name]) != "object") {
        return this.render(partials[name], context, partials, true);
      }
      return this.render(partials[name], context[name], partials, true);
    },

    /*
      Renders inverted (^) and normal (#) sections
    */
    render_section: function(template, context, partials) {
      if(!this.includes("#", template) && !this.includes("^", template)) {
        // did not render anything, there were no sections
        return false;
      }

      var that = this;

      var regex = this.getCachedRegex("render_section", function(otag, ctag) {
        // This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder
        return new RegExp(
          "^([\\s\\S]*?)" +         // all the crap at the beginning that is not {{*}} ($1)

          otag +                    // {{
          "(\\^|\\#)\\s*(.+)\\s*" + //  #foo (# == $2, foo == $3)
          ctag +                    // }}

          "\n*([\\s\\S]*?)" +       // between the tag ($2). leading newlines are dropped

          otag +                    // {{
          "\\/\\s*\\3\\s*" +        //  /foo (backreference to the opening tag).
          ctag +                    // }}

          "\\s*([\\s\\S]*)$",       // everything else in the string ($4). leading whitespace is dropped.

        "g");
      });

      // for each {{#foo}}{{/foo}} section do...
      return template.replace(regex, function(match, before, type, name, content, after) {
        // before contains only tags, no sections
        var renderedBefore = before ? that.render_tags(before, context, partials, true) : "",

        // after may contain both sections and tags, so use full rendering function
            renderedAfter = after ? that.render(after, context, partials, true) : "",

        // will be computed below
            renderedContent,

            value = that.find(name, context);

        if (type === "^") { // inverted section
          if (!value || that.is_array(value) && value.length === 0) {
            // false or empty list, render it
            renderedContent = that.render(content, context, partials, true);
          } else {
            renderedContent = "";
          }
        } else if (type === "#") { // normal section
          if (that.is_array(value)) { // Enumerable, Let's loop!
            renderedContent = that.map(value, function(row) {
              return that.render(content, that.create_context(row), partials, true);
            }).join("");
          } else if (that.is_object(value)) { // Object, Use it as subcontext!
            renderedContent = that.render(content, that.create_context(value),
              partials, true);
          } else if (typeof value === "function") {
            // higher order section
            renderedContent = value.call(context, content, function(text) {
              return that.render(text, context, partials, true);
            });
          } else if (value) { // boolean section
            renderedContent = that.render(content, context, partials, true);
          } else {
            renderedContent = "";
          }
        }

        return renderedBefore + renderedContent + renderedAfter;
      });
    },

    /*
      Replace {{foo}} and friends with values from our view
    */
    render_tags: function(template, context, partials, in_recursion) {
      // tit for tat
      var that = this;

      var new_regex = function() {
        return that.getCachedRegex("render_tags", function(otag, ctag) {
          return new RegExp(otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" + ctag + "+", "g");
        });
      };

      var regex = new_regex();
      var tag_replace_callback = function(match, operator, name) {
        switch(operator) {
        case "!": // ignore comments
          return "";
        case "=": // set new delimiters, rebuild the replace regexp
          that.set_delimiters(name);
          regex = new_regex();
          return "";
        case ">": // render partial
          return that.render_partial(name, context, partials);
        case "{": // the triple mustache is unescaped
          return that.find(name, context);
        default: // escape the value
          return that.escape(that.find(name, context));
        }
      };
      var lines = template.split("\n");
      for(var i = 0; i < lines.length; i++) {
        lines[i] = lines[i].replace(regex, tag_replace_callback, this);
        if(!in_recursion) {
          this.send(lines[i]);
        }
      }

      if(in_recursion) {
        return lines.join("\n");
      }
    },

    set_delimiters: function(delimiters) {
      var dels = delimiters.split(" ");
      this.otag = this.escape_regex(dels[0]);
      this.ctag = this.escape_regex(dels[1]);
    },

    escape_regex: function(text) {
      // thank you Simon Willison
      if(!arguments.callee.sRE) {
        var specials = [
          '/', '.', '*', '+', '?', '|',
          '(', ')', '[', ']', '{', '}', '\\'
        ];
        arguments.callee.sRE = new RegExp(
          '(\\' + specials.join('|\\') + ')', 'g'
        );
      }
      return text.replace(arguments.callee.sRE, '\\$1');
    },

    /*
      find `name` in current `context`. That is find me a value
      from the view object
    */
    find: function(name, context) {
      name = this.trim(name);

      // Checks whether a value is thruthy or false or 0
      function is_kinda_truthy(bool) {
        return bool === false || bool === 0 || bool;
      }

      var value;

      // check for dot notation eg. foo.bar
      if(name.match(/([a-z_]+)\./ig)){
        value = is_kinda_truthy(this.walk_context(name, context));
      }
      else{
        if(is_kinda_truthy(context[name])) {
          value = context[name];
        } else if(is_kinda_truthy(this.context[name])) {
          value = this.context[name];
        }
      }

      if(typeof value === "function") {
        return value.apply(context);
      }
      if(value !== undefined) {
        return value;
      }
      // silently ignore unkown variables
      return "";
    },

    walk_context: function(name, context){
      var path = name.split('.');
      // if the var doesn't exist in current context, check the top level context
      var value_context = (context[path[0]] != undefined) ? context : this.context;
      var value = value_context[path.shift()];
      while(value != undefined && path.length > 0){
        value_context = value;
        value = value[path.shift()];
      }
      // if the value is a function, call it, binding the correct context
      if(typeof value === "function") {
        return value.apply(value_context);
      }
      return value;
    },

    // Utility methods

    /* includes tag */
    includes: function(needle, haystack) {
      return haystack.indexOf(this.otag + needle) != -1;
    },

    /*
      Does away with nasty characters
    */
    escape: function(s) {
      s = String(s === null ? "" : s);
      return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) {
        switch(s) {
        case "&": return "&";
        case '"': return '"';
        case "'": return ''';
        case "<": return "<";
        case ">": return ">";
        default: return s;
        }
      });
    },

    // by @langalex, support for arrays of strings
    create_context: function(_context) {
      if(this.is_object(_context)) {
        return _context;
      } else {
        var iterator = ".";
        if(this.pragmas["IMPLICIT-ITERATOR"]) {
          iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
        }
        var ctx = {};
        ctx[iterator] = _context;
        return ctx;
      }
    },

    is_object: function(a) {
      return a && typeof a == "object";
    },

    is_array: function(a) {
      return Object.prototype.toString.call(a) === '[object Array]';
    },

    /*
      Gets rid of leading and trailing whitespace
    */
    trim: function(s) {
      return s.replace(/^\s*|\s*$/g, "");
    },

    /*
      Why, why, why? Because IE. Cry, cry cry.
    */
    map: function(array, fn) {
      if (typeof array.map == "function") {
        return array.map(fn);
      } else {
        var r = [];
        var l = array.length;
        for(var i = 0; i < l; i++) {
          r.push(fn(array[i]));
        }
        return r;
      }
    },

    getCachedRegex: function(name, generator) {
      var byOtag = regexCache[this.otag];
      if (!byOtag) {
        byOtag = regexCache[this.otag] = {};
      }

      var byCtag = byOtag[this.ctag];
      if (!byCtag) {
        byCtag = byOtag[this.ctag] = {};
      }

      var regex = byCtag[name];
      if (!regex) {
        regex = byCtag[name] = generator(this.otag, this.ctag);
      }

      return regex;
    }
  };

  return({
    name: "mustache.js",
    version: "0.4.0-dev",

    /*
      Turns a template and view into HTML
    */
    to_html: function(template, view, partials, send_fun) {
      var renderer = new Renderer();
      if(send_fun) {
        renderer.send = send_fun;
      }
      renderer.render(template, view || {}, partials);
      if(!send_fun) {
        return renderer.buffer.join("\n");
      }
    }
  });
}();

exports.name = Mustache.name;
exports.version = Mustache.version;

exports.to_html = function() {
  return Mustache.to_html.apply(this, arguments);
};
<commit_msg>update mustache.js used in example app to 0.4.2<commit_after>/*
 * CommonJS-compatible mustache.js module
 *
 * See http://github.com/janl/mustache.js for more info.
 */

/*
  mustache.js — Logic-less templates in JavaScript

  See http://mustache.github.com/ for more info.
*/

var Mustache = function () {
  var _toString = Object.prototype.toString;

  Array.isArray = Array.isArray || function (obj) {
    return _toString.call(obj) == "[object Array]";
  }

  var _trim = String.prototype.trim, trim;

  if (_trim) {
    trim = function (text) {
      return text == null ? "" : _trim.call(text);
    }
  } else {
    var trimLeft, trimRight;

    // IE doesn't match non-breaking spaces with \s.
    if ((/\S/).test("\xA0")) {
      trimLeft = /^[\s\xA0]+/;
      trimRight = /[\s\xA0]+$/;
    } else {
      trimLeft = /^\s+/;
      trimRight = /\s+$/;
    }

    trim = function (text) {
      return text == null ? "" :
        text.toString().replace(trimLeft, "").replace(trimRight, "");
    }
  }

  var escapeMap = {
    "&": "&",
    "<": "<",
    ">": ">",
    '"': '"',
    "'": '''
  };

  function escapeHTML(string) {
    return String(string).replace(/&(?!#?\w+;)|[<>"']/g, function (s) {
      return escapeMap[s] || s;
    });
  }

  var regexCache = {};
  var Renderer = function () {};

  Renderer.prototype = {
    otag: "{{",
    ctag: "}}",
    pragmas: {},
    buffer: [],
    pragmas_implemented: {
      "IMPLICIT-ITERATOR": true
    },
    context: {},

    render: function (template, context, partials, in_recursion) {
      // reset buffer & set context
      if (!in_recursion) {
        this.context = context;
        this.buffer = []; // TODO: make this non-lazy
      }

      // fail fast
      if (!this.includes("", template)) {
        if (in_recursion) {
          return template;
        } else {
          this.send(template);
          return;
        }
      }

      // get the pragmas together
      template = this.render_pragmas(template);

      // render the template
      var html = this.render_section(template, context, partials);

      // render_section did not find any sections, we still need to render the tags
      if (html === false) {
        html = this.render_tags(template, context, partials, in_recursion);
      }

      if (in_recursion) {
        return html;
      } else {
        this.sendLines(html);
      }
    },

    /*
      Sends parsed lines
    */
    send: function (line) {
      if (line !== "") {
        this.buffer.push(line);
      }
    },

    sendLines: function (text) {
      if (text) {
        var lines = text.split("\n");
        for (var i = 0; i < lines.length; i++) {
          this.send(lines[i]);
        }
      }
    },

    /*
      Looks for %PRAGMAS
    */
    render_pragmas: function (template) {
      // no pragmas
      if (!this.includes("%", template)) {
        return template;
      }

      var that = this;
      var regex = this.getCachedRegex("render_pragmas", function (otag, ctag) {
        return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g");
      });

      return template.replace(regex, function (match, pragma, options) {
        if (!that.pragmas_implemented[pragma]) {
          throw({message:
            "This implementation of mustache doesn't understand the '" +
            pragma + "' pragma"});
        }
        that.pragmas[pragma] = {};
        if (options) {
          var opts = options.split("=");
          that.pragmas[pragma][opts[0]] = opts[1];
        }
        return "";
        // ignore unknown pragmas silently
      });
    },

    /*
      Tries to find a partial in the curent scope and render it
    */
    render_partial: function (name, context, partials) {
      name = trim(name);
      if (!partials || partials[name] === undefined) {
        throw({message: "unknown_partial '" + name + "'"});
      }
      if (!context || typeof context[name] != "object") {
        return this.render(partials[name], context, partials, true);
      }
      return this.render(partials[name], context[name], partials, true);
    },

    /*
      Renders inverted (^) and normal (#) sections
    */
    render_section: function (template, context, partials) {
      if (!this.includes("#", template) && !this.includes("^", template)) {
        // did not render anything, there were no sections
        return false;
      }

      var that = this;

      var regex = this.getCachedRegex("render_section", function (otag, ctag) {
        // This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder
        return new RegExp(
          "^([\\s\\S]*?)" +         // all the crap at the beginning that is not {{*}} ($1)

          otag +                    // {{
          "(\\^|\\#)\\s*(.+?)\\s*" +//  #foo (# == $2, foo == $3), not greedy
          ctag +                    // }}

          "\n*([\\s\\S]*?)" +       // between the tag ($2). leading newlines are dropped

          otag +                    // {{
          "\\/\\s*\\3\\s*" +        //  /foo (backreference to the opening tag).
          ctag +                    // }}

          "\\s*([\\s\\S]*)$",       // everything else in the string ($4). leading whitespace is dropped.

        "g");
      });

      // for each {{#foo}}{{/foo}} section do...
      return template.replace(regex, function (match, before, type, name, content, after) {
        // before contains only tags, no sections
        var renderedBefore = before ? that.render_tags(before, context, partials, true) : "",

        // after may contain both sections and tags, so use full rendering function
            renderedAfter = after ? that.render(after, context, partials, true) : "",

        // will be computed below
            renderedContent,

            value = that.find(name, context);

        if (type === "^") { // inverted section
          if (!value || Array.isArray(value) && value.length === 0) {
            // false or empty list, render it
            renderedContent = that.render(content, context, partials, true);
          } else {
            renderedContent = "";
          }
        } else if (type === "#") { // normal section
          if (Array.isArray(value)) { // Enumerable, Let's loop!
            renderedContent = that.map(value, function (row) {
              return that.render(content, that.create_context(row), partials, true);
            }).join("");
          } else if (that.is_object(value)) { // Object, Use it as subcontext!
            renderedContent = that.render(content, that.create_context(value),
              partials, true);
          } else if (typeof value == "function") {
            // higher order section
            renderedContent = value.call(context, content, function (text) {
              return that.render(text, context, partials, true);
            });
          } else if (value) { // boolean section
            renderedContent = that.render(content, context, partials, true);
          } else {
            renderedContent = "";
          }
        }

        return renderedBefore + renderedContent + renderedAfter;
      });
    },

    /*
      Replace {{foo}} and friends with values from our view
    */
    render_tags: function (template, context, partials, in_recursion) {
      // tit for tat
      var that = this;

      var new_regex = function () {
        return that.getCachedRegex("render_tags", function (otag, ctag) {
          return new RegExp(otag + "(=|!|>|&|\\{|%)?([^#\\^]+?)\\1?" + ctag + "+", "g");
        });
      };

      var regex = new_regex();
      var tag_replace_callback = function (match, operator, name) {
        switch(operator) {
        case "!": // ignore comments
          return "";
        case "=": // set new delimiters, rebuild the replace regexp
          that.set_delimiters(name);
          regex = new_regex();
          return "";
        case ">": // render partial
          return that.render_partial(name, context, partials);
        case "{": // the triple mustache is unescaped
        case "&": // & operator is an alternative unescape method
          return that.find(name, context);
        default: // escape the value
          return escapeHTML(that.find(name, context));
        }
      };
      var lines = template.split("\n");
      for(var i = 0; i < lines.length; i++) {
        lines[i] = lines[i].replace(regex, tag_replace_callback, this);
        if (!in_recursion) {
          this.send(lines[i]);
        }
      }

      if (in_recursion) {
        return lines.join("\n");
      }
    },

    set_delimiters: function (delimiters) {
      var dels = delimiters.split(" ");
      this.otag = this.escape_regex(dels[0]);
      this.ctag = this.escape_regex(dels[1]);
    },

    escape_regex: function (text) {
      // thank you Simon Willison
      if (!arguments.callee.sRE) {
        var specials = [
          '/', '.', '*', '+', '?', '|',
          '(', ')', '[', ']', '{', '}', '\\'
        ];
        arguments.callee.sRE = new RegExp(
          '(\\' + specials.join('|\\') + ')', 'g'
        );
      }
      return text.replace(arguments.callee.sRE, '\\$1');
    },

    /*
      find `name` in current `context`. That is find me a value
      from the view object
    */
    find: function (name, context) {
      name = trim(name);

      // Checks whether a value is thruthy or false or 0
      function is_kinda_truthy(bool) {
        return bool === false || bool === 0 || bool;
      }

      var value;

      // check for dot notation eg. foo.bar
      if (name.match(/([a-z_]+)\./ig)) {
        var childValue = this.walk_context(name, context);
        if (is_kinda_truthy(childValue)) {
          value = childValue;
        }
      } else {
        if (is_kinda_truthy(context[name])) {
          value = context[name];
        } else if (is_kinda_truthy(this.context[name])) {
          value = this.context[name];
        }
      }

      if (typeof value == "function") {
        return value.apply(context);
      }
      if (value !== undefined) {
        return value;
      }
      // silently ignore unkown variables
      return "";
    },

    walk_context: function (name, context) {
      var path = name.split('.');
      // if the var doesn't exist in current context, check the top level context
      var value_context = (context[path[0]] != undefined) ? context : this.context;
      var value = value_context[path.shift()];
      while (value != undefined && path.length > 0) {
        value_context = value;
        value = value[path.shift()];
      }
      // if the value is a function, call it, binding the correct context
      if (typeof value == "function") {
        return value.apply(value_context);
      }
      return value;
    },

    // Utility methods

    /* includes tag */
    includes: function (needle, haystack) {
      return haystack.indexOf(this.otag + needle) != -1;
    },

    // by @langalex, support for arrays of strings
    create_context: function (_context) {
      if (this.is_object(_context)) {
        return _context;
      } else {
        var iterator = ".";
        if (this.pragmas["IMPLICIT-ITERATOR"]) {
          iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
        }
        var ctx = {};
        ctx[iterator] = _context;
        return ctx;
      }
    },

    is_object: function (a) {
      return a && typeof a == "object";
    },

    /*
      Why, why, why? Because IE. Cry, cry cry.
    */
    map: function (array, fn) {
      if (typeof array.map == "function") {
        return array.map(fn);
      } else {
        var r = [];
        var l = array.length;
        for(var i = 0; i < l; i++) {
          r.push(fn(array[i]));
        }
        return r;
      }
    },

    getCachedRegex: function (name, generator) {
      var byOtag = regexCache[this.otag];
      if (!byOtag) {
        byOtag = regexCache[this.otag] = {};
      }

      var byCtag = byOtag[this.ctag];
      if (!byCtag) {
        byCtag = byOtag[this.ctag] = {};
      }

      var regex = byCtag[name];
      if (!regex) {
        regex = byCtag[name] = generator(this.otag, this.ctag);
      }

      return regex;
    }
  };

  return({
    name: "mustache.js",
    version: "0.4.2",

    /*
      Turns a template and view into HTML
    */
    to_html: function (template, view, partials, send_fun) {
      var renderer = new Renderer();
      if (send_fun) {
        renderer.send = send_fun;
      }
      renderer.render(template, view || {}, partials);
      if (!send_fun) {
        return renderer.buffer.join("\n");
      }
    }
  });
}();
if (typeof module !== 'undefined' && module.exports) {
    exports.name = Mustache.name;
    exports.version = Mustache.version;

    exports.to_html = function() {
      return Mustache.to_html.apply(this, arguments);
    };
}
<|endoftext|>


<commit_before>import React, { Component } from "react";
import gql from "graphql-tag";
import { Container, Row, Col, Button, Card, CardBody } from "reactstrap";
import { graphql, withApollo } from "react-apollo";
import Tour from "reactour";
import FontAwesome from "react-fontawesome";

import "./style.scss";

const SYSTEMS_SUB = gql`
  subscription SystemsUpdate($simulatorId: ID) {
    systemsUpdate(simulatorId: $simulatorId, extra: true) {
      id
      name
      damage {
        damaged
        destroyed
        report
        requested
        reactivationCode
        neededReactivationCode
        currentStep
        validate
      }
      simulatorId
      type
    }
  }
`;

class DamageControl extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedSystem: null,
      reactivationCodeModal: false,
      codeEntry: ""
    };
    this.systemSub = null;
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (!this.systemSub && !nextProps.data.loading) {
      this.systemSub = nextProps.data.subscribeToMore({
        document: SYSTEMS_SUB,
        variables: {
          simulatorId: nextProps.simulator.id
        },
        updateQuery: (previousResult, { subscriptionData }) => {
          return Object.assign({}, previousResult, {
            systems: subscriptionData.data.systemsUpdate
          });
        }
      });
    }
    if (!nextProps.data.loading && nextProps.data.systems) {
      const selectedSystem = nextProps.data.systems.find(
        s => s.id === this.state.selectedSystem
      );
      if (selectedSystem) {
        this.setState({
          codeEntry: selectedSystem.damage.reactivationCode || ""
        });
      }
    }
  }
  componentWillUnmount() {
    this.systemSub && this.systemSub();
  }
  systemName(sys) {
    if (sys.type === "Shield") {
      return `${sys.name} Shields`;
    }
    if (sys.type === "Engine") {
      return `${sys.name} Engines`;
    }
    return sys.name;
  }
  selectSystem(id) {
    const selectedSystem = this.props.data.systems.find(s => s.id === id);
    this.setState({
      selectedSystem: id,
      codeEntry: selectedSystem.damage.reactivationCode || ""
    });
  }
  requestReport() {
    const mutation = gql`
      mutation RequestReport($systemId: ID!) {
        requestDamageReport(systemId: $systemId)
      }
    `;
    const variables = {
      systemId: this.state.selectedSystem
    };
    this.props.client.mutate({
      mutation,
      variables
    });
  }
  toggle = () => {
    this.setState({
      reactivationCodeModal: !this.state.reactivationCodeModal
    });
  };
  cancelReactivationCode = () => {
    this.setState({
      reactivationCodeModal: false,
      codeEntry: ""
    });
  };
  setCodeEntry = c => {
    if ((this.state.codeEntry + c).length <= 8) {
      this.setState({
        codeEntry: this.state.codeEntry + c
      });
    }
  };
  clearCodeEntry = () => {
    this.setState({
      codeEntry: ""
    });
  };
  reactivateCode = () => {
    this.toggle();
    const mutation = gql`
      mutation SendReactivationCode(
        $systemId: ID!
        $station: String!
        $code: String!
      ) {
        systemReactivationCode(
          systemId: $systemId
          station: $station
          code: $code
        )
      }
    `;
    const variables = {
      systemId: this.state.selectedSystem,
      code: this.state.codeEntry,
      station: this.props.station.name
    };
    this.props.client.mutate({
      mutation,
      variables
    });
  };
  setStep = step => {
    const mutation = gql`
      mutation SetDamageStep($systemId: ID!, $step: Int!) {
        updateCurrentDamageStep(systemId: $systemId, step: $step)
      }
    `;
    const variables = {
      systemId: this.state.selectedSystem,
      step: Math.max(0, step)
    };
    this.props.client.mutate({
      mutation,
      variables
    });
  };
  damageReportText = (system, steps, stepDamage) => {
    if (system) {
      if (stepDamage) {
        return steps[system.damage.currentStep || 0];
      }
      return system.damage.report;
    }
  };
  verifyStep = () => {
    const mutation = gql`
      mutation SetDamageStepValidation($id: ID!) {
        setDamageStepValidation(id: $id, validation: true)
      }
    `;
    const variables = {
      id: this.state.selectedSystem
    };
    this.props.client.mutate({
      mutation,
      variables
    });
  };
  render() {
    if (this.props.data.loading) return null;
    const systems = this.props.data.systems;
    const simulators = this.props.data.simulators;
    if (!systems || !simulators) return null;
    const { stepDamage, verifyStep } = simulators[0];
    const damagedSystem = systems.find(
      s => this.state.selectedSystem === s.id
    ) || { damage: {} };
    const system =
      this.state.selectedSystem && systems
        ? systems.find(s => s.id === this.state.selectedSystem)
        : null;
    const report = system ? system.damage.report : "";
    const steps = report
      ? report.split(/Step [0-9]+:\n/gi).filter(s => s && s !== "\n")
      : [];
    return (
      <Container fluid className="damage-control">
        <Row>
          <Col
            sm="3"
            className={`damage-list ${
              damagedSystem.damage.neededReactivationCode
                ? "reactivation-code"
                : ""
            }`}
          >

Damaged Systems

            <Card>
              <CardBody className="damaged-systems">
                {this.state.reactivationCodeModal ? (

                      {["¥", "Ω", "∏", "§", "-", "∆", "£", "∑", "∂"].map(
                        (c, i) => (

 this.setCodeEntry(c)}>
                            {c}

                        )
                      )}

                    <Row>
                      <Col sm={5}>
                        <Button
                          block
                          color="danger"
                          onClick={this.cancelReactivationCode}
                        >
                          Cancel
                        </Button>
                      </Col>
                      <Col sm={{ size: 5, offset: 2 }}>
                        <Button
                          block
                          color="warning"
                          onClick={this.clearCodeEntry}
                        >
                          Clear
                        </Button>
                      </Col>
                    </Row>

                ) : (
                  systems.filter(s => s.damage.damaged).map(s => (
                    <p
                      key={s.id}
                      className={`${
                        this.state.selectedSystem === s.id ? "selected" : ""
                      } ${s.damage.requested ? "requested" : ""} ${
                        s.damage.report ? "report" : ""
                      } ${s.damage.validate ? "validate" : ""} ${
                        s.damage.destroyed ? "destroyed" : ""
                      }`}
                      onClick={
                        s.damage.destroyed
                          ? () => {}
                          : this.selectSystem.bind(this, s.id)
                      }
                    >
                      {s.damage.validate ? (
                        <FontAwesome name="refresh" spin />
                      ) : null}{" "}
                      {this.systemName(s)}

                  ))
                )}
              </CardBody>
            </Card>
            {this.state.reactivationCodeModal ? (
              <Button
                block
                size="lg"
                color="primary"
                onClick={this.reactivateCode}
              >
                Reactivate
              </Button>
            ) : (
              <Button
                block
                className="request-report"
                disabled={!this.state.selectedSystem}
                onClick={this.requestReport.bind(this)}
                color="primary"
              >
                Request Damage Report
              </Button>
            )}
            {damagedSystem.damage.neededReactivationCode && (
              <Card
                className="reactivation-code-entry"
                onClick={
                  this.state.reactivationCodeModal ? () => {} : this.toggle
                }
              >
                <CardBody>
                  <p className={`${this.state.codeEntry ? "code-entry" : ""}`}>
                    {this.state.codeEntry
                      ? this.state.codeEntry
                      : "Enter Reactivation Code..."}

                </CardBody>
              </Card>
            )}
          </Col>
          <Col sm="9" className="damage-report">
            <Row>
              <Col sm={12}>

Damage Report

                <Card>
                  <CardBody>

                      {this.damageReportText(system, steps, stepDamage)}

                  </CardBody>
                </Card>
              </Col>
            </Row>
            {stepDamage && (
              <Row>
                <Col sm={3}>
                  {!verifyStep && (
                    <Button
                      disabled={!system || system.damage.currentStep === 0}
                      block
                      color="secondary"
                      onClick={() =>
                        this.setStep(system.damage.currentStep - 1)
                      }
                    >
                      Previous Step
                    </Button>
                  )}
                </Col>
                <Col sm={6}>

                    {system && system.damage.damageReportText
                      ? system.damage.currentStep + 1
                      : 0}{" "}
                    / {steps.length}

                </Col>
                <Col sm={3}>
                  {verifyStep ? (
                    <Button
                      disabled={
                        !system ||
                        steps.length === 0 ||
                        system.damage.currentStep === steps.length - 1 ||
                        system.damage.validate
                      }
                      block
                      color="secondary"
                      onClick={this.verifyStep}
                    >
                      {system && system.damage.validate
                        ? "Validating Step"
                        : "Verify Step"}
                    </Button>
                  ) : (
                    <Button
                      disabled={
                        !system ||
                        steps.length === 0 ||
                        system.damage.currentStep === steps.length - 1
                      }
                      block
                      color="secondary"
                      onClick={() =>
                        this.setStep(system.damage.currentStep + 1)
                      }
                    >
                      Next Step
                    </Button>
                  )}
                </Col>
              </Row>
            )}
          </Col>
        </Row>

        <Tour
          steps={trainingSteps}
          isOpen={this.props.clientObj.training}
          onRequestClose={this.props.stopTraining}
        />
      </Container>
    );
  }
}
const trainingSteps = [
  {
    selector: ".damaged-systems",
    content:
      "The ship’s systems are intelligent enough to know when they’re damaged, and to understand (mostly) how they can be fixed. A list of damaged systems appears here. Click a system to see the damage report"
  },
  {
    selector: ".request-report",
    content:
      "If a damage report hasn't been calculated, you need to request a damage report by clicking on this button."
  },
  {
    selector: ".damageReport-text",
    content:
      "When a system is damaged, instructions to troubleshoot and repair the damaged system will appear here. Follow them exactly."
  },
  {
    selector: ".damage-control",
    content:
      "Sometimes, a system needs a reactivation code to be entered before it can be repaired. Click the 'Enter Reactivation Code' button, then press the symbols listed in your damage report. Once the reactivation code is accepted, the system will be repaired."
  }
];

const SYSTEMS_QUERY = gql`
  query Systems($simulatorId: ID, $simId: String) {
    simulators(id: $simId) {
      id
      stepDamage
      verifyStep
    }
    systems(simulatorId: $simulatorId, extra: true) {
      id
      name
      damage {
        damaged
        destroyed
        report
        requested
        reactivationCode
        neededReactivationCode
        currentStep
        validate
      }
      simulatorId
      type
    }
  }
`;

export default graphql(SYSTEMS_QUERY, {
  options: ownProps => ({
    fetchPolicy: "cache-and-network",
    variables: {
      simulatorId: ownProps.simulator.id,
      simId: ownProps.simulator.id
    }
  })
})(withApollo(DamageControl));
<commit_msg>Fixes an issue with the current step not showing up. Closes #1104<commit_after>import React, { Component } from "react";
import gql from "graphql-tag";
import { Container, Row, Col, Button, Card, CardBody } from "reactstrap";
import { graphql, withApollo } from "react-apollo";
import Tour from "reactour";
import FontAwesome from "react-fontawesome";

import "./style.scss";

const SYSTEMS_SUB = gql`
  subscription SystemsUpdate($simulatorId: ID) {
    systemsUpdate(simulatorId: $simulatorId, extra: true) {
      id
      name
      damage {
        damaged
        destroyed
        report
        requested
        reactivationCode
        neededReactivationCode
        currentStep
        validate
      }
      simulatorId
      type
    }
  }
`;

class DamageControl extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedSystem: null,
      reactivationCodeModal: false,
      codeEntry: ""
    };
    this.systemSub = null;
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (!this.systemSub && !nextProps.data.loading) {
      this.systemSub = nextProps.data.subscribeToMore({
        document: SYSTEMS_SUB,
        variables: {
          simulatorId: nextProps.simulator.id
        },
        updateQuery: (previousResult, { subscriptionData }) => {
          return Object.assign({}, previousResult, {
            systems: subscriptionData.data.systemsUpdate
          });
        }
      });
    }
    if (!nextProps.data.loading && nextProps.data.systems) {
      const selectedSystem = nextProps.data.systems.find(
        s => s.id === this.state.selectedSystem
      );
      if (selectedSystem) {
        this.setState({
          codeEntry: selectedSystem.damage.reactivationCode || ""
        });
      }
    }
  }
  componentWillUnmount() {
    this.systemSub && this.systemSub();
  }
  systemName(sys) {
    if (sys.type === "Shield") {
      return `${sys.name} Shields`;
    }
    if (sys.type === "Engine") {
      return `${sys.name} Engines`;
    }
    return sys.name;
  }
  selectSystem(id) {
    const selectedSystem = this.props.data.systems.find(s => s.id === id);
    this.setState({
      selectedSystem: id,
      codeEntry: selectedSystem.damage.reactivationCode || ""
    });
  }
  requestReport() {
    const mutation = gql`
      mutation RequestReport($systemId: ID!) {
        requestDamageReport(systemId: $systemId)
      }
    `;
    const variables = {
      systemId: this.state.selectedSystem
    };
    this.props.client.mutate({
      mutation,
      variables
    });
  }
  toggle = () => {
    this.setState({
      reactivationCodeModal: !this.state.reactivationCodeModal
    });
  };
  cancelReactivationCode = () => {
    this.setState({
      reactivationCodeModal: false,
      codeEntry: ""
    });
  };
  setCodeEntry = c => {
    if ((this.state.codeEntry + c).length <= 8) {
      this.setState({
        codeEntry: this.state.codeEntry + c
      });
    }
  };
  clearCodeEntry = () => {
    this.setState({
      codeEntry: ""
    });
  };
  reactivateCode = () => {
    this.toggle();
    const mutation = gql`
      mutation SendReactivationCode(
        $systemId: ID!
        $station: String!
        $code: String!
      ) {
        systemReactivationCode(
          systemId: $systemId
          station: $station
          code: $code
        )
      }
    `;
    const variables = {
      systemId: this.state.selectedSystem,
      code: this.state.codeEntry,
      station: this.props.station.name
    };
    this.props.client.mutate({
      mutation,
      variables
    });
  };
  setStep = step => {
    const mutation = gql`
      mutation SetDamageStep($systemId: ID!, $step: Int!) {
        updateCurrentDamageStep(systemId: $systemId, step: $step)
      }
    `;
    const variables = {
      systemId: this.state.selectedSystem,
      step: Math.max(0, step)
    };
    this.props.client.mutate({
      mutation,
      variables
    });
  };
  damageReportText = (system, steps, stepDamage) => {
    if (system) {
      if (stepDamage) {
        return steps[system.damage.currentStep || 0];
      }
      return system.damage.report;
    }
  };
  verifyStep = () => {
    const mutation = gql`
      mutation SetDamageStepValidation($id: ID!) {
        setDamageStepValidation(id: $id, validation: true)
      }
    `;
    const variables = {
      id: this.state.selectedSystem
    };
    this.props.client.mutate({
      mutation,
      variables
    });
  };
  render() {
    if (this.props.data.loading) return null;
    const systems = this.props.data.systems;
    const simulators = this.props.data.simulators;
    if (!systems || !simulators) return null;
    const { stepDamage, verifyStep } = simulators[0];
    const damagedSystem = systems.find(
      s => this.state.selectedSystem === s.id
    ) || { damage: {} };
    const system =
      this.state.selectedSystem && systems
        ? systems.find(s => s.id === this.state.selectedSystem)
        : null;
    const report = system ? system.damage.report : "";
    const steps = report
      ? report.split(/Step [0-9]+:\n/gi).filter(s => s && s !== "\n")
      : [];
    return (
      <Container fluid className="damage-control">
        <Row>
          <Col
            sm="3"
            className={`damage-list ${
              damagedSystem.damage.neededReactivationCode
                ? "reactivation-code"
                : ""
            }`}
          >

Damaged Systems

            <Card>
              <CardBody className="damaged-systems">
                {this.state.reactivationCodeModal ? (

                      {["¥", "Ω", "∏", "§", "-", "∆", "£", "∑", "∂"].map(
                        (c, i) => (

 this.setCodeEntry(c)}>
                            {c}

                        )
                      )}

                    <Row>
                      <Col sm={5}>
                        <Button
                          block
                          color="danger"
                          onClick={this.cancelReactivationCode}
                        >
                          Cancel
                        </Button>
                      </Col>
                      <Col sm={{ size: 5, offset: 2 }}>
                        <Button
                          block
                          color="warning"
                          onClick={this.clearCodeEntry}
                        >
                          Clear
                        </Button>
                      </Col>
                    </Row>

                ) : (
                  systems.filter(s => s.damage.damaged).map(s => (
                    <p
                      key={s.id}
                      className={`${
                        this.state.selectedSystem === s.id ? "selected" : ""
                      } ${s.damage.requested ? "requested" : ""} ${
                        s.damage.report ? "report" : ""
                      } ${s.damage.validate ? "validate" : ""} ${
                        s.damage.destroyed ? "destroyed" : ""
                      }`}
                      onClick={
                        s.damage.destroyed
                          ? () => {}
                          : this.selectSystem.bind(this, s.id)
                      }
                    >
                      {s.damage.validate ? (
                        <FontAwesome name="refresh" spin />
                      ) : null}{" "}
                      {this.systemName(s)}

                  ))
                )}
              </CardBody>
            </Card>
            {this.state.reactivationCodeModal ? (
              <Button
                block
                size="lg"
                color="primary"
                onClick={this.reactivateCode}
              >
                Reactivate
              </Button>
            ) : (
              <Button
                block
                className="request-report"
                disabled={!this.state.selectedSystem}
                onClick={this.requestReport.bind(this)}
                color="primary"
              >
                Request Damage Report
              </Button>
            )}
            {damagedSystem.damage.neededReactivationCode && (
              <Card
                className="reactivation-code-entry"
                onClick={
                  this.state.reactivationCodeModal ? () => {} : this.toggle
                }
              >
                <CardBody>
                  <p className={`${this.state.codeEntry ? "code-entry" : ""}`}>
                    {this.state.codeEntry
                      ? this.state.codeEntry
                      : "Enter Reactivation Code..."}

                </CardBody>
              </Card>
            )}
          </Col>
          <Col sm="9" className="damage-report">
            <Row>
              <Col sm={12}>

Damage Report

                <Card>
                  <CardBody>

                      {this.damageReportText(system, steps, stepDamage)}

                  </CardBody>
                </Card>
              </Col>
            </Row>
            {stepDamage && (
              <Row>
                <Col sm={3}>
                  {!verifyStep && (
                    <Button
                      disabled={!system || system.damage.currentStep === 0}
                      block
                      color="secondary"
                      onClick={() =>
                        this.setStep(system.damage.currentStep - 1)
                      }
                    >
                      Previous Step
                    </Button>
                  )}
                </Col>
                <Col sm={6}>

                    {(() => {
                      system &&
                        console.log(
                          system.damage,
                          system.damage.damageReportText,
                          system.damage.currentStep
                        );
                    })()}
                    {system &&
                    (system.damage.damageReportText || system.damage.report)
                      ? system.damage.currentStep + 1
                      : 0}{" "}
                    / {steps.length}

                </Col>
                <Col sm={3}>
                  {verifyStep ? (
                    <Button
                      disabled={
                        !system ||
                        steps.length === 0 ||
                        system.damage.currentStep === steps.length - 1 ||
                        system.damage.validate
                      }
                      block
                      color="secondary"
                      onClick={this.verifyStep}
                    >
                      {system && system.damage.validate
                        ? "Validating Step"
                        : "Verify Step"}
                    </Button>
                  ) : (
                    <Button
                      disabled={
                        !system ||
                        steps.length === 0 ||
                        system.damage.currentStep === steps.length - 1
                      }
                      block
                      color="secondary"
                      onClick={() =>
                        this.setStep(system.damage.currentStep + 1)
                      }
                    >
                      Next Step
                    </Button>
                  )}
                </Col>
              </Row>
            )}
          </Col>
        </Row>

        <Tour
          steps={trainingSteps}
          isOpen={this.props.clientObj.training}
          onRequestClose={this.props.stopTraining}
        />
      </Container>
    );
  }
}
const trainingSteps = [
  {
    selector: ".damaged-systems",
    content:
      "The ship’s systems are intelligent enough to know when they’re damaged, and to understand (mostly) how they can be fixed. A list of damaged systems appears here. Click a system to see the damage report"
  },
  {
    selector: ".request-report",
    content:
      "If a damage report hasn't been calculated, you need to request a damage report by clicking on this button."
  },
  {
    selector: ".damageReport-text",
    content:
      "When a system is damaged, instructions to troubleshoot and repair the damaged system will appear here. Follow them exactly."
  },
  {
    selector: ".damage-control",
    content:
      "Sometimes, a system needs a reactivation code to be entered before it can be repaired. Click the 'Enter Reactivation Code' button, then press the symbols listed in your damage report. Once the reactivation code is accepted, the system will be repaired."
  }
];

const SYSTEMS_QUERY = gql`
  query Systems($simulatorId: ID, $simId: String) {
    simulators(id: $simId) {
      id
      stepDamage
      verifyStep
    }
    systems(simulatorId: $simulatorId, extra: true) {
      id
      name
      damage {
        damaged
        destroyed
        report
        requested
        reactivationCode
        neededReactivationCode
        currentStep
        validate
      }
      simulatorId
      type
    }
  }
`;

export default graphql(SYSTEMS_QUERY, {
  options: ownProps => ({
    fetchPolicy: "cache-and-network",
    variables: {
      simulatorId: ownProps.simulator.id,
      simId: ownProps.simulator.id
    }
  })
})(withApollo(DamageControl));
<|endoftext|>


<commit_before>'use strict';

var webpack = require('webpack');
var WebpackServer = require('webpack-dev-server');

var hopsConfig = require('hops-config');
var hopsBuildConfig = require('hops-build-config');
var createMiddleware = require('hops-middleware');
var server = require('hops-server');

var cleanup = require('./lib/cleanup');

process.on('unhandledRejection', function (error) {
  throw error;
});

function runDevelop (options, callback) {
  var config = require(hopsBuildConfig.developConfig);
  var watchOptions = config.devServer.watchOptions || config.watchOptions;
  var app = new WebpackServer(
    webpack(config),
    Object.assign({}, config.devServer, {
      after: function (app) {
        app.use(server.rewritePath);
        server.bootstrap(app, hopsConfig);
        server.registerMiddleware(app, createMiddleware(
          require(hopsBuildConfig.nodeConfig),
          watchOptions
        ));
        server.teardown(app, hopsConfig);
      },
      watchOptions: watchOptions
    })
  );
  server.run(app, callback);
}

module.exports = function (options, callback) {
  if (options.clean) {
    var dirs = [hopsConfig.buildDir, hopsConfig.cacheDir];
    return cleanup(dirs).then(runDevelop.bind(null, options, callback));
  } else {
    return runDevelop(options, callback);
  }
};
<commit_msg>refactor(build): change order of applied config objects<commit_after>'use strict';

var webpack = require('webpack');
var WebpackServer = require('webpack-dev-server');

var hopsConfig = require('hops-config');
var hopsBuildConfig = require('hops-build-config');
var createMiddleware = require('hops-middleware');
var server = require('hops-server');

var cleanup = require('./lib/cleanup');

process.on('unhandledRejection', function (error) {
  throw error;
});

function runDevelop (options, callback) {
  var config = require(hopsBuildConfig.developConfig);
  var watchOptions = config.devServer.watchOptions || config.watchOptions;
  var app = new WebpackServer(
    webpack(config),
    Object.assign({}, {
      after: function (app) {
        app.use(server.rewritePath);
        server.bootstrap(app, hopsConfig);
        server.registerMiddleware(app, createMiddleware(
          require(hopsBuildConfig.nodeConfig),
          watchOptions
        ));
        server.teardown(app, hopsConfig);
      },
      watchOptions: watchOptions
    }, config.devServer)
  );
  server.run(app, callback);
}

module.exports = function (options, callback) {
  if (options.clean) {
    var dirs = [hopsConfig.buildDir, hopsConfig.cacheDir];
    return cleanup(dirs).then(runDevelop.bind(null, options, callback));
  } else {
    return runDevelop(options, callback);
  }
};
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */
/* global TimelineDataSeries, TimelineGraphView */

'use strict';

var audio2 = document.querySelector('audio#audio2');
var callButton = document.querySelector('button#callButton');
var hangupButton = document.querySelector('button#hangupButton');
var codecSelector = document.querySelector('select#codec');
hangupButton.disabled = true;
callButton.onclick = call;
hangupButton.onclick = hangup;

var pc1;
var pc2;
var localStream;

var bitrateGraph;
var bitrateSeries;

var packetGraph;
var packetSeries;

var lastResult;

var offerOptions = {
  offerToReceiveAudio: 1,
  offerToReceiveVideo: 0,
  voiceActivityDetection: false
};

function gotStream(stream) {
  hangupButton.disabled = false;
  trace('Received local stream');
  localStream = stream;
  var audioTracks = localStream.getAudioTracks();
  if (audioTracks.length > 0) {
    trace('Using Audio device: ' + audioTracks[0].label);
  }
  pc1.addStream(localStream);
  trace('Adding Local Stream to peer connection');

  pc1.createOffer(gotDescription1, onCreateSessionDescriptionError,
      offerOptions);

  bitrateSeries = new TimelineDataSeries();
  bitrateGraph = new TimelineGraphView('bitrateGraph', 'bitrateCanvas');
  bitrateGraph.updateEndDate();

  packetSeries = new TimelineDataSeries();
  packetGraph = new TimelineGraphView('packetGraph', 'packetCanvas');
  packetGraph.updateEndDate();
}

function onCreateSessionDescriptionError(error) {
  trace('Failed to create session description: ' + error.toString());
}

function gumFailed(e) {
  alert('getUserMedia() error: ' + e.name);
}

function call() {
  callButton.disabled = true;
  codecSelector.disabled = true;
  trace('Starting call');
  var servers = null;
  var pcConstraints = {
    'optional': []
  };
  pc1 = new RTCPeerConnection(servers, pcConstraints);
  trace('Created local peer connection object pc1');
  pc1.onicecandidate = iceCallback1;
  pc2 = new RTCPeerConnection(servers, pcConstraints);
  trace('Created remote peer connection object pc2');
  pc2.onicecandidate = iceCallback2;
  pc2.onaddstream = gotRemoteStream;
  trace('Requesting local stream');

  var constraints = {
    audio: true,
    video: true
  };
  if (typeof Promise === 'undefined') {
    navigator.getUserMedia(constraints, gotStream, gumFailed);
  } else {
    navigator.mediaDevices.getUserMedia(constraints)
    .then(gotStream)
    .catch(gumFailed);
  }
}

function gotDescription1(desc) {
  desc.sdp = forceChosenAudioCodec(desc.sdp);
  trace('Offer from pc1 \n' + desc.sdp);
  pc1.setLocalDescription(desc, function() {
    pc2.setRemoteDescription(desc, function() {
      // Since the 'remote' side has no media stream we need
      // to pass in the right constraints in order for it to
      // accept the incoming offer of audio.
      pc2.createAnswer(gotDescription2, onCreateSessionDescriptionError);
    }, onSetSessionDescriptionError);
  }, onSetSessionDescriptionError);
}

function gotDescription2(desc) {
  desc.sdp = forceChosenAudioCodec(desc.sdp);
  pc2.setLocalDescription(desc, function() {
    trace('Answer from pc2 \n' + desc.sdp);
    pc1.setRemoteDescription(desc, function() {
    }, onSetSessionDescriptionError);
  }, onSetSessionDescriptionError);
}

function hangup() {
  trace('Ending call');
  localStream.getTracks().forEach(function(track) {
    track.stop();
  });
  pc1.close();
  pc2.close();
  pc1 = null;
  pc2 = null;
  hangupButton.disabled = true;
  callButton.disabled = false;
  codecSelector.disabled = false;
}

function gotRemoteStream(e) {
  audio2 = attachMediaStream(audio2, e.stream);
  trace('Received remote stream');
}

function iceCallback1(event) {
  if (event.candidate) {
    pc2.addIceCandidate(new RTCIceCandidate(event.candidate),
        onAddIceCandidateSuccess, onAddIceCandidateError);
    trace('Local ICE candidate: \n' + event.candidate.candidate);
  }
}

function iceCallback2(event) {
  if (event.candidate) {
    pc1.addIceCandidate(new RTCIceCandidate(event.candidate),
        onAddIceCandidateSuccess, onAddIceCandidateError);
    trace('Remote ICE candidate: \n ' + event.candidate.candidate);
  }
}

function onAddIceCandidateSuccess() {
  trace('AddIceCandidate success.');
}

function onAddIceCandidateError(error) {
  trace('Failed to add ICE Candidate: ' + error.toString());
}

function onSetSessionDescriptionError(error) {
  trace('Failed to set session description: ' + error.toString());
}

function forceChosenAudioCodec(sdp) {
  return maybePreferCodec(sdp, 'audio', 'send', codecSelector.value);
}

// Copied from AppRTC's sdputils.js:

// Sets |codec| as the default |type| codec if it's present.
// The format of |codec| is 'NAME/RATE', e.g. 'opus/48000'.
function maybePreferCodec(sdp, type, dir, codec) {
  var str = type + ' ' + dir + ' codec';
  if (codec === '') {
    trace('No preference on ' + str + '.');
    return sdp;
  }

  trace('Prefer ' + str + ': ' + codec);

  var sdpLines = sdp.split('\r\n');

  // Search for m line.
  var mLineIndex = findLine(sdpLines, 'm=', type);
  if (mLineIndex === null) {
    return sdp;
  }

  // If the codec is available, set it as the default in m line.
  var codecIndex = findLine(sdpLines, 'a=rtpmap', codec);
  console.log('codecIndex', codecIndex);
  if (codecIndex) {
    var payload = getCodecPayloadType(sdpLines[codecIndex]);
    if (payload) {
      sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], payload);
    }
  }

  sdp = sdpLines.join('\r\n');
  return sdp;
}

// Find the line in sdpLines that starts with |prefix|, and, if specified,
// contains |substr| (case-insensitive search).
function findLine(sdpLines, prefix, substr) {
  return findLineInRange(sdpLines, 0, -1, prefix, substr);
}

// Find the line in sdpLines[startLine...endLine - 1] that starts with |prefix|
// and, if specified, contains |substr| (case-insensitive search).
function findLineInRange(sdpLines, startLine, endLine, prefix, substr) {
  var realEndLine = endLine !== -1 ? endLine : sdpLines.length;
  for (var i = startLine; i < realEndLine; ++i) {
    if (sdpLines[i].indexOf(prefix) === 0) {
      if (!substr ||
          sdpLines[i].toLowerCase().indexOf(substr.toLowerCase()) !== -1) {
        return i;
      }
    }
  }
  return null;
}

// Gets the codec payload type from an a=rtpmap:X line.
function getCodecPayloadType(sdpLine) {
  var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
  var result = sdpLine.match(pattern);
  return (result && result.length === 2) ? result[1] : null;
}

// Returns a new m= line with the specified codec as the first one.
function setDefaultCodec(mLine, payload) {
  var elements = mLine.split(' ');

  // Just copy the first three parameters; codec order starts on fourth.
  var newLine = elements.slice(0, 3);

  // Put target payload first and copy in the rest.
  newLine.push(payload);
  for (var i = 3; i < elements.length; i++) {
    if (elements[i] !== payload) {
      newLine.push(elements[i]);
    }
  }
  return newLine.join(' ');
}

function gotStats(res) {
  Object.keys(res).forEach(function(key) {
    var report = res[key];
    var bytes;
    var packets;
    var now = report.timestamp;
    if ((report.type === 'outboundrtp') ||
        (report.type === 'outbound-rtp') ||
        (report.type === 'ssrc' && report.bytesSent)) {
      bytes = report.bytesSent;
      packets = report.packetsSent;
      if (lastResult && lastResult[report.id]) {
        // calculate bitrate
        var bitrate = 8 * (bytes - lastResult[report.id].bytesSent) /
            (now - lastResult[report.id].timestamp);

        // append to chart
        bitrateSeries.addPoint(now, bitrate);
        bitrateGraph.setDataSeries([bitrateSeries]);
        bitrateGraph.updateEndDate();

        // calculate number of packets and append to chart
        packetSeries.addPoint(now, packets -
            lastResult[report.id].packetsSent);
        packetGraph.setDataSeries([packetSeries]);
        packetGraph.updateEndDate();
      }
    }
  });
  lastResult = res;
}

// query getStats every second
window.setInterval(function() {
  if (!window.pc1) {
    return;
  }
  window.pc1.getStats(null, gotStats, function(){});
}, 1000);
<commit_msg>No video on audio-only calls…<commit_after>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */
/* global TimelineDataSeries, TimelineGraphView */

'use strict';

var audio2 = document.querySelector('audio#audio2');
var callButton = document.querySelector('button#callButton');
var hangupButton = document.querySelector('button#hangupButton');
var codecSelector = document.querySelector('select#codec');
hangupButton.disabled = true;
callButton.onclick = call;
hangupButton.onclick = hangup;

var pc1;
var pc2;
var localStream;

var bitrateGraph;
var bitrateSeries;

var packetGraph;
var packetSeries;

var lastResult;

var offerOptions = {
  offerToReceiveAudio: 1,
  offerToReceiveVideo: 0,
  voiceActivityDetection: false
};

function gotStream(stream) {
  hangupButton.disabled = false;
  trace('Received local stream');
  localStream = stream;
  var audioTracks = localStream.getAudioTracks();
  if (audioTracks.length > 0) {
    trace('Using Audio device: ' + audioTracks[0].label);
  }
  pc1.addStream(localStream);
  trace('Adding Local Stream to peer connection');

  pc1.createOffer(gotDescription1, onCreateSessionDescriptionError,
      offerOptions);

  bitrateSeries = new TimelineDataSeries();
  bitrateGraph = new TimelineGraphView('bitrateGraph', 'bitrateCanvas');
  bitrateGraph.updateEndDate();

  packetSeries = new TimelineDataSeries();
  packetGraph = new TimelineGraphView('packetGraph', 'packetCanvas');
  packetGraph.updateEndDate();
}

function onCreateSessionDescriptionError(error) {
  trace('Failed to create session description: ' + error.toString());
}

function gumFailed(e) {
  alert('getUserMedia() error: ' + e.name);
}

function call() {
  callButton.disabled = true;
  codecSelector.disabled = true;
  trace('Starting call');
  var servers = null;
  var pcConstraints = {
    'optional': []
  };
  pc1 = new RTCPeerConnection(servers, pcConstraints);
  trace('Created local peer connection object pc1');
  pc1.onicecandidate = iceCallback1;
  pc2 = new RTCPeerConnection(servers, pcConstraints);
  trace('Created remote peer connection object pc2');
  pc2.onicecandidate = iceCallback2;
  pc2.onaddstream = gotRemoteStream;
  trace('Requesting local stream');

  var constraints = {
    audio: true,
    video: false
  };
  if (typeof Promise === 'undefined') {
    navigator.getUserMedia(constraints, gotStream, gumFailed);
  } else {
    navigator.mediaDevices.getUserMedia(constraints)
    .then(gotStream)
    .catch(gumFailed);
  }
}

function gotDescription1(desc) {
  desc.sdp = forceChosenAudioCodec(desc.sdp);
  trace('Offer from pc1 \n' + desc.sdp);
  pc1.setLocalDescription(desc, function() {
    pc2.setRemoteDescription(desc, function() {
      // Since the 'remote' side has no media stream we need
      // to pass in the right constraints in order for it to
      // accept the incoming offer of audio.
      pc2.createAnswer(gotDescription2, onCreateSessionDescriptionError);
    }, onSetSessionDescriptionError);
  }, onSetSessionDescriptionError);
}

function gotDescription2(desc) {
  desc.sdp = forceChosenAudioCodec(desc.sdp);
  pc2.setLocalDescription(desc, function() {
    trace('Answer from pc2 \n' + desc.sdp);
    pc1.setRemoteDescription(desc, function() {
    }, onSetSessionDescriptionError);
  }, onSetSessionDescriptionError);
}

function hangup() {
  trace('Ending call');
  localStream.getTracks().forEach(function(track) {
    track.stop();
  });
  pc1.close();
  pc2.close();
  pc1 = null;
  pc2 = null;
  hangupButton.disabled = true;
  callButton.disabled = false;
  codecSelector.disabled = false;
}

function gotRemoteStream(e) {
  audio2 = attachMediaStream(audio2, e.stream);
  trace('Received remote stream');
}

function iceCallback1(event) {
  if (event.candidate) {
    pc2.addIceCandidate(new RTCIceCandidate(event.candidate),
        onAddIceCandidateSuccess, onAddIceCandidateError);
    trace('Local ICE candidate: \n' + event.candidate.candidate);
  }
}

function iceCallback2(event) {
  if (event.candidate) {
    pc1.addIceCandidate(new RTCIceCandidate(event.candidate),
        onAddIceCandidateSuccess, onAddIceCandidateError);
    trace('Remote ICE candidate: \n ' + event.candidate.candidate);
  }
}

function onAddIceCandidateSuccess() {
  trace('AddIceCandidate success.');
}

function onAddIceCandidateError(error) {
  trace('Failed to add ICE Candidate: ' + error.toString());
}

function onSetSessionDescriptionError(error) {
  trace('Failed to set session description: ' + error.toString());
}

function forceChosenAudioCodec(sdp) {
  return maybePreferCodec(sdp, 'audio', 'send', codecSelector.value);
}

// Copied from AppRTC's sdputils.js:

// Sets |codec| as the default |type| codec if it's present.
// The format of |codec| is 'NAME/RATE', e.g. 'opus/48000'.
function maybePreferCodec(sdp, type, dir, codec) {
  var str = type + ' ' + dir + ' codec';
  if (codec === '') {
    trace('No preference on ' + str + '.');
    return sdp;
  }

  trace('Prefer ' + str + ': ' + codec);

  var sdpLines = sdp.split('\r\n');

  // Search for m line.
  var mLineIndex = findLine(sdpLines, 'm=', type);
  if (mLineIndex === null) {
    return sdp;
  }

  // If the codec is available, set it as the default in m line.
  var codecIndex = findLine(sdpLines, 'a=rtpmap', codec);
  console.log('codecIndex', codecIndex);
  if (codecIndex) {
    var payload = getCodecPayloadType(sdpLines[codecIndex]);
    if (payload) {
      sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], payload);
    }
  }

  sdp = sdpLines.join('\r\n');
  return sdp;
}

// Find the line in sdpLines that starts with |prefix|, and, if specified,
// contains |substr| (case-insensitive search).
function findLine(sdpLines, prefix, substr) {
  return findLineInRange(sdpLines, 0, -1, prefix, substr);
}

// Find the line in sdpLines[startLine...endLine - 1] that starts with |prefix|
// and, if specified, contains |substr| (case-insensitive search).
function findLineInRange(sdpLines, startLine, endLine, prefix, substr) {
  var realEndLine = endLine !== -1 ? endLine : sdpLines.length;
  for (var i = startLine; i < realEndLine; ++i) {
    if (sdpLines[i].indexOf(prefix) === 0) {
      if (!substr ||
          sdpLines[i].toLowerCase().indexOf(substr.toLowerCase()) !== -1) {
        return i;
      }
    }
  }
  return null;
}

// Gets the codec payload type from an a=rtpmap:X line.
function getCodecPayloadType(sdpLine) {
  var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
  var result = sdpLine.match(pattern);
  return (result && result.length === 2) ? result[1] : null;
}

// Returns a new m= line with the specified codec as the first one.
function setDefaultCodec(mLine, payload) {
  var elements = mLine.split(' ');

  // Just copy the first three parameters; codec order starts on fourth.
  var newLine = elements.slice(0, 3);

  // Put target payload first and copy in the rest.
  newLine.push(payload);
  for (var i = 3; i < elements.length; i++) {
    if (elements[i] !== payload) {
      newLine.push(elements[i]);
    }
  }
  return newLine.join(' ');
}

function gotStats(res) {
  Object.keys(res).forEach(function(key) {
    var report = res[key];
    var bytes;
    var packets;
    var now = report.timestamp;
    if ((report.type === 'outboundrtp') ||
        (report.type === 'outbound-rtp') ||
        (report.type === 'ssrc' && report.bytesSent)) {
      bytes = report.bytesSent;
      packets = report.packetsSent;
      if (lastResult && lastResult[report.id]) {
        // calculate bitrate
        var bitrate = 8 * (bytes - lastResult[report.id].bytesSent) /
            (now - lastResult[report.id].timestamp);

        // append to chart
        bitrateSeries.addPoint(now, bitrate);
        bitrateGraph.setDataSeries([bitrateSeries]);
        bitrateGraph.updateEndDate();

        // calculate number of packets and append to chart
        packetSeries.addPoint(now, packets -
            lastResult[report.id].packetsSent);
        packetGraph.setDataSeries([packetSeries]);
        packetGraph.updateEndDate();
      }
    }
  });
  lastResult = res;
}

// query getStats every second
window.setInterval(function() {
  if (!window.pc1) {
    return;
  }
  window.pc1.getStats(null, gotStats, function(){});
}, 1000);
<|endoftext|>


<commit_before>import * as React from "react";

/**
 * Component used as an indicator for build status.
 * Statuses are differentiated by alternative
 * styling rules.
 * @param props.status the build status. Partially determines
 * the styling of the rules.
 */
const StatusIndicator = (props) => {
  const className = 'indicator #'.replace('#', props.status);
  return (

  );
}

/**
 * Component used to display information for a builder.
 * @param props.status the build status of the bot.
 * @param props.name the name of the bot.
 */
const Builder = (props) => {
  return (
    <button className='builder' onClick={props.onClick}>
      <StatusIndicator status={props.status}/>
      {props.name}
    </button>
  );
}

/**
 * Component used to display the list of builders that built a commit.
 *
 * @param props.builders
 * @param props.builders[].builder.status
 * @param props.builders[].builder.name
 */
export const BuilderGrid = (props) => {
  return (

      {props.builders.map((b, idx) => <Builder status={b.status} name={b.name} onClick={props.onClick.bind(this, idx)}/>)}

  );
}<commit_msg>Use builder index as key for component instances<commit_after>import * as React from "react";

/**
 * Component used as an indicator for build status.
 * Statuses are differentiated by alternative
 * styling rules.
 * @param props.status the build status. Partially determines
 * the styling of the rules.
 */
const StatusIndicator = (props) => {
  const className = 'indicator #'.replace('#', props.status);
  return (

  );
}

/**
 * Component used to display information for a builder.
 * @param props.status the build status of the bot.
 * @param props.name the name of the bot.
 */
const Builder = (props) => {
  return (
    <button className='builder' onClick={props.onClick}>
      <StatusIndicator status={props.status}/>
      {props.name}
    </button>
  );
}

/**
 * Component used to display the list of builders that built a commit.
 *
 * @param props.builders
 * @param props.builders[].builder.status
 * @param props.builders[].builder.name
 */
export const BuilderGrid = (props) => {
  return (

      {props.builders.map((b, idx) => <Builder key={idx} status={b.status} name={b.name} onClick={props.onClick.bind(this, idx)}/>)}

  );
}<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import { FormattedTime } from 'react-intl';
import { secondsToTimeString } from '../_utils/DateUtils';
import { NumberColored, NumberPlain, Modal } from '../_common';
import ContractSoldDetails from './ContractSoldDetails';

const returnOnContract = (contract, proposal) => (proposal.bid_price - contract.buy_price) * 100 / contract.buy_price;
const ContractDetailsCard = ({ contract, proposal, nowEpoch, soldResultShown, actions }) => (

		<Modal shown={!!soldResultShown} onClose={actions.closeSoldResult}>
			<ContractSoldDetails
				buyPrice={contract.buy_price}
				soldPrice={soldResultShown && soldResultShown.soldPrice}
				transID={soldResultShown && soldResultShown.transId}
			/>
		</Modal>

					Start Time
					Current Spot Time
					End Time

					{proposal && <FormattedTime value={proposal.date_start * 1000} format="full" />}
					{proposal && <FormattedTime value={window.parseInt(proposal.current_spot_time) * 1000} format="full" />}
					{proposal && <FormattedTime value={proposal.date_expiry * 1000} format="full" />}

						{proposal && secondsToTimeString(nowEpoch - proposal.date_start)}

					{proposal && secondsToTimeString(proposal.date_expiry - nowEpoch)}

					Entry Spot
					Current Spot
					Exit Spot

					{proposal && proposal.entry_spot}
					{proposal && <NumberColored value={proposal.current_spot} isProfit={v => v - proposal.entry_spot}/>}
					{proposal && (proposal.exit_spot || '-')}

					Purchase Price
					Indicative Price
					Final Price

					<NumberPlain value={contract.buy_price} currency={contract.currency}/>

						{proposal &&
						<NumberColored
						value={proposal.bid_price}
						currency={contract.currency}
						isProfit={v => v - contract.buy_price}
						/>}

					{contract.final_price ? <NumberPlain value={contract.final_price} currency={contract.currency}/> : '-'}

					{proposal && <NumberColored value={returnOnContract(contract, proposal).toFixed(2)} />}%

					Description

					{contract.longcode}

		{proposal && (proposal.is_valid_to_sell === 1) ?
		<button onClick={() => actions.sellContract(contract.contract_id, 0)}>Sell</button> :

{proposal && proposal.validation_error}
}

);

ContractDetailsCard.propTypes = {
	contract: PropTypes.object,
	proposal: PropTypes.object,
	nowEpoch: PropTypes.number,
	soldResultShown: PropTypes.object,
	actions: PropTypes.object,
};

export default ContractDetailsCard;
<commit_msg>Show market price as manual sell will rely on market price<commit_after>import React, { PropTypes } from 'react';
import { FormattedTime } from 'react-intl';
import { secondsToTimeString } from '../_utils/DateUtils';
import { NumberColored, NumberPlain, Modal, LabeledText } from '../_common';
import ContractSoldDetails from './ContractSoldDetails';

const returnOnContract = (contract, proposal) => (proposal.bid_price - contract.buy_price) * 100 / contract.buy_price;
const ContractDetailsCard = ({ contract, proposal, nowEpoch, soldResultShown, actions }) => (

		<Modal shown={!!soldResultShown} onClose={actions.closeSoldResult}>
			<ContractSoldDetails
				buyPrice={contract.buy_price}
				soldPrice={soldResultShown && soldResultShown.soldPrice}
				transID={soldResultShown && soldResultShown.transId}
			/>
		</Modal>

					Start Time
					Current Spot Time
					End Time

					{proposal && <FormattedTime value={proposal.date_start * 1000} format="full" />}
					{proposal && <FormattedTime value={window.parseInt(proposal.current_spot_time) * 1000} format="full" />}
					{proposal && <FormattedTime value={proposal.date_expiry * 1000} format="full" />}

						{proposal && secondsToTimeString(nowEpoch - proposal.date_start)}

					{proposal && secondsToTimeString(proposal.date_expiry - nowEpoch)}

					Entry Spot
					Current Spot
					Exit Spot

					{proposal && proposal.entry_spot}
					{proposal && <NumberColored value={proposal.current_spot} isProfit={v => v - proposal.entry_spot}/>}
					{proposal && (proposal.exit_spot || '-')}

					Purchase Price
					Indicative Price
					Final Price

					<NumberPlain value={contract.buy_price} currency={contract.currency}/>

						{proposal &&
						<NumberColored
						value={proposal.bid_price}
						currency={contract.currency}
						isProfit={v => v - contract.buy_price}
						/>}

					{contract.final_price ? <NumberPlain value={contract.final_price} currency={contract.currency}/> : '-'}

					{proposal && <NumberColored value={returnOnContract(contract, proposal).toFixed(2)} />}%

					Description

					{contract.longcode}

		{proposal && (proposal.is_valid_to_sell === 1) ?

			<LabeledText id="market-price" label="Market Price" value={proposal.bid_price}/>
			<button onClick={() => actions.sellContract(contract.contract_id, 0)}>Sell on market</button>

 :

{proposal && proposal.validation_error}
}

);

ContractDetailsCard.propTypes = {
	contract: PropTypes.object,
	proposal: PropTypes.object,
	nowEpoch: PropTypes.number,
	soldResultShown: PropTypes.object,
	actions: PropTypes.object,
};

export default ContractDetailsCard;
<|endoftext|>