<commit_before>/*
 * Flush stats to graphite (http://graphite.wikidot.com/).
 *
 * To enable this backend, include 'graphite' in the backends
 * configuration array:
 *
 *   backends: ['graphite']
 *
 * This backend supports the following config options:
 *
 *   graphiteHost: Hostname of graphite server.
 *   graphitePort: Port to contact graphite server at.
 */

var net = require('net'),
   util = require('util');

var debug;
var flushInterval;
var graphiteHost;
var graphitePort;

var graphiteStats = {};

var post_stats = function graphite_post_stats(statString) {
  var last_flush = graphiteStats.last_flush || 0;
  var last_exception = graphiteStats.last_exception || 0;
  if (graphiteHost) {
    try {
      var graphite = net.createConnection(graphitePort, graphiteHost);
      graphite.addListener('error', function(connectionException){
        if (debug) {
          util.log(connectionException);
        }
      });
      graphite.on('connect', function() {
        var ts = Math.round(new Date().getTime() / 1000);
        statString += 'stats.statsd.graphiteStats.last_exception ' + last_exception + ' ' + ts + "\n";
        statString += 'stats.statsd.graphiteStats.last_flush ' + last_flush + ' ' + ts + "\n";
        this.write(statString);
        this.end();
        graphiteStats.last_flush = Math.round(new Date().getTime() / 1000);
      });
    } catch(e){
      if (debug) {
        util.log(e);
      }
      graphiteStats.last_exception = Math.round(new Date().getTime() / 1000);
    }
  }
}

var flush_stats = function graphite_flush(ts, metrics) {
  var starttime = Date.now();
  var statString = '';
  var numStats = 0;
  var key;

  var counters = metrics.counters;
  var gauges = metrics.gauges;
  var timers = metrics.timers;
  var sets = metrics.sets;
  var pctThreshold = metrics.pctThreshold;

  for (key in counters) {
    var value = counters[key];
    var valuePerSecond = value / (flushInterval / 1000); // calculate "per second" rate

    statString += 'stats.'        + key + ' ' + valuePerSecond + ' ' + ts + "\n";
    statString += 'stats_counts.' + key + ' ' + value          + ' ' + ts + "\n";

    numStats += 1;
  }

  for (key in timers) {
    if (timers[key].length > 0) {
      var values = timers[key].sort(function (a,b) { return a-b; });
      var count = values.length;
      var min = values[0];
      var max = values[count - 1];

      var cumulativeValues = [min];
      for (var i = 1; i < count; i++) {
          cumulativeValues.push(values[i] + cumulativeValues[i-1]);
      }

      var sum = min;
      var mean = min;
      var maxAtThreshold = max;

      var message = "";

      var key2;

      for (key2 in pctThreshold) {
        var pct = pctThreshold[key2];
        if (count > 1) {
          var thresholdIndex = Math.round(((100 - pct) / 100) * count);
          var numInThreshold = count - thresholdIndex;

          maxAtThreshold = values[numInThreshold - 1];
          sum = cumulativeValues[numInThreshold - 1];
          mean = sum / numInThreshold;
        }

        var clean_pct = '' + pct;
        clean_pct.replace('.', '_');
        message += 'stats.timers.' + key + '.mean_'  + clean_pct + ' ' + mean           + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.upper_' + clean_pct + ' ' + maxAtThreshold + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.sum_' + clean_pct + ' ' + sum + ' ' + ts + "\n";
      }

      sum = cumulativeValues[count-1];
      mean = sum / count;

      var sumOfDiffs = 0;
      for (var i = 0; i < count; i++) {
         sumOfDiffs += (values[i] - mean) * (values[i] - mean);
      }
      var stddev = Math.sqrt(sumOfDiffs / count);

      message += 'stats.timers.' + key + '.std ' + stddev  + ' ' + ts + "\n";
      message += 'stats.timers.' + key + '.upper ' + max   + ' ' + ts + "\n";
      message += 'stats.timers.' + key + '.lower ' + min   + ' ' + ts + "\n";
      message += 'stats.timers.' + key + '.count ' + count + ' ' + ts + "\n";
      message += 'stats.timers.' + key + '.sum ' + sum  + ' ' + ts + "\n";
      message += 'stats.timers.' + key + '.mean ' + mean + ' ' + ts + "\n";
      statString += message;

      numStats += 1;
    }
  }

  for (key in gauges) {
    statString += 'stats.gauges.' + key + ' ' + gauges[key] + ' ' + ts + "\n";
    numStats += 1;
  }

  for (key in sets) {
    statString += 'stats.sets.' + key + '.count ' + sets[key].values().length + ' ' + ts + "\n";
    numStats += 1;
  }

  statString += 'statsd.numStats ' + numStats + ' ' + ts + "\n";
  statString += 'stats.statsd.graphiteStats.calculationtime ' + (Date.now() - starttime) + ' ' + ts + "\n";
  post_stats(statString);
};

var backend_status = function graphite_status(writeCb) {
  for (stat in graphiteStats) {
    writeCb(null, 'graphite', stat, graphiteStats[stat]);
  }
};

exports.init = function graphite_init(startup_time, config, events) {
  debug = config.debug;
  graphiteHost = config.graphiteHost;
  graphitePort = config.graphitePort;

  graphiteStats.last_flush = startup_time;
  graphiteStats.last_exception = startup_time;

  flushInterval = config.flushInterval;

  events.on('flush', flush_stats);
  events.on('status', backend_status);

  return true;
};
<commit_msg>Simplify threshold calculation<commit_after>/*
 * Flush stats to graphite (http://graphite.wikidot.com/).
 *
 * To enable this backend, include 'graphite' in the backends
 * configuration array:
 *
 *   backends: ['graphite']
 *
 * This backend supports the following config options:
 *
 *   graphiteHost: Hostname of graphite server.
 *   graphitePort: Port to contact graphite server at.
 */

var net = require('net'),
   util = require('util');

var debug;
var flushInterval;
var graphiteHost;
var graphitePort;

var graphiteStats = {};

var post_stats = function graphite_post_stats(statString) {
  var last_flush = graphiteStats.last_flush || 0;
  var last_exception = graphiteStats.last_exception || 0;
  if (graphiteHost) {
    try {
      var graphite = net.createConnection(graphitePort, graphiteHost);
      graphite.addListener('error', function(connectionException){
        if (debug) {
          util.log(connectionException);
        }
      });
      graphite.on('connect', function() {
        var ts = Math.round(new Date().getTime() / 1000);
        statString += 'stats.statsd.graphiteStats.last_exception ' + last_exception + ' ' + ts + "\n";
        statString += 'stats.statsd.graphiteStats.last_flush ' + last_flush + ' ' + ts + "\n";
        this.write(statString);
        this.end();
        graphiteStats.last_flush = Math.round(new Date().getTime() / 1000);
      });
    } catch(e){
      if (debug) {
        util.log(e);
      }
      graphiteStats.last_exception = Math.round(new Date().getTime() / 1000);
    }
  }
}

var flush_stats = function graphite_flush(ts, metrics) {
  var starttime = Date.now();
  var statString = '';
  var numStats = 0;
  var key;

  var counters = metrics.counters;
  var gauges = metrics.gauges;
  var timers = metrics.timers;
  var sets = metrics.sets;
  var pctThreshold = metrics.pctThreshold;

  for (key in counters) {
    var value = counters[key];
    var valuePerSecond = value / (flushInterval / 1000); // calculate "per second" rate

    statString += 'stats.'        + key + ' ' + valuePerSecond + ' ' + ts + "\n";
    statString += 'stats_counts.' + key + ' ' + value          + ' ' + ts + "\n";

    numStats += 1;
  }

  for (key in timers) {
    if (timers[key].length > 0) {
      var values = timers[key].sort(function (a,b) { return a-b; });
      var count = values.length;
      var min = values[0];
      var max = values[count - 1];

      var cumulativeValues = [min];
      for (var i = 1; i < count; i++) {
          cumulativeValues.push(values[i] + cumulativeValues[i-1]);
      }

      var sum = min;
      var mean = min;
      var maxAtThreshold = max;

      var message = "";

      var key2;

      for (key2 in pctThreshold) {
        var pct = pctThreshold[key2];
        if (count > 1) {
          var numInThreshold = Math.round(pct / 100 * count);

          maxAtThreshold = values[numInThreshold - 1];
          sum = cumulativeValues[numInThreshold - 1];
          mean = sum / numInThreshold;
        }

        var clean_pct = '' + pct;
        clean_pct.replace('.', '_');
        message += 'stats.timers.' + key + '.mean_'  + clean_pct + ' ' + mean           + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.upper_' + clean_pct + ' ' + maxAtThreshold + ' ' + ts + "\n";
        message += 'stats.timers.' + key + '.sum_' + clean_pct + ' ' + sum + ' ' + ts + "\n";
      }

      sum = cumulativeValues[count-1];
      mean = sum / count;

      var sumOfDiffs = 0;
      for (var i = 0; i < count; i++) {
         sumOfDiffs += (values[i] - mean) * (values[i] - mean);
      }
      var stddev = Math.sqrt(sumOfDiffs / count);

      message += 'stats.timers.' + key + '.std ' + stddev  + ' ' + ts + "\n";
      message += 'stats.timers.' + key + '.upper ' + max   + ' ' + ts + "\n";
      message += 'stats.timers.' + key + '.lower ' + min   + ' ' + ts + "\n";
      message += 'stats.timers.' + key + '.count ' + count + ' ' + ts + "\n";
      message += 'stats.timers.' + key + '.sum ' + sum  + ' ' + ts + "\n";
      message += 'stats.timers.' + key + '.mean ' + mean + ' ' + ts + "\n";
      statString += message;

      numStats += 1;
    }
  }

  for (key in gauges) {
    statString += 'stats.gauges.' + key + ' ' + gauges[key] + ' ' + ts + "\n";
    numStats += 1;
  }

  for (key in sets) {
    statString += 'stats.sets.' + key + '.count ' + sets[key].values().length + ' ' + ts + "\n";
    numStats += 1;
  }

  statString += 'statsd.numStats ' + numStats + ' ' + ts + "\n";
  statString += 'stats.statsd.graphiteStats.calculationtime ' + (Date.now() - starttime) + ' ' + ts + "\n";
  post_stats(statString);
};

var backend_status = function graphite_status(writeCb) {
  for (stat in graphiteStats) {
    writeCb(null, 'graphite', stat, graphiteStats[stat]);
  }
};

exports.init = function graphite_init(startup_time, config, events) {
  debug = config.debug;
  graphiteHost = config.graphiteHost;
  graphitePort = config.graphitePort;

  graphiteStats.last_flush = startup_time;
  graphiteStats.last_exception = startup_time;

  flushInterval = config.flushInterval;

  events.on('flush', flush_stats);
  events.on('status', backend_status);

  return true;
};
<|endoftext|>


<commit_before>import $ from 'jquery';
import { clearStyles } from '../util';

export default function () {
    let jews = {};
    jews.title = $('.title_main').contents().eq(0).text().trim();
    jews.subtitle = $('.title_sub').text() || undefined;
    jews.content = (function () {
        var content = $('#atic_txt1')[0].cloneNode(true);
        $('#hnsIframe, #ifrm_photolink, #googleAdTable', content).remove();
        $('.dklink', content).each(function (i, v) {
            $(v).replaceWith(v.innerHTML);
        });
        return clearStyles(content).innerHTML;
    })();
    jews.timestamp = {
        created: new Date($('.VCdate').text().trim().split(' ')[0]),
        lastModified: undefined
    };
    jews.reporters = [];
    return jews;
}
<commit_msg>서울신문 제목, 작성일 나오게 수정<commit_after>import $ from 'jquery';
import { clearStyles } from '../util';

export default function () {
    let jews = {};
    jews.title = $('.atit2').contents().eq(0).text().trim();
    jews.subtitle = $('.title_sub').text() || undefined;
    jews.content = (function () {
        var content = $('#atic_txt1')[0].cloneNode(true);
        $('#hnsIframe, #ifrm_photolink, #googleAdTable', content).remove();
        $('.dklink', content).each(function (i, v) {
            $(v).replaceWith(v.innerHTML);
        });
        return clearStyles(content).innerHTML;
    })();
    jews.timestamp = {
        created: undefined,
        lastModified: undefined
    };
    $('.v_days').text()
        .replace(/(입력|수정)\s\:\s(\d{4}-\d{2}-\d{2})\s*(\d{2}:\d{2})/g, function (_, p1, p2, p3) {
            var ts = p2 + 'T' + p3 + '+09:00'; // ISO 8601
            if (p1 === '입력') jews.timestamp.created = new Date(ts);
            else if (p1 === '수정') jews.timestamp.lastModified = new Date(ts);
        });
    jews.reporters = [];
    return jews;
}
<|endoftext|>


<commit_before>let fs = require('fs');
let path = require('path');
let md5 = require('md5');
let chokidar = require('chokidar');
let mkdirp = require('mkdirp');
let uglify = require('uglify-js');
let UglifyCss = require('clean-css');

class File {
    /**
     * Create a new File instance.
     *
     * @param {string} file
     */
    constructor(file) {
        this.file = file;
        this.fileType = path.extname(file);
    }

    /**
     * Static constructor.
     *
     * @param {string} file
     */
    static find(file) {
        return new File(file);
    }

    /**
     * Make all nested directories in the current file path.
     */
    makeDirectories() {
        mkdirp.sync(this.parsePath().base);

        return this;
    }

    /**
     * Minify the file, if it is CSS or JS.
     */
    minify() {
        if (this.fileType === '.js') {
            this.write(uglify.minify(this.file).code);
        }

        if (this.fileType === '.css') {
            this.write(
                new UglifyCss().minify(this.read()).styles
            );
        }
    }

    /**
     * Determine if the given file exists.
     *
     * @param {string} file
     */
    static exists(file) {
        return fs.existsSync(file);
    }

    /**
     * Read the file.
     */
    read() {
        return fs.readFileSync(this.file, {
            encoding: 'utf-8'
        });
    }

    /**
     * Write the given contents to the file.
     *
     * @param {string} body
     */
    write(body) {
        if (typeof body === 'object') {
            body = JSON.stringify(body, null, 2);
        }

        fs.writeFileSync(this.file, body);

        return this;
    }

    /**
     * Delete/Unlink the current file.
     */
    delete() {
        if (fs.existsSync(this.file)) {
            fs.unlinkSync(this.file);
        }
    }

    /**
     * Watch the current file for changes.
     *
     * @param {Function} callback
     */
    watch(callback) {
        return chokidar.watch(
            this.path(), { persistent: true }
        ).on('change', () => callback(this));
    }

    /**
     * Fetch the full path to the file.
     *
     * @return {string}
     */
    path() {
        return path.resolve(this.file);
    }

    /**
     * Version the current file.
     */
    version() {
        let contents = this.read();

        let versionedPath = this.versionedPath(md5(contents));

        return new File(versionedPath).write(contents);
    }

    /**
     * Fetch a full, versioned path to the file.
     *
     * @param {string} hash
     */
    versionedPath(hash) {
        if (! hash) hash = md5(this.read());

        return this.parsePath().hashedPath.replace('[hash]', hash);
    }

    /**
     * Parse the file path into segments.
     */
    parsePath() {
        let outputSegments = path.parse(this.file);

        return {
            path: this.file,
            pathWithoutExt: path.join(outputSegments.dir, `${outputSegments.name}`),
            hashedPath: path.join(outputSegments.dir, `${outputSegments.name}.[hash]${outputSegments.ext}`),
            base: outputSegments.dir,
            file: outputSegments.base,
            hashedFile: `${outputSegments.name}.[hash]${outputSegments.ext}`,
            name: outputSegments.name,
            isDir: ! outputSegments.ext,
            ext: outputSegments.ext
        };
    }

    /**
     * Rename the file.
     *
     * @param {string} to
     */
    rename(to) {
        fs.renameSync(this.file, to);

        this.file = to;

        return this;
    }
}

module.exports = File;
<commit_msg>Use Mix's uglify options to minify - closes #537<commit_after>let fs = require('fs');
let path = require('path');
let md5 = require('md5');
let chokidar = require('chokidar');
let mkdirp = require('mkdirp');
let options = require('./Options');
let uglify = require('uglify-js');
let UglifyCss = require('clean-css');

class File {
    /**
     * Create a new File instance.
     *
     * @param {string} file
     */
    constructor(file) {
        this.file = file;
        this.fileType = path.extname(file);
    }

    /**
     * Static constructor.
     *
     * @param {string} file
     */
    static find(file) {
        return new File(file);
    }

    /**
     * Make all nested directories in the current file path.
     */
    makeDirectories() {
        mkdirp.sync(this.parsePath().base);

        return this;
    }

    /**
     * Minify the file, if it is CSS or JS.
     */
    minify() {
        if (this.fileType === '.js') {
            this.write(uglify.minify(this.file, options.uglify).code);
        }

        if (this.fileType === '.css') {
            this.write(
                new UglifyCss().minify(this.read()).styles
            );
        }
    }

    /**
     * Determine if the given file exists.
     *
     * @param {string} file
     */
    static exists(file) {
        return fs.existsSync(file);
    }

    /**
     * Read the file.
     */
    read() {
        return fs.readFileSync(this.file, {
            encoding: 'utf-8'
        });
    }

    /**
     * Write the given contents to the file.
     *
     * @param {string} body
     */
    write(body) {
        if (typeof body === 'object') {
            body = JSON.stringify(body, null, 2);
        }

        fs.writeFileSync(this.file, body);

        return this;
    }

    /**
     * Delete/Unlink the current file.
     */
    delete() {
        if (fs.existsSync(this.file)) {
            fs.unlinkSync(this.file);
        }
    }

    /**
     * Watch the current file for changes.
     *
     * @param {Function} callback
     */
    watch(callback) {
        return chokidar.watch(
            this.path(), { persistent: true }
        ).on('change', () => callback(this));
    }

    /**
     * Fetch the full path to the file.
     *
     * @return {string}
     */
    path() {
        return path.resolve(this.file);
    }

    /**
     * Version the current file.
     */
    version() {
        let contents = this.read();

        let versionedPath = this.versionedPath(md5(contents));

        return new File(versionedPath).write(contents);
    }

    /**
     * Fetch a full, versioned path to the file.
     *
     * @param {string} hash
     */
    versionedPath(hash) {
        if (! hash) hash = md5(this.read());

        return this.parsePath().hashedPath.replace('[hash]', hash);
    }

    /**
     * Parse the file path into segments.
     */
    parsePath() {
        let outputSegments = path.parse(this.file);

        return {
            path: this.file,
            pathWithoutExt: path.join(outputSegments.dir, `${outputSegments.name}`),
            hashedPath: path.join(outputSegments.dir, `${outputSegments.name}.[hash]${outputSegments.ext}`),
            base: outputSegments.dir,
            file: outputSegments.base,
            hashedFile: `${outputSegments.name}.[hash]${outputSegments.ext}`,
            name: outputSegments.name,
            isDir: ! outputSegments.ext,
            ext: outputSegments.ext
        };
    }

    /**
     * Rename the file.
     *
     * @param {string} to
     */
    rename(to) {
        fs.renameSync(this.file, to);

        this.file = to;

        return this;
    }
}

module.exports = File;
<|endoftext|>


<commit_before>/* @flow */
'use strict';

import type {Font} from './parsing/font';

const SAMPLE_TEXT = 'Hidden Text';
import {SMALL_IMAGE} from './Util';

export class FontMetrics {
    _data: {};
    _document: Document;

    constructor(document: Document) {
        this._data = {};
        this._document = document;
    }
    _parseMetrics(font: Font) {
        const container = this._document.createElement('div');
        const img = this._document.createElement('img');
        const span = this._document.createElement('span');

        const body = this._document.body;
        if (!body) {
            throw new Error(__DEV__ ? 'No document found for font metrics' : '');
        }

        container.style.visibility = 'hidden';
        container.style.fontFamily = font.fontFamily;
        container.style.fontSize = font.fontSize;
        container.style.margin = '0';
        container.style.padding = '0';

        body.appendChild(container);

        img.src = SMALL_IMAGE;
        img.width = 1;
        img.height = 1;

        img.style.margin = '0';
        img.style.padding = '0';
        img.style.verticalAlign = 'baseline';

        span.style.fontFamily = font.fontFamily;
        span.style.fontSize = font.fontSize;
        span.style.margin = '0';
        span.style.padding = '0';

        span.appendChild(this._document.createTextNode(SAMPLE_TEXT));
        container.appendChild(span);
        container.appendChild(img);
        const baseline = img.offsetTop - span.offsetTop + 2;

        container.removeChild(span);
        container.appendChild(this._document.createTextNode(SAMPLE_TEXT));

        container.style.lineHeight = 'normal';
        img.style.verticalAlign = 'super';

        const middle = img.offsetTop - container.offsetTop + 2;

        body.removeChild(container);

        return {baseline, middle};
    }
    getMetrics(font: Font) {
        if (this._data[`${font.fontFamily} ${font.fontSize}`] === undefined) {
            this._data[`${font.fontFamily} ${font.fontSize}`] = this._parseMetrics(font);
        }
        return this._data[`${font.fontFamily} ${font.fontSize}`];
    }
}
<commit_msg>Refactor Font.js<commit_after>/* @flow */
'use strict';

import type {Font} from './parsing/font';

const SAMPLE_TEXT = 'Hidden Text';
import {SMALL_IMAGE} from './Util';

export class FontMetrics {
    _data: {};
    _document: Document;

    constructor(document: Document) {
        this._data = {};
        this._document = document;
    }
    _parseMetrics(font: Font) {
        const container = this._document.createElement('div');
        const img = this._document.createElement('img');
        const span = this._document.createElement('span');

        const body = this._document.body;
        if (!body) {
            throw new Error(__DEV__ ? 'No document found for font metrics' : '');
        }

        container.style.visibility = 'hidden';
        container.style.fontFamily = font.fontFamily;
        container.style.fontSize = font.fontSize;
        container.style.margin = '0';
        container.style.padding = '0';

        body.appendChild(container);

        img.src = SMALL_IMAGE;
        img.width = 1;
        img.height = 1;

        img.style.margin = '0';
        img.style.padding = '0';
        img.style.verticalAlign = 'baseline';

        span.style.fontFamily = font.fontFamily;
        span.style.fontSize = font.fontSize;
        span.style.margin = '0';
        span.style.padding = '0';

        span.appendChild(this._document.createTextNode(SAMPLE_TEXT));
        container.appendChild(span);
        container.appendChild(img);
        const baseline = img.offsetTop - span.offsetTop + 2;

        container.removeChild(span);
        container.appendChild(this._document.createTextNode(SAMPLE_TEXT));

        container.style.lineHeight = 'normal';
        img.style.verticalAlign = 'super';

        const middle = img.offsetTop - container.offsetTop + 2;

        body.removeChild(container);

        return {baseline, middle};
    }
    getMetrics(font: Font) {
        const key = `${font.fontFamily} ${font.fontSize}`;
        if (this._data[key] === undefined) {
            this._data[key] = this._parseMetrics(font);
        }

        return this._data[key];
    }
}
<|endoftext|>


<commit_before>import _ from 'lodash';

import FormState from './FormState';
import FieldsManager from './FieldsManager';

export default class Form {
  constructor(storage) {
    this.$storage = storage;
    this._formState = new FormState(this);
    this._fieldsManager = new FieldsManager(this);

    this._onChangeCallback = null;
    this._onSubmitCallback = null;
    this.fields = this._fieldsManager.fields;
  }

  $stateValueChanged(stateName, newValue) {
    this._formState.setStateValue(stateName, newValue);
  }

  $valueChangedByUser(fieldName, newValue) {
    if (this._onChangeCallback) this._onChangeCallback(fieldName, newValue);
  }

  $validChanged(fieldName, isValid, invalidMsg) {
    var newInvalidMessages = { ...this.invalidMsg };
    if (isValid) {
      delete newInvalidMessages[fieldName];
    }
    else {
      newInvalidMessages[fieldName] = invalidMsg;
    }

    this._formState.setStateValue('invalidMsg', newInvalidMessages);

    var isFormValid = _.isEmpty(newInvalidMessages);
    this._formState.setStateValue('valid', isFormValid);
  }

  $valueChanged(fieldName, newValue) {
    this._formState.setFieldValue(fieldName, newValue);
  }

  $initialValueChanged(fieldName, newInitialValue) {
    this._formState.setFieldInitialValue(fieldName, newInitialValue);
  }

  init(initialState) {
    this.setInitialValues(initialState);
  }

  getValues() {
    return this._formState.getValues();
  }

  getInitialValues() {
    return this._formState.getInitialValues();
  }

  setValues(newValues) {
    this._fieldsManager.setValues(_.cloneDeep(newValues));
  }

  setInitialValues(initialState) {
    this._fieldsManager.setInitialValues(initialState);
  }

  onChange(cb) {
    this._onChangeCallback = cb;
  }

  /**
   * It must be placed to <form> element on onSubmit attribute.
   */
  handleSubmit() {
    if (!this._onSubmitCallback) return;
    this._formState.setStateValue('submitting', true);
    var returnedValue = this._onSubmitCallback(this.values);
    // if promise
    if (returnedValue && returnedValue.then) {
      return returnedValue.then(() => {
        this._formState.setStateValue('submitting', false);
      }, () => {
        this._formState.setStateValue('submitting', false);
      });
    }
    this._formState.setStateValue('submitting', false);
  }

  onSubmit(cb) {
    this._onSubmitCallback = cb;
  }

  reset() {
    // TODO: !!!
  }
}
<commit_msg>add onAnyChange<commit_after>import _ from 'lodash';

import FormState from './FormState';
import FieldsManager from './FieldsManager';

export default class Form {
  constructor(storage) {
    this.$storage = storage;
    this._formState = new FormState(this);
    this._fieldsManager = new FieldsManager(this);

    this._onChangeCallback = null;
    this._onAnyChangeCallback = null;
    this._onSubmitCallback = null;
    this.fields = this._fieldsManager.fields;
  }

  $stateValueChanged(stateName, newValue) {
    this._formState.setStateValue(stateName, newValue);
  }

  $valueChangedByUser(fieldName, newValue) {
    if (this._onChangeCallback) this._onChangeCallback(fieldName, newValue);
  }

  $validChanged(fieldName, isValid, invalidMsg) {
    var newInvalidMessages = { ...this.invalidMsg };
    if (isValid) {
      delete newInvalidMessages[fieldName];
    }
    else {
      newInvalidMessages[fieldName] = invalidMsg;
    }

    this._formState.setStateValue('invalidMsg', newInvalidMessages);

    var isFormValid = _.isEmpty(newInvalidMessages);
    this._formState.setStateValue('valid', isFormValid);
  }

  $valueChanged(fieldName, newValue) {
    this._formState.setFieldValue(fieldName, newValue);
    if (this._onAnyChangeCallback) this._onAnyChangeCallback({[fieldName]: newValue});
  }

  $initialValueChanged(fieldName, newInitialValue) {
    this._formState.setFieldInitialValue(fieldName, newInitialValue);
  }

  init(initialState) {
    this.setInitialValues(initialState);
  }

  getValues() {
    return this._formState.getValues();
  }

  getInitialValues() {
    return this._formState.getInitialValues();
  }

  setValues(newValues) {
    this._fieldsManager.setValues(_.cloneDeep(newValues));
  }

  setInitialValues(initialState) {
    this._fieldsManager.setInitialValues(initialState);
  }

  onChange(cb) {
    this._onChangeCallback = cb;
  }

  onAnyChange(cb) {
    this._onAnyChangeCallback = cb;
  }

  /**
   * It must be placed to <form> element on onSubmit attribute.
   */
  handleSubmit() {
    if (!this._onSubmitCallback) return;
    this._formState.setStateValue('submitting', true);
    var returnedValue = this._onSubmitCallback(this.values);
    // if promise
    if (returnedValue && returnedValue.then) {
      return returnedValue.then(() => {
        this._formState.setStateValue('submitting', false);
      }, () => {
        this._formState.setStateValue('submitting', false);
      });
    }
    this._formState.setStateValue('submitting', false);
  }

  onSubmit(cb) {
    this._onSubmitCallback = cb;
  }

  reset() {
    // TODO: !!!
  }
}
<|endoftext|>


<commit_before>TS.Game = function(game){
	// define needed variables for TS.Game
	var player;
	var moneyGoal;

	var goodGroup;
	var badGroup;

	var clock;
	var moneyText;
	var wellbeingText;
};

TS.Game.prototype = {
	create: function(){

		// Add physics
		this.game.physics.startSystem(Phaser.Physics.ARCADE);

		// display background
		var background = this.add.sprite(0, 0, 'background');
		background.scale.setTo(10, 10);

		// Spelare
		this.moneyGoal = 5;
		this.player = new Player(this.game);
		this.game.add.existing(this.player);

		// Clock (timer)
		this.clock = new Clock(this.game, 720, 50, 2000);
		this.game.add.existing(this.clock);

		// create group for good things
		this.goodGroup = this.game.add.group();
		this.goodGroup.enableBody = true;
		this.goodGroup.outOfBoundsKill = true;

		// Create group for all bad things
		this.badGroup = this.game.add.group();
		this.badGroup.enableBody = true;
		this.badGroup.outOfBoundsKill = true;

		//  Start our folk-loop
		this.createFolk();

		// Set money and health text
		this.moneyText = this.game.add.text(16, 520, 'Pengar: ' + this.player.money + ' / ' + this.moneyGoal + ' kr', { fontSize: '32px', fill: '#000' });
		this.wellbeingText = this.game.add.text(16, 540, 'Hälsa: ' + this.player.wellbeing, { fontSize: '32px', fill: '#000' });
	},
	update: function(){

		if(	 this.player.wellbeing <= 0
			|| this.clock.timeUp ){
			this.state.start('GameEnd', true, false, this.player.wellbeing, this.player.money, this.player.money >= this.moneyGoal);
		}

		this.player.update();

		this.game.physics.arcade.overlap(	this.player,
																			this.goodGroup,
																			this.gotMoney,
																			null,
																			this);
		this.game.physics.arcade.overlap(	this.player,
																			this.badGroup,
																			this.gotHurt,
																			null,
																			this);

	},
	createFolk: function(){
		var naughtiness = this.game.rnd.integerInRange(0, 100);
		var stuff;

		if(naughtiness < 30)
			stuff = this.goodGroup.create(0, 0, 'peng');
		else if(naughtiness > 90)
			stuff = this.badGroup.create(0, 0, 'glob');

		var p = new Folk(this.game, stuff); // send some money with them
		this.game.add.existing(p);

		var timer = this.game.time.create(this.game);
		timer.add(this.game.rnd.integerInRange(500, 2000), this.createFolk, this);
		timer.start();
	},
	gotMoney: function (player, money){
		this.player.money += 1;
		this.moneyText.text = 'Pengar: ' + this.player.money + ' / ' + this.moneyGoal + ' kr';
		money.kill();
	},
	gotHurt: function (player, hurtingThing){
		this.player.wellbeing -= 1;
		this.wellbeingText.text = 'Hälsa: ' + this.player.wellbeing;
		hurtingThing.kill();
	}
};
<commit_msg>aaaaand forgot some other things<commit_after>TS.Game = function(game){
	// define needed variables for TS.Game
	var player;
	var moneyGoal;

	var goodGroup;
	var badGroup;

	var clock;
	var moneyText;
	var wellbeingText;
};

TS.Game.prototype = {
	create: function(){

		// Add physics
		this.game.physics.startSystem(Phaser.Physics.ARCADE);

		// display background
		var background = this.add.sprite(0, 0, 'background');
		background.scale.setTo(10, 10);

		// Spelare
		this.moneyGoal = 5;
		this.player = new Player(this.game);
		this.game.add.existing(this.player);

		// Clock (timer)
		this.clock = new Clock(this.game, 720, 50, 25000);
		this.game.add.existing(this.clock);

		// create group for good things
		this.goodGroup = this.game.add.group();
		this.goodGroup.enableBody = true;
		this.goodGroup.outOfBoundsKill = true;

		// Create group for all bad things
		this.badGroup = this.game.add.group();
		this.badGroup.enableBody = true;
		this.badGroup.outOfBoundsKill = true;

		//  Start our folk-loop
		this.createFolk();

		// Set money and health text
		this.moneyText = this.game.add.text(16, 520, 'Pengar: ' + this.player.money + ' / ' + this.moneyGoal + ' kr', { fontSize: '32px', fill: '#000' });
		this.wellbeingText = this.game.add.text(16, 540, 'Hälsa: ' + this.player.wellbeing, { fontSize: '32px', fill: '#000' });
	},
	update: function(){

		if(	 this.player.wellbeing <= 0
			|| this.clock.timeUp ){
			this.state.start('GameEnd', true, false, this.player.wellbeing, this.player.money, this.player.money >= this.moneyGoal);
		}

		this.player.update();

		this.game.physics.arcade.overlap(	this.player,
																			this.goodGroup,
																			this.gotMoney,
																			null,
																			this);
		this.game.physics.arcade.overlap(	this.player,
																			this.badGroup,
																			this.gotHurt,
																			null,
																			this);

	},
	createFolk: function(){
		var naughtiness = this.game.rnd.integerInRange(0, 100);
		var stuff;

		if(naughtiness < 30)
			stuff = this.goodGroup.create(0, 0, 'peng');
		else if(naughtiness > 90)
			stuff = this.badGroup.create(0, 0, 'glob');

		var p = new Folk(this.game, stuff); // send some money with them
		this.game.add.existing(p);

		var timer = this.game.time.create(this.game);
		timer.add(this.game.rnd.integerInRange(500, 2000), this.createFolk, this);
		timer.start();
	},
	gotMoney: function (player, money){
		this.player.money += 1;
		this.moneyText.text = 'Pengar: ' + this.player.money + ' / ' + this.moneyGoal + ' kr';
		money.kill();
	},
	gotHurt: function (player, hurtingThing){
		this.player.wellbeing -= 1;
		this.wellbeingText.text = 'Hälsa: ' + this.player.wellbeing;
		hurtingThing.kill();
	}
};
<|endoftext|>


<commit_before>(function() {
  var input;
  var Game = {
    currentPlayer: null,
    goFirst: null,

    changeCurrentPlayer: function(currentPlayer) {
      this.currentPlayer = currentPlayer == "X" ? "O" : "X";
    },

    winner: function(currentPlayer) {
      return currentPlayer == "X" ? "Player" : "Computer";
    },

    firstMove: function(button) {
      var input = UI.askFirstMove();
      if(input == "y" || input == "n") {
        UI.toggleDisplayedButton(".btn-restart", ".btn-new");
        this.goFirst = input;
      }
      else {
        UI.inputErrorMessage();
        this.firstMove();
      }
    },

    checkGameOver: function(currentPlayer) {
      Game.changeCurrentPlayer(Game.currentPlayer);
      if(GameRules.gameOver(GameBoard)) {
        UI.visualWhenGameOver(currentPlayer);
        return true;
      }
      return false;
    },

    humanChoice: function(chosenSpotID, callback) {
      if (Human.choiceSpot(GameBoard, chosenSpotID, Game.currentPlayer)) {
        UI.unbindClick("tr td");
        UI.hideHumanMessage();
        if (Game.checkGameOver(Game.currentPlayer) === false) {
          callback(Game.playGame);
        }
      }
      else {
        return;
      }
    },

    computerChoice: function(callback) {
      Computer.chooseTheBestSpot(Game.currentPlayer);
      if (Game.checkGameOver(Game.currentPlayer) === false) {
        callback(Game.playGame);
      }
    },

    playGame: function() {
      if (Game.goFirst === "y") {
        UI.humanPlay();
      }
      else if (Game.goFirst === "n") {
        UI.computerPlay();
      }
    }
  };
  window.Game = Game;
})();
<commit_msg>delete needless argument<commit_after>(function() {
  var input;
  var Game = {
    currentPlayer: null,
    goFirst: null,

    changeCurrentPlayer: function(currentPlayer) {
      this.currentPlayer = currentPlayer == "X" ? "O" : "X";
    },

    winner: function(currentPlayer) {
      return currentPlayer == "X" ? "Player" : "Computer";
    },

    firstMove: function() {
      var input = UI.askFirstMove();
      if(input == "y" || input == "n") {
        UI.toggleDisplayedButton(".btn-restart", ".btn-new");
        this.goFirst = input;
      }
      else {
        UI.inputErrorMessage();
        this.firstMove();
      }
    },

    checkGameOver: function(currentPlayer) {
      Game.changeCurrentPlayer(Game.currentPlayer);
      if(GameRules.gameOver(GameBoard)) {
        UI.visualWhenGameOver(currentPlayer);
        return true;
      }
      return false;
    },

    humanChoice: function(chosenSpotID, callback) {
      if (Human.choiceSpot(GameBoard, chosenSpotID, Game.currentPlayer)) {
        UI.unbindClick("tr td");
        UI.hideHumanMessage();
        if (Game.checkGameOver(Game.currentPlayer) === false) {
          callback(Game.playGame);
        }
      }
      else {
        return;
      }
    },

    computerChoice: function(callback) {
      Computer.chooseTheBestSpot(Game.currentPlayer);
      if (Game.checkGameOver(Game.currentPlayer) === false) {
        callback(Game.playGame);
      }
    },

    playGame: function() {
      if (Game.goFirst === "y") {
        UI.humanPlay();
      }
      else if (Game.goFirst === "n") {
        UI.computerPlay();
      }
    }
  };
  window.Game = Game;
})();
<|endoftext|>


<commit_before>'use strict';

/* eslint  max-len: 0, no-catch-shadow: 0, no-use-before-define: 0 */

const https = require('https');
const path = require('path');
const zlib = require('zlib');
const fs = require('fs');
const { execSync } = require('child_process');

/**
 * Install required npm modules
 */
if (!fs.existsSync(path.join(__dirname, 'node_modules'))) {
  execSync('npm install', { cwd: __dirname, shell: true });
}

const fse = require('fs-extra');
const yaml = require('js-yaml');
const sass = require('node-sass');
const uglifyJs = require('uglify-js');
const { minify } = require('html-minifier');

/**
 * Read directory recursively
 * @param dir
 * @param filter
 * @param callback
 */
function walkDir(dir, filter, callback) {
  if (!fs.existsSync(dir)) {
    return;
  }

  let files = fs.readdirSync(dir);

  for (let i = 0; i < files.length; i++) {
    let filename = path.join(dir, files[i]);
    let stat = fs.lstatSync(filename);

    if (stat.isDirectory()) {
      walkDir(filename, filter, callback);
    } else if (filter.test(filename)) {
      callback(filename);
    }
  }
}

/**
 * Replace by pattern
 * @param file
 * @param pattern
 * @param replacement
 */
function replaceInFile(file, pattern, replacement) {
  fs.writeFileSync(file, fs.readFileSync(file).toString().replace(pattern, replacement));
}

function get(url, cb) {
  https.get(url, response => {
    let rawData = '';
    let output = response;

    if (response.headers['content-encoding'] === 'gzip') {
      output = zlib.createGunzip();
      response.pipe(output);
    }

    output.on('data', chunk => {
      rawData += chunk;
    });

    output.on('end', () => {
      cb(null, rawData);
    });
  }).on('error', error => {
    cb(error, null);
  });
}

const articlesPaths = [
  '/nytimes/www.nytimes.com/2016/07/04/technology',
  '/bloomberg/www.bloomberg.com/news/articles',
  '/wapost/www.washingtonpost.com/news/the-fix',
  '/wapost/www.washingtonpost.com/politics/clinton-headed-to-nebraska-which-could-provide-exactly-1-of-270-electoral-votes'
];

module.exports = function(callback) {
  const mService = this.microservice;
  const env = mService.property.env;
  const frontendPath = path.join(__dirname, 'frontend');
  const buildPath = path.join(frontendPath, '_build');
  const frontendParams = mService.parameters.frontend;

  console.log('Downloading latest Swagger Specification file');
  get(frontendParams.swaggerUrl, (err, res) => {
    if (err) {
      throw err;
    }

    let subDomain;
    switch (env) {
      case 'prod':
        subDomain = 'api';
        break;
      case 'stage':
        subDomain = 'api-stage';
        break;
      default:
        subDomain = 'api-test';
    }

    let json = yaml.load(res);
    json.host = `${subDomain}.adtechmedia.io`;

    fse.ensureDirSync(`${buildPath}/files`);
    fs.writeFileSync(`${buildPath}/files/swagger.json`, JSON.stringify(json));

    getDeepFramework();
  });

  function getDeepFramework() {
    console.log('Installing latest deep-framework from GitHub');
    const deepFramework = 'https://raw.githubusercontent.com/MitocGroup/deep-framework/master/src/deep-framework/browser/framework.js';

    get(deepFramework, (err, res) => {
      if (err) {
        throw err;
      }

      fs.writeFileSync(`${buildPath}/js/vendor/deep-framework.min.js`, res);
    });

    injectRobotsTxt();
  }

  function injectRobotsTxt() {
    console.log('Inject corresponding robots.txt');

    let sourceRobots = (env === 'prod') ? 'prod-robots.txt' : 'dev-robots.txt';
    fs.writeFileSync(`${buildPath}/robots.txt`, fs.readFileSync(`${frontendPath}/files/${sourceRobots}`));
    fs.writeFileSync(`${buildPath}/sitemap.xml`, fs.readFileSync(`${frontendPath}/files/sitemap.xml`));

    minifyJsFiles();
  }

  function minifyJsFiles() {
    console.log('Minifying js files');

    const srcPath = path.join(frontendPath, 'js/src');
    fse.ensureDirSync(`${buildPath}/js`);

    walkDir(srcPath, /\.js$/, srcFilePath => {
      let sourceJs = fs.readFileSync(srcFilePath, {encoding: 'utf8'});
      let minResult = uglifyJs.minify(sourceJs);

      fs.writeFileSync(
        `${buildPath}/js/${path.basename(srcFilePath)}`,
        minResult.code
      );
    });

    fse.copySync(`${frontendPath}/js/vendor`, `${buildPath}/js/vendor`);

    minifyStaticPages();
  }

  function minifyStaticPages() {
    console.log('Minifying static pages');

    let srcDir = `${frontendPath}/static-pages`;
    walkDir(srcDir, /\.html$/, srcFile => {
      // fs.copySync(srcFile, srcFile.replace(srcDir, buildPath));
      const destFile = srcFile.replace(srcDir, buildPath);
      fse.ensureDirSync(path.dirname(destFile));

      let srcFileContent = fs.readFileSync(srcFile, { encoding: 'utf8' });
      fs.writeFileSync(destFile, minify(srcFileContent, {
        minifyJS: true,
        minifyCSS: true,
        removeComments: true,
        collapseWhitespace: true,
        removeStyleLinkTypeAttributes: true
      }));

    });

    minifyCssFiles();
  }

  function minifyCssFiles() {
    console.log('Compiling sass to css');

    fse.ensureDirSync(`${buildPath}/css`);

    const srcDir = `${frontendPath}/css/src`;
    walkDir(srcDir, /main\.scss$/, sassFile => {
      sass.render({ file: sassFile, outputStyle: 'compressed' }, (error, result) => {
        if (error) {
          throw error;
        }

        const name = path.dirname(sassFile.replace(srcDir, ''));
        const cssName = (name !== '/') ? `${name}.min.css` : 'main.min.css';

        fs.writeFileSync(`${buildPath}/css/${cssName}`, result.css);
      });
    });

    fse.copySync(`${frontendPath}/css/vendor`, `${buildPath}/css/vendor`);

    copyAssets();
  }

  function copyAssets() {
    console.log('Preparing site assets');

    fse.copySync(`${frontendPath}/data`, `${buildPath}/data`);
    fse.copySync(`${frontendPath}/fonts`, `${buildPath}/fonts`);
    fse.copySync(`${frontendPath}/images`, `${buildPath}/images`);
    fse.copySync(`${frontendPath}/demo-pages`, `${buildPath}/demo-pages`);
    fse.copySync(`${frontendPath}/.well-known`, `${buildPath}/.well-known`);

    prepareDemoPages();
  }

  function prepareDemoPages() {
    console.log('Injecting ATM base, SW and ribbon');

    articlesPaths.forEach(articlesPath => {
      const swSource = frontendParams.swSource;
      const atmSource = frontendParams.atmSource;
      const manageBaseUrl = frontendParams.dashboardUrl;
      const fullArticlesPath = path.join(buildPath, 'demo-pages', articlesPath);
      const ribbonContent = fs.readFileSync(`${frontendPath}/files/nyt-ribbon.html`).toString();

      walkDir(fullArticlesPath, /\.html$/, filename => {
        console.log(`Injecting into article: ${path.basename(filename)}`);

        try {
          replaceInFile(filename, /%_ATM_NYT_RIBBON_PLACEHOLDER_%/g, ribbonContent);
          replaceInFile(filename, /%_ATM_BASE_URL_PLACEHOLDER_%/g, manageBaseUrl);
          replaceInFile(filename, /%_ATM_SW_PATH_PLACEHOLDER_%/g, swSource);
          replaceInFile(filename, /%_ATM_URL_PLACEHOLDER_%/g, atmSource);
        } catch (error) {
          console.error(error);
        }
      });
    });

    callback();
  }
};
<commit_msg>try catch<commit_after>'use strict';

/* eslint  max-len: 0, no-catch-shadow: 0, no-use-before-define: 0 */

const https = require('https');
const path = require('path');
const zlib = require('zlib');
const fs = require('fs');
const { execSync } = require('child_process');

/**
 * Install required npm modules
 */
if (!fs.existsSync(path.join(__dirname, 'node_modules'))) {
  try {
    execSync('npm install', { cwd: __dirname, shell: true });
  } catch (err) {
    console.log('Cannot install modules');
  }
}

const fse = require('fs-extra');
const yaml = require('js-yaml');
const sass = require('node-sass');
const uglifyJs = require('uglify-js');
const { minify } = require('html-minifier');

/**
 * Read directory recursively
 * @param dir
 * @param filter
 * @param callback
 */
function walkDir(dir, filter, callback) {
  if (!fs.existsSync(dir)) {
    return;
  }

  let files = fs.readdirSync(dir);

  for (let i = 0; i < files.length; i++) {
    let filename = path.join(dir, files[i]);
    let stat = fs.lstatSync(filename);

    if (stat.isDirectory()) {
      walkDir(filename, filter, callback);
    } else if (filter.test(filename)) {
      callback(filename);
    }
  }
}

/**
 * Replace by pattern
 * @param file
 * @param pattern
 * @param replacement
 */
function replaceInFile(file, pattern, replacement) {
  fs.writeFileSync(file, fs.readFileSync(file).toString().replace(pattern, replacement));
}

function get(url, cb) {
  https.get(url, response => {
    let rawData = '';
    let output = response;

    if (response.headers['content-encoding'] === 'gzip') {
      output = zlib.createGunzip();
      response.pipe(output);
    }

    output.on('data', chunk => {
      rawData += chunk;
    });

    output.on('end', () => {
      cb(null, rawData);
    });
  }).on('error', error => {
    cb(error, null);
  });
}

const articlesPaths = [
  '/nytimes/www.nytimes.com/2016/07/04/technology',
  '/bloomberg/www.bloomberg.com/news/articles',
  '/wapost/www.washingtonpost.com/news/the-fix',
  '/wapost/www.washingtonpost.com/politics/clinton-headed-to-nebraska-which-could-provide-exactly-1-of-270-electoral-votes'
];

module.exports = function(callback) {
  const mService = this.microservice;
  const env = mService.property.env;
  const frontendPath = path.join(__dirname, 'frontend');
  const buildPath = path.join(frontendPath, '_build');
  const frontendParams = mService.parameters.frontend;

  console.log('Downloading latest Swagger Specification file');
  get(frontendParams.swaggerUrl, (err, res) => {
    if (err) {
      throw err;
    }

    let subDomain;
    switch (env) {
      case 'prod':
        subDomain = 'api';
        break;
      case 'stage':
        subDomain = 'api-stage';
        break;
      default:
        subDomain = 'api-test';
    }

    let json = yaml.load(res);
    json.host = `${subDomain}.adtechmedia.io`;

    fse.ensureDirSync(`${buildPath}/files`);
    fs.writeFileSync(`${buildPath}/files/swagger.json`, JSON.stringify(json));

    getDeepFramework();
  });

  function getDeepFramework() {
    console.log('Installing latest deep-framework from GitHub');
    const deepFramework = 'https://raw.githubusercontent.com/MitocGroup/deep-framework/master/src/deep-framework/browser/framework.js';

    get(deepFramework, (err, res) => {
      if (err) {
        throw err;
      }

      fs.writeFileSync(`${buildPath}/js/vendor/deep-framework.min.js`, res);
    });

    injectRobotsTxt();
  }

  function injectRobotsTxt() {
    console.log('Inject corresponding robots.txt');

    let sourceRobots = (env === 'prod') ? 'prod-robots.txt' : 'dev-robots.txt';
    fs.writeFileSync(`${buildPath}/robots.txt`, fs.readFileSync(`${frontendPath}/files/${sourceRobots}`));
    fs.writeFileSync(`${buildPath}/sitemap.xml`, fs.readFileSync(`${frontendPath}/files/sitemap.xml`));

    minifyJsFiles();
  }

  function minifyJsFiles() {
    console.log('Minifying js files');

    const srcPath = path.join(frontendPath, 'js/src');
    fse.ensureDirSync(`${buildPath}/js`);

    walkDir(srcPath, /\.js$/, srcFilePath => {
      let sourceJs = fs.readFileSync(srcFilePath, {encoding: 'utf8'});
      let minResult = uglifyJs.minify(sourceJs);

      fs.writeFileSync(
        `${buildPath}/js/${path.basename(srcFilePath)}`,
        minResult.code
      );
    });

    fse.copySync(`${frontendPath}/js/vendor`, `${buildPath}/js/vendor`);

    minifyStaticPages();
  }

  function minifyStaticPages() {
    console.log('Minifying static pages');

    let srcDir = `${frontendPath}/static-pages`;
    walkDir(srcDir, /\.html$/, srcFile => {
      // fs.copySync(srcFile, srcFile.replace(srcDir, buildPath));
      const destFile = srcFile.replace(srcDir, buildPath);
      fse.ensureDirSync(path.dirname(destFile));

      let srcFileContent = fs.readFileSync(srcFile, { encoding: 'utf8' });
      fs.writeFileSync(destFile, minify(srcFileContent, {
        minifyJS: true,
        minifyCSS: true,
        removeComments: true,
        collapseWhitespace: true,
        removeStyleLinkTypeAttributes: true
      }));

    });

    minifyCssFiles();
  }

  function minifyCssFiles() {
    console.log('Compiling sass to css');

    fse.ensureDirSync(`${buildPath}/css`);

    const srcDir = `${frontendPath}/css/src`;
    walkDir(srcDir, /main\.scss$/, sassFile => {
      sass.render({ file: sassFile, outputStyle: 'compressed' }, (error, result) => {
        if (error) {
          throw error;
        }

        const name = path.dirname(sassFile.replace(srcDir, ''));
        const cssName = (name !== '/') ? `${name}.min.css` : 'main.min.css';

        fs.writeFileSync(`${buildPath}/css/${cssName}`, result.css);
      });
    });

    fse.copySync(`${frontendPath}/css/vendor`, `${buildPath}/css/vendor`);

    copyAssets();
  }

  function copyAssets() {
    console.log('Preparing site assets');

    fse.copySync(`${frontendPath}/data`, `${buildPath}/data`);
    fse.copySync(`${frontendPath}/fonts`, `${buildPath}/fonts`);
    fse.copySync(`${frontendPath}/images`, `${buildPath}/images`);
    fse.copySync(`${frontendPath}/demo-pages`, `${buildPath}/demo-pages`);
    fse.copySync(`${frontendPath}/.well-known`, `${buildPath}/.well-known`);

    prepareDemoPages();
  }

  function prepareDemoPages() {
    console.log('Injecting ATM base, SW and ribbon');

    articlesPaths.forEach(articlesPath => {
      const swSource = frontendParams.swSource;
      const atmSource = frontendParams.atmSource;
      const manageBaseUrl = frontendParams.dashboardUrl;
      const fullArticlesPath = path.join(buildPath, 'demo-pages', articlesPath);
      const ribbonContent = fs.readFileSync(`${frontendPath}/files/nyt-ribbon.html`).toString();

      walkDir(fullArticlesPath, /\.html$/, filename => {
        console.log(`Injecting into article: ${path.basename(filename)}`);

        try {
          replaceInFile(filename, /%_ATM_NYT_RIBBON_PLACEHOLDER_%/g, ribbonContent);
          replaceInFile(filename, /%_ATM_BASE_URL_PLACEHOLDER_%/g, manageBaseUrl);
          replaceInFile(filename, /%_ATM_SW_PATH_PLACEHOLDER_%/g, swSource);
          replaceInFile(filename, /%_ATM_URL_PLACEHOLDER_%/g, atmSource);
        } catch (error) {
          console.error(error);
        }
      });
    });

    callback();
  }
};
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import Select from 'react-select';
import axios from 'axios';
import base from  './utils/base';
import loadingSpinner from './spinning-bubbles.svg';
import Specifications from './Specifications';
import HistoryVehicle from './HistoryVehicle';

var options = [
    { value: '2016', label: '2016' },
    { value: '2015', label: '2015' },
    { value: '2014', label: '2014' },
    { value: '2013', label: '2013' },
    { value: '2012', label: '2012' },
    { value: '2011', label: '2011' },
    { value: '2010', label: '2010' },
    { value: '2009', label: '2009' },
    { value: '2008', label: '2008' },
    { value: '2007', label: '2007' },
    { value: '2006', label: '2006' },
    { value: '2005', label: '2005' }
];

class Home extends Component {
    constructor() {
        super();
        this.state = {
            error: null,
            make: null,
            model: null,
            year: null,
            engine: null,
            loading: null,
            specs: [],
            showSpecs: null,
            selectedYear: null,
            availableMakes: null,
            makesLoading: false,
            modelsLoading: false,
            enginesLoading: false,
            previousVehicles: []
        }
    };
    replaceVehicle = (v) => {
        // Replaces the first item in previousVehicles array and adds new one to end
        let prevVehicles = this.state.previousVehicles;
        prevVehicles.shift();
        prevVehicles.push(v);
        this.setState({
            previousVehicles: prevVehicles
        });
    };
    setYear = (e) => {
        if (e === null) {
            this.setState({
                year: null,
                make: null,
                model: null,
                engine: null,
                makesLoading: false,
                availableEngines: null,
                availableMakes: null,
                availableModels: null,
                showSpecs: null
            })
            this.refs.vinNumber.value = '';
            return false;
        }
        this.setState({
            year: e.value,
            make: null,
            model: null,
            engine: null,
            makesLoading: true,
            showSpecs: null
        })
        base.bindToState(`${e.value}`, {
            context: this,
            state: 'availableMakes',
            asArray: true,
            then(response) {
                this.setState({
                    makesLoading: false
                })
            }
        })
    };
    setMake = (e) => {
        if (e === null) {
            this.setState({
                make: null,
                model: null,
                engine: null,
                availableEngines: null,
                availableModels: null,
                showSpecs: null
            })
            this.refs.vinNumber.value = '';
            return false;
        }
        this.setState({
            make: e.value,
            modelsLoading: true
        })
        base.bindToState(`${this.state.year}/${e.value}/`, {
            context: this,
            state: 'availableModels',
            asArray: true,
            then(response) {
                this.setState({
                    modelsLoading: false
                })
            }
        })
    };
    setModel = (e) => {
        if (e === null) {
            this.setState({
                model: null,
                engine: null,
                availableEngines: null,
                showSpecs: null
            })
            this.refs.vinNumber.value = '';
            return false;
        }
        this.setState({
            model: e.value,
            enginesLoading: true
        })
        base.bindToState(`${this.state.year}/${this.state.make}/${e.value}`, {
            context: this,
            asArray: true,
            state: 'availableEngines',
            then(response) {
                this.setState({
                    enginesLoading: false
                })
            }
        });
    };
    setEngine = (e) => {
        if (e === null) {
            this.setState({
                engine: null,
                showSpecs: null
            })
            this.refs.vinNumber.value = '';
            return false;
        }
        const engineSizePeriod = e.value.replace(',', '.');
        this.setState({
            loading: true,
            engine: e.value,
            engineSizePeriod: engineSizePeriod
        })
        const vehicle = `${this.state.year}/${this.state.make}/${this.state.model}/${e.value}`;
        this.replaceVehicle(vehicle);
        base.bindToState(`${this.state.year}/${this.state.make}/${this.state.model}/${e.value}`, {
            context: this,
            state: 'specs',
            asArray: false
        });
        this.refs.vinNumber.value = '';
        this.setState({
            error: null,
            loading: null,
            showSpecs: true
        })
    };
    submitVin = (e) => {
        e.preventDefault();
        this.setState({
            year: null,
            make: null,
            model: null,
            engine: null,
            makesLoading: false,
            availableEngines: null,
            availableMakes: null,
            availableModels: null,
            showSpecs: null,
            loading: true
        })
        const vinNumber = this.refs.vinNumber.value;
        if (vinNumber.length < 17) {
            this.setState({
                loading: null,
                error: 'VIN number must be 17 characters long.'
            })
        } else {
            const vinDecodeUrl = `https://api.edmunds.com/v1/api/toolsrepository/vindecoder?vin=${vinNumber}&fmt=json&api_key=${process.env.REACT_APP_EDMUNDS_KEY}`;
            axios.get(vinDecodeUrl)
                .then(response => {
                    const data = response.data.styleHolder[0];
                    let engineSize;
                    if (data.engineSize.toString().length === 1) {
                        engineSize = `${data.engineSize}.0`;
                    } else {
                        engineSize = data.engineSize;
                    }
                    this.setState({
                        error: null,
                        make: data.makeName,
                        model: data.modelName,
                        engine: engineSize,
                        year: data.year,
                        engineSizeComma: engineSize.toString().replace('.',','),
                        engineSizeFormatted: engineSize
                    });
                    const engineSizeComma = this.state.engine.toString().replace('.', ',');
                    const vehicle = `${this.state.year}/${this.state.make}/${this.state.model}/${engineSizeComma}`;
                    base.fetch(`${this.state.year}/${this.state.make}/${this.state.model}/${engineSizeComma}`, {
                        context: this,
                        asArray:false
                    }).then(data => {
                        if (data == null) {
                            console.log('no data');
                            this.setState({
                                loading: null,
                                error: 'This vehicle has not been added yet. We are working on it.'
                            });
                            base.push(`notAdded/${this.state.year}-${this.state.make}-${this.state.model}-${this.state.engineComma}`, {
                                data: true
                            });
                            return false;
                        }
                        base.bindToState(`${this.state.year}/${this.state.make}/${this.state.model}/${engineSizeComma}`, {
                            context: this,
                            state: 'specs',
                            asArray: false
                        });

                        // Replace vehicle in last 10 array
                        this.replaceVehicle(vehicle);

                        this.setState({
                            error: null,
                            loading: null,
                            showSpecs: true
                        })
                    }).catch(error => {
                        console.log(error);
                    })
                }).catch(err => {
                    console.log(err);
                    this.refs.vinNumber.value = '';
                    this.setState({
                        loading: null,
                        error: 'Invalid VIN Number. Please try again.'
                    })
                })
        }
    };
    searchVehicle = (vehicle) => {
        console.log(vehicle);
        const vehicleSplit = vehicle.split('/');
        const year = vehicleSplit[0];
        const make = vehicleSplit[1];
        const model = vehicleSplit[2];
        const engine = vehicleSplit[3];
        const vehicleString = `${year}/${make}/${model}/${engine}`;
        console.log(vehicleSplit);

        base.bindToState(`${vehicleString}`, {
            context: this,
            state: 'specs',
            asArray: false
        });

        this.setState({
            year: year,
            make: make,
            model: model,
            engine: engine,
            engineSizePeriod: engine.replace(',','.'),
            error: null,
            loading: null,
            showSpecs: true
        })
    };
    componentDidMount() {
        base.syncState(`previousVehicles`,{
            context: this,
            state: 'previousVehicles',
            asArray: true
        })
    };
    render() {
        function logChange(val) {
            console.log("Selected: " + val);
        }
        let availableMakes = [];
        let availableModels = [];
        let availableEngines = [];
        if (this.state.availableMakes) {
            this.state.availableMakes.map((val, key) => {
                availableMakes.push( { "value": val.key, "label": val.key } );
            });
        }
        if (this.state.availableModels) {
            this.state.availableModels.map((val, key) => {
                availableModels.push( { "value": val.key, "label": val.key } );
            });
        }
        if (this.state.availableEngines) {
            this.state.availableEngines.map((val, key) => {
                availableEngines.push( { "value": val.key, "label": val.key.replace(',', '.') } );
            });
        }
        let loadingStatus;
        if (this.state.loading) {
            loadingStatus =

;
        } else {
            loadingStatus = null;
        }

        let previousTen = this.state.previousVehicles.map((vehicle, key) => {
            const vehicleSplit = vehicle.split('/');
            const year = vehicleSplit[0];
            const make = vehicleSplit[1];
            const model = vehicleSplit[2];
            const engine = vehicleSplit[3].replace(',', '.');
            const vehicleString = `${year} ${make} ${model} ${engine} L`;
            return <HistoryVehicle data={vehicleString} link={vehicle} key={key} handleClick={this.searchVehicle.bind(this)} />;
        });

        return (

Previous Vehicles

                        {
                            previousTen
                        }

                        <form className="col-sm-4 offset-sm-4" onSubmit={this.submitVin}>

                                {this.state.error ?

                                                        Error! {this.state.error}

                                                    : null}

Enter VIN Number

                                <input className="form-control" type="text" ref="vinNumber" />

                                <button className="btn btn-primary" type="submit"> Submit</button>

                        </form>

                        <Select
                            name="form-field-year"
                            value={this.state.year}
                            options={options}
                            onChange={this.setYear}
                        />

                        <Select
                            name="form-field-make"
                            value={this.state.make}
                            options={availableMakes}
                            onChange={this.setMake}
                            isLoading={this.state.makesLoading}
                        />

                        <Select
                            name="form-field-model"
                            value={this.state.model}
                            options={availableModels}
                            onChange={this.setModel}
                            isLoading={this.state.modelsLoading}
                        />

                        <Select
                            name="form-field-engine"
                            value={this.state.engine}
                            options={availableEngines}
                            onChange={this.setEngine}
                            isLoading={this.state.enginesLoading}
                        />

                    {
                        this.state.showSpecs ? <Specifications make={this.state.make} model={this.state.model} year={this.state.year} engine={this.state.engineSizePeriod} data={this.state.specs} />
                                             : loadingStatus
                    }

        );
    }
}

export default Home;<commit_msg>Fix engineSizeComma variable misspelling<commit_after>import React, {Component} from 'react';
import Select from 'react-select';
import axios from 'axios';
import base from  './utils/base';
import loadingSpinner from './spinning-bubbles.svg';
import Specifications from './Specifications';
import HistoryVehicle from './HistoryVehicle';

var options = [
    { value: '2016', label: '2016' },
    { value: '2015', label: '2015' },
    { value: '2014', label: '2014' },
    { value: '2013', label: '2013' },
    { value: '2012', label: '2012' },
    { value: '2011', label: '2011' },
    { value: '2010', label: '2010' },
    { value: '2009', label: '2009' },
    { value: '2008', label: '2008' },
    { value: '2007', label: '2007' },
    { value: '2006', label: '2006' },
    { value: '2005', label: '2005' }
];

class Home extends Component {
    constructor() {
        super();
        this.state = {
            error: null,
            make: null,
            model: null,
            year: null,
            engine: null,
            loading: null,
            specs: [],
            showSpecs: null,
            selectedYear: null,
            availableMakes: null,
            makesLoading: false,
            modelsLoading: false,
            enginesLoading: false,
            previousVehicles: []
        }
    };
    replaceVehicle = (v) => {
        // Replaces the first item in previousVehicles array and adds new one to end
        let prevVehicles = this.state.previousVehicles;
        prevVehicles.shift();
        prevVehicles.push(v);
        this.setState({
            previousVehicles: prevVehicles
        });
    };
    setYear = (e) => {
        if (e === null) {
            this.setState({
                year: null,
                make: null,
                model: null,
                engine: null,
                makesLoading: false,
                availableEngines: null,
                availableMakes: null,
                availableModels: null,
                showSpecs: null
            })
            this.refs.vinNumber.value = '';
            return false;
        }
        this.setState({
            year: e.value,
            make: null,
            model: null,
            engine: null,
            makesLoading: true,
            showSpecs: null
        })
        base.bindToState(`${e.value}`, {
            context: this,
            state: 'availableMakes',
            asArray: true,
            then(response) {
                this.setState({
                    makesLoading: false
                })
            }
        })
    };
    setMake = (e) => {
        if (e === null) {
            this.setState({
                make: null,
                model: null,
                engine: null,
                availableEngines: null,
                availableModels: null,
                showSpecs: null
            })
            this.refs.vinNumber.value = '';
            return false;
        }
        this.setState({
            make: e.value,
            modelsLoading: true
        })
        base.bindToState(`${this.state.year}/${e.value}/`, {
            context: this,
            state: 'availableModels',
            asArray: true,
            then(response) {
                this.setState({
                    modelsLoading: false
                })
            }
        })
    };
    setModel = (e) => {
        if (e === null) {
            this.setState({
                model: null,
                engine: null,
                availableEngines: null,
                showSpecs: null
            })
            this.refs.vinNumber.value = '';
            return false;
        }
        this.setState({
            model: e.value,
            enginesLoading: true
        })
        base.bindToState(`${this.state.year}/${this.state.make}/${e.value}`, {
            context: this,
            asArray: true,
            state: 'availableEngines',
            then(response) {
                this.setState({
                    enginesLoading: false
                })
            }
        });
    };
    setEngine = (e) => {
        if (e === null) {
            this.setState({
                engine: null,
                showSpecs: null
            })
            this.refs.vinNumber.value = '';
            return false;
        }
        const engineSizePeriod = e.value.replace(',', '.');
        this.setState({
            loading: true,
            engine: e.value,
            engineSizePeriod: engineSizePeriod
        })
        const vehicle = `${this.state.year}/${this.state.make}/${this.state.model}/${e.value}`;
        this.replaceVehicle(vehicle);
        base.bindToState(`${this.state.year}/${this.state.make}/${this.state.model}/${e.value}`, {
            context: this,
            state: 'specs',
            asArray: false
        });
        this.refs.vinNumber.value = '';
        this.setState({
            error: null,
            loading: null,
            showSpecs: true
        })
    };
    submitVin = (e) => {
        e.preventDefault();
        this.setState({
            year: null,
            make: null,
            model: null,
            engine: null,
            makesLoading: false,
            availableEngines: null,
            availableMakes: null,
            availableModels: null,
            showSpecs: null,
            loading: true
        })
        const vinNumber = this.refs.vinNumber.value;
        if (vinNumber.length < 17) {
            this.setState({
                loading: null,
                error: 'VIN number must be 17 characters long.'
            })
        } else {
            const vinDecodeUrl = `https://api.edmunds.com/v1/api/toolsrepository/vindecoder?vin=${vinNumber}&fmt=json&api_key=${process.env.REACT_APP_EDMUNDS_KEY}`;
            axios.get(vinDecodeUrl)
                .then(response => {
                    const data = response.data.styleHolder[0];
                    let engineSize;
                    if (data.engineSize.toString().length === 1) {
                        engineSize = `${data.engineSize}.0`;
                    } else {
                        engineSize = data.engineSize;
                    }
                    this.setState({
                        error: null,
                        make: data.makeName,
                        model: data.modelName,
                        engine: engineSize,
                        year: data.year,
                        engineSizeComma: engineSize.toString().replace('.',','),
                        engineSizeFormatted: engineSize
                    });
                    const engineSizeComma = this.state.engine.toString().replace('.', ',');
                    const vehicle = `${this.state.year}/${this.state.make}/${this.state.model}/${engineSizeComma}`;
                    base.fetch(`${this.state.year}/${this.state.make}/${this.state.model}/${engineSizeComma}`, {
                        context: this,
                        asArray:false
                    }).then(data => {
                        if (data == null) {
                            console.log('no data');
                            this.setState({
                                loading: null,
                                error: 'This vehicle has not been added yet. We are working on it.'
                            });
                            base.push(`notAdded/${this.state.year}-${this.state.make}-${this.state.model}-${this.state.engineSizeComma}`, {
                                data: true
                            });
                            return false;
                        }
                        base.bindToState(`${this.state.year}/${this.state.make}/${this.state.model}/${engineSizeComma}`, {
                            context: this,
                            state: 'specs',
                            asArray: false
                        });

                        // Replace vehicle in last 10 array
                        this.replaceVehicle(vehicle);

                        this.setState({
                            error: null,
                            loading: null,
                            showSpecs: true
                        })
                    }).catch(error => {
                        console.log(error);
                    })
                }).catch(err => {
                    console.log(err);
                    this.refs.vinNumber.value = '';
                    this.setState({
                        loading: null,
                        error: 'Invalid VIN Number. Please try again.'
                    })
                })
        }
    };
    searchVehicle = (vehicle) => {
        console.log(vehicle);
        const vehicleSplit = vehicle.split('/');
        const year = vehicleSplit[0];
        const make = vehicleSplit[1];
        const model = vehicleSplit[2];
        const engine = vehicleSplit[3];
        const vehicleString = `${year}/${make}/${model}/${engine}`;
        console.log(vehicleSplit);

        base.bindToState(`${vehicleString}`, {
            context: this,
            state: 'specs',
            asArray: false
        });

        this.setState({
            year: year,
            make: make,
            model: model,
            engine: engine,
            engineSizePeriod: engine.replace(',','.'),
            error: null,
            loading: null,
            showSpecs: true
        })
    };
    componentDidMount() {
        base.syncState(`previousVehicles`,{
            context: this,
            state: 'previousVehicles',
            asArray: true
        })
    };
    render() {
        function logChange(val) {
            console.log("Selected: " + val);
        }
        let availableMakes = [];
        let availableModels = [];
        let availableEngines = [];
        if (this.state.availableMakes) {
            this.state.availableMakes.map((val, key) => {
                availableMakes.push( { "value": val.key, "label": val.key } );
            });
        }
        if (this.state.availableModels) {
            this.state.availableModels.map((val, key) => {
                availableModels.push( { "value": val.key, "label": val.key } );
            });
        }
        if (this.state.availableEngines) {
            this.state.availableEngines.map((val, key) => {
                availableEngines.push( { "value": val.key, "label": val.key.replace(',', '.') } );
            });
        }
        let loadingStatus;
        if (this.state.loading) {
            loadingStatus =

;
        } else {
            loadingStatus = null;
        }

        let previousTen = this.state.previousVehicles.map((vehicle, key) => {
            const vehicleSplit = vehicle.split('/');
            const year = vehicleSplit[0];
            const make = vehicleSplit[1];
            const model = vehicleSplit[2];
            const engine = vehicleSplit[3].replace(',', '.');
            const vehicleString = `${year} ${make} ${model} ${engine} L`;
            return <HistoryVehicle data={vehicleString} link={vehicle} key={key} handleClick={this.searchVehicle.bind(this)} />;
        });

        return (

Previous Vehicles

                        {
                            previousTen
                        }

                        <form className="col-sm-4 offset-sm-4" onSubmit={this.submitVin}>

                                {this.state.error ?

                                                        Error! {this.state.error}

                                                    : null}

Enter VIN Number

                                <input className="form-control" type="text" ref="vinNumber" />

                                <button className="btn btn-primary" type="submit"> Submit</button>

                        </form>

                        <Select
                            name="form-field-year"
                            value={this.state.year}
                            options={options}
                            onChange={this.setYear}
                        />

                        <Select
                            name="form-field-make"
                            value={this.state.make}
                            options={availableMakes}
                            onChange={this.setMake}
                            isLoading={this.state.makesLoading}
                        />

                        <Select
                            name="form-field-model"
                            value={this.state.model}
                            options={availableModels}
                            onChange={this.setModel}
                            isLoading={this.state.modelsLoading}
                        />

                        <Select
                            name="form-field-engine"
                            value={this.state.engine}
                            options={availableEngines}
                            onChange={this.setEngine}
                            isLoading={this.state.enginesLoading}
                        />

                    {
                        this.state.showSpecs ? <Specifications make={this.state.make} model={this.state.model} year={this.state.year} engine={this.state.engineSizePeriod} data={this.state.specs} />
                                             : loadingStatus
                    }

        );
    }
}

export default Home;
<|endoftext|>


<commit_before>/**
 * Conversation View
 *
 * The class extends Y.View. It represents the view for a single conversation.
 */
Y.namespace('LIMS.View');

Y.LIMS.View.ConversationListView = Y.Base.create('conversationListView', Y.View, [], {

    // Specify an optional model to associate with the view.
    model: Y.LIMS.Model.MessageListModel,

    initializer: function () {
        // Init model
        this._initModel();
        // Attach events
        this._attachEvents();

        return this;
    },

    // Init model attached to the view
    _initModel: function () {
        var model = this.get('model');
        // Update the display when a new item is added to the list, or when the
        // entire list is reset.
        model.after('messageAdded', this._addMessage, this);
        model.after('messagesUpdated', this._renderMessagesList, this);

        // Load saved items from server or local storage
        model.load();
    },

    _attachEvents: function () {
        // Attach event to text field
        var messageTextField = this.get('messageTextField');
        if (messageTextField !== null) {
            messageTextField.on('keydown', this._onMessageTextFieldUpdated, this);
            messageTextField.on('focus', this._onMessageTextFieldUpdated, this);
        }
    },

    _addMessage: function (message) {

        // Vars
        var conversation, // Newly created conversation
            panelContentList = this.get('panelContentList'); // The place where are messages will be rendered to

        // Hide indicator if it wasn't already hidden
        this.get('activityIndicator').hide();

        // New conversation item
        conversation = new Y.LIMS.View.ConversationItemView({model: message});
        // Render it
        conversation.render();
        // Append to list
        panelContentList.append(conversation.get('container'));

        // Scroll to the last message
        this._scrollToBottom();
    },

    /**
     * Renders message list
     *
     * @param messageList
     * @private
     */
    _renderMessagesList: function (messageList) {

        // Vars
        var instance = this;

        // TODO: Clear the content of panel

        // Create view for each message
        messageList.each(function (message) {
            instance._addMessage(message, false);
        });
    },

    /**
     * Scrolls to the last message
     * @private
     */
    _scrollToBottom: function () {
        var panelContent = this.get('panelContent');
        setTimeout(function () {
            panelContent.set('scrollTop', panelContent.get('scrollHeight'));
        }, 1);
    },

    /**
     * Called whenever the message field is updated
     *
     * @param event
     * @private
     */
    _onMessageTextFieldUpdated: function (event) {
        var textField = this.get('messageTextField'),
            model = this.get('model'),
        // Get rid of new line characters
            value = textField.get('value').replace(/\n|\r/gim, '');

        // Send message on enter
        if (event.keyCode === 13 && !event.shiftKey && value.length) {
            event.preventDefault();
            // Empty text field
            textField.set('value', '');
            model.addMessage(new Y.LIMS.Model.MessageItemModel({body: value}));
        }
    }
}, {

    // Specify attributes and static properties for your View here.
    ATTRS: {
        // Override the default container attribute.
        container: {
            value: null
        },

        // Conversation model
        model: {
            value: null // default value
        },

        // Panel content container
        panelContent: {
            valueFn: function () {
                var container = this.get('container').one('.panel-content');
                if (container !== undefined) {
                    return container;
                }
            }
        },

        // List that hold messages
        panelContentList: {
            valueFn: function () {
                var container = this.get('container').one('.panel-content ul');
                if (container !== undefined) {
                    return container;
                }
            }
        },

        // Container for activity indicator
        activityIndicator: {
            valueFn: function () {
                var container = this.get('container').one('.preloader');
                if (container !== undefined) {
                    return container;
                }
            }
        },

        // Message text field container
        messageTextField: {
            valueFn: function () {
                var container = this.get('container').one('.panel-input textarea');
                if (container !== undefined) {
                    return container;
                }
            }
        }

    }

});

<commit_msg>issue with preloader visible on no messages fixed<commit_after>/**
 * Conversation View
 *
 * The class extends Y.View. It represents the view for a single conversation.
 */
Y.namespace('LIMS.View');

Y.LIMS.View.ConversationListView = Y.Base.create('conversationListView', Y.View, [], {

    // Specify an optional model to associate with the view.
    model: Y.LIMS.Model.MessageListModel,

    initializer: function () {
        // Init model
        this._initModel();
        // Attach events
        this._attachEvents();

        return this;
    },

    // Init model attached to the view
    _initModel: function () {
        var model = this.get('model');
        // Update the display when a new item is added to the list, or when the
        // entire list is reset.
        model.after('messageAdded', this._addMessage, this);
        model.after('messagesUpdated', this._renderMessagesList, this);

        // Load saved items from server or local storage
        model.load();
    },

    _attachEvents: function () {
        // Attach event to text field
        var messageTextField = this.get('messageTextField');
        if (messageTextField !== null) {
            messageTextField.on('keydown', this._onMessageTextFieldUpdated, this);
            messageTextField.on('focus', this._onMessageTextFieldUpdated, this);
        }
    },

    _addMessage: function (message) {

        // Vars
        var conversation, // Newly created conversation
            panelContentList = this.get('panelContentList'); // The place where are messages will be rendered to

        // New conversation item
        conversation = new Y.LIMS.View.ConversationItemView({model: message});
        // Render it
        conversation.render();
        // Append to list
        panelContentList.append(conversation.get('container'));

        // Scroll to the last message
        this._scrollToBottom();
    },

    /**
     * Renders message list
     *
     * @param messageList
     * @private
     */
    _renderMessagesList: function (messageList) {

        // Vars
        var instance = this;

        // Hide indicator if it wasn't already hidden
        this.get('activityIndicator').hide();

        // Create view for each message
        messageList.each(function (message) {
            instance._addMessage(message, false);
        });
    },

    /**
     * Scrolls to the last message
     * @private
     */
    _scrollToBottom: function () {
        var panelContent = this.get('panelContent');
        setTimeout(function () {
            panelContent.set('scrollTop', panelContent.get('scrollHeight'));
        }, 1);
    },

    /**
     * Called whenever the message field is updated
     *
     * @param event
     * @private
     */
    _onMessageTextFieldUpdated: function (event) {
        var textField = this.get('messageTextField'),
            model = this.get('model'),
        // Get rid of new line characters
            value = textField.get('value').replace(/\n|\r/gim, '');

        // Send message on enter
        if (event.keyCode === 13 && !event.shiftKey && value.length) {
            event.preventDefault();
            // Empty text field
            textField.set('value', '');
            model.addMessage(new Y.LIMS.Model.MessageItemModel({body: value}));
        }
    }
}, {

    // Specify attributes and static properties for your View here.
    ATTRS: {
        // Override the default container attribute.
        container: {
            value: null
        },

        // Conversation model
        model: {
            value: null // default value
        },

        // Panel content container
        panelContent: {
            valueFn: function () {
                var container = this.get('container').one('.panel-content');
                if (container !== undefined) {
                    return container;
                }
            }
        },

        // List that hold messages
        panelContentList: {
            valueFn: function () {
                var container = this.get('container').one('.panel-content ul');
                if (container !== undefined) {
                    return container;
                }
            }
        },

        // Container for activity indicator
        activityIndicator: {
            valueFn: function () {
                var container = this.get('container').one('.preloader');
                if (container !== undefined) {
                    return container;
                }
            }
        },

        // Message text field container
        messageTextField: {
            valueFn: function () {
                var container = this.get('container').one('.panel-input textarea');
                if (container !== undefined) {
                    return container;
                }
            }
        }

    }

});

<|endoftext|>


<commit_before>import React from 'react';

import ResultStore from '../stores/ResultStore.js';

function resultsForNamespace(ns) {
  const results = ResultStore.getResults(ns);
  const response = ResultStore.getResponse(ns);
  return {
    results: results ? results.toJS() : [],
    response: response ? response.toJS() : {},
    fuzzy: ResultStore.getFuzzy(ns),
    aggregates: ResultStore.getAggregates(ns),
  };
}

class ResultInjector extends React.Component {
  constructor(props) {
    super(props);
    this.resultsUpdated = this.resultsUpdated.bind(this);
  }

  componentDidMount() {
    ResultStore.addChangeListener(this.resultsUpdated);
  }

  componentWillUnmount() {
    ResultStore.removeChangeListener(this.resultsUpdated);
  }

  resultsUpdated() {
    const results = {};
    if (typeof this.props.namespace === 'string') {
      results[this.props.namespace] = resultsForNamespace(this.props.namespace);
    } else if (this.props.namespace instanceof Array) {
      this.props.namespace.forEach(ns => {
        results[ns] = resultsForNamespace(ns);
      });
    }
    this.setState({ results })
  }

  componentWillReceiveProps(nextProps) {
    // If the namespace is a string and is different to the last namespace, clear the stored results
    if (typeof nextProps.namespace === 'string' && nextProps.namespace !== this.props.namespace) {
      this.setState({ results: null })
    }
  }

  render() {
    const results = this.state.results ? this.state.results : null;
    const childrenWithProps = React.Children.map(this.props.children, c => (
      React.cloneElement(c, { results })
    ));
    return (

        {childrenWithProps}

    );
  }
}

ResultInjector.propTypes = {
  namespace: React.PropTypes.oneOfType([
    React.PropTypes.string,
    React.PropTypes.arrayOf(React.PropTypes.string),
  ]),
};

ResultInjector.defaultProps = {
  namespace: 'default',
};

export default ResultInjector;
<commit_msg>Fix bug in ResultInjector Constructor<commit_after>import React from 'react';

import ResultStore from '../stores/ResultStore.js';

function resultsForNamespace(ns) {
  const results = ResultStore.getResults(ns);
  const response = ResultStore.getResponse(ns);
  return {
    results: results ? results.toJS() : [],
    response: response ? response.toJS() : {},
    fuzzy: ResultStore.getFuzzy(ns),
    aggregates: ResultStore.getAggregates(ns),
  };
}

class ResultInjector extends React.Component {
  constructor(props) {
    super(props);
    this.state = { results: null }
    this.resultsUpdated = this.resultsUpdated.bind(this);
  }

  componentDidMount() {
    ResultStore.addChangeListener(this.resultsUpdated);
  }

  componentWillUnmount() {
    ResultStore.removeChangeListener(this.resultsUpdated);
  }

  resultsUpdated() {
    const results = {};
    if (typeof this.props.namespace === 'string') {
      results[this.props.namespace] = resultsForNamespace(this.props.namespace);
    } else if (this.props.namespace instanceof Array) {
      this.props.namespace.forEach(ns => {
        results[ns] = resultsForNamespace(ns);
      });
    }
    this.setState({ results })
  }

  componentWillReceiveProps(nextProps) {
    // If the namespace is a string and is different to the last namespace, clear the stored results
    if (typeof nextProps.namespace === 'string' && nextProps.namespace !== this.props.namespace) {
      this.setState({ results: null })
    }
  }

  render() {
    const results = this.state.results ? this.state.results : null;
    const childrenWithProps = React.Children.map(this.props.children, c => (
      React.cloneElement(c, { results })
    ));
    return (

        {childrenWithProps}

    );
  }
}

ResultInjector.propTypes = {
  namespace: React.PropTypes.oneOfType([
    React.PropTypes.string,
    React.PropTypes.arrayOf(React.PropTypes.string),
  ]),
};

ResultInjector.defaultProps = {
  namespace: 'default',
};

export default ResultInjector;
<|endoftext|>


<commit_before>var Chats = {
    startX: 0,

    refresh: function() {
        var list = document.querySelector('#chats_widget_list');
        list.innerHTML = list.innerHTML.trim();

        var items = document.querySelectorAll('ul#chats_widget_list li:not(.subheader)');
        var i = 0;

        while(i < items.length)
        {
            if (items[i].dataset.jid != null) {
                items[i].onclick = function(e) {
                    Rooms.refresh();

                    Chat_ajaxGet(this.dataset.jid);

                    items.forEach(item => item.classList.remove('active'));
                    this.classList.add('active');
                };

                items[i].onmousedown = function(e) {
                    if (e.which == 2) {
                        Chats_ajaxClose(this.dataset.jid, (MovimUtils.urlParts().params[0] === this.dataset.jid));
                        e.preventDefault();
                    }
                }

                items[i].addEventListener('touchstart', function(event) {
                    Chats.startX = event.targetTouches[0].pageX;
                }, true);

                items[i].addEventListener('touchmove', function(event) {
                    move = Math.abs(parseInt(event.targetTouches[0].pageX - Chats.startX));

                    if (move > this.offsetWidth/2) {
                        this.classList.add('close');
                    }

                    this.style.transform = 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '
                        + parseInt(event.targetTouches[0].pageX - Chats.startX)
                        +', 0, 0, 1)';
                }, true);

                items[i].addEventListener('touchend', function(event) {
                    move = Math.abs(parseInt(event.changedTouches[0].pageX - Chats.startX));

                    if (move > this.offsetWidth/2) {
                        this.style.display = 'none';
                        Chats_ajaxClose(this.dataset.jid, (MovimUtils.urlParts().params[0] === this.dataset.jid));
                    }

                    this.style.transform = '';
                    this.classList.remove('close');
                    Chats.startX = 0;
                }, true);
            }

            items[i].classList.remove('active');
            i++;
        }

        Notification_ajaxGet();
    },
    prepend: function(from, html) {
        MovimTpl.remove('#' + MovimUtils.cleanupId(from + '_chat_item'));
        MovimTpl.prepend('#chats_widget_list', html);
        Chats.refresh();
        Notification_ajaxGet();
    }
};

MovimWebsocket.attach(function() {
    Chats_ajaxGet();
});
<commit_msg>Last CSS fix for slide-to-close event<commit_after>var Chats = {
    startX: 0,

    refresh: function() {
        var list = document.querySelector('#chats_widget_list');
        list.innerHTML = list.innerHTML.trim();

        var items = document.querySelectorAll('ul#chats_widget_list li:not(.subheader)');
        var i = 0;

        while(i < items.length)
        {
            if (items[i].dataset.jid != null) {
                items[i].onclick = function(e) {
                    Rooms.refresh();

                    Chat_ajaxGet(this.dataset.jid);

                    items.forEach(item => item.classList.remove('active'));
                    this.classList.add('active');
                };

                items[i].onmousedown = function(e) {
                    if (e.which == 2) {
                        Chats_ajaxClose(this.dataset.jid, (MovimUtils.urlParts().params[0] === this.dataset.jid));
                        e.preventDefault();
                    }
                }

                items[i].addEventListener('touchstart', function(event) {
                    Chats.startX = event.targetTouches[0].pageX;
                }, true);

                items[i].addEventListener('touchmove', function(event) {
                    move = Math.abs(parseInt(event.targetTouches[0].pageX - Chats.startX));

                    if (move > this.offsetWidth/2) {
                        this.classList.add('close');
                    } else {
                        this.classList.remove('close');
                    }

                    this.style.transform = 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '
                        + parseInt(event.targetTouches[0].pageX - Chats.startX)
                        +', 0, 0, 1)';
                }, true);

                items[i].addEventListener('touchend', function(event) {
                    move = Math.abs(parseInt(event.changedTouches[0].pageX - Chats.startX));

                    if (move > this.offsetWidth/2) {
                        this.style.display = 'none';
                        Chats_ajaxClose(this.dataset.jid, (MovimUtils.urlParts().params[0] === this.dataset.jid));
                    }

                    this.style.transform = '';
                    this.classList.remove('close');
                    Chats.startX = 0;
                }, true);
            }

            items[i].classList.remove('active');
            i++;
        }

        Notification_ajaxGet();
    },
    prepend: function(from, html) {
        MovimTpl.remove('#' + MovimUtils.cleanupId(from + '_chat_item'));
        MovimTpl.prepend('#chats_widget_list', html);
        Chats.refresh();
        Notification_ajaxGet();
    }
};

MovimWebsocket.attach(function() {
    Chats_ajaxGet();
});
<|endoftext|>