<commit_before>module.exports = function(sceneName,sceneParam,fadeConfig) {
  fadeConfig = fadeConfig || {};
  var fader = Crafty.e('2D, DOM, Tween, Persist')
    .attr({
      alpha: 0.0,
      x: fadeConfig.x1 || 0,
      y: fadeConfig.y1 || 0,
      w: fadeConfig.w1 || Crafty.viewport.width,
      h: fadeConfig.h1 || Crafty.viewport.height
    })
    .css('background-color','white')
    .one('TweenEnd',function() {
      this.one('TweenEnd', this.destroy)
      .tween({alpha:0.0},500);
      Crafty.enterScene(sceneName,sceneParam);

    })
    .tween({alpha:1.0},500);
  fader.z = 1000;
};
<commit_msg>possibly fixed fader position<commit_after>module.exports = function(sceneName,sceneParam,fadeConfig) {
  fadeConfig = fadeConfig || {};
  var fader = Crafty.e('2D, DOM, Tween, Persist')
    .attr({
      alpha: 0.0,
      x: Math.abs(Crafty.viewport.x),
      y: Math.abs(Crafty.viewport.y),
      w: Crafty.viewport.width,
      h: Crafty.viewport.height
    })
    .css('background-color','white')
    .one('TweenEnd',function() {
      this.one('TweenEnd', this.destroy)
      .attr({
        alpha: 0.0,
        x: Math.abs(Crafty.viewport.x),
        y: Math.abs(Crafty.viewport.y),
        w: Crafty.viewport.width,
        h: Crafty.viewport.height
      })
      .tween({alpha:0.0},500);
      Crafty.enterScene(sceneName,sceneParam);

    })
    .tween({alpha:1.0},500);
  fader.z = 1000;
};<|endoftext|>


<commit_before>/**
 * @typedef {ColumnInfo} Description of the columns of tabular data.
 * @property {number} dateIndex - Date index.
 * @property {number} payeeIndex - Payee index.
 * @property {number} inflowIndex - Inflow index.
 */

/**
 * Map a [header type] to an [array of possible header labels].
 */
let POSSIBLE_HEADER_LABELS = {
  dateIndex: ['datum', 'date', 'data'],
  payeeIndex: ['mottagare', 'transaktion', 'payee', 'descrição', 'histórico', 'lançamento'],
  inflowIndex: ['belopp', 'belopp sek', 'inflow', 'value', 'valor']
}

/**
 * Find information about the columns of tabular data.
 * @param  {TabularData} tabularData - Tabular data.
 * @return {ColumnInfo} Column information.
 */
function getColumnInfo(tabularData, domSelectionRange) {
  var columnInfo;
  //1: try using the table header
  if (tabularData.header) {
    columnInfo = findIndexesFromHeader(tabularData.header)
    // if (isValid(columnInfo)) { return columnInfo }
  }

  // 2: try using the table values
  columnInfo = findIndexesFromValues(tabularData.data)
  // if (isValid(columnInfo)) { return columnInfo }
  //
  throw Error('Could not find column information.')
}

/**
 * Find the index of each header type based on the header labels.
 * @param {string[]} tableHeaderLabels - Labels on the table headers.
 * @return {ColumnInfo} Column information.
 */
function findIndexesFromHeader(tableHeaderLabels) {
  var columnInfo = {}

  for(var headerType in POSSIBLE_HEADER_LABELS) {
    var possibleHeaderLabels = POSSIBLE_HEADER_LABELS[headerType]
    var index = findHeaderIndexByLabel(tableHeaderLabels, possibleHeaderLabels)
    if(index >= 0) {
      columnInfo[headerType] = index
    }
  }

  return columnInfo
}

/**
 * Find the index of each header type based on the table values.
 * @param {string[]} tableValues - Table values.
 * @return {ColumnInfo} Column information.
 */
function findIndexesFromValues(tableHeaderLabels) {
  //TODO
  return {}
}

/**
 * Given all the table headers, find the index of the header with the label more similar to the provided labels.
 * @param {string[]} tableHeaderLabels - Labels on the table headers.
 * @param {string[]} possibleLabelsForHeader - Possible labels for the searched header (in decrescent order of priority).
 * @return {number|undefined} Index of the header or undefined, if not found.
 *
 * Example: find the 'inflow' header index
 * - tableHeaderLabels = ['date', 'Amount', 'Balance $']
 * - possibleLabelsForHeader = ['total', 'amount', 'value', '$']
 * Returns 1, since there were 2 matches ('Amount' ~ 'amount' and 'Balance $' ~ '$'), but the first had greater priority.
 */
function findHeaderIndexByLabel(tableHeaderLabels, possibleLabelsForHeader) {
  var bestMatch = undefined

  for (var headerIdx = 0  headerIdx < tableHeaderLabels.length  headerIdx++) {
    var headerLabel = tableHeaderLabels[headerIdx]

    // Index of possibleLabelsForHeader is usead as priority (smaller index = higher priority)
    for (var prio = 0  prio < possibleLabelsForHeader.length  prio++) {
      var possibleHeader = possibleLabelsForHeader[prio]

      if(containsIgnoringCase(headerLabel, possibleHeader)) {
        //match!
        if (bestMatch === undefined || prio < bestMatch.prio) {
          bestMatch = {
            prio: prio,
            index: headerIdx
          }
        }
      }
    }
  }
  if (bestMatch === undefined) {
    return undefined
  }
  return bestMatch.index
}

/**
 * Check if the column info is valid.
 * @param  {ColumnInfo} Column information.
 * @return {Boolean}
 */
function isValid (columnInfo) {
  // TODO
  return false
}

/**
 * TODO: Move to jsturbo
 * Check if a string contains another string ignoring case.
 * @param  {string} str - String where the search should be executed.
 * @param  {string} searched - String that should be contained.
 * @return {Boolean}
 */
function containsIgnoringCase(str, searched) {
  return str.toLowerCase().indexOf(searched.toLowerCase()) >= 0
}

module.exports = {
  getColumnInfo: getColumnInfo
}
<commit_msg>column-finder first implementation ready to test.<commit_after>import JsTurbo from 'jsturbo'

/**
 * @typedef {ColumnInfo} Description of the columns of tabular data.
 * @property {number} dateIndex - Date index.
 * @property {number} payeeIndex - Payee index.
 * @property {number} inflowIndex - Inflow index.
 */

/**
 * Map a [header type] to an [array of possible header labels].
 */
let POSSIBLE_HEADER_LABELS = {
  dateIndex: ['datum', 'date', 'data'],
  payeeIndex: ['mottagare', 'transaktion', 'payee', 'descrição', 'histórico', 'lançamento'],
  inflowIndex: ['belopp', 'belopp sek', 'inflow', 'value', 'valor']
}

/**
 * Find information about the columns of tabular data.
 * @param  {TabularData} tabularData - Tabular data.
 * @return {ColumnInfo} Column information.
 */
function getColumnInfo(tabularData, domSelectionRange) {
  var columnInfo;
  //1: try using the table header
  if (tabularData.header) {
    columnInfo = findIndexesFromHeader(tabularData.header)
    if (isValid(columnInfo)) {
      return columnInfo
    }
  }

  // 2: try using the table values
  columnInfo = findIndexesFromValues(tabularData.data)
  if (isValid(columnInfo)) {
    return columnInfo
  }
  throw Error('Could not find column information.')
}

/**
 * Find the index of each header type based on the header labels.
 * @param {string[]} tableHeaderLabels - Labels on the table headers.
 * @return {ColumnInfo} Column information.
 */
function findIndexesFromHeader(tableHeaderLabels) {
  var columnInfo = {}
  for(var headerType in POSSIBLE_HEADER_LABELS) {
    var possibleHeaderLabels = POSSIBLE_HEADER_LABELS[headerType]
    var index = findHeaderIndexByLabel(tableHeaderLabels, possibleHeaderLabels)
    if(index >= 0) {
      columnInfo[headerType] = index
    }
  }
  return columnInfo
}

/**
 * Find the index of each header type based on the table values.
 * @param {string[]} tableValues - Table values.
 * @return {ColumnInfo} Column information.
 */
function findIndexesFromValues(tableValues) {
  var row = tableValues[0]
  var columnInfo = {}

  for (var i = 0; i < row.length; i++) {
    if (JsTurbo.date.isDate(row[i])) {
      columnInfo.dateIndex = i
      break
    }
  }

  for (var i = 0; i < row.length; i++) {
    if (JsTurbo.str.isNumber(row[i])) {
      columnInfo.inflowIndex = i
      break
    }
  }

  for (var i = 0; i < row.length; i++) {
    // Payee: at least 3 letters
    if (JsTurbo.str.containsAlpha(row[i], 3)) {
      columnInfo.payeeIndex = i
      break
    }
  }
  return columnInfo
}

/**
 * Given all the table headers, find the index of the header with the label more similar to the provided labels.
 * @param {string[]} tableHeaderLabels - Labels on the table headers.
 * @param {string[]} possibleLabelsForHeader - Possible labels for the searched header (in decrescent order of priority).
 * @return {number|undefined} Index of the header or undefined, if not found.
 *
 * Example: find the 'inflow' header index
 * - tableHeaderLabels = ['date', 'Amount', 'Balance $']
 * - possibleLabelsForHeader = ['total', 'amount', 'value', '$']
 * Returns 1, since there were 2 matches ('Amount' ~ 'amount' and 'Balance $' ~ '$'), but the first had greater priority.
 */
function findHeaderIndexByLabel(tableHeaderLabels, possibleLabelsForHeader) {
  var bestMatch = undefined

  for (var headerIdx = 0  headerIdx < tableHeaderLabels.length  headerIdx++) {
    var headerLabel = tableHeaderLabels[headerIdx]

    // Index of possibleLabelsForHeader is usead as priority (smaller index = higher priority)
    for (var prio = 0  prio < possibleLabelsForHeader.length  prio++) {
      var possibleHeader = possibleLabelsForHeader[prio]

      if(containsIgnoringCase(headerLabel, possibleHeader)) {
        //match!
        if (bestMatch === undefined || prio < bestMatch.prio) {
          bestMatch = {
            prio: prio,
            index: headerIdx
          }
        }
      }
    }
  }
  if (bestMatch === undefined) {
    return undefined
  }
  return bestMatch.index
}

/**
 * Check if the column info is valid.
 * @param  {ColumnInfo} Column information.
 * @return {Boolean}
 */
function isValid (columnInfo) {
  // Required indexes
  if (!(columnInfo.dateIndex >= 0) ||
    !(columnInfo.inflowIndex >= 0)) {
    return false
  }
  return true
}

/**
 * Check if a string contains another string ignoring case.
 * @param  {string} str - String where the search should be executed.
 * @param  {string} searched - String that should be contained.
 * @return {Boolean}
 */
function containsIgnoringCase(str, searched) {
  return str.toLowerCase().indexOf(searched.toLowerCase()) >= 0
}

module.exports = {
  getColumnInfo: getColumnInfo
}
<|endoftext|>


<commit_before>const knex = require('../db/connection');
const parsePurchases = require('./purchase');

function findCommune(commune_id) {
    return knex('communes').where('commune_id', commune_id).first();
}

function findCommuneChores(commune_id) {
    return knex.raw('SELECT DISTINCT ON (foo.chore_id) foo.username AS lastdoer, max(foo.max) AS lastdone, foo.priority, foo.points, foo.chore_id, foo.name AS chorename' +
                    ' FROM ( SELECT users.username, max(tasks.created_at), chores.chore_id, chores.name, chores.priority, chores.points FROM communes'+
                    ' LEFT JOIN chores on chores.commune_id = communes.commune_id' +
                    ' LEFT JOIN tasks on chores.chore_id = tasks.chore_id' +
                    ' LEFT JOIN users on users.user_id = tasks.user_id' +
                    ' WHERE communes.commune_id = '+ commune_id +
                    ' GROUP BY chores.chore_id, chores.name, users.username, chores.priority, chores.points ) foo' +
                    ' GROUP BY foo.username, foo.chore_id, foo.name, foo.priority, foo.points;').then((chores) => {
                      if (!chores.rows[0].chore_id){
                        return [];
                      }
                      return chores.rows;
                  });
}

function findCommunePurchases(commune_id) {
    return knex.raw('SELECT users.username, purchases.cancelled, purchases.purchase_id, purchases.amount, purchases.description, purchases.user_id, purchases.created_at' +
                    ' FROM purchases' +
                    ' LEFT JOIN users on users.user_id = purchases.user_id ' +
                    ' WHERE purchases.commune_id = ' + commune_id +
                    ' ORDER BY purchases.purchase_id DESC;').then((result) => {
                      if (!result.rows[0].purchase_id){
                        return [];
                      }
                      return result.rows;
                    })

    /*return knex.raw('SELECT users.username, communes.commune_id, sum(amount) as amount, avg(amount) FROM purchases' +
        ' RIGHT JOIN users on users.user_id = purchases.user_id' +
        ' RIGHT JOIN communes on communes.commune_id = users.commune_id' +
        ' WHERE communes.commune_id =' + commune_id + ' GROUP BY users.username, communes.commune_id;').then((result) => {
        return sortAndParsePurchases(result.rows)
    });*/
}

function findCommuneTasks(commune_id) {
  return knex.raw('SELECT users.username, chores.name, tasks.created_at, tasks.task_id, tasks.chore_id' +
                  ' FROM chores' +
                  ' LEFT JOIN tasks ON tasks.chore_id =chores.chore_id' +
                  ' LEFT JOIN users ON tasks.user_id = users.user_id' +
                  ' WHERE chores.commune_id = '+ commune_id + ';').then((result) => {
                    return result.rows;
                  })
}

function sortAndParsePurchases(purchases) {
    var sum_of_all = 0;
    for (var i = 0; i < purchases.length; i++) {
        sum_of_all = sum_of_all + parseFloat(purchases[i].amount);
    }
    var average_of_all = sum_of_all / purchases.length;
    for (var i = 0; i < purchases.length; i++) {
        purchases[i].differential = purchases[i].amount - average_of_all;
    }
    purchases.sort(function(a, b) {
        return (b.differential - a.differential);
    });
    return purchases;
}

function getCommune(user, callBack) {
    var commune_id = user.commune_id;
    var resJson = {};
    var retUser = {
        user_id: user.user_id,
        username: user.username,
        name: user.name,
        admin: user.admin
    }
    resJson.user = retUser;

    if (commune_id) {
      findCommune(commune_id).then((commune) => {
          resJson.commune = commune;
          findCommuneChores(commune_id).then((chores) => {
              resJson.chores = chores;
              findCommunePurchases(commune_id).then((purchases) => {
                  resJson.purchases = purchases;
                  findCommuneTasks(commune_id).then((tasks) => {
                    var newChores = addTasksToChores(resJson.chores, tasks);
                    resJson.chores = newChores;
                      callBack(null, resJson);
                  })
              });
          });
      }).catch((err) => {
        callBack(err, null);
      });

    } else {
        callBack(null, resJson);
    }
}

function addTasksToChores(chores, tasks){
  var newChores = chores;
  for (var i = 0; i < tasks.length; i++){
    for (var j = 0; j < newChores.length; j++){
        if (tasks[i].chore_id === newChores[j].chore_id){
          if (newChores[j].tasks){
            newChores[j].tasks.push(tasks[i]);
          } else {
            newChores[j].tasks = [];
            newChores[j].tasks.push(tasks[i]);
          }
          //i += 999;
        }
    }
  }
  return chores;
}

function postCommune(user, name, callBack) {
  if (user.commune_id){
    callBack({message: "User already has a commune"}, null);
    return;
  }
  if (!name){
    callBack({message: "No name given."}, null);
    return;
  }
  knex('communes').insert({name: name}).returning(['commune_id', 'name']).then((asd) => {
      var commune_id = asd[0].commune_id;
      knex.raw('UPDATE users SET commune_id = ' + commune_id + ', admin = true WHERE user_id = \'' + user.user_id + '\';').then(() => {
          callBack(null, {message: "Commune created succesfully"});
      });
  }).catch((err) => {
      callBack(err, null);
  });
}

module.exports = {
    getCommune,
    postCommune
};
<commit_msg>Update commune.js<commit_after>const knex = require('../db/connection');
const parsePurchases = require('./purchase');

function findCommune(commune_id) {
    return knex('communes').where('commune_id', commune_id).first();
}

function findCommuneChores(commune_id) {
    return knex.raw('SELECT DISTINCT ON (foo.chore_id) foo.username AS lastdoer, max(foo.max) AS lastdone, foo.priority, foo.points, foo.chore_id, foo.name AS chorename' +
                    ' FROM ( SELECT users.username, max(tasks.created_at), chores.chore_id, chores.name, chores.priority, chores.points FROM communes'+
                    ' LEFT JOIN chores on chores.commune_id = communes.commune_id' +
                    ' LEFT JOIN tasks on chores.chore_id = tasks.chore_id' +
                    ' LEFT JOIN users on users.user_id = tasks.user_id' +
                    ' WHERE communes.commune_id = '+ commune_id +
                    ' GROUP BY chores.chore_id, chores.name, users.username, chores.priority, chores.points ) foo' +
                    ' GROUP BY foo.username, foo.chore_id, foo.name, foo.priority, foo.points;').then((chores) => {
                      if (!chores.rows[0].chore_id){
                        return [];
                      }
                      return chores.rows;
                  });
}

function findCommunePurchases(commune_id) {
    return knex.raw('SELECT users.username, purchases.cancelled, purchases.purchase_id, purchases.amount, purchases.description, purchases.user_id, purchases.created_at' +
                    ' FROM purchases' +
                    ' LEFT JOIN users on users.user_id = purchases.user_id ' +
                    ' WHERE purchases.commune_id = ' + commune_id +
                    ' ORDER BY purchases.purchase_id DESC;').then((result) => {
                      return result.rows;
                    })

    /*return knex.raw('SELECT users.username, communes.commune_id, sum(amount) as amount, avg(amount) FROM purchases' +
        ' RIGHT JOIN users on users.user_id = purchases.user_id' +
        ' RIGHT JOIN communes on communes.commune_id = users.commune_id' +
        ' WHERE communes.commune_id =' + commune_id + ' GROUP BY users.username, communes.commune_id;').then((result) => {
        return sortAndParsePurchases(result.rows)
    });*/
}

function findCommuneTasks(commune_id) {
  return knex.raw('SELECT users.username, chores.name, tasks.created_at, tasks.task_id, tasks.chore_id' +
                  ' FROM chores' +
                  ' LEFT JOIN tasks ON tasks.chore_id =chores.chore_id' +
                  ' LEFT JOIN users ON tasks.user_id = users.user_id' +
                  ' WHERE chores.commune_id = '+ commune_id + ';').then((result) => {
                    return result.rows;
                  })
}

function sortAndParsePurchases(purchases) {
    var sum_of_all = 0;
    for (var i = 0; i < purchases.length; i++) {
        sum_of_all = sum_of_all + parseFloat(purchases[i].amount);
    }
    var average_of_all = sum_of_all / purchases.length;
    for (var i = 0; i < purchases.length; i++) {
        purchases[i].differential = purchases[i].amount - average_of_all;
    }
    purchases.sort(function(a, b) {
        return (b.differential - a.differential);
    });
    return purchases;
}

function getCommune(user, callBack) {
    var commune_id = user.commune_id;
    var resJson = {};
    var retUser = {
        user_id: user.user_id,
        username: user.username,
        name: user.name,
        admin: user.admin
    }
    resJson.user = retUser;

    if (commune_id) {
      findCommune(commune_id).then((commune) => {
          resJson.commune = commune;
          findCommuneChores(commune_id).then((chores) => {
              resJson.chores = chores;
              findCommunePurchases(commune_id).then((purchases) => {
                  resJson.purchases = purchases;
                  findCommuneTasks(commune_id).then((tasks) => {
                    var newChores = addTasksToChores(resJson.chores, tasks);
                    resJson.chores = newChores;
                      callBack(null, resJson);
                  })
              });
          });
      }).catch((err) => {
        callBack(err, null);
      });

    } else {
        callBack(null, resJson);
    }
}

function addTasksToChores(chores, tasks){
  var newChores = chores;
  for (var i = 0; i < tasks.length; i++){
    for (var j = 0; j < newChores.length; j++){
        if (tasks[i].chore_id === newChores[j].chore_id){
          if (newChores[j].tasks){
            newChores[j].tasks.push(tasks[i]);
          } else {
            newChores[j].tasks = [];
            newChores[j].tasks.push(tasks[i]);
          }
          //i += 999;
        }
    }
  }
  return chores;
}

function postCommune(user, name, callBack) {
  if (user.commune_id){
    callBack({message: "User already has a commune"}, null);
    return;
  }
  if (!name){
    callBack({message: "No name given."}, null);
    return;
  }
  knex('communes').insert({name: name}).returning(['commune_id', 'name']).then((asd) => {
      var commune_id = asd[0].commune_id;
      knex.raw('UPDATE users SET commune_id = ' + commune_id + ', admin = true WHERE user_id = \'' + user.user_id + '\';').then(() => {
          callBack(null, {message: "Commune created succesfully"});
      });
  }).catch((err) => {
      callBack(err, null);
  });
}

module.exports = {
    getCommune,
    postCommune
};
<|endoftext|>


<commit_before>// ========================================================================
// SproutCore
// copyright 2006-2008 Sprout Systems, Inc.
// ========================================================================

require('application/root_responder');

/**
  Order layer for regular Panels.  Panels appear in front of the main view, but behind palettes, popups.
*/
SC.PANEL_ORDER_LAYER = 0x1000 ;

/**
  Order layer for Palettes.  Palettes appear in front of the main view and panels, but behind popups.
*/
SC.PALETTE_ORDER_LAYER = 0x2000 ;

/**
  Order layer for Popups.  Popups appear in fron of hte main view and panels.
*/
SC.POPUP_ORDER_LAYER = 0x3000 ;

/*
  This is the root responder subclass for desktop-style applications.  It
  supports mouse events and window resize events in addition to the built
  in keyboard handling provided by the base class.
*/
SC.RootResponder = SC.RootResponder.extend(
/** @scope SC.RootResponder.prototype */ {

  platform: 'desktop',

  /** @property
    The current front view.  This view should have the highest z-index of all the other views.
  */
  focusedPane: function() {
    var views = this.get('orderedPanes');
    return views[views.length-1];
  }.property('orderedPanes'),

  /** @property
    Array of panes currently displayed that can be reordered.  This property when you orderBack() or orderOut() a pane to determine the next frontmost pane.
  */
  orderedPanes: null,

  /**
    Inserts the passed panes into the orderedPanes array before the named pane array.  Pass null to order at the front.  If this changes the frontmost view, then focus will also be shifted.  The pane you request must have the same orderLayer property at the pane you are passing in.  If it does not, the pane will be placed nearest to the target as possible.

    @param {SC.Pane} pane
    @param {SC.Pane} beforePane
    @returns {SC.RootResponder} receiver
  */
  orderBefore: function(pane, beforePane) {
    var currentFocus = this.get('focusedPane');
    var panes = this.get('orderedPanes').without(pane);
    var len, idx, currentOrder, newFocus ;

    // adjust the beforePane to match orderLayer
    var orderLayer = pane.get('orderLayer');
    if (beforePane) {
      len = panes.length;
      idx = panes.indexOf(beforePane);
      currentOrder = beforePane.get('orderLayer');

      if (currentOrder<orderLayer) {
        while((beforePane.get('orderLayer')<orderLayer) && (++idx<len)) beforePane = panes[idx];
        if (idx>=len) beforePane = null ; // insert at end if needed
      } else if (currentOrder>orderLayer) {
        while((beforePane.get('orderLayer')>orderLayer) && (--idx>=0)) beforePane = panes[idx];
        beforePane = (idx<0) ? panes[0] : panes[idx+1]; // go to next pane
      }

    // otherwise, find the highest pane matching the order...
    } else {
      idx = panes.length ;
      while((--idx >= 0) && !beforePane) {
        beforePane = panes[idx] ;
        if (beforePane.get('orderLayer') > orderLayer) beforePane = null; // try next one
      }
      if (idx<0) { // did not find a match, insert at beginning
        beforePane = panes[0];
      } else beforePane = panes[idx+1]; // go to next pane
    }

    // adjust array
    if (beforePane) {
      idx = panes.indexOf(beforePane);
      panes.insertAt(idx, pane);
    } else panes.push(pane);
    this.set('orderedPanes', panes); // update

    newFocus = this.get('focusedPane');
    if (newFocus !== currentFocus) {
      if (currentFocus) currentFocus.blurTo(newFocus);
      if (newFocus) newFocus.focusFrom(currentFocus);
    }

    this.panes.add(pane) ; // make sure its in the set...
    return this ;
  },

  /**
    Removes the named pane from the orderedPanes array.  If the pane was also focused, it will also blur the pane and focus the next view.  If the view is key, it will also determine the next view to make key by going down the list of ordered panes, finally ending with the mainPane.

    @param {SC.Pane} pane
    @param {SC.Pane} beforePane
    @returns {SC.RootResponder} receiver
  */
  orderOut: function(pane) {
    var currentFocus = this.get('focusedPane'), currentKey = this.get('keyPane');

    var panes = this.get('orderedPanes').without(pane) ;
    this.set('orderedPanes', panes) ;

    // focus only changes if we are removing the current focus view.
    // in this case, blur the old view and focus the new.  Also, if the view was
    // key, try to make the new focus view key or make main key.
    if (currentFocus === pane) {
      var newFocus = this.get('focusedPane') ;
      if (currentFocus) currentFocus.blurTo(newFocus) ;
      if (newFocus) newFocus.focusFrom(currentFocus) ;
      if (currentKey === pane) this.makeKeyPane(newFocus);

    // if the front is not changing, just check for key view.  Go back to main...
    } else if (currentKey === pane) {
      this.makeKeyPane(null);
    }

    this.panes.remove(pane) ; // remove pane from set of panes...
    return this ;
  },

  init: function() {
    sc_super();
    this.orderedPanes = []; // create new array
  },

  // .......................................................
  // EVENT HANDLING
  //

  setup: function() {
    sc_super();

    // handle basic events
    this.listenFor('mousedown mouseup click dblclick mouseout mouseover mousemove'.w(), document)
      .listenFor('resize focus blur'.w(), window);

    // handle these two events specially in IE
    'drag selectstart'.w().forEach(function(keyName) {
      var method = this[keyName] ;
      if (method) {
        if (SC.browser.msie) {
          var responder = this ;
          document.body['on' + keyName] = function(e) {
            return method.call(responder, SC.Event.normalizeEvent(e));
          };

          // be sure to cleanup memory leaks
           SC.Event.add(window, 'unload', this, function() {
            document.body['on' + keyName] = null;
          });

        } else {
          SC.Event.add(document, keyName, this, method);
        }
      }
    }, this);

    // handle mousewheel specifically for FireFox
    var mousewheel = SC.browser.mozilla ? 'DOMMouseScroll' : 'mousewheel';
    SC.Event.add(document, mousewheel, this, this.mousewheel);

    // do some initial set
    this.set('currentWindowSize', this.computeWindowSize()) ;
    this.focus(); // assume the window is focused when you load.
  },

  /**
    Invoked on a keyDown event that is not handled by any actual value.  This
    will get the key equivalent string and then walk down the keyPane, then
    the focusedPane, then the mainPane, looking for someone to handle it.
    Note that this will walk DOWN the view hierarchy, not up it like most.

    @returns {Object} Object that handled evet or null
  */
  attemptKeyEquivalent: function(evt) {
    var ret = null ;

    // keystring is a method name representing the keys pressed (i.e
    // 'alt_shift_escape')
    var keystring = evt.commandCodes()[0];

    // couldn't build a keystring for this key event, nothing to do
    if (!keystring) return NO;

    var keyPane  = this.get('keyPane'), mainPane = this.get('mainPane'),
        mainMenu = this.get('mainMenu');

    // try the keyPane
    if (keyPane) ret = keyPane.performKeyEquivalent(keystring, evt) ;

    // if not, then try the main pane
    if (!ret && mainPane && (mainPane!==keyPane)) {
      ret = mainPane.performKeyEquivalent(keystring, evt);
    }

    // if not, then try the main menu
    if (!ret && mainMenu) {
      ret = mainMenu.performKeyEquivalent(keystring, evt);
    }

    return ret ;
  },

  /** @property The last known window size. */
  currentWindowSize: null,

  /** Computes the window size from the DOM. */
  computeWindowSize: function() {
    var size ;
    if (window.innerHeight) {
      size = {
        width: window.innerWidth,
        height: window.innerHeight
      } ;

    } else if (document.documentElement && document.documentElement.clientHeight) {
      size = {
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight
      } ;

    } else if (document.body) {
      size = {
        width: document.body.clientWidth,
        height: document.body.clientHeight
      } ;
    }
    return size;
  },

  /**
    On window resize, notifies panes of the change.

    @returns {Boolean}
  */
  resize: function() {
    this._resize();
    //this.invokeLater(this._resize, 10);
    return YES; //always allow normal processing to continue.
  },

  _resize: function() {
    // calculate new window size...
    var newSize = this.computeWindowSize(), oldSize = this.get('currentWindowSize');
    this.set('currentWindowSize', newSize); // update size

    if (!SC.rectsEqual(newSize, oldSize)) {
      // notify panes
      SC.runLoop.beginRunLoop();
      this.panes.invoke('windowSizeDidChange', oldSize, newSize) ;
      SC.runLoop.endRunLoop();
    }
  },

  /**
    Indicates whether or not the window currently has focus.  If you need
    to do something based on whether or not the window is in focus, you can
    setup a binding or observer to this property.  Note that the SproutCore
    automatically adds an sc-focus or sc-blur CSS class to the body tag as
    appropriate.  If you only care about changing the appearance of your
    controls, you should use those classes in your CSS rules instead.
  */
  hasFocus: NO,

  /** Handle window focus.  Change hasFocus and add sc-focus CSS class (removing sc-blur).  Also notify panes. */
  focus: function() {
    if (!this.get('hasFocus')) {
      SC.$('body').addClass('sc-focus').removeClass('sc-blur');

      SC.runLoop.beginRunLoop();
      this.set('hasFocus', YES);
      SC.runLoop.endRunLoop();
    }
    return YES ; // allow default
  },

  /** Handle window focus.  Change hasFocus and add sc-focus CSS class (removing sc-blur).  Also notify panes. */
  blur: function() {
    if (this.get('hasFocus')) {
      SC.$('body').addClass('sc-blur').removeClass('sc-focus');

      SC.runLoop.beginRunLoop();
      this.set('hasFocus', NO);
      SC.runLoop.endRunLoop();
    }
    return YES ; // allow default
  },

  mousedown: function(evt) {

    // make sure the window gets focus no matter what.  FF is inconsistant
    // about this.
    this.focus();

    // first, save the click count.  Click count resets if your down is
    // more than 125msec after you last click up.
    this._clickCount = this._clickCount + 1 ;
    if (!this._lastMouseUpAt || ((Date.now() - this._lastMouseUpAt) > 200)) {
      this._clickCount = 1 ;
    }
    evt.clickCount = this._clickCount ;

    var view = this.targetViewForEvent(evt) ;
    view = this._mouseDownView = this.sendEvent('mouseDown', evt, view) ;
    if (view && view.respondsTo('mouseDragged')) this._mouseCanDrag = YES ;
    return view ? evt.hasCustomEventHandling : YES;
  },

  // mouseUp only gets delivered to the view that handled the mouseDown evt.
  // we also handle click and double click notifications through here to
  // ensure consistant delivery.  Note that if mouseDownView is not
  // implemented, then no mouseUp event will be sent, but a click will be
  // send.
  mouseup: function(evt) {
    var handler = null;
    this._lastMouseUpAt = Date.now();

    // record click count.
    evt.clickCount = this._clickCount ;

    // attempt the mouseup call only if there's a target.
    // don't want a mouseup going to anyone unless they handled the mousedown...
    if (this._mouseDownView) {
      handler = this.sendEvent('mouseUp', evt, this._mouseDownView);
    }

    // no one handled the mouseup... try doubleclick...
    if (!handler && (this._clickCount === 2)) {
      handler = this.sendEvent('doubleClick', evt, this._mouseDownView);
    }

    // no one handled the doubleclick... try click...
    if (!handler) {
      handler = this.sendEvent('click', evt, this._mouseDownView) ;
    }
    this._mouseCanDrag = NO; this._mouseDownView = null;

    return (handler) ? evt.hasCustomEventHandling : YES ;
  },

  dblclick: function(evt){
    if(SC.browser.isIE) {
      this._clickCount = 2;
      this._onmouseup(evt);
    }
  },

  mousewheel: function(evt) {
    var view = this.targetViewForEvent(evt) ;
    var handler = this.sendEvent('mouseWheel', evt, view) ;
    return (handler) ? evt.hasCustomEventHandling : YES ;
  },

  _lastHovered: null,

  // this will sent mouseOver, mouseOut, and mouseMoved to the views you
  // hover over.  To receive these events, you must implement the method.
  // If any subviews implement them and return true, then you won't receive
  // any notices.
  //
  // if there is a target mouseDown view, then mouse moved events will also
  // trigger calls to mouseDragged.
  //
  mousemove: function(evt) {

    SC.runLoop.beginRunLoop();

    // make sure the view gets focus no matter what.  FF is inconsistant
    // about this.
    this.focus();

    var lh = this._lastHovered || [] ;
    var nh = [] ;
    var view = this.targetViewForEvent(evt) ;

    // work up the view chain.  Notify of mouse entered and
    // mouseMoved if implemented.
    while(view && (view !== this)) {
      var entered = view.mouseOver || view.didMouseOver || view.mouseEntered;
      var moved = view.mouseMoved || view.mouseDidMove  ;

      if (lh.include(view)) {
        if (moved) moved.call(view,evt) ;
        nh.push(view) ;
      } else {
        if (entered) entered.call(view,evt) ;
        nh.push(view) ;
      }

      view = view.get('nextResponder');
    }

    // now find those views last hovered over that were no longer found
    // in this chain and notify of mouseExited.
    for(var loc=0; loc < lh.length; loc++) {
      view = lh[loc] ;
      var exited = view.mouseOut || view.didMouseOut || view.mouseExited ;
      if (exited && !nh.include(view)) exited.call(view, evt) ;
    }

    this._lastHovered = nh;

    // also, if a mouseDownView exists, call the mouseDragged action, if it
    // exists.
    if (this._mouseDownView && this._mouseDownView.respondsTo('mouseDragged')) {
      this._mouseDownView.mouseDragged(evt) ;
    }

    SC.runLoop.endRunLoop();
  },

  // these methods are used to prevent unnecessary text-selection in IE,
  // there could be some more work to improve this behavior and make it
  // a bit more useful; right now it's just to prevent bugs when dragging
  // and dropping.

  _mouseCanDrag: true,

  selectstart: function() {
    if(this._mouseCanDrag) {
      return false;
    } else {
      return true;
    }
  },

  drag: function() { return false; }

}) ;
<commit_msg>RootResponder should use tryToPerform()<commit_after>// ========================================================================
// SproutCore
// copyright 2006-2008 Sprout Systems, Inc.
// ========================================================================

require('application/root_responder');

/**
  Order layer for regular Panels.  Panels appear in front of the main view, but behind palettes, popups.
*/
SC.PANEL_ORDER_LAYER = 0x1000 ;

/**
  Order layer for Palettes.  Palettes appear in front of the main view and panels, but behind popups.
*/
SC.PALETTE_ORDER_LAYER = 0x2000 ;

/**
  Order layer for Popups.  Popups appear in fron of hte main view and panels.
*/
SC.POPUP_ORDER_LAYER = 0x3000 ;

/*
  This is the root responder subclass for desktop-style applications.  It
  supports mouse events and window resize events in addition to the built
  in keyboard handling provided by the base class.
*/
SC.RootResponder = SC.RootResponder.extend(
/** @scope SC.RootResponder.prototype */ {

  platform: 'desktop',

  /** @property
    The current front view.  This view should have the highest z-index of all the other views.
  */
  focusedPane: function() {
    var views = this.get('orderedPanes');
    return views[views.length-1];
  }.property('orderedPanes'),

  /** @property
    Array of panes currently displayed that can be reordered.  This property when you orderBack() or orderOut() a pane to determine the next frontmost pane.
  */
  orderedPanes: null,

  /**
    Inserts the passed panes into the orderedPanes array before the named pane array.  Pass null to order at the front.  If this changes the frontmost view, then focus will also be shifted.  The pane you request must have the same orderLayer property at the pane you are passing in.  If it does not, the pane will be placed nearest to the target as possible.

    @param {SC.Pane} pane
    @param {SC.Pane} beforePane
    @returns {SC.RootResponder} receiver
  */
  orderBefore: function(pane, beforePane) {
    var currentFocus = this.get('focusedPane');
    var panes = this.get('orderedPanes').without(pane);
    var len, idx, currentOrder, newFocus ;

    // adjust the beforePane to match orderLayer
    var orderLayer = pane.get('orderLayer');
    if (beforePane) {
      len = panes.length;
      idx = panes.indexOf(beforePane);
      currentOrder = beforePane.get('orderLayer');

      if (currentOrder<orderLayer) {
        while((beforePane.get('orderLayer')<orderLayer) && (++idx<len)) beforePane = panes[idx];
        if (idx>=len) beforePane = null ; // insert at end if needed
      } else if (currentOrder>orderLayer) {
        while((beforePane.get('orderLayer')>orderLayer) && (--idx>=0)) beforePane = panes[idx];
        beforePane = (idx<0) ? panes[0] : panes[idx+1]; // go to next pane
      }

    // otherwise, find the highest pane matching the order...
    } else {
      idx = panes.length ;
      while((--idx >= 0) && !beforePane) {
        beforePane = panes[idx] ;
        if (beforePane.get('orderLayer') > orderLayer) beforePane = null; // try next one
      }
      if (idx<0) { // did not find a match, insert at beginning
        beforePane = panes[0];
      } else beforePane = panes[idx+1]; // go to next pane
    }

    // adjust array
    if (beforePane) {
      idx = panes.indexOf(beforePane);
      panes.insertAt(idx, pane);
    } else panes.push(pane);
    this.set('orderedPanes', panes); // update

    newFocus = this.get('focusedPane');
    if (newFocus !== currentFocus) {
      if (currentFocus) currentFocus.blurTo(newFocus);
      if (newFocus) newFocus.focusFrom(currentFocus);
    }

    this.panes.add(pane) ; // make sure its in the set...
    return this ;
  },

  /**
    Removes the named pane from the orderedPanes array.  If the pane was also focused, it will also blur the pane and focus the next view.  If the view is key, it will also determine the next view to make key by going down the list of ordered panes, finally ending with the mainPane.

    @param {SC.Pane} pane
    @param {SC.Pane} beforePane
    @returns {SC.RootResponder} receiver
  */
  orderOut: function(pane) {
    var currentFocus = this.get('focusedPane'), currentKey = this.get('keyPane');

    var panes = this.get('orderedPanes').without(pane) ;
    this.set('orderedPanes', panes) ;

    // focus only changes if we are removing the current focus view.
    // in this case, blur the old view and focus the new.  Also, if the view was
    // key, try to make the new focus view key or make main key.
    if (currentFocus === pane) {
      var newFocus = this.get('focusedPane') ;
      if (currentFocus) currentFocus.blurTo(newFocus) ;
      if (newFocus) newFocus.focusFrom(currentFocus) ;
      if (currentKey === pane) this.makeKeyPane(newFocus);

    // if the front is not changing, just check for key view.  Go back to main...
    } else if (currentKey === pane) {
      this.makeKeyPane(null);
    }

    this.panes.remove(pane) ; // remove pane from set of panes...
    return this ;
  },

  init: function() {
    sc_super();
    this.orderedPanes = []; // create new array
  },

  // .......................................................
  // EVENT HANDLING
  //

  setup: function() {
    sc_super();

    // handle basic events
    this.listenFor('mousedown mouseup click dblclick mouseout mouseover mousemove'.w(), document)
      .listenFor('resize focus blur'.w(), window);

    // handle these two events specially in IE
    'drag selectstart'.w().forEach(function(keyName) {
      var method = this[keyName] ;
      if (method) {
        if (SC.browser.msie) {
          var responder = this ;
          document.body['on' + keyName] = function(e) {
            return method.call(responder, SC.Event.normalizeEvent(e));
          };

          // be sure to cleanup memory leaks
           SC.Event.add(window, 'unload', this, function() {
            document.body['on' + keyName] = null;
          });

        } else {
          SC.Event.add(document, keyName, this, method);
        }
      }
    }, this);

    // handle mousewheel specifically for FireFox
    var mousewheel = SC.browser.mozilla ? 'DOMMouseScroll' : 'mousewheel';
    SC.Event.add(document, mousewheel, this, this.mousewheel);

    // do some initial set
    this.set('currentWindowSize', this.computeWindowSize()) ;
    this.focus(); // assume the window is focused when you load.
  },

  /**
    Invoked on a keyDown event that is not handled by any actual value.  This
    will get the key equivalent string and then walk down the keyPane, then
    the focusedPane, then the mainPane, looking for someone to handle it.
    Note that this will walk DOWN the view hierarchy, not up it like most.

    @returns {Object} Object that handled evet or null
  */
  attemptKeyEquivalent: function(evt) {
    var ret = null ;

    // keystring is a method name representing the keys pressed (i.e
    // 'alt_shift_escape')
    var keystring = evt.commandCodes()[0];

    // couldn't build a keystring for this key event, nothing to do
    if (!keystring) return NO;

    var keyPane  = this.get('keyPane'), mainPane = this.get('mainPane'),
        mainMenu = this.get('mainMenu');

    // try the keyPane
    if (keyPane) ret = keyPane.performKeyEquivalent(keystring, evt) ;

    // if not, then try the main pane
    if (!ret && mainPane && (mainPane!==keyPane)) {
      ret = mainPane.performKeyEquivalent(keystring, evt);
    }

    // if not, then try the main menu
    if (!ret && mainMenu) {
      ret = mainMenu.performKeyEquivalent(keystring, evt);
    }

    return ret ;
  },

  /** @property The last known window size. */
  currentWindowSize: null,

  /** Computes the window size from the DOM. */
  computeWindowSize: function() {
    var size ;
    if (window.innerHeight) {
      size = {
        width: window.innerWidth,
        height: window.innerHeight
      } ;

    } else if (document.documentElement && document.documentElement.clientHeight) {
      size = {
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight
      } ;

    } else if (document.body) {
      size = {
        width: document.body.clientWidth,
        height: document.body.clientHeight
      } ;
    }
    return size;
  },

  /**
    On window resize, notifies panes of the change.

    @returns {Boolean}
  */
  resize: function() {
    this._resize();
    //this.invokeLater(this._resize, 10);
    return YES; //always allow normal processing to continue.
  },

  _resize: function() {
    // calculate new window size...
    var newSize = this.computeWindowSize(), oldSize = this.get('currentWindowSize');
    this.set('currentWindowSize', newSize); // update size

    if (!SC.rectsEqual(newSize, oldSize)) {
      // notify panes
      SC.runLoop.beginRunLoop();
      this.panes.invoke('windowSizeDidChange', oldSize, newSize) ;
      SC.runLoop.endRunLoop();
    }
  },

  /**
    Indicates whether or not the window currently has focus.  If you need
    to do something based on whether or not the window is in focus, you can
    setup a binding or observer to this property.  Note that the SproutCore
    automatically adds an sc-focus or sc-blur CSS class to the body tag as
    appropriate.  If you only care about changing the appearance of your
    controls, you should use those classes in your CSS rules instead.
  */
  hasFocus: NO,

  /** Handle window focus.  Change hasFocus and add sc-focus CSS class (removing sc-blur).  Also notify panes. */
  focus: function() {
    if (!this.get('hasFocus')) {
      SC.$('body').addClass('sc-focus').removeClass('sc-blur');

      SC.runLoop.beginRunLoop();
      this.set('hasFocus', YES);
      SC.runLoop.endRunLoop();
    }
    return YES ; // allow default
  },

  /** Handle window focus.  Change hasFocus and add sc-focus CSS class (removing sc-blur).  Also notify panes. */
  blur: function() {
    if (this.get('hasFocus')) {
      SC.$('body').addClass('sc-blur').removeClass('sc-focus');

      SC.runLoop.beginRunLoop();
      this.set('hasFocus', NO);
      SC.runLoop.endRunLoop();
    }
    return YES ; // allow default
  },

  mousedown: function(evt) {

    // make sure the window gets focus no matter what.  FF is inconsistant
    // about this.
    this.focus();

    // first, save the click count.  Click count resets if your down is
    // more than 125msec after you last click up.
    this._clickCount = this._clickCount + 1 ;
    if (!this._lastMouseUpAt || ((Date.now() - this._lastMouseUpAt) > 200)) {
      this._clickCount = 1 ;
    }
    evt.clickCount = this._clickCount ;

    var view = this.targetViewForEvent(evt) ;
    view = this._mouseDownView = this.sendEvent('mouseDown', evt, view) ;
    if (view && view.respondsTo('mouseDragged')) this._mouseCanDrag = YES ;
    return view ? evt.hasCustomEventHandling : YES;
  },

  // mouseUp only gets delivered to the view that handled the mouseDown evt.
  // we also handle click and double click notifications through here to
  // ensure consistant delivery.  Note that if mouseDownView is not
  // implemented, then no mouseUp event will be sent, but a click will be
  // send.
  mouseup: function(evt) {
    var handler = null;
    this._lastMouseUpAt = Date.now();

    // record click count.
    evt.clickCount = this._clickCount ;

    // attempt the mouseup call only if there's a target.
    // don't want a mouseup going to anyone unless they handled the mousedown...
    if (this._mouseDownView) {
      handler = this.sendEvent('mouseUp', evt, this._mouseDownView);
    }

    // no one handled the mouseup... try doubleclick...
    if (!handler && (this._clickCount === 2)) {
      handler = this.sendEvent('doubleClick', evt, this._mouseDownView);
    }

    // no one handled the doubleclick... try click...
    if (!handler) {
      handler = this.sendEvent('click', evt, this._mouseDownView) ;
    }
    this._mouseCanDrag = NO; this._mouseDownView = null;

    return (handler) ? evt.hasCustomEventHandling : YES ;
  },

  dblclick: function(evt){
    if(SC.browser.isIE) {
      this._clickCount = 2;
      this._onmouseup(evt);
    }
  },

  mousewheel: function(evt) {
    var view = this.targetViewForEvent(evt) ;
    var handler = this.sendEvent('mouseWheel', evt, view) ;
    return (handler) ? evt.hasCustomEventHandling : YES ;
  },

  _lastHovered: null,

  // this will sent mouseOver, mouseOut, and mouseMoved to the views you
  // hover over.  To receive these events, you must implement the method.
  // If any subviews implement them and return true, then you won't receive
  // any notices.
  //
  // if there is a target mouseDown view, then mouse moved events will also
  // trigger calls to mouseDragged.
  //
  mousemove: function(evt) {

    SC.runLoop.beginRunLoop();

    // make sure the view gets focus no matter what.  FF is inconsistant
    // about this.
    this.focus();

    var lh = this._lastHovered || [] ;
    var nh = [] ;
    var view = this.targetViewForEvent(evt) ;

    // work up the view chain.  Notify of mouse entered and
    // mouseMoved if implemented.
    while(view && (view !== this)) {
      if (lh.include(view)) {
        view.tryToPerform('mouseMoved', evt);
        nh.push(view) ;
      } else {
        view.tryToPerform('mouseEntered', evt);
        nh.push(view) ;
      }

      view = view.get('nextResponder');
    }

    // now find those views last hovered over that were no longer found
    // in this chain and notify of mouseExited.
    for(var loc=0; loc < lh.length; loc++) {
      view = lh[loc] ;
      var exited = view.respondsTo('mouseExited') ;
      if (exited && !nh.include(view)) view.tryToPerform('mouseExited',evt);
    }

    this._lastHovered = nh;

    // also, if a mouseDownView exists, call the mouseDragged action, if it
    // exists.
    if (this._mouseDownView) {
      this._mouseDownView.tryToPerform('mouseDragged', evt);
    }

    SC.runLoop.endRunLoop();
  },

  // these methods are used to prevent unnecessary text-selection in IE,
  // there could be some more work to improve this behavior and make it
  // a bit more useful; right now it's just to prevent bugs when dragging
  // and dropping.

  _mouseCanDrag: true,

  selectstart: function() {
    if(this._mouseCanDrag) {
      return false;
    } else {
      return true;
    }
  },

  drag: function() { return false; }

}) ;
<|endoftext|>


<commit_before>/* eslint-disable react/no-string-refs, react/prefer-es6-class */
import React from 'react';
import { mount } from 'enzyme';
import Upload from '..';

describe('Upload', () => {
  // https://github.com/react-component/upload/issues/36
  it('should get refs inside Upload in componentDidMount', () => {
    let ref;
    class App extends React.Component {
      componentDidMount() {
        ref = this.refs.input;
      }
      render() {
        return (
          <Upload supportServerRender={false}>
            <input ref="input" />
          </Upload>
        );
      }
    }
    mount(<App />);
    expect(ref).toBeDefined();
  });

  it('return promise in beforeUpload', (done) => {
    const data = jest.fn();
    const props = {
      action: 'http://upload.com',
      beforeUpload: () => new Promise(resolve =>
        setTimeout(() => resolve('success'))
      ),
      data,
      onChange: ({ file }) => {
        if (file.status !== 'uploading') {
          expect(data).toBeCalled();
          done();
        }
      },
    };

    const wrapper = mount(
      <Upload {...props}>
        <button>upload</button>
      </Upload>
    );

    wrapper.find('input').simulate('change', {
      target: {
        files: [
          { filename: 'foo.png' },
        ],
      },
    });
  });

  it('should not stop upload when return value of beforeUpload is not false', (done) => {
    const data = jest.fn();
    const props = {
      action: 'http://upload.com',
      beforeUpload: () => false,
      data,
      onChange: () => {
        expect(data).not.toBeCalled();
        done();
      },
    };

    const wrapper = mount(
      <Upload {...props}>
        <button>upload</button>
      </Upload>
    );

    wrapper.find('input').simulate('change', {
      target: {
        files: [
          { filename: 'foo.png' },
        ],
      },
    });
  });

  it('should not stop upload when return value of beforeUpload is not false', (done) => {
    const data = jest.fn();
    const props = {
      action: 'http://upload.com',
      beforeUpload() {},
      data,
      onChange: () => {
        expect(data).toBeCalled();
        done();
      },
    };

    const wrapper = mount(
      <Upload {...props}>
        <button>upload</button>
      </Upload>
    );

    wrapper.find('input').simulate('change', {
      target: {
        files: [
          { filename: 'foo.png' },
        ],
      },
    });
  });
});
<commit_msg>fix Upload ci<commit_after>/* eslint-disable react/no-string-refs, react/prefer-es6-class */
import React from 'react';
import { mount } from 'enzyme';
import Upload from '..';

describe('Upload', () => {
  // https://github.com/react-component/upload/issues/36
  it('should get refs inside Upload in componentDidMount', () => {
    let ref;
    class App extends React.Component {
      componentDidMount() {
        ref = this.refs.input;
      }
      render() {
        return (
          <Upload supportServerRender={false}>
            <input ref="input" />
          </Upload>
        );
      }
    }
    mount(<App />);
    expect(ref).toBeDefined();
  });

  it('return promise in beforeUpload', (done) => {
    const data = jest.fn();
    const props = {
      action: 'http://upload.com',
      beforeUpload: () => new Promise(resolve =>
        setTimeout(() => resolve('success'), 1000)
      ),
      data,
      onChange: ({ file }) => {
        if (file.status !== 'uploading') {
          expect(data).toBeCalled();
          done();
        }
      },
    };

    const wrapper = mount(
      <Upload {...props}>
        <button>upload</button>
      </Upload>
    );

    wrapper.find('input').simulate('change', {
      target: {
        files: [
          { filename: 'foo.png' },
        ],
      },
    });
  });

  it('should not stop upload when return value of beforeUpload is not false', (done) => {
    const data = jest.fn();
    const props = {
      action: 'http://upload.com',
      beforeUpload: () => false,
      data,
      onChange: () => {
        expect(data).not.toBeCalled();
        done();
      },
    };

    const wrapper = mount(
      <Upload {...props}>
        <button>upload</button>
      </Upload>
    );

    wrapper.find('input').simulate('change', {
      target: {
        files: [
          { filename: 'foo.png' },
        ],
      },
    });
  });

  it('should not stop upload when return value of beforeUpload is not false', (done) => {
    const data = jest.fn();
    const props = {
      action: 'http://upload.com',
      beforeUpload() {},
      data,
      onChange: () => {
        expect(data).toBeCalled();
        done();
      },
    };

    const wrapper = mount(
      <Upload {...props}>
        <button>upload</button>
      </Upload>
    );

    wrapper.find('input').simulate('change', {
      target: {
        files: [
          { filename: 'foo.png' },
        ],
      },
    });
  });
});
<|endoftext|>


<commit_before>/*
Copyright (c) 2014, Intel Corporation

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
    * Neither the name of Intel Corporation nor the names of its contributors
      may be used to endorse or promote products derived from this software
      without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

var logger = require("../lib/logger").init(),
    common = require('../lib/common'),
    utils = require("../lib/utils").init(),
    path = require('path');

function readConfig () {
    var fullFilename = common.getConfigName();
    return common.readFileToJson(fullFilename);
}

function writeConfig (data) {
    var fullFilename = common.getConfigName();
    common.writeToJson(fullFilename, data);
}

var configFileKey = {
    gatewayId : 'gateway_id',
    deviceId: 'device_id',
    dataDirectory: 'data_directory',
    activationCode: 'activation_code',
    defaultConnector: 'default_connector',
    loggerLevel: 'logger.LEVEL',
    connectorRestProxyHost: 'connector.rest.proxy.host',
    connectorRestProxyPort: 'connector.rest.proxy.port'
};

var saveToConfig = function () {
    if (arguments.length < 2) {
        logger.error("Not enough arguments : ", arguments);
        process.exit(1);
    }
    var key = arguments[0];
    var value = arguments[1];
    var data = readConfig();
    var keys = key.split('.');
    var configSaver = function (data, keys) {
        var k = keys.splice(0, 1);
        if (data && (data[k[0]] !== undefined)) {
            logger.info("Config Key : ", k[0], " value ", value);
            if (keys.length > 0) {
                data[k[0]] = configSaver(data[k[0]], keys);
            } else {
                data[k[0]] = value;
                logger.debug("Config Key : ", data);
            }
            return data;
        } else {
            logger.error("Key : ", key, " not found");
            return false;
        }
    };
    data = configSaver(data, keys);
    if (data) {
        writeConfig(data);
    }
    return true;
};

var setHostFor = function (host_value, port_value) {
    var data = readConfig();
    var proxy;
    if (data) {
       proxy = data["default_connector"];
       logger.info("Config Key : ", proxy, " value ", host_value);
       var host_key = 'connector.' + proxy + '.host';

       if(proxy === "rest"){
           var protocol;
           var protocol_key = 'connector.' + proxy + '.protocol';
           if(host_value.indexOf("https://")===0){
               host_value = host_value.replace("https://", "");
               protocol = "https";
           }else if(host_value.indexOf("http://")===0){
               host_value = host_value.replace("http://", "");
               protocol = "http";
           }
           if(protocol){
               saveToConfig(protocol_key, protocol);
           }
       }
       saveToConfig(host_key, host_value);
       if (port_value) {
        var port_key = 'connector.' + proxy + '.port';
        saveToConfig(port_key, port_value);
       }
    }
};

var setProxy = function (host_proxy, port_proxy) {
    saveToConfig(configFileKey.connectorRestProxyHost, host_proxy);
    saveToConfig(configFileKey.connectorRestProxyPort, port_proxy);
    logger.info("Set Proxy data");
};
var resetProxy = function () {
    saveToConfig(configFileKey.connectorRestProxyHost, false);
    saveToConfig(configFileKey.connectorRestProxyPort, false);
    logger.info("Set Proxy data");
};

var setGatewayId = function(id, cb) {
    saveToConfig(configFileKey.gatewayId, id);
    cb(id);
};

var setDeviceId = function(id) {
    saveToConfig(configFileKey.deviceId, id);
};

var getGatewayId = function(cb) {
    utils.getGatewayId(configFileKey.gatewayId, cb);
};

var loggerLevel = {
    info: true,
    warn: true,
    error: true,
    debug: true
};
module.exports = {
    addCommand : function (program) {
        program
            .command('protocol <protocol>')
            .description('Set the protocol to \'mqtt\' or \'rest\'')
            .action(function(protocol){
                if (protocol === 'mqtt' || protocol === 'rest') {
                    saveToConfig(configFileKey.defaultConnector, protocol);
                    logger.info("protocol set to: " + protocol);
                } else {
                    logger.error("invalid protocol: %s - please use \'mqtt\' or \'rest\'", protocol);
                    // do not clear the previous protocol
                }
            });

        program
            .command('host <host> [<port>]')
            .description('Sets the cloud hostname for the current protocol.')
            .action(setHostFor);

        program
            .command('device-id')
            .description('Displays the device id.')
            .action(function() {
                utils.getDeviceId(function (id) {
                    logger.info("Device ID: %s", id);
                });
            });

        program
            .command('set-device-id <id>')
            .description('Overrides the device id.')
            .action(function(id) {
                saveToConfig(configFileKey.deviceId, id);
                logger.info("Device ID set to: %s", id);
            });

        program
            .command('clear-device-id')
            .description('Reverts to using the default device id.')
            .action(function() {
                saveToConfig(configFileKey.deviceId, false);
                logger.info("Device ID cleared.");
            });

        program
            .command('save-code <activation_code>')
            .description('Adds the activation code to the device.')
            .action(function(activation_code) {
                saveToConfig(configFileKey.activationCode, activation_code);
                logger.info("Activation code saved.");
            });

        program
            .command('reset-code')
            .description('Clears the activation code of the device.')
            .action(function() {
                saveToConfig(configFileKey.activationCode, null);
                logger.info("Activation code cleared.");
            });

        program
            .command('proxy <host> <port>')
            .description('Sets proxy For REST protocol.')
            .action(setProxy);

        program
            .command('reset-proxy')
            .description('Clears proxy For REST protocol.')
            .action(resetProxy);

        program
            .command('set-logger-level <level>')
            .description('Set the logger level to \'debug\', \'info\', \'warn\', \'error\'')
            .action(function(level) {
                if (loggerLevel[level]) {
                    saveToConfig(configFileKey.loggerLevel, level);
                    logger.info("Logger Level set to: %s", level);
                } else {
                    logger.error("invalid level: %s - please use %s", level,
                                                Object.keys(loggerLevel).toString());
                }
            });

        program
            .command('set-data-directory <path>')
            .description('Sets path of directory that contains sensor data.')
            .action(function(path) {
                saveToConfig(configFileKey.dataDirectory, path);
                logger.info("Data directory changed.");
            });

        program
            .command('reset-data-directory')
            .description('Resets to default the path of directory that contains sensor data.')
            .action(function() {
                saveToConfig(configFileKey.dataDirectory, path.join(__dirname, '../data/'));
                logger.info("Data directory changed to default.");
            });

        program
            .command('gateway-id')
            .description('Displays the geteway id.')
            .action(function() {
                getGatewayId(function (id) {
                    logger.info("Gateway ID: %s", id);
                });
            });

        program
            .command('set-gateway-id <id>')
            .description('Overrides the geteway id.')
            .action(function(id) {
                setGatewayId(id, function(id){
                    logger.info("Gateway Id set to: %s", id);
                });
            });

    },
    getGatewayId: getGatewayId,
    setGatewayId: setGatewayId,
    setDeviceId: setDeviceId
};
<commit_msg>DP-2775: adding agent command to set UDP listener port<commit_after>/*
Copyright (c) 2014, Intel Corporation

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
    * Neither the name of Intel Corporation nor the names of its contributors
      may be used to endorse or promote products derived from this software
      without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

var logger = require("../lib/logger").init(),
    common = require('../lib/common'),
    utils = require("../lib/utils").init(),
    path = require('path');

function readConfig () {
    var fullFilename = common.getConfigName();
    return common.readFileToJson(fullFilename);
}

function writeConfig (data) {
    var fullFilename = common.getConfigName();
    common.writeToJson(fullFilename, data);
}

var configFileKey = {
    gatewayId : 'gateway_id',
    deviceId: 'device_id',
    dataDirectory: 'data_directory',
    activationCode: 'activation_code',
    defaultConnector: 'default_connector',
    loggerLevel: 'logger.LEVEL',
    connectorRestProxyHost: 'connector.rest.proxy.host',
    connectorRestProxyPort: 'connector.rest.proxy.port',
    udpListenerPort: 'listeners.udp_port'
};

var saveToConfig = function () {
    if (arguments.length < 2) {
        logger.error("Not enough arguments : ", arguments);
        process.exit(1);
    }
    var key = arguments[0];
    var value = arguments[1];
    var data = readConfig();
    var keys = key.split('.');
    var configSaver = function (data, keys) {
        var k = keys.splice(0, 1);
        if (data && (data[k[0]] !== undefined)) {
            logger.info("Config Key : ", k[0], " value ", value);
            if (keys.length > 0) {
                data[k[0]] = configSaver(data[k[0]], keys);
            } else {
                data[k[0]] = value;
                logger.debug("Config Key : ", data);
            }
            return data;
        } else {
            logger.error("Key : ", key, " not found");
            return false;
        }
    };
    data = configSaver(data, keys);
    if (data) {
        writeConfig(data);
    }
    return true;
};

var setHostFor = function (host_value, port_value) {
    var data = readConfig();
    var proxy;
    if (data) {
       proxy = data["default_connector"];
       logger.info("Config Key : ", proxy, " value ", host_value);
       var host_key = 'connector.' + proxy + '.host';

       if(proxy === "rest"){
           var protocol;
           var protocol_key = 'connector.' + proxy + '.protocol';
           if(host_value.indexOf("https://")===0){
               host_value = host_value.replace("https://", "");
               protocol = "https";
           }else if(host_value.indexOf("http://")===0){
               host_value = host_value.replace("http://", "");
               protocol = "http";
           }
           if(protocol){
               saveToConfig(protocol_key, protocol);
           }
       }
       saveToConfig(host_key, host_value);
       if (port_value) {
        var port_key = 'connector.' + proxy + '.port';
        saveToConfig(port_key, port_value);
       }
    }
};

var setProxy = function (host_proxy, port_proxy) {
    saveToConfig(configFileKey.connectorRestProxyHost, host_proxy);
    saveToConfig(configFileKey.connectorRestProxyPort, port_proxy);
    logger.info("Set Proxy data");
};
var resetProxy = function () {
    saveToConfig(configFileKey.connectorRestProxyHost, false);
    saveToConfig(configFileKey.connectorRestProxyPort, false);
    logger.info("Set Proxy data");
};

var setGatewayId = function(id, cb) {
    saveToConfig(configFileKey.gatewayId, id);
    cb(id);
};

var setDeviceId = function(id) {
    saveToConfig(configFileKey.deviceId, id);
};

var getGatewayId = function(cb) {
    utils.getGatewayId(configFileKey.gatewayId, cb);
};

var consts = {
    PORT_MIN_VALUE: 1025,
    PORT_MAX_VALUE: 65535
};

var portValidator = {
    'Port value must be an integer': function(value) {
        return !isNaN(value) && value % 1 === 0;
    },
    'Port value out of valid range': function(value) {
        return value >= consts.PORT_MIN_VALUE && value <= consts.PORT_MAX_VALUE;
    }
};

var setListenerUdpPort = function(udp_port, onUdpPortSet) {
    logger.info("Set UDP port");

    var err;
    for(var key in portValidator) {
        if(portValidator.hasOwnProperty(key) &&
            !portValidator[key](udp_port)) {
            err = key;
        }
    }

    if(!err) {
        saveToConfig(configFileKey.udpListenerPort, parseInt(udp_port));
    }

    onUdpPortSet(udp_port, err);
};

var loggerLevel = {
    info: true,
    warn: true,
    error: true,
    debug: true
};
module.exports = {
    addCommand : function (program) {
        program
            .command('protocol <protocol>')
            .description('Set the protocol to \'mqtt\' or \'rest\'')
            .action(function(protocol){
                if (protocol === 'mqtt' || protocol === 'rest') {
                    saveToConfig(configFileKey.defaultConnector, protocol);
                    logger.info("protocol set to: " + protocol);
                } else {
                    logger.error("invalid protocol: %s - please use \'mqtt\' or \'rest\'", protocol);
                    // do not clear the previous protocol
                }
            });

        program
            .command('host <host> [<port>]')
            .description('Sets the cloud hostname for the current protocol.')
            .action(setHostFor);

        program
            .command('device-id')
            .description('Displays the device id.')
            .action(function() {
                utils.getDeviceId(function (id) {
                    logger.info("Device ID: %s", id);
                });
            });

        program
            .command('set-device-id <id>')
            .description('Overrides the device id.')
            .action(function(id) {
                saveToConfig(configFileKey.deviceId, id);
                logger.info("Device ID set to: %s", id);
            });

        program
            .command('clear-device-id')
            .description('Reverts to using the default device id.')
            .action(function() {
                saveToConfig(configFileKey.deviceId, false);
                logger.info("Device ID cleared.");
            });

        program
            .command('save-code <activation_code>')
            .description('Adds the activation code to the device.')
            .action(function(activation_code) {
                saveToConfig(configFileKey.activationCode, activation_code);
                logger.info("Activation code saved.");
            });

        program
            .command('reset-code')
            .description('Clears the activation code of the device.')
            .action(function() {
                saveToConfig(configFileKey.activationCode, null);
                logger.info("Activation code cleared.");
            });

        program
            .command('proxy <host> <port>')
            .description('Sets proxy For REST protocol.')
            .action(setProxy);

        program
            .command('reset-proxy')
            .description('Clears proxy For REST protocol.')
            .action(resetProxy);

        program
            .command('set-logger-level <level>')
            .description('Set the logger level to \'debug\', \'info\', \'warn\', \'error\'')
            .action(function(level) {
                if (loggerLevel[level]) {
                    saveToConfig(configFileKey.loggerLevel, level);
                    logger.info("Logger Level set to: %s", level);
                } else {
                    logger.error("invalid level: %s - please use %s", level,
                                                Object.keys(loggerLevel).toString());
                }
            });

        program
            .command('set-data-directory <path>')
            .description('Sets path of directory that contains sensor data.')
            .action(function(path) {
                saveToConfig(configFileKey.dataDirectory, path);
                logger.info("Data directory changed.");
            });

        program
            .command('reset-data-directory')
            .description('Resets to default the path of directory that contains sensor data.')
            .action(function() {
                saveToConfig(configFileKey.dataDirectory, path.join(__dirname, '../data/'));
                logger.info("Data directory changed to default.");
            });

        program
            .command('gateway-id')
            .description('Displays the geteway id.')
            .action(function() {
                getGatewayId(function (id) {
                    logger.info("Gateway ID: %s", id);
                });
            });

        program
            .command('set-gateway-id <id>')
            .description('Overrides the geteway id.')
            .action(function(id) {
                setGatewayId(id, function(id){
                    logger.info("Gateway Id set to: %s", id);
                });
            });

        program
            .command('set-udp-port <udp_port>')
            .description('Overrides the port UDP listener binds to')
            .action(function(udp_port) {
                setListenerUdpPort(udp_port, function(udp_port, err){
                    if(!err) {
                        logger.info("UDP port is listening on port: %s", udp_port);
                    }
                    else {
                        logger.error(err);
                    }
                });
            });
    },
    getGatewayId: getGatewayId,
    setGatewayId: setGatewayId,
    setDeviceId: setDeviceId
};
<|endoftext|>


<commit_before>(
    function()
    {
        "use strict";

        // must always be running
        // nohup node server-admin&

        var express = require('express');

        var app = express();
        var bodyParser = require("body-parser");

        app.disable('view cache');
        app.set('json spaces', 4);
        app.use(bodyParser.urlencoded(
        {
            extended: true
        }));
        app.use(bodyParser.json());

        var http = require('http');
        var url = require('url');
        var path = require('path');
        var fs = require('fs');
        var R = require('ramda');

        var s3 = require('../s3client');

        var bucket = 'functal-images';
        var bucketJson = 'functal-json';

        http.createServer(app).listen(process.env.PORT || 8083);

        var handleError = function(res, errNo, err)
        {
            res.writeHead(errNo,
            {
                "Content-Type": "text/plain"
            });
            res.write(errNo + " " + err + "\n");
            res.end();
            return;
        };

        var htmlHead = function(res)
        {
            res.setHeader("Content-Type", "text/html");
            res.writeHead(200);

            res.write('\n');

            // head
            res.write('\n');
            res.write('<title>Functal Admin ({{images.length}})</title>\n');
            res.write('<link rel="icon" type="image/png" href="/images/favicon.png" />\n');
            res.write('<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" type="text/css" />\n');
            res.write('<link href="css/base.css" rel="stylesheet" type="text/css" />\n');
            res.write('\n');
            // body
            res.write('\n');
        };

        var htmlEnd = function(res)
        {

            res.write('\n');
            res.write('\n');
            res.write('\n');

            res.write('\n');
            res.write('\n');
            res.write('\n');

            res.write('\n');

            // end
            res.end('\n');
        };

        // javascript files
        app.get(/\.js$/, function(req, res)
        {
            var uri = url.parse(req.url, true, false);
            var filename = path.join(process.cwd(), uri.pathname);

            fs.readFile(filename, "binary", function(err, file)
            {
                if (err)
                {
                    handleError(res, 404, "Not found " + err);
                }
                else
                {
                    res.setHeader("Content-Type", "application/javascript");
                    res.writeHead(200);
                    res.write(file, "binary");
                    res.end();
                }
            });
        });

        // css files
        app.get(/\.css$/, function(req, res)
        {
            var uri = url.parse(req.url, true, false);
            var filename = path.join(process.cwd(), uri.pathname);

            fs.readFile(filename, "binary", function(err, file)
            {
                if (err)
                {
                    handleError(res, 404, "Not found " + err);
                }
                else
                {
                    res.setHeader("Content-Type", "text/css");
                    res.writeHead(200);
                    res.write(file, "binary");
                    res.end();
                }
            });
        });

        // images
        app.get(/\.(png|jpg)$/, function(req, res)
        {
            var uri = url.parse(req.url, true, false);
            var filename = path.join(process.cwd(), uri.pathname);

            fs.readFile(filename, "binary", function(err, file)
            {
                if (err)
                {
                    handleError(res, 404, "Not found " + err);
                }
                else
                {
                    res.setHeader("Content-Type", "image/" + path.extname(filename).substr(1));
                    res.writeHead(200);
                    res.write(file, "binary");
                    res.end();
                }
            });
        });

        app.get('/', function(req, res)
        {
            htmlHead(res);

            // start container
            res.write('
\n');

            // heading
            res.write('
\n');
            res.write('
\n');

            res.write('
Functal Admin
');
            res.write('

');
            res.write('

');
            res.write('
loading...
');

            res.write('
\n');
            res.write('
\n');

            // content
            res.write('
\n');
            res.write('
\n');
            res.write('
\n');
            res.write('\n');
            res.write('
\n');
            res.write('
\n');
            res.write('<button class="btn btn-primary btn-xl" ng-click="gotoTop()">top</button>\n');
            res.write('<button class="btn btn-info btn-xl" ng-click="showJson(image)">json</button>\n');
            res.write('<button class="btn btn-danger btn-xl" ng-click="delete(image)">delete</button>\n');
            res.write('
\n');
            res.write('
\n');
            res.write('
\n');

            res.write('
\n');

            // end container
            res.write('
\n');

            htmlEnd(res);
        });

        // get images on s3
        app.get('/getimages', function(req, res)
        {
            s3.list(bucket).then(function(result)
            {
                // console.log(result.files);

                var images = R.pluck('Key', result.files);
                images = R.reverse(images);

                res.json(
                {
                    images: images
                });

            });
        });

        // delete image on s3
        app.post('/delete', function(req, res)
        {
            var key = req.body.key;

            s3.delete(bucket, key)
                .then(function()
                {
                    return s3.delete(bucketJson, key.replace(/png$/, 'json'));
                })
                .then(function(result)
                {
                    res.json(result);
                });
        });

    }()
);
<commit_msg>unset height<commit_after>(
    function()
    {
        "use strict";

        // must always be running
        // nohup node server-admin&

        var express = require('express');

        var app = express();
        var bodyParser = require("body-parser");

        app.disable('view cache');
        app.set('json spaces', 4);
        app.use(bodyParser.urlencoded(
        {
            extended: true
        }));
        app.use(bodyParser.json());

        var http = require('http');
        var url = require('url');
        var path = require('path');
        var fs = require('fs');
        var R = require('ramda');

        var s3 = require('../s3client');

        var bucket = 'functal-images';
        var bucketJson = 'functal-json';

        http.createServer(app).listen(process.env.PORT || 8083);

        var handleError = function(res, errNo, err)
        {
            res.writeHead(errNo,
            {
                "Content-Type": "text/plain"
            });
            res.write(errNo + " " + err + "\n");
            res.end();
            return;
        };

        var htmlHead = function(res)
        {
            res.setHeader("Content-Type", "text/html");
            res.writeHead(200);

            res.write('\n');

            // head
            res.write('\n');
            res.write('<title>Functal Admin ({{images.length}})</title>\n');
            res.write('<link rel="icon" type="image/png" href="/images/favicon.png" />\n');
            res.write('<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" type="text/css" />\n');
            res.write('<link href="css/base.css" rel="stylesheet" type="text/css" />\n');
            res.write('\n');
            // body
            res.write('\n');
        };

        var htmlEnd = function(res)
        {

            res.write('\n');
            res.write('\n');
            res.write('\n');

            res.write('\n');
            res.write('\n');
            res.write('\n');

            res.write('\n');

            // end
            res.end('\n');
        };

        // javascript files
        app.get(/\.js$/, function(req, res)
        {
            var uri = url.parse(req.url, true, false);
            var filename = path.join(process.cwd(), uri.pathname);

            fs.readFile(filename, "binary", function(err, file)
            {
                if (err)
                {
                    handleError(res, 404, "Not found " + err);
                }
                else
                {
                    res.setHeader("Content-Type", "application/javascript");
                    res.writeHead(200);
                    res.write(file, "binary");
                    res.end();
                }
            });
        });

        // css files
        app.get(/\.css$/, function(req, res)
        {
            var uri = url.parse(req.url, true, false);
            var filename = path.join(process.cwd(), uri.pathname);

            fs.readFile(filename, "binary", function(err, file)
            {
                if (err)
                {
                    handleError(res, 404, "Not found " + err);
                }
                else
                {
                    res.setHeader("Content-Type", "text/css");
                    res.writeHead(200);
                    res.write(file, "binary");
                    res.end();
                }
            });
        });

        // images
        app.get(/\.(png|jpg)$/, function(req, res)
        {
            var uri = url.parse(req.url, true, false);
            var filename = path.join(process.cwd(), uri.pathname);

            fs.readFile(filename, "binary", function(err, file)
            {
                if (err)
                {
                    handleError(res, 404, "Not found " + err);
                }
                else
                {
                    res.setHeader("Content-Type", "image/" + path.extname(filename).substr(1));
                    res.writeHead(200);
                    res.write(file, "binary");
                    res.end();
                }
            });
        });

        app.get('/', function(req, res)
        {
            htmlHead(res);

            // start container
            res.write('
\n');

            // heading
            res.write('
\n');
            res.write('
\n');

            res.write('
Functal Admin
');
            res.write('

');
            res.write('

');
            res.write('
loading...
');

            res.write('
\n');
            res.write('
\n');

            // content
            res.write('
\n');
            res.write('
\n');
            res.write('
\n');
            res.write('\n');
            res.write('
\n');
            res.write('
\n');
            res.write('<button class="btn btn-primary btn-xl" ng-click="gotoTop()">top</button>\n');
            res.write('<button class="btn btn-info btn-xl" ng-click="showJson(image)">json</button>\n');
            res.write('<button class="btn btn-danger btn-xl" ng-click="delete(image)">delete</button>\n');
            res.write('
\n');
            res.write('
\n');
            res.write('
\n');

            res.write('
\n');

            // end container
            res.write('
\n');

            htmlEnd(res);
        });

        // get images on s3
        app.get('/getimages', function(req, res)
        {
            s3.list(bucket).then(function(result)
            {
                // console.log(result.files);

                var images = R.pluck('Key', result.files);
                images = R.reverse(images);

                res.json(
                {
                    images: images
                });

            });
        });

        // delete image on s3
        app.post('/delete', function(req, res)
        {
            var key = req.body.key;

            s3.delete(bucket, key)
                .then(function()
                {
                    return s3.delete(bucketJson, key.replace(/png$/, 'json'));
                })
                .then(function(result)
                {
                    res.json(result);
                });
        });

    }()
);
<|endoftext|>


<commit_before>// load native modules
var p = require('path');
var fs = require('fs');

// load 3rd party modules
var gm = require('gm');

var formidable = require('formidable');

// some default values
var defaultRatio = null,
	defaultMaxWidth = 1024,
	defaultMediumWidth = 600,
	defaultThumbWidth = 300;

var config = require('./config');

module.exports = function(req, res, next) {
	var ratio = req.query.ratio || defaultRatio,
		maxWidth = req.query.max || defaultMaxWidth,
		mediumWidth = req.query.medium || defaultMediumWidth,
		thumbWidth = req.query.thumb || defaultThumbWidth,
		maxHeight = ratio ? Math.floor(maxWidth / ratio) : null,
		mediumHeight = ratio ? Math.floor(mediumWidth / ratio) : null,
		thumbHeight = ratio ? Math.floor(thumbWidth / ratio) : null,
		type = req.query.type ? req.query.type + '-' : '';

	var form = new formidable.IncomingForm();

	form.onPart = function (part) {
		var done = _.after(3, function() {
			// from original Formidable.handlePart
			form._flushing--;
			form.emit('file', part.name, file);
			form._maybeEnd();
		});

		if (part.filename === undefined) {
			// let formidable handle everything besides files
			return this.handlePart(part);
		}

		// from original Formidable.handlePart
		this._flushing++;

		var basename = type + new Date().toISOString().split(':').join('_');
		var ext = p.extname(part.filename);

		var file = {
			basename: basename,
			filePath: p.join(config.dir.uploads, basename + ext),
			mediumFilePath: p.join(config.dir.uploads, basename + '-medium' + ext),
			thumbFilePath: p.join(config.dir.uploads, basename + '-thumb' + ext),
			urlPath: p.join('/uploads', basename + ext),
			mediumUrlPath: p.join('/uploads', basename + '-medium' + ext),
			thumbUrlPath: p.join('/uploads', basename + '-thumb' + ext),
			ext: ext,
			uploadDate: new Date(),
			mime: part.mime,
			hash: form.hash,
			thumbnail: {
				width: thumbWidth,
				height: thumbHeight
			}
		};

		// noProfile removes all EXIF data
		gm(part).noProfile()
			// if you need data from read functions (eg size), you need to
			// pass options obj with bufferStream: true and call all manipulations inside
			// the callback
			.size({ bufferStream: true }, function(err, value) {
				var width,
					height,
					imgRatio = value.width / value.height,
					shaveHeight,
					shaveWidth;

				// calculate how much to shave off to make thumbnail correct ratio
				if(ratio) {
					if(imgRatio >= ratio) {
						shaveWidth = (1 - ratio / imgRatio) * 50;// 50 = 100% / 2
						shaveHeight = 0;
						if(value.width > maxWidth)
							width = maxWidth;
					} else {
						shaveWidth = 0;
						shaveHeight = (1 - imgRatio / ratio) * 50;// 50 = 100% / 2
						if(value.height > maxHeight)
							height = maxHeight;
					}
				}

				// only downsize large version if it is large than max size
				((width || height) ? this.resize(width, height) : this )
					.stream(function (err, stdout, stderr) {

						file.width = width || value.width;
						file.height = height || value.height;

						var size = 0;
						stdout.on('data', function(chunk) {
							size += chunk.length;
						});

						stdout.on('end', function() {
							file.contentSize = size;
						});

						// write large image
						var writeStream = fs.createWriteStream(file.filePath);
						stdout.pipe(writeStream);
						writeStream.on('finish', function() {
							done();
						});

						(ratio ?
							gm(stdout)
							// crop thumbnail so it is correct ratio
								.shave(shaveWidth, shaveHeight, true) :
							gm(stdout))
							.stream(function(err, stdout, stderr) {
								gm(stdout)
									.resize(mediumWidth, null)
									// write medium image
									.write(file.mediumFilePath, function(err) {
										if(err) return next(err);

										done();
									});

								gm(stdout)
									// resize thumbnail
									.resize(thumbWidth, null)
									// write thumbnail
									.stream(function(err, stdout, stderr) {
										var size = 0;
										stdout.on('data', function(chunk) {
											size += chunk.length;
										});

										stdout.on('end', function() {
											file.thumbnail.contentSize = size;
										});

										var writeStream = fs.createWriteStream(file.thumbFilePath);

										stdout.pipe(writeStream);

										writeStream.on('finish', function() {
											done();
										});
									});

							});
				});
			});
	};

	form.parse(req, function(err, fields, files) {
		if(err) return next(err);

		res.status(201).json(files);
	});
};
<commit_msg>New image/upload.<commit_after>// load native modules
var p = require('path');
var fs = require('fs');

// load 3rd party modules
var gm = require('gm');

var formidable = require('formidable');

// some default values
var defaultRatio = null,
	defaultMaxWidth = 1024,
	defaultMediumWidth = 600,
	defaultThumbWidth = 300;

var config = require('./config');

module.exports = function(req, res, next) {
	var ratio = req.query.ratio || defaultRatio,
		maxWidth = req.query.max || defaultMaxWidth,
		mediumWidth = req.query.medium || defaultMediumWidth,
		thumbWidth = req.query.thumb || defaultThumbWidth,
		maxHeight = ratio ? Math.floor(maxWidth / ratio) : null,
		mediumHeight = ratio ? Math.floor(mediumWidth / ratio) : null,
		thumbHeight = ratio ? Math.floor(thumbWidth / ratio) : null,
		type = req.query.type ? req.query.type + '-' : '';

	var form = new formidable.IncomingForm();

	form.onPart = function (part) {
		var done = _.after(3, function() {
			// from original Formidable.handlePart
			form._flushing--;
			form.emit('file', part.name, file);
			form._maybeEnd();
		});

		if (part.filename === undefined) {
			// let formidable handle everything besides files
			return this.handlePart(part);
		}

		// from original Formidable.handlePart
		this._flushing++;

		var basename = type + new Date().toISOString().split(':').join('_');
		var ext = p.extname(part.filename);

		var file = {
			basename: basename,
			filePath: p.join(config.dir.uploads, 'img', basename + ext),
			mediumFilePath: p.join(config.dir.uploads, 'img', basename + '-medium' + ext),
			thumbFilePath: p.join(config.dir.uploads, 'img', basename + '-thumb' + ext),
			urlPath: p.join('/uploads/img', basename + ext),
			mediumUrlPath: p.join('/uploads/img', basename + '-medium' + ext),
			thumbUrlPath: p.join('/uploads/img', basename + '-thumb' + ext),
			ext: ext,
			uploadDate: new Date(),
			mime: part.mime,
			hash: form.hash,
			thumbnail: {
				width: thumbWidth,
				height: thumbHeight
			}
		};

		// noProfile removes all EXIF data
		gm(part).noProfile()
			// if you need data from read functions (eg size), you need to
			// pass options obj with bufferStream: true and call all manipulations inside
			// the callback
			.size({ bufferStream: true }, function(err, value) {
				var width,
					height,
					imgRatio = value.width / value.height,
					shaveHeight,
					shaveWidth;

				// calculate how much to shave off to make thumbnail correct ratio
				if(ratio) {
					if(imgRatio >= ratio) {
						shaveWidth = (1 - ratio / imgRatio) * 50;// 50 = 100% / 2
						shaveHeight = 0;
						if(value.width > maxWidth)
							width = maxWidth;
					} else {
						shaveWidth = 0;
						shaveHeight = (1 - imgRatio / ratio) * 50;// 50 = 100% / 2
						if(value.height > maxHeight)
							height = maxHeight;
					}
				}

				// only downsize large version if it is large than max size
				((width || height) ? this.resize(width, height) : this )
					.stream(function (err, stdout, stderr) {

						file.width = width || value.width;
						file.height = height || value.height;

						var size = 0;
						stdout.on('data', function(chunk) {
							size += chunk.length;
						});

						stdout.on('end', function() {
							file.contentSize = size;
						});

						// write large image
						var writeStream = fs.createWriteStream(file.filePath);
						stdout.pipe(writeStream);
						writeStream.on('finish', function() {
							done();
						});

						(ratio ?
							gm(stdout)
							// crop thumbnail so it is correct ratio
								.shave(shaveWidth, shaveHeight, true) :
							gm(stdout))
							.stream(function(err, stdout, stderr) {
								gm(stdout)
									.resize(mediumWidth, null)
									// write medium image
									.write(file.mediumFilePath, function(err) {
										if(err) return next(err);

										done();
									});

								gm(stdout)
									// resize thumbnail
									.resize(thumbWidth, null)
									// write thumbnail
									.stream(function(err, stdout, stderr) {
										var size = 0;
										stdout.on('data', function(chunk) {
											size += chunk.length;
										});

										stdout.on('end', function() {
											file.thumbnail.contentSize = size;
										});

										var writeStream = fs.createWriteStream(file.thumbFilePath);

										stdout.pipe(writeStream);

										writeStream.on('finish', function() {
											done();
										});
									});

							});
				});
			});
	};

	form.parse(req, function(err, fields, files) {
		if(err) return next(err);

		res.status(201).json(files);
	});
};
<|endoftext|>