<commit_before>export { Pointwise_HigherHalfDifferent };
export { Depthwise_HigherHalfDifferent };
export { AvgMax_Or_ChannelMultiplier };

import { Int } from "./ValueDesc_Base.js";

/** Describe id, range, name of the processing mode of pointwise convolution's higher half channels.
 *
 * Convert number value into integer between [ 0, 4 ] representing:
 *   - 0: NONE                                                 (normal poitwise convolution. no higher half different.)
 *   - 1: HIGHER_HALF_COPY_LOWER_HALF__LOWER_HALF_PASS_THROUGH (pointwise1 of ShuffleNetV2_ByMobileNetV1's head) ( pointwise1ChannelCount == 0 )
 *   - 2: HIGHER_HALF_COPY_LOWER_HALF                          (pointwise1 of ShuffleNetV2_ByMobileNetV1's head) ( pointwise1ChannelCount > 0 )
 *   - 3: HIGHER_HALF_ANOTHER_POINTWISE                        (pointwise2 of ShuffleNetV2_ByMobileNetV1's head)
 *   - 4: HIGHER_HALF_PASS_THROUGH                             (pointwise1/pointwise2 of ShuffleNetV2_ByMobileNetV1's body/tail)
 */
class Pointwise_HigherHalfDifferent extends Int {

  constructor() {
    super( 0, 4, [
      "NONE",                                                 // (0)
      "HIGHER_HALF_COPY_LOWER_HALF__LOWER_HALF_PASS_THROUGH", // (1)
      "HIGHER_HALF_COPY_LOWER_HALF",                          // (2)
      "HIGHER_HALF_ANOTHER_POINTWISE",                        // (3)
      "HIGHER_HALF_PASS_THROUGH",                             // (4)
    ] );
  }

}

/** The only one ValueDesc.Pointwise_HigherHalfDifferent instance. */
Pointwise_HigherHalfDifferent.Singleton = new Pointwise_HigherHalfDifferent;

/** Describe id, range, name of the processing mode of depthwise convolution's higher half channels.
 *
 * Convert number value into integer between [ 0, 2 ] representing:
 *   - 0: NONE                                    (normal depthwise convolution. no higher half different.)
 *   - 1: HIGHER_HALF_DEPTHWISE2                  (depthwise1 of ShuffleNetV2_ByMobileNetV1's head)
 *   - 2: HIGHER_HALF_PASS_THROUGH                (depthwise1 of ShuffleNetV2_ByMobileNetV1's body/tail)

//!!! (2022/07/13 Remarked) Does not work.
// *   - 3: HIGHER_HALF_COPY_LOWER_HALF_DEPTHWISE2  (depthwise1 of ShuffleNetV2_ByMobileNetV1's head when ( pointwiseChannelCount == 0 )

 *                                                   and ( depthwise_AvgMax_Or_ChannelMultiplier == 2 ) )
 */
class Depthwise_HigherHalfDifferent extends Int {

  constructor() {
    super( 0, 2, [
      "NONE",                     // (0)
      "HIGHER_HALF_DEPTHWISE2",   // (1)
      "HIGHER_HALF_PASS_THROUGH", // (2)

//!!! (2022/07/13 Remarked) Does not work.
//      "HIGHER_HALF_COPY_LOWER_HALF_DEPTHWISE2", // (3)
    ] );
  }

}

/** The only one ValueDesc.Depthwise_HigherHalfDifferent instance. */
Depthwise_HigherHalfDifferent.Singleton = new Depthwise_HigherHalfDifferent;

/** Describe depthwise operation's id, range, name.
 *
 * Convert number value into integer between [ -2, 32 ] representing depthwise operation:
 *   - -2: average pooling. (AVG)
 *   - -1: maximum pooling. (MAX)
 *   -  0: no depthwise operation. (NONE)
 *   - [ 1, 32 ]: depthwise convolution with channel multiplier between 1 and 32 (inclusive).
 */
class AvgMax_Or_ChannelMultiplier extends Int {

  constructor() {
    super( -2, 32, [ "AVG", "MAX", "NONE" ] );
  }

}

/** The only one ValueDesc.AvgMax_Or_ChannelMultiplier instance. */
AvgMax_Or_ChannelMultiplier.Singleton = new AvgMax_Or_ChannelMultiplier;

<commit_msg>Update ValueDesc_Other.js<commit_after>export { Pointwise_HigherHalfDifferent };
export { Depthwise_HigherHalfDifferent };
export { AvgMax_Or_ChannelMultiplier };

import { Int } from "./ValueDesc_Base.js";

/** Describe id, range, name of the processing mode of pointwise convolution's higher half channels.
 *
 * Convert number value into integer between [ 0, 4 ] representing:
 *   - 0: NONE                                                 (normal poitwise convolution. no higher half different.)
 *   - 1: HIGHER_HALF_COPY_LOWER_HALF__LOWER_HALF_PASS_THROUGH (pointwise1 of ShuffleNetV2_ByMobileNetV1's head) ( pointwise1ChannelCount == 0 )
 *   - 2: HIGHER_HALF_COPY_LOWER_HALF                          (pointwise1 of ShuffleNetV2_ByMobileNetV1's head) ( pointwise1ChannelCount > 0 )
 *   - 3: HIGHER_HALF_ANOTHER_POINTWISE                        (pointwise2 of ShuffleNetV2_ByMobileNetV1's head)
 *   - 4: HIGHER_HALF_PASS_THROUGH                             (pointwise1/pointwise2 of ShuffleNetV2_ByMobileNetV1's body/tail)
 */
class Pointwise_HigherHalfDifferent extends Int {

  constructor() {
    super( 0, 4, {
      NONE:                                                 0,
      HIGHER_HALF_COPY_LOWER_HALF__LOWER_HALF_PASS_THROUGH: 1,
      HIGHER_HALF_COPY_LOWER_HALF:                          2,
      HIGHER_HALF_ANOTHER_POINTWISE:                        3,
      HIGHER_HALF_PASS_THROUGH:                             4,
    } );
  }

}

/** The only one ValueDesc.Pointwise_HigherHalfDifferent instance. */
Pointwise_HigherHalfDifferent.Singleton = new Pointwise_HigherHalfDifferent;

/** Describe id, range, name of the processing mode of depthwise convolution's higher half channels.
 *
 * Convert number value into integer between [ 0, 2 ] representing:
 *   - 0: NONE                                    (normal depthwise convolution. no higher half different.)
 *   - 1: HIGHER_HALF_DEPTHWISE2                  (depthwise1 of ShuffleNetV2_ByMobileNetV1's head)
 *   - 2: HIGHER_HALF_PASS_THROUGH                (depthwise1 of ShuffleNetV2_ByMobileNetV1's body/tail)

//!!! (2022/07/13 Remarked) Does not work.
// *   - 3: HIGHER_HALF_COPY_LOWER_HALF_DEPTHWISE2  (depthwise1 of ShuffleNetV2_ByMobileNetV1's head when ( pointwiseChannelCount == 0 )

 *                                                   and ( depthwise_AvgMax_Or_ChannelMultiplier == 2 ) )
 */
class Depthwise_HigherHalfDifferent extends Int {

  constructor() {
    super( 0, 2, {
      NONE:                     0,
      HIGHER_HALF_DEPTHWISE2:   1,
      HIGHER_HALF_PASS_THROUGH: 2,

//!!! (2022/07/13 Remarked) Does not work.
//      "HIGHER_HALF_COPY_LOWER_HALF_DEPTHWISE2: 3)
    } );
  }

}

/** The only one ValueDesc.Depthwise_HigherHalfDifferent instance. */
Depthwise_HigherHalfDifferent.Singleton = new Depthwise_HigherHalfDifferent;

/** Describe depthwise operation's id, range, name.
 *
 * Convert number value into integer between [ -2, 32 ] representing depthwise operation:
 *   - -2: average pooling. (AVG)
 *   - -1: maximum pooling. (MAX)
 *   -  0: no depthwise operation. (NONE)
 *   - [ 1, 32 ]: depthwise convolution with channel multiplier between 1 and 32 (inclusive).
 */
class AvgMax_Or_ChannelMultiplier extends Int {

  constructor() {
    super( -2, 32, { AVG: -2, MAX: -1, NONE: 0 } );
  }

}

/** The only one ValueDesc.AvgMax_Or_ChannelMultiplier instance. */
AvgMax_Or_ChannelMultiplier.Singleton = new AvgMax_Or_ChannelMultiplier;

<|endoftext|>


<commit_before>export { AsyncWorker_Proxy as Proxy };

import * as Pool from "../Pool.js";
import * as Recyclable from "../Recyclable.js";
import { PromiseResolveReject } from "./AsyncWorker_PromiseResolveReject.js";
import { processingId_Resulter_Map } from "./AsyncWorker_processingId_Resulter_Map.js";
import { Resulter } from "./AsyncWorker_Resulter.js";

/**
 * Hold the worker and its related promise map. It is a wrapper of a neural network
 * web worker for handling and communicating easily.
 *
 * @member {string} workerURL
 *   The worker's source codes URL.
 *
 * @member {Worker} worker
 *   The worker.
 *
 * @member {number} processingId_next
 *   The next processing id. Zero means no command has been sent. Every
 * postCommand_and_expectResult() call will use a new id.
 *
 * @member {processingId_Resulter_Map} the_processingId_Resulter_Map
 *   Every worker has a result pending promise map. The key of the map is processing
 * id. The value of the map is a AsyncWorker.Resulter.
 *
 */
class AsyncWorker_Proxy extends Recyclable.Root {

  /**
   * Used as default AsyncWorker.Proxy provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "AsyncWorker.Proxy.Pool",
    AsyncWorker_Proxy, AsyncWorker_Proxy.setAsConstructor );

  /** */
  constructor( workerURL ) {
    super();
    AsyncWorker_Proxy.setAsConstructor_self.call( this, workerURL );
  }

  /** @override */
  static setAsConstructor() {
    super.setAsConstructor();
    AsyncWorker_Proxy.setAsConstructor_self.call( this, workerURL );
    return this;
  }

  /** @override */
  static setAsConstructor_self( workerURL ) {

    // Q: What if processingId become too large (e.g. infinity)?
    // A: Because Number.MAX_SAFE_INTEGER is pretty large (at least, 2 ** 52 ),
    //    it is not so easy to become out of bounds.
    //
    this.processingId_next = 0;

    if ( this.the_processingId_Resulter_Map )
      this.the_processingId_Resulter_Map.clear();
    else
      this.the_processingId_Resulter_Map = new processingId_Resulter_Map();

    AsyncWorker_Proxy.createWorker.call( this, workerURL );
  }

  /** @override */
  disposeResources() {

    if ( this.worker ) {
      // Note: No processingId, because this command needs not return value.
      this.postCommandArgs( "disposeResources" );
      this.worker = null;
    }

    this.workerOptions = undefined;
    this.workerURL = workerURL;

    this.the_processingId_Resulter_Map.clear();

    this.processingId_next = undefined;

    super.disposeResources();
  }

  /**
   * @param {AsyncWorker_Proxy} this
   *   The worker proxy.
   */
  static createWorker( workerURL ) {
    this.workerURL = workerURL;

    // Should not use "module" type worker, otherwise the worker can not use
    // importScripts() to load tensorflow.js library.
    //
    //this.workerOptions = { type: "module" }; // So that the worker script could use import statement.
    this.workerOptions = null;

    this.worker = new Worker( this.workerURL, this.workerOptions );

    // Register callback from the web worker.
    this.worker.onmessage = AsyncWorker_Proxy.onmessage_from_AsyncWorker_Body.bind( this );
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * and expect the final result.
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   *   - The command is a string which is the WorkerBody's method function to be
   *       called.
   *
   *   - The args is an array which will be destructured into multiple argements
   *       and passed into the WorkerBody's method function.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   *
   * @return {Promise}
   *   Return a promise resolved to the final value of the processing's resulter
   * from WorkerBody. (i.e. Only the Xxx of { done: true, value: Xxx } resolved.
   * All other intermediate result { done: false, value: Yyy } are discarded.)
   */
  createPromise_by_postCommandArgs( commandArgs, transferableObjectArray ) {
    let resulter = this.createResulter_by_postCommandArgs(
      commandArgs, transferableObjectArray );
    return resulter.untilDone();
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * and expect result.
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   *   - The command is a string which is the WorkerBody's method function to be
   *       called.
   *
   *   - The args is an array which will be destructured into multiple argements
   *       and passed into the WorkerBody's method function.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   *
   * @return {AsyncWorker.Resulter}
   *   Return an async generator for receving result from WorkerBody of the processing.
   */
  createResulter_by_postCommandArgs( commandArgs, transferableObjectArray ) {
    let processingId = this.processingId_next;
    ++this.processingId_next;

    let resulter = this.the_processingId_Resulter_Map.createResulter_by_processingId(
      processingId );
    this.worker.postMessage( data, transferableObjectArray );
    return resulter;
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * without expecting result. (i.e. fire-and-forget)
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   */
  postCommandArgs( commandArgs, transferableObjectArray ) {
    this.worker.postMessage( commandArgs, transferableObjectArray );
  }

  /**
   * Dispatch messages come from the owned web worker. Please register this method
   * as this WorkerProxy's Worker.onmessage.
   *
   * @param {AsyncWorker_Proxy} this
   *   The "this" should be binded to this AsyncWorker_Proxy object.
   */
  static onmessage_from_AsyncWorker_Body( e ) {

    // ( e.data == [ processingId, done, value ] )
    let [ processingId, done, value ] = e.data;

    this.the_processingId_Resulter_Map.resolve_by_processingId_done_value(
      processingId, done, value );
  }

}
<commit_msg>createResulter_by_postCommandArgs<commit_after>export { AsyncWorker_Proxy as Proxy };

import * as Pool from "../Pool.js";
import * as Recyclable from "../Recyclable.js";
import { PromiseResolveReject } from "./AsyncWorker_PromiseResolveReject.js";
import { processingId_Resulter_Map } from "./AsyncWorker_processingId_Resulter_Map.js";
import { Resulter } from "./AsyncWorker_Resulter.js";

/**
 * Hold the worker and its related promise map. It is a wrapper of a neural network
 * web worker for handling and communicating easily.
 *
 * @member {string} workerURL
 *   The worker's source codes URL.
 *
 * @member {Worker} worker
 *   The worker.
 *
 * @member {number} processingId_next
 *   The next processing id. Zero means no command has been sent. Every
 * postCommand_and_expectResult() call will use a new id.
 *
 * @member {processingId_Resulter_Map} the_processingId_Resulter_Map
 *   Every worker has a result pending promise map. The key of the map is processing
 * id. The value of the map is a AsyncWorker.Resulter.
 *
 */
class AsyncWorker_Proxy extends Recyclable.Root {

  /**
   * Used as default AsyncWorker.Proxy provider for conforming to Recyclable interface.
   */
  static Pool = new Pool.Root( "AsyncWorker.Proxy.Pool",
    AsyncWorker_Proxy, AsyncWorker_Proxy.setAsConstructor );

  /** */
  constructor( workerURL ) {
    super();
    AsyncWorker_Proxy.setAsConstructor_self.call( this, workerURL );
  }

  /** @override */
  static setAsConstructor() {
    super.setAsConstructor();
    AsyncWorker_Proxy.setAsConstructor_self.call( this, workerURL );
    return this;
  }

  /** @override */
  static setAsConstructor_self( workerURL ) {

    // Q: What if processingId become too large (e.g. infinity)?
    // A: Because Number.MAX_SAFE_INTEGER is pretty large (at least, 2 ** 52 ),
    //    it is not so easy to become out of bounds.
    //
    this.processingId_next = 0;

    if ( this.the_processingId_Resulter_Map )
      this.the_processingId_Resulter_Map.clear();
    else
      this.the_processingId_Resulter_Map = new processingId_Resulter_Map();

    AsyncWorker_Proxy.createWorker.call( this, workerURL );
  }

  /** @override */
  disposeResources() {

    if ( this.worker ) {
      // Note: No processingId, because this command needs not return value.
      this.postCommandArgs( "disposeResources" );
      this.worker = null;
    }

    this.workerOptions = undefined;
    this.workerURL = workerURL;

    this.the_processingId_Resulter_Map.clear();

    this.processingId_next = undefined;

    super.disposeResources();
  }

  /**
   * @param {AsyncWorker_Proxy} this
   *   The worker proxy.
   */
  static createWorker( workerURL ) {
    this.workerURL = workerURL;

    // Should not use "module" type worker, otherwise the worker can not use
    // importScripts() to load tensorflow.js library.
    //
    //this.workerOptions = { type: "module" }; // So that the worker script could use import statement.
    this.workerOptions = null;

    this.worker = new Worker( this.workerURL, this.workerOptions );

    // Register callback from the web worker.
    this.worker.onmessage = AsyncWorker_Proxy.onmessage_from_AsyncWorker_Body.bind( this );
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * and expect the final result.
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   *   - The command is a string which is the WorkerBody's method function to be
   *       called.
   *
   *   - The args is an array which will be destructured into multiple argements
   *       and passed into the WorkerBody's method function.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   *
   * @return {Promise}
   *   Return a promise resolved to the final value of the processing's resulter
   * from WorkerBody. (i.e. Only the Xxx of { done: true, value: Xxx } resolved.
   * All other intermediate result { done: false, value: Yyy } are discarded.)
   */
  createPromise_by_postCommandArgs( commandArgs, transferableObjectArray ) {
    let resulter = this.createResulter_by_postCommandArgs(
      commandArgs, transferableObjectArray );
    return resulter.untilDone();
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * and expect result.
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   *   - The command is a string which is the WorkerBody's method function to be
   *       called.
   *
   *   - The args is an array which will be destructured into multiple argements
   *       and passed into the WorkerBody's method function.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   *
   * @return {AsyncWorker.Resulter}
   *   Return an async generator for receving result from WorkerBody of the processing.
   */
  createResulter_by_postCommandArgs( commandArgs, transferableObjectArray ) {
    let processingId = this.processingId_next;
    ++this.processingId_next;

    let resulter = this.the_processingId_Resulter_Map.createResulter_by_processingId(
      processingId );
    this.worker.postMessage( commandArgs, transferableObjectArray );
    return resulter;
  }

  /**
   * Send command and args (perhaps, with transferable object array) to WorkerBody
   * without expecting result. (i.e. fire-and-forget)
   *
   * @param {Array} commandArgs
   *   An array (i.e. [ comand, ...args ]) which will be sent to the WorkerBody.
   *
   * @param {Array} transferableObjectArray
   *   The transferable object array when postMessage. It could be undefined (but
   * can not be null).
   */
  postCommandArgs( commandArgs, transferableObjectArray ) {
    this.worker.postMessage( commandArgs, transferableObjectArray );
  }

  /**
   * Dispatch messages come from the owned web worker. Please register this method
   * as this WorkerProxy's Worker.onmessage.
   *
   * @param {AsyncWorker_Proxy} this
   *   The "this" should be binded to this AsyncWorker_Proxy object.
   */
  static onmessage_from_AsyncWorker_Body( e ) {

    // ( e.data == [ processingId, done, value ] )
    let [ processingId, done, value ] = e.data;

    this.the_processingId_Resulter_Map.resolve_by_processingId_done_value(
      processingId, done, value );
  }

}
<|endoftext|>


<commit_before>ZBase.registerView((function() {
  var query_mgr;
  var path_prefix = "/a/apps/dawanda_seller_analytics";

  var load = function(path) {
    var result;
    var page = $.getTemplate(
        "views/seller",
        "seller_overview_main_tpl");

    $.onClick($("z-checkbox.premium", page), paramChanged);
    $("z-dropdown.metrics", page).addEventListener("change", function() {
      renderTable($(".zbase_seller_overview table.overview"), result, path);
      $.pushHistoryState(path_prefix + "?" + $.buildQueryString(getQueryParams()));
    });
    $("z-search.seller", page).addEventListener("z-search-submit", function(e) {
      $.navigateTo(path_prefix + "/" + e.detail.value);
    });

    $.handleLinks(page);
    $.replaceViewport(page);

    setParamPremiumSeller(UrlUtil.getParamValue(path, "premium"));
    setParamMetrics(UrlUtil.getParamValue(path, "metrics"));
    setParamOffset(UrlUtil.getParamValue(path, "offset"));
    setParamsOrder(
        UrlUtil.getParamValue(path, "order_by"),
        UrlUtil.getParamValue(path, "order_fn"));

    query_mgr = EventSourceHandler();
    var query = query_mgr.get(
      "sql_query",
      "/api/v1/sql?format=json_sse&query=" + encodeURIComponent(getSQLQuery()));

    query.addEventListener("result", function(e) {
      query_mgr.close("sql_query");
      result = JSON.parse(e.data).results[0];
      hideLoader();
      renderTable($(".zbase_seller_overview table.overview"), result, path);
      setPaginationFor(result.rows.length);
      setPaginationBack();

      var until = Date.now();
      $(".zbase_seller_overview .time_range").innerHTML =
         DateUtil.printDate(until - DateUtil.millisPerDay) + "-" +
         DateUtil.printDate(until);
    });

    query.addEventListener("error", function(e) {
      query_mgr.close("sql_query");
      $.fatalError();
    }, false);

    query.addEventListener("status", function(e) {
      renderQueryProgress(JSON.parse(e.data));
    }, false);
  };

  var destroy = function() {
    query_mgr.closeAll();
  };

  var getSQLQuery = function() {
    var order = getParamsOrder();
    var offset = getParamOffset();

    var query_str =
      "select count(1) as days, shop_id, " +
      "sum(num_active_products) num_active_products, " +
      "sum(num_listed_products) num_listed_products, " +
      "sum(num_purchases) num_purchases, " +
      "sum(num_refunds) num_refunds," +
      "sum(refund_rate) refund_rate," +
      "sum(gmv_eurcent) gmv_eurcent, " +
      "sum(refunded_gmv_eurcent) refunded_gmv_eurcent," +
      "sum(gmv_per_transaction_eurcent) / count(1) gmv_per_transaction_eurcent, " +
      "sum(shop_page_views) shop_page_views, " +
      "sum(product_page_views) product_page_views, " +
      "sum(listview_views_search_page) + sum(listview_views_shop_page) + sum(listview_views_catalog_page) + sum(listview_views_ads) + sum(listview_views_recos) as total_listviews, " +
      "sum(listview_views_search_page) listview_views_search_page," +
      "sum(listview_clicks_search_page) listview_clicks_search_page," +
      "sum(listview_ctr_search_page) / count(1) listview_ctr_search_page," +
      "sum(listview_views_catalog_page) listview_views_catalog_page," +
      "sum(listview_clicks_catalog_page) listview_clicks_catalog_page," +
      "sum(listview_ctr_catalog_page) / count(1) listview_ctr_catalog_page," +
      "sum(listview_views_shop_page) listview_views_shop_page," +
      "sum(listview_clicks_shop_page) listview_clicks_shop_page," +
      "sum(listview_ctr_shop_page) / count(1) listview_ctr_shop_page," +
      "sum(listview_views_ads) listview_views_ads, " +
      "sum(listview_clicks_ads) listview_clicks_ads, " +
      "sum(listview_ctr_ads) / count(1) listview_ctr_ads, " +
      "sum(listview_views_recos) listview_views_recos, " +
      "sum(listview_clicks_recos) listview_clicks_recos, " +
      "sum(listview_ctr_recos) / count(1) listview_ctr_recos " +
      "from shop_stats.last30d where " +
      order.order_by + " > 0 group by shop_id order by " + order.order_by +
      " " + order.order_fn + " limit 20 offset " + offset + ";";

    return query_str;
  };

  var renderQueryProgress = function(progress) {
    QueryProgressWidget.render(
        $(".zbase_seller_stats .query_progress"),
        progress);
  };

  var hideLoader = function() {
    $(".zbase_seller_stats .zbase_seller_overview").classList.remove("hidden");
    $(".zbase_seller_stats .query_progress").classList.add("hidden");
  };

  var renderTable = function(elem, result, path) {
    var metrics = {shop_id: true};
    $(".zbase_seller_stats z-dropdown.metrics")
        .getValue()
        .split(",")
        .forEach(function(metric) {
          metrics[metric] = true;
        });

    var table_tpl = $.getTemplate(
        "views/seller_overview",
        "seller_overview_table_tpl");

    result.columns.forEach(function(metric) {
      if (metrics[metric]) {
        var th = $("th." + metric, table_tpl);
        th.classList.remove("hidden");
        $.onClick($(".asc", th), function() {
          orderByParamChanged(metric, "asc");
        });
        $.onClick($(".desc", th), function() {
          orderByParamChanged(metric, "desc");
        });
      }
    });

    var tr_tpl = $.getTemplate(
        "views/seller_overview",
        "seller_overview_row_tpl");

    var tbody = $("tbody", table_tpl);
    result.rows.forEach(function(row) {
      var tr = tr_tpl.cloneNode(true);
      var url = "/a/apps/dawanda_seller_analytics/" + row[1]

      for (var i = 0; i < row.length; i++) {
        if (metrics[result.columns[i]]) {
          var td = $("td." + result.columns[i], tr);
          var a = $("a", td);
          a.innerHTML = ZBaseSellerMetrics[result.columns[i]].print(row[i]);
          a.href = url;
          td.classList.remove("hidden");
        }
      }

      tbody.appendChild(tr);
    });

    $.handleLinks(table_tpl);
    $.replaceContent(elem, table_tpl);

    setParamsOrder(
        UrlUtil.getParamValue(path, "order_by"),
        UrlUtil.getParamValue(path, "order_fn"));
  };

  var setPaginationFor = function(num_results) {
    var params = getQueryParams();
    params.limit = parseInt(params.limit, 10);

    if (num_results < params.limit) {
      $(".zbase_seller_stats .pager .for").classList.add("disabled");
      return;
    }

    params.offset = parseInt(params.offset, 10) + params.limit;
    $(".zbase_seller_stats .pager .for").href =
        path_prefix + "?" + $.buildQueryString(params);
  };

  var setPaginationBack = function() {
    var params = getQueryParams();
    params.offset = parseInt(params.offset, 10);

    if (params.offset <= 0) {
      $(".zbase_seller_stats .pager .back").classList.add("disabled");
      return;
    }

    params.offset = params.offset - parseInt(params.limit, 10);
    $(".zbase_seller_stats .pager .back").href =
        path_prefix + "?" + $.buildQueryString(params);
  };

  var setParamPremiumSeller = function(value) {
    if (value) {
      $(".zbase_seller_stats z-checkbox.premium").setAttribute(
        "data-active", "active");
    } else {
      $(".zbase_seller_stats z-checkbox.premium").removeAttribute("data-active");
    }
  };

  var setParamMetrics = function(metrics) {
    if (metrics) {
      $(".zbase_seller_stats z-dropdown.metrics").setValue(metrics.split(","));
    }
  };

  var setParamsOrder = function(order_by, order_fn) {
    if (order_by && order_fn) {
      if ($(".zbase_seller_stats thead")) {
        $(".zbase_seller_stats th.order_by").classList.remove("order_by");
        $(".zbase_seller_stats th." + order_by).classList.add("order_by");
      }

      var table = $(".zbase_seller_stats table.overview");
      table.setAttribute("data-order-by", order_by);
      table.setAttribute("data-order-fn", order_fn);
    }
  };

  var setParamOffset = function(offset) {
    if (!offset) {
      offset = 0;
    }

    $(".zbase_seller_stats .pager").setAttribute("data-offset", offset);
  };

  var getParamsOrder = function() {
    var table = $(".zbase_seller_stats table.overview");

    return {
      order_by: table.getAttribute("data-order-by"),
      order_fn: table.getAttribute("data-order-fn")
    };
  };

  var getParamOffset = function() {
    return parseInt(
        $(".zbase_seller_stats .pager").getAttribute("data-offset"), 10);
  };

  var getQueryParams = function() {
    var params = getParamsOrder();
    params.offset = getParamOffset();
    params.metrics = $(".zbase_seller_stats z-dropdown.metrics").getValue();
    params.premium = $(".zbase_seller_stats z-checkbox.premium").hasAttribute(
          "data-active");
    params.limit = "20";

    return params;
  };

  var paramChanged = function() {
    $.navigateTo(path_prefix + "?" + $.buildQueryString(getQueryParams()));
  };

  var orderByParamChanged = function(order_by, order_fn) {
    setParamsOrder(order_by, order_fn);
    setParamOffset(0);
    paramChanged();
  };

  return {
    name: "seller_overview",
    loadView: function(params) {load(params.path);},
    unloadView: destroy,
    handleNavigationChange: load
  };

})());
<commit_msg>seller list: set bread crumbs<commit_after>ZBase.registerView((function() {
  var query_mgr;
  var path_prefix = "/a/apps/dawanda_seller_analytics";

  var load = function(path) {
    ZBaseMainMenu.show();
    HeaderWidget.setBreadCrumbs([
      {href: path_prefix, title: "Analytics"},
      {href: path_prefix, title: "Sellers"}]);

    var result;
    var page = $.getTemplate(
        "views/seller",
        "seller_overview_main_tpl");

    $.onClick($("z-checkbox.premium", page), paramChanged);
    $("z-dropdown.metrics", page).addEventListener("change", function() {
      renderTable($(".zbase_seller_overview table.overview"), result, path);
      $.pushHistoryState(path_prefix + "?" + $.buildQueryString(getQueryParams()));
    });
    $("z-search.seller", page).addEventListener("z-search-submit", function(e) {
      $.navigateTo(path_prefix + "/" + e.detail.value);
    });

    $.handleLinks(page);
    $.replaceViewport(page);

    setParamPremiumSeller(UrlUtil.getParamValue(path, "premium"));
    setParamMetrics(UrlUtil.getParamValue(path, "metrics"));
    setParamOffset(UrlUtil.getParamValue(path, "offset"));
    setParamsOrder(
        UrlUtil.getParamValue(path, "order_by"),
        UrlUtil.getParamValue(path, "order_fn"));

    query_mgr = EventSourceHandler();
    var query = query_mgr.get(
      "sql_query",
      "/api/v1/sql?format=json_sse&query=" + encodeURIComponent(getSQLQuery()));

    query.addEventListener("result", function(e) {
      query_mgr.close("sql_query");
      result = JSON.parse(e.data).results[0];
      hideLoader();
      renderTable($(".zbase_seller_overview table.overview"), result, path);
      setPaginationFor(result.rows.length);
      setPaginationBack();

      var until = Date.now();
      $(".zbase_seller_overview .time_range").innerHTML =
         DateUtil.printDate(until - DateUtil.millisPerDay) + "-" +
         DateUtil.printDate(until);
    });

    query.addEventListener("error", function(e) {
      query_mgr.close("sql_query");
      $.fatalError();
    }, false);

    query.addEventListener("status", function(e) {
      renderQueryProgress(JSON.parse(e.data));
    }, false);
  };

  var destroy = function() {
    query_mgr.closeAll();
  };

  var getSQLQuery = function() {
    var order = getParamsOrder();
    var offset = getParamOffset();

    var query_str =
      "select count(1) as days, shop_id, " +
      "sum(num_active_products) num_active_products, " +
      "sum(num_listed_products) num_listed_products, " +
      "sum(num_purchases) num_purchases, " +
      "sum(num_refunds) num_refunds," +
      "sum(refund_rate) refund_rate," +
      "sum(gmv_eurcent) gmv_eurcent, " +
      "sum(refunded_gmv_eurcent) refunded_gmv_eurcent," +
      "sum(gmv_per_transaction_eurcent) / count(1) gmv_per_transaction_eurcent, " +
      "sum(shop_page_views) shop_page_views, " +
      "sum(product_page_views) product_page_views, " +
      "sum(listview_views_search_page) + sum(listview_views_shop_page) + sum(listview_views_catalog_page) + sum(listview_views_ads) + sum(listview_views_recos) as total_listviews, " +
      "sum(listview_views_search_page) listview_views_search_page," +
      "sum(listview_clicks_search_page) listview_clicks_search_page," +
      "sum(listview_ctr_search_page) / count(1) listview_ctr_search_page," +
      "sum(listview_views_catalog_page) listview_views_catalog_page," +
      "sum(listview_clicks_catalog_page) listview_clicks_catalog_page," +
      "sum(listview_ctr_catalog_page) / count(1) listview_ctr_catalog_page," +
      "sum(listview_views_shop_page) listview_views_shop_page," +
      "sum(listview_clicks_shop_page) listview_clicks_shop_page," +
      "sum(listview_ctr_shop_page) / count(1) listview_ctr_shop_page," +
      "sum(listview_views_ads) listview_views_ads, " +
      "sum(listview_clicks_ads) listview_clicks_ads, " +
      "sum(listview_ctr_ads) / count(1) listview_ctr_ads, " +
      "sum(listview_views_recos) listview_views_recos, " +
      "sum(listview_clicks_recos) listview_clicks_recos, " +
      "sum(listview_ctr_recos) / count(1) listview_ctr_recos " +
      "from shop_stats.last30d where " +
      order.order_by + " > 0 group by shop_id order by " + order.order_by +
      " " + order.order_fn + " limit 20 offset " + offset + ";";

    return query_str;
  };

  var renderQueryProgress = function(progress) {
    QueryProgressWidget.render(
        $(".zbase_seller_stats .query_progress"),
        progress);
  };

  var hideLoader = function() {
    $(".zbase_seller_stats .zbase_seller_overview").classList.remove("hidden");
    $(".zbase_seller_stats .query_progress").classList.add("hidden");
  };

  var renderTable = function(elem, result, path) {
    var metrics = {shop_id: true};
    $(".zbase_seller_stats z-dropdown.metrics")
        .getValue()
        .split(",")
        .forEach(function(metric) {
          metrics[metric] = true;
        });

    var table_tpl = $.getTemplate(
        "views/seller_overview",
        "seller_overview_table_tpl");

    result.columns.forEach(function(metric) {
      if (metrics[metric]) {
        var th = $("th." + metric, table_tpl);
        th.classList.remove("hidden");
        $.onClick($(".asc", th), function() {
          orderByParamChanged(metric, "asc");
        });
        $.onClick($(".desc", th), function() {
          orderByParamChanged(metric, "desc");
        });
      }
    });

    var tr_tpl = $.getTemplate(
        "views/seller_overview",
        "seller_overview_row_tpl");

    var tbody = $("tbody", table_tpl);
    result.rows.forEach(function(row) {
      var tr = tr_tpl.cloneNode(true);
      var url = "/a/apps/dawanda_seller_analytics/" + row[1]

      for (var i = 0; i < row.length; i++) {
        if (metrics[result.columns[i]]) {
          var td = $("td." + result.columns[i], tr);
          var a = $("a", td);
          a.innerHTML = ZBaseSellerMetrics[result.columns[i]].print(row[i]);
          a.href = url;
          td.classList.remove("hidden");
        }
      }

      tbody.appendChild(tr);
    });

    $.handleLinks(table_tpl);
    $.replaceContent(elem, table_tpl);

    setParamsOrder(
        UrlUtil.getParamValue(path, "order_by"),
        UrlUtil.getParamValue(path, "order_fn"));
  };

  var setPaginationFor = function(num_results) {
    var params = getQueryParams();
    params.limit = parseInt(params.limit, 10);

    if (num_results < params.limit) {
      $(".zbase_seller_stats .pager .for").classList.add("disabled");
      return;
    }

    params.offset = parseInt(params.offset, 10) + params.limit;
    $(".zbase_seller_stats .pager .for").href =
        path_prefix + "?" + $.buildQueryString(params);
  };

  var setPaginationBack = function() {
    var params = getQueryParams();
    params.offset = parseInt(params.offset, 10);

    if (params.offset <= 0) {
      $(".zbase_seller_stats .pager .back").classList.add("disabled");
      return;
    }

    params.offset = params.offset - parseInt(params.limit, 10);
    $(".zbase_seller_stats .pager .back").href =
        path_prefix + "?" + $.buildQueryString(params);
  };

  var setParamPremiumSeller = function(value) {
    if (value) {
      $(".zbase_seller_stats z-checkbox.premium").setAttribute(
        "data-active", "active");
    } else {
      $(".zbase_seller_stats z-checkbox.premium").removeAttribute("data-active");
    }
  };

  var setParamMetrics = function(metrics) {
    if (metrics) {
      $(".zbase_seller_stats z-dropdown.metrics").setValue(metrics.split(","));
    }
  };

  var setParamsOrder = function(order_by, order_fn) {
    if (order_by && order_fn) {
      if ($(".zbase_seller_stats thead")) {
        $(".zbase_seller_stats th.order_by").classList.remove("order_by");
        $(".zbase_seller_stats th." + order_by).classList.add("order_by");
      }

      var table = $(".zbase_seller_stats table.overview");
      table.setAttribute("data-order-by", order_by);
      table.setAttribute("data-order-fn", order_fn);
    }
  };

  var setParamOffset = function(offset) {
    if (!offset) {
      offset = 0;
    }

    $(".zbase_seller_stats .pager").setAttribute("data-offset", offset);
  };

  var getParamsOrder = function() {
    var table = $(".zbase_seller_stats table.overview");

    return {
      order_by: table.getAttribute("data-order-by"),
      order_fn: table.getAttribute("data-order-fn")
    };
  };

  var getParamOffset = function() {
    return parseInt(
        $(".zbase_seller_stats .pager").getAttribute("data-offset"), 10);
  };

  var getQueryParams = function() {
    var params = getParamsOrder();
    params.offset = getParamOffset();
    params.metrics = $(".zbase_seller_stats z-dropdown.metrics").getValue();
    params.premium = $(".zbase_seller_stats z-checkbox.premium").hasAttribute(
          "data-active");
    params.limit = "20";

    return params;
  };

  var paramChanged = function() {
    $.navigateTo(path_prefix + "?" + $.buildQueryString(getQueryParams()));
  };

  var orderByParamChanged = function(order_by, order_fn) {
    setParamsOrder(order_by, order_fn);
    setParamOffset(0);
    paramChanged();
  };

  return {
    name: "seller_overview",
    loadView: function(params) {load(params.path);},
    unloadView: destroy,
    handleNavigationChange: load
  };

})());
<|endoftext|>


<commit_before>import Ember from 'ember';
import { getKeyCode } from 'ember-keyboard';

const keyEvent = function keyEvent(app, attributes, type, element) {
  const event = attributes.split('+').reduce((event, attribute) => {
    if (['ctrl', 'meta', 'alt', 'shift'].indexOf(attribute) > -1) {
      event[`${attribute}Key`] = true;
    } else {
      event.keyCode = getKeyCode(attribute);
    }

    return event;
  }, {});

  return app.testHelpers.triggerEvent(element || document, type, event);
}

export default function() {
  Ember.Test.registerAsyncHelper('keyDown', function(app, attributes, element) {
    return keyEvent(app, attributes, 'keydown', element);
  });

  Ember.Test.registerAsyncHelper('keyUp', function(app, attributes, element) {
    return keyEvent(app, attributes, 'keyup', element);
  });

  Ember.Test.registerAsyncHelper('keyPress', function(app, attributes, element) {
    return keyEvent(app, attributes, 'keypress', element);
  });
}
<commit_msg>allow cmd to be used for acceptance test helpers<commit_after>import Ember from 'ember';
import { getKeyCode } from 'ember-keyboard';
import validModifiers from 'ember-keyboard/fixtures/modifiers-array';
import getCmdKey from 'ember-keyboard/utils/get-cmd-key';

const keyEvent = function keyEvent(app, attributes, type, element) {
  const event = attributes.split('+').reduce((event, attribute) => {
    if (validModifiers.indexOf(attribute) > -1) {
      attribute = attribute === 'cmd' ? getCmdKey() : attribute;
      event[`${attribute}Key`] = true;
    } else {
      event.keyCode = getKeyCode(attribute);
    }

    return event;
  }, {});

  return app.testHelpers.triggerEvent(element || document, type, event);
}

export default function() {
  Ember.Test.registerAsyncHelper('keyDown', function(app, attributes, element) {
    return keyEvent(app, attributes, 'keydown', element);
  });

  Ember.Test.registerAsyncHelper('keyUp', function(app, attributes, element) {
    return keyEvent(app, attributes, 'keyup', element);
  });

  Ember.Test.registerAsyncHelper('keyPress', function(app, attributes, element) {
    return keyEvent(app, attributes, 'keypress', element);
  });
}
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        watch: {
            css: {
                files: ['sass/*.scss'],
                tasks: ['sass:all']
            }
        },
        sass: {
            all: {
                options: {
                    style: 'compressed'
                },
                files: {
                    'css/global.css': 'sass/global.scss'
                }
            }
        }
    });
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.registerTask('default', ['sass']);
};
<commit_msg>Add task<commit_after>module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        watch: {
            css: {
                files: ['sass/*.scss'],
                tasks: ['sass:all']
            }
        },
        sass: {
            all: {
                options: {
                    style: 'compressed'
                },
                files: {
                    'css/global.css': 'sass/global.scss'
                }
            }
        }
    });
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.registerTask('watchIt', ['watch']);
    grunt.registerTask('default', ['sass']);
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {
    grunt.initConfig({
        jshint: {
            all: ['Gruntfile.js', 'hulk.js'],
            options: {
                "forin": true,
                "latedef": true,
                "unused": true,
                "trailing": true
            }
        },

        uglify: {
            options: {
                mangle: {
                    except: ['jQuery']
                },
                compress: true
            },
            my_target: {
                files: {
                    'hulk.min.js': ['hulk.js']
                }
            }
        },

        qunit: {
            files: ['tests/test.html']
        },

        sass: {
            dist: {
                files: {
                    'hulk-all.css': 'hulk-all.scss'
                }
            }
        },

        watch: {
            scripts: {
                files: 'hulk.js',
                tasks: ['jshint', 'uglify']
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    //grunt.loadNpmTasks('grunt-contrib-qunit');
    grunt.loadNpmTasks('grunt-contrib-watch');
};
<commit_msg>add scss, css to Gruntfile<commit_after>module.exports = function(grunt) {
    grunt.initConfig({
        jshint: {
            all: ['Gruntfile.js', 'hulk.js'],
            options: {
                "forin": true,
                "latedef": true,
                "unused": true,
                "trailing": true
            }
        },

        uglify: {
            options: {
                mangle: {
                    except: ['jQuery']
                },
                compress: true
            },
            my_target: {
                files: {
                    'hulk.min.js': ['hulk.js']
                }
            }
        },

        qunit: {
            files: ['tests/test.html']
        },

        sass: {
            dist: {
                files: {
                    'css/hulk-all.css': 'scss/hulk-all.scss',
                    'css/hulk.css': 'scss/hulk.scss',
                    'css/hulk-colors.css': 'scss/hulk-colors.scss',
                }
            }
        },

        watch: {
            scripts: {
                files: 'hulk.js',
                tasks: ['jshint', 'uglify']
            },
            css: {
                files: '**/*.scss',
                tasks: ['sass']
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    //grunt.loadNpmTasks('grunt-contrib-qunit');
    grunt.loadNpmTasks('grunt-contrib-watch');
};
<|endoftext|>


<commit_before>module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        simplemocha: {
            options: {
                globals: ['expect'],
                timeout: 3000,
                ignoreLeaks: false,
                ui: 'bdd'
            },
            all: { src: ['tests/*.js'] }
        },
        xo: {
             target: ['lib/*']
        },
        jsdoc2md: {
            oneOutputFile: {
                src: 'lib/*.js',
                dest: 'doc/api.md'
            }
        },
        concat: {
            options: {
                separator: '\n'
            },
            dist: {
                src: ['doc/README.header.md', 'doc/api.md', 'doc/README.footer.md'],
                dest: 'README.md'
            }
        },
        shell: {
            coveralls: {
                command: 'node_modules/.bin/nyc node_modules/.bin/mocha tests/*.js && node_modules/.bin/nyc report --reporter=text-lcov | node_modules/.bin/coveralls --force'
            },
            purgebadges: {
                command: 'curl -X PURGE https://camo.githubusercontent.com/a554890f3c5ef62df1a95c58135b5e2fe82ad381/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f686f6262797175616b65722f62696e7270632f62616467652e7376673f6272616e63683d6d6173746572 ; curl -X PURGE https://camo.githubusercontent.com/1634c087285b3ef4930287325ae07bce5329515a/68747470733a2f2f7472617669732d63692e6f72672f686f6262797175616b65722f62696e7270632e7376673f6272616e63683d6d6173746572'
            }
        }
    });

    grunt.loadNpmTasks('grunt-xo');
    grunt.loadNpmTasks('grunt-simple-mocha');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-shell');
    grunt.registerTask('test', ['xo', 'shell:coveralls', 'simplemocha', 'shell:purgebadges']);

    grunt.loadNpmTasks('grunt-jsdoc-to-markdown');
    grunt.registerTask('doc', ['jsdoc2md', 'concat']);
};
<commit_msg>purge readme badges after build<commit_after>module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        simplemocha: {
            options: {
                globals: ['expect'],
                timeout: 3000,
                ignoreLeaks: false,
                ui: 'bdd'
            },
            all: { src: ['tests/*.js'] }
        },
        xo: {
             target: ['lib/*']
        },
        jsdoc2md: {
            oneOutputFile: {
                src: 'lib/*.js',
                dest: 'doc/api.md'
            }
        },
        concat: {
            options: {
                separator: '\n'
            },
            dist: {
                src: ['doc/README.header.md', 'doc/api.md', 'doc/README.footer.md'],
                dest: 'README.md'
            }
        },
        shell: {
            coveralls: {
                command: 'node_modules/.bin/nyc node_modules/.bin/mocha tests/*.js && node_modules/.bin/nyc report --reporter=text-lcov | node_modules/.bin/coveralls --force'
            },
            purgebadges: {
                command: 'curl -X PURGE https://camo.githubusercontent.com/a554890f3c5ef62df1a95c58135b5e2fe82ad381/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f686f6262797175616b65722f62696e7270632f62616467652e7376673f6272616e63683d6d6173746572 ; curl -X PURGE https://camo.githubusercontent.com/1634c087285b3ef4930287325ae07bce5329515a/68747470733a2f2f7472617669732d63692e6f72672f686f6262797175616b65722f62696e7270632e7376673f6272616e63683d6d6173746572 ; curl -X PURGE https://camo.githubusercontent.com/7622a087fe96b8f6dd6739bfedb0f866740b9f65/68747470733a2f2f696d672e736869656c64732e696f2f67656d6e617369756d2f686f6262797175616b65722f62696e7270632e7376673f6d61784167653d32353932303030'
            }
        }
    });

    grunt.loadNpmTasks('grunt-xo');
    grunt.loadNpmTasks('grunt-simple-mocha');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-shell');
    grunt.registerTask('test', ['xo', 'shell:coveralls', 'simplemocha', 'shell:purgebadges']);

    grunt.loadNpmTasks('grunt-jsdoc-to-markdown');
    grunt.registerTask('doc', ['jsdoc2md', 'concat']);
};
<|endoftext|>


<commit_before>/** Grunt Tasks for GeoMoose
 *
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 GeoMoose
 *
 * 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.
 */

var webpackConfig = require('./webpack.config');
var webpackDeployConfig = require('./webpack-deploy.config');

module.exports = function(grunt) {
    grunt.loadNpmTasks('gruntify-eslint');
    grunt.loadNpmTasks('grunt-contrib-compress');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-gitinfo');
    grunt.loadNpmTasks('grunt-webpack');

    grunt.initConfig({
        // linting task. Used to ensure code is clean
        //  before trying to build.
        eslint: {
            options: {
                configFile: 'eslint.config.js',
            },
            target: ['src/**/*.jsx', 'src/**/*.js']
        },

        // makes a compressed archive of the SDK release
        compress: {
             main: {
                 options: {
                     archive: 'gm3-sdk-<%= gitinfo.local.branch.current.shortSHA %>.zip'
                 },
                 files: [
                     { src: [
                           'demo/**',
                           'dist/**',
                           'docs/**',
                           'eslint.config.js',
                           'Gruntfile.js',
                           'LICENSE',
                           'package.json',
                           'README.md',
                           'src/**',
                           'tests/**',
                           'webpack.config.js',
                           'webpack-deploy.config.js'
                       ], dest: 'geomoose' }
                 ]
             }
        },
        // copies useful files places.
        copy: {
            // this will copy the "test" files into dist,
            //  used for 'rapid' development work.
            test: {
                files: [
                    {expand: true, flatten: true, src: ['src/test.*'], dest: 'dist/'},
                ]
            },
            fonts: {
                files: [
                    {
                        expand: true, flatten: true,
                        src: ['node_modules/font-awesome/fonts/*'],
                        dest: 'dist/fonts/'
                    },
                    {
                        expand: true, flatten: true,
                        src: ['node_modules/mapskin/fonts/*'],
                        dest: 'dist/fonts/'
                    }
                ]
            },
            ol: {
                files: [
                    {
                        src: ['node_modules/openlayers/dist/ol.js'],
                        dest: 'dist/ol.js'
                    }
                ]
            },
            services: {
                files: [
                    {
                        expand: true, flatten: true,
                        src: ['src/services/*.js'],
                        dest: 'dist/services/'
                    }
                ]
            }
        },

        less: {
            build: {
                options: {
                    paths: ['src/less'],
                },
                files: {
                    'dist/css/geomoose.css' : 'src/less/gm3.less'
                }
            }
        },

        watch: {
            gm3: {
                files: ['src/gm3/**/*'],
                tasks: ['webpack:build-dev'],
                options: {
                    spawn: false,
                }
            },
            services: {
                files: ['src/services/*'],
                tasks: ['copy:services']
            }
        },

        webpack: {
            'build-dev': webpackConfig,
            'build-deploy': webpackDeployConfig
        },

        'webpack-dev-server': {
            options: {
                webpack: webpackConfig,
                publicPath: "./"
            },
            start: Object.assign({}, webpackConfig.devServer)
        }
    });

    grunt.task.registerTask('lint', ['eslint']);

    grunt.task.registerTask('serve', ['webpack-dev-server:start', 'watch']);

    // only build the non-minified version.
    grunt.task.registerTask('build-dev', ['eslint', 'copy:services', 'webpack:build-dev']);

    // update the css and fonts.
    grunt.task.registerTask('build-css', ['less:build', 'copy:fonts']);

    // build everything
    grunt.task.registerTask('build', ['eslint', 'webpack:build-dev', 'webpack:build-deploy', 'build-css', 'copy:ol', 'copy:services']);

    // build release.zip
    grunt.task.registerTask('build-release', ['build', 'gitinfo', 'compress']);
};
<commit_msg>Add Less to grunt serve watch list<commit_after>/** Grunt Tasks for GeoMoose
 *
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 GeoMoose
 *
 * 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.
 */

var webpackConfig = require('./webpack.config');
var webpackDeployConfig = require('./webpack-deploy.config');

module.exports = function(grunt) {
    grunt.loadNpmTasks('gruntify-eslint');
    grunt.loadNpmTasks('grunt-contrib-compress');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-gitinfo');
    grunt.loadNpmTasks('grunt-webpack');

    grunt.initConfig({
        // linting task. Used to ensure code is clean
        //  before trying to build.
        eslint: {
            options: {
                configFile: 'eslint.config.js',
            },
            target: ['src/**/*.jsx', 'src/**/*.js']
        },

        // makes a compressed archive of the SDK release
        compress: {
             main: {
                 options: {
                     archive: 'gm3-sdk-<%= gitinfo.local.branch.current.shortSHA %>.zip'
                 },
                 files: [
                     { src: [
                           'demo/**',
                           'dist/**',
                           'docs/**',
                           'eslint.config.js',
                           'Gruntfile.js',
                           'LICENSE',
                           'package.json',
                           'README.md',
                           'src/**',
                           'tests/**',
                           'webpack.config.js',
                           'webpack-deploy.config.js'
                       ], dest: 'geomoose' }
                 ]
             }
        },
        // copies useful files places.
        copy: {
            // this will copy the "test" files into dist,
            //  used for 'rapid' development work.
            test: {
                files: [
                    {expand: true, flatten: true, src: ['src/test.*'], dest: 'dist/'},
                ]
            },
            fonts: {
                files: [
                    {
                        expand: true, flatten: true,
                        src: ['node_modules/font-awesome/fonts/*'],
                        dest: 'dist/fonts/'
                    },
                    {
                        expand: true, flatten: true,
                        src: ['node_modules/mapskin/fonts/*'],
                        dest: 'dist/fonts/'
                    }
                ]
            },
            ol: {
                files: [
                    {
                        src: ['node_modules/openlayers/dist/ol.js'],
                        dest: 'dist/ol.js'
                    }
                ]
            },
            services: {
                files: [
                    {
                        expand: true, flatten: true,
                        src: ['src/services/*.js'],
                        dest: 'dist/services/'
                    }
                ]
            }
        },

        less: {
            build: {
                options: {
                    paths: ['src/less'],
                },
                files: {
                    'dist/css/geomoose.css' : 'src/less/gm3.less'
                }
            }
        },

        watch: {
            gm3: {
                files: ['src/gm3/**/*'],
                tasks: ['webpack:build-dev'],
                options: {
                    spawn: false,
                }
            },
            less: {
                files: ['src/less/**/*'],
                tasks: ['less:build']
            },
            services: {
                files: ['src/services/*'],
                tasks: ['copy:services']
            }
        },

        webpack: {
            'build-dev': webpackConfig,
            'build-deploy': webpackDeployConfig
        },

        'webpack-dev-server': {
            options: {
                webpack: webpackConfig,
                publicPath: "./"
            },
            start: Object.assign({}, webpackConfig.devServer)
        }
    });

    grunt.task.registerTask('lint', ['eslint']);

    grunt.task.registerTask('serve', ['webpack-dev-server:start', 'watch']);

    // only build the non-minified version.
    grunt.task.registerTask('build-dev', ['eslint', 'copy:services', 'webpack:build-dev']);

    // update the css and fonts.
    grunt.task.registerTask('build-css', ['less:build', 'copy:fonts']);

    // build everything
    grunt.task.registerTask('build', ['eslint', 'webpack:build-dev', 'webpack:build-deploy', 'build-css', 'copy:ol', 'copy:services']);

    // build release.zip
    grunt.task.registerTask('build-release', ['build', 'gitinfo', 'compress']);
};
<|endoftext|>


<commit_before>(function() { 'use strict';

    // NPM dependencies
    var _ = require('lodash');
    var request = require('request');
    var YAML = require('yamljs');
    var cheerio = require('cheerio');
    var slug = require('slug');
    var S = require('string');

    module.exports = function(grunt) {

        // Load dependencies
        require('time-grunt')(grunt);

        // Project configuration
        grunt.initConfig({
            pkg: grunt.file.readJSON('package.json'),

            tempYAMLDir: '_tempYAML',

            compass: {
                dist: {
                    options: {
                        config: 'config.rb'
                    }
                }
            },

            jekyll: {
                build: {
                    dest: '_site'
                },
            },

            watch: {
                sass: {
                    files: ['_sass/**/*.sass'],
                    tasks: ['compass', 'copy:assets'],
                },
                jekyll: {
                    files: ['_config.yml', '**/*.{html, md, yaml, yml}'],
                    tasks: ['jekyll']
                },
                js: {
                    files: ['_js/**/*.js'],
                    tasks: ['concat:js', 'uglify', 'copy:assets']
                }
            },

            connect: {
                server: {
                    options: {
                       port: 4000,
                        base: '_site'
                    }
                }
            },

            concat: {
                definitions: {
                    src: ['<%= tempYAMLDir %>/*.yaml'],
                    dest: '_data/definitions.yaml',
                },
                js: {
                    src: ['_js/jquery-1.11.0.min.js', '_js/**/*.js'],
                    dest: 'assets/_app.js'
                }
            },

            copy: {
                assets: {
                    src: ['assets/*'],
                    dest: '_site/'
                }
            },

            uglify: {
                dist: {
                    files: {
                        'assets/app.min.js': ['assets/_app.js']
                    }
                }
            }

        });

        grunt.registerTask(
            'scrapePages',
            'Runs the scrapePage task on every page of the Guardian style guide',
            function () {

                // Generate the alphabet
                var letters = [];
                for (var i = 97; i <= 122; i++) {
                    letters[letters.length] = String.fromCharCode(i);
                }

                letters.forEach(function (letter) {
                    grunt.task.run('scrapePage:' + letter);
                });
            }
        );

        grunt.registerTask(
            'scrapePage',
            'Scrape an individual page of the Guardian style guide for data and save as a YAML file',
            function(letter) {
                var filename = grunt.config.get('tempYAMLDir') + '/' + letter + '.yaml';
                var url = 'http://www.theguardian.com/styleguide/' + letter;

                var slugOptions = {
                    charmap: _.extend(slug.charmap, {
                        "'": null,
                        '*': 'star'
                    })
                };

                grunt.log.write('Retrieving ' + url + '... ');

                var done = this.async();
                request(url, function (error, response, body) {
                    if (error || response.statusCode !== 200) {
                        grunt.log.error(error);
                        done(false);
                    } else {

                        grunt.log.ok();

                        // Parse it
                        grunt.log.write('Parsing to YAML... ');
                        var $ = cheerio.load(body);
                        var definitions = [];
                        $('#content').find('li.normal').each(function() {
                            var title = $(this).find('h3').text().trim();

                            // Have to use string because slug doesn't correctly
                            // strip punctuation :/
                            definitions.push({
                                title: _.escape(title),
                                slug: slug(S(title).stripPunctuation().s).toLowerCase(),
                                text: _.escape($(this).find('.trailtext').text().trim())
                            });
                        });
                        grunt.log.ok();

                        // Write the file
                        var output = [{
                            letter: letter,
                            definitions: definitions
                        }];
                        grunt.log.write('Writing to ' + filename + '... ');
                        grunt.file.write(filename, YAML.stringify(output, 4, 4));
                        grunt.log.ok();

                        // Finish
                        grunt.log.ok('Scrape complete!');
                        done();

                    }

                });

            }

        );

        grunt.registerTask(
            'cleanup',
            function () {
                grunt.log.write('Deleting temporary directory... ');
                var path = grunt.config.get('tempYAMLDir');
                if (grunt.file.exists(path)) {
                    grunt.file.delete(path);
                    grunt.log.ok();
                } else {
                    grunt.log.ok('Directory doesn\'t exist!');
                }
            }
        );

        grunt.registerTask(
            'default',
            'Default task: serve',
            ['serve']
        );

        grunt.registerTask(
            'build',
            'Compile the sass, js, and rebuilds Jekyll',
            function() {
                grunt.loadNpmTasks('grunt-contrib-concat');
                grunt.loadNpmTasks('grunt-contrib-compass');
                grunt.loadNpmTasks('grunt-jekyll');
                grunt.loadNpmTasks('grunt-contrib-uglify');
                grunt.task.run(['compass', 'concat:js', 'uglify', 'jekyll']);
            }
        );

        grunt.registerTask(
            'serve',
            'Build the site, start a server on port 4000, and watch for changes',
            function() {
                grunt.loadNpmTasks('grunt-contrib-connect');
                grunt.loadNpmTasks('grunt-contrib-watch');
                grunt.loadNpmTasks('grunt-contrib-copy');
                grunt.task.run(['build', 'connect', 'watch']);
            }
        );

        grunt.registerTask(
            'scrape',
            'Scrape the Guardian style guide',
            function() {
                grunt.loadNpmTasks('grunt-contrib-concat');
                grunt.loadNpmTasks('grunt-jekyll');
                grunt.task.run([
                    'scrapePages',
                    'concat:definitions',
                    'cleanup',
                    'jekyll'
                ]);
            }
        );

    };

})();
<commit_msg>Load NPM shorthand<commit_after>(function() { 'use strict';

    // NPM dependencies
    var _ = require('lodash');
    var request = require('request');
    var YAML = require('yamljs');
    var cheerio = require('cheerio');
    var slug = require('slug');
    var S = require('string');

    module.exports = function(grunt) {

        // Load dependencies
        require('time-grunt')(grunt);

        // grunt.loadnpmtasks shorthand
        var lnpm = function (inputTasks) {
            if (_.isString(inputTasks)) {
                inputTasks = [inputTasks];
            }
            inputTasks.forEach(function(task) {
                grunt.loadNpmTasks(task);
            });
        };

        // Project configuration
        grunt.initConfig({
            pkg: grunt.file.readJSON('package.json'),

            tempYAMLDir: '_tempYAML',

            compass: {
                dist: {
                    options: {
                        config: 'config.rb'
                    }
                }
            },

            jekyll: {
                build: {
                    dest: '_site'
                },
            },

            watch: {
                sass: {
                    files: ['_sass/**/*.sass'],
                    tasks: ['compass', 'copy:assets'],
                },
                jekyll: {
                    files: ['_config.yml', '**/*.{html, md, yaml, yml}'],
                    tasks: ['jekyll']
                },
                js: {
                    files: ['_js/**/*.js'],
                    tasks: ['concat:js', 'uglify', 'copy:assets']
                }
            },

            connect: {
                server: {
                    options: {
                       port: 4000,
                        base: '_site'
                    }
                }
            },

            concat: {
                definitions: {
                    src: ['<%= tempYAMLDir %>/*.yaml'],
                    dest: '_data/definitions.yaml',
                },
                js: {
                    src: ['_js/jquery-1.11.0.min.js', '_js/**/*.js'],
                    dest: 'assets/_app.js'
                }
            },

            copy: {
                assets: {
                    src: ['assets/*'],
                    dest: '_site/'
                }
            },

            uglify: {
                dist: {
                    files: {
                        'assets/app.min.js': ['assets/_app.js']
                    }
                }
            }

        });

        grunt.registerTask(
            'scrapePages',
            'Runs the scrapePage task on every page of the Guardian style guide',
            function () {

                // Generate the alphabet
                var letters = [];
                for (var i = 97; i <= 122; i++) {
                    letters[letters.length] = String.fromCharCode(i);
                }

                letters.forEach(function (letter) {
                    grunt.task.run('scrapePage:' + letter);
                });
            }
        );

        grunt.registerTask(
            'scrapePage',
            'Scrape an individual page of the Guardian style guide for data and save as a YAML file',
            function(letter) {
                var filename = grunt.config.get('tempYAMLDir') + '/' + letter + '.yaml';
                var url = 'http://www.theguardian.com/styleguide/' + letter;

                var slugOptions = {
                    charmap: _.extend(slug.charmap, {
                        "'": null,
                        '*': 'star'
                    })
                };

                grunt.log.write('Retrieving ' + url + '... ');

                var done = this.async();
                request(url, function (error, response, body) {
                    if (error || response.statusCode !== 200) {
                        grunt.log.error(error);
                        done(false);
                    } else {

                        grunt.log.ok();

                        // Parse it
                        grunt.log.write('Parsing to YAML... ');
                        var $ = cheerio.load(body);
                        var definitions = [];
                        $('#content').find('li.normal').each(function() {
                            var title = $(this).find('h3').text().trim();

                            // Have to use string because slug doesn't correctly
                            // strip punctuation :/
                            definitions.push({
                                title: _.escape(title),
                                slug: slug(S(title).stripPunctuation().s).toLowerCase(),
                                text: _.escape($(this).find('.trailtext').text().trim())
                            });
                        });
                        grunt.log.ok();

                        // Write the file
                        var output = [{
                            letter: letter,
                            definitions: definitions
                        }];
                        grunt.log.write('Writing to ' + filename + '... ');
                        grunt.file.write(filename, YAML.stringify(output, 4, 4));
                        grunt.log.ok();

                        // Finish
                        grunt.log.ok('Scrape complete!');
                        done();

                    }

                });

            }

        );

        grunt.registerTask(
            'cleanup',
            function () {
                grunt.log.write('Deleting temporary directory... ');
                var path = grunt.config.get('tempYAMLDir');
                if (grunt.file.exists(path)) {
                    grunt.file.delete(path);
                    grunt.log.ok();
                } else {
                    grunt.log.ok('Directory doesn\'t exist!');
                }
            }
        );

        grunt.registerTask(
            'default',
            'Default task: serve',
            ['serve']
        );

        grunt.registerTask(
            'build',
            'Compile the sass, js, and rebuilds Jekyll',
            function() {
                lnpm(['grunt-contrib-concat', 'grunt-contrib-compass', 'grunt-jekyll', 'grunt-contrib-uglify']);
                grunt.task.run(['compass', 'concat:js', 'uglify', 'jekyll']);
            }
        );

        grunt.registerTask(
            'serve',
            'Build the site, start a server on port 4000, and watch for changes',
            function() {
                lnpm(['grunt-contrib-connect', 'grunt-contrib-watch', 'grunt-contrib-copy']);
                grunt.task.run(['build', 'connect', 'watch']);
            }
        );

        grunt.registerTask(
            'scrape',
            'Scrape the Guardian style guide',
            function() {
                lnpm(['grunt-contrib-concat', 'grunt-jekyll']);
                grunt.task.run([
                    'scrapePages',
                    'concat:definitions',
                    'cleanup',
                    'jekyll'
                ]);
            }
        );

    };

})();
<|endoftext|>


<commit_before>module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    uglify: {
      front: {
        options: {
          banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
        },
        files: {
          'public/javascripts/profile.min.js': ['src/javascripts/profile.js']
        }
      },
      back: {
        options: {
          banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
        },
        files: {
          'routes.min.js': ['src/root/routes.js'],
          'app.min.js': ['src/root/app.js'],
          'passport.min.js': ['src/root/passport.js']
        }
      },
      models: {
        options: {
          banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
        },
        files: {
          'models/admin.min.js': ['src/models/admin.js'],
          'models/modlist.min.js': ['src/models/modlist.js'],
          'models/blog.min.js': ['src/models/blog.js']
        }
      }
    },
    cssmin: {
      target: {
        files: {
          'public/stylesheets/profile.min.css': ['src/stylesheets/profile.css'],
          'public/stylesheets/home.min.css': ['src/stylesheets/home.css'],
          'public/stylesheets/users.min.css': ['src/stylesheets/users.css']
        }
      }
    },
    imagemin: {
      dist: {
        options: {
          optimizationLevel: 3
        },
        files: {
          'public/images/FNV_NEXUS_small.png': 'src/images/FNV_NEXUS_small.png',
          'public/images/congruent_outline.png': 'src/images/congruent_outline.png',
          'public/images/GitHub-Logo_invert.png': 'src/images/GitHub-Logo_invert.png',
          'public/images/ajax-loader.gif': 'src/images/ajax-loader.gif'
        }
      }
    },
    watch: {
      javascript: {
        files: ['src/javascripts/*.js'],
        tasks: ['uglify:front']
      },
      css: {
        files: ['src/stylesheets/*.css'],
        tasks: ['cssmin']
      },
      backend: {
        files: ['src/root/*.js'],
        tasks: ['uglify:back']
      },
      models: {
        files: ['src/models/*.js'],
        tasks: ['uglify:models']
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-imagemin');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('default', ['uglify','cssmin']);
};<commit_msg>Switched grunt config to minify by directory<commit_after>module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    uglify: {
      front: {
        options: {
          banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
        },
        files: [
          {
            expand: true,
            cwd: 'src/javascripts/',
            src: ['*.js'],
            dest: 'public/javascripts/',
            ext: '.min.js'
          }
        ]
      },
      back: {
        options: {
          banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
        },
        files: [
          {
            expand: true,
            cwd: 'src/root/',
            src: ['*.js'],
            dest: '/',
            ext: '.min.js'
          }
        ]
      },
      models: {
        options: {
          banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
        },
        files: [
          {
            expand: true,
            cwd: 'src/models/',
            src: ['*.js'],
            dest: 'public/models/',
            ext: '.min.js'
          }
        ]
      }
    },
    cssmin: {
      target: {
        files: [
          {
            expand: true,
            cwd: 'src/stylesheets/',
            src: ['*.css'],
            dest: 'public/stylesheets/',
            ext: '.min.css'
          }
        ]
      }
    },
    imagemin: {
      dist: {
        options: {
          optimizationLevel: 3
        },
        files: {
          'public/images/FNV_NEXUS_small.png': 'src/images/FNV_NEXUS_small.png',
          'public/images/congruent_outline.png': 'src/images/congruent_outline.png',
          'public/images/GitHub-Logo_invert.png': 'src/images/GitHub-Logo_invert.png',
          'public/images/ajax-loader.gif': 'src/images/ajax-loader.gif'
        }
      }
    },
    watch: {
      javascript: {
        files: ['src/javascripts/*.js'],
        tasks: ['uglify:front']
      },
      css: {
        files: ['src/stylesheets/*.css'],
        tasks: ['cssmin']
      },
      backend: {
        files: ['src/root/*.js'],
        tasks: ['uglify:back']
      },
      models: {
        files: ['src/models/*.js'],
        tasks: ['uglify:models']
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-imagemin');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('default', ['uglify','cssmin']);
};
<|endoftext|>


<commit_before>// Generated on 2015-09-24 using generator-chromeapp 0.2.19
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths
  var config = {
    app: 'app',
    dist: 'dist',
    tasks: grunt.cli.tasks
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    config: config,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['bowerInstall']
      },
      js: {
        files: ['<%= config.app %>/scripts/{,*/}*.js'],
        tasks: ['jshint'],
        options: {
          livereload: true
        }
      },
      templates: {
        files: ['<%= config.app %>/templates/{,*/}*.html'],
        tasks: [],
        options: {
          livereload: true
        }
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      styles: {
        files: ['<%= config.app %>/styles/{,*/}*.css'],
        tasks: [],
        options: {
          livereload: true
        }
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '.tmp/styles/{,*/}*.css',
          '<%= config.app %>/*.html',
          '<%= config.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= config.app %>/manifest.json',
          '<%= config.app %>/_locales/{,*/}*.json'
        ]
      }
    },

    // Grunt server and debug server settings
    connect: {
      options: {
        port: 9000,
        livereload: 35729,
        // change this to '0.0.0.0' to access the server from outside
        hostname: 'localhost',
        open: true,
      },
      server: {
        options: {
          middleware: function(connect) {
            return [
              connect.static('.tmp'),
              connect().use('/bower_components', connect.static('./bower_components')),
              connect.static(config.app)
            ];
          }
        }
      },
      chrome: {
        options: {
          open: false,
          base: [
            '<%= config.app %>'
          ]
        }
      },
      test: {
        options: {
          open: false,
          base: [
            'test',
            '<%= config.app %>'
          ]
        }
      }
    },

    // Empties folders to start fresh
    clean: {
      server: '.tmp',
      chrome: '.tmp',
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= config.dist %>/*',
            '!<%= config.dist %>/.git*'
          ]
        }]
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: [
        'Gruntfile.js',
        '<%= config.app %>/scripts/{,*/}*.js',
        '!<%= config.app %>/scripts/vendor/*',
        'test/spec/{,*/}*.js'
      ]
    },

    // Mocha testing framework configuration options
    mocha: {
      all: {
        options: {
          run: true,
          urls: ['http://localhost:<%= connect.options.port %>/index.html']
        }
      }
    },

    // Automatically inject Bower components into the HTML file
    bowerInstall: {
      app: {
        src: ['<%= config.app %>/index.html'],
        ignorePath: '<%= config.app %>/'
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      options: {
        dest: '<%= config.dist %>'
      },
      html: [
        '<%= config.app %>/index.html'
      ]
    },

    // Performs rewrites based on rev and the useminPrepare configuration
    usemin: {
      options: {
        assetsDirs: ['<%= config.dist %>', '<%= config.dist %>/images']
      },
      html: ['<%= config.dist %>/{,*/}*.html'],
      css: ['<%= config.dist %>/styles/{,*/}*.css']
    },

    // The following *-min tasks produce minified files in the dist folder
    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= config.app %>/images',
          src: '{,*/}*.{gif,jpeg,jpg,png}',
          dest: '<%= config.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= config.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= config.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          customAttrAssign: [/\?=/],
          collapseBooleanAttributes: true,
          collapseWhitespace: true,
          removeAttributeQuotes: true,
          removeCommentsFromCDATA: true,
          removeEmptyAttributes: true,
          removeOptionalTags: true,
          removeRedundantAttributes: true,
          useShortDoctype: true
        },
        files: [{
          expand: true,
          cwd: '<%= config.dist %>',
          src: '{,*/}*.html',
          dest: '<%= config.dist %>'
        }]
      }
    },

    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= config.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css',
    //         '<%= config.app %>/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= config.dist %>/scripts/scripts.js': [
    //         '<%= config.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= config.app %>',
          dest: '<%= config.dist %>',
          src: [
            '*.{ico,png,txt}',
            'images/{,*/}*.{webp,gif}',
            '{,*/}*.html',
            'styles/fonts/{,*/}*.*',
            '_locales/{,*/}*.json',
          ]
        }]
      },
      styles: {
        expand: true,
        dot: true,
        cwd: '<%= config.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up build process
    concurrent: {
      server: [
        'copy:styles'
      ],
      chrome: [
        'copy:styles'
      ],
      dist: [
        'copy:styles',
        'imagemin',
        'svgmin'
      ],
      test: [
        'copy:styles'
      ],
    },

    // Merge event page, update build number, exclude the debug script
    chromeManifest: {
      dist: {
        options: {
          buildnumber: true,
          background: {
            target: 'scripts/background.js',
            exclude: [
              'scripts/chromereload.js'
            ]
          }
        },
        src: '<%= config.app %>',
        dest: '<%= config.dist %>'
      }
    },

    // Compress files in dist to make Chromea Apps package
    compress: {
      dist: {
        options: {
          archive: function() {
            var manifest = grunt.file.readJSON('app/manifest.json');
            return 'package/chromeapps-' + manifest.version + '.zip';
          }
        },
        files: [{
          expand: true,
          cwd: 'dist/',
          src: ['**'],
          dest: ''
        }]
      }
    }
  });

  grunt.registerTask('debug', function (platform) {
    var watch = grunt.config('watch');
    platform = platform || 'chrome';

    // Configure style task for debug:server task
    if (platform === 'server') {
      watch.styles.tasks = ['newer:copy:styles'];
      watch.styles.options.livereload = false;

    }

    // Configure updated watch task
    grunt.config('watch', watch);

    grunt.task.run([
      'clean:' + platform,
      'concurrent:' + platform,
      'connect:' + platform,
      'watch'
    ]);
  });

  grunt.registerTask('test', [
    'connect:test',
    'mocha'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'chromeManifest:dist',
    'useminPrepare',
    'concurrent:dist',
    'concat',
    'cssmin',
    'uglify',
    'copy',
    'usemin',
    'htmlmin',
    'compress'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<commit_msg>fix generated package name<commit_after>// Generated on 2015-09-24 using generator-chromeapp 0.2.19
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths
  var config = {
    app: 'app',
    dist: 'dist',
    tasks: grunt.cli.tasks
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    config: config,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['bowerInstall']
      },
      js: {
        files: ['<%= config.app %>/scripts/{,*/}*.js'],
        tasks: ['jshint'],
        options: {
          livereload: true
        }
      },
      templates: {
        files: ['<%= config.app %>/templates/{,*/}*.html'],
        tasks: [],
        options: {
          livereload: true
        }
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      styles: {
        files: ['<%= config.app %>/styles/{,*/}*.css'],
        tasks: [],
        options: {
          livereload: true
        }
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '.tmp/styles/{,*/}*.css',
          '<%= config.app %>/*.html',
          '<%= config.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= config.app %>/manifest.json',
          '<%= config.app %>/_locales/{,*/}*.json'
        ]
      }
    },

    // Grunt server and debug server settings
    connect: {
      options: {
        port: 9000,
        livereload: 35729,
        // change this to '0.0.0.0' to access the server from outside
        hostname: 'localhost',
        open: true,
      },
      server: {
        options: {
          middleware: function(connect) {
            return [
              connect.static('.tmp'),
              connect().use('/bower_components', connect.static('./bower_components')),
              connect.static(config.app)
            ];
          }
        }
      },
      chrome: {
        options: {
          open: false,
          base: [
            '<%= config.app %>'
          ]
        }
      },
      test: {
        options: {
          open: false,
          base: [
            'test',
            '<%= config.app %>'
          ]
        }
      }
    },

    // Empties folders to start fresh
    clean: {
      server: '.tmp',
      chrome: '.tmp',
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= config.dist %>/*',
            '!<%= config.dist %>/.git*'
          ]
        }]
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: [
        'Gruntfile.js',
        '<%= config.app %>/scripts/{,*/}*.js',
        '!<%= config.app %>/scripts/vendor/*',
        'test/spec/{,*/}*.js'
      ]
    },

    // Mocha testing framework configuration options
    mocha: {
      all: {
        options: {
          run: true,
          urls: ['http://localhost:<%= connect.options.port %>/index.html']
        }
      }
    },

    // Automatically inject Bower components into the HTML file
    bowerInstall: {
      app: {
        src: ['<%= config.app %>/index.html'],
        ignorePath: '<%= config.app %>/'
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      options: {
        dest: '<%= config.dist %>'
      },
      html: [
        '<%= config.app %>/index.html'
      ]
    },

    // Performs rewrites based on rev and the useminPrepare configuration
    usemin: {
      options: {
        assetsDirs: ['<%= config.dist %>', '<%= config.dist %>/images']
      },
      html: ['<%= config.dist %>/{,*/}*.html'],
      css: ['<%= config.dist %>/styles/{,*/}*.css']
    },

    // The following *-min tasks produce minified files in the dist folder
    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= config.app %>/images',
          src: '{,*/}*.{gif,jpeg,jpg,png}',
          dest: '<%= config.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= config.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= config.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          customAttrAssign: [/\?=/],
          collapseBooleanAttributes: true,
          collapseWhitespace: true,
          removeAttributeQuotes: true,
          removeCommentsFromCDATA: true,
          removeEmptyAttributes: true,
          removeOptionalTags: true,
          removeRedundantAttributes: true,
          useShortDoctype: true
        },
        files: [{
          expand: true,
          cwd: '<%= config.dist %>',
          src: '{,*/}*.html',
          dest: '<%= config.dist %>'
        }]
      }
    },

    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= config.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css',
    //         '<%= config.app %>/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= config.dist %>/scripts/scripts.js': [
    //         '<%= config.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= config.app %>',
          dest: '<%= config.dist %>',
          src: [
            '*.{ico,png,txt}',
            'images/{,*/}*.{webp,gif}',
            '{,*/}*.html',
            'styles/fonts/{,*/}*.*',
            '_locales/{,*/}*.json',
          ]
        }]
      },
      styles: {
        expand: true,
        dot: true,
        cwd: '<%= config.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up build process
    concurrent: {
      server: [
        'copy:styles'
      ],
      chrome: [
        'copy:styles'
      ],
      dist: [
        'copy:styles',
        'imagemin',
        'svgmin'
      ],
      test: [
        'copy:styles'
      ],
    },

    // Merge event page, update build number, exclude the debug script
    chromeManifest: {
      dist: {
        options: {
          buildnumber: true,
          background: {
            target: 'scripts/background.js',
            exclude: [
              'scripts/chromereload.js'
            ]
          }
        },
        src: '<%= config.app %>',
        dest: '<%= config.dist %>'
      }
    },

    // Compress files in dist to make Chromea Apps package
    compress: {
      dist: {
        options: {
          archive: function() {
            var manifest = grunt.file.readJSON('app/manifest.json');
            return 'package/fimfiction-' + manifest.version + '.zip';
          }
        },
        files: [{
          expand: true,
          cwd: 'dist/',
          src: ['**'],
          dest: ''
        }]
      }
    }
  });

  grunt.registerTask('debug', function (platform) {
    var watch = grunt.config('watch');
    platform = platform || 'chrome';

    // Configure style task for debug:server task
    if (platform === 'server') {
      watch.styles.tasks = ['newer:copy:styles'];
      watch.styles.options.livereload = false;

    }

    // Configure updated watch task
    grunt.config('watch', watch);

    grunt.task.run([
      'clean:' + platform,
      'concurrent:' + platform,
      'connect:' + platform,
      'watch'
    ]);
  });

  grunt.registerTask('test', [
    'connect:test',
    'mocha'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'chromeManifest:dist',
    'useminPrepare',
    'concurrent:dist',
    'concat',
    'cssmin',
    'uglify',
    'copy',
    'usemin',
    'htmlmin',
    'compress'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<|endoftext|>