<commit_before>/**
 * @fileOverview The fetch() method mixin implementation.
 */

var cip = require('cip');
var __ = require('lodash');
var Promise = require('bluebird');
var appErr = require('nodeon-error');

/**
 * The fetch() method mixin implementation.
 *
 * @constructor
 */
var Fetch = module.exports = cip.extend(function() {
  /** @type {?Object} A token based index for token items */
  this.tokenItemIndex = null;
});

/** @const {string} Wildcard used by redis for fetching keys */
Fetch.WILDCARD = '*';

/**
 * Execute the query.
 *
 * @return {Promise} The instance promise.
 */
Fetch.prototype.fetch = Promise.method(function() {
  if (this.operates || this.fetched) {
    // try to contain the error only in the fetch() invocation
    // and do not propagate it in the master defer.
    throw new appErr.Error('Already fetched from redis');
  }
  this.operates = true;

  return this._resolveTokensByUser()
    .bind(this)
    .then(this._generateKeysQuery)
    .then(this._fetchKeys)
    .then(this._fetchData)
    .spread(this._processResults);
});

/**
 * Will resolve all ownerIds to tokens if they exist in the query.
 *
 * @return {Promise(Array)} A Promise with an array of tokens.
 * @private
 */
Fetch.prototype._resolveTokensByUser = Promise.method(function() {
  var indexKeys = this.query.user.map(function(ownerId) {
    return this.prefix + ':kansas:index:token:' + ownerId;
  }, this);

  return Promise.resolve(indexKeys)
    .bind(this)
    .map(function(key) {
      return this.redisSmembers(key)
        .then(function(res) {
          return res;
        });
    });
});

/**
 * Generates the execution query for the KEYS redis operation.
 *
 * @return {Promise(Array.<string>)} A Promise with the execution query.
 * @private
 */
Fetch.prototype._generateKeysQuery = Promise.method(function(userTokens) {
  var flattenedUserTokens = __.flatten(userTokens);

  var allTokens = this.query.token.concat(flattenedUserTokens);

  var prefix = this.prefix + ':kansas:usage:';

  var dateRanges = this._prepareDateKeys();

  var totalTokens = allTokens.length;
  var totalDateRanges = dateRanges.length;

  var query = [];
  // get the 'fetch all records' out of the way fast...
  if (totalTokens === 0 && totalDateRanges === 0) {
    query.push(prefix += Fetch.WILDCARD);
  } else {
    if (totalDateRanges) {
      dateRanges.forEach(function(dateRange) {
        var queryPart = prefix + dateRange + ':' + Fetch.WILDCARD;
        if (totalTokens) {
          query = query.concat(this._generateTokensQuery(queryPart, allTokens));
        } else {
          query.push(queryPart);
        }
      }, this);
    } else {
      query = this._generateTokensQuery(prefix + Fetch.WILDCARD, allTokens);
    }
  }

  return query;
});

/**
 * Generate query for redis KEYS command.
 *
 * @param {string} prefix The prefix to use.
 * @param {Array.<string>} allTokens All tokens to query.
 * @return {Array.<string>} All queries based on provided arguments.
 * @private
 */
Fetch.prototype._generateTokensQuery = function(prefix, allTokens) {
  return allTokens.map(function(token) {
    return prefix + token;
  });
};

/**
 * Prepares the date range query, will return an array with the date ranges
 * to query, bare without prefixes.
 *
 * @return {Array.<string>} Array items to query by, eg ['2014-05-01'].
 */
Fetch.prototype._prepareDateKeys = function() {
  if (!this.query.from && !this.query.to) {
    return [];
  }

  // Set default TO range to today.
  var now = new Date();
  var toYear = now.getFullYear();
  var toMonth = now.getMonth();

  // Set default FROM range to when Kansas was originally released.
  var fromYear = 2013;
  var fromMonth = 2; // march
  if (this.query.from) {
    fromYear = this.query.from.getFullYear();
    fromMonth = this.query.from.getMonth();
  }

  if (this.query.to) {
    toYear = this.query.to.getFullYear();
    toMonth = this.query.to.getMonth();
  }

  var ranges = [];
  for (var year = fromYear; year <= toYear; year++) {
    var month = fromMonth;
    if (year !== fromYear) {
      month = 0;
    }
    for (; (year === toYear && month <= toMonth) ||
      (year < toYear && month <= 11); month++) {
      ranges.push(year + '-' + this._getStringMonth(month) + '-' + '01');
    }
  }
  return ranges;
};

/**
 * Returns a string format of a native Date month value (0-11).
 *
 * @param {number} month Native data month(0-11)
 * @return {string} String formated month ('01' - '12')
 */
Fetch.prototype._getStringMonth = function(month) {
  month++;
  if (month < 10) {
    return '0' + month;
  } else {
    return month + '';
  }
};

/**
 * Will perform the Redis KEYS operation and fetch all canonical keys that
 * match the desired user query.
 *
 * @param {Array.<string>} queries The KEYS queries to perform.
 * @return {Promise(Array.<string>)} A Promise with the canonical keys to fetch.
 */
Fetch.prototype._fetchKeys = Promise.method(function(queries) {
  return Promise.resolve(queries)
    .bind(this)
    .map(function(query) {
      return this.redisKeys(query);
    }, {concurrency: this._options.concurrency})
    .then(function(results) {
      this.canonicalKeys = __.uniq(__.flatten(results));
      return this.canonicalKeys;
    });
});

/**
 * Will parallelize fetching the usage keys and token items.
 *
 * @param {Array.<string>} keys All keys to fetch usage records for.
 * @return {Promise(Array)} Containing the results of the parallel operation.
 */
Fetch.prototype._fetchData = Promise.method(function(keys) {
  return Promise.all([
    this._fetchUsageRecords(keys),
    this._fetchTokenItems(keys),
  ]);
});

/**
 * Will fetch all the usage records based on the provided canonical keys.
 *
 * @param {Array.<string>} keys All keys to fetch usage records for.
 * @return {Promise(Array.<string>)} A promise with the results.
 * @private
 */
Fetch.prototype._fetchUsageRecords = Promise.method(function(keys) {
  return Promise.resolve(keys)
    .bind(this)
    .map(function(key) {
      return this.redisGet(key);
      // use concurrency / 2 as this is an op in parallel with another
      // redis query operation (fetch token items)
    }, {concurrency: ( this._options.concurrency / 2 )})
    .then(function(results) {
      this.usageResults = results;
      return this.usageResults;
    });
});

/**
 * Will fetch all the token items data objects.
 *
 * @param {Array.<string>} keys All keys to fetch usage records for.
 * @return {Promise(Array.<Object>)} A promise with the results.
 * @private
 */
Fetch.prototype._fetchTokenItems = Promise.method(function(keys) {
  var tokenKeys = this._extractTokenItemKeys(keys);
  return Promise.resolve(tokenKeys)
    .bind(this)
    .map(function(key) {
      return this.redisHgetall(key);

      // use concurrency / 2 as this is an op in parallel with another
      // redis query operation (fetch usage)
    }, {concurrency: ( this._options.concurrency / 2 )})
    .then(function(results) {
      this.tokenItems = results;

      // create an index of token items based on token
      this.tokenItemIndex = {};
      results.forEach(function(tokenItem) {
        this.tokenItemIndex[tokenItem.token] = tokenItem;
      }, this);
      return this.tokenItems;
    });
});

/**
 * Will extract unique token item keys from the usage keys and return
 * proper Kansas token paths for fetching the token items.
 *
 * @param {Array.<string>} keys All keys to fetch usage records for.
 * @return {Array.<strimg>} Proper Kansas key paths.
 * @private
 */
Fetch.prototype._extractTokenItemKeys = function(keys) {
  var tokens = [];
  keys.forEach(function(key) {
    var token = key.split(':').pop();
    if (tokens.indexOf(token) === -1) {
      tokens.push(token);
    }
  });

  var prefix = this.prefix + ':kansas:token:';
  return tokens.map(function(token) {
    return prefix + token;
  });
};

/**
 * Will Process all the raw redis results and combine them in a single
 * properly structured Kansas Metrics data object.
 *
 * @param {Array.<string>} usageResults The usage results as fetched.
 * @param {Array.<Object>} tokenItemResults The token items results.
 * @return {Promise(Array)} The final results.
 * @private
 */
Fetch.prototype._processResults = Promise.method(function(usageResults) {

  this.fetched = true;
  this.operates = false;

  var results = [];
  if (!usageResults.length) {
    return results;
  }
  results = usageResults.map(function(usageResult, index) {
    var canonicalKey = this.canonicalKeys[index];
    var keyParts = canonicalKey.split(':');
    var token = keyParts.pop();
    var datePeriod = keyParts.pop();
    var isCount = false;
    // beware of count type usage tokens
    if (datePeriod === 'count') {
      isCount = true;
      datePeriod = keyParts.pop();
    }
    var dtPeriod = new Date(datePeriod);
    var month = dtPeriod.getMonth() + 1;
    var year = dtPeriod.getFullYear();

    var tokenItem = this.tokenItemIndex[token];

    var item = {
      token: token,
      ownerId: tokenItem.ownerId,
      policyName: tokenItem.policyName,
      policyLimit: parseInt(tokenItem.limit, 10),
      isPolicyCount: isCount,
      month: month,
      year: year,
      date: dtPeriod.toISOString(),
      period: 'month',
      usage: parseInt(usageResult, 10),
    };
    return item;

  }, this);

  return results;
});
<commit_msg>Defense in case of token item not found<commit_after>/**
 * @fileOverview The fetch() method mixin implementation.
 */

var cip = require('cip');
var __ = require('lodash');
var Promise = require('bluebird');
var appErr = require('nodeon-error');

/**
 * The fetch() method mixin implementation.
 *
 * @constructor
 */
var Fetch = module.exports = cip.extend(function() {
  /** @type {?Object} A token based index for token items */
  this.tokenItemIndex = null;
});

/** @const {string} Wildcard used by redis for fetching keys */
Fetch.WILDCARD = '*';

/**
 * Execute the query.
 *
 * @return {Promise} The instance promise.
 */
Fetch.prototype.fetch = Promise.method(function() {
  if (this.operates || this.fetched) {
    // try to contain the error only in the fetch() invocation
    // and do not propagate it in the master defer.
    throw new appErr.Error('Already fetched from redis');
  }
  this.operates = true;

  return this._resolveTokensByUser()
    .bind(this)
    .then(this._generateKeysQuery)
    .then(this._fetchKeys)
    .then(this._fetchData)
    .spread(this._processResults);
});

/**
 * Will resolve all ownerIds to tokens if they exist in the query.
 *
 * @return {Promise(Array)} A Promise with an array of tokens.
 * @private
 */
Fetch.prototype._resolveTokensByUser = Promise.method(function() {
  var indexKeys = this.query.user.map(function(ownerId) {
    return this.prefix + ':kansas:index:token:' + ownerId;
  }, this);

  return Promise.resolve(indexKeys)
    .bind(this)
    .map(function(key) {
      return this.redisSmembers(key)
        .then(function(res) {
          return res;
        });
    });
});

/**
 * Generates the execution query for the KEYS redis operation.
 *
 * @return {Promise(Array.<string>)} A Promise with the execution query.
 * @private
 */
Fetch.prototype._generateKeysQuery = Promise.method(function(userTokens) {
  var flattenedUserTokens = __.flatten(userTokens);

  var allTokens = this.query.token.concat(flattenedUserTokens);

  var prefix = this.prefix + ':kansas:usage:';

  var dateRanges = this._prepareDateKeys();

  var totalTokens = allTokens.length;
  var totalDateRanges = dateRanges.length;

  var query = [];
  // get the 'fetch all records' out of the way fast...
  if (totalTokens === 0 && totalDateRanges === 0) {
    query.push(prefix += Fetch.WILDCARD);
  } else {
    if (totalDateRanges) {
      dateRanges.forEach(function(dateRange) {
        var queryPart = prefix + dateRange + ':' + Fetch.WILDCARD;
        if (totalTokens) {
          query = query.concat(this._generateTokensQuery(queryPart, allTokens));
        } else {
          query.push(queryPart);
        }
      }, this);
    } else {
      query = this._generateTokensQuery(prefix + Fetch.WILDCARD, allTokens);
    }
  }

  return query;
});

/**
 * Generate query for redis KEYS command.
 *
 * @param {string} prefix The prefix to use.
 * @param {Array.<string>} allTokens All tokens to query.
 * @return {Array.<string>} All queries based on provided arguments.
 * @private
 */
Fetch.prototype._generateTokensQuery = function(prefix, allTokens) {
  return allTokens.map(function(token) {
    return prefix + token;
  });
};

/**
 * Prepares the date range query, will return an array with the date ranges
 * to query, bare without prefixes.
 *
 * @return {Array.<string>} Array items to query by, eg ['2014-05-01'].
 */
Fetch.prototype._prepareDateKeys = function() {
  if (!this.query.from && !this.query.to) {
    return [];
  }

  // Set default TO range to today.
  var now = new Date();
  var toYear = now.getFullYear();
  var toMonth = now.getMonth();

  // Set default FROM range to when Kansas was originally released.
  var fromYear = 2013;
  var fromMonth = 2; // march
  if (this.query.from) {
    fromYear = this.query.from.getFullYear();
    fromMonth = this.query.from.getMonth();
  }

  if (this.query.to) {
    toYear = this.query.to.getFullYear();
    toMonth = this.query.to.getMonth();
  }

  var ranges = [];
  for (var year = fromYear; year <= toYear; year++) {
    var month = fromMonth;
    if (year !== fromYear) {
      month = 0;
    }
    for (; (year === toYear && month <= toMonth) ||
      (year < toYear && month <= 11); month++) {
      ranges.push(year + '-' + this._getStringMonth(month) + '-' + '01');
    }
  }
  return ranges;
};

/**
 * Returns a string format of a native Date month value (0-11).
 *
 * @param {number} month Native data month(0-11)
 * @return {string} String formated month ('01' - '12')
 */
Fetch.prototype._getStringMonth = function(month) {
  month++;
  if (month < 10) {
    return '0' + month;
  } else {
    return month + '';
  }
};

/**
 * Will perform the Redis KEYS operation and fetch all canonical keys that
 * match the desired user query.
 *
 * @param {Array.<string>} queries The KEYS queries to perform.
 * @return {Promise(Array.<string>)} A Promise with the canonical keys to fetch.
 */
Fetch.prototype._fetchKeys = Promise.method(function(queries) {
  return Promise.resolve(queries)
    .bind(this)
    .map(function(query) {
      return this.redisKeys(query);
    }, {concurrency: this._options.concurrency})
    .then(function(results) {
      this.canonicalKeys = __.uniq(__.flatten(results));
      return this.canonicalKeys;
    });
});

/**
 * Will parallelize fetching the usage keys and token items.
 *
 * @param {Array.<string>} keys All keys to fetch usage records for.
 * @return {Promise(Array)} Containing the results of the parallel operation.
 */
Fetch.prototype._fetchData = Promise.method(function(keys) {
  return Promise.all([
    this._fetchUsageRecords(keys),
    this._fetchTokenItems(keys),
  ]);
});

/**
 * Will fetch all the usage records based on the provided canonical keys.
 *
 * @param {Array.<string>} keys All keys to fetch usage records for.
 * @return {Promise(Array.<string>)} A promise with the results.
 * @private
 */
Fetch.prototype._fetchUsageRecords = Promise.method(function(keys) {
  return Promise.resolve(keys)
    .bind(this)
    .map(function(key) {
      return this.redisGet(key);
      // use concurrency / 2 as this is an op in parallel with another
      // redis query operation (fetch token items)
    }, {concurrency: ( this._options.concurrency / 2 )})
    .then(function(results) {
      this.usageResults = results;
      return this.usageResults;
    });
});

/**
 * Will fetch all the token items data objects.
 *
 * @param {Array.<string>} keys All keys to fetch usage records for.
 * @return {Promise(Array.<Object>)} A promise with the results.
 * @private
 */
Fetch.prototype._fetchTokenItems = Promise.method(function(keys) {
  var tokenKeys = this._extractTokenItemKeys(keys);
  return Promise.resolve(tokenKeys)
    .bind(this)
    .map(function(key) {
      return this.redisHgetall(key);

      // use concurrency / 2 as this is an op in parallel with another
      // redis query operation (fetch usage)
    }, {concurrency: ( this._options.concurrency / 2 )})
    .then(function(results) {
      this.tokenItems = results;

      // create an index of token items based on token
      this.tokenItemIndex = {};
      results.forEach(function(tokenItem) {
        if (!tokenItem) {
          return;
        }
        this.tokenItemIndex[tokenItem.token] = tokenItem;
      }, this);
      return this.tokenItems;
    });
});

/**
 * Will extract unique token item keys from the usage keys and return
 * proper Kansas token paths for fetching the token items.
 *
 * @param {Array.<string>} keys All keys to fetch usage records for.
 * @return {Array.<strimg>} Proper Kansas key paths.
 * @private
 */
Fetch.prototype._extractTokenItemKeys = function(keys) {
  var tokens = [];
  keys.forEach(function(key) {
    var token = key.split(':').pop();
    if (tokens.indexOf(token) === -1) {
      tokens.push(token);
    }
  });

  var prefix = this.prefix + ':kansas:token:';
  return tokens.map(function(token) {
    return prefix + token;
  });
};

/**
 * Will Process all the raw redis results and combine them in a single
 * properly structured Kansas Metrics data object.
 *
 * @param {Array.<string>} usageResults The usage results as fetched.
 * @param {Array.<Object>} tokenItemResults The token items results.
 * @return {Promise(Array)} The final results.
 * @private
 */
Fetch.prototype._processResults = Promise.method(function(usageResults) {

  this.fetched = true;
  this.operates = false;

  var results = [];
  if (!usageResults.length) {
    return results;
  }
  results = usageResults.map(function(usageResult, index) {
    var canonicalKey = this.canonicalKeys[index];
    var keyParts = canonicalKey.split(':');
    var token = keyParts.pop();
    var datePeriod = keyParts.pop();
    var isCount = false;
    // beware of count type usage tokens
    if (datePeriod === 'count') {
      isCount = true;
      datePeriod = keyParts.pop();
    }
    var dtPeriod = new Date(datePeriod);
    var month = dtPeriod.getMonth() + 1;
    var year = dtPeriod.getFullYear();

    var tokenItem = this.tokenItemIndex[token];

    if (!tokenItem) {
      return null;
    }

    var item = {
      token: token,
      ownerId: tokenItem.ownerId,
      policyName: tokenItem.policyName,
      policyLimit: parseInt(tokenItem.limit, 10),
      isPolicyCount: isCount,
      month: month,
      year: year,
      date: dtPeriod.toISOString(),
      period: 'month',
      usage: parseInt(usageResult, 10),
    };
    return item;

  }, this);

  // eliminate null results
  results = results.filter(function(item) {
    return !!item;
  });

  return results;
});
<|endoftext|>


<commit_before>/**
 * Инъект-скрипт. Вешает обработчики для плеера и радио.
 * Этот скрипт имеет доступ к JS переменным этого window. Поэтому мы можем пользоваться JS функциями от PDJ.
 *
 * Deliaz, Декабрь 2013
 * http://promodj.com/deliaz
 */

console.log("Скрипт инъектирован.");

document.body.addEventListener('playstop_ext', function() {
    // Для плеера миксов
    var CP = window.CORE.CurrentPlayer;
    if(CP) {
        switch(CP.status) {
            case 'play':
                CP.perform("pause");
                console.log("Пауза");
                break;
            case 'pause':
                CP.perform("play");
                console.log("Воспроизведение");
                break;
        }
    }

    // Для радио
    var R = window.Radio;
    if(R) {
        if (R.played) {
            R.Playa.PlayerStop();
            R.Unfire();
            console.log("Радио выкл.");
        }
        else {
            R.Playa.PlayerPlay();
            console.log("Радио вкл.");
        }
    }
});<commit_msg>fix: ошибка с повторным запуском радио<commit_after>/**
 * Инъект-скрипт. Вешает обработчики для плеера и радио.
 * Этот скрипт имеет доступ к JS переменным этого window. Поэтому мы можем пользоваться JS функциями от PDJ.
 *
 * Deliaz, Декабрь 2013
 * http://promodj.com/deliaz
 */

console.log("Скрипт инъектирован.");

document.body.addEventListener('playstop_ext', function() {
    // Для плеера миксов
    var CP = window.CORE.CurrentPlayer;
    if(CP) {
        switch(CP.status) {
            case 'play':
                CP.perform("pause");
                console.log("Пауза");
                break;
            case 'pause':
                CP.perform("play");
                console.log("Воспроизведение");
                break;
        }
    }

    // Для радио
    var R = window.Radio;
    if(R) {
        if (R.played) {
            R.Playa.PlayerStop();
            R.Unfire();
            console.log("Радио выкл.");
            R.played = false;
        }
        else {
            R.Playa.PlayerPlay();
            console.log("Радио вкл.");
            R.played = true;
        }
    }
});<|endoftext|>


<commit_before>OV.Panel = class
{
    constructor (parentDiv)
    {
        this.parentDiv = parentDiv;
        this.panelDiv = $('<div>').appendTo (parentDiv).hide ();
        this.visible = false;
    }

    GetIcon ()
    {
        return null;
    }

    GetPanelDiv ()
    {
        return this.panelDiv;
    }

    IsVisible ()
    {
        return this.visible;
    }

    Show (show)
    {
        if (this.visible === show) {
            return;
        }

        this.visible = show;
        if (this.visible) {
            this.panelDiv.show ();
        } else {
            this.panelDiv.hide ();
        }
    }

    Resize ()
    {

    }

    Clear ()
    {

    }
};

OV.PanelSet = class
{
    constructor (parentDiv)
    {
        this.parentDiv = parentDiv;
        this.menuDiv = $('<div>').addClass ('ov_panel_set_menu').appendTo (parentDiv);
        this.contentDiv = $('<div>').addClass ('ov_panel_set_content').addClass ('ov_thin_scrollbar').appendTo (parentDiv);
        this.panels = [];
        this.panelButtons = [];
        this.panelsVisible = true;
        this.requestedPanelsVisible = true;
        this.panelsPrevWidth = null;
        this.callbacks = null;
    }

    Init (callbacks)
    {
        this.callbacks = callbacks;
    }

    GetContentDiv ()
    {
        return this.contentDiv;
    }

    AddPanel (panel)
    {
        this.panels.push (panel);
        let button = OV.AddSvgIcon (this.menuDiv, panel.GetIcon (), 'ov_panel_set_menu_button');
        button.attr ('alt', panel.GetName ()).attr ('title', panel.GetName ());
        this.panelButtons.push (button);
        button.click (() => {
            if (panel === this.GetVisiblePanel ()) {
                this.ShowPanels (false);
            } else {
                this.ShowPanels (true);
                this.ShowPanel (panel);
            }
        });
    }

    IsPanelsVisible ()
    {
        return this.panelsVisible;
    }

    ShowPanels (show)
    {
        if (!this.IsParentVisible ()) {
            this.requestedPanelsVisible = show;
            return;
        }

        if (this.panelsVisible === show) {
            return;
        }

        this.panelsVisible = show;
        this.requestedPanelsVisible = show;
        if (this.panelsVisible) {
            this.contentDiv.show ();
            this.parentDiv.outerWidth (this.menuDiv.outerWidth (true) + this.panelsPrevWidth, true);
        } else {
            for (let otherPanelButton of this.panelButtons) {
                otherPanelButton.removeClass ('selected');
            }
            this.panelsPrevWidth = this.contentDiv.outerWidth (true);
            this.parentDiv.outerWidth (this.menuDiv.outerWidth (true), true);
            this.contentDiv.hide ();
        }

        this.callbacks.onShowHidePanels (this.panelsVisible);
        this.callbacks.onResize ();
    }

    ShowPanel (panel)
    {
        for (let otherPanel of this.panels) {
            otherPanel.Show (false);
        }

        for (let otherPanelButton of this.panelButtons) {
            otherPanelButton.removeClass ('selected');
        }

        let panelButton = this.GetPanelButton (panel);
        panelButton.addClass ('selected');

        panel.Show (true);
        panel.Resize ();
    }

    GetVisiblePanel ()
    {
        if (!this.panelsVisible) {
            return null;
        }
        for (let panel of this.panels) {
            if (panel.IsVisible ()) {
                return panel;
            }
        }
        return null;
    }

    SetPanelIcon (panel, icon)
    {
        let panelButton = this.GetPanelButton (panel);
        OV.SetSvgIconImage (panelButton, icon);
    }

    GetPanelButton (panel)
    {
        const panelIndex = this.panels.indexOf (panel);
        return this.panelButtons[panelIndex];
    }

    Resize ()
    {
        if (this.requestedPanelsVisible !== this.isPanelsVisible) {
            this.ShowPanels (this.requestedPanelsVisible);
        }
        let height = this.parentDiv.height ();
        this.menuDiv.outerHeight (height, true);
        this.contentDiv.outerHeight (height, true);
        for (let panel of this.panels) {
            panel.Resize ();
        }
    }

    IsParentVisible ()
    {
        return this.parentDiv.is (':visible');
    }

    Clear ()
    {
        for (let panel of this.panels) {
            panel.Clear ();
        }
    }
};
<commit_msg>Panel resize speedup.<commit_after>OV.Panel = class
{
    constructor (parentDiv)
    {
        this.parentDiv = parentDiv;
        this.panelDiv = $('<div>').appendTo (parentDiv).hide ();
        this.visible = false;
    }

    GetIcon ()
    {
        return null;
    }

    GetPanelDiv ()
    {
        return this.panelDiv;
    }

    IsVisible ()
    {
        return this.visible;
    }

    Show (show)
    {
        if (this.visible === show) {
            return;
        }

        this.visible = show;
        if (this.visible) {
            this.panelDiv.show ();
        } else {
            this.panelDiv.hide ();
        }
    }

    Resize ()
    {

    }

    Clear ()
    {

    }
};

OV.PanelSet = class
{
    constructor (parentDiv)
    {
        this.parentDiv = parentDiv;
        this.menuDiv = $('<div>').addClass ('ov_panel_set_menu').appendTo (parentDiv);
        this.contentDiv = $('<div>').addClass ('ov_panel_set_content').addClass ('ov_thin_scrollbar').appendTo (parentDiv);
        this.panels = [];
        this.panelButtons = [];
        this.panelsVisible = true;
        this.requestedPanelsVisible = true;
        this.panelsPrevWidth = null;
        this.callbacks = null;
    }

    Init (callbacks)
    {
        this.callbacks = callbacks;
    }

    GetContentDiv ()
    {
        return this.contentDiv;
    }

    AddPanel (panel)
    {
        this.panels.push (panel);
        let button = OV.AddSvgIcon (this.menuDiv, panel.GetIcon (), 'ov_panel_set_menu_button');
        button.attr ('alt', panel.GetName ()).attr ('title', panel.GetName ());
        this.panelButtons.push (button);
        button.click (() => {
            if (panel === this.GetVisiblePanel ()) {
                this.ShowPanels (false);
            } else {
                this.ShowPanels (true);
                this.ShowPanel (panel);
            }
        });
    }

    IsPanelsVisible ()
    {
        return this.panelsVisible;
    }

    ShowPanels (show)
    {
        if (!this.IsParentVisible ()) {
            this.requestedPanelsVisible = show;
            return;
        }

        if (this.panelsVisible === show) {
            return;
        }

        this.panelsVisible = show;
        this.requestedPanelsVisible = show;
        if (this.panelsVisible) {
            this.contentDiv.show ();
            this.parentDiv.outerWidth (this.menuDiv.outerWidth (true) + this.panelsPrevWidth, true);
        } else {
            for (let otherPanelButton of this.panelButtons) {
                otherPanelButton.removeClass ('selected');
            }
            this.panelsPrevWidth = this.contentDiv.outerWidth (true);
            this.parentDiv.outerWidth (this.menuDiv.outerWidth (true), true);
            this.contentDiv.hide ();
        }

        this.callbacks.onShowHidePanels (this.panelsVisible);
        this.callbacks.onResize ();
    }

    ShowPanel (panel)
    {
        for (let otherPanel of this.panels) {
            otherPanel.Show (false);
        }

        for (let otherPanelButton of this.panelButtons) {
            otherPanelButton.removeClass ('selected');
        }

        let panelButton = this.GetPanelButton (panel);
        panelButton.addClass ('selected');

        panel.Show (true);
        panel.Resize ();
    }

    GetVisiblePanel ()
    {
        if (!this.panelsVisible) {
            return null;
        }
        for (let panel of this.panels) {
            if (panel.IsVisible ()) {
                return panel;
            }
        }
        return null;
    }

    SetPanelIcon (panel, icon)
    {
        let panelButton = this.GetPanelButton (panel);
        OV.SetSvgIconImage (panelButton, icon);
    }

    GetPanelButton (panel)
    {
        const panelIndex = this.panels.indexOf (panel);
        return this.panelButtons[panelIndex];
    }

    Resize ()
    {
        if (this.requestedPanelsVisible !== this.panelsVisible) {
            this.ShowPanels (this.requestedPanelsVisible);
        }
        let height = this.parentDiv.height ();
        this.menuDiv.outerHeight (height, true);
        this.contentDiv.outerHeight (height, true);
        for (let panel of this.panels) {
            panel.Resize ();
        }
    }

    IsParentVisible ()
    {
        return this.parentDiv.is (':visible');
    }

    Clear ()
    {
        for (let panel of this.panels) {
            panel.Clear ();
        }
    }
};
<|endoftext|>


<commit_before>"use strict";

var querystring = require('querystring');
var https = require('https');
var _ = require('underscore');
var fs = require('fs');
var SmtpapiHeaders = require('./smtpapi_headers');

function Email(params) {
  /*
   * Default parameters for sending mail
   */
  var default_mail_params = {
    to: [],
    from: '',
    smtpapi: new SmtpapiHeaders(),
    subject: '',
    text: '',
    html: '',
    bcc: [],
    replyto: '',
    date: new Date(),
    files: {},
    file_data: {},
    headers: {}
  };

  _.extend(this, default_mail_params, params);
}

/*
 * Validates an email. This is used before sending, but
 * can still be invoked programatically
 *
 * @return {Boolean} The result of the validation
 */
Email.prototype.validate = function() {
  //TODO: add validation
}

Email.prototype.setHeaders = function(val) {
  if (_.isObject(val)) {
    this.headers = val;
  }
}

Email.prototype.addHeaders = function(val){
  if (_.isObject(val)) {
    _.extend(this.headers, val);
  }
}

Email.prototype.addTo = function(to) {
  this.smtpapi.addTo(to);
}

Email.prototype.addSubVal = function(key, val) {
  this.smtpapi.addSubVal(key, val);
}

Email.prototype.setUniqueArgs = function(val) {
  this.smtpapi.setUniqueArgs(val);
}

Email.prototype.addUniqueArgs = function (val) {
  this.smtpapi.addUniqueArgs(val);
}

Email.prototype.setCategory = function(val) {
  this.smtpapi.setCategory(val);
}

Email.prototype.addCategory = function(val) {
  this.smtpapi.addCategory(val);
}

Email.prototype.setSection = function(val) {
  this.smtpapi.setSection(val);
}

Email.prototype.addSection = function(val) {
  this.smtpapi.addSection(val);
}

Email.prototype.addFilterSetting = function(filter, setting, val) {
  this.smtpapi.addFilterSetting(filter, setting, val);
}

Email.prototype.setFilterSetting = function(filters) {
  this.smtpapi.setFilterSetting(filters);
}

Email.prototype.addFile = function(filename, filepath) {
  this.files[filename] = filepath;
}

Email.prototype.processFiles = function(callback) {
  var self = this;
  var attachments_count = _.size(this.files);
  _(this.files).each(function(v, k) {
    fs.readFile(v, function(error, data) {
      attachments_count--;
      if (error) {
        return callback(false, error);
      } else {
        self.file_data[k] = data;
      }

      if (attachments_count == 0) {
        callback(true);
      }
    });
  });
}

Email.prototype.toWebFormat = function() {
  var data = {
    to: this.to,
    from: this.from,
    'x-smtpapi': this.smtpapi.toJson(),
    subject: this.subject,
    text: this.text,
    html: this.html,
    bcc: this.bcc,
    replyto: this.replyto,
    headers: JSON.stringify(this.headers)
  };

  // there needs to be at least 1 to address.
  // If it is missing, just copy over the from.
  // Only do this is we have a value for the to
  // address on this.smtpapi
  this.checkAddTo(data);

  return data;
}

Email.prototype.toSmtpFormat = function() {
  var data = {
    to: this.to,
    sender: this.from,
    subject: this.subject,
    body: this.text,
    html: this.html,
    reply_to: this.replyto,
    headers: this.headers
  };
  data.headers['x-smtpapi'] = this.smtpapi.toJson();

  if (_.size(this.file_data) > 0) {
    var attachments = [];
    _(this.file_data).each(function(v, k) {
      attachments.push({filename: k, contents: v});
    });
    data.attachments = attachments;
  }

  // there needs to be at least 1 to address.
  // If it is missing, just copy over the from.
  // Only do this is we have a value for the to
  // address on this.smtpapi
  this.checkAddTo(data);

  return data;
}

Email.prototype.checkAddTo = function(data) {
  if (_.isEmpty(data.to) && this.smtpapi.to && !_.isEmpty(this.smtpapi.to)) {
    data.to = data.from;
  }
}

Email.prototype.hasFiles = function() {
  return _(this.files).size() > 0;
}

module.exports = Email;
<commit_msg>Fixed pulling data.to from data.from in case of smtpapi<commit_after>"use strict";

var querystring = require('querystring');
var https = require('https');
var _ = require('underscore');
var fs = require('fs');
var SmtpapiHeaders = require('./smtpapi_headers');

function Email(params) {
  /*
   * Default parameters for sending mail
   */
  var default_mail_params = {
    to: [],
    from: '',
    smtpapi: new SmtpapiHeaders(),
    subject: '',
    text: '',
    html: '',
    bcc: [],
    replyto: '',
    date: new Date(),
    files: {},
    file_data: {},
    headers: {}
  };

  _.extend(this, default_mail_params, params);
}

/*
 * Validates an email. This is used before sending, but
 * can still be invoked programatically
 *
 * @return {Boolean} The result of the validation
 */
Email.prototype.validate = function() {
  //TODO: add validation
}

Email.prototype.setHeaders = function(val) {
  if (_.isObject(val)) {
    this.headers = val;
  }
}

Email.prototype.addHeaders = function(val){
  if (_.isObject(val)) {
    _.extend(this.headers, val);
  }
}

Email.prototype.addTo = function(to) {
  this.smtpapi.addTo(to);
}

Email.prototype.addSubVal = function(key, val) {
  this.smtpapi.addSubVal(key, val);
}

Email.prototype.setUniqueArgs = function(val) {
  this.smtpapi.setUniqueArgs(val);
}

Email.prototype.addUniqueArgs = function (val) {
  this.smtpapi.addUniqueArgs(val);
}

Email.prototype.setCategory = function(val) {
  this.smtpapi.setCategory(val);
}

Email.prototype.addCategory = function(val) {
  this.smtpapi.addCategory(val);
}

Email.prototype.setSection = function(val) {
  this.smtpapi.setSection(val);
}

Email.prototype.addSection = function(val) {
  this.smtpapi.addSection(val);
}

Email.prototype.addFilterSetting = function(filter, setting, val) {
  this.smtpapi.addFilterSetting(filter, setting, val);
}

Email.prototype.setFilterSetting = function(filters) {
  this.smtpapi.setFilterSetting(filters);
}

Email.prototype.addFile = function(filename, filepath) {
  this.files[filename] = filepath;
}

Email.prototype.processFiles = function(callback) {
  var self = this;
  var attachments_count = _.size(this.files);
  _(this.files).each(function(v, k) {
    fs.readFile(v, function(error, data) {
      attachments_count--;
      if (error) {
        return callback(false, error);
      } else {
        self.file_data[k] = data;
      }

      if (attachments_count == 0) {
        callback(true);
      }
    });
  });
}

Email.prototype.toWebFormat = function() {
  var data = {
    to: this.to,
    from: this.from,
    'x-smtpapi': this.smtpapi.toJson(),
    subject: this.subject,
    text: this.text,
    html: this.html,
    bcc: this.bcc,
    replyto: this.replyto,
    headers: JSON.stringify(this.headers)
  };

  // there needs to be at least 1 to address.
  // If it is missing, just copy over the from.
  // Only do this is we have a value for the to
  // address on this.smtpapi
  this.checkAddTo(data);

  return data;
}

Email.prototype.toSmtpFormat = function() {
  var data = {
    to: this.to,
    sender: this.from,
    subject: this.subject,
    body: this.text,
    html: this.html,
    reply_to: this.replyto,
    headers: this.headers
  };
  data.headers['x-smtpapi'] = this.smtpapi.toJson();

  if (_.size(this.file_data) > 0) {
    var attachments = [];
    _(this.file_data).each(function(v, k) {
      attachments.push({filename: k, contents: v});
    });
    data.attachments = attachments;
  }

  // there needs to be at least 1 to address.
  // If it is missing, just copy over the from.
  // Only do this is we have a value for the to
  // address on this.smtpapi
  this.checkAddTo(data);

  return data;
}

Email.prototype.checkAddTo = function(data) {
  if (_.isEmpty(data.to) && this.smtpapi.to && !_.isEmpty(this.smtpapi.to)) {
    data.to = this.from;
  }
}

Email.prototype.hasFiles = function() {
  return _(this.files).size() > 0;
}

module.exports = Email;
<|endoftext|>


<commit_before>var http = require("http"),
    https = require("https"),
    urllib = require("url"),
    utillib = require("util"),
    zlib = require('zlib'),
    dns = require('dns'),
    Stream = require("stream").Stream,
    CookieJar = require("./cookiejar").CookieJar,
    Iconv = require("iconv").Iconv;

/*

maxRedirects : 10
disableRedirects : false
headers: {}
maxResponseLength : Infinity
method: GET
payload: str
disableGzip: false
asyncDnsLoookup: false

cookies: ['name=val']

outputEncoding: utf-8 | latin-1 jne

disableDecoding: false
*/

//TODO:
// - meta infosse faili nimi, juhul kui tegu downloadiga
// - wrapper fetch(url, callback)
// - wrapperile options.setEncoding = true | "UTF-8"
// - dokumentatsioon

exports.FetchStream = FetchStream;
exports.CookieJar = CookieJar;

exports.fetchUrl = fetchUrl;

function FetchStream(url, options){
    Stream.call(this);

    this.url = url;
    if(!this.url){
        return this.emit("error", new Error("url not defined"));
    }

    this.userAgent = "FetchStream";

    this._redirect_count = 0;

    this.options = options || {};
    this.normalizeOptions();

    this.runStream(url);
}
utillib.inherits(FetchStream, Stream);

FetchStream.prototype.normalizeOptions = function(){

    // cookiejar
    this.cookieJar = this.options.cookieJar || new CookieJar();

    // default redirects - 10
    // if disableRedirect is set, then 0
    if(!this.options.disableRedirect && typeof this.options.maxredirects != "number" &&
      !(this.options.maxredirects instanceof Number)){
        this.options.maxRedirects = 10;
    }else if(this.options.disableRedirects){
        this.options.maxRedirects = 0;
    }

    // normalize header keys
    // HTTP and HTTPS takes in key names in case insensitive but to find
    // an exact value from an object key name needs to be case sensitive
    // so we're just lowercasing all input keys
    this.options.headers = this.options.headers || {};

    var keys = Object.keys(this.options.headers),
        newheaders = {},
        i;

    for(i=keys.length-1; i>=0; i--){
        newheaders[keys[i].toLowerCase().trim()] = this.options.headers[keys[i]];
    }

    this.options.headers = newheaders;

    if(!this.options.headers["user-agent"]){
        this.options.headers["user-agent"] = this.userAgent;
    }

    if(!this.options.headers["pragma"]){
        this.options.headers["pragma"] = "no-cache";
    }

    if(!this.options.headers["cache-control"]){
        this.options.headers["cache-control"] = "no-cache";
    }

    if(!this.options.disableGzip){
        this.options.headers['accept-encoding'] = 'gzip, deflate';
    }else{
        delete this.options.headers['accept-encoding'];
    }

    // max length for the response,
    // if not set, default is Infinity
    if(!this.options.maxResponseLength){
        this.options.maxResponseLength = Infinity;
    }

    // method:
    // defaults to GET, or when payload present to POST
    if(!this.options.method){
        this.options.method = this.options.payload || this.options.payloadSize?"POST":"GET";
    }

    // set cookies
    // takes full cookie definition strings as params
    if(this.options.cookies){
        for(var i=0; i<this.options.cookies.length; i++){
            this.cookieJar.setCookie(this.options.cookies[i], this.url);
        }
    }

}

FetchStream.prototype.parseUrl = function(url){
    var urlparts = urllib.parse(url, false, true),
        transport,
        urloptions = {
            host: urlparts.hostname,
            port: urlparts.port,
            path: urlparts.pathname + (urlparts.search || "") || "/",
            method: this.options.method
        };

    switch(urlparts.protocol){
        case "https:":
            transport = https;
            break;
        case "http:":
        default:
            transport = http;
            break;
    }

    if(!urloptions.port){
        switch(urlparts.protocol){
            case "https:":
                urloptions.port = 443;
                break;
            case "http:":
            default:
                urloptions.port = 80;
                break;
        }
    }

    urloptions.headers = this.options.headers;

    return {
        urloptions: urloptions,
        transport: transport
    }
}

FetchStream.prototype.setEncoding = function(encoding){
    this.options.encoding = encoding;
}

FetchStream.prototype.absoluteUrl = function(url, base){

    var target_url = urllib.parse(url, false, true),
        base_url = urllib.parse(base || "", false, true),
        base_path, target_path, final_path;

    // if protocol is set, then it's good to go
    if(target_url.protocol){
        return url;
    }

    // the url might be int the form of "//www.example.com" with leading slashes -
    // the protocol from the base url must be used, defaults to http
    if(target_url.hostname){
        return (base_url.protocol || "http:") + (url.substr(0,2)!="//"?"//":"") + url;
    }

    // this is absolute path for relative domain
    if((target_url.pathname || "/").substr(0,1)=="/"){
        return (base_url.protocol || "http:") + "//" + (base_url.hostname || "") + url;
    }

    // relative path
    // remove also .. and . directory references
    base_path = (base_url.pathname || "/").split("/");
    base_path.pop(); // ditch the last element, empty for dir or a file name

    target_path = (target_url.pathname || "/").split("/");

    target_path = base_path.concat(target_path);
    final_path = [];

    target_path.forEach(function(dir){
        if(dir=="."){
            return;
        }

        if(dir==".."){
            final_path.pop();
            return;
        }

        if(dir){
            final_path.push(dir);
        }
    });

    return (base_url.protocol || "http:") + "//" + (base_url.hostname || "") + "/" +
        final_path.join("/") + (target_url.search || "");
}

FetchStream.prototype.runStream = function(url){
    var url_data = this.parseUrl(url),
        cookies = this.cookieJar.getCookies(url);

    if(cookies){
        url_data.urloptions.headers.cookie = cookies;
    }else{
        delete url_data.urloptions.headers.cookie;
    }

    if(this.options.payload){
        url_data.urloptions.headers['content-length'] = Buffer.byteLength(this.options.payload || "","utf-8");
    }

    if(this.options.payloadSize){
        url_data.urloptions.headers['content-length'] = this.options.payloadSize;
    }

    if (this.options.asyncDnsLoookup) {
        var dnsCallback = (function (err, adresses){
            if (err) {
                this.emit("error", err);
                return;
            }

            url_data.urloptions.headers['host'] = url_data.urloptions.hostname+url_data.urloptions.port;
            url_data.urloptions.hostname = adresses[0];
            url_data.urloptions.host=url_data.urloptions.hostname  + (url_data.urloptions.port || '');

            this._runStream(url_data, url);
        }).bind(this);

        dns.resolve4(url_data.urloptions.host, dnsCallback);
    } else {
        this._runStream(url_data, url);
    }
}

FetchStream.prototype._runStream = function(url_data, url){

    var req = url_data.transport.request(url_data.urloptions, (function(res) {

        // catch new cookies before potential redirect
        if(Array.isArray(res.headers['set-cookie'])){
            for(var i=0; i<res.headers['set-cookie'].length; i++){
                this.cookieJar.setCookie(res.headers['set-cookie'][i], url)
            }
        }

        if([301, 302].indexOf(res.statusCode)>=0){
            if(!this.options.disableRedirects && this.options.maxRedirects>this._redirect_count && res.headers.location){
                this._redirect_count++;
                this.runStream(this.absoluteUrl(res.headers.location, url));
                return;
            }
        }

        this.meta = {
            status: res.statusCode,
            responseHeaders: res.headers,
            finalUrl: url,
            redirectCount: this._redirect_count,
            cookieJar: this.cookieJar
        }

        var curlen = 0,
            maxlen,

            receive = (function(chunk){

                if(curlen + chunk.length > this.options.maxResponseLength){
                    maxlen = this.options.maxResponseLength - curlen;
                }else{
                    maxlen = chunk.length;
                }
                if(maxlen<=0)return;

                curlen += Math.min(maxlen, chunk.length);

                if(maxlen>=chunk.length){
                    if(this.options.encoding){
                        this.emit("data", chunk.toString(this.options.encoding));
                    }else{
                        this.emit("data", chunk);
                    }
                }else{
                    if(this.options.encoding){
                        this.emit("data", chunk.slice(0, maxlen).toString(this.options.encoding));
                    }else{
                        this.emit("data", chunk.slice(0, maxlen));
                    }
                }
            }).bind(this),

            error = (function(e){
                this.emit("error", e);
            }).bind(this),

            end = (function(){
                this.emit("end");
            }).bind(this),

            unpack = (function(type, res){
                var z = zlib["create"+type]();
                z.on("data", receive);
                z.on("error", error);
                z.on("end", end);
                res.pipe(z);
            }).bind(this);

        this.emit("meta", this.meta);

        if(res.headers['content-encoding']){
            switch(res.headers['content-encoding'].toLowerCase().trim()){
                case "gzip":
                    return unpack("Gunzip", res);
                case "deflate":
                    return unpack("InflateRaw", res);
            }
        }

        res.on('data', receive);
        res.on('end', end);

    }).bind(this));

    req.on('error', (function(e){
        this.emit("error", e);
    }).bind(this));

    if(this.options.payload){
        req.end(this.options.payload);
    }else if(this.options.payloadStream){
        this.options.payloadStream.pipe(req);
        this.options.payloadStream.resume();
    }else{
        req.end();
    }
}

function fetchUrl(url, options, callback){
    if(!callback && typeof options=="function"){
        callback = options;
        options = undefined;
    }
    options = options || {};

    var fetchstream = new FetchStream(url, options),
        response_data, chunks = [], length=0, curpos=0, buffer,
        content_type;

    fetchstream.on("meta", function(meta){
        response_data = meta;
        content_type = _parseContentType(meta.responseHeaders['content-type']);
    });

    fetchstream.on("data", function(chunk){
        if(chunk){
            chunks.push(chunk);
            length += chunk.length;
        }
    });

    fetchstream.on("error", function(error){
        callback(error);
    });

    fetchstream.on("end", function(error){
        var convert;

        buffer = new Buffer(length);
        for(var i=0, len = chunks.length; i<len; i++){
            chunks[i].copy(buffer, curpos);
            curpos += chunks[i].length;
        }

        if(content_type.mimeType == "text/html"){
            content_type.charset = _findHTMLCharset(buffer) || content_type.charset;
        }

        content_type.charset = (options.overrideCharset || content_type.charset || "utf-8").trim().toLowerCase();

        if(!this.options.disableDecoding && !content_type.charset.match(/^utf-?8$/i)){
            try{
                convert = new Iconv(content_type.charset, "UTF-8//TRANSLIT//IGNORE");
                buffer = convert.convert(buffer);
            }catch(E){}
        }

        if(this.options.outputEncoding){
            callback(null, response_data, buffer.toString(this.options.outputEncoding));
        }else{
            callback(null, response_data, buffer);
        }

    });
}

function _parseContentType(str){
    if(!str){
        return {};
    }
    var parts = str.split(";"),
        mimeType = parts.shift(),
        charset, chparts;

    for(var i=0, len = parts.length; i<len; i++){
        chparts = parts[i].split("=");
        if(chparts.length>1){
            if(chparts[0].trim().toLowerCase() == "charset"){
                charset = chparts[1];
            }
        }
    }

    return {
        mimeType: (mimeType || "").trim().toLowerCase(),
        charset: (charset || "UTF-8").trim().toLowerCase() // defaults to UTF-8
    }
}

function _findHTMLCharset(htmlbuffer){

    var body = htmlbuffer.toString("ascii"),
        input, meta, charset;

    if(meta = body.match(/<meta\s+http-equiv=["']content-type["'][^>]*?>/i)){
        input = meta[0];
    }

    if(input){
        charset = input.match(/charset\s?=\s?([a-zA-Z\-0-9]*);?/);
        if(charset){
            charset = (charset[1] || "").trim().toLowerCase();
        }
    }

    if(!charset && (meta = body.match(/<meta\s+charset=["'](.*?)["']/i))){
        charset = (meta[1] || "").trim().toLowerCase();
    }

    return charset;
}

<commit_msg>fixed url with port<commit_after>var http = require("http"),
    https = require("https"),
    urllib = require("url"),
    utillib = require("util"),
    zlib = require('zlib'),
    dns = require('dns'),
    Stream = require("stream").Stream,
    CookieJar = require("./cookiejar").CookieJar,
    Iconv = require("iconv").Iconv;

/*

maxRedirects : 10
disableRedirects : false
headers: {}
maxResponseLength : Infinity
method: GET
payload: str
disableGzip: false
asyncDnsLoookup: false

cookies: ['name=val']

outputEncoding: utf-8 | latin-1 jne

disableDecoding: false
*/

//TODO:
// - meta infosse faili nimi, juhul kui tegu downloadiga
// - wrapper fetch(url, callback)
// - wrapperile options.setEncoding = true | "UTF-8"
// - dokumentatsioon

exports.FetchStream = FetchStream;
exports.CookieJar = CookieJar;

exports.fetchUrl = fetchUrl;

function FetchStream(url, options){
    Stream.call(this);

    this.url = url;
    if(!this.url){
        return this.emit("error", new Error("url not defined"));
    }

    this.userAgent = "FetchStream";

    this._redirect_count = 0;

    this.options = options || {};
    this.normalizeOptions();

    this.runStream(url);
}
utillib.inherits(FetchStream, Stream);

FetchStream.prototype.normalizeOptions = function(){

    // cookiejar
    this.cookieJar = this.options.cookieJar || new CookieJar();

    // default redirects - 10
    // if disableRedirect is set, then 0
    if(!this.options.disableRedirect && typeof this.options.maxredirects != "number" &&
      !(this.options.maxredirects instanceof Number)){
        this.options.maxRedirects = 10;
    }else if(this.options.disableRedirects){
        this.options.maxRedirects = 0;
    }

    // normalize header keys
    // HTTP and HTTPS takes in key names in case insensitive but to find
    // an exact value from an object key name needs to be case sensitive
    // so we're just lowercasing all input keys
    this.options.headers = this.options.headers || {};

    var keys = Object.keys(this.options.headers),
        newheaders = {},
        i;

    for(i=keys.length-1; i>=0; i--){
        newheaders[keys[i].toLowerCase().trim()] = this.options.headers[keys[i]];
    }

    this.options.headers = newheaders;

    if(!this.options.headers["user-agent"]){
        this.options.headers["user-agent"] = this.userAgent;
    }

    if(!this.options.headers["pragma"]){
        this.options.headers["pragma"] = "no-cache";
    }

    if(!this.options.headers["cache-control"]){
        this.options.headers["cache-control"] = "no-cache";
    }

    if(!this.options.disableGzip){
        this.options.headers['accept-encoding'] = 'gzip, deflate';
    }else{
        delete this.options.headers['accept-encoding'];
    }

    // max length for the response,
    // if not set, default is Infinity
    if(!this.options.maxResponseLength){
        this.options.maxResponseLength = Infinity;
    }

    // method:
    // defaults to GET, or when payload present to POST
    if(!this.options.method){
        this.options.method = this.options.payload || this.options.payloadSize?"POST":"GET";
    }

    // set cookies
    // takes full cookie definition strings as params
    if(this.options.cookies){
        for(var i=0; i<this.options.cookies.length; i++){
            this.cookieJar.setCookie(this.options.cookies[i], this.url);
        }
    }

}

FetchStream.prototype.parseUrl = function(url){
    var urlparts = urllib.parse(url, false, true),
        transport,
        urloptions = {
            host: urlparts.hostname,
            port: urlparts.port,
            path: urlparts.pathname + (urlparts.search || "") || "/",
            method: this.options.method
        };

    switch(urlparts.protocol){
        case "https:":
            transport = https;
            break;
        case "http:":
        default:
            transport = http;
            break;
    }

    if(!urloptions.port){
        switch(urlparts.protocol){
            case "https:":
                urloptions.port = 443;
                break;
            case "http:":
            default:
                urloptions.port = 80;
                break;
        }
    }

    urloptions.headers = this.options.headers;

    return {
        urloptions: urloptions,
        transport: transport
    }
}

FetchStream.prototype.setEncoding = function(encoding){
    this.options.encoding = encoding;
}

FetchStream.prototype.absoluteUrl = function(url, base){

    var target_url = urllib.parse(url, false, true),
        base_url = urllib.parse(base || "", false, true),
        base_path, target_path, final_path;

    // if protocol is set, then it's good to go
    if(target_url.protocol){
        return url;
    }

    // the url might be int the form of "//www.example.com" with leading slashes -
    // the protocol from the base url must be used, defaults to http
    if(target_url.hostname){
        return (base_url.protocol || "http:") + (url.substr(0,2)!="//"?"//":"") + url;
    }

    // this is absolute path for relative domain
    if((target_url.pathname || "/").substr(0,1)=="/"){
        return (base_url.protocol || "http:") + "//" + (base_url.hostname || "") + url;
    }

    // relative path
    // remove also .. and . directory references
    base_path = (base_url.pathname || "/").split("/");
    base_path.pop(); // ditch the last element, empty for dir or a file name

    target_path = (target_url.pathname || "/").split("/");

    target_path = base_path.concat(target_path);
    final_path = [];

    target_path.forEach(function(dir){
        if(dir=="."){
            return;
        }

        if(dir==".."){
            final_path.pop();
            return;
        }

        if(dir){
            final_path.push(dir);
        }
    });

    return (base_url.protocol || "http:") + "//" + (base_url.hostname || "") + "/" +
        final_path.join("/") + (target_url.search || "");
}

FetchStream.prototype.runStream = function(url){
    var url_data = this.parseUrl(url),
        cookies = this.cookieJar.getCookies(url);

    if(cookies){
        url_data.urloptions.headers.cookie = cookies;
    }else{
        delete url_data.urloptions.headers.cookie;
    }

    if(this.options.payload){
        url_data.urloptions.headers['content-length'] = Buffer.byteLength(this.options.payload || "","utf-8");
    }

    if(this.options.payloadSize){
        url_data.urloptions.headers['content-length'] = this.options.payloadSize;
    }

    if (this.options.asyncDnsLoookup) {
        var dnsCallback = (function (err, adresses){
            if (err) {
                this.emit("error", err);
                return;
            }

            url_data.urloptions.headers['host'] = url_data.urloptions.hostname+url_data.urloptions.port;
            url_data.urloptions.hostname = adresses[0];
            url_data.urloptions.host=url_data.urloptions.hostname + (url_data.urloptions.port? ':' + url_data.urloptions.port: '');

            this._runStream(url_data, url);
        }).bind(this);

        dns.resolve4(url_data.urloptions.host, dnsCallback);
    } else {
        this._runStream(url_data, url);
    }
}

FetchStream.prototype._runStream = function(url_data, url){

    var req = url_data.transport.request(url_data.urloptions, (function(res) {

        // catch new cookies before potential redirect
        if(Array.isArray(res.headers['set-cookie'])){
            for(var i=0; i<res.headers['set-cookie'].length; i++){
                this.cookieJar.setCookie(res.headers['set-cookie'][i], url)
            }
        }

        if([301, 302].indexOf(res.statusCode)>=0){
            if(!this.options.disableRedirects && this.options.maxRedirects>this._redirect_count && res.headers.location){
                this._redirect_count++;
                this.runStream(this.absoluteUrl(res.headers.location, url));
                return;
            }
        }

        this.meta = {
            status: res.statusCode,
            responseHeaders: res.headers,
            finalUrl: url,
            redirectCount: this._redirect_count,
            cookieJar: this.cookieJar
        }

        var curlen = 0,
            maxlen,

            receive = (function(chunk){

                if(curlen + chunk.length > this.options.maxResponseLength){
                    maxlen = this.options.maxResponseLength - curlen;
                }else{
                    maxlen = chunk.length;
                }
                if(maxlen<=0)return;

                curlen += Math.min(maxlen, chunk.length);

                if(maxlen>=chunk.length){
                    if(this.options.encoding){
                        this.emit("data", chunk.toString(this.options.encoding));
                    }else{
                        this.emit("data", chunk);
                    }
                }else{
                    if(this.options.encoding){
                        this.emit("data", chunk.slice(0, maxlen).toString(this.options.encoding));
                    }else{
                        this.emit("data", chunk.slice(0, maxlen));
                    }
                }
            }).bind(this),

            error = (function(e){
                this.emit("error", e);
            }).bind(this),

            end = (function(){
                this.emit("end");
            }).bind(this),

            unpack = (function(type, res){
                var z = zlib["create"+type]();
                z.on("data", receive);
                z.on("error", error);
                z.on("end", end);
                res.pipe(z);
            }).bind(this);

        this.emit("meta", this.meta);

        if(res.headers['content-encoding']){
            switch(res.headers['content-encoding'].toLowerCase().trim()){
                case "gzip":
                    return unpack("Gunzip", res);
                case "deflate":
                    return unpack("InflateRaw", res);
            }
        }

        res.on('data', receive);
        res.on('end', end);

    }).bind(this));

    req.on('error', (function(e){
        this.emit("error", e);
    }).bind(this));

    if(this.options.payload){
        req.end(this.options.payload);
    }else if(this.options.payloadStream){
        this.options.payloadStream.pipe(req);
        this.options.payloadStream.resume();
    }else{
        req.end();
    }
}

function fetchUrl(url, options, callback){
    if(!callback && typeof options=="function"){
        callback = options;
        options = undefined;
    }
    options = options || {};

    var fetchstream = new FetchStream(url, options),
        response_data, chunks = [], length=0, curpos=0, buffer,
        content_type;

    fetchstream.on("meta", function(meta){
        response_data = meta;
        content_type = _parseContentType(meta.responseHeaders['content-type']);
    });

    fetchstream.on("data", function(chunk){
        if(chunk){
            chunks.push(chunk);
            length += chunk.length;
        }
    });

    fetchstream.on("error", function(error){
        callback(error);
    });

    fetchstream.on("end", function(error){
        var convert;

        buffer = new Buffer(length);
        for(var i=0, len = chunks.length; i<len; i++){
            chunks[i].copy(buffer, curpos);
            curpos += chunks[i].length;
        }

        if(content_type.mimeType == "text/html"){
            content_type.charset = _findHTMLCharset(buffer) || content_type.charset;
        }

        content_type.charset = (options.overrideCharset || content_type.charset || "utf-8").trim().toLowerCase();

        if(!this.options.disableDecoding && !content_type.charset.match(/^utf-?8$/i)){
            try{
                convert = new Iconv(content_type.charset, "UTF-8//TRANSLIT//IGNORE");
                buffer = convert.convert(buffer);
            }catch(E){}
        }

        if(this.options.outputEncoding){
            callback(null, response_data, buffer.toString(this.options.outputEncoding));
        }else{
            callback(null, response_data, buffer);
        }

    });
}

function _parseContentType(str){
    if(!str){
        return {};
    }
    var parts = str.split(";"),
        mimeType = parts.shift(),
        charset, chparts;

    for(var i=0, len = parts.length; i<len; i++){
        chparts = parts[i].split("=");
        if(chparts.length>1){
            if(chparts[0].trim().toLowerCase() == "charset"){
                charset = chparts[1];
            }
        }
    }

    return {
        mimeType: (mimeType || "").trim().toLowerCase(),
        charset: (charset || "UTF-8").trim().toLowerCase() // defaults to UTF-8
    }
}

function _findHTMLCharset(htmlbuffer){

    var body = htmlbuffer.toString("ascii"),
        input, meta, charset;

    if(meta = body.match(/<meta\s+http-equiv=["']content-type["'][^>]*?>/i)){
        input = meta[0];
    }

    if(input){
        charset = input.match(/charset\s?=\s?([a-zA-Z\-0-9]*);?/);
        if(charset){
            charset = (charset[1] || "").trim().toLowerCase();
        }
    }

    if(!charset && (meta = body.match(/<meta\s+charset=["'](.*?)["']/i))){
        charset = (meta[1] || "").trim().toLowerCase();
    }

    return charset;
}

<|endoftext|>


<commit_before>var debug = require('debug')('flint');

var nodesparky = require('node-sparky');
var async = require('async');
var _ = require('lodash');

var monitor = require('./monitor');
var server = require('./server');
var Bot = require('./bot');

// constructor
function Flint(config) {
  this.config = config;

  var $this = this;

  $this.monitorInterval = 15000;

  $this._lexicon = [];
  $this._bots = [];

  $this.sparky = nodesparky({
    token: $this.config.sparkToken,
    webhook: $this.config.hookUrl + '/spark'
  });

  server.listen('0.0.0.0', $this.config.localPort);
  server.route('/spark', $this);

  // start monitor
  monitor($this);

}

// process callback from webhook
Flint.prototype._processWebhook = function(resource, req) {
  var $this = this;

  var trigger = {};

  // compare string with pattern
  function compare(pattern, string) {
    // if regex match
    if(pattern instanceof RegExp && pattern.test(string)) {
      return true;
    }
    // if string match on first word
    if(typeof pattern === 'string' && pattern === string.split(' ')[0]) {
      return true;
    }
    // else
    return false;
  }

  async.series([
    function(cb) {
      $this.sparky.room.get(req.params.data.roomId, cb);
    },
    function(cb) {
      $this.sparky.person.get(req.params.data.personId, cb);
    },
    function(cb) {
      $this.sparky.message.get(req.params.data.id, cb);
    }

  ],
  function(err, results) {

    if(err){
      debug('has encountered an error processing an incoming webhook');
    } else {
      trigger.room = results[0][0]; // room object
      trigger.person = results[1][0]; // person object
      trigger.message =  results[2][0]; // message object
      trigger.args = _.toLower(trigger.message.text).split(' ');
      trigger.command = trigger.args.shift();

      // ignore messages from bot
      if(trigger.person.emails[0] === $this.config.sparkEmail) {
        return;
      }

      // iterate through registered lexicon of commands
      $this._lexicon.forEach(function(lex) {
        if(compare(lex.phrase, trigger.message.text)) {

          // find bot for the room that trigger the webhok
          var bot = _.find($this._bots, function(bot) {
            return bot._room.id === trigger.room.id;
          });

          // check if bot was found for toom trigger originated
          if(bot) {
            // execute function with bot in room from trigger
            lex.action(bot, trigger);
          } else {
            debug('ignored webhook callback');
          }
        }
      });
    }

  });
};

// bot factory
Flint.prototype.botSpawner = function(roomId, callback) {
  var $this = this;

  // create new bot
  var newBot = new Bot($this.sparky);

  // load bot
  async.series([

    // get room object where bot lives
    function(cb) {
      $this.sparky.room.get(roomId, function(err, room) {
        if(!err) newBot._room = room[0];
        return cb(err);
      });
    },

    // get person object for self
    function(cb) {
      $this.sparky.person.self(function(err, person) {
        if(!err) newBot._person = person[0];
        return cb(err);
      });
    },

    // get memebership of self for room
    function(cb) {
      $this.sparky.memberships.get(function(err, memberships) {
        if(err) {
          return cb(err);
        } else {
          newBot._membership = _.find(memberships, { 'roomId': newBot._room.id });
          if(!newBot._membership) {
            return cb(new Error('membership not found'));
          } else {
            return cb(null);
          }
        }
      });
    }

  ], function(err) {

    if(err) {
      newBot.destroy();
      // return last error
      return callback(err[err.length - 1]);
    } else {
      //add bot to flint
      $this._bots.push(newBot);
      return callback(null);
    }

  });
};

Flint.prototype.hears = function(phrase, options, action) {
  var $this = this;

  // parse args
  var args = [];
  for (var i = 0; i < arguments.length; i++) {
    args.push(arguments[i]);
  }
  phrase = args.shift();
  action = args.pop();
  // optional args
  options = (args.length > 0 && typeof args[0] === 'object') ? args.shift() : null;

  $this._lexicon.push({'phrase': phrase, 'options': options, 'action': action });

};

module.exports = Flint;
<commit_msg>Bugfix<commit_after>var debug = require('debug')('flint');

var nodesparky = require('node-sparky');
var async = require('async');
var _ = require('lodash');

var monitor = require('./monitor');
var server = require('./server');
var Bot = require('./bot');

// constructor
function Flint(config) {
  this.config = config;

  var $this = this;

  $this.monitorInterval = 15000;

  $this._lexicon = [];
  $this._bots = [];

  $this.sparky = nodesparky({
    token: $this.config.sparkToken,
    webhook: $this.config.hookUrl + '/spark'
  });

  server.listen('0.0.0.0', $this.config.localPort);
  server.route('/spark', $this);

  // start monitor
  monitor($this);

}

// process callback from webhook
Flint.prototype._processWebhook = function(resource, req) {
  var $this = this;

  var trigger = {};

  // compare string with pattern
  function compare(pattern, string) {
    // if regex match
    if(pattern instanceof RegExp && pattern.test(string)) {
      return true;
    }
    // if string match on first word
    if(typeof pattern === 'string' && pattern === string.split(' ')[0]) {
      return true;
    }
    // else
    return false;
  }

  async.series([
    function(cb) {
      $this.sparky.room.get(req.params.data.roomId, cb);
    },
    function(cb) {
      $this.sparky.person.get(req.params.data.personId, cb);
    },
    function(cb) {
      $this.sparky.message.get(req.params.data.id, cb);
    }

  ],
  function(err, results) {

    if(err){
      debug('has encountered an error processing an incoming webhook');
    } else {
      trigger.room = results[0][0]; // room object
      trigger.person = results[1][0]; // person object
      trigger.message =  results[2][0]; // message object
      trigger.args = _.toLower(trigger.message.text).split(' ');
      trigger.command = trigger.args.shift();

      // ignore messages from bot
      if(trigger.person.emails[0] === $this.config.sparkEmail) {
        return;
      }

      // iterate through registered lexicon of commands
      $this._lexicon.forEach(function(lex) {
        if(compare(lex.phrase, trigger.message.text)) {

          // find bot for the room that trigger the webhok
          var bot = _.find($this._bots, function(bot) {
            return bot._room.id === trigger.room.id;
          });

          // check if bot was found for toom trigger originated
          if(bot) {
            // execute function with bot in room from trigger
            lex.action(bot, trigger);
          } else {
            debug('ignored webhook callback');
          }
        }
      });
    }

  });
};

// bot factory
Flint.prototype.botSpawner = function(roomId, callback) {
  var $this = this;

  // create new bot
  var newBot = new Bot($this.sparky);

  // load bot
  async.series([

    // get room object where bot lives
    function(cb) {
      $this.sparky.room.get(roomId, function(err, room) {
        if(!err && room) {
          newBot._room = room[0];
          return cb(null);
        } else {
          return cb(err || new Error('room not found'));
        }
        ;
      });
    },

    // get person object for self
    function(cb) {
      $this.sparky.person.self(function(err, person) {
        if(!err) newBot._person = person[0];
        return cb(err);
      });
    },

    // get memebership of self for room
    function(cb) {
      $this.sparky.memberships.get(function(err, memberships) {
        if(err) {
          return cb(err);
        } else {
          newBot._membership = _.find(memberships, { 'roomId': newBot._room.id });
          if(!newBot._membership) {
            return cb(new Error('membership not found'));
          } else {
            return cb(null);
          }
        }
      });
    }

  ], function(err) {

    if(err) {
      newBot.destroy();
      // return last error
      return callback(err[err.length - 1]);
    } else {
      //add bot to flint
      $this._bots.push(newBot);
      return callback(null);
    }

  });
};

Flint.prototype.hears = function(phrase, options, action) {
  var $this = this;

  // parse args
  var args = [];
  for (var i = 0; i < arguments.length; i++) {
    args.push(arguments[i]);
  }
  phrase = args.shift();
  action = args.pop();
  // optional args
  options = (args.length > 0 && typeof args[0] === 'object') ? args.shift() : null;

  $this._lexicon.push({'phrase': phrase, 'options': options, 'action': action });

};

module.exports = Flint;
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import {injectIntl, intlShape} from 'react-intl'

import Button from '../../Button'
import {
  StyledDateAbstractControl,
  StyledDateAbstractInput,
  StyledDateAbstractWrapper
} from './StyledDateAbstract'

class DateAbstract extends React.Component {
  Flatpickr = null

  constructor(props) {
    super(props)
    this.state = {hideButton: true}
    this.wrapper = React.createRef()

    import(/* webpackChunkName: "flatpickr" */ '!style-loader!css-loader!flatpickr/dist/themes/light.css')

    Promise.all([
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/de.js'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/fr.js'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/it.js')
    ]).then(response => {
      this.Flatpickr = response[0].default
      this.localeMap = {
        'de-CH': response[1].German,
        'de': response[1].German,
        'fr': response[2].French,
        'it': response[3].Italian
      }

      this.initializeFlatPickr()
    })
  }

  initializeFlatPickr = flatpickr => {
    const locale = this.localeMap[this.props.intl.locale]

    this.options = {
      wrap: true,
      onChange: this.handleOnChange,
      altInput: true,
      altInputClass: '',
      clickOpens: !this.props.readOnly,
      defaultDate: this.props.value,
      ...(locale ? {locale} : {}),
      ...(this.props.options ? this.props.options.flatpickrOptions : {})
    }

    this.flatpickr = new this.Flatpickr(this.wrapper.current, this.options)
    this.flatpickr.calendarContainer.classList.add('tocco-ui-theme')

    if (this.props.initialized) {
      this.props.initialized()
    }
  }

  getLocale = localeCode => {
    if (this.localeMap) {
      let locale = this.localeMap[localeCode]

      // Fallback english
      if (!locale && this.Flatpickr) {
        locale = this.Flatpickr.l10ns.en
      }
      return locale
    }
    return null
  }

  componentWillReceiveProps(props) {
    this.handleButtonVisibility()
    const locale = this.getLocale(props.intl.locale)

    if (this.Flatpickr && this.flatpickr) {
      this.Flatpickr.localize(locale)
      this.flatpickr.set('locale', locale)

      this.flatpickr.set('altFormat', props.options.flatpickrOptions.altFormat)
      this.flatpickr.setDate(props.value, false)
      this.flatpickr.redraw()
    }
  }

  componentDidMount() {
    this.handleButtonVisibility()
  }

  componentWillUnmount() {
    this.flatpickr.destroy()
  }

  handleOnChange = selectedDates => {
    const isoStrings = selectedDates.map(date => date.toISOString())
    this.props.onChange(isoStrings)
  }

  hasValue = () => {
    return this.props.value && this.props.value.length > 0 && this.props.value.every(v => v)
  }

  handleOnBlur = () => {
    if (this.props.onBlur) {
      const altValue = this.flatpickr.altInput.value
      this.props.onBlur(altValue, this.flatpickr.selectedDates, r => this.flatpickr.setDate(r, true))
    }
  }

  handleButtonVisibility = () => {
    this.setState({hideButton: !this.hasValue() && !this.props.readOnly})
  }

  render() {
    return (
      <StyledDateAbstractWrapper
        data-wrap
        onBlur={this.handleOnBlur}
        readOnly={this.props.readOnly}
        ref={this.wrapper}
      >
        <StyledDateAbstractInput
          type="text"
          data-input
          {...(this.props.options ? {placeholder: this.props.options.placeholderText} : {})}
        />
        <StyledDateAbstractInput
          disabled
          value={this.flatpickr ? this.flatpickr.altInput.value : ''}
        />
        <StyledDateAbstractControl
          data-clear
          hideButton={this.state.hideButton}
        >
          <Button
            icon="times"
            look="ball"
            tabIndex={-1}
          />
        </StyledDateAbstractControl>
      </StyledDateAbstractWrapper>
    )
  }
}

DateAbstract.propTypes = {
  intl: intlShape.isRequired,
  onBlur: PropTypes.func,
  onChange: PropTypes.func,
  value: PropTypes.arrayOf(PropTypes.string),
  options: PropTypes.shape({
    placeholderText: PropTypes.string,
    flatpickrOptions: PropTypes.object
  }),
  readOnly: PropTypes.bool,
  initialized: PropTypes.func,
  events: PropTypes.shape({
    onFocus: PropTypes.func
  })
}

export default injectIntl(DateAbstract)
<commit_msg>feat(tocco-ui): add hide links on readOnly<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import {injectIntl, intlShape} from 'react-intl'

import Button from '../../Button'
import {
  StyledDateAbstractControl,
  StyledDateAbstractInput,
  StyledDateAbstractWrapper
} from './StyledDateAbstract'

class DateAbstract extends React.Component {
  Flatpickr = null

  constructor(props) {
    super(props)
    this.state = {hideButton: true}
    this.wrapper = React.createRef()

    import(/* webpackChunkName: "flatpickr" */ '!style-loader!css-loader!flatpickr/dist/themes/light.css')

    Promise.all([
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/de.js'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/fr.js'),
      import(/* webpackChunkName: "flatpickr" */ 'flatpickr/dist/l10n/it.js')
    ]).then(response => {
      this.Flatpickr = response[0].default
      this.localeMap = {
        'de-CH': response[1].German,
        'de': response[1].German,
        'fr': response[2].French,
        'it': response[3].Italian
      }

      this.initializeFlatPickr()
    })
  }

  initializeFlatPickr = flatpickr => {
    const locale = this.localeMap[this.props.intl.locale]

    this.options = {
      wrap: true,
      onChange: this.handleOnChange,
      altInput: true,
      altInputClass: '',
      clickOpens: !this.props.readOnly,
      defaultDate: this.props.value,
      ...(locale ? {locale} : {}),
      ...(this.props.options ? this.props.options.flatpickrOptions : {})
    }

    this.flatpickr = new this.Flatpickr(this.wrapper.current, this.options)
    this.flatpickr.calendarContainer.classList.add('tocco-ui-theme')

    if (this.props.initialized) {
      this.props.initialized()
    }
  }

  getLocale = localeCode => {
    if (this.localeMap) {
      let locale = this.localeMap[localeCode]

      // Fallback english
      if (!locale && this.Flatpickr) {
        locale = this.Flatpickr.l10ns.en
      }
      return locale
    }
    return null
  }

  componentWillReceiveProps(props) {
    this.handleButtonVisibility()
    const locale = this.getLocale(props.intl.locale)

    if (this.Flatpickr && this.flatpickr) {
      this.Flatpickr.localize(locale)
      this.flatpickr.set('locale', locale)

      this.flatpickr.set('altFormat', props.options.flatpickrOptions.altFormat)
      this.flatpickr.setDate(props.value, false)
      this.flatpickr.redraw()
    }
  }

  componentDidMount() {
    this.handleButtonVisibility()
  }

  componentWillUnmount() {
    this.flatpickr.destroy()
  }

  handleOnChange = selectedDates => {
    const isoStrings = selectedDates.map(date => date.toISOString())
    this.props.onChange(isoStrings)
  }

  hasValue = () => {
    return this.props.value && this.props.value.length > 0 && this.props.value.every(v => v)
  }

  handleOnBlur = () => {
    if (this.props.onBlur) {
      const altValue = this.flatpickr.altInput.value
      this.props.onBlur(altValue, this.flatpickr.selectedDates, r => this.flatpickr.setDate(r, true))
    }
  }

  handleButtonVisibility = () => {
    this.setState({hideButton: !this.hasValue() && !this.props.readOnly})
  }

  render() {
    return (
      <StyledDateAbstractWrapper
        data-wrap
        onBlur={this.handleOnBlur}
        readOnly={this.props.readOnly}
        ref={this.wrapper}
      >
        <StyledDateAbstractInput
          type="text"
          data-input
          {...(this.props.options ? {placeholder: this.props.options.placeholderText} : {})}
        />
        <StyledDateAbstractInput
          disabled
          value={this.flatpickr ? this.flatpickr.altInput.value : ''}
        />
        <StyledDateAbstractControl
          data-clear
          hideButton={this.state.hideButton || this.props.readOnly}
        >
          <Button
            icon="times"
            look="ball"
            tabIndex={-1}
          />
        </StyledDateAbstractControl>
      </StyledDateAbstractWrapper>
    )
  }
}

DateAbstract.propTypes = {
  intl: intlShape.isRequired,
  onBlur: PropTypes.func,
  onChange: PropTypes.func,
  value: PropTypes.arrayOf(PropTypes.string),
  options: PropTypes.shape({
    placeholderText: PropTypes.string,
    flatpickrOptions: PropTypes.object
  }),
  readOnly: PropTypes.bool,
  initialized: PropTypes.func,
  events: PropTypes.shape({
    onFocus: PropTypes.func
  })
}

export default injectIntl(DateAbstract)
<|endoftext|>


<commit_before>/**
 * Copyright 2013-present NightWorld.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

module.exports = OAuth2Error;

/**
 * Error
 *
 * @param {Number} code        Numeric error code
 * @param {String} error       Error descripton
 * @param {String} description Full error description
 */
function OAuth2Error (error, description, err) {

  if (!(this instanceof OAuth2Error)) return new OAuth2Error(error, description, err);

  switch (error) {
    case 'invalid_client':
    case 'invalid_grant':
    case 'invalid_request':
      this.code = 400;
      break;
    case 'server_error':
      this.code = 503;
      break;
    default:
      this.code = 500;
  }

  this.error = error;
  this.error_description = description || error;
  this.stack = (err && err.stack) || err;
}
<commit_msg>Detect 'invalid_token' as 400<commit_after>/**
 * Copyright 2013-present NightWorld.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

module.exports = OAuth2Error;

/**
 * Error
 *
 * @param {Number} code        Numeric error code
 * @param {String} error       Error descripton
 * @param {String} description Full error description
 */
function OAuth2Error (error, description, err) {

  if (!(this instanceof OAuth2Error)) return new OAuth2Error(error, description, err);

  switch (error) {
    case 'invalid_client':
    case 'invalid_grant':
    case 'invalid_request':
    case 'invalid_token':
      this.code = 400;
      break;
    case 'server_error':
      this.code = 503;
      break;
    default:
      this.code = 500;
  }

  this.error = error;
  this.error_description = description || error;
  this.stack = (err && err.stack) || err;
}
<|endoftext|>


<commit_before>import usersApi from '../../api/users'
import auth from '../../auth'

const state = {
  current: null,
  byIds: {},
}

const getters = {
  findById (state) {
    return id => {
      const user = state.byIds[id]
      return {
        ...user,
        activated: !!user.username,
        displayedName: user.username || user.email,
        identifier: user.username || user.id,
        isLoggedIn: auth.isLoggedIn(),
        urlShow: '/dashboard',  // there is no user's profile page yet
      }
    }
  },

  current (state, getters) {
    const currentId = state.current
    if (currentId == null) {
      return null
    }
    return getters.findById(state.current)
  },
}

const actions = {
  register ({ commit }, email) {
    return usersApi.register(email)
      .then((res) => {
        auth.login(res.meta.token)
        commit('setCurrent', res.data)
      })
  },

  resendActivationEmail ({ commit }, { email }) {
    return usersApi.resendActivationEmail(email)
  },

  activate ({ commit }, { token, username, password }) {
    return usersApi.activate(token, username, password)
      .then((res) => {
        auth.login(res.meta.token)
        commit('setCurrent', res.data)
      })
  },

  login ({ commit }, { username, password }) {
    return usersApi.login(username, password)
      .then((res) => {
        auth.login(res.meta.token)
        commit('setCurrent', res.data)
      })
  },

  getCurrent ({ commit }) {
    return usersApi.getCurrent()
                   .then((res) => commit('setCurrent', res.data))
  },

  logout ({ commit }) {
    auth.logout()
  },

  acceptTermsOfService ({ commit }) {
    return usersApi.acceptTermsOfService()
                   .then((res) => commit('update', res.data))
  },

  resetPassword ({ commit }, { email }) {
    return usersApi.resetPassword(email)
  },

  changePassword ({ commit }, { token, password }) {
    return usersApi.changePassword(token, password)
      .then((res) => {
        auth.login(res.meta.token)
        commit('setCurrent', res.data)
      })
  },
}

const mutations = {
  setCurrent (state, data) {
    state.byIds = {
      ...state.byIds,
      [data.id]: {
        id: data.id,
        ...data.attributes,
      },
    }
    state.current = data.id
  },

  update (state, data) {
    state.byIds = {
      ...state.byIds,
      [data.id]: {
        ...state.byIds[data.id],
        ...data.attributes,
      },
    }
  },

  reset (state) {
    state.byIds = {}
    state.current = null
  }
}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations,
}
<commit_msg>tec: Remove useless info in user findById getter<commit_after>import usersApi from '../../api/users'
import auth from '../../auth'

const state = {
  current: null,
  byIds: {},
}

const getters = {
  findById (state) {
    return id => {
      const user = state.byIds[id]
      return {
        ...user,
        activated: !!user.username,
        displayedName: user.username || user.email,
      }
    }
  },

  current (state, getters) {
    const currentId = state.current
    if (currentId == null) {
      return null
    }
    return getters.findById(state.current)
  },
}

const actions = {
  register ({ commit }, email) {
    return usersApi.register(email)
      .then((res) => {
        auth.login(res.meta.token)
        commit('setCurrent', res.data)
      })
  },

  resendActivationEmail ({ commit }, { email }) {
    return usersApi.resendActivationEmail(email)
  },

  activate ({ commit }, { token, username, password }) {
    return usersApi.activate(token, username, password)
      .then((res) => {
        auth.login(res.meta.token)
        commit('setCurrent', res.data)
      })
  },

  login ({ commit }, { username, password }) {
    return usersApi.login(username, password)
      .then((res) => {
        auth.login(res.meta.token)
        commit('setCurrent', res.data)
      })
  },

  getCurrent ({ commit }) {
    return usersApi.getCurrent()
                   .then((res) => commit('setCurrent', res.data))
  },

  logout ({ commit }) {
    auth.logout()
  },

  acceptTermsOfService ({ commit }) {
    return usersApi.acceptTermsOfService()
                   .then((res) => commit('update', res.data))
  },

  resetPassword ({ commit }, { email }) {
    return usersApi.resetPassword(email)
  },

  changePassword ({ commit }, { token, password }) {
    return usersApi.changePassword(token, password)
      .then((res) => {
        auth.login(res.meta.token)
        commit('setCurrent', res.data)
      })
  },
}

const mutations = {
  setCurrent (state, data) {
    state.byIds = {
      ...state.byIds,
      [data.id]: {
        id: data.id,
        ...data.attributes,
      },
    }
    state.current = data.id
  },

  update (state, data) {
    state.byIds = {
      ...state.byIds,
      [data.id]: {
        ...state.byIds[data.id],
        ...data.attributes,
      },
    }
  },

  reset (state) {
    state.byIds = {}
    state.current = null
  }
}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations,
}
<|endoftext|>


<commit_before>'use strict';

module.exports = function promises (request) {
  request['then'] = _then.bind(request);
  request['catch'] = _catch.bind(request);
  return request;
}

function _then (fulfilled, rejected) {
  this.promise = this.promise ? this.promise : new Promise((resolve, reject) => {
    this.end((err, res) => err ? reject(err) : resolve(res));
  }.bind(this))
  return this.promise.then(fulfilled, rejected);
}

function _catch (rejected) {
  this.promise = this.promise ? this.promise : this.then();
  return this.promise.catch(rejected);
}
<commit_msg>improve request promise<commit_after>'use strict';

module.exports = function promises (request) {
  request['then'] = _then.bind(request);
  request['catch'] = _catch.bind(request);
  return request;
}

function _then (fulfilled, rejected) {
  this.promise = this.promise ? this.promise : new Promise((resolve, reject) => {
    this.end((res) => res.error ? reject(res) : resolve(res));
  }.bind(this))
  return this.promise.then(fulfilled, rejected);
}

function _catch (rejected) {
  this.promise = this.promise ? this.promise : this.then();
  return this.promise.catch(rejected);
}
<|endoftext|>


<commit_before>Template.adManagerRandomAd.onCreated(function () {
  this.ad = new ReactiveVar(null);

  Meteor.call('AdManager.getRandomAdvert', (err, res) => {
    if (err) {
      console.log(err);
    } else {
      this.ad.set(res);
    }
  });
});

Template.adManagerRandomAd.helpers({
  ad: function () {
    return Template.instance().ad.get();
  }
});

Template.adManagerAd.events({
  'click a': function (e) {
    if (!Template.currentData().dontRegisterClick) {
      AdManager.clickAdvert.call({_id: this._id});
    }
  }
});<commit_msg>capturing right click events for ads<commit_after>Template.adManagerRandomAd.onCreated(function () {
  this.ad = new ReactiveVar(null);

  Meteor.call('AdManager.getRandomAdvert', (err, res) => {
    if (err) {
      console.log(err);
    } else {
      this.ad.set(res);
    }
  });
});

Template.adManagerRandomAd.helpers({
  ad: function () {
    return Template.instance().ad.get();
  }
});

Template.adManagerAd.events({
  // contextmenu captures right clicks. Doesn't mean the user necessarily navigated to that
  // page when he right clicks, but good chance he did. Not sure there's an easy way to know
  // for sure if someone right clicked and then opened in a new tab
  'click a, contextmenu a': function (e) {
    if (!Template.currentData().dontRegisterClick) {
      AdManager.clickAdvert.call({_id: this._id});
    }
  }
});<|endoftext|>


<commit_before>Template.settings.helpers({
  settings: function () {
    var settings = Settings.findOne();

    return settings;
  }
});
<commit_msg>Add settings subscription<commit_after>Template.settings.created = function () {
  // Get reference to template instance
  var instance = this;

  // Subscribe to setings
  instance.subscribe("settings");
};

Template.settings.helpers({
  settings: function () {
    var settings = Settings.findOne();

    return settings;
  }
});
<|endoftext|>