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

/*
 * A bucket that can be used to store spherical objects.  Manages the addition and removal of the spheres, stacks them
 * as they are added, and manages the stack as spheres are removed.
 *
 * This expects the spheres to have certain properties, please inspect the code to understand the 'contract' between the
 * bucket and the spheres.
 *
 * @author John Blanco
 */
define( function( require ) {
  'use strict';

  // modules
  var cleanArray = require( 'PHET_CORE/cleanArray' );
  var Vector2 = require( 'DOT/Vector2' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Bucket = require( 'PHETCOMMON/model/Bucket' );
  var phetcommon = require( 'PHETCOMMON/phetcommon' );

  /**
   * @param {Object} options
   * @constructor
   */
  function SphereBucket( options ) {
    Bucket.call( this, options );
    options = _.extend( {
      tandemName: null,
      sphereRadius: 10,  // expected radius of the spheres that will be placed in this bucket
      usableWidthProportion: 1.0  // proportion of the bucket width that the spheres can occupy
    }, options );
    this.tandemName = options.tandemName;

    this._sphereRadius = options.sphereRadius;
    this._usableWidthProportion = options.usableWidthProportion;

    // Empirically determined, for positioning particles inside the bucket.
    this._verticalParticleOffset = options.verticalParticleOffset || -this._sphereRadius * 0.4;

    // particles managed by this bucket
    this._particles = [];
  }

  phetcommon.register( 'SphereBucket', SphereBucket );

  // Inherit from base type.
  inherit( Bucket, SphereBucket, {

    // @public
    addParticleFirstOpen: function( particle, animate ) {
      particle.destinationProperty.set( this.getFirstOpenLocation() );
      this.addParticle( particle, animate );
    },

    // @public
    addParticleNearestOpen: function( particle, animate ) {
      particle.destinationProperty.set( this.getNearestOpenLocation( particle.destinationProperty.get() ) );
      this.addParticle( particle, animate );
    },

    // @private
    addParticle: function( particle, animate ) {
      if ( !animate ) {
        particle.positionProperty.set( particle.destinationProperty.get() );
      }
      this._particles.push( particle );
      var self = this;
      var particleRemovedListener = function( userControlled ) {
        self.removeParticle( particle );
        particle.userControlledProperty.unlink( particleRemovedListener );
        delete particle.bucketRemovalListener;
      };
      particle.userControlledProperty.lazyLink( particleRemovedListener );
      particle.bucketRemovalListener = particleRemovedListener; // Attach to the particle to aid unlinking in some cases.
    },

    // @public
    removeParticle: function( particle, skipLayout ) {
      if ( this._particles.indexOf( particle ) === -1 ) {
        console.log( 'Error: Attempt to remove particle not contained in bucket, ignoring.' );
        return;
      }
      this._particles = _.without( this._particles, particle );
      if ( !skipLayout ) {
        this.relayoutBucketParticles();
      }
    },

    // @public
    containsParticle: function( particle ) {
      return this._particles.indexOf( particle ) !== -1;
    },

    // @public
    extractClosestParticle: function( location ) {
      var closestParticle = null;
      this._particles.forEach( function( particle ) {
        if ( closestParticle === null ||
             closestParticle.positionProperty.get().distance( location ) > particle.positionProperty.get().distance( location ) ) {
          closestParticle = particle;
        }
      } );
      if ( closestParticle !== null ) {
        // The particle is removed by setting 'userControlled' to true.  This
        // relies on the listener that was added when the particle was placed
        // into the bucket.
        closestParticle.userControlledProperty.set( true );
      }
      return closestParticle;
    },

    // @public
    getParticleList: function() { return this._particles; },

    // @public
    reset: function() {
      this._particles.forEach( function( particle ) {
        // Remove listeners that are watching for removal from bucket.
        if ( typeof( particle.bucketRemovalListener ) === 'function' ) {
          particle.userControlledProperty.unlink( particle.bucketRemovalListener );
          delete particle.bucketRemovalListener;
        }
      } );
      cleanArray( this._particles );
    },

    // @private
    isPositionOpen: function( position ) {
      var positionOpen = true;
      for ( var i = 0; i < this._particles.length; i++ ) {
        var particle = this._particles[ i ];
        if ( particle.destinationProperty.get().equals( position ) ) {
          positionOpen = false;
          break;
        }
      }
      return positionOpen;
    },

    // @private
    getFirstOpenLocation: function() {
      var openLocation = Vector2.ZERO;
      var usableWidth = this.size.width * this._usableWidthProportion - 2 * this._sphereRadius;
      var offsetFromBucketEdge = ( this.size.width - usableWidth ) / 2 + this._sphereRadius;
      var numParticlesInLayer = Math.floor( usableWidth / ( this._sphereRadius * 2 ) );
      var row = 0;
      var positionInLayer = 0;
      var found = false;
      while ( !found ) {
        var testLocation = new Vector2( this.position.x - this.size.width / 2 + offsetFromBucketEdge + positionInLayer * 2 * this._sphereRadius,
          this.getYPositionForLayer( row ) );
        if ( this.isPositionOpen( testLocation ) ) {
          // We found a location that is open.
          openLocation = testLocation;
          found = true;
        }
        else {
          positionInLayer++;
          if ( positionInLayer >= numParticlesInLayer ) {
            // Move to the next layer.
            row++;
            positionInLayer = 0;
            numParticlesInLayer--;
            offsetFromBucketEdge += this._sphereRadius;
            if ( numParticlesInLayer === 0 ) {
              // This algorithm doesn't handle the situation where
              // more particles are added than can be stacked into
              // a pyramid of the needed size, but so far it hasn't
              // needed to.  If this requirement changes, the
              // algorithm will need to change too.
              numParticlesInLayer = 1;
              offsetFromBucketEdge -= this._sphereRadius;
            }
          }
        }
      }
      return openLocation;
    },

    // @private
    getLayerForYPosition: function( yPosition ) {
      return Math.abs( Math.round( ( yPosition - ( this.position.y + this._verticalParticleOffset ) ) / ( this._sphereRadius * 2 * 0.866 ) ) );
    },

    /*
     * Get the nearest open location to the provided current location.  This is used for particle stacking.
     *
     * @param {Vector2} position
     * @return {Vector2}
     * @private
     */
    getNearestOpenLocation: function( position ) {
      // Determine the highest occupied layer.  The bottom layer is 0.
      var highestOccupiedLayer = 0;
      var self = this;
      _.each( this._particles, function( particle ) {
        var layer = self.getLayerForYPosition( particle.destinationProperty.get().y );
        if ( layer > highestOccupiedLayer ) {
          highestOccupiedLayer = layer;
        }
      } );

      // Make a list of all open locations in the occupied layers.
      var openLocations = [];
      var usableWidth = this.size.width * this._usableWidthProportion - 2 * this._sphereRadius;
      var offsetFromBucketEdge = ( this.size.width - usableWidth ) / 2 + this._sphereRadius;
      var numParticlesInLayer = Math.floor( usableWidth / ( this._sphereRadius * 2 ) );

      // Loop, searching for open positions in the particle stack.
      for ( var layer = 0; layer <= highestOccupiedLayer + 1; layer++ ) {

        // Add all open locations in the current layer.
        for ( var positionInLayer = 0; positionInLayer < numParticlesInLayer; positionInLayer++ ) {
          var testPosition = new Vector2( this.position.x - this.size.width / 2 + offsetFromBucketEdge + positionInLayer * 2 * this._sphereRadius,
            this.getYPositionForLayer( layer ) );
          if ( this.isPositionOpen( testPosition ) ) {

            // We found a location that is unoccupied.
            if ( layer === 0 || this.countSupportingParticles( testPosition ) === 2 ) {
              // This is a valid open location.
              openLocations.push( testPosition );
            }
          }
        }

        // Adjust variables for the next layer.
        numParticlesInLayer--;
        offsetFromBucketEdge += this._sphereRadius;
        if ( numParticlesInLayer === 0 ) {
          // If the stacking pyramid is full, meaning that there are
          // no locations that are open within it, this algorithm
          // classifies the locations directly above the top of the
          // pyramid as being open.  This would result in a stack
          // of particles with a pyramid base.  So far, this hasn't
          // been a problem, but this limitation may limit
          // reusability of this algorithm.
          numParticlesInLayer = 1;
          offsetFromBucketEdge -= this._sphereRadius;
        }
      }

      // Find the closest open location to the provided current location.
      // Only the X-component is used for this determination, because if
      // the Y-component is used the particles often appear to fall sideways
      // when released above the bucket, which just looks weird.
      var closestOpenLocation = openLocations[ 0 ] || Vector2.ZERO;

      _.each( openLocations, function( location ) {
        if ( location.distance( position ) < closestOpenLocation.distance( position ) ) {
          // This location is closer.
          closestOpenLocation = location;
        }
      } );
      return closestOpenLocation;
    },

    // @private
    getYPositionForLayer: function( layer ) {
      return this.position.y + this._verticalParticleOffset + layer * this._sphereRadius * 2 * 0.866;
    },

    /*
     * Determine whether a particle is 'dangling', i.e. hanging above an open
     * space in the stack of particles.  Dangling particles should fall.
     * @private
     */
    isDangling: function( particle ) {
      var onBottomRow = particle.destinationProperty.get().y === this.position.y + this._verticalParticleOffset;
      return !onBottomRow && this.countSupportingParticles( particle.destinationProperty.get() ) < 2;
    },

    // @private
    countSupportingParticles: function( position ) {
      var count = 0;
      for ( var i = 0; i < this._particles.length; i++ ) {
        var p = this._particles[ i ];
        if ( p.destinationProperty.get().y < position.y && // Must be in a lower layer
             p.destinationProperty.get().distance( position ) < this._sphereRadius * 3 ) {
          // Must be a supporting particle.
          count++;
        }
      }
      return count;
    },

    // @private
    relayoutBucketParticles: function() {
      var particleMoved;
      do {
        for ( var i = 0; i < this._particles.length; i++ ) {
          particleMoved = false;
          var particle = this._particles[ i ];
          if ( this.isDangling( particle ) ) {
            particle.destinationProperty.set( this.getNearestOpenLocation( particle.destinationProperty.get() ) );
            particleMoved = true;
            break;
          }
        }
      } while ( particleMoved );
    }

  } );

  return SphereBucket;
} );
<commit_msg>continued instrumenting Build and Atom, see https://github.com/phetsims/build-an-atom/issues/107<commit_after>// Copyright 2013-2015, University of Colorado Boulder

/*
 * A bucket that can be used to store spherical objects.  Manages the addition and removal of the spheres, stacks them
 * as they are added, and manages the stack as spheres are removed.
 *
 * This expects the spheres to have certain properties, please inspect the code to understand the 'contract' between the
 * bucket and the spheres.
 *
 * @author John Blanco
 */
define( function( require ) {
  'use strict';

  // modules
  var Bucket = require( 'PHETCOMMON/model/Bucket' );
  var cleanArray = require( 'PHET_CORE/cleanArray' );
  var inherit = require( 'PHET_CORE/inherit' );
  var phetcommon = require( 'PHETCOMMON/phetcommon' );
  var Tandem = require( 'TANDEM/Tandem' );
  var Vector2 = require( 'DOT/Vector2' );

  /**
   * @param {Object} options
   * @constructor
   */
  function SphereBucket( options ) {
    Bucket.call( this, options );
    options = _.extend( {
      sphereRadius: 10,  // expected radius of the spheres that will be placed in this bucket
      usableWidthProportion: 1.0,  // proportion of the bucket width that the spheres can occupy
      tandem: Tandem.tandemOptional()
    }, options );
    this.sphereBucketTandem = options.tandem;

    this._sphereRadius = options.sphereRadius;
    this._usableWidthProportion = options.usableWidthProportion;

    // Empirically determined, for positioning particles inside the bucket.
    this._verticalParticleOffset = options.verticalParticleOffset || -this._sphereRadius * 0.4;

    // particles managed by this bucket
    this._particles = [];
  }

  phetcommon.register( 'SphereBucket', SphereBucket );

  // Inherit from base type.
  inherit( Bucket, SphereBucket, {

    // @public
    addParticleFirstOpen: function( particle, animate ) {
      particle.destinationProperty.set( this.getFirstOpenLocation() );
      this.addParticle( particle, animate );
    },

    // @public
    addParticleNearestOpen: function( particle, animate ) {
      particle.destinationProperty.set( this.getNearestOpenLocation( particle.destinationProperty.get() ) );
      this.addParticle( particle, animate );
    },

    // @private
    addParticle: function( particle, animate ) {
      if ( !animate ) {
        particle.positionProperty.set( particle.destinationProperty.get() );
      }
      this._particles.push( particle );
      var self = this;
      var particleRemovedListener = function( userControlled ) {
        self.removeParticle( particle );
        particle.userControlledProperty.unlink( particleRemovedListener );
        delete particle.bucketRemovalListener;
      };
      particle.userControlledProperty.lazyLink( particleRemovedListener );
      particle.bucketRemovalListener = particleRemovedListener; // Attach to the particle to aid unlinking in some cases.
    },

    // @public
    removeParticle: function( particle, skipLayout ) {
      if ( this._particles.indexOf( particle ) === -1 ) {
        console.log( 'Error: Attempt to remove particle not contained in bucket, ignoring.' );
        return;
      }
      this._particles = _.without( this._particles, particle );
      if ( !skipLayout ) {
        this.relayoutBucketParticles();
      }
    },

    // @public
    containsParticle: function( particle ) {
      return this._particles.indexOf( particle ) !== -1;
    },

    // @public
    extractClosestParticle: function( location ) {
      var closestParticle = null;
      this._particles.forEach( function( particle ) {
        if ( closestParticle === null ||
             closestParticle.positionProperty.get().distance( location ) > particle.positionProperty.get().distance( location ) ) {
          closestParticle = particle;
        }
      } );
      if ( closestParticle !== null ) {
        // The particle is removed by setting 'userControlled' to true.  This
        // relies on the listener that was added when the particle was placed
        // into the bucket.
        closestParticle.userControlledProperty.set( true );
      }
      return closestParticle;
    },

    // @public
    getParticleList: function() { return this._particles; },

    // @public
    reset: function() {
      this._particles.forEach( function( particle ) {
        // Remove listeners that are watching for removal from bucket.
        if ( typeof( particle.bucketRemovalListener ) === 'function' ) {
          particle.userControlledProperty.unlink( particle.bucketRemovalListener );
          delete particle.bucketRemovalListener;
        }
      } );
      cleanArray( this._particles );
    },

    // @private
    isPositionOpen: function( position ) {
      var positionOpen = true;
      for ( var i = 0; i < this._particles.length; i++ ) {
        var particle = this._particles[ i ];
        if ( particle.destinationProperty.get().equals( position ) ) {
          positionOpen = false;
          break;
        }
      }
      return positionOpen;
    },

    // @private
    getFirstOpenLocation: function() {
      var openLocation = Vector2.ZERO;
      var usableWidth = this.size.width * this._usableWidthProportion - 2 * this._sphereRadius;
      var offsetFromBucketEdge = ( this.size.width - usableWidth ) / 2 + this._sphereRadius;
      var numParticlesInLayer = Math.floor( usableWidth / ( this._sphereRadius * 2 ) );
      var row = 0;
      var positionInLayer = 0;
      var found = false;
      while ( !found ) {
        var testLocation = new Vector2( this.position.x - this.size.width / 2 + offsetFromBucketEdge + positionInLayer * 2 * this._sphereRadius,
          this.getYPositionForLayer( row ) );
        if ( this.isPositionOpen( testLocation ) ) {
          // We found a location that is open.
          openLocation = testLocation;
          found = true;
        }
        else {
          positionInLayer++;
          if ( positionInLayer >= numParticlesInLayer ) {
            // Move to the next layer.
            row++;
            positionInLayer = 0;
            numParticlesInLayer--;
            offsetFromBucketEdge += this._sphereRadius;
            if ( numParticlesInLayer === 0 ) {
              // This algorithm doesn't handle the situation where
              // more particles are added than can be stacked into
              // a pyramid of the needed size, but so far it hasn't
              // needed to.  If this requirement changes, the
              // algorithm will need to change too.
              numParticlesInLayer = 1;
              offsetFromBucketEdge -= this._sphereRadius;
            }
          }
        }
      }
      return openLocation;
    },

    // @private
    getLayerForYPosition: function( yPosition ) {
      return Math.abs( Math.round( ( yPosition - ( this.position.y + this._verticalParticleOffset ) ) / ( this._sphereRadius * 2 * 0.866 ) ) );
    },

    /*
     * Get the nearest open location to the provided current location.  This is used for particle stacking.
     *
     * @param {Vector2} position
     * @return {Vector2}
     * @private
     */
    getNearestOpenLocation: function( position ) {
      // Determine the highest occupied layer.  The bottom layer is 0.
      var highestOccupiedLayer = 0;
      var self = this;
      _.each( this._particles, function( particle ) {
        var layer = self.getLayerForYPosition( particle.destinationProperty.get().y );
        if ( layer > highestOccupiedLayer ) {
          highestOccupiedLayer = layer;
        }
      } );

      // Make a list of all open locations in the occupied layers.
      var openLocations = [];
      var usableWidth = this.size.width * this._usableWidthProportion - 2 * this._sphereRadius;
      var offsetFromBucketEdge = ( this.size.width - usableWidth ) / 2 + this._sphereRadius;
      var numParticlesInLayer = Math.floor( usableWidth / ( this._sphereRadius * 2 ) );

      // Loop, searching for open positions in the particle stack.
      for ( var layer = 0; layer <= highestOccupiedLayer + 1; layer++ ) {

        // Add all open locations in the current layer.
        for ( var positionInLayer = 0; positionInLayer < numParticlesInLayer; positionInLayer++ ) {
          var testPosition = new Vector2( this.position.x - this.size.width / 2 + offsetFromBucketEdge + positionInLayer * 2 * this._sphereRadius,
            this.getYPositionForLayer( layer ) );
          if ( this.isPositionOpen( testPosition ) ) {

            // We found a location that is unoccupied.
            if ( layer === 0 || this.countSupportingParticles( testPosition ) === 2 ) {
              // This is a valid open location.
              openLocations.push( testPosition );
            }
          }
        }

        // Adjust variables for the next layer.
        numParticlesInLayer--;
        offsetFromBucketEdge += this._sphereRadius;
        if ( numParticlesInLayer === 0 ) {
          // If the stacking pyramid is full, meaning that there are
          // no locations that are open within it, this algorithm
          // classifies the locations directly above the top of the
          // pyramid as being open.  This would result in a stack
          // of particles with a pyramid base.  So far, this hasn't
          // been a problem, but this limitation may limit
          // reusability of this algorithm.
          numParticlesInLayer = 1;
          offsetFromBucketEdge -= this._sphereRadius;
        }
      }

      // Find the closest open location to the provided current location.
      // Only the X-component is used for this determination, because if
      // the Y-component is used the particles often appear to fall sideways
      // when released above the bucket, which just looks weird.
      var closestOpenLocation = openLocations[ 0 ] || Vector2.ZERO;

      _.each( openLocations, function( location ) {
        if ( location.distance( position ) < closestOpenLocation.distance( position ) ) {
          // This location is closer.
          closestOpenLocation = location;
        }
      } );
      return closestOpenLocation;
    },

    // @private
    getYPositionForLayer: function( layer ) {
      return this.position.y + this._verticalParticleOffset + layer * this._sphereRadius * 2 * 0.866;
    },

    /*
     * Determine whether a particle is 'dangling', i.e. hanging above an open
     * space in the stack of particles.  Dangling particles should fall.
     * @private
     */
    isDangling: function( particle ) {
      var onBottomRow = particle.destinationProperty.get().y === this.position.y + this._verticalParticleOffset;
      return !onBottomRow && this.countSupportingParticles( particle.destinationProperty.get() ) < 2;
    },

    // @private
    countSupportingParticles: function( position ) {
      var count = 0;
      for ( var i = 0; i < this._particles.length; i++ ) {
        var p = this._particles[ i ];
        if ( p.destinationProperty.get().y < position.y && // Must be in a lower layer
             p.destinationProperty.get().distance( position ) < this._sphereRadius * 3 ) {
          // Must be a supporting particle.
          count++;
        }
      }
      return count;
    },

    // @private
    relayoutBucketParticles: function() {
      var particleMoved;
      do {
        for ( var i = 0; i < this._particles.length; i++ ) {
          particleMoved = false;
          var particle = this._particles[ i ];
          if ( this.isDangling( particle ) ) {
            particle.destinationProperty.set( this.getNearestOpenLocation( particle.destinationProperty.get() ) );
            particleMoved = true;
            break;
          }
        }
      } while ( particleMoved );
    }

  } );

  return SphereBucket;
} );
<|endoftext|>


<commit_before>
/**
  REQ_CONTEX
        1000 -> signup
        2000 -> signin
        3000 -> account_verify
        4000 -> recovery_password

  REQ_ACTION
        1000:1010 -> createNewUser

        2000:2010 -> login
        2000:2020 -> logout

        3000:3010 -> checkAccount
        3000:3020 -> validateAccountEmail
        3000:3030 -> validateAccountCode

        4000:4010 -> recoveryPasswordEmail
        4000:4020 -> recoveryPasswordCode
        4000:4030 -> recoveryPasswordReset

 */

const AuthenticationController = require('./AuthenticationController')
const AccountPolicy = require('../policies/AccountPolicy')
const main = this
main['httpRequest'] = null
main['httpResponse'] = null
main['REQ_CONTEX'] = 0
main['REQ_ACTION'] = 0
main['REQ_INPUTS'] = {}

function preparams () {
  let msg = null
  if (!main.httpRequest) { msg = 'Error [Http] [missing httpRequest]' }
  if (!main.httpResponse) { msg = 'Error [Http] [missing httpResponse]' }
  const body = main.httpRequest.body
  const {REQ_CONTEX, REQ_ACTION, REQ_INPUTS} = body
  if (!REQ_CONTEX) { msg = 'Error [Parameter] [missing REQ_CONTEXT]' }
  if (!REQ_ACTION) { msg = 'Error [Parameter] [missing REQ_ACTION]' }
  if (!REQ_INPUTS) { msg = 'Error [Parameter] [missing REQ_INPUTS]' }
  if (msg) { return {isok: false, error: msg} }
  main.REQ_CONTEX = REQ_CONTEX
  main.REQ_ACTION = REQ_ACTION
  main.REQ_INPUTS = REQ_INPUTS
  /** use debug mode */
  console.log(main.REQ_CONTEX, main.REQ_ACTION, main.REQ_INPUTS)
  return {isok: true, error: msg}
}
function validateSignInAndUp () { return AccountPolicy.validateSignInAndUp(main.REQ_INPUTS) }
function accountRecovery (mode) { return AccountPolicy.accountRecovery(mode, main.REQ_INPUTS) }
module.exports = {
  async execute (req, res) {
    console.log('Account Management execute')
    main.httpRequest = req
    main.httpResponse = res
    const paramValidator = preparams()
    let checkpoint = null
    if (paramValidator.isok) {
      // checkAccountStatus API
      if (main.REQ_CONTEX === AuthenticationController.options.CHECKACCOUNTSTATUS) {
        if (main.REQ_ACTION === AuthenticationController.options.onCheckAccountStatus) {
          accountStatus()
        } else if (main.REQ_ACTION === AuthenticationController.options.onGenerateAccountCode) {
          generateAccountCode()
        } else if (main.REQ_ACTION === AuthenticationController.options.onGenerateAccountCode) {
          validateAccountCode()
        } else {
          responseSender({status: 400, output: {error: 'REQ_ACTION not found.', isok: false}})
        }
        return true
      }
      if (main.REQ_CONTEX === AuthenticationController.options.ACCOUNT_RECOVERY) {
        let mode = null
        if (main.REQ_ACTION === AuthenticationController.options.ACCOUNT_RECOVERY_EMAIL) {
          mode = 'email'
        }
        if (main.REQ_ACTION === AuthenticationController.options.ACCOUNT_RECOVERY_RESET) {
          mode = 'reset'
        }
        if (mode) {
          checkpoint = accountRecovery(mode)
        }
        if ((checkpoint && checkpoint.isok) || main.REQ_ACTION === AuthenticationController.options.ACCOUNT_RECOVERY_CODE) {
          passwordRecovery()
        } else {
          responseSender({status: 400, output: checkpoint})
        }
        return true
      }
      if (main.REQ_CONTEX === AuthenticationController.options.SIGNUP) {
        if (main.REQ_ACTION === AuthenticationController.options.NEW_SIGNUP) {
          checkpoint = validateSignInAndUp()
          if (checkpoint.isok) {
            signup()
          } else {
            responseSender({status: 400, output: checkpoint})
          }
          return true
        }
      }
      if (main.REQ_CONTEX === AuthenticationController.options.SIGNIN) {
        if (main.REQ_ACTION === AuthenticationController.options.ON_SIGNIN) {
          checkpoint = validateSignInAndUp()
          if (checkpoint.isok) {
            signin()
          } else {
            responseSender({status: 400, output: checkpoint})
          }
        } else if (main.REQ_ACTION === AuthenticationController.options.ON_SIGNOUT) {
          signout()
        }
        return true
      }
      if (main.REQ_CONTEX === AuthenticationController.options.backoffice) {
        if (main.REQ_ACTION === AuthenticationController.options.backoffice_hardReset) {
          const _res = await backOfficeHardReset(main.REQ_INPUTS)
          if (_res) {
            console.log(_res)
          }
        }
      }
      if (main.REQ_CONTEX === 659832) {
        if (main.REQ_ACTION === 659832) {
          sendSMS(main.REQ_INPUTS)
        }
      }
      return true
    }
    const error = (paramValidator.error && paramValidator.error.length !== 0) ? paramValidator.error : 'Não foi possivel concluir o pedido requerido. Por favor tente mais tarde. Obrigado.'
    responseSender({status: 500, output: {error: error}})
  }
}

async function signup () {
  try {
    const result = await AuthenticationController.signup(main.REQ_INPUTS)
    return responseSender(result)
  } catch (error) {
    console.log(error)
  }
}

async function signin () {
  try {
    const result = await AuthenticationController.signin(main.REQ_INPUTS)
    return responseSender(result)
  } catch (error) {
    console.log(error)
  }
}

async function signout () {
  const result = await AuthenticationController.signout(main)
  return responseSender(result)
}

async function passwordRecovery () {
  const result = await AuthenticationController.passwordRecovery(main)
  return responseSender(result)
}

async function accountStatus () {
  const result = await AuthenticationController.accountStatus(main)
  return responseSender(result)
}

async function generateAccountCode () {
  const result = await AuthenticationController.generateAccountCode(main)
  return responseSender(result)
}

async function validateAccountCode () {
  const result = await AuthenticationController.validateAccountCode(main)
  return responseSender(result)
}

async function backOfficeHardReset (credentials) {
  const result = await AuthenticationController.backOfficeHardReset(credentials)
  return responseSender(result)
}

function responseSender (result) {
  main.httpResponse.status(result.status).send(result.output)
  return result
}

async function sendSMS (credentials) {
  try {
    const buddySecret = require('../utils/SecretFriendSms')
    buddySecret.credentials(credentials.username, credentials.password)
    const contactsList = []
    contactsList.push({name: 'Oscar Campos', mobile: '+351913859014'})
    contactsList.push({name: 'Melissa Martinez', mobile: '+351912329091'})
    contactsList.push({name: 'João Campos', mobile: '+351962504421'})
    contactsList.push({name: 'Alice Pires', mobile: '+351925485839'})
    contactsList.push({name: 'Paulo Pires', mobile: '+351912238628'})
    contactsList.push({name: 'Olga Pinho', mobile: '+351918406762'})
    contactsList.push({name: 'Lucas Pires', mobile: '+351927563654'})
    buddySecret.adicionarListaContactos(contactsList)
    const responses = await buddySecret.sentBulkSms()
    if (responses) {
      console.log(responses)
    }
    main.httpResponse.status(responses.status).send({result: responses.output})
  } catch (error) {
    console.log(error)
  }
  /**
  const BulkSMS = require('../utils/BulkSMS')
  const sms = new BulkSMS('', '')
  sms.send('+351913859014', 'teste', (err, result) => {
    if (err) {
      console.log(err)
      return false
    }
    console.log(result)
    return true
  })
  */
}
<commit_msg>fix nr mb<commit_after>
/**
  REQ_CONTEX
        1000 -> signup
        2000 -> signin
        3000 -> account_verify
        4000 -> recovery_password

  REQ_ACTION
        1000:1010 -> createNewUser

        2000:2010 -> login
        2000:2020 -> logout

        3000:3010 -> checkAccount
        3000:3020 -> validateAccountEmail
        3000:3030 -> validateAccountCode

        4000:4010 -> recoveryPasswordEmail
        4000:4020 -> recoveryPasswordCode
        4000:4030 -> recoveryPasswordReset

 */

const AuthenticationController = require('./AuthenticationController')
const AccountPolicy = require('../policies/AccountPolicy')
const main = this
main['httpRequest'] = null
main['httpResponse'] = null
main['REQ_CONTEX'] = 0
main['REQ_ACTION'] = 0
main['REQ_INPUTS'] = {}

function preparams () {
  let msg = null
  if (!main.httpRequest) { msg = 'Error [Http] [missing httpRequest]' }
  if (!main.httpResponse) { msg = 'Error [Http] [missing httpResponse]' }
  const body = main.httpRequest.body
  const {REQ_CONTEX, REQ_ACTION, REQ_INPUTS} = body
  if (!REQ_CONTEX) { msg = 'Error [Parameter] [missing REQ_CONTEXT]' }
  if (!REQ_ACTION) { msg = 'Error [Parameter] [missing REQ_ACTION]' }
  if (!REQ_INPUTS) { msg = 'Error [Parameter] [missing REQ_INPUTS]' }
  if (msg) { return {isok: false, error: msg} }
  main.REQ_CONTEX = REQ_CONTEX
  main.REQ_ACTION = REQ_ACTION
  main.REQ_INPUTS = REQ_INPUTS
  /** use debug mode */
  console.log(main.REQ_CONTEX, main.REQ_ACTION, main.REQ_INPUTS)
  return {isok: true, error: msg}
}
function validateSignInAndUp () { return AccountPolicy.validateSignInAndUp(main.REQ_INPUTS) }
function accountRecovery (mode) { return AccountPolicy.accountRecovery(mode, main.REQ_INPUTS) }
module.exports = {
  async execute (req, res) {
    console.log('Account Management execute')
    main.httpRequest = req
    main.httpResponse = res
    const paramValidator = preparams()
    let checkpoint = null
    if (paramValidator.isok) {
      // checkAccountStatus API
      if (main.REQ_CONTEX === AuthenticationController.options.CHECKACCOUNTSTATUS) {
        if (main.REQ_ACTION === AuthenticationController.options.onCheckAccountStatus) {
          accountStatus()
        } else if (main.REQ_ACTION === AuthenticationController.options.onGenerateAccountCode) {
          generateAccountCode()
        } else if (main.REQ_ACTION === AuthenticationController.options.onGenerateAccountCode) {
          validateAccountCode()
        } else {
          responseSender({status: 400, output: {error: 'REQ_ACTION not found.', isok: false}})
        }
        return true
      }
      if (main.REQ_CONTEX === AuthenticationController.options.ACCOUNT_RECOVERY) {
        let mode = null
        if (main.REQ_ACTION === AuthenticationController.options.ACCOUNT_RECOVERY_EMAIL) {
          mode = 'email'
        }
        if (main.REQ_ACTION === AuthenticationController.options.ACCOUNT_RECOVERY_RESET) {
          mode = 'reset'
        }
        if (mode) {
          checkpoint = accountRecovery(mode)
        }
        if ((checkpoint && checkpoint.isok) || main.REQ_ACTION === AuthenticationController.options.ACCOUNT_RECOVERY_CODE) {
          passwordRecovery()
        } else {
          responseSender({status: 400, output: checkpoint})
        }
        return true
      }
      if (main.REQ_CONTEX === AuthenticationController.options.SIGNUP) {
        if (main.REQ_ACTION === AuthenticationController.options.NEW_SIGNUP) {
          checkpoint = validateSignInAndUp()
          if (checkpoint.isok) {
            signup()
          } else {
            responseSender({status: 400, output: checkpoint})
          }
          return true
        }
      }
      if (main.REQ_CONTEX === AuthenticationController.options.SIGNIN) {
        if (main.REQ_ACTION === AuthenticationController.options.ON_SIGNIN) {
          checkpoint = validateSignInAndUp()
          if (checkpoint.isok) {
            signin()
          } else {
            responseSender({status: 400, output: checkpoint})
          }
        } else if (main.REQ_ACTION === AuthenticationController.options.ON_SIGNOUT) {
          signout()
        }
        return true
      }
      if (main.REQ_CONTEX === AuthenticationController.options.backoffice) {
        if (main.REQ_ACTION === AuthenticationController.options.backoffice_hardReset) {
          const _res = await backOfficeHardReset(main.REQ_INPUTS)
          if (_res) {
            console.log(_res)
          }
        }
      }
      if (main.REQ_CONTEX === 659832) {
        if (main.REQ_ACTION === 659832) {
          sendSMS(main.REQ_INPUTS)
        }
      }
      return true
    }
    const error = (paramValidator.error && paramValidator.error.length !== 0) ? paramValidator.error : 'Não foi possivel concluir o pedido requerido. Por favor tente mais tarde. Obrigado.'
    responseSender({status: 500, output: {error: error}})
  }
}

async function signup () {
  try {
    const result = await AuthenticationController.signup(main.REQ_INPUTS)
    return responseSender(result)
  } catch (error) {
    console.log(error)
  }
}

async function signin () {
  try {
    const result = await AuthenticationController.signin(main.REQ_INPUTS)
    return responseSender(result)
  } catch (error) {
    console.log(error)
  }
}

async function signout () {
  const result = await AuthenticationController.signout(main)
  return responseSender(result)
}

async function passwordRecovery () {
  const result = await AuthenticationController.passwordRecovery(main)
  return responseSender(result)
}

async function accountStatus () {
  const result = await AuthenticationController.accountStatus(main)
  return responseSender(result)
}

async function generateAccountCode () {
  const result = await AuthenticationController.generateAccountCode(main)
  return responseSender(result)
}

async function validateAccountCode () {
  const result = await AuthenticationController.validateAccountCode(main)
  return responseSender(result)
}

async function backOfficeHardReset (credentials) {
  const result = await AuthenticationController.backOfficeHardReset(credentials)
  return responseSender(result)
}

function responseSender (result) {
  main.httpResponse.status(result.status).send(result.output)
  return result
}

async function sendSMS (credentials) {
  try {
    const buddySecret = require('../utils/SecretFriendSms')
    buddySecret.credentials(credentials.username, credentials.password)
    const contactsList = []
    contactsList.push({name: 'Oscar Campos', mobile: '+3519138'})
    contactsList.push({name: 'Melissa Martinez', mobile: '+3519123'})
    contactsList.push({name: 'João Campos', mobile: '+3519625'})
    contactsList.push({name: 'Alice Pires', mobile: '+3519254'})
    contactsList.push({name: 'Paulo Pires', mobile: '+3519122'})
    contactsList.push({name: 'Olga Pinho', mobile: '+3519184'})
    contactsList.push({name: 'Lucas Pires', mobile: '+3519279'})
    buddySecret.adicionarListaContactos(contactsList)
    const responses = await buddySecret.sentBulkSms()
    if (responses) {
      console.log(responses)
    }
    main.httpResponse.status(responses.status).send({result: responses.output})
  } catch (error) {
    console.log(error)
  }
  /**
  const BulkSMS = require('../utils/BulkSMS')
  const sms = new BulkSMS('', '')
  sms.send('+351913859014', 'teste', (err, result) => {
    if (err) {
      console.log(err)
      return false
    }
    console.log(result)
    return true
  })
  */
}
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import { Route, Switch, Redirect } from 'react-router-dom'
import { Empty, Header, Navigation, Tab } from 'bonde-components'
import styled from 'styled-components'
import { useSession } from 'bonde-core-tools'
import Mobilizers from './Mobilizers'

const SubHeader = styled.div`
  display: flex;
  flex-direction: column;
  background-color: #000;
  padding: 0 60px;

  h3 {
    color: #fff;
    margin: 10px 0 30px;
  }
`

const SubContent = styled.div`
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  padding: 30px 60px;
`

const PageWrap = styled.div`
  display: flex;
  flex-direction: column;
  flex-grow: 1;
`

const CommunityPage = ({ match, location }) => {
  const { community } = useSession()

  // RegexWith parameters number
  // \/community\/\d+\/mobilizers\/*
  const isActive = new RegExp(/\/community\/mobilizers\/*/).test(location.pathname)

  return community ? (
    <PageWrap>
      <SubHeader>
        <Header.h3>{community.name}</Header.h3>
        <Navigation>
          <Tab active={isActive}>Mobilizadores</Tab>
          <Tab
            onClick={() => {
              if (process.env.REACT_APP_DOMAIN_ADMIN) {
                window.location.href = new URL('/community/settings', process.env.REACT_APP_DOMAIN_ADMIN).href;
              }
            }}
          >
            Outras configurações
          </Tab>
        </Navigation>
      </SubHeader>
      <SubContent>
        <Switch>
          <Route exact path={`${match.path}/mobilizers`}>
            <Mobilizers community={community} />
          </Route>
          <Redirect from={`${match.path}/settings`} to={`${match.path}/mobilizers`} />
        </Switch>
      </SubContent>
    </PageWrap>
  ) : <Empty message='Nada por aqui...' />
}

CommunityPage.propTypes = {
  location: PropTypes.object.isRequired,
  match: PropTypes.object.isRequired
}

export default CommunityPage
<commit_msg>fix(canary): add url to other settings community<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import { Route, Switch, Redirect } from 'react-router-dom'
import { Empty, Header, Navigation, Tab } from 'bonde-components'
import styled from 'styled-components'
import { useSession } from 'bonde-core-tools'
import Mobilizers from './Mobilizers'

const SubHeader = styled.div`
  display: flex;
  flex-direction: column;
  background-color: #000;
  padding: 0 60px;

  h3 {
    color: #fff;
    margin: 10px 0 30px;
  }
`

const SubContent = styled.div`
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  padding: 30px 60px;
`

const PageWrap = styled.div`
  display: flex;
  flex-direction: column;
  flex-grow: 1;
`

const CommunityPage = ({ match, location }) => {
  const { community } = useSession()

  // RegexWith parameters number
  // \/community\/\d+\/mobilizers\/*
  const isActive = new RegExp(/\/community\/mobilizers\/*/).test(location.pathname)

  return community ? (
    <PageWrap>
      <SubHeader>
        <Header.h3>{community.name}</Header.h3>
        <Navigation>
          <Tab active={isActive}>Mobilizadores</Tab>
          <Tab
            onClick={() => {
              if (process.env.REACT_APP_DOMAIN_ADMIN) {
                window.location.href = new URL('/community/settings', process.env.REACT_APP_DOMAIN_ADMIN).href
              }
            }}
          >
            Outras configurações
          </Tab>
        </Navigation>
      </SubHeader>
      <SubContent>
        <Switch>
          <Route exact path={`${match.path}/mobilizers`}>
            <Mobilizers community={community} />
          </Route>
          <Redirect from={`${match.path}/settings`} to={`${match.path}/mobilizers`} />
        </Switch>
      </SubContent>
    </PageWrap>
  ) : <Empty message='Nada por aqui...' />
}

CommunityPage.propTypes = {
  location: PropTypes.object.isRequired,
  match: PropTypes.object.isRequired
}

export default CommunityPage
<|endoftext|>


<commit_before>const Benchmark = require('benchmark');

const u = require('../lib');
const _ = require('lodash');

const suite = Benchmark.Suite(); // eslint-disable

const add = (x, y) => x + y;
const fakeCurryAdd = x => y => x + y;
const curryAdd = _.curry(add);

const array = [0, 1, 2, 3, 4, 5];

suite
  .add('regular function call', () => {
    add(3, 4);
  })
  .add('fake curry', () => {
    fakeCurryAdd(3)(4);
  })
  .add('curry full call', () => {
    curryAdd(3, 4);
  })
  .add('curry partial call', () => {
    curryAdd(3)(4);
  })
  .add('_.map', () => {
    _.map(array, curryAdd(8));
  })
  .add('u.map', () => {
    u.map(curryAdd(8), array);
  })
  .add('_.map no changes', () => {
    _.map(array, x => x);
  })
  .add('u.map no changes', () => {
    u.map(x => x, array);
  })

  .on('cycle', (event) => {
    if (typeof document !== 'undefined') {
      const el = document.getElementById('perf');
      el.innerHTML = el.innerHTML + String(event.target) + '
';
    }
  })
  .run({ async: true });
<commit_msg>Add lots of benchmark stuff<commit_after>const Benchmark = require('benchmark');

const u = require('../lib');
const _ = require('lodash');
const { curry2 } = require('../lib/util/curry');

const suite = Benchmark.Suite(); // eslint-disable

const add = (x, y) => x + y;
const fakeCurryAdd = x => y => x + y;
const curryAdd = _.curry(add);
const updeepCurry = curry2(add);
// const updeepCurryBig = curry.curryBig(add);

const array = [0, 1, 2, 3, 4, 5];
// const doUpdate = u(x => x + 1);

suite
.add('updeep curry partial call', () => {
  updeepCurry(3)(4);
})
.add('lodash curry partial call', () => {
  curryAdd(3)(4);
})
.add('_.map', () => {
  _.map(array, fakeCurryAdd(8));
})
.add('u.map', () => {
  u.map(fakeCurryAdd(8), array);
})
// .add('updeep curry', () => {
//   u.map(curryAdd(3), array);
// })
// .add('updeep big curry', () => {
//   u.map(curryAdd(3), array);
// })
// .add('no curry', () => {
//   u.map(x => x + 1, array);
// })
// .add('regular function call', () => {
//   add(3, 4);
// })
// .add('updeep full curry', () => {
//   updeepCurry(3, 4);
// })
// .add('updeep big full curry', () => {
//   updeepCurryBig(3, 4);
// })
// .add('curry full call', () => {
//   curryAdd(3, 4);
// })
// .add('fake curry', () => {
//   fakeCurryAdd(3)(4);
// })
// .add('_.map no changes', () => {
//   _.map(array, x => x);
// })
// .add('u.map no changes', () => {
//   u.map(x => x, array);
// })

.on('cycle', (event) => {
  if (typeof document !== 'undefined') {
    const el = document.getElementById('perf');
    el.innerHTML = el.innerHTML + String(event.target) + '
';
  }
})
.run({ async: true });
<|endoftext|>


<commit_before>/*jshint newcap:false*/
import Ember from "ember-metal/core"; // Ember.lookup
import jQuery from "ember-views/system/jquery";
import run from "ember-metal/run_loop";
import Namespace from "ember-runtime/system/namespace";
import EmberView from "ember-views/views/view";
import _MetamorphView from "ember-views/views/metamorph_view";
import EmberHandlebars from "ember-handlebars";
import EmberObject from "ember-runtime/system/object";
import { A } from "ember-runtime/system/native_array";
import { computed } from "ember-metal/computed";
import ContainerView from "ember-views/views/container_view";
import { Binding } from "ember-metal/binding";
import TextField from "ember-views/views/text_field";
import Container from "ember-runtime/system/container";
import { ViewHelper as handlebarsViewHelper } from "ember-handlebars/helpers/view";
import { ViewHelper as htmlbarsViewHelper } from "ember-htmlbars/helpers/view";

var trim = jQuery.trim;

import { get } from "ember-metal/property_get";
import { set } from "ember-metal/property_set";

var caretPosition = function (element) {
  var ctrl = element[0];
  var caretPos = 0;

  // IE Support
  if (document.selection) {
    ctrl.focus();
    var selection = document.selection.createRange();

    selection.moveStart('character', -ctrl.value.length);

    caretPos = selection.text.length;
  }
  // Firefox support
  else if (ctrl.selectionStart || ctrl.selectionStart === '0') {
    caretPos = ctrl.selectionStart;
  }

  return caretPos;
};

var setCaretPosition = function (element, pos) {
  var ctrl = element[0];

  if (ctrl.setSelectionRange) {
    ctrl.focus();
    ctrl.setSelectionRange(pos,pos);
  } else if (ctrl.createTextRange) {
    var range = ctrl.createTextRange();
    range.collapse(true);
    range.moveEnd('character', pos);
    range.moveStart('character', pos);
    range.select();
  }
};

var view;

var appendView = function() {
  run(function() { view.appendTo('#qunit-fixture'); });
};

var originalLookup = Ember.lookup;
var TemplateTests, container, lookup;

/**
  This module specifically tests integration with Handlebars and Ember-specific
  Handlebars extensions.

  If you add additional template support to View, you should create a new
  file in which to test.
*/
QUnit.module("View - handlebars integration", {
  setup: function() {
    Ember.lookup = lookup = {};
    lookup.TemplateTests = TemplateTests = Namespace.create();
    container = new Container();
    container.optionsForType('template', { instantiate: false });
    container.register('view:default', _MetamorphView);
    container.register('view:toplevel', EmberView.extend());
  },

  teardown: function() {
    run(function() {
        if (container) {
          container.destroy();
        }
        if (view) {
          view.destroy();
        }
        container = view = null;
    });
    Ember.lookup = lookup = originalLookup;
    TemplateTests = null;
  }
});

test("template view should call the function of the associated template", function() {
  container.register('template:testTemplate', EmberHandlebars.compile("
template was called
"));

  view = EmberView.create({
    container: container,
    templateName: 'testTemplate'
  });

  appendView();

  ok(view.$('#twas-called').length, "the named template was called");
});

test("template view should call the function of the associated template with itself as the context", function() {
  container.register('template:testTemplate', EmberHandlebars.compile("
template was called for {{view.personName}}. Yea {{view.personName}}
"));

  view = EmberView.createWithMixins({
    container: container,
    templateName: 'testTemplate',

    _personName: "Tom DAAAALE",
    _i: 0,

    personName: computed(function() {
      this._i++;
      return this._personName + this._i;
    })
  });

  appendView();

  equal("template was called for Tom DAAAALE1. Yea Tom DAAAALE1", view.$('#twas-called').text(), "the named template was called with the view as the data source");
});

test("View should not use keyword incorrectly - Issue #1315", function() {
  container.register('template:foo', EmberHandlebars.compile('{{#each value in view.content}}{{value}}-{{#each option in view.options}}{{option.value}}:{{option.label}} {{/each}}{{/each}}'));

  view = EmberView.create({
    container: container,
    templateName: 'foo',

    content: A(['X', 'Y']),
    options: A([
      { label: 'One', value: 1 },
      { label: 'Two', value: 2 }
    ])
  });

  appendView();

  equal(view.$().text(), 'X-1:One 2:Two Y-1:One 2:Two ');
});

test("View should update when a property changes and no bind helper is used", function() {
  container.register('template:foo', EmberHandlebars.compile('
{{#with view.content as thing}}{{thing.wham}}{{/with}}
'));

  view = EmberView.create({
    container: container,
    templateName: 'foo',

    content: EmberObject.create({
      wham: 'bam',
      thankYou: "ma'am"
    })
  });

  appendView();

  equal(view.$('#first').text(), "bam", "precond - view renders Handlebars template");

  run(function() { set(get(view, 'content'), 'wham', 'bazam'); });

  equal(view.$('#first').text(), "bazam", "view updates when a bound property changes");
});

test("Template views return throw if their template cannot be found", function() {
  view = EmberView.create({
    templateName: 'cantBeFound',
    container: { lookup: function() { }}
  });

  expectAssertion(function() {
    get(view, 'template');
  }, /cantBeFound/);
});

test("Layout views return throw if their layout cannot be found", function() {
  view = EmberView.create({
    layoutName: 'cantBeFound',
    container: { lookup: function() { }}
  });

  expectAssertion(function() {
    get(view, 'layout');
  }, /cantBeFound/);
});

test("should not reset cursor position when text field receives keyUp event", function() {
  view = TextField.create({
    value: "Broseidon, King of the Brocean"
  });

  run(function() {
    view.append();
  });

  view.$().val('Brosiedoon, King of the Brocean');
  setCaretPosition(view.$(), 5);

  run(function() {
    view.trigger('keyUp', {});
  });

  equal(caretPosition(view.$()), 5, "The keyUp event should not result in the cursor being reset due to the bind-attr observers");

  run(function() {
    view.destroy();
  });
});

test("should allow standard Handlebars template usage", function() {
  view = EmberView.create({
    context: { name: "Erik" },
    template: Handlebars.compile("Hello, {{name}}")
  });

  appendView();

  equal(view.$().text(), "Hello, Erik");
});

test("should be able to use standard Handlebars #each helper", function() {
  view = EmberView.create({
    context: { items: ['a', 'b', 'c'] },
    template: Handlebars.compile("{{#each items}}{{this}}{{/each}}")
  });

  appendView();

  equal(view.$().html(), "abc");
});

QUnit.module("Ember.View - handlebars integration", {
  setup: function() {
    Ember.lookup = lookup = { Ember: Ember };
  },

  teardown: function() {
    if (view) {
      run(function() {
        view.destroy();
      });
      view = null;
    }

    Ember.lookup = originalLookup;
  }
});

var MyApp;

QUnit.module("Templates redrawing and bindings", {
  setup: function() {
    Ember.lookup = lookup = { Ember: Ember };
    MyApp = lookup.MyApp = EmberObject.create({});
  },
  teardown: function() {
    run(function() {
      if (view) view.destroy();
    });
    Ember.lookup = originalLookup;
  }
});

test("should be able to update when bound property updates", function() {
  MyApp.set('controller', EmberObject.create({name: 'first'}));

  var View = EmberView.extend({
    template: EmberHandlebars.compile('{{view.value.name}}, {{view.computed}}'),
    valueBinding: 'MyApp.controller',
    computed: computed(function() {
      return this.get('value.name') + ' - computed';
    }).property('value')
  });

  run(function() {
    view = View.create();
  });

  appendView();

  run(function() {
    MyApp.set('controller', EmberObject.create({
      name: 'second'
    }));
  });

  equal(view.get('computed'), "second - computed", "view computed properties correctly update");
  equal(view.$('i').text(), 'second, second - computed', "view rerenders when bound properties change");
});

test('should cleanup bound properties on rerender', function() {
  view = EmberView.create({
    controller: EmberObject.create({name: 'wycats'}),
    template: EmberHandlebars.compile('{{name}}')
  });

  appendView();

  equal(view.$().text(), 'wycats', 'rendered binding');

  run(view, 'rerender');

  equal(view._childViews.length, 1);
});

// https://github.com/emberjs/ember.js/issues/120

test("should not enter an infinite loop when binding an attribute in Handlebars", function() {
  var LinkView = EmberView.extend({
    classNames: ['app-link'],
    tagName: 'a',
    attributeBindings: ['href'],
    href: '#none',

    click: function() {
      return false;
    }
  });

  var parentView = EmberView.create({
    linkView: LinkView,
    test: EmberObject.create({ href: 'test' }),
    template: EmberHandlebars.compile('{{#view view.linkView hrefBinding="view.test.href"}} Test {{/view}}')
  });

  run(function() {
    parentView.appendTo('#qunit-fixture');
  });

  // Use match, since old IE appends the whole URL
  var href = parentView.$('a').attr('href');
  ok(href.match(/(^|\/)test$/), "Expected href to be 'test' but got '"+href+"'");

  run(function() {
    parentView.destroy();
  });
});

test("should update bound values after view's parent is removed and then re-appended", function() {
  expectDeprecation("Setting `childViews` on a Container is deprecated.");

  var controller = EmberObject.create();

  var parentView = ContainerView.create({
    childViews: ['testView'],

    controller: controller,

    testView: EmberView.create({
      template: EmberHandlebars.compile("{{#if showStuff}}{{boundValue}}{{else}}Not true.{{/if}}")
    })
  });

  controller.setProperties({
    showStuff: true,
    boundValue: "foo"
  });

  run(function() {
    parentView.appendTo('#qunit-fixture');
  });
  view = parentView.get('testView');

  equal(trim(view.$().text()), "foo");
  run(function() {
    set(controller, 'showStuff', false);
  });
  equal(trim(view.$().text()), "Not true.");

  run(function() {
    set(controller, 'showStuff', true);
  });
  equal(trim(view.$().text()), "foo");

  run(function() {
    parentView.remove();
    set(controller, 'showStuff', false);
  });
  run(function() {
    set(controller, 'showStuff', true);
  });
  run(function() {
    parentView.appendTo('#qunit-fixture');
  });

  run(function() {
    set(controller, 'boundValue', "bar");
  });
  equal(trim(view.$().text()), "bar");

  run(function() {
    parentView.destroy();
  });
});

test("should call a registered helper for mustache without parameters", function() {
  EmberHandlebars.registerHelper('foobar', function() {
    return 'foobar';
  });

  view = EmberView.create({
    template: EmberHandlebars.compile("{{foobar}}")
  });

  appendView();

  ok(view.$().text() === 'foobar', "Regular helper was invoked correctly");
});

test("should bind to the property if no registered helper found for a mustache without parameters", function() {
  view = EmberView.createWithMixins({
    template: EmberHandlebars.compile("{{view.foobarProperty}}"),
    foobarProperty: computed(function() {
      return 'foobarProperty';
    })
  });

  appendView();

  ok(view.$().text() === 'foobarProperty', "Property was bound to correctly");
});

test("should accept bindings as a string or an Ember.Binding", function() {
  var viewClass = EmberView.extend({
    template: EmberHandlebars.compile("binding: {{view.bindingTest}}, string: {{view.stringTest}}")
  });

  EmberHandlebars.registerHelper('boogie', function(id, options) {
    options.hash = options.hash || {};
    options.hashTypes = options.hashTypes || {};

    options.hash.bindingTestBinding = Binding.oneWay('context.' + id);
    options.hash.stringTestBinding = id;

    var result;
    if (Ember.FEATURES.isEnabled('ember-htmlbars')) {
      result = htmlbarsViewHelper.helper(viewClass, options.hash, options, options);
    } else {
      result = handlebarsViewHelper.helper(this, viewClass, options);
    }

    return result;
  });

  view = EmberView.create({
    context: EmberObject.create({
      direction: 'down'
    }),
    template: EmberHandlebars.compile("{{boogie direction}}")
  });

  appendView();

  equal(trim(view.$().text()), "binding: down, string: down");
});

if (!Ember.FEATURES.isEnabled('ember-htmlbars')) {
// HTMLBars properly handles this scenario
// https://github.com/tildeio/htmlbars/pull/162
test("should provide a helpful assertion for bindings within HTML comments", function() {
  view = EmberView.create({
    template: EmberHandlebars.compile(''),
    someThing: 'foo',
    _debugTemplateName: 'blahzorz'
  });

  expectAssertion(function() {
    appendView();
  }, 'An error occured while setting up template bindings. Please check "blahzorz" template for invalid markup or bindings within HTML comments.');
});

// HTMLBars does not throw an error when a missing helper is found
test("using Handlebars helper that doesn't exist should result in an error", function() {
  var names = [{ name: 'Alex' }, { name: 'Stef' }];
  var context = { content: A(names) };

  throws(function() {
    view = EmberView.create({
      context: context,
      template: EmberHandlebars.compile('{{#group}}{{#each name in content}}{{name}}{{/each}}{{/group}}')
    });

    appendView();
  }, "Missing helper: 'group'");
});
}
<commit_msg>Removing duplicate tests<commit_after>/*jshint newcap:false*/
import Ember from "ember-metal/core"; // Ember.lookup
import jQuery from "ember-views/system/jquery";
import run from "ember-metal/run_loop";
import Namespace from "ember-runtime/system/namespace";
import EmberView from "ember-views/views/view";
import _MetamorphView from "ember-views/views/metamorph_view";
import EmberHandlebars from "ember-handlebars";
import EmberObject from "ember-runtime/system/object";
import { A } from "ember-runtime/system/native_array";
import { computed } from "ember-metal/computed";
import ContainerView from "ember-views/views/container_view";
import { Binding } from "ember-metal/binding";
import TextField from "ember-views/views/text_field";
import Container from "ember-runtime/system/container";
import { ViewHelper as handlebarsViewHelper } from "ember-handlebars/helpers/view";
import { ViewHelper as htmlbarsViewHelper } from "ember-htmlbars/helpers/view";

var trim = jQuery.trim;

import { get } from "ember-metal/property_get";
import { set } from "ember-metal/property_set";

var caretPosition = function (element) {
  var ctrl = element[0];
  var caretPos = 0;

  // IE Support
  if (document.selection) {
    ctrl.focus();
    var selection = document.selection.createRange();

    selection.moveStart('character', -ctrl.value.length);

    caretPos = selection.text.length;
  }
  // Firefox support
  else if (ctrl.selectionStart || ctrl.selectionStart === '0') {
    caretPos = ctrl.selectionStart;
  }

  return caretPos;
};

var setCaretPosition = function (element, pos) {
  var ctrl = element[0];

  if (ctrl.setSelectionRange) {
    ctrl.focus();
    ctrl.setSelectionRange(pos,pos);
  } else if (ctrl.createTextRange) {
    var range = ctrl.createTextRange();
    range.collapse(true);
    range.moveEnd('character', pos);
    range.moveStart('character', pos);
    range.select();
  }
};

var view;

var appendView = function() {
  run(function() { view.appendTo('#qunit-fixture'); });
};

var originalLookup = Ember.lookup;
var TemplateTests, container, lookup;

/**
  This module specifically tests integration with Handlebars and Ember-specific
  Handlebars extensions.

  If you add additional template support to View, you should create a new
  file in which to test.
*/
QUnit.module("View - handlebars integration", {
  setup: function() {
    Ember.lookup = lookup = {};
    lookup.TemplateTests = TemplateTests = Namespace.create();
    container = new Container();
    container.optionsForType('template', { instantiate: false });
    container.register('view:default', _MetamorphView);
    container.register('view:toplevel', EmberView.extend());
  },

  teardown: function() {
    run(function() {
        if (container) {
          container.destroy();
        }
        if (view) {
          view.destroy();
        }
        container = view = null;
    });
    Ember.lookup = lookup = originalLookup;
    TemplateTests = null;
  }
});

test("View should not use keyword incorrectly - Issue #1315", function() {
  container.register('template:foo', EmberHandlebars.compile('{{#each value in view.content}}{{value}}-{{#each option in view.options}}{{option.value}}:{{option.label}} {{/each}}{{/each}}'));

  view = EmberView.create({
    container: container,
    templateName: 'foo',

    content: A(['X', 'Y']),
    options: A([
      { label: 'One', value: 1 },
      { label: 'Two', value: 2 }
    ])
  });

  appendView();

  equal(view.$().text(), 'X-1:One 2:Two Y-1:One 2:Two ');
});

test("View should update when a property changes and no bind helper is used", function() {
  container.register('template:foo', EmberHandlebars.compile('
{{#with view.content as thing}}{{thing.wham}}{{/with}}
'));

  view = EmberView.create({
    container: container,
    templateName: 'foo',

    content: EmberObject.create({
      wham: 'bam',
      thankYou: "ma'am"
    })
  });

  appendView();

  equal(view.$('#first').text(), "bam", "precond - view renders Handlebars template");

  run(function() { set(get(view, 'content'), 'wham', 'bazam'); });

  equal(view.$('#first').text(), "bazam", "view updates when a bound property changes");
});

test("Template views return throw if their template cannot be found", function() {
  view = EmberView.create({
    templateName: 'cantBeFound',
    container: { lookup: function() { }}
  });

  expectAssertion(function() {
    get(view, 'template');
  }, /cantBeFound/);
});

test("Layout views return throw if their layout cannot be found", function() {
  view = EmberView.create({
    layoutName: 'cantBeFound',
    container: { lookup: function() { }}
  });

  expectAssertion(function() {
    get(view, 'layout');
  }, /cantBeFound/);
});

test("should not reset cursor position when text field receives keyUp event", function() {
  view = TextField.create({
    value: "Broseidon, King of the Brocean"
  });

  run(function() {
    view.append();
  });

  view.$().val('Brosiedoon, King of the Brocean');
  setCaretPosition(view.$(), 5);

  run(function() {
    view.trigger('keyUp', {});
  });

  equal(caretPosition(view.$()), 5, "The keyUp event should not result in the cursor being reset due to the bind-attr observers");

  run(function() {
    view.destroy();
  });
});

test("should allow standard Handlebars template usage", function() {
  view = EmberView.create({
    context: { name: "Erik" },
    template: Handlebars.compile("Hello, {{name}}")
  });

  appendView();

  equal(view.$().text(), "Hello, Erik");
});

test("should be able to use standard Handlebars #each helper", function() {
  view = EmberView.create({
    context: { items: ['a', 'b', 'c'] },
    template: Handlebars.compile("{{#each items}}{{this}}{{/each}}")
  });

  appendView();

  equal(view.$().html(), "abc");
});

QUnit.module("Ember.View - handlebars integration", {
  setup: function() {
    Ember.lookup = lookup = { Ember: Ember };
  },

  teardown: function() {
    if (view) {
      run(function() {
        view.destroy();
      });
      view = null;
    }

    Ember.lookup = originalLookup;
  }
});

var MyApp;

QUnit.module("Templates redrawing and bindings", {
  setup: function() {
    Ember.lookup = lookup = { Ember: Ember };
    MyApp = lookup.MyApp = EmberObject.create({});
  },
  teardown: function() {
    run(function() {
      if (view) view.destroy();
    });
    Ember.lookup = originalLookup;
  }
});

test("should be able to update when bound property updates", function() {
  MyApp.set('controller', EmberObject.create({name: 'first'}));

  var View = EmberView.extend({
    template: EmberHandlebars.compile('{{view.value.name}}, {{view.computed}}'),
    valueBinding: 'MyApp.controller',
    computed: computed(function() {
      return this.get('value.name') + ' - computed';
    }).property('value')
  });

  run(function() {
    view = View.create();
  });

  appendView();

  run(function() {
    MyApp.set('controller', EmberObject.create({
      name: 'second'
    }));
  });

  equal(view.get('computed'), "second - computed", "view computed properties correctly update");
  equal(view.$('i').text(), 'second, second - computed', "view rerenders when bound properties change");
});

test('should cleanup bound properties on rerender', function() {
  view = EmberView.create({
    controller: EmberObject.create({name: 'wycats'}),
    template: EmberHandlebars.compile('{{name}}')
  });

  appendView();

  equal(view.$().text(), 'wycats', 'rendered binding');

  run(view, 'rerender');

  equal(view._childViews.length, 1);
});

// https://github.com/emberjs/ember.js/issues/120

test("should not enter an infinite loop when binding an attribute in Handlebars", function() {
  var LinkView = EmberView.extend({
    classNames: ['app-link'],
    tagName: 'a',
    attributeBindings: ['href'],
    href: '#none',

    click: function() {
      return false;
    }
  });

  var parentView = EmberView.create({
    linkView: LinkView,
    test: EmberObject.create({ href: 'test' }),
    template: EmberHandlebars.compile('{{#view view.linkView hrefBinding="view.test.href"}} Test {{/view}}')
  });

  run(function() {
    parentView.appendTo('#qunit-fixture');
  });

  // Use match, since old IE appends the whole URL
  var href = parentView.$('a').attr('href');
  ok(href.match(/(^|\/)test$/), "Expected href to be 'test' but got '"+href+"'");

  run(function() {
    parentView.destroy();
  });
});

test("should update bound values after view's parent is removed and then re-appended", function() {
  expectDeprecation("Setting `childViews` on a Container is deprecated.");

  var controller = EmberObject.create();

  var parentView = ContainerView.create({
    childViews: ['testView'],

    controller: controller,

    testView: EmberView.create({
      template: EmberHandlebars.compile("{{#if showStuff}}{{boundValue}}{{else}}Not true.{{/if}}")
    })
  });

  controller.setProperties({
    showStuff: true,
    boundValue: "foo"
  });

  run(function() {
    parentView.appendTo('#qunit-fixture');
  });
  view = parentView.get('testView');

  equal(trim(view.$().text()), "foo");
  run(function() {
    set(controller, 'showStuff', false);
  });
  equal(trim(view.$().text()), "Not true.");

  run(function() {
    set(controller, 'showStuff', true);
  });
  equal(trim(view.$().text()), "foo");

  run(function() {
    parentView.remove();
    set(controller, 'showStuff', false);
  });
  run(function() {
    set(controller, 'showStuff', true);
  });
  run(function() {
    parentView.appendTo('#qunit-fixture');
  });

  run(function() {
    set(controller, 'boundValue', "bar");
  });
  equal(trim(view.$().text()), "bar");

  run(function() {
    parentView.destroy();
  });
});

test("should call a registered helper for mustache without parameters", function() {
  EmberHandlebars.registerHelper('foobar', function() {
    return 'foobar';
  });

  view = EmberView.create({
    template: EmberHandlebars.compile("{{foobar}}")
  });

  appendView();

  ok(view.$().text() === 'foobar', "Regular helper was invoked correctly");
});

test("should bind to the property if no registered helper found for a mustache without parameters", function() {
  view = EmberView.createWithMixins({
    template: EmberHandlebars.compile("{{view.foobarProperty}}"),
    foobarProperty: computed(function() {
      return 'foobarProperty';
    })
  });

  appendView();

  ok(view.$().text() === 'foobarProperty', "Property was bound to correctly");
});

test("should accept bindings as a string or an Ember.Binding", function() {
  var viewClass = EmberView.extend({
    template: EmberHandlebars.compile("binding: {{view.bindingTest}}, string: {{view.stringTest}}")
  });

  EmberHandlebars.registerHelper('boogie', function(id, options) {
    options.hash = options.hash || {};
    options.hashTypes = options.hashTypes || {};

    options.hash.bindingTestBinding = Binding.oneWay('context.' + id);
    options.hash.stringTestBinding = id;

    var result;
    if (Ember.FEATURES.isEnabled('ember-htmlbars')) {
      result = htmlbarsViewHelper.helper(viewClass, options.hash, options, options);
    } else {
      result = handlebarsViewHelper.helper(this, viewClass, options);
    }

    return result;
  });

  view = EmberView.create({
    context: EmberObject.create({
      direction: 'down'
    }),
    template: EmberHandlebars.compile("{{boogie direction}}")
  });

  appendView();

  equal(trim(view.$().text()), "binding: down, string: down");
});

if (!Ember.FEATURES.isEnabled('ember-htmlbars')) {
// HTMLBars properly handles this scenario
// https://github.com/tildeio/htmlbars/pull/162
test("should provide a helpful assertion for bindings within HTML comments", function() {
  view = EmberView.create({
    template: EmberHandlebars.compile(''),
    someThing: 'foo',
    _debugTemplateName: 'blahzorz'
  });

  expectAssertion(function() {
    appendView();
  }, 'An error occured while setting up template bindings. Please check "blahzorz" template for invalid markup or bindings within HTML comments.');
});

// HTMLBars does not throw an error when a missing helper is found
test("using Handlebars helper that doesn't exist should result in an error", function() {
  var names = [{ name: 'Alex' }, { name: 'Stef' }];
  var context = { content: A(names) };

  throws(function() {
    view = EmberView.create({
      context: context,
      template: EmberHandlebars.compile('{{#group}}{{#each name in content}}{{name}}{{/each}}{{/group}}')
    });

    appendView();
  }, "Missing helper: 'group'");
});
}
<|endoftext|>


<commit_before>// Style
import './_SearchPage.css';
// React & Redux
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
// Actions
import * as SearchPageActions from '../../actions/search-page-actions';
import * as mainActions from '../../actions/main-actions';

import Pagination from 'rc-pagination';

const tabMapping = {
  ARTICLE: {title: 'Article'},
  FILE: {title: 'File'},
  WORKLOG: {title: 'Worklog'},
  COMMENT: {title: 'Comment'}
};

class SearchPage extends Component {
  render() {
    let {
        searchKeyword,
        currentSearchTab,
        pagesize,

        articleSearchResult,
        articleTotal,
        articleCurPage,
        fileSearchResult,
        fileTotal,
        fileCurPage,
        worklogSearchResult,
        worklogTotal,
        worklogCurPage,
        commentSearchResult,
        commentTotal,
        commentCurPage,

        searchArticle
        } = this.props;

    let searchResultTitle = tabMapping[currentSearchTab] ? tabMapping[currentSearchTab].title : '';

    let articleBodyStyle = {};
    let fileBodyStyle = {};
    let worklogBodyStyle = {};
    let commentBodyStyle = {};
    let articleFootStyle = {};
    let fileFootStyle = {};
    let worklogFootStyle = {};
    let commentFootStyle = {};
    if (currentSearchTab!=='ARTICLE') {
      articleBodyStyle.display = articleFootStyle.display = 'none';
    }
    if (currentSearchTab!=='FILE') {
      fileBodyStyle.display = fileFootStyle.display = 'none';
    }
    if (currentSearchTab!=='WORKLOG') {
      worklogBodyStyle.display = worklogFootStyle.display = 'none';
    }
    if (currentSearchTab!=='COMMENT') {
      commentBodyStyle.display = commentFootStyle.display = 'none';
    }
    return (

          Toggle: <button type="button" onClick={()=>{
            searchArticle('knowledges');
          }}>Knowledge</button>
          <button type="button">Files</button>

          {searchResultTitle} Result for "{searchKeyword}":

            {!articleSearchResult || !articleSearchResult.length ? 'No article.' : ''}

{articleSearchResult.map((item, idx)=>{
              let _files = item._source && item._source.files
              _files = _files || [];

              return

{item._source.title}

{item._source.updated_at}{' '}{'['+item._source.document_type+']'}

{item._source.content}

{item._source.author_name}

                  {_files.map((fileItem,idx)=>{
                    return

                    {fileItem.name}

;
                  })}

;
            })}

            {!fileSearchResult || !fileSearchResult.length ? 'No file.' : ''}

{fileSearchResult.map((fileItem, idx)=>{
              return (

                    {fileItem.name}

);
            })}

            {!worklogSearchResult || !worklogSearchResult.length ? 'No worklog.' : ''}

{worklogSearchResult.map((item, idx)=>{
              return
{item._id}
;
            })}

            {!commentSearchResult || !commentSearchResult.length ? 'No comment.' : ''}

{commentSearchResult.map((item, idx)=>{
              return
{item._id}
;
            })}

            <Pagination onChange={this._onClickArticlePaginate} pageSize={pagesize} current={articleCurPage} total={articleTotal} />

            <Pagination onChange={this._onClickFilePaginate} pageSize={pagesize} current={fileCurPage} total={fileTotal} />

            <Pagination onChange={this._onClickWorklogPaginate} pageSize={pagesize} current={worklogCurPage} total={worklogTotal} />

            <Pagination onChange={this._onClickCommentPaginate} pageSize={pagesize} current={commentCurPage} total={commentTotal} />

    );
  }
}

SearchPage.propTypes = {
  searchKeyword: PropTypes.string,
  currentSearchTab: PropTypes.string,
  pagesize: PropTypes.number,

  articleSearchResult: PropTypes.array,
  articleTotal: PropTypes.number,
  articleCurPage: PropTypes.number,
  fileSearchResult: PropTypes.array,
  fileTotal: PropTypes.number,
  fileCurPage: PropTypes.number,
  worklogSearchResult: PropTypes.array,
  worklogTotal: PropTypes.number,
  worklogCurPage: PropTypes.number,
  commentSearchResult: PropTypes.array,
  commentTotal: PropTypes.number,
  commentCurPage: PropTypes.number,
  articleSearchResult: PropTypes.array,
  commentSearchResult: PropTypes.array,
  fileSearchResult: PropTypes.array,
  worklogSearchResult: PropTypes.array,

  searchArticle: PropTypes.func,
};
SearchPage.defaultProps = {
  searchKeyword: '',
  articleSearchResult: [],
  commentSearchResult: [],
  fileSearchResult: [],
  worklogSearchResult: []
};

function mapStateToProps(state) {
    return Object.assign(
        {},
        state.search.toJS(),
        state.app.toJS()
    );
}

function mapDispatchToProps(dispatch) {
    return Object.assign(
        {},
        bindActionCreators(SearchPageActions, dispatch)
    );
}

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(SearchPage);
<commit_msg>[Search] fix eslintrc<commit_after>// Style
import './_SearchPage.css';
// React & Redux
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
// Actions
import * as SearchPageActions from '../../actions/search-page-actions';
import * as mainActions from '../../actions/main-actions';

import Pagination from 'rc-pagination';

const tabMapping = {
  ARTICLE: {title: 'Article'},
  FILE: {title: 'File'},
  WORKLOG: {title: 'Worklog'},
  COMMENT: {title: 'Comment'}
};

class SearchPage extends Component {
  render() {
    let {
        searchKeyword,
        currentSearchTab,
        pagesize,

        articleSearchResult,
        articleTotal,
        articleCurPage,
        fileSearchResult,
        fileTotal,
        fileCurPage,
        worklogSearchResult,
        worklogTotal,
        worklogCurPage,
        commentSearchResult,
        commentTotal,
        commentCurPage,

        searchArticle
        } = this.props;

    let searchResultTitle = tabMapping[currentSearchTab] ? tabMapping[currentSearchTab].title : '';

    let articleBodyStyle = {};
    let fileBodyStyle = {};
    let worklogBodyStyle = {};
    let commentBodyStyle = {};
    let articleFootStyle = {};
    let fileFootStyle = {};
    let worklogFootStyle = {};
    let commentFootStyle = {};
    if (currentSearchTab!=='ARTICLE') {
      articleBodyStyle.display = articleFootStyle.display = 'none';
    }
    if (currentSearchTab!=='FILE') {
      fileBodyStyle.display = fileFootStyle.display = 'none';
    }
    if (currentSearchTab!=='WORKLOG') {
      worklogBodyStyle.display = worklogFootStyle.display = 'none';
    }
    if (currentSearchTab!=='COMMENT') {
      commentBodyStyle.display = commentFootStyle.display = 'none';
    }
    return (

          Toggle: <button type="button" onClick={()=>{
            searchArticle('knowledges');
          }}>Knowledge</button>
          <button type="button">Files</button>

          {searchResultTitle} Result for "{searchKeyword}":

            {!articleSearchResult || !articleSearchResult.length ? 'No article.' : ''}

{articleSearchResult.map((item, idx)=>{
              let _files = item._source && item._source.files;
              _files = _files || [];

              return (

{item._source.title}

{item._source.updated_at}{' '}{'['+item._source.document_type+']'}

{item._source.content}

{item._source.author_name}

                  {_files.map((fileItem,fileIdx)=>{
                    return (

                    {fileItem.name}

);
                  })}

);
            })}

            {!fileSearchResult || !fileSearchResult.length ? 'No file.' : ''}

{fileSearchResult.map((fileItem, idx)=>{
              return (

                    {fileItem.name}

);
            })}

            {!worklogSearchResult || !worklogSearchResult.length ? 'No worklog.' : ''}

{worklogSearchResult.map((item, idx)=>{
              return
{item._id}
;
            })}

            {!commentSearchResult || !commentSearchResult.length ? 'No comment.' : ''}

{commentSearchResult.map((item, idx)=>{
              return
{item._id}
;
            })}

            <Pagination onChange={this._onClickArticlePaginate} pageSize={pagesize} current={articleCurPage} total={articleTotal} />

            <Pagination onChange={this._onClickFilePaginate} pageSize={pagesize} current={fileCurPage} total={fileTotal} />

            <Pagination onChange={this._onClickWorklogPaginate} pageSize={pagesize} current={worklogCurPage} total={worklogTotal} />

            <Pagination onChange={this._onClickCommentPaginate} pageSize={pagesize} current={commentCurPage} total={commentTotal} />

    );
  }
}

SearchPage.propTypes = {
  searchKeyword: PropTypes.string,
  currentSearchTab: PropTypes.string,
  pagesize: PropTypes.number,

  articleSearchResult: PropTypes.array,
  articleTotal: PropTypes.number,
  articleCurPage: PropTypes.number,
  fileSearchResult: PropTypes.array,
  fileTotal: PropTypes.number,
  fileCurPage: PropTypes.number,
  worklogSearchResult: PropTypes.array,
  worklogTotal: PropTypes.number,
  worklogCurPage: PropTypes.number,
  commentSearchResult: PropTypes.array,
  commentTotal: PropTypes.number,
  commentCurPage: PropTypes.number,
  articleSearchResult: PropTypes.array,
  commentSearchResult: PropTypes.array,
  fileSearchResult: PropTypes.array,
  worklogSearchResult: PropTypes.array,

  searchArticle: PropTypes.func,
};
SearchPage.defaultProps = {
  searchKeyword: '',
  articleSearchResult: [],
  commentSearchResult: [],
  fileSearchResult: [],
  worklogSearchResult: []
};

function mapStateToProps(state) {
    return Object.assign(
        {},
        state.search.toJS(),
        state.app.toJS()
    );
}

function mapDispatchToProps(dispatch) {
    return Object.assign(
        {},
        bindActionCreators(SearchPageActions, dispatch)
    );
}

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(SearchPage);
<|endoftext|>


<commit_before>Slipmat.Views.RecordForm = Backbone.ImageableView.extend({

  tagName: "form",
  id: "record-form",
  template: JST["records/form"],

  initialize: function (options) {
    this.sort = 0;
    this.artists = new Slipmat.Collections.Artists();
    this.labels = new Slipmat.Collections.Labels();
    this.artists.fetch();
    this.labels.fetch();

    this.listenTo(this.model, "sync", this.render);
    this.listenTo(this.artists, "sync", this.addArtists);
    this.listenTo(this.labels, "sync", this.addLabels);
  },

  events: {
    "change #image-form": "replaceFormImage",
    "click #upload": "triggerUpload",
    "click .new-selector": "replaceInputField",
    "click .add-track": "addTrack",
    "click .remove-track": "removeTrack",
    "sortbeforestop .tracks-container": "updateTracklistOrder",
    "submit": "submit"
  },

  render: function () {
    var content = this.template({ record: this.model });
    this.$el.html(content);
    this.addCountries();
    this.addGenres();
    this.addTracks();

    return this;
  },

  submit: function (e) {
    e.preventDefault();

    var view = this;
    var image = this.$("#image-form")[0].files[0];
    var attributes = this.$el.serializeJSON();
    var callback = function (model) {
      Backbone.history.navigate("/records/" + model.id, { trigger: true });
    }

    this.model.save(attributes, {
      success: function (model) {
        if (!image) {
          callback(model);
          return;
        }
        view.submitImage({
          image: image,
          param: "record[image]",
          model: model,
          success: callback.bind(view, model)
        });
      }
    });
  },

  addArtists: function (artists) {
    artists.forEach(function (artist) {
      var selected = (artist.id === this.model.artist().id);
      var template = JST["records/_formOption"]({
        id: artist.id,
        attribute: artist.get("name"),
        selected: selected
      });

      this.$("#record_artist").append(template);
    }, this);
  },

  addLabels: function (labels) {
    labels.forEach(function (label) {
      var selected = (label.id === this.model.label().id);
      var template = JST["records/_formOption"]({
        id: label.id,
        attribute: label.get("title"),
        selected: selected
      });

      this.$("#record_label").append(template);
    }, this);
  },

  addCountries: function () {
    Slipmat.countries.forEach(function (country) {
      var selected = (country.id === this.model.country().id);
      var template = JST["records/_formOption"]({
        id: country.id,
        attribute: country.name,
        selected: selected
      });

      this.$("#record_country").append(template);
    }, this);
  },

  addGenres: function () {
    Slipmat.genres.forEach(function (genre) {
      var checked = this.model.genres().some(function (modelGenre) {
        return genre.id === modelGenre.id;
      });

      var template = JST["records/_genreCheckbox"]({
        genre: genre,
        checked: checked
      });

      this.$(".genre-container").append(template);
    }, this);
  },

  addTracks: function () {
    var tracks = _.sortBy(this.model.tracks(), function (track) {
      return track.ord;
    });

    var content = JST["tracks/form"]();
    this.$(".tracklist-form").html(content);

    // display all the tracks, or some initial blank fields
    var numTracks = this.model.tracks().length || 4;
    for (var i = 0; i < numTracks; i++) {
      var track = tracks[i] || {};
      this._addTrack(track);
    }

    this.$(".tracks-container").sortable({ handle: "small" });
  },

  addTrack: function (e) {
    e.preventDefault();
    this._addTrack({});
  },

  _addTrack: function (track) {
    var content = JST["tracks/_formItem"]({
      item: this.sort++,
      track: track
    });

    this.$(".tracks-container").append(content);
  },

  removeTrack: function (e) {
    e.preventDefault();

    var $track = $(e.currentTarget).parents(".tracklist-form-track");

    if (this.model.isNew()) {
      $track.remove();
    } else {
      var $_destroy = $('<input type="hidden">')
        .attr("name", "record[tracks_attributes][][_destroy]")
        .attr("value", "true");

      $track.hide();
      $track.append($_destroy);
    }
  },

  updateTracklistOrder: function () {
    var order = this.$(".tracks-container").sortable("toArray");

    for (var i = 0; i < order.length; i++) {
      var input = this.$("input.track-ord")[i];
      $(input).val(i + 1);
    }
  },

  replaceInputField: function (e) {
    e.preventDefault();

    var $el = $(e.currentTarget);
    var id = $el.data("id");
    var template = JST["records/_formInput"]({
      id: id,
      name: $el.data("name")
    });

    $el.remove();
    this.$("#" + id).replaceWith(template);
  }

});
<commit_msg>Remove depreciated RecordForm event<commit_after>Slipmat.Views.RecordForm = Backbone.ImageableView.extend({

  tagName: "form",
  id: "record-form",
  template: JST["records/form"],

  initialize: function (options) {
    this.sort = 0;
    this.artists = new Slipmat.Collections.Artists();
    this.labels = new Slipmat.Collections.Labels();
    this.artists.fetch();
    this.labels.fetch();

    this.listenTo(this.model, "sync", this.render);
    this.listenTo(this.artists, "sync", this.addArtists);
    this.listenTo(this.labels, "sync", this.addLabels);
  },

  events: {
    "change #image-form": "replaceFormImage",
    "click #upload": "triggerUpload",
    "click .add-track": "addTrack",
    "click .remove-track": "removeTrack",
    "sortbeforestop .tracks-container": "updateTracklistOrder",
    "submit": "submit"
  },

  render: function () {
    var content = this.template({ record: this.model });
    this.$el.html(content);
    this.addCountries();
    this.addGenres();
    this.addTracks();

    return this;
  },

  submit: function (e) {
    e.preventDefault();

    var view = this;
    var image = this.$("#image-form")[0].files[0];
    var attributes = this.$el.serializeJSON();
    var callback = function (model) {
      Backbone.history.navigate("/records/" + model.id, { trigger: true });
    }

    this.model.save(attributes, {
      success: function (model) {
        if (!image) {
          callback(model);
          return;
        }
        view.submitImage({
          image: image,
          param: "record[image]",
          model: model,
          success: callback.bind(view, model)
        });
      }
    });
  },

  addArtists: function (artists) {
    artists.forEach(function (artist) {
      var selected = (artist.id === this.model.artist().id);
      var template = JST["records/_formOption"]({
        id: artist.id,
        attribute: artist.get("name"),
        selected: selected
      });

      this.$("#record_artist").append(template);
    }, this);
  },

  addLabels: function (labels) {
    labels.forEach(function (label) {
      var selected = (label.id === this.model.label().id);
      var template = JST["records/_formOption"]({
        id: label.id,
        attribute: label.get("title"),
        selected: selected
      });

      this.$("#record_label").append(template);
    }, this);
  },

  addCountries: function () {
    Slipmat.countries.forEach(function (country) {
      var selected = (country.id === this.model.country().id);
      var template = JST["records/_formOption"]({
        id: country.id,
        attribute: country.name,
        selected: selected
      });

      this.$("#record_country").append(template);
    }, this);
  },

  addGenres: function () {
    Slipmat.genres.forEach(function (genre) {
      var checked = this.model.genres().some(function (modelGenre) {
        return genre.id === modelGenre.id;
      });

      var template = JST["records/_genreCheckbox"]({
        genre: genre,
        checked: checked
      });

      this.$(".genre-container").append(template);
    }, this);
  },

  addTracks: function () {
    var tracks = _.sortBy(this.model.tracks(), function (track) {
      return track.ord;
    });

    var content = JST["tracks/form"]();
    this.$(".tracklist-form").html(content);

    // display all the tracks, or some initial blank fields
    var numTracks = this.model.tracks().length || 4;
    for (var i = 0; i < numTracks; i++) {
      var track = tracks[i] || {};
      this._addTrack(track);
    }

    this.$(".tracks-container").sortable({ handle: "small" });
  },

  addTrack: function (e) {
    e.preventDefault();
    this._addTrack({});
  },

  _addTrack: function (track) {
    var content = JST["tracks/_formItem"]({
      item: this.sort++,
      track: track
    });

    this.$(".tracks-container").append(content);
  },

  removeTrack: function (e) {
    e.preventDefault();

    var $track = $(e.currentTarget).parents(".tracklist-form-track");

    if (this.model.isNew()) {
      $track.remove();
    } else {
      var $_destroy = $('<input type="hidden">')
        .attr("name", "record[tracks_attributes][][_destroy]")
        .attr("value", "true");

      $track.hide();
      $track.append($_destroy);
    }
  },

  updateTracklistOrder: function () {
    var order = this.$(".tracks-container").sortable("toArray");

    for (var i = 0; i < order.length; i++) {
      var input = this.$("input.track-ord")[i];
      $(input).val(i + 1);
    }
  }

});
<|endoftext|>


<commit_before><commit_msg>Changed effect of lenientIfSlow param of Timer#stop<commit_after><|endoftext|>


<commit_before>/**
* Expose the device information of the Edison device
*
* Reference: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.device_information.xml
*/

var util = require('util'),
  os = require('os'),
  exec = require('child_process').exec,
  bleno = require('bleno'),
  Descriptor = bleno.Descriptor,
  Characteristic = bleno.Characteristic;

/**
* Reference:
* https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.manufacturer_name_string.xml
*/
var EdisonDeviceStatusCharacteristic = function() {
  EdisonDeviceStatusCharacteristic.super_.call(this, {
      uuid: '2A29',
      properties: ['read'],
      descriptors: [
        new Descriptor({
        uuid: '2901',
        value: 'Device Status'
      })]
  });
};

util.inherits(EdisonDeviceStatusCharacteristic, Characteristic);

EdisonDeviceStatusCharacteristic.prototype.onReadRequest = function(offset, callback) {
 if (offset) {
    callback(this.RESULT_ATTR_NOT_LONG, null);
  } else {
    callback(this.RESULT_SUCCESS, new Buffer('online'));
  }
};

module.exports = EdisonDeviceStatusCharacteristic;
<commit_msg>bug fixes<commit_after>/**
* Reference:
* https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.manufacturer_name_string.xml
*/
var util = require('util'),
  bleno = require('bleno'),
  BlenoPrimaryService = bleno.PrimaryService,
  EdisonDeviceManufacturerCharacteristic = require('./edison-device-manufacturer-characteristic');

// Everything we want to be able to read / write about Edison using our paired mobile app.
function EdisonDeviceInformationService() {
  EdisonDeviceInformationService.super_.call(this, {
      uuid: '180A',
      characteristics: [
          new EdisonDeviceManufacturerCharacteristic()
      ]
  });
}

util.inherits(EdisonDeviceInformationService, BlenoPrimaryService);
module.exports = EdisonDeviceInformationService;<|endoftext|>


<commit_before>(function() {

  /**
   * Feather's default ui toolkit is jQuery UI. This file is intended
   * to provide a lightweight API shim to program against (which will be similar to jQuery's),
   * which will make it easier to use another ui toolkit if desired, assuming fairly
   * similar components.
   *
   * Where this API differs from jQueryUI is that it's for use with the feather widget
   * rendering cycle, which is markedly different than the standard jQueryUI approach of first
   * defining the markup and $() wrapping a container before calling .dialog() on it (or the like).
   * In our case, the user-facing markup (of the feather widget) is usually sent from the server
   * and the skeleton markup required by the underlying jQueryUI component will be auto-created.
   * The end result will be a seamless integration point between feather widgets and jQueryUI,
   * with the added bonus of a simple API that can be used to write an adapter to a different
   * ui toolkit if desired.
   *
   * (Include jQuery UI and this file in your page to make use of this API)
   *
   * When implementing a similar adapter for another toolkit, the idea is to include that toolkit
   * and a different file _like_ this one, that implements the same API, thus minimizing
   * changes to higher level application code.
   */

  feather.ns("feather.ui");

  /**
   * Wrap $.dialog with options and auto-generated markup
   * @param {Object} options
   */
  var dialogTmpl = "
${content}
"
  feather.ui.dialog = function(options) {
    options = options || {};
    options.title = options.title || "";
    options.id = options.id || feather.id();
    options.content = options.content || "";

    /**
     * TEMP workaround for the issue outlined here: http://bugs.jqueryui.com/ticket/7293
     * TODO: remove these two lines when jQueryUI 1.8.13 is released (target release for the bugfix)
     */
    options.resizable = false;
    window.console && window.console.debug("disabling resizable dialogs until jqueryUI 1.8.13 is released (see source comments)");

    var dialog = $.tmpl(dialogTmpl, options)
      .appendTo(document)
      .dialog(options);
    //make some conveniences
    dialog.open = function() {
      dialog.dialog("open");
    };
    dialog.close = function() {
      dialog.dialog("close");
    };
    dialog.destroy = function() {
      dialog.dialog("destroy");
    };
    return dialog;
  };

  /**
   * Create a simple dialog containerizer (and make it the default as well)
   */
  feather.widget.containerizers.dialog = feather.widget.containerizers["default"] = {
    containerize: function(widget) {
      var dialog = feather.ui.dialog(widget.containerOptions);
      widget.container = dialog;
      //wrap the dispose method to destroy the dialog, and the make closing the dialog dispose of the widget nicely as well
      var disposing = false;
      var oldDispose = widget.dispose;
      widget.dispose = function() {
        oldDispose.call(widget);
        if (!disposing) {
          disposing = true;
          dialog.destroy();
        }
      };
      if (widget.containerOptions.disposeOnClose !== false) {
        dialog.bind("dialogclose", function() {
          if (!disposing) {
            disposing = true;
            widget.dispose();
            dialog.destroy();
          }
        });
      }
    }
  }

  /**
   * empty containerizer
   */
  feather.widget.containerizers.empty = {containerize: feather.emptyFn};

})();
<commit_msg>Added missing semi-colons.<commit_after>(function() {

  /**
   * Feather's default ui toolkit is jQuery UI. This file is intended
   * to provide a lightweight API shim to program against (which will be similar to jQuery's),
   * which will make it easier to use another ui toolkit if desired, assuming fairly
   * similar components.
   *
   * Where this API differs from jQueryUI is that it's for use with the feather widget
   * rendering cycle, which is markedly different than the standard jQueryUI approach of first
   * defining the markup and $() wrapping a container before calling .dialog() on it (or the like).
   * In our case, the user-facing markup (of the feather widget) is usually sent from the server
   * and the skeleton markup required by the underlying jQueryUI component will be auto-created.
   * The end result will be a seamless integration point between feather widgets and jQueryUI,
   * with the added bonus of a simple API that can be used to write an adapter to a different
   * ui toolkit if desired.
   *
   * (Include jQuery UI and this file in your page to make use of this API)
   *
   * When implementing a similar adapter for another toolkit, the idea is to include that toolkit
   * and a different file _like_ this one, that implements the same API, thus minimizing
   * changes to higher level application code.
   */

  feather.ns("feather.ui");

  /**
   * Wrap $.dialog with options and auto-generated markup
   * @param {Object} options
   */
  var dialogTmpl = "
${content}
";
  feather.ui.dialog = function(options) {
    options = options || {};
    options.title = options.title || "";
    options.id = options.id || feather.id();
    options.content = options.content || "";

    /**
     * TEMP workaround for the issue outlined here: http://bugs.jqueryui.com/ticket/7293
     * TODO: remove these two lines when jQueryUI 1.8.13 is released (target release for the bugfix)
     */
    options.resizable = false;
    window.console && window.console.debug("disabling resizable dialogs until jqueryUI 1.8.13 is released (see source comments)");

    var dialog = $.tmpl(dialogTmpl, options)
      .appendTo(document)
      .dialog(options);
    //make some conveniences
    dialog.open = function() {
      dialog.dialog("open");
    };
    dialog.close = function() {
      dialog.dialog("close");
    };
    dialog.destroy = function() {
      dialog.dialog("destroy");
    };
    return dialog;
  };

  /**
   * Create a simple dialog containerizer (and make it the default as well)
   */
  feather.widget.containerizers.dialog = feather.widget.containerizers["default"] = {
    containerize: function(widget) {
      var dialog = feather.ui.dialog(widget.containerOptions);
      widget.container = dialog;
      //wrap the dispose method to destroy the dialog, and the make closing the dialog dispose of the widget nicely as well
      var disposing = false;
      var oldDispose = widget.dispose;
      widget.dispose = function() {
        oldDispose.call(widget);
        if (!disposing) {
          disposing = true;
          dialog.destroy();
        }
      };
      if (widget.containerOptions.disposeOnClose !== false) {
        dialog.bind("dialogclose", function() {
          if (!disposing) {
            disposing = true;
            widget.dispose();
            dialog.destroy();
          }
        });
      }
    }
  };

  /**
   * empty containerizer
   */
  feather.widget.containerizers.empty = {containerize: feather.emptyFn};

})();
<|endoftext|>