<commit_before>import React from 'react';
import FocusTrap from 'focus-trap-react';
import { Container, Modal, Segment } from 'semantic-ui-react';
let fileSaver = require('../../custom_modules/fabricjs/fileSaver');

const headerStyle = {
    'textAlign': 'center'
};

const canvasStyle = {
    'height': '0px',
    'width': '0px',
    'border': '1px solid #000000'
};

class PaintModal extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            modalOpen: false,
            activeTrap: false
        };

        this.reader = new FileReader();
        this.primaryColor = 'black';
        this.secondaryColor = 'black';
        this.drawingMode = false;
        this.canvas = null;
        this.handleOpen = this.handleOpen.bind(this);
        this.startFabric = this.startFabric.bind(this);
        this.addRect = this.addRect.bind(this);
        this.addCircle = this.addCircle.bind(this);
        this.addTriangle = this.addTriangle.bind(this);
        this.downloadImg = this.downloadImg.bind(this);
        this.deleteElement = this.deleteElement.bind(this);
        this.setDrawingMode = this.setDrawingMode.bind(this);
        this.setLineWidth = this.setLineWidth.bind(this);
        this.loadImg = this.loadImg.bind(this);
    }

    componentDidMount() {
        this.startFabric();
    }

    componentDidUpdate() {

    }

    startFabric(){
        this.canvas = new fabric.Canvas('fabriccanvas');

        this.canvas.setHeight(500);
        this.canvas.setWidth(600);

        // Adding event listeners to the color inputs.

        let primaryColorInput = document.getElementById('primaryColor');
        let secondaryColorInput = document.getElementById('secondaryColor');

        if (primaryColorInput) {
            primaryColorInput.addEventListener('input', () => {
                this.primaryColor = primaryColorInput.value;
                this.canvas.freeDrawingBrush.color = this.primaryColor;
            });

            secondaryColorInput.addEventListener('input', () => {
                this.secondaryColor = secondaryColorInput.value;
            });
        }

        /*event handler for the file reader*/
        this.reader.onload = (event) => {
            let imgObj = new Image();
            imgObj.src = event.target.result;
            imgObj.onload = () => {
                let image = new fabric.Image(imgObj);
                image.set({
                    angle: 0,
                    padding: 0
                });
                this.canvas.centerObject(image);
                this.canvas.add(image);
                this.canvas.renderAll();
            };
        };
    }

    handleOpen(){
        $('#app').attr('aria-hidden', 'true');
        this.setState({
            modalOpen:true,
            activeTrap:true
        });

    }

    unmountTrap() {
        if(this.state.activeTrap){
            this.setState({ activeTrap: false });
            $('#app').attr('aria-hidden','false');
        }
    }

    addRect() {
        let coord = {left: 10, top: 10};
        this.canvas.add(new fabric.Rect({
            left: coord.left,
            top: coord.top,
            fill: this.primaryColor,
            width: 50,
            height: 50,
            opacity: 1
        }));
    }

    addCircle() {
        let coord = {left: 10, top: 10};

        this.canvas.add(new fabric.Circle({
            left: coord.left,
            top: coord.top,
            fill: this.primaryColor,
            radius: 50,
            opacity: 1
        }));
    }

    addTriangle() {
        let coord = {left: 10, top: 10};

        this.canvas.add(new fabric.Triangle({
            left: coord.left,
            top: coord.top,
            fill: this.primaryColor,
            width: 50,
            height: 50,
            opacity: 1
        }));
    }

    deleteElement() {
        let activeObjects = this.canvas.getActiveObjects();
        this.canvas.discardActiveObject();
        if (activeObjects.length) {
            this.canvas.remove.apply(this.canvas, activeObjects);
        }
    }

    setDrawingMode() {
        this.drawingMode = !this.drawingMode;
        this.canvas.isDrawingMode = this.drawingMode;
    }

    setLineWidth(event) {
        let value = parseInt(event.target.value, 10) || 1;
        this.canvas.freeDrawingBrush.width = value;
    }

    loadImg(event) {
        this.reader.readAsDataURL(event.target.files[0]);
    }

    downloadImg() {

    }

    render() {

        return(

            <Modal
                trigger={
                     this.handleKeyPress(evt, 'handleOpen')}>
                         Paint

                }
                open={this.state.modalOpen}
                onOpen={this.handleOpen}
                onClose={this.handleClose}
                id="paintModal"
                aria-labelledby="paintModalHeader"
                aria-describedby="paintModalDescription"
                tabIndex="0"
            >
                <FocusTrap
                    id="focus-trap-paintModal"
                    className = "header"
                    active={this.state.activeTrap}
                    focusTrapOptions={{
                        onDeactivate:this.unmountTrap,
                        clickOutsideDeactivates:true,
                        initialFocus: '#paintModalDescription'
                    }}
                >
                    <Modal.Header className="ui center aligned" id="paintModalHeader">

Draw and Paint

                    </Modal.Header>
                    <Modal.Content>
                        <Container>
                            <Segment color="blue" textAlign="left" padded>

Draw your own SVG image

                                <Segment textAlign="center" >

Draw inside the canvas using the tools provided.

                                    <button onClick={this.startFabric} onKeyPress={(evt) => this.handleKeyPress(evt, 'startFabric')}>Click and start drawing!</button>

                                    <canvas id="fabriccanvas" style={canvasStyle}></canvas>

                                        <button onClick={this.addRect}>Add Rectangle</button>
                                        <button onClick={this.addCircle}>Add Circle</button>
                                        <button onClick={this.addTriangle}>Add Triangle</button>
                                        <button onClick={this.downloadImg}>Download Image</button>
                                        <input type="color" id="primaryColor"/>
                                        <input type="color" id="secondaryColor"/>
                                        <button onClick={this.deleteElement}>Delete selected objects</button>

                                            <input type="checkbox" name="newsletter" onClick={this.setDrawingMode}/>
                                            Drawing mode

                                        <input type="range" min="0" max="50" onChange={this.setLineWidth}/>

Load Image!
<input type="file" onChange={this.loadImg}/>

                                </Segment>
                            </Segment>

                        </Container>

                    </Modal.Content>

                </FocusTrap>
            </Modal>

        );
    }
}

PaintModal.contextTypes = {
    executeAction: React.PropTypes.func.isRequired,
    intl: React.PropTypes.object.isRequired
};

export default PaintModal;
<commit_msg>Basic undo/redo after unsuccessfull attempt of something more elaborated..<commit_after>import React from 'react';
import FocusTrap from 'focus-trap-react';
import { Container, Modal, Segment } from 'semantic-ui-react';
let fileSaver = require('../../custom_modules/fabricjs/fileSaver');

const headerStyle = {
    'textAlign': 'center'
};

const canvasStyle = {
    'height': '0px',
    'width': '0px',
    'border': '1px solid #000000'
};

class PaintModal extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            modalOpen: false,
            activeTrap: false
        };

        //
        this.reader = new FileReader();
        this.primaryColor = 'black';
        this.secondaryColor = 'black';
        this.drawingMode = false;
        this.canvas = null;

        // For undo - redo
        /*this.canvasState = {
            current: null,
            list: [],
            state: [],
            index: 0,
            index2: 0,
            action: false,
            refresh: true,
        };
*/
        this.objectsStack = [];

        //
        this.handleOpen = this.handleOpen.bind(this);
        this.startFabric = this.startFabric.bind(this);
        this.addRect = this.addRect.bind(this);
        this.addCircle = this.addCircle.bind(this);
        this.addTriangle = this.addTriangle.bind(this);
        this.downloadImg = this.downloadImg.bind(this);
        this.deleteElement = this.deleteElement.bind(this);
        this.setDrawingMode = this.setDrawingMode.bind(this);
        this.setLineWidth = this.setLineWidth.bind(this);
        this.loadImg = this.loadImg.bind(this);
        this.undo = this.undo.bind(this);
        this.redo = this.redo.bind(this);
    }

    componentDidMount() {
        this.startFabric();
    }

    componentDidUpdate() {

    }

    startFabric(){
        this.canvas = new fabric.Canvas('fabriccanvas');

        this.canvas.setHeight(500);
        this.canvas.setWidth(600);

        // Adding event listeners to the color inputs.

        let primaryColorInput = document.getElementById('primaryColor');
        let secondaryColorInput = document.getElementById('secondaryColor');

        if (primaryColorInput) {
            primaryColorInput.addEventListener('input', () => {
                this.primaryColor = primaryColorInput.value;
                this.canvas.freeDrawingBrush.color = this.primaryColor;
            });

            secondaryColorInput.addEventListener('input', () => {
                this.secondaryColor = secondaryColorInput.value;
            });
        }

        /*event handler for the file reader*/
        this.reader.onload = (event) => {
            let imgObj = new Image();
            imgObj.src = event.target.result;
            imgObj.onload = () => {
                let image = new fabric.Image(imgObj);
                image.set({
                    angle: 0,
                    padding: 0
                });
                this.canvas.centerObject(image);
                this.canvas.add(image);
                this.canvas.renderAll();
            };
        };

        /*
        // Event handlers for undo/redo
        this.canvas.on("object:added", (e) => {
            let object = e.target;
            //console.log('object:modified');

            if (this.canvasState.action === true) {
                this.canvasState.state = [this.canvasState.state[this.canvasState.index2]];
                this.canvasState.list = [this.canvasState.list[this.canvasState.index2]];
                this.canvasState.list = this.canvasState.list[];
                this.canvasState.action = false;
                this.canvasState.index = 1;
            }
            object.saveState();

            console.log(JSON.stringify(object.originalState));
            this.canvasState.state[this.canvasState.index] = object;
            this.canvasState.list[this.canvasState.index] = object;
            this.canvasState.index++;
            this.canvasState.index2 = this.canvasState.index - 1;
            this.canvasState.refresh = true;
        });

        this.canvas.on("object:modified", (e) => {
            let object = e.target;
            //console.log('object:modified');

            if (this.action === true) {
                this.canvasState.state = [this.canvasState.state[this.canvasState.index2]];
                this.canvasState.list = [this.canvasState.list[this.canvasState.index2]];

                this.canvasState.action = false;
                //console.log(state);
                this.canvasState.index = 1;
            }

            object.saveState();

            this.canvasState.state[this.canvasState.index] = object.originalState;
            this.list[this.canvasState.index] = object;
            this.canvasState.index++;
            this.canvasState.index2 = this.canvasState.index - 1;

            //console.log(state);
            this.canvasState.refresh = true;
        });*/
    }

    handleOpen(){
        $('#app').attr('aria-hidden', 'true');
        this.setState({
            modalOpen:true,
            activeTrap:true
        });

    }

    unmountTrap() {
        if(this.state.activeTrap){
            this.setState({ activeTrap: false });
            $('#app').attr('aria-hidden','false');
        }
    }

    addRect() {
        let coord = {left: 10, top: 10};
        this.canvas.add(new fabric.Rect({
            left: coord.left,
            top: coord.top,
            fill: this.primaryColor,
            width: 50,
            height: 50,
            opacity: 1
        }));
    }

    addCircle() {
        let coord = {left: 10, top: 10};

        this.canvas.add(new fabric.Circle({
            left: coord.left,
            top: coord.top,
            fill: this.primaryColor,
            radius: 50,
            opacity: 1
        }));
    }

    addTriangle() {
        let coord = {left: 10, top: 10};

        this.canvas.add(new fabric.Triangle({
            left: coord.left,
            top: coord.top,
            fill: this.primaryColor,
            width: 50,
            height: 50,
            opacity: 1
        }));
    }

    deleteElement() {
        let activeObjects = this.canvas.getActiveObjects();
        this.canvas.discardActiveObject();
        if (activeObjects.length) {
            this.canvas.remove.apply(this.canvas, activeObjects);
        }
    }

    setDrawingMode() {
        this.drawingMode = !this.drawingMode;
        this.canvas.isDrawingMode = this.drawingMode;
    }

    setLineWidth(event) {
        let value = parseInt(event.target.value, 10) || 1;
        this.canvas.freeDrawingBrush.width = value;
    }

    loadImg(event) {
        this.reader.readAsDataURL(event.target.files[0]);
    }

    downloadImg() {

    }

    undo() {
        let objects = this.canvas.getObjects();
        if (objects.length !== 0) {
            let last = objects[objects.length - 1];
            console.log('////////////////eo');
            console.log(this);
            console.log(this.objectsStack);
            this.objectsStack.push(last);
            this.canvas.remove(last);
            this.canvas.renderAll();
        }
        /*
        if (this.canvasState.index <= 0) {
            this.canvasState.index = 0;
            return;
        }

        if (this.canvasState.refresh === true) {
            this.canvasState.index--;
            this.canvasState.refresh = false;
        }

        this.canvasState.index2 = this.canvasState.index - 1;
        this.canvasState.current = this.canvasState.list[this.canvasState.index2];
        console.log(this.canvasState.current);
        console.log(this.canvasState.state);
        this.canvasState.current = this.canvasState.state[this.canvasState.index2];

        this.canvasState.index--;

        this.canvasState.current.setCoords();
        this.canvas.renderAll();
        this.canvasState.action = true;
*/
    }

    redo() {

        if (this.objectsStack.length > 0) {
            let object = this.objectsStack.pop();
            this.canvas.add(object);
        }

        /*
        this.canvasState.action = true;
        if (this.canvasState.index >= this.canvasState.state.length - 1) {
            return;
        }

        this.canvasState.index2 = this.canvasState.index + 1;
        this.canvasState.current = this.canvasState.list[this.canvasState.index2];
        this.canvasState.current.setOptions(JSON.parse(this.canvasState.state[this.canvasState.index2]));

        this.canvasState.index++;
        this.canvasState.current.setCoords();
        this.canvas.renderAll();
        */
    }

    render() {

        return(

            <Modal
                trigger={
                     this.handleKeyPress(evt, 'handleOpen')}>
                         Paint

                }
                open={this.state.modalOpen}
                onOpen={this.handleOpen}
                onClose={this.handleClose}
                id="paintModal"
                aria-labelledby="paintModalHeader"
                aria-describedby="paintModalDescription"
                tabIndex="0"
            >
                <FocusTrap
                    id="focus-trap-paintModal"
                    className = "header"
                    active={this.state.activeTrap}
                    focusTrapOptions={{
                        onDeactivate:this.unmountTrap,
                        clickOutsideDeactivates:true,
                        initialFocus: '#paintModalDescription'
                    }}
                >
                    <Modal.Header className="ui center aligned" id="paintModalHeader">

Draw and Paint

                    </Modal.Header>
                    <Modal.Content>
                        <Container>
                            <Segment color="blue" textAlign="left" padded>

Draw your own SVG image

                                <Segment textAlign="center" >

Draw inside the canvas using the tools provided.

                                    <button onClick={this.startFabric} onKeyPress={(evt) => this.handleKeyPress(evt, 'startFabric')}>Click and start drawing!</button>

                                    <canvas id="fabriccanvas" style={canvasStyle}/>

                                        <button onClick={this.addRect}>Add Rectangle</button>
                                        <button onClick={this.addCircle}>Add Circle</button>
                                        <button onClick={this.addTriangle}>Add Triangle</button>
                                        <button onClick={this.downloadImg}>Download Image</button>
                                        <input type="color" id="primaryColor"/>
                                        <input type="color" id="secondaryColor"/>
                                        <button onClick={this.deleteElement}>Delete selected objects</button>

                                            <input type="checkbox" name="newsletter" onClick={this.setDrawingMode}/>
                                            Drawing mode

                                        <input type="range" min="0" max="50" onChange={this.setLineWidth}/>

Load Image!
<input type="file" onChange={this.loadImg}/>

                                        <button onClick={this.undo}>Undo</button>
                                        <button onClick={this.redo}>Redo</button>

                                </Segment>
                            </Segment>

                        </Container>

                    </Modal.Content>

                </FocusTrap>
            </Modal>

        );
    }
}

PaintModal.contextTypes = {
    executeAction: React.PropTypes.func.isRequired,
    intl: React.PropTypes.object.isRequired
};

export default PaintModal;
<|endoftext|>


<commit_before>export SlideLeft from './slide-left';
export SlideRight from './slide-right';
export ZoomIn from './zoom-in';
export ZoomOut from './zoom-out';
<commit_msg>Full extension imports in animations<commit_after>export SlideLeft from './slide-left.scss';
export SlideRight from './slide-right.scss';
export ZoomIn from './zoom-in.scss';
export ZoomOut from './zoom-out.scss';
<|endoftext|>


<commit_before>import assign from 'object-assign';
import customElements from '../native/custom-elements';
import init from './init';
import support from '../native/support';

export default function (name, props) {
  let elem;
  const Ctor = customElements.get(name);

  if (Ctor) {
    if (support.v1) {
      elem = document.createElement(name, { is: Ctor.extends || null });
    } else if (support.v0) {
      elem = Ctor.extends ? document.createElement(Ctor.extends, name) : document.createElement(name);
    } else {
      if (Ctor.extends) {
        elem = document.createElement(Ctor.extends);
        elem.setAttribute('is', name);
      } else {
        elem = document.createElement(name);
      }
      init(elem);
    }
  } else {
    elem = document.createElement(name);
  }

  return assign(elem, props);
}
<commit_msg>Remove second argument to create().<commit_after>import customElements from '../native/custom-elements';
import init from './init';
import support from '../native/support';

export default function (name) {
  let elem;
  const Ctor = customElements.get(name);

  if (Ctor) {
    if (support.v1) {
      elem = document.createElement(name, { is: Ctor.extends || null });
    } else if (support.v0) {
      elem = Ctor.extends ? document.createElement(Ctor.extends, name) : document.createElement(name);
    } else {
      if (Ctor.extends) {
        elem = document.createElement(Ctor.extends);
        elem.setAttribute('is', name);
      } else {
        elem = document.createElement(name);
      }
      init(elem);
    }
  } else {
    elem = document.createElement(name);
  }

  return elem;
}
<|endoftext|>


<commit_before>var _ = require('../util')
var config = require('../config')

/**
 * Expose useful internals
 */

exports.util = _
exports.config = config
exports.set = _.set
exports.delete = _.delete
exports.nextTick = _.nextTick

/**
 * The following are exposed for advanced usage / plugins
 */

exports.compiler = require('../compiler')
exports.FragmentFactory = require('../fragment/factory')
exports.internalDirectives = require('../directives/internal')
exports.parsers = {
  path: require('../parsers/path'),
  text: require('../parsers/text'),
  template: require('../parsers/template'),
  directive: require('../parsers/directive'),
  expression: require('../parsers/expression')
}

/**
 * Each instance constructor, including Vue, has a unique
 * cid. This enables us to create wrapped "child
 * constructors" for prototypal inheritance and cache them.
 */

exports.cid = 0
var cid = 1

/**
 * Class inheritance
 *
 * @param {Object} extendOptions
 */

exports.extend = function (extendOptions) {
  extendOptions = extendOptions || {}
  var Super = this
  var isFirstExtend = Super.cid === 0
  if (isFirstExtend && extendOptions._Ctor) {
    return extendOptions._Ctor
  }
  var name = extendOptions.name || Super.options.name
  var Sub = createClass(name || 'VueComponent')
  Sub.prototype = Object.create(Super.prototype)
  Sub.prototype.constructor = Sub
  Sub.cid = cid++
  Sub.options = _.mergeOptions(
    Super.options,
    extendOptions
  )
  Sub['super'] = Super
  // allow further extension
  Sub.extend = Super.extend
  // create asset registers, so extended classes
  // can have their private assets too.
  config._assetTypes.forEach(function (type) {
    Sub[type] = Super[type]
  })
  // enable recursive self-lookup
  if (name) {
    Sub.options.components[name] = Sub
  }
  // cache constructor
  if (isFirstExtend) {
    extendOptions._Ctor = Sub
  }
  return Sub
}

/**
 * A function that returns a sub-class constructor with the
 * given name. This gives us much nicer output when
 * logging instances in the console.
 *
 * @param {String} name
 * @return {Function}
 */

function createClass (name) {
  return new Function(
    'return function ' + _.classify(name) +
    ' (options) { this._init(options) }'
  )()
}

/**
 * Plugin system
 *
 * @param {Object} plugin
 */

exports.use = function (plugin) {
  /* istanbul ignore if */
  if (plugin.installed) {
    return
  }
  // additional parameters
  var args = _.toArray(arguments, 1)
  args.unshift(this)
  if (typeof plugin.install === 'function') {
    plugin.install.apply(plugin, args)
  } else {
    plugin.apply(null, args)
  }
  plugin.installed = true
  return this
}

/**
 * Apply a global mixin by merging it into the default
 * options.
 */

exports.mixin = function (mixin) {
  var Vue = _.Vue
  Vue.options = _.mergeOptions(Vue.options, mixin)
}

/**
 * Create asset registration methods with the following
 * signature:
 *
 * @param {String} id
 * @param {*} definition
 */

config._assetTypes.forEach(function (type) {
  exports[type] = function (id, definition) {
    if (!definition) {
      return this.options[type + 's'][id]
    } else {
      if (
        type === 'component' &&
        _.isPlainObject(definition)
      ) {
        definition.name = id
        definition = _.Vue.extend(definition)
      }
      this.options[type + 's'][id] = definition
      return definition
    }
  }
})
<commit_msg>also warn built-in element as component for global registration<commit_after>var _ = require('../util')
var config = require('../config')

/**
 * Expose useful internals
 */

exports.util = _
exports.config = config
exports.set = _.set
exports.delete = _.delete
exports.nextTick = _.nextTick

/**
 * The following are exposed for advanced usage / plugins
 */

exports.compiler = require('../compiler')
exports.FragmentFactory = require('../fragment/factory')
exports.internalDirectives = require('../directives/internal')
exports.parsers = {
  path: require('../parsers/path'),
  text: require('../parsers/text'),
  template: require('../parsers/template'),
  directive: require('../parsers/directive'),
  expression: require('../parsers/expression')
}

/**
 * Each instance constructor, including Vue, has a unique
 * cid. This enables us to create wrapped "child
 * constructors" for prototypal inheritance and cache them.
 */

exports.cid = 0
var cid = 1

/**
 * Class inheritance
 *
 * @param {Object} extendOptions
 */

exports.extend = function (extendOptions) {
  extendOptions = extendOptions || {}
  var Super = this
  var isFirstExtend = Super.cid === 0
  if (isFirstExtend && extendOptions._Ctor) {
    return extendOptions._Ctor
  }
  var name = extendOptions.name || Super.options.name
  var Sub = createClass(name || 'VueComponent')
  Sub.prototype = Object.create(Super.prototype)
  Sub.prototype.constructor = Sub
  Sub.cid = cid++
  Sub.options = _.mergeOptions(
    Super.options,
    extendOptions
  )
  Sub['super'] = Super
  // allow further extension
  Sub.extend = Super.extend
  // create asset registers, so extended classes
  // can have their private assets too.
  config._assetTypes.forEach(function (type) {
    Sub[type] = Super[type]
  })
  // enable recursive self-lookup
  if (name) {
    Sub.options.components[name] = Sub
  }
  // cache constructor
  if (isFirstExtend) {
    extendOptions._Ctor = Sub
  }
  return Sub
}

/**
 * A function that returns a sub-class constructor with the
 * given name. This gives us much nicer output when
 * logging instances in the console.
 *
 * @param {String} name
 * @return {Function}
 */

function createClass (name) {
  return new Function(
    'return function ' + _.classify(name) +
    ' (options) { this._init(options) }'
  )()
}

/**
 * Plugin system
 *
 * @param {Object} plugin
 */

exports.use = function (plugin) {
  /* istanbul ignore if */
  if (plugin.installed) {
    return
  }
  // additional parameters
  var args = _.toArray(arguments, 1)
  args.unshift(this)
  if (typeof plugin.install === 'function') {
    plugin.install.apply(plugin, args)
  } else {
    plugin.apply(null, args)
  }
  plugin.installed = true
  return this
}

/**
 * Apply a global mixin by merging it into the default
 * options.
 */

exports.mixin = function (mixin) {
  var Vue = _.Vue
  Vue.options = _.mergeOptions(Vue.options, mixin)
}

/**
 * Create asset registration methods with the following
 * signature:
 *
 * @param {String} id
 * @param {*} definition
 */

config._assetTypes.forEach(function (type) {
  exports[type] = function (id, definition) {
    if (!definition) {
      return this.options[type + 's'][id]
    } else {
      /* istanbul ignore if */
      if (process.env.NODE_ENV !== 'production') {
        if (type === 'component' && _.commonTagRE.test(id)) {
          _.warn(
            'Do not use built-in HTML elements as component ' +
            'id: ' + id
          )
        }
      }
      if (
        type === 'component' &&
        _.isPlainObject(definition)
      ) {
        definition.name = id
        definition = _.Vue.extend(definition)
      }
      this.options[type + 's'][id] = definition
      return definition
    }
  }
})
<|endoftext|>


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

var EventEmitter = require('eventemitter3');
var IFrameMessageSender = require('./iframe-message-sender');
var Message = require('../message');
var Util = require('../util');

// Save the executing script. This will be used to calculate the embed URL.
var CURRENT_SCRIPT_SRC = Util.getCurrentScript().src;
var FAKE_FULLSCREEN_CLASS = 'vrview-fake-fullscreen';

/**
 * Entry point for the VR View JS API.
 *
 * Emits the following events:
 *    ready: When the player is loaded.
 *    modechange: When the viewing mode changes (normal, fullscreen, VR).
 *    click (id): When a hotspot is clicked.
 */
function Player(selector, contentInfo) {
  // Create a VR View iframe depending on the parameters.
  var iframe = this.createIframe_(contentInfo);
  this.iframe = iframe;

  var parentEl = document.querySelector(selector);
  parentEl.appendChild(iframe);

  // Make a sender as well, for relying commands to the child IFrame.
  this.sender = new IFrameMessageSender(iframe);

  // Listen to messages from the IFrame.
  window.addEventListener('message', this.onMessage_.bind(this), false);

  // Expose a public .isPaused attribute.
  this.isPaused = false;

  // Other public attributes
  this.currentTime = 0;
  this.duration = 0;
  this.volume = 1;

  if (Util.isIOS()) {
    this.injectFullscreenStylesheet_();
  }
}
Player.prototype = new EventEmitter();

/**
 * @param pitch {Number} The latitude of center, specified in degrees, between
 * -90 and 90, with 0 at the horizon.
 * @param yaw {Number} The longitude of center, specified in degrees, between
 * -180 and 180, with 0 at the image center.
 * @param radius {Number} The radius of the hotspot, specified in meters.
 * @param distance {Number} The distance of the hotspot from camera, specified
 * in meters.
 * @param hotspotId {String} The ID of the hotspot.
 */
Player.prototype.addHotspot = function(hotspotId, params) {
  // TODO: Add validation to params.
  var data = {
    pitch: params.pitch,
    yaw: params.yaw,
    radius: params.radius,
    distance: params.distance,
    id: hotspotId
  };
  this.sender.send({type: Message.ADD_HOTSPOT, data: data});
};

Player.prototype.play = function() {
  this.sender.send({type: Message.PLAY});
};

Player.prototype.pause = function() {
  this.sender.send({type: Message.PAUSE});
};

/**
 * Equivalent of HTML5 setSrc().
 * @param {String} contentInfo
 */
Player.prototype.setContent = function(contentInfo) {
  this.absolutifyPaths_(contentInfo);
  var data = {
    contentInfo: contentInfo
  };
  this.sender.send({type: Message.SET_CONTENT, data: data});
};

/**
 * Sets the software volume of the video. 0 is mute, 1 is max.
 */
Player.prototype.setVolume = function(volumeLevel) {
  var data = {
    volumeLevel: volumeLevel
  };
  this.sender.send({type: Message.SET_VOLUME, data: data});
};

Player.prototype.getVolume = function() {
  return this.volume;
};

/**
 * Set the current time of the media being played
 * @param {Number} time
 */
Player.prototype.setCurrentTime = function(time) {
  var data = {
    currentTime: time
  };
  this.sender.send({type: Message.SET_CURRENT_TIME, data: data});
};

Player.prototype.getCurrentTime = function() {
  return this.currentTime;
};

Player.prototype.getDuration = function() {
  return this.duration;
};

/**
 * Helper for creating an iframe.
 *
 * @return {IFrameElement} The iframe.
 */
Player.prototype.createIframe_ = function(contentInfo) {
  this.absolutifyPaths_(contentInfo);

  var iframe = document.createElement('iframe');
  iframe.setAttribute('allowfullscreen', true);
  iframe.setAttribute('scrolling', 'no');
  iframe.style.border = 0;

  // Handle iframe size if width and height are specified.
  if (contentInfo.hasOwnProperty('width')) {
    iframe.setAttribute('width', contentInfo.width);
    delete contentInfo.width;
  }
  if (contentInfo.hasOwnProperty('height')) {
    iframe.setAttribute('height', contentInfo.height);
    delete contentInfo.height;
  }

  var url = this.getEmbedUrl_() + Util.createGetParams(contentInfo);
  iframe.src = url;

  return iframe;
};

Player.prototype.onMessage_ = function(event) {
  var message = event.data;
  if (!message || !message.type) {
    console.warn('Received message with no type.');
    return;
  }
  var type = message.type.toLowerCase();
  var data = message.data;

  switch (type) {
    case 'ready':
    case 'modechange':
    case 'error':
    case 'click':
    case 'ended':
      if (type === 'ready') {
        if (data !== undefined) {
          this.duration = data.duration;
	}
      }
      this.emit(type, data);
      break;
    case 'volumechange':
      this.volume = data;
      this.emit('volumechange', data);
      break;
    case 'timeupdate':
      this.currentTime = data;
      this.emit('timeupdate', {
        currentTime: this.currentTime,
        duration: this.duration
      });
      break;
    case 'play':
    case 'paused':
      this.isPaused = data;
      if (this.isPaused) {
        this.emit('pause', data);
      } else {
        this.emit('play', data);
      }
      break;
    case 'enter-fullscreen':
    case 'enter-vr':
      this.setFakeFullscreen_(true);
      break;
    case 'exit-fullscreen':
      this.setFakeFullscreen_(false);
      break;
    default:
      console.warn('Got unknown message of type %s from %s', message.type, message.origin);
  }
};

/**
 * Note: iOS doesn't support the fullscreen API.
 * In standalone <iframe> mode, VR View emulates fullscreen by redirecting to
 * another page.
 * In JS API mode, we stretch the iframe to cover the extent of the page using
 * CSS. To do this cleanly, we also inject a stylesheet.
 */
Player.prototype.setFakeFullscreen_ = function(isFullscreen) {
  if (isFullscreen) {
    this.iframe.classList.add(FAKE_FULLSCREEN_CLASS);
  } else {
    this.iframe.classList.remove(FAKE_FULLSCREEN_CLASS);
  }
};

Player.prototype.injectFullscreenStylesheet_ = function() {
  var styleString = [
    'iframe.' + FAKE_FULLSCREEN_CLASS,
    '{',
      'position: fixed !important;',
      'display: block !important;',
      'z-index: 9999999999 !important;',
      'top: 0 !important;',
      'left: 0 !important;',
      'width: 100% !important;',
      'height: 100% !important;',
      'margin: 0 !important;',
    '}',
  ].join('\n');
  var style = document.createElement('style');
  style.innerHTML = styleString;
  document.body.appendChild(style);
};

Player.prototype.getEmbedUrl_ = function() {
  // Assume that the script is in $ROOT/build/something.js, and that the iframe
  // HTML is in $ROOT/index.html.
  //
  // E.g: /vrview/2.0/build/vrview.min.js => /vrview/2.0/index.html.
  var path = CURRENT_SCRIPT_SRC;
  var split = path.split('/');
  var rootSplit = split.slice(0, split.length - 2);
  var rootPath = rootSplit.join('/');
  return rootPath + '/index.html';
};

Player.prototype.getDirName_ = function() {
  var path = window.location.pathname;
  path = path.substring(0, path.lastIndexOf('/'));
  return location.protocol + '//' + location.host + path;
};

/**
 * Make all of the URLs inside contentInfo absolute instead of relative.
 */
Player.prototype.absolutifyPaths_ = function(contentInfo) {
  var dirName = this.getDirName_();
  var urlParams = ['image', 'preview', 'video'];

  for (var i = 0; i < urlParams.length; i++) {
    var name = urlParams[i];
    var path = contentInfo[name];
    if (path && Util.isPathAbsolute(path)) {
      var absolute = Util.relativeToAbsolutePath(dirName, path);
      contentInfo[name] = absolute;
      //console.log('Converted to absolute: %s', absolute);
    }
  }
};

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

var EventEmitter = require('eventemitter3');
var IFrameMessageSender = require('./iframe-message-sender');
var Message = require('../message');
var Util = require('../util');

// Save the executing script. This will be used to calculate the embed URL.
var CURRENT_SCRIPT_SRC = Util.getCurrentScript().src;
var FAKE_FULLSCREEN_CLASS = 'vrview-fake-fullscreen';

/**
 * Entry point for the VR View JS API.
 *
 * Emits the following events:
 *    ready: When the player is loaded.
 *    modechange: When the viewing mode changes (normal, fullscreen, VR).
 *    click (id): When a hotspot is clicked.
 */
function Player(selector, contentInfo) {
  // Create a VR View iframe depending on the parameters.
  var iframe = this.createIframe_(contentInfo);
  this.iframe = iframe;

  var parentEl = document.querySelector(selector);
  parentEl.appendChild(iframe);

  // Make a sender as well, for relying commands to the child IFrame.
  this.sender = new IFrameMessageSender(iframe);

  // Listen to messages from the IFrame.
  window.addEventListener('message', this.onMessage_.bind(this), false);

  // Expose a public .isPaused attribute.
  this.isPaused = false;

  // Other public attributes
  this.currentTime = 0;
  this.duration = 0;
  this.volume = 1;

  if (Util.isIOS()) {
    this.injectFullscreenStylesheet_();
  }
}
Player.prototype = new EventEmitter();

/**
 * @param pitch {Number} The latitude of center, specified in degrees, between
 * -90 and 90, with 0 at the horizon.
 * @param yaw {Number} The longitude of center, specified in degrees, between
 * -180 and 180, with 0 at the image center.
 * @param radius {Number} The radius of the hotspot, specified in meters.
 * @param distance {Number} The distance of the hotspot from camera, specified
 * in meters.
 * @param hotspotId {String} The ID of the hotspot.
 */
Player.prototype.addHotspot = function(hotspotId, params) {
  // TODO: Add validation to params.
  var data = {
    pitch: params.pitch,
    yaw: params.yaw,
    radius: params.radius,
    distance: params.distance,
    id: hotspotId
  };
  this.sender.send({type: Message.ADD_HOTSPOT, data: data});
};

Player.prototype.play = function() {
  this.sender.send({type: Message.PLAY});
};

Player.prototype.pause = function() {
  this.sender.send({type: Message.PAUSE});
};

/**
 * Equivalent of HTML5 setSrc().
 * @param {String} contentInfo
 */
Player.prototype.setContent = function(contentInfo) {
  this.absolutifyPaths_(contentInfo);
  var data = {
    contentInfo: contentInfo
  };
  this.sender.send({type: Message.SET_CONTENT, data: data});
};

/**
 * Sets the software volume of the video. 0 is mute, 1 is max.
 */
Player.prototype.setVolume = function(volumeLevel) {
  var data = {
    volumeLevel: volumeLevel
  };
  this.sender.send({type: Message.SET_VOLUME, data: data});
};

Player.prototype.getVolume = function() {
  return this.volume;
};

/**
 * Set the current time of the media being played
 * @param {Number} time
 */
Player.prototype.setCurrentTime = function(time) {
  var data = {
    currentTime: time
  };
  this.sender.send({type: Message.SET_CURRENT_TIME, data: data});
};

Player.prototype.getCurrentTime = function() {
  return this.currentTime;
};

Player.prototype.getDuration = function() {
  return this.duration;
};

/**
 * Helper for creating an iframe.
 *
 * @return {IFrameElement} The iframe.
 */
Player.prototype.createIframe_ = function(contentInfo) {
  this.absolutifyPaths_(contentInfo);

  var iframe = document.createElement('iframe');
  iframe.setAttribute('allowfullscreen', true);
  iframe.setAttribute('scrolling', 'no');
  iframe.style.border = 0;

  // Handle iframe size if width and height are specified.
  if (contentInfo.hasOwnProperty('width')) {
    iframe.setAttribute('width', contentInfo.width);
    delete contentInfo.width;
  }
  if (contentInfo.hasOwnProperty('height')) {
    iframe.setAttribute('height', contentInfo.height);
    delete contentInfo.height;
  }

  var url = this.getEmbedUrl_() + Util.createGetParams(contentInfo);
  iframe.src = url;

  return iframe;
};

Player.prototype.onMessage_ = function(event) {
  var message = event.data;
  if (!message || !message.type) {
    console.warn('Received message with no type.');
    return;
  }
  var type = message.type.toLowerCase();
  var data = message.data;

  switch (type) {
    case 'ready':
      if (data !== undefined && data.duration !== undefined) {
        this.duration = data.duration;
      }
    case 'modechange':
    case 'error':
    case 'click':
    case 'ended':
      this.emit(type, data);
      break;
    case 'volumechange':
      this.volume = data;
      this.emit('volumechange', data);
      break;
    case 'timeupdate':
      this.currentTime = data;
      this.emit('timeupdate', {
        currentTime: this.currentTime,
        duration: this.duration
      });
      break;
    case 'play':
    case 'paused':
      this.isPaused = data;
      if (this.isPaused) {
        this.emit('pause', data);
      } else {
        this.emit('play', data);
      }
      break;
    case 'enter-fullscreen':
    case 'enter-vr':
      this.setFakeFullscreen_(true);
      break;
    case 'exit-fullscreen':
      this.setFakeFullscreen_(false);
      break;
    default:
      console.warn('Got unknown message of type %s from %s', message.type, message.origin);
  }
};

/**
 * Note: iOS doesn't support the fullscreen API.
 * In standalone <iframe> mode, VR View emulates fullscreen by redirecting to
 * another page.
 * In JS API mode, we stretch the iframe to cover the extent of the page using
 * CSS. To do this cleanly, we also inject a stylesheet.
 */
Player.prototype.setFakeFullscreen_ = function(isFullscreen) {
  if (isFullscreen) {
    this.iframe.classList.add(FAKE_FULLSCREEN_CLASS);
  } else {
    this.iframe.classList.remove(FAKE_FULLSCREEN_CLASS);
  }
};

Player.prototype.injectFullscreenStylesheet_ = function() {
  var styleString = [
    'iframe.' + FAKE_FULLSCREEN_CLASS,
    '{',
      'position: fixed !important;',
      'display: block !important;',
      'z-index: 9999999999 !important;',
      'top: 0 !important;',
      'left: 0 !important;',
      'width: 100% !important;',
      'height: 100% !important;',
      'margin: 0 !important;',
    '}',
  ].join('\n');
  var style = document.createElement('style');
  style.innerHTML = styleString;
  document.body.appendChild(style);
};

Player.prototype.getEmbedUrl_ = function() {
  // Assume that the script is in $ROOT/build/something.js, and that the iframe
  // HTML is in $ROOT/index.html.
  //
  // E.g: /vrview/2.0/build/vrview.min.js => /vrview/2.0/index.html.
  var path = CURRENT_SCRIPT_SRC;
  var split = path.split('/');
  var rootSplit = split.slice(0, split.length - 2);
  var rootPath = rootSplit.join('/');
  return rootPath + '/index.html';
};

Player.prototype.getDirName_ = function() {
  var path = window.location.pathname;
  path = path.substring(0, path.lastIndexOf('/'));
  return location.protocol + '//' + location.host + path;
};

/**
 * Make all of the URLs inside contentInfo absolute instead of relative.
 */
Player.prototype.absolutifyPaths_ = function(contentInfo) {
  var dirName = this.getDirName_();
  var urlParams = ['image', 'preview', 'video'];

  for (var i = 0; i < urlParams.length; i++) {
    var name = urlParams[i];
    var path = contentInfo[name];
    if (path && Util.isPathAbsolute(path)) {
      var absolute = Util.relativeToAbsolutePath(dirName, path);
      contentInfo[name] = absolute;
      //console.log('Converted to absolute: %s', absolute);
    }
  }
};

module.exports = Player;
<|endoftext|>


<commit_before>export async function get () {
  return /* await */ this.getPlugins()
}

get.description = 'returns a list of all installed plugins'

get.permission = 'admin'

// -------------------------------------------------------------------

export async function configure ({ id, configuration }) {
  await this.configurePlugin(id, configuration)
}

configure.description = 'sets the configuration of a plugin'

configure.params = {
  id: {
    type: 'string'
  },
  configuration: {}
}

configure.permission = 'admin'

// -------------------------------------------------------------------

export async function disableAutoload ({ id }) {
  await this.disablePluginAutoload(id)
}

disableAutoload.description = ''

disableAutoload.params = {
  id: {
    type: 'string'
  }
}

disableAutoload.permission = 'admin'

// -------------------------------------------------------------------

export async function enableAutoload ({ id }) {
  await this.enablePluginAutoload(id)
}

enableAutoload.description = 'enables a plugin, allowing it to be loaded'

enableAutoload.params = {
  id: {
    type: 'string'
  }
}

enableAutoload.permission = 'admin'

// -------------------------------------------------------------------

export async function load ({ id }) {
  await this.loadPlugin(id)
}

load.description = 'loads a plugin'

load.params = {
  id: {
    type: 'string'
  }
}

load.permission = 'admin'

// -------------------------------------------------------------------

export async function unload ({ id }) {
  await this.unloadPlugin(id)
}

unload.description = 'unloads a plugin'

unload.params = {
  id: {
    type: 'string'
  }
}

unload.permission = 'admin'

// -------------------------------------------------------------------

export async function purgeConfiguration ({ id }) {
  await this.purgePluginConfiguration(id)
}

purgeConfiguration.description = 'removes a plugin configuration'

purgeConfiguration.params = {
  id: {
    type: 'string'
  }
}

purgeConfiguration.permission = 'admin'

// ---------------------------------------------------------------------

export async function test ({ id, data }) {
  await this.testPlugin(id, data)
}

test.description = 'Test a plugin with its current configuration'

test.params = {
  id: {
    type: 'string'
  },
  data: {}
}

test.permission = 'admin'

// ---------------------------------------------------------------------
<commit_msg>fix(plugin.test): data param is optional (#451)<commit_after>export async function get () {
  return /* await */ this.getPlugins()
}

get.description = 'returns a list of all installed plugins'

get.permission = 'admin'

// -------------------------------------------------------------------

export async function configure ({ id, configuration }) {
  await this.configurePlugin(id, configuration)
}

configure.description = 'sets the configuration of a plugin'

configure.params = {
  id: {
    type: 'string'
  },
  configuration: {}
}

configure.permission = 'admin'

// -------------------------------------------------------------------

export async function disableAutoload ({ id }) {
  await this.disablePluginAutoload(id)
}

disableAutoload.description = ''

disableAutoload.params = {
  id: {
    type: 'string'
  }
}

disableAutoload.permission = 'admin'

// -------------------------------------------------------------------

export async function enableAutoload ({ id }) {
  await this.enablePluginAutoload(id)
}

enableAutoload.description = 'enables a plugin, allowing it to be loaded'

enableAutoload.params = {
  id: {
    type: 'string'
  }
}

enableAutoload.permission = 'admin'

// -------------------------------------------------------------------

export async function load ({ id }) {
  await this.loadPlugin(id)
}

load.description = 'loads a plugin'

load.params = {
  id: {
    type: 'string'
  }
}

load.permission = 'admin'

// -------------------------------------------------------------------

export async function unload ({ id }) {
  await this.unloadPlugin(id)
}

unload.description = 'unloads a plugin'

unload.params = {
  id: {
    type: 'string'
  }
}

unload.permission = 'admin'

// -------------------------------------------------------------------

export async function purgeConfiguration ({ id }) {
  await this.purgePluginConfiguration(id)
}

purgeConfiguration.description = 'removes a plugin configuration'

purgeConfiguration.params = {
  id: {
    type: 'string'
  }
}

purgeConfiguration.permission = 'admin'

// ---------------------------------------------------------------------

export async function test ({ id, data }) {
  await this.testPlugin(id, data)
}

test.description = 'Test a plugin with its current configuration'

test.params = {
  id: {
    type: 'string'
  },
  data: {
    optional: true
  }
}

test.permission = 'admin'

// ---------------------------------------------------------------------
<|endoftext|>


<commit_before>const Koa = require('koa');
const convert = require('koa-convert');
const Router = require('koa-better-router');
const bodyParser = require('koa-better-body');
const router = Router({ prefix: '/api' }).loadMethods();
const logger = require('./logger');
const userAPI = require('./user');
const groupAPI = require('./group');
const tagAPI = require('./tag');
const notificationAPI = require('./notification');
const templateAPI = require('./template');
const webhookAPI = require('./webhook');
const koaJsend = require('./middleware/jsend');

const app = new Koa();

logger.info('Starting Notification Microservice...');

router.post('user', userAPI.createSchema, userAPI.create);
router.get('user/:id', userAPI.get);
router.put('user/:id', userAPI.updateSchema, userAPI.update);
router.delete('user/:id', userAPI.delete);
router.put('user/:id/group/:group_name', userAPI.addToGroup);
router.delete('user/:id/group/:group_name', userAPI.removeFromGroup);
router.put('user/:id/tag/:tag_name', userAPI.addTag);
router.delete('user/:id/tag/:tag_name', userAPI.removeTag);

router.get('group/:name', groupAPI.get);
router.delete('group/:user_id/:group_name', groupAPI.delete);

router.get('tag/:name', tagAPI.get);
router.delete('tag/:user_id/:tag_name', tagAPI.delete);

router.get('notification/sent', notificationAPI.getSent);
router.get('notification/unsent', notificationAPI.getUnsent);

router.post('notification', notificationAPI.createSchema, notificationAPI.create);
router.get('notification/:id', notificationAPI.get);
router.put('notification/:id', notificationAPI.updateSchema, notificationAPI.update);
router.delete('notification/:id', notificationAPI.delete);

router.post('template', templateAPI.create);
router.get('template/:id', templateAPI.get);
router.put('template/:id', templateAPI.update);
router.delete('template/:id', templateAPI.delete);

router.post('webhook', webhookAPI.createSchema, webhookAPI.create);
router.get('webhook', webhookAPI.get);
router.get('webhook/:url', webhookAPI.getOne)
router.put('webhook/:url', webhookAPI.update);
router.delete('webhook/:url', webhookAPI.delete);

router.get('ping', async ctx => ctx.success({ time: Math.floor(Date.now() / 1000) }));

/** Parse body and inject body it in ctx.request.body **/
app.use(convert(bodyParser({ fields: 'body' })));

/** Inject jsend formatter to ctx **/
app.use(koaJsend());

/** Catch and format Internal Server Errors **/
app.use(async function onServerError(ctx, next) {
  try {
    await next();
  } catch (e) {
    logger.error('[Internal Server Error]', e);
    ctx.response.status = 500;
    ctx.error('Internal Server Error');
  }
});

/** Catch and format validation errors **/
app.use(async function onValidationError(ctx, next) {
  try {
    await next();
  } catch (error) {
    if (!error.isJoi) {
      throw error;
    }
    logger.info('[Validation Error]', error.details);

    const formatedMessage = error.details.reduce((acc, item) => {
      acc[item.path] = item.message;
      return acc;
    }, {});

    ctx.response.status = 400;
    ctx.fail(formatedMessage);
  }
});

app.use(router.middleware());

/** Async version of app.listen **/
app.asyncListen = port => {
  return new Promise((resolve, reject) => {
    const server = app.listen(port, error => {
      if (error) {
        reject(error);
        return;
      }
      resolve(server);
    });
  });
};

module.exports = app;
<commit_msg>forgot to change the delete tag and delete group server routes<commit_after>const Koa = require('koa');
const convert = require('koa-convert');
const Router = require('koa-better-router');
const bodyParser = require('koa-better-body');
const router = Router({ prefix: '/api' }).loadMethods();
const logger = require('./logger');
const userAPI = require('./user');
const groupAPI = require('./group');
const tagAPI = require('./tag');
const notificationAPI = require('./notification');
const templateAPI = require('./template');
const webhookAPI = require('./webhook');
const koaJsend = require('./middleware/jsend');

const app = new Koa();

logger.info('Starting Notification Microservice...');

router.post('user', userAPI.createSchema, userAPI.create);
router.get('user/:id', userAPI.get);
router.put('user/:id', userAPI.updateSchema, userAPI.update);
router.delete('user/:id', userAPI.delete);
router.put('user/:id/group/:group_name', userAPI.addToGroup);
router.delete('user/:id/group/:group_name', userAPI.removeFromGroup);
router.put('user/:id/tag/:tag_name', userAPI.addTag);
router.delete('user/:id/tag/:tag_name', userAPI.removeTag);

router.get('group/:name', groupAPI.get);
router.delete('group/:group_name', groupAPI.delete);

router.get('tag/:name', tagAPI.get);
router.delete('tag/:tag_name', tagAPI.delete);

router.get('notification/sent', notificationAPI.getSent);
router.get('notification/unsent', notificationAPI.getUnsent);

router.post('notification', notificationAPI.createSchema, notificationAPI.create);
router.get('notification/:id', notificationAPI.get);
router.put('notification/:id', notificationAPI.updateSchema, notificationAPI.update);
router.delete('notification/:id', notificationAPI.delete);

router.post('template', templateAPI.create);
router.get('template/:id', templateAPI.get);
router.put('template/:id', templateAPI.update);
router.delete('template/:id', templateAPI.delete);

router.post('webhook', webhookAPI.createSchema, webhookAPI.create);
router.get('webhook', webhookAPI.get);
router.get('webhook/:url', webhookAPI.getOne)
router.put('webhook/:url', webhookAPI.update);
router.delete('webhook/:url', webhookAPI.delete);

router.get('ping', async ctx => ctx.success({ time: Math.floor(Date.now() / 1000) }));

/** Parse body and inject body it in ctx.request.body **/
app.use(convert(bodyParser({ fields: 'body' })));

/** Inject jsend formatter to ctx **/
app.use(koaJsend());

/** Catch and format Internal Server Errors **/
app.use(async function onServerError(ctx, next) {
  try {
    await next();
  } catch (e) {
    logger.error('[Internal Server Error]', e);
    ctx.response.status = 500;
    ctx.error('Internal Server Error');
  }
});

/** Catch and format validation errors **/
app.use(async function onValidationError(ctx, next) {
  try {
    await next();
  } catch (error) {
    if (!error.isJoi) {
      throw error;
    }
    logger.info('[Validation Error]', error.details);

    const formatedMessage = error.details.reduce((acc, item) => {
      acc[item.path] = item.message;
      return acc;
    }, {});

    ctx.response.status = 400;
    ctx.fail(formatedMessage);
  }
});

app.use(router.middleware());

/** Async version of app.listen **/
app.asyncListen = port => {
  return new Promise((resolve, reject) => {
    const server = app.listen(port, error => {
      if (error) {
        reject(error);
        return;
      }
      resolve(server);
    });
  });
};

module.exports = app;
<|endoftext|>


<commit_before>import { Router } from 'express'
var PythonShell = require('python-shell')

export default ({ config, db }) => {
  let router = Router()

  router.post('/', async ({ body }, res) => {
    try {
      var port = body.port
      var mode = body.mode
      var brix = body.brix
      var rotation = 50
      var total = brix * 211
      var rotations = total / rotation

      var options = {
        mode: 'text',
        pythonOptions: ['-u'],
        scriptPath: '/home/pi/Desktop/pi2/bioreator-api/scripts',
        args: [port]
      }
      for (var index = 0; index < rotations; index++) {
        PythonShell.run('turn_' + mode + '.py', options, function (err, results) {
          if (err) throw err
          // results is an array consisting of messages collected during execution
          console.log('results: %j', results)
        })
      }
      res.json({teste: 'Açucar adicionado com sucesso.'})
    } catch (err) {
      res.status(404).json({ error: err.name + ': ' + err.message })
    }
  })

  return router
}
<commit_msg>Update script call<commit_after>import { Router } from 'express'
var PythonShell = require('python-shell')

export default ({ config, db }) => {
  let router = Router()

  router.post('/', async ({ body }, res) => {
    try {
      var port = body.port
      var mode = body.mode

      var options = {
        mode: 'text',
        pythonOptions: ['-u'],
        scriptPath: '/home/pi/Desktop/pi2/bioreator-api/scripts',
        args: [port]
      }
      PythonShell.run('turn_' + mode + '.py', options, function (err, results) {
        if (err) throw err
        // results is an array consisting of messages collected during execution
        console.log('results: %j', results)
      })
      res.json({teste: 'Componente acionado com sucesso.'})
    } catch (err) {
      res.status(404).json({ error: err.name + ': ' + err.message })
    }
  })

  router.post('/sugar', async ({ body }, res) => {
    try {
      var port = body.port
      var brix = body.brix
      var rotation = 50
      var total = brix * 211
      var rotations = total / rotation

      var options = {
        mode: 'text',
        pythonOptions: ['-u'],
        scriptPath: '/home/pi/Desktop/pi2/bioreator-api/scripts',
        args: [port]
      }
      for (var index = 0; index < rotations; index++) {
        PythonShell.run('turn_on_and_off.py', options, function (err, results) {
          if (err) throw err
          // results is an array consisting of messages collected during execution
          console.log('results: %j', results)
        })
      }
      res.json({teste: 'Açucar adicionado com sucesso.'})
    } catch (err) {
      res.status(404).json({ error: err.name + ': ' + err.message })
    }
  })

  return router
}
<|endoftext|>


<commit_before>/**
 * Created by Abdellatif on 1/9/2017.
 */
var React = require('react');
var ReactDOM = require('react-dom');
import Paper from 'material-ui/Paper'
import {Card, CardActions, CardHeader, CardMedia, CardTitle, CardText} from 'material-ui/Card';
import FlatButton from 'material-ui/FlatButton';

export default class Events extends React.Component{

    constructor(props) {
        super(props);
        this.state = {
            events: [{
                id: 1,
                title: 'event 1',
                type: 'Social',
                picture: '',
                dayAndTime: 'Tuesday at 2:30pm',
                locationAndDate: 'BBQ pit - 1/9/2017',
                description: 'lorem ipsum loves me'
            },
                {
                    id: 2,
                    type: 'Social',
                    picture: '',
                    day: '',
                    time: '',
                    location: '',
                },
                {
                    id: 3,
                    type: 'Social',
                    picture: '',
                    day: '',
                    time: '',
                    location: '',
                },
            ]
        }
    }

    render() {

        const archiveStyle = {
            marginTop: 20,
        };

        const titleStyle = {
            fontSize: '160%',
            textTransform: 'uppercase'
        };

        const titleStyle2 = {
            fontSize: '120%',
        };

        const subtitleStyle = {
            color: '#ababab'
        };

        const imgStyle = {
            width: '100%'
        };

        const cardStyle = {
            textAlign: 'left',
        };

        const cardTextStyle = {
            // color: '#000',
        };

        const cardTextExpanded = false;

        var events = this.state.events.map(event =>

                <Card style={cardStyle}>
                    <CardHeader
                        title={event.title} titleStyle={titleStyle}
                        subtitle={event.type} subtitleStyle={subtitleStyle}
                        actAsExpander={true}
                        showExpandableButton={true}
                    />

                    <CardText style={cardTextStyle} expandable={true}>
                        {event.description}
                    </CardText>
                    <CardTitle title={event.dayAndTime} subtitle={event.locationAndDate} titleStyle={titleStyle2} subtitleStyle={subtitleStyle} />
                    <CardActions>
                        <FlatButton label="Description" primary={true}/>
                        <FlatButton label="RSVP" secondary={true}/>
                    </CardActions>
                </Card>

        );

        return (
            <Paper className="section" rounded={false} zDepth={1} id="events">

EVENTS

                    {events}

                <FlatButton label="Events Archive" style={archiveStyle}/>
            </Paper>
        );
    }
};

<commit_msg>get firebase to load events<commit_after>/**
 * Created by Abdellatif on 1/9/2017.
 */
var React = require('react');
var ReactDOM = require('react-dom');
var firebase = require('firebase');
import Paper from 'material-ui/Paper'
import {Card, CardActions, CardHeader, CardMedia, CardTitle, CardText} from 'material-ui/Card';
import FlatButton from 'material-ui/FlatButton';

export default class Events extends React.Component{

    /*
     const aboutRef = firebase.database().ref('About');
     aboutRef.on('value', snap => {
     this.setState({
     about: snap.val()
     });
     })
     */
    constructor(props) {
        super(props);
        var database = firebase.database();
        var eventsRef = database.ref().root;
        eventsRef.on('value', snap => {
        console.log(snap.val())
        })
        console.log(eventsRef);
        this.state = {
            events: [{
                id: 1,
                title: 'event 1',
                type: 'Social',
                pictureURL: '',
                dayAndTime: 'Tuesday at 2:30pm',
                locationAndDate: 'BBQ pit - 1/9/2017',
                description: 'lorem ipsum loves me'
            },
                {
                    id: 2,
                    type: 'Social',
                    picture: '',
                    day: '',
                    time: '',
                    location: '',
                },
                {
                    id: 3,
                    type: 'Social',
                    pictureURL: '',
                    day: '',
                    time: '',
                    location: '',
                },
            ]
        }
    }

    render() {

        const archiveStyle = {
            marginTop: 20,
        };

        const titleStyle = {
            fontSize: '160%',
            textTransform: 'uppercase'
        };

        const titleStyle2 = {
            fontSize: '120%',
        };

        const subtitleStyle = {
            color: '#ababab'
        };

        const imgStyle = {
            width: '100%'
        };

        const cardStyle = {
            textAlign: 'left',
        };

        const cardTextStyle = {
            // color: '#000',
        };

        const cardTextExpanded = false;

        var events = this.state.events.map(event =>

                <Card style={cardStyle}>
                    <CardHeader
                        title={event.title} titleStyle={titleStyle}
                        subtitle={event.type} subtitleStyle={subtitleStyle}
                        actAsExpander={true}
                        showExpandableButton={true}
                    />

                    <CardText style={cardTextStyle} expandable={true}>
                        {event.description}
                    </CardText>
                    <CardTitle title={event.dayAndTime} subtitle={event.locationAndDate} titleStyle={titleStyle2} subtitleStyle={subtitleStyle} />
                    <CardActions>
                        <FlatButton label="Description" primary={true}/>
                        <FlatButton label="RSVP" secondary={true}/>
                    </CardActions>
                </Card>

        );

        return (
            <Paper className="section" rounded={false} zDepth={1} id="events">

EVENTS

                    {events}

                <FlatButton label="Events Archive" style={archiveStyle}/>
            </Paper>
        );
    }
};

<|endoftext|>


<commit_before>/** File: asi-github.js
 * asi-github
 *
 * Authors:
 *   - jmgoncalves
 */

/**
 *  REQUIRES
 */

var http = require('http');
var https = require('https');
var url = require('url');

/**
 *  CONSTANTS
 */

var PROCESS_NAME = 'asi-github';
var DEFAULT_PORT = 1337;
var USAGE_MESSAGE = 'Usage: http://node.jmgoncalv.es/<username> (e.g. http://node.jmgoncalv.es/jmgoncalves)';

/**
 *  HTTP HELPER FUNCTIONS
 *
 *  Functions for help querying the GitHub API
 */

/** Function: buildRequestOptions
 *  Builds the http.request options object for the target URL, taking in account proxy settings
 *
 *  Parameters:
 *   (String) targetUrl - target URL, enconding the endpoint of the HTTPS request
 *  Returns:
 *   (Object) options object for sending an HTTPS request to the target URL
 */
var buildRequestOptions = function(targetUrl) {
	timestampsDate = new Date();
	console.log('['+timestampsDate.toISOString()+'] Building HTTPS request for '+targetUrl);

	var parsedUrl = url.parse(targetUrl);

	var request = {
		headers: {'User-Agent': PROCESS_NAME},
		method: 'GET',
		hostname: parsedUrl.hostname,
		port: 443,
		path: parsedUrl.path
	}

	return request;
};

/** Function: getFromSource
 *  Requests an endpoint via HTTPS and calls the callback function with the response data as parameter
 *
 *  Parameters:
 *   (Object) requestOptions - options object, describing the endpoint of the HTTPS request
 *   (Function) callback - function to handle the HTTPS response data
 */
var getFromSource = function(requestOptions, callback) {
	var req = https.request(requestOptions, function(res) {
	  res.setEncoding('utf8');
	  var responseData = '';

		res.on('data', function (chunk) {
	    responseData = responseData + chunk;
	  });

	  res.on('end', function () {
	    callback(responseData);
	  });
	});

	req.on('error', function(e) {
	  console.log('Problem with request: ' + e.message);
	});

  req.end();
};

/**
 *  LOGIC
 *
 *  App Logic
 */

 /** Function: top5
  *	 Sorts the repositories by size and returns the top5
  *
  *  Parameters:
  *   (http.IncomingMessage) req - Incomming request to be handled
  *   (http.ServerResponse) res - Response to be returned
  */
var top5 = function(reposJson) {
	reposJson.sort(function(a,b){
	  return b.size-a.size;
	});
	return reposJson.slice(0,5);
}

/**
 *  MAIN
 *
 *  Main part of the application, where the main HTTP server function and the application intialization are defined
 */

/** Function: main
 *  Handles incomming requests, calls the logic function and responds
 *
 *  Parameters:
 *   (http.IncomingMessage) req - Incomming request to be handled
 *   (http.ServerResponse) res - Response to be returned
 */
var main = function (req, res) {
	timestampsDate = new Date();
	console.log('['+timestampsDate.toISOString()+'] Received '+req.url+' request from '+req.connection.remoteAddress);

	var githubUsername = url.parse(req.url).pathname.slice(1,req.url.length);

	if (githubUsername.length>0) {
		var requestOptions = buildRequestOptions('https://api.github.com/users/'+githubUsername+'/repos');
		getFromSource(requestOptions, function(responseData) {
			var repos = JSON.parse(responseData);
			var topRepos = top5(repos);
			res.writeHead(200, {'Content-Type': 'application/json'});
			res.end(JSON.stringify(topRepos));
		});
	} else {
		res.writeHead(200);
		res.end(USAGE_MESSAGE);
	}
};

/** Application Init
 *
 *  Renames process
 *  Aquires HTTP Proxy from env, if configured
 *  Aquires port setting from arguments
 *  Starts listening for HTTP requests
 *  Outputs configuration
 */

process.title = PROCESS_NAME;

var timestampsDate = new Date();

var port = DEFAULT_PORT;
if (process.argv.length>2) {
	port = parseInt(process.argv[2],10);
	if (isNaN(port)) {
		port = DEFAULT_PORT;
		console.log('['+timestampsDate.toISOString()+'] Bad port supplied: "'+process.argv[2]+'" - using default...');
	}
}

http.createServer(main).listen(port);
console.log('['+timestampsDate.toISOString()+'] Server running at port '+port+'...');
<commit_msg>protect against bad handles<commit_after>/** File: asi-github.js
 * asi-github
 *
 * Authors:
 *   - jmgoncalves
 */

/**
 *  REQUIRES
 */

var http = require('http');
var https = require('https');
var url = require('url');

/**
 *  CONSTANTS
 */

var PROCESS_NAME = 'asi-github';
var DEFAULT_PORT = 1337;
var USAGE_MESSAGE = 'Usage: http://node.jmgoncalv.es/<username> (e.g. http://node.jmgoncalv.es/jmgoncalves)';

/**
 *  HTTP HELPER FUNCTIONS
 *
 *  Functions for help querying the GitHub API
 */

/** Function: buildRequestOptions
 *  Builds the http.request options object for the target URL, taking in account proxy settings
 *
 *  Parameters:
 *   (String) targetUrl - target URL, enconding the endpoint of the HTTPS request
 *  Returns:
 *   (Object) options object for sending an HTTPS request to the target URL
 */
var buildRequestOptions = function(targetUrl) {
	timestampsDate = new Date();
	console.log('['+timestampsDate.toISOString()+'] Building HTTPS request for '+targetUrl);

	var parsedUrl = url.parse(targetUrl);

	var request = {
		headers: {'User-Agent': PROCESS_NAME},
		method: 'GET',
		hostname: parsedUrl.hostname,
		port: 443,
		path: parsedUrl.path
	}

	return request;
};

/** Function: getFromSource
 *  Requests an endpoint via HTTPS and calls the callback function with the response data as parameter
 *
 *  Parameters:
 *   (Object) requestOptions - options object, describing the endpoint of the HTTPS request
 *   (Function) callback - function to handle the HTTPS response data
 */
var getFromSource = function(requestOptions, callback) {
	var req = https.request(requestOptions, function(res) {
	  res.setEncoding('utf8');
	  var responseData = '';

		res.on('data', function (chunk) {
	    responseData = responseData + chunk;
	  });

	  res.on('end', function () {
	    callback(responseData);
	  });
	});

	req.on('error', function(e) {
	  console.log('Problem with request: ' + e.message);
	});

  req.end();
};

/**
 *  LOGIC
 *
 *  App Logic
 */

 /** Function: top5
  *	 Sorts the repositories by size and returns the top5
  *
  *  Parameters:
  *   (http.IncomingMessage) req - Incomming request to be handled
  *   (http.ServerResponse) res - Response to be returned
  */
var top5 = function(reposJson) {
	reposJson.sort(function(a,b){
	  return b.size-a.size;
	});
	return reposJson.slice(0,5);
}

/**
 *  MAIN
 *
 *  Main part of the application, where the main HTTP server function and the application intialization are defined
 */

/** Function: main
 *  Handles incomming requests, calls the logic function and responds
 *
 *  Parameters:
 *   (http.IncomingMessage) req - Incomming request to be handled
 *   (http.ServerResponse) res - Response to be returned
 */
var main = function (req, res) {
	timestampsDate = new Date();
	console.log('['+timestampsDate.toISOString()+'] Received '+req.url+' request from '+req.connection.remoteAddress);

	var githubUsername = url.parse(req.url).pathname.slice(1,req.url.length);

	if (githubUsername.length>0) {
		var requestOptions = buildRequestOptions('https://api.github.com/users/'+githubUsername+'/repos');
		getFromSource(requestOptions, function(responseData) {
			var repos = JSON.parse(responseData);
			res.writeHead(200, {'Content-Type': 'application/json'});

			if (repos.constructor === Array) {
				// got array from GitHub - handle normal case
				res.end(JSON.stringify(top5(repos)));
			} else {
				// forward the object GitHub returned
				res.end(JSON.stringify(repos));
			}
		});
	} else {
		res.writeHead(200);
		res.end(USAGE_MESSAGE);
	}
};

/** Application Init
 *
 *  Renames process
 *  Aquires HTTP Proxy from env, if configured
 *  Aquires port setting from arguments
 *  Starts listening for HTTP requests
 *  Outputs configuration
 */

process.title = PROCESS_NAME;

var timestampsDate = new Date();

var port = DEFAULT_PORT;
if (process.argv.length>2) {
	port = parseInt(process.argv[2],10);
	if (isNaN(port)) {
		port = DEFAULT_PORT;
		console.log('['+timestampsDate.toISOString()+'] Bad port supplied: "'+process.argv[2]+'" - using default...');
	}
}

http.createServer(main).listen(port);
console.log('['+timestampsDate.toISOString()+'] Server running at port '+port+'...');
<|endoftext|>


<commit_before>/*
 * Copyright 2017 SideeX committers
 *
 *  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.
 *
 */

import browser from "webextension-polyfill";

let panelId = undefined;

function openPage() {
  const getContentWindowInfo = browser.windows.getLastFocused();
  const getSideexWindowInfo = browser.windows.create({
    url: browser.extension.getURL("assets/index.html"),
    type: "popup",
    height: 730,
    width: 480
  });

  Promise.all([getContentWindowInfo, getSideexWindowInfo])
    .then(function(windowInfo) {
      console.log("get the window info");
      let contentWindowInfo = windowInfo[0];
      let sideexWindowInfo = windowInfo[1];
      console.log("contentWindowInfo Id:" + contentWindowInfo.id);
      console.log("contentWindowInfo:", contentWindowInfo);
      console.log("sideexWindowInfo Id:" + sideexWindowInfo.id);
      console.log("sideexWindowInfo:", sideexWindowInfo);
      return new Promise(function(resolve, reject) {
        let count = 0;
        let interval = setInterval(function() {
          if (count > 100) {
            reject("SideeX editor has no response");
            clearInterval(interval);
          }

          browser.tabs.query({
            active: true,
            windowId: sideexWindowInfo.id
          }).then(function(tabs) {
            if (tabs.length != 1) {
              count++;
              return;
            }
            let sideexTabInfo = tabs[0];
            if (sideexTabInfo.status == "loading") {
              count++;
              return;
            } else {
              console.log("SideeX has been fully loaded");
              resolve(windowInfo);
              clearInterval(interval);
            }
          });
        }, 200);
      });
    }).then(passWindowId)
    .catch(function(e) {
      console.error(e);
    });

  browser.contextMenus.create({
    id: "verifyText",
    title: "verifyText",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });
  browser.contextMenus.create({
    id: "verifyTitle",
    title: "verifyTitle",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });
  browser.contextMenus.create({
    id: "assertText",
    title: "assertText",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });
  browser.contextMenus.create({
    id: "assertTitle",
    title: "assertTitle",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });
  browser.contextMenus.create({
    id: "storeText",
    title: "storeText",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });
  browser.contextMenus.create({
    id: "storeTitle",
    title: "storeTitle",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });

}

browser.browserAction.onClicked.addListener(openPage);

function disconnectAllTabs(tabs) {
  for (let tab of tabs) {
    browser.tabs.sendMessage(tab.id, { active: false });
  }
}

function queryError(error) {
  console.error(`Error: ${error}`);
}

browser.windows.onRemoved.addListener(function(windowId) {
  if (windowId === panelId) {
    console.log("Editor has closed");
    const querying = browser.tabs.query({ url: "<all_urls>" });
    querying.then(disconnectAllTabs, queryError);
    panelId = undefined;
  }

  browser.contextMenus.removeAll();
});

function passWindowId(windowInfo){
  let contentWindowInfo = windowInfo[0];
  let sideexWindowInfo = windowInfo[1];
  let contentWindowId = contentWindowInfo.id;
  let sideexTabId = sideexWindowInfo.tabs[0].id;
  let sideexWindowId = sideexWindowInfo.id;

  return browser.tabs.sendMessage(sideexTabId, {
    selfWindowId: sideexWindowId,
    commWindowId: contentWindowId
  });
}

let port;
browser.contextMenus.onClicked.addListener(function(info) {
  port.postMessage({ cmd: info.menuItemId });
});

browser.runtime.onConnect.addListener(function(m) {
  port = m;
});
<commit_msg>resize the popup again<commit_after>/*
 * Copyright 2017 SideeX committers
 *
 *  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.
 *
 */

import browser from "webextension-polyfill";

let panelId = undefined;

function openPage() {
  const getContentWindowInfo = browser.windows.getLastFocused();
  const getSideexWindowInfo = browser.windows.create({
    url: browser.extension.getURL("assets/index.html"),
    type: "popup",
    height: 930,
    width: 600
  });

  Promise.all([getContentWindowInfo, getSideexWindowInfo])
    .then(function(windowInfo) {
      console.log("get the window info");
      let contentWindowInfo = windowInfo[0];
      let sideexWindowInfo = windowInfo[1];
      console.log("contentWindowInfo Id:" + contentWindowInfo.id);
      console.log("contentWindowInfo:", contentWindowInfo);
      console.log("sideexWindowInfo Id:" + sideexWindowInfo.id);
      console.log("sideexWindowInfo:", sideexWindowInfo);
      return new Promise(function(resolve, reject) {
        let count = 0;
        let interval = setInterval(function() {
          if (count > 100) {
            reject("SideeX editor has no response");
            clearInterval(interval);
          }

          browser.tabs.query({
            active: true,
            windowId: sideexWindowInfo.id
          }).then(function(tabs) {
            if (tabs.length != 1) {
              count++;
              return;
            }
            let sideexTabInfo = tabs[0];
            if (sideexTabInfo.status == "loading") {
              count++;
              return;
            } else {
              console.log("SideeX has been fully loaded");
              resolve(windowInfo);
              clearInterval(interval);
            }
          });
        }, 200);
      });
    }).then(passWindowId)
    .catch(function(e) {
      console.error(e);
    });

  browser.contextMenus.create({
    id: "verifyText",
    title: "verifyText",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });
  browser.contextMenus.create({
    id: "verifyTitle",
    title: "verifyTitle",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });
  browser.contextMenus.create({
    id: "assertText",
    title: "assertText",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });
  browser.contextMenus.create({
    id: "assertTitle",
    title: "assertTitle",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });
  browser.contextMenus.create({
    id: "storeText",
    title: "storeText",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });
  browser.contextMenus.create({
    id: "storeTitle",
    title: "storeTitle",
    documentUrlPatterns: ["<all_urls>"],
    contexts: ["all"]
  });

}

browser.browserAction.onClicked.addListener(openPage);

function disconnectAllTabs(tabs) {
  for (let tab of tabs) {
    browser.tabs.sendMessage(tab.id, { active: false });
  }
}

function queryError(error) {
  console.error(`Error: ${error}`);
}

browser.windows.onRemoved.addListener(function(windowId) {
  if (windowId === panelId) {
    console.log("Editor has closed");
    const querying = browser.tabs.query({ url: "<all_urls>" });
    querying.then(disconnectAllTabs, queryError);
    panelId = undefined;
  }

  browser.contextMenus.removeAll();
});

function passWindowId(windowInfo){
  let contentWindowInfo = windowInfo[0];
  let sideexWindowInfo = windowInfo[1];
  let contentWindowId = contentWindowInfo.id;
  let sideexTabId = sideexWindowInfo.tabs[0].id;
  let sideexWindowId = sideexWindowInfo.id;

  return browser.tabs.sendMessage(sideexTabId, {
    selfWindowId: sideexWindowId,
    commWindowId: contentWindowId
  });
}

let port;
browser.contextMenus.onClicked.addListener(function(info) {
  port.postMessage({ cmd: info.menuItemId });
});

browser.runtime.onConnect.addListener(function(m) {
  port = m;
});
<|endoftext|>


<commit_before>var notificationID = 0;

$(document).ready(function() {
	checkInstall();
	chrome.contextMenus.create({
		"title": "Download with Real-Debrid",
		"contexts": ["link", "selection"],
		"onclick" : contextClickHandler
	});
});

function contextClickHandler(info){
	if(typeof info.selectionText !== "undefined"){
		selectionHandler(info.selectionText);
	}else if(typeof info.linkUrl !== "undefined"){
		urlHandler(info.linkUrl);
	}
}

function selectionHandler(selection){
	var urls = selection.split(" ");
	var regex = new RegExp(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/);
	$.each(urls, function(index, url){
		if(url.match(regex)){
			urlHandler(url);
		}
	});
}

function urlHandler(url){
	unrestrict(url, function(result){
		if(!result.error){
			download(result);
		}else if(result.error == 1){
			notify("Real-Debrid", "Please login on real-debrid.com");
		}else{
			notify(result.message, url);
		}
	});
}

function download(data){
	var downloadUrl = data.generated_links[0][2];
	if(downloadUrl){
		chrome.tabs.create({
			url: downloadUrl,
			active: false
		});
	}
}

function unrestrict(url, callback) {
	var apiUrl = 'https://real-debrid.com/ajax/unrestrict.php?link=' + url;
	$.ajax(
		{
			type: "GET",
			url: apiUrl,
			dataType: 'json',
			data: {},
			crossDomain: true,
			xhrFields: {
				withCredentials: true
			},
			success: callback,
			error: function (xhr) {
				notify("Real Debrid","Could not reach real-debrid.com");
			}
		}
	);
}

function onInstall() {
	notify("Real Debrid", "Extension installed");
}

function onUpdate() {
	notify("Real Debrid", "Extension updated to version " + getVersion());
}

function getVersion() {
	var details = chrome.app.getDetails();
	return details.version;
}

function checkInstall(){
	var currVersion = getVersion();
	var prevVersion = localStorage['version'];
	if (currVersion != prevVersion) {
		if (typeof prevVersion == 'undefined') {
		  onInstall();
		} else {
		  onUpdate();
		}
		localStorage['version'] = currVersion;
	}
}

function notify(title, text){
	var id = ++notificationID;
	var options = {
		iconUrl: "/icons/icon-128.png",
		type : "basic",
		title: title,
		message: text,
		priority: 1
	};
	chrome.notifications.create("id"+id, options, function(){});
}
<commit_msg>Update background.js<commit_after>/*
Copyright 2014 Jonas Devlieghere

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.
*/

var notificationID = 0;

$(document).ready(function() {
	checkInstall();
	chrome.contextMenus.create({
		"title": "Download with Real-Debrid",
		"contexts": ["link", "selection"],
		"onclick" : contextClickHandler
	});
});

function contextClickHandler(info){
	if(typeof info.selectionText !== "undefined"){
		selectionHandler(info.selectionText);
	}else if(typeof info.linkUrl !== "undefined"){
		urlHandler(info.linkUrl);
	}
}

function selectionHandler(selection){
	var urls = selection.split(" ");
	var regex = new RegExp(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/);
	$.each(urls, function(index, url){
		if(url.match(regex)){
			urlHandler(url);
		}
	});
}

function urlHandler(url){
	unrestrict(url, function(result){
		if(!result.error){
			download(result);
		}else if(result.error == 1){
			notify("Real-Debrid", "Please login on real-debrid.com");
		}else{
			notify(result.message, url);
		}
	});
}

function download(data){
	var downloadUrl = data.generated_links[0][2];
	if(downloadUrl){
		chrome.tabs.create({
			url: downloadUrl,
			active: false
		});
	}
}

function unrestrict(url, callback) {
	var apiUrl = 'https://real-debrid.com/ajax/unrestrict.php?link=' + url;
	$.ajax(
		{
			type: "GET",
			url: apiUrl,
			dataType: 'json',
			data: {},
			crossDomain: true,
			xhrFields: {
				withCredentials: true
			},
			success: callback,
			error: function (xhr) {
				notify("Real Debrid","Could not reach real-debrid.com");
			}
		}
	);
}

function onInstall() {
	notify("Real Debrid", "Extension installed");
}

function onUpdate() {
	notify("Real Debrid", "Extension updated to version " + getVersion());
}

function getVersion() {
	var details = chrome.app.getDetails();
	return details.version;
}

function checkInstall(){
	var currVersion = getVersion();
	var prevVersion = localStorage['version'];
	if (currVersion != prevVersion) {
		if (typeof prevVersion == 'undefined') {
		  onInstall();
		} else {
		  onUpdate();
		}
		localStorage['version'] = currVersion;
	}
}

function notify(title, text){
	var id = ++notificationID;
	var options = {
		iconUrl: "/icons/icon-128.png",
		type : "basic",
		title: title,
		message: text,
		priority: 1
	};
	chrome.notifications.create("id"+id, options, function(){});
}
<|endoftext|>


<commit_before>class Background {
  constructor() {
    this.listeners = {};
    this.lastTab = null

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      if (!message.background) {
        return;
      }
      console.log('Background: got message:', message);

      let readMessage;
      switch (message.action) {
        case 'findAudibleTabs':
          readMessage = this.findAudibleTabs();
          break;
        case 'openPopup':
          readMessage = this.onPopupOpen();
          break;
        case 'closePopup':
          readMessage = this.onPopupClose();
          break;
        default:
          throw new Error(
            `Background got an unexpected action: ${message.action}`);
      }

      readMessage.then(reply => sendResponse(reply))
        .catch(error => {
          console.error('Background: error reading message', error);
        });

      return true;
    });
  }

  onPopupOpen() {
    this.addListeners({
      onUpdated: this.onTabsUpdated,
      onRemoved: this.onTabRemoved,
    });
    return Promise.resolve();
  }

  onPopupClose() {
    this.removeListeners();
    return Promise.resolve();
  }

  sendToPopup(message) {
    return new Promise((resolve, reject) => {
      const id = undefined;
      const options = undefined;
      chrome.runtime.sendMessage(
        id,
        {
          popup: true,
          ...message,
        },
        options,
        (result) => {
          if (chrome.runtime.lastError) {
            console.log(
              'background: got error:', chrome.runtime.lastError);
            reject(chrome.runtime.lastError);
          } else {
            resolve(result);
          }
        }
      );
    });
  }

  visitListeners(visit) {
    Object.keys(this.listeners).forEach(eventName => {
      const callback = this.listeners[eventName];
      if (!callback) {
        throw new Error(
          `eventName "${eventName}" is not a valid listener callback; ` +
          `value=${callback}`);
      }
      const event = chrome.tabs[eventName];
      if (!event) {
        throw new Error(
          `chrome.tabs["${eventName}"] is not a valid event; value=${event}`);
      }
      visit({event, callback});
    });
  }

  addListeners(listeners) {
    this.listeners = listeners;
    this.visitListeners(({event, callback}) => {
      event.addListener(callback);
    });
  }

  removeListeners() {
    this.visitListeners(({event, callback}) => {
      event.removeListener(callback);
    });
  }

  onTabsUpdated = (tabId, changeInfo, tab) => {
    console.log(`background: Tab ${tab.id} was updated`, changeInfo);
    if (this.lastTab.id === tabId) {
      this.lastTab = tab;
    }
    this.sendToPopup({
      action: 'onTabsUpdated',
      data: {tab, changeInfo},
    });
  }

  onTabRemoved = (tabId) => {
    console.log(`background: Tab ${tabId} was removed`);
    if (this.lastTab.id === tabId) {
      this.lastTab = null;
    }
    this.sendToPopup({
      action: 'onTabRemoved',
      data: tabId,
    });
  }

  queryTabs(query) {
    return new Promise((resolve, reject) => {
      chrome.tabs.query(query, tabs => {
        if (chrome.runtime.lastError) {
          return reject(chrome.runtime.lastError);
        }
        resolve(tabs);
      });
    });
  }

  findAudibleTabs = () => {
    return Promise.all([
      this.queryTabs({active: true, currentWindow: true}),
      this.queryTabs({audible: true}),
    ])
      .then(([activeTabs, audibleTabsResult]) => {

        let tabList;
        if (this.lastTab) {
          // Put the last viewed site at the top of the list so you
          // can easily jump between what you're working on and what
          // you're listening to.
          tabList = [
            this.lastTab,
            ...audibleTabsResult.filter(tab => tab.id !== this.lastTab.id)
          ];
        } else {
          tabList = audibleTabsResult;
        }

        this.lastTab = activeTabs[0];

        return tabList;
      })
      .catch((error) => {
        console.log('background: findAudibleTabs: error:', error);
      });
  }

  listen() {
    console.log('background: listening for info about audible websites');
  }
}

const background = new Background();
background.listen();
<commit_msg>Keep inaudible tabs around (in case you just paused the music)<commit_after>class Background {
  constructor() {
    this.listeners = {};
    this.lastTab = null;
    this.tabList = [];

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      if (!message.background) {
        return;
      }
      console.log('Background: got message:', message);

      let readMessage;
      switch (message.action) {
        case 'findAudibleTabs':
          readMessage = this.findAudibleTabs();
          break;
        case 'openPopup':
          readMessage = this.onPopupOpen();
          break;
        case 'closePopup':
          readMessage = this.onPopupClose();
          break;
        default:
          throw new Error(
            `Background got an unexpected action: ${message.action}`);
      }

      readMessage.then(reply => sendResponse(reply))
        .catch(error => {
          console.error('Background: error reading message', error);
        });

      return true;
    });
  }

  onPopupOpen() {
    this.addListeners({
      onUpdated: this.onTabsUpdated,
      onRemoved: this.onTabRemoved,
    });
    return Promise.resolve();
  }

  onPopupClose() {
    this.removeListeners();
    return Promise.resolve();
  }

  sendToPopup(message) {
    return new Promise((resolve, reject) => {
      const id = undefined;
      const options = undefined;
      chrome.runtime.sendMessage(
        id,
        {
          popup: true,
          ...message,
        },
        options,
        (result) => {
          if (chrome.runtime.lastError) {
            console.log(
              'background: got error:', chrome.runtime.lastError);
            reject(chrome.runtime.lastError);
          } else {
            resolve(result);
          }
        }
      );
    });
  }

  visitListeners(visit) {
    Object.keys(this.listeners).forEach(eventName => {
      const callback = this.listeners[eventName];
      if (!callback) {
        throw new Error(
          `eventName "${eventName}" is not a valid listener callback; ` +
          `value=${callback}`);
      }
      const event = chrome.tabs[eventName];
      if (!event) {
        throw new Error(
          `chrome.tabs["${eventName}"] is not a valid event; value=${event}`);
      }
      visit({event, callback});
    });
  }

  addListeners(listeners) {
    this.listeners = listeners;
    this.visitListeners(({event, callback}) => {
      event.addListener(callback);
    });
  }

  removeListeners() {
    this.visitListeners(({event, callback}) => {
      event.removeListener(callback);
    });
  }

  onTabsUpdated = (tabId, changeInfo, tab) => {
    console.log(`background: Tab ${tab.id} was updated`, changeInfo);
    if (this.lastTab.id === tabId) {
      this.lastTab = tab;
    }
    this.tabList = this.tabList.map(
      oldTab => oldTab.id === tab.id ? tab : oldTab);

    this.sendToPopup({
      action: 'onTabsUpdated',
      data: {tab, changeInfo},
    });
  }

  onTabRemoved = (tabId) => {
    console.log(`background: Tab ${tabId} was removed`);
    if (this.lastTab.id === tabId) {
      this.lastTab = null;
    }

    this.tabList = this.tabList.filter(tab => tab.id !== tabId);

    this.sendToPopup({
      action: 'onTabRemoved',
      data: tabId,
    });
  }

  queryTabs(query) {
    return new Promise((resolve, reject) => {
      chrome.tabs.query(query, tabs => {
        if (chrome.runtime.lastError) {
          return reject(chrome.runtime.lastError);
        }
        resolve(tabs);
      });
    });
  }

  findAudibleTabs = () => {
    return Promise.all([
      this.queryTabs({active: true, currentWindow: true}),
      this.queryTabs({audible: true}),
    ])
      .then(([activeTabs, audibleTabs]) => {
        const newTabList = [];
        if (this.lastTab) {
          // Put the last viewed site at the top of the list so you
          // can easily jump between what you're working on and what
          // you're listening to.
          newTabList.push(this.lastTab);
        }

        function addUniqueTabs(tabList) {
          const existingIds = new Set(newTabList.map(tab => tab.id));
          tabList.forEach(tab => {
            if (!existingIds.has(tab.id)) {
              newTabList.push(tab);
            }
          });
        }

        addUniqueTabs(audibleTabs);
        // Keep inaudible tabs around since the music may have just been paused
        addUniqueTabs(this.tabList);

        while (newTabList.length > 10) {
          newTabList.pop();
        }

        this.tabList = newTabList;
        this.lastTab = activeTabs[0];

        return this.tabList;
      })
      .catch((error) => {
        console.log('background: findAudibleTabs: error:', error);
      });
  }

  listen() {
    console.log('background: listening for info about audible websites');
  }
}

const background = new Background();
background.listen();
<|endoftext|>