<commit_before>var propertyMethodAssignment = require("./es6-property-method-assignment");
var traverse                 = require("../../traverse");
var util                     = require("../../util");
var t                        = require("../../types");

exports.ClassDeclaration = function (node, parent, file, scope) {
  return new Class(node, file, scope, true).run();
};

exports.ClassExpression = function (node, parent, file, scope) {
  if (!node.id) {
    if (t.isProperty(parent) && parent.value === node && !parent.computed && t.isIdentifier(parent.key)) {
      // var o = { foo: class {} };
      node.id = parent.key
    }

    if (t.isVariableDeclarator(parent)) {
      node.id = parent.id;
    }
  }

  return new Class(node, file, scope, false).run();
};

/**
 * Description
 *
 * @param {Node} node
 * @param {File} file
 * @param {Scope} scope
 * @param {Boolean} closure
 */

function Class(node, file, scope, isStatement) {
  this.isStatement = isStatement;
  this.scope       = scope;
  this.node        = node;
  this.file        = file;

  this.hasInstanceMutators = false;
  this.hasStaticMutators   = false;

  this.instanceMutatorMap = {};
  this.staticMutatorMap   = {};
  this.hasConstructor     = false;
  this.className          = node.id || file.generateUidIdentifier("class", scope);
  this.superName          = node.superClass;
  this.isLoose            = file.isLoose("classes");
}

/**
 * Description
 *
 * @returns {Array}
 */

Class.prototype.run = function () {
  var superName = this.superName;
  var className = this.className;
  var file      = this.file;

  //

  var body = this.body = [];

  var constructor;
  if (this.node.id) {
    constructor = t.functionDeclaration(className, [], t.blockStatement([]));
    body.push(constructor);
  } else {
    constructor = t.functionExpression(null, [], t.blockStatement([]));
    body.push(t.variableDeclaration("var", [
      t.variableDeclarator(className, constructor)
    ]));
  }
  this.constructor = constructor;

  var closureParams = [];
  var closureArgs = [];

  //

  if (superName) {
    closureArgs.push(superName);

    if (!t.isIdentifier(superName)) {
      var superRef = this.scope.generateUidBasedOnNode(superName, this.file);
      superName = superRef;
    }

    closureParams.push(superName);

    this.superName = superName;
    body.push(t.expressionStatement(t.callExpression(file.addHelper("inherits"), [className, superName])));
  }

  this.buildBody();

  t.inheritsComments(body[0], this.node);

  var init;

  if (body.length === 1) {
    // only a constructor so no need for a closure container
    init = t.toExpression(constructor);
  } else {
    body.push(t.returnStatement(className));
    init = t.callExpression(
      t.functionExpression(null, closureParams, t.blockStatement(body)),
      closureArgs
    );
  }

  if (this.isStatement) {
    return t.variableDeclaration("let", [
      t.variableDeclarator(className, init)
    ]);
  } else {
    return init;
  }
};

/**
 * Description
 */

Class.prototype.buildBody = function () {
  var constructor = this.constructor;
  var className   = this.className;
  var superName   = this.superName;
  var classBody   = this.node.body.body;
  var body        = this.body;

  for (var i in classBody) {
    var node = classBody[i];
    if (t.isMethodDefinition(node)) {
      this.replaceInstanceSuperReferences(node);

      if (node.key.name === "constructor") {
        this.pushConstructor(node);
      } else {
        this.pushMethod(node);
      }
    } else if (t.isPrivateDeclaration(node)) {
      this.closure = true;
      body.unshift(node);
    }
  }

  // we have no constructor, we have a super, and the super doesn't appear to be falsy
  if (!this.hasConstructor && superName && !t.isFalsyExpression(superName)) {
    var defaultConstructorTemplate = "class-super-constructor-call";
    if (this.isLoose) defaultConstructorTemplate += "-loose";

    constructor.body.body.push(util.template(defaultConstructorTemplate, {
      CLASS_NAME: className,
      SUPER_NAME: this.superName
    }, true));
  }

  var instanceProps;
  var staticProps;

  if (this.hasInstanceMutators) {
    instanceProps = util.buildDefineProperties(this.instanceMutatorMap);
  }

  if (this.hasStaticMutators) {
    staticProps = util.buildDefineProperties(this.staticMutatorMap);
  }

  if (instanceProps || staticProps) {
    staticProps = staticProps || t.literal(null);

    var args = [className, staticProps];
    if (instanceProps) args.push(instanceProps);

    body.push(t.expressionStatement(
      t.callExpression(this.file.addHelper("prototype-properties"), args)
    ));
  }
};

/**
 * Push a method to it's respective mutatorMap.
 *
 * @param {Node} node MethodDefinition
 */

Class.prototype.pushMethod = function (node) {
  var methodName = node.key;

  var kind = node.kind;

  if (kind === "") {
    propertyMethodAssignment._namedMethod(node, this.file, this.scope);

    if (this.isLoose) {
      // use assignments instead of define properties for loose classes

      var className = this.className;
      if (!node.static) className = t.memberExpression(className, t.identifier("prototype"));
      methodName = t.memberExpression(className, methodName, node.computed);

      var expr = t.expressionStatement(t.assignmentExpression("=", methodName, node.value));
      t.inheritsComments(expr, node);
      this.body.push(expr);
      return;
    }

    kind = "value";
  }

  var mutatorMap = this.instanceMutatorMap;
  if (node.static) {
    this.hasStaticMutators = true;
    mutatorMap = this.staticMutatorMap;
  } else {
    this.hasInstanceMutators = true;
  }

  util.pushMutatorMap(mutatorMap, methodName, kind, node.computed, node);
};

/**
 * Gets a node representing the super class value of the named property.
 *
 * @example
 *
 *   _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
 *
 * @param {Node} property
 * @param {boolean} isStatic
 * @param {boolean} isComputed
 *
 * @returns {Node}
 */

Class.prototype.superProperty = function (property, isStatic, isComputed, thisExpression) {
  return t.callExpression(
    this.file.addHelper("get"),
    [
      t.callExpression(
        t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
        [
          isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
        ]
      ),
      isComputed ? property : t.literal(property.name),
      thisExpression
    ]
  );
};

/**
 * Description
 *
 * @param {Object} node
 * @param {Object} id
 * @param {Object} parent
 * @returns {Object}
 */

Class.prototype.looseSuperProperty = function (methodNode, id, parent) {
  var methodName = methodNode.key;
  var superName  = this.superName || t.identifier("Function");

  if (parent.property === id) {
    return;
  } else if (t.isCallExpression(parent, { callee: id })) {
    // super(); -> ClassName.prototype.MethodName.call(this);
    parent.arguments.unshift(t.thisExpression());

    if (methodName.name === "constructor") {
      // constructor() { super(); }
      return t.memberExpression(superName, t.identifier("call"));
    } else {
      id = superName;

      // foo() { super(); }
      if (!methodNode.static) {
        id = t.memberExpression(id, t.identifier("prototype"));
      }

      id = t.memberExpression(id, methodName, methodNode.computed);
      return t.memberExpression(id, t.identifier("call"));
    }
  } else if (t.isMemberExpression(parent) && !methodNode.static) {
    // super.test -> ClassName.prototype.test
    return t.memberExpression(superName, t.identifier("prototype"));
  } else {
    return superName;
  }
};

/**
 * Replace all `super` references with a reference to our `superClass`.
 *
 * @param {Node} methodNode MethodDefinition
 */

Class.prototype.replaceInstanceSuperReferences = function (methodNode) {
  var method = methodNode.value;
  var self   = this;

  var topLevelThisReference;

  traverseLevel(method, true);

  if (topLevelThisReference) {
    method.body.body.unshift(t.variableDeclaration("var", [
      t.variableDeclarator(topLevelThisReference, t.thisExpression())
    ]));
  }

  function traverseLevel(node, topLevel) {
    traverse(node, {
      enter: function (node, parent) {
        if (t.isFunction(node) && !t.isArrowFunctionExpression(node)) {
          // we need to call traverseLevel again so we're context aware
          traverseLevel(node, false);
          return this.skip();
        }

        var getThisReference = function () {
          if (topLevel) {
            // top level so `this` is the instance
            return t.thisExpression();
          } else {
            // not in the top level so we need to create a reference
            return topLevelThisReference = topLevelThisReference || self.file.generateUidIdentifier("this");
          }
        };

        var callback = specHandle;
        if (self.isLoose) callback = looseHandle;
        return callback(getThisReference, node, parent);
      }
    });
  }

  function looseHandle(getThisReference, node, parent) {
    if (t.isIdentifier(node, { name: "super" })) {
      return self.looseSuperProperty(methodNode, node, parent);
    } else if (t.isCallExpression(node)) {
      var callee = node.callee;
      if (!t.isMemberExpression(callee)) return;
      if (callee.object.name !== "super") return;

      // super.test(); -> ClassName.prototype.MethodName.call(this);
      t.appendToMemberExpression(callee, t.identifier("call"));
      node.arguments.unshift(getThisReference());
    }
  }

  function specHandle(getThisReference, node, parent) {
    var property;
    var computed;
    var args;

    if (t.isIdentifier(node, { name: "super" })) {
      if (!(t.isMemberExpression(parent) && !parent.computed && parent.property === node)) {
        throw self.file.errorWithNode(node, "illegal use of bare super");
      }
    } else if (t.isCallExpression(node)) {
      var callee = node.callee;
      if (t.isIdentifier(callee, { name: "super" })) {
        // super(); -> _get(Object.getPrototypeOf(ClassName), "MethodName", this).call(this);
        property = methodNode.key;
        computed = methodNode.computed;
        args = node.arguments;
      } else {
        if (!t.isMemberExpression(callee)) return;
        if (callee.object.name !== "super") return;

        // super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this);
        property = callee.property;
        computed = callee.computed;
        args = node.arguments;
      }
    } else if (t.isMemberExpression(node)) {
      if (!t.isIdentifier(node.object, { name: "super" })) return;

      // super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this);
      property = node.property;
      computed = node.computed;
    }

    if (!property) return;

    var thisReference = getThisReference();
    var superProperty = self.superProperty(property, methodNode.static, computed, thisReference);
    if (args) {
      if (args.length === 1 && t.isSpreadElement(args[0])) {
        // super(...arguments);
        return t.callExpression(
          t.memberExpression(superProperty, t.identifier("apply")),
          [thisReference, args[0].argument]
        );
      } else {
        return t.callExpression(
          t.memberExpression(superProperty, t.identifier("call")),
          [thisReference].concat(args)
        );
      }
    } else {
      return superProperty;
    }
  }
};

/**
 * Replace the constructor body of our class.
 *
 * @param {Node} method MethodDefinition
 */

Class.prototype.pushConstructor = function (method) {
  if (method.kind) {
    throw this.file.errorWithNode(method, "illegal kind for constructor method");
  }

  var construct = this.constructor;
  var fn        = method.value;

  this.hasConstructor = true;

  t.inherits(construct, fn);
  t.inheritsComments(construct, method);

  construct._ignoreUserWhitespace = true;
  construct.defaults              = fn.defaults;
  construct.params                = fn.params;
  construct.body                  = fn.body;
  construct.rest                  = fn.rest;
};
<commit_msg>add missing semicolon<commit_after>var propertyMethodAssignment = require("./es6-property-method-assignment");
var traverse                 = require("../../traverse");
var util                     = require("../../util");
var t                        = require("../../types");

exports.ClassDeclaration = function (node, parent, file, scope) {
  return new Class(node, file, scope, true).run();
};

exports.ClassExpression = function (node, parent, file, scope) {
  if (!node.id) {
    if (t.isProperty(parent) && parent.value === node && !parent.computed && t.isIdentifier(parent.key)) {
      // var o = { foo: class {} };
      node.id = parent.key;
    }

    if (t.isVariableDeclarator(parent)) {
      node.id = parent.id;
    }
  }

  return new Class(node, file, scope, false).run();
};

/**
 * Description
 *
 * @param {Node} node
 * @param {File} file
 * @param {Scope} scope
 * @param {Boolean} closure
 */

function Class(node, file, scope, isStatement) {
  this.isStatement = isStatement;
  this.scope       = scope;
  this.node        = node;
  this.file        = file;

  this.hasInstanceMutators = false;
  this.hasStaticMutators   = false;

  this.instanceMutatorMap = {};
  this.staticMutatorMap   = {};
  this.hasConstructor     = false;
  this.className          = node.id || file.generateUidIdentifier("class", scope);
  this.superName          = node.superClass;
  this.isLoose            = file.isLoose("classes");
}

/**
 * Description
 *
 * @returns {Array}
 */

Class.prototype.run = function () {
  var superName = this.superName;
  var className = this.className;
  var file      = this.file;

  //

  var body = this.body = [];

  var constructor;
  if (this.node.id) {
    constructor = t.functionDeclaration(className, [], t.blockStatement([]));
    body.push(constructor);
  } else {
    constructor = t.functionExpression(null, [], t.blockStatement([]));
    body.push(t.variableDeclaration("var", [
      t.variableDeclarator(className, constructor)
    ]));
  }
  this.constructor = constructor;

  var closureParams = [];
  var closureArgs = [];

  //

  if (superName) {
    closureArgs.push(superName);

    if (!t.isIdentifier(superName)) {
      var superRef = this.scope.generateUidBasedOnNode(superName, this.file);
      superName = superRef;
    }

    closureParams.push(superName);

    this.superName = superName;
    body.push(t.expressionStatement(t.callExpression(file.addHelper("inherits"), [className, superName])));
  }

  this.buildBody();

  t.inheritsComments(body[0], this.node);

  var init;

  if (body.length === 1) {
    // only a constructor so no need for a closure container
    init = t.toExpression(constructor);
  } else {
    body.push(t.returnStatement(className));
    init = t.callExpression(
      t.functionExpression(null, closureParams, t.blockStatement(body)),
      closureArgs
    );
  }

  if (this.isStatement) {
    return t.variableDeclaration("let", [
      t.variableDeclarator(className, init)
    ]);
  } else {
    return init;
  }
};

/**
 * Description
 */

Class.prototype.buildBody = function () {
  var constructor = this.constructor;
  var className   = this.className;
  var superName   = this.superName;
  var classBody   = this.node.body.body;
  var body        = this.body;

  for (var i in classBody) {
    var node = classBody[i];
    if (t.isMethodDefinition(node)) {
      this.replaceInstanceSuperReferences(node);

      if (node.key.name === "constructor") {
        this.pushConstructor(node);
      } else {
        this.pushMethod(node);
      }
    } else if (t.isPrivateDeclaration(node)) {
      this.closure = true;
      body.unshift(node);
    }
  }

  // we have no constructor, we have a super, and the super doesn't appear to be falsy
  if (!this.hasConstructor && superName && !t.isFalsyExpression(superName)) {
    var defaultConstructorTemplate = "class-super-constructor-call";
    if (this.isLoose) defaultConstructorTemplate += "-loose";

    constructor.body.body.push(util.template(defaultConstructorTemplate, {
      CLASS_NAME: className,
      SUPER_NAME: this.superName
    }, true));
  }

  var instanceProps;
  var staticProps;

  if (this.hasInstanceMutators) {
    instanceProps = util.buildDefineProperties(this.instanceMutatorMap);
  }

  if (this.hasStaticMutators) {
    staticProps = util.buildDefineProperties(this.staticMutatorMap);
  }

  if (instanceProps || staticProps) {
    staticProps = staticProps || t.literal(null);

    var args = [className, staticProps];
    if (instanceProps) args.push(instanceProps);

    body.push(t.expressionStatement(
      t.callExpression(this.file.addHelper("prototype-properties"), args)
    ));
  }
};

/**
 * Push a method to it's respective mutatorMap.
 *
 * @param {Node} node MethodDefinition
 */

Class.prototype.pushMethod = function (node) {
  var methodName = node.key;

  var kind = node.kind;

  if (kind === "") {
    propertyMethodAssignment._namedMethod(node, this.file, this.scope);

    if (this.isLoose) {
      // use assignments instead of define properties for loose classes

      var className = this.className;
      if (!node.static) className = t.memberExpression(className, t.identifier("prototype"));
      methodName = t.memberExpression(className, methodName, node.computed);

      var expr = t.expressionStatement(t.assignmentExpression("=", methodName, node.value));
      t.inheritsComments(expr, node);
      this.body.push(expr);
      return;
    }

    kind = "value";
  }

  var mutatorMap = this.instanceMutatorMap;
  if (node.static) {
    this.hasStaticMutators = true;
    mutatorMap = this.staticMutatorMap;
  } else {
    this.hasInstanceMutators = true;
  }

  util.pushMutatorMap(mutatorMap, methodName, kind, node.computed, node);
};

/**
 * Gets a node representing the super class value of the named property.
 *
 * @example
 *
 *   _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
 *
 * @param {Node} property
 * @param {boolean} isStatic
 * @param {boolean} isComputed
 *
 * @returns {Node}
 */

Class.prototype.superProperty = function (property, isStatic, isComputed, thisExpression) {
  return t.callExpression(
    this.file.addHelper("get"),
    [
      t.callExpression(
        t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
        [
          isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
        ]
      ),
      isComputed ? property : t.literal(property.name),
      thisExpression
    ]
  );
};

/**
 * Description
 *
 * @param {Object} node
 * @param {Object} id
 * @param {Object} parent
 * @returns {Object}
 */

Class.prototype.looseSuperProperty = function (methodNode, id, parent) {
  var methodName = methodNode.key;
  var superName  = this.superName || t.identifier("Function");

  if (parent.property === id) {
    return;
  } else if (t.isCallExpression(parent, { callee: id })) {
    // super(); -> ClassName.prototype.MethodName.call(this);
    parent.arguments.unshift(t.thisExpression());

    if (methodName.name === "constructor") {
      // constructor() { super(); }
      return t.memberExpression(superName, t.identifier("call"));
    } else {
      id = superName;

      // foo() { super(); }
      if (!methodNode.static) {
        id = t.memberExpression(id, t.identifier("prototype"));
      }

      id = t.memberExpression(id, methodName, methodNode.computed);
      return t.memberExpression(id, t.identifier("call"));
    }
  } else if (t.isMemberExpression(parent) && !methodNode.static) {
    // super.test -> ClassName.prototype.test
    return t.memberExpression(superName, t.identifier("prototype"));
  } else {
    return superName;
  }
};

/**
 * Replace all `super` references with a reference to our `superClass`.
 *
 * @param {Node} methodNode MethodDefinition
 */

Class.prototype.replaceInstanceSuperReferences = function (methodNode) {
  var method = methodNode.value;
  var self   = this;

  var topLevelThisReference;

  traverseLevel(method, true);

  if (topLevelThisReference) {
    method.body.body.unshift(t.variableDeclaration("var", [
      t.variableDeclarator(topLevelThisReference, t.thisExpression())
    ]));
  }

  function traverseLevel(node, topLevel) {
    traverse(node, {
      enter: function (node, parent) {
        if (t.isFunction(node) && !t.isArrowFunctionExpression(node)) {
          // we need to call traverseLevel again so we're context aware
          traverseLevel(node, false);
          return this.skip();
        }

        var getThisReference = function () {
          if (topLevel) {
            // top level so `this` is the instance
            return t.thisExpression();
          } else {
            // not in the top level so we need to create a reference
            return topLevelThisReference = topLevelThisReference || self.file.generateUidIdentifier("this");
          }
        };

        var callback = specHandle;
        if (self.isLoose) callback = looseHandle;
        return callback(getThisReference, node, parent);
      }
    });
  }

  function looseHandle(getThisReference, node, parent) {
    if (t.isIdentifier(node, { name: "super" })) {
      return self.looseSuperProperty(methodNode, node, parent);
    } else if (t.isCallExpression(node)) {
      var callee = node.callee;
      if (!t.isMemberExpression(callee)) return;
      if (callee.object.name !== "super") return;

      // super.test(); -> ClassName.prototype.MethodName.call(this);
      t.appendToMemberExpression(callee, t.identifier("call"));
      node.arguments.unshift(getThisReference());
    }
  }

  function specHandle(getThisReference, node, parent) {
    var property;
    var computed;
    var args;

    if (t.isIdentifier(node, { name: "super" })) {
      if (!(t.isMemberExpression(parent) && !parent.computed && parent.property === node)) {
        throw self.file.errorWithNode(node, "illegal use of bare super");
      }
    } else if (t.isCallExpression(node)) {
      var callee = node.callee;
      if (t.isIdentifier(callee, { name: "super" })) {
        // super(); -> _get(Object.getPrototypeOf(ClassName), "MethodName", this).call(this);
        property = methodNode.key;
        computed = methodNode.computed;
        args = node.arguments;
      } else {
        if (!t.isMemberExpression(callee)) return;
        if (callee.object.name !== "super") return;

        // super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this);
        property = callee.property;
        computed = callee.computed;
        args = node.arguments;
      }
    } else if (t.isMemberExpression(node)) {
      if (!t.isIdentifier(node.object, { name: "super" })) return;

      // super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this);
      property = node.property;
      computed = node.computed;
    }

    if (!property) return;

    var thisReference = getThisReference();
    var superProperty = self.superProperty(property, methodNode.static, computed, thisReference);
    if (args) {
      if (args.length === 1 && t.isSpreadElement(args[0])) {
        // super(...arguments);
        return t.callExpression(
          t.memberExpression(superProperty, t.identifier("apply")),
          [thisReference, args[0].argument]
        );
      } else {
        return t.callExpression(
          t.memberExpression(superProperty, t.identifier("call")),
          [thisReference].concat(args)
        );
      }
    } else {
      return superProperty;
    }
  }
};

/**
 * Replace the constructor body of our class.
 *
 * @param {Node} method MethodDefinition
 */

Class.prototype.pushConstructor = function (method) {
  if (method.kind) {
    throw this.file.errorWithNode(method, "illegal kind for constructor method");
  }

  var construct = this.constructor;
  var fn        = method.value;

  this.hasConstructor = true;

  t.inherits(construct, fn);
  t.inheritsComments(construct, method);

  construct._ignoreUserWhitespace = true;
  construct.defaults              = fn.defaults;
  construct.params                = fn.params;
  construct.body                  = fn.body;
  construct.rest                  = fn.rest;
};
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap-sprockets
//= require bootstrap
//= require bootstrap-datepicker
//= require select2
//= require_tree .
<commit_msg>changing order in application.js to test dropdown menu<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap
//= require bootstrap-sprockets
//= require bootstrap-datepicker
//= require select2
//= require_tree .
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require jquery.ui.sortable
//= require buckets
<commit_msg>Require bootstrap-sprockets javascript<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require bootstrap-sprockets
//= require turbolinks
//= require jquery.ui.sortable
//= require buckets
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require twitter/bootstrap
//= require dropzone
//= require papaparse.min
//= require_tree .
<commit_msg>remove twitter bootstrap js<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require dropzone
//= require papaparse.min
//= require_tree .
<|endoftext|>


<commit_before>import {
  ChannelResource,
  LearnerGroupResource,
  ContentNodeResource,
  ExamResource,
  ExamLogResource,
  FacilityUserResource,
} from 'kolibri.resources';
import ConditionalPromise from 'kolibri.lib.conditionalPromise';
import router from 'kolibri.coreVue.router';
import {
  handleError,
  handleApiError,
  createSnackbar,
  samePageCheckGenerator,
} from 'kolibri.coreVue.vuex.actions';
import { ContentNodeKinds } from 'kolibri.coreVue.vuex.constants';
import { getExamReport } from 'kolibri.utils.exams';
import { assessmentMetaDataState } from 'kolibri.coreVue.vuex.mappers';
import { createTranslator } from 'kolibri.utils.i18n';
import { PageNames } from '../../constants';
import { setClassState, handleCoachPageError } from './main';

const translator = createTranslator('coachExamPageTitles', {
  allChannels: 'All channels',
  coachExamListPageTitle: 'Exams',
  coachExamCreationPageTitle: 'Create new exam',
  coachExamReportDetailPageTitle: 'Exam Report Detail',
  examReportTitle: '{examTitle} report',
});

const snackbarTranslator = createTranslator('examPageSnackbarTexts', {
  changesToExamSaved: 'Changes to exam saved',
  copiedExamToClass: 'Copied exam to { className }',
  examDeleted: 'Exam deleted',
  examIsNowActive: 'Exam is now active',
  examIsNowInactive: 'Exam is now inactive',
  newExamCreated: 'New exam created',
});

function _currentTopicState(topic, ancestors = []) {
  return {
    id: topic.id,
    title: topic.title,
    breadcrumbs: [
      { id: null, title: translator.$tr('allChannels') },
      ...ancestors,
      { id: topic.id, title: topic.title },
    ],
  };
}

function _exerciseState(exercise) {
  return {
    id: exercise.id,
    title: exercise.title,
    numAssessments: assessmentMetaDataState(exercise).assessmentIds.length,
    num_coach_contents: exercise.num_coach_contents,
  };
}

function _exercisesState(exercises) {
  return exercises.map(exercise => _exerciseState(exercise));
}

function _examState(exam) {
  return {
    id: exam.id,
    title: exam.title,
    channelId: exam.channel_id,
    collection: exam.collection,
    active: exam.active,
    archive: exam.archive,
    questionCount: exam.question_count,
    questionSources: exam.question_sources,
    seed: exam.seed,
    assignments: exam.assignments,
  };
}

function _examsState(exams) {
  return exams.map(exam => _examState(exam));
}

export function _createExam(store, exam) {
  return new Promise((resolve, reject) => {
    ExamResource.createModel(exam)
      .save()
      .then(exam => resolve(exam), error => reject(error));
  });
}

/**
 * EXAMS PAGE
 */

export function showExamsPage(store, classId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXAMS);

  const promises = [
    ExamResource.getCollection({ collection: classId }).fetch({}, true),
    setClassState(store, classId),
  ];

  return ConditionalPromise.all(promises).only(
    samePageCheckGenerator(store),
    ([exams]) => {
      store.dispatch('SET_PAGE_STATE', {
        exams: _examsState(exams),
        examsModalSet: false,
        busy: false,
      });
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('CORE_SET_TITLE', translator.$tr('coachExamListPageTitle'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    },
    error => handleError(store, error)
  );
}

export function setExamsModal(store, modalName) {
  store.dispatch('SET_EXAMS_MODAL', modalName);
}

function updateExamStatus(store, { examId, isActive }) {
  return ExamResource.getModel(examId)
    .save({ active: isActive })
    .then(
      () => {
        store.dispatch('SET_EXAM_STATUS', { examId, isActive });
        setExamsModal(store, false);
        createSnackbar(store, {
          text: snackbarTranslator.$tr(isActive ? 'examIsNowActive' : 'examIsNowInactive'),
          autoDismiss: true,
        });
      },
      error => handleError(store, error)
    );
}

export function activateExam(store, examId) {
  return updateExamStatus(store, { examId, isActive: true });
}

export function deactivateExam(store, examId) {
  return updateExamStatus(store, { examId, isActive: false });
}

export function copyExam(store, exam, className) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _createExam(store, exam).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      setExamsModal(store, false);
      createSnackbar(store, {
        text: snackbarTranslator.$tr('copiedExamToClass', { className }),
        autoDismiss: true,
      });
    },
    error => handleApiError(store, error)
  );
}

export function updateExamDetails(store, examId, payload) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  return new Promise((resolve, reject) => {
    ExamResource.getModel(examId)
      .save(payload)
      .then(
        exam => {
          const exams = store.state.pageState.exams;
          const examIndex = exams.findIndex(exam => exam.id === examId);
          exams[examIndex] = _examState(exam);

          store.dispatch('SET_EXAMS', exams);
          setExamsModal(store, false);
          createSnackbar(store, {
            text: snackbarTranslator.$tr('changesToExamSaved'),
            autoDismiss: true,
          });
          store.dispatch('CORE_SET_PAGE_LOADING', false);
          resolve();
        },
        error => {
          store.dispatch('CORE_SET_PAGE_LOADING', false);
          reject(error);
        }
      );
  });
}

export function deleteExam(store, examId) {
  return ExamResource.getModel(examId)
    .delete()
    .then(
      () => {
        const exams = store.state.pageState.exams;
        const updatedExams = exams.filter(exam => exam.id !== examId);
        store.dispatch('SET_EXAMS', updatedExams);

        router.replace({ name: PageNames.EXAMS });
        createSnackbar(store, {
          text: snackbarTranslator.$tr('examDeleted'),
          autoDismiss: true,
        });
        setExamsModal(store, false);
      },
      error => handleError(store, error)
    );
}

/**
 * EXAM CREATION
 */

export function showCreateExamPage(store, classId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.CREATE_EXAM);
  store.dispatch('CORE_SET_TITLE', translator.$tr('coachExamCreationPageTitle'));
  store.dispatch('SET_PAGE_STATE', {
    topic: {},
    subtopics: [],
    exercises: [],
    selectedExercises: [],
    exerciseContentNodes: [],
    examsModalSet: false,
  });

  const examsPromise = ExamResource.getCollection({
    collection: classId,
  }).fetch({}, true);
  const goToTopLevelPromise = goToTopLevel(store);

  ConditionalPromise.all([examsPromise, setClassState(store, classId), goToTopLevelPromise]).only(
    samePageCheckGenerator(store),
    ([exams]) => {
      store.dispatch('SET_EXAMS', exams);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    },
    error => handleError(store, error)
  );
}

// TODO: Optimize
export function goToTopLevel(store) {
  return new Promise((resolve, reject) => {
    const channelPromise = ChannelResource.getCollection({
      available: true,
      has_exercise: true,
    }).fetch();

    ConditionalPromise.all([channelPromise]).only(
      samePageCheckGenerator(store),
      ([channelsCollection]) => {
        const fetchTopicPromises = channelsCollection.map(channel =>
          fetchTopic(store, channel.root)
        );
        ConditionalPromise.all(fetchTopicPromises).only(
          samePageCheckGenerator(store),
          channelsContent => {
            const subtopics = channelsContent.map(channel => {
              const subtopic = channel.topic;
              subtopic.allExercisesWithinTopic = channel.subtopics.reduce(
                (acc, subtopic) => acc.concat(subtopic.allExercisesWithinTopic),
                channel.exercises
              );
              return subtopic;
            });

            const topic = {
              allExercisesWithinTopic: subtopics.reduce(
                (acc, subtopic) => acc.concat(subtopic.allExercisesWithinTopic),
                []
              ),
              id: null,
              title: translator.$tr('allChannels'),
            };
            store.dispatch('SET_TOPIC', topic);
            store.dispatch('SET_SUBTOPICS', subtopics);
            store.dispatch('SET_EXERCISES', []);
            resolve();
          },
          error => reject(error)
        );
      },
      error => reject(error)
    );
  });
}

export function getAllExercisesWithinTopic(store, topicId) {
  return new Promise((resolve, reject) => {
    const exercisesPromise = ContentNodeResource.getDescendantsCollection(topicId, {
      descendant_kind: ContentNodeKinds.EXERCISE,
      fields: ['id', 'title', 'assessmentmetadata', 'num_coach_contents'],
    }).fetch();

    ConditionalPromise.all([exercisesPromise]).only(
      samePageCheckGenerator(store),
      ([exercisesCollection]) => {
        const exercises = _exercisesState(exercisesCollection);
        resolve(exercises);
      },
      error => reject(error)
    );
  });
}

// fetches topic, it's children subtopics, and children exercises
// TODO: Optimize
function fetchTopic(store, topicId) {
  return new Promise((resolve, reject) => {
    const topicPromise = ContentNodeResource.getModel(topicId).fetch();
    const ancestorsPromise = ContentNodeResource.fetchAncestors(topicId);
    const subtopicsPromise = ContentNodeResource.getCollection({
      parent: topicId,
      kind: ContentNodeKinds.TOPIC,
      fields: ['id', 'title', 'ancestors', 'num_coach_contents'],
    }).fetch();
    const exercisesPromise = ContentNodeResource.getCollection({
      parent: topicId,
      kind: ContentNodeKinds.EXERCISE,
      fields: ['id', 'title', 'assessmentmetadata', 'num_coach_contents'],
    }).fetch();

    ConditionalPromise.all([
      topicPromise,
      subtopicsPromise,
      exercisesPromise,
      ancestorsPromise,
    ]).only(
      samePageCheckGenerator(store),
      ([topicModel, subtopicsCollection, exercisesCollection, ancestors]) => {
        const topic = _currentTopicState(topicModel, ancestors);
        const exercises = _exercisesState(exercisesCollection);
        let subtopics = [...subtopicsCollection];

        const subtopicsExercisesPromises = subtopics.map(subtopic =>
          getAllExercisesWithinTopic(store, subtopic.id)
        );

        ConditionalPromise.all(subtopicsExercisesPromises).only(
          samePageCheckGenerator(store),
          subtopicsExercises => {
            subtopics = subtopics.map((subtopic, index) => {
              subtopic.allExercisesWithinTopic = subtopicsExercises[index];
              return subtopic;
            });

            resolve({ topic, subtopics, exercises });
          },
          error => reject(error)
        );
      },
      error => reject(error)
    );
  });
}

export function goToTopic(store, topicId) {
  return new Promise((resolve, reject) => {
    fetchTopic(store, topicId).then(
      content => {
        store.dispatch('SET_TOPIC', content.topic);
        store.dispatch('SET_SUBTOPICS', content.subtopics);
        store.dispatch('SET_EXERCISES', content.exercises);
        resolve();
      },
      error => reject(error)
    );
  });
}

export function addExercise(store, exercise) {
  const selectedExercises = store.state.pageState.selectedExercises;
  if (!selectedExercises.some(selectedExercise => selectedExercise.id === exercise.id)) {
    setSelectedExercises(store, selectedExercises.concat(exercise));
  }
}

export function removeExercise(store, exercise) {
  let selectedExercises = store.state.pageState.selectedExercises;
  selectedExercises = selectedExercises.filter(
    selectedExercise => selectedExercise.id !== exercise.id
  );
  setSelectedExercises(store, selectedExercises);
}

export function setSelectedExercises(store, selectedExercises) {
  store.dispatch('SET_SELECTED_EXERCISES', selectedExercises);
}

export function createExamAndRoute(store, exam) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _createExam(store, exam).then(
    () => {
      router.getInstance().push({ name: PageNames.EXAMS });
      createSnackbar(store, {
        text: snackbarTranslator.$tr('newExamCreated'),
        autoDismiss: true,
      });
    },
    error => handleApiError(store, error)
  );
}

/**
 * EXAM REPORTS
 */

export function showExamReportPage(store, classId, examId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXAM_REPORT);

  ConditionalPromise.all([ExamResource.getModel(examId).fetch()]).only(
    samePageCheckGenerator(store),
    ([exam]) => {
      const promises = [
        ExamLogResource.getCollection({ exam: examId, collection: classId }).fetch(),
        FacilityUserResource.getCollection({ member_of: classId }).fetch(),
        LearnerGroupResource.getCollection({ parent: classId }).fetch(),
        ExamResource.getCollection({ collection: classId }).fetch({}, true),
        ContentNodeResource.getCollection({
          in_exam: exam.id,
          fields: ['id', 'num_coach_contents'],
        }).fetch(),
        setClassState(store, classId),
      ];
      ConditionalPromise.all(promises).only(
        samePageCheckGenerator(store),
        ([examLogs, facilityUsers, learnerGroups, exams, contentNodes]) => {
          const examTakers = facilityUsers.map(user => {
            const examTakenByUser =
              examLogs.find(examLog => String(examLog.user) === user.id) || {};
            const learnerGroup =
              learnerGroups.find(group => group.user_ids.indexOf(user.id) > -1) || {};
            return {
              id: user.id,
              name: user.full_name,
              group: learnerGroup,
              score: examTakenByUser.score,
              progress: examTakenByUser.progress,
              closed: examTakenByUser.closed,
            };
          });
          store.dispatch('SET_PAGE_STATE', {
            examTakers,
            exam,
            examsModalSet: null,
            exams,
            learnerGroups,
            exerciseContentNodes: [...contentNodes],
          });
          store.dispatch('CORE_SET_ERROR', null);
          store.dispatch('CORE_SET_TITLE', exam.title);
          store.dispatch('CORE_SET_PAGE_LOADING', false);
        },
        error => {
          handleApiError(store, error);
        }
      );
    },
    error => {
      if (error.status.code === 404) {
        // TODO: route to 404 page
        router.replace({ name: PageNames.EXAMS });
      } else {
        handleCoachPageError(store, error);
      }
    }
  );
}

/**
 * EXAM REPORT DETAILS
 */

export function showExamReportDetailPage(
  store,
  classId,
  userId,
  examId,
  questionNumber,
  interactionIndex
) {
  // idk what this is for
  if (store.state.pageName !== PageNames.EXAM_REPORT_DETAIL) {
    store.dispatch('CORE_SET_PAGE_LOADING', true);
    store.dispatch('SET_PAGE_NAME', PageNames.EXAM_REPORT_DETAIL);
  }
  const promises = [
    getExamReport(store, examId, userId, questionNumber, interactionIndex),
    setClassState(store, classId),
  ];
  ConditionalPromise.all(promises).then(
    ([examReport]) => {
      store.dispatch('SET_PAGE_STATE', examReport);
      store.dispatch('SET_TOOLBAR_ROUTE', { name: PageNames.EXAM_REPORT });
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('CORE_SET_TITLE', translator.$tr('coachExamReportDetailPageTitle'));
      store.dispatch(
        'SET_TOOLBAR_TITLE',
        translator.$tr('examReportTitle', {
          examTitle: examReport.exam.title,
        })
      );
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    },
    () =>
      router.replace({
        name: PageNames.EXAM_REPORT,
        params: { classId, examId },
      })
  );
}
<commit_msg>Show coach content icon at top-level in exam creation<commit_after>import {
  ChannelResource,
  LearnerGroupResource,
  ContentNodeResource,
  ExamResource,
  ExamLogResource,
  FacilityUserResource,
} from 'kolibri.resources';
import ConditionalPromise from 'kolibri.lib.conditionalPromise';
import router from 'kolibri.coreVue.router';
import {
  handleError,
  handleApiError,
  createSnackbar,
  samePageCheckGenerator,
} from 'kolibri.coreVue.vuex.actions';
import { ContentNodeKinds } from 'kolibri.coreVue.vuex.constants';
import { getExamReport } from 'kolibri.utils.exams';
import { assessmentMetaDataState } from 'kolibri.coreVue.vuex.mappers';
import { createTranslator } from 'kolibri.utils.i18n';
import { PageNames } from '../../constants';
import { setClassState, handleCoachPageError } from './main';

const translator = createTranslator('coachExamPageTitles', {
  allChannels: 'All channels',
  coachExamListPageTitle: 'Exams',
  coachExamCreationPageTitle: 'Create new exam',
  coachExamReportDetailPageTitle: 'Exam Report Detail',
  examReportTitle: '{examTitle} report',
});

const snackbarTranslator = createTranslator('examPageSnackbarTexts', {
  changesToExamSaved: 'Changes to exam saved',
  copiedExamToClass: 'Copied exam to { className }',
  examDeleted: 'Exam deleted',
  examIsNowActive: 'Exam is now active',
  examIsNowInactive: 'Exam is now inactive',
  newExamCreated: 'New exam created',
});

function _currentTopicState(topic, ancestors = []) {
  return {
    id: topic.id,
    title: topic.title,
    num_coach_contents: topic.num_coach_contents,
    breadcrumbs: [
      { id: null, title: translator.$tr('allChannels') },
      ...ancestors,
      { id: topic.id, title: topic.title },
    ],
  };
}

function _exerciseState(exercise) {
  return {
    id: exercise.id,
    title: exercise.title,
    numAssessments: assessmentMetaDataState(exercise).assessmentIds.length,
    num_coach_contents: exercise.num_coach_contents,
  };
}

function _exercisesState(exercises) {
  return exercises.map(exercise => _exerciseState(exercise));
}

function _examState(exam) {
  return {
    id: exam.id,
    title: exam.title,
    channelId: exam.channel_id,
    collection: exam.collection,
    active: exam.active,
    archive: exam.archive,
    questionCount: exam.question_count,
    questionSources: exam.question_sources,
    seed: exam.seed,
    assignments: exam.assignments,
  };
}

function _examsState(exams) {
  return exams.map(exam => _examState(exam));
}

export function _createExam(store, exam) {
  return new Promise((resolve, reject) => {
    ExamResource.createModel(exam)
      .save()
      .then(exam => resolve(exam), error => reject(error));
  });
}

/**
 * EXAMS PAGE
 */

export function showExamsPage(store, classId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXAMS);

  const promises = [
    ExamResource.getCollection({ collection: classId }).fetch({}, true),
    setClassState(store, classId),
  ];

  return ConditionalPromise.all(promises).only(
    samePageCheckGenerator(store),
    ([exams]) => {
      store.dispatch('SET_PAGE_STATE', {
        exams: _examsState(exams),
        examsModalSet: false,
        busy: false,
      });
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('CORE_SET_TITLE', translator.$tr('coachExamListPageTitle'));
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    },
    error => handleError(store, error)
  );
}

export function setExamsModal(store, modalName) {
  store.dispatch('SET_EXAMS_MODAL', modalName);
}

function updateExamStatus(store, { examId, isActive }) {
  return ExamResource.getModel(examId)
    .save({ active: isActive })
    .then(
      () => {
        store.dispatch('SET_EXAM_STATUS', { examId, isActive });
        setExamsModal(store, false);
        createSnackbar(store, {
          text: snackbarTranslator.$tr(isActive ? 'examIsNowActive' : 'examIsNowInactive'),
          autoDismiss: true,
        });
      },
      error => handleError(store, error)
    );
}

export function activateExam(store, examId) {
  return updateExamStatus(store, { examId, isActive: true });
}

export function deactivateExam(store, examId) {
  return updateExamStatus(store, { examId, isActive: false });
}

export function copyExam(store, exam, className) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _createExam(store, exam).then(
    () => {
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      setExamsModal(store, false);
      createSnackbar(store, {
        text: snackbarTranslator.$tr('copiedExamToClass', { className }),
        autoDismiss: true,
      });
    },
    error => handleApiError(store, error)
  );
}

export function updateExamDetails(store, examId, payload) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  return new Promise((resolve, reject) => {
    ExamResource.getModel(examId)
      .save(payload)
      .then(
        exam => {
          const exams = store.state.pageState.exams;
          const examIndex = exams.findIndex(exam => exam.id === examId);
          exams[examIndex] = _examState(exam);

          store.dispatch('SET_EXAMS', exams);
          setExamsModal(store, false);
          createSnackbar(store, {
            text: snackbarTranslator.$tr('changesToExamSaved'),
            autoDismiss: true,
          });
          store.dispatch('CORE_SET_PAGE_LOADING', false);
          resolve();
        },
        error => {
          store.dispatch('CORE_SET_PAGE_LOADING', false);
          reject(error);
        }
      );
  });
}

export function deleteExam(store, examId) {
  return ExamResource.getModel(examId)
    .delete()
    .then(
      () => {
        const exams = store.state.pageState.exams;
        const updatedExams = exams.filter(exam => exam.id !== examId);
        store.dispatch('SET_EXAMS', updatedExams);

        router.replace({ name: PageNames.EXAMS });
        createSnackbar(store, {
          text: snackbarTranslator.$tr('examDeleted'),
          autoDismiss: true,
        });
        setExamsModal(store, false);
      },
      error => handleError(store, error)
    );
}

/**
 * EXAM CREATION
 */

export function showCreateExamPage(store, classId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.CREATE_EXAM);
  store.dispatch('CORE_SET_TITLE', translator.$tr('coachExamCreationPageTitle'));
  store.dispatch('SET_PAGE_STATE', {
    topic: {},
    subtopics: [],
    exercises: [],
    selectedExercises: [],
    exerciseContentNodes: [],
    examsModalSet: false,
  });

  const examsPromise = ExamResource.getCollection({
    collection: classId,
  }).fetch({}, true);
  const goToTopLevelPromise = goToTopLevel(store);

  ConditionalPromise.all([examsPromise, setClassState(store, classId), goToTopLevelPromise]).only(
    samePageCheckGenerator(store),
    ([exams]) => {
      store.dispatch('SET_EXAMS', exams);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    },
    error => handleError(store, error)
  );
}

// TODO: Optimize
export function goToTopLevel(store) {
  return new Promise((resolve, reject) => {
    const channelPromise = ChannelResource.getCollection({
      available: true,
      has_exercise: true,
    }).fetch();

    ConditionalPromise.all([channelPromise]).only(
      samePageCheckGenerator(store),
      ([channelsCollection]) => {
        const fetchTopicPromises = channelsCollection.map(channel =>
          fetchTopic(store, channel.root)
        );
        ConditionalPromise.all(fetchTopicPromises).only(
          samePageCheckGenerator(store),
          channelsContent => {
            const subtopics = channelsContent.map(channel => {
              const subtopic = channel.topic;
              subtopic.allExercisesWithinTopic = channel.subtopics.reduce(
                (acc, subtopic) => acc.concat(subtopic.allExercisesWithinTopic),
                channel.exercises
              );
              return subtopic;
            });

            const topic = {
              allExercisesWithinTopic: subtopics.reduce(
                (acc, subtopic) => acc.concat(subtopic.allExercisesWithinTopic),
                []
              ),
              id: null,
              title: translator.$tr('allChannels'),
            };
            store.dispatch('SET_TOPIC', topic);
            store.dispatch('SET_SUBTOPICS', subtopics);
            store.dispatch('SET_EXERCISES', []);
            resolve();
          },
          error => reject(error)
        );
      },
      error => reject(error)
    );
  });
}

export function getAllExercisesWithinTopic(store, topicId) {
  return new Promise((resolve, reject) => {
    const exercisesPromise = ContentNodeResource.getDescendantsCollection(topicId, {
      descendant_kind: ContentNodeKinds.EXERCISE,
      fields: ['id', 'title', 'assessmentmetadata', 'num_coach_contents'],
    }).fetch();

    ConditionalPromise.all([exercisesPromise]).only(
      samePageCheckGenerator(store),
      ([exercisesCollection]) => {
        const exercises = _exercisesState(exercisesCollection);
        resolve(exercises);
      },
      error => reject(error)
    );
  });
}

// fetches topic, it's children subtopics, and children exercises
// TODO: Optimize
function fetchTopic(store, topicId) {
  return new Promise((resolve, reject) => {
    const topicPromise = ContentNodeResource.getModel(topicId).fetch();
    const ancestorsPromise = ContentNodeResource.fetchAncestors(topicId);
    const subtopicsPromise = ContentNodeResource.getCollection({
      parent: topicId,
      kind: ContentNodeKinds.TOPIC,
      fields: ['id', 'title', 'ancestors', 'num_coach_contents'],
    }).fetch();
    const exercisesPromise = ContentNodeResource.getCollection({
      parent: topicId,
      kind: ContentNodeKinds.EXERCISE,
      fields: ['id', 'title', 'assessmentmetadata', 'num_coach_contents'],
    }).fetch();

    ConditionalPromise.all([
      topicPromise,
      subtopicsPromise,
      exercisesPromise,
      ancestorsPromise,
    ]).only(
      samePageCheckGenerator(store),
      ([topicModel, subtopicsCollection, exercisesCollection, ancestors]) => {
        const topic = _currentTopicState(topicModel, ancestors);
        const exercises = _exercisesState(exercisesCollection);
        let subtopics = [...subtopicsCollection];

        const subtopicsExercisesPromises = subtopics.map(subtopic =>
          getAllExercisesWithinTopic(store, subtopic.id)
        );

        ConditionalPromise.all(subtopicsExercisesPromises).only(
          samePageCheckGenerator(store),
          subtopicsExercises => {
            subtopics = subtopics.map((subtopic, index) => {
              subtopic.allExercisesWithinTopic = subtopicsExercises[index];
              return subtopic;
            });

            resolve({ topic, subtopics, exercises });
          },
          error => reject(error)
        );
      },
      error => reject(error)
    );
  });
}

export function goToTopic(store, topicId) {
  return new Promise((resolve, reject) => {
    fetchTopic(store, topicId).then(
      content => {
        store.dispatch('SET_TOPIC', content.topic);
        store.dispatch('SET_SUBTOPICS', content.subtopics);
        store.dispatch('SET_EXERCISES', content.exercises);
        resolve();
      },
      error => reject(error)
    );
  });
}

export function addExercise(store, exercise) {
  const selectedExercises = store.state.pageState.selectedExercises;
  if (!selectedExercises.some(selectedExercise => selectedExercise.id === exercise.id)) {
    setSelectedExercises(store, selectedExercises.concat(exercise));
  }
}

export function removeExercise(store, exercise) {
  let selectedExercises = store.state.pageState.selectedExercises;
  selectedExercises = selectedExercises.filter(
    selectedExercise => selectedExercise.id !== exercise.id
  );
  setSelectedExercises(store, selectedExercises);
}

export function setSelectedExercises(store, selectedExercises) {
  store.dispatch('SET_SELECTED_EXERCISES', selectedExercises);
}

export function createExamAndRoute(store, exam) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  _createExam(store, exam).then(
    () => {
      router.getInstance().push({ name: PageNames.EXAMS });
      createSnackbar(store, {
        text: snackbarTranslator.$tr('newExamCreated'),
        autoDismiss: true,
      });
    },
    error => handleApiError(store, error)
  );
}

/**
 * EXAM REPORTS
 */

export function showExamReportPage(store, classId, examId) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.EXAM_REPORT);

  ConditionalPromise.all([ExamResource.getModel(examId).fetch()]).only(
    samePageCheckGenerator(store),
    ([exam]) => {
      const promises = [
        ExamLogResource.getCollection({ exam: examId, collection: classId }).fetch(),
        FacilityUserResource.getCollection({ member_of: classId }).fetch(),
        LearnerGroupResource.getCollection({ parent: classId }).fetch(),
        ExamResource.getCollection({ collection: classId }).fetch({}, true),
        ContentNodeResource.getCollection({
          in_exam: exam.id,
          fields: ['id', 'num_coach_contents'],
        }).fetch(),
        setClassState(store, classId),
      ];
      ConditionalPromise.all(promises).only(
        samePageCheckGenerator(store),
        ([examLogs, facilityUsers, learnerGroups, exams, contentNodes]) => {
          const examTakers = facilityUsers.map(user => {
            const examTakenByUser =
              examLogs.find(examLog => String(examLog.user) === user.id) || {};
            const learnerGroup =
              learnerGroups.find(group => group.user_ids.indexOf(user.id) > -1) || {};
            return {
              id: user.id,
              name: user.full_name,
              group: learnerGroup,
              score: examTakenByUser.score,
              progress: examTakenByUser.progress,
              closed: examTakenByUser.closed,
            };
          });
          store.dispatch('SET_PAGE_STATE', {
            examTakers,
            exam,
            examsModalSet: null,
            exams,
            learnerGroups,
            exerciseContentNodes: [...contentNodes],
          });
          store.dispatch('CORE_SET_ERROR', null);
          store.dispatch('CORE_SET_TITLE', exam.title);
          store.dispatch('CORE_SET_PAGE_LOADING', false);
        },
        error => {
          handleApiError(store, error);
        }
      );
    },
    error => {
      if (error.status.code === 404) {
        // TODO: route to 404 page
        router.replace({ name: PageNames.EXAMS });
      } else {
        handleCoachPageError(store, error);
      }
    }
  );
}

/**
 * EXAM REPORT DETAILS
 */

export function showExamReportDetailPage(
  store,
  classId,
  userId,
  examId,
  questionNumber,
  interactionIndex
) {
  // idk what this is for
  if (store.state.pageName !== PageNames.EXAM_REPORT_DETAIL) {
    store.dispatch('CORE_SET_PAGE_LOADING', true);
    store.dispatch('SET_PAGE_NAME', PageNames.EXAM_REPORT_DETAIL);
  }
  const promises = [
    getExamReport(store, examId, userId, questionNumber, interactionIndex),
    setClassState(store, classId),
  ];
  ConditionalPromise.all(promises).then(
    ([examReport]) => {
      store.dispatch('SET_PAGE_STATE', examReport);
      store.dispatch('SET_TOOLBAR_ROUTE', { name: PageNames.EXAM_REPORT });
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('CORE_SET_TITLE', translator.$tr('coachExamReportDetailPageTitle'));
      store.dispatch(
        'SET_TOOLBAR_TITLE',
        translator.$tr('examReportTitle', {
          examTitle: examReport.exam.title,
        })
      );
      store.dispatch('CORE_SET_PAGE_LOADING', false);
    },
    () =>
      router.replace({
        name: PageNames.EXAM_REPORT,
        params: { classId, examId },
      })
  );
}
<|endoftext|>


<commit_before>//= require jquery
//= require jquery_ujs
//= require spin.js/spin
//= require ladda/js/ladda
//= require noty
//= require sifter
//= require microplugin
//= require selectize
//= require bootstrap
//= require dynamic_fields_for
//= require i18n
//= require i18n/translations
//= require moment/moment
//= require moment-init
//= require twix/bin/twix
//= require d3
//= require nvd3
//= require accounting/accounting
//= require nprogress
//= require fastclick
//= require pdf.js/build/pdf
//= require pdf-viewer
//= require helper
//= require_tree ./helpers
//= require tabs
//= require app
//= require_tree ./helpers
//= require_tree ./app
//= require angular-init
//= require base
//= require blank
//= require timesheet

window.ApiBasePath = "//api." + window.location.host;

$(document).on('show.bs.collapse', '.navbar-collapse', function() {
  $('.navbar-collapse.in').not(this).collapse('hide');
});

$(function() {
  FastClick.attach(document.body);

  $('.btn.btn-loading').click(function() {
    $(this).button('loading');
  });
});

if (("standalone" in window.navigator) && window.navigator.standalone) {
  var noddy, remotes = false;

  document.addEventListener('click', function(event) {
    noddy = event.target;

    while(noddy.nodeName !== "A" && noddy.nodeName !== "HTML") {
      noddy = noddy.parentNode;
    }

    if('href' in noddy && noddy.href.indexOf('http') !== -1 && (noddy.href.indexOf(document.location.host) !== -1 || remotes)) {
      event.preventDefault();
      document.location.href = noddy.href;
    }

  }, false);
}
<commit_msg>remove safari hack for webapps<commit_after>//= require jquery
//= require jquery_ujs
//= require spin.js/spin
//= require ladda/js/ladda
//= require noty
//= require sifter
//= require microplugin
//= require selectize
//= require bootstrap
//= require dynamic_fields_for
//= require i18n
//= require i18n/translations
//= require moment/moment
//= require moment-init
//= require twix/bin/twix
//= require d3
//= require nvd3
//= require accounting/accounting
//= require nprogress
//= require fastclick
//= require pdf.js/build/pdf
//= require pdf-viewer
//= require helper
//= require_tree ./helpers
//= require tabs
//= require app
//= require_tree ./helpers
//= require_tree ./app
//= require angular-init
//= require base
//= require blank
//= require timesheet

window.ApiBasePath = "//api." + window.location.host;

$(document).on('show.bs.collapse', '.navbar-collapse', function() {
  $('.navbar-collapse.in').not(this).collapse('hide');
});

$(function() {
  FastClick.attach(document.body);

  $('.btn.btn-loading').click(function() {
    $(this).button('loading');
  });
});
<|endoftext|>


<commit_before>(function($) {

	var Login = function(page)
	{
		this.page = page;
	}

	Login.prototype.login = function(username, password, callback)
	{
		if(this.isLoggedIn()) return;
		var parser = this;
		this.page.open('https://wwws.mint.com/login.event', function(status) {

			if(!parser.success(status)) {
				console.log("{'error':'Unable to load the login page: "+status+"'}");
				phantom.exit();
			}

			parser.page.injectJs('lib/jquery.js');

			var results = parser.page.evaluate(function(username, password)
			{
				jQuery('#form-login-username').val(username);
				jQuery('#form-login-password').val(password);
				jQuery('#form-login').submit();
				return true;
			}, username, password);

			window.setTimeout(function() {
				if(parser.isLoggedIn()) {
					if(typeof callback !== 'undefined') callback();
				} else {
					console.log("{'error':'Bad Username or Password'}");
					phantom.exit();
				}
			}, 5000);
		});
	}

	Login.prototype.isLoggedIn = function()
	{
		return this.page.evaluate(function(){
			return (document.cookie.indexOf("wa_login") != -1);
		});
	}

	Login.prototype.success = function(status)
	{
		if (status != 'success')
		{
			return false;
		}
		return true;
	}

	window.Login = Login;

})(jQuery);<commit_msg>have to keep up with mint<commit_after>(function($) {

	var Login = function(page)
	{
		this.page = page;
	}

	Login.prototype.login = function(username, password, callback)
	{
		if(this.isLoggedIn()) return;
		var parser = this;
		this.page.open('https://wwws.mint.com/login.event', function(status) {
		  setTimeout(function() {
    			if(!parser.success(status)) {
    				console.log("{'error':'Unable to load the login page: "+status+"'}");
    				phantom.exit();
    			}

    			parser.page.injectJs('lib/jquery.js');
    		    console.log('login page loaded, injecting jquery');
    			var results = parser.page.evaluate(function(username, password)
    			{
    				jQuery('#form-login-username').val(username);
    				jQuery('#form-login-password').val(password);
    				jQuery('#form-login, #submit, input[value="Log in"]').click();
    				return true;
    			}, username, password);

    			window.setTimeout(function() {
    				if(parser.isLoggedIn()) {
    					if(typeof callback !== 'undefined') callback();
    				} else {
    					console.log("{'error':'Bad Username or Password'}");
    					phantom.exit();
    				}
    			}, 5000);
            }, 3000);
		});
	}

	Login.prototype.isLoggedIn = function()
	{
		return this.page.evaluate(function(){
			return (document.cookie.indexOf("wa_login") != -1);
		});
	}

	Login.prototype.success = function(status)
	{
		if (status != 'success')
		{
			return false;
		}
		return true;
	}

	window.Login = Login;

})(jQuery);<|endoftext|>


<commit_before>//= require jquery
//= require jquery_ujs
//= require cocoon
//= require ckeditor-jquery

function initEditable() {
    $.fn.editable.defaults.mode = 'inline';
    $('.editable').each(function (_, o) {
        $(o).editable(
                {
                    ajaxOptions: {
                        type: 'PUT'
                    },
                    emptytext: '-',
                    params: function (data) {
                        var params = {};
                        params[data.name] = data.value;
                        return params;
                    },
                    error: function (xhr) {
                        try {
                            var json = $.parseJSON(xhr.responseText.replace(/<br\s*[\/]?>/gi, "\\n"));
                        }
                        catch (e) {
                            return 'Internal error';
                        }

                        if (json && json.errors) {
                            return json.errors.join("\n");
                        }
                    }
                }
        );
    });
}

$(document).ready(function () {
    initEditable();
    $('.thumbnails').each(function () {
        $(this).galereya({size: 200});
    });
});
<commit_msg>gallery spacing<commit_after>//= require jquery
//= require jquery_ujs
//= require cocoon
//= require ckeditor-jquery

function initEditable() {
    $.fn.editable.defaults.mode = 'inline';
    $('.editable').each(function (_, o) {
        $(o).editable(
                {
                    ajaxOptions: {
                        type: 'PUT'
                    },
                    emptytext: '-',
                    params: function (data) {
                        var params = {};
                        params[data.name] = data.value;
                        return params;
                    },
                    error: function (xhr) {
                        try {
                            var json = $.parseJSON(xhr.responseText.replace(/<br\s*[\/]?>/gi, "\\n"));
                        }
                        catch (e) {
                            return 'Internal error';
                        }

                        if (json && json.errors) {
                            return json.errors.join("\n");
                        }
                    }
                }
        );
    });
}

$(document).ready(function () {
    initEditable();
    $('.thumbnails').each(function () {
        $(this).galereya({size: 200, spacing: 20});
    });
});
<|endoftext|>


<commit_before>module.exports = function($q) {
  'njInject';

  var self = this;

  var companyUrl = '/api/companies';

  this.companies = {};

  this.createCompany = function(company) {
    console.log(company);
    var id = new Date().getTime();

    self.companies[id] = angular.copy(company);
    self.companies[id]._id = id;
    return $q.when(self.companies[id]);
  };

  this.deleteCompany = function(id) {
    delete self.companies[id];
    return $q.when(true);
  };

  this.getCompanies = function() {
    return $q.when(self.companies);
  };

  this.updateCompany = function(company) {
    self.companies[company._id] = company;
    return $q.when(true);
  };
};
<commit_msg>http call to get companies<commit_after>module.exports = function($q, $http) {
  'njInject';

  var self = this;

  var companyUrl = 'https://mysterious-citadel-17041.herokuapp.com/api/companies';

  var formatCompanies = function(response) {
    var obj = {};

    for (var i = 0; i < response.length; i++) {
      obj[response[i]._id] = response[i];
    }
    self.companies = obj;
    return obj;
  };

  this.companies = {};

  this.createCompany = function(company) {
    var id = new Date().getTime();

    self.companies[id] = angular.copy(company);
    self.companies[id]._id = id;
    return $q.when(self.companies[id]);
  };

  this.deleteCompany = function(id) {
    delete self.companies[id];
    return $q.when(true);
  };

  this.getCompanies = function() {
    return $http.get(companyUrl).then(function(response) {
      return formatCompanies(response.data);
    });
  };

  this.updateCompany = function(company) {
    self.companies[company._id] = company;
    return $q.when(true);
  };
};
<|endoftext|>


<commit_before>// = require jquery
// = require bootstrap
// = require turbolinks
// = require select2.full
$(document).ready(function() {
    $("select").select2({
        theme: "bootstrap",
        containerCssClass: ":all:"
    });
});<commit_msg>Add jquery_ujs to Application<commit_after>// = require jquery
// = require jquery_ujs
// = require bootstrap
// = require turbolinks
// = require select2.full
$(document).ready(function() {
    $("select").select2({
        theme: "bootstrap",
        containerCssClass: ":all:"
    });
});
<|endoftext|>


<commit_before>//= require jquery
//= require jquery_ujs
//= require jquery.cookiebar

$(document).ready(function(){

  // alert cookies (bottom)
  // http://www.primebox.co.uk/projects/jquery-cookiebar/
  $.cookieBar({
    message: $('.js-cookie-message').html(),
    acceptText: 'OK'
  });
});
<commit_msg>Whitespace cleanup pass<commit_after>//= require jquery
//= require jquery_ujs
//= require jquery.cookiebar

$(document).ready(function(){

  // alert cookies (bottom)
  // http://www.primebox.co.uk/projects/jquery-cookiebar/
  $.cookieBar({
    message: $('.js-cookie-message').html(),
    acceptText: 'OK'
  });
});
<|endoftext|>


<commit_before>import LandingPage from '../components/LandingPage'
import MultipleProducts from '../components/MultipleProducts'
import React, { Component } from 'react';
import { connect } from 'react-redux'

const mapStateToProps = (state) => {
  const products = state.products

  return {
    products: products.allProducts
  }
}

class LandingPageContainer extends Component {
  constructor(props) {
    super(props);
    this.state = { inputValue: ''}
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(evt) {
    const inputValue = evt.target.value
    this.setState({ inputValue })
  }

  render() {
    const inputValue = this.state.inputValue
    const filteredProducts = this.props.products.filter(product => product.name.match(inputValue))

    return (

        <LandingPage handleChange={this.state.handleChange} />
        <MultipleProducts products={filteredProducts} />

    );
  }
}

export default connect(
  mapStateToProps
)(LandingPageContainer)

<commit_msg>refactor(landingPageConntainer): fixes handleChange name + adds img tag<commit_after>import LandingPage from '../components/LandingPage'
import MultipleProducts from '../components/MultipleProducts'
import React, { Component } from 'react';
import { connect } from 'react-redux'

const mapStateToProps = (state) => {
  const products = state.products

  return {
    products: products.allProducts
  }
}

class LandingPageContainer extends Component {
  constructor(props) {
    super(props);
    this.state = { inputValue: ''}
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(evt) {
    const inputValue = evt.target.value
    this.setState({ inputValue })
  }

  render() {
    const inputValue = this.state.inputValue
    const filteredProducts = this.props.products.filter(product => product.name.match(inputValue))

    return (

        <LandingPage handleChange={this.handleChange} inputValue={inputValue} />
        <MultipleProducts products={filteredProducts} />

    );
  }
}

export default connect(
  mapStateToProps
)(LandingPageContainer)

<|endoftext|>


<commit_before>import React from 'react';
import ReCAPTCHA from 'react-google-recaptcha';
import { conf } from '../../app.config';

export default class Captcha extends React.Component { // eslint-disable-line react/prefer-stateless-function

  componentWillReceiveProps(nextProps) {
    if (nextProps.error && nextProps.error !== this.props.error) {
      this.recaptcha.reset();
    }
  }

  render() {
    return (

        <ReCAPTCHA
          ref={(recaptcha) => { this.recaptcha = recaptcha; }}
          sitekey={conf().recaptchaKey}
          onChange={this.props.input.onChange}
        />

    );
  }
}

Captcha.propTypes = {
  error: React.PropTypes.any,
  input: React.PropTypes.any,
};
<commit_msg>Reset captcha value when register is failed (#551)<commit_after>import React from 'react';
import ReCAPTCHA from 'react-google-recaptcha';
import { conf } from '../../app.config';

export default class Captcha extends React.Component { // eslint-disable-line react/prefer-stateless-function

  componentWillReceiveProps(nextProps) {
    if (nextProps.error && nextProps.error !== this.props.error) {
      this.recaptcha.reset();
      if (typeof nextProps.input.onChange === 'function') {
        nextProps.input.onChange(false);
      }
    }
  }

  render() {
    return (

        <ReCAPTCHA
          ref={(recaptcha) => { this.recaptcha = recaptcha; }}
          sitekey={conf().recaptchaKey}
          onChange={this.props.input.onChange}
        />

    );
  }
}

Captcha.propTypes = {
  error: React.PropTypes.any,
  input: React.PropTypes.any,
};
<|endoftext|>


<commit_before>$(document).ready(function(){
  //Detect browser type and revision
  navigator.sayswho = (function(){
    var browser = document.querySelector('.alert_browser');
    var N= navigator.appName, ua= navigator.userAgent, tem;
    var M= ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
    if(M && (tem= ua.match(/version\/([\.\d]+)/i))!= null) M[2]= tem[1];
    M= M? [M[1], M[2]]: [N, navigator.appVersion,'-?'];
    var version = parseFloat(M[1]);
    var browserName = M[0]

    if(browserName == 'Firefox' && version >= 23){
      browser.innerHTML = '';
    }

    if(browserName == 'Firefox' && version < 23){
      browser.innerHTML = '
 To use this service please upgrade your version of Firefox  Here
';
    }

    if(browserName == 'Chrome' && version >= 31){
      browser.innerHTML = '
 We currently do not support this browser.  We recommend using  FireFox.
';
    }
  })();
});

function Sender(file){
  var thisSender = this;
  thisSender.peer = new Peer({ host: "ec2-54-201-154-161.us-west-2.compute.amazonaws.com", port: 9000 });

  thisSender.peer.on('open', function(id){
    thisSender.peer_id = id;
    thisSender.setDownloadUrl();
  });

  window.onunload = function(){
    thisSender.peer.destroy();
  }

  thisSender.file = file;
}

Sender.prototype.handleConnection = function(){
  var thisSender = this;
  thisSender.peer.on("connection", function(connection){
    thisSender.connection = connection;

    thisSender.connection.on("open", function(){
      thisSender.sendFileAndMetadata();
      thisSender.updateProgressBar();
    });
  });
}

Sender.prototype.updateProgressBar = function(){
  var progress = document.querySelector('.percent');
  var progress_bar = document.querySelector('#progress_bar')
  var value_prop = document.querySelector(".value_prop");
  var link_field = document.querySelector('.link_field');
  var button_upload = document.querySelector(".button_upload");
  var errorElement = $("#error_message");
  var thisSender = this;
  var sliceSize = 1000;
  link_field.style.display = "none";

  value_prop.innerHTML = "
 File Being Transferred
"
  thisSender.connection.on("data", function(data){

    if(data.isChunkCount){
      errorElement.text("");
      var chunksReceivedByRemotePeer = parseInt(data.chunksReceived);
      var percentLoaded = Math.round((chunksReceivedByRemotePeer / (thisSender.file.size/sliceSize) ) * 100);
      progress.style.width = percentLoaded + '%';
      progress.textContent = percentLoaded + '%';

      // Communication heartbeat check
      if(percentLoaded < 100){
        clearTimeout(thisSender.timeout);
        thisSender.timeout = setTimeout(function(){
          errorElement.text("Connection may have failed. File transfer may have aborted.");
        }, 5000);
      }
      else if(percentLoaded >= 100){
        clearTimeout(thisSender.timeout);
        value_prop.innerHTML = "
 File Successfully Transferred
";
        button_upload.style.display = "inline";
        progress.style.display = "none";
        progress_bar.style.display = "none";
        window.onbeforeunload = null;
      }
    }
  });
}

Sender.prototype.sendFileAndMetadata = function(){
  var thisSender = this;

  var fileMetadata = {
    isFileMetaData: true,
    fileSize: thisSender.file.size,
    fileName: thisSender.file.name
  }
  thisSender.connection.send(fileMetadata);

  thisSender.sendFile();
}

Sender.prototype.sendFile = function(){
  var thisSender = this;
  var fileReader = new FileReader();
  fileReader.readAsArrayBuffer(thisSender.file);

  window.onbeforeunload = function() {
    return "If you close the window the file will not finish transfer.";
  };

  fileReader.onload = function(){
    var fileData = fileReader.result;
    var blob = [];
    var sliceSize = 1000;

    //Setting up variables to display to initiating user
    var status = document.querySelector('.status_view');

    var percent = document.querySelector('.percent');
    var progress_bar = document.querySelector('#progress_bar');
    var userFileName = document.querySelector('.file_name');
    var userFileSize = document.querySelector('.file_size');

    status.style.display = 'inline';
    progress_bar.style.display = '';
    percent.style.display = '';
    userFileName.textContent = thisSender.file.name;
    userFileSize.textContent = byteConverter(thisSender.file.size);

    for(var sliceId = 0; sliceId < fileData.byteLength/sliceSize; sliceId++) {

      if(sliceId >= Math.floor(fileData.byteLength/sliceSize)) {
        var lastStatus = 1;
      }
      else {
        var lastStatus = 0;
      }

      blob = fileData.slice(sliceId * sliceSize, (sliceId + 1) * sliceSize);

      var fileSlice = {
        isFile: true,
        arrayBufferFileData: blob,
        isLast:   lastStatus
      }

      thisSender.connection.send(fileSlice);
    }
  }
}

// url seed words
var adjs = [
            'red',
            'slow',
            'huge',
            'bashful',
            'daring',
            'tired',
            'joyful',
            'bright',
            'shy',
            'dreamy',
            'quiet',
            'blue',
            'sweet',
            'funny',
            'tiny',
            'manic',
            'evil',
            'smart',
            'brave',
            'cunning',
            'tricky',
            'hungry'
           ],

    nouns = [
             'fox',
             'salamander',
             'coyote',
             'firefly',
             'nighthawk',
             'grasshopper',
             'olitaur',
             'dragon',
             'ent',
             'squirrel',
             'rhino',
             'monkey',
             'dog',
             'wolf',
             'cat',
             'ant',
             'kitten',
             'fly',
             'eagle'
             'gopher',
             'woodchuck',
             'meerkat',
             'tiger',
             'leopard',
             'whale',
             'penguin'
            ],

    verbs = [
             'runs',
             'gallops',
             'trots',
             'sleeps',
             'hunts',
             'burrows',
             'drinks',
             'eats',
             'codes',
             'reads',
             'sews',
             'swims',
             'floats',
             'smells',
             'smiles',
             'grins'
            ]

Sender.prototype.setDownloadUrl = function(){

  var value_prop = document.querySelector(".value_prop");
  var button_upload = document.querySelector(".button_upload");
  var link_field  = document.querySelector(".link_field");
  var status = document.querySelector('.status_view');
  var window_open = document.querySelector('.window_open');

  value_prop.innerHTML = "
Share this link to start file transfer

";
  window_open.style.display = "inline";
  button_upload.style.display = "none";
  link_field.style.display = "inline";

  // for scope
  peer_id = this.peer_id;

  function randIndex(anArray) {
    return Math.floor(Math.random() * anArray.length);
  }

  (function makePath() {
    // word pair, with dashes
    var wordTrio = adjs[randIndex(adjs)] + "-"
                     + nouns[randIndex(nouns)] + "-"
                     + verbs[randIndex(verbs)] + "-";

    // random four digits
    var randomFour = [0, 0, 0, 0].map(function(digit) {
      return Math.floor(Math.random(10) * 10);
    }).join('');

    // the combination of the two, a la Heroku
    var path = wordTrio + randomFour;

    // the root Firebase store
    var urlStore = new Firebase('https://quickbits.firebaseio.com/');
    // make a local reference to a Firebase key of `path`
    var url = urlStore.child(path);
    url.set(peer_id);
    // on callback, print the url
    url.on('value', function(snapshot) {
      $("#url").val(window.location.href + path);
    });

    /* delete the reference from Firebase
     * when the window closes */
    window.onunload = function() {
      url.remove();
    }

  })();

  status.style.display = "none";
  window.onbeforeunload = function() {
    return "If you close the window the file will not finish transfer.";
  };

  $("#url").select();
}

$(function(){

  $("#file_input").change(function(event){
    var file = event.target.files[0];
    var sender = new Sender(file);
    sender.handleConnection();
  });

  $("#drop_zone").on("dragover", function(event){
    event.preventDefault();
    event.stopPropagation();
    $(this).css("background","#EBEBEB");
    // $(this).css("-webkit-background-size","cover");
    // $(this).css(" -moz-background-size","cover");
    // $(this).css("-o-background-size","cover");
    // $(this).css("background-size","cover");
    event.originalEvent.dataTransfer.dropEffect = "copy";
  });

  $("#drop_zone").on("dragleave", function(event){
    $(this).css("background", "white");
  });

  $("#drop_zone").on("drop", function(event){
    $(this).css("background","white");
    event.stopPropagation();
    event.preventDefault();
    var file = event.originalEvent.dataTransfer.files[0];
    var sender = new Sender(file);
    sender.handleConnection();
  });

  $(document).on("dragover", function(event){
    event.stopPropagation();
    event.preventDefault();
  });

  $(document).on("drop", function(event){
    event.stopPropagation();
    event.preventDefault();
  });

  $("#copy_link_form").on("submit", function(event){
    event.preventDefault();
  });
});

function byteConverter(bytes){
  var kilobyte = 1024;
  var megabyte = kilobyte * 1024;
  var gigabyte = megabyte * 1024;

  if (Math.floor(bytes/gigabyte) > 0){
    return (bytes/gigabyte).toFixed(2) + " GB"
  }
  else if (Math.floor(bytes/megabyte) > 0){
    return (bytes/megabyte).toFixed(2) + " MB"
  }
  else if (Math.floor(bytes/kilobyte) > 0){
    return (bytes/kilobyte).toFixed(2) + " kB"
  }
  else {
    return bytes + " B"
  }
}
<commit_msg>missing comma<commit_after>$(document).ready(function(){
  //Detect browser type and revision
  navigator.sayswho = (function(){
    var browser = document.querySelector('.alert_browser');
    var N= navigator.appName, ua= navigator.userAgent, tem;
    var M= ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
    if(M && (tem= ua.match(/version\/([\.\d]+)/i))!= null) M[2]= tem[1];
    M= M? [M[1], M[2]]: [N, navigator.appVersion,'-?'];
    var version = parseFloat(M[1]);
    var browserName = M[0]

    if(browserName == 'Firefox' && version >= 23){
      browser.innerHTML = '';
    }

    if(browserName == 'Firefox' && version < 23){
      browser.innerHTML = '
 To use this service please upgrade your version of Firefox  Here
';
    }

    if(browserName == 'Chrome' && version >= 31){
      browser.innerHTML = '
 We currently do not support this browser.  We recommend using  FireFox.
';
    }
  })();
});

function Sender(file){
  var thisSender = this;
  thisSender.peer = new Peer({ host: "ec2-54-201-154-161.us-west-2.compute.amazonaws.com", port: 9000 });

  thisSender.peer.on('open', function(id){
    thisSender.peer_id = id;
    thisSender.setDownloadUrl();
  });

  window.onunload = function(){
    thisSender.peer.destroy();
  }

  thisSender.file = file;
}

Sender.prototype.handleConnection = function(){
  var thisSender = this;
  thisSender.peer.on("connection", function(connection){
    thisSender.connection = connection;

    thisSender.connection.on("open", function(){
      thisSender.sendFileAndMetadata();
      thisSender.updateProgressBar();
    });
  });
}

Sender.prototype.updateProgressBar = function(){
  var progress = document.querySelector('.percent');
  var progress_bar = document.querySelector('#progress_bar')
  var value_prop = document.querySelector(".value_prop");
  var link_field = document.querySelector('.link_field');
  var button_upload = document.querySelector(".button_upload");
  var errorElement = $("#error_message");
  var thisSender = this;
  var sliceSize = 1000;
  link_field.style.display = "none";

  value_prop.innerHTML = "
 File Being Transferred
"
  thisSender.connection.on("data", function(data){

    if(data.isChunkCount){
      errorElement.text("");
      var chunksReceivedByRemotePeer = parseInt(data.chunksReceived);
      var percentLoaded = Math.round((chunksReceivedByRemotePeer / (thisSender.file.size/sliceSize) ) * 100);
      progress.style.width = percentLoaded + '%';
      progress.textContent = percentLoaded + '%';

      // Communication heartbeat check
      if(percentLoaded < 100){
        clearTimeout(thisSender.timeout);
        thisSender.timeout = setTimeout(function(){
          errorElement.text("Connection may have failed. File transfer may have aborted.");
        }, 5000);
      }
      else if(percentLoaded >= 100){
        clearTimeout(thisSender.timeout);
        value_prop.innerHTML = "
 File Successfully Transferred
";
        button_upload.style.display = "inline";
        progress.style.display = "none";
        progress_bar.style.display = "none";
        window.onbeforeunload = null;
      }
    }
  });
}

Sender.prototype.sendFileAndMetadata = function(){
  var thisSender = this;

  var fileMetadata = {
    isFileMetaData: true,
    fileSize: thisSender.file.size,
    fileName: thisSender.file.name
  }
  thisSender.connection.send(fileMetadata);

  thisSender.sendFile();
}

Sender.prototype.sendFile = function(){
  var thisSender = this;
  var fileReader = new FileReader();
  fileReader.readAsArrayBuffer(thisSender.file);

  window.onbeforeunload = function() {
    return "If you close the window the file will not finish transfer.";
  };

  fileReader.onload = function(){
    var fileData = fileReader.result;
    var blob = [];
    var sliceSize = 1000;

    //Setting up variables to display to initiating user
    var status = document.querySelector('.status_view');

    var percent = document.querySelector('.percent');
    var progress_bar = document.querySelector('#progress_bar');
    var userFileName = document.querySelector('.file_name');
    var userFileSize = document.querySelector('.file_size');

    status.style.display = 'inline';
    progress_bar.style.display = '';
    percent.style.display = '';
    userFileName.textContent = thisSender.file.name;
    userFileSize.textContent = byteConverter(thisSender.file.size);

    for(var sliceId = 0; sliceId < fileData.byteLength/sliceSize; sliceId++) {

      if(sliceId >= Math.floor(fileData.byteLength/sliceSize)) {
        var lastStatus = 1;
      }
      else {
        var lastStatus = 0;
      }

      blob = fileData.slice(sliceId * sliceSize, (sliceId + 1) * sliceSize);

      var fileSlice = {
        isFile: true,
        arrayBufferFileData: blob,
        isLast:   lastStatus
      }

      thisSender.connection.send(fileSlice);
    }
  }
}

// url seed words
var adjs = [
            'red',
            'slow',
            'huge',
            'bashful',
            'daring',
            'tired',
            'joyful',
            'bright',
            'shy',
            'dreamy',
            'quiet',
            'blue',
            'sweet',
            'funny',
            'tiny',
            'manic',
            'evil',
            'smart',
            'brave',
            'cunning',
            'tricky',
            'hungry'
           ],

    nouns = [
             'fox',
             'salamander',
             'coyote',
             'firefly',
             'nighthawk',
             'grasshopper',
             'olitaur',
             'dragon',
             'ent',
             'squirrel',
             'rhino',
             'monkey',
             'dog',
             'wolf',
             'cat',
             'ant',
             'kitten',
             'fly',
             'eagle',
             'gopher',
             'woodchuck',
             'meerkat',
             'tiger',
             'leopard',
             'whale',
             'penguin'
            ],

    verbs = [
             'runs',
             'gallops',
             'trots',
             'sleeps',
             'hunts',
             'burrows',
             'drinks',
             'eats',
             'codes',
             'reads',
             'sews',
             'swims',
             'floats',
             'smells',
             'smiles',
             'grins'
            ]

Sender.prototype.setDownloadUrl = function(){

  var value_prop = document.querySelector(".value_prop");
  var button_upload = document.querySelector(".button_upload");
  var link_field  = document.querySelector(".link_field");
  var status = document.querySelector('.status_view');
  var window_open = document.querySelector('.window_open');

  value_prop.innerHTML = "
Share this link to start file transfer

";
  window_open.style.display = "inline";
  button_upload.style.display = "none";
  link_field.style.display = "inline";

  // for scope
  peer_id = this.peer_id;

  function randIndex(anArray) {
    return Math.floor(Math.random() * anArray.length);
  }

  (function makePath() {
    // word pair, with dashes
    var wordTrio = adjs[randIndex(adjs)] + "-"
                     + nouns[randIndex(nouns)] + "-"
                     + verbs[randIndex(verbs)] + "-";

    // random four digits
    var randomFour = [0, 0, 0, 0].map(function(digit) {
      return Math.floor(Math.random(10) * 10);
    }).join('');

    // the combination of the two, a la Heroku
    var path = wordTrio + randomFour;

    // the root Firebase store
    var urlStore = new Firebase('https://quickbits.firebaseio.com/');
    // make a local reference to a Firebase key of `path`
    var url = urlStore.child(path);
    url.set(peer_id);
    // on callback, print the url
    url.on('value', function(snapshot) {
      $("#url").val(window.location.href + path);
    });

    /* delete the reference from Firebase
     * when the window closes */
    window.onunload = function() {
      url.remove();
    }

  })();

  status.style.display = "none";
  window.onbeforeunload = function() {
    return "If you close the window the file will not finish transfer.";
  };

  $("#url").select();
}

$(function(){

  $("#file_input").change(function(event){
    var file = event.target.files[0];
    var sender = new Sender(file);
    sender.handleConnection();
  });

  $("#drop_zone").on("dragover", function(event){
    event.preventDefault();
    event.stopPropagation();
    $(this).css("background","#EBEBEB");
    // $(this).css("-webkit-background-size","cover");
    // $(this).css(" -moz-background-size","cover");
    // $(this).css("-o-background-size","cover");
    // $(this).css("background-size","cover");
    event.originalEvent.dataTransfer.dropEffect = "copy";
  });

  $("#drop_zone").on("dragleave", function(event){
    $(this).css("background", "white");
  });

  $("#drop_zone").on("drop", function(event){
    $(this).css("background","white");
    event.stopPropagation();
    event.preventDefault();
    var file = event.originalEvent.dataTransfer.files[0];
    var sender = new Sender(file);
    sender.handleConnection();
  });

  $(document).on("dragover", function(event){
    event.stopPropagation();
    event.preventDefault();
  });

  $(document).on("drop", function(event){
    event.stopPropagation();
    event.preventDefault();
  });

  $("#copy_link_form").on("submit", function(event){
    event.preventDefault();
  });
});

function byteConverter(bytes){
  var kilobyte = 1024;
  var megabyte = kilobyte * 1024;
  var gigabyte = megabyte * 1024;

  if (Math.floor(bytes/gigabyte) > 0){
    return (bytes/gigabyte).toFixed(2) + " GB"
  }
  else if (Math.floor(bytes/megabyte) > 0){
    return (bytes/megabyte).toFixed(2) + " MB"
  }
  else if (Math.floor(bytes/kilobyte) > 0){
    return (bytes/kilobyte).toFixed(2) + " kB"
  }
  else {
    return bytes + " B"
  }
}
<|endoftext|>