<commit_before>import { on, off } from 'utils/mixins';
import { bindAll } from 'underscore';

export default class Droppable {
  constructor(em) {
    this.em = em;
    const el = em
      .get('DomComponents')
      .getWrapper()
      .getEl();
    this.el = el;
    this.counter = 0;
    bindAll(
      this,
      'handleDragEnter',
      'handleDragOver',
      'handleDrop',
      'handleDragLeave'
    );
    on(el, 'dragenter', this.handleDragEnter);
    on(el, 'dragover', this.handleDragOver);
    on(el, 'drop', this.handleDrop);
    on(el, 'dragleave', this.handleDragLeave);

    return this;
  }

  endDrop(cancel) {
    this.counter = 0;
    this.over = 0;
    console.log('DROP END');
    // force out like in BlockView
    const sorter = this.sorter;
    cancel && (sorter.moved = 0);
    this.em.set('dragContent', '');
    sorter.endMove();
  }

  handleDragLeave(ev) {
    this.updateCounter(-1);
  }

  updateCounter(value) {
    this.counter += value;
    if (this.counter === 0) {
      this.endDrop(1);
    }
  }

  handleDragEnter(ev) {
    const em = this.em;
    this.updateCounter(1);
    if (this.over) return;
    this.over = 1;
    console.log('IM IN');

    const utils = em.get('Utils');
    const canvas = em.get('Canvas');
    this.sorter = new utils.Sorter({
      em,
      wmargin: 1,
      nested: 1,
      canvasRelative: 1,
      direction: 'a',
      container: canvas.getBody(),
      placer: canvas.getPlacerEl(),
      eventMoving: 'mousemove dragover',
      containerSel: '*',
      itemSel: '*',
      pfx: 'gjs-',
      onStart: () => em.stopDefault(),
      onEndMove: () => em.runDefault(),
      document: canvas.getFrameEl().contentDocument
    });
    const content = this.getContentByData(ev.dataTransfer) || '
';
    this.sorter.setDropContent(content); // should not be empty
    this.sorter.startSort(this.el);
  }

  /**
   * Always need to have this handler active for enabling the drop
   * @param {Event} ev
   */
  handleDragOver(ev) {
    ev.preventDefault();
  }

  handleDrop(ev) {
    ev.preventDefault();
    var content = this.getContentByData(ev.dataTransfer);
    ev.target.style.border = '';
    if (content) {
      this.sorter.setDropContent(content);
    } else {
      this.sorter.moved = 0;
    }
    this.endDrop();
  }

  getContentByData(dataTransfer) {
    let result = dataTransfer.getData('text');
    let dragContent = this.em.get('dragContent');
    const types = dataTransfer.types;
    const files = dataTransfer.files;
    console.log('Files', files);

    const items = dataTransfer.items;
    for (var i = 0; i < items.length; i++) console.log('DataType', items[i]);

    if (files.length) {
      result = [];
      for (let i = 0; i < files.length; i++) {
        const file = files[i];
        result.push({
          type: 'image',
          attributes: { alt: file.name }
        });
      }
      const fu = this.em.get('AssetManager').FileUploader();
      fu.uploadFile({ dataTransfer }, res => console.log('RES upload', res));
    } else if (types.indexOf('text/html') >= 0) {
      result = dataTransfer.getData('text/html').replace(/<\/?meta[^>]*>/g, '');
    } else if (types.indexOf('text/uri-list') >= 0) {
      result = {
        type: 'link',
        attributes: { href: result },
        content: result
      };
    } else if (dragContent) {
      result = dragContent;
    } else {
      result = result && `<div>${result}</div>`;
    }

    //this.uploadFile(e);
    console.log('CONTENT', result);
    // TODO result = clbContent(result);
    return result;
  }
}
<commit_msg>Update Droppable events<commit_after>/*
  This class makes the canvas droppable
 */

import { on } from 'utils/mixins';
import { bindAll } from 'underscore';

export default class Droppable {
  constructor(em) {
    this.em = em;
    const el = em
      .get('DomComponents')
      .getWrapper()
      .getEl();
    this.el = el;
    this.counter = 0;
    bindAll(
      this,
      'handleDragEnter',
      'handleDragOver',
      'handleDrop',
      'handleDragLeave'
    );
    on(el, 'dragenter', this.handleDragEnter);
    on(el, 'dragover', this.handleDragOver);
    on(el, 'drop', this.handleDrop);
    on(el, 'dragleave', this.handleDragLeave);

    return this;
  }

  endDrop(cancel, ev) {
    const em = this.em;
    this.counter = 0;
    this.over = 0;
    // force out like in BlockView
    const sorter = this.sorter;
    cancel && (sorter.moved = 0);
    em.set('dragContent', '');
    sorter.endMove();
    em.trigger('canvas:dragend', ev);
  }

  handleDragLeave(ev) {
    this.updateCounter(-1, ev);
  }

  updateCounter(value, ev) {
    this.counter += value;
    this.counter === 0 && this.endDrop(1, ev);
  }

  handleDragEnter(ev) {
    const em = this.em;
    const dt = ev.dataTransfer;
    this.updateCounter(1, ev);
    if (this.over) return;
    this.over = 1;
    const utils = em.get('Utils');
    const canvas = em.get('Canvas');
    this.sorter = new utils.Sorter({
      em,
      wmargin: 1,
      nested: 1,
      canvasRelative: 1,
      direction: 'a',
      container: canvas.getBody(),
      placer: canvas.getPlacerEl(),
      eventMoving: 'mousemove dragover',
      containerSel: '*',
      itemSel: '*',
      pfx: 'gjs-',
      onStart: () => em.stopDefault(),
      onEndMove: () => em.runDefault(),
      document: canvas.getFrameEl().contentDocument
    });
    const content = this.getContentByData(dt).content || '
';
    this.sorter.setDropContent(content); // should not be empty
    this.sorter.startSort(this.el);
    em.trigger('canvas:dragenter', dt, content);
  }

  /**
   * Always need to have this handler active for enabling the drop
   * @param {Event} ev
   */
  handleDragOver(ev) {
    ev.preventDefault();
    this.em.trigger('canvas:dragover', ev);
  }

  handleDrop(ev) {
    ev.preventDefault();
    const dt = ev.dataTransfer;
    const content = this.getContentByData(dt).content;
    ev.target.style.border = '';

    if (content) {
      this.sorter.setDropContent(content);
    } else {
      this.sorter.moved = 0;
    }

    this.endDrop(0, ev);
    this.em.trigger('canvas:drop', dt, content);
  }

  getContentByData(dataTransfer) {
    const em = this.em;
    const types = dataTransfer.types;
    const files = dataTransfer.files;
    const dragContent = em.get('dragContent'); // Used by blocks
    let content = dataTransfer.getData('text');

    if (files.length) {
      content = [];
      for (let i = 0; i < files.length; i++) {
        const file = files[i];
        content.push({
          type: 'image',
          attributes: { alt: file.name }
        });
      }
      const fu = em.get('AssetManager').FileUploader();
      fu.uploadFile({ dataTransfer }, res => console.log('RES upload', res));
    } else if (types.indexOf('text/html') >= 0) {
      content = dataTransfer
        .getData('text/html')
        .replace(/<\/?meta[^>]*>/g, '');
    } else if (types.indexOf('text/uri-list') >= 0) {
      content = {
        type: 'link',
        attributes: { href: content },
        content: content
      };
    } else if (dragContent) {
      content = dragContent;
    } else {
      content = content && `<div>${content}</div>`;
    }

    const result = { content, dragContent };
    em.trigger('canvas:dragdata', dataTransfer, result);

    return result;
  }
}
<|endoftext|>


<commit_before>/**
 * A module for http calls (similar to jquery.http
 * @export http
 * @desc This is my desc
 */
define('http', ['extend'], function (extend) {

    var serialize = function (obj) {
        var str = [];
        for (var p in obj)
            if (obj.hasOwnProperty(p)) {
                str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
            }
        return str.join("&");
    };

    var win = window,
        CORSxhr = (function () {
            var xhr;

            if (win.XMLHttpRequest && ('withCredentials' in new win.XMLHttpRequest())) {
                xhr = win.XMLHttpRequest;

            } else if (win.XDomainRequest) {
                xhr = win.XDomainRequest;
            }

            return xhr;
        }()),
        methods = ['head', 'get', 'post', 'put', 'delete'],
        i,
        methodsLength = methods.length,
        result = {};

    /**
     * @param options {object}
     * @constructor
     * @alias http
     */
    function Request(options) {
        this.init(options);
    }

    function getRequestResult(that) {
        var headers = parseResponseHeaders(that.xhr.getAllResponseHeaders());
        var response = that.xhr.responseText.trim();
        var start;
        var end;
        if (response) {
            start = response[0];
            end = response[response.length - 1];
        }
        if (response && (start === '{' && end === '}') || (start === '[' && end === ']')) {
            response = response ? JSON.parse(response.replace(/\/\*.*?\*\//g, '')) : response;
        }
        return {
            data: response,
            request: {
                method: that.method,
                url: that.url,
                data: that.data,
                headers: that.headers
            },
            headers: headers,
            status: this.status
        };
    }

    Request.prototype.init = function (options) {
        var that = this;

        that.xhr = new CORSxhr();
        that.method = options.method;
        that.url = options.url;
        that.success = options.success;
        that.error = options.error;
        that.data = options.data;
        that.headers = options.headers;
        that.timeout = options.timeout;
        that.ontimeout = options.ontimeout;
        that.async = options.async === undefined ? true : options.async;

        if (options.credentials === true) {
            that.xhr.withCredentials = true;
        }

        that.send();

        return that;
    };

    Request.prototype.send = function () {
        var that = this;

        // serialize data if GET
        if (that.method === 'GET' && that.data) {
            var concat = that.url.indexOf('?') > -1 ? '&' : '?';
            that.url += concat + serialize(that.data);
        } else {
            that.data = JSON.stringify(that.data);
        }

        // Success callback
        if (that.success !== undefined) {
            that.xhr.onload = function () {
                var result = getRequestResult.call(that.xhr, that),
                    self = this;
                function onLoad() {
                    if (that.xhr.status >= 200 && that.xhr.status < 400) {
                        that.success.call(self, result);
                    } else if (that.error !== undefined) {
                        that.error.call(self, result);
                    }
                }
                if (this.onloadInterceptor) {
                    this.onloadInterceptor(onLoad, result);
                } else {
                    onLoad();
                }
            };
        }

        // Timeout
        if(that.timeout) {
            that.xhr.timeout = that.timeout;
            that.xhr.ontimeout = function() {
                    var result = getRequestResult.call(that.xhr, that);
                    if(that.ontimeout) {
                        that.ontimeout.call(this, result);
                    } else if(that.error) {
                        that.error.call(this, result);
                    }
                };
        }

        // Error callback
        if (that.error !== undefined) {
            that.xhr.onerror = function () {
                var result = getRequestResult.call(that.xhr, that);
                that.error.call(this, result);
            };
        }

        that.xhr.open(that.method, that.url, that.async);

        if (that.headers !== undefined) {
            that.setHeaders();
        }

        // Send
        that.xhr.send(that.data);

        return that;
    };

    Request.prototype.setHeaders = function () {
        var that = this,
            headers = that.headers,
            key;

        for (key in headers) {
            if (headers.hasOwnProperty(key)) {
                that.xhr.setRequestHeader(key, headers[key]);
            }
        }

        return that;
    };

    function parseResponseHeaders(str) {
        var list = str.split("\n");
        var headers = {};
        var parts;
        var i = 0, len = list.length;
        while (i < len) {
            parts = list[i].split(': ');
            if (parts[0] && parts[1]) {
                parts[0] = parts[0].split('-').join('').split('');
                parts[0][0] = parts[0][0].toLowerCase();
                headers[parts[0].join('')] = parts[1];
            }
            i += 1;
        }
        return headers;
    }

    function addDefaults(options, defaults) {
        return extend(options, defaults);
    }

    function handleInterceptor(options) {
        return !!(result.intercept && result.intercept(options, Request));
    }

    /**
     * Public Methods
     */
    for (i = 0; i < methodsLength; i += 1) {
        /* jshint ignore:start */
        (function () {
            var method = methods[i];
            result[method] = function (url, success, error) {
                var options = {};

                if (url === undefined) {
                    throw new Error('CORS: url must be defined');
                }

                if (typeof url === 'object') {
                    options = url;
                } else {
                    if (typeof success === 'function') {
                        options.success = success;
                    }
                    if (typeof error === 'function') {
                        options.error = error;
                    }

                    options.url = url;
                }

                options.method = method.toUpperCase();
                addDefaults(options, result.defaults);
                if (handleInterceptor(options)) {
                    return;
                }
                return new Request(options).xhr;
            };
        }());
        /* jshint ignore:end */
    }

    result.intercept = null; // to show where to assign interceptor handlers.
    result.defaults = {
        headers: {}
    };

    return result;

});<commit_msg>recursive encoding of get params.<commit_after>/**
 * A module for http calls (similar to jquery.http
 * @export http
 * @desc This is my desc
 */
define('http', ['extend'], function (extend) {

    var serialize = function(obj, prefix) {
        var str = [], p;
        for(p in obj) {
            if (obj.hasOwnProperty(p)) {
                var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
                str.push((v !== null && typeof v === "object") ?
                    serialize(v, k) :
                    encodeURIComponent(k) + "=" + encodeURIComponent(v));
            }
        }
        return str.join("&");
    };

    var win = window,
        CORSxhr = (function () {
            var xhr;

            if (win.XMLHttpRequest && ('withCredentials' in new win.XMLHttpRequest())) {
                xhr = win.XMLHttpRequest;

            } else if (win.XDomainRequest) {
                xhr = win.XDomainRequest;
            }

            return xhr;
        }()),
        methods = ['head', 'get', 'post', 'put', 'delete'],
        i,
        methodsLength = methods.length,
        result = {serialize:serialize};

    /**
     * @param options {object}
     * @constructor
     * @alias http
     */
    function Request(options) {
        this.init(options);
    }

    function getRequestResult(that) {
        var headers = parseResponseHeaders(that.xhr.getAllResponseHeaders());
        var response = that.xhr.responseText.trim();
        var start;
        var end;
        if (response) {
            start = response[0];
            end = response[response.length - 1];
        }
        if (response && (start === '{' && end === '}') || (start === '[' && end === ']')) {
            response = response ? JSON.parse(response.replace(/\/\*.*?\*\//g, '')) : response;
        }
        return {
            data: response,
            request: {
                method: that.method,
                url: that.url,
                data: that.data,
                headers: that.headers
            },
            headers: headers,
            status: this.status
        };
    }

    Request.prototype.init = function (options) {
        var that = this;

        that.xhr = new CORSxhr();
        that.method = options.method;
        that.url = options.url;
        that.success = options.success;
        that.error = options.error;
        that.data = options.data;
        that.headers = options.headers;
        that.timeout = options.timeout;
        that.ontimeout = options.ontimeout;
        that.async = options.async === undefined ? true : options.async;

        if (options.credentials === true) {
            that.xhr.withCredentials = true;
        }

        that.send();

        return that;
    };

    Request.prototype.send = function () {
        var that = this;

        // serialize data if GET
        if (that.method === 'GET' && that.data) {
            var concat = that.url.indexOf('?') > -1 ? '&' : '?';
            that.url += concat + serialize(that.data);
        } else {
            that.data = JSON.stringify(that.data);
        }

        // Success callback
        if (that.success !== undefined) {
            that.xhr.onload = function () {
                var result = getRequestResult.call(that.xhr, that),
                    self = this;
                function onLoad() {
                    if (that.xhr.status >= 200 && that.xhr.status < 400) {
                        that.success.call(self, result);
                    } else if (that.error !== undefined) {
                        that.error.call(self, result);
                    }
                }
                if (this.onloadInterceptor) {
                    this.onloadInterceptor(onLoad, result);
                } else {
                    onLoad();
                }
            };
        }

        // Timeout
        if(that.timeout) {
            that.xhr.timeout = that.timeout;
            that.xhr.ontimeout = function() {
                    var result = getRequestResult.call(that.xhr, that);
                    if(that.ontimeout) {
                        that.ontimeout.call(this, result);
                    } else if(that.error) {
                        that.error.call(this, result);
                    }
                };
        }

        // Error callback
        if (that.error !== undefined) {
            that.xhr.onerror = function () {
                var result = getRequestResult.call(that.xhr, that);
                that.error.call(this, result);
            };
        }

        that.xhr.open(that.method, that.url, that.async);

        if (that.headers !== undefined) {
            that.setHeaders();
        }

        // Send
        that.xhr.send(that.data);

        return that;
    };

    Request.prototype.setHeaders = function () {
        var that = this,
            headers = that.headers,
            key;

        for (key in headers) {
            if (headers.hasOwnProperty(key)) {
                that.xhr.setRequestHeader(key, headers[key]);
            }
        }

        return that;
    };

    function parseResponseHeaders(str) {
        var list = str.split("\n");
        var headers = {};
        var parts;
        var i = 0, len = list.length;
        while (i < len) {
            parts = list[i].split(': ');
            if (parts[0] && parts[1]) {
                parts[0] = parts[0].split('-').join('').split('');
                parts[0][0] = parts[0][0].toLowerCase();
                headers[parts[0].join('')] = parts[1];
            }
            i += 1;
        }
        return headers;
    }

    function addDefaults(options, defaults) {
        return extend(options, defaults);
    }

    function handleInterceptor(options) {
        return !!(result.intercept && result.intercept(options, Request));
    }

    /**
     * Public Methods
     */
    for (i = 0; i < methodsLength; i += 1) {
        /* jshint ignore:start */
        (function () {
            var method = methods[i];
            result[method] = function (url, success, error) {
                var options = {};

                if (url === undefined) {
                    throw new Error('CORS: url must be defined');
                }

                if (typeof url === 'object') {
                    options = url;
                } else {
                    if (typeof success === 'function') {
                        options.success = success;
                    }
                    if (typeof error === 'function') {
                        options.error = error;
                    }

                    options.url = url;
                }

                options.method = method.toUpperCase();
                addDefaults(options, result.defaults);
                if (handleInterceptor(options)) {
                    return;
                }
                return new Request(options).xhr;
            };
        }());
        /* jshint ignore:end */
    }

    result.intercept = null; // to show where to assign interceptor handlers.
    result.defaults = {
        headers: {}
    };

    return result;

});<|endoftext|>


<commit_before>import React from 'react'
import 'styles/core.scss'
import Firebase from 'firebase'
import { connect } from 'react-redux'
import constants from 'utils/constants'
import { actions as quoteActions } from '../redux/modules/quote'
import {reduxForm} from 'redux-form'

const ref = new Firebase(constants.FIREBASE)
const quotesRef = ref.child('quotes')
export const fields = ['title', 'description', 'author', 'tags', 'category', 'image']

const mapStateToProps = (state, props) => ({
  auth: state.auth,
  quote: props.route.name === 'edit' ? state.quote : ''
})

export class QuotesNew extends React.Component {

  static propTypes = {
    auth: React.PropTypes.object,
    fields: React.PropTypes.object.isRequired,
    handleSubmit: React.PropTypes.func.isRequired,
    resetForm: React.PropTypes.func.isRequired,
    submitting: React.PropTypes.bool.isRequired,
    getQuote: React.PropTypes.func,
    route: React.PropTypes.object,
    statename: React.PropTypes.object,
    clearQuote: React.PropTypes.func,
    params: React.PropTypes.object
  }

  componentDidMount (state) {
    if (this.props.route.name === 'edit') {
      this.props.getQuote(this.props.params.id)
    }
  }

  handleFile (fieldName, e) {
    console.log(e)
    e.preventDefault()
    console.log(fieldName)
    //let fields = this.props.fields
    // convert files to an array
    //const files = [ ...e.target.files ];
    //fields[fieldName].handleChange(files);

  }

  handleSubmit (e) {
    e.preventDefault()

    let fields = this.props.fields
    let userId = this.props.auth.uid
    let image = _.first(fields.image.value)
    let imageBase64
    let fr = new FileReader()
    let quote

    fr.onloadend = function (res) {
      console.log(res)
      imageBase64 = res.currentTarget.result

      quote = {
        title: fields.title ? fields.title.value : '',
        description: fields.description ? fields.description.value : '',
        author: fields.author ? fields.author.value : '',
        category: fields.category ? fields.category.value : '',
        createdBy: userId,
        createdAt: new Date(),
        tags: fields.tags ? fields.tags.value : [],
        image: fields.image ? imageBase64 : ''
      }

      if (this.props.route.name === 'new') {
        quotesRef.push(quote)
      } else {
        let quoteId = this.props.params.id
        let currentQuote = ref.child('quotes/'+quoteId)

        currentQuote.update(quote)

      }

    }.bind(this)
    fr.readAsDataURL(image)

  }

  updateQuote (e) {
    let currentQuote = quotesRef.child(this.props.params.id)
    console.log(currentQuote)
  }

  render () {
    const {
      fields: {title, description, author, tags, category, image},
      resetForm,
      submitting
    } = this.props

    let header = this.props.route.name === 'edit' ? 'Edit quote' : 'New Quote'
    let btnLabel = this.props.route.name === 'edit' ? 'Update the quote' : 'Create new quote'
    // console.log(this.props.fields.description)
    console.log(this.props.fields)
    // const { fields: { image } } = this.props;
    // pull out value so it isn't passed into the file input
    let { value, ...imageProps } = image;

    return (

        <form onSubmit={this.handleSubmit.bind(this)}>

{header}

            Title
            <input type='text' className='form-control' id='title' placeholder='Title (optional)' ref='title' {...title} />

            Description
            <textarea className='form-control' rows='4' id='description' ref='description' placeholder='text or descriptions' {...description} />

            Author
            <input type='text' className='form-control' id='author' placeholder='author' ref='author' {...author} />

            Category
            <input type='text' className='form-control' id='category' placeholder='category (quote, joke, etc)' ref='category' {...category} />

            Tags
            <input type='text' className='form-control' id='tags' placeholder='tags (comma separated)' ref='tags' {...tags} />

            Background
            <input type='file' className='form-control' id='image' onChange={this.handleFile.bind(this, 'image')} placeholder='background image' ref='image' {...image} value={null} />

          <input type='submit' value={btnLabel} className='btn btn-primary' />
          <input type='button' value='Reset' className='btn btn-danger' onClick={resetForm} />
        </form>

    )
  }
}

QuotesNew = reduxForm({
  form: 'newQuote',
  fields,
  normalize: ['tags']
},
function (state, props) {
  if (props.route.name === 'edit') {
    return {initialValues: state.quote}
  }
}
)(QuotesNew)

export default connect(mapStateToProps, quoteActions)(QuotesNew)
<commit_msg>refactor (form now better handles quote with or without image)<commit_after>import React from 'react'
import 'styles/core.scss'
import Firebase from 'firebase'
import { connect } from 'react-redux'
import constants from 'utils/constants'
import { actions as quoteActions } from '../redux/modules/quote'
import {reduxForm} from 'redux-form'

const ref = new Firebase(constants.FIREBASE)
const quotesRef = ref.child('quotes')
export const fields = ['title', 'description', 'author', 'tags', 'category', 'image']

const mapStateToProps = (state, props) => ({
  auth: state.auth,
  quote: props.route.name === 'edit' ? state.quote : ''
})

export class QuotesNew extends React.Component {

  static propTypes = {
    auth: React.PropTypes.object,
    fields: React.PropTypes.object.isRequired,
    handleSubmit: React.PropTypes.func.isRequired,
    resetForm: React.PropTypes.func.isRequired,
    submitting: React.PropTypes.bool.isRequired,
    getQuote: React.PropTypes.func,
    route: React.PropTypes.object,
    statename: React.PropTypes.object,
    clearQuote: React.PropTypes.func,
    params: React.PropTypes.object
  }

  componentDidMount (state) {
    if (this.props.route.name === 'edit') {
      this.props.getQuote(this.props.params.id)
    }
  }

  handleFile (fieldName, e) {
    console.log(e)
    e.preventDefault()
    console.log(fieldName)
    //let fields = this.props.fields
    // convert files to an array
    //const files = [ ...e.target.files ];
    //fields[fieldName].handleChange(files);

  }

  handleSubmit (e) {
    e.preventDefault()

    let fields = this.props.fields
    let userId = this.props.auth.uid
    let image = _.first(fields.image.value)
    let imageBase64
    let fr = new FileReader()
    let quote = {
      title: fields.title ? fields.title.value : '',
      description: fields.description ? fields.description.value : '',
      author: fields.author ? fields.author.value : '',
      category: fields.category ? fields.category.value : '',
      createdBy: userId,
      createdAt: new Date(),
      tags: fields.tags ? fields.tags.value : []
    }

    let pushToFirebase = function() {
      if (this.props.route.name === 'new') {
        quotesRef.push(quote)
      } else {
        let quoteId = this.props.params.id
        let currentQuote = ref.child('quotes/'+quoteId)
        currentQuote.update(quote)
      }
    }.bind(this)

    if(image) {
      fr.onloadend = function (res) {
        imageBase64 = res.currentTarget.result
        quote.image = imageBase64
        pushToFirebase()
      }.bind(this)

      fr.readAsDataURL(image)
    } else {
      pushToFirebase()
    }

  }

  updateQuote (e) {
    let currentQuote = quotesRef.child(this.props.params.id)
    console.log(currentQuote)
  }

  render () {
    const {
      fields: {title, description, author, tags, category, image},
      resetForm,
      submitting
    } = this.props

    let header = this.props.route.name === 'edit' ? 'Edit quote' : 'New Quote'
    let btnLabel = this.props.route.name === 'edit' ? 'Update the quote' : 'Create new quote'
    // console.log(this.props.fields.description)
    console.log(this.props.fields)
    // const { fields: { image } } = this.props;
    // pull out value so it isn't passed into the file input
    let { value, ...imageProps } = image

    return (

        <form onSubmit={this.handleSubmit.bind(this)}>

{header}

            Title
            <input type='text' className='form-control' id='title' placeholder='Title (optional)' ref='title' {...title} />

            Description
            <textarea className='form-control' rows='4' id='description' ref='description' placeholder='text or descriptions' {...description} />

            Author
            <input type='text' className='form-control' id='author' placeholder='author' ref='author' {...author} />

            Category
            <input type='text' className='form-control' id='category' placeholder='category (quote, joke, etc)' ref='category' {...category} />

            Tags
            <input type='text' className='form-control' id='tags' placeholder='tags (comma separated)' ref='tags' {...tags} />

            Background
            <input type='file' className='form-control' id='image' onChange={this.handleFile.bind(this, 'image')} placeholder='background image' ref='image' {...image} value={null} />

          <input type='submit' value={btnLabel} className='btn btn-primary' />
          <input type='button' value='Reset' className='btn btn-danger' onClick={resetForm} />
        </form>

    )
  }
}

QuotesNew = reduxForm({
  form: 'newQuote',
  fields,
  normalize: ['tags']
},
function (state, props) {
  if (props.route.name === 'edit') {
    return {initialValues: state.quote}
  }
}
)(QuotesNew)

export default connect(mapStateToProps, quoteActions)(QuotesNew)
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

/* More information about these options at jshint.com/docs/options */

/* exported setUpFullScreen, fullScreenElement, isFullScreen,
   requestTurnServers, sendAsyncUrlRequest, sendSyncUrlRequest, randomString, $,
   queryStringToDictionary */
/* globals chrome */

'use strict';

function $(selector) {
  return document.querySelector(selector);
}

// Returns the URL query key-value pairs as a dictionary object.
function queryStringToDictionary(queryString) {
  var pairs = queryString.slice(1).split('&');

  var result = {};
  pairs.forEach(function(pair) {
    if (pair) {
      pair = pair.split('=');
      if (pair[0]) {
        result[pair[0]] = decodeURIComponent(pair[1] || '');
      }
    }
  });
  return result;
}

// Sends the URL request and returns a Promise as the result.
function sendAsyncUrlRequest(method, url, body) {
  return sendUrlRequest(method, url, true, body);
}

// If async is true, returns a Promise and executes the xhr request
// async. If async is false, the xhr will be executed sync and a
// resolved promise is returned.
function sendUrlRequest(method, url, async, body) {
  return new Promise(function(resolve, reject) {
    var xhr;
    var reportResults = function() {
      if (xhr.status !== 200) {
        reject(
            Error('Status=' + xhr.status + ', response=' +
                  xhr.responseText));
        return;
      }
      resolve(xhr.responseText);
    };

    xhr = new XMLHttpRequest();
    if (async) {
      xhr.onreadystatechange = function() {
        if (xhr.readyState !== 4) {
          return;
        }
        reportResults();
      };
    }
    xhr.open(method, url, async);
    xhr.send(body);

    if (!async) {
      reportResults();
    }
  });
}

// Returns a list of turn servers after requesting it from CEOD.
function requestTurnServers(turnRequestUrl, turnTransports) {
  return new Promise(function(resolve, reject) {
    // Chrome apps don't send origin header for GET requests, but
    // do send it for POST requests. Origin header is required for
    // access to turn request url.
    var method = isChromeApp() ? 'POST' : 'GET';
    sendAsyncUrlRequest(method, turnRequestUrl).then(function(response) {
      var turnServerResponse = parseJSON(response);
      if (!turnServerResponse) {
        reject(Error('Error parsing response JSON: ' + response));
        return;
      }
      // Filter the TURN URLs to only use the desired transport, if specified.
      if (turnTransports.length > 0) {
        filterTurnUrls(turnServerResponse.uris, turnTransports);
      }

      // Create the RTCIceServer objects from the response.
      var turnServers = createIceServers(turnServerResponse.uris,
          turnServerResponse.username, turnServerResponse.password);
      if (!turnServers) {
        reject(Error('Error creating ICE servers from response.'));
        return;
      }
      trace('Retrieved TURN server information.');
      resolve(turnServers);
    }).catch(function(error) {
      reject(Error('TURN server request error: ' + error.message));
      return;
    });
  });
}

// Parse the supplied JSON, or return null if parsing fails.
function parseJSON(json) {
  try {
    return JSON.parse(json);
  } catch (e) {
    trace('Error parsing json: ' + json);
  }
  return null;
}

// Filter a list of TURN urls to only contain those with transport=|protocol|.
function filterTurnUrls(urls, protocol) {
  for (var i = 0; i < urls.length;) {
    var parts = urls[i].split('?');
    if (parts.length > 1 && parts[1] !== ('transport=' + protocol)) {
      urls.splice(i, 1);
    } else {
      ++i;
    }
  }
}

// Start shims for fullscreen
function setUpFullScreen() {
  if (isChromeApp()) {
    document.cancelFullScreen = function() {
      chrome.app.window.current().restore();
    };
  } else {
    document.cancelFullScreen = document.webkitCancelFullScreen ||
        document.mozCancelFullScreen || document.cancelFullScreen;
  }

  if (isChromeApp()) {
    document.body.requestFullScreen = function() {
      chrome.app.window.current().fullscreen();
    };
  } else {
    document.body.requestFullScreen = document.body.webkitRequestFullScreen ||
        document.body.mozRequestFullScreen || document.body.requestFullScreen;
  }

  document.onfullscreenchange = document.onfullscreenchange ||
        document.onwebkitfullscreenchange || document.onmozfullscreenchange;
}

function isFullScreen() {
  if (isChromeApp()) {
    return chrome.app.window.current().isFullscreen();
  }

  return !!(document.webkitIsFullScreen || document.mozFullScreen ||
    document.isFullScreen); // if any defined and true
}

function fullScreenElement() {
  return document.webkitFullScreenElement ||
      document.webkitCurrentFullScreenElement ||
      document.mozFullScreenElement ||
      document.fullScreenElement;
}

// End shims for fullscreen

// Return a random numerical string.
function randomString(strLength) {
  var result = [];
  strLength = strLength || 5;
  var charSet = '0123456789';
  while (strLength--) {
    result.push(charSet.charAt(Math.floor(Math.random() * charSet.length)));
  }
  return result.join('');
}

// Returns true if the code is running in a packaged Chrome App.
function isChromeApp() {
  return (typeof chrome !== 'undefined' &&
          typeof chrome.storage !== 'undefined' &&
          typeof chrome.storage.local !== 'undefined');
}
<commit_msg>remove createIceServers<commit_after>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

/* More information about these options at jshint.com/docs/options */

/* exported setUpFullScreen, fullScreenElement, isFullScreen,
   requestTurnServers, sendAsyncUrlRequest, sendSyncUrlRequest, randomString, $,
   queryStringToDictionary */
/* globals chrome */

'use strict';

function $(selector) {
  return document.querySelector(selector);
}

// Returns the URL query key-value pairs as a dictionary object.
function queryStringToDictionary(queryString) {
  var pairs = queryString.slice(1).split('&');

  var result = {};
  pairs.forEach(function(pair) {
    if (pair) {
      pair = pair.split('=');
      if (pair[0]) {
        result[pair[0]] = decodeURIComponent(pair[1] || '');
      }
    }
  });
  return result;
}

// Sends the URL request and returns a Promise as the result.
function sendAsyncUrlRequest(method, url, body) {
  return sendUrlRequest(method, url, true, body);
}

// If async is true, returns a Promise and executes the xhr request
// async. If async is false, the xhr will be executed sync and a
// resolved promise is returned.
function sendUrlRequest(method, url, async, body) {
  return new Promise(function(resolve, reject) {
    var xhr;
    var reportResults = function() {
      if (xhr.status !== 200) {
        reject(
            Error('Status=' + xhr.status + ', response=' +
                  xhr.responseText));
        return;
      }
      resolve(xhr.responseText);
    };

    xhr = new XMLHttpRequest();
    if (async) {
      xhr.onreadystatechange = function() {
        if (xhr.readyState !== 4) {
          return;
        }
        reportResults();
      };
    }
    xhr.open(method, url, async);
    xhr.send(body);

    if (!async) {
      reportResults();
    }
  });
}

// Returns a list of turn servers after requesting it from CEOD.
function requestTurnServers(turnRequestUrl, turnTransports) {
  return new Promise(function(resolve, reject) {
    // Chrome apps don't send origin header for GET requests, but
    // do send it for POST requests. Origin header is required for
    // access to turn request url.
    var method = isChromeApp() ? 'POST' : 'GET';
    sendAsyncUrlRequest(method, turnRequestUrl).then(function(response) {
      var turnServerResponse = parseJSON(response);
      if (!turnServerResponse) {
        reject(Error('Error parsing response JSON: ' + response));
        return;
      }
      // Filter the TURN URLs to only use the desired transport, if specified.
      if (turnTransports.length > 0) {
        filterTurnUrls(turnServerResponse.uris, turnTransports);
      }

      // Create the RTCIceServer objects from the response.
      var turnServers = {
        urls: turnServerResponse.uris,
        username: turnServerResponse.username,
        credential: turnServerResponse.password
      };
      trace('Retrieved TURN server information.');
      resolve(turnServers);
    }).catch(function(error) {
      reject(Error('TURN server request error: ' + error.message));
      return;
    });
  });
}

// Parse the supplied JSON, or return null if parsing fails.
function parseJSON(json) {
  try {
    return JSON.parse(json);
  } catch (e) {
    trace('Error parsing json: ' + json);
  }
  return null;
}

// Filter a list of TURN urls to only contain those with transport=|protocol|.
function filterTurnUrls(urls, protocol) {
  for (var i = 0; i < urls.length;) {
    var parts = urls[i].split('?');
    if (parts.length > 1 && parts[1] !== ('transport=' + protocol)) {
      urls.splice(i, 1);
    } else {
      ++i;
    }
  }
}

// Start shims for fullscreen
function setUpFullScreen() {
  if (isChromeApp()) {
    document.cancelFullScreen = function() {
      chrome.app.window.current().restore();
    };
  } else {
    document.cancelFullScreen = document.webkitCancelFullScreen ||
        document.mozCancelFullScreen || document.cancelFullScreen;
  }

  if (isChromeApp()) {
    document.body.requestFullScreen = function() {
      chrome.app.window.current().fullscreen();
    };
  } else {
    document.body.requestFullScreen = document.body.webkitRequestFullScreen ||
        document.body.mozRequestFullScreen || document.body.requestFullScreen;
  }

  document.onfullscreenchange = document.onfullscreenchange ||
        document.onwebkitfullscreenchange || document.onmozfullscreenchange;
}

function isFullScreen() {
  if (isChromeApp()) {
    return chrome.app.window.current().isFullscreen();
  }

  return !!(document.webkitIsFullScreen || document.mozFullScreen ||
    document.isFullScreen); // if any defined and true
}

function fullScreenElement() {
  return document.webkitFullScreenElement ||
      document.webkitCurrentFullScreenElement ||
      document.mozFullScreenElement ||
      document.fullScreenElement;
}

// End shims for fullscreen

// Return a random numerical string.
function randomString(strLength) {
  var result = [];
  strLength = strLength || 5;
  var charSet = '0123456789';
  while (strLength--) {
    result.push(charSet.charAt(Math.floor(Math.random() * charSet.length)));
  }
  return result.join('');
}

// Returns true if the code is running in a packaged Chrome App.
function isChromeApp() {
  return (typeof chrome !== 'undefined' &&
          typeof chrome.storage !== 'undefined' &&
          typeof chrome.storage.local !== 'undefined');
}
<|endoftext|>


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

/**
 * @fileoverview Utilities function for debug.
 *
 * NOTE: these code are stripped using compiler prefix feature.
 * See more detail in tools/strip_debug.txt file.
 *
 * @author kyawtun@yathit.com (Kyaw Tun)
 */

goog.provide('ydn.debug.error.ArgumentException');
goog.provide('ydn.debug.error.ConstraintError');
goog.provide('ydn.debug.error.InternalError');
goog.provide('ydn.debug.error.InvalidOperationException');
goog.provide('ydn.debug.error.NotImplementedException');
goog.provide('ydn.debug.error.NotSupportedException');
goog.provide('ydn.debug.error.TypeError');

goog.require('goog.debug.Error');

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {goog.debug.Error}
 */
ydn.debug.error.ArgumentException = function(opt_msg) {
  goog.base(this, opt_msg);
  this.name = 'ydn.error.ArgumentException';
};
goog.inherits(ydn.debug.error.ArgumentException, goog.debug.Error);

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {goog.debug.Error}
 */
ydn.debug.error.TypeError = function(opt_msg) {
  goog.base(this, opt_msg);
  this.name = 'ydn.error.TypeError';
};
goog.inherits(ydn.debug.error.TypeError, goog.debug.Error);

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {goog.debug.Error}
 */
ydn.debug.error.NotSupportedException = function(opt_msg) {
  goog.base(this, opt_msg);
  this.name = 'ydn.error.NotSupportedException';
};
goog.inherits(ydn.debug.error.NotSupportedException, goog.debug.Error);

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {goog.debug.Error}
 */
ydn.debug.error.NotImplementedException = function(opt_msg) {
  goog.base(this, opt_msg);
  this.name = 'ydn.error.NotImplementedException';
};
goog.inherits(ydn.debug.error.NotImplementedException, goog.debug.Error);

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {goog.debug.Error}
 */
ydn.debug.error.InvalidOperationException = function(opt_msg) {
  goog.base(this, opt_msg);
  this.name = 'ydn.error.InvalidOperationException';
};
goog.inherits(ydn.debug.error.InvalidOperationException, goog.debug.Error);

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {Error}
 */
ydn.debug.error.InternalError = function(opt_msg) {

  // Ensure there is a stack trace.
  if (Error.captureStackTrace) {
    Error.captureStackTrace(this, ydn.debug.error.InternalError);
  } else {
    this.stack = new Error().stack || '';
  }

  if (opt_msg) {
    this.message = String(opt_msg);
  }
  this.name = 'ydn.error.InternalError';
};
goog.inherits(ydn.debug.error.InternalError, Error);

/**
 * Name of error.
 * @type {string}
 */
ydn.debug.error.InternalError.prototype.name = 'ydn.error.InternalError';

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {Error}
 */
ydn.debug.error.ConstraintError = function(opt_msg) {

  // Ensure there is a stack trace.
  if (Error.captureStackTrace) {
    Error.captureStackTrace(this, ydn.error.ConstraintError);
  } else {
    this.stack = new Error().stack || '';
  }

  if (opt_msg) {
    this.message = String(opt_msg);
  }
  this.name = 'ydn.error.ConstraintError';
};
goog.inherits(ydn.debug.error.ConstraintError, Error);

/**
 * Name of error.
 * @type {string}
 */
ydn.debug.error.ConstraintError.prototype.name = 'ydn.error.ConstraintError';

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

/**
 * @fileoverview Utilities function for debug.
 *
 * NOTE: these code are stripped using compiler prefix feature.
 * See more detail in tools/strip_debug.txt file.
 *
 * @author kyawtun@yathit.com (Kyaw Tun)
 */

goog.provide('ydn.debug.error.ArgumentException');
goog.provide('ydn.debug.error.ConstraintError');
goog.provide('ydn.debug.error.InternalError');
goog.provide('ydn.debug.error.InvalidOperationException');
goog.provide('ydn.debug.error.NotImplementedException');
goog.provide('ydn.debug.error.NotSupportedException');
goog.provide('ydn.debug.error.TypeError');

goog.require('goog.debug.Error');

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {goog.debug.Error}
 */
ydn.debug.error.ArgumentException = function(opt_msg) {
  goog.base(this, opt_msg);
  this.name = 'ydn.error.ArgumentException';
};
goog.inherits(ydn.debug.error.ArgumentException, goog.debug.Error);

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {goog.debug.Error}
 */
ydn.debug.error.TypeError = function(opt_msg) {
  goog.base(this, opt_msg);
  this.name = 'ydn.error.TypeError';
};
goog.inherits(ydn.debug.error.TypeError, goog.debug.Error);

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {goog.debug.Error}
 */
ydn.debug.error.NotSupportedException = function(opt_msg) {
  goog.base(this, opt_msg);
  this.name = 'ydn.error.NotSupportedException';
};
goog.inherits(ydn.debug.error.NotSupportedException, goog.debug.Error);

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {goog.debug.Error}
 */
ydn.debug.error.NotImplementedException = function(opt_msg) {
  goog.base(this, opt_msg);
  this.name = 'ydn.error.NotImplementedException';
};
goog.inherits(ydn.debug.error.NotImplementedException, goog.debug.Error);

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {goog.debug.Error}
 */
ydn.debug.error.InvalidOperationException = function(opt_msg) {
  goog.base(this, opt_msg);
  this.name = 'ydn.error.InvalidOperationException';
};
goog.inherits(ydn.debug.error.InvalidOperationException, goog.debug.Error);

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {Error}
 */
ydn.debug.error.InternalError = function(opt_msg) {

  // Ensure there is a stack trace.
  if (Error.captureStackTrace) {
    Error.captureStackTrace(this, ydn.debug.error.InternalError);
  } else {
    this.stack = new Error().stack || '';
  }

  if (opt_msg) {
    this.message = String(opt_msg);
  }
  this.name = 'ydn.error.InternalError';
};
goog.inherits(ydn.debug.error.InternalError, Error);

/**
 * Name of error.
 * @type {string}
 */
ydn.debug.error.InternalError.prototype.name = 'ydn.error.InternalError';

/**
 * Base class for custom error objects.
 * @param {*=} opt_msg The message associated with the error.
 * @constructor
 * @extends {Error}
 */
ydn.debug.error.ConstraintError = function(opt_msg) {

  // Ensure there is a stack trace.
  if (Error.captureStackTrace) {
    Error.captureStackTrace(this, ydn.debug.error.ConstraintError);
  } else {
    this.stack = new Error().stack || '';
  }

  if (opt_msg) {
    this.message = String(opt_msg);
  }
  this.name = 'ydn.error.ConstraintError';
};
goog.inherits(ydn.debug.error.ConstraintError, Error);

/**
 * Name of error.
 * @type {string}
 */
ydn.debug.error.ConstraintError.prototype.name = 'ydn.error.ConstraintError';

<|endoftext|>


<commit_before>function addFilterMethods(block, type) {

    console.log("[DEBUG] addFilterMethods()", type);

    // make sure this is an allowed type
    var _allowedFilterTypes = allowedFilterTypes();
    if(_allowedFilterTypes.indexOf(type) == -1) {
        console.log("Invalid filter block type: " + type);
        return;
    }

    block.inputCount = type === "not" || type === "box" || type === "ema" || type === "absolute value" ? 1 : 2;
    block.outputCount = 1;

    // filter-specific block attributes
    block.lastAverage = null;
    block.averageStorage = [];

    // This will execute the switch once when the block is created. After that,
    // computeFilterValue will just be one of these functions.
    block.computeFilterValue = (function() {

        console.log("[DEBUG] computeFilterValue()");

        switch (block.type) {
            case 'and':
                return function(inputs) {
                    return (inputs[0] & inputs[1]);
                };
            case 'or':
                return function(inputs) {
                    return (inputs[0] | inputs[1]);
                };
            case 'xor':
                return function(inputs) {
                    return (inputs[0] ^ inputs[1]);
                };
            case 'not':
                return function(inputs) {
                    return 1 - inputs[0];
                };
            case 'nand':
                return function(inputs) {
                    return 1 - (inputs[0] & inputs[1]);
                };
            case 'plus':
                return function(inputs) {
                    return inputs[0] + inputs[1];
                };
            case 'minus':
                return function(inputs) {
                    return inputs[0] - inputs[1];
                };
            case 'times':
                return function(inputs) {
                    return inputs[0] * inputs[1];
                };
            case 'divided by':
                return function(inputs) {
                    return (Math.abs( inputs[1] ) > 1e-8) ? inputs[0] / inputs[1] : 0;
                };
            case 'absolute value':
                return function(inputs) {
                    return Math.abs( inputs[0] );
                };
            case 'equals':
                return function(inputs) {
                    return inputs[0] == inputs[1] ? 1 : 0;
                };
            case 'not equals':
                return function(inputs) {
                    return inputs[0] !== inputs[1] ? 1 : 0;
                };
            case 'less than':
                return function(inputs) {
                    return inputs[0] < inputs[1] ? 1 : 0;
                };
            case 'greater than':
                return function(inputs) {
                    return inputs[0] > inputs[1] ? 1 : 0;
                };
            case 'box':
                return function(inputs) {
                    return block.computeMovingAverage(inputs[0], block.boxSize);
                };
            case 'ema':
                return function(inputs) {
                    return block.computeEMA(inputs[0], block.boxSize);
                };
        }
    })();

    // Box size isn't intended to be dynamic.
    // To do that we'd have to shift averageStorage in a while loop.
    block.computeMovingAverage = function(newValue, boxSize) {
        var avg = 0;

        block.averageStorage.push(newValue);
        if(block.averageStorage.length > boxSize) {
            block.averageStorage.shift();
        }

        var len = block.averageStorage.length;
        if (len < boxSize && len > 0) {
            for (var i = 0; i < len; i++) {
                avg += block.averageStorage[i] / len;
            }
        } else if (block.lastAverage !== null) {
            avg = block.lastAverage + 1 / boxSize * (newValue - block.averageStorage[0]);
        }
        block.lastAverage = avg;
        return avg;
    };

    block.computeEMA = function(newValue, boxSize) {
        var avg = 0;
        if (block.lastAverage !== null) {
            var alpha = boxSize / (boxSize + 1);
            avg = block.lastAverage * alpha + newValue * (1 - alpha);
        }
        block.lastAverage = avg;
        return avg;
    };
}

function allowedFilterTypes() {
    return [
        "not", "and", "or", "xor", "nand",
        "box", "ema",
        "plus", "minus", "times", "divided by", "absolute value",
        "equals", "not equals", "less than", "greater than",
		"number_display_and_input"
    ];
}

<commit_msg>fix averages<commit_after>function addFilterMethods(block, type) {

    console.log("[DEBUG] addFilterMethods()", type);

    // make sure this is an allowed type
    var _allowedFilterTypes = allowedFilterTypes();
    if(_allowedFilterTypes.indexOf(type) == -1) {
        console.log("Invalid filter block type: " + type);
        return;
    }

    block.inputCount = type === "not" || type === "box" || type === "ema" || type === "absolute value" ? 1 : 2;
    block.outputCount = 1;

    // filter-specific block attributes
    block.lastAverage = null;
    block.averageStorage = [];

    // This will execute the switch once when the block is created. After that,
    // computeFilterValue will just be one of these functions.
    block.computeFilterValue = (function() {

        console.log("[DEBUG] computeFilterValue()");

        switch (block.type) {
            case 'and':
                return function(inputs) {
                    return (inputs[0] & inputs[1]);
                };
            case 'or':
                return function(inputs) {
                    return (inputs[0] | inputs[1]);
                };
            case 'xor':
                return function(inputs) {
                    return (inputs[0] ^ inputs[1]);
                };
            case 'not':
                return function(inputs) {
                    return 1 - inputs[0];
                };
            case 'nand':
                return function(inputs) {
                    return 1 - (inputs[0] & inputs[1]);
                };
            case 'plus':
                return function(inputs) {
                    return inputs[0] + inputs[1];
                };
            case 'minus':
                return function(inputs) {
                    return inputs[0] - inputs[1];
                };
            case 'times':
                return function(inputs) {
                    return inputs[0] * inputs[1];
                };
            case 'divided by':
                return function(inputs) {
                    return (Math.abs( inputs[1] ) > 1e-8) ? inputs[0] / inputs[1] : 0;
                };
            case 'absolute value':
                return function(inputs) {
                    return Math.abs( inputs[0] );
                };
            case 'equals':
                return function(inputs) {
                    return inputs[0] == inputs[1] ? 1 : 0;
                };
            case 'not equals':
                return function(inputs) {
                    return inputs[0] !== inputs[1] ? 1 : 0;
                };
            case 'less than':
                return function(inputs) {
                    return inputs[0] < inputs[1] ? 1 : 0;
                };
            case 'greater than':
                return function(inputs) {
                    return inputs[0] > inputs[1] ? 1 : 0;
                };
            case 'box':
                return function(inputs) {
                    return block.computeMovingAverage(inputs[0], block.boxSize);
                };
            case 'ema':
                return function(inputs) {
                    return block.computeEMA(inputs[0], block.boxSize);
                };
        }
    })();

    // Box size isn't intended to be dynamic.
    // To do that we'd have to shift averageStorage in a while loop.
    block.computeMovingAverage = function(newValue, boxSize) {
        var avg = 0;

        block.averageStorage.push(newValue);
        if(block.averageStorage.length > boxSize) {
            block.averageStorage.shift();
        }

        var len = block.averageStorage.length;
        if (len < boxSize && len > 0) {
            for (var i = 0; i < len; i++) {
                avg += block.averageStorage[i] / len;
            }
        } else if (block.lastAverage !== null) {
            avg = block.lastAverage + 1 / boxSize * (newValue - block.averageStorage[0]);
        }
        block.lastAverage = avg;
        return avg;
    };

    block.computeEMA = function(newValue, boxSize) {
        var avg = 0;
        if (block.lastAverage !== null) {
            var alpha = boxSize / (boxSize + 1);
            avg = block.lastAverage * alpha + newValue * (1 - alpha);
        }
        block.lastAverage = avg;
        return avg;
    };
}

function allowedFilterTypes() {
    return [
        "not", "and", "or", "xor", "nand",
        "box", "ema",
        "plus", "minus", "times", "divided by", "absolute value",
        "equals", "not equals", "less than", "greater than",
    ];
}

<|endoftext|>


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

'use strict';

var assert = require('assert');
var async = require('async');
var bigqueryLibrary = require('@google-cloud/bigquery');
var exec = require('methmeth');
var extend = require('extend');
var is = require('is');
var prop = require('propprop');
var pubsubLibrary = require('@google-cloud/pubsub');
var storageLibrary = require('@google-cloud/storage');
var uuid = require('uuid');

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

describe('Logging', function() {
  var PROJECT_ID;
  var TESTS_PREFIX = 'gcloud-logging-test';
  var WRITE_CONSISTENCY_DELAY_MS = 3000;

  var bigQuery = bigqueryLibrary();
  var pubsub = pubsubLibrary();
  var storage = storageLibrary();

  var logging = new Logging();

  // Create the possible destinations for sinks that we will create.
  var bucket = storage.bucket(generateName());
  var dataset = bigQuery.dataset(generateName().replace(/-/g, '_'));
  var topic = pubsub.topic(generateName());

  before(function(done) {
    async.parallel(
      [
        callback => {
          bucket.create(callback);
        },
        callback => {
          dataset.create(callback);
        },
        callback => {
          topic.create(callback);
        },
        callback => {
          logging.auth.getProjectId((err, projectId) => {
            if (err) {
              callback(err);
              return;
            }
            PROJECT_ID = projectId;
            callback();
          });
        },
      ],
      done
    );
  });

  after(function(done) {
    async.parallel(
      [deleteBuckets, deleteDatasets, deleteTopics, deleteSinks],
      done
    );

    function deleteBuckets(callback) {
      storage.getBuckets(
        {
          prefix: TESTS_PREFIX,
        },
        function(err, buckets) {
          if (err) {
            done(err);
            return;
          }

          function deleteBucket(bucket, callback) {
            bucket.deleteFiles(function(err) {
              if (err) {
                callback(err);
                return;
              }

              bucket.delete(callback);
            });
          }

          async.each(buckets, deleteBucket, callback);
        }
      );
    }

    function deleteDatasets(callback) {
      getAndDelete(bigQuery.getDatasets.bind(bigQuery), callback);
    }

    function deleteTopics(callback) {
      getAndDelete(pubsub.getTopics.bind(pubsub), callback);
    }

    function deleteSinks(callback) {
      getAndDelete(logging.getSinks.bind(logging), callback);
    }

    function getAndDelete(method, callback) {
      method(function(err, objects) {
        if (err) {
          callback(err);
          return;
        }

        objects = objects.filter(function(object) {
          return (object.name || object.id).indexOf(TESTS_PREFIX) === 0;
        });

        async.each(objects, exec('delete'), callback);
      });
    }
  });

  describe('sinks', function() {
    it('should create a sink with a Bucket destination', function(done) {
      var sink = logging.sink(generateName());

      sink.create(
        {
          destination: bucket,
        },
        function(err, sink, apiResponse) {
          assert.ifError(err);

          var destination = 'storage.googleapis.com/' + bucket.name;
          assert.strictEqual(apiResponse.destination, destination);

          done();
        }
      );
    });

    it('should create a sink with a Dataset destination', function(done) {
      var sink = logging.sink(generateName());

      sink.create(
        {
          destination: dataset,
        },
        function(err, sink, apiResponse) {
          assert.ifError(err);

          var destination = 'bigquery.googleapis.com/datasets/' + dataset.id;

          // The projectId may have been replaced depending on how the system
          // tests are being run, so let's not care about that.
          apiResponse.destination = apiResponse.destination.replace(
            /projects\/[^/]*\//,
            ''
          );

          assert.strictEqual(apiResponse.destination, destination);

          done();
        }
      );
    });

    it('should create a sink with a Topic destination', function(done) {
      var sink = logging.sink(generateName());

      sink.create(
        {
          destination: topic,
        },
        function(err, sink, apiResponse) {
          assert.ifError(err);

          var destination = 'pubsub.googleapis.com/' + topic.name;

          // The projectId may have been replaced depending on how the system
          // tests are being run, so let's not care about that.
          assert.strictEqual(
            apiResponse.destination.replace(/projects\/[^/]*\//, ''),
            destination.replace(/projects\/[^/]*\//, '')
          );

          done();
        }
      );
    });

    describe('metadata', function() {
      var sink = logging.sink(generateName());
      var FILTER = 'severity = ALERT';

      before(function(done) {
        sink.create(
          {
            destination: topic,
          },
          done
        );
      });

      it('should set metadata', function(done) {
        var metadata = {
          filter: FILTER,
        };

        sink.setMetadata(metadata, function(err, apiResponse) {
          assert.ifError(err);
          assert.strictEqual(apiResponse.filter, FILTER);
          done();
        });
      });

      it('should set a filter', function(done) {
        sink.setFilter(FILTER, function(err, apiResponse) {
          assert.ifError(err);
          assert.strictEqual(apiResponse.filter, FILTER);
          done();
        });
      });
    });

    describe('listing sinks', function() {
      var sink = logging.sink(generateName());

      before(function(done) {
        sink.create(
          {
            destination: topic,
          },
          done
        );
      });

      it('should list sinks', function(done) {
        logging.getSinks(function(err, sinks) {
          assert.ifError(err);
          assert(sinks.length > 0);
          done();
        });
      });

      it('should list sinks as a stream', function(done) {
        logging
          .getSinksStream({pageSize: 1})
          .on('error', done)
          .once('data', function() {
            this.end();
            done();
          });
      });

      it('should get metadata', function(done) {
        logging
          .getSinksStream({pageSize: 1})
          .on('error', done)
          .once('data', function(sink) {
            sink.getMetadata(function(err, metadata) {
              assert.ifError(err);
              assert.strictEqual(is.object(metadata), true);
              done();
            });
          });
      });
    });
  });

  describe('logs', function() {
    var log = logging.log('syslog');

    var logEntries = [
      // string data
      log.entry('log entry 1'),

      // object data
      log.entry({delegate: 'my_username'}),

      // various data types
      log.entry({
        nonValue: null,
        boolValue: true,
        arrayValue: [1, 2, 3],
      }),

      // nested object data
      log.entry({
        nested: {
          delegate: 'my_username',
        },
      }),
    ];

    var options = {
      resource: {
        type: 'gce_instance',
        labels: {
          zone: 'global',
          instance_id: '3',
        },
      },
    };

    it('should list log entries', function(done) {
      logging.getEntries(
        {
          autoPaginate: false,
          pageSize: 1,
        },
        function(err, entries) {
          assert.ifError(err);
          assert.strictEqual(entries.length, 1);
          done();
        }
      );
    });

    it('should list log entries as a stream', function(done) {
      logging
        .getEntriesStream({
          autoPaginate: false,
          pageSize: 1,
        })
        .on('error', done)
        .once('data', function() {
          this.end();
        })
        .on('end', done);
    });

    describe('log-specific entries', function() {
      before(function(done) {
        log.write(logEntries, options, done);
      });

      it('should list log entries', function(done) {
        log.getEntries(
          {
            autoPaginate: false,
            pageSize: 1,
          },
          function(err, entries) {
            assert.ifError(err);
            assert.strictEqual(entries.length, 1);
            done();
          }
        );
      });

      it('should list log entries as a stream', function(done) {
        log
          .getEntriesStream({
            autoPaginate: false,
            pageSize: 1,
          })
          .on('error', done)
          .once('data', function() {
            this.end();
            done();
          });
      });
    });

    it('should write a single entry to a log', function(done) {
      log.write(logEntries[0], options, done);
    });

    it('should write multiple entries to a log', function(done) {
      log.write(logEntries, options, function(err) {
        assert.ifError(err);

        setTimeout(function() {
          log.getEntries(
            {
              autoPaginate: false,
              pageSize: logEntries.length,
            },
            function(err, entries) {
              assert.ifError(err);

              assert.deepEqual(entries.map(prop('data')).reverse(), [
                'log entry 1',
                {
                  delegate: 'my_username',
                },
                {
                  nonValue: null,
                  boolValue: true,
                  arrayValue: [1, 2, 3],
                },
                {
                  nested: {
                    delegate: 'my_username',
                  },
                },
              ]);

              done();
            }
          );
        }, WRITE_CONSISTENCY_DELAY_MS);
      });
    });

    it('should preserve order of entries', function(done) {
      var entry1 = log.entry('1');

      setTimeout(function() {
        var entry2 = log.entry('2');
        var entry3 = log.entry({timestamp: entry2.metadata.timestamp}, '3');

        // Re-arrange to confirm the timestamp is sent and honored.
        log.write([entry2, entry3, entry1], options, function(err) {
          assert.ifError(err);

          setTimeout(function() {
            log.getEntries(
              {
                autoPaginate: false,
                pageSize: 3,
              },
              function(err, entries) {
                assert.ifError(err);
                assert.deepEqual(entries.map(prop('data')), ['3', '2', '1']);
                done();
              }
            );
          }, WRITE_CONSISTENCY_DELAY_MS * 4);
        });
      }, 1000);
    });

    it('should preserve order for sequential write calls', function(done) {
      var messages = ['1', '2', '3', '4', '5'];

      messages.forEach(function(message) {
        log.write(log.entry(message));
      });

      setTimeout(function() {
        log.getEntries(
          {
            autoPaginate: false,
            pageSize: messages.length,
          },
          function(err, entries) {
            assert.ifError(err);
            assert.deepEqual(entries.reverse().map(prop('data')), messages);
            done();
          }
        );
      }, WRITE_CONSISTENCY_DELAY_MS * 4);
    });

    it('should write an entry with primitive values', function(done) {
      var logEntry = log.entry({
        when: new Date(),
        matchUser: /username: (.+)/,
        matchUserError: new Error('No user found.'),
        shouldNotBeSaved: undefined,
      });

      log.write(logEntry, options, function(err) {
        assert.ifError(err);

        setTimeout(function() {
          log.getEntries(
            {
              autoPaginate: false,
              pageSize: 1,
            },
            function(err, entries) {
              assert.ifError(err);

              var entry = entries[0];

              assert.deepEqual(entry.data, {
                when: logEntry.data.when.toString(),
                matchUser: logEntry.data.matchUser.toString(),
                matchUserError: logEntry.data.matchUserError.toString(),
              });

              done();
            }
          );
        }, WRITE_CONSISTENCY_DELAY_MS);
      });
    });

    it('should write a log with metadata', function(done) {
      var metadata = extend({}, options, {
        severity: 'DEBUG',
      });

      var data = {
        embeddedData: true,
      };

      var logEntry = log.entry(metadata, data);

      log.write(logEntry, function(err) {
        assert.ifError(err);

        setTimeout(function() {
          log.getEntries(
            {
              autoPaginate: false,
              pageSize: 1,
            },
            function(err, entries) {
              assert.ifError(err);

              var entry = entries[0];

              assert.strictEqual(entry.metadata.severity, metadata.severity);
              assert.deepEqual(entry.data, data);

              done();
            }
          );
        }, WRITE_CONSISTENCY_DELAY_MS);
      });
    });

    it('should set the default resource', function(done) {
      var text = 'entry-text';
      var entry = log.entry(text);

      log.write(entry, function(err) {
        assert.ifError(err);

        setTimeout(function() {
          log.getEntries(
            {
              autoPaginate: false,
              pageSize: 1,
            },
            function(err, entries) {
              assert.ifError(err);

              var entry = entries[0];

              assert.strictEqual(entry.data, text);
              assert.deepEqual(entry.metadata.resource, {
                type: 'global',
                labels: {
                  project_id: PROJECT_ID,
                },
              });

              done();
            }
          );
        }, WRITE_CONSISTENCY_DELAY_MS);
      });
    });

    it('should write a log with camelcase resource label keys', function(done) {
      log.write(
        logEntries,
        {
          resource: {
            type: 'gce_instance',
            labels: {
              zone: 'global',
              instanceId: '3',
            },
          },
        },
        done
      );
    });

    it('should write to a log with alert helper', function(done) {
      log.alert(logEntries, options, done);
    });

    it('should write to a log with critical helper', function(done) {
      log.critical(logEntries, options, done);
    });

    it('should write to a log with debug helper', function(done) {
      log.debug(logEntries, options, done);
    });

    it('should write to a log with emergency helper', function(done) {
      log.emergency(logEntries, options, done);
    });

    it('should write to a log with error helper', function(done) {
      log.error(logEntries, options, done);
    });

    it('should write to a log with info helper', function(done) {
      log.info(logEntries, options, done);
    });

    it('should write to a log with notice helper', function(done) {
      log.notice(logEntries, options, done);
    });

    it('should write to a log with warning helper', function(done) {
      log.warning(logEntries, options, done);
    });
  });

  function generateName() {
    return TESTS_PREFIX + uuid.v1();
  }
});
<commit_msg>Extend system test delay. (#83)<commit_after>/*!
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var assert = require('assert');
var async = require('async');
var bigqueryLibrary = require('@google-cloud/bigquery');
var exec = require('methmeth');
var extend = require('extend');
var is = require('is');
var prop = require('propprop');
var pubsubLibrary = require('@google-cloud/pubsub');
var storageLibrary = require('@google-cloud/storage');
var uuid = require('uuid');

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

describe('Logging', function() {
  var PROJECT_ID;
  var TESTS_PREFIX = 'gcloud-logging-test';
  var WRITE_CONSISTENCY_DELAY_MS = 10000;

  var bigQuery = bigqueryLibrary();
  var pubsub = pubsubLibrary();
  var storage = storageLibrary();

  var logging = new Logging();

  // Create the possible destinations for sinks that we will create.
  var bucket = storage.bucket(generateName());
  var dataset = bigQuery.dataset(generateName().replace(/-/g, '_'));
  var topic = pubsub.topic(generateName());

  before(function(done) {
    async.parallel(
      [
        callback => {
          bucket.create(callback);
        },
        callback => {
          dataset.create(callback);
        },
        callback => {
          topic.create(callback);
        },
        callback => {
          logging.auth.getProjectId((err, projectId) => {
            if (err) {
              callback(err);
              return;
            }
            PROJECT_ID = projectId;
            callback();
          });
        },
      ],
      done
    );
  });

  after(function(done) {
    async.parallel(
      [deleteBuckets, deleteDatasets, deleteTopics, deleteSinks],
      done
    );

    function deleteBuckets(callback) {
      storage.getBuckets(
        {
          prefix: TESTS_PREFIX,
        },
        function(err, buckets) {
          if (err) {
            done(err);
            return;
          }

          function deleteBucket(bucket, callback) {
            bucket.deleteFiles(function(err) {
              if (err) {
                callback(err);
                return;
              }

              bucket.delete(callback);
            });
          }

          async.each(buckets, deleteBucket, callback);
        }
      );
    }

    function deleteDatasets(callback) {
      getAndDelete(bigQuery.getDatasets.bind(bigQuery), callback);
    }

    function deleteTopics(callback) {
      getAndDelete(pubsub.getTopics.bind(pubsub), callback);
    }

    function deleteSinks(callback) {
      getAndDelete(logging.getSinks.bind(logging), callback);
    }

    function getAndDelete(method, callback) {
      method(function(err, objects) {
        if (err) {
          callback(err);
          return;
        }

        objects = objects.filter(function(object) {
          return (object.name || object.id).indexOf(TESTS_PREFIX) === 0;
        });

        async.each(objects, exec('delete'), callback);
      });
    }
  });

  describe('sinks', function() {
    it('should create a sink with a Bucket destination', function(done) {
      var sink = logging.sink(generateName());

      sink.create(
        {
          destination: bucket,
        },
        function(err, sink, apiResponse) {
          assert.ifError(err);

          var destination = 'storage.googleapis.com/' + bucket.name;
          assert.strictEqual(apiResponse.destination, destination);

          done();
        }
      );
    });

    it('should create a sink with a Dataset destination', function(done) {
      var sink = logging.sink(generateName());

      sink.create(
        {
          destination: dataset,
        },
        function(err, sink, apiResponse) {
          assert.ifError(err);

          var destination = 'bigquery.googleapis.com/datasets/' + dataset.id;

          // The projectId may have been replaced depending on how the system
          // tests are being run, so let's not care about that.
          apiResponse.destination = apiResponse.destination.replace(
            /projects\/[^/]*\//,
            ''
          );

          assert.strictEqual(apiResponse.destination, destination);

          done();
        }
      );
    });

    it('should create a sink with a Topic destination', function(done) {
      var sink = logging.sink(generateName());

      sink.create(
        {
          destination: topic,
        },
        function(err, sink, apiResponse) {
          assert.ifError(err);

          var destination = 'pubsub.googleapis.com/' + topic.name;

          // The projectId may have been replaced depending on how the system
          // tests are being run, so let's not care about that.
          assert.strictEqual(
            apiResponse.destination.replace(/projects\/[^/]*\//, ''),
            destination.replace(/projects\/[^/]*\//, '')
          );

          done();
        }
      );
    });

    describe('metadata', function() {
      var sink = logging.sink(generateName());
      var FILTER = 'severity = ALERT';

      before(function(done) {
        sink.create(
          {
            destination: topic,
          },
          done
        );
      });

      it('should set metadata', function(done) {
        var metadata = {
          filter: FILTER,
        };

        sink.setMetadata(metadata, function(err, apiResponse) {
          assert.ifError(err);
          assert.strictEqual(apiResponse.filter, FILTER);
          done();
        });
      });

      it('should set a filter', function(done) {
        sink.setFilter(FILTER, function(err, apiResponse) {
          assert.ifError(err);
          assert.strictEqual(apiResponse.filter, FILTER);
          done();
        });
      });
    });

    describe('listing sinks', function() {
      var sink = logging.sink(generateName());

      before(function(done) {
        sink.create(
          {
            destination: topic,
          },
          done
        );
      });

      it('should list sinks', function(done) {
        logging.getSinks(function(err, sinks) {
          assert.ifError(err);
          assert(sinks.length > 0);
          done();
        });
      });

      it('should list sinks as a stream', function(done) {
        logging
          .getSinksStream({pageSize: 1})
          .on('error', done)
          .once('data', function() {
            this.end();
            done();
          });
      });

      it('should get metadata', function(done) {
        logging
          .getSinksStream({pageSize: 1})
          .on('error', done)
          .once('data', function(sink) {
            sink.getMetadata(function(err, metadata) {
              assert.ifError(err);
              assert.strictEqual(is.object(metadata), true);
              done();
            });
          });
      });
    });
  });

  describe('logs', function() {
    var log = logging.log('syslog');

    var logEntries = [
      // string data
      log.entry('log entry 1'),

      // object data
      log.entry({delegate: 'my_username'}),

      // various data types
      log.entry({
        nonValue: null,
        boolValue: true,
        arrayValue: [1, 2, 3],
      }),

      // nested object data
      log.entry({
        nested: {
          delegate: 'my_username',
        },
      }),
    ];

    var options = {
      resource: {
        type: 'gce_instance',
        labels: {
          zone: 'global',
          instance_id: '3',
        },
      },
    };

    it('should list log entries', function(done) {
      logging.getEntries(
        {
          autoPaginate: false,
          pageSize: 1,
        },
        function(err, entries) {
          assert.ifError(err);
          assert.strictEqual(entries.length, 1);
          done();
        }
      );
    });

    it('should list log entries as a stream', function(done) {
      logging
        .getEntriesStream({
          autoPaginate: false,
          pageSize: 1,
        })
        .on('error', done)
        .once('data', function() {
          this.end();
        })
        .on('end', done);
    });

    describe('log-specific entries', function() {
      before(function(done) {
        log.write(logEntries, options, done);
      });

      it('should list log entries', function(done) {
        log.getEntries(
          {
            autoPaginate: false,
            pageSize: 1,
          },
          function(err, entries) {
            assert.ifError(err);
            assert.strictEqual(entries.length, 1);
            done();
          }
        );
      });

      it('should list log entries as a stream', function(done) {
        log
          .getEntriesStream({
            autoPaginate: false,
            pageSize: 1,
          })
          .on('error', done)
          .once('data', function() {
            this.end();
            done();
          });
      });
    });

    it('should write a single entry to a log', function(done) {
      log.write(logEntries[0], options, done);
    });

    it('should write multiple entries to a log', function(done) {
      log.write(logEntries, options, function(err) {
        assert.ifError(err);

        setTimeout(function() {
          log.getEntries(
            {
              autoPaginate: false,
              pageSize: logEntries.length,
            },
            function(err, entries) {
              assert.ifError(err);

              assert.deepEqual(entries.map(prop('data')).reverse(), [
                'log entry 1',
                {
                  delegate: 'my_username',
                },
                {
                  nonValue: null,
                  boolValue: true,
                  arrayValue: [1, 2, 3],
                },
                {
                  nested: {
                    delegate: 'my_username',
                  },
                },
              ]);

              done();
            }
          );
        }, WRITE_CONSISTENCY_DELAY_MS);
      });
    });

    it('should preserve order of entries', function(done) {
      var entry1 = log.entry('1');

      setTimeout(function() {
        var entry2 = log.entry('2');
        var entry3 = log.entry({timestamp: entry2.metadata.timestamp}, '3');

        // Re-arrange to confirm the timestamp is sent and honored.
        log.write([entry2, entry3, entry1], options, function(err) {
          assert.ifError(err);

          setTimeout(function() {
            log.getEntries(
              {
                autoPaginate: false,
                pageSize: 3,
              },
              function(err, entries) {
                assert.ifError(err);
                assert.deepEqual(entries.map(prop('data')), ['3', '2', '1']);
                done();
              }
            );
          }, WRITE_CONSISTENCY_DELAY_MS * 4);
        });
      }, 1000);
    });

    it('should preserve order for sequential write calls', function(done) {
      var messages = ['1', '2', '3', '4', '5'];

      messages.forEach(function(message) {
        log.write(log.entry(message));
      });

      setTimeout(function() {
        log.getEntries(
          {
            autoPaginate: false,
            pageSize: messages.length,
          },
          function(err, entries) {
            assert.ifError(err);
            assert.deepEqual(entries.reverse().map(prop('data')), messages);
            done();
          }
        );
      }, WRITE_CONSISTENCY_DELAY_MS * 4);
    });

    it('should write an entry with primitive values', function(done) {
      var logEntry = log.entry({
        when: new Date(),
        matchUser: /username: (.+)/,
        matchUserError: new Error('No user found.'),
        shouldNotBeSaved: undefined,
      });

      log.write(logEntry, options, function(err) {
        assert.ifError(err);

        setTimeout(function() {
          log.getEntries(
            {
              autoPaginate: false,
              pageSize: 1,
            },
            function(err, entries) {
              assert.ifError(err);

              var entry = entries[0];

              assert.deepEqual(entry.data, {
                when: logEntry.data.when.toString(),
                matchUser: logEntry.data.matchUser.toString(),
                matchUserError: logEntry.data.matchUserError.toString(),
              });

              done();
            }
          );
        }, WRITE_CONSISTENCY_DELAY_MS);
      });
    });

    it('should write a log with metadata', function(done) {
      var metadata = extend({}, options, {
        severity: 'DEBUG',
      });

      var data = {
        embeddedData: true,
      };

      var logEntry = log.entry(metadata, data);

      log.write(logEntry, function(err) {
        assert.ifError(err);

        setTimeout(function() {
          log.getEntries(
            {
              autoPaginate: false,
              pageSize: 1,
            },
            function(err, entries) {
              assert.ifError(err);

              var entry = entries[0];

              assert.strictEqual(entry.metadata.severity, metadata.severity);
              assert.deepEqual(entry.data, data);

              done();
            }
          );
        }, WRITE_CONSISTENCY_DELAY_MS);
      });
    });

    it('should set the default resource', function(done) {
      var text = 'entry-text';
      var entry = log.entry(text);

      log.write(entry, function(err) {
        assert.ifError(err);

        setTimeout(function() {
          log.getEntries(
            {
              autoPaginate: false,
              pageSize: 1,
            },
            function(err, entries) {
              assert.ifError(err);

              var entry = entries[0];

              assert.strictEqual(entry.data, text);
              assert.deepEqual(entry.metadata.resource, {
                type: 'global',
                labels: {
                  project_id: PROJECT_ID,
                },
              });

              done();
            }
          );
        }, WRITE_CONSISTENCY_DELAY_MS);
      });
    });

    it('should write a log with camelcase resource label keys', function(done) {
      log.write(
        logEntries,
        {
          resource: {
            type: 'gce_instance',
            labels: {
              zone: 'global',
              instanceId: '3',
            },
          },
        },
        done
      );
    });

    it('should write to a log with alert helper', function(done) {
      log.alert(logEntries, options, done);
    });

    it('should write to a log with critical helper', function(done) {
      log.critical(logEntries, options, done);
    });

    it('should write to a log with debug helper', function(done) {
      log.debug(logEntries, options, done);
    });

    it('should write to a log with emergency helper', function(done) {
      log.emergency(logEntries, options, done);
    });

    it('should write to a log with error helper', function(done) {
      log.error(logEntries, options, done);
    });

    it('should write to a log with info helper', function(done) {
      log.info(logEntries, options, done);
    });

    it('should write to a log with notice helper', function(done) {
      log.notice(logEntries, options, done);
    });

    it('should write to a log with warning helper', function(done) {
      log.warning(logEntries, options, done);
    });
  });

  function generateName() {
    return TESTS_PREFIX + uuid.v1();
  }
});
<|endoftext|>