<commit_before>/* -*- mode: espresso; espresso-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set softtabstop=2 shiftwidth=2 tabstop=2 expandtab: */

// Namespace declaration
var CATMAID = CATMAID || {};
CATMAID.tools = CATMAID.tools || {};

/**
 * get the width of an element from the offsetWidth of all of its children
 * use this as width-expression for boxes to be floated completely
 */

function ieCSSWidth(o) {
  var c = o.firstChild;
  var w = c.offsetWidth;
  /* jshint boss:true */ // Allow assignment in conditional
  while (c = c.nextSibling) {
    w += c.offsetWidth;
  }
  return w;
}

/**
 * Simplify more robust prototype inheritance. From:
 * http://michaux.ca/articles/class-based-inheritance-in-javascript
 */
function extend(subclass, superclass) {
   function Dummy() {}
   Dummy.prototype = superclass.prototype;
   subclass.prototype = new Dummy();
   subclass.prototype.constructor = subclass;
   subclass.superclass = superclass;
   subclass.superproto = superclass.prototype;
}

/**
 * Makes a synchronous jQuery AJAX call and return the result.
 */
function sync_request(url, type, data) {
  // check parameters
  if (!type)
    type = "GET";
  // init return variable
  var result = "";
  // make the call
  jQuery.ajax({
    type: type,
    url: url,
    data: data,
    success: function(response) {
      result = response;
    },
    async:false
  });

  return result;
}

/**
 * Stops default behaviour of an event. Found here:
 * http://stackoverflow.com/questions/891581
 */
function stopDefault(e) {
    if (e && e.preventDefault) {
        e.preventDefault();
    }
    else {
        window.event.returnValue = false;
    }
    return false;
}

/**
 * Creates a deep copy of an object. Based on:
 * http://stackoverflow.com/questions/122102
 */
function deepCopy(obj) {
    if(obj === null || typeof(obj) !== 'object'){
        return obj;
    }
    //make sure the returned object has the same prototype as the original
    var ret = Object.create(Object.getPrototypeOf(obj));
    for(var key in obj){
        ret[key] = deepCopy(obj[key]);
    }
    return ret;
}

/**
 * Convert a (usually base64 encorded) dataURI image to a binary blob.
 * From: http://stackoverflow.com/questions/4998908
 */
function dataURItoBlob(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
    else
        byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    return new Blob([ia], {type:mimeString});
}

/**
 * Creates a jQuery UI based error dialog. If detail is passed, it is hidden by
 * default. The dialog allows to expand it, however.
 */
window.ErrorDialog = function(text, detail) {
  this.dialog = document.createElement('div');
  this.dialog.setAttribute("id", "dialog-confirm");
  this.dialog.setAttribute("title", "An error occured");
  // Create error message tags
  var msg = document.createElement('p');
  msg.appendChild(document.createTextNode(text));
  this.dialog.appendChild(msg);
  // Create detail field, if detail available
  if (detail) {
    var detail_head = document.createElement('p');
    var detail_head_em = document.createElement('em');
    detail_head_em.appendChild(document.createTextNode('Show/hide detail'));
    detail_head.appendChild(detail_head_em);
    this.dialog.appendChild(detail_head);
    var detail_text = document.createElement('p');
    detail_text.appendChild(document.createTextNode(detail));
    this.dialog.appendChild(detail_text);
    // Hide detail by default and toggle display by click on header
    $(detail_text).hide();
    $(detail_head).click(function() {
      $(detail_text).toggle();
    });
    $(detail_head_em).css('cursor', 'pointer');
  }
};

window.ErrorDialog.prototype = {};

/**
 * Displays the error dialog.
 */
window.ErrorDialog.prototype.show = function() {
  $(this.dialog).dialog({
    width: '400px',
    height: 'auto',
    modal: true,
    buttons: {
      "OK": function() {
        $(this).dialog("close");
      }
    }
  });
};

/**
 * Convenience function to show an error dialog.
 */
window.error = function(msg, detail)
{
  new ErrorDialog(msg, detail).show();
};

/**
 * Creates a generic JSON response handler that complains when the response
 * status is different from 200 or a JSON error is set.
 */
window.jsonResponseHandler = function(success, error)
{
  return function(status, text, xml) {
    if (status === 200 && text) {
      var json = $.parseJSON(text);
      if (json.error) {
        new ErrorDialog(json.error, json.detail).show();
        if (typeof(error) == 'function') {
          error();
        }
      } else {
        if (typeof(success) == 'function') {
          success(json);
        }
      }
    } else {
      new ErrorDialog("An error occured",
          "The server returned an unexpected status: " + status).show();
      if (typeof(error) == 'function') {
        error();
      }
    }
  };
};

/**
 * Creates a simple login dialog.
 */
window.LoginDialog = function(text, callback) {
  this.dialog = new OptionsDialog("Permission required");
  if (text) {
    this.dialog.appendMessage(text);
  }
  // Add short login text
  var login_text = "Please enter the credentials for a user with the " +
      "necessary credentials to continue to the requested information";
  this.dialog.appendMessage(login_text);
  // Add input fields
  var user_field = this.dialog.appendField('Username', 'username', '', true);
  var pass_field = this.dialog.appendField('Password', 'password', '', true);
  pass_field.setAttribute('type', 'password');
  // Align input fields better
  $(this.dialog.dialog).find('label').css('width', '25%');
  $(this.dialog.dialog).find('label').css('display', 'inline-block');

  // If OK is pressed, the dialog should cause a (re-)login
  this.dialog.onOK = function() {
    login($(user_field).val(), $(pass_field).val(), callback);
  };
};

window.LoginDialog.prototype = {};

/**
 * Displays the login dialog.
 */
window.LoginDialog.prototype.show = function() {
  this.dialog.show('400', 'auto', true);
};

/**
 * Definition of methods in CATMAID.tools namespace.
 */
(function(tools) {

  "use strict";

  /**
   * Does a simple user agent test and returns one of 'MAC', 'WIN', 'LINUX' or
   * 'UNKNOWN'.
   */
  tools.getOS = function()
  {
    var ua = navigator.userAgent.toUpperCase();
    if (-1 !== ua.indexOf('MAC')) {
      return 'MAC';
    } else if (-1 !== ua.indexOf('WIN')) {
      return 'WIN';
    } else if (-1 !== ua.indexOf('LINUX')) {
      return 'LINUX';
    } else {
      return 'UNKNOWN';
    }
  };

  /**
   * Compare two strings while respecting locales and numbers. This is
   * essentially a wrapper around String.localeCompare() to have one
   * place where it is parameterized.
   */
  tools.compareStrings = function(str1, str2)
  {
    return str1.localeCompare(str2, undefined, {numeric: true});
  };

  /**
   * Parse a string as integer or return false if this is not possible or the
   * integer is negative.
   */
  tools.parseIndex = function(str) {
    var pattern = /(\d+)$/;
    if (pattern.test(str)) return parseInt(RegExp.$1);
    else
    return false;
  };

  /**
   * Get a "unique" id for a new element in the DOM.
   */
  var UNIQUE_ID;
  tools.uniqueId = function() {
    if (!UNIQUE_ID) {
      UNIQUE_ID = Math.floor(1073741824 * Math.random());
    }
    return ++UNIQUE_ID;
  };

  /**
   * Parse the query part of the current URL
   */

  tools.parseQuery = function() {
    if (location.search) {
      var r, query;
      query = /\?(.*?)$/i;
      /* jshint boss:true */ // Allow assignment in conditional
      if (r = query.exec(location.search)) {
        var o, p, value;
        o = {};
        value = /([^&=]+)=([^&=]+)/gi;
        while (p = value.exec(r[1])) {
          o[p[1]] = p[2];
        }
        return o;
      } else
      return undefined;
    } else
    return undefined;
  };

})(CATMAID.tools);
<commit_msg>Tools: remove assignment in condition<commit_after>/* -*- mode: espresso; espresso-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set softtabstop=2 shiftwidth=2 tabstop=2 expandtab: */

// Namespace declaration
var CATMAID = CATMAID || {};
CATMAID.tools = CATMAID.tools || {};

/**
 * get the width of an element from the offsetWidth of all of its children
 * use this as width-expression for boxes to be floated completely
 */

function ieCSSWidth(o) {
  var c = o.firstChild;
  var w = c.offsetWidth;
  /* jshint boss:true */ // Allow assignment in conditional
  while (c = c.nextSibling) {
    w += c.offsetWidth;
  }
  return w;
}

/**
 * Simplify more robust prototype inheritance. From:
 * http://michaux.ca/articles/class-based-inheritance-in-javascript
 */
function extend(subclass, superclass) {
   function Dummy() {}
   Dummy.prototype = superclass.prototype;
   subclass.prototype = new Dummy();
   subclass.prototype.constructor = subclass;
   subclass.superclass = superclass;
   subclass.superproto = superclass.prototype;
}

/**
 * Makes a synchronous jQuery AJAX call and return the result.
 */
function sync_request(url, type, data) {
  // check parameters
  if (!type)
    type = "GET";
  // init return variable
  var result = "";
  // make the call
  jQuery.ajax({
    type: type,
    url: url,
    data: data,
    success: function(response) {
      result = response;
    },
    async:false
  });

  return result;
}

/**
 * Stops default behaviour of an event. Found here:
 * http://stackoverflow.com/questions/891581
 */
function stopDefault(e) {
    if (e && e.preventDefault) {
        e.preventDefault();
    }
    else {
        window.event.returnValue = false;
    }
    return false;
}

/**
 * Creates a deep copy of an object. Based on:
 * http://stackoverflow.com/questions/122102
 */
function deepCopy(obj) {
    if(obj === null || typeof(obj) !== 'object'){
        return obj;
    }
    //make sure the returned object has the same prototype as the original
    var ret = Object.create(Object.getPrototypeOf(obj));
    for(var key in obj){
        ret[key] = deepCopy(obj[key]);
    }
    return ret;
}

/**
 * Convert a (usually base64 encorded) dataURI image to a binary blob.
 * From: http://stackoverflow.com/questions/4998908
 */
function dataURItoBlob(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
    else
        byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    return new Blob([ia], {type:mimeString});
}

/**
 * Creates a jQuery UI based error dialog. If detail is passed, it is hidden by
 * default. The dialog allows to expand it, however.
 */
window.ErrorDialog = function(text, detail) {
  this.dialog = document.createElement('div');
  this.dialog.setAttribute("id", "dialog-confirm");
  this.dialog.setAttribute("title", "An error occured");
  // Create error message tags
  var msg = document.createElement('p');
  msg.appendChild(document.createTextNode(text));
  this.dialog.appendChild(msg);
  // Create detail field, if detail available
  if (detail) {
    var detail_head = document.createElement('p');
    var detail_head_em = document.createElement('em');
    detail_head_em.appendChild(document.createTextNode('Show/hide detail'));
    detail_head.appendChild(detail_head_em);
    this.dialog.appendChild(detail_head);
    var detail_text = document.createElement('p');
    detail_text.appendChild(document.createTextNode(detail));
    this.dialog.appendChild(detail_text);
    // Hide detail by default and toggle display by click on header
    $(detail_text).hide();
    $(detail_head).click(function() {
      $(detail_text).toggle();
    });
    $(detail_head_em).css('cursor', 'pointer');
  }
};

window.ErrorDialog.prototype = {};

/**
 * Displays the error dialog.
 */
window.ErrorDialog.prototype.show = function() {
  $(this.dialog).dialog({
    width: '400px',
    height: 'auto',
    modal: true,
    buttons: {
      "OK": function() {
        $(this).dialog("close");
      }
    }
  });
};

/**
 * Convenience function to show an error dialog.
 */
window.error = function(msg, detail)
{
  new ErrorDialog(msg, detail).show();
};

/**
 * Creates a generic JSON response handler that complains when the response
 * status is different from 200 or a JSON error is set.
 */
window.jsonResponseHandler = function(success, error)
{
  return function(status, text, xml) {
    if (status === 200 && text) {
      var json = $.parseJSON(text);
      if (json.error) {
        new ErrorDialog(json.error, json.detail).show();
        if (typeof(error) == 'function') {
          error();
        }
      } else {
        if (typeof(success) == 'function') {
          success(json);
        }
      }
    } else {
      new ErrorDialog("An error occured",
          "The server returned an unexpected status: " + status).show();
      if (typeof(error) == 'function') {
        error();
      }
    }
  };
};

/**
 * Creates a simple login dialog.
 */
window.LoginDialog = function(text, callback) {
  this.dialog = new OptionsDialog("Permission required");
  if (text) {
    this.dialog.appendMessage(text);
  }
  // Add short login text
  var login_text = "Please enter the credentials for a user with the " +
      "necessary credentials to continue to the requested information";
  this.dialog.appendMessage(login_text);
  // Add input fields
  var user_field = this.dialog.appendField('Username', 'username', '', true);
  var pass_field = this.dialog.appendField('Password', 'password', '', true);
  pass_field.setAttribute('type', 'password');
  // Align input fields better
  $(this.dialog.dialog).find('label').css('width', '25%');
  $(this.dialog.dialog).find('label').css('display', 'inline-block');

  // If OK is pressed, the dialog should cause a (re-)login
  this.dialog.onOK = function() {
    login($(user_field).val(), $(pass_field).val(), callback);
  };
};

window.LoginDialog.prototype = {};

/**
 * Displays the login dialog.
 */
window.LoginDialog.prototype.show = function() {
  this.dialog.show('400', 'auto', true);
};

/**
 * Definition of methods in CATMAID.tools namespace.
 */
(function(tools) {

  "use strict";

  /**
   * Does a simple user agent test and returns one of 'MAC', 'WIN', 'LINUX' or
   * 'UNKNOWN'.
   */
  tools.getOS = function()
  {
    var ua = navigator.userAgent.toUpperCase();
    if (-1 !== ua.indexOf('MAC')) {
      return 'MAC';
    } else if (-1 !== ua.indexOf('WIN')) {
      return 'WIN';
    } else if (-1 !== ua.indexOf('LINUX')) {
      return 'LINUX';
    } else {
      return 'UNKNOWN';
    }
  };

  /**
   * Compare two strings while respecting locales and numbers. This is
   * essentially a wrapper around String.localeCompare() to have one
   * place where it is parameterized.
   */
  tools.compareStrings = function(str1, str2)
  {
    return str1.localeCompare(str2, undefined, {numeric: true});
  };

  /**
   * Parse a string as integer or return false if this is not possible or the
   * integer is negative.
   */
  tools.parseIndex = function(str) {
    var pattern = /(\d+)$/;
    if (pattern.test(str)) return parseInt(RegExp.$1);
    else
    return false;
  };

  /**
   * Get a "unique" id for a new element in the DOM.
   */
  var UNIQUE_ID;
  tools.uniqueId = function() {
    if (!UNIQUE_ID) {
      UNIQUE_ID = Math.floor(1073741824 * Math.random());
    }
    return ++UNIQUE_ID;
  };

  /**
   * Parse the query part of the current URL
   */

  tools.parseQuery = function() {
    if (location.search) {
      var r, query;
      query = /\?(.*?)$/i;
      var r = query.exec(location.search);
      if (r) {
        var o, p, value;
        o = {};
        value = /([^&=]+)=([^&=]+)/gi;
        while (p = value.exec(r[1])) {
          o[p[1]] = p[2];
        }
        return o;
      } else
      return undefined;
    } else
    return undefined;
  };

})(CATMAID.tools);
<|endoftext|>


<commit_before>var queries = require('./queries');
var insertPlayer = queries.insertPlayer;
var utility = require('./utility');
var getData = utility.getData;
var async = require('async');
var db = require('./db');
var constants = require('./constants');
var max;
start();

function start()
{
    getSummaries(function(err)
    {
        if (err)
        {
            throw err;
        }
        return setTimeout(start, 1000);
    });
}

function getSummaries(cb)
{
    db.raw(`select max(match_id) from matches`).asCallback(function(err, result)
    {
        if (err)
        {
            return cb(err);
        }
        max = Number(result.rows[0].max);
        var min = max - 10000000;
        db.raw(`
        select distinct account_id
        from player_matches
        where match_id in (SELECT (?::bigint + random()*(?::bigint - ?::bigint))::bigint as rand
        from generate_series(1,50))
        and account_id < ? limit 100
        `, [min, max, min, constants.anonymous_account_id]).asCallback(function(err, results)
        {
            if (err)
            {
                return cb(err);
            }
            console.log('players sampled: %s', results.rows.length);
            var container = utility.generateJob("api_summaries",
            {
                players: results.rows
            });
            getData(container.url, function(err, body)
            {
                if (err)
                {
                    //couldn't get data from api, non-retryable
                    return cb(JSON.stringify(err));
                }
                //player summaries response
                async.each(body.response.players, function(player, cb)
                {
                    insertPlayer(db, player, cb);
                }, cb);
            });
        });
    });
}<commit_msg>fixed profiler requesting empty steamids<commit_after>var queries = require('./queries');
var insertPlayer = queries.insertPlayer;
var utility = require('./utility');
var getData = utility.getData;
var async = require('async');
var db = require('./db');
var constants = require('./constants');
var max;
start();

function start()
{
    getSummaries(function(err)
    {
        if (err)
        {
            throw err;
        }
        return setTimeout(start, 1000);
    });
}

function getSummaries(cb)
{
    db.raw(`select max(match_id) from matches`).asCallback(function(err, result)
    {
        if (err)
        {
            return cb(err);
        }
        max = Number(result.rows[0].max);
        var min = max - 10000000;
        db.raw(`
        select distinct account_id
        from player_matches
        where match_id in (SELECT (?::bigint + random()*(?::bigint - ?::bigint))::bigint as rand
        from generate_series(1,50))
        and account_id < ? limit 100
        `, [min, max, min, constants.anonymous_account_id]).asCallback(function(err, results)
        {
            if (err)
            {
                return cb(err);
            }
	    if (results.rows.length === 0)
	    {
		console.log('No Steamids to scan for...');
		return cb();
	    }
            console.log('players sampled: %s', results.rows.length);
            var container = utility.generateJob("api_summaries",
            {
                players: results.rows
            });
            getData(container.url, function(err, body)
            {
                if (err)
                {
                    //couldn't get data from api, non-retryable
                    return cb(JSON.stringify(err));
                }
                //player summaries response
                async.each(body.response.players, function(player, cb)
                {
                    insertPlayer(db, player, cb);
                }, cb);
            });
        });
    });
}
<|endoftext|>


<commit_before>/* eslint-disable no-process-env */
import path from 'path'
import ora from 'ora'
import execa from 'execa'
import split2 from 'split2'
import chalk from 'chalk'
import progrescii from 'progrescii'
import {noop, padEnd, throttle} from 'lodash'

// Use require.resolve to ensure it actually exists
const useProgress = (process.stderr && process.stderr.isTTY) && !process.env.CI
const binDir = path.join(__dirname, '..', '..', '..', 'vendor')
const yarnPath = require.resolve(path.join(binDir, 'yarn'))

export default function yarnWithProgress(args, options = {}) {
  /* eslint-disable no-console */
  const print = options.print || console.log
  const error = options.error || console.error
  /* eslint-enable no-console */

  const padLength = 'Resolving dependencies'.length
  const getProgressTemplate = (symbol, msg) =>
    `${symbol} ${padEnd(msg, padLength)} :b :p% (:ts)`

  const execOpts = Object.assign({
    cwd: options.rootDir || process.cwd(),
    env: {PATH: [binDir, process.env.PATH].join(path.delimiter)}
  }, options.execOpts || {})

  const nodePath = process.argv[0]
  const nodeArgs = [yarnPath].concat(args, ['--json', '--non-interactive'])

  const state = {firstStepReceived: false}

  // Yarn takes a while before starting to emit events, we want to show
  // some sort of indication while it's getting started
  onStep({data: {message: 'Resolving dependencies'}})
  onActivityStart({})

  const proc = execa(nodePath, nodeArgs, execOpts)
  proc.catch(onNativeError)

  // Will throw error async through the promise above
  if (!proc.stdout) {
    return proc
  }

  [proc.stdout, proc.stderr].forEach(stream => {
    stream
      .pipe(split2(JSON.parse))
      .on('data', onChunk)
      .on('error', onNativeError)
  })

  const interceptors = options.interceptors || {}
  const throttledOnProgressTick = throttle(onProgressTick, 50)

  function onChunk(event) { // eslint-disable-line complexity
    if (interceptors[event.type]) {
      return interceptors[event.type](event)
    }

    switch (event.type) {
      case 'error':
        return onError(event)
      case 'warning':
        return onWarning(event)
      case 'step':
        return onStep(event)
      case 'activityStart':
        return onActivityStart(event)
      case 'activityTick':
        return onActivityTick(event)
      case 'activitySetEnd':
      case 'activityEnd':
        return onActivityEnd(event)
      case 'progressStart':
        return onProgressStart(event)
      case 'progressTick':
        return throttledOnProgressTick(event)
      case 'progressFinish':
        return onProgressFinish(event)
      case 'success':
        return onSuccess(event)
      case 'finished':
        return onFinished(event)
      default:
        // console.log(event)
        return noop()
    }
  }

  function onActivityStart(event) {
    if (!state.step) {
      return
    }

    if (!state.firstStepReceived && state.spinner) {
      state.firstStepReceived = true
      onActivityEnd()
    }

    state.spinner = ora(state.step.message).start()
  }

  function onActivityTick(event) {
    if (!state.spinner) {
      return
    }

    state.spinner.text = `${state.step.message} (${event.data.name})`
  }

  function onActivityEnd(event) {
    if (!state.spinner) {
      return
    }

    state.spinner.text = state.step.message
    state.spinner.succeed()
  }

  function onProgressStart(event) {
    if (state.spinner) {
      state.spinner.stop()
    }

    if (useProgress) {
      state.progress = progrescii.create({
        template: getProgressTemplate(chalk.yellow('●'), state.step.message),
        total: event.data.total
      })
    } else {
      print(`${chalk.yellow('●')} ${state.step.message}`)
    }
  }

  function onProgressTick(event) {
    const prog = state.progress
    if (!prog) {
      return
    }

    if (event.data.current >= prog.total) {
      return // Will be taken care of by onProgressFinish
    }

    prog.set(event.data.current)
  }

  function onProgressFinish(event) {
    const prog = state.progress
    if (!prog) {
      return
    }

    prog.template = getProgressTemplate(chalk.green('✔'), state.step.message)
    prog.set(prog.total)
  }

  function onStep(event) {
    state.step = event.data
  }

  function onSuccess(event) {
    if (state.spinner) {
      state.spinner.stop()
    }

    print(`\n${chalk.green('✔')} Saved lockfile`)
  }

  function onFinished(event) {
    if (state.spinner) {
      state.spinner.stop()
    }

    const time = `${(event.data / 1000).toFixed(2)}s`
    print(`${chalk.green('✔')} Done in ${time}`)
  }

  function onWarning(event) {
    // For now, skip the warnings as they seem to only contain the first line of the text,
    // so it makes no sense to show it. Debug this later and consider reimplementing this.
    // holdSpinner(() => print(`${chalk.yellow('●')} ${event.data}`))
  }

  function onError(event) {
    // Skip certain errors from being logged
    if (shouldIgnoreError(event)) {
      return
    }

    if (state.spinner) {
      state.spinner.fail()
    }

    error(`${chalk.red('✖')} ${event.data}`)
  }

  function onNativeError(err) {
    if (state.spinner) {
      state.spinner.fail()
    }

    throw err
  }

  function holdSpinner(op) { // eslint-disable-line no-unused-vars
    if (state.spinner) {
      state.spinner.stop()
    }

    op()

    if (state.spinner) {
      state.spinner.start()
    }
  }

  return proc.catch(err => {
    const detailed = new Error('Command failed :(')
    detailed.code = err.code
    detailed.killed = err.killed
    detailed.err = err.message
    throw detailed
  })
}

const ignoredMessages = ['install script for optional dependency', 'Command failed: yarn']

function shouldIgnoreError(event) {
  if (!event || !event.data) {
    return false
  }

  return ignoredMessages.some(ignore => event.data.indexOf(ignore) !== -1)
}
<commit_msg>[cli] Filter yarn output (#331)<commit_after>/* eslint-disable no-process-env */
import path from 'path'
import ora from 'ora'
import execa from 'execa'
import split2 from 'split2'
import chalk from 'chalk'
import progrescii from 'progrescii'
import {noop, padEnd, throttle} from 'lodash'

// Use require.resolve to ensure it actually exists
const useProgress = (process.stderr && process.stderr.isTTY) && !process.env.CI
const binDir = path.join(__dirname, '..', '..', '..', 'vendor')
const yarnPath = require.resolve(path.join(binDir, 'yarn'))
const parseJson = data => {
  try {
    return JSON.parse(data)
  } catch (err) {
    return undefined
  }
}

export default function yarnWithProgress(args, options = {}) {
  /* eslint-disable no-console */
  const print = options.print || console.log
  const error = options.error || console.error
  /* eslint-enable no-console */

  const padLength = 'Resolving dependencies'.length
  const getProgressTemplate = (symbol, msg) =>
    `${symbol} ${padEnd(msg, padLength)} :b :p% (:ts)`

  const execOpts = Object.assign({
    cwd: options.rootDir || process.cwd(),
    env: {PATH: [binDir, process.env.PATH].join(path.delimiter)}
  }, options.execOpts || {})

  const nodePath = process.argv[0]
  const nodeArgs = [yarnPath].concat(args, ['--json', '--non-interactive'])

  const state = {firstStepReceived: false, currentProgressStep: null}

  // Yarn takes a while before starting to emit events, we want to show
  // some sort of indication while it's getting started
  onStep({data: {message: 'Resolving dependencies'}})
  onActivityStart({})

  const proc = execa(nodePath, nodeArgs, execOpts)
  proc.catch(onNativeError)

  // Will throw error async through the promise above
  if (!proc.stdout) {
    return proc
  }

  [proc.stdout, proc.stderr].forEach(stream => {
    stream
      .pipe(split2(parseJson))
      .on('data', onChunk)
      .on('error', onNativeError)
  })

  const interceptors = options.interceptors || {}
  const throttledOnProgressTick = throttle(onProgressTick, 50)

  function onChunk(event) { // eslint-disable-line complexity
    if (interceptors[event.type]) {
      return interceptors[event.type](event)
    }

    switch (event.type) {
      case 'error':
        return onError(event)
      case 'warning':
        return onWarning(event)
      case 'step':
        return onStep(event)
      case 'activityStart':
        return onActivityStart(event)
      case 'activityTick':
        return onActivityTick(event)
      case 'activitySetEnd':
      case 'activityEnd':
        return onActivityEnd(event)
      case 'progressStart':
        return onProgressStart(event)
      case 'progressTick':
        return throttledOnProgressTick(event)
      case 'progressFinish':
        return onProgressFinish(event)
      case 'success':
        return onSuccess(event)
      case 'finished':
        return onFinished(event)
      default:
        // console.log(event)
        return noop()
    }
  }

  function onActivityStart(event) {
    if (!state.step) {
      return
    }

    if (!state.firstStepReceived && state.spinner) {
      state.firstStepReceived = true
      onActivityEnd()
    }

    state.spinner = ora(state.step.message).start()
  }

  function onActivityTick(event) {
    if (!state.spinner) {
      return
    }

    state.spinner.text = `${state.step.message} (${event.data.name})`
  }

  function onActivityEnd(event) {
    if (!state.spinner) {
      return
    }

    state.spinner.text = state.step.message
    state.spinner.succeed()
  }

  function onProgressStart(event) {
    // For some events (Linking dependencies, for instance), multiple progress
    // start events are emitted, which doesn't look great. Skip those.
    if (state.step.message === state.currentProgressStep) {
      return
    }

    if (state.spinner) {
      state.spinner.stop()
    }

    if (useProgress && event.data.total) {
      state.currentProgressStep = state.step.message
      state.progress = progrescii.create({
        template: getProgressTemplate(chalk.yellow('●'), state.step.message),
        total: event.data.total
      })
    } else {
      print(`${chalk.yellow('●')} ${state.step.message}`)
    }
  }

  function onProgressTick(event) {
    const prog = state.progress
    if (!prog) {
      return
    }

    if (event.data.current >= prog.total) {
      return // Will be taken care of by onProgressFinish
    }

    prog.set(event.data.current)
  }

  function onProgressFinish(event) {
    const prog = state.progress
    if (!prog) {
      return
    }

    prog.template = getProgressTemplate(chalk.green('✔'), state.step.message)
    prog.set(prog.total)
  }

  function onStep(event) {
    state.step = event.data
  }

  function onSuccess(event) {
    if (state.spinner) {
      state.spinner.stop()
    }

    print(`\n${chalk.green('✔')} Saved lockfile`)
  }

  function onFinished(event) {
    if (state.spinner) {
      state.spinner.stop()
    }

    const time = `${(event.data / 1000).toFixed(2)}s`
    print(`${chalk.green('✔')} Done in ${time}`)
  }

  function onWarning(event) {
    // For now, skip the warnings as they seem to only contain the first line of the text,
    // so it makes no sense to show it. Debug this later and consider reimplementing this.
    // holdSpinner(() => print(`${chalk.yellow('●')} ${event.data}`))
  }

  function onError(event) {
    // Skip certain errors from being logged
    if (shouldIgnoreError(event)) {
      return
    }

    if (state.spinner) {
      state.spinner.fail()
    }

    error(`${chalk.red('✖')} ${event.data}`)
  }

  function onNativeError(err) {
    if (state.spinner) {
      state.spinner.fail()
    }

    throw err
  }

  function holdSpinner(op) { // eslint-disable-line no-unused-vars
    if (state.spinner) {
      state.spinner.stop()
    }

    op()

    if (state.spinner) {
      state.spinner.start()
    }
  }

  return proc.catch(err => {
    const detailed = new Error('Command failed :(')
    detailed.code = err.code
    detailed.killed = err.killed
    detailed.err = err.message
    throw detailed
  })
}

const ignoredMessages = ['install script for optional dependency', 'Command failed: yarn']

function shouldIgnoreError(event) {
  if (!event || !event.data) {
    return false
  }

  return ignoredMessages.some(ignore => event.data.indexOf(ignore) !== -1)
}
<|endoftext|>


<commit_before>'use strict';

define([
  'jquery',
  'views/reply-form-view'
], function ($, ReplyFormView) {
  var ReplyableView = {
    renderReplyBox: function (ev) {
      if (!this.replyBoxRendered) {
        this.renderIt(ev);
      }
      return false;
    },

    renderIt: function (ev) {
      var placeholder = $(ev.currentTarget).siblings();
      this.replyBox = new ReplyFormView({model: this.post, user: this.user, parentView: this, parentId: this.parentId()});
      this.replyBox.render();
      this.$(placeholder).html(this.replyBox.el);
    },

    parentId: function () {
      return 0;
    },

    replyRendered: function () {
      this.replyBoxRendered = true;
    },

    replyDestroyed: function () {
      this.replyBox = null;
      this.replyBoxRendered = false;
    },
  };

  return ReplyableView;
});<commit_msg>Minor adjustment to replyable-view placeholder<commit_after>'use strict';

define([
  'jquery',
  'views/reply-form-view'
], function ($, ReplyFormView) {
  var ReplyableView = {
    renderReplyBox: function (ev) {
      if (!this.replyBoxRendered) {
        this.renderIt(ev);
      }
      return false;
    },

    renderIt: function (ev) {
      var placeholder = $(ev.currentTarget).siblings('.b3-reply-section');
      this.replyBox = new ReplyFormView({model: this.post, user: this.user, parentView: this, parentId: this.parentId()});
      this.replyBox.render();
      this.$(placeholder).html(this.replyBox.el);
    },

    parentId: function () {
      return 0;
    },

    replyRendered: function () {
      this.replyBoxRendered = true;
    },

    replyDestroyed: function () {
      this.replyBox = null;
      this.replyBoxRendered = false;
    },
  };

  return ReplyableView;
});<|endoftext|>


<commit_before>/* global describe, it */

import assert from 'assert'
import React from 'react'
import {MemoryRouter} from 'react-router'
import {mount} from 'enzyme'
import {Broadcast} from 'react-broadcast'
import {Stepper, StepperStepFooter} from '../'
import {Button} from '../../..'

describe('Stepper', () => {
  it('should work', () => {
    const location = {pathname: '', search: '', hash: ''}
    const steps = [
      {
        title: 'first',
        href: '/first',
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: () =>
second

      }
    ]
    const wrapper = mount(
      <Broadcast channel='location' value={location}>
        <Stepper steps={steps} />
      </Broadcast>
    )
    assert.equal(wrapper.find('.Stepper').length, 1)
  })

  it('should work horizontal', () => {
    const location = {pathname: '', search: '', hash: ''}
    const steps = [
      {
        title: 'first',
        href: '/first',
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: () =>
second

      }
    ]
    const wrapper = mount(
      <Broadcast channel='location' value={location}>
        <Stepper steps={steps} horizontal />
      </Broadcast>
    )
    assert.equal(wrapper.find('.Stepper--horizontal').length, 1)
  })

  it('should work with optional text', () => {
    const location = {pathname: '', search: '', hash: ''}
    const optionalText = 'Optional'
    const steps = [
      {
        title: 'first',
        href: '/first',
        optional: optionalText,
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: () =>
second

      }
    ]
    const wrapper = mount(
      <Broadcast channel='location' value={location}>
        <Stepper steps={steps} />
      </Broadcast>
    )
    assert.equal(wrapper.find('.Stepper-step-optional').length, 1)
    assert(wrapper.find('.Stepper-step-optional').text(), optionalText)
  })

  it('should work with error', () => {
    const location = {pathname: '', search: '', hash: ''}
    const errorText = 'my error'
    const steps = [
      {
        title: 'first',
        href: '/first',
        error: {message: errorText},
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: () =>
second

      }
    ]
    const wrapper = mount(
      <Broadcast channel='location' value={location}>
        <Stepper steps={steps} />
      </Broadcast>
    )
    assert.equal(wrapper.find('.Stepper--error').length, 2)
    assert(wrapper.find('.Stepper--error > .Stepper-step-optional').text(), errorText)
  })

  it('should work StepperStepFooter', () => {
    const wrapper = mount(
      <StepperStepFooter />
    )
    assert.equal(wrapper.find('.Stepper-footer').length, 1)
  })

  it('should work StepperStepFooter with labels and callbacks', () => {
    const back = (index) => {}
    const cancel = () => {}
    const wrapper = mount(
      <StepperStepFooter
        labelBack='Back'
        labelNext='Next'
        labelCancel='Cancel'
        onBack={back}
        onNext={back}
        onCancel={cancel}
      />
    )
    assert.equal(wrapper.find('.Stepper-footer').length, 1)
    assert.equal(wrapper.find('.Stepper-step-back').length, 1)
    assert.equal(wrapper.find('.Stepper-step-next').length, 1)
    assert.equal(wrapper.find('.Stepper-step-cancel').length, 1)
  })

  it('should apply active class name to currently active step', () => {
    const location = {pathname: '/second', search: '', hash: ''}
    const steps = [
      {
        title: 'first',
        href: '/first',
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: () =>
second

      }
    ]
    const wrapper = mount(
      <Broadcast channel='location' value={location}>
        <Stepper steps={steps} />
      </Broadcast>
    )
    assert(wrapper.find('a[href="/second"]').hasClass('is-active'))
  })

  it('should apply active class name to currently active step and StepperStepFooter test next', () => {
    const location = {pathname: '/second', search: '', hash: ''}
    const step = ({index, isLast, cancel, back, next, error}) => (

step second

        <Button onClick={() => error(new Error('My Error'))}>
          Set error
        </Button>
        <Button onClick={() => error()}>
          Clear error
        </Button>
        <StepperStepFooter
          labelBack='Back'
          labelNext='Next'
          labelCancel='Cancel'
          onBack={back}
          onNext={next}
          onCancel={cancel}
        />

    )

    const steps = [
      {
        title: 'first',
        href: '/first',
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: step
      },
      {
        title: 'third',
        href: '/third',
        component: () =>
third

      }
    ]

    const onCancel = (index) => {
      // let num = index + 1
      // console.log('canceled at step' + num)
    }

    const onError = (index, message) => {
      // let steps = this.state.steps.slice()
      // if (index > 0 && index < steps.length) {
      //   steps[index].error = message
      //   this.setState({
      //     steps: steps
      //   })
      // }
    }

    const transitionTo = (href) => {
      console.log(href)
    }
    const wrapper = mount(
      <MemoryRouter initialEntries={[location.pathname]} initialIndex={0} >
        <Stepper
          steps={steps}
          onError={(i, me) => onError(i, me)}
          onCancel={(i) => onCancel(i)}
        />
      </MemoryRouter>
    , {context: {transitionTo: {transitionTo}}})
    assert(wrapper.find('a[href="/second"]').hasClass('is-active'))
    wrapper.find('.Stepper-step-next').childAt(0).simulate('click')
    // assert(wrapper.find('a[href="/third"]').hasClass('is-active'))
    // wrapper.find('.Stepper-title .Stepper-title-text')[1].simulate('click')
    // assert(wrapper.find('a[href="/second"]').hasClass('is-active'))
    // wrapper.find('.Stepper-step-back .Button').simulate('click')
    // wrapper.find('.Stepper-title .Stepper-title-text')[1].simulate('click')
    // assert(wrapper.find('a[href="/second"]').hasClass('is-active'))
    // wrapper.find('.Stepper-step-cancel .Button').simulate('click')
    console.log('--------------------------------------------------------------')
    console.log(wrapper.html())
  })
})
<commit_msg>Everything is tested<commit_after>/* global describe, it */

import assert from 'assert'
import React from 'react'
import {MemoryRouter} from 'react-router'
import {mount} from 'enzyme'
import {Broadcast} from 'react-broadcast'
import {Stepper, StepperStepFooter} from '../'
import {Button} from '../../..'

describe('Stepper', () => {
  it('should work', () => {
    const location = {pathname: '', search: '', hash: ''}
    const steps = [
      {
        title: 'first',
        href: '/first',
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: () =>
second

      }
    ]
    const wrapper = mount(
      <Broadcast channel='location' value={location}>
        <Stepper steps={steps} />
      </Broadcast>
    )
    assert.equal(wrapper.find('.Stepper').length, 1)
  })

  it('should work horizontal', () => {
    const location = {pathname: '', search: '', hash: ''}
    const steps = [
      {
        title: 'first',
        href: '/first',
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: () =>
second

      }
    ]
    const wrapper = mount(
      <Broadcast channel='location' value={location}>
        <Stepper steps={steps} horizontal />
      </Broadcast>
    )
    assert.equal(wrapper.find('.Stepper--horizontal').length, 1)
  })

  it('should work with optional text', () => {
    const location = {pathname: '', search: '', hash: ''}
    const optionalText = 'Optional'
    const steps = [
      {
        title: 'first',
        href: '/first',
        optional: optionalText,
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: () =>
second

      }
    ]
    const wrapper = mount(
      <Broadcast channel='location' value={location}>
        <Stepper steps={steps} />
      </Broadcast>
    )
    assert.equal(wrapper.find('.Stepper-step-optional').length, 1)
    assert(wrapper.find('.Stepper-step-optional').text(), optionalText)
  })

  it('should work with error', () => {
    const location = {pathname: '', search: '', hash: ''}
    const errorText = 'my error'
    const steps = [
      {
        title: 'first',
        href: '/first',
        error: {message: errorText},
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: () =>
second

      }
    ]
    const wrapper = mount(
      <Broadcast channel='location' value={location}>
        <Stepper steps={steps} />
      </Broadcast>
    )
    assert.equal(wrapper.find('.Stepper--error').length, 2)
    assert(wrapper.find('.Stepper--error > .Stepper-step-optional').text(), errorText)
  })

  it('should work StepperStepFooter', () => {
    const wrapper = mount(
      <StepperStepFooter />
    )
    assert.equal(wrapper.find('.Stepper-footer').length, 1)
  })

  it('should work StepperStepFooter with labels and callbacks', () => {
    const back = (index) => {}
    const cancel = () => {}
    const wrapper = mount(
      <StepperStepFooter
        labelBack='Back'
        labelNext='Next'
        labelCancel='Cancel'
        onBack={back}
        onNext={back}
        onCancel={cancel}
      />
    )
    assert.equal(wrapper.find('.Stepper-footer').length, 1)
    assert.equal(wrapper.find('.Stepper-step-back').length, 1)
    assert.equal(wrapper.find('.Stepper-step-next').length, 1)
    assert.equal(wrapper.find('.Stepper-step-cancel').length, 1)
  })

  it('should apply active class name to currently active step', () => {
    const location = {pathname: '/second', search: '', hash: ''}
    const steps = [
      {
        title: 'first',
        href: '/first',
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: () =>
second

      }
    ]
    const wrapper = mount(
      <Broadcast channel='location' value={location}>
        <Stepper steps={steps} />
      </Broadcast>
    )
    assert(wrapper.find('a[href="/second"]').hasClass('is-active'))
  })

  it('should apply active class name to currently active step and StepperStepFooter test next', () => {
    const step = ({index, isLast, cancel, back, next, error}) => (

step second

          <Button onClick={() => error(new Error('My Error'))}>
            Set error
          </Button>

          <Button onClick={() => error()}>
            Clear error
          </Button>

        <StepperStepFooter
          labelBack='Back'
          labelNext='Next'
          labelCancel='Cancel'
          onBack={back}
          onNext={next}
          onCancel={cancel}
        />

    )

    const steps = [
      {
        title: 'first',
        href: '/first',
        component: () =>
first

      },
      {
        title: 'second',
        href: '/second',
        component: step
      },
      {
        title: 'third',
        href: '/third',
        component: () =>
third

      }
    ]

    const onCancel = (index) => {
      // let num = index + 1
      // console.log('canceled at step' + num)
    }

    const onError = (index, message) => {
      // let steps = this.state.steps.slice()
      // if (index > 0 && index < steps.length) {
      //   steps[index].error = message
      //   this.setState({
      //     steps: steps
      //   })
      // }
    }

    let wrapper = mount(
      <MemoryRouter initialEntries={['/second']} initialIndex={0} >
        <Stepper
          steps={steps}
          onError={(i, me) => onError(i, me)}
          onCancel={(i) => onCancel(i)}
        />
      </MemoryRouter>
    )
    assert(wrapper.find('a[href="/second"]').hasClass('is-active'))
    wrapper.find('.Stepper-step-cancel').childAt(0).simulate('click')
    wrapper.find('.button-setError').childAt(0).simulate('click')
    wrapper.find('.button-clearError').childAt(0).simulate('click')
    wrapper.find('.Stepper-step-next').childAt(0).simulate('click')
    assert(wrapper.find('a[href="/third"]').hasClass('is-active'))

    wrapper = mount(
      <MemoryRouter initialEntries={['/second']} initialIndex={0} >
        <Stepper
          steps={steps}
          onError={(i, me) => onError(i, me)}
          onCancel={(i) => onCancel(i)}
        />
      </MemoryRouter>
    )
    assert(wrapper.find('a[href="/second"]').hasClass('is-active'))
    wrapper.find('.Stepper-step-back').childAt(0).simulate('click')
    assert(wrapper.find('a[href="/first"]').hasClass('is-active'))
  })
})
<|endoftext|>


<commit_before>/**
 * Select UI component
 *
 * @class select
 * @augments elation.ui.base
 * @memberof elation.ui
 * @todo this could probably inherit from ui.list to be more general
 *
 * @param {object} args
 * @param {string} args.items
 */
elation.require(['ui.base', 'ui.label'], function() {
  elation.component.add('ui.select', function() {
    this.defaultcontainer = { tag: 'div', classname: 'ui_select' };

    this.init = function() {
      if (this.args.label) {
        this.label = elation.ui.label({
          append: this,
          label: this.args.label,
          classname: 'ui_select_label'
        });
      }
      if (this.container instanceof HTMLSelectElement) {
        this.select = this.container;
      } else {
        this.select = elation.html.create({tag: 'select', append: this.container});
      }
      elation.events.add(this.select, "change", this);
      if (this.args.items) {
        this.setItems(this.args.items, this.args.selected);
      }
      this.value = this.select.value;
    }
    this.setItems = function(items, selected) {
      if (items instanceof Array) {
        this.set('args.items', items.join(';'));
      } else {
        this.set('args.items', items);
        items = items.split(';');
      }
      this.select.innerHTML = '';
      for (var i = 0; i < items.length; i++) {
        this.addItem(items[i]);
      }
      if (selected) {
        this.setSelected(selected);
      }
    }
    this.addItem = function(value, selected) {
      var option = elation.html.create({tag: 'option'});
      option.value = value;
      option.innerHTML = value;
      if (selected) {
        option.selected = selected;
      }
      this.select.appendChild(option);
    }
    this.setSelected = function(value) {
      this.value = value;
      var found = false;
      for (var i = 0; i < this.select.childNodes.length; i++) {
        var node = this.select.childNodes[i];
        if (node.value == value) {
          node.selected = true;
          found = true;
        } else {
          node.selected = false;
        }
      }
      if (!found) {
        this.addItem(value, true);
      }
    }
    this.change = function(ev) {
      this.value = this.select.value;
      // FIXME - instead of having custom events per-type, we should reuse common names like "change".
      //          Here we fire both for compatibility
      elation.events.fire({type: "ui_select_change", data: this.select.value, element: this});
      elation.events.fire({type: "change", data: this.select.value, element: this});
    }
  }, elation.ui.base);
});
<commit_msg>Call parent class init<commit_after>/**
 * Select UI component
 *
 * @class select
 * @augments elation.ui.base
 * @memberof elation.ui
 * @todo this could probably inherit from ui.list to be more general
 *
 * @param {object} args
 * @param {string} args.items
 */
elation.require(['ui.base', 'ui.label'], function() {
  elation.component.add('ui.select', function() {
    this.defaultcontainer = { tag: 'div', classname: 'ui_select' };

    this.init = function() {
      elation.ui.select.extendclass.init.call(this);

      if (this.args.label) {
        this.label = elation.ui.label({
          append: this,
          label: this.args.label,
          classname: 'ui_select_label'
        });
      }
      if (this.container instanceof HTMLSelectElement) {
        this.select = this.container;
      } else {
        this.select = elation.html.create({tag: 'select', append: this.container});
      }
      elation.events.add(this.select, "change", this);
      if (this.args.items) {
        this.setItems(this.args.items, this.args.selected);
      }
      this.value = this.select.value;
    }
    this.setItems = function(items, selected) {
      if (items instanceof Array) {
        this.set('args.items', items.join(';'));
      } else {
        this.set('args.items', items);
        items = items.split(';');
      }
      this.select.innerHTML = '';
      for (var i = 0; i < items.length; i++) {
        this.addItem(items[i]);
      }
      if (selected) {
        this.setSelected(selected);
      }
    }
    this.addItem = function(value, selected) {
      var option = elation.html.create({tag: 'option'});
      option.value = value;
      option.innerHTML = value;
      if (selected) {
        option.selected = selected;
      }
      this.select.appendChild(option);
    }
    this.setSelected = function(value) {
      this.value = value;
      var found = false;
      for (var i = 0; i < this.select.childNodes.length; i++) {
        var node = this.select.childNodes[i];
        if (node.value == value) {
          node.selected = true;
          found = true;
        } else {
          node.selected = false;
        }
      }
      if (!found) {
        this.addItem(value, true);
      }
    }
    this.change = function(ev) {
      this.value = this.select.value;
      // FIXME - instead of having custom events per-type, we should reuse common names like "change".
      //          Here we fire both for compatibility
      elation.events.fire({type: "ui_select_change", data: this.select.value, element: this});
      elation.events.fire({type: "change", data: this.select.value, element: this});
    }
  }, elation.ui.base);
});
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { DragSource } from 'react-dnd';
import { Autobind } from 'es-decorators';
import classNames from 'classnames';

// Store
import withRedux from 'next-redux-wrapper';
import { initStore } from 'store';
import { removeFilter, removeColor, removeDimensionX, removeDimensionY, removeSize } from 'redactions/widgetEditor';
import { toggleTooltip } from 'redactions/tooltip';

// Components
import Icon from 'components/ui/Icon';
import FilterTooltip from 'components/widgets/FilterTooltip';
import AggregateFunctionTooltip from 'components/widgets/AggregateFunctionTooltip';

/**
 * Implements the drag source contract.
 */
const columnBoxSource = {
  beginDrag(props) {
    return {
      name: props.name,
      type: props.type,
      datasetID: props.datasetID,
      tableName: props.tableName
    };
  }
};

/**
 * Specifies the props to inject into your component.
 */
function collect(connect, monitor) {
  return {
    connectDragSource: connect.dragSource(),
    isDragging: monitor.isDragging()
  };
}

class ColumnBox extends React.Component {

  /**
   * Return the position of the click within the page taking
   * into account the scroll (relative to the page, not the
   * viewport )
   * @static
   * @param {MouseEvent} e Event
   * @returns {{ x: number, y: number }}
   */
  static getClickPosition(e) {
    return {
      x: window.scrollX + e.clientX,
      y: window.scrollY + e.clientY
    };
  }

  constructor(props) {
    super(props);
    this.state = {
      // Value of the aggregate function for dimension X
      aggregateFunctionX: null,
      // Value of the aggregate function for dimension Y
      aggregateFunctionY: null,
      // Value of the filter
      filter: null
    };
  }

  componentWillReceiveProps(nextProps) {
    // We add a dragging cursor to the column box if it's being dragged
    // We have to set the CSS property to the body otherwise it won't be
    // taken into account
    if (nextProps.isDragging !== this.props.isDragging) {
      document.body.classList.toggle('-dragging', nextProps.isDragging);
    }
  }

  @Autobind
  onApplyFilter(filter) {
    this.setState({ filter });

    if (this.props.onConfigure) {
      this.props.onConfigure({ name: this.props.name, value: filter });
    }
  }

  @Autobind
  onApplyAggregateFunction(aggregateFunction) {
    this.setState({ aggregateFunction });
    console.log(aggregateFunction);
  }

  @Autobind
  triggerClose() {
    const { isA } = this.props;
    switch (isA) {
      case 'color':
        this.props.removeColor({ name: this.props.name });
        break;
      case 'size':
        this.props.removeSize({ name: this.props.name });
        break;
      case 'filter':
        this.props.removeFilter({ name: this.props.name });
        break;
      case 'dimensionX':
        this.props.removeDimensionX();
        break;
      case 'dimensionY':
        this.props.removeDimensionY();
        break;
      default:
    }
  }

  @Autobind
  triggerConfigure(event) {
    const { isA, name, type, datasetID, tableName } = this.props;

    switch (isA) {
      case 'color':
        break;
      case 'size':
        break;
      case 'filter':
        this.props.toggleTooltip(true, {
          follow: false,
          position: ColumnBox.getClickPosition(event),
          children: FilterTooltip,
          childrenProps: {
            name,
            type,
            datasetID,
            tableName,
            dimension: 'x',
            filter: this.state.filter,
            onApply: this.onApplyFilter
          }
        });
        break;
      case 'dimensionX':
        this.props.toggleTooltip(true, {
          follow: false,
          position: ColumnBox.getClickPosition(event),
          children: AggregateFunctionTooltip,
          childrenProps: {
            name,
            type,
            datasetID,
            tableName,
            dimension: 'x',
            onApply: this.onApplyAggregateFunction
          }
        });
        break;
      case 'dimensionY':
        this.props.toggleTooltip(true, {
          follow: false,
          position: ColumnBox.getClickPosition(event),
          children: AggregateFunctionTooltip,
          childrenProps: {
            name,
            type,
            datasetID,
            tableName,
            dimension: 'y',
            onApply: this.onApplyAggregateFunction
          }
        });
        break;
      default:
    }
  }

  render() {
    const { aggregateFunction } = this.state;
    const { isDragging, connectDragSource, name, type, closable, configurable } = this.props;
    const iconName = (type.toLowerCase() === 'string') ? 'icon-type' : 'icon-hash';

    return connectDragSource(

        <Icon
          name={iconName}
          className="-smaller"
        />
        {name}
        {aggregateFunction &&

            {aggregateFunction}

        }
        {closable &&
          <button onClick={this.triggerClose}>
            <Icon
              name="icon-cross"
              className="-smaller close-button"
            />
          </button>
        }
        {configurable &&
          <button onClick={this.triggerConfigure}>
            <Icon
              name="icon-cog"
              className="-smaller configure-button"
            />
          </button>
        }

    );
  }
}

ColumnBox.propTypes = {
  // NOTE: Don't make any of the following props as required as React will
  // throw prop checks errors because of react-dnd (don't know why)
  tableName: PropTypes.string,
  datasetID: PropTypes.string,
  name: PropTypes.string,
  type: PropTypes.string,
  isA: PropTypes.string,
  closable: PropTypes.bool,
  configurable: PropTypes.bool,
  onConfigure: PropTypes.func,
  // Injected by React DnD:
  isDragging: PropTypes.bool,
  connectDragSource: PropTypes.func,
  // ACTIONS
  removeFilter: PropTypes.func.isRequired,
  removeSize: PropTypes.func.isRequired,
  removeColor: PropTypes.func.isRequired,
  removeDimensionX: PropTypes.func.isRequired,
  removeDimensionY: PropTypes.func.isRequired,
  toggleTooltip: PropTypes.func.isRequired
};

const mapDispatchToProps = dispatch => ({
  removeFilter: (filter) => {
    dispatch(removeFilter(filter));
  },
  removeColor: (color) => {
    dispatch(removeColor(color));
  },
  removeSize: (size) => {
    dispatch(removeSize(size));
  },
  removeDimensionX: (dimensionX) => {
    dispatch(removeDimensionX(dimensionX));
  },
  removeDimensionY: (dimensionY) => {
    dispatch(removeDimensionY(dimensionY));
  },
  toggleTooltip: (opened, opts) => {
    dispatch(toggleTooltip(opened, opts));
  }
});

export default DragSource('columnbox', columnBoxSource, collect)(withRedux(initStore, null, mapDispatchToProps)(ColumnBox));
<commit_msg>only show aggregate function when is different to none<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { DragSource } from 'react-dnd';
import { Autobind } from 'es-decorators';
import classNames from 'classnames';

// Store
import withRedux from 'next-redux-wrapper';
import { initStore } from 'store';
import { removeFilter, removeColor, removeDimensionX, removeDimensionY, removeSize } from 'redactions/widgetEditor';
import { toggleTooltip } from 'redactions/tooltip';

// Components
import Icon from 'components/ui/Icon';
import FilterTooltip from 'components/widgets/FilterTooltip';
import AggregateFunctionTooltip from 'components/widgets/AggregateFunctionTooltip';

/**
 * Implements the drag source contract.
 */
const columnBoxSource = {
  beginDrag(props) {
    return {
      name: props.name,
      type: props.type,
      datasetID: props.datasetID,
      tableName: props.tableName
    };
  }
};

/**
 * Specifies the props to inject into your component.
 */
function collect(connect, monitor) {
  return {
    connectDragSource: connect.dragSource(),
    isDragging: monitor.isDragging()
  };
}

class ColumnBox extends React.Component {

  /**
   * Return the position of the click within the page taking
   * into account the scroll (relative to the page, not the
   * viewport )
   * @static
   * @param {MouseEvent} e Event
   * @returns {{ x: number, y: number }}
   */
  static getClickPosition(e) {
    return {
      x: window.scrollX + e.clientX,
      y: window.scrollY + e.clientY
    };
  }

  constructor(props) {
    super(props);
    this.state = {
      // Value of the aggregate function
      aggregateFunction: null,
      // Value of the filter
      filter: null
    };
  }

  componentWillReceiveProps(nextProps) {
    // We add a dragging cursor to the column box if it's being dragged
    // We have to set the CSS property to the body otherwise it won't be
    // taken into account
    if (nextProps.isDragging !== this.props.isDragging) {
      document.body.classList.toggle('-dragging', nextProps.isDragging);
    }
  }

  @Autobind
  onApplyFilter(filter) {
    this.setState({ filter });

    if (this.props.onConfigure) {
      this.props.onConfigure({ name: this.props.name, value: filter });
    }
  }

  @Autobind
  onApplyAggregateFunction(aggregateFunction) {
    this.setState({ aggregateFunction });
  }

  @Autobind
  triggerClose() {
    const { isA } = this.props;
    switch (isA) {
      case 'color':
        this.props.removeColor({ name: this.props.name });
        break;
      case 'size':
        this.props.removeSize({ name: this.props.name });
        break;
      case 'filter':
        this.props.removeFilter({ name: this.props.name });
        break;
      case 'dimensionX':
        this.props.removeDimensionX();
        break;
      case 'dimensionY':
        this.props.removeDimensionY();
        break;
      default:
    }
  }

  @Autobind
  triggerConfigure(event) {
    const { isA, name, type, datasetID, tableName } = this.props;

    switch (isA) {
      case 'color':
        break;
      case 'size':
        break;
      case 'filter':
        this.props.toggleTooltip(true, {
          follow: false,
          position: ColumnBox.getClickPosition(event),
          children: FilterTooltip,
          childrenProps: {
            name,
            type,
            datasetID,
            tableName,
            dimension: 'x',
            filter: this.state.filter,
            onApply: this.onApplyFilter
          }
        });
        break;
      case 'dimensionX':
        this.props.toggleTooltip(true, {
          follow: false,
          position: ColumnBox.getClickPosition(event),
          children: AggregateFunctionTooltip,
          childrenProps: {
            name,
            type,
            datasetID,
            tableName,
            dimension: 'x',
            onApply: this.onApplyAggregateFunction
          }
        });
        break;
      case 'dimensionY':
        this.props.toggleTooltip(true, {
          follow: false,
          position: ColumnBox.getClickPosition(event),
          children: AggregateFunctionTooltip,
          childrenProps: {
            name,
            type,
            datasetID,
            tableName,
            dimension: 'y',
            onApply: this.onApplyAggregateFunction
          }
        });
        break;
      default:
    }
  }

  render() {
    const { aggregateFunction } = this.state;
    const { isDragging, connectDragSource, name, type, closable, configurable } = this.props;
    const iconName = (type.toLowerCase() === 'string') ? 'icon-type' : 'icon-hash';

    return connectDragSource(

        <Icon
          name={iconName}
          className="-smaller"
        />
        {name}
        {aggregateFunction && aggregateFunction !== 'none' &&

            {aggregateFunction}

        }
        {closable &&
          <button onClick={this.triggerClose}>
            <Icon
              name="icon-cross"
              className="-smaller close-button"
            />
          </button>
        }
        {configurable &&
          <button onClick={this.triggerConfigure}>
            <Icon
              name="icon-cog"
              className="-smaller configure-button"
            />
          </button>
        }

    );
  }
}

ColumnBox.propTypes = {
  // NOTE: Don't make any of the following props as required as React will
  // throw prop checks errors because of react-dnd (don't know why)
  tableName: PropTypes.string,
  datasetID: PropTypes.string,
  name: PropTypes.string,
  type: PropTypes.string,
  isA: PropTypes.string,
  closable: PropTypes.bool,
  configurable: PropTypes.bool,
  onConfigure: PropTypes.func,
  // Injected by React DnD:
  isDragging: PropTypes.bool,
  connectDragSource: PropTypes.func,
  // ACTIONS
  removeFilter: PropTypes.func.isRequired,
  removeSize: PropTypes.func.isRequired,
  removeColor: PropTypes.func.isRequired,
  removeDimensionX: PropTypes.func.isRequired,
  removeDimensionY: PropTypes.func.isRequired,
  toggleTooltip: PropTypes.func.isRequired
};

const mapDispatchToProps = dispatch => ({
  removeFilter: (filter) => {
    dispatch(removeFilter(filter));
  },
  removeColor: (color) => {
    dispatch(removeColor(color));
  },
  removeSize: (size) => {
    dispatch(removeSize(size));
  },
  removeDimensionX: (dimensionX) => {
    dispatch(removeDimensionX(dimensionX));
  },
  removeDimensionY: (dimensionY) => {
    dispatch(removeDimensionY(dimensionY));
  },
  toggleTooltip: (opened, opts) => {
    dispatch(toggleTooltip(opened, opts));
  }
});

export default DragSource('columnbox', columnBoxSource, collect)(withRedux(initStore, null, mapDispatchToProps)(ColumnBox));
<|endoftext|>


<commit_before>var DtlsSrtpKeyAgreement = {
   DtlsSrtpKeyAgreement: true
};

var optional = {
   optional: [DtlsSrtpKeyAgreement]
};

var pc;
var remoteStream;

// Set up audio and video regardless of what devices are present.
var sdpConstraints = {'mandatory': {
                      'OfferToReceiveAudio': true,
                      'OfferToReceiveVideo': true }};

function onIceCandidate(event) {
    Visio.log('onIceCandidate');
    Visio.log(event);
}

function onIceConnectionStateChanged(event) {
    Visio.log('onIceConnectionStateChanged');
    Visio.log(event);
}

function onSignalingStateChanged(event) {
    Visio.log('onSignalingStateChanged');
    Visio.log(event);
}

function onRemoteStreamAdded(event) {
    var vid = document.getElementById('remote-video');

    vid.src = window.URL.createObjectURL(event.stream);

    /*remoteStream = event.stream;

    audioTracks = remoteStream.getAudioTracks();

    for (i = 0; i < audioTracks.length; i++) {
      audioTracks[i].enabled = true;
    }*/
}

function onError(err) {
    window.alert(err.message);
}

function onOfferCreated(offer) {
    //Visio.log(offer);

    pc.setLocalDescription(offer,onSetSessionDescriptionSuccess, onSetSessionDescriptionError);

    sendMessage(offer);
}

function onAnswerCreated(offer) {
    //Visio.log(offer);

    pc.setLocalDescription(offer,onSetSessionDescriptionSuccess, onSetSessionDescriptionError);

    sendMessage(offer, true);
}

function sendMessage(msg, accept) {
    offer = {};
    offer.sdp = msg.sdp;
    offer.jid = VISIO_JID;
    offer.ressource = VISIO_RESSOURCE;

    var msgString = JSON.stringify(offer);

    if(accept) {
        Visio.log('Send the acceptance.');
        Visio.log('ACCEPTANCE ' + msg.sdp);
        Visio.call(['VisioExt_ajaxSendAcceptance', msgString]);
    } else {
        Visio.log('Send the proposal.');
        Visio.log('PROPOSAL ' + msg.sdp);
        Visio.call(['VisioExt_ajaxSendProposal', msgString]);
    }
}

function onSetSessionDescriptionSuccess() {
    Visio.log('Set session description success.');
}

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

function onSetRemoteSessionDescriptionSuccess() {
    Visio.log('Set remote session description success.');
}

function onSetRemoteSessionDescriptionError(error) {
    Visio.log('Failed to set remote session description: ' + error.message);
}

function onOffer(offer) {
    offer = offer[0];

    Visio.log('Offer received.');
    Visio.log('OFFER ' + offer);

    if(!pc)
        init(false);

    if(offer != null) {
        var desc = new RTCSessionDescription();
        desc.sdp = offer;
        desc.type = 'offer';

        pc.setRemoteDescription(desc,
            onSetRemoteSessionDescriptionSuccess, onSetRemoteSessionDescriptionError);
    }
}

function onAccept(offer) {
    offer = offer[0];

    Visio.log('Accept received.');
    Visio.log('ACCEPT ' + offer);

    if(offer != null) {
        var desc = new RTCSessionDescription();
        desc.sdp = offer;
        desc.type = 'answer';

        pc.setRemoteDescription(desc,
            onSetRemoteSessionDescriptionSuccess, onSetRemoteSessionDescriptionError);
    }
}

function init(isCaller) {
    var configuration = {"iceServers":[{"url": "stun:23.21.150.121:3478"}]};

    try {
        pc = new RTCPeerConnection(configuration, optional);

        pc.onicecandidate = onIceCandidate;
        pc.onsignalingstatechange = onSignalingStateChanged;
        pc.oniceconnectionstatechange = onIceConnectionStateChanged;
        pc.onaddstream = onRemoteStreamAdded;
    } catch (e) {
        Visio.log('Failed to create PeerConnection, exception: ' + e.message);
        alert('Cannot create RTCPeerConnection object; \
              WebRTC is not supported by this browser.');
        return;
    }

    if(getUserMedia) {
        if (getUserMedia) {
            getUserMedia = getUserMedia.bind(navigator);
        }

        // Request the camera.
        getUserMedia(
        // Constraints
        {
          video: true, audio: true
        },

        // Success Callback
        function(localMediaStream) {
            // Get a reference to the video element on the page.
            var vid = document.getElementById('local-video');
            var avatar = document.getElementById('avatar');

            // Create an object URL for the video stream and use this
            // to set the video source.
            vid.src = window.URL.createObjectURL(localMediaStream);

            setTimeout(
                function() {
                    vid.className = 'tiny';
                    avatar.className = 'tiny';
                },
                3000);

            Visio.log(localMediaStream);

            pc.addStream(localMediaStream);
            channel = pc.createDataChannel("visio");

            console.log(pc);

            if(isCaller)
                pc.createOffer(onOfferCreated, onError);
            else
                pc.createAnswer(onAnswerCreated, onError);

            //pc.createOffer(onOfferCreated, onError);
        },

        // Error Callback
        function(err) {
            // Log the error to the console.
            Visio.log('The following error occurred when trying to use getUserMedia: ' + err);
        }

        );
    } else {
        alert('Sorry, your browser does not support getUserMedia');
    }

    //Visio.log(pc);
}

function terminate() {
    pc.close();
    Visio.call(['VisioExt_ajaxSendSessionTerminate'], VISIO_JID, VISIO_RESSOURCE);

    // Get a reference to the video elements on the page.
    var vid = document.getElementById('local-video');
    var rvid = document.getElementById('remote-video');
    var avatar = document.getElementById('avatar');
    vid.className = vid.className.replace('tiny', 'off');
    rvid.className = 'off';
    avatar.className = avatar.className.replace('tiny', '');
}
<commit_msg>- fixed VisioExt_ajaxSendSessionTerminate call<commit_after>var DtlsSrtpKeyAgreement = {
   DtlsSrtpKeyAgreement: true
};

var optional = {
   optional: [DtlsSrtpKeyAgreement]
};

var pc;
var remoteStream;

// Set up audio and video regardless of what devices are present.
var sdpConstraints = {'mandatory': {
                      'OfferToReceiveAudio': true,
                      'OfferToReceiveVideo': true }};

function onIceCandidate(event) {
    Visio.log('onIceCandidate');
    Visio.log(event);
}

function onIceConnectionStateChanged(event) {
    Visio.log('onIceConnectionStateChanged');
    Visio.log(event);
}

function onSignalingStateChanged(event) {
    Visio.log('onSignalingStateChanged');
    Visio.log(event);
}

function onRemoteStreamAdded(event) {
    var vid = document.getElementById('remote-video');

    vid.src = window.URL.createObjectURL(event.stream);

    /*remoteStream = event.stream;

    audioTracks = remoteStream.getAudioTracks();

    for (i = 0; i < audioTracks.length; i++) {
      audioTracks[i].enabled = true;
    }*/
}

function onError(err) {
    window.alert(err.message);
}

function onOfferCreated(offer) {
    //Visio.log(offer);

    pc.setLocalDescription(offer,onSetSessionDescriptionSuccess, onSetSessionDescriptionError);

    sendMessage(offer);
}

function onAnswerCreated(offer) {
    //Visio.log(offer);

    pc.setLocalDescription(offer,onSetSessionDescriptionSuccess, onSetSessionDescriptionError);

    sendMessage(offer, true);
}

function sendMessage(msg, accept) {
    offer = {};
    offer.sdp = msg.sdp;
    offer.jid = VISIO_JID;
    offer.ressource = VISIO_RESSOURCE;

    var msgString = JSON.stringify(offer);

    if(accept) {
        Visio.log('Send the acceptance.');
        Visio.log('ACCEPTANCE ' + msg.sdp);
        Visio.call(['VisioExt_ajaxSendAcceptance', msgString]);
    } else {
        Visio.log('Send the proposal.');
        Visio.log('PROPOSAL ' + msg.sdp);
        Visio.call(['VisioExt_ajaxSendProposal', msgString]);
    }
}

function onSetSessionDescriptionSuccess() {
    Visio.log('Set session description success.');
}

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

function onSetRemoteSessionDescriptionSuccess() {
    Visio.log('Set remote session description success.');
}

function onSetRemoteSessionDescriptionError(error) {
    Visio.log('Failed to set remote session description: ' + error.message);
}

function onOffer(offer) {
    offer = offer[0];

    Visio.log('Offer received.');
    Visio.log('OFFER ' + offer);

    if(!pc)
        init(false);

    if(offer != null) {
        var desc = new RTCSessionDescription();
        desc.sdp = offer;
        desc.type = 'offer';

        pc.setRemoteDescription(desc,
            onSetRemoteSessionDescriptionSuccess, onSetRemoteSessionDescriptionError);
    }
}

function onAccept(offer) {
    offer = offer[0];

    Visio.log('Accept received.');
    Visio.log('ACCEPT ' + offer);

    if(offer != null) {
        var desc = new RTCSessionDescription();
        desc.sdp = offer;
        desc.type = 'answer';

        pc.setRemoteDescription(desc,
            onSetRemoteSessionDescriptionSuccess, onSetRemoteSessionDescriptionError);
    }
}

function init(isCaller) {
    var configuration = {"iceServers":[{"url": "stun:23.21.150.121:3478"}]};

    try {
        pc = new RTCPeerConnection(configuration, optional);

        pc.onicecandidate = onIceCandidate;
        pc.onsignalingstatechange = onSignalingStateChanged;
        pc.oniceconnectionstatechange = onIceConnectionStateChanged;
        pc.onaddstream = onRemoteStreamAdded;
    } catch (e) {
        Visio.log('Failed to create PeerConnection, exception: ' + e.message);
        alert('Cannot create RTCPeerConnection object; \
              WebRTC is not supported by this browser.');
        return;
    }

    if(getUserMedia) {
        if (getUserMedia) {
            getUserMedia = getUserMedia.bind(navigator);
        }

        // Request the camera.
        getUserMedia(
        // Constraints
        {
          video: true, audio: true
        },

        // Success Callback
        function(localMediaStream) {
            // Get a reference to the video element on the page.
            var vid = document.getElementById('local-video');
            var avatar = document.getElementById('avatar');

            // Create an object URL for the video stream and use this
            // to set the video source.
            vid.src = window.URL.createObjectURL(localMediaStream);

            setTimeout(
                function() {
                    vid.className = 'tiny';
                    avatar.className = 'tiny';
                },
                3000);

            Visio.log(localMediaStream);

            pc.addStream(localMediaStream);
            channel = pc.createDataChannel("visio");

            console.log(pc);

            if(isCaller)
                pc.createOffer(onOfferCreated, onError);
            else
                pc.createAnswer(onAnswerCreated, onError);

            //pc.createOffer(onOfferCreated, onError);
        },

        // Error Callback
        function(err) {
            // Log the error to the console.
            Visio.log('The following error occurred when trying to use getUserMedia: ' + err);
        }

        );
    } else {
        alert('Sorry, your browser does not support getUserMedia');
    }

    //Visio.log(pc);
}

function terminate() {
    pc.close();
    Visio.call(['VisioExt_ajaxSendSessionTerminate', VISIO_JID, VISIO_RESSOURCE]);

    // Get a reference to the video elements on the page.
    var vid = document.getElementById('local-video');
    var rvid = document.getElementById('remote-video');
    var avatar = document.getElementById('avatar');
    vid.className = vid.className.replace('tiny', 'off');
    rvid.className = 'off';
    avatar.className = avatar.className.replace('tiny', '');
}
<|endoftext|>