<commit_before>backsplash.Editor = (function(){

var clone = backsplash._clone;

jQuery.fn.backsplashEditor = function(opts) {
    this.each(function() {
        var editor = new Editor(this, opts);
        $(this).data('backsplash-editor', editor);
    })
}

var Editor = function(elem, opts) {

    this.$elem = $(elem);
    this.opts = $.extend({}, this.$elem.data('backsplash'), opts);

    this.selection = []

    this.$elem.on('keydown.backsplash', $.proxy(this, 'onKeydown'));
    this.$elem.on('mousedown.backsplash', '.backsplash-tile', $.proxy(this, 'onMousedown'));
    this.$elem.on('click.backsplash', '.backsplash-tile', function(e) {
        e.preventDefault();
    });

    var editor = this;
    this.tiles = [];
    this.$elem.children().each(function() {

        var $tile = $(this);

        $tile.addClass('backsplash-tile');

        var tile = $tile.data('tile') || {};
        $tile.data('tile', tile);
        tile.$elem = $tile;

        editor.tiles.push(tile);
    })

}

Editor.prototype.resetTile = function(m, old_tile, opts) {
    var new_tile = m.add(old_tile, opts);
    old_tile.$elem.css(m.css(new_tile));
    old_tile.row = new_tile.row;
    old_tile.col = new_tile.col;
}

Editor.prototype.resetTiles = function() {

    var layout = new backsplash.Layout(this.opts);

    for (var i = 0; i < this.tiles.length; i++) {
        if (this.tiles[i].locked) {
            this.resetTile(layout, this.tiles[i].locked)
        }
    }
    for (var i = 0; i < this.tiles.length; i++) {
        if (!this.tiles[i].locked) {
            this.resetTile(layout, this.tiles[i], {ignore_position: true})
        }
    }

    return layout;

}

Editor.prototype.onKeydown = function(e) {

    switch (e.keyCode) {

        case 82: // r
            for (var i = 0; i < all_tiles.length; i++) {
                all_tiles[i].locked = null
                all_tiles[i].$tile.removeClass('tile-locked')
                all_tiles[i].$tile.removeClass('tile-selected')
            }
            resetTiles();
            break;

        case 38: // up
        case 40: // down
            e.preventDefault()
            for (var i = 0; i < selection.length; i++) {
                if (e.metaKey) {
                    selection[i].locked.height += e.keyCode == 40 ? 1 : -1;
                } else {
                    selection[i].locked.row += e.keyCode == 40 ? 1 : -1;
                }
            }
            resetTiles();
            break;

        case 37: // left
        case 39: // right
            e.preventDefault()
            for (var i = 0; i < selection.length; i++) {
                if (e.metaKey) {
                    selection[i].locked.width += e.keyCode == 39 ? 1 : -1;
                } else {
                    selection[i].locked.col += e.keyCode == 39 ? 1 : -1;
                }            }
            resetTiles();
            break;

        default:
            console.log('unknown key', e.keyCode, e)
    }

}

Editor.prototype.onMousedown = function(e) {

    e.preventDefault();
    this.mousedown = e;

    var $tile = $(e.target).closest('.backsplash-tile');
    var tile = $tile.data('tile');

    console.log($tile, tile);

    $tile.addClass('tile-locked');
    $tile.addClass('tile-selected');
    tile.locked = clone(tile)

    $(window).on('mouseup.backsplash', $.proxy(this, 'onMouseup'));
    $(window).on('mousemove.backsplash', $.proxy(this, 'onMousemove'));

    if (!e.shiftKey) {
        for (var i = 0; i < this.selection.length; i++) {
            this.selection[i].$elem.removeClass('tile-selected');
        }
        this.selection = []
    }
    this.selection.push(tile);

    this.resetTiles();

}

Editor.prototype.onMousemove = function(e) {

    e.preventDefault();

    var origin = this.$elem.offset();
    var x = e.pageX - origin.left - this.mousedown.offsetX;
    var y = e.pageY - origin.top - this.mousedown.offsetY;

    var row = Math.floor(y / (this.opts.tile_size + this.opts.padding) + 0.5);
    var col = Math.floor(x / (this.opts.tile_size + this.opts.padding) + 0.5);

    var tile = this.selection[0];
    var changed = (tile.locked.row != row || tile.locked.col != col);
    tile.locked.row = row;
    tile.locked.col = col;

    if (changed) {
        this.resetTiles();
    }

    this.selection[0].$elem.css({left: x, top: y});

}

Editor.prototype.onMouseup = function(e) {

    e.preventDefault();
    e.stopPropagation()

    $(window).off('mouseup.backsplash');
    $(window).off('mousemove.backsplash');

    this.resetTiles();

    return false;
}

return Editor;

})();
<commit_msg>Fix key controls and a cloning bug<commit_after>backsplash.Editor = (function(){

var clone = backsplash._clone;

jQuery.fn.backsplashEditor = function(opts) {
    this.each(function() {
        var editor = new Editor(this, opts);
        $(this).data('backsplash-editor', editor);
    })
}

var Editor = function(elem, opts) {

    this.$elem = $(elem);
    this.opts = $.extend({}, this.$elem.data('backsplash'), opts);

    this.selection = []

    $(window).on('keydown.backsplash', $.proxy(this, 'onKeydown'));
    this.$elem.on('mousedown.backsplash', '.backsplash-tile', $.proxy(this, 'onMousedown'));
    this.$elem.on('click.backsplash', '.backsplash-tile', function(e) {
        e.preventDefault();
    });

    var editor = this;
    this.tiles = [];
    this.$elem.children().each(function() {

        var $tile = $(this);

        $tile.addClass('backsplash-tile');

        var tile = $tile.data('tile') || {};
        $tile.data('tile', tile);
        tile.$elem = $tile;

        editor.tiles.push(tile);
    })

}

Editor.prototype.resetTile = function(layout, old_tile, opts) {
    var new_tile = layout.add(old_tile, opts);
    old_tile.$elem.css(layout.css(new_tile));
    old_tile.row = new_tile.row;
    old_tile.col = new_tile.col;
}

Editor.prototype.resetTiles = function() {

    var layout = new backsplash.Layout(this.opts);

    for (var i = 0; i < this.tiles.length; i++) {
        if (this.tiles[i].locked) {
            this.resetTile(layout, this.tiles[i].locked)
        }
    }
    for (var i = 0; i < this.tiles.length; i++) {
        if (!this.tiles[i].locked) {
            this.resetTile(layout, this.tiles[i], {ignore_position: true})
        }
    }

    return layout;

}

Editor.prototype.onKeydown = function(e) {

    console.log(e);

    switch (e.which) {

        case 114: // r
            for (var i = 0; i < this.tiles.length; i++) {
                this.tiles[i].locked = null
                this.tiles[i].$elem.removeClass('tile-locked')
                this.tiles[i].$elem.removeClass('tile-selected')
            }
            this.resetTiles();
            break;

        case 38: // up
        case 40: // down
            e.preventDefault()
            for (var i = 0; i < this.selection.length; i++) {
                if (e.metaKey) {
                    this.selection[i].locked.height += e.which == 40 ? 1 : -1;
                    if (this.opts.resized) {
                        this.opts.resized(this.selection[i].locked, this);
                    }
                } else {
                    this.selection[i].locked.row += e.which == 40 ? 1 : -1;
                }
            }
            this.resetTiles();
            break;

        case 37: // left
        case 39: // right
            e.preventDefault()
            for (var i = 0; i < this.selection.length; i++) {
                if (e.metaKey) {
                    this.selection[i].locked.width += e.which == 39 ? 1 : -1;
                    if (this.opts.resized) {
                        this.opts.resized(this.selection[i].locked, this);
                    }
                } else {
                    this.selection[i].locked.col += e.which == 39 ? 1 : -1;
                }
            }
            this.resetTiles();
            break;

        default:
            console.log('unknown key', e.which, e)
    }

}

Editor.prototype.onMousedown = function(e) {

    e.preventDefault();
    this.mousedown = e;

    var $tile = $(e.target).closest('.backsplash-tile');
    var tile = $tile.data('tile');

    console.log($tile, tile);

    $tile.addClass('tile-locked');
    $tile.addClass('tile-selected');
    tile.locked = clone(tile.locked || tile)

    $(window).on('mouseup.backsplash', $.proxy(this, 'onMouseup'));
    $(window).on('mousemove.backsplash', $.proxy(this, 'onMousemove'));

    if (!e.shiftKey) {
        for (var i = 0; i < this.selection.length; i++) {
            this.selection[i].$elem.removeClass('tile-selected');
        }
        this.selection = []
    }
    this.selection.push(tile);

    this.resetTiles();

}

Editor.prototype.onMousemove = function(e) {

    e.preventDefault();

    var origin = this.$elem.offset();
    var x = e.pageX - origin.left - this.mousedown.offsetX;
    var y = e.pageY - origin.top - this.mousedown.offsetY;

    var row = Math.floor(y / (this.opts.tile_size + this.opts.padding) + 0.5);
    var col = Math.floor(x / (this.opts.tile_size + this.opts.padding) + 0.5);

    var tile = this.selection[0];
    var changed = (tile.locked.row != row || tile.locked.col != col);
    tile.locked.row = row;
    tile.locked.col = col;

    if (changed) {
        this.resetTiles();
    }

    this.selection[0].$elem.css({left: x, top: y});

}

Editor.prototype.onMouseup = function(e) {

    e.preventDefault();
    e.stopPropagation()

    $(window).off('mouseup.backsplash');
    $(window).off('mousemove.backsplash');

    this.resetTiles();

    return false;
}

return Editor;

})();
<|endoftext|>


<commit_before>foam.CLASS({
  refines: 'foam.core.InnerClass',
  requires: [
    'foam.swift.Method',
    'foam.swift.Argument',
  ],
  methods: [
    function writeToSwiftClass(cls) {
      if ( !this.model.generateSwift ) return;
      var innerClass = this.model.buildClass();
      var innerSwiftClass = innerClass.toSwiftClass();
      innerSwiftClass.imports = [];
      cls.classes.push(innerSwiftClass);

      cls.methods.push(this.Method.create({
        name: this.model.swiftName + '_create',
        returnType: this.model.swiftName,
        visibility: 'public',
	body: this.swiftInitializer(),
        args: [
          this.Argument.create({
            localName: 'args',
            defaultValue: '[:]',
            type: '[String:Any?]',
          }),
        ],
      }));
    }
  ],
  templates: [
    {
      name: 'swiftInitializer',
      args: [],
      template: function() {/*
__subContext__.registerClass(cls: <%=this.model.swiftName%>.classInfo())
return __subContext__.create(<%=this.model.swiftName%>.self, args: args)!
      */},
    },
  ],
});
<commit_msg>Don't register InnerClasses in swift. This might change in the future but the code to register wasn't fully thought through so we'll simplify it for now.<commit_after>foam.CLASS({
  refines: 'foam.core.InnerClass',
  requires: [
    'foam.swift.Method',
    'foam.swift.Argument',
  ],
  methods: [
    function writeToSwiftClass(cls) {
      if ( !this.model.generateSwift ) return;
      var innerClass = this.model.buildClass();
      var innerSwiftClass = innerClass.toSwiftClass();
      innerSwiftClass.imports = [];
      cls.classes.push(innerSwiftClass);

      cls.methods.push(this.Method.create({
        name: this.model.swiftName + '_create',
        returnType: this.model.swiftName,
        visibility: 'public',
	body: this.swiftInitializer(),
        args: [
          this.Argument.create({
            localName: 'args',
            defaultValue: '[:]',
            type: '[String:Any?]',
          }),
        ],
      }));
    }
  ],
  templates: [
    {
      name: 'swiftInitializer',
      args: [],
      template: function() {/*
return <%=this.model.swiftName%>(args, __subContext__)
      */},
    },
  ],
});
<|endoftext|>


<commit_before>export {Base, HTMLProgress};

/** Do nothing when receives value, max and done. */
class Base {
  /**
   * Handle current value and maximum value.
   * @param {object} valueMax An object with property valuePercentage and maxPercentage. e.g. { valuePercentage: 20, maxPercentage: 100 }
   */
  setValueMax(valueMax) {}

  /**
   * Inform the process is done.
   * @param {any} doneValue Any value.
   */
  informDone(doneValue) {}
}

/** Dummy receiver which discards all information. */
Base.dummy = new Base();

/**
 * Report progress to HTMLProgressElement.
 */
class HTMLProgress extends Base {
  /** @param {HTMLProgressElement} htmlProgress The HTMLProgressElement for reporting progress. can not null. */
  constructor(htmlProgress) {
    super();
    this.htmlProgress = htmlProgress;
  }

  /** Set HTMLProgressElement.value and HTMLProgressElement.max to valueMax.valuePercentage and valueMax.maxPercentage. */
  setValueMax(valueMax) {
    this.htmlProgress.value = valueMax.valuePercentage;
    this.htmlProgress.max = valueMax.maxPercentage;
  }

  /** Call HTMLProgressElement.onclick(). */
  informDone(doneValue) {
    this.htmlProgress.dispatchEvent(new Event("click"));
  }
}

/**
 * @param {string} htmlProgressTitle The title of HTMLProgressElement.
 * @return
 *   Return a new ProgressReceiver.HTMLProgress, if found.
 *   Return the shared ProgressReceiver.Base.dummy, If not found.
 */
HTMLProgress.createByTitle_or_getDummy = function (htmlProgressTitle) {
  if (htmlProgressTitle) {
    let htmlProgress = document.querySelector(`progress[title="${htmlProgressTitle}"]`);
    if (htmlProgress)
      return new HTMLProgress(htmlProgress);
  }
  return Base.dummy;
}
<commit_msg>Update Receiver.js<commit_after>export {Base, HTMLProgress};

/** Do nothing when receives value, max and done. */
class Base {
  /**
   * @param {number} value The current value.
   * @param {number} max   The maximum value.
   */
  setValueMax( value, max ) {}

  /**
   * @param {number} value The current value.
   */
  setValue( value ) {}

  /**
   * @param {number} max   The maximum value.
   */
  setMax( max ) {}

  /**
   * Inform the process is done.
   * @param {any} doneValue Any value.
   */
  informDone(doneValue) {}
}

/** Dummy receiver which discards all information. */
Base.dummy = new Base();

/**
 * Report progress to HTMLProgressElement.
 */
class HTMLProgress extends Base {
  /** @param {HTMLProgressElement} htmlProgress The HTMLProgressElement for reporting progress. can not null. */
  constructor(htmlProgress) {
    super();
    this.htmlProgress = htmlProgress;
  }

  /** Set HTMLProgressElement.value and HTMLProgressElement.max to valueMax.valuePercentage and valueMax.maxPercentage. */
  setValueMax(valueMax) {
    this.htmlProgress.value = valueMax.valuePercentage;
    this.htmlProgress.max = valueMax.maxPercentage;
  }

  /**
   * Set HTMLProgressElement.value and HTMLProgressElement.max to value and max.
   * @param {number} value The current value.
   * @param {number} max   The maximum value.
   */
  setValueMax( value, max ) {
    this.htmlProgress.value = value;
    this.htmlProgress.max = max;
  }

  /**
   * Set HTMLProgressElement.value to value.
   * @param {number} value The current value.
   */
  setValue( value ) {
    this.htmlProgress.value = value;
  }

  /**
   * HTMLProgressElement.max max.
   * @param {number} max   The maximum value.
   */
  setMax( max ) {
    this.htmlProgress.max = max;
  }

  /** Call HTMLProgressElement.onclick(). */
  informDone(doneValue) {
    this.htmlProgress.dispatchEvent(new Event("click"));
  }
}

/**
 * @param {string} htmlProgressTitle The title of HTMLProgressElement.
 * @return
 *   Return a new ProgressReceiver.HTMLProgress, if found.
 *   Return the shared ProgressReceiver.Base.dummy, If not found.
 */
HTMLProgress.createByTitle_or_getDummy = function (htmlProgressTitle) {
  if (htmlProgressTitle) {
    let htmlProgress = document.querySelector(`progress[title="${htmlProgressTitle}"]`);
    if (htmlProgress)
      return new HTMLProgress(htmlProgress);
  }
  return Base.dummy;
}
<|endoftext|>


<commit_before>/*
 *
 * (c) Copyright Ascensio System Limited 2010-2018
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
 * EU, LV-1021.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
*/
/**
 *  ComboBorderSize.js
 *
 *  Created by Julia Radzhabova on 2/10/14
 *  Copyright (c) 2018 Ascensio System SIA. All rights reserved.
 *
 */

/**
 *  Using template
 *
 *

 *

 *

 *      <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"></button>
 *

 *

 *
 */

if (Common === undefined)
    var Common = {};

define([
    'common/main/lib/component/ComboBox'
], function () {
    'use strict';

    Common.UI.BordersModel = Backbone.Model.extend({
        defaults: function() {
            return {
                value: null,
                displayValue: null,
                pxValue: null,
                id: Common.UI.getId(),
                offsety: undefined
            }
        }
    });

    Common.UI.BordersStore = Backbone.Collection.extend({
        model: Common.UI.BordersModel
    });

    Common.UI.ComboBorderSize = Common.UI.ComboBox.extend(_.extend({
        template: _.template([
            '<div class="input-group combobox combo-border-size input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
                '<div class="form-control" style="<%= style %>">
',
                '

',
                '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"></button>',
                '<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
                    '<% _.each(items, function(item) { %>',
                        '<li id="<%= item.id %>" data-value="<%= item.value %>">',
                            '<%= item.displayValue %>',
                            '<% if (item.offsety!==undefined) { %>',
                                '<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" align="right" style="background-position: 0 -<%= item.offsety %>px;">',
                            '<% } %>',
                        '
',
                    '<% }); %>',
                '
',
            '
'
        ].join('')),

        initialize : function(options) {
            var txtPt = Common.Utils.Metric.getMetricName(Common.Utils.Metric.c_MetricUnits.pt),
                data = [
                    {displayValue: '0.5 ' + txtPt,   value: 0.5, pxValue: 0.5, offsety: 0},
                    {displayValue: '1 ' + txtPt,     value: 1,   pxValue: 1, offsety: 20},
                    {displayValue: '1.5 ' + txtPt,   value: 1.5, pxValue: 2, offsety: 40},
                    {displayValue: '2.25 ' + txtPt,  value: 2.25,pxValue: 3, offsety: 60},
                    {displayValue: '3 ' + txtPt,     value: 3,   pxValue: 4, offsety: 80},
                    {displayValue: '4.5 ' + txtPt,   value: 4.5, pxValue: 5, offsety: 100},
                    {displayValue: '6 ' + txtPt,     value: 6,   pxValue: 6, offsety: 120}
                ];
            if (options.allowNoBorders !== false)
                data.unshift({displayValue: this.txtNoBorders, value: 0, pxValue: 0 });

            Common.UI.ComboBox.prototype.initialize.call(this, _.extend({
                editable: false,
                store: new Common.UI.BordersStore(),
                data: data,
                menuStyle: 'min-width: 150px;'
            }, options));
        },

        render : function(parentEl) {
            Common.UI.ComboBox.prototype.render.call(this, parentEl);
            return this;
        },

        itemClicked: function (e) {
            var el = $(e.currentTarget).parent();

            this._selectedItem = this.store.findWhere({
                id: el.attr('id')
            });
            if (this._selectedItem) {
                $('.selected', $(this.el)).removeClass('selected');
                el.addClass('selected');
                this.updateFormControl(this._selectedItem);

                this.trigger('selected', this, _.extend({}, this._selectedItem.toJSON()), e);
                e.preventDefault();
            }
        },

        updateFormControl: function(record) {
            var formcontrol = $(this.el).find('.form-control');

            if (record.get('value')>0) {
                formcontrol[0].innerHTML = '';
                formcontrol.removeClass('text').addClass('image');
                formcontrol.css('background-position', '0 -' + record.get('offsety') + 'px');
            } else {
                formcontrol[0].innerHTML = this.txtNoBorders;
                formcontrol.removeClass('image').addClass('text');
            }
        },

        setValue: function(value) {
            this._selectedItem = (value===null || value===undefined) ? undefined : _.find(this.store.models, function(item) {
                if ( value<item.attributes.value+0.01 && value>item.attributes.value-0.01) {
                    return true;
                }
            });

            $('.selected', $(this.el)).removeClass('selected');

            if (this._selectedItem) {
                this.updateFormControl(this._selectedItem);
                $('#' + this._selectedItem.get('id'), $(this.el)).addClass('selected');
            } else {
                var formcontrol = $(this.el).find('.form-control');
                formcontrol[0].innerHTML = '';
                formcontrol.removeClass('image').addClass('text');
            }
        },

        txtNoBorders: 'No Borders'
    }, Common.UI.ComboBorderSize || {}));

    Common.UI.ComboBorderSizeEditable = Common.UI.ComboBox.extend(_.extend({
        template: _.template([
            '<span class="input-group combobox combo-border-size input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
                '<input type="text" class="form-control text">',
                '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"></button>',
                '<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
                    '<% _.each(items, function(item) { %>',
                        '<li id="<%= item.id %>" data-value="<%= item.value %>">',
                            '<%= item.displayValue %>',
                            '<% if (item.offsety!==undefined) { %>',
                             '<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" align="right" style="background-position: 0 -<%= item.offsety %>px;">',
                            '<% } %>',
                        '
',
                    '<% }); %>',
                '
',
            ''
        ].join('')),

        initialize : function(options) {
            this.txtNoBorders = options.txtNoBorders || this.txtNoBorders;
            var txtPt = Common.Utils.Metric.getMetricName(Common.Utils.Metric.c_MetricUnits.pt),
                data = [
                    {displayValue: '0.5 ' + txtPt,   value: 0.5, pxValue: 0.5, offsety: 0},
                    {displayValue: '1 ' + txtPt,     value: 1,   pxValue: 1, offsety: 20},
                    {displayValue: '1.5 ' + txtPt,   value: 1.5, pxValue: 2, offsety: 40},
                    {displayValue: '2.25 ' + txtPt,  value: 2.25,pxValue: 3, offsety: 60},
                    {displayValue: '3 ' + txtPt,     value: 3,   pxValue: 4, offsety: 80},
                    {displayValue: '4.5 ' + txtPt,   value: 4.5, pxValue: 5, offsety: 100},
                    {displayValue: '6 ' + txtPt,     value: 6,   pxValue: 6, offsety: 120}
                ];

            if (options.allowNoBorders !== false)
                data.unshift({displayValue: this.txtNoBorders, value: 0, pxValue: 0 });

            Common.UI.ComboBox.prototype.initialize.call(this, _.extend({
                editable: true,
                store: new Common.UI.BordersStore(),
                data: data,
                menuStyle: 'min-width: 150px;'
            }, options));
        },

        render : function(parentEl) {
            Common.UI.ComboBox.prototype.render.call(this, parentEl);
            return this;
        },

        txtNoBorders: 'No Borders'
    }, Common.UI.ComboBorderSizeEditable || {}));

    Common.UI.ComboBorderType = Common.UI.ComboBorderSize.extend(_.extend({
        template: _.template([
            '<div class="input-group combobox combo-border-size input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
                '<div class="form-control" style="<%= style %>">
',
                '

',
                '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"></button>',
                '<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
                    '<% _.each(items, function(item) { %>',
                        '<li id="<%= item.id %>" data-value="<%= item.value %>">',
                            '',
                            '<% if (item.offsety!==undefined) { %>',
                                '<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" align="left" style="background-position: 0 -<%= item.offsety %>px;">',
                            '<% } %>',
                        '
',
                    '<% }); %>',
                '
',
            '
'
        ].join('')),

        initialize : function(options) {
            Common.UI.ComboBorderSize.prototype.initialize.call(this, _.extend({
                store: new Common.UI.BordersStore(),
                data: [
                    {value: Asc.c_oDashType.solid, offsety: 140},
                    {value: Asc.c_oDashType.sysDot, offsety: 160},
                    {value: Asc.c_oDashType.sysDash, offsety: 180},
                    {value: Asc.c_oDashType.dash, offsety: 200},
                    {value: Asc.c_oDashType.dashDot, offsety: 220},
                    {value: Asc.c_oDashType.lgDash, offsety: 240},
                    {value: Asc.c_oDashType.lgDashDot, offsety: 260},
                    {value: Asc.c_oDashType.lgDashDotDot, offsety: 280}
                ]
            }, options));
        },

        render : function(parentEl) {
            Common.UI.ComboBorderSize.prototype.render.call(this, parentEl);
            return this;
        },

        updateFormControl: function(record) {
            var formcontrol = $(this.el).find('.form-control');
            formcontrol[0].innerHTML = '';
            formcontrol.removeClass('text').addClass('image');
            formcontrol.css('background-position', '0 -' + record.get('offsety') + 'px');
        }
    }, Common.UI.ComboBorderType || {}));
});<commit_msg>FIx Bug 38497<commit_after>/*
 *
 * (c) Copyright Ascensio System Limited 2010-2018
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia,
 * EU, LV-1021.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
*/
/**
 *  ComboBorderSize.js
 *
 *  Created by Julia Radzhabova on 2/10/14
 *  Copyright (c) 2018 Ascensio System SIA. All rights reserved.
 *
 */

/**
 *  Using template
 *
 *

 *

 *

 *      <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"></button>
 *

 *

 *
 */

if (Common === undefined)
    var Common = {};

define([
    'common/main/lib/component/ComboBox'
], function () {
    'use strict';

    Common.UI.BordersModel = Backbone.Model.extend({
        defaults: function() {
            return {
                value: null,
                displayValue: null,
                pxValue: null,
                id: Common.UI.getId(),
                offsety: undefined
            }
        }
    });

    Common.UI.BordersStore = Backbone.Collection.extend({
        model: Common.UI.BordersModel
    });

    Common.UI.ComboBorderSize = Common.UI.ComboBox.extend(_.extend({
        template: _.template([
            '<div class="input-group combobox combo-border-size input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
                '<div class="form-control" style="padding-top:2px; <%= style %>">
',
                '

',
                '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"></button>',
                '<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
                    '<% _.each(items, function(item) { %>',
                        '<li id="<%= item.id %>" data-value="<%= item.value %>">',
                            '<%= item.displayValue %>',
                            '<% if (item.offsety!==undefined) { %>',
                                '<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" align="right" style="background-position: 0 -<%= item.offsety %>px;">',
                            '<% } %>',
                        '
',
                    '<% }); %>',
                '
',
            '
'
        ].join('')),

        initialize : function(options) {
            var txtPt = Common.Utils.Metric.getMetricName(Common.Utils.Metric.c_MetricUnits.pt),
                data = [
                    {displayValue: '0.5 ' + txtPt,   value: 0.5, pxValue: 0.5, offsety: 0},
                    {displayValue: '1 ' + txtPt,     value: 1,   pxValue: 1, offsety: 20},
                    {displayValue: '1.5 ' + txtPt,   value: 1.5, pxValue: 2, offsety: 40},
                    {displayValue: '2.25 ' + txtPt,  value: 2.25,pxValue: 3, offsety: 60},
                    {displayValue: '3 ' + txtPt,     value: 3,   pxValue: 4, offsety: 80},
                    {displayValue: '4.5 ' + txtPt,   value: 4.5, pxValue: 5, offsety: 100},
                    {displayValue: '6 ' + txtPt,     value: 6,   pxValue: 6, offsety: 120}
                ];
            if (options.allowNoBorders !== false)
                data.unshift({displayValue: this.txtNoBorders, value: 0, pxValue: 0 });

            Common.UI.ComboBox.prototype.initialize.call(this, _.extend({
                editable: false,
                store: new Common.UI.BordersStore(),
                data: data,
                menuStyle: 'min-width: 150px;'
            }, options));
        },

        render : function(parentEl) {
            Common.UI.ComboBox.prototype.render.call(this, parentEl);
            return this;
        },

        itemClicked: function (e) {
            var el = $(e.currentTarget).parent();

            this._selectedItem = this.store.findWhere({
                id: el.attr('id')
            });
            if (this._selectedItem) {
                $('.selected', $(this.el)).removeClass('selected');
                el.addClass('selected');
                this.updateFormControl(this._selectedItem);

                this.trigger('selected', this, _.extend({}, this._selectedItem.toJSON()), e);
                e.preventDefault();
            }
        },

        updateFormControl: function(record) {
            var formcontrol = $(this.el).find('.form-control');

            if (record.get('value')>0) {
                formcontrol[0].innerHTML = '';
                formcontrol.removeClass('text').addClass('image');
                formcontrol.css('background-position', '0 -' + record.get('offsety') + 'px');
            } else {
                formcontrol[0].innerHTML = this.txtNoBorders;
                formcontrol.removeClass('image').addClass('text');
            }
        },

        setValue: function(value) {
            this._selectedItem = (value===null || value===undefined) ? undefined : _.find(this.store.models, function(item) {
                if ( value<item.attributes.value+0.01 && value>item.attributes.value-0.01) {
                    return true;
                }
            });

            $('.selected', $(this.el)).removeClass('selected');

            if (this._selectedItem) {
                this.updateFormControl(this._selectedItem);
                $('#' + this._selectedItem.get('id'), $(this.el)).addClass('selected');
            } else {
                var formcontrol = $(this.el).find('.form-control');
                formcontrol[0].innerHTML = '';
                formcontrol.removeClass('image').addClass('text');
            }
        },

        txtNoBorders: 'No Borders'
    }, Common.UI.ComboBorderSize || {}));

    Common.UI.ComboBorderSizeEditable = Common.UI.ComboBox.extend(_.extend({
        template: _.template([
            '<span class="input-group combobox combo-border-size input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
                '<input type="text" class="form-control text">',
                '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"></button>',
                '<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
                    '<% _.each(items, function(item) { %>',
                        '<li id="<%= item.id %>" data-value="<%= item.value %>">',
                            '<%= item.displayValue %>',
                            '<% if (item.offsety!==undefined) { %>',
                             '<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" align="right" style="background-position: 0 -<%= item.offsety %>px;">',
                            '<% } %>',
                        '
',
                    '<% }); %>',
                '
',
            ''
        ].join('')),

        initialize : function(options) {
            this.txtNoBorders = options.txtNoBorders || this.txtNoBorders;
            var txtPt = Common.Utils.Metric.getMetricName(Common.Utils.Metric.c_MetricUnits.pt),
                data = [
                    {displayValue: '0.5 ' + txtPt,   value: 0.5, pxValue: 0.5, offsety: 0},
                    {displayValue: '1 ' + txtPt,     value: 1,   pxValue: 1, offsety: 20},
                    {displayValue: '1.5 ' + txtPt,   value: 1.5, pxValue: 2, offsety: 40},
                    {displayValue: '2.25 ' + txtPt,  value: 2.25,pxValue: 3, offsety: 60},
                    {displayValue: '3 ' + txtPt,     value: 3,   pxValue: 4, offsety: 80},
                    {displayValue: '4.5 ' + txtPt,   value: 4.5, pxValue: 5, offsety: 100},
                    {displayValue: '6 ' + txtPt,     value: 6,   pxValue: 6, offsety: 120}
                ];

            if (options.allowNoBorders !== false)
                data.unshift({displayValue: this.txtNoBorders, value: 0, pxValue: 0 });

            Common.UI.ComboBox.prototype.initialize.call(this, _.extend({
                editable: true,
                store: new Common.UI.BordersStore(),
                data: data,
                menuStyle: 'min-width: 150px;'
            }, options));
        },

        render : function(parentEl) {
            Common.UI.ComboBox.prototype.render.call(this, parentEl);
            return this;
        },

        txtNoBorders: 'No Borders'
    }, Common.UI.ComboBorderSizeEditable || {}));

    Common.UI.ComboBorderType = Common.UI.ComboBorderSize.extend(_.extend({
        template: _.template([
            '<div class="input-group combobox combo-border-size input-group-nr <%= cls %>" id="<%= id %>" style="<%= style %>">',
                '<div class="form-control" style="<%= style %>">
',
                '

',
                '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"></button>',
                '<ul class="dropdown-menu <%= menuCls %>" style="<%= menuStyle %>" role="menu">',
                    '<% _.each(items, function(item) { %>',
                        '<li id="<%= item.id %>" data-value="<%= item.value %>">',
                            '',
                            '<% if (item.offsety!==undefined) { %>',
                                '<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" align="left" style="background-position: 0 -<%= item.offsety %>px;">',
                            '<% } %>',
                        '
',
                    '<% }); %>',
                '
',
            '
'
        ].join('')),

        initialize : function(options) {
            Common.UI.ComboBorderSize.prototype.initialize.call(this, _.extend({
                store: new Common.UI.BordersStore(),
                data: [
                    {value: Asc.c_oDashType.solid, offsety: 140},
                    {value: Asc.c_oDashType.sysDot, offsety: 160},
                    {value: Asc.c_oDashType.sysDash, offsety: 180},
                    {value: Asc.c_oDashType.dash, offsety: 200},
                    {value: Asc.c_oDashType.dashDot, offsety: 220},
                    {value: Asc.c_oDashType.lgDash, offsety: 240},
                    {value: Asc.c_oDashType.lgDashDot, offsety: 260},
                    {value: Asc.c_oDashType.lgDashDotDot, offsety: 280}
                ]
            }, options));
        },

        render : function(parentEl) {
            Common.UI.ComboBorderSize.prototype.render.call(this, parentEl);
            return this;
        },

        updateFormControl: function(record) {
            var formcontrol = $(this.el).find('.form-control');
            formcontrol[0].innerHTML = '';
            formcontrol.removeClass('text').addClass('image');
            formcontrol.css('background-position', '0 -' + record.get('offsety') + 'px');
        }
    }, Common.UI.ComboBorderType || {}));
});<|endoftext|>


<commit_before>import _ from 'underscore';
import Field from '../Field';
import React from 'react';
import tinymce from 'tinymce';
import { FormInput } from 'elemental';

/**
 * TODO:
 * - Remove dependency on underscore
 */

var lastId = 0;

function getId() {
	return 'keystone-html-' + lastId++;
}

module.exports = Field.create({

	displayName: 'HtmlField',

	getInitialState () {
		return {
			id: getId(),
			isFocused: false
		};
	},

	initWysiwyg () {
		if (!this.props.wysiwyg) return;

		var self = this;
		var opts = this.getOptions();

		opts.setup = function (editor) {
			self.editor = editor;
			editor.on('change', self.valueChanged);
			editor.on('focus', self.focusChanged.bind(self, true));
			editor.on('blur', self.focusChanged.bind(self, false));
		};

		this._currentValue = this.props.value;
		tinymce.init(opts);
	},

	componentDidUpdate (prevProps, prevState) {
		if (prevState.isCollapsed && !this.state.isCollapsed) {
			this.initWysiwyg();
		}

		if (_.isEqual(this.props.dependsOn, this.props.currentDependencies)
			&& !_.isEqual(this.props.currentDependencies, prevProps.currentDependencies)) {
			var instance = tinymce.get(prevState.id);
			if (instance) {
				tinymce.EditorManager.execCommand('mceRemoveEditor', true, prevState.id);
				this.initWysiwyg();
			} else {
				this.initWysiwyg();
			}
		}
	},

	componentDidMount () {
		this.initWysiwyg();
	},

	componentWillReceiveProps (nextProps) {
		if (this.editor && this._currentValue !== nextProps.value) {
			this.editor.setContent(nextProps.value);
		}
	},

	focusChanged (focused) {
		this.setState({
			isFocused: focused
		});
	},

	valueChanged  () {
		var content;
		if (this.editor) {
			content = this.editor.getContent();
		} else if (this.refs.editor) {
			content = this.refs.editor.getDOMNode().value;
		} else {
			return;
		}

		this._currentValue = content;
		this.props.onChange({
			path: this.props.path,
			value: content
		});
	},

	getOptions () {
		var plugins = ['code', 'link'],
			options = _.defaults(
				{},
				this.props.wysiwyg,
				Keystone.wysiwyg.options
			),
			toolbar = options.overrideToolbar ? '' : 'bold italic | alignleft aligncenter alignright | bullist numlist | outdent indent | link',
			i;

		if (options.enableImages) {
			plugins.push('image');
			toolbar += ' | image';
		}

		if (options.enableCloudinaryUploads || options.enableS3Uploads) {
			plugins.push('uploadimage');
			toolbar += options.enableImages ? ' uploadimage' : ' | uploadimage';
		}

		if (options.additionalButtons) {
			var additionalButtons = options.additionalButtons.split(',');
			for (i = 0; i < additionalButtons.length; i++) {
				toolbar += (' | ' + additionalButtons[i]);
			}
		}
		if (options.additionalPlugins) {
			var additionalPlugins = options.additionalPlugins.split(',');
			for (i = 0; i < additionalPlugins.length; i++) {
				plugins.push(additionalPlugins[i]);
			}
		}
		if (options.importcss) {
			plugins.push('importcss');
			var importcssOptions = {
				content_css: options.importcss,
				importcss_append: true,
				importcss_merge_classes: true
			};

			Object.assign(options.additionalOptions, importcssOptions);
		}

		if (!options.overrideToolbar) {
			toolbar += ' | code';
		}

		var opts = {
			selector: '#' + this.state.id,
			toolbar:  toolbar,
			plugins:  plugins,
			menubar:  options.menubar || false,
			skin:     options.skin || 'keystone'
		};

		if (this.shouldRenderField()) {
			opts.uploadimage_form_url = options.enableS3Uploads ? '/keystone/api/s3/upload' : '/keystone/api/cloudinary/upload';
		} else {
			Object.assign(opts, {
				mode: 'textareas',
				readonly: true,
				menubar: false,
				toolbar: 'code',
				statusbar: false
			});
		}

		if (options.additionalOptions){
			Object.assign(opts, options.additionalOptions);
		}

		return opts;
	},

	getFieldClassName () {
		var className = this.props.wysiwyg ? 'wysiwyg' : 'code';
		return className;
	},

	renderField () {
		var className = this.state.isFocused ? 'is-focused' : '';
		var style = {
			height: this.props.height
		};
		return (

				<FormInput multiline ref="editor" style={style} onChange={this.valueChanged} id={this.state.id} className={this.getFieldClassName()} name={this.props.path} value={this.props.value} />

		);
	},

	renderValue () {
		return <FormInput multiline noedit value={this.props.value} />;
	}

});
<commit_msg>Remove `underscore` dependency in `HtmlField`<commit_after>import _ from 'underscore';
import Field from '../Field';
import React from 'react';
import tinymce from 'tinymce';
import { FormInput } from 'elemental';

/**
 * TODO:
 * - Remove dependency on underscore
 */

var lastId = 0;

function getId() {
	return 'keystone-html-' + lastId++;
}

module.exports = Field.create({

	displayName: 'HtmlField',

	getInitialState () {
		return {
			id: getId(),
			isFocused: false
		};
	},

	initWysiwyg () {
		if (!this.props.wysiwyg) return;

		var self = this;
		var opts = this.getOptions();

		opts.setup = function (editor) {
			self.editor = editor;
			editor.on('change', self.valueChanged);
			editor.on('focus', self.focusChanged.bind(self, true));
			editor.on('blur', self.focusChanged.bind(self, false));
		};

		this._currentValue = this.props.value;
		tinymce.init(opts);
	},

	componentDidUpdate (prevProps, prevState) {
		if (prevState.isCollapsed && !this.state.isCollapsed) {
			this.initWysiwyg();
		}

		if (_.isEqual(this.props.dependsOn, this.props.currentDependencies)
			&& !_.isEqual(this.props.currentDependencies, prevProps.currentDependencies)) {
			var instance = tinymce.get(prevState.id);
			if (instance) {
				tinymce.EditorManager.execCommand('mceRemoveEditor', true, prevState.id);
				this.initWysiwyg();
			} else {
				this.initWysiwyg();
			}
		}
	},

	componentDidMount () {
		this.initWysiwyg();
	},

	componentWillReceiveProps (nextProps) {
		if (this.editor && this._currentValue !== nextProps.value) {
			this.editor.setContent(nextProps.value);
		}
	},

	focusChanged (focused) {
		this.setState({
			isFocused: focused
		});
	},

	valueChanged  () {
		var content;
		if (this.editor) {
			content = this.editor.getContent();
		} else if (this.refs.editor) {
			content = this.refs.editor.getDOMNode().value;
		} else {
			return;
		}

		this._currentValue = content;
		this.props.onChange({
			path: this.props.path,
			value: content
		});
	},

	getOptions () {
		var plugins = ['code', 'link'],
			options = Object.assign(
				{},
				Keystone.wysiwyg.options,
				this.props.wysiwyg
			),
			toolbar = options.overrideToolbar ? '' : 'bold italic | alignleft aligncenter alignright | bullist numlist | outdent indent | link',
			i;

		if (options.enableImages) {
			plugins.push('image');
			toolbar += ' | image';
		}

		if (options.enableCloudinaryUploads || options.enableS3Uploads) {
			plugins.push('uploadimage');
			toolbar += options.enableImages ? ' uploadimage' : ' | uploadimage';
		}

		if (options.additionalButtons) {
			var additionalButtons = options.additionalButtons.split(',');
			for (i = 0; i < additionalButtons.length; i++) {
				toolbar += (' | ' + additionalButtons[i]);
			}
		}
		if (options.additionalPlugins) {
			var additionalPlugins = options.additionalPlugins.split(',');
			for (i = 0; i < additionalPlugins.length; i++) {
				plugins.push(additionalPlugins[i]);
			}
		}
		if (options.importcss) {
			plugins.push('importcss');
			var importcssOptions = {
				content_css: options.importcss,
				importcss_append: true,
				importcss_merge_classes: true
			};

			Object.assign(options.additionalOptions, importcssOptions);
		}

		if (!options.overrideToolbar) {
			toolbar += ' | code';
		}

		var opts = {
			selector: '#' + this.state.id,
			toolbar:  toolbar,
			plugins:  plugins,
			menubar:  options.menubar || false,
			skin:     options.skin || 'keystone'
		};

		if (this.shouldRenderField()) {
			opts.uploadimage_form_url = options.enableS3Uploads ? '/keystone/api/s3/upload' : '/keystone/api/cloudinary/upload';
		} else {
			Object.assign(opts, {
				mode: 'textareas',
				readonly: true,
				menubar: false,
				toolbar: 'code',
				statusbar: false
			});
		}

		if (options.additionalOptions){
			Object.assign(opts, options.additionalOptions);
		}

		return opts;
	},

	getFieldClassName () {
		var className = this.props.wysiwyg ? 'wysiwyg' : 'code';
		return className;
	},

	renderField () {
		var className = this.state.isFocused ? 'is-focused' : '';
		var style = {
			height: this.props.height
		};
		return (

				<FormInput multiline ref="editor" style={style} onChange={this.valueChanged} id={this.state.id} className={this.getFieldClassName()} name={this.props.path} value={this.props.value} />

		);
	},

	renderValue () {
		return <FormInput multiline noedit value={this.props.value} />;
	}

});
<|endoftext|>


<commit_before>const checkForDuplicateIssue = require('./utils/check-for-duplicate-issue')
const handlerSetup = require('./utils/handler-setup')
const { assignFlow, lineBreak } = require('./utils/helpers')
const chunkDiff = require('./utils/chunk-diff')
const parseChunk = require('./utils/parse-chunk')
const reopenClosed = require('./utils/reopen-closed')
const { issue } = require('./templates')

module.exports = async context => {
  // Only trigger push handler on pushes to master
  if (context.payload.ref !== `refs/heads/${context.payload.repository.master_branch}`) {
    return
  }

  // Do not trigger on merge commits
  const commit = await context.github.gitdata.getCommit(context.repo({sha: context.payload.head_commit.id}))
  if (commit.data.parents.length > 1) return

  const [
    { regex, config, labels },
    chunks
  ] = await Promise.all([
    handlerSetup(context),
    chunkDiff(context)
  ])

  let match
  for (let i = 0; i < chunks.length; i++) {
    const chunk = chunks[i]

    while ((match = regex.exec(chunk)) !== null) {
      const parsed = parseChunk({ match, context, config })

      if (parsed.filename === '.github/config.yml') continue

      // Prevent duplicates
      const existingIssue = await checkForDuplicateIssue(context, parsed.title)
      if (existingIssue) {
        context.log(`Duplicate issue found with title [${parsed.title}]`)
        await reopenClosed({ context, config, issue: existingIssue }, parsed)
        continue
      }

      let body = issue(context.repo({
        sha: parsed.sha,
        assignedToString: parsed.assignedToString,
        range: parsed.range,
        filename: parsed.filename,
        keyword: parsed.keyword,
        body: parsed.body
      }))

<<<<<<< HEAD
      body = lineBreak(body)
=======
      const regEx = /\/?<br(?:\s\/)?>/g // Regular expression to match all occurences of '<br&gt'
      body = body.replace(regEx, '<br>')
>>>>>>> origin/Make-Line-Breaks-Work
      context.log(`Creating issue [${parsed.title}] in [${context.repo().owner}/${context.repo().repo}]`)
      await context.github.issues.create(context.repo({ title: parsed.title, body, labels, ...assignFlow(config, parsed.username) }))
    }
  }
}
<commit_msg>Fix merge conflict<commit_after>const checkForDuplicateIssue = require('./utils/check-for-duplicate-issue')
const handlerSetup = require('./utils/handler-setup')
const { assignFlow, lineBreak } = require('./utils/helpers')
const chunkDiff = require('./utils/chunk-diff')
const parseChunk = require('./utils/parse-chunk')
const reopenClosed = require('./utils/reopen-closed')
const { issue } = require('./templates')

module.exports = async context => {
  // Only trigger push handler on pushes to master
  if (context.payload.ref !== `refs/heads/${context.payload.repository.master_branch}`) {
    return
  }

  // Do not trigger on merge commits
  const commit = await context.github.gitdata.getCommit(context.repo({sha: context.payload.head_commit.id}))
  if (commit.data.parents.length > 1) return

  const [
    { regex, config, labels },
    chunks
  ] = await Promise.all([
    handlerSetup(context),
    chunkDiff(context)
  ])

  let match
  for (let i = 0; i < chunks.length; i++) {
    const chunk = chunks[i]

    while ((match = regex.exec(chunk)) !== null) {
      const parsed = parseChunk({ match, context, config })

      if (parsed.filename === '.github/config.yml') continue

      // Prevent duplicates
      const existingIssue = await checkForDuplicateIssue(context, parsed.title)
      if (existingIssue) {
        context.log(`Duplicate issue found with title [${parsed.title}]`)
        await reopenClosed({ context, config, issue: existingIssue }, parsed)
        continue
      }

      let body = issue(context.repo({
        sha: parsed.sha,
        assignedToString: parsed.assignedToString,
        range: parsed.range,
        filename: parsed.filename,
        keyword: parsed.keyword,
        body: parsed.body
      }))

      body = lineBreak(body)
      context.log(`Creating issue [${parsed.title}] in [${context.repo().owner}/${context.repo().repo}]`)
      await context.github.issues.create(context.repo({ title: parsed.title, body, labels, ...assignFlow(config, parsed.username) }))
    }
  }
}
<|endoftext|>


<commit_before>var g = require('../global')

module.exports = {
  connect: function(url) {
    return {
      authenticate: function(username, apiKey, callback) {
        var path = g.format(url + '/users/%s/authenticate', g.escape(username));
        g.log('info', "POST %s", path);
        g.rest.post(path, { data: apiKey }).on('complete', function(token, response) {
          if ( token instanceof Error)
            return callback(token);
          else if ( response.statusCode !== 200 )
            return callback(g.format("POST %s failed : %s", path, response.statusCode));

          callback(null, token);
        })
      }
    }
  },
  username: function(token) {
    return g.username(token);
  },
  tokenHeader: function(token) {
    return g.format('Token token="%s"', new Buffer(JSON.stringify(token)).toString('base64'))
  }
}
<commit_msg>add casLogin<commit_after>var g = require('../global')

module.exports = {
  connect: function(url) {
    return {
      casLogin: function(ticket, callback) {
        var path = g.format(url + '/users/login?ticket=%s', ticket);
        g.log('info', "POST %s", path);
        g.rest.post(path).on('complete', function(apiKey, response) {
          if ( apiKey instanceof Error)
            return callback(apiKey);
          else if ( response.statusCode !== 200 )
            return callback(g.format("POST %s failed : %s", path, response.statusCode));

          callback(null, apiKey);
        })
      },
      authenticate: function(username, apiKey, callback) {
        var path = g.format(url + '/users/%s/authenticate', g.escape(username));
        g.log('info', "POST %s", path);
        g.rest.post(path, { data: apiKey }).on('complete', function(token, response) {
          if ( token instanceof Error)
            return callback(token);
          else if ( response.statusCode !== 200 )
            return callback(g.format("POST %s failed : %s", path, response.statusCode));

          callback(null, token);
        })
      }
    }
  },
  username: function(token) {
    return g.username(token);
  },
  tokenHeader: function(token) {
    return g.format('Token token="%s"', new Buffer(JSON.stringify(token)).toString('base64'))
  }
}
<|endoftext|>


<commit_before>
var assert = require('assert');
var request = require('../');

test('Request inheritance', function(){
  assert(request.get('/') instanceof request.Request);
});

test('request() simple GET without callback', function(next){
  request('GET', 'test/test.request.js').end();
  next();
});

test('request() simple GET', function(next){
  request('GET', 'test/test.request.js').end(function(res){
    assert(res instanceof request.Response, 'respond with Response');
    assert(res.ok, 'response should be ok');
    assert(res.text, 'res.text');
    next();
  });
});

test('request() simple HEAD', function(next){
  request.head('test/test.request.js').end(function(res){
    assert(res instanceof request.Response, 'respond with Response');
    assert(res.ok, 'response should be ok');
    assert(!res.text, 'res.text');
    next();
  });
});

test('request() GET 5xx', function(next){
  request('GET', '/error').end(function(res){
    assert(!res.ok, 'response should not be ok');
    assert(res.error, 'response should be an error');
    assert(!res.clientError, 'response should not be a client error');
    assert(res.serverError, 'response should be a server error');
    next();
  });
});

test('request() GET 4xx', function(next){
  request('GET', '/notfound').end(function(res){
    assert(!res.ok, 'response should not be ok');
    assert(res.error, 'response should be an error');
    assert(res.clientError, 'response should be a client error');
    assert(!res.serverError, 'response should not be a server error');
    next();
  });
});

test('request() GET 404 Not Found', function(next){
  request('GET', '/notfound').end(function(res){
    assert(res.notFound, 'response should be .notFound');
    next();
  });
});

test('request() GET 400 Bad Request', function(next){
  request('GET', '/bad-request').end(function(res){
    assert(res.badRequest, 'response should be .badRequest');
    next();
  });
});

test('request() GET 401 Bad Request', function(next){
  request('GET', '/unauthorized').end(function(res){
    assert(res.unauthorized, 'response should be .unauthorized');
    next();
  });
});

test('request() GET 406 Not Acceptable', function(next){
  request('GET', '/not-acceptable').end(function(res){
    assert(res.notAcceptable, 'response should be .notAcceptable');
    next();
  });
});

test('request() GET 204 No Content', function(next){
  request('GET', '/no-content').end(function(res){
    assert(res.noContent, 'response should be .noContent');
    next();
  });
});

test('request() header parsing', function(next){
  request('GET', '/notfound').end(function(res){
    assert('text/plain' == res.header['content-type']);
    assert('Express' == res.header['x-powered-by']);
    next();
  });
});

test('request() .status', function(next){
  request('GET', '/notfound').end(function(res){
    assert(404 == res.status, 'response .status');
    assert(4 == res.statusType, 'response .statusType');
    next();
  });
});

test('get()', function(next){
  request.get('/notfound').end(function(res){
    assert(404 == res.status, 'response .status');
    assert(4 == res.statusType, 'response .statusType');
    next();
  });
});

test('patch()', function(next){
  request.patch('/user/12').end(function(res){
    assert('updated' == res.text, 'response text');
    next();
  });
});

test('put()', function(next){
  request.put('/user/12').end(function(res){
    assert('updated' == res.text, 'response text');
    next();
  });
});

test('post()', function(next){
  request.post('/user').end(function(res){
    assert('created' == res.text, 'response text');
    next();
  });
});

test('del()', function(next){
  request.del('/user/12').end(function(res){
    assert('deleted' == res.text, 'response text');
    next();
  });
});

test('post() data', function(next){
  request.post('/todo/item')
  .type('application/octet-stream')
  .send('tobi')
  .end(function(res){
    assert('added "tobi"' == res.text, 'response text');
    next();
  });
});

test('request .type()', function(next){
  request
  .post('/user/12/pet')
  .type('urlencoded')
  .send('pet=tobi')
  .end(function(res){
    assert('added pet "tobi"' == res.text, 'response text');
    next();
  });
});

test('request .type() with alias', function(next){
  request
  .post('/user/12/pet')
  .type('application/x-www-form-urlencoded')
  .send('pet=tobi')
  .end(function(res){
    assert('added pet "tobi"' == res.text, 'response text');
    next();
  });
});

test('request .get() with no data or callback', function(next){
  request.get('/echo-header/content-type');
  next();
});

test('request .send() with no data only', function(next){
  request.post('/user/5/pet').type('urlencoded').send('pet=tobi');
  next();
});

test('request .send() with callback only', function(next){
  request
  .get('/echo-header/accept')
  .set('Accept', 'foo/bar')
  .end(function(res){
    assert('foo/bar' == res.text);
    next();
  });
});

test('request .accept() with json', function(next){
  request
  .get('/echo-header/accept')
  .accept('json')
  .end(function(res){
    assert('application/json' == res.text);
    next();
  });
});

test('request .accept() with application/json', function(next){
  request
  .get('/echo-header/accept')
  .accept('application/json')
  .end(function(res){
    assert('application/json' == res.text);
    next();
  });
});

test('request .accept() with xml', function(next){
  request
  .get('/echo-header/accept')
  .accept('xml')
  .end(function(res){
    assert('application/xml' == res.text);
    next();
  });
});

test('request .accept() with application/xml', function(next){
  request
  .get('/echo-header/accept')
  .accept('application/xml')
  .end(function(res){
    assert('application/xml' == res.text);
    next();
  });
});

// FIXME: ie6 will POST rather than GET here due to data(),
//        but I'm not 100% sure why.  Newer IEs are OK.
test('request .end()', function(next){
  request
  .get('/echo-header/content-type')
  .set('Content-Type', 'text/plain')
  .send('wahoo')
  .end(function(res){
    assert('text/plain' == res.text);
    next();
  });
});

test('request .send()', function(next){
  request
  .get('/echo-header/content-type')
  .set('Content-Type', 'text/plain')
  .send('wahoo')
  .end(function(res){
    assert('text/plain' == res.text);
    next();
  });
});

test('request .set()', function(next){
  request
  .get('/echo-header/content-type')
  .set('Content-Type', 'text/plain')
  .send('wahoo')
  .end(function(res){
    assert('text/plain' == res.text);
    next();
  });
});

test('request .set(object)', function(next){
  request
  .get('/echo-header/content-type')
  .set({ 'Content-Type': 'text/plain' })
  .send('wahoo')
  .end(function(res){
    assert('text/plain' == res.text);
    next();
  });
});

test('POST urlencoded', function(next){
  request
  .post('/pet')
  .type('urlencoded')
  .send({ name: 'Manny', species: 'cat' })
  .end(function(res){
    assert('added Manny the cat' == res.text);
    next();
  });
});

test('POST json', function(next){
  request
  .post('/pet')
  .type('json')
  .send({ name: 'Manny', species: 'cat' })
  .end(function(res){
    assert('added Manny the cat' == res.text);
    next();
  });
});

test('POST json array', function(next){
  request
  .post('/echo')
  .send([1,2,3])
  .end(function(res){
    assert('application/json' == res.header['content-type'].split(';')[0]);
    assert('[1,2,3]' == res.text);
    next();
  });
});

test('POST json default', function(next){
  request
  .post('/pet')
  .send({ name: 'Manny', species: 'cat' })
  .end(function(res){
    assert('added Manny the cat' == res.text);
    next();
  });
});

test('POST multiple .send() calls', function(next){
  request
  .post('/pet')
  .send({ name: 'Manny' })
  .send({ species: 'cat' })
  .end(function(res){
    assert('added Manny the cat' == res.text);
    next();
  });
});

test('POST multiple .send() strings', function(next){
  request
  .post('/echo')
  .send('user[name]=tj')
  .send('user[email]=tj@vision-media.ca')
  .end(function(res){
    assert('application/x-www-form-urlencoded' == res.header['content-type'].split(';')[0]);
    assert(res.text == 'user[name]=tj&user[email]=tj@vision-media.ca')
    next();
  })
});

test('GET .type', function(next){
  request
  .get('/pets')
  .end(function(res){
    assert('application/json' == res.type);
    next();
  });
});

test('GET Content-Type params', function(next){
  request
  .get('/text')
  .end(function(res){
    assert('utf-8' == res.charset);
    next();
  });
});

test('GET json', function(next){
  request
  .get('/pets')
  .end(function(res){
    assert.deepEqual(res.body, ['tobi', 'loki', 'jane']);
    next();
  });
});

test('GET x-www-form-urlencoded', function(next){
  request
  .get('/foo')
  .end(function(res){
    assert.deepEqual(res.body, { foo: 'bar' });
    next();
  });
});

test('GET shorthand', function(next){
  request.get('/foo', function(res){
    assert('foo=bar' == res.text);
    next();
  });
});

test('POST shorthand', function(next){
  request.post('/user/0/pet', { pet: 'tobi' }, function(res){
    assert('added pet "tobi"' == res.text);
    next();
  });
});

test('POST shorthand without callback', function(next){
  request.post('/user/0/pet', { pet: 'tobi' }).end(function(res){
    assert('added pet "tobi"' == res.text);
    next();
  });
});

test('GET querystring object', function(next){
  request
  .get('/querystring')
  .query({ search: 'Manny' })
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny' });
    next();
  });
});

test('GET querystring append original', function(next){
  request
  .get('/querystring?search=Manny')
  .query({ range: '1..5' })
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny', range: '1..5' });
    next();
  });
});

test('GET querystring multiple objects', function(next){
  request
  .get('/querystring')
  .query({ search: 'Manny' })
  .query({ range: '1..5' })
  .query({ order: 'desc' })
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny', range: '1..5', order: 'desc' });
    next();
  });
});

test('GET querystring empty objects', function(next){
  var req = request
  .get('/querystring')
  .query({})
  .end(function(res){
    assert.deepEqual(req._query, []);
    assert.deepEqual(res.body, {});
    next();
  });
});

test('GET querystring with strings', function(next){
  request
  .get('/querystring')
  .query('search=Manny')
  .query('range=1..5')
  .query('order=desc')
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny', range: '1..5', order: 'desc' });
    next();
  });
});

test('GET querystring with strings and objects', function(next){
  request
  .get('/querystring')
  .query('search=Manny')
  .query({ order: 'desc', range: '1..5' })
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny', range: '1..5', order: 'desc' });
    next();
  });
});

test('GET querystring object .get(uri, obj)', function(next){
  request
  .get('/querystring', { search: 'Manny' })
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny' });
    next();
  });
});

test('GET querystring object .get(uri, obj, fn)', function(next){
  request
  .get('/querystring', { search: 'Manny'}, function(res){
    assert.deepEqual(res.body, { search: 'Manny' });
    next();
  });
});

test('request(method, url)', function(next){
  request('GET', '/foo').end(function(res){
    assert('bar' == res.body.foo);
    next();
  });
});

test('request(url)', function(next){
  request('/foo').end(function(res){
    assert('bar' == res.body.foo);
    next();
  });
});

test('request(url, fn)', function(next){
  request('/foo', function(res){
    assert('bar' == res.body.foo);
    next();
  });
});

test('req.timeout(ms)', function(next){
  request
  .get('/delay/3000')
  .timeout(1000)
  .end(function(err, res){
    assert(err, 'error missing');
    assert(1000 == err.timeout, 'err.timeout missing');
    assert('timeout of 1000ms exceeded' == err.message, 'err.message incorrect');
    assert(null == res);
    next();
  })
})

test('basic auth', function(next){
  request
  .post('/auth')
  .auth('foo', 'bar')
  .end(function(res){
    assert('foo' == res.body.user);
    assert('bar' == res.body.pass);
    next();
  });
});
<commit_msg>Add test for request() error object structure and message<commit_after>
var assert = require('assert');
var request = require('../');

test('Request inheritance', function(){
  assert(request.get('/') instanceof request.Request);
});

test('request() simple GET without callback', function(next){
  request('GET', 'test/test.request.js').end();
  next();
});

test('request() simple GET', function(next){
  request('GET', 'test/test.request.js').end(function(res){
    assert(res instanceof request.Response, 'respond with Response');
    assert(res.ok, 'response should be ok');
    assert(res.text, 'res.text');
    next();
  });
});

test('request() simple HEAD', function(next){
  request.head('test/test.request.js').end(function(res){
    assert(res instanceof request.Response, 'respond with Response');
    assert(res.ok, 'response should be ok');
    assert(!res.text, 'res.text');
    next();
  });
});

test('request() error object', function(next) {
  request('GET', '/error').end(function(res) {
    assert(res.error, 'response should be an error');
    assert(res.error.message == 'cannot GET /error (500)');
    assert(res.error.status == 500);
    assert(res.error.method == 'GET');
    assert(res.error.url == '/error');
    next();
  });
});

test('request() GET 5xx', function(next){
  request('GET', '/error').end(function(res){
    assert(!res.ok, 'response should not be ok');
    assert(res.error, 'response should be an error');
    assert(!res.clientError, 'response should not be a client error');
    assert(res.serverError, 'response should be a server error');
    next();
  });
});

test('request() GET 4xx', function(next){
  request('GET', '/notfound').end(function(res){
    assert(!res.ok, 'response should not be ok');
    assert(res.error, 'response should be an error');
    assert(res.clientError, 'response should be a client error');
    assert(!res.serverError, 'response should not be a server error');
    next();
  });
});

test('request() GET 404 Not Found', function(next){
  request('GET', '/notfound').end(function(res){
    assert(res.notFound, 'response should be .notFound');
    next();
  });
});

test('request() GET 400 Bad Request', function(next){
  request('GET', '/bad-request').end(function(res){
    assert(res.badRequest, 'response should be .badRequest');
    next();
  });
});

test('request() GET 401 Bad Request', function(next){
  request('GET', '/unauthorized').end(function(res){
    assert(res.unauthorized, 'response should be .unauthorized');
    next();
  });
});

test('request() GET 406 Not Acceptable', function(next){
  request('GET', '/not-acceptable').end(function(res){
    assert(res.notAcceptable, 'response should be .notAcceptable');
    next();
  });
});

test('request() GET 204 No Content', function(next){
  request('GET', '/no-content').end(function(res){
    assert(res.noContent, 'response should be .noContent');
    next();
  });
});

test('request() header parsing', function(next){
  request('GET', '/notfound').end(function(res){
    assert('text/plain' == res.header['content-type']);
    assert('Express' == res.header['x-powered-by']);
    next();
  });
});

test('request() .status', function(next){
  request('GET', '/notfound').end(function(res){
    assert(404 == res.status, 'response .status');
    assert(4 == res.statusType, 'response .statusType');
    next();
  });
});

test('get()', function(next){
  request.get('/notfound').end(function(res){
    assert(404 == res.status, 'response .status');
    assert(4 == res.statusType, 'response .statusType');
    next();
  });
});

test('patch()', function(next){
  request.patch('/user/12').end(function(res){
    assert('updated' == res.text, 'response text');
    next();
  });
});

test('put()', function(next){
  request.put('/user/12').end(function(res){
    assert('updated' == res.text, 'response text');
    next();
  });
});

test('post()', function(next){
  request.post('/user').end(function(res){
    assert('created' == res.text, 'response text');
    next();
  });
});

test('del()', function(next){
  request.del('/user/12').end(function(res){
    assert('deleted' == res.text, 'response text');
    next();
  });
});

test('post() data', function(next){
  request.post('/todo/item')
  .type('application/octet-stream')
  .send('tobi')
  .end(function(res){
    assert('added "tobi"' == res.text, 'response text');
    next();
  });
});

test('request .type()', function(next){
  request
  .post('/user/12/pet')
  .type('urlencoded')
  .send('pet=tobi')
  .end(function(res){
    assert('added pet "tobi"' == res.text, 'response text');
    next();
  });
});

test('request .type() with alias', function(next){
  request
  .post('/user/12/pet')
  .type('application/x-www-form-urlencoded')
  .send('pet=tobi')
  .end(function(res){
    assert('added pet "tobi"' == res.text, 'response text');
    next();
  });
});

test('request .get() with no data or callback', function(next){
  request.get('/echo-header/content-type');
  next();
});

test('request .send() with no data only', function(next){
  request.post('/user/5/pet').type('urlencoded').send('pet=tobi');
  next();
});

test('request .send() with callback only', function(next){
  request
  .get('/echo-header/accept')
  .set('Accept', 'foo/bar')
  .end(function(res){
    assert('foo/bar' == res.text);
    next();
  });
});

test('request .accept() with json', function(next){
  request
  .get('/echo-header/accept')
  .accept('json')
  .end(function(res){
    assert('application/json' == res.text);
    next();
  });
});

test('request .accept() with application/json', function(next){
  request
  .get('/echo-header/accept')
  .accept('application/json')
  .end(function(res){
    assert('application/json' == res.text);
    next();
  });
});

test('request .accept() with xml', function(next){
  request
  .get('/echo-header/accept')
  .accept('xml')
  .end(function(res){
    assert('application/xml' == res.text);
    next();
  });
});

test('request .accept() with application/xml', function(next){
  request
  .get('/echo-header/accept')
  .accept('application/xml')
  .end(function(res){
    assert('application/xml' == res.text);
    next();
  });
});

// FIXME: ie6 will POST rather than GET here due to data(),
//        but I'm not 100% sure why.  Newer IEs are OK.
test('request .end()', function(next){
  request
  .get('/echo-header/content-type')
  .set('Content-Type', 'text/plain')
  .send('wahoo')
  .end(function(res){
    assert('text/plain' == res.text);
    next();
  });
});

test('request .send()', function(next){
  request
  .get('/echo-header/content-type')
  .set('Content-Type', 'text/plain')
  .send('wahoo')
  .end(function(res){
    assert('text/plain' == res.text);
    next();
  });
});

test('request .set()', function(next){
  request
  .get('/echo-header/content-type')
  .set('Content-Type', 'text/plain')
  .send('wahoo')
  .end(function(res){
    assert('text/plain' == res.text);
    next();
  });
});

test('request .set(object)', function(next){
  request
  .get('/echo-header/content-type')
  .set({ 'Content-Type': 'text/plain' })
  .send('wahoo')
  .end(function(res){
    assert('text/plain' == res.text);
    next();
  });
});

test('POST urlencoded', function(next){
  request
  .post('/pet')
  .type('urlencoded')
  .send({ name: 'Manny', species: 'cat' })
  .end(function(res){
    assert('added Manny the cat' == res.text);
    next();
  });
});

test('POST json', function(next){
  request
  .post('/pet')
  .type('json')
  .send({ name: 'Manny', species: 'cat' })
  .end(function(res){
    assert('added Manny the cat' == res.text);
    next();
  });
});

test('POST json array', function(next){
  request
  .post('/echo')
  .send([1,2,3])
  .end(function(res){
    assert('application/json' == res.header['content-type'].split(';')[0]);
    assert('[1,2,3]' == res.text);
    next();
  });
});

test('POST json default', function(next){
  request
  .post('/pet')
  .send({ name: 'Manny', species: 'cat' })
  .end(function(res){
    assert('added Manny the cat' == res.text);
    next();
  });
});

test('POST multiple .send() calls', function(next){
  request
  .post('/pet')
  .send({ name: 'Manny' })
  .send({ species: 'cat' })
  .end(function(res){
    assert('added Manny the cat' == res.text);
    next();
  });
});

test('POST multiple .send() strings', function(next){
  request
  .post('/echo')
  .send('user[name]=tj')
  .send('user[email]=tj@vision-media.ca')
  .end(function(res){
    assert('application/x-www-form-urlencoded' == res.header['content-type'].split(';')[0]);
    assert(res.text == 'user[name]=tj&user[email]=tj@vision-media.ca')
    next();
  })
});

test('GET .type', function(next){
  request
  .get('/pets')
  .end(function(res){
    assert('application/json' == res.type);
    next();
  });
});

test('GET Content-Type params', function(next){
  request
  .get('/text')
  .end(function(res){
    assert('utf-8' == res.charset);
    next();
  });
});

test('GET json', function(next){
  request
  .get('/pets')
  .end(function(res){
    assert.deepEqual(res.body, ['tobi', 'loki', 'jane']);
    next();
  });
});

test('GET x-www-form-urlencoded', function(next){
  request
  .get('/foo')
  .end(function(res){
    assert.deepEqual(res.body, { foo: 'bar' });
    next();
  });
});

test('GET shorthand', function(next){
  request.get('/foo', function(res){
    assert('foo=bar' == res.text);
    next();
  });
});

test('POST shorthand', function(next){
  request.post('/user/0/pet', { pet: 'tobi' }, function(res){
    assert('added pet "tobi"' == res.text);
    next();
  });
});

test('POST shorthand without callback', function(next){
  request.post('/user/0/pet', { pet: 'tobi' }).end(function(res){
    assert('added pet "tobi"' == res.text);
    next();
  });
});

test('GET querystring object', function(next){
  request
  .get('/querystring')
  .query({ search: 'Manny' })
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny' });
    next();
  });
});

test('GET querystring append original', function(next){
  request
  .get('/querystring?search=Manny')
  .query({ range: '1..5' })
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny', range: '1..5' });
    next();
  });
});

test('GET querystring multiple objects', function(next){
  request
  .get('/querystring')
  .query({ search: 'Manny' })
  .query({ range: '1..5' })
  .query({ order: 'desc' })
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny', range: '1..5', order: 'desc' });
    next();
  });
});

test('GET querystring empty objects', function(next){
  var req = request
  .get('/querystring')
  .query({})
  .end(function(res){
    assert.deepEqual(req._query, []);
    assert.deepEqual(res.body, {});
    next();
  });
});

test('GET querystring with strings', function(next){
  request
  .get('/querystring')
  .query('search=Manny')
  .query('range=1..5')
  .query('order=desc')
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny', range: '1..5', order: 'desc' });
    next();
  });
});

test('GET querystring with strings and objects', function(next){
  request
  .get('/querystring')
  .query('search=Manny')
  .query({ order: 'desc', range: '1..5' })
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny', range: '1..5', order: 'desc' });
    next();
  });
});

test('GET querystring object .get(uri, obj)', function(next){
  request
  .get('/querystring', { search: 'Manny' })
  .end(function(res){
    assert.deepEqual(res.body, { search: 'Manny' });
    next();
  });
});

test('GET querystring object .get(uri, obj, fn)', function(next){
  request
  .get('/querystring', { search: 'Manny'}, function(res){
    assert.deepEqual(res.body, { search: 'Manny' });
    next();
  });
});

test('request(method, url)', function(next){
  request('GET', '/foo').end(function(res){
    assert('bar' == res.body.foo);
    next();
  });
});

test('request(url)', function(next){
  request('/foo').end(function(res){
    assert('bar' == res.body.foo);
    next();
  });
});

test('request(url, fn)', function(next){
  request('/foo', function(res){
    assert('bar' == res.body.foo);
    next();
  });
});

test('req.timeout(ms)', function(next){
  request
  .get('/delay/3000')
  .timeout(1000)
  .end(function(err, res){
    assert(err, 'error missing');
    assert(1000 == err.timeout, 'err.timeout missing');
    assert('timeout of 1000ms exceeded' == err.message, 'err.message incorrect');
    assert(null == res);
    next();
  })
})

test('basic auth', function(next){
  request
  .post('/auth')
  .auth('foo', 'bar')
  .end(function(res){
    assert('foo' == res.body.user);
    assert('bar' == res.body.pass);
    next();
  });
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'ReciprocalSearch',
  extends: 'foam.u2.View',

  requires: [
    'foam.core.SimpleSlot',
    'foam.u2.search.SearchManager',
    'foam.u2.search.TextSearchView',
    'foam.u2.view.SearchViewWrapper'
  ],

  imports: [
    'dao',
    'searchColumns'
  ],

  exports: [
    'as filterController',
    'as data',
    'searchManager'
  ],

  css: `
    ^ {
      background-color: white;
      border-radius: 2px;
      min-width: 250px;
      font-size: smaller;
    }

    ^ input {
      font-size: medium;
    }

    ^ .foam-u2-tag-Input {
      width: 100%;
    }

    ^ input:not([type="checkbox"]):focus,
    ^ select:focus {
      outline: none;
      border: 1px solid /*%PRIMARY3%*/ #406dea;
    }

    ^ .general-query {
      padding: 16px 20px;
    }

    ^count {
      font-size: 12pt;
      color: #555;
      margin: 20px 20px 0 20px;
    }

    ^ .foam-u2-ActionView-clear {
      margin: 20px;
    }
  `,

  properties: [
    {
      class: 'Class',
      name: 'of'
    },
    {
      name: 'data'
    },
    {
      class: 'Array',
      name: 'filters',
      factory: null,
      expression: function(dao, searchColumns) {
        var of = dao && dao.of;

        if ( ! of ) return [];

        if ( searchColumns ) return searchColumns;

        if ( of.model_.searchColumns ) return of.model_.searchColumns;

        if ( of.model_.tableColumns ) {
          return of.model_.tableColumns.filter(function(c) {
            var axiom = of.getAxiomByName(c);
            return axiom && axiom.searchView;
          });
        }

        return of.getAxiomsByClass(foam.core.Property)
            .filter((prop) => prop.searchView && ! prop.hidden)
            .map(foam.core.Property.NAME.f);
      }
    },
    {
      class: 'Int',
      name: 'selectedCount',
      postSet: function() {
        this.isLoading = false;
      }
    },
    {
      class: 'Int',
      name: 'totalCount',
      postSet: function() {
        this.isLoading = false;
      }
    },
    {
      name: 'searchManager',
      factory: function() {
        return this.SearchManager.create({
          dao$: this.dao$,
          predicate$: this.data$
        });
      }
    },
    {
      class: 'Boolean',
      name: 'isLoading',
      documentation: `
        Indicates that the view hasn't gotten the count of objects in the DAO
        back yet and is therefore still loading.
      `,
      value: true
    },
    {
      class: 'String',
      name: 'countText',
      documentation: `
        The formatted text that shows how many items have been selected from the
        DAO. Shows "Loading..." while waiting for the total count to avoid
        "0 of 0 selected" being shown while loading.
      `,
      expression: function(selectedCount, totalCount, isLoading) {
        if ( isLoading ) {
          return 'Loading...';
        }
        return `${selectedCount.toLocaleString()} of ${totalCount.toLocaleString()} selected`;
      }
    }
  ],

  methods: [
    function initE() {
      var self = this;

      this.dao.on.sub(this.updateTotalCount);
      this.updateTotalCount();

      this.
        addClass(self.myClass()).
        add(this.slot(function(filters) {
          self.show(filters.length);

          this.searchManager.filteredDAO$.sub(self.updateSelectedCount);
          self.updateSelectedCount(0, 0, 0, this.searchManager.filteredDAO$);

          var e = this.E('div');

          e.onDetach(this.searchManager);

          var slot = self.SimpleSlot.create();

          e
            .start(self.TextSearchView, {
                richSearch: true,
                of: self.dao.of.id,
                onKey: true,
                viewSpec: {
                  class: 'foam.u2.tag.Input',
                  focused: true
                }
            }, slot)
              .addClass('general-query')
            .end();

          this.searchManager.add(slot.value);

          e.forEach(filters, function(f) {
            var axiom = self.dao.of.getAxiomByName(f);

            this
              .start(self.SearchViewWrapper, {
                searchView: axiom.searchView,
                property: axiom,
                dao: self.dao
              })
                .addClass(self.myClass('filter'))
              .end();
          });

          return e;
        }, this.filters$))
        .start()
          .addClass(self.myClass('count'))
          .add(self.countText$)
        .end()
        .tag(this.CLEAR, { buttonStyle: 'SECONDARY' });
    },

    function addFilter(key) {
      this.filters = this.filters.concat(key);
    },

    function removeFilter(key) {
      this.filters = this.filters.filter(function(k) {
        return key !== k;
      });
    }
  ],

  actions: [
    {
      name: 'clear',
      code: function() {
        this.data = undefined;
        this.filters = this.filters.slice();
      }
    }
  ],

  listeners: [
    {
      name: 'updateTotalCount',
      isFramed: true,
      code: function() {
        this.dao.select(foam.mlang.sink.Count.create()).then(function(c) {
          this.totalCount = c.value;
        }.bind(this));
      }
    },
    {
      name: 'updateSelectedCount',
      isFramed: true,
      code: function(_, __, ___, dao) {
        dao.get().select(foam.mlang.sink.Count.create()).then(function(c) {
          this.selectedCount = c.value;
        }.bind(this));
      }
    }
  ]
});
<commit_msg>Fix bug where "Loading..." wouldn't wait for all calls to finish<commit_after>/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'ReciprocalSearch',
  extends: 'foam.u2.View',

  requires: [
    'foam.core.SimpleSlot',
    'foam.u2.search.SearchManager',
    'foam.u2.search.TextSearchView',
    'foam.u2.view.SearchViewWrapper'
  ],

  imports: [
    'dao',
    'searchColumns'
  ],

  exports: [
    'as filterController',
    'as data',
    'searchManager'
  ],

  css: `
    ^ {
      background-color: white;
      border-radius: 2px;
      min-width: 250px;
      font-size: smaller;
    }

    ^ input {
      font-size: medium;
    }

    ^ .foam-u2-tag-Input {
      width: 100%;
    }

    ^ input:not([type="checkbox"]):focus,
    ^ select:focus {
      outline: none;
      border: 1px solid /*%PRIMARY3%*/ #406dea;
    }

    ^ .general-query {
      padding: 16px 20px;
    }

    ^count {
      font-size: 12pt;
      color: #555;
      margin: 20px 20px 0 20px;
    }

    ^ .foam-u2-ActionView-clear {
      margin: 20px;
    }
  `,

  properties: [
    {
      class: 'Class',
      name: 'of'
    },
    {
      name: 'data'
    },
    {
      class: 'Array',
      name: 'filters',
      factory: null,
      expression: function(dao, searchColumns) {
        var of = dao && dao.of;

        if ( ! of ) return [];

        if ( searchColumns ) return searchColumns;

        if ( of.model_.searchColumns ) return of.model_.searchColumns;

        if ( of.model_.tableColumns ) {
          return of.model_.tableColumns.filter(function(c) {
            var axiom = of.getAxiomByName(c);
            return axiom && axiom.searchView;
          });
        }

        return of.getAxiomsByClass(foam.core.Property)
            .filter((prop) => prop.searchView && ! prop.hidden)
            .map(foam.core.Property.NAME.f);
      }
    },
    {
      class: 'Int',
      name: 'selectedCount',
      postSet: function() {
        this.isLoading = false;
      }
    },
    {
      class: 'Int',
      name: 'totalCount',
      postSet: function() {
        this.isLoading = false;
      }
    },
    {
      name: 'searchManager',
      factory: function() {
        return this.SearchManager.create({
          dao$: this.dao$,
          predicate$: this.data$
        });
      }
    },
    {
      class: 'Int',
      name: 'loadingRequests',
      documentation: `
        Incremented every time an async call is made to the DAO and decremented
        every time a call finishes. A non-zero value indicates that this view is
        loading.
      `
    },
    {
      class: 'String',
      name: 'countText',
      documentation: `
        The formatted text that shows how many items have been selected from the
        DAO. Shows "Loading..." while waiting for the total count to avoid
        "0 of 0 selected" being shown while loading.
      `,
      expression: function(selectedCount, totalCount, loadingRequests) {
        if ( loadingRequests > 0 ) {
          return 'Loading...';
        }
        return `${selectedCount.toLocaleString()} of ${totalCount.toLocaleString()} selected`;
      }
    }
  ],

  methods: [
    function initE() {
      var self = this;

      this.dao.on.sub(this.updateTotalCount);
      this.updateTotalCount();

      this.
        addClass(self.myClass()).
        add(this.slot(function(filters) {
          self.show(filters.length);

          this.searchManager.filteredDAO$.sub(self.updateSelectedCount);
          self.updateSelectedCount(0, 0, 0, this.searchManager.filteredDAO$);

          var e = this.E('div');

          e.onDetach(this.searchManager);

          var slot = self.SimpleSlot.create();

          e
            .start(self.TextSearchView, {
                richSearch: true,
                of: self.dao.of.id,
                onKey: true,
                viewSpec: {
                  class: 'foam.u2.tag.Input',
                  focused: true
                }
            }, slot)
              .addClass('general-query')
            .end();

          this.searchManager.add(slot.value);

          e.forEach(filters, function(f) {
            var axiom = self.dao.of.getAxiomByName(f);

            this
              .start(self.SearchViewWrapper, {
                searchView: axiom.searchView,
                property: axiom,
                dao: self.dao
              })
                .addClass(self.myClass('filter'))
              .end();
          });

          return e;
        }, this.filters$))
        .start()
          .addClass(self.myClass('count'))
          .add(self.countText$)
        .end()
        .tag(this.CLEAR, { buttonStyle: 'SECONDARY' });
    },

    function addFilter(key) {
      this.filters = this.filters.concat(key);
    },

    function removeFilter(key) {
      this.filters = this.filters.filter(function(k) {
        return key !== k;
      });
    }
  ],

  actions: [
    {
      name: 'clear',
      code: function() {
        this.data = undefined;
        this.filters = this.filters.slice();
      }
    }
  ],

  listeners: [
    {
      name: 'updateTotalCount',
      isFramed: true,
      code: function() {
        this.loadingRequests++;
        this.dao
          .select(foam.mlang.sink.Count.create())
          .then((c) => {
            this.totalCount = c.value;
          })
          .finally(() => {
            this.loadingRequests--;
          });
      }
    },
    {
      name: 'updateSelectedCount',
      isFramed: true,
      code: function(_, __, ___, sink) {
        this.loadingRequests++;
        sink
          .get()
          .select(foam.mlang.sink.Count.create())
          .then((c) => {
            this.selectedCount = c.value;
          })
          .finally(() => {
            this.loadingRequests--;
          });
      }
    }
  ]
});
<|endoftext|>