<commit_before>export { Base };

import * as RandTools from "../../util/RandTools.js";
import * as ValueDesc from "../../Unpacker/ValueDesc.js";
import * as PointDepthPoint_Reference from "./PointDepthPoint_Reference.js";

/**
 * Dynamically create random image data with specified channelCount, depthwise_AvgMax_Or_ChannelMultiplier, depthwiseFilterHeight,
 * depthwiseStridesPad. The same image data will be returned when same specification is requested. So that the testing performance
 * could be improved.
 */
class Base {

  /**
   * @param {number} originalHeight The original image's height.
   * @param {number} originalWidth  The original image's width.
   */
  constructor( originalHeight, originalWidth ) {
    this.originalHeight = originalHeight;
    this.originalWidth = originalWidth;
    this.imagesBy_channelCount_filterHeight_stridesPad = new Map(); // Images indexed by [ channelCount, filterHeight, stridesPad ].
    this.tensorsBy_channelCount_filterHeight_stridesPad = new Map();
  }

  /**
   * If ( depthwiseFilterHeight == 1 ) and ( depthwiseStridesPad == 0 ), the original image will be returned. The original
   * image has the size ( originalHeight, originalWidth, channelCount ). Its value is generated randomly.
   *
   *
   * @param {number} channelCount
   *   A positive integer which represents the returned image's depth.
   *
   * @param {number} depthwise_AvgMax_Or_ChannelMultiplier
   *   An integer represents the returned image should be the original image processed by depthwise convolution filter of this kinds.
   * Its should be in the range of ValueDesc.AvgMax_Or_ChannelMultiplier.Singleton.range.
   *
   * @param {number} depthwiseFilterHeight
   *   An integer represents the returned image should be the original image processed by depthwise convolution filter of this size.
   * Its should be in the range of ValueDesc.depthwiseFilterHeight.Singleton.range.
   *
   * @param {number} depthwiseStridesPad
   *   An integer represents the returned image should be the original image processed by depthwise convolution of this strides and pad.
   * Its should be in the range of ValueDesc.depthwiseStridesPad.Singleton.range.
   *
   * @return {object}
   *   Return an image data with the specified specification. It has the following properties:
   *     - object.height:    Image height
   *     - object.width:     Image width
   *     - object.depth:     Image channel count
   *     - object.dataArray: Image data
   */
  getImage_by( channelCount, depthwise_AvgMax_Or_ChannelMultiplier = 0, depthwiseFilterHeight = 1, depthwiseStridesPad = 0 ) {

    // 1. When no depthwise operation, the original image is returned directly (i.e. will not be shrinked).
    //
    // Because there is not depthwise operation, there is not possible to shrink.
    if ( depthwise_AvgMax_Or_ChannelMultiplier == ValueDesc.AvgMax_Or_ChannelMultiplier.Singleton.Ids.NONE ) {
      let originalImage = Base.internal_getImage_by.call( this, channelCount );
      return originalImage;
    }

    // 2. Otherwise, return image which is adjusted by depthwise operation.
    let image = Base.internal_getImage_by.call( this, channelCount, depthwiseFilterHeight, depthwiseStridesPad );
    return image;
  }

  /**
   *
   * @return {tf.tensor3d}
   *   Return a tensor with the specified specification.
   */
  getTensor3d_by( channelCount, depthwise_AvgMax_Or_ChannelMultiplier = 0, depthwiseFilterHeight = 1, depthwiseStridesPad = 0 ) {

    // 1. When no depthwise operation, the original image's tensor is returned directly (i.e. will not be shrinked).
    //
    // Because there is not depthwise operation, there is not possible to shrink.
    if ( depthwise_AvgMax_Or_ChannelMultiplier == ValueDesc.AvgMax_Or_ChannelMultiplier.Singleton.Ids.NONE ) {
      let originalTensor = Base.internal_getTensor3d_by.call( this, channelCount );
      return originalTensor;
    }

    // 2. Otherwise, return image tensor which is adjusted by depthwise operation.
    let tensor = Base.internal_getTensor3d_by.call( this, channelCount, depthwiseFilterHeight, depthwiseStridesPad );
    return tensor;
  }

  /**
   * Similiar to this.getImage_by() but does not consider depthwise_AvgMax_Or_ChannelMultiplier.
   */
  static internal_getImage_by( channelCount, depthwiseFilterHeight = 1, depthwiseStridesPad = 0 ) {

    let imagesBy_filterHeight_stridesPad = this.imagesBy_channelCount_filterHeight_stridesPad.get( channelCount );
    if ( !imagesBy_filterHeight_stridesPad )
      this.imagesBy_channelCount_filterHeight_stridesPad.set( channelCount, imagesBy_filterHeight_stridesPad = new Map() );

    let imagesBy_stridesPad = imagesBy_filterHeight_stridesPad.get( depthwiseFilterHeight );
    if ( !imagesBy_stridesPad )
      imagesBy_filterHeight_stridesPad.set( depthwiseFilterHeight, imagesBy_stridesPad = new Map() );

    let image = imagesBy_stridesPad.get( depthwiseStridesPad );
    if ( image )
      return image; // 1. The requested image has already been created. Re-use it. Return it directly.

    // 2. The requested has not yet existed. It should be created newly.

    // 2.1 The original image is requested.
    if ( ( depthwiseFilterHeight == 1 ) && ( depthwiseStridesPad == 0 ) ) {
      image = { height: this.originalHeight, width: this.originalWidth, depth: channelCount };
      let elementCount = image.height * image.width * image.depth;
      let randomOffsetMin = -200; // Just choosed randomly.
      let randomOffsetMax = +200;
      image.dataArray = RandTools.generate_numberArray( elementCount, randomOffsetMin, randomOffsetMax );

    // 2.2 The shrinked image requested.
    } else {
      let originalImage = Base.internal_getImage_by.call( this, channelCount ); // Use original image to create shrinked image.

      // Borrow the calcDepthwise() function to create an input image which is shrink by specified filter size and strides and pad.
      image = PointDepthPoint_Reference.Base.calcDepthwise(
        originalImage,
        ValueDesc.AvgMax_Or_ChannelMultiplier.Singleton.Ids.MAX, // Max Pooling is faster and without filter weights.
        depthwiseFilterHeight,
        depthwiseStridesPad,
        null, false, null, ValueDesc.ActivationFunction.NONE, //depthwiseFiltersArray, bDepthwiseBias, depthwiseBiasesArray, depthwiseActivationId,
        "Base.internal_getImage_by()", ""
      );
    }

    imagesBy_stridesPad.set( depthwiseStridesPad, image ); // Cache it.
    return image;
  }

  /**
   * Similiar to this.getTensor3d_by() but does not consider depthwise_AvgMax_Or_ChannelMultiplier.
   */
  static internal_getTensor3d_by( channelCount, depthwiseFilterHeight = 1, depthwiseStridesPad = 0 ) {

    let tensorsBy_filterHeight_stridesPad = this.tensorsBy_channelCount_filterHeight_stridesPad.get( channelCount );
    if ( !tensorsBy_filterHeight_stridesPad )
      this.tensorsBy_channelCount_filterHeight_stridesPad.set( channelCount, tensorsBy_filterHeight_stridesPad = new Map() );

    let tensorsBy_stridesPad = tensorsBy_filterHeight_stridesPad.get( depthwiseFilterHeight );
    if ( !tensorsBy_stridesPad )
      tensorsBy_filterHeight_stridesPad.set( depthwiseFilterHeight, tensorsBy_stridesPad = new Map() );

    let tensor = tensorsBy_stridesPad.get( depthwiseStridesPad );
    if ( tensor )
      return tensor; // 1. The requested tensor has already been created. Re-use it. Return it directly.

    // 2. Create new tensor according to its corresponding image.
    let image = Base.internal_getImage_by.call( this, channelCount, depthwiseFilterHeight, depthwiseStridesPad );
    let shape = [ image.height, image.width, image.depth ];
    tensor = tf.tensor3d( image.dataArray, shape ); // Create new tensor of specified specification.

    tensorsBy_stridesPad.set( depthwiseStridesPad, tensor ); // Cache it.

    return tensor;
  }

  /** Release all tensors. */
  disposeTensors() {
    if ( this.tensorsBy_channelCount_filterHeight_stridesPad ) {
      for ( let tensorsBy_filterHeight_stridesPad of this.tensorsBy_channelCount_filterHeight_stridesPad.values() )
        for ( let tensorsBy_stridesPad of tensorsBy_filterHeight_stridesPad.values() )
          for ( let tensor of tensorsBy_stridesPad.values() )
            tensor.dispose();

      this.tensorsBy_channelCount_filterHeight_stridesPad.clear();
    }
  }

}
<commit_msg>Update ImageSourceBag.js<commit_after>export { Base };

import * as MapTools from "../../util/MapTools.js";
import * as RandTools from "../../util/RandTools.js";
import * as ValueDesc from "../../Unpacker/ValueDesc.js";
import * as PointDepthPoint_Reference from "./PointDepthPoint_Reference.js";

/**
 * Dynamically create random image data with specified channelCount, depthwise_AvgMax_Or_ChannelMultiplier, depthwiseFilterHeight,
 * depthwiseStridesPad. The same image data will be returned when same specification is requested. So that the testing performance
 * could be improved.
 */
class Base {

  /**
   * @param {number} originalHeight The original image's height.
   * @param {number} originalWidth  The original image's width.
   */
  constructor( originalHeight, originalWidth ) {
    this.originalHeight = originalHeight;
    this.originalWidth = originalWidth;
    this.imagesBy_channelCount_filterHeight_stridesPad = new Map(); // Images indexed by [ channelCount, filterHeight, stridesPad ].
    this.tensorsBy_channelCount_filterHeight_stridesPad = new Map();
  }

  /**
   * If ( depthwiseFilterHeight == 1 ) and ( depthwiseStridesPad == 0 ), the original image will be returned. The original
   * image has the size ( originalHeight, originalWidth, channelCount ). Its value is generated randomly.
   *
   *
   * @param {number} channelCount
   *   A positive integer which represents the returned image's depth.
   *
   * @param {number} depthwise_AvgMax_Or_ChannelMultiplier
   *   An integer represents the returned image should be the original image processed by depthwise convolution filter of this kinds.
   * Its should be in the range of ValueDesc.AvgMax_Or_ChannelMultiplier.Singleton.range.
   *
   * @param {number} depthwiseFilterHeight
   *   An integer represents the returned image should be the original image processed by depthwise convolution filter of this size.
   * Its should be in the range of ValueDesc.depthwiseFilterHeight.Singleton.range.
   *
   * @param {number} depthwiseStridesPad
   *   An integer represents the returned image should be the original image processed by depthwise convolution of this strides and pad.
   * Its should be in the range of ValueDesc.depthwiseStridesPad.Singleton.range.
   *
   * @return {object}
   *   Return an image data with the specified specification. It has the following properties:
   *     - object.height:    Image height
   *     - object.width:     Image width
   *     - object.depth:     Image channel count
   *     - object.dataArray: Image data
   */
  getImage_by( channelCount, depthwise_AvgMax_Or_ChannelMultiplier = 0, depthwiseFilterHeight = 1, depthwiseStridesPad = 0 ) {

    // 1. When no depthwise operation, the original image is returned directly (i.e. will not be shrinked).
    //
    // Because there is not depthwise operation, there is not possible to shrink.
    if ( depthwise_AvgMax_Or_ChannelMultiplier == ValueDesc.AvgMax_Or_ChannelMultiplier.Singleton.Ids.NONE ) {
      let originalImage = Base.internal_getImage_by.call( this, channelCount );
      return originalImage;
    }

    // 2. Otherwise, return image which is adjusted by depthwise operation.
    let image = Base.internal_getImage_by.call( this, channelCount, depthwiseFilterHeight, depthwiseStridesPad );
    return image;
  }

  /**
   *
   * @return {tf.tensor3d}
   *   Return a tensor with the specified specification.
   */
  getTensor3d_by( channelCount, depthwise_AvgMax_Or_ChannelMultiplier = 0, depthwiseFilterHeight = 1, depthwiseStridesPad = 0 ) {

    // 1. When no depthwise operation, the original image's tensor is returned directly (i.e. will not be shrinked).
    //
    // Because there is not depthwise operation, there is not possible to shrink.
    if ( depthwise_AvgMax_Or_ChannelMultiplier == ValueDesc.AvgMax_Or_ChannelMultiplier.Singleton.Ids.NONE ) {
      let originalTensor = Base.internal_getTensor3d_by.call( this, channelCount );
      return originalTensor;
    }

    // 2. Otherwise, return image tensor which is adjusted by depthwise operation.
    let tensor = Base.internal_getTensor3d_by.call( this, channelCount, depthwiseFilterHeight, depthwiseStridesPad );
    return tensor;
  }

  /**
   * Similiar to this.getImage_by() but does not consider depthwise_AvgMax_Or_ChannelMultiplier.
   */
  static internal_getImage_by( channelCount, depthwiseFilterHeight = 1, depthwiseStridesPad = 0 ) {

//!!! (2021/09/03 Remarked) Using MapTools instead.
//     let imagesBy_filterHeight_stridesPad = this.imagesBy_channelCount_filterHeight_stridesPad.get( channelCount );
//     if ( !imagesBy_filterHeight_stridesPad )
//       this.imagesBy_channelCount_filterHeight_stridesPad.set( channelCount, imagesBy_filterHeight_stridesPad = new Map() );
//
//     let imagesBy_stridesPad = imagesBy_filterHeight_stridesPad.get( depthwiseFilterHeight );
//     if ( !imagesBy_stridesPad )
//       imagesBy_filterHeight_stridesPad.set( depthwiseFilterHeight, imagesBy_stridesPad = new Map() );
//
//     let image = imagesBy_stridesPad.get( depthwiseStridesPad );
//     if ( image )
//       return image; // 1. The requested image has already been created. Re-use it. Return it directly.

    let imagesBy_filterHeight_stridesPad = MapTools.get_or_create( this.imagesBy_channelCount_filterHeight_stridesPad, channelCount );
    let imagesBy_stridesPad = MapTools.get_or_create( imagesBy_filterHeight_stridesPad, depthwiseFilterHeight );
    let image = MapTools.get_or_create( imagesBy_stridesPad, depthwiseStridesPad );

    if ( image )
      return image; // 1. The requested image has already been created. Re-use it. Return it directly.

    // 2. The requested has not yet existed. It should be created newly.

    // 2.1 The original image is requested.
    if ( ( depthwiseFilterHeight == 1 ) && ( depthwiseStridesPad == 0 ) ) {
      image = { height: this.originalHeight, width: this.originalWidth, depth: channelCount };
      let elementCount = image.height * image.width * image.depth;
      let randomOffsetMin = -200; // Just choosed randomly.
      let randomOffsetMax = +200;
      image.dataArray = RandTools.generate_numberArray( elementCount, randomOffsetMin, randomOffsetMax );

    // 2.2 The shrinked image requested.
    } else {
      let originalImage = Base.internal_getImage_by.call( this, channelCount ); // Use original image to create shrinked image.

      // Borrow the calcDepthwise() function to create an input image which is shrink by specified filter size and strides and pad.
      image = PointDepthPoint_Reference.Base.calcDepthwise(
        originalImage,
        ValueDesc.AvgMax_Or_ChannelMultiplier.Singleton.Ids.MAX, // Max Pooling is faster and without filter weights.
        depthwiseFilterHeight,
        depthwiseStridesPad,
        null, false, null, ValueDesc.ActivationFunction.NONE, //depthwiseFiltersArray, bDepthwiseBias, depthwiseBiasesArray, depthwiseActivationId,
        "Base.internal_getImage_by()", ""
      );
    }

    imagesBy_stridesPad.set( depthwiseStridesPad, image ); // Cache it.
    return image;
  }

  /**
   * Similiar to this.getTensor3d_by() but does not consider depthwise_AvgMax_Or_ChannelMultiplier.
   */
  static internal_getTensor3d_by( channelCount, depthwiseFilterHeight = 1, depthwiseStridesPad = 0 ) {

//!!! (2021/09/03 Remarked) Using MapTools instead.
//     let tensorsBy_filterHeight_stridesPad = this.tensorsBy_channelCount_filterHeight_stridesPad.get( channelCount );
//     if ( !tensorsBy_filterHeight_stridesPad )
//       this.tensorsBy_channelCount_filterHeight_stridesPad.set( channelCount, tensorsBy_filterHeight_stridesPad = new Map() );
//
//     let tensorsBy_stridesPad = tensorsBy_filterHeight_stridesPad.get( depthwiseFilterHeight );
//     if ( !tensorsBy_stridesPad )
//       tensorsBy_filterHeight_stridesPad.set( depthwiseFilterHeight, tensorsBy_stridesPad = new Map() );
//
//     let tensor = tensorsBy_stridesPad.get( depthwiseStridesPad );
//     if ( tensor )
//       return tensor; // 1. The requested tensor has already been created. Re-use it. Return it directly.

    let tensorsBy_filterHeight_stridesPad = MapTools.get_or_create( this.tensorsBy_channelCount_filterHeight_stridesPad, channelCount );
    let tensorsBy_stridesPad = MapTools.get_or_create( tensorsBy_filterHeight_stridesPad, depthwiseFilterHeight );
    let tensor = MapTools.get_or_create( tensorsBy_stridesPad, depthwiseStridesPad );

    if ( tensor )
      return tensor; // 1. The requested tensor has already been created. Re-use it. Return it directly.

    // 2. Create new tensor according to its corresponding image.
    let image = Base.internal_getImage_by.call( this, channelCount, depthwiseFilterHeight, depthwiseStridesPad );
    let shape = [ image.height, image.width, image.depth ];
    tensor = tf.tensor3d( image.dataArray, shape ); // Create new tensor of specified specification.

    tensorsBy_stridesPad.set( depthwiseStridesPad, tensor ); // Cache it.

    return tensor;
  }

  /** Release all tensors. */
  disposeTensors() {
    if ( this.tensorsBy_channelCount_filterHeight_stridesPad ) {
      for ( let tensorsBy_filterHeight_stridesPad of this.tensorsBy_channelCount_filterHeight_stridesPad.values() )
        for ( let tensorsBy_stridesPad of tensorsBy_filterHeight_stridesPad.values() )
          for ( let tensor of tensorsBy_stridesPad.values() )
            tensor.dispose();

      this.tensorsBy_channelCount_filterHeight_stridesPad.clear();
    }
  }

}
<|endoftext|>


<commit_before>"use strict";

var filetree = new (require("events").EventEmitter)(),
    dirs     = {},
    todoDirs = [],
    noLog    = true;

var _        = require("lodash"),
    chalk    = require("chalk"),
    chokidar = require("chokidar"),
    fs       = require("graceful-fs"),
    path     = require("path"),
    readdirp = require("readdirp");

var log      = require("./log.js"),
    paths    = require("./paths.js").get(),
    utils    = require("./utils.js");

function filterDirs(dirs) {
    return dirs.sort(function (a, b) {
        return a.match(/\//g).length - b.match(/\//g).length;
    }).filter(function (path, _, self) {
        return self.every(function (another) {
            return another === path || path.indexOf(another + "/") !== 0;
        });
    }).filter(function (path, index, self) {
        return self.indexOf(path) === index;
    });
}

var debouncedUpdate = _.debounce(function() {
    filterDirs(todoDirs).forEach(function (dir) {
        filetree.emit("update", dir);
    });
    todoDirs = [];
}, 100, {trailing: true});

function update(dir) {
    updateDirSizes();
    todoDirs.push(dir);
    debouncedUpdate();
}

filetree.updateDir = function updateDir(dir, cb) {
    if (dir === null) { dir = "/"; dirs = {}; }
    if (noLog) noLog = false; else log.debug(chalk.magenta("Updating " + dir));

    fs.stat(utils.addFilesPath(dir), function (err, stats) {
        readdirp({root: utils.addFilesPath(dir)}, function (errs, results) {
            dirs[dir] = {files: {}, size: 0, mtime: stats ? stats.mtime.getTime() : Date.now()};
            if (errs) {
                errs.forEach(function (err) {
                    if (err.code === "ENOENT" && dirs[utils.removeFilesPath(err.path)])
                        delete dirs[utils.removeFilesPath(err.path)];
                    else
                        log.error(err);
                });
                if (typeof cb === "function") cb();
            }

            // Add dirs
            results.directories.forEach(function (d) {
                dirs[utils.removeFilesPath(d.fullPath)] = {files: {}, size: 0, mtime: d.stat.mtime.getTime() || 0};
            });

            // Add files
            results.files.forEach(function (f) {
                var parentDir = utils.removeFilesPath(f.fullParentDir);
                dirs[parentDir].files[f.name] = {size: f.stat.size, mtime: f.stat.mtime.getTime() || 0};
                dirs[parentDir].size += f.stat.size;
            });

            update(dir);
            if (typeof cb === "function") cb();
        });
    });
};

function updateDirSizes() {
    var todo = Object.keys(dirs);
    todo = todo.sort(function (a, b) {
        return -(a.match(/\//g).length - b.match(/\//g).length);
    });

    todo.forEach(function (d) {
        dirs[d].size = 0;
        Object.keys(dirs[d].files).forEach(function (f) {
            dirs[d].size += dirs[d].files[f].size;
        });
    });

    todo.forEach(function (d) {
        if (path.dirname(d) !== "/")
            dirs[path.dirname(d)].size += dirs[d].size;
    });
}

filetree.del = function del(dir) {
    fs.stat(utils.addFilesPath(dir), function (err, stats) {
        if (err) log.error(err);
        if (!stats) return;
        if(stats.isFile()) {
            filetree.unlink(dir);
        } else if (stats.isDirectory()) {
            filetree.unlinkdir(dir);
        }
    });
};

filetree.unlink = function unlink(dir) {
    lookAway();
    utils.rm(utils.addFilesPath(dir), function (err) {
        if (err) log.error(err);
        delete dirs[path.dirname(dir)].files[path.basename(dir)];
        update(path.dirname(dir));
    });
};

filetree.unlinkdir = function unlinkdir(dir) {
    lookAway();
    utils.rm(utils.addFilesPath(dir), function (err) {
        if (err) log.error(err);
        delete dirs[dir];
        Object.keys(dirs).forEach(function (d) {
            if (new RegExp("^" + dir + "/").test(d)) delete dirs[d];
        });
        update(path.dirname(dir));
    });
};

filetree.clipboard = function clipboard(src, dst, type) {
    fs.stat(utils.addFilesPath(src), function (err, stats) {
        lookAway();
        if (err) log.error(err);
        if(stats.isFile())
            filetree[type === "cut" ? "mv" : "cp"](src, dst);
        else if (stats.isDirectory())
            filetree[type === "cut" ? "mvdir" : "cpdir"](src, dst);
    });
};

filetree.mk = function mk(dir, cb) {
    lookAway();
    fs.stat(utils.addFilesPath(dir), function (err) {
        if (err && err.code === "ENOENT") {
            fs.open(utils.addFilesPath(dir), "wx", function (err, fd) {
                if (err) log.error(err);
                fs.close(fd, function (error) {
                    if (error) log.error(error);
                    dirs[path.dirname(dir)].files[path.basename(dir)] = {size: 0, mtime: Date.now()};
                    update(path.dirname(dir));
                    if (cb) cb();
                });
            });
        } else {
            if (cb) cb();
        }
    });
};

filetree.mkdir = function mkdir(dir, cb) {
    lookAway();
    fs.stat(utils.addFilesPath(dir), function (err) {
        if (err && err.code === "ENOENT") {
           utils.mkdir(utils.addFilesPath(dir), function (err) {
             if (err) log.error(err);
             dirs[dir] = {files: {}, size: 0, mtime: Date.now()};
             update(path.dirname(dir));
             if (cb) cb();
           });
       } else {
           if (cb) cb();
       }
    });
};

filetree.move = function move(src, dst, cb) {
    lookAway();
    fs.stat(utils.addFilesPath(src), function (err, stats) {
        if (err) log.error(err);
        if (stats.isFile())
            filetree.mv(src, dst, cb);
        else if (stats.isDirectory())
            filetree.mvdir(src, dst, cb);
    });
};

filetree.mv = function mv(src, dst, cb) {
    lookAway();
    utils.move(utils.addFilesPath(src), utils.addFilesPath(dst), function (err) {
        if (err) log.error(err);
        dirs[path.dirname(dst)].files[path.basename(dst)] = dirs[path.dirname(src)].files[path.basename(src)];
        delete dirs[path.dirname(src)].files[path.basename(src)];
        update(path.dirname(src));
        update(path.dirname(dst));
        if (cb) cb();
    });
};

filetree.mvdir = function mvdir(src, dst, cb) {
    lookAway();
    utils.move(utils.addFilesPath(src), utils.addFilesPath(dst), function (err) {
        if (err) log.error(err);
        // Basedir
        dirs[dst] = dirs[src];
        delete dirs[src];
        // Subdirs
        Object.keys(dirs).forEach(function (dir) {
            if (new RegExp("^" + src + "/").test(dir) && dir !== src && dir !== dst) {
                dirs[dir.replace(new RegExp("^" + src + "/"), dst + "/")] = dirs[dir];
                delete dirs[dir];
            }
        });
        update(path.dirname(src));
        update(path.dirname(dst));
        if (cb) cb();
    });
};

filetree.cp = function cp(src, dst, cb) {
    lookAway();
    utils.copyFile(utils.addFilesPath(src), utils.addFilesPath(dst), function () {
        dirs[path.dirname(dst)].files[path.basename(dst)] = _.clone(dirs[path.dirname(src)].files[path.basename(src)], true);
        dirs[path.dirname(dst)].files[path.basename(dst)].mtime = Date.now();
        update(path.dirname(dst));
        if (cb) cb();
    });
};

filetree.cpdir = function cpdir(src, dst, cb) {
    lookAway();
    utils.copyDir(utils.addFilesPath(src), utils.addFilesPath(dst), function () {
        // Basedir
        dirs[dst] = _.clone(dirs[src], true);
        dirs[dst].mtime = Date.now();
        // Subdirs
        Object.keys(dirs).forEach(function (dir) {
            if (new RegExp("^" + src + "/").test(dir) && dir !== src && dir !== dst) {
                dirs[dir.replace(new RegExp("^" + src + "/"), dst + "/")] = _.clone(dirs[dir], true);
                dirs[dir.replace(new RegExp("^" + src + "/"), dst + "/")].mtime = Date.now();
            }
        });
        update(path.dirname(dst));
        if (cb) cb();
    });
};

filetree.save = function save(dst, data, cb) {
    lookAway();
    fs.stat(utils.addFilesPath(dst), function (err) {
        if (err && err.code !== "ENOENT") return cb(err);
        fs.writeFile(utils.addFilesPath(dst), data, function (err) {
            dirs[path.dirname(dst)].files[path.basename(dst)] = {size: Buffer.byteLength(data), mtime: Date.now()};
            update(path.dirname(dst));
            if (cb) cb(err);
        });
    });
};

filetree.getDirContents = function getDirContents(p) {
    if (!dirs[p]) return;
    var entries = {}, files = dirs[p].files;
    Object.keys(files).forEach(function (file) {
        entries[file] = [
            "f",
            Math.round(files[file].mtime / 1e3),
            files[file].size
        ].join("|");
    });
    Object.keys(dirs).forEach(function (dir) {
        if (path.dirname(dir) === p && path.basename(dir)) {
            entries[path.basename(dir)] = [
                "d",
                Math.round(dirs[dir].mtime / 1e3),
                dirs[dir].size
            ].join("|");
        }
    });
    return entries;
};

// local fs changes. debounced heavily but refresh everything.
var watcher;
var watching = false;
var timer = null;

var updateAll = _.debounce(function () {
    log.debug(chalk.magenta("Updating file tree from watcher"));
    noLog = true;
    filetree.updateDir(null, function() {
        filetree.emit("updateall");
    });
}, 4000);

function watch() {
    watching = true;
    watcher = chokidar.watch(paths.files, {
        alwaysStat    : true,
        ignoreInitial : true,
        usePolling    : true,
        interval      : 2000,
        binaryInterval: 2000
    }).on("error", log.error).on("all", function () {
        if (watching) updateAll();
    });
}

function lookAway() {
    watching = false;
    clearTimeout(timer);
    timer = setTimeout(function () {
        watching = true;
    }, 4000);
}

watch();

module.exports = filetree;
<commit_msg>Reduce watcher delay to 3s, add constants<commit_after>"use strict";

var filetree = new (require("events").EventEmitter)(),
    dirs     = {},
    todoDirs = [],
    noLog    = true;

var _        = require("lodash"),
    chalk    = require("chalk"),
    chokidar = require("chokidar"),
    fs       = require("graceful-fs"),
    path     = require("path"),
    readdirp = require("readdirp");

var log      = require("./log.js"),
    paths    = require("./paths.js").get(),
    utils    = require("./utils.js");

var WATCHER_DELAY = 3000;
var POLL_INTERVAL = 2000;

function filterDirs(dirs) {
    return dirs.sort(function (a, b) {
        return a.match(/\//g).length - b.match(/\//g).length;
    }).filter(function (path, _, self) {
        return self.every(function (another) {
            return another === path || path.indexOf(another + "/") !== 0;
        });
    }).filter(function (path, index, self) {
        return self.indexOf(path) === index;
    });
}

var debouncedUpdate = _.debounce(function() {
    filterDirs(todoDirs).forEach(function (dir) {
        filetree.emit("update", dir);
    });
    todoDirs = [];
}, 100, {trailing: true});

function update(dir) {
    updateDirSizes();
    todoDirs.push(dir);
    debouncedUpdate();
}

filetree.updateDir = function updateDir(dir, cb) {
    if (dir === null) { dir = "/"; dirs = {}; }
    if (noLog) noLog = false; else log.debug(chalk.magenta("Updating " + dir));

    fs.stat(utils.addFilesPath(dir), function (err, stats) {
        readdirp({root: utils.addFilesPath(dir)}, function (errs, results) {
            dirs[dir] = {files: {}, size: 0, mtime: stats ? stats.mtime.getTime() : Date.now()};
            if (errs) {
                errs.forEach(function (err) {
                    if (err.code === "ENOENT" && dirs[utils.removeFilesPath(err.path)])
                        delete dirs[utils.removeFilesPath(err.path)];
                    else
                        log.error(err);
                });
                if (typeof cb === "function") cb();
            }

            // Add dirs
            results.directories.forEach(function (d) {
                dirs[utils.removeFilesPath(d.fullPath)] = {files: {}, size: 0, mtime: d.stat.mtime.getTime() || 0};
            });

            // Add files
            results.files.forEach(function (f) {
                var parentDir = utils.removeFilesPath(f.fullParentDir);
                dirs[parentDir].files[f.name] = {size: f.stat.size, mtime: f.stat.mtime.getTime() || 0};
                dirs[parentDir].size += f.stat.size;
            });

            update(dir);
            if (typeof cb === "function") cb();
        });
    });
};

function updateDirSizes() {
    var todo = Object.keys(dirs);
    todo = todo.sort(function (a, b) {
        return -(a.match(/\//g).length - b.match(/\//g).length);
    });

    todo.forEach(function (d) {
        dirs[d].size = 0;
        Object.keys(dirs[d].files).forEach(function (f) {
            dirs[d].size += dirs[d].files[f].size;
        });
    });

    todo.forEach(function (d) {
        if (path.dirname(d) !== "/")
            dirs[path.dirname(d)].size += dirs[d].size;
    });
}

filetree.del = function del(dir) {
    fs.stat(utils.addFilesPath(dir), function (err, stats) {
        if (err) log.error(err);
        if (!stats) return;
        if(stats.isFile()) {
            filetree.unlink(dir);
        } else if (stats.isDirectory()) {
            filetree.unlinkdir(dir);
        }
    });
};

filetree.unlink = function unlink(dir) {
    lookAway();
    utils.rm(utils.addFilesPath(dir), function (err) {
        if (err) log.error(err);
        delete dirs[path.dirname(dir)].files[path.basename(dir)];
        update(path.dirname(dir));
    });
};

filetree.unlinkdir = function unlinkdir(dir) {
    lookAway();
    utils.rm(utils.addFilesPath(dir), function (err) {
        if (err) log.error(err);
        delete dirs[dir];
        Object.keys(dirs).forEach(function (d) {
            if (new RegExp("^" + dir + "/").test(d)) delete dirs[d];
        });
        update(path.dirname(dir));
    });
};

filetree.clipboard = function clipboard(src, dst, type) {
    fs.stat(utils.addFilesPath(src), function (err, stats) {
        lookAway();
        if (err) log.error(err);
        if(stats.isFile())
            filetree[type === "cut" ? "mv" : "cp"](src, dst);
        else if (stats.isDirectory())
            filetree[type === "cut" ? "mvdir" : "cpdir"](src, dst);
    });
};

filetree.mk = function mk(dir, cb) {
    lookAway();
    fs.stat(utils.addFilesPath(dir), function (err) {
        if (err && err.code === "ENOENT") {
            fs.open(utils.addFilesPath(dir), "wx", function (err, fd) {
                if (err) log.error(err);
                fs.close(fd, function (error) {
                    if (error) log.error(error);
                    dirs[path.dirname(dir)].files[path.basename(dir)] = {size: 0, mtime: Date.now()};
                    update(path.dirname(dir));
                    if (cb) cb();
                });
            });
        } else {
            if (cb) cb();
        }
    });
};

filetree.mkdir = function mkdir(dir, cb) {
    lookAway();
    fs.stat(utils.addFilesPath(dir), function (err) {
        if (err && err.code === "ENOENT") {
           utils.mkdir(utils.addFilesPath(dir), function (err) {
             if (err) log.error(err);
             dirs[dir] = {files: {}, size: 0, mtime: Date.now()};
             update(path.dirname(dir));
             if (cb) cb();
           });
       } else {
           if (cb) cb();
       }
    });
};

filetree.move = function move(src, dst, cb) {
    lookAway();
    fs.stat(utils.addFilesPath(src), function (err, stats) {
        if (err) log.error(err);
        if (stats.isFile())
            filetree.mv(src, dst, cb);
        else if (stats.isDirectory())
            filetree.mvdir(src, dst, cb);
    });
};

filetree.mv = function mv(src, dst, cb) {
    lookAway();
    utils.move(utils.addFilesPath(src), utils.addFilesPath(dst), function (err) {
        if (err) log.error(err);
        dirs[path.dirname(dst)].files[path.basename(dst)] = dirs[path.dirname(src)].files[path.basename(src)];
        delete dirs[path.dirname(src)].files[path.basename(src)];
        update(path.dirname(src));
        update(path.dirname(dst));
        if (cb) cb();
    });
};

filetree.mvdir = function mvdir(src, dst, cb) {
    lookAway();
    utils.move(utils.addFilesPath(src), utils.addFilesPath(dst), function (err) {
        if (err) log.error(err);
        // Basedir
        dirs[dst] = dirs[src];
        delete dirs[src];
        // Subdirs
        Object.keys(dirs).forEach(function (dir) {
            if (new RegExp("^" + src + "/").test(dir) && dir !== src && dir !== dst) {
                dirs[dir.replace(new RegExp("^" + src + "/"), dst + "/")] = dirs[dir];
                delete dirs[dir];
            }
        });
        update(path.dirname(src));
        update(path.dirname(dst));
        if (cb) cb();
    });
};

filetree.cp = function cp(src, dst, cb) {
    lookAway();
    utils.copyFile(utils.addFilesPath(src), utils.addFilesPath(dst), function () {
        dirs[path.dirname(dst)].files[path.basename(dst)] = _.clone(dirs[path.dirname(src)].files[path.basename(src)], true);
        dirs[path.dirname(dst)].files[path.basename(dst)].mtime = Date.now();
        update(path.dirname(dst));
        if (cb) cb();
    });
};

filetree.cpdir = function cpdir(src, dst, cb) {
    lookAway();
    utils.copyDir(utils.addFilesPath(src), utils.addFilesPath(dst), function () {
        // Basedir
        dirs[dst] = _.clone(dirs[src], true);
        dirs[dst].mtime = Date.now();
        // Subdirs
        Object.keys(dirs).forEach(function (dir) {
            if (new RegExp("^" + src + "/").test(dir) && dir !== src && dir !== dst) {
                dirs[dir.replace(new RegExp("^" + src + "/"), dst + "/")] = _.clone(dirs[dir], true);
                dirs[dir.replace(new RegExp("^" + src + "/"), dst + "/")].mtime = Date.now();
            }
        });
        update(path.dirname(dst));
        if (cb) cb();
    });
};

filetree.save = function save(dst, data, cb) {
    lookAway();
    fs.stat(utils.addFilesPath(dst), function (err) {
        if (err && err.code !== "ENOENT") return cb(err);
        fs.writeFile(utils.addFilesPath(dst), data, function (err) {
            dirs[path.dirname(dst)].files[path.basename(dst)] = {size: Buffer.byteLength(data), mtime: Date.now()};
            update(path.dirname(dst));
            if (cb) cb(err);
        });
    });
};

filetree.getDirContents = function getDirContents(p) {
    if (!dirs[p]) return;
    var entries = {}, files = dirs[p].files;
    Object.keys(files).forEach(function (file) {
        entries[file] = [
            "f",
            Math.round(files[file].mtime / 1e3),
            files[file].size
        ].join("|");
    });
    Object.keys(dirs).forEach(function (dir) {
        if (path.dirname(dir) === p && path.basename(dir)) {
            entries[path.basename(dir)] = [
                "d",
                Math.round(dirs[dir].mtime / 1e3),
                dirs[dir].size
            ].join("|");
        }
    });
    return entries;
};

// local fs changes. debounced heavily but refresh everything.
var watcher;
var watching = false;
var timer = null;

var updateAll = _.debounce(function () {
    log.debug(chalk.magenta("Updating file tree from watcher"));
    noLog = true;
    filetree.updateDir(null, function() {
        filetree.emit("updateall");
    });
}, WATCHER_DELAY);

function watch() {
    watching = true;
    watcher = chokidar.watch(paths.files, {
        alwaysStat    : true,
        ignoreInitial : true,
        usePolling    : true,
        interval      : POLL_INTERVAL,
        binaryInterval: POLL_INTERVAL
    }).on("error", log.error).on("all", function () {
        if (watching) updateAll();
    });
}

function lookAway() {
    watching = false;
    clearTimeout(timer);
    timer = setTimeout(function () {
        watching = true;
    }, WATCHER_DELAY);
}

watch();

module.exports = filetree;
<|endoftext|>


<commit_before>/**
 * Pimcore
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.pimcore.org/license
 *
 * @copyright  Copyright (c) 2009-2013 pimcore GmbH (http://www.pimcore.org)
 * @license    http://www.pimcore.org/license     New BSD License
 */

pimcore.registerNS("pimcore.object.tags.hotspotimage");
pimcore.object.tags.hotspotimage = Class.create(pimcore.object.tags.image, {

    type: "hotspotimage",
    data: null,

    marginTop: 10,
    marginLeft: 8,
    fileinfo: null,
    previewItems: [],

    initialize: function (data, fieldConfig) {
        this.hotspots = [];
        this.marker = [];
        this.crop = [];

        this.data = null;
        if (data) {
            this.data = data.image;
            this.hotspots = data.hotspots;
            this.marker = data.marker;
            this.crop = data.crop;
        }
        this.fieldConfig = fieldConfig;
    },

    getGridColumnConfig: function(field) {

        return {header: ts(field.label), width: 100, sortable: false, dataIndex: field.key,
            renderer: function (key, value, metaData, record) {
                this.applyPermissionStyle(key, value, metaData, record);

                if(record.data.inheritedFields[key] && record.data.inheritedFields[key].inherited == true) {
                    metaData.css += " grid_value_inherited";
                }

                if (value && value.id) {
                    return '';
                }
            }.bind(this, field.key)};
    },

    getLayoutEdit: function () {

        if (intval(this.fieldConfig.width) < 1) {
            this.fieldConfig.width = 100;
        }
        if (intval(this.fieldConfig.height) < 1) {
            this.fieldConfig.height = 100;
        }

        var conf = {
            width: this.fieldConfig.width,
            height: this.fieldConfig.height,
            tbar: [{
                xtype: "tbspacer",
                width: 20,
                height: 16,
                cls: "pimcore_icon_droptarget"
            },
                {
                    xtype: "tbtext",
                    text: "" + this.fieldConfig.title + ""
                },"->",{
                    xtype: "button",
                    tooltip: t("crop"),
                    iconCls: "pimcore_icon_image_region",
                    handler: this.openCropWindow.bind(this)
                },{
                    xtype: "button",
                    tooltip: t("add_marker_or_hotspots"),
                    iconCls: "pimcore_icon_image_add_hotspot",
                    handler: this.openHotspotWindow.bind(this)
                },{
                    xtype: "button",
                    tooltip: t("clear_marker_or_hotspots"),
                    iconCls: "pimcore_icon_clear_marker",
                    handler: this.clearData.bind(this)
                },{
                    xtype: "button",
                    iconCls: "pimcore_icon_edit",
                    handler: this.openImage.bind(this)
                }, {
                    xtype: "button",
                    iconCls: "pimcore_icon_delete",
                    handler: this.empty.bind(this)
                },{
                    xtype: "button",
                    iconCls: "pimcore_icon_search",
                    handler: this.openSearchEditor.bind(this)
                },{
                    xtype: "button",
                    iconCls: "pimcore_icon_upload_single",
                    cls: "pimcore_inline_upload",
                    handler: this.uploadDialog.bind(this)
                }]
        };

        this.component = new Ext.Panel(conf);
        this.createImagePanel();

        return this.component;
    },

    createImagePanel: function() {
        this.panel = new Ext.Panel({
            width: this.fieldConfig.width,
            height: this.fieldConfig.height-27,
            bodyCssClass: "pimcore_droptarget_image",
            bodyStyle: "text-align: center; "
        });
        this.component.add(this.panel);

        this.panel.on("afterrender", function (el) {

            // add drop zone
            new Ext.dd.DropZone(el.getEl(), {
                reference: this,
                ddGroup: "element",
                getTargetFromEvent: function(e) {
                    return this.reference.component.getEl();
                },

                onNodeOver : function(target, dd, e, data) {

                    if (data.node.attributes.type == "image") {
                        return Ext.dd.DropZone.prototype.dropAllowed;
                    } else {
                        return Ext.dd.DropZone.prototype.dropNotAllowed;
                    }
                },

                onNodeDrop : this.onNodeDrop.bind(this)
            });

            el.getEl().on("contextmenu", this.onContextMenu.bind(this));

            if (this.data) {
                this.updateImage();
            }

        }.bind(this));

        this.component.doLayout();

    },

    updateImage: function () {
        // 5px padding (-10)
        this.originalWidth = this.component.getInnerWidth();
        this.originalHeight = this.component.getInnerHeight();

        var width = this.getBody().getWidth()-10;
        var height = this.getBody().getHeight()-10;

        var path = "/admin/asset/get-image-thumbnail/id/" + this.data + "/width/" + width
            + "/height/" + height + "/contain/true" + "?" + Ext.urlEncode(this.crop);

        this.getBody().setStyle({
            backgroundImage: "url(" + path + ")",
            backgroundPosition: "center center",
            backgroundRepeat: "no-repeat"
        });

        this.getBody().repaint();

        this.getFileInfo(path);

        this.showPreview();
    },

    getFileInfo: function(path) {
        if (!this.fileinfo) {
            Ext.Ajax.request({
                url: path,
                params: {
                    fileinfo: 1
                },
                success: function (response) {
                    this.fileinfo = Ext.decode(response.responseText);
                    this.showPreview();
                }.bind(this)
            });
        }
    },

    openCropWindow: function () {
        var editor = new pimcore.element.tag.imagecropper(this.data, this.crop, function (data) {
            this.crop = {};
            this.crop["cropWidth"] = data.cropWidth;
            this.crop["cropHeight"] = data.cropHeight;
            this.crop["cropTop"] = data.cropTop;
            this.crop["cropLeft"] = data.cropLeft;
            this.crop["cropPercent"] = true;

            this.dirty = true;

            this.updateImage();
        }.bind(this));
        editor.open(true);
    },

    openHotspotWindow: function() {
        if(this.data) {
            var editor = new pimcore.element.tag.imagehotspotmarkereditor(this.data, {hotspots: this.hotspots, marker: this.marker}, function (data) {
                this.hotspots = data["hotspots"];
                this.marker = data["marker"];

                this.showPreview();

                this.dirty = true;
            }.bind(this));
            editor.open(false);
        }
    },

    clearData: function() {
        this.doClearData();
        this.updateImage();
        pimcore.helpers.showNotification(t("success"), t("hotspots_cleared"), "success");

    },

    doClearData: function() {
        this.hotspots = [];
        this.marker = [];
        this.crop = [];
        this.dirty = true;
    },

    empty: function (nodeDrop) {
        this.data = null;
        this.fileinfo = null;

        if (!nodeDrop) {
            this.doClearData();
        }
        this.dirty = true;
        this.component.removeAll();
        this.createImagePanel();
    },

    getValue: function () {
        return {image: this.data, hotspots: this.hotspots, marker: this.marker, crop: this.crop};
    },

    showPreview: function() {
        if (this.fileinfo) {
            var originalWidth = this.originalWidth;
            var originalHeight = this.originalHeight;

            var addX = (originalWidth - this.fileinfo.width) / 2;
            var addY = (originalHeight - this.fileinfo.height) / 2;

            for(i = 0; i < this.previewItems.length; i++) {
                document.getElementById(this.previewItems[i]).remove();
            }
            this.previewItems = [];

            for (i = 0; i < this.hotspots.length; i++) {
                var hotspotId = "hotspotId-" + uniqid();
                this.panel.body.insertHtml("beforeEnd", '

');
                this.previewItems.push(hotspotId);

                var hotspotEl = Ext.get(hotspotId);
                var config = this.hotspots[i];

                var top = config["top"]/100;
                var left = config["left"]/100;
                var width = ((config["width"] / 100) * this.fileinfo.width) / originalWidth;
                var height = ((config["height"]/100) * this.fileinfo.height) / originalHeight;

                left = ((left * this.fileinfo.width) + addX) / originalWidth;
                top = ((top * this.fileinfo.height) + addY) / originalHeight;

                hotspotEl.applyStyles({
                    top: (originalHeight * top) + "px",
                    left: (originalWidth * left) + "px",
                    width: (originalWidth * width) + "px",
                    height: (originalHeight * height) + "px"
                });

                this.addHotspotInfo(hotspotEl, config);
            }

            for (i = 0; i < this.marker.length; i++) {
                var markerId = "marker-" + uniqid();
                this.panel.body.insertHtml("beforeEnd", '

');
                this.previewItems.push(markerId);
                var markerEl = Ext.get(markerId);

                var config = this.marker[i];
                var top = config["top"]/100;
                var left = config["left"]/100;

                left = ((left * this.fileinfo.width) + addX) / originalWidth;
                top = ((top * this.fileinfo.height) + addY) / originalHeight;

                markerEl.applyStyles({
                    top: ((originalHeight * top) - 35) + "px",
                    left: ((originalWidth * left) - 12)+ "px"
                });

                this.addHotspotInfo(markerEl, config);
            }
        }
    },

    addHotspotInfo: function(element, config) {
        if(config["name"]) {
            element.dom.setAttribute("title", config["name"]);
        }

        var functionCallback = function () {
            this.openHotspotWindow();
        }

        element.addListener('click', functionCallback.bind(this), false);
    }
});<commit_msg>bugfix: imageadvanced, missing css class<commit_after>/**
 * Pimcore
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.pimcore.org/license
 *
 * @copyright  Copyright (c) 2009-2013 pimcore GmbH (http://www.pimcore.org)
 * @license    http://www.pimcore.org/license     New BSD License
 */

pimcore.registerNS("pimcore.object.tags.hotspotimage");
pimcore.object.tags.hotspotimage = Class.create(pimcore.object.tags.image, {

    type: "hotspotimage",
    data: null,

    marginTop: 10,
    marginLeft: 8,
    fileinfo: null,
    previewItems: [],

    initialize: function (data, fieldConfig) {
        this.hotspots = [];
        this.marker = [];
        this.crop = [];

        this.data = null;
        if (data) {
            this.data = data.image;
            this.hotspots = data.hotspots;
            this.marker = data.marker;
            this.crop = data.crop;
        }
        this.fieldConfig = fieldConfig;
    },

    getGridColumnConfig: function(field) {

        return {header: ts(field.label), width: 100, sortable: false, dataIndex: field.key,
            renderer: function (key, value, metaData, record) {
                this.applyPermissionStyle(key, value, metaData, record);

                if(record.data.inheritedFields[key] && record.data.inheritedFields[key].inherited == true) {
                    metaData.css += " grid_value_inherited";
                }

                if (value && value.id) {
                    return '';
                }
            }.bind(this, field.key)};
    },

    getLayoutEdit: function () {

        if (intval(this.fieldConfig.width) < 1) {
            this.fieldConfig.width = 100;
        }
        if (intval(this.fieldConfig.height) < 1) {
            this.fieldConfig.height = 100;
        }

        var conf = {
            width: this.fieldConfig.width,
            height: this.fieldConfig.height,
            tbar: [{
                xtype: "tbspacer",
                width: 20,
                height: 16,
                cls: "pimcore_icon_droptarget"
            },
                {
                    xtype: "tbtext",
                    text: "" + this.fieldConfig.title + ""
                },"->",{
                    xtype: "button",
                    tooltip: t("crop"),
                    iconCls: "pimcore_icon_image_region",
                    handler: this.openCropWindow.bind(this)
                },{
                    xtype: "button",
                    tooltip: t("add_marker_or_hotspots"),
                    iconCls: "pimcore_icon_image_add_hotspot",
                    handler: this.openHotspotWindow.bind(this)
                },{
                    xtype: "button",
                    tooltip: t("clear_marker_or_hotspots"),
                    iconCls: "pimcore_icon_clear_marker",
                    handler: this.clearData.bind(this)
                },{
                    xtype: "button",
                    iconCls: "pimcore_icon_edit",
                    handler: this.openImage.bind(this)
                }, {
                    xtype: "button",
                    iconCls: "pimcore_icon_delete",
                    handler: this.empty.bind(this)
                },{
                    xtype: "button",
                    iconCls: "pimcore_icon_search",
                    handler: this.openSearchEditor.bind(this)
                },{
                    xtype: "button",
                    iconCls: "pimcore_icon_upload_single",
                    cls: "pimcore_inline_upload",
                    handler: this.uploadDialog.bind(this)
                }]
        };

        this.component = new Ext.Panel(conf);
        this.createImagePanel();

        return this.component;
    },

    createImagePanel: function() {
        this.panel = new Ext.Panel({
            width: this.fieldConfig.width,
            height: this.fieldConfig.height-27,
            bodyCssClass: "pimcore_droptarget_image pimcore_image_container",
            bodyStyle: "text-align: center; "
        });
        this.component.add(this.panel);

        this.panel.on("afterrender", function (el) {

            // add drop zone
            new Ext.dd.DropZone(el.getEl(), {
                reference: this,
                ddGroup: "element",
                getTargetFromEvent: function(e) {
                    return this.reference.component.getEl();
                },

                onNodeOver : function(target, dd, e, data) {

                    if (data.node.attributes.type == "image") {
                        return Ext.dd.DropZone.prototype.dropAllowed;
                    } else {
                        return Ext.dd.DropZone.prototype.dropNotAllowed;
                    }
                },

                onNodeDrop : this.onNodeDrop.bind(this)
            });

            el.getEl().on("contextmenu", this.onContextMenu.bind(this));

            if (this.data) {
                this.updateImage();
            }

        }.bind(this));

        this.component.doLayout();

    },

    updateImage: function () {
        // 5px padding (-10)
        this.originalWidth = this.component.getInnerWidth();
        this.originalHeight = this.component.getInnerHeight();

        var width = this.getBody().getWidth()-10;
        var height = this.getBody().getHeight()-10;

        var path = "/admin/asset/get-image-thumbnail/id/" + this.data + "/width/" + width
            + "/height/" + height + "/contain/true" + "?" + Ext.urlEncode(this.crop);

        this.getBody().setStyle({
            backgroundImage: "url(" + path + ")",
            backgroundPosition: "center center",
            backgroundRepeat: "no-repeat"
        });

        this.getBody().repaint();

        this.getFileInfo(path);

        this.showPreview();
    },

    getFileInfo: function(path) {
        if (!this.fileinfo) {
            Ext.Ajax.request({
                url: path,
                params: {
                    fileinfo: 1
                },
                success: function (response) {
                    this.fileinfo = Ext.decode(response.responseText);
                    this.showPreview();
                }.bind(this)
            });
        }
    },

    openCropWindow: function () {
        var editor = new pimcore.element.tag.imagecropper(this.data, this.crop, function (data) {
            this.crop = {};
            this.crop["cropWidth"] = data.cropWidth;
            this.crop["cropHeight"] = data.cropHeight;
            this.crop["cropTop"] = data.cropTop;
            this.crop["cropLeft"] = data.cropLeft;
            this.crop["cropPercent"] = true;

            this.dirty = true;

            this.updateImage();
        }.bind(this));
        editor.open(true);
    },

    openHotspotWindow: function() {
        if(this.data) {
            var editor = new pimcore.element.tag.imagehotspotmarkereditor(this.data, {hotspots: this.hotspots, marker: this.marker}, function (data) {
                this.hotspots = data["hotspots"];
                this.marker = data["marker"];

                this.showPreview();

                this.dirty = true;
            }.bind(this));
            editor.open(false);
        }
    },

    clearData: function() {
        this.doClearData();
        this.updateImage();
        pimcore.helpers.showNotification(t("success"), t("hotspots_cleared"), "success");

    },

    doClearData: function() {
        this.hotspots = [];
        this.marker = [];
        this.crop = [];
        this.dirty = true;
    },

    empty: function (nodeDrop) {
        this.data = null;
        this.fileinfo = null;

        if (!nodeDrop) {
            this.doClearData();
        }
        this.dirty = true;
        this.component.removeAll();
        this.createImagePanel();
    },

    getValue: function () {
        return {image: this.data, hotspots: this.hotspots, marker: this.marker, crop: this.crop};
    },

    showPreview: function() {
        if (this.fileinfo) {
            var originalWidth = this.originalWidth;
            var originalHeight = this.originalHeight;

            var addX = (originalWidth - this.fileinfo.width) / 2;
            var addY = (originalHeight - this.fileinfo.height) / 2;

            for(i = 0; i < this.previewItems.length; i++) {
                document.getElementById(this.previewItems[i]).remove();
            }
            this.previewItems = [];

            for (i = 0; i < this.hotspots.length; i++) {
                var hotspotId = "hotspotId-" + uniqid();
                this.panel.body.insertHtml("beforeEnd", '

');
                this.previewItems.push(hotspotId);

                var hotspotEl = Ext.get(hotspotId);
                var config = this.hotspots[i];

                var top = config["top"]/100;
                var left = config["left"]/100;
                var width = ((config["width"] / 100) * this.fileinfo.width) / originalWidth;
                var height = ((config["height"]/100) * this.fileinfo.height) / originalHeight;

                left = ((left * this.fileinfo.width) + addX) / originalWidth;
                top = ((top * this.fileinfo.height) + addY) / originalHeight;

                hotspotEl.applyStyles({
                    top: (originalHeight * top) + "px",
                    left: (originalWidth * left) + "px",
                    width: (originalWidth * width) + "px",
                    height: (originalHeight * height) + "px"
                });

                this.addHotspotInfo(hotspotEl, config);
            }

            for (i = 0; i < this.marker.length; i++) {
                var markerId = "marker-" + uniqid();
                this.panel.body.insertHtml("beforeEnd", '

');
                this.previewItems.push(markerId);
                var markerEl = Ext.get(markerId);

                var config = this.marker[i];
                var top = config["top"]/100;
                var left = config["left"]/100;

                left = ((left * this.fileinfo.width) + addX) / originalWidth;
                top = ((top * this.fileinfo.height) + addY) / originalHeight;

                markerEl.applyStyles({
                    top: ((originalHeight * top) - 35) + "px",
                    left: ((originalWidth * left) - 12)+ "px"
                });

                this.addHotspotInfo(markerEl, config);
            }
        }
    },

    addHotspotInfo: function(element, config) {
        if(config["name"]) {
            element.dom.setAttribute("title", config["name"]);
        }

        var functionCallback = function () {
            this.openHotspotWindow();
        }

        element.addListener('click', functionCallback.bind(this), false);
    }
});<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2014
 *
 * Woonsan Ko
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE
 */

/**
 *
 * Reverse Proxy Script using Node.js
 * ( https://github.com/woonsan/hippo7-rproxy-nodejs )
 *
 * Usage: `sudo node rproxy.js` will open 80 port.
 *        `node rproxy.js 8888` will open 8888 port.
 *        `node rproxy.js 8888 8443` will open 8888 port and 8443 ssl port.
 *
 */

/*============================================================*/
/* Reverse Proxy Server Default Options Configuration         */
/*------------------------------------------------------------*/

var defaultOptions = {
  xfwd: true, // add X-Forwarded-* headers
};

// SSL Key file paths; change those paths if you have those in other paths.
var ssl_private_key_path = './priv.pem';
var ssl_certificate_path = './cert.pem';

/*------------------------------------------------------------*/
/* URL Path Mappings Configuration for Reverse Proxy Targets  */
/*------------------------------------------------------------*/
// You can add edit mappings below!

var mappings = [
  {
    host: '*',
    pathregex: /^\/cms(\/|$)/,
    route: {
      target: 'http://127.0.0.1:8080'
    }
  },
  {
    host: '*',
    pathregex: /^\/site(\/|$)/,
    route: {
      target: 'http://127.0.0.1:8080'
    }
  },
  {
    host: '*',
    pathregex: /^/,
    pathreplace: '/site',
    route: {
      target: 'http://127.0.0.1:8080'
    }
  },
];

/*------------------------------------------------------------*/
/* End of Configuration                                       */
/*============================================================*/

// Normally you don't need to look into the detail below
// in most cases unless you want to debug. :-)

var colors = require('colors');

colors.setTheme({
  silly: 'rainbow',
  input: 'grey',
  verbose: 'cyan',
  prompt: 'grey',
  info: 'green',
  data: 'grey',
  help: 'cyan',
  warn: 'yellow',
  debug: 'blue',
  error: 'red'
});

/**************************************************************/
/* Internal Server Handling Code from here                    */
/*------------------------------------------------------------*/

// find out the port number command line argument
var port = 80;
if (process.argv[2]) {
  port = parseInt(process.argv[2]);
}

// build up the ssl options
var sslOptions = {};
var fs = require('fs');
if (fs.existsSync(ssl_private_key_path)) {
  sslOptions.key = fs.readFileSync(ssl_private_key_path, 'utf8');
} else {
  console.log(('SSL Disabled. SSL private key file does not exist: ' + ssl_private_key_path).warn);
}
if (fs.existsSync(ssl_certificate_path)) {
  sslOptions.cert = fs.readFileSync(ssl_certificate_path, 'utf8');
} else {
  console.log(('SSL Disabled. SSL certificate does not exist: ' + ssl_certificate_path).warn);
}

// let's start building proxy server from here

var http = require('http'),
    httpProxy = require('http-proxy');

//
// function to find a mapping by request path
//
var findMapping = function(req) {
  var host = req.headers['host'];
  for (var i in mappings) {
    var um = mappings[i];
    if (um.host && um.host != '*' && um.host != host) {
      continue;
    }
    if (um.pathregex && req.url.match(um.pathregex)) {
      return um;
    }
  }
  return null;
};

//
// Create a proxy server with custom application logic
//
var proxyServer = httpProxy.createProxyServer(defaultOptions);
proxyServer.on('error', function(error) {
  console.log('ERROR'.warn, 'Proxy server error: '.error, error);
});
proxyServer.on('proxyReq', function(proxyReq, req, res, options) {
  var target = options.target;
  if (target) {
    if ((target.protocol == 'http' && target.port == '80') ||
        (target.protocol == 'https' && target.port == '443')) {
      proxyReq.setHeader('Host', target.hostname);
    } else {
      proxyReq.setHeader('Host', target.host);
    }
  }
  if (req.proxyMapping && req.proxyMapping.reqHeaders) {
    var headers = req.proxyMapping.reqHeaders;
    for (var name in headers) {
      proxyReq.setHeader(name, headers[name]);
    }
  }
});

//
// proxy handler
//
var proxyHandler = function(req, res) {
  var mapping = findMapping(req);
  if (!mapping) {
    res.writeHead(404);
    res.end();
    console.log('WARN'.warn, 'Mapping not found for '.info, req.url.data);
  } else {
    req.proxyMapping = mapping;
    var oldReqUrl = req.url;
    if (mapping.pathreplace) {
      req.url = oldReqUrl.replace(mapping.pathregex, mapping.pathreplace);
    }
    console.log('INFO'.info, oldReqUrl.data, '->'.verbose, ('' + mapping.route.target + req.url).data);
    proxyServer.web(req, res, mapping.route);
  }
};

//
// Create your custom server and just call `proxy.web()` to proxy
// a web request to the target passed in the options
// also you can use `proxy.ws()` to proxy a websockets request
//
http.createServer(proxyHandler).listen(port);
console.log('');
console.log(('Reverse Proxy Server started at port ' + port + ' ...').info);

// start another server at ssl port if configured
if (sslOptions.key && sslOptions.cert) {
  var sslPort = 443;
  if (process.argv[3]) {
    sslPort = parseInt(process.argv[3]);
  }
  // Create the HTTPS proxy server in front of an HTTP server
  httpProxy.createServer({
    target: {
      host: 'localhost',
      port: port
    },
    ssl: {
      key: sslOptions.key,
      cert: sslOptions.cert
    },
    xfwd: true
  }).listen(sslPort);
  console.log(('Reverse Proxy Server started at SSL port ' + sslPort + ' ...').info);
}

// print out the route mapping information
console.log('');
console.log('Route mappings are as follows:'.info);
console.log('***********************************************************'.info);
console.log(mappings);
console.log('***********************************************************'.info);
console.log('');
<commit_msg>Update rproxy.js<commit_after>/*
 * Copyright (c) 2013-2015
 *
 * Woonsan Ko
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE
 */

/**
 *
 * Reverse Proxy Script using Node.js
 * ( https://github.com/woonsan/hippo7-rproxy-nodejs )
 *
 * Usage: `sudo node rproxy.js` will open 80 port.
 *        `node rproxy.js 8888` will open 8888 port.
 *        `node rproxy.js 8888 8443` will open 8888 port and 8443 ssl port.
 *
 */

/*============================================================*/
/* Reverse Proxy Server Default Options Configuration         */
/*------------------------------------------------------------*/

var defaultOptions = {
  xfwd: true, // add X-Forwarded-* headers
};

// SSL Key file paths; change those paths if you have those in other paths.
var ssl_private_key_path = './priv.pem';
var ssl_certificate_path = './cert.pem';

/*------------------------------------------------------------*/
/* URL Path Mappings Configuration for Reverse Proxy Targets  */
/*------------------------------------------------------------*/
// You can add edit mappings below!

var mappings = [
  {
    host: '*',
    pathregex: /^\/cms(\/|$)/,
    route: {
      target: 'http://localhost:8080'
    }
  },
  {
    host: '*',
    pathregex: /^\/site(\/|$)/,
    route: {
      target: 'http://localhost:8080'
    }
  },
  {
    host: '*',
    pathregex: /^/,
    pathreplace: '/site',
    route: {
      target: 'http://localhost:8080'
    }
  },
];

/*------------------------------------------------------------*/
/* End of Configuration                                       */
/*============================================================*/

// Normally you don't need to look into the detail below
// in most cases unless you want to debug. :-)

var colors = require('colors');

colors.setTheme({
  silly: 'rainbow',
  input: 'grey',
  verbose: 'cyan',
  prompt: 'grey',
  info: 'green',
  data: 'grey',
  help: 'cyan',
  warn: 'yellow',
  debug: 'blue',
  error: 'red'
});

/**************************************************************/
/* Internal Server Handling Code from here                    */
/*------------------------------------------------------------*/

// find out the port number command line argument
var port = 80;
if (process.argv[2]) {
  port = parseInt(process.argv[2]);
}

// build up the ssl options
var sslOptions = {};
var fs = require('fs');
if (fs.existsSync(ssl_private_key_path)) {
  sslOptions.key = fs.readFileSync(ssl_private_key_path, 'utf8');
} else {
  console.log(('SSL Disabled. SSL private key file does not exist: ' + ssl_private_key_path).warn);
}
if (fs.existsSync(ssl_certificate_path)) {
  sslOptions.cert = fs.readFileSync(ssl_certificate_path, 'utf8');
} else {
  console.log(('SSL Disabled. SSL certificate does not exist: ' + ssl_certificate_path).warn);
}

// let's start building proxy server from here

var http = require('http'),
    httpProxy = require('http-proxy');

//
// function to find a mapping by request path
//
var findMapping = function(req) {
  var host = req.headers['host'];
  for (var i in mappings) {
    var um = mappings[i];
    if (um.host && um.host != '*' && um.host != host) {
      continue;
    }
    if (um.pathregex && req.url.match(um.pathregex)) {
      return um;
    }
  }
  return null;
};

//
// Create a proxy server with custom application logic
//
var proxyServer = httpProxy.createProxyServer(defaultOptions);
proxyServer.on('error', function(error) {
  console.log('-',
              ('[' + new Date().toISOString() + ']').data,
              'ERROR'.warn,
              '-',
              '-'.data,
              ('[Gateway Error: ' + error).warn,
              ('503').info);
});
proxyServer.on('proxyReq', function(proxyReq, req, res, options) {
  var target = options.target;
  if (target) {
    if ((target.protocol == 'http' && target.port == '80') ||
        (target.protocol == 'https' && target.port == '443')) {
      proxyReq.setHeader('Host', target.hostname);
    } else {
      proxyReq.setHeader('Host', target.host);
    }
    target['targetHostHeaderValue'] = proxyReq.getHeader('Host');
    req.proxyAttrs['target'] = target;
  }
  if (req.proxyAttrs['proxyMapping'] && req.proxyAttrs['proxyMapping'].reqHeaders) {
    var headers = req.proxyAttrs['proxyMapping'].reqHeaders;
    for (var name in headers) {
      proxyReq.setHeader(name, headers[name]);
    }
  }
});
proxyServer.on('proxyRes', function(proxyRes, req, res, options) {
  //console.log('DEBUG'.debug, req);
  var location = proxyRes.headers['location'];
  if (location && req.proxyAttrs['target']) {
    var target = req.proxyAttrs['target'];
    if (location.indexOf(target.href) == 0) {
      var sourceBase = req.headers['x-forwarded-proto'] + '://' + req.headers['host'] + '/';
      location = sourceBase + location.substring(target.href.length);
      proxyRes.headers['location'] = location;
    }
  }
  console.log(req.headers['x-forwarded-for'],
              ('[' + new Date().toISOString() + ']').data,
              req.method.info,
              req.proxyAttrs['requestUrl'],
              ('HTTP/' + proxyRes.httpVersion).data,
              (req.proxyAttrs['target'].href + req.proxyAttrs['targetRequestUrl'].substring(1)),
              ('' + proxyRes.statusCode).info);
});

//
// proxy handler
//
var proxyHandler = function(req, res) {
  req.proxyAttrs = {};
  var mapping = findMapping(req);
  if (!mapping) {
    res.writeHead(404);
    res.end();
    console.log('WARN'.warn, 'Mapping not found for '.info, req.url.data);
  } else {
    req.proxyAttrs['proxyMapping'] = mapping;
    var oldReqUrl = req.url;
    req.proxyAttrs['requestUrl'] = oldReqUrl;
    if (mapping.pathreplace) {
      req.url = oldReqUrl.replace(mapping.pathregex, mapping.pathreplace);
    }
    req.proxyAttrs['targetRequestUrl'] = req.url;
    proxyServer.web(req, res, mapping.route);
  }
};

//
// Create your custom server and just call `proxy.web()` to proxy
// a web request to the target passed in the options
// also you can use `proxy.ws()` to proxy a websockets request
//
http.createServer(proxyHandler).listen(port);
console.log('');
console.log(('Reverse Proxy Server started at port ' + port + ' ...').info);

// start another server at ssl port if configured
if (sslOptions.key && sslOptions.cert) {
  var sslPort = 443;
  if (process.argv[3]) {
    sslPort = parseInt(process.argv[3]);
  }
  // Create the HTTPS proxy server in front of an HTTP server
  httpProxy.createServer({
    target: {
      host: 'localhost',
      port: port
    },
    ssl: {
      key: sslOptions.key,
      cert: sslOptions.cert
    },
    xfwd: true
  }).listen(sslPort);
  console.log(('Reverse Proxy Server started at SSL port ' + sslPort + ' ...').info);
}

// print out the route mapping information
console.log('');
console.log('Route mappings are as follows:'.info);
console.log('***********************************************************'.info);
console.log(mappings);
console.log('***********************************************************'.info);
console.log('');
<|endoftext|>


<commit_before>/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2014 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

(function() {

  var module = angular.module('pnc.common.restclient');

  module.value('BUILD_RECORD_ENDPOINT', '/build-records/:recordId');

  /**
   *
   */
  module.factory('BuildRecordDAO', [
    '$resource',
    'cachedGetter',
    'REST_BASE_URL',
    'BUILD_RECORD_ENDPOINT',
    'BuildConfigurationDAO',
    'UserDAO',
    'PageFactory',
    'QueryHelper',
    function($resource, cachedGetter, REST_BASE_URL, BUILD_RECORD_ENDPOINT,
             BuildConfigurationDAO, UserDAO, PageFactory, qh) {
      var ENDPOINT = REST_BASE_URL + BUILD_RECORD_ENDPOINT;

      var resource = $resource(ENDPOINT, {
        recordId: '@id',
        q: '@q'
      }, {
        _getAll: {
          method: 'GET',
          url: ENDPOINT + qh.searchOnly(['buildConfigurationAudited.name', 'buildConfigurationAudited.project.name'])
        },
        getLog: {
          method: 'GET',
          url: ENDPOINT + '/log',
          transformResponse: function(data) { return { payload: data }; }
        },
        _getArtifacts: {
          method: 'GET',
          url: ENDPOINT + '/artifacts'
        },
        _getByConfiguration: {
          method: 'GET',
          url: REST_BASE_URL + '/build-records/build-configurations/:configurationId' +
            qh.searchOnly(['buildConfigurationAudited.name'])
        },
        _getByUser: {
          method: 'GET',
          url: ENDPOINT + '/?q=user.id==:userId'
        },
        _getAllForProject: {
          method: 'GET',
          url: REST_BASE_URL + 'record/projects/:projectId'
        },
        _getLatestForConfiguration: {
          method: 'GET',
          url: REST_BASE_URL + '/build-records/build-configurations/:configurationId?pageIndex=0&pageSize=1&sort==desc=id'
        },
        getAuditedBuildConfiguration: {
          method: 'GET',
          url: ENDPOINT + '/build-configuration-audited'
        },
        _getByBCSetRecord: {
          method: 'GET',
          url: REST_BASE_URL + '/build-records' +
          '?q=' + qh.search(['buildConfigSetRecord.buildConfigurationSet.name']) +
          ';buildConfigSetRecord.id==:bcSetRecordId'
        }
      });

      PageFactory.decorateNonPaged(resource, '_getAll', 'query');
      PageFactory.decorateNonPaged(resource, '_getArtifacts', 'getArtifacts');
      PageFactory.decorateNonPaged(resource, '_getByConfiguration', 'getByConfiguration');
      PageFactory.decorateNonPaged(resource, '_getAllForProject', 'getAllForProject');
      PageFactory.decorateNonPaged(resource, '_getLatestForConfiguration', 'getLatestForConfiguration');

      PageFactory.decorate(resource, '_getAll', 'getPaged');
      PageFactory.decorate(resource, '_getByConfiguration', 'getPagedByConfiguration');
      PageFactory.decorate(resource, '_getByBCSetRecord', 'getPagedByBCSetRecord');
      PageFactory.decorate(resource, '_getByUser', 'getPagedByUser');

      resource.prototype.getBuildConfiguration = cachedGetter(
        function(buildRecord) {
          return BuildConfigurationDAO.get({ configurationId: buildRecord.buildConfigurationId });
        }
      );

      resource.prototype.getUser = cachedGetter(
        function(record) {
          return UserDAO.get({ userId: record.userId });
        }
      );

      return resource;
    }

  ]);

})();
<commit_msg>Mapped endpoint on client<commit_after>/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2014 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict';

(function() {

  var module = angular.module('pnc.common.restclient');

  module.value('BUILD_RECORD_ENDPOINT', '/build-records/:recordId');

  /**
   *
   */
  module.factory('BuildRecordDAO', [
    '$resource',
    'cachedGetter',
    'REST_BASE_URL',
    'BUILD_RECORD_ENDPOINT',
    'BuildConfigurationDAO',
    'UserDAO',
    'PageFactory',
    'QueryHelper',
    function($resource, cachedGetter, REST_BASE_URL, BUILD_RECORD_ENDPOINT,
             BuildConfigurationDAO, UserDAO, PageFactory, qh) {
      var ENDPOINT = REST_BASE_URL + BUILD_RECORD_ENDPOINT;

      var resource = $resource(ENDPOINT, {
        recordId: '@id',
        q: '@q'
      }, {
        _getAll: {
          method: 'GET',
          url: ENDPOINT + qh.searchOnly(['buildConfigurationAudited.name', 'buildConfigurationAudited.project.name'])
        },
        getLog: {
          method: 'GET',
          url: ENDPOINT + '/log',
          transformResponse: function(data) { return { payload: data }; }
        },
        _getArtifacts: {
          method: 'GET',
          url: ENDPOINT + '/artifacts'
        },
        _getByConfiguration: {
          method: 'GET',
          url: REST_BASE_URL + '/build-records/build-configurations/:configurationId' +
            qh.searchOnly(['buildConfigurationAudited.name'])
        },
        _getByUser: {
          method: 'GET',
          url: ENDPOINT + '/?q=user.id==:userId'
        },
        _getAllForProject: {
          method: 'GET',
          url: REST_BASE_URL + 'record/projects/:projectId'
        },
        _getLatestForConfiguration: {
          method: 'GET',
          url: REST_BASE_URL + '/build-records/build-configurations/:configurationId?pageIndex=0&pageSize=1&sort==desc=id'
        },
        getAuditedBuildConfiguration: {
          method: 'GET',
          url: ENDPOINT + '/build-configuration-audited'
        },
        getCompletedOrRunning: {
          method: 'GET',
          url: ENDPOINT + '/completed-or-running'
        },
        _getByBCSetRecord: {
          method: 'GET',
          url: REST_BASE_URL + '/build-records' +
          '?q=' + qh.search(['buildConfigSetRecord.buildConfigurationSet.name']) +
          ';buildConfigSetRecord.id==:bcSetRecordId'
        }
      });

      PageFactory.decorateNonPaged(resource, '_getAll', 'query');
      PageFactory.decorateNonPaged(resource, '_getArtifacts', 'getArtifacts');
      PageFactory.decorateNonPaged(resource, '_getByConfiguration', 'getByConfiguration');
      PageFactory.decorateNonPaged(resource, '_getAllForProject', 'getAllForProject');
      PageFactory.decorateNonPaged(resource, '_getLatestForConfiguration', 'getLatestForConfiguration');

      PageFactory.decorate(resource, '_getAll', 'getPaged');
      PageFactory.decorate(resource, '_getByConfiguration', 'getPagedByConfiguration');
      PageFactory.decorate(resource, '_getByBCSetRecord', 'getPagedByBCSetRecord');
      PageFactory.decorate(resource, '_getByUser', 'getPagedByUser');

      resource.prototype.getBuildConfiguration = cachedGetter(
        function(buildRecord) {
          return BuildConfigurationDAO.get({ configurationId: buildRecord.buildConfigurationId });
        }
      );

      resource.prototype.getUser = cachedGetter(
        function(record) {
          return UserDAO.get({ userId: record.userId });
        }
      );

      return resource;
    }

  ]);

})();
<|endoftext|>


<commit_before>import { Typeahead } from 'react-bootstrap-typeahead';
import React from 'react';
import style from './ComboBox.css';
import { compose, withState, mapProps, mapPropsStream } from 'recompose';
import R from 'ramda';
import wrapComponentWithClass from '../../../hoc/wrap-component-with-class';
const noop = () => {};
const compareLowerCase = (a, b) =>
            (a && a.toLowerCase && a.toLowerCase()) === (b && b.toLowerCase && b.toLowerCase());

const comp = compose(
  withState('currentInputValue', 'setCurrentInputValue', ''),
  mapProps(({ options, currentInputValue, showValueInOptions, ...props }) => ({
    options: currentInputValue && showValueInOptions && R.findIndex(x => x.label === currentInputValue)(options) < 0 ?
        [({ label: currentInputValue, value: currentInputValue }), ...options] : options,
    currentInputValue, ...props,
  })
  ),
  mapPropsStream(props$ => props$.scan((prev, next) =>
    (prev.selected && prev.selected.length > 0 && next.selected && next.selected.length === 0) ?
    {
      ...next,
      currentInputValue: '',
    } : next
  )
  )
)(({ ...props, options,
  selected = [],
  autofocus,
  setCurrentInputValue,
  currentInputValue,
  onChange = noop,
  onInputChange = noop,
}) => {
  const wrapperThemeClass = props.wrapperThemeClass ?
    props.wrapperThemeClass : style['combo-box-default-wrapper-theme-class'];
  return (

      <Typeahead
        {...{ ...props, options, selected }}
        onChange={selectedValues => {
          if (onChange === noop) return;
          if (selectedValues.length < 1) {
            if (props.clearButton) onChange();
            return;
          }
          setCurrentInputValue(selectedValues[0].label);
          onChange(selectedValues[0]);
          onChange = noop;
        }}
        onInputChange={text => {
          setCurrentInputValue(text);
          const selectedItem = options.find((x) => compareLowerCase(x, text) || compareLowerCase(x.label, text));
          if (selectedItem && selectedItem !== selected[0]) {
            onChange(selectedItem);
            onChange = noop;
          }
          onInputChange(text);
        }}
        ref={e =>
        {
          e && autofocus && e.refs.instance.focus();
          if (currentInputValue === '' && selected.length === 0) {
            const value = e && e.refs.instance.refs.input && e.refs.instance.refs.input.props.value;
            if (value && value !== '') {
              e.refs.instance.clear();
            }
          }
        }}
      />

  );
});

export default wrapComponentWithClass(comp);
<commit_msg>fix ugly hack<commit_after>import { Typeahead } from 'react-bootstrap-typeahead';
import React from 'react';
import style from './ComboBox.css';
import { compose, withState, mapProps, mapPropsStream } from 'recompose';
import R from 'ramda';
import wrapComponentWithClass from '../../../hoc/wrap-component-with-class';
const noop = () => {};
const compareLowerCase = (a, b) =>
            (a && a.toLowerCase && a.toLowerCase()) === (b && b.toLowerCase && b.toLowerCase());

const comp = compose(
  withState('currentInputValue', 'setCurrentInputValue', ''),
  mapProps(({ options, currentInputValue, showValueInOptions, ...props }) => ({
    options: currentInputValue && showValueInOptions && R.findIndex(x => x.label === currentInputValue)(options) < 0 ?
        [({ label: currentInputValue, value: currentInputValue }), ...options] : options,
    currentInputValue, ...props,
  })
  ),
  mapPropsStream(props$ => props$.scan((prev, next) =>
    (prev.selected && prev.selected.length > 0 && next.selected && next.selected.length === 0) ?
    {
      ...next,
      currentInputValue: '',
    } : next
  )
  )
)(({ ...props, options,
  selected = [],
  autofocus,
  setCurrentInputValue,
  currentInputValue,
  onChange = noop,
  onInputChange = noop,
}) => {
  const wrapperThemeClass = props.wrapperThemeClass ?
    props.wrapperThemeClass : style['combo-box-default-wrapper-theme-class'];
  return (

      <Typeahead
        {...{ ...props, options, selected }}
        onChange={selectedValues => {
          if (onChange === noop) return;
          if (selectedValues.length < 1) {
            if (props.clearButton) onChange();
            return;
          }
          setCurrentInputValue(selectedValues[0].label);
        }}
        onInputChange={text => {
          setCurrentInputValue(text);
          const selectedItem = options.find((x) => compareLowerCase(x, text) || compareLowerCase(x.label, text));
          if (selectedItem) {
            onChange(selectedItem);
          }
          onInputChange(text);
        }}
        ref={e =>
        {
          e && autofocus && e.refs.instance.focus();
          if (currentInputValue === '' && selected.length === 0) {
            const value = e && e.refs.instance.refs.input && e.refs.instance.refs.input.props.value;
            if (value && value !== '') {
              e.refs.instance.clear();
            }
          }
        }}
      />

  );
});

export default wrapComponentWithClass(comp);
<|endoftext|>


<commit_before>const Action = require("../models/action");

// Below are the possible actions
var actions = {
    // Normal user actions
    signIn: {
        displayName: "Sign in",
        inlineDisplayName: "Signed in",
        category: "auth"
    },
    signUp: {
        displayName: "Sign up",
        inlineDisplayName: "Signed up",
        category: "auth"
    },
    signOut: {
        displayName: "Sign out",
        inlineDisplayName: "Signed out",
        category: "auth"
    },
    changePassword: {
        displayName: "Change password",
        inlineDisplayName: "Changed password",
        category: "account"
    },
    deactivate: {
        displayName: "Deactivate own account",
        inlineDisplayName: "Deactivated their account",
        category: "account"
    },
    place: {
        displayName: "Place pixel",
        inlineDisplayName: "Placed a pixel",
        category: "gameplay",
        hideInfo: true,
        sentenceEndTextFormatting: " at (${x}, ${y})"
    },
    sendChatMessage: {
        displayName: "Send chat message",
        inlineDisplayName: "Sent a chat message",
        category: "chat"
    },
    // Moderation actions
    ban: {
        displayName: "Ban user",
        inlineDisplayName: "Banned user",
        category: "moderation",
        requiresModerator: true,
        isPrivileged: true
    },
    unban: {
        displayName: "Unban user",
        inlineDisplayName: "Unbanned user",
        category: "moderation",
        requiresModerator: true,
        isPrivileged: true
    },
    activateOther: {
        displayName: "Activate account",
        inlineDisplayName: "Activated account",
        category: "moderation",
        requiresModerator: true,
        isPrivileged: true
    },
    deactivateOther: {
        displayName: "Deactivate account",
        inlineDisplayName: "Deactivated account",
        category: "moderation",
        requiresModerator: true,
        isPrivileged: true
    },
    updateNotes: {
        displayName: "Update user notes",
        inlineDisplayName: "Updated user notes",
        category: "moderation",
        requiresModerator: true,
        isPrivileged: true
    },
    // Administrative actions
    giveModerator: {
        displayName: "Give moderator",
        inlineDisplayName: "Gave moderator to",
        category: "administrative",
        requiresModerator: true,
        isPrivileged: true
    },
    removeModerator: {
        displayName: "Remove moderator",
        inlineDisplayName: "Removed moderator from",
        category: "administrative",
        requiresModerator: true,
        isPrivileged: true
    },
    reloadConfig: {
        displayName: "Reload site config",
        inlineDisplayName: "Reloaded site config",
        category: "administrative",
        isPrivileged: true
    },
    refreshClients: {
        displayName: "Refresh all clients",
        inlineDisplayName: "Refreshed all clients",
        category: "administrative",
        isPrivileged: true
    },
    sendBroadcast: {
        displayName: "Broadcast a message to all users",
        inlineDisplayName: "Broadcasted a message to all users",
        category: "administrative",
        isPrivileged: true
    }
}

var actionLogger = {
    log: function(actionID, performingUser, moderatingUser = null, info = null) {
        Action({
            actionID: actionID,
            performingUserID: performingUser.id,
            moderatingUserID: moderatingUser ? moderatingUser.id : null,
            info: info,
            date: new Date()
        }).save().catch(err => app.reportError("An error occurred while trying to log action: " + err));
    },

    infoForAction: function(actionID) {
        return actions[actionID];
    },

    getAllActionInfo: function() {
        return actions;
    },

    actionIDsToRetrieve: function(modOnly = false) {
        return Object.keys(actions).filter(a => modOnly ? actions[a].isPrivileged : true);
    }
}

module.exports = actionLogger;
<commit_msg>Fix display name for update user notes<commit_after>const Action = require("../models/action");

// Below are the possible actions
var actions = {
    // Normal user actions
    signIn: {
        displayName: "Sign in",
        inlineDisplayName: "Signed in",
        category: "auth"
    },
    signUp: {
        displayName: "Sign up",
        inlineDisplayName: "Signed up",
        category: "auth"
    },
    signOut: {
        displayName: "Sign out",
        inlineDisplayName: "Signed out",
        category: "auth"
    },
    changePassword: {
        displayName: "Change password",
        inlineDisplayName: "Changed password",
        category: "account"
    },
    deactivate: {
        displayName: "Deactivate own account",
        inlineDisplayName: "Deactivated their account",
        category: "account"
    },
    place: {
        displayName: "Place pixel",
        inlineDisplayName: "Placed a pixel",
        category: "gameplay",
        hideInfo: true,
        sentenceEndTextFormatting: " at (${x}, ${y})"
    },
    sendChatMessage: {
        displayName: "Send chat message",
        inlineDisplayName: "Sent a chat message",
        category: "chat"
    },
    // Moderation actions
    ban: {
        displayName: "Ban user",
        inlineDisplayName: "Banned user",
        category: "moderation",
        requiresModerator: true,
        isPrivileged: true
    },
    unban: {
        displayName: "Unban user",
        inlineDisplayName: "Unbanned user",
        category: "moderation",
        requiresModerator: true,
        isPrivileged: true
    },
    activateOther: {
        displayName: "Activate account",
        inlineDisplayName: "Activated account",
        category: "moderation",
        requiresModerator: true,
        isPrivileged: true
    },
    deactivateOther: {
        displayName: "Deactivate account",
        inlineDisplayName: "Deactivated account",
        category: "moderation",
        requiresModerator: true,
        isPrivileged: true
    },
    updateNotes: {
        displayName: "Update user notes",
        inlineDisplayName: "Updated user notes for",
        category: "moderation",
        requiresModerator: true,
        isPrivileged: true
    },
    // Administrative actions
    giveModerator: {
        displayName: "Give moderator",
        inlineDisplayName: "Gave moderator to",
        category: "administrative",
        requiresModerator: true,
        isPrivileged: true
    },
    removeModerator: {
        displayName: "Remove moderator",
        inlineDisplayName: "Removed moderator from",
        category: "administrative",
        requiresModerator: true,
        isPrivileged: true
    },
    reloadConfig: {
        displayName: "Reload site config",
        inlineDisplayName: "Reloaded site config",
        category: "administrative",
        isPrivileged: true
    },
    refreshClients: {
        displayName: "Refresh all clients",
        inlineDisplayName: "Refreshed all clients",
        category: "administrative",
        isPrivileged: true
    },
    sendBroadcast: {
        displayName: "Broadcast a message to all users",
        inlineDisplayName: "Broadcasted a message to all users",
        category: "administrative",
        isPrivileged: true
    }
}

var actionLogger = {
    log: function(actionID, performingUser, moderatingUser = null, info = null) {
        Action({
            actionID: actionID,
            performingUserID: performingUser.id,
            moderatingUserID: moderatingUser ? moderatingUser.id : null,
            info: info,
            date: new Date()
        }).save().catch(err => app.reportError("An error occurred while trying to log action: " + err));
    },

    infoForAction: function(actionID) {
        return actions[actionID];
    },

    getAllActionInfo: function() {
        return actions;
    },

    actionIDsToRetrieve: function(modOnly = false) {
        return Object.keys(actions).filter(a => modOnly ? actions[a].isPrivileged : true);
    }
}

module.exports = actionLogger;
<|endoftext|>