<commit_before>function renderDisplayObject(child, ctx, transform, cxform) {
  var m = transform;
  ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);

  if (cxform) {
    // We only support alpha channel transformation for now
    ctx.globalAlpha = (ctx.globalAlpha * cxform.alphaMultiplier + cxform.alphaOffset) / 256;
  }

  if (child._graphics) {
    var graphics = child._graphics;

    var scale = graphics._scale;
    if (scale !== 1)
      ctx.scale(scale, scale);

    var subpaths = graphics._subpaths;
    for (var j = 0, o = subpaths.length; j < o; j++) {
      var path = subpaths[j];
      if (path.fillStyle) {
        ctx.fillStyle = path.fillStyle;
        if (path.fillTransform) {
          var m = path.fillTransform;
          ctx.beginPath();
          path.__draw__(ctx);
          ctx.save();
          ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);
          ctx.fill();
          ctx.restore();
        } else {
          ctx.fill(path);
        }
      }
      if (path.strokeStyle) {
        ctx.strokeStyle = path.strokeStyle;
        var drawingStyles = path.drawingStyles;
        for (var prop in drawingStyles)
          ctx[prop] = drawingStyles[prop];
        ctx.stroke(path);
      }
    }
  }

  if (child.draw)
    child.draw(ctx, child.ratio);
}

function renderStage(stage, ctx) {
  var frameWidth = ctx.canvas.width;
  var frameHeight = ctx.canvas.height;

  var scaleX = frameWidth / stage._stageWidth;
  var scaleY = frameHeight / stage._stageHeight;

  var scale = Math.min(scaleX, scaleY);
  var offsetX = (frameWidth - scale * stage.stageWidth) / 2;
  var offsetY = (frameHeight - scale * stage.stageHeight) / 2;

  ctx.translate(offsetX, offsetY);
  ctx.scale(scale, scale);

  // All the visitors close over this class to do instance testing.
  var MovieClipClass = avm2.systemDomain.getClass("flash.display.MovieClip");
  var ContainerClass = avm2.systemDomain.getClass("flash.display.DisplayObjectContainer");
  var SimpleButtonClass = avm2.systemDomain.getClass("flash.display.SimpleButton");
  var InteractiveClass = avm2.systemDomain.getClass("flash.display.InteractiveObject");

  function visitContainer(container, visitor, interactiveParent) {
    var children = container._children;
    var dirty = false;

    visitor.childrenStart(container);

    for (var i = 0, n = children.length; i < n; i++) {
      var child = children[i];
      if (child) {
        var isContainer = ContainerClass.isInstanceOf(child) ||
                          SimpleButtonClass.isInstanceOf(child);

        if (InteractiveClass.isInstanceOf(child)) {
          if (!interactiveParent || interactiveParent._mouseChildren)
            interactiveParent = child;
        }

        visitor.visit(child, isContainer, interactiveParent);

        if (isContainer)
          visitContainer(child, visitor, interactiveParent);

        if (child._dirtyArea)
          dirty = true;
      }
    }

    visitor.childrenEnd(container);

    if (dirty)
      container._bounds = null;
  }

  function PreVisitor(ctx) {
    this.ctx = ctx;
  }
  PreVisitor.prototype = {
    childrenStart: function() {},
    childrenEnd: function() {},
    visit: function (child, isContainer, interactiveParent) {
      if (MovieClipClass.isInstanceOf(child)) {
        if (child.isPlaying()) {
          child.nextFrame();
        }
        child.dispatchEvent(new flash.events.Event("enterFrame"));
      }

      if (child._refreshAS2Variables) {
        child._refreshAS2Variables();
      }

      if (interactiveParent && (stage._mouseOver || stage._mouseJustLeft)) {
        var hitArea = child._hitArea || child;
        var pt = new flash.geom.Point(stage._mouseX, stage._mouseY);
        child._applyCurrentInverseTransform(pt, child._parent);

        if (child._hitTest(true, pt.x, pt.y, true)) {
          if (interactiveParent._mouseOver) {
            interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseMove'));
          } else {
            interactiveParent._mouseOver = true;
            interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOver'));
          }

          stage._clickTarget = interactiveParent;
        } else {
          if (interactiveParent._mouseOver) {
            interactiveParent._mouseOver = false;
            interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOut'));
          }

          if (stage._clickTarget === interactiveParent)
            stage._clickTarget = null;
        }
        stage._mouseJustLeft = false;
      }

      if (child._dirtyArea) {
        var b1 = child._dirtyArea;
        var b2 = child.getBounds();
        this.ctx.rect((~~b1.x) - 5, (~~b1.y) - 5, (~~b1.width) + 10, (~~b1.height) + 10);
        this.ctx.rect((~~b2.x) - 5, (~~b2.y) - 5, (~~b2.width) + 10, (~~b2.height) + 10);
      } else if (child._graphics && (child._graphics._revision !== child._revision)) {
        child._revision = child._graphics._revision;
        child._markAsDirty();
        // redraw entire stage till we calculate bounding boxes for dynamic graphics
        this.ctx.rect(0, 0, frameWidth, frameHeight);
      }
    }
  };

  function PostVisitor() {
  }
  PostVisitor.prototype = {
    childrenStart: function() {},
    childrenEnd: function() {},
    visit: function (child) {
      if (MovieClipClass.isInstanceOf(child))
        child.dispatchEvent(new flash.events.Event("exitFrame"));
    }
  };

  function ScriptExecutionVisitor() {}
  ScriptExecutionVisitor.prototype = {
    childrenStart: function() {},
    childrenEnd: function() {},
    visit: function (obj) {
      if (obj._scriptExecutionPending) {
        obj._scriptExecutionPending = false;

        var currentFrame = obj._currentFrame;
        obj._callFrame(currentFrame);
      }
    }
  };

  function RenderVisitor(ctx) {
    this.ctx = ctx;
    this.depth = 0;
  }
  RenderVisitor.prototype = {
    childrenStart: function(parent) {
      if (this.depth == 0) {
        var ctx = this.ctx;

        ctx.save();

        ctx.clip();

        ctx.clearRect(0, 0, frameWidth, frameHeight);

        ctx.mozFillRule = 'evenodd';

        stage._canvasState = {
          canvas: ctx.canvas,
          scale: scale,
          offsetX: offsetX,
          offsetY: offsetY
        };
      }
      this.depth++;
    },
    childrenEnd: function(parent) {
      this.depth--;
      this.ctx.restore();
    },
    visit: function (child, isContainer) {
      if (child._clipDepth) {
        // TODO handle masking
        return;
      }

      var ctx = this.ctx;
      ctx.save();

      renderDisplayObject(child, ctx, child._currentTransform, child._cxform);

      if (!isContainer) {
        // letting the container to restore transforms after all children are painted
        ctx.restore();
      }

      if (stage._showRedrawRegions && child._dirtyArea) {
        var b = child._dirtyArea;
        ctx.save();
        ctx.strokeStyle = '#f00';
        ctx.lineWidth = 1;
        ctx.strokeRect(b.x, b.y, b.width, b.height);
        ctx.restore();
      }

      child._dirtyArea = null;
    }
  };

  var frameTime = 0;
  var maxDelay = 1000 / stage.frameRate;

  var requestAnimationFrame = window.requestAnimationFrame ||
                              window.mozRequestAnimationFrame ||
                              window.webkitRequestAnimationFrame ||
                              window.oRequestAnimationFrame ||
                              window.msRequestAnimationFrame ||
                              window.setTimeout;

  (function draw() {
    var now = +new Date;
    if (now - frameTime >= maxDelay) {
      frameTime = now;

      ctx.beginPath();

      stage._callFrameRequested = false;
      visitContainer(stage, new PreVisitor(ctx));
      while (stage._callFrameRequested) {
        stage._callFrameRequested = false;
        visitContainer(stage, new ScriptExecutionVisitor());
      }
      visitContainer(stage, new RenderVisitor(ctx));
      visitContainer(stage, new PostVisitor());
      stage._syncCursor();
    }
    requestAnimationFrame(draw);
  })();
}
<commit_msg>Check for InteractiveObject::mouseEnabled.<commit_after>function renderDisplayObject(child, ctx, transform, cxform) {
  var m = transform;
  ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);

  if (cxform) {
    // We only support alpha channel transformation for now
    ctx.globalAlpha = (ctx.globalAlpha * cxform.alphaMultiplier + cxform.alphaOffset) / 256;
  }

  if (child._graphics) {
    var graphics = child._graphics;

    var scale = graphics._scale;
    if (scale !== 1)
      ctx.scale(scale, scale);

    var subpaths = graphics._subpaths;
    for (var j = 0, o = subpaths.length; j < o; j++) {
      var path = subpaths[j];
      if (path.fillStyle) {
        ctx.fillStyle = path.fillStyle;
        if (path.fillTransform) {
          var m = path.fillTransform;
          ctx.beginPath();
          path.__draw__(ctx);
          ctx.save();
          ctx.transform(m.a, m.b, m.c, m.d, m.tx, m.ty);
          ctx.fill();
          ctx.restore();
        } else {
          ctx.fill(path);
        }
      }
      if (path.strokeStyle) {
        ctx.strokeStyle = path.strokeStyle;
        var drawingStyles = path.drawingStyles;
        for (var prop in drawingStyles)
          ctx[prop] = drawingStyles[prop];
        ctx.stroke(path);
      }
    }
  }

  if (child.draw)
    child.draw(ctx, child.ratio);
}

function renderStage(stage, ctx) {
  var frameWidth = ctx.canvas.width;
  var frameHeight = ctx.canvas.height;

  var scaleX = frameWidth / stage._stageWidth;
  var scaleY = frameHeight / stage._stageHeight;

  var scale = Math.min(scaleX, scaleY);
  var offsetX = (frameWidth - scale * stage.stageWidth) / 2;
  var offsetY = (frameHeight - scale * stage.stageHeight) / 2;

  ctx.translate(offsetX, offsetY);
  ctx.scale(scale, scale);

  // All the visitors close over this class to do instance testing.
  var MovieClipClass = avm2.systemDomain.getClass("flash.display.MovieClip");
  var ContainerClass = avm2.systemDomain.getClass("flash.display.DisplayObjectContainer");
  var SimpleButtonClass = avm2.systemDomain.getClass("flash.display.SimpleButton");
  var InteractiveClass = avm2.systemDomain.getClass("flash.display.InteractiveObject");

  function visitContainer(container, visitor, interactiveParent) {
    var children = container._children;
    var dirty = false;

    visitor.childrenStart(container);

    for (var i = 0, n = children.length; i < n; i++) {
      var child = children[i];
      if (child) {
        var isContainer = ContainerClass.isInstanceOf(child) ||
                          SimpleButtonClass.isInstanceOf(child);

        if (InteractiveClass.isInstanceOf(child) && child._mouseEnabled) {
          if (!interactiveParent || interactiveParent._mouseChildren)
            interactiveParent = child;
        }

        visitor.visit(child, isContainer, interactiveParent);

        if (isContainer)
          visitContainer(child, visitor, interactiveParent);

        if (child._dirtyArea)
          dirty = true;
      }
    }

    visitor.childrenEnd(container);

    if (dirty)
      container._bounds = null;
  }

  function PreVisitor(ctx) {
    this.ctx = ctx;
  }
  PreVisitor.prototype = {
    childrenStart: function() {},
    childrenEnd: function() {},
    visit: function (child, isContainer, interactiveParent) {
      if (MovieClipClass.isInstanceOf(child)) {
        if (child.isPlaying()) {
          child.nextFrame();
        }
        child.dispatchEvent(new flash.events.Event("enterFrame"));
      }

      if (child._refreshAS2Variables) {
        child._refreshAS2Variables();
      }

      if (interactiveParent && (stage._mouseOver || stage._mouseJustLeft)) {
        var hitArea = child._hitArea || child;
        var pt = new flash.geom.Point(stage._mouseX, stage._mouseY);
        child._applyCurrentInverseTransform(pt, child._parent);

        if (child._hitTest(true, pt.x, pt.y, true)) {
          if (interactiveParent._mouseOver) {
            interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseMove'));
          } else {
            interactiveParent._mouseOver = true;
            interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOver'));
          }

          stage._clickTarget = interactiveParent;
        } else {
          if (interactiveParent._mouseOver) {
            interactiveParent._mouseOver = false;
            interactiveParent.dispatchEvent(new flash.events.MouseEvent('mouseOut'));
          }

          if (stage._clickTarget === interactiveParent)
            stage._clickTarget = null;
        }
        stage._mouseJustLeft = false;
      }

      if (child._dirtyArea) {
        var b1 = child._dirtyArea;
        var b2 = child.getBounds();
        this.ctx.rect((~~b1.x) - 5, (~~b1.y) - 5, (~~b1.width) + 10, (~~b1.height) + 10);
        this.ctx.rect((~~b2.x) - 5, (~~b2.y) - 5, (~~b2.width) + 10, (~~b2.height) + 10);
      } else if (child._graphics && (child._graphics._revision !== child._revision)) {
        child._revision = child._graphics._revision;
        child._markAsDirty();
        // redraw entire stage till we calculate bounding boxes for dynamic graphics
        this.ctx.rect(0, 0, frameWidth, frameHeight);
      }
    }
  };

  function PostVisitor() {
  }
  PostVisitor.prototype = {
    childrenStart: function() {},
    childrenEnd: function() {},
    visit: function (child) {
      if (MovieClipClass.isInstanceOf(child))
        child.dispatchEvent(new flash.events.Event("exitFrame"));
    }
  };

  function ScriptExecutionVisitor() {}
  ScriptExecutionVisitor.prototype = {
    childrenStart: function() {},
    childrenEnd: function() {},
    visit: function (obj) {
      if (obj._scriptExecutionPending) {
        obj._scriptExecutionPending = false;

        var currentFrame = obj._currentFrame;
        obj._callFrame(currentFrame);
      }
    }
  };

  function RenderVisitor(ctx) {
    this.ctx = ctx;
    this.depth = 0;
  }
  RenderVisitor.prototype = {
    childrenStart: function(parent) {
      if (this.depth == 0) {
        var ctx = this.ctx;

        ctx.save();

        ctx.clip();

        ctx.clearRect(0, 0, frameWidth, frameHeight);

        ctx.mozFillRule = 'evenodd';

        stage._canvasState = {
          canvas: ctx.canvas,
          scale: scale,
          offsetX: offsetX,
          offsetY: offsetY
        };
      }
      this.depth++;
    },
    childrenEnd: function(parent) {
      this.depth--;
      this.ctx.restore();
    },
    visit: function (child, isContainer) {
      if (child._clipDepth) {
        // TODO handle masking
        return;
      }

      var ctx = this.ctx;
      ctx.save();

      renderDisplayObject(child, ctx, child._currentTransform, child._cxform);

      if (!isContainer) {
        // letting the container to restore transforms after all children are painted
        ctx.restore();
      }

      if (stage._showRedrawRegions && child._dirtyArea) {
        var b = child._dirtyArea;
        ctx.save();
        ctx.strokeStyle = '#f00';
        ctx.lineWidth = 1;
        ctx.strokeRect(b.x, b.y, b.width, b.height);
        ctx.restore();
      }

      child._dirtyArea = null;
    }
  };

  var frameTime = 0;
  var maxDelay = 1000 / stage.frameRate;

  var requestAnimationFrame = window.requestAnimationFrame ||
                              window.mozRequestAnimationFrame ||
                              window.webkitRequestAnimationFrame ||
                              window.oRequestAnimationFrame ||
                              window.msRequestAnimationFrame ||
                              window.setTimeout;

  (function draw() {
    var now = +new Date;
    if (now - frameTime >= maxDelay) {
      frameTime = now;

      ctx.beginPath();

      stage._callFrameRequested = false;
      visitContainer(stage, new PreVisitor(ctx));
      while (stage._callFrameRequested) {
        stage._callFrameRequested = false;
        visitContainer(stage, new ScriptExecutionVisitor());
      }
      visitContainer(stage, new RenderVisitor(ctx));
      visitContainer(stage, new PostVisitor());
      stage._syncCursor();
    }
    requestAnimationFrame(draw);
  })();
}
<|endoftext|>


<commit_before>var _ = require('../lodash-local')                               // import _ from 'lodash'
var util = require('../util')                           // import util from '../util'
var taskOps = require('../constants/task-op')           // import * as taskOps from '../constants/task-op'

/*
  syntax: request(url|connection[, config])

  json: {
    "op": "request",
    "params": {
      "method": "",
      "connection": "",
      "url": "",
      "username": "",
      "password": "",
      "params": {},
      "data": {},
      "headers": {}
    }
  }
*/

// task definition function
var request = function() {
  var args = Array.from(arguments)
  var url = _.get(args, '[0]', '')
  var params = _.get(args, '[1]', {})

  // if we specify all of the options as a param object, we're basically done
  // and we can skip all of the parameterization checks below
  if (_.isPlainObject(_.get(args, '[0]', {})))
  {
    params = _.get(args, '[0]', {})
  }
   else
  {
    params = _.assign({}, { url }, params)
  }

  // default to `GET` method
  params = _.assign({ method: 'GET' }, params)

  return {
    op: taskOps.TASK_OP_REQUEST,
    params
  }
}

request.toCode = function(json, Flexio) {
  var params = _.get(json, 'params', {})
  var url = _.get(params, 'url', '')
  var opts = _.omit(params, ['url'])
  if (_.get(opts, 'method', '') == 'GET')
    opts = _.omit(opts, ['method'])

  if (_.isEmpty(opts))
    return 'request(' + JSON.stringify(url) + ')'
     else
    return 'request(' + JSON.stringify(url) + ', ' + JSON.stringify(opts, null, 2) + ')'
}

module.exports = request // export default request
<commit_msg>removed _.isEqual() dependency<commit_after>var _ = require('../lodash-local')                               // import _ from 'lodash'
var util = require('../util')                           // import util from '../util'
var taskOps = require('../constants/task-op')           // import * as taskOps from '../constants/task-op'

/*
  syntax: request(url|connection[, config])

  json: {
    "op": "request",
    "params": {
      "method": "",
      "connection": "",
      "url": "",
      "username": "",
      "password": "",
      "params": {},
      "data": {},
      "headers": {}
    }
  }
*/

// task definition function
var request = function() {
  var args = Array.from(arguments)
  var url = _.get(args, '[0]', '')
  var params = _.get(args, '[1]', {})

  // if we specify all of the options as a param object, we're basically done
  // and we can skip all of the parameterization checks below
  if (_.isPlainObject(_.get(args, '[0]', {})))
  {
    params = _.get(args, '[0]', {})
  }
   else
  {
    params = _.assign({}, { url }, params)
  }

  // default to `GET` method
  params = _.assign({ method: 'GET' }, params)

  return {
    op: taskOps.TASK_OP_REQUEST,
    params
  }
}

request.toCode = function(json, Flexio) {
  var params = _.get(json, 'params', {})
  var url = _.get(params, 'url', '')
  var opts = _.omit(params, ['url'])
  if (_.get(opts, 'method', '') == 'GET')
    opts = _.omit(opts, ['method'])

  if (Object.keys(opts).length == 0)
    return 'request(' + JSON.stringify(url) + ')'
     else
    return 'request(' + JSON.stringify(url) + ', ' + JSON.stringify(opts, null, 2) + ')'
}

module.exports = request // export default request
<|endoftext|>


<commit_before>"use strict";

/**
 * Copyright 2017 XcooBee LLC

 * 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.
 */
const runTest = (argv, callback) => {
    const path = require("path");
    const fs = require("fs");

    let parametersFilePath = path.resolve("./parameters.json");
    let outputPath = path.resolve("./");
    let ttl = 30000;
    // How long have we been running?
    let ellapsed = 0;

    // The amount of time reserved for clean up tasks
    const timeToCleanUp = 5000;

    // Track the number of open write streams
    const streamArray = [];

    let callbackCalled = false;

    const closeStreams = () => {
        streamArray.forEach((value) => {
            value.close();
        });
    };

    let globalSequence = 1;
    const getNextId = () => {
        const current = globalSequence;
        globalSequence += 1;
        return current;
    };

    const createServices = (inputFilePath) => {
        // TODO: Validation for fileName, what should happen if the user requests a writeStream for an
        // already created fileName
        // Create the services object
        const services = {
            // Just log a message to the system console
            log: (message, type) => {
                const chunk = `${Date.now()},${type},${message}\n`;
                console.log(chunk);
            },
            // email service to mock the sending of an email
            mail: () => {
                // TODO: What do in here? Log something? Do Nothing?
            },
            getNextId,
            addParam: (key, value) => {
                console.log(`${key} => ${value} added to the next bee`);
            },
            timeToRun: () => ttl - ellapsed,
            // The default streams for reading and writing
            readStream: fs.createReadStream(inputFilePath),
            // TODO: Should overwrite the files
            writeStream: fs.createWriteStream(`${outputPath}${path.sep}output${path.sep}bee_default_output`),
            writeStreamManager: () => ({
                getWriteStream: (fileName, type) => {
                    const typePath = type === "wip" ? "workFiles" : "output";
                    const stream = fs.createWriteStream(`${outputPath}${path.sep}${typePath}${path.sep}${fileName}`);
                    streamArray.push(stream);
                    return stream;
                },
                getReadStream: (fileName, type) => {
                    const typePath = type === "wip" ? "workFiles" : "output";
                    const stream = fs.createReadStream(`${outputPath}${path.sep}${typePath}${path.sep}${fileName}`);
                    return stream;
                },
            }),
        };

        return services;
    };

    // Assume we are on the node project directory
    // unless otherwise specified by the --bee switch
    let beeModule = null;
    try {
        const beeIndex = argv.indexOf("--bee");
        if (beeIndex !== -1) {
            const pathToBee = path.resolve(argv[beeIndex + 1]);
            beeModule = require(pathToBee);
        } else {
            // TODO: Don't rely on cwd
            beeModule = require(process.cwd());
        }
    } catch (err) {
        callback(new Error("It was not possible to load the bee, make sure you are inside a valid node project or use the '--bee' switch"));
    }

    // Set the size instance in which this bee will be run
    // We use the size to, among other things, choose the proper ttl
    const sizeIndex = argv.indexOf("--size");
    if (sizeIndex !== -1) {
        const validSizes = ["s", "m", "l"];
        const size = argv[sizeIndex + 1].toLowerCase();

        if (validSizes.indexOf(size) === -1) {
            callback(new Error(`'${size}' is not a valid size, must be one of [s, m, l]`));
        }

        if (size === "s") {
            ttl = 30000;
        } else if (size === "m") {
            ttl = 150000;
        } else {
            ttl = 300000;
        }
    }

    // Substract the timeToCleanUp from ttl to get the net time the bee got available
    ttl -= timeToCleanUp;

    // If no params file are provided we assume the bee won't require integrations
    // nor parameters, unless the '--params' flag is used in which case it is, probably,
    // an user error pointing to an unexistent file
    const paramsIndex = argv.indexOf("--params");
    if (paramsIndex !== -1) {
        parametersFilePath = path.resolve(argv[paramsIndex + 1]);

        if (!fs.existsSync(parametersFilePath)) {
            callback(Error(`${parametersFilePath} doesn't exist`));
        }
    }

    // If the user specifies the output as a directory, use a default file name 'output' with no extension
    // The output directory must exists, the utility WON'T create it
    const outputIndex = argv.indexOf("--out");
    if (outputIndex !== -1) {
        outputPath = path.resolve(argv[outputIndex + 1]);

        // TODO: A way to create the hierarchy
        if (!fs.existsSync(outputPath)) {
            callback(new Error(`${outputPath} is not a valid directory`));
        }

        const stats = fs.lstatSync(outputPath);

        if (!stats.isDirectory()) {
            callback(new Error(`${outputPath} is not a valid directory`));
        }
    }

    if (!fs.existsSync(`${outputPath}${path.sep}output`)) {
        fs.mkdirSync(`${outputPath}${path.sep}output`);
    }

    if (!fs.existsSync(`${outputPath}${path.sep}workFiles`)) {
        fs.mkdirSync(`${outputPath}${path.sep}workFiles`);
    }

    // The input file must be the first argument
    const inputFilePath = path.resolve(argv[2]);

    if (!fs.existsSync(inputFilePath)) {
        callback(new Error(`Input file '${inputFilePath}' doesn't exist`));
    }

    const services = createServices(inputFilePath);

    const data = {
        // Mock data just for testing purposes
        user_data: {
            first_name: "John",
            last_name: "Testerson",
            xcoobee_id: "~johnt",
        },
    };

    let parametersContent = null;

    if (fs.existsSync(parametersFilePath)) {
        try {
            parametersContent = JSON.parse(fs.readFileSync(parametersFilePath, "utf8"));
            data.integrations = parametersContent.integrations;
            data.parameters = parametersContent.bee_params;
        } catch (err) {
            callback(new Error(`${parametersFilePath} is not a valid JSON file`));
        }
    }

    const beeCallback = (err, result) => {
        callbackCalled = true;
        clearInterval();
        console.log(`Total exec time: ${ellapsed} millis`);
        closeStreams();
        if (err) {
            return callback(err);
        }

        return callback(null, result);
    };

    setTimeout(() => {
        if (!callbackCalled) {
            clearInterval();
            closeStreams();
            callback(new Error("Timed-out"));
        }
    }, ttl);

    setInterval(() => {
        ellapsed += 2;
    }, 2);

    beeModule.flight(services, data, beeCallback);
};

if (require.main === module) {
    const callback = (err, result) => {
        if (err) {
            console.log(err.message);
            return process.exit(1);
        }
        console.log(result);
        return process.exit(0);
    };
    runTest(process.argv, callback);
}

module.exports.runTest = (argv, callback) => {
    runTest(argv, callback);
};
<commit_msg>Removes writeStream service<commit_after>"use strict";

/**
 * Copyright 2017 XcooBee LLC

 * 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.
 */
const runTest = (argv, callback) => {
    const path = require("path");
    const fs = require("fs");

    let parametersFilePath = path.resolve("./parameters.json");
    let outputPath = path.resolve(".");
    let ttl = 30000;
    // How long have we been running?
    let ellapsed = 0;

    // The amount of time reserved for clean up tasks
    const timeToCleanUp = 5000;

    // Track the number of open write streams
    const streamArray = [];

    let callbackCalled = false;

    const closeStreams = () => {
        streamArray.forEach((value) => {
            value.close();
        });
    };

    let globalSequence = 1;
    const getNextId = () => {
        const current = globalSequence;
        globalSequence += 1;
        return current;
    };

    const createServices = (inputFilePath) => {
        // TODO: Validation for fileName, what should happen if the user requests a writeStream for an
        // already created fileName
        // Create the services object
        const services = {
            // Just log a message to the system console
            log: (message, type) => {
                const chunk = `${Date.now()},${type},${message}\n`;
                console.log(chunk);
            },
            // email service to mock the sending of an email
            mail: () => {
                // TODO: What do in here? Log something? Do Nothing?
            },
            getNextId,
            addParam: (key, value) => {
                console.log(`${key} => ${value} added to the next bee`);
            },
            timeToRun: () => ttl - ellapsed,
            // The default streams for reading and writing
            readStream: fs.createReadStream(inputFilePath),
            // TODO: Should overwrite the files
            writeStreamManager: () => ({
                getWriteStream: (fileName, type) => {
                    const typePath = type === "wip" ? "workFiles" : "output";
                    const stream = fs.createWriteStream(`${outputPath}${path.sep}${typePath}${path.sep}${fileName}`);
                    streamArray.push(stream);
                    return stream;
                },
                getReadStream: (fileName, type) => {
                    const typePath = type === "wip" ? "workFiles" : "output";
                    const stream = fs.createReadStream(`${outputPath}${path.sep}${typePath}${path.sep}${fileName}`);
                    return stream;
                },
            }),
        };

        return services;
    };

    // Assume we are on the node project directory
    // unless otherwise specified by the --bee switch
    let beeModule = null;
    try {
        const beeIndex = argv.indexOf("--bee");
        if (beeIndex !== -1) {
            const pathToBee = path.resolve(argv[beeIndex + 1]);
            beeModule = require(pathToBee);
        } else {
            // TODO: Don't rely on cwd
            beeModule = require(process.cwd());
        }
    } catch (err) {
        callback(new Error("It was not possible to load the bee, make sure you are inside a valid node project or use the '--bee' switch"));
    }

    // Set the size instance in which this bee will be run
    // We use the size to, among other things, choose the proper ttl
    const sizeIndex = argv.indexOf("--size");
    if (sizeIndex !== -1) {
        const validSizes = ["s", "m", "l"];
        const size = argv[sizeIndex + 1].toLowerCase();

        if (validSizes.indexOf(size) === -1) {
            callback(new Error(`'${size}' is not a valid size, must be one of [s, m, l]`));
        }

        if (size === "s") {
            ttl = 30000;
        } else if (size === "m") {
            ttl = 150000;
        } else {
            ttl = 300000;
        }
    }

    // Substract the timeToCleanUp from ttl to get the net time the bee got available
    ttl -= timeToCleanUp;

    // If no params file are provided we assume the bee won't require integrations
    // nor parameters, unless the '--params' flag is used in which case it is, probably,
    // an user error pointing to an unexistent file
    const paramsIndex = argv.indexOf("--params");
    if (paramsIndex !== -1) {
        parametersFilePath = path.resolve(argv[paramsIndex + 1]);

        if (!fs.existsSync(parametersFilePath)) {
            callback(Error(`${parametersFilePath} doesn't exist`));
        }
    }

    // If the user specifies the output as a directory, use a default file name 'output' with no extension
    // The output directory must exists, the utility WON'T create it
    const outputIndex = argv.indexOf("--out");
    if (outputIndex !== -1) {
        outputPath = path.resolve(argv[outputIndex + 1]);

        // TODO: A way to create the hierarchy
        if (!fs.existsSync(outputPath)) {
            callback(new Error(`${outputPath} is not a valid directory`));
        }

        const stats = fs.lstatSync(outputPath);

        if (!stats.isDirectory()) {
            callback(new Error(`${outputPath} is not a valid directory`));
        }
    }

    if (!fs.existsSync(`${outputPath}${path.sep}output`)) {
        fs.mkdirSync(`${outputPath}${path.sep}output`);
    }

    if (!fs.existsSync(`${outputPath}${path.sep}workFiles`)) {
        fs.mkdirSync(`${outputPath}${path.sep}workFiles`);
    }

    // The input file must be the first argument
    const inputFilePath = path.resolve(argv[2]);

    if (!fs.existsSync(inputFilePath)) {
        callback(new Error(`Input file '${inputFilePath}' doesn't exist`));
    }

    const services = createServices(inputFilePath);

    const data = {
        // Mock data just for testing purposes
        user_data: {
            first_name: "John",
            last_name: "Testerson",
            xcoobee_id: "~johnt",
        },
    };

    let parametersContent = null;

    if (fs.existsSync(parametersFilePath)) {
        try {
            parametersContent = JSON.parse(fs.readFileSync(parametersFilePath, "utf8"));
            data.integrations = parametersContent.integrations;
            data.parameters = parametersContent.bee_params;
        } catch (err) {
            callback(new Error(`${parametersFilePath} is not a valid JSON file`));
        }
    }

    const beeCallback = (err, result) => {
        callbackCalled = true;
        clearInterval();
        console.log(`Total exec time: ${ellapsed} millis`);
        closeStreams();
        if (err) {
            return callback(err);
        }

        return callback(null, result);
    };

    setTimeout(() => {
        if (!callbackCalled) {
            clearInterval();
            closeStreams();
            callback(new Error("Timed-out"));
        }
    }, ttl);

    setInterval(() => {
        ellapsed += 2;
    }, 2);

    beeModule.flight(services, data, beeCallback);
};

if (require.main === module) {
    const callback = (err, result) => {
        if (err) {
            console.log(err.message);
            return process.exit(1);
        }
        console.log(result);
        return process.exit(0);
    };
    runTest(process.argv, callback);
}

module.exports.runTest = (argv, callback) => {
    runTest(argv, callback);
};
<|endoftext|>


<commit_before>Template.postSubmit.events({
  'submit form': function(e) {
    e.preventDefault();

    var post = {
      url: $(e.target).find('[name=url]').val(),
      title: $(e.target).find('[name=title]').val(),
      message: $(e.target).find('[name=message]').val()
    }

    Meteor.call('post', post, function(error, id) {
      if (error)
        return alert(error.reason);

      Router.go('postPage', {_id: id});
    });
  }
});<commit_msg>Demonstrate the order that posts appear using a sleep<commit_after>Template.postSubmit.events({
  'submit form': function(e) {
    e.preventDefault();

    var post = {
      url: $(e.target).find('[name=url]').val(),
      title: $(e.target).find('[name=title]').val(),
      message: $(e.target).find('[name=message]').val()
    }

    Meteor.call('post', post, function(error, id) {
      if (error)
        return alert(error.reason);
    });
      Router.go('postsList');
  }
});<|endoftext|>


<commit_before>var cIndex = 0; //color index

Template.comment.helpers({
	showingReplies: function () {
		return SessionAmplify.get("showingReplies").indexOf(this._id) > -1;
	},
	liked: function () {
		if (Meteor.user() && Meteor.user().activity && Meteor.user().activity.liked)
			return Meteor.user().activity.liked.indexOf(this._id) > -1;
	}
});

Template.newComment.events({
	"click .js-post-comment": function (event, template) {
		if(!Session.get("currentTopic")) return;

		var siblings = $(event.target).siblings();
		var input = $(siblings[0]);
		var content = input.val();
		var	side = $(siblings[1]).hasClass("btn-pro") ? "pro" : "con";
		var	replyTo = this.id;
		var	replyToUser = replyTo && Comments.findOne(replyTo).userId;

		Meteor.call("newComment", Meteor.userId(), Session.get("currentTopic"), content, side, replyTo, replyToUser, function(error, result) {
			if(error)
				alert(formatError(error));
			else
				scrollToId(result);
		});

		input.val("");
	},
	"click .js-post-side": function(event, template) {
		var t = $(event.target);
		t.toggleClass("btn-pro");
		t.toggleClass("btn-con");
	}
});

// Template.commentRow.destroyed = function () {
// 	console.log('destroyed');
// }

/**
 * Takes an arbitrary div and recursively removes
 * all reply boxes of equal or deeper nesting, and
 * updates the session array appropriately
 *
 * commentRow [jQuery obj]
 */
function closeReplies (commentRow) {
	if (!commentRow) return;

	// get all siblings that are reply boxes
	var siblings = commentRow.siblings(".comment-container");
	// id of the top level reply being closed
	var closingReply;

	// walk through each sibling (should only be one; opening multiple
	// replies of same level isn't possible since all siblings
	// are removed) and store the comment id. then traverse children
	// of each sibling recursively. subsequently remove the stored ids
	// from session, and finally remove siblings from dom
	if (siblings.length) {
		var ids = []; // the ids of replies being closed
		var siblingId; // temporary var to simplify substringing

		siblings.each(function () {
			siblingId = $(this).attr("id");
			siblingId = siblingId.substring(0, siblingId.indexOf("-"));
			ids.push(siblingId);

			if (siblings.length === 1)
				closingReply = siblingId;

			if ($(this).children(".comment-container").length)
				closeReplies($(this).children().first());
		});

		var showingReplies = SessionAmplify.get("showingReplies");
		showingReplies = _.difference(showingReplies, ids);
		SessionAmplify.set("showingReplies", showingReplies);
		siblings.remove();
	}

	return closingReply;
}

Template.comment.events({
	"click .comment-content": function (event, template) {
		$(event.target).toggleClass("collapsed");
	},
	// "click .comment-replyto": function (event, template) {
	// 	event.preventDefault();
	// 	if(this.replyTo)
	// 		scrollToId(this.replyTo);
	// },
	"click .js-toggle-replies": function (event, template) {
		var self = this; //store the reference because context changes when rendering template

		// remove replies on equal or deeper level than commentRow
		var commentRow = $(event.target).closest(".comment-row");
		var closingReply = closeReplies(commentRow);

		if (closingReply && closingReply === self._id) return;

		var arr = SessionAmplify.get("showingReplies");
		arr.push(self._id.toString());
		SessionAmplify.set("showingReplies", arr);

		//update the color index
		cIndex = (cIndex >= 4) ? 0 : cIndex + 1;

		// add the replies
		scrollToId(self._id);
		var replyTo = $("#" + self._id).closest(".comment-row");
		Blaze.renderWithData(Template.replies, //template to render
												{id: self._id, side: self.side, color: cIndex}, //data context
												replyTo.parent().get(0), // insert within
												replyTo.next().get(0)); // insert before

	},
	"click .js-like-comment": function (event, template) {
		Meteor.call("likeComment", Meteor.userId(), this._id, this.userId);
	},
	"click .js-unlike-comment": function (event, template) {
		Meteor.call("unlikeComment", Meteor.userId(), this._id, this.userId);
	}
});

<commit_msg>Color reply boxes based on level of nesting instead of looping through the indexes<commit_after>// number of colors for each side. so: pro0, pro1, pro2, pro3
var numColors = 4;

Template.comment.helpers({
	showingReplies: function () {
		return SessionAmplify.get("showingReplies").indexOf(this._id) > -1;
	},
	liked: function () {
		if (Meteor.user() && Meteor.user().activity && Meteor.user().activity.liked)
			return Meteor.user().activity.liked.indexOf(this._id) > -1;
	}
});

Template.newComment.events({
	"click .js-post-comment": function (event, template) {
		if(!Session.get("currentTopic")) return;

		var siblings = $(event.target).siblings();
		var input = $(siblings[0]);
		var content = input.val();
		var	side = $(siblings[1]).hasClass("btn-pro") ? "pro" : "con";
		var	replyTo = this.id;
		var	replyToUser = replyTo && Comments.findOne(replyTo).userId;

		Meteor.call("newComment", Meteor.userId(), Session.get("currentTopic"), content, side, replyTo, replyToUser, function(error, result) {
			if(error)
				alert(formatError(error));
			else
				scrollToId(result);
		});

		input.val("");
	},
	"click .js-post-side": function(event, template) {
		var t = $(event.target);
		t.toggleClass("btn-pro");
		t.toggleClass("btn-con");
	}
});

// Template.commentRow.destroyed = function () {
// 	console.log('destroyed');
// }

/**
 * Takes an arbitrary div and recursively removes
 * all reply boxes of equal or deeper nesting, and
 * updates the session array appropriately
 *
 * commentRow [jQuery obj]
 */
function closeReplies (commentRow) {
	if (!commentRow) return;

	// get all siblings that are reply boxes
	var siblings = commentRow.siblings(".comment-container");
	// id of the top level reply being closed
	var closingReply;

	// walk through each sibling (should only be one; opening multiple
	// replies of same level isn't possible since all siblings
	// are removed) and store the comment id. then traverse children
	// of each sibling recursively. subsequently remove the stored ids
	// from session, and finally remove siblings from dom
	if (siblings.length) {
		var ids = []; // the ids of replies being closed
		var siblingId; // temporary var to simplify substringing

		siblings.each(function () {
			siblingId = $(this).attr("id");
			siblingId = siblingId.substring(0, siblingId.indexOf("-"));
			ids.push(siblingId);

			if (siblings.length === 1)
				closingReply = siblingId;

			if ($(this).children(".comment-container").length)
				closeReplies($(this).children().first());
		});

		var showingReplies = SessionAmplify.get("showingReplies");
		showingReplies = _.difference(showingReplies, ids);
		SessionAmplify.set("showingReplies", showingReplies);
		siblings.remove();
	}

	return closingReply;
}

Template.comment.events({
	"click .comment-content": function (event, template) {
		$(event.target).toggleClass("collapsed");
	},
	// "click .comment-replyto": function (event, template) {
	// 	event.preventDefault();
	// 	if(this.replyTo)
	// 		scrollToId(this.replyTo);
	// },
	"click .js-toggle-replies": function (event, template) {
		var self = this; //store the reference because context changes when rendering template

		// remove replies on equal or deeper level than commentRow
		var commentRow = $(event.target).closest(".comment-row");
		var closingReply = closeReplies(commentRow);

		if (closingReply && closingReply === self._id) return;

		var arr = SessionAmplify.get("showingReplies");
		arr.push(self._id.toString());
		SessionAmplify.set("showingReplies", arr);

		//update the color index
		var color = (arr.length - 1) % numColors;

		// add the replies
		scrollToId(self._id);
		var replyTo = $("#" + self._id).closest(".comment-row");
		Blaze.renderWithData(Template.replies, //template to render
												{id: self._id, side: self.side, color: color}, //data context
												replyTo.parent().get(0), // insert within
												replyTo.next().get(0)); // insert before

	},
	"click .js-like-comment": function (event, template) {
		Meteor.call("likeComment", Meteor.userId(), this._id, this.userId);
	},
	"click .js-unlike-comment": function (event, template) {
		Meteor.call("unlikeComment", Meteor.userId(), this._id, this.userId);
	}
});

<|endoftext|>


<commit_before>// Copyright 2009 The Closure Library 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 provides a reusable youtube UI component given a youtube data
 * model.
 *
 * goog.ui.media.Youtube is actually a {@link goog.ui.ControlRenderer}, a
 * stateless class - that could/should be used as a Singleton with the static
 * method {@code goog.ui.media.Youtube.getInstance} -, that knows how to render
 * youtube videos. It is designed to be used with a {@link goog.ui.Control},
 * which will actually control the media renderer and provide the
 * {@link goog.ui.Component} base. This design guarantees that all different
 * types of medias will behave alike but will look different.
 *
 * goog.ui.media.Youtube expects {@code goog.ui.media.YoutubeModel} on
 * {@code goog.ui.Control.getModel} as data models, and render a flash object
 * that will play that URL.
 *
 * Example of usage:
 *
 *

 *   var video = goog.ui.media.YoutubeModel.newInstance(
 *       'http://www.youtube.com/watch?v=ddl5f44spwQ');
 *   goog.ui.media.Youtube.newControl(video).render();
 *

 *
 * youtube medias currently support the following states:
 *
 *

 *
 {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
 *
 {@link goog.ui.Component.State.HOVER}: mouse cursor is over the video
 *
 {@link !goog.ui.Component.State.SELECTED}: a static thumbnail is shown
 *
 {@link goog.ui.Component.State.SELECTED}: video is playing
 *

 *
 * Which can be accessed by
 *

 *   youtube.setEnabled(true);
 *   youtube.setHighlighted(true);
 *   youtube.setSelected(true);
 *

 *
 * This package also provides a few static auxiliary methods, such as:
 *
 *

 * var videoId = goog.ui.media.Youtube.parseUrl(
 *     'http://www.youtube.com/watch?v=ddl5f44spwQ');
 *

 *
 *
 * @supported IE6, FF2+, Safari. Requires flash to actually work.
 *
 * TODO(user): test on other browsers
 */

goog.provide('goog.ui.media.Youtube');
goog.provide('goog.ui.media.YoutubeModel');

goog.require('goog.string');
goog.require('goog.ui.Component.Error');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.media.FlashObject');
goog.require('goog.ui.media.Media');
goog.require('goog.ui.media.MediaModel');
goog.require('goog.ui.media.MediaModel.Player');
goog.require('goog.ui.media.MediaModel.Thumbnail');
goog.require('goog.ui.media.MediaRenderer');

/**
 * Subclasses a goog.ui.media.MediaRenderer to provide a Youtube specific media
 * renderer.
 *
 * This class knows how to parse youtube urls, and render the DOM structure
 * of youtube video players and previews. This class is meant to be used as a
 * singleton static stateless class, that takes {@code goog.ui.media.Media}
 * instances and renders it. It expects {@code goog.ui.media.Media.getModel} to
 * return a well formed, previously constructed, youtube video id, which is the
 * data model this renderer will use to construct the DOM structure.
 * {@see goog.ui.media.Youtube.newControl} for a example of constructing a
 * control with this renderer.
 *
 * goog.ui.media.Youtube currently supports all {@link goog.ui.Component.State}.
 * It will change its DOM structure between SELECTED and !SELECTED, and rely on
 * CSS definitions on the others. On !SELECTED, the renderer will render a
 * youtube static , with a thumbnail of the video. On SELECTED, the
 * renderer will append to the DOM a flash object, that contains the youtube
 * video.
 *
 * This design is patterned after http://go/closure_control_subclassing
 *
 * It uses {@link goog.ui.media.FlashObject} to embed the flash object.
 *
 * @constructor
 * @extends {goog.ui.media.MediaRenderer}
 */
goog.ui.media.Youtube = function() {
  goog.ui.media.MediaRenderer.call(this);
};
goog.inherits(goog.ui.media.Youtube, goog.ui.media.MediaRenderer);
goog.addSingletonGetter(goog.ui.media.Youtube);

/**
 * A static convenient method to construct a goog.ui.media.Media control out of
 * a youtube model. It sets it as the data model goog.ui.media.Youtube renderer
 * uses, sets the states supported by the renderer, and returns a Control that
 * binds everything together. This is what you should be using for constructing
 * Youtube videos, except if you need finer control over the configuration.
 *
 * @param {goog.ui.media.YoutubeModel} youtubeModel The youtube data model.
 * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
 *     document interaction.
 * @return {goog.ui.media.Media} A Control binded to the youtube renderer.
 */
goog.ui.media.Youtube.newControl = function(youtubeModel, opt_domHelper) {
  var control = new goog.ui.media.Media(
      youtubeModel,
      goog.ui.media.Youtube.getInstance(),
      opt_domHelper);
  control.setStateInternal(goog.ui.Component.State.ACTIVE);
  return control;
};

/**
 * Default CSS class to be applied to the root element of components rendered
 * by this renderer.
 * @type {string}
 */
goog.ui.media.Youtube.CSS_CLASS = goog.getCssName('goog-ui-media-youtube');

/**
 * Changes the state of a {@code control}. Currently only changes the DOM
 * structure when the youtube movie is SELECTED (by default fired by a MOUSEUP
 * on the thumbnail), which means we have to embed the youtube flash video and
 * play it.
 *
 * @param {goog.ui.media.Media} control The media control.
 * @param {goog.ui.Component.State} state The state to be set or cleared.
 * @param {boolean} enable Whether the state is enabled or disabled.
 */
goog.ui.media.Youtube.prototype.setState = function(control, state, enable) {
  goog.ui.media.Youtube.superClass_.setState.call(this, control, state, enable);

  // control.createDom has to be called before any state is set.
  // Use control.setStateInternal if you need to set states
  if (!control.getElement()) {
    throw Error(goog.ui.Component.Error.STATE_INVALID);
  }

  var domHelper = control.getDomHelper();
  var dataModel =
      /** @type {goog.ui.media.YoutubeModel} */ (control.getDataModel());

  if (!!(state & goog.ui.Component.State.SELECTED) && enable) {
    var flashEls = domHelper.getElementsByTagNameAndClass(
        'div',
        goog.ui.media.FlashObject.CSS_CLASS,
        control.getElement());
    if (flashEls.length > 0) {
      return;
    }
    var youtubeFlash = new goog.ui.media.FlashObject(
        dataModel.getPlayer().getUrl() || '',
        domHelper);
    control.addChild(youtubeFlash, true);
  }
};

/**
 * Returns the CSS class to be applied to the root element of components
 * rendered using this renderer.
 *
 * @return {string} Renderer-specific CSS class.
 */
goog.ui.media.Youtube.prototype.getCssClass = function() {
  return goog.ui.media.Youtube.CSS_CLASS;
};

/**
 * The {@code goog.ui.media.Youtube} media data model. It stores a required
 * {@code videoId} field, sets the youtube URL, and allows a few optional
 * parameters.
 *
 * @param {string} videoId The youtube video id.
 * @param {string=} opt_caption An optional caption of the youtube video.
 * @param {string=} opt_description An optional description of the youtube
 *     video.
 * @constructor
 * @extends {goog.ui.media.MediaModel}
 */
goog.ui.media.YoutubeModel = function(videoId, opt_caption, opt_description) {
  goog.ui.media.MediaModel.call(
      this,
      goog.ui.media.YoutubeModel.buildUrl(videoId),
      opt_caption,
      opt_description,
      goog.ui.media.MediaModel.MimeType.FLASH);

  /**
   * The Youtube video id.
   * @type {string}
   * @private
   */
  this.videoId_ = videoId;

  this.setThumbnails([new goog.ui.media.MediaModel.Thumbnail(
      goog.ui.media.YoutubeModel.getThumbnailUrl(videoId))]);

  this.setPlayer(new goog.ui.media.MediaModel.Player(
      this.getFlashUrl(videoId, true)));
};
goog.inherits(goog.ui.media.YoutubeModel, goog.ui.media.MediaModel);

/**
 * A youtube regular expression matcher. It matches the VIDEOID of URLs like
 * http://www.youtube.com/watch?v=VIDEOID. Based on:
 * googledata/contentonebox/opencob/specs/common/YTPublicExtractorCard.xml
 * @type {RegExp}
 * @private
 * @const
 */
goog.ui.media.YoutubeModel.MATCHER_ = new RegExp(
    // Lead in.
    'http://(?:[a-zA_Z]{2,3}.)?' +
    // Watch URL prefix.  This should handle new URLs of the form:
    // http://www.youtube.com/watch#!v=jqxENMKaeCU&feature=related
    // where the parameters appear after "#!" instead of "?".
    '(?:youtube\.com/watch)' +
    // Get the video id:
    // The video ID is a parameter v=[videoid] either right after the "?"
    // or after some other parameters.
    '(?:\\?(?:[\\w\-\=]+&(?:amp;)?)*v=([\\w\-]+)' +
    '(?:&(?:amp;)?[\\w\-\=]+)*)?' +
    // Get any extra arguments in the URL's hash part.
    '(?:#[!]?(?:' +
    // Video ID from the v=[videoid] parameter, optionally surrounded by other
    // & separated parameters.
    '(?:(?:[\\w\-\=]+&(?:amp;)?)*(?:v=([\\w\-]+))' +
    '(?:&(?:amp;)?[\\w\-\=]+)*)' +
    '|' +
    // Continue supporting "?" for the video ID
    // and "#" for other hash parameters.
    '(?:[\\w\-\=&]+)' +
    '))?' +
    // Should terminate with a word break or a /.
    '(?:/|\\b)', 'i');

/**
 * A auxiliary static method that parses a youtube URL, extracting the ID of the
 * video, and builds a YoutubeModel.
 *
 * @param {string} youtubeUrl A youtube URL.
 * @param {string=} opt_caption An optional caption of the youtube video.
 * @param {string=} opt_description An optional description of the youtube
 *     video.
 * @return {goog.ui.media.YoutubeModel} The data model that represents the
 *     youtube URL.
 * @see goog.ui.media.YoutubeModel.getVideoId()
 * @throws Error in case the parsing fails.
 */
goog.ui.media.YoutubeModel.newInstance = function(youtubeUrl,
                                                  opt_caption,
                                                  opt_description) {
  var extract = goog.ui.media.YoutubeModel.MATCHER_.exec(youtubeUrl);
  if (extract) {
    var videoId = extract[1] || extract[2];
    return new goog.ui.media.YoutubeModel(
        videoId, opt_caption, opt_description);
  }

  throw Error('failed to parse video id from youtube url: ' + youtubeUrl);
};

/**
 * The opposite of {@code goog.ui.media.Youtube.newInstance}: it takes a videoId
 * and returns a youtube URL.
 *
 * @param {string} videoId The youtube video ID.
 * @return {string} The youtube URL.
 */
goog.ui.media.YoutubeModel.buildUrl = function(videoId) {
  return 'http://www.youtube.com/watch?v=' + goog.string.urlEncode(videoId);
};

/**
 * A static auxiliary method that builds a static image URL with a preview of
 * the youtube video.
 *
 * NOTE(user): patterned after Gmail's gadgets/youtube,
 *
 * TODO(user): how do I specify the width/height of the resulting image on the
 * url ? is there an official API for http://ytimg.com ?
 *
 * @param {string} youtubeId The youtube video ID.
 * @return {string} An URL that contains an image with a preview of the youtube
 *     movie.
 */
goog.ui.media.YoutubeModel.getThumbnailUrl = function(youtubeId) {
  return 'http://i.ytimg.com/vi/' + youtubeId + '/default.jpg';
};

/**
 * An auxiliary method that builds URL of the flash movie to be embedded,
 * out of the youtube video id.
 *
 * @param {string} videoId The youtube video ID.
 * @param {boolean=} opt_autoplay Whether the flash movie should start playing
 *     as soon as it is shown, or if it should show a 'play' button.
 * @return {string} The flash URL to be embedded on the page.
 */
goog.ui.media.YoutubeModel.prototype.getFlashUrl = function(videoId,
                                                            opt_autoplay) {
  var autoplay = opt_autoplay ? '&autoplay=1' : '';
  // YouTube video ids are extracted from youtube URLs, which are user
  // generated input. the video id is later used to embed a flash object,
  // which is generated through HTML construction. We goog.string.urlEncode
  // the video id to make sure the URL is safe to be embedded.
  return 'http://www.youtube.com/v/' + goog.string.urlEncode(videoId) +
      '&hl=en&fs=1' + autoplay;
};

/**
 * Gets the Youtube video id.
 * @return {string} The Youtube video id.
 */
goog.ui.media.YoutubeModel.prototype.getVideoId = function() {
  return this.videoId_;
};
<commit_msg><commit_after>// Copyright 2009 The Closure Library 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 provides a reusable youtube UI component given a youtube data
 * model.
 *
 * goog.ui.media.Youtube is actually a {@link goog.ui.ControlRenderer}, a
 * stateless class - that could/should be used as a Singleton with the static
 * method {@code goog.ui.media.Youtube.getInstance} -, that knows how to render
 * youtube videos. It is designed to be used with a {@link goog.ui.Control},
 * which will actually control the media renderer and provide the
 * {@link goog.ui.Component} base. This design guarantees that all different
 * types of medias will behave alike but will look different.
 *
 * goog.ui.media.Youtube expects {@code goog.ui.media.YoutubeModel} on
 * {@code goog.ui.Control.getModel} as data models, and render a flash object
 * that will play that URL.
 *
 * Example of usage:
 *
 *

 *   var video = goog.ui.media.YoutubeModel.newInstance(
 *       'http://www.youtube.com/watch?v=ddl5f44spwQ');
 *   goog.ui.media.Youtube.newControl(video).render();
 *

 *
 * youtube medias currently support the following states:
 *
 *

 *
 {@link goog.ui.Component.State.DISABLED}: shows 'flash not available'
 *
 {@link goog.ui.Component.State.HOVER}: mouse cursor is over the video
 *
 {@link !goog.ui.Component.State.SELECTED}: a static thumbnail is shown
 *
 {@link goog.ui.Component.State.SELECTED}: video is playing
 *

 *
 * Which can be accessed by
 *

 *   youtube.setEnabled(true);
 *   youtube.setHighlighted(true);
 *   youtube.setSelected(true);
 *

 *
 * This package also provides a few static auxiliary methods, such as:
 *
 *

 * var videoId = goog.ui.media.Youtube.parseUrl(
 *     'http://www.youtube.com/watch?v=ddl5f44spwQ');
 *

 *
 *
 * @supported IE6, FF2+, Safari. Requires flash to actually work.
 *
 * TODO(user): test on other browsers
 */

goog.provide('goog.ui.media.Youtube');
goog.provide('goog.ui.media.YoutubeModel');

goog.require('goog.string');
goog.require('goog.ui.Component.Error');
goog.require('goog.ui.Component.State');
goog.require('goog.ui.media.FlashObject');
goog.require('goog.ui.media.Media');
goog.require('goog.ui.media.MediaModel');
goog.require('goog.ui.media.MediaModel.Player');
goog.require('goog.ui.media.MediaModel.Thumbnail');
goog.require('goog.ui.media.MediaRenderer');

/**
 * Subclasses a goog.ui.media.MediaRenderer to provide a Youtube specific media
 * renderer.
 *
 * This class knows how to parse youtube urls, and render the DOM structure
 * of youtube video players and previews. This class is meant to be used as a
 * singleton static stateless class, that takes {@code goog.ui.media.Media}
 * instances and renders it. It expects {@code goog.ui.media.Media.getModel} to
 * return a well formed, previously constructed, youtube video id, which is the
 * data model this renderer will use to construct the DOM structure.
 * {@see goog.ui.media.Youtube.newControl} for a example of constructing a
 * control with this renderer.
 *
 * goog.ui.media.Youtube currently supports all {@link goog.ui.Component.State}.
 * It will change its DOM structure between SELECTED and !SELECTED, and rely on
 * CSS definitions on the others. On !SELECTED, the renderer will render a
 * youtube static , with a thumbnail of the video. On SELECTED, the
 * renderer will append to the DOM a flash object, that contains the youtube
 * video.
 *
 * This design is patterned after http://go/closure_control_subclassing
 *
 * It uses {@link goog.ui.media.FlashObject} to embed the flash object.
 *
 * @constructor
 * @extends {goog.ui.media.MediaRenderer}
 */
goog.ui.media.Youtube = function() {
  goog.ui.media.MediaRenderer.call(this);
};
goog.inherits(goog.ui.media.Youtube, goog.ui.media.MediaRenderer);
goog.addSingletonGetter(goog.ui.media.Youtube);

/**
 * A static convenient method to construct a goog.ui.media.Media control out of
 * a youtube model. It sets it as the data model goog.ui.media.Youtube renderer
 * uses, sets the states supported by the renderer, and returns a Control that
 * binds everything together. This is what you should be using for constructing
 * Youtube videos, except if you need finer control over the configuration.
 *
 * @param {goog.ui.media.YoutubeModel} youtubeModel The youtube data model.
 * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper, used for
 *     document interaction.
 * @return {goog.ui.media.Media} A Control binded to the youtube renderer.
 */
goog.ui.media.Youtube.newControl = function(youtubeModel, opt_domHelper) {
  var control = new goog.ui.media.Media(
      youtubeModel,
      goog.ui.media.Youtube.getInstance(),
      opt_domHelper);
  control.setStateInternal(goog.ui.Component.State.ACTIVE);
  return control;
};

/**
 * Default CSS class to be applied to the root element of components rendered
 * by this renderer.
 * @type {string}
 */
goog.ui.media.Youtube.CSS_CLASS = goog.getCssName('goog-ui-media-youtube');

/**
 * Changes the state of a {@code control}. Currently only changes the DOM
 * structure when the youtube movie is SELECTED (by default fired by a MOUSEUP
 * on the thumbnail), which means we have to embed the youtube flash video and
 * play it.
 *
 * @param {goog.ui.media.Media} control The media control.
 * @param {goog.ui.Component.State} state The state to be set or cleared.
 * @param {boolean} enable Whether the state is enabled or disabled.
 */
goog.ui.media.Youtube.prototype.setState = function(control, state, enable) {
  goog.ui.media.Youtube.superClass_.setState.call(this, control, state, enable);

  // control.createDom has to be called before any state is set.
  // Use control.setStateInternal if you need to set states
  if (!control.getElement()) {
    throw Error(goog.ui.Component.Error.STATE_INVALID);
  }

  var domHelper = control.getDomHelper();
  var dataModel =
      /** @type {goog.ui.media.YoutubeModel} */ (control.getDataModel());

  if (!!(state & goog.ui.Component.State.SELECTED) && enable) {
    var flashEls = domHelper.getElementsByTagNameAndClass(
        'div',
        goog.ui.media.FlashObject.CSS_CLASS,
        control.getElement());
    if (flashEls.length > 0) {
      return;
    }
    var youtubeFlash = new goog.ui.media.FlashObject(
        dataModel.getPlayer().getUrl() || '',
        domHelper);
    control.addChild(youtubeFlash, true);
  }
};

/**
 * Returns the CSS class to be applied to the root element of components
 * rendered using this renderer.
 *
 * @return {string} Renderer-specific CSS class.
 */
goog.ui.media.Youtube.prototype.getCssClass = function() {
  return goog.ui.media.Youtube.CSS_CLASS;
};

/**
 * The {@code goog.ui.media.Youtube} media data model. It stores a required
 * {@code videoId} field, sets the youtube URL, and allows a few optional
 * parameters.
 *
 * @param {string} videoId The youtube video id.
 * @param {string=} opt_caption An optional caption of the youtube video.
 * @param {string=} opt_description An optional description of the youtube
 *     video.
 * @constructor
 * @extends {goog.ui.media.MediaModel}
 */
goog.ui.media.YoutubeModel = function(videoId, opt_caption, opt_description) {
  goog.ui.media.MediaModel.call(
      this,
      goog.ui.media.YoutubeModel.buildUrl(videoId),
      opt_caption,
      opt_description,
      goog.ui.media.MediaModel.MimeType.FLASH);

  /**
   * The Youtube video id.
   * @type {string}
   * @private
   */
  this.videoId_ = videoId;

  this.setThumbnails([new goog.ui.media.MediaModel.Thumbnail(
      goog.ui.media.YoutubeModel.getThumbnailUrl(videoId))]);

  this.setPlayer(new goog.ui.media.MediaModel.Player(
      this.getFlashUrl(videoId, true)));
};
goog.inherits(goog.ui.media.YoutubeModel, goog.ui.media.MediaModel);

/**
 * A youtube regular expression matcher. It matches the VIDEOID of URLs like
 * http://www.youtube.com/watch?v=VIDEOID. Based on:
 * googledata/contentonebox/opencob/specs/common/YTPublicExtractorCard.xml
 * @type {RegExp}
 * @private
 * @const
 */
// Be careful about the placement of the dashes in the character classes. Eg,
// use "[\\w=-]" instead of "[\\w-=]" if you mean to include the dash as a
// character and not create a character range like "[a-f]".
goog.ui.media.YoutubeModel.MATCHER_ = new RegExp(
    // Lead in.
    'http://(?:[a-zA-Z]{2,3}.)?' +
    // Watch URL prefix.  This should handle new URLs of the form:
    // http://www.youtube.com/watch#!v=jqxENMKaeCU&feature=related
    // where the parameters appear after "#!" instead of "?".
    '(?:youtube\.com/watch)' +
    // Get the video id:
    // The video ID is a parameter v=[videoid] either right after the "?"
    // or after some other parameters.
    '(?:\\?(?:[\\w=-]+&(?:amp;)?)*v=([\\w-]+)' +
    '(?:&(?:amp;)?[\\w=-]+)*)?' +
    // Get any extra arguments in the URL's hash part.
    '(?:#[!]?(?:' +
    // Video ID from the v=[videoid] parameter, optionally surrounded by other
    // & separated parameters.
    '(?:(?:[\\w=-]+&(?:amp;)?)*(?:v=([\\w-]+))' +
    '(?:&(?:amp;)?[\\w=-]+)*)' +
    '|' +
    // Continue supporting "?" for the video ID
    // and "#" for other hash parameters.
    '(?:[\\w=&-]+)' +
    '))?' +
    // Should terminate with a word break or a /.
    '(?:/|\\b)', 'i');

/**
 * A auxiliary static method that parses a youtube URL, extracting the ID of the
 * video, and builds a YoutubeModel.
 *
 * @param {string} youtubeUrl A youtube URL.
 * @param {string=} opt_caption An optional caption of the youtube video.
 * @param {string=} opt_description An optional description of the youtube
 *     video.
 * @return {goog.ui.media.YoutubeModel} The data model that represents the
 *     youtube URL.
 * @see goog.ui.media.YoutubeModel.getVideoId()
 * @throws Error in case the parsing fails.
 */
goog.ui.media.YoutubeModel.newInstance = function(youtubeUrl,
                                                  opt_caption,
                                                  opt_description) {
  var extract = goog.ui.media.YoutubeModel.MATCHER_.exec(youtubeUrl);
  if (extract) {
    var videoId = extract[1] || extract[2];
    return new goog.ui.media.YoutubeModel(
        videoId, opt_caption, opt_description);
  }

  throw Error('failed to parse video id from youtube url: ' + youtubeUrl);
};

/**
 * The opposite of {@code goog.ui.media.Youtube.newInstance}: it takes a videoId
 * and returns a youtube URL.
 *
 * @param {string} videoId The youtube video ID.
 * @return {string} The youtube URL.
 */
goog.ui.media.YoutubeModel.buildUrl = function(videoId) {
  return 'http://www.youtube.com/watch?v=' + goog.string.urlEncode(videoId);
};

/**
 * A static auxiliary method that builds a static image URL with a preview of
 * the youtube video.
 *
 * NOTE(user): patterned after Gmail's gadgets/youtube,
 *
 * TODO(user): how do I specify the width/height of the resulting image on the
 * url ? is there an official API for http://ytimg.com ?
 *
 * @param {string} youtubeId The youtube video ID.
 * @return {string} An URL that contains an image with a preview of the youtube
 *     movie.
 */
goog.ui.media.YoutubeModel.getThumbnailUrl = function(youtubeId) {
  return 'http://i.ytimg.com/vi/' + youtubeId + '/default.jpg';
};

/**
 * An auxiliary method that builds URL of the flash movie to be embedded,
 * out of the youtube video id.
 *
 * @param {string} videoId The youtube video ID.
 * @param {boolean=} opt_autoplay Whether the flash movie should start playing
 *     as soon as it is shown, or if it should show a 'play' button.
 * @return {string} The flash URL to be embedded on the page.
 */
goog.ui.media.YoutubeModel.prototype.getFlashUrl = function(videoId,
                                                            opt_autoplay) {
  var autoplay = opt_autoplay ? '&autoplay=1' : '';
  // YouTube video ids are extracted from youtube URLs, which are user
  // generated input. the video id is later used to embed a flash object,
  // which is generated through HTML construction. We goog.string.urlEncode
  // the video id to make sure the URL is safe to be embedded.
  return 'http://www.youtube.com/v/' + goog.string.urlEncode(videoId) +
      '&hl=en&fs=1' + autoplay;
};

/**
 * Gets the Youtube video id.
 * @return {string} The Youtube video id.
 */
goog.ui.media.YoutubeModel.prototype.getVideoId = function() {
  return this.videoId_;
};
<|endoftext|>


<commit_before>import Input from './input'
import Status from './status'

const Registration = React.createClass({
  getInitialState: function () {
    let date = new Date()
    return {
      time: {
        hour: date.getHours()
        ,minute: date.getMinutes()
        ,second: date.getSeconds()
      },
      attendees: {
        listed: 0
        ,registered: 0
        ,waiting: 0
      }
    }
  },
  updateTime: function (evt) {
    let date = new Date()
    this.setState(Object.assign({}, this.state, {
      time: {
        hour: date.getHours()
        ,minute: date.getMinutes()
        ,second: date.getSeconds()
      }
    }))
  },
  componentDidMount: function () {
    this.updateTime()
  },
  render: function () {
    return (

{ this.props.title }

        <Status message="Systemet er klar til bruk!"
          time={ this.state.time } />
        <Input placeholder="Skriv inn RFID eller brukernavn..." />

          Møtt: { this.state.attendees.registered}
           - Påmeldt: { this.state.attendees.listed
            + this.state.attendees.waiting}
           - Plasser: { this.state.attendees.registered}

    )
  }
})

export default Registration
<commit_msg>Added JSDoc comments to the Registration component<commit_after>import Input from './input'
import Status from './status'

/**
 * Registration view. This is what the user see
 * as the initial outlook. The component should:
 *  - Show status of the system.
 *  - Handle input from user/RFID.
 *  - Show user stats in numbers.
 */
const Registration = React.createClass({
  getInitialState: function () {
    let date = new Date()
    return {
      time: {
        hour: date.getHours()
        ,minute: date.getMinutes()
        ,second: date.getSeconds()
      },
      attendees: {
        listed: 0
        ,registered: 0
        ,waiting: 0
      }
    }
  },

  /**
   * This is called when the status gets updated
   * and needs to save the timestamp.
   */
  updateTime: function () {
    let date = new Date()
    this.setState(Object.assign({}, this.state, {
      time: {
        hour: date.getHours()
        ,minute: date.getMinutes()
        ,second: date.getSeconds()
      }
    }))
  },
  componentDidMount: function () {
    this.updateTime()
  },
  render: function () {
    return (

{ this.props.title }

        <Status message="Systemet er klar til bruk!"
          time={ this.state.time } />
        <Input placeholder="Skriv inn RFID eller brukernavn..." />

          Møtt: { this.state.attendees.registered}
           - Påmeldt: { this.state.attendees.listed
            + this.state.attendees.waiting}
           - Plasser: { this.state.attendees.registered}

    )
  }
})

export default Registration
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { Entity } from 'draft-js';
import DraftailEditor from 'draftail';

import 'draftail/dist/draftail.css';
import './wagtaildraftail.css';

import decorators from './decorators';
import sources from './sources';
import {registerDecorator, getDecorator, registerSource, getSource, getStrategy} from './registry';

// Register Decorators, Sources and Strategies
Object.keys(decorators).forEach(function(key) {
  registerDecorator(key, decorators[key]);
});
Object.keys(sources).forEach(function(key) {
  registerSource(key, sources[key]);
});

// TODO: Use the one from draftail once implemented https://github.com/springload/draftail/issues/48
const getDefaultStrategy = (entityType) => {
  return (contentBlock, callback) => {
    contentBlock.findEntityRanges((character) => {
      const entityKey = character.getEntity();
      return (
        entityKey !== null &&
        Entity.get(entityKey).getType() === entityType
      );
    }, callback);
  };
};

const initDraftailEditor = (fieldName, options = {}) => {
  console.log('initDraftailEditor');
  const field = document.querySelector(`[name="${fieldName}"]`);
  const editorWrapper = document.createElement('div');
  field.parentNode.appendChild(editorWrapper);

  const serialiseInputValue = (rawContentState) => {
    field.value = JSON.stringify(rawContentState);
  };

  if (options.entityTypes) {
    // eslint-disable-next-line no-param-reassign
    options.entityTypes = options.entityTypes.map(entity => Object.assign(entity, {
      // TODO: Rename keys accordingly once changed in draftail https://github.com/springload/draftail/issues/49
      control: getSource(entity.source),
      strategy: getStrategy(entity.type) || getDefaultStrategy(entity.type),
      component: getDecorator(entity.decorator),
    }));
  }

  const editor = (
    <DraftailEditor
      rawContentState={JSON.parse(field.value)}
      onSave={serialiseInputValue}
      {...options}
    />
  );

  ReactDOM.render(editor, editorWrapper);
};

window.initDraftailEditor = initDraftailEditor;

export default initDraftailEditor;
<commit_msg>Expose Registry and basic React functions globally<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { Entity } from 'draft-js';
import DraftailEditor from 'draftail';

import 'draftail/dist/draftail.css';
import './wagtaildraftail.css';

import decorators from './decorators';
import sources from './sources';
import {registerDecorator, getDecorator, registerSource, getSource, registerStrategy, getStrategy} from './registry';

// Register Decorators, Sources and Strategies
Object.keys(decorators).forEach(function(key) {
  registerDecorator(key, decorators[key]);
});
Object.keys(sources).forEach(function(key) {
  registerSource(key, sources[key]);
});

// TODO: Use the one from draftail once implemented https://github.com/springload/draftail/issues/48
const getDefaultStrategy = (entityType) => {
  return (contentBlock, callback) => {
    contentBlock.findEntityRanges((character) => {
      const entityKey = character.getEntity();
      return (
        entityKey !== null &&
        Entity.get(entityKey).getType() === entityType
      );
    }, callback);
  };
};

const initDraftailEditor = (fieldName, options = {}) => {
  console.log('initDraftailEditor');
  const field = document.querySelector(`[name="${fieldName}"]`);
  const editorWrapper = document.createElement('div');
  field.parentNode.appendChild(editorWrapper);

  const serialiseInputValue = (rawContentState) => {
    field.value = JSON.stringify(rawContentState);
  };

  if (options.entityTypes) {
    // eslint-disable-next-line no-param-reassign
    options.entityTypes = options.entityTypes.map(entity => Object.assign(entity, {
      // TODO: Rename keys accordingly once changed in draftail https://github.com/springload/draftail/issues/49
      control: getSource(entity.source),
      strategy: getStrategy(entity.type) || getDefaultStrategy(entity.type),
      component: getDecorator(entity.decorator),
    }));
  }

  const editor = (
    <DraftailEditor
      rawContentState={JSON.parse(field.value)}
      onSave={serialiseInputValue}
      {...options}
    />
  );

  ReactDOM.render(editor, editorWrapper);
};

window.initDraftailEditor = initDraftailEditor;

window.wagtaildraftail = {
  // Expose registry methods
  registerDecorator: registerDecorator,
  getDecorator: getDecorator,
  registerSource: registerSource,
  getSource: getSource,
  registerStrategy: registerStrategy,
  getStrategy: getStrategy,

  // Expose basic React methods for basic needs
  createClass: React.createClass,
  createElement: React.createElement,
};

export default initDraftailEditor;
<|endoftext|>


<commit_before>var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var util = require('./util');
var autoprefixer = require('autoprefixer');

module.exports = {
	entry: {
		'polyfills': './src/e2e-app/polyfills.ts',
		'vendor': './src/e2e-app/vendor.ts',
		'app': './src/e2e-app/main.ts'
	},

	resolve: {
		extensions: ['', '.js', '.ts'],
		mainFields: ["module", "main", "browser"]
	},

	// avoid errors like Error: Can't resolve 'net' in '...angular2-mdl-ext/node_modules/debug'
	node: {
		fs: 'empty',
		net: 'empty'
	},

	module: {
		preLoaders: [
			{
				test: /.ts$/,
				loader: 'string-replace-loader',
				query: {
					search: 'moduleId: module.id,',
					replace: '',
					flags: 'g'
				}
			},
		],
		loaders: [
			{
				test: /\.ts$/,
				loaders: ['awesome-typescript-loader?tsconfig=./src/e2e-app/tsconfig.json', 'angular2-template-loader']
			},
			{
				test: /\.html$/,
				loader: 'html'
			},
			{
				test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
				loader: 'file?name=assets/[name].[hash].[ext]'
			},
			{
				test: /\.scss$/,
				exclude: [util.root('src', 'e2e-app', 'app'), util.root('src', 'components')],
				loaders: [
					ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: 'css-loader?sourceMap' }),
					'css-loader',
					'postcss-loader',
					'sass-loader']
			},
			{
				test: /\.scss$/,
				include: [util.root('src', 'e2e-app', 'app'), util.root('src', 'components')],
				loaders: ['raw-loader', 'postcss-loader', 'sass-loader']
			},
			{
				test: /\.hbs$/,
				loader: 'handlebars'
			}
		]
	},

	postcss: function () {
		return [autoprefixer];
	},

	plugins: [
		new webpack.optimize.CommonsChunkPlugin({
			name: ['app', 'vendor', 'polyfills']
		}),

		new HtmlWebpackPlugin({
			template: '!!handlebars!src/e2e-app/index.hbs',
			baseUrl: process.env.NODE_ENV == 'production' ? '/angular2-mdl-ext/' : '/',
			production: process.env.NODE_ENV == 'production' ? true : false
		})
	],

	sassLoader: {
		includePaths: [util.root('node_modules', 'angular2-mdl', 'scss')]
	}
};
<commit_msg>suppress prod build warnings<commit_after>var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var util = require('./util');
var autoprefixer = require('autoprefixer');

module.exports = {
	entry: {
		'polyfills': './src/e2e-app/polyfills.ts',
		'vendor': './src/e2e-app/vendor.ts',
		'app': './src/e2e-app/main.ts'
	},

	resolve: {
		extensions: ['', '.js', '.ts'],
		mainFields: ["module", "main", "browser"]
	},

	// avoid errors like Error: Can't resolve 'net' in '...angular2-mdl-ext/node_modules/debug'
	node: {
		fs: 'empty',
		net: 'empty'
	},

	module: {
		preLoaders: [
			{
				test: /.ts$/,
				loader: 'string-replace-loader',
				query: {
					search: 'moduleId: module.id,',
					replace: '',
					flags: 'g'
				}
			},
		],
		loaders: [
			{
				test: /\.ts$/,
				loaders: ['awesome-typescript-loader?tsconfig=./src/e2e-app/tsconfig.json', 'angular2-template-loader']
			},
			{
				test: /\.html$/,
				loader: 'html'
			},
			{
				test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
				loader: 'file?name=assets/[name].[hash].[ext]'
			},
			{
				test: /\.scss$/,
				exclude: [util.root('src', 'e2e-app', 'app'), util.root('src', 'components')],
				loaders: [
					ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: 'css-loader?sourceMap' }),
					'css-loader',
					'postcss-loader',
					'sass-loader']
			},
			{
				test: /\.scss$/,
				include: [util.root('src', 'e2e-app', 'app'), util.root('src', 'components')],
				loaders: ['raw-loader', 'postcss-loader', 'sass-loader']
			},
			{
				test: /\.hbs$/,
				loader: 'handlebars'
			}
		]
	},

	postcss: function () {
		return [autoprefixer];
	},

	plugins: [
		// should fix: https://github.com/angular/angular/issues/11580
		new webpack.ContextReplacementPlugin(
			// The (\\|\/) piece accounts for path separators in *nix and Windows
			/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
			util.root('src')
		),
		new webpack.optimize.CommonsChunkPlugin({
			name: ['app', 'vendor', 'polyfills']
		}),

		new HtmlWebpackPlugin({
			template: '!!handlebars!src/e2e-app/index.hbs',
			baseUrl: process.env.NODE_ENV == 'production' ? '/angular2-mdl-ext/' : '/',
			production: process.env.NODE_ENV == 'production' ? true : false
		})
	],

	sassLoader: {
		includePaths: [util.root('node_modules', 'angular2-mdl', 'scss')]
	}
};
<|endoftext|>


<commit_before>var mongoose = require("mongoose");
var sessionDB = mongoose.model("sessions");
var userDB = mongoose.model("User");

var sendJsonResponse = function(res, status, content) {
    res.status(status);
    res.json(content);
};

module.exports.participationsList = function(req, res){
    sessionDB.find({
        participants: {$elemMatch: {$eq: req.user._id}}
    },function(err, session){
        console.log("inside participations request "+err);
        console.log(session);

            sessionDB.find({}, function(err, session){
                console.log("all sessions "+session.length);
            })
        if (err){
            sendJsonResponse(res, 404, err);
        }else{
            sendJsonResponse(res, 200, session);
        }
    }
    );
};

<commit_msg>other traces<commit_after>var mongoose = require("mongoose");
var sessionDB = mongoose.model("sessions");
var userDB = mongoose.model("User");

var sendJsonResponse = function(res, status, content) {
    res.status(status);
    res.json(content);
};

module.exports.participationsList = function(req, res){
    sessionDB.find({
        participants: {$elemMatch: {$eq: req.user._id}}
    },function(err, session){
        console.log("inside participations request "+err);
        console.log("request id = "+req.user._id);
        console.log(session);

            sessionDB.find({}, function(err, session){
                console.log("all sessions "+session.length);
                console.log(session);
            })
        if (err){
            sendJsonResponse(res, 404, err);
        }else{
            sendJsonResponse(res, 200, session);
        }
    }
    );
};

<|endoftext|>


<commit_before>import Quill from 'quill';

// replace
 tag with

const Block = Quill.import('blots/block');
Block.tagName = 'DIV';
Quill.register(Block, true);

// table
const Table = Quill.import('formats/table-container');
const superCreate = Table.create.bind(Table);
Table.create = (value) => {
	const node = superCreate(value);
	node.classList.add('table');
	node.classList.add('table-bordered');
	return node;
}
Quill.register(Table, true);

// hidden blot
class HiddenBlock extends Block {
	static create(value) {
		const node = super.create(value);
		node.setAttribute('data-comment', value);
		node.classList.add('hidden');
		return node;
	}

	static formats(node) {
		return node.getAttribute('data-comment');
	}
}
HiddenBlock.blotName = 'hiddenblot';
HiddenBlock.tagName = 'DIV';
Quill.register(HiddenBlock, true);

// image uploader
const Uploader = Quill.import('modules/uploader');
Uploader.DEFAULTS.mimetypes.push('image/gif');

// inline style
const BackgroundStyle = Quill.import('attributors/style/background');
const ColorStyle = Quill.import('attributors/style/color');
const SizeStyle = Quill.import('attributors/style/size');
const FontStyle = Quill.import('attributors/style/font');
const AlignStyle = Quill.import('attributors/style/align');
const DirectionStyle = Quill.import('attributors/style/direction');
Quill.register(BackgroundStyle, true);
Quill.register(ColorStyle, true);
Quill.register(SizeStyle, true);
Quill.register(FontStyle, true);
Quill.register(AlignStyle, true);
Quill.register(DirectionStyle, true);

frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({
	make_input() {
		this.has_input = true;
		this.make_quill_editor();
	},

	make_quill_editor() {
		if (this.quill) return;
		this.quill_container = $('
').appendTo(this.input_area);
		this.quill = new Quill(this.quill_container[0], this.get_quill_options());
		this.bind_events();
	},

	bind_events() {
		this.quill.on('text-change', frappe.utils.debounce((delta, oldDelta, source) => {
			if (!this.is_quill_dirty(source)) return;

			const input_value = this.get_input_value();
			this.parse_validate_and_set_in_model(input_value);
		}, 300));

		$(this.quill.root).on('keydown', (e) => {
			const key = frappe.ui.keys.get_key(e);
			if (['ctrl+b', 'meta+b'].includes(key)) {
				e.stopPropagation();
			}
		});

		$(this.quill.root).on('drop', (e) => {
			e.stopPropagation();
		});

		// table commands
		this.$wrapper.on('click', '.ql-table .ql-picker-item', (e) => {
			const $target = $(e.currentTarget);
			const action = $target.data().value;
			e.preventDefault();

			const table = this.quill.getModule('table');
			if (action === 'insert-table') {
				table.insertTable(2, 2);
			} else if (action === 'insert-row-above') {
				table.insertRowAbove();
			} else if (action === 'insert-row-below') {
				table.insertRowBelow();
			} else if (action === 'insert-column-left') {
				table.insertColumnLeft();
			} else if (action === 'insert-column-right') {
				table.insertColumnRight();
			} else if (action === 'delete-row') {
				table.deleteRow();
			} else if (action === 'delete-column') {
				table.deleteColumn();
			} else if (action === 'delete-table') {
				table.deleteTable();
			}

			if (action !== 'delete-row') {
				table.balanceTables();
			}

			e.preventDefault();
		});
	},

	is_quill_dirty(source) {
		if (source === 'api') return false;
		let input_value = this.get_input_value();
		return this.value !== input_value;
	},

	get_quill_options() {
		return {
			modules: {
				toolbar: this.get_toolbar_options(),
				table: true
			},
			theme: 'snow'
		};
	},

	get_toolbar_options() {
		return [
			[{ 'header': [1, 2, 3, false] }],
			['bold', 'italic', 'underline'],
			['blockquote', 'code-block'],
			['link', 'image'],
			[{ 'list': 'ordered' }, { 'list': 'bullet' }],
			[{ 'align': [] }],
			[{ 'indent': '-1'}, { 'indent': '+1' }],
			[{'table': [
				'insert-table',
				'insert-row-above',
				'insert-row-below',
				'insert-column-right',
				'insert-column-left',
				'delete-row',
				'delete-column',
				'delete-table',
			]}],
			['clean']
		];
	},

	parse(value) {
		if (value == null) {
			value = "";
		}
		return frappe.dom.remove_script_and_style(value);
	},

	set_formatted_input(value) {
		if (!this.quill) return;
		if (value === this.get_input_value()) return;
		if (!value) {
			// clear contents for falsy values like '', undefined or null
			this.quill.setText('');
			return;
		}

		this.quill.clipboard.dangerouslyPasteHTML(value);
	},

	get_input_value() {
		return this.quill ? this.quill.root.innerHTML : '';
	}
});
<commit_msg>fix(Quill): Set HTML without triggering a focus (#6456)<commit_after>import Quill from 'quill';

// replace
 tag with

const Block = Quill.import('blots/block');
Block.tagName = 'DIV';
Quill.register(Block, true);

// table
const Table = Quill.import('formats/table-container');
const superCreate = Table.create.bind(Table);
Table.create = (value) => {
	const node = superCreate(value);
	node.classList.add('table');
	node.classList.add('table-bordered');
	return node;
}
Quill.register(Table, true);

// hidden blot
class HiddenBlock extends Block {
	static create(value) {
		const node = super.create(value);
		node.setAttribute('data-comment', value);
		node.classList.add('hidden');
		return node;
	}

	static formats(node) {
		return node.getAttribute('data-comment');
	}
}
HiddenBlock.blotName = 'hiddenblot';
HiddenBlock.tagName = 'DIV';
Quill.register(HiddenBlock, true);

// image uploader
const Uploader = Quill.import('modules/uploader');
Uploader.DEFAULTS.mimetypes.push('image/gif');

// inline style
const BackgroundStyle = Quill.import('attributors/style/background');
const ColorStyle = Quill.import('attributors/style/color');
const SizeStyle = Quill.import('attributors/style/size');
const FontStyle = Quill.import('attributors/style/font');
const AlignStyle = Quill.import('attributors/style/align');
const DirectionStyle = Quill.import('attributors/style/direction');
Quill.register(BackgroundStyle, true);
Quill.register(ColorStyle, true);
Quill.register(SizeStyle, true);
Quill.register(FontStyle, true);
Quill.register(AlignStyle, true);
Quill.register(DirectionStyle, true);

frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({
	make_input() {
		this.has_input = true;
		this.make_quill_editor();
	},

	make_quill_editor() {
		if (this.quill) return;
		this.quill_container = $('
').appendTo(this.input_area);
		this.quill = new Quill(this.quill_container[0], this.get_quill_options());
		this.bind_events();
	},

	bind_events() {
		this.quill.on('text-change', frappe.utils.debounce((delta, oldDelta, source) => {
			if (!this.is_quill_dirty(source)) return;

			const input_value = this.get_input_value();
			this.parse_validate_and_set_in_model(input_value);
		}, 300));

		$(this.quill.root).on('keydown', (e) => {
			const key = frappe.ui.keys.get_key(e);
			if (['ctrl+b', 'meta+b'].includes(key)) {
				e.stopPropagation();
			}
		});

		$(this.quill.root).on('drop', (e) => {
			e.stopPropagation();
		});

		// table commands
		this.$wrapper.on('click', '.ql-table .ql-picker-item', (e) => {
			const $target = $(e.currentTarget);
			const action = $target.data().value;
			e.preventDefault();

			const table = this.quill.getModule('table');
			if (action === 'insert-table') {
				table.insertTable(2, 2);
			} else if (action === 'insert-row-above') {
				table.insertRowAbove();
			} else if (action === 'insert-row-below') {
				table.insertRowBelow();
			} else if (action === 'insert-column-left') {
				table.insertColumnLeft();
			} else if (action === 'insert-column-right') {
				table.insertColumnRight();
			} else if (action === 'delete-row') {
				table.deleteRow();
			} else if (action === 'delete-column') {
				table.deleteColumn();
			} else if (action === 'delete-table') {
				table.deleteTable();
			}

			if (action !== 'delete-row') {
				table.balanceTables();
			}

			e.preventDefault();
		});
	},

	is_quill_dirty(source) {
		if (source === 'api') return false;
		let input_value = this.get_input_value();
		return this.value !== input_value;
	},

	get_quill_options() {
		return {
			modules: {
				toolbar: this.get_toolbar_options(),
				table: true
			},
			theme: 'snow'
		};
	},

	get_toolbar_options() {
		return [
			[{ 'header': [1, 2, 3, false] }],
			['bold', 'italic', 'underline'],
			['blockquote', 'code-block'],
			['link', 'image'],
			[{ 'list': 'ordered' }, { 'list': 'bullet' }],
			[{ 'align': [] }],
			[{ 'indent': '-1'}, { 'indent': '+1' }],
			[{'table': [
				'insert-table',
				'insert-row-above',
				'insert-row-below',
				'insert-column-right',
				'insert-column-left',
				'delete-row',
				'delete-column',
				'delete-table',
			]}],
			['clean']
		];
	},

	parse(value) {
		if (value == null) {
			value = "";
		}
		return frappe.dom.remove_script_and_style(value);
	},

	set_formatted_input(value) {
		if (!this.quill) return;
		if (value === this.get_input_value()) return;
		if (!value) {
			// clear contents for falsy values like '', undefined or null
			this.quill.setText('');
			return;
		}

		// set html without triggering a focus
		const delta = this.quill.clipboard.convert({ html: value, text: '' });
		this.quill.setContents(delta);
	},

	get_input_value() {
		return this.quill ? this.quill.root.innerHTML : '';
	}
});
<|endoftext|>


<commit_before>export default class GoogleDrivePicker {
    constructor({
        pickerCallback,
        enabled,
        appId,
        developerKey,
        clientId
    } = {}) {
        this.scope = ['https://www.googleapis.com/auth/drive.readonly'];
        this.pickerApiLoaded = false;
        this.enabled = enabled;
        this.appId = appId;
        this.pickerCallback = pickerCallback;
        this.developerKey = developerKey;
        this.clientId = clientId;
    }

    loadPicker() {
        // load the google API library
        $.ajax({
            method: "GET",
            url: "https://apis.google.com/js/api.js",
            dataType: "script",
            cache: true
        }).done(this.loadGapi.bind(this));
    }

    loadGapi() {
        // load auth and picker libraries
        if (!frappe.boot.user.google_drive_token) {
            gapi.load('auth', this.onAuthApiLoad.bind(this));
        }

        gapi.load('picker', this.onPickerApiLoad.bind(this));
    }

    onAuthApiLoad() {
        gapi.auth.authorize({
            'client_id': this.clientId,
            'scope': this.scope,
            'immediate': false
        }, this.handleAuthResult.bind(this));
    }

    handleAuthResult(authResult) {
        if (authResult && !authResult.error) {
            frappe.boot.user.google_drive_token = authResult.access_token;
            this.createPicker();
        }
    }

    onPickerApiLoad() {
        this.pickerApiLoaded = true;
        this.createPicker();
    }

    createPicker() {
        // Create and render a Picker object for searching images.
        if (this.pickerApiLoaded && frappe.boot.user.google_drive_token) {
            var view = new google.picker.DocsView(google.picker.ViewId.DOCS)
                .setParent('root') // show the root folder by default
                .setIncludeFolders(true); // also show folders, not just files

            var picker = new google.picker.PickerBuilder()
                .setAppId(this.appId)
                .setDeveloperKey(this.developerKey)
                .setOAuthToken(frappe.boot.user.google_drive_token)
                .addView(view)
                .setLocale(frappe.boot.lang)
                .setCallback(this.pickerCallback)
                .build();

            picker.setVisible(true);
        }
    }
}
<commit_msg>fix: spaces to tabs<commit_after>export default class GoogleDrivePicker {
	constructor({
		pickerCallback,
		enabled,
		appId,
		developerKey,
		clientId
	} = {}) {
		this.scope = ['https://www.googleapis.com/auth/drive.readonly'];
		this.pickerApiLoaded = false;
		this.enabled = enabled;
		this.appId = appId;
		this.pickerCallback = pickerCallback;
		this.developerKey = developerKey;
		this.clientId = clientId;
	}

	loadPicker() {
		// load the google API library
		$.ajax({
			method: "GET",
			url: "https://apis.google.com/js/api.js",
			dataType: "script",
			cache: true
		}).done(this.loadGapi.bind(this));
	}

	loadGapi() {
		// load auth and picker libraries
		if (!frappe.boot.user.google_drive_token) {
			gapi.load('auth', this.onAuthApiLoad.bind(this));
		}

		gapi.load('picker', this.onPickerApiLoad.bind(this));
	}

	onAuthApiLoad() {
		gapi.auth.authorize({
			'client_id': this.clientId,
			'scope': this.scope,
			'immediate': false
		}, this.handleAuthResult.bind(this));
	}

	handleAuthResult(authResult) {
		if (authResult && !authResult.error) {
			frappe.boot.user.google_drive_token = authResult.access_token;
			this.createPicker();
		}
	}

	onPickerApiLoad() {
		this.pickerApiLoaded = true;
		this.createPicker();
	}

	createPicker() {
		// Create and render a Picker object for searching images.
		if (this.pickerApiLoaded && frappe.boot.user.google_drive_token) {
			var view = new google.picker.DocsView(google.picker.ViewId.DOCS)
				.setParent('root') // show the root folder by default
				.setIncludeFolders(true); // also show folders, not just files

			var picker = new google.picker.PickerBuilder()
				.setAppId(this.appId)
				.setDeveloperKey(this.developerKey)
				.setOAuthToken(frappe.boot.user.google_drive_token)
				.addView(view)
				.setLocale(frappe.boot.lang)
				.setCallback(this.pickerCallback)
				.build();

			picker.setVisible(true);
		}
	}
}
<|endoftext|>