<commit_before>/*
	WebPlotDigitizer - http://arohatgi.info/WebPlotDigitizer

	Copyright 2010-2014 Ankit Rohatgi <ankitrohatgi@hotmail.com>

	This file is part of WebPlotDigitizer.

    WebPlotDigitizer is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    WebPlotDigitizer is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with WebPlotDigitizer.  If not, see <http://www.gnu.org/licenses/>.

*/

/* Zoomed-in view */
var wpd = wpd || {};
wpd.zoomView = (function() {
    var zCanvas,
        zctx,
        tempCanvas,
        tctx,
        zWindowWidth = 250,
        zWindowHeight = 250,
        $mPosn,
        extendedCrosshair = false,
        pix = [],
        zoomTimeout,
        zoomRatio,
        crosshairColorText = 'black';

    pix[0] = new Array();

    function init() {

        zCanvas = document.getElementById('zoomCanvas');
    	zctx = zCanvas.getContext('2d');
	    tempCanvas = document.createElement('canvas');
        tctx = tempCanvas.getContext('2d');

        $mPosn = document.getElementById('mousePosition');

        zoomRatio = 5;

        drawCrosshair();
    }

    function drawCrosshair() {
        var zCrossHair = document.getElementById("zoomCrossHair");
        var zchCtx = zCrossHair.getContext("2d");

        zCrossHair.width = zCrossHair.width;

        if(crosshairColorText === 'black') {
            zchCtx.strokeStyle = "rgba(0,0,0,1)";
        } else if(crosshairColorText === 'red') {
            zchCtx.strokeStyle = "rgba(255,0,0,1)";
        } else if(crosshairColorText === 'yellow') {
            zchCtx.strokeStyle = "rgba(255,255,0,1)";
        } else {
            zchCtx.strokeStyle = "rgba(0,0,0,1)";
        }

        zchCtx.beginPath();
        zchCtx.moveTo(zWindowWidth/2, 0);
        zchCtx.lineTo(zWindowWidth/2, zWindowHeight);
        zchCtx.moveTo(0, zWindowHeight/2);
        zchCtx.lineTo(zWindowWidth, zWindowHeight/2);
        zchCtx.stroke();
    }

    function setZoomRatio(zratio) {
        zoomRatio = zratio;
    }

    function getZoomRatio() {
        return zoomRatio;
    }

    function getSize() {
         return {
            width: zWindowWidth,
            height: zWindowHeight
        };

    }

    function setZoomImage(imgData, x0, y0, zwidth, zheight) {
        tempCanvas.width = zwidth/zoomRatio;
        tempCanvas.height = zheight/zoomRatio;
        tctx.putImageData(imgData, 0, 0);
        zCanvas.width = zCanvas.width;
        zctx.drawImage(tempCanvas, x0, y0, zwidth, zheight);
    }

    function setCoords(imageX, imageY) {
        if(wpd.appData.isAligned()) {
            var plotData = wpd.appData.getPlotData();
            $mPosn.innerText = plotData.axes.pixelToLiveString(imageX, imageY);
        } else {
            $mPosn.innerText = imageX.toFixed(2) + ', ' + imageY.toFixed(2);
        }
    }

    function showSettingsWindow() {
        document.getElementById('zoom-magnification-value').value = zoomRatio;
        document.getElementById('zoom-crosshair-color-value').value = crosshairColorText;
        wpd.popup.show('zoom-settings-popup');
    }

    function applySettings() {
        zoomRatio = document.getElementById('zoom-magnification-value').value;
        crosshairColorText = document.getElementById('zoom-crosshair-color-value').value;
        drawCrosshair();
        wpd.popup.close('zoom-settings-popup');
    }

    return {
        initZoom: init,
        setZoomImage: setZoomImage,
        setCoords: setCoords,
        setZoomRatio: setZoomRatio,
        getZoomRatio: getZoomRatio,
        getSize: getSize,
        showSettingsWindow: showSettingsWindow,
        applySettings: applySettings
    };
})();

<commit_msg>innerText does not work in Firefox<commit_after>/*
	WebPlotDigitizer - http://arohatgi.info/WebPlotDigitizer

	Copyright 2010-2014 Ankit Rohatgi <ankitrohatgi@hotmail.com>

	This file is part of WebPlotDigitizer.

    WebPlotDigitizer is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    WebPlotDigitizer is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with WebPlotDigitizer.  If not, see <http://www.gnu.org/licenses/>.

*/

/* Zoomed-in view */
var wpd = wpd || {};
wpd.zoomView = (function() {
    var zCanvas,
        zctx,
        tempCanvas,
        tctx,
        zWindowWidth = 250,
        zWindowHeight = 250,
        $mPosn,
        extendedCrosshair = false,
        pix = [],
        zoomTimeout,
        zoomRatio,
        crosshairColorText = 'black';

    pix[0] = new Array();

    function init() {

        zCanvas = document.getElementById('zoomCanvas');
    	zctx = zCanvas.getContext('2d');
	    tempCanvas = document.createElement('canvas');
        tctx = tempCanvas.getContext('2d');

        $mPosn = document.getElementById('mousePosition');

        zoomRatio = 5;

        drawCrosshair();
    }

    function drawCrosshair() {
        var zCrossHair = document.getElementById("zoomCrossHair");
        var zchCtx = zCrossHair.getContext("2d");

        zCrossHair.width = zCrossHair.width;

        if(crosshairColorText === 'black') {
            zchCtx.strokeStyle = "rgba(0,0,0,1)";
        } else if(crosshairColorText === 'red') {
            zchCtx.strokeStyle = "rgba(255,0,0,1)";
        } else if(crosshairColorText === 'yellow') {
            zchCtx.strokeStyle = "rgba(255,255,0,1)";
        } else {
            zchCtx.strokeStyle = "rgba(0,0,0,1)";
        }

        zchCtx.beginPath();
        zchCtx.moveTo(zWindowWidth/2, 0);
        zchCtx.lineTo(zWindowWidth/2, zWindowHeight);
        zchCtx.moveTo(0, zWindowHeight/2);
        zchCtx.lineTo(zWindowWidth, zWindowHeight/2);
        zchCtx.stroke();
    }

    function setZoomRatio(zratio) {
        zoomRatio = zratio;
    }

    function getZoomRatio() {
        return zoomRatio;
    }

    function getSize() {
         return {
            width: zWindowWidth,
            height: zWindowHeight
        };

    }

    function setZoomImage(imgData, x0, y0, zwidth, zheight) {
        tempCanvas.width = zwidth/zoomRatio;
        tempCanvas.height = zheight/zoomRatio;
        tctx.putImageData(imgData, 0, 0);
        zCanvas.width = zCanvas.width;
        zctx.drawImage(tempCanvas, x0, y0, zwidth, zheight);
    }

    function setCoords(imageX, imageY) {
        if(wpd.appData.isAligned()) {
            var plotData = wpd.appData.getPlotData();
            $mPosn.innerHTML = plotData.axes.pixelToLiveString(imageX, imageY);
        } else {
            $mPosn.innerHTML = imageX.toFixed(2) + ', ' + imageY.toFixed(2);
        }
    }

    function showSettingsWindow() {
        document.getElementById('zoom-magnification-value').value = zoomRatio;
        document.getElementById('zoom-crosshair-color-value').value = crosshairColorText;
        wpd.popup.show('zoom-settings-popup');
    }

    function applySettings() {
        zoomRatio = document.getElementById('zoom-magnification-value').value;
        crosshairColorText = document.getElementById('zoom-crosshair-color-value').value;
        drawCrosshair();
        wpd.popup.close('zoom-settings-popup');
    }

    return {
        initZoom: init,
        setZoomImage: setZoomImage,
        setCoords: setCoords,
        setZoomRatio: setZoomRatio,
        getZoomRatio: getZoomRatio,
        getSize: getSize,
        showSettingsWindow: showSettingsWindow,
        applySettings: applySettings
    };
})();

<|endoftext|>


<commit_before>// Copyright 2013-2016, University of Colorado Boulder

/**
 * Utility functions for scenery that are specifically useful for Accessibility.
 * These generally pertain to DOM traversal and manipulation.
 *
 * @author Jesse Greenberg
 */

define( function( require ) {
  'use strict';

  // modules
  var scenery = require( 'SCENERY/scenery' );

  // constants
  var NEXT = 'NEXT';
  var PREVIOUS = 'PREVIOUS';

  /**
   * Get all 'element' nodes off the parent element, placing them in an array for easy traversal.  Note that this
   * includes all elements, even those that are 'hidden' or purely for structure.
   *
   * @param  {HTMLElement} domElement - parent whose children will be linearized
   * @return {HTMLElement[]}
   * @private
   */
  function getLinearDOMElements( domElement ) {

    // gets ALL descendant children for the element
    var children = domElement.getElementsByTagName( '*' );

    var linearDOM = [];
    for ( var i = 0; i < children.length; i++ ) {

      // searching for the HTML elemetn nodes
      if ( children[ i ].nodeType === HTMLElement.ELEMENT_NODE ) {
        linearDOM[ i ] = ( children[ i ] );
      }
    }
    return linearDOM;
  }

  /**
   * Verify that an id is unique in the document, by searching through the id's of all HTML elements in the body.
   *
   * @param  {string} id
   * @return {boolean}
   */
  function verifyUniqueId( id ) {
    var unique = true;

    // search through the elements
    var elements = getLinearDOMElements( document.body );
    for ( var i = 0; i < elements.length; i++ ) {
      if ( elements[ i ].id === id ) {
        unique = false;
        break;
      }
    }
    return unique;
  }

  /**
   * Determine if an element is hidden.  An element is considered 'hidden' if it (or any of its ancestors) has the
   * 'hidden' attribute.
   * @private
   *
   * @param {HTMLElement} domElement
   * @return {Boolean}
   */
  function isElementHidden( domElement ) {
    if ( domElement.hidden ) {
      return true;
    }
    else if ( domElement === document.body ) {
      return false;
    }
    else {
      return isElementHidden( domElement.parentElement );
    }
  }

  /**
   * Get the next or previous focusable element in the parallel DOM, relative to this Node's domElement
   * depending on the direction. Useful if you need to set focus dynamically or need to prevent default behavior
   * when focus changes. If no next or previous focusable is found, it returns the currently focused element.
   * This function should not be used directly, use getNextFocusable() or getPreviousFocusable() instead.
   * @private
   *
   * @param {string} direction - direction of traversal, one of 'NEXT' | 'PREVIOUS'
   * @param {HTMLElement} [parentElement] - optional, search will be limited to children of this element
   * @return {HTMLElement}
   */
  function getNextPreviousFocusable( direction, parentElement ) {

    // linearize the document [or the desired parent] for traversal
    var parent = parentElement || document.body;
    var linearDOM = getLinearDOMElements( parent );

    var activeElement = document.activeElement;
    var activeIndex = linearDOM.indexOf( activeElement );
    var delta = direction === NEXT ? +1 : -1;

    // find the next focusable element in the DOM
    var nextIndex = activeIndex + delta;
    var nextFocusable;
    while ( !nextFocusable && nextIndex < linearDOM.length && nextIndex >= 0 ) {
      var nextElement = linearDOM[ nextIndex ];
      nextIndex += delta;

      // continue to next element if this one is meant to be hidden
      if ( isElementHidden( nextElement ) ) {
        continue;
      }

      // if tabindex is greater than -1, the element is focusable so break
      if ( nextElement.tabIndex > -1 ) {
        nextFocusable = nextElement;
        break;
      }
    }

    // if no next focusable is found, return the active DOM element
    return nextFocusable || activeElement;
  }

  var AccessibilityUtil = {

    /**
     * Get the next focusable element. This should very rarely be used.  The next focusable element can almost
     * always be focused automatically with 'Tab'.  However, if the 'Tab' key needs to be emulated this can be
     * helpful. If no next focusable can be found, it will return the currently focused element.
     * @public
     *
     * @param{HTMLElement} [parentElement] - optional, search will be limited to elements under this element
     * @return {HTMLElement}
     */
    getNextFocusable: function( parentElement ) {
      return getNextPreviousFocusable( NEXT, parentElement );
    },

    /**
     * Get the previous focusable element. This should very rarely be used.  The previous focusable element can almost
     * always be found automatically with default 'Shift+Tab' behavior.  However, if the 'Tab' key needs to be emulated
     * this can be helpful.  If no next focusable can be found, it will return the currently focused element.
     * @public
     *
     * @param {HTMLElement} [parentElement] - optional, search will be limited to elements under this parent
     * @return {HTMLElement}
     */
    getPreviousFocusable: function( parentElement ) {
      return getNextPreviousFocusable( PREVIOUS, parentElement );
    },

    /**
     * Generate a random unique id for a DOM element.  After generating
     * a unique id, we verify that the id is not shared with any other id in the
     * document. The return value is a string because the DOM API generally
     * handles id references by string.if
     *
     * @return {string}
     */
    generateHTMLElementId: function() {
      var id;

      var isUnique = false;
      while( !isUnique ) {

        // try a random sequence of values
        id = Math.random().toString().substr( 2, 16 );
        isUnique = verifyUniqueId( id );
      }

      return id;
    }
  };

  scenery.register( 'AccessibilityUtil', AccessibilityUtil );

  return AccessibilityUtil;
} );
<commit_msg>remove unused functions from AccessibilityUtil, see #596<commit_after>// Copyright 2013-2016, University of Colorado Boulder

/**
 * Utility functions for scenery that are specifically useful for Accessibility.
 * These generally pertain to DOM traversal and manipulation.
 *
 * @author Jesse Greenberg
 */

define( function( require ) {
  'use strict';

  // modules
  var scenery = require( 'SCENERY/scenery' );

  // constants
  var NEXT = 'NEXT';
  var PREVIOUS = 'PREVIOUS';

  /**
   * Get all 'element' nodes off the parent element, placing them in an array for easy traversal.  Note that this
   * includes all elements, even those that are 'hidden' or purely for structure.
   *
   * @param  {HTMLElement} domElement - parent whose children will be linearized
   * @return {HTMLElement[]}
   * @private
   */
  function getLinearDOMElements( domElement ) {

    // gets ALL descendant children for the element
    var children = domElement.getElementsByTagName( '*' );

    var linearDOM = [];
    for ( var i = 0; i < children.length; i++ ) {

      // searching for the HTML elemetn nodes
      if ( children[ i ].nodeType === HTMLElement.ELEMENT_NODE ) {
        linearDOM[ i ] = ( children[ i ] );
      }
    }
    return linearDOM;
  }

  /**
   * Determine if an element is hidden.  An element is considered 'hidden' if it (or any of its ancestors) has the
   * 'hidden' attribute.
   * @private
   *
   * @param {HTMLElement} domElement
   * @return {Boolean}
   */
  function isElementHidden( domElement ) {
    if ( domElement.hidden ) {
      return true;
    }
    else if ( domElement === document.body ) {
      return false;
    }
    else {
      return isElementHidden( domElement.parentElement );
    }
  }

  /**
   * Get the next or previous focusable element in the parallel DOM, relative to this Node's domElement
   * depending on the direction. Useful if you need to set focus dynamically or need to prevent default behavior
   * when focus changes. If no next or previous focusable is found, it returns the currently focused element.
   * This function should not be used directly, use getNextFocusable() or getPreviousFocusable() instead.
   * @private
   *
   * @param {string} direction - direction of traversal, one of 'NEXT' | 'PREVIOUS'
   * @param {HTMLElement} [parentElement] - optional, search will be limited to children of this element
   * @return {HTMLElement}
   */
  function getNextPreviousFocusable( direction, parentElement ) {

    // linearize the document [or the desired parent] for traversal
    var parent = parentElement || document.body;
    var linearDOM = getLinearDOMElements( parent );

    var activeElement = document.activeElement;
    var activeIndex = linearDOM.indexOf( activeElement );
    var delta = direction === NEXT ? +1 : -1;

    // find the next focusable element in the DOM
    var nextIndex = activeIndex + delta;
    var nextFocusable;
    while ( !nextFocusable && nextIndex < linearDOM.length && nextIndex >= 0 ) {
      var nextElement = linearDOM[ nextIndex ];
      nextIndex += delta;

      // continue to next element if this one is meant to be hidden
      if ( isElementHidden( nextElement ) ) {
        continue;
      }

      // if tabindex is greater than -1, the element is focusable so break
      if ( nextElement.tabIndex > -1 ) {
        nextFocusable = nextElement;
        break;
      }
    }

    // if no next focusable is found, return the active DOM element
    return nextFocusable || activeElement;
  }

  var AccessibilityUtil = {

    /**
     * Get the next focusable element. This should very rarely be used.  The next focusable element can almost
     * always be focused automatically with 'Tab'.  However, if the 'Tab' key needs to be emulated this can be
     * helpful. If no next focusable can be found, it will return the currently focused element.
     * @public
     *
     * @param{HTMLElement} [parentElement] - optional, search will be limited to elements under this element
     * @return {HTMLElement}
     */
    getNextFocusable: function( parentElement ) {
      return getNextPreviousFocusable( NEXT, parentElement );
    },

    /**
     * Get the previous focusable element. This should very rarely be used.  The previous focusable element can almost
     * always be found automatically with default 'Shift+Tab' behavior.  However, if the 'Tab' key needs to be emulated
     * this can be helpful.  If no next focusable can be found, it will return the currently focused element.
     * @public
     *
     * @param {HTMLElement} [parentElement] - optional, search will be limited to elements under this parent
     * @return {HTMLElement}
     */
    getPreviousFocusable: function( parentElement ) {
      return getNextPreviousFocusable( PREVIOUS, parentElement );
    }

  };

  scenery.register( 'AccessibilityUtil', AccessibilityUtil );

  return AccessibilityUtil;
} );
<|endoftext|>


<commit_before>import {actionBuilder} from '../entity-actions-builder';
import {PENDING, SUCCESS, ERROR} from '../entity-actions-builder';

describe('The actionBuilder', () => {
    describe('when called with wrong parameters', () => {
        it('should throw a type error when called without all parameters', () => {
            expect(() => { actionBuilder()}).to.throw(TypeError,'Cannot read property \'names\' of undefined');
        });
        it('should throw an error when called without a string name parameter', () => {
            const NAMES_MESSAGE = 'ACTION_BUILDER: the names parameter should be a non empty array.';
            expect(() => { actionBuilder({names: undefined})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: 1})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: {}})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: () => {}})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: ''})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: []})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: ['test']})}).to.not.throw(NAMES_MESSAGE);
        });

        it('should throw an error when called without a string name parameter', () => {
            const NAME_MESSAGE = 'ACTION_BUILDER: the names parameter should be made of strings';
            expect(() => { actionBuilder({names: [undefined]})}).to.throw(NAME_MESSAGE);
            expect(() => { actionBuilder({names: [1]})}).to.throw(NAME_MESSAGE);
            expect(() => { actionBuilder({names: [{}]})}).to.throw(NAME_MESSAGE);
            expect(() => { actionBuilder({names: [() => {}]})}).to.throw(NAME_MESSAGE);
            expect(() => { actionBuilder({names: ['']})}).to.throw(NAME_MESSAGE);
            expect(() => { actionBuilder({names: ['test']})}).to.not.throw(NAME_MESSAGE);
        });

        it('should throw an error when called without a string type parameter : load,save,delete,error', () => {
            const TYPE_MESSAGE = 'ACTION_BUILDER: the type parameter should be a string and the value one of these: load,save,delete,error.';
            expect(() => { actionBuilder({names: ['test']})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: undefined})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 1})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: {}})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: () => {}})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: ''})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'nimp'})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load'})}).to.not.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'save'})}).to.not.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'error'})}).to.not.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'delete'})}).to.not.throw(TYPE_MESSAGE);
        });
        it('should throw an error when called without a function returning a Promise service parameter', () => {
            const SERVICE_MESSAGE = 'ACTION_BUILDER: the service parameter should be a function.';
            expect(() => { actionBuilder({names: ['test'], type: 'load'})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: undefined})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: 1})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: 'nimp'})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: {}})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: null})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: () => Promise.resolve({test: 'test'})})}).to.not.throw(SERVICE_MESSAGE);
        });
    })
    describe('when called with right parameters', () => {
        const RESOLVE_VALUE = {testValue: 'tests'};
        const REJECT_VALUE = {error: 'error'};
        const TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_RESOLVE = {names: ['test'], type: 'load', service: () => Promise.resolve(RESOLVE_VALUE)};
        const TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_REJECT = {names: ['test'], type: 'load', service: () => Promise.reject(REJECT_VALUE)};
        const TEST_VALID_ACTION_SAVE_BUILDER_PARAMS_RESOLVE = {names: ['test'], type: 'save', service: () => Promise.resolve(RESOLVE_VALUE)};
        const TEST_VALID_ACTION_SAVE_BUILDER_PARAMS_REJECT = {names: ['test'], type: 'save', service: () => Promise.reject(REJECT_VALUE)};

        it('should return an object with types, creators, action', () => {
            const actionBuilded = actionBuilder(TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_RESOLVE);
            expect(actionBuilded).to.be.an('object');
            expect(actionBuilded).to.include.keys('types', 'creators', 'action');
        });
        describe('The types part of the result', () => {
            it('should return an object with three types with REQUEST, RESPONSE and ERROR', () => {
                const {types: actionBuildedTypes} = actionBuilder(TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_RESOLVE);
                expect(actionBuildedTypes).to.be.an('object');
                expect(actionBuildedTypes).to.include.keys('REQUEST_LOAD_TEST', 'RESPONSE_LOAD_TEST', 'ERROR_LOAD_TEST');
            });
        });
        describe('The action part of the result', () => {
            const {action: actionBuildedLoadResolveAsync} = actionBuilder(TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_RESOLVE);
            const {action: actionBuildedLoadRejectAsync} = actionBuilder(TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_REJECT);
            const {action: actionBuildedSaveResolveAsync} = actionBuilder(TEST_VALID_ACTION_SAVE_BUILDER_PARAMS_RESOLVE);
            const {action: actionBuildedSaveRejectAsync} = actionBuilder(TEST_VALID_ACTION_SAVE_BUILDER_PARAMS_REJECT);

            const CRITERIA = {id: 'test'};
            it('should return a function', () => {
                expect(actionBuildedLoadResolveAsync).to.be.a.function;
                expect(actionBuildedLoadRejectAsync).to.be.a.function;
                expect(actionBuildedSaveResolveAsync).to.be.a.function;
                expect(actionBuildedSaveRejectAsync).to.be.a.function;
            });
            it('when called with a successfull load service should call the response and request action creators', async done => {
                const dispatchSpy = sinon.spy();
                await actionBuildedLoadResolveAsync()(dispatchSpy);
                expect(dispatchSpy).to.have.callCount(2);
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'REQUEST_LOAD_TEST', syncTypeForm: 'request', formKey: undefined, entityPath: 'test', _meta: {status: PENDING, loading: true, saving: false,  error: false}});
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'RESPONSE_LOAD_TEST', payload: RESOLVE_VALUE, formKey: undefined, syncTypeForm: 'response', entityPath: 'test', _meta: {status: SUCCESS, loading: true, saving: false,  error: false}});

                done();
            });
            it('when called with an unsuccessfull load service should call the error action creator', async done => {
                const dispatchSpy = sinon.spy();
                await actionBuildedLoadRejectAsync()(dispatchSpy);
                expect(dispatchSpy).to.have.callCount(2);
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'REQUEST_LOAD_TEST', syncTypeForm: 'request', formKey: undefined, entityPath: 'test', _meta: {status: PENDING, loading: true, saving: false,  error: false}});
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'ERROR_LOAD_TEST', payload: REJECT_VALUE, syncTypeForm: 'error',formKey: undefined,  entityPath: 'test', _meta: {status: ERROR, loading: false, saving: false, error: true}});
                done();
            });
            it('when called with a successfull save service should call the response and request action creators', async done => {
                const dispatchSpy = sinon.spy();
                await actionBuildedSaveResolveAsync()(dispatchSpy);
                expect(dispatchSpy).to.have.callCount(3);
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'REQUEST_SAVE_TEST', syncTypeForm: 'request', formKey: undefined, entityPath: 'test', _meta: {status: PENDING, loading: false, saving: true,  error: false}});
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'RESPONSE_SAVE_TEST', payload: RESOLVE_VALUE,  formKey: undefined,syncTypeForm: 'response', entityPath: 'test', _meta: {status: SUCCESS, loading: false, saving: true, error: false}});
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'PUSH_MESSAGE', message:  {content: 'test.fields.saved', id:"msgId_1", type: 'success'}});
                done();
            });
            it('when called with an unsuccessfull save service should call the error action creator', async done => {
                const dispatchSpy = sinon.spy();
                dispatchSpy.reset();
                await actionBuildedSaveRejectAsync()(dispatchSpy);
                expect(dispatchSpy).to.have.callCount(2);
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'REQUEST_SAVE_TEST',  syncTypeForm: 'request', formKey: undefined, entityPath: 'test', _meta: {status: PENDING, loading: false, saving: true,  error: false}});
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'ERROR_SAVE_TEST', payload: REJECT_VALUE, syncTypeForm: 'error',formKey: undefined,  entityPath: 'test', _meta: {status: ERROR, loading: false, saving: false, error: true}});
                done();
            });
        });
    });
});
<commit_msg>[ActionBuilder] fix tests<commit_after>import {actionBuilder} from '../entity-actions-builder';
import {PENDING, SUCCESS, ERROR} from '../entity-actions-builder';

describe('The actionBuilder', () => {
    describe('when called with wrong parameters', () => {
        it('should throw a type error when called without all parameters', () => {
            expect(() => { actionBuilder()}).to.throw(TypeError,'Cannot read property \'names\' of undefined');
        });
        it('should throw an error when called without a string name parameter', () => {
            const NAMES_MESSAGE = 'ACTION_BUILDER: the names parameter should be a non empty array.';
            expect(() => { actionBuilder({names: undefined})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: 1})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: {}})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: () => {}})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: ''})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: []})}).to.throw(NAMES_MESSAGE);
            expect(() => { actionBuilder({names: ['test']})}).to.not.throw(NAMES_MESSAGE);
        });

        it('should throw an error when called without a string name parameter', () => {
            const NAME_MESSAGE = 'ACTION_BUILDER: the names parameter should be made of strings';
            expect(() => { actionBuilder({names: [undefined]})}).to.throw(NAME_MESSAGE);
            expect(() => { actionBuilder({names: [1]})}).to.throw(NAME_MESSAGE);
            expect(() => { actionBuilder({names: [{}]})}).to.throw(NAME_MESSAGE);
            expect(() => { actionBuilder({names: [() => {}]})}).to.throw(NAME_MESSAGE);
            expect(() => { actionBuilder({names: ['']})}).to.throw(NAME_MESSAGE);
            expect(() => { actionBuilder({names: ['test']})}).to.not.throw(NAME_MESSAGE);
        });

        it('should throw an error when called without a string type parameter : load,save,delete,error', () => {
            const TYPE_MESSAGE = 'ACTION_BUILDER: the type parameter should be a string and the value one of these: load,save,delete,error.';
            expect(() => { actionBuilder({names: ['test']})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: undefined})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 1})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: {}})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: () => {}})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: ''})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'nimp'})}).to.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load'})}).to.not.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'save'})}).to.not.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'error'})}).to.not.throw(TYPE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'delete'})}).to.not.throw(TYPE_MESSAGE);
        });
        it('should throw an error when called without a function returning a Promise service parameter', () => {
            const SERVICE_MESSAGE = 'ACTION_BUILDER: the service parameter should be a function.';
            expect(() => { actionBuilder({names: ['test'], type: 'load'})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: undefined})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: 1})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: 'nimp'})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: {}})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: null})}).to.throw(SERVICE_MESSAGE);
            expect(() => { actionBuilder({names: ['test'], type: 'load', service: () => Promise.resolve({test: 'test'})})}).to.not.throw(SERVICE_MESSAGE);
        });
    })
    describe('when called with right parameters', () => {
        const RESOLVE_VALUE = {testValue: 'tests'};
        const REJECT_VALUE = {error: 'error'};
        const TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_RESOLVE = {names: ['test'], type: 'load', service: () => (Promise.resolve(RESOLVE_VALUE).then(data => ({response: data})))};
        const TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_REJECT = {names: ['test'], type: 'load', service: () => (Promise.reject(REJECT_VALUE).then(data => ({response: data, status: 'ERROR'})))};
        const TEST_VALID_ACTION_SAVE_BUILDER_PARAMS_RESOLVE = {names: ['test'], type: 'save', service: () => (Promise.resolve(RESOLVE_VALUE).then(data => ({response: data})))};
        const TEST_VALID_ACTION_SAVE_BUILDER_PARAMS_REJECT = {names: ['test'], type: 'save', service: () => (Promise.reject(REJECT_VALUE).then(data => ({response: data, status: 'ERROR'})))};

        it('should return an object with types, creators, action', () => {
            const actionBuilded = actionBuilder(TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_RESOLVE);
            expect(actionBuilded).to.be.an('object');
            expect(actionBuilded).to.include.keys('types', 'creators', 'action');
        });
        describe('The types part of the result', () => {
            it('should return an object with three types with REQUEST, RESPONSE and ERROR', () => {
                const {types: actionBuildedTypes} = actionBuilder(TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_RESOLVE);
                expect(actionBuildedTypes).to.be.an('object');
                expect(actionBuildedTypes).to.include.keys('REQUEST_LOAD_TEST', 'RESPONSE_LOAD_TEST', 'ERROR_LOAD_TEST');
            });
        });
        describe('The action part of the result', () => {
            const {action: actionBuildedLoadResolveAsync} = actionBuilder(TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_RESOLVE);
            const {action: actionBuildedLoadRejectAsync} = actionBuilder(TEST_VALID_ACTION_LOAD_BUILDER_PARAMS_REJECT);
            const {action: actionBuildedSaveResolveAsync} = actionBuilder(TEST_VALID_ACTION_SAVE_BUILDER_PARAMS_RESOLVE);
            const {action: actionBuildedSaveRejectAsync} = actionBuilder(TEST_VALID_ACTION_SAVE_BUILDER_PARAMS_REJECT);

            const CRITERIA = {id: 'test'};
            it('should return a function', () => {
                expect(actionBuildedLoadResolveAsync).to.be.a.function;
                expect(actionBuildedLoadRejectAsync).to.be.a.function;
                expect(actionBuildedSaveResolveAsync).to.be.a.function;
                expect(actionBuildedSaveRejectAsync).to.be.a.function;
            });
            it('when called with a successfull load service should call the response and request action creators', async done => {
                const dispatchSpy = sinon.spy();
                await actionBuildedLoadResolveAsync()(dispatchSpy);
                expect(dispatchSpy).to.have.callCount(3);
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'REQUEST_LOAD_TEST', syncTypeForm: 'request', formKey: undefined, entityPath: 'test', _meta: {status: PENDING, loading: true, saving: false,  error: false}});
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'RESPONSE_LOAD_TEST', payload: RESOLVE_VALUE, formKey: undefined, syncTypeForm: 'response', entityPath: 'test', _meta: {status: SUCCESS, loading: true, saving: false,  error: false}});

                done();
            });
            it('when called with an unsuccessfull load service should call the error action creator', async done => {
                const dispatchSpy = sinon.spy();
                await actionBuildedLoadRejectAsync()(dispatchSpy);
                expect(dispatchSpy).to.have.callCount(2);
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'REQUEST_LOAD_TEST', syncTypeForm: 'request', formKey: undefined, entityPath: 'test', _meta: {status: PENDING, loading: true, saving: false,  error: false}});
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'ERROR_LOAD_TEST', payload: REJECT_VALUE, syncTypeForm: 'error',formKey: undefined,  entityPath: 'test', _meta: {status: ERROR, loading: false, saving: false, error: true}});
                done();
            });
            it('when called with a successfull save service should call the response and request action creators', async done => {
                const dispatchSpy = sinon.spy();
                await actionBuildedSaveResolveAsync()(dispatchSpy);
                expect(dispatchSpy).to.have.callCount(4);
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'REQUEST_SAVE_TEST', syncTypeForm: 'request', formKey: undefined, entityPath: 'test', _meta: {status: PENDING, loading: false, saving: true,  error: false}});
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'RESPONSE_SAVE_TEST', payload: RESOLVE_VALUE,  formKey: undefined,syncTypeForm: 'response', entityPath: 'test', _meta: {status: SUCCESS, loading: false, saving: true, error: false}});
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'PUSH_MESSAGE', message:  {content: 'test.fields.saved', id:"msgId_1", type: 'success'}});
                done();
            });
            it('when called with an unsuccessfull save service should call the error action creator', async done => {
                const dispatchSpy = sinon.spy();
                dispatchSpy.reset();
                await actionBuildedSaveRejectAsync()(dispatchSpy);
                expect(dispatchSpy).to.have.callCount(2);
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'REQUEST_SAVE_TEST',  syncTypeForm: 'request', formKey: undefined, entityPath: 'test', _meta: {status: PENDING, loading: false, saving: true,  error: false}});
                expect(dispatchSpy).to.have.been.called.calledWith({type: 'ERROR_SAVE_TEST', payload: REJECT_VALUE, syncTypeForm: 'error',formKey: undefined,  entityPath: 'test', _meta: {status: ERROR, loading: false, saving: false, error: true}});
                done();
            });
        });
    });
});
<|endoftext|>


<commit_before>function candidateLineGraph(nationalData) {
  var parseDate = d3.time.format("%Y-%m-%d");
  nationalData.forEach(function(candidate) {
    candidate.minDate = d3.min(candidate.attributes.responses.map(function(d) { return parseDate.parse(d.date); }));
    candidate.maxDate = d3.max(candidate.attributes.responses.map(function(d) { return parseDate.parse(d.date); }));
    candidate.maxPercentage = d3.max(candidate.attributes.responses.map(function(d) { return d.percentage; }));
  });
  var graph = d3.select("#line-graph");
  var WIDTH = 1000;
  var HEIGHT = 500;
  var MARGINS = {
      top: 20,
      right: 20,
      bottom: 26,
      left: 50
    };
  var Xscale = d3.time.scale().range([MARGINS.left, WIDTH - MARGINS.right]);
  Xscale.domain([
      d3.min(nationalData.map(function(candidate) { return candidate.minDate; })),
      d3.max(nationalData.map(function(candidate) { return candidate.maxDate; }))
    ]);
  var Yscale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([0,30]);

  var colorScale = d3.scale.category20();

  var Xaxis = d3.svg.axis()
      .scale(Xscale)
      .orient("bottom");

  var Yaxis = d3.svg.axis()
      .scale(Yscale)
      .orient("left");

  graph.append("svg:g")
    .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
    .call(Xaxis);

  graph.append("svg:g")
    .attr("transform", "translate(" + (MARGINS.left) + ",0)")
    .call(Yaxis);

  var lineGen = d3.svg.line()
    .x(function(d) {
      return Xscale(parseDate.parse(d.date));
    })
    .y(function(d) {
      return Yscale(parseFloat(d.percentage));
    });

  nationalData.forEach(function(candidate, index) {
    var line = graph.append("svg:path")
      .attr("stroke", colorScale(index))
      .attr("stroke-width", 3)
      .attr("fill", "none");

    line.transition()
      .duration(4000)
      .delay(500 + index * 500)
      .ease("linear")
      .attr()
      .attr('d', lineGen(candidate.attributes.responses));
  });

  var yaxiscords = d3.range(26, HEIGHT, 45.4);
  var xaxiscords = d3.range(50, WIDTH, 25);

  graph.selectAll("line.vertical")
    .data(xaxiscords)
    .enter().append("svg:line")
    .attr("x1", function(d) {return d;})
    .attr("y1", 26)
    .attr("x2", function(d) {return d;})
    .attr("y2", HEIGHT - 25)
    .style("stroke", "rgb(192,192,192)")
    .style("opacity", 0.3)
    .style("stroke-width", 2);

  graph.selectAll("line.horizontal")
    .data(yaxiscords)
    .enter().append("svg:line")
    .attr("x1", 50)
    .attr("y1", function(d) {return d;})
    .attr("x2", WIDTH - 25)
    .attr("y2", function(d) {return d;})
    .style("stroke", "rgb(192,192,192)")
    .style("opacity", 0.3)
    .style("stroke-width", 2);
}

<commit_msg>Add final animation for GOP candidate line graph<commit_after>function candidateLineGraph(nationalData) {
  var parseDate = d3.time.format("%Y-%m-%d");
  nationalData.forEach(function(candidate) {
    candidate.minDate = d3.min(candidate.attributes.responses.map(function(d) { return parseDate.parse(d.date); }));
    candidate.maxDate = d3.max(candidate.attributes.responses.map(function(d) { return parseDate.parse(d.date); }));
    candidate.maxPercentage = d3.max(candidate.attributes.responses.map(function(d) { return d.percentage; }));
  });
  var graph = d3.select("#line-graph");
  var WIDTH = 1000;
  var HEIGHT = 500;
  var MARGINS = {
      top: 20,
      right: 20,
      bottom: 26,
      left: 50
    };
  var Xscale = d3.time.scale().range([MARGINS.left, WIDTH - MARGINS.right]);
  Xscale.domain([
      d3.min(nationalData.map(function(candidate) { return candidate.minDate; })),
      d3.max(nationalData.map(function(candidate) { return candidate.maxDate; }))
    ]);
  var Yscale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([0,30]);

  var colorScale = d3.scale.category20();

  var Xaxis = d3.svg.axis()
      .scale(Xscale)
      .orient("bottom");

  var Yaxis = d3.svg.axis()
      .scale(Yscale)
      .orient("left");

  graph.append("svg:g")
    .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
    .call(Xaxis);

  graph.append("svg:g")
    .attr("transform", "translate(" + (MARGINS.left) + ",0)")
    .call(Yaxis);

  var lineGen = d3.svg.line()
    .x(function(d) {
      return Xscale(parseDate.parse(d.date));
    })
    .y(function(d) {
      return Yscale(parseFloat(d.percentage));
    });

  nationalData.forEach(function(candidate, index) {
    var line = graph.append("svg:path")
      .attr("stroke", colorScale(index))
      .attr("stroke-width", 3)
      .attr("fill", "none");

    line.transition()
      .duration(4000)
      .delay(500 + index * 500)
      .ease("linear")
      .attr('d', lineGen(candidate.attributes.responses));
  });

  var yaxiscords = d3.range(26, HEIGHT, 45.4);
  var xaxiscords = d3.range(50, WIDTH, 25);

  graph.selectAll("line.vertical")
    .data(xaxiscords)
    .enter().append("svg:line")
    .attr("x1", function(d) {return d;})
    .attr("y1", 26)
    .attr("x2", function(d) {return d;})
    .attr("y2", HEIGHT - 25)
    .style("stroke", "rgb(192,192,192)")
    .style("opacity", 0.3)
    .style("stroke-width", 2);

  graph.selectAll("line.horizontal")
    .data(yaxiscords)
    .enter().append("svg:line")
    .attr("x1", 50)
    .attr("y1", function(d) {return d;})
    .attr("x2", WIDTH - 25)
    .attr("y2", function(d) {return d;})
    .style("stroke", "rgb(192,192,192)")
    .style("opacity", 0.3)
    .style("stroke-width", 2);
}

<|endoftext|>


<commit_before>import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import moment from 'moment';

export const MUTATION = gql`
  mutation GetGivingStatement($limit: Int, $skip: Int, $people: [Int], $start: String, $end: String) {
    transactionStatement(
      limit: $limit,
      skip: $skip,
      people: $people,
      start: $start,
      end: $end
    ){
      file
    }
  }
`;

export default graphql(MUTATION, {
  props: ({ mutate }) => ({
    getPDF: year => mutate({
      variables: {
        start: moment()
          .utc()
          .year(year)
          .startOf('year')
          .format('MM/DD/YYYY'),
        end: moment()
          .utc()
          .year(year)
          .endOf('year')
          .format('MM/DD/YYYY'),
      },
    }),
  }),
});

<commit_msg>Added Moment fix (#769)<commit_after>import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import moment from 'moment';

export const MUTATION = gql`
  mutation GetGivingStatement($limit: Int, $skip: Int, $people: [Int], $start: String, $end: String) {
    transactionStatement(
      limit: $limit,
      skip: $skip,
      people: $people,
      start: $start,
      end: $end
    ){
      file
    }
  }
`;

export default graphql(MUTATION, {
  props: ({ mutate }) => ({
    getPDF: year => mutate({
      variables: {
        start: moment()
          .utc()
          .year(year)
          .startOf('year')
          .format('MM/DD/YYYY'),
        end: moment()
          .utc()
          .year(year)
          .endOf('year')
          .format('MM/DD/YYYY 23:59:59'),
      },
    }),
  }),
});
<|endoftext|>


<commit_before>'use strict';

const union = require('lodash/union');
const cip = require('../../services/cip');
const motifTagController = require('../../controllers/motif-tagging');

module.exports = (metadata, context) => {
  // Let's save some cost and bandwidth and not analyze the asset unless
  // explicitly told. As in run only if one of the indexVison args
  // are specified.
  const enabled = context.vision && context.vision.enabled;
  const forced = context.vision && context.vision.forced;

  if (enabled) {
    // Convert tags to a comma seperated string
    if (!Array.isArray(metadata.tags_vision)) {
      metadata.tags_vision = [];
    }

    if(metadata.tags_vision.length > 0 && !forced) {
      console.log('Asset has vision tags, skipping it');
      return metadata;
    } else if (metadata.tags_vision.length > 0) {
      console.log('Asset has vision tags, but we´re forced');
    }

    // Still here. Let's grab the image directly from Cumulus.
    let path = 'preview/thumbnail/' + metadata.collection + '/' + metadata.id;
    let url = cip.generateURL(path);

    // Loading here to prevent circular dependency.
    var motif = require('../../../lib/controllers/motif-tagging');

    return motif.fetchSuggestions(url)
    .then(tags => {
      // Hang on to the tags prior to this run
      const tagsBefore = metadata.tags_vision;
      // Override the tags with the new suggestions
      metadata.tags_vision = union(metadata.tags_vision, tags);
      // Calculate the numberOfNewTags
      const numberOfNewTags = metadata.tags_vision.length - tagsBefore.length;

      // If no new tags was added, we don't save
      if (numberOfNewTags === 0) {
        console.log('No new tags found, let´s not save to the CIP.',
                    'Now the asset has', metadata.tags_vision.length, 'tags');
        return metadata;
      } else {
        console.log('Derived', numberOfNewTags, 'new tags.',
                    'Now the asset has', metadata.tags_vision.length, 'tags');
        // TODO: Move the saving to ../processing/result.js
        return motifTagController.save(metadata, {
          tags_vision: metadata.tags_vision
        })
        .then(response => {
          return metadata;
        });
      }
    });
  }
  return metadata;
};
<commit_msg>Fix a late require needed to avoid circular dependencies - hard to find :O<commit_after>'use strict';

const union = require('lodash/union');
const cip = require('../../services/cip');
const motifTagController = require('../../controllers/motif-tagging');

module.exports = (metadata, context) => {
  // Let's save some cost and bandwidth and not analyze the asset unless
  // explicitly told. As in run only if one of the indexVison args
  // are specified.
  const enabled = context.vision && context.vision.enabled;
  const forced = context.vision && context.vision.forced;

  if (enabled) {
    // Convert tags to a comma seperated string
    if (!Array.isArray(metadata.tags_vision)) {
      metadata.tags_vision = [];
    }

    if(metadata.tags_vision.length > 0 && !forced) {
      console.log('Asset has vision tags, skipping it');
      return metadata;
    } else if (metadata.tags_vision.length > 0) {
      console.log('Asset has vision tags, but we´re forced');
    }

    // Still here. Let's grab the image directly from Cumulus.
    let path = 'preview/thumbnail/' + metadata.collection + '/' + metadata.id;
    let url = cip.generateURL(path);

    // Loading here to prevent circular dependency.
    var motif = require('../../lib/controllers/motif-tagging');

    return motif.fetchSuggestions(url)
    .then(tags => {
      // Hang on to the tags prior to this run
      const tagsBefore = metadata.tags_vision;
      // Override the tags with the new suggestions
      metadata.tags_vision = union(metadata.tags_vision, tags);
      // Calculate the numberOfNewTags
      const numberOfNewTags = metadata.tags_vision.length - tagsBefore.length;

      // If no new tags was added, we don't save
      if (numberOfNewTags === 0) {
        console.log('No new tags found, let´s not save to the CIP.',
                    'Now the asset has', metadata.tags_vision.length, 'tags');
        return metadata;
      } else {
        console.log('Derived', numberOfNewTags, 'new tags.',
                    'Now the asset has', metadata.tags_vision.length, 'tags');
        // TODO: Move the saving to ../processing/result.js
        return motifTagController.save(metadata, {
          tags_vision: metadata.tags_vision
        })
        .then(response => {
          return metadata;
        });
      }
    });
  }
  return metadata;
};
<|endoftext|>


<commit_before>/*global $, jQuery, alert, document, SkimishTroupMovement, SkirmishClient, SkirmishMap, SkirmishGameState, google, Handlebars */
"use strict";

var SkirmishMap = (function () {
    var map, cityOverlayTemplate, miniCityOverlayTemplate, overlays;
    overlays = [];

    function compileTemplates() {
        cityOverlayTemplate = Handlebars.compile($("#city-overlay-template").html());
        miniCityOverlayTemplate = Handlebars.compile($("#mini-city-overlay-template").html());
    }

    function zoomChanged() {
        var zoom = map.getZoom();
        overlays.forEach(function (overlay) {
            overlay.scaleTemplate(zoom);
        });
    }

    function initialize() {
        console.log("SkirmishMap initializing");
        var mapOptions;

        compileTemplates();

        mapOptions = {
            center: new google.maps.LatLng(39.8282, -98.5795),
            disableDoubleClickZoom: true,
            streetViewControl: false,
            zoom: 5
        };

        map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);

        google.maps.event.addListener(map, 'zoom_changed', zoomChanged);
    }

    function displayCircle(city) {
      var range = 1000

      var circleOptions = {
          strokeColor: "#000FFF",
          strokeOpacity: 0.35,
          strokeWeight: 10,
          fillColor: "#0000FF",
          fillOpacity: .25,
          map: map,
          center: new google.maps.LatLng(city.latLng[0],city.latLng[1]),
          radius: range * 1000
        };

        var cityCircle = new google.maps.Circle(circleOptions);
        return cityCircle;
    }

    function clearCircle(cityCircle) {
        cityCircle.setMap(null);
    }

    function displayCity(city) {
        var cityOverlay = new SkirmishMap.CityOverlay(city)
        overlays.push(cityOverlay);
        setupDomClickListener(cityOverlay);
        setupDomHoverListener(cityOverlay);
    }

    function setupDomClickListener(cityOverlay) {
        console.log('set up event for city '+cityOverlay.overlay[0]);
        google.maps.event.addDomListener(cityOverlay.overlay[0], 'click', function() {
            SkirmishTroupMovement.clickHandler(cityOverlay.city);
        });
    }

    function setupDomHoverListener(cityOverlay) {
        google.maps.event.addDomListener(cityOverlay.overlay[0], 'mouseover', function() {
            SkirmishTroupMovement.hoverHandler(cityOverlay.city);
        });
    }

    function displayCities(cities) {
        var city,
            i;

        for (i = 0; i < cities.length; i += 1) {
            city = cities[i];
            SkirmishMap.displayCity(city);
        }
    }

    function clearOverlays() {
        overlays.forEach(function (overlay) {
            overlay.onRemove();
        });
    }

    function CityOverlay(city) {
        this.city = city;
        this.setMap(map);
        this.overlay = $('

');
    }

    function gravatarURL(gravatarHash) {
        return 'http://www.gravatar.com/avatar/' + gravatarHash + '?s=40&d=retro';
    }

    CityOverlay.prototype = new google.maps.OverlayView; //subclassing google's overlayView

    CityOverlay.prototype.onAdd = function () {
        this.scaleTemplate(map.getZoom());
        this.getPanes().overlayImage.appendChild(this.overlay[0]); //attach it to overlay panes so it behaves like markers
        this.draw();
    };

    CityOverlay.prototype.scaleTemplate = function (zoom) {
        if (zoom <= 5) {
            this.renderMiniTemplate();
        } else {
            this.renderFullTemplate();
        }
    };

    CityOverlay.prototype.renderHTML = function (html) {
        this.overlay.empty();
        this.overlay.append($(html));
    };

    CityOverlay.prototype.gravatarURL = function () {
        return gravatarURL(this.city.gravatarHash);
    };

    CityOverlay.prototype.renderFullTemplate = function () {
        this.renderHTML(cityOverlayTemplate({
            city: this.city,
            playerName: SkirmishGameState.players()[this.city.playerId],
            gravatar: this.gravatarURL()
        }));
    };

    CityOverlay.prototype.renderMiniTemplate = function () {
        this.renderHTML(miniCityOverlayTemplate({
            gravatar: this.gravatarURL()
        }));
    };

    CityOverlay.prototype.onRemove = function () {
        this.overlay.remove();
    };

    CityOverlay.prototype.draw = function () {
        var overlayProjection,
            position;

        overlayProjection = this.getProjection();

        position = overlayProjection.fromLatLngToDivPixel(new google.maps.LatLng(this.city.latLng[0], this.city.latLng[1]));

        this.overlay.css({
            top: (position.y - this.overlay.height() / 2) + 'px',
            left: (position.x - this.overlay.width() / 2) + 'px',
            position: 'absolute',
            background: 'white'
        });
    };

    return {
        displayCity: displayCity,
        displayCities: displayCities,
        initialize: initialize,
        CityOverlay: CityOverlay,
        clearOverlays: clearOverlays,
        setupDomClickListener: setupDomClickListener,
        displayCircle: displayCircle,
        clearCircle: clearCircle
     };

}());
<commit_msg>Started work. Changes city positions, when it should change pixel values<commit_after>/*global $, jQuery, alert, document, SkirmishTroupMovement, SkirmishClient, SkirmishMap, SkirmishGameState, google, Handlebars */
"use strict";

var SkirmishMap = (function () {
    var map, cityOverlayTemplate, miniCityOverlayTemplate, overlays, MIN_CITY_DISTANCE;
    overlays = [];

    MIN_CITY_DISTANCE = 500;

    function compileTemplates() {
        cityOverlayTemplate = Handlebars.compile($("#city-overlay-template").html());
        miniCityOverlayTemplate = Handlebars.compile($("#mini-city-overlay-template").html());
    }

    function zoomChanged() {
        var zoom = map.getZoom();
        overlays.forEach(function (overlay) {
            overlay.scaleTemplate(zoom);
        });

        declusterCities(SkirmishGameState.cities(), MIN_CITY_DISTANCE / zoom);
    }

    function initialize() {
        console.log("SkirmishMap initializing");
        var mapOptions;

        compileTemplates();

        mapOptions = {
            center: new google.maps.LatLng(39.8282, -98.5795),
            disableDoubleClickZoom: true,
            streetViewControl: false,
            zoom: 5
        };

        map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);

        google.maps.event.addListener(map, 'zoom_changed', zoomChanged);
    }

    function displayCircle(city) {
        var range = 1000,
            circleOptions,
            cityCircle;

        circleOptions = {
            strokeColor: "#000FFF",
            strokeOpacity: 0.35,
            strokeWeight: 10,
            fillColor: "#0000FF",
            fillOpacity: 0.25,
            map: map,
            center: new google.maps.LatLng(city.latLng[0], city.latLng[1]),
            radius: range * 1000
        };

        cityCircle = new google.maps.Circle(circleOptions);
        return cityCircle;
    }

    function clearCircle(cityCircle) {
        cityCircle.setMap(null);
    }

    function setupDomClickListener(cityOverlay) {
        console.log('set up event for city ' + cityOverlay.overlay[0]);
        google.maps.event.addDomListener(cityOverlay.overlay[0], 'click', function () {
            SkirmishTroupMovement.clickHandler(cityOverlay.city);
        });
    }

    function setupDomHoverListener(cityOverlay) {
        google.maps.event.addDomListener(cityOverlay.overlay[0], 'mouseover', function () {
            SkirmishTroupMovement.hoverHandler(cityOverlay.city);
        });
    }

    function displayCity(city) {
        var cityOverlay = new SkirmishMap.CityOverlay(city);
        overlays.push(cityOverlay);
        setupDomClickListener(cityOverlay);
        setupDomHoverListener(cityOverlay);
    }

    // FIXME - copied from SkirmishTroupMovements, should be common

    function rad(x) {
        return x * Math.PI / 180;
    }

    function getDistance(p1, p2) {
        var R,
            dLat,
            dLong,
            a,
            c,
            d;

        R = 6378137; // Earth’s mean radius in meter
        dLat = rad(p2.lat - p1.lat);
        dLong = rad(p2.lng - p1.lng);
        a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(rad(p1.lat)) * Math.cos(rad(p2.lat)) *
            Math.sin(dLong / 2) * Math.sin(dLong / 2);
        c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        d = R * c;
        return d / 1000; // returns the distance in meter
    }

    function cityDistance(cityA, cityB) {
        return getDistance({lat: cityA.latLng[0], lng: cityA.latLng[1]}, {lat: cityB.latLng[0], lng: cityB.latLng[1]});
    }

    function nearestOtherCityDistance(cities, ourCity) {
        var cityDistances = cities.map(function (city) {
            if (city === ourCity) {
                return 10 * 10 * 10 * 10000000;
            }
            return cityDistance(city, ourCity);
        });
        return Math.min.apply(this, cityDistances);
    }

    function getCitiesWithCloseNeighbours(cities, minDistance) {
        console.log(minDistance);
        return cities.filter(function (city) {
            return nearestOtherCityDistance(cities, city) < minDistance;
        });
    }

    function getClosestNeighbour(cities, city) {
        var closestCity = null,
            minDistance = 0,
            otherCityDistance;

        cities.forEach(function (otherCity) {
            if (otherCity === city) {
                return false;
            }

            otherCityDistance = cityDistance(city, otherCity);

            if (closestCity === null || otherCityDistance < minDistance) {
                minDistance = otherCityDistance;
                closestCity = otherCity;
            }

        });

        return closestCity;
    }

    function moveCityAwayFromNeighbours(cities, city) {
        // finds the closest neighbour
        // finds distance between
        // moves city that distance away again

        var closestNeighbour = getClosestNeighbour(cities, city);

        console.log('Moving ' + city.name + ' away from ' + closestNeighbour.name);

        var distanceLat = closestNeighbour.latLng[0] - city.latLng[0];
        var distanceLng = closestNeighbour.latLng[1] - city.latLng[1];

        var moveFactor = 0.5;

        city.latLng[0] -= distanceLat;
        city.latLng[1] -= distanceLng;
    }

    function declusterCities(cities, minDistance) {
        var nearCities = getCitiesWithCloseNeighbours(cities, minDistance),
            moveCity = function (city) { moveCityAwayFromNeighbours(cities, city); };

        while (nearCities.length > 0) {
            console.log('remaining bad cities', nearCities.length);
            nearCities.map(moveCity);

            nearCities = getCitiesWithCloseNeighbours(cities);
        }
    }

    function displayCities(cities) {
        var city,
            i;

        for (i = 0; i < cities.length; i += 1) {
            city = cities[i];
            SkirmishMap.displayCity(city);
        }
    }

    function clearOverlays() {
        overlays.forEach(function (overlay) {
            overlay.onRemove();
        });
    }

    function CityOverlay(city) {
        this.city = city;
        this.setMap(map);
        this.overlay = $('

');
    }

    function gravatarURL(gravatarHash) {
        return 'http://www.gravatar.com/avatar/' + gravatarHash + '?s=40&d=retro';
    }

    CityOverlay.prototype = new google.maps.OverlayView; //subclassing google's overlayView

    CityOverlay.prototype.onAdd = function () {
        this.scaleTemplate(map.getZoom());
        this.getPanes().overlayImage.appendChild(this.overlay[0]); //attach it to overlay panes so it behaves like markers
        this.draw();
    };

    CityOverlay.prototype.scaleTemplate = function (zoom) {
        if (zoom <= 5) {
            this.renderMiniTemplate();
        } else {
            this.renderFullTemplate();
        }
    };

    CityOverlay.prototype.renderHTML = function (html) {
        this.overlay.empty();
        this.overlay.append($(html));
    };

    CityOverlay.prototype.gravatarURL = function () {
        return gravatarURL(this.city.gravatarHash);
    };

    CityOverlay.prototype.renderFullTemplate = function () {
        this.renderHTML(cityOverlayTemplate({
            city: this.city,
            playerName: SkirmishGameState.players()[this.city.playerId],
            gravatar: this.gravatarURL()
        }));
    };

    CityOverlay.prototype.renderMiniTemplate = function () {
        this.renderHTML(miniCityOverlayTemplate({
            gravatar: this.gravatarURL()
        }));
    };

    CityOverlay.prototype.onRemove = function () {
        this.overlay.remove();
    };

    CityOverlay.prototype.draw = function () {
        var overlayProjection,
            position;

        overlayProjection = this.getProjection();

        position = overlayProjection.fromLatLngToDivPixel(new google.maps.LatLng(this.city.latLng[0], this.city.latLng[1]));

        this.overlay.css({
            top: (position.y - this.overlay.height() / 2) + 'px',
            left: (position.x - this.overlay.width() / 2) + 'px',
            position: 'absolute',
            background: 'white'
        });
    };

    return {
        displayCity: displayCity,
        displayCities: displayCities,
        initialize: initialize,
        CityOverlay: CityOverlay,
        clearOverlays: clearOverlays,
        setupDomClickListener: setupDomClickListener,
        displayCircle: displayCircle,
        clearCircle: clearCircle
     };

}());
<|endoftext|>


<commit_before>/**
 * Angular directives for inline editing v0.0.1 (https://github.com/flexjoy/angular-bs-edit)
 *
 * Copyright 2016 Sergey Cherepanov
 * Licensed under the MIT license (https://opensource.org/licenses/mit-license.php)
 */

'use strict';

var app = angular.module('bs-edit', []);

const EMPTY_VALUE = 'empty';

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// bseText directive
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
app.directive('bseText', function() {
	return {
		restrict: 'A',
		scope: {
			value: '=bseText',
			empty: '=?',
			name: '@'
		},
		template: '<input name="{{name}}" ng-model="newValue" class="form-control">',
		link: function(scope, element) {

			scope.empty = scope.empty ? scope.empty : EMPTY_VALUE;
			element.addClass('edit-in-place');
			var inputElement = angular.element(element.children()[0]);

			element.bind('click', function () {
				scope.newValue = angular.copy(scope.value);
				scope.$apply();
				element.addClass('active');
				inputElement[0].focus();
			});

			inputElement.bind('blur', function() {
				scope.value = scope.newValue;
				scope.$apply();
				element.removeClass('active');
			});

			inputElement.bind('keydown', function (event) {
				if(event.which === 13) {
					this.blur();
					event.preventDefault();
				}

				if(event.which === 27) {
					scope.newValue = scope.value;
					this.blur();
					event.preventDefault();
				}
			});
		}
	};
});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// bseSelect directive
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
app.directive('bseSelect', function() {
	var showDropdown = function (element) {
		var event = document.createEvent('MouseEvents');
		event.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
		setTimeout(function(){
			element.dispatchEvent(event);
		}, 1);
	};
	return {
		restrict: 'A',
		scope: {
			value: '=bseSelect',
			onshow: '&',
			empty: '=?',
			name: '@'
		},
		template: '<select name="{{name}}" ng-model="value" class="form-control" ng-options="v.name for v in values track by v.id"></select>',
		link: function(scope, element) {

			scope.empty = scope.empty ? scope.empty : EMPTY_VALUE;
			element.addClass('edit-in-place');
			var inputElement = angular.element(element.children()[0]);
			var spanElement = angular.element( element.children()[1]);

			spanElement.bind('click', function () {
				scope.onshow().then(
					function (data){
						scope.values = data;
						element.addClass('active');
						inputElement[0].focus();
						showDropdown(inputElement[0]);
					}
				);
			});

			inputElement.bind('blur', function() {
				scope.$apply();
				element.removeClass('active');
			});

			inputElement.bind('change', function(event) {
				this.blur();
				event.preventDefault();
			});

			inputElement.bind('keydown', function (event) {
				if(event.which === 27) {
					this.blur();
					event.preventDefault();
				}
			});
		}
	};
});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// bseTextarea directive
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
app.directive('bseTextarea', function() {
	return {
		restrict: 'A',
		scope: {
			value: '=bseTextarea',
			empty: '=?',
			name: '@'
		},
		template: '<textarea name="{{name}}" ng-model="newValue" class="form-control"></textarea>

',
		link: function(scope, element) {

			scope.empty = scope.empty ? scope.empty : EMPTY_VALUE;
			element.addClass('edit-in-place');
			var inputElement = angular.element( element.children()[0]);
			var preElement = angular.element( element.children()[1]);

			preElement.bind('click', function () {
				inputElement[0].style.height = element[0].offsetHeight + 'px';
				scope.newValue = angular.copy(scope.value);
				scope.$apply();
				element.addClass('active');
				inputElement[0].focus();
			});

			inputElement.bind('blur', function() {
				scope.value = scope.newValue;
				scope.$apply();
				element.removeClass('active');
			});

			inputElement.bind('keydown', function (event) {
				if(event.which === 13) {
					var h = inputElement[0].offsetHeight + 20;
					inputElement[0].style.height = h + 'px';
				}

				if(event.which === 27) {
					scope.newValue = scope.value;
					this.blur();
					event.preventDefault();
				}
			});
		}
	};
});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// bseDate directive
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
app.directive('bseDate', function($timeout) {
	return {
		restrict: 'A',
		scope: {
			value: '=bseDate',
			empty: '=?',
			locale: '=',
			name: '@'
		},
		template: '<input name="{{name}}" ng-model="name" class="form-control">{{(value | date: "dd-MM-yyyy") || empty}}',

		link: function(scope, element) {

			scope.empty = scope.empty ? scope.empty : EMPTY_VALUE;
			element.addClass('edit-in-place');
			var inputElement = angular.element( element.children()[0]);
			var spanElement = angular.element( element.children()[1]);

			var options = {
				language: scope.locale,
				format: "dd-mm-yyyy",
				orientation: "bottom auto",
				todayHighlight: true,
				autoclose: true,
				clearBtn: true
			};

			function initDatepicker() {
				inputElement.datepicker(options).attr('readonly','readonly');
			}

			scope.$watch('locale', function(val) {
				angular.extend(options, {language: val});

				$timeout(function() {
					inputElement.datepicker('remove');
					initDatepicker();
				});
			});

			spanElement.bind('click', function () {
				inputElement.datepicker('setDate', scope.value);
				element.addClass('active');
				inputElement[0].focus();
			});

			inputElement.bind('hide', function(res) {
				element.removeClass('active');
				scope.value = res.date;
				scope.$apply();
			});
		}
	};
});
<commit_msg>Change 'empty' type from model to string<commit_after>/**
 * Angular directives for inline editing v0.0.1 (https://github.com/flexjoy/angular-bs-edit)
 *
 * Copyright 2016 Sergey Cherepanov
 * Licensed under the MIT license (https://opensource.org/licenses/mit-license.php)
 */

'use strict';

var app = angular.module('bs-edit', []);

const EMPTY_VALUE = 'empty';

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// bseText directive
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
app.directive('bseText', function() {
	return {
		restrict: 'A',
		scope: {
			value: '=bseText',
			empty: '@',
			name: '@'
		},
		template: '<input name="{{name}}" ng-model="newValue" class="form-control">',
		link: function(scope, element) {

			scope.empty = scope.empty ? scope.empty : EMPTY_VALUE;
			element.addClass('edit-in-place');
			var inputElement = angular.element(element.children()[0]);

			element.bind('click', function () {
				scope.newValue = angular.copy(scope.value);
				scope.$apply();
				element.addClass('active');
				inputElement[0].focus();
			});

			inputElement.bind('blur', function() {
				scope.value = scope.newValue;
				scope.$apply();
				element.removeClass('active');
			});

			inputElement.bind('keydown', function (event) {
				if(event.which === 13) {
					this.blur();
					event.preventDefault();
				}

				if(event.which === 27) {
					scope.newValue = scope.value;
					this.blur();
					event.preventDefault();
				}
			});
		}
	};
});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// bseSelect directive
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
app.directive('bseSelect', function() {
	var showDropdown = function (element) {
		var event = document.createEvent('MouseEvents');
		event.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
		setTimeout(function(){
			element.dispatchEvent(event);
		}, 1);
	};
	return {
		restrict: 'A',
		scope: {
			value: '=bseSelect',
			onshow: '&',
			empty: '@',
			name: '@'
		},
		template: '<select name="{{name}}" ng-model="value" class="form-control" ng-options="v.name for v in values track by v.id"></select>',
		link: function(scope, element) {

			scope.empty = scope.empty ? scope.empty : EMPTY_VALUE;
			element.addClass('edit-in-place');
			var inputElement = angular.element(element.children()[0]);
			var spanElement = angular.element( element.children()[1]);

			spanElement.bind('click', function () {
				scope.onshow().then(
					function (data){
						scope.values = data;
						element.addClass('active');
						inputElement[0].focus();
						showDropdown(inputElement[0]);
					}
				);
			});

			inputElement.bind('blur', function() {
				scope.$apply();
				element.removeClass('active');
			});

			inputElement.bind('change', function(event) {
				this.blur();
				event.preventDefault();
			});

			inputElement.bind('keydown', function (event) {
				if(event.which === 27) {
					this.blur();
					event.preventDefault();
				}
			});
		}
	};
});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// bseTextarea directive
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
app.directive('bseTextarea', function() {
	return {
		restrict: 'A',
		scope: {
			value: '=bseTextarea',
			empty: '@',
			name: '@'
		},
		template: '<textarea name="{{name}}" ng-model="newValue" class="form-control"></textarea>

',
		link: function(scope, element) {

			scope.empty = scope.empty ? scope.empty : EMPTY_VALUE;
			element.addClass('edit-in-place');
			var inputElement = angular.element( element.children()[0]);
			var preElement = angular.element( element.children()[1]);

			preElement.bind('click', function () {
				inputElement[0].style.height = element[0].offsetHeight + 'px';
				scope.newValue = angular.copy(scope.value);
				scope.$apply();
				element.addClass('active');
				inputElement[0].focus();
			});

			inputElement.bind('blur', function() {
				scope.value = scope.newValue;
				scope.$apply();
				element.removeClass('active');
			});

			inputElement.bind('keydown', function (event) {
				if(event.which === 13) {
					var h = inputElement[0].offsetHeight + 20;
					inputElement[0].style.height = h + 'px';
				}

				if(event.which === 27) {
					scope.newValue = scope.value;
					this.blur();
					event.preventDefault();
				}
			});
		}
	};
});

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// bseDate directive
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
app.directive('bseDate', function($timeout) {
	return {
		restrict: 'A',
		scope: {
			value: '=bseDate',
			empty: '@',
			locale: '=',
			name: '@'
		},
		template: '<input name="{{name}}" ng-model="name" class="form-control">{{(value | date: "dd-MM-yyyy") || empty}}',

		link: function(scope, element) {

			scope.empty = scope.empty ? scope.empty : EMPTY_VALUE;
			element.addClass('edit-in-place');
			var inputElement = angular.element( element.children()[0]);
			var spanElement = angular.element( element.children()[1]);

			var options = {
				language: scope.locale,
				format: "dd-mm-yyyy",
				orientation: "bottom auto",
				todayHighlight: true,
				autoclose: true,
				clearBtn: true
			};

			function initDatepicker() {
				inputElement.datepicker(options).attr('readonly','readonly');
			}

			scope.$watch('locale', function(val) {
				angular.extend(options, {language: val});

				$timeout(function() {
					inputElement.datepicker('remove');
					initDatepicker();
				});
			});

			spanElement.bind('click', function () {
				inputElement.datepicker('setDate', scope.value);
				element.addClass('active');
				inputElement[0].focus();
			});

			inputElement.bind('hide', function(res) {
				element.removeClass('active');
				scope.value = res.date;
				scope.$apply();
			});
		}
	};
});
<|endoftext|>


<commit_before>
  var global_url      = "http://datos.rtve.es/elecciones/autonomicas-municipales/data";
  var tiles_pngs_url  = "http://datos.rtve.es/elecciones/autonomicas-municipales/data/tiles/";
  var proxy_url       = "proxy.php";
  var tiles_version   = "live"; //"current"; //3;
  var bubbles_version = "current"; //10;
  var gmaps_version   = "current"; //4;
  var graph_version   = "current"; //"v7";
  var ua              = $.browser;
  var ie_             = false;

  if (window.location.hostname == "localhost" || window.location.hostname == "elections" || window.location.hostname == "192.168.1.147") {
    global_url = proxy_url+"?proxy_url="+global_url;
    //tiles_pngs_url = "http://rtvedata{n}.ipq.co/data/tiles/";
  } else if (window.location.hostname == "datos.rtve.es") {
    global_url = "http://datos.rtve.es/elecciones/autonomicas-municipales/data";
  }

  //Go to IE6 page
  if (ua.msie) {
    if (ua.version.slice(0,3) < '7.0') {
      window.location.href = "http://cartodb.com/";
    } else if (ua.version.slice(0,3) < '9.0') {
      ie_ = true;
    }
  }

<commit_msg>new tiles urls<commit_after>
  var global_url      = "http://datos.rtve.es/elecciones/autonomicas-municipales/data";
  var tiles_pngs_url  = "http://datos{n}.rtve.es/elecciones/autonomicas-municipales/data/tiles/";
  var proxy_url       = "proxy.php";
  var tiles_version   = "live"; //"current"; //3;
  var bubbles_version = "current"; //10;
  var gmaps_version   = "current"; //4;
  var graph_version   = "current"; //"v7";
  var ua              = $.browser;
  var ie_             = false;

  if (window.location.hostname == "localhost" || window.location.hostname == "elections" || window.location.hostname == "192.168.1.147") {
    global_url = proxy_url+"?proxy_url="+global_url;
    //tiles_pngs_url = "http://rtvedata{n}.ipq.co/data/tiles/";
  } else if (window.location.hostname == "datos.rtve.es") {
    global_url = "http://datos.rtve.es/elecciones/autonomicas-municipales/data";
  }

  //Go to IE6 page
  if (ua.msie) {
    if (ua.version.slice(0,3) < '7.0') {
      window.location.href = "http://cartodb.com/";
    } else if (ua.version.slice(0,3) < '9.0') {
      ie_ = true;
    }
  }

<|endoftext|>


<commit_before>import constants from 'src/database/constants';
import SqlCommands from 'src/database/sql-related/sqlCommands';
import DateTime from 'src/database/generated-data/dateTime';
import SqlArray from 'src/database/generated-data/sqlArray';
import StringManipulation from 'src/database/stringManipulation';

const sqlCommands = new SqlCommands();
const dateTime = new DateTime();
const alasqlArray = new SqlArray();
const stringManipulator = new StringManipulation();

function createNewFile(organizationId, filePath, folderId, newFileId, newFileName) {
  return new Promise((resolve, reject) => {
    const currentDateTime = dateTime.getCurrentDateTime();

    const fileOrganizationId = organizationId;
    const fileFolderId = folderId;
    const fileId = newFileId;
    const fileName = newFileName;
    const fileMarkDown = constants.DEFAULT_EMPTY;
    const filePermission = constants.PERMISSION_CREATOR;
    const fileCreationDateTime = currentDateTime;
    const fileLastModified = fileCreationDateTime;
    const fileThisPath = filePath;

    alasqlArray.initializeAlasqlArray();
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_ORGANIZATION_ID, fileOrganizationId);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_FOLDER_ID, fileFolderId);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_FILE_ID, fileId);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_FILE_NAME, fileName);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_FILE_MARKDOWN, fileMarkDown);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_PERMISSION_INDEX, filePermission);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_CREATION_DATE, fileCreationDateTime);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_LAST_MODIFIED_DATE, fileLastModified);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_PATH, fileThisPath);
    const newFileData = alasqlArray.endAlasqlArray();

    return sqlCommands.insertContent(constants.ENTITIES_FILE_MANAGER, newFileData)
    .then(success => resolve(newFileData[0]))
    .catch(sqlErr => reject(sqlErr));
  });
}

function createNewFolder(organizationId, folderPath, currentFolderId, newFolderId, newFolderName) {
  return new Promise((resolve, reject) => {
    const currentDateTime = dateTime.getCurrentDateTime();

    const folderId = newFolderId;
    const folderParentFolderId = currentFolderId;
    const folderpermissionIndex = constants.PERMISSION_CREATOR;
    const folderOrganizationId = organizationId;
    const folderCreationDate = currentDateTime;
    const folderName = newFolderName;
    const folderlastModifiedDate = folderCreationDate;
    const folderThisPath = folderPath;

    alasqlArray.initializeAlasqlArray();
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_FOLDER_ID, folderId);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_PARENT_FOLDER_ID, folderParentFolderId);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_PERMISSION_INDEX, folderpermissionIndex);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_ORGANIZATION_ID, folderOrganizationId);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_CREATION_DATE, folderCreationDate);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_FOLDER_NAME, folderName);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_LAST_MODIFIED_DATE, folderlastModifiedDate);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_PATH, folderThisPath);
    const newFolderData = alasqlArray.endAlasqlArray();

    return sqlCommands.insertContent(constants.ENTITIES_FOLDER, newFolderData)
    .then(success => resolve(newFolderData[0]))
    .catch(err => reject(err));
  });
}

export default class dataAdd {
  static constructor() {}

  static createNewFile(organizationId, filePath, folderId) {
    return new Promise((resolve, reject) =>
      // set default new ID if not exist
      sqlCommands.getMaxFileId()
        .then((maxId) => {
          const newFileId = maxId + 1;
          // search all possible identical fileNames
          return sqlCommands.exactSearchStartFileNameInFolder(filePath)
          .then((queryFiles) => {
            const newFileName = constants.DEFAULT_FILE_NAME;
            return createNewFile(organizationId, filePath, folderId, newFileId, newFileName)
            .then(data => resolve(data))
            .catch(err => reject(err));
          })
          .catch(sqlErr => reject(sqlErr));
        }).catch(sqlError => reject(sqlError))
    );
  }

  static duplicateFile(fileId) {
    return new Promise((resolve, reject) => {
      sqlCommands.getMaxFileId()
      .then((maxId) => {
        const newFileId = maxId + 1;
        return sqlCommands.retrieveFullFile(fileId)
        .then((files) => {
          files[0].file_id = newFileId;
          files[0].file_name = stringManipulator.stringConcat('copy of ', files[0].file_name);
          return files;
        })
        .then(duplicatedFile =>
          sqlCommands.insertContent(constants.ENTITIES_FILE_MANAGER, duplicatedFile)
          .then(() =>
            resolve(duplicatedFile)
          )
          .catch(sqlError => reject(sqlError)))
        .catch(sqlError => reject(sqlError));
      })
      .catch(sqlError => reject(sqlError));
    });
  }

  static createNewFolder(organizationId, folderPath, folderId) {
    return new Promise((resolve, reject) =>
      // set default new ID if not exist (already have 0)
      sqlCommands.getMaxFolderId()
      .then((maxId) => {
        const newFolderId = maxId + 1;
        // search all possible identical folderNames
        return sqlCommands.exactSearchStartFolderNameInFolder(folderId)
        .then((queryFiles) => {
          const newFolderName = constants.DEFAULT_FOLDER_NAME;
          const newFolderPath = stringManipulator.stringConcat(folderPath, newFolderName, '/');
          return createNewFolder(organizationId, newFolderPath, folderId, newFolderId, newFolderName)
          .then(data => resolve(data))
          .catch(err => reject(err));
        })
        .catch(sqlErr => reject(sqlErr));
      }).catch(sqlError => reject(sqlError))
    );
  }
}
<commit_msg>Update dateTime to long time for dataAdd.js<commit_after>import constants from 'src/database/constants';
import SqlCommands from 'src/database/sql-related/sqlCommands';
import DateTime from 'src/database/generated-data/dateTime';
import SqlArray from 'src/database/generated-data/sqlArray';
import StringManipulation from 'src/database/stringManipulation';

const sqlCommands = new SqlCommands();
const dateTime = new DateTime();
const alasqlArray = new SqlArray();
const stringManipulator = new StringManipulation();

function createNewFile(organizationId, filePath, folderId, newFileId, newFileName) {
  return new Promise((resolve, reject) => {
    const currentDateTime = dateTime.getCurrentLongTime();

    const fileOrganizationId = organizationId;
    const fileFolderId = folderId;
    const fileId = newFileId;
    const fileName = newFileName;
    const fileMarkDown = constants.DEFAULT_EMPTY;
    const filePermission = constants.PERMISSION_CREATOR;
    const fileCreationDateTime = currentDateTime;
    const fileLastModified = fileCreationDateTime;
    const fileThisPath = filePath;

    alasqlArray.initializeAlasqlArray();
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_ORGANIZATION_ID, fileOrganizationId);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_FOLDER_ID, fileFolderId);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_FILE_ID, fileId);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_FILE_NAME, fileName);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_FILE_MARKDOWN, fileMarkDown);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_PERMISSION_INDEX, filePermission);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_CREATION_DATE, fileCreationDateTime);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_LAST_MODIFIED_DATE, fileLastModified);
    alasqlArray.addKeyBasePair(constants.HEADER_FILE_MANAGER_PATH, fileThisPath);
    const newFileData = alasqlArray.endAlasqlArray();

    return sqlCommands.insertContent(constants.ENTITIES_FILE_MANAGER, newFileData)
    .then(success => resolve(newFileData[0]))
    .catch(sqlErr => reject(sqlErr));
  });
}

function createNewFolder(organizationId, folderPath, currentFolderId, newFolderId, newFolderName) {
  return new Promise((resolve, reject) => {
    const currentDateTime = dateTime.getCurrentLongTime();

    const folderId = newFolderId;
    const folderParentFolderId = currentFolderId;
    const folderpermissionIndex = constants.PERMISSION_CREATOR;
    const folderOrganizationId = organizationId;
    const folderCreationDate = currentDateTime;
    const folderName = newFolderName;
    const folderlastModifiedDate = folderCreationDate;
    const folderThisPath = folderPath;

    alasqlArray.initializeAlasqlArray();
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_FOLDER_ID, folderId);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_PARENT_FOLDER_ID, folderParentFolderId);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_PERMISSION_INDEX, folderpermissionIndex);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_ORGANIZATION_ID, folderOrganizationId);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_CREATION_DATE, folderCreationDate);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_FOLDER_NAME, folderName);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_LAST_MODIFIED_DATE, folderlastModifiedDate);
    alasqlArray.addKeyBasePair(constants.HEADER_FOLDER_PATH, folderThisPath);
    const newFolderData = alasqlArray.endAlasqlArray();

    return sqlCommands.insertContent(constants.ENTITIES_FOLDER, newFolderData)
    .then(success => resolve(newFolderData[0]))
    .catch(err => reject(err));
  });
}

export default class dataAdd {
  static constructor() {}

  static createNewFile(organizationId, filePath, folderId) {
    return new Promise((resolve, reject) =>
      // set default new ID if not exist
      sqlCommands.getMaxFileId()
        .then((maxId) => {
          const newFileId = maxId + 1;
          // search all possible identical fileNames
          return sqlCommands.exactSearchStartFileNameInFolder(filePath)
          .then((queryFiles) => {
            const newFileName = constants.DEFAULT_FILE_NAME;
            return createNewFile(organizationId, filePath, folderId, newFileId, newFileName)
            .then(data => resolve(data))
            .catch(err => reject(err));
          })
          .catch(sqlErr => reject(sqlErr));
        }).catch(sqlError => reject(sqlError))
    );
  }

  static duplicateFile(fileId) {
    return new Promise((resolve, reject) => {
      sqlCommands.getMaxFileId()
      .then((maxId) => {
        const newFileId = maxId + 1;
        return sqlCommands.retrieveFullFile(fileId)
        .then((files) => {
          const currentDateTime = dateTime.getCurrentLongTime();
          files[0].file_id = newFileId;
          files[0].file_name = stringManipulator.stringConcat('copy of ', files[0].file_name);
          files[0].last_modified_date = currentDateTime;
          files[0].creation_date = currentDateTime;
          return files;
        })
        .then(duplicatedFile =>
          sqlCommands.insertContent(constants.ENTITIES_FILE_MANAGER, duplicatedFile)
          .then(() =>
            resolve(duplicatedFile)
          )
          .catch(sqlError => reject(sqlError)))
        .catch(sqlError => reject(sqlError));
      })
      .catch(sqlError => reject(sqlError));
    });
  }

  static createNewFolder(organizationId, folderPath, folderId) {
    return new Promise((resolve, reject) =>
      // set default new ID if not exist (already have 0)
      sqlCommands.getMaxFolderId()
      .then((maxId) => {
        const newFolderId = maxId + 1;
        const newFolderName = constants.DEFAULT_FOLDER_NAME;
        const newFolderPath = stringManipulator.stringConcat(folderPath, newFolderName, '/');
        return createNewFolder(organizationId, newFolderPath, folderId, newFolderId, newFolderName)
        .then(data => resolve(data))
        .catch(err => reject(err));
      }).catch(sqlError => reject(sqlError))
    );
  }
}
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const RequestHandler = require('./request_handler');
const TestPlayerClient = require('./test_player_client');

class TestContextBase
{
    constructor()
    {
        const { BEEFWEB_TEST_BUILD_TYPE, BEEFWEB_TEST_PORT } = process.env;

        const testsRootDir = path.dirname(__dirname);
        const rootDir = path.dirname(path.dirname(testsRootDir));
        const buildType = BEEFWEB_TEST_BUILD_TYPE || 'debug';
        const port = parseInt(BEEFWEB_TEST_PORT) || 8879;
        const serverUrl = `http://localhost:${port}`;

        const toolsDir = path.join(rootDir, 'tools');
        const webRootDir = path.join(testsRootDir, 'webroot');
        const musicDir = path.join(testsRootDir, 'tracks');

        const pluginSettings = {
            port,
            allowRemote: false,
            musicDirs: [musicDir],
            staticDir: webRootDir,
        };

        const config = {
            buildType,
            port,
            serverUrl,
            rootDir,
            testsRootDir,
            toolsDir,
            webRootDir,
            musicDir,
            pluginSettings,
        };

        this.initConfig(config);
        this.config = Object.freeze(config);

        this.client = new TestPlayerClient(new RequestHandler(serverUrl));
        this.player = this.createController(config);

        this.tracks = Object.freeze({
            t1: path.join(musicDir, 'track1.flac'),
            t2: path.join(musicDir, 'track2.flac'),
            t3: path.join(musicDir, 'subdir', 'track3.flac'),
        });

        this.usePlayer = this.usePlayer.bind(this);
    }

    usePlayer(options = {})
    {
        const pluginSettings = Object.assign(
            {}, this.config.pluginSettings, options.pluginSettings);

        const axiosConfig = options.axiosConfig || null;
        const environment = options.environment || null;

        this.options = { pluginSettings, axiosConfig, environment };

        return {
            before: () => this.beginModule(),
            after: () => this.endModule(),
            beforeEach: () => this.beginTest(),
            afterEach: () => this.endTest(),
        };
    }

    async beginModule()
    {
        const { axiosConfig } = this.options;

        await this.player.start(this.options);

        this.client.handler.init(axiosConfig);

        if (await this.client.waitUntilReady())
            return;

        const logData = await this.player.getLog();

        if (logData)
            console.error('Player run log:\n%s', logData);

        throw Error('Failed to reach API endpoint');
    }

    async endModule()
    {
        await this.player.stop();
    }

    async beginTest()
    {
        this.client.handler.init(this.options.axiosConfig);
        await this.client.resetState();
    }

    endTest()
    {
        this.client.handler.shutdown();
    }

    initConfig(config)
    {
        throw new Error('initConfig() is not implemented');
    }

    createController(config)
    {
        throw new Error('createController() is not implemented');
    }
}

module.exports = TestContextBase;
<commit_msg>api_tests: fix regression with init<commit_after>'use strict';

const path = require('path');
const RequestHandler = require('./request_handler');
const TestPlayerClient = require('./test_player_client');

class TestContextBase
{
    constructor()
    {
        const { BEEFWEB_TEST_BUILD_TYPE, BEEFWEB_TEST_PORT } = process.env;

        const testsRootDir = path.dirname(__dirname);
        const rootDir = path.dirname(path.dirname(testsRootDir));
        const buildType = BEEFWEB_TEST_BUILD_TYPE || 'debug';
        const port = parseInt(BEEFWEB_TEST_PORT) || 8879;
        const serverUrl = `http://localhost:${port}`;

        const toolsDir = path.join(rootDir, 'tools');
        const webRootDir = path.join(testsRootDir, 'webroot');
        const musicDir = path.join(testsRootDir, 'tracks');

        const pluginSettings = {
            port,
            allowRemote: false,
            musicDirs: [musicDir],
            staticDir: webRootDir,
        };

        const config = {
            buildType,
            port,
            serverUrl,
            rootDir,
            testsRootDir,
            toolsDir,
            webRootDir,
            musicDir,
            pluginSettings,
        };

        this.initConfig(config);
        this.config = Object.freeze(config);

        this.client = new TestPlayerClient(new RequestHandler(serverUrl));
        this.player = this.createController(config);

        this.tracks = Object.freeze({
            t1: path.join(musicDir, 'track1.flac'),
            t2: path.join(musicDir, 'track2.flac'),
            t3: path.join(musicDir, 'subdir', 'track3.flac'),
        });

        this.usePlayer = this.usePlayer.bind(this);
    }

    usePlayer(options = {})
    {
        const pluginSettings = Object.assign(
            {}, this.config.pluginSettings, options.pluginSettings);

        const axiosConfig = options.axiosConfig || null;
        const environment = options.environment || null;

        options = { pluginSettings, axiosConfig, environment };

        return {
            before: () => this.beginModule(options),
            after: () => this.endModule(),
            beforeEach: () => this.beginTest(options),
            afterEach: () => this.endTest(),
        };
    }

    async beginModule(options)
    {
        await this.player.start(options);

        this.client.handler.init(options.axiosConfig);

        if (await this.client.waitUntilReady())
            return;

        const logData = await this.player.getLog();

        if (logData)
            console.error('Player run log:\n%s', logData);

        throw Error('Failed to reach API endpoint');
    }

    async endModule()
    {
        await this.player.stop();
    }

    async beginTest(options)
    {
        this.client.handler.init(options.axiosConfig);
        await this.client.resetState();
    }

    endTest()
    {
        this.client.handler.shutdown();
    }

    initConfig(config)
    {
        throw new Error('initConfig() is not implemented');
    }

    createController(config)
    {
        throw new Error('createController() is not implemented');
    }
}

module.exports = TestContextBase;
<|endoftext|>