<commit_before>/**
 * @license
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Methods for graphically rendering a block as SVG.
 * @author fenichel@google.com (Rachel Fenichel)
 */
'use strict';

goog.provide('Blockly.blockRendering.Debug');

goog.require('Blockly.blockRendering.Measurable');
goog.require('Blockly.blockRendering.RenderInfo');
goog.require('Blockly.blockRendering.Row');
goog.require('Blockly.blockRendering.Types');
goog.require('Blockly.connectionTypes');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.Svg');

goog.requireType('Blockly.blockRendering.ConstantProvider');
goog.requireType('Blockly.blockRendering.InRowSpacer');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.RenderedConnection');

/**
 * An object that renders rectangles and dots for debugging rendering code.
 * @param {!Blockly.blockRendering.ConstantProvider} constants The renderer's
 *     constants.
 * @package
 * @constructor
 */
Blockly.blockRendering.Debug = function(constants) {
  /**
   * An array of SVG elements that have been created by this object.
   * @type {Array<!SVGElement>}
   * @private
   */
  this.debugElements_ = [];

  /**
   * The SVG root of the block that is being rendered.  Debug elements will
   * be attached to this root.
   * @type {SVGElement}
   * @private
   */
  this.svgRoot_ = null;

  /**
   * The renderer's constant provider.
   * @type {!Blockly.blockRendering.ConstantProvider}
   * @private
   */
  this.constants_ = constants;
};

/**
 * Configuration object containing booleans to enable and disable debug
 * rendering of specific rendering components.
 * @type {!Object<string, boolean>}
 */
Blockly.blockRendering.Debug.config = {
  rowSpacers: true,
  elemSpacers: true,
  rows: true,
  elems: true,
  connections: true,
  blockBounds: true,
  connectedBlockBounds: true,
  render: true
};

/**
 * Remove all elements the this object created on the last pass.
 * @package
 */
Blockly.blockRendering.Debug.prototype.clearElems = function() {
  for (var i = 0, elem; (elem = this.debugElements_[i]); i++) {
    Blockly.utils.dom.removeNode(elem);
  }

  this.debugElements_ = [];
};

/**
 * Draw a debug rectangle for a spacer (empty) row.
 * @param {!Blockly.blockRendering.Row} row The row to render.
 * @param {number} cursorY The y position of the top of the row.
 * @param {boolean} isRtl Whether the block is rendered RTL.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawSpacerRow = function(row, cursorY, isRtl) {
  if (!Blockly.blockRendering.Debug.config.rowSpacers) {
    return;
  }

  var height = Math.abs(row.height);
  var isNegativeSpacing = row.height < 0;
  if (isNegativeSpacing) {
    cursorY -= height;
  }

  this.debugElements_.push(Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.RECT,
      {
        'class': 'rowSpacerRect blockRenderDebug',
        'x': isRtl ? -(row.xPos + row.width) : row.xPos,
        'y': cursorY,
        'width': row.width,
        'height': height,
        'stroke': isNegativeSpacing ? 'black' : 'blue',
        'fill': 'blue',
        'fill-opacity': '0.5',
        'stroke-width': '1px'
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for a horizontal spacer.
 * @param {!Blockly.blockRendering.InRowSpacer} elem The spacer to render.
 * @param {number} rowHeight The height of the container row.
 * @param {boolean} isRtl Whether the block is rendered RTL.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawSpacerElem = function(elem, rowHeight, isRtl) {
  if (!Blockly.blockRendering.Debug.config.elemSpacers) {
    return;
  }

  var width = Math.abs(elem.width);
  var isNegativeSpacing = elem.width < 0;
  var xPos = isNegativeSpacing ? elem.xPos - width : elem.xPos;
  if (isRtl) {
    xPos = -(xPos + width);
  }
  var yPos = elem.centerline - elem.height / 2;
  this.debugElements_.push(Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.RECT,
      {
        'class': 'elemSpacerRect blockRenderDebug',
        'x': xPos,
        'y': yPos,
        'width': width,
        'height': elem.height,
        'stroke': 'pink',
        'fill': isNegativeSpacing ? 'black' : 'pink',
        'fill-opacity': '0.5',
        'stroke-width': '1px'
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for an in-row element.
 * @param {!Blockly.blockRendering.Measurable} elem The element to render.
 * @param {boolean} isRtl Whether the block is rendered RTL.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRenderedElem = function(elem, isRtl) {
  if (Blockly.blockRendering.Debug.config.elems) {
    var xPos = elem.xPos;
    if (isRtl) {
      xPos = -(xPos + elem.width);
    }
    var yPos = elem.centerline - elem.height / 2;
    this.debugElements_.push(Blockly.utils.dom.createSvgElement(
        Blockly.utils.Svg.RECT,
        {
          'class': 'rowRenderingRect blockRenderDebug',
          'x': xPos,
          'y': yPos,
          'width': elem.width,
          'height': elem.height,
          'stroke': 'black',
          'fill': 'none',
          'stroke-width': '1px'
        },
        this.svgRoot_));

    if (Blockly.blockRendering.Types.isField(elem) &&
        elem.field instanceof Blockly.FieldLabel) {
      var baseline = this.constants_.FIELD_TEXT_BASELINE;
      this.debugElements_.push(Blockly.utils.dom.createSvgElement(
          Blockly.utils.Svg.RECT,
          {
            'class': 'rowRenderingRect blockRenderDebug',
            'x': xPos,
            'y': yPos + baseline,
            'width': elem.width,
            'height': '0.1px',
            'stroke': 'red',
            'fill': 'none',
            'stroke-width': '0.5px'
          },
          this.svgRoot_));
    }
  }

  if (Blockly.blockRendering.Types.isInput(elem) &&
      Blockly.blockRendering.Debug.config.connections) {
    this.drawConnection(elem.connectionModel);
  }
};

/**
 * Draw a circle at the location of the given connection.  Inputs and outputs
 * share the same colours, as do previous and next.  When positioned correctly
 * a connected pair will look like a bullseye.
 * @param {Blockly.RenderedConnection} conn The connection to circle.
 * @suppress {visibility} Suppress visibility of conn.offsetInBlock_ since this
 *     is a debug module.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawConnection = function(conn) {
  if (!Blockly.blockRendering.Debug.config.connections) {
    return;
  }

  var colour;
  var size;
  var fill;
  if (conn.type == Blockly.connectionTypes.INPUT_VALUE) {
    size = 4;
    colour = 'magenta';
    fill = 'none';
  } else if (conn.type == Blockly.connectionTypes.OUTPUT_VALUE) {
    size = 2;
    colour = 'magenta';
    fill = colour;
  } else if (conn.type == Blockly.connectionTypes.NEXT_STATEMENT) {
    size = 4;
    colour = 'goldenrod';
    fill = 'none';
  } else if (conn.type == Blockly.connectionTypes.PREVIOUS_STATEMENT) {
    size = 2;
    colour = 'goldenrod';
    fill = colour;
  }
  this.debugElements_.push(Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.CIRCLE,
      {
        'class': 'blockRenderDebug',
        'cx': conn.offsetInBlock_.x,
        'cy': conn.offsetInBlock_.y,
        'r': size,
        'fill': fill,
        'stroke': colour,
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for a non-empty row.
 * @param {!Blockly.blockRendering.Row} row The non-empty row to render.
 * @param {number} cursorY The y position of the top of the row.
 * @param {boolean} isRtl Whether the block is rendered RTL.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRenderedRow = function(row, cursorY, isRtl) {
  if (!Blockly.blockRendering.Debug.config.rows) {
    return;
  }
  this.debugElements_.push(Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.RECT,
      {
        'class': 'elemRenderingRect blockRenderDebug',
        'x': isRtl ? -(row.xPos + row.width) : row.xPos,
        'y': row.yPos,
        'width': row.width,
        'height': row.height,
        'stroke': 'red',
        'fill': 'none',
        'stroke-width': '1px'
      },
      this.svgRoot_));

  if (Blockly.blockRendering.Types.isTopOrBottomRow(row)) {
    return;
  }

  if (Blockly.blockRendering.Debug.config.connectedBlockBounds) {
    this.debugElements_.push(Blockly.utils.dom.createSvgElement(
        Blockly.utils.Svg.RECT,
        {
          'class': 'connectedBlockWidth blockRenderDebug',
          'x': isRtl ? -(row.xPos + row.widthWithConnectedBlocks) : row.xPos,
          'y': row.yPos,
          'width': row.widthWithConnectedBlocks,
          'height': row.height,
          'stroke': this.randomColour_,
          'fill': 'none',
          'stroke-width': '1px',
          'stroke-dasharray': '3,3'
        },
        this.svgRoot_));
  }
};

/**
 * Draw debug rectangles for a non-empty row and all of its subcomponents.
 * @param {!Blockly.blockRendering.Row} row The non-empty row to render.
 * @param {number} cursorY The y position of the top of the row.
 * @param {boolean} isRtl Whether the block is rendered RTL.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRowWithElements = function(row, cursorY, isRtl) {
  for (var i = 0, l = row.elements.length; i < l; i++) {
    var elem = row.elements[i];
    if (!elem) {
      console.warn('A row has an undefined or null element.', row, elem);
      continue;
    }
    if (Blockly.blockRendering.Types.isSpacer(elem)) {
      this.drawSpacerElem(
          /** @type {!Blockly.blockRendering.InRowSpacer} */ (elem),
          row.height, isRtl);
    } else {
      this.drawRenderedElem(elem, isRtl);
    }
  }
  this.drawRenderedRow(row, cursorY, isRtl);
};

/**
 * Draw a debug rectangle around the entire block.
 * @param {!Blockly.blockRendering.RenderInfo} info Rendering information about
 *     the block to debug.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawBoundingBox = function(info) {
  if (!Blockly.blockRendering.Debug.config.blockBounds) {
    return;
  }
  // Bounding box without children.
  var xPos = info.RTL ? -info.width : 0;
  var yPos = 0;
  this.debugElements_.push(Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.RECT,
      {
        'class': 'blockBoundingBox blockRenderDebug',
        'x': xPos,
        'y': yPos,
        'width': info.width,
        'height': info.height,
        'stroke': 'black',
        'fill': 'none',
        'stroke-width': '1px',
        'stroke-dasharray': '5,5'
      },
      this.svgRoot_));

  if (Blockly.blockRendering.Debug.config.connectedBlockBounds) {
    // Bounding box with children.
    xPos = info.RTL ? -info.widthWithChildren : 0;
    this.debugElements_.push(Blockly.utils.dom.createSvgElement(
        Blockly.utils.Svg.RECT,
        {
          'class': 'blockRenderDebug',
          'x': xPos,
          'y': yPos,
          'width': info.widthWithChildren,
          'height': info.height,
          'stroke': '#DF57BC',
          'fill': 'none',
          'stroke-width': '1px',
          'stroke-dasharray': '3,3'
        },
        this.svgRoot_));
  }
};

/**
 * Do all of the work to draw debug information for the whole block.
 * @param {!Blockly.BlockSvg} block The block to draw debug information for.
 * @param {!Blockly.blockRendering.RenderInfo} info Rendering information about
 *     the block to debug.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawDebug = function(block, info) {
  this.clearElems();
  this.svgRoot_ = block.getSvgRoot();

  this.randomColour_ = '#' + Math.floor(Math.random() * 16777215).toString(16);

  var cursorY = 0;
  for (var i = 0, row; (row = info.rows[i]); i++) {
    if (Blockly.blockRendering.Types.isBetweenRowSpacer(row)) {
      this.drawSpacerRow(row, cursorY, info.RTL);
    } else {
      this.drawRowWithElements(row, cursorY, info.RTL);
    }
    cursorY += row.height;
  }

  if (block.previousConnection) {
    this.drawConnection(block.previousConnection);
  }
  if (block.nextConnection) {
    this.drawConnection(block.nextConnection);
  }
  if (block.outputConnection) {
    this.drawConnection(block.outputConnection);
  }
  if (info.rightSide) {
    this.drawRenderedElem(info.rightSide, info.RTL);
  }

  this.drawBoundingBox(info);

  this.drawRender(block.pathObject.svgPath);
};

/**
 * Show a debug filter to highlight that a block has been rendered.
 * @param {!SVGElement} svgPath The block's SVG path.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRender = function(svgPath) {
  if (!Blockly.blockRendering.Debug.config.render) {
    return;
  }
  svgPath.setAttribute('filter',
      'url(#' + this.constants_.debugFilterId + ')');
  setTimeout(function() {
    svgPath.setAttribute('filter', '');
  }, 100);
};
<commit_msg>Migrate core/renderers/common/debugger.js to ES6 const/let<commit_after>/**
 * @license
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Methods for graphically rendering a block as SVG.
 * @author fenichel@google.com (Rachel Fenichel)
 */
'use strict';

goog.provide('Blockly.blockRendering.Debug');

goog.require('Blockly.blockRendering.Measurable');
goog.require('Blockly.blockRendering.RenderInfo');
goog.require('Blockly.blockRendering.Row');
goog.require('Blockly.blockRendering.Types');
goog.require('Blockly.connectionTypes');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.Svg');

goog.requireType('Blockly.blockRendering.ConstantProvider');
goog.requireType('Blockly.blockRendering.InRowSpacer');
goog.requireType('Blockly.BlockSvg');
goog.requireType('Blockly.RenderedConnection');

/**
 * An object that renders rectangles and dots for debugging rendering code.
 * @param {!Blockly.blockRendering.ConstantProvider} constants The renderer's
 *     constants.
 * @package
 * @constructor
 */
Blockly.blockRendering.Debug = function(constants) {
  /**
   * An array of SVG elements that have been created by this object.
   * @type {Array<!SVGElement>}
   * @private
   */
  this.debugElements_ = [];

  /**
   * The SVG root of the block that is being rendered.  Debug elements will
   * be attached to this root.
   * @type {SVGElement}
   * @private
   */
  this.svgRoot_ = null;

  /**
   * The renderer's constant provider.
   * @type {!Blockly.blockRendering.ConstantProvider}
   * @private
   */
  this.constants_ = constants;
};

/**
 * Configuration object containing booleans to enable and disable debug
 * rendering of specific rendering components.
 * @type {!Object<string, boolean>}
 */
Blockly.blockRendering.Debug.config = {
  rowSpacers: true,
  elemSpacers: true,
  rows: true,
  elems: true,
  connections: true,
  blockBounds: true,
  connectedBlockBounds: true,
  render: true
};

/**
 * Remove all elements the this object created on the last pass.
 * @package
 */
Blockly.blockRendering.Debug.prototype.clearElems = function() {
  for (let i = 0; i < this.debugElements_.length; i++) {
    const elem = this.debugElements_[i];
    Blockly.utils.dom.removeNode(elem);
  }

  this.debugElements_ = [];
};

/**
 * Draw a debug rectangle for a spacer (empty) row.
 * @param {!Blockly.blockRendering.Row} row The row to render.
 * @param {number} cursorY The y position of the top of the row.
 * @param {boolean} isRtl Whether the block is rendered RTL.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawSpacerRow = function(row, cursorY, isRtl) {
  if (!Blockly.blockRendering.Debug.config.rowSpacers) {
    return;
  }

  const height = Math.abs(row.height);
  const isNegativeSpacing = row.height < 0;
  if (isNegativeSpacing) {
    cursorY -= height;
  }

  this.debugElements_.push(Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.RECT,
      {
        'class': 'rowSpacerRect blockRenderDebug',
        'x': isRtl ? -(row.xPos + row.width) : row.xPos,
        'y': cursorY,
        'width': row.width,
        'height': height,
        'stroke': isNegativeSpacing ? 'black' : 'blue',
        'fill': 'blue',
        'fill-opacity': '0.5',
        'stroke-width': '1px'
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for a horizontal spacer.
 * @param {!Blockly.blockRendering.InRowSpacer} elem The spacer to render.
 * @param {number} rowHeight The height of the container row.
 * @param {boolean} isRtl Whether the block is rendered RTL.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawSpacerElem = function(elem, rowHeight, isRtl) {
  if (!Blockly.blockRendering.Debug.config.elemSpacers) {
    return;
  }

  const width = Math.abs(elem.width);
  const isNegativeSpacing = elem.width < 0;
  let xPos = isNegativeSpacing ? elem.xPos - width : elem.xPos;
  if (isRtl) {
    xPos = -(xPos + width);
  }
  const yPos = elem.centerline - elem.height / 2;
  this.debugElements_.push(Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.RECT,
      {
        'class': 'elemSpacerRect blockRenderDebug',
        'x': xPos,
        'y': yPos,
        'width': width,
        'height': elem.height,
        'stroke': 'pink',
        'fill': isNegativeSpacing ? 'black' : 'pink',
        'fill-opacity': '0.5',
        'stroke-width': '1px'
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for an in-row element.
 * @param {!Blockly.blockRendering.Measurable} elem The element to render.
 * @param {boolean} isRtl Whether the block is rendered RTL.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRenderedElem = function(elem, isRtl) {
  if (Blockly.blockRendering.Debug.config.elems) {
    let xPos = elem.xPos;
    if (isRtl) {
      xPos = -(xPos + elem.width);
    }
    const yPos = elem.centerline - elem.height / 2;
    this.debugElements_.push(Blockly.utils.dom.createSvgElement(
        Blockly.utils.Svg.RECT,
        {
          'class': 'rowRenderingRect blockRenderDebug',
          'x': xPos,
          'y': yPos,
          'width': elem.width,
          'height': elem.height,
          'stroke': 'black',
          'fill': 'none',
          'stroke-width': '1px'
        },
        this.svgRoot_));

    if (Blockly.blockRendering.Types.isField(elem) &&
        elem.field instanceof Blockly.FieldLabel) {
      const baseline = this.constants_.FIELD_TEXT_BASELINE;
      this.debugElements_.push(Blockly.utils.dom.createSvgElement(
          Blockly.utils.Svg.RECT,
          {
            'class': 'rowRenderingRect blockRenderDebug',
            'x': xPos,
            'y': yPos + baseline,
            'width': elem.width,
            'height': '0.1px',
            'stroke': 'red',
            'fill': 'none',
            'stroke-width': '0.5px'
          },
          this.svgRoot_));
    }
  }

  if (Blockly.blockRendering.Types.isInput(elem) &&
      Blockly.blockRendering.Debug.config.connections) {
    this.drawConnection(elem.connectionModel);
  }
};

/**
 * Draw a circle at the location of the given connection.  Inputs and outputs
 * share the same colours, as do previous and next.  When positioned correctly
 * a connected pair will look like a bullseye.
 * @param {Blockly.RenderedConnection} conn The connection to circle.
 * @suppress {visibility} Suppress visibility of conn.offsetInBlock_ since this
 *     is a debug module.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawConnection = function(conn) {
  if (!Blockly.blockRendering.Debug.config.connections) {
    return;
  }

  let colour;
  let size;
  let fill;
  if (conn.type == Blockly.connectionTypes.INPUT_VALUE) {
    size = 4;
    colour = 'magenta';
    fill = 'none';
  } else if (conn.type == Blockly.connectionTypes.OUTPUT_VALUE) {
    size = 2;
    colour = 'magenta';
    fill = colour;
  } else if (conn.type == Blockly.connectionTypes.NEXT_STATEMENT) {
    size = 4;
    colour = 'goldenrod';
    fill = 'none';
  } else if (conn.type == Blockly.connectionTypes.PREVIOUS_STATEMENT) {
    size = 2;
    colour = 'goldenrod';
    fill = colour;
  }
  this.debugElements_.push(Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.CIRCLE,
      {
        'class': 'blockRenderDebug',
        'cx': conn.offsetInBlock_.x,
        'cy': conn.offsetInBlock_.y,
        'r': size,
        'fill': fill,
        'stroke': colour,
      },
      this.svgRoot_));
};

/**
 * Draw a debug rectangle for a non-empty row.
 * @param {!Blockly.blockRendering.Row} row The non-empty row to render.
 * @param {number} cursorY The y position of the top of the row.
 * @param {boolean} isRtl Whether the block is rendered RTL.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRenderedRow = function(row, cursorY, isRtl) {
  if (!Blockly.blockRendering.Debug.config.rows) {
    return;
  }
  this.debugElements_.push(Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.RECT,
      {
        'class': 'elemRenderingRect blockRenderDebug',
        'x': isRtl ? -(row.xPos + row.width) : row.xPos,
        'y': row.yPos,
        'width': row.width,
        'height': row.height,
        'stroke': 'red',
        'fill': 'none',
        'stroke-width': '1px'
      },
      this.svgRoot_));

  if (Blockly.blockRendering.Types.isTopOrBottomRow(row)) {
    return;
  }

  if (Blockly.blockRendering.Debug.config.connectedBlockBounds) {
    this.debugElements_.push(Blockly.utils.dom.createSvgElement(
        Blockly.utils.Svg.RECT,
        {
          'class': 'connectedBlockWidth blockRenderDebug',
          'x': isRtl ? -(row.xPos + row.widthWithConnectedBlocks) : row.xPos,
          'y': row.yPos,
          'width': row.widthWithConnectedBlocks,
          'height': row.height,
          'stroke': this.randomColour_,
          'fill': 'none',
          'stroke-width': '1px',
          'stroke-dasharray': '3,3'
        },
        this.svgRoot_));
  }
};

/**
 * Draw debug rectangles for a non-empty row and all of its subcomponents.
 * @param {!Blockly.blockRendering.Row} row The non-empty row to render.
 * @param {number} cursorY The y position of the top of the row.
 * @param {boolean} isRtl Whether the block is rendered RTL.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRowWithElements = function(row, cursorY, isRtl) {
  for (let i = 0; i < row.elements.length; i++) {
    const elem = row.elements[i];
    if (!elem) {
      console.warn('A row has an undefined or null element.', row, elem);
      continue;
    }
    if (Blockly.blockRendering.Types.isSpacer(elem)) {
      this.drawSpacerElem(
          /** @type {!Blockly.blockRendering.InRowSpacer} */ (elem),
          row.height, isRtl);
    } else {
      this.drawRenderedElem(elem, isRtl);
    }
  }
  this.drawRenderedRow(row, cursorY, isRtl);
};

/**
 * Draw a debug rectangle around the entire block.
 * @param {!Blockly.blockRendering.RenderInfo} info Rendering information about
 *     the block to debug.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawBoundingBox = function(info) {
  if (!Blockly.blockRendering.Debug.config.blockBounds) {
    return;
  }
  // Bounding box without children.
  let xPos = info.RTL ? -info.width : 0;
  const yPos = 0;
  this.debugElements_.push(Blockly.utils.dom.createSvgElement(
      Blockly.utils.Svg.RECT,
      {
        'class': 'blockBoundingBox blockRenderDebug',
        'x': xPos,
        'y': yPos,
        'width': info.width,
        'height': info.height,
        'stroke': 'black',
        'fill': 'none',
        'stroke-width': '1px',
        'stroke-dasharray': '5,5'
      },
      this.svgRoot_));

  if (Blockly.blockRendering.Debug.config.connectedBlockBounds) {
    // Bounding box with children.
    xPos = info.RTL ? -info.widthWithChildren : 0;
    this.debugElements_.push(Blockly.utils.dom.createSvgElement(
        Blockly.utils.Svg.RECT,
        {
          'class': 'blockRenderDebug',
          'x': xPos,
          'y': yPos,
          'width': info.widthWithChildren,
          'height': info.height,
          'stroke': '#DF57BC',
          'fill': 'none',
          'stroke-width': '1px',
          'stroke-dasharray': '3,3'
        },
        this.svgRoot_));
  }
};

/**
 * Do all of the work to draw debug information for the whole block.
 * @param {!Blockly.BlockSvg} block The block to draw debug information for.
 * @param {!Blockly.blockRendering.RenderInfo} info Rendering information about
 *     the block to debug.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawDebug = function(block, info) {
  this.clearElems();
  this.svgRoot_ = block.getSvgRoot();

  this.randomColour_ = '#' + Math.floor(Math.random() * 16777215).toString(16);

  let cursorY = 0;
  for (let i = 0; i < info.rows.length; i++) {
    const row = info.rows[i];
    if (Blockly.blockRendering.Types.isBetweenRowSpacer(row)) {
      this.drawSpacerRow(row, cursorY, info.RTL);
    } else {
      this.drawRowWithElements(row, cursorY, info.RTL);
    }
    cursorY += row.height;
  }

  if (block.previousConnection) {
    this.drawConnection(block.previousConnection);
  }
  if (block.nextConnection) {
    this.drawConnection(block.nextConnection);
  }
  if (block.outputConnection) {
    this.drawConnection(block.outputConnection);
  }
  if (info.rightSide) {
    this.drawRenderedElem(info.rightSide, info.RTL);
  }

  this.drawBoundingBox(info);

  this.drawRender(block.pathObject.svgPath);
};

/**
 * Show a debug filter to highlight that a block has been rendered.
 * @param {!SVGElement} svgPath The block's SVG path.
 * @package
 */
Blockly.blockRendering.Debug.prototype.drawRender = function(svgPath) {
  if (!Blockly.blockRendering.Debug.config.render) {
    return;
  }
  svgPath.setAttribute('filter',
      'url(#' + this.constants_.debugFilterId + ')');
  setTimeout(function() {
    svgPath.setAttribute('filter', '');
  }, 100);
};
<|endoftext|>


<commit_before>const { expect } = require('chai');
var Draw = require("../DrawAnnots.js");
var ProxyTools = require("../../resource/ProxyTool.js")

describe('Draw annotations Component', function () {
  var context = ProxyTools.delayer({})
  var draw

  it('should initalize', async function () {
    draw = new Draw({}, context, true);
  });
  it('should accept points', async function () {
    draw.startDrawing()
    draw.extendFeature(0,0)
    draw.extendFeature(0,1)
    draw.extendFeature(1,1)
    draw.extendFeature(1,0)
  });
  it('should return a geojson', async function () {
    var geojson = draw.stopDrawing()
    expect(geojson).to.exist;
  });
});
<commit_msg>req path for proxy<commit_after>const { expect } = require('chai');
var Draw = require("../DrawAnnots.js");
var ProxyTools = require("../reqs/ProxyTool.js")

describe('Draw annotations Component', function () {
  var context = ProxyTools.delayer({})
  var draw

  it('should initalize', async function () {
    draw = new Draw({}, context, true);
  });
  it('should accept points', async function () {
    draw.startDrawing()
    draw.extendFeature(0,0)
    draw.extendFeature(0,1)
    draw.extendFeature(1,1)
    draw.extendFeature(1,0)
  });
  it('should return a geojson', async function () {
    var geojson = draw.stopDrawing()
    expect(geojson).to.exist;
  });
});
<|endoftext|>


<commit_before>sap.ui.define([
   'sap/ui/core/mvc/Controller',
   'sap/ui/model/json/JSONModel',
   'sap/ui/commons/CheckBox',
   'sap/ui/commons/Menu',
   'sap/ui/commons/MenuItem',
   'sap/ui/core/Item',
   'sap/ui/table/Column',
   'sap/m/Input',
   'sap/m/Button',
   "sap/m/FormattedText",
   "sap/ui/core/ResizeHandler",
   "sap/ui/layout/VerticalLayout",
   "sap/ui/layout/HorizontalLayout",
   "sap/m/MessageBox"
], function (Controller, JSONModel, CheckBox, Menu, MenuItem, coreItem, Column,
             mInput, mButton, FormattedText, ResizeHandler, VerticalLayout, HorizontalLayout) {

   "use strict";

   return Controller.extend("rootui5.eve7.controller.EveTable", {

      onInit : function() {
         var data = this.getView().getViewData();
         // console.log("VIEW DATA", data);

         var id = this.getView().getId();
         console.log("eve.GL.onInit id = ", id );

         this._load_scripts = true;
         this._render_html = false;

         this.mgr = data.mgr;
         this.eveViewerId = data.eveViewerId;
         this.kind = data.kind;

<<<<<<0))
            this.getView().byId("table").setRowHeight(rh);

=======
>>>>>>> 6360691bd8... Use two level sort and shade entries in cell table that do not pass filter.
         this.bindTableColumns = true;
         var element = this.mgr.GetElement(this.eveViewerId);
         // loop over scene and add dependency
         for (var k=0;k<element.childs.length;++k) {
            var scene = element.childs[k];
            this.mgr.RegisterSceneReceiver(scene.fSceneId, this);
            this.onSceneCreate();
         }
      },
      sortTable: function(e) {
	   var col = e.mParameters.column;
	   var colId = col.getId();

            // Do one-level sort on Filtered entry
           if ( col.mProperties.sortProperty === "Filtered")
               return;

	   var col = e.mParameters.column;
	   var bDescending = (e.mParameters.sortOrder ==  sap.ui.core.SortOrder.Descending);
	   var sv = bDescending;

	   var oSorter0 = new sap.ui.model.Sorter({
	       path: "Filtered",
	       descending: true
	   });

	   var oSorter1 = new sap.ui.model.Sorter({
	       path: col.mProperties.sortProperty,
	       descending: sv
	   });

          if ( col.mProperties.sortProperty === "Name")
          {
             let off = this.collection.fName.length;
             oSorter1.fnCompare = function(value1In, value2In) {
               let value1 = value1In.substring(off);
               let value2 = value2In.substring(off);
	       value2 = parseInt(value2);
	       value1 = parseInt(value1);
	       if (value1 < value2) return -1;
	       if (value1 == value2) return 0;
	       if (value1 > value2) return 1;
	     };
          }
          else {
	   oSorter1.fnCompare = function(value1, value2) {
	       value2 = parseFloat(value2);
	       value1 = parseFloat(value1);
	       if (value1 < value2) return -1;
	       if (value1 == value2) return 0;
	       if (value1 > value2) return 1;
	   };
          }
           var oTable = this.getView().byId("table");
	   var oItemsBinding = oTable.getBinding("rows");
	   oItemsBinding.sort([oSorter0, oSorter1]);
           col.setSorted(true);

           if (sv)
               col.setSortOrder(sap.ui.table.SortOrder.Descending);
           else
               col.setSortOrder(sap.ui.table.SortOrder.Ascending);

	   e.preventDefault();
      },

      locateEveTable: function()
      {
         this.eveTable = 0;
         var element = this.mgr.GetElement(this.eveViewerId);
         var sceneInfo = element.childs[0];
         var scene = this.mgr.GetElement(sceneInfo.fSceneId);
         // console.log(">>>table scene", scene);
         if (scene.childs[0]._typename == "ROOT::Experimental::REveTableViewInfo") {
            // presume table view manger is first child of table scene
            this.viewInfo = scene.childs[0];
         }

         // console.log("table viewinfo", this.viewInfo  );
         this.collection = this.mgr.GetElement(this.viewInfo.fDisplayedCollection);
         // loop over products
         for (var i = 1; i < scene.childs.length; ++i) {
            var product = scene.childs[i];
            if (product.childs && product.childs.length && product.childs[0].fCollectionId == this.viewInfo.fDisplayedCollection) {
               // console.log("table found  ",product.childs[0] );
               this.eveTable =  product.childs[0];
               break;
            }
         }

      },
      getCellText : function(value, filtered) {
	 return "" + value + ""
      },
      buildTableBody: function()
      {
         var oTable = this.getView().byId("table");

         // row definition
         var rowData = this.eveTable.body;

         // parse to float -- AMT in future data should be streamed as floats
         for (var r=0; r < rowData.length; r++) {
            var xr = rowData[r];
            for (var xri = 0; xri < xr.length; xri++) {
               var nv = parseFloat(xr[i]);
               if (nv != NaN) {
                  rowData[r][ri] = nv;
               }
            }
         }

         for (var i = 0; i < this.collection.childs.length; i++)
         {
            rowData[i].Name =  this.collection.childs[i].fName;
            rowData[i].Filtered =  this.collection.childs[i].fFiltered === true ? 0 : 1;
         }

         if (this.bindTableColumns) {
            // column definition
            var columnData = [];

            columnData.push({columnName:"Name"});
            columnData.push({columnName:"Filtered"});

            var eveColumns = this.eveTable.childs;
            for (var i = 0; i < eveColumns.length; i++)
            {
               var cname = eveColumns[i].fName;
               columnData.push({columnName : cname});
            }

            // table model
            var oModel = new JSONModel();
            oModel.setData({
               rows: rowData,
               columns: columnData
            });
            oTable.setModel(oModel);

	     var pthis = this;
             oTable.bindAggregation("columns", "/columns", function(sId, oContext) {
                 return new sap.ui.table.Column(sId, {
	             label: "{columnName}",
	             sortProperty: "{columnName}",
		     template: new FormattedText({
		         htmlText: {
			     parts: [
			         {path: oContext.getProperty("columnName")},
			         {path: "Filtered"}
			     ],
			     formatter: pthis.getCellText
		         }
		     }),
                     showFilterMenuEntry: true,
                     width: "100px"
               });
            });

	     // bind the Table items to the data collection
	     var oBinding = oTable.bindRows({
		 path : "/rows",
		 sorter: [
		     new sap.ui.model.Sorter({
			 path: 'Filtered',
			 descending: true
		     })
		 ]

	     });
            this.bindTableColumns = false;
         }
         else
         {
            var model = oTable.getModel();
            var data = model.getData();
            model.setData({"rows":rowData, "columns":data.columns});
         }
      },
      buildTableHeader: function()
      {
         var oModel = new JSONModel();
         var collection = this.mgr.GetElement(this.eveTable.fCollectionId);
         var clist = this.mgr.GetElement(collection.fMotherId);
         // console.log("collection list ", clist);

	 var mData = {
	    "itemx": [
	    ]};

         for (var i = 0; i < clist.childs.length; i++)
         {
            mData.itemx.push({"text" :clist.childs[i].fName, "key": clist.childs[i].fName, "collectionEveId":clist.childs[i].fElementId });
         }
         oModel.setData(mData);
         this.getView().setModel(oModel, "collections");

         var combo = this.getView().byId("ccombo");
         combo.setSelectedKey(collection.fName);
         combo.data("controller", this);
      },

      onLoadScripts: function() {
         this._load_scripts = true;
         this.checkScenes();
      },

      // function called from GuiPanelController
      onExit : function() {
         if (this.mgr) this.mgr.Unregister(this);
      },

      onSceneCreate: function(element, id) {
         console.log("EveTable onSceneChanged", id);
         this.locateEveTable();
         this.buildTableHeader();
         this.buildTableBody(true);
      },

      UpdateMgr : function(mgr) {
         var elem = mgr.map[this.eveViewerId];
         var scene = mgr.map[ elem.fMotherId];
         this.mgr = mgr;
      },

      onAfterRendering: function() {
         this._render_html = true;
         this.checkScenes();
      },

      checkScenes: function() {
      },

      toggleTableEdit: function() {
         var header = sap.ui.getCore().byId("EveViewer21--header");
         if (!this.editor) {
            this.editor = new VerticalLayout("tableEdit", {"width":"100%"});

            header.addContent(this.editor);

            // expression row
            {
               var collection = this.mgr.GetElement(this.eveTable.fCollectionId);
               var exprIn = new sap.m.Input("inputExp", {
    		  placeholder: "Start expression with \"i.\" to access object",
    		  showValueHelp: true,
    		  showTableSuggestionValueHelp: false,
    		  width: "100%",
    		  maxSuggestionWidth: "500px",
    		  showSuggestion: true,
    		  valueHelpRequest: function (oEvent) {
                     MessageBox.alert("Write any valid expression.\n Using \"i.\" convetion to access an object in collection. Below is an example:\ni.GetPdgCode() + 2");
    		  },
    		  suggestionItemSelected: function(oEvent){
    		     var oItem = oEvent.getParameter("selectedRow");
    		     console.log("sap.m.Input id with suggestion: selected item text is ------ " , oItem.getCells());
                     // fill in title if empty
                     var it = sap.ui.getCore().byId("titleEx");
                     if ((it.getValue() && it.getValue().length) == false) {
                        var v =  oItem.getCells()[0].getText().substring(2);
                        var t = v.split("(");
                        it.setValue(t[0]);
                     }
                     //fill in precision if empty
                     var ip = sap.ui.getCore().byId("precisionEx");
                     if ((ip.getValue() && ip.getValue().length) == false) {
                        var p = oItem.getCells()[1].getText();
                        if (p.startsWith("Int") || p.startsWith("int"))
                           ip.setValue("0");
                        else
                           ip.setValue("3");
                     }
    		  },
    		  suggestionColumns : [
    		     new sap.m.Column({
    			styleClass : "f",
    			hAlign : "Begin",
    			header : new sap.m.Label({
                           text : "Funcname"
    			})
    		     }),
    		     new sap.m.Column({
    			hAlign : "Center",
    			styleClass : "r",
    			popinDisplay : "Inline",
    			header : new sap.m.Label({
    			   text : "Return"
    			}),
    			minScreenWidth : "Tablet",
    			demandPopin : true
    		     }),

    		     new sap.m.Column({
    			hAlign : "End",
    			styleClass : "c",
    			width : "30%",
    			popinDisplay : "Inline",
    			header : new sap.m.Label({
                           text : "Class"
    			}),
    			minScreenWidth : "400px",
    			demandPopin : true
    		     })
    		  ]
    	       }).addStyleClass("inputRight");

               exprIn.setModel(oModel);

    	       var oTableItemTemplate = new sap.m.ColumnListItem({
    		  type : "Active",
    		  vAlign : "Middle",
    		  cells : [
    		     new sap.m.Label({
    			text : "{f}"
    		     }),
                     new sap.m.Label({
    			text: "{r}"
    		     }),
                     new sap.m.Label({
    			text : "{c}"
    		     })
    		  ]
    	       });
    	       var oModel = new sap.ui.model.json.JSONModel();
               var oSuggestionData = collection.fPublicFunctions;
               console.log("suggested data ",oSuggestionData );
    	       oModel.setData(oSuggestionData);
    	       exprIn.setModel(oModel);
    	       exprIn.bindAggregation("suggestionRows", "/", oTableItemTemplate);

               this.editor.addContent(exprIn);
            }

            // title & prec
            {
               var hl = new HorizontalLayout( {"width":"100%"});
               var titleIn = new mInput("titleEx", {placeholder:"Title", tooltip:"column title"});
             titleIn.setWidth("100%");
               hl.addContent(titleIn);

               var precIn = new mInput("precisionEx", {placeholder:"Precision", type: sap.m.InputType.Number, constraints: {minimum:"0", maximum:"9"}});
               precIn.setWidth("100%");
               hl.addContent(precIn);

               this.editor.addContent(hl);
            }

            //  button actions
            {
               var ll = new HorizontalLayout();
               var addBut = new mButton("AddCol", {text:"Add", press: this.addColumn});
               addBut.data("controller", this);
               ll.addContent(addBut);
               this.editor.visible = true;
               this.editor.addContent(ll);
            }
            return;
         }

         if (this.editor.visible) {
            var x = header.getContent().pop();
            header.removeContent(x);
            this.editor.visible = false;
         }
         else {
            header.addContent(this.editor);
            this.editor.visible = true;
         }
      },

      addColumn: function(event) {
         // console.log("add column s", event.getSource(), this);
         // console.log("add column p", this.data("controller"));
         var pthis = this.data("controller");
         var ws = pthis.editor.getContent();

         var expr = ws[0].getProperty("value");
         if (!expr) {
            alert("need a new column expression");
         }
         var hl =  ws[1].getContent();
         var title = hl[0].getProperty("value");
         if (!title) {
            title = expr;
         }

         pthis.mgr.SendMIR("AddNewColumnToCurrentCollection( \"" + expr + "\", \"" + title + "\" )",
                           pthis.viewInfo.fElementId, pthis.viewInfo._typename);

         // reset values
         sap.ui.getCore().byId("titleEx").setValue("");
         sap.ui.getCore().byId("precisionEx").setValue("");
      },

      collectionChanged: function(oEvent) {
         // console.log("collectionChanged ", oEvent.getSource());
         var model = oEvent.oSource.getSelectedItem().getBindingContext("collections");
         var path = model.getPath();
         var entry = model.getProperty(path);
         var coll = entry.collectionEveId;
         var mng =  this.viewInfo;

<<<<<<>>>>>> 6360691bd8... Use two level sort and shade entries in cell table that do not pass filter.
      },

      sceneElementChange : function(el)
      {
         // console.log("table sceneElementChange", el);
         if (el._typename == "ROOT::Experimental::REveTableViewInfo") {
            this.bindTableColumns = true;
         }
      },

      endChanges : function(oEvent) {
         // console.log("table controller endChanges ",this.eveTable );
         this.locateEveTable();
         this.buildTableBody();
      },

      elementRemoved: function(elId) {
         var el = this.mgr.GetElement(elId);
         // console.log("EveTable element removed ", el);
      }
   });
});
<commit_msg>Store Filtered value in items as a filter passed value.<commit_after>sap.ui.define([
   'sap/ui/core/mvc/Controller',
   'sap/ui/model/json/JSONModel',
   'sap/ui/commons/CheckBox',
   'sap/ui/commons/Menu',
   'sap/ui/commons/MenuItem',
   'sap/ui/core/Item',
   'sap/ui/table/Column',
   'sap/m/Input',
   'sap/m/Button',
   "sap/m/FormattedText",
   "sap/ui/core/ResizeHandler",
   "sap/ui/layout/VerticalLayout",
   "sap/ui/layout/HorizontalLayout",
   "sap/m/MessageBox"
], function (Controller, JSONModel, CheckBox, Menu, MenuItem, coreItem, Column,
             mInput, mButton, FormattedText, ResizeHandler, VerticalLayout, HorizontalLayout) {

   "use strict";

   return Controller.extend("rootui5.eve7.controller.EveTable", {

      onInit : function() {
         var data = this.getView().getViewData();
         // console.log("VIEW DATA", data);

         var id = this.getView().getId();
         console.log("eve.GL.onInit id = ", id );

         this._load_scripts = true;
         this._render_html = false;

         this.mgr = data.mgr;
         this.eveViewerId = data.eveViewerId;
         this.kind = data.kind;

         var rh = this.mgr.handle.GetUserArgs("TableRowHeight");
         if (rh && (rh>0))
            this.getView().byId("table").setRowHeight(rh);

         this.bindTableColumns = true;
         var element = this.mgr.GetElement(this.eveViewerId);
         // loop over scene and add dependency
         for (var k=0;k<element.childs.length;++k) {
            var scene = element.childs[k];
            this.mgr.RegisterSceneReceiver(scene.fSceneId, this);
            this.onSceneCreate();
         }
      },
      sortTable: function(e) {
	   var col = e.mParameters.column;
	   var colId = col.getId();

	   var col = e.mParameters.column;
	   var bDescending = (e.mParameters.sortOrder ==  sap.ui.core.SortOrder.Descending);
	   var sv = bDescending;

	   var oSorter0 = new sap.ui.model.Sorter({
	       path: "Filtered",
	       descending: false
	   });

	   var oSorter1 = new sap.ui.model.Sorter({
	       path: col.mProperties.sortProperty,
	       descending: sv
	   });

	   oSorter1.fnCompare = function(value1, value2) {
	       value2 = parseFloat(value2);
	       value1 = parseFloat(value1);
	       if (value1 < value2) return -1;
	       if (value1 == value2) return 0;
	       if (value1 > value2) return 1;
	   };

           var oTable = this.getView().byId("table");
	   var oItemsBinding = oTable.getBinding("rows");
	   oItemsBinding.sort([oSorter0, oSorter1]);
           col.setSorted(true);

           if (sv)
               col.setSortOrder(sap.ui.table.SortOrder.Descending);
           else
               col.setSortOrder(sap.ui.table.SortOrder.Ascending);

	   e.preventDefault();
      },

      locateEveTable: function()
      {
         this.eveTable = 0;
         var element = this.mgr.GetElement(this.eveViewerId);
         var sceneInfo = element.childs[0];
         var scene = this.mgr.GetElement(sceneInfo.fSceneId);
         // console.log(">>>table scene", scene);
         if (scene.childs[0]._typename == "ROOT::Experimental::REveTableViewInfo") {
            // presume table view manger is first child of table scene
            this.viewInfo = scene.childs[0];
         }

         // console.log("table viewinfo", this.viewInfo  );
         this.collection = this.mgr.GetElement(this.viewInfo.fDisplayedCollection);
         // loop over products
         for (var i = 1; i < scene.childs.length; ++i) {
            var product = scene.childs[i];
            if (product.childs && product.childs.length && product.childs[0].fCollectionId == this.viewInfo.fDisplayedCollection) {
               // console.log("table found  ",product.childs[0] );
               this.eveTable =  product.childs[0];
               break;
            }
         }

      },
      getCellText : function(value, filtered) {
	 return "" + value + ""
      },
      buildTableBody: function()
      {
         var oTable = this.getView().byId("table");

         // row definition
         var rowData = this.eveTable.body;

         // parse to float -- AMT in future data should be streamed as floats
         for (var r=0; r < rowData.length; r++) {
            var xr = rowData[r];
            for (var xri = 0; xri < xr.length; xri++) {
               var nv = parseFloat(xr[i]);
               if (nv != NaN) {
                  rowData[r][ri] = nv;
               }
            }
         }

         for (var i = 0; i < this.collection.childs.length; i++)
         {
            rowData[i].Name =  this.collection.childs[i].fName;
            rowData[i].Filtered =  this.collection.childs[i].fFiltered === true ? 1 : 0;
         }

         if (this.bindTableColumns) {
            // column definition
            var columnData = [];

            columnData.push({columnName:"Name"});
            columnData.push({columnName:"Filtered"});

            var eveColumns = this.eveTable.childs;
            for (var i = 0; i < eveColumns.length; i++)
            {
               var cname = eveColumns[i].fName;
               columnData.push({columnName : cname});
            }

            // table model
            var oModel = new JSONModel();
            oModel.setData({
               rows: rowData,
               columns: columnData
            });
            oTable.setModel(oModel);

	     var pthis = this;
             oTable.bindAggregation("columns", "/columns", function(sId, oContext) {
                 return new sap.ui.table.Column(sId, {
	             label: "{columnName}",
	             sortProperty: "{columnName}",
		     template: new FormattedText({
		         htmlText: {
			     parts: [
			         {path: oContext.getProperty("columnName")},
			         {path: "Filtered"}
			     ],
			     formatter: pthis.getCellText
		         }
		     }),
                     showFilterMenuEntry: true,
                     width: "100px"
               });
            });

	     // bind the Table items to the data collection
	     var oBinding = oTable.bindRows({
		 path : "/rows",
		 sorter: [
		     new sap.ui.model.Sorter({
			 path: 'Filtered',
			 descending: false
		     })
		 ]

	     });
            this.bindTableColumns = false;
         }
         else
         {
            var model = oTable.getModel();
            var data = model.getData();
            model.setData({"rows":rowData, "columns":data.columns});
         }
      },
      buildTableHeader: function()
      {
         var oModel = new JSONModel();
         var collection = this.mgr.GetElement(this.eveTable.fCollectionId);
         var clist = this.mgr.GetElement(collection.fMotherId);
         // console.log("collection list ", clist);

	 var mData = {
	    "itemx": [
	    ]};

         for (var i = 0; i < clist.childs.length; i++)
         {
            mData.itemx.push({"text" :clist.childs[i].fName, "key": clist.childs[i].fName, "collectionEveId":clist.childs[i].fElementId });
         }
         oModel.setData(mData);
         this.getView().setModel(oModel, "collections");

         var combo = this.getView().byId("ccombo");
         combo.setSelectedKey(collection.fName);
         combo.data("controller", this);
      },

      onLoadScripts: function() {
         this._load_scripts = true;
         this.checkScenes();
      },

      // function called from GuiPanelController
      onExit : function() {
         if (this.mgr) this.mgr.Unregister(this);
      },

      onSceneCreate: function(element, id) {
         console.log("EveTable onSceneChanged", id);
         this.locateEveTable();
         this.buildTableHeader();
         this.buildTableBody(true);
      },

      UpdateMgr : function(mgr) {
         var elem = mgr.map[this.eveViewerId];
         var scene = mgr.map[ elem.fMotherId];
         this.mgr = mgr;
      },

      onAfterRendering: function() {
         this._render_html = true;
         this.checkScenes();
      },

      checkScenes: function() {
      },

      toggleTableEdit: function() {
         var header = sap.ui.getCore().byId("EveViewer21--header");
         if (!this.editor) {
            this.editor = new VerticalLayout("tableEdit", {"width":"100%"});

            header.addContent(this.editor);

            // expression row
            {
               var collection = this.mgr.GetElement(this.eveTable.fCollectionId);
               var exprIn = new sap.m.Input("inputExp", {
    		  placeholder: "Start expression with \"i.\" to access object",
    		  showValueHelp: true,
    		  showTableSuggestionValueHelp: false,
    		  width: "100%",
    		  maxSuggestionWidth: "500px",
    		  showSuggestion: true,
    		  valueHelpRequest: function (oEvent) {
                     MessageBox.alert("Write any valid expression.\n Using \"i.\" convetion to access an object in collection. Below is an example:\ni.GetPdgCode() + 2");
    		  },
    		  suggestionItemSelected: function(oEvent){
    		     var oItem = oEvent.getParameter("selectedRow");
    		     console.log("sap.m.Input id with suggestion: selected item text is ------ " , oItem.getCells());
                     // fill in title if empty
                     var it = sap.ui.getCore().byId("titleEx");
                     if ((it.getValue() && it.getValue().length) == false) {
                        var v =  oItem.getCells()[0].getText().substring(2);
                        var t = v.split("(");
                        it.setValue(t[0]);
                     }
                     //fill in precision if empty
                     var ip = sap.ui.getCore().byId("precisionEx");
                     if ((ip.getValue() && ip.getValue().length) == false) {
                        var p = oItem.getCells()[1].getText();
                        if (p.startsWith("Int") || p.startsWith("int"))
                           ip.setValue("0");
                        else
                           ip.setValue("3");
                     }
    		  },
    		  suggestionColumns : [
    		     new sap.m.Column({
    			styleClass : "f",
    			hAlign : "Begin",
    			header : new sap.m.Label({
                           text : "Funcname"
    			})
    		     }),
    		     new sap.m.Column({
    			hAlign : "Center",
    			styleClass : "r",
    			popinDisplay : "Inline",
    			header : new sap.m.Label({
    			   text : "Return"
    			}),
    			minScreenWidth : "Tablet",
    			demandPopin : true
    		     }),

    		     new sap.m.Column({
    			hAlign : "End",
    			styleClass : "c",
    			width : "30%",
    			popinDisplay : "Inline",
    			header : new sap.m.Label({
                           text : "Class"
    			}),
    			minScreenWidth : "400px",
    			demandPopin : true
    		     })
    		  ]
    	       }).addStyleClass("inputRight");

               exprIn.setModel(oModel);

    	       var oTableItemTemplate = new sap.m.ColumnListItem({
    		  type : "Active",
    		  vAlign : "Middle",
    		  cells : [
    		     new sap.m.Label({
    			text : "{f}"
    		     }),
                     new sap.m.Label({
    			text: "{r}"
    		     }),
                     new sap.m.Label({
    			text : "{c}"
    		     })
    		  ]
    	       });
    	       var oModel = new sap.ui.model.json.JSONModel();
               var oSuggestionData = collection.fPublicFunctions;
               console.log("suggested data ",oSuggestionData );
    	       oModel.setData(oSuggestionData);
    	       exprIn.setModel(oModel);
    	       exprIn.bindAggregation("suggestionRows", "/", oTableItemTemplate);

               this.editor.addContent(exprIn);
            }

            // title & prec
            {
               var hl = new HorizontalLayout( {"width":"100%"});
               var titleIn = new mInput("titleEx", {placeholder:"Title", tooltip:"column title"});
             titleIn.setWidth("100%");
               hl.addContent(titleIn);

               var precIn = new mInput("precisionEx", {placeholder:"Precision", type: sap.m.InputType.Number, constraints: {minimum:"0", maximum:"9"}});
               precIn.setWidth("100%");
               hl.addContent(precIn);

               this.editor.addContent(hl);
            }

            //  button actions
            {
               var ll = new HorizontalLayout();
               var addBut = new mButton("AddCol", {text:"Add", press: this.addColumn});
               addBut.data("controller", this);
               ll.addContent(addBut);
               this.editor.visible = true;
               this.editor.addContent(ll);
            }
            return;
         }

         if (this.editor.visible) {
            var x = header.getContent().pop();
            header.removeContent(x);
            this.editor.visible = false;
         }
         else {
            header.addContent(this.editor);
            this.editor.visible = true;
         }
      },

      addColumn: function(event) {
         // console.log("add column s", event.getSource(), this);
         // console.log("add column p", this.data("controller"));
         var pthis = this.data("controller");
         var ws = pthis.editor.getContent();

         var expr = ws[0].getProperty("value");
         if (!expr) {
            alert("need a new column expression");
         }
         var hl =  ws[1].getContent();
         var title = hl[0].getProperty("value");
         if (!title) {
            title = expr;
         }

         pthis.mgr.SendMIR("AddNewColumnToCurrentCollection( \"" + expr + "\", \"" + title + "\" )",
                           pthis.viewInfo.fElementId, pthis.viewInfo._typename);

         // reset values
         sap.ui.getCore().byId("titleEx").setValue("");
         sap.ui.getCore().byId("precisionEx").setValue("");
      },

      collectionChanged: function(oEvent) {
         // console.log("collectionChanged ", oEvent.getSource());
         var model = oEvent.oSource.getSelectedItem().getBindingContext("collections");
         var path = model.getPath();
         var entry = model.getProperty(path);
         var coll = entry.collectionEveId;
         var mng =  this.viewInfo;

         this.mgr.SendMIR("SetDisplayedCollection(" + coll + ")", mng.fElementId, mng._typename);
      },

      sceneElementChange : function(el)
      {
         // console.log("table sceneElementChange", el);
         if (el._typename == "ROOT::Experimental::REveTableViewInfo") {
            this.bindTableColumns = true;
         }
      },

      endChanges : function(oEvent) {
         // console.log("table controller endChanges ",this.eveTable );
         this.locateEveTable();
         this.buildTableBody();
      },

      elementRemoved: function(elId) {
         var el = this.mgr.GetElement(elId);
         // console.log("EveTable element removed ", el);
      }
   });
});
<|endoftext|>


<commit_before>'use strict';
/**
 * @file Retrieve contacts for the account
 */

var config = require('../../config/configuration.js');
var mapper = require('./mapper.js');
var request = require('request');

/**
 * Use the Google refresh token to get a new accessToken,
 *
 * @param {String} refreshToken Refresh token issued by Google
 * @param {Function} cb First parameter is the error (if any), then the new accessToken (valid for one hour)
 */
var refreshAccessToken = function(refreshToken, cb) {

  // See https://developers.google.com/accounts/docs/OAuth2WebServer#refresh for details
  var params = {
    url: 'https://accounts.google.com/o/oauth2/token',
    form: {
      'refresh_token': refreshToken,
      'client_id': config.googleId,
      'client_secret': config.googleSecret,
      'grant_type': 'refresh_token'
    },
    json: true
  };

  request.post(params, function (err, res) {
    if(err){
      return cb(err);
    }

    if(res.statusCode === 401){
      return cb(new Error("Access to this refresh_token has been revoked."));
    }
    if(res.statusCode !== 200) {
      return cb(new Error("Google Error: " + res.body.message));
    }

    cb(null, res.body.access_token);
  });
};

/**
 * Retrieve all contacts associated with this user account,
 *
 * @param {String} accessToken AccessToken to identify the account
 * @param {Date} since Retrieve contacts updated since this date
 * @param {Function} cb Callback. First parameter is the error (if any), then an array of all the contacts.
 */
var retrieveContacts = function(accessToken, since, cb) {

  // Pad n to have a length of width,
  // pad(1, 3) == 001
  var pad = function(n, width) {
    width = width || 2;
    n = n + '';
    return n.length >= width ? n : new Array(width - n.length + 1).join(0) + n;
  };

  // Date, formatted as 2007-03-16T00:00:00
  var formattedDate = since.getFullYear() + '-' + pad(since.getMonth() + 1) + '-' + pad(since.getDate()) + 'T' + pad(since.getHours()) + ':' + pad(since.getMinutes()) + ':' + pad(since.getSeconds());

  // See https://developers.google.com/google-apps/contacts/v3/?csw=1#retrieving_contacts_using_query_parameters for details
  var params = {
    url: 'https://www.google.com/m8/feeds/contacts/default/full',
    qs: {
      alt: 'json',
      'max-results': 100000,
      'showdeleted': true,
      'orderby': 'lastmodified',
      'updated-min': formattedDate
    },
    headers: {
      'Authorization': 'OAuth ' + accessToken,
      'GData-Version': '3.0'
    },
    json: true
  };

  request.get(params, function (err, resp, body) {
    if(err) {
      return cb(err);
    }
    if(resp.statusCode === 401){
      return cb (new Error("Wrong Google Authorization provided."));
    }

    var contacts = body.feed.entry ? body.feed.entry.map(mapper):[];

    // Contacts is now full!
    cb(null, contacts);
  });
};

/**
 * Download all contacts from the specified Google Account.
 *
 * @param {String} refreshToken Refresh_token to identify the account
 * @param {Date} since Retrieve contacts updated since this date
 * @param {Function} cb Callback. First parameter is the error (if any), second an array of all the contacts.
 */
module.exports = function(refreshToken, since, cb) {
  refreshAccessToken(refreshToken, function(err, accessToken) {
    if(err) {
      return cb(err);
    }

    retrieveContacts(accessToken, since, cb);
  });
};
<commit_msg>Add groups request<commit_after>'use strict';
/**
 * @file Retrieve contacts for the account
 */

var config = require('../../config/configuration.js');
var mapper = require('./mapper.js');
var request = require('request');
var async = require('async');
var rarity = require('rarity');

/**
 * Use the Google refresh token to get a new accessToken,
 *
 * @param {String} refreshToken Refresh token issued by Google
 * @param {Function} cb First parameter is the error (if any), then the new accessToken (valid for one hour)
 */
var refreshAccessToken = function(refreshToken, cb) {

  // See https://developers.google.com/accounts/docs/OAuth2WebServer#refresh for details
  var params = {
    url: 'https://accounts.google.com/o/oauth2/token',
    form: {
      'refresh_token': refreshToken,
      'client_id': config.googleId,
      'client_secret': config.googleSecret,
      'grant_type': 'refresh_token'
    },
    json: true
  };

  request.post(params, function (err, res) {
    if(err){
      return cb(err);
    }

    if(res.statusCode === 401){
      return cb(new Error("Access to this refresh_token has been revoked."));
    }
    if(res.statusCode !== 200) {
      return cb(new Error("Google Error: " + res.body.message));
    }

    cb(null, res.body.access_token);
  });
};

/**
 * Retrieve all contacts associated with this user account,
 *
 * @param {String} accessToken AccessToken to identify the account
 * @param {Date} since Retrieve contacts updated since this date
 * @param {Function} cb Callback. First parameter is the error (if any), then an array of all the contacts.
 */
var retrieveContacts = function(accessToken, since, cb) {

  // Pad n to have a length of width,
  // pad(1, 3) == 001
  var pad = function(n, width) {
    width = width || 2;
    n = n + '';
    return n.length >= width ? n : new Array(width - n.length + 1).join(0) + n;
  };

  // Date, formatted as 2007-03-16T00:00:00
  var formattedDate = since.getFullYear() + '-' + pad(since.getMonth() + 1) + '-' + pad(since.getDate()) + 'T' + pad(since.getHours()) + ':' + pad(since.getMinutes()) + ':' + pad(since.getSeconds());

  async.waterfall([
    function requestContacts(cb) {
      // See https://developers.google.com/google-apps/contacts/v3/?csw=1#retrieving_contacts_using_query_parameters for details
      var params = {
        url: 'https://www.google.com/m8/feeds/contacts/default/full',
        qs: {
          alt: 'json',
          'max-results': 100000,
          'showdeleted': true,
          'orderby': 'lastmodified',
          'updated-min': formattedDate
        },
        headers: {
          'Authorization': 'OAuth ' + accessToken,
          'GData-Version': '3.0'
        },
        json: true
      };

      request.get(params, cb);
    },
    function getContacts(resp, body, cb) {
      if(resp.statusCode === 401){
        return cb(new Error("Wrong Google Authorization provided."));
      }

      cb(null, body.feed.entry ? body.feed.entry.map(mapper):[]);
    },
    function requestGroups(contacts, cb) {
      var params = {
        url: 'https://www.google.com/m8/feeds/groups/default/full',

        qs: {
          alt: 'json'
        },
        headers: {
          'Authorization': 'OAuth ' + accessToken,
          'GData-Version': '3.0'
        },
        json: true
      };

      request.get(params, rarity.carry([contacts], cb));
    },
    function getGroups(contacts, resp, body, cb) {
      if(resp.statusCode === 401){
        return cb(new Error("Wrong Google Authorization provided."));
      }

      var groups = {};
      body.feed.entry.forEach(function(r) {
        groups[r.id['$t']] = r.title['$t'];
      });

      cb(null, contacts, groups);
    },
    function associateContactsAndGroups(contacts, groups, cb) {
      contacts.forEach(function(contact) {
        if(contact.groups) {
          for(var i = 0, len = contact.groups.length; i < len; i += 1) {
            contact.groups[i] = groups[contact.groups[i]];
          }
        }
      });

      cb(null, contacts);
    }
  ], cb);
};

/**
 * Download all contacts from the specified Google Account.
 *
 * @param {String} refreshToken Refresh_token to identify the account
 * @param {Date} since Retrieve contacts updated since this date
 * @param {Function} cb Callback. First parameter is the error (if any), second an array of all the contacts.
 */
module.exports = function(refreshToken, since, cb) {
  refreshAccessToken(refreshToken, function(err, accessToken) {
    if(err) {
      return cb(err);
    }

    retrieveContacts(accessToken, since, cb);
  });
};
<|endoftext|>


<commit_before>import {
  RECEIVE_REVISIONS,
  REVISIONS_LOADING,
  RECEIVE_COURSE_SCOPED_REVISIONS,
  COURSE_SCOPED_REVISIONS_LOADING,
  SORT_REVISIONS,
  RECEIVE_REFERENCES,
  RECEIVE_ASSESSMENTS
} from '../constants';
import { sortByKey } from '../utils/model_utils';
import moment from 'moment';

const initialState = {
  revisions: [],
  limitReached: false,
  courseScopedRevisions: [],
  courseScopedLimit: 50,
  courseScopedLimitReached: false,
  sort: {
    key: null,
    sortKey: null,
  },
  revisionsLoaded: false,
  courseScopedRevisionsLoaded: false,
  last_date: moment().format(),
};

const isLimitReachedCourseSpecific = (revs, limit) => {
  return (revs.length < limit);
};

const isLimitReached = (course_start, last_date) => {
  return moment(course_start).isAfter(moment(last_date)) || moment(last_date).isBefore(moment().subtract(5, 'years'));
};

export default function revisions(state = initialState, action) {
  switch (action.type) {
    case RECEIVE_REFERENCES: {
      const newState = { ...state };
      const revisionsArray = newState.revisions;
      const referencesAdded = action.data.referencesAdded;
      newState.revisions = revisionsArray.map((revision) => {
        return { references_added: referencesAdded?.[revision.revid] ?? 0, ...revision };
      });
      return newState;
    }
    case RECEIVE_ASSESSMENTS: {
      const newState = { ...state };
      const revisionsArray = newState.revisions;
      const pageAssessments = action.data.assessments;
      newState.revisions = revisionsArray.map((revision) => {
        return {
          rating_num: pageAssessments?.[revision.revid]?.rating_num,
          pretty_rating: pageAssessments?.[revision.revid]?.pretty_rating,
          rating: pageAssessments?.[revision.revid]?.rating,
          ...revision
        };
      });
      return newState;
    }
    case RECEIVE_REVISIONS:
      return {
        ...state,
        revisions: action.data.course.revisions,
        limitReached: isLimitReached(action.data.course.start, state.last_date),
        revisionsLoaded: true,
        last_date: action.data.last_date
      };
    case RECEIVE_COURSE_SCOPED_REVISIONS:
      return {
        ...state,
        courseScopedRevisions: action.data.course.revisions,
        courseScopedLimit: action.limit,
        courseScopedLimitReached: isLimitReachedCourseSpecific(action.data.course.revisions, action.limit),
        courseScopedRevisionsLoaded: true
      };
    case REVISIONS_LOADING:
      return {
        ...state,
        revisionsLoaded: false,
      };
    case COURSE_SCOPED_REVISIONS_LOADING:
      return {
        ...state,
        courseScopedRevisionsLoaded: false
      };
    case SORT_REVISIONS: {
      const absolute = action.key === 'characters';
      const desc = action.key === state.sort.sortKey;

      const sortedRevisions = sortByKey(state.revisions, action.key, null, desc, absolute);
      const sortedCourseScopedRevisions = sortByKey(state.courseScopedRevisions, action.key, null, desc, absolute);
      return { ...state,
        revisions: sortedRevisions.newModels,
        courseScopedRevisions: sortedCourseScopedRevisions.newModels,
        sort: {
          sortKey: desc ? null : action.key,
          key: action.key
        }
      };
    }
    default:
      return state;
  }
}
<commit_msg>Changed default value of references added<commit_after>import {
  RECEIVE_REVISIONS,
  REVISIONS_LOADING,
  RECEIVE_COURSE_SCOPED_REVISIONS,
  COURSE_SCOPED_REVISIONS_LOADING,
  SORT_REVISIONS,
  RECEIVE_REFERENCES,
  RECEIVE_ASSESSMENTS
} from '../constants';
import { sortByKey } from '../utils/model_utils';
import moment from 'moment';

const initialState = {
  revisions: [],
  limitReached: false,
  courseScopedRevisions: [],
  courseScopedLimit: 50,
  courseScopedLimitReached: false,
  sort: {
    key: null,
    sortKey: null,
  },
  revisionsLoaded: false,
  courseScopedRevisionsLoaded: false,
  last_date: moment().format(),
};

const isLimitReachedCourseSpecific = (revs, limit) => {
  return (revs.length < limit);
};

const isLimitReached = (course_start, last_date) => {
  return moment(course_start).isAfter(moment(last_date)) || moment(last_date).isBefore(moment().subtract(5, 'years'));
};

export default function revisions(state = initialState, action) {
  switch (action.type) {
    case RECEIVE_REFERENCES: {
      const newState = { ...state };
      const revisionsArray = newState.revisions;
      const referencesAdded = action.data.referencesAdded;
      newState.revisions = revisionsArray.map((revision) => {
        return { references_added: referencesAdded?.[revision?.revid], ...revision };
      });
      return newState;
    }
    case RECEIVE_ASSESSMENTS: {
      const newState = { ...state };
      const revisionsArray = newState.revisions;
      const pageAssessments = action.data.assessments;
      newState.revisions = revisionsArray.map((revision) => {
        return {
          rating_num: pageAssessments?.[revision.revid]?.rating_num,
          pretty_rating: pageAssessments?.[revision.revid]?.pretty_rating,
          rating: pageAssessments?.[revision.revid]?.rating,
          ...revision
        };
      });
      return newState;
    }
    case RECEIVE_REVISIONS:
      return {
        ...state,
        revisions: action.data.course.revisions,
        limitReached: isLimitReached(action.data.course.start, state.last_date),
        revisionsLoaded: true,
        last_date: action.data.last_date
      };
    case RECEIVE_COURSE_SCOPED_REVISIONS:
      return {
        ...state,
        courseScopedRevisions: action.data.course.revisions,
        courseScopedLimit: action.limit,
        courseScopedLimitReached: isLimitReachedCourseSpecific(action.data.course.revisions, action.limit),
        courseScopedRevisionsLoaded: true
      };
    case REVISIONS_LOADING:
      return {
        ...state,
        revisionsLoaded: false,
      };
    case COURSE_SCOPED_REVISIONS_LOADING:
      return {
        ...state,
        courseScopedRevisionsLoaded: false
      };
    case SORT_REVISIONS: {
      const absolute = action.key === 'characters';
      const desc = action.key === state.sort.sortKey;

      const sortedRevisions = sortByKey(state.revisions, action.key, null, desc, absolute);
      const sortedCourseScopedRevisions = sortByKey(state.courseScopedRevisions, action.key, null, desc, absolute);
      return { ...state,
        revisions: sortedRevisions.newModels,
        courseScopedRevisions: sortedCourseScopedRevisions.newModels,
        sort: {
          sortKey: desc ? null : action.key,
          key: action.key
        }
      };
    }
    default:
      return state;
  }
}
<|endoftext|>


<commit_before>var
  fs = require('fs'),
  path = require('path'),
  q = require('q'),
  childProcess = require('child_process'),
  lockfile = require('proper-lockfile'),
  _ = require('lodash'),
  clc = require('cli-color'),
  configuration = require('rc')('proxy'),
  clcError = clc.red,
  clcOk = clc.green.bold;

module.exports = function pluginsInstall () {
  if (!childProcess.hasOwnProperty('execSync')) {
    console.error(clcError('███ kuzzle-plugins: Make sure you\'re using Node version >= 0.12'));
    process.exit(1);
  }

  // Prevents multiple plugins install at the same time.
  lockfile.lock('./node_modules', {retries: 1000, minTimeout: 200, maxTimeout: 1000, stale: 60000, update: 10000}, (err, release) => {
    if (err) {
      console.error(clcError('███ kuzzle-plugins: Unable to acquire lock: '), err);
      process.exit(1);
    }

    q.fcall(() => {
      console.log('███ kuzzle-plugins: Starting plugins installation...');

      return acquirePlugins(configuration.protocolPlugins);
    })
      .then(() => {
        release();

        console.log(clcOk('███ kuzzle-plugins: Plugins installed'));

        process.exit(0);
      })
      .catch(error => {
        release();

        console.error(clcError('Error: '), error);
        process.exit(error.status);
      });
  });
};

/**
 * Download given plugins
 *
 * @param {*} plugins
 * @returns {boolean}
 */
function acquirePlugins(plugins) {
  var
    newInstalled = false,
    installViaNpm = true,
    pluginInstallId;

  _.forEach(plugins, (plugin, name) => {
    /** @var {{gitUrl: String, npmVersion: String}} plugin */
    if (plugin.path) {
      console.log('███ kuzzle-plugins: Plugin', name, 'uses local plugin. Config will be overrided with local changes.');
      installViaNpm = false;
    }
    else if (plugin.gitUrl) {
      pluginInstallId = plugin.gitUrl;
    }
    else if (plugin.npmVersion) {
      pluginInstallId = name + '@' + plugin.npmVersion;
    }
    else {
      console.error(clcError('███ kuzzle-plugins: Plugin'), name, 'provides no means of installation. Expected: path, git URL or npm version');
      process.exit(1);
    }

    if (!plugin.path && !needInstall(plugin, name, pluginInstallId)) {
      console.log('███ kuzzle-plugins: Plugin', name, 'is already installed. Skipping...');
      return true;
    }

    console.log('███ kuzzle-plugins: Downloading plugin: ', name);

    newInstalled = true;
    if (installViaNpm) {
      npmInstall(pluginInstallId);
    }

    console.log('███ kuzzle-plugins: Plugin', name, 'downloaded');
  });

  return newInstalled;
}

/**
 * Install a plugin with NPM
 * @param plugin
 */
function npmInstall(plugin) {
  return childProcess
    .execSync('npm install ' + plugin)
    .toString();
}

/**
 * Detects if the configured plugin must be installed
 * If the plugin is configured with an url from GIT, the plugin is installed every time
 *   to ensure getting the latest release
 * If the plugin come from NPM or , the plugin is installed only if the required version
 *   is different from the version of the already installed plugin
 *
 * @param plugin
 * @param name
 * @param from previously installation information with version or git url with branch
 * @returns {boolean} true if the plugin must be installed, false if not
 */
function needInstall(plugin, name, from) {
  var
    packageDefinition,
    packagePath,
    pluginPath = getPathPlugin(plugin, name);

  // If we want to install a plugin with git, maybe there is no version and we want to 'pull' the plugin
  if (from.indexOf('git') !== -1) {
    return true;
  }

  if (!fs.existsSync(pluginPath)) {
    return true;
  }

  packagePath = path.join(pluginPath, 'package.json');
  if (!fs.existsSync(packagePath)) {
    return true;
  }

  /** @type {{_from: String}} */
  packageDefinition = require(path.join(pluginPath, 'package.json'));

  // If version in package.json is different from the version the plugins.json, we want to install the updated plugin
  return (packageDefinition._from !== from);
}

/**
 * Return the real plugin path
 *
 * @param pluginConfig
 * @param pluginName
 * @returns {String}
 */
function getPathPlugin (pluginConfig, pluginName) {
  if (pluginConfig.path) {
    return pluginConfig.path;
  }
  return path.join(__dirname, '..', '..', 'node_modules', pluginName);
}
<commit_msg>Fix node_modules folder behavior when installing<commit_after>var
  fs = require('fs'),
  path = require('path'),
  q = require('q'),
  childProcess = require('child_process'),
  lockfile = require('proper-lockfile'),
  _ = require('lodash'),
  clc = require('cli-color'),
  configuration = require('rc')('proxy'),
  clcError = clc.red,
  clcOk = clc.green.bold;

module.exports = function pluginsInstall () {
  if (!childProcess.hasOwnProperty('execSync')) {
    console.error(clcError('███ kuzzle-plugins: Make sure you\'re using Node version >= 0.12'));
    process.exit(1);
  }

  // Prevents multiple plugins install at the same time.
  lockfile.lock('./node_modules', {retries: 1000, minTimeout: 200, maxTimeout: 1000, stale: 60000, update: 10000}, (err, release) => {
    if (err) {
      console.error(clcError('███ kuzzle-plugins: Unable to acquire lock: '), err);
      process.exit(1);
    }

    q.fcall(() => {
      console.log('███ kuzzle-plugins: Starting plugins installation...');

      return acquirePlugins(configuration.protocolPlugins);
    })
      .then(() => {
        release();

        console.log(clcOk('███ kuzzle-plugins: Plugins installed'));

        process.exit(0);
      })
      .catch(error => {
        release();

        console.error(clcError('Error: '), error);
        process.exit(error.status);
      });
  });
};

/**
 * Download given plugins
 *
 * @param {*} plugins
 * @returns {boolean}
 */
function acquirePlugins(plugins) {
  var
    newInstalled = false,
    installViaNpm = true,
    pluginInstallId;

  if (!fs.existsSync(getNodeModuleFolder())) {
    fs.mkdirSync(getNodeModuleFolder());
  }

  _.forEach(plugins, (plugin, name) => {
    /** @var {{gitUrl: String, npmVersion: String}} plugin */
    if (plugin.path) {
      console.log('███ kuzzle-plugins: Plugin', name, 'uses local plugin. Config will be overrided with local changes.');
      installViaNpm = false;
    }
    else if (plugin.gitUrl) {
      pluginInstallId = plugin.gitUrl;
    }
    else if (plugin.npmVersion) {
      pluginInstallId = name + '@' + plugin.npmVersion;
    }
    else {
      console.error(clcError('███ kuzzle-plugins: Plugin'), name, 'provides no means of installation. Expected: path, git URL or npm version');
      process.exit(1);
    }

    if (!plugin.path && !needInstall(plugin, name, pluginInstallId)) {
      console.log('███ kuzzle-plugins: Plugin', name, 'is already installed. Skipping...');
      return true;
    }

    console.log('███ kuzzle-plugins: Downloading plugin: ', name);

    newInstalled = true;
    if (installViaNpm) {
      npmInstall(pluginInstallId);
    }

    console.log('███ kuzzle-plugins: Plugin', name, 'downloaded');
  });

  return newInstalled;
}

/**
 * Install a plugin with NPM
 * @param plugin
 */
function npmInstall(plugin) {
  return childProcess
    .execSync('npm install ' + plugin)
    .toString();
}

/**
 * Detects if the configured plugin must be installed
 * If the plugin is configured with an url from GIT, the plugin is installed every time
 *   to ensure getting the latest release
 * If the plugin come from NPM or , the plugin is installed only if the required version
 *   is different from the version of the already installed plugin
 *
 * @param plugin
 * @param name
 * @param from previously installation information with version or git url with branch
 * @returns {boolean} true if the plugin must be installed, false if not
 */
function needInstall(plugin, name, from) {
  var
    packageDefinition,
    packagePath,
    pluginPath = getPathPlugin(plugin, name);

  // If we want to install a plugin with git, maybe there is no version and we want to 'pull' the plugin
  if (from.indexOf('git') !== -1) {
    return true;
  }

  if (!fs.existsSync(pluginPath)) {
    return true;
  }

  packagePath = path.join(pluginPath, 'package.json');
  if (!fs.existsSync(packagePath)) {
    return true;
  }

  /** @type {{_from: String}} */
  packageDefinition = require(path.join(pluginPath, 'package.json'));

  // If version in package.json is different from the version the plugins.json, we want to install the updated plugin
  return (packageDefinition._from !== from);
}

/**
 * Return the real plugin path
 *
 * @param pluginConfig
 * @param pluginName
 * @returns {String}
 */
function getPathPlugin (pluginConfig, pluginName) {
  if (pluginConfig.path) {
    return pluginConfig.path;
  }
  return path.join(getNodeModuleFolder(), pluginName);
}

function getNodeModuleFolder () {
  return path.join(__dirname, '..', '..', 'node_modules');
}
<|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 Globals for the Karma test environment.
 */

var GLOBALS = {
  INTERACTION_SPECS: {},
  GADGET_SPECS: {},
  PANEL_SPECS: {}
};

// jscs:disable maximumLineLength
/* This function overwrites the translationProvider for a dummy function
 * (customLoader). This is necessary to prevent the js test warnings about an
 * "unexpected GET request" when the translationProvider tries to load the
 * translation files.
 * More info in the angular-translate documentation
 * http://angular-translate.github.io/docs/#/guide/22_unit-testing-with-angular-translate
 */
// jscs:enable maximumLineLength
GLOBALS.TRANSLATOR_PROVIDER_FOR_TESTS = function($provide, $translateProvider) {
  $provide.factory('customLoader', function($q) {
    return function() {
      var deferred = $q.defer();
      deferred.resolve({});
      return deferred.promise;
    };
  });
  $translateProvider.useLoader('customLoader');
};
<commit_msg>Fix lint issue.<commit_after>// Copyright 2016 The Oppia Authors. 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.

/**
 * @fileoverview Globals for the Karma test environment.
 */

var GLOBALS = {
  INTERACTION_SPECS: {},
  GADGET_SPECS: {},
  PANEL_SPECS: {}
};

/* This function overwrites the translationProvider for a dummy function
 * (customLoader). This is necessary to prevent the js test warnings about an
 * "unexpected GET request" when the translationProvider tries to load the
 * translation files.
 * More info in the angular-translate documentation:
 *   http://angular-translate.github.io/docs/#/guide
 * (see the "Unit Testing" section).
 */
GLOBALS.TRANSLATOR_PROVIDER_FOR_TESTS = function($provide, $translateProvider) {
  $provide.factory('customLoader', function($q) {
    return function() {
      var deferred = $q.defer();
      deferred.resolve({});
      return deferred.promise;
    };
  });
  $translateProvider.useLoader('customLoader');
};
<|endoftext|>


<commit_before>var http = require('http');
var url = require('url');
var querystring = require('querystring');

function Client(serverUrl){
    var parsed_url = url.parse(serverUrl);
    this.request_options = {
        protocol: parsed_url.protocol,
        port: parsed_url.port,
        pathname: parsed_url.pathname,
        headers: {
            "Content-Type": "application/json"
        }
    };
    this.headers = {
        "Content-Type": "application/json"
    };
}

Client.prototype.get = function(path, parameters, options, callback, errCallback){
    var opts = {
        method: 'GET'
    };
    opts = Object.assign(opts, this.request_options, options);
    var query = querystring.stringify(parameters);
    opts.pathname = opts.pathname + path;
    opts.path = opts.pathname + '?' + query;
    delete opts.pathname;

    var req = http.request(opts, callback);
    req.on('error', errCallback || console.error);

    req.end();
}

function createMethodRequest(method){
    return function(path, parameters, options, callback, errCallback){
        var opts = {
            method: method
        };

        opts = Object.assign(opts, this.request_options, options);
        opts.pathname = opts.pathname + path;
        opts.path = opts.pathname;
        delete opts.pathname;

        var req = http.request(opts, callback);
        req.on('error', errCallback || console.error);

        req.write(JSON.stringify(parameters));
        req.end();
    }
}

Client.prototype.post = createMethodRequest('post');

Client.prototype.delete = createMethodRequest('delete');

Client.prototype.put = createMethodRequest('put');

Client.prototype.patch = createMethodRequest('patch');

module.exports = {
    client: Client
}
<commit_msg>Add hostname and host<commit_after>var http = require('http');
var url = require('url');
var querystring = require('querystring');

function Client(serverUrl){
    var parsed_url = url.parse(serverUrl);
    this.request_options = {
        protocol: parsed_url.protocol,
        port: parsed_url.port,
        host: parsed_url.host,
        hostname: parsed_url.hostname,
        pathname: parsed_url.pathname,
        headers: {
            "Content-Type": "application/json"
        }
    };
    this.headers = {
        "Content-Type": "application/json"
    };
}

Client.prototype.get = function(path, parameters, options, callback, errCallback){
    var opts = {
        method: 'GET'
    };
    opts = Object.assign(opts, this.request_options, options);
    var query = querystring.stringify(parameters);
    opts.pathname = opts.pathname + path;
    opts.path = opts.pathname + '?' + query;
    delete opts.pathname;

    var req = http.request(opts, callback);
    req.on('error', errCallback || console.error);

    req.end();
}

function createMethodRequest(method){
    return function(path, parameters, options, callback, errCallback){
        var opts = {
            method: method
        };

        opts = Object.assign(opts, this.request_options, options);
        opts.pathname = opts.pathname + path;
        opts.path = opts.pathname;
        delete opts.pathname;

        var req = http.request(opts, callback);
        req.on('error', errCallback || console.error);

        req.write(JSON.stringify(parameters));
        req.end();
    }
}

Client.prototype.post = createMethodRequest('post');

Client.prototype.delete = createMethodRequest('delete');

Client.prototype.put = createMethodRequest('put');

Client.prototype.patch = createMethodRequest('patch');

module.exports = {
    client: Client
}
<|endoftext|>


<commit_before>'use strict';

define(["app"], function(app) {

app.factory("DataCache", [
  "$rootScope", "ImagesUtils", "ArrayUtils", "Network",
  function($rootScope, $imagesUtils, $arrayUtils, $network) {

  var _cache = {};
  var _callback = {};

  function add(key, data) {
    _cache[key] = data;
    fireEvent(key);
  }

  function fireEvent(key) {
    if(_callback[key] !== undefined) {
      for (var i = 0; i < _callback[key].length; i++) {
        _callback[key][i](_cache[key]);
      };
    }
  }

  $rootScope.$on('userInfos', function(evt, data) {
    if(_cache.userInfos == undefined) {
      _cache.userInfos = [];
      _cache.userInfos.push(data);
    } else {
      var index = $arrayUtils.indexOf(_cache.userInfos, data, "socialType");
      if(index > -1) {
        _cache.userInfos[index] = data;
      } else {
        if($imagesUtils.isDefaultImage(_cache.userInfos[0].avatar)) {
          _cache.userInfos.splice(0, 0, data);
        } else {
          _cache.userInfos.push(data);
        }
      }
    }
    fireEvent('userInfos');
  });

  $rootScope.$on('allColumns', function(evt, columns) {
    add('allColumns', columns);
  });

  $rootScope.$on('addColumn', function(evt, column) {
    _cache.allColumns.push(column);
    fireEvent('allColumns');
  });

  $rootScope.$on('modColumn', function(evt, column) {
    var index = $arrayUtils.indexOf(_cache.allColumns, column, "title");
    if(index > -1) {
      _cache.allColumns.splice(index, 1);
      _cache.allColumns.push(column.column);
      fireEvent('allColumns');
    }
  });

  $rootScope.$on('delColumn', function(evt, column) {
    var index = $arrayUtils.indexOf(_cache.allColumns, column, "title");
    if(index > -1) {
      _cache.allColumns.splice(index, 1);
      fireEvent('allColumns');
    }
  });

  $rootScope.$on('allUnifiedRequests', function(evt, providers) {
    add('allUnifiedRequests', providers);
  });

  return {
    get: function(key, callback) {
      return _cache[key];
    },
    add: function(key, data) {
      add(key, data);
    },
    on: function(key, callback) {
      _callback[key] = _callback[key] || [];
      _callback[key].push(callback);
      console.log(_cache);
      if(_cache[key] !== undefined) {
        callback(_cache[key]);
      } else if(key == "allUnifiedRequests") {
        $network.send({cmd:"allUnifiedRequests"});
      }
    }
  }

}]);

return app;
});<commit_msg>fix mod column bug<commit_after>'use strict';

define(["app"], function(app) {

app.factory("DataCache", [
  "$rootScope", "ImagesUtils", "ArrayUtils", "Network",
  function($rootScope, $imagesUtils, $arrayUtils, $network) {

  var _cache = {};
  var _callback = {};

  function add(key, data) {
    _cache[key] = data;
    fireEvent(key);
  }

  function fireEvent(key) {
    if(_callback[key] !== undefined) {
      for (var i = 0; i < _callback[key].length; i++) {
        _callback[key][i](_cache[key]);
      };
    }
  }

  $rootScope.$on('userInfos', function(evt, data) {
    if(_cache.userInfos == undefined) {
      _cache.userInfos = [];
      _cache.userInfos.push(data);
    } else {
      var index = $arrayUtils.indexOf(_cache.userInfos, data, "socialType");
      if(index > -1) {
        _cache.userInfos[index] = data;
      } else {
        if($imagesUtils.isDefaultImage(_cache.userInfos[0].avatar)) {
          _cache.userInfos.splice(0, 0, data);
        } else {
          _cache.userInfos.push(data);
        }
      }
    }
    fireEvent('userInfos');
  });

  $rootScope.$on('allColumns', function(evt, columns) {
    add('allColumns', columns);
  });

  $rootScope.$on('addColumn', function(evt, column) {
    _cache.allColumns.push(column);
    fireEvent('allColumns');
  });

  $rootScope.$on('modColumn', function(evt, column) {
    var index = $arrayUtils.indexOf(_cache.allColumns, column, "title");
    if(index > -1) {
      _cache.allColumns[index] = column.column;
      fireEvent('allColumns');
    }
  });

  $rootScope.$on('delColumn', function(evt, column) {
    var index = $arrayUtils.indexOf(_cache.allColumns, column, "title");
    if(index > -1) {
      _cache.allColumns.splice(index, 1);
      fireEvent('allColumns');
    }
  });

  $rootScope.$on('allUnifiedRequests', function(evt, providers) {
    add('allUnifiedRequests', providers);
  });

  return {
    get: function(key, callback) {
      return _cache[key];
    },
    add: function(key, data) {
      add(key, data);
    },
    on: function(key, callback) {
      _callback[key] = _callback[key] || [];
      _callback[key].push(callback);
      console.log(_cache);
      if(_cache[key] !== undefined) {
        callback(_cache[key]);
      } else if(key == "allUnifiedRequests") {
        $network.send({cmd:"allUnifiedRequests"});
      }
    }
  }

}]);

return app;
});<|endoftext|>