<commit_before>var benchrest = require('bench-rest');
var chanceReq = require('chance');
var chance = new chanceReq();

var dataFn = function() {
  var data = {
    chirp: {
      content: chance.sentence(),
      username: chance.name(),
      loc: [
        chance.latitude({min: 36.95, max: 48}),
        chance.longitude({min: -124.45, max: -120.49})
      ]
    }
  };

  return data;
};

var flow = {
  main: [
    { post: 'http://104.40.13.35/chirp-api/addChirp', json: dataFn },
    //        { get: 'http://localhost:8000/foo_#{INDEX}' }
  ]
};

// if the above flow will be used with the command line runner or
// programmatically from a separate file then export it.
module.exports = flow;

// There are even more flow options like setup and teardown, see detailed usage

var runOptions = {
  limit: 20,     // concurrent connections
  iterations: 10000,  // number of iterations to perform
  progress: 1000
};
benchrest(flow, runOptions)
  .on('progress', function(statsObj, percent, concurrentCount, ips) {
    console.log({ ips: ips , percent: percent });
  })
  .on('error', function (err, ctxName) { console.error('Failed in %s with err: ', ctxName, err); })
  .on('end', function (stats, errorCount) {
    console.log('error count: ', errorCount);
    console.log('stats', stats);
  });
<commit_msg>Hostname for benchmark.<commit_after>var benchrest = require('bench-rest');
var chanceReq = require('chance');
var chance = new chanceReq();
var hostname = process.argv[2];

var dataFn = function() {
  var data = {
    chirp: {
      content: chance.sentence(),
      username: chance.name(),
      loc: [
        chance.latitude({min: 36.95, max: 48}),
        chance.longitude({min: -124.45, max: -120.49})
      ]
    }
  };

  return data;
};

var flow = {
  main: [
    { post: 'http://' + hostname + '/chirp-api/addChirp', json: dataFn },
    //        { get: 'http://localhost:8000/foo_#{INDEX}' }
  ]
};

// if the above flow will be used with the command line runner or
// programmatically from a separate file then export it.
module.exports = flow;

// There are even more flow options like setup and teardown, see detailed usage

var runOptions = {
  limit: 20,     // concurrent connections
  iterations: 10000,  // number of iterations to perform
  progress: 1000
};
benchrest(flow, runOptions)
  .on('progress', function(statsObj, percent, concurrentCount, ips) {
    console.log({ ips: ips , percent: percent });
  })
  .on('error', function (err, ctxName) { console.error('Failed in %s with err: ', ctxName, err); })
  .on('end', function (stats, errorCount) {
    console.log('error count: ', errorCount);
    console.log('stats', stats);
  });
<|endoftext|>


<commit_before>const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const config = {
  // Add common Configurations
  module: {},
};

const mainConfig = Object.assign({}, config, {
  entry: {
    vendor: './ui/bundle_vendor.js',
    style: './ui/bundle_style.js',
    systemTools: './ui/bundle_tools.js',
    xibo: './ui/bundle_xibo.js',
    layoutDesigner: './ui/src/designer/main.js',
    playlistEditor: './ui/src/playlist-editor/main.js',
  },
  output: {
    path: path.resolve(__dirname, 'web/dist'),
    filename: '[name].bundle.min.js',
  },
  target: ['web', 'es5'],
  module: {
    rules: [
      {
        test: /datatables\.net.*/,
        use: [
          'imports-loader?define=>false',
        ],
      },
      {
        test: /\.(css)$/,
        use: [
          'style-loader',
          'css-loader',
        ],
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
      {
        test: /\.(scss)$/,
        use: [{
          loader: 'style-loader', // inject CSS to page
        }, {
          loader: 'css-loader', // translates CSS into CommonJS modules
        }, {
          loader: 'postcss-loader', // Run post css actions
          options: {
            // post css plugins, can be exported to postcss.config.js
            plugins: function() {
              return [
                require('precss'),
                require('autoprefixer'),
              ];
            },
          },
        }, {
          loader: 'sass-loader', // compiles Sass to CSS
        }],
      },
      {
        test: /\.(png|svg|jpg|gif|ttf|eot|woff|woff2)$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[hash].[ext]',
          },
        }],
      },
      {
        test: /\.(csv|tsv)$/,
        use: [
          'csv-loader',
        ],
      },
      {
        test: /\.xml$/,
        use: [
          'xml-loader',
        ],
      },
      {
        test: /\.hbs$/,
        use: [{
          loader: 'handlebars-loader',
          options: {
            helperDirs: path.join(__dirname, 'ui/src/helpers/handlebars'),
            precompileOptions: {
              knownHelpersOnly: false,
            },
          },
        }],
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', {targets: 'defaults'}],
            ],
          },
        },
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(['web/dist']),
    new CopyWebpackPlugin({
      patterns: [
        // Copy directory contents to {output}/
        {
          from: 'ui/src/core',
          to: 'core',
        },
        {
          from: 'ui/src/preview',
          to: 'preview',
        },
        {
          from: 'ui/src/assets',
          to: 'assets',
        },
        {
          from: 'ui/src/vendor',
          to: 'vendor',
        },
      ],
    }),
  ],
});

const moduleConfig = Object.assign({}, config, {
  entry: {
    'xibo-calendar-render': './modules/src/xibo-calendar-render.js',
  },
  output: {
    path: path.resolve(__dirname, 'modules'),
  },
  target: ['web', 'es5'],
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', {targets: 'defaults'}],
            ],
          },
        },
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(['modules/xibo-calendar-render.*']),
  ],
});

module.exports = (env, argv) => {
  if (argv.mode === 'development') {
    mainConfig.devtool = 'source-map';
    moduleConfig.devtool = 'source-map';
  }

  if (argv.mode === 'production') {
    mainConfig.devtool = false;
    moduleConfig.devtool = false;
  }

  return [mainConfig, moduleConfig];
};
<commit_msg>Possible fix for module build relates to xibosignage/xibo#2464<commit_after>const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const config = {
  // Add common Configurations
  module: {},
};

const mainConfig = Object.assign({}, config, {
  entry: {
    vendor: './ui/bundle_vendor.js',
    style: './ui/bundle_style.js',
    systemTools: './ui/bundle_tools.js',
    xibo: './ui/bundle_xibo.js',
    layoutDesigner: './ui/src/designer/main.js',
    playlistEditor: './ui/src/playlist-editor/main.js',
  },
  output: {
    path: path.resolve(__dirname, 'web/dist'),
    filename: '[name].bundle.min.js',
  },
  target: ['web', 'es5'],
  module: {
    rules: [
      {
        test: /datatables\.net.*/,
        use: [
          'imports-loader?define=>false',
        ],
      },
      {
        test: /\.(css)$/,
        use: [
          'style-loader',
          'css-loader',
        ],
      },
      {
        test: /\.less$/,
        use: [
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
      {
        test: /\.(scss)$/,
        use: [{
          loader: 'style-loader', // inject CSS to page
        }, {
          loader: 'css-loader', // translates CSS into CommonJS modules
        }, {
          loader: 'postcss-loader', // Run post css actions
          options: {
            // post css plugins, can be exported to postcss.config.js
            plugins: function() {
              return [
                require('precss'),
                require('autoprefixer'),
              ];
            },
          },
        }, {
          loader: 'sass-loader', // compiles Sass to CSS
        }],
      },
      {
        test: /\.(png|svg|jpg|gif|ttf|eot|woff|woff2)$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[hash].[ext]',
          },
        }],
      },
      {
        test: /\.(csv|tsv)$/,
        use: [
          'csv-loader',
        ],
      },
      {
        test: /\.xml$/,
        use: [
          'xml-loader',
        ],
      },
      {
        test: /\.hbs$/,
        use: [{
          loader: 'handlebars-loader',
          options: {
            helperDirs: path.join(__dirname, 'ui/src/helpers/handlebars'),
            precompileOptions: {
              knownHelpersOnly: false,
            },
          },
        }],
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', {targets: 'defaults'}],
            ],
          },
        },
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(['web/dist']),
    new CopyWebpackPlugin({
      patterns: [
        // Copy directory contents to {output}/
        {
          from: 'ui/src/core',
          to: 'core',
        },
        {
          from: 'ui/src/preview',
          to: 'preview',
        },
        {
          from: 'ui/src/assets',
          to: 'assets',
        },
        {
          from: 'ui/src/vendor',
          to: 'vendor',
        },
      ],
    }),
  ],
});

const moduleConfig = Object.assign({}, config, {
  entry: {
    'xibo-calendar-render': './modules/src/xibo-calendar-render.js',
  },
  output: {
    path: path.resolve(__dirname, 'modules'),
  },
  target: ['web', 'es5'],
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', {targets: 'defaults'}],
            ],
          },
        },
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(['modules/xibo-calendar-render.*']),
  ],
});

module.exports = (env, argv) => {
  if (argv.mode === 'development') {
    mainConfig.devtool = 'source-map';
    moduleConfig.devtool = 'source-map';
  }

  if (argv.mode === 'production') {
    mainConfig.devtool = false;
    moduleConfig.devtool = false;
  }

  return [moduleConfig, mainConfig];
};
<|endoftext|>


<commit_before>/*global define, console*/

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

define([
    'dojo/text!./templates/Nearest.html',
    'dojo/_base/declare',
    "dojo/_base/lang",
    "dojo/promise/all",
    'dijit/_Widget',
    'dijit/_TemplatedMixin',
    'dijit/_WidgetsInTemplateMixin',
    './_NearestBase',
    "dojo/dom-construct",
    "./tasks/ClientNearestTask",
    "./tasks/LayerInfoTask",
    "./NearestLayer",
    'dojo/topic'
],
function (
    template, declare, lang, all, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, _NearestBase, domConstruct, ClientNearestTask, LayerInfoTask, NearestLayer, topic) {

    return declare([_Widget, _NearestBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
        // description:
        //    Find the nearest features around a point

        templateString: template,
        baseClass: 'nearest',
        widgetsInTemplate: true,

        layerPopUpFields: [],

        // Properties to be sent into constructor

        constructor: function (options, srcRefNode) {
            this.options = {
                webmapId: "", // The id of the webmap to use.
                location: null, // The location to use as the centre point.
                maxResults: 10, // The maximum number of features to return.
                searchRadius: 5, // The search radius in miles.
                display: "expandable", // How to display the results. Expandable or fixed.
                layerOptions: [], // Options for each layer. These override the default radius and max results
                showOnMap: true, // Display the 'Show On Map' link
                showCounters: true, // Show the feature counts
                showDistance: true, // Show the distance
                findNearestMode: "geodesic"
            };

            /*
                layerOptions:[
                    {
                        itemId: ""
                        maxResults:
                        searchRadius:,
                        showOnMap:
                        showCounters:
                        display:
                    }
                ]
            */

            // mix in settings and defaults
            var defaults = lang.mixin({}, this.options, options);

            // Set properties
            this.set("webmapId", defaults.webmapId);
            this.set("location", defaults.location);
            this.set("maxResults", defaults.maxResults);
            this.set("searchRadius", defaults.searchRadius);
            this.set("display", defaults.display);
            this.set("layerOptions", defaults.layerOptions);
            this.set("showOnMap", defaults.showOnMap);
            this.set("showCounters", defaults.showCounters);
            this.set("showDistance", defaults.showDistance);
            this.set("findNearestMode", defaults.findNearestMode);

            // widget node
            this.domNode = srcRefNode;
        },

        buildRendering: function () {
            this.inherited(arguments);

        },

        postCreate: function() {
            // summary:
            //    Overrides method of same name in dijit._Widget.
            // tags:
            //    private
            //console.log('app.Nearest::postCreate', arguments);

            this.setupConnections();

            this.inherited(arguments);
        },

        // start widget. called by user
        startup: function () {
            this._init();
        },

        // connections/subscriptions will be cleaned up during the destroy() lifecycle phase
        destroy: function () {
            // call the superclass method of the same name.
            this.inherited(arguments);
        },

        setupConnections: function() {
            // summary:
            //    wire events, and such
            //
            //console.log('app.Nearest::setupConnections', arguments);

        },

        /* ---------------- */
        /* Public Functions */
        /* ---------------- */

        /* ---------------- */
        /* Private Functions */
        /* ---------------- */

        _init: function () {
            var _this = this;

            // Do query and build results
            if (!this._isNullOrEmpty(this.webmapId)) {
                this._getItemData(this.webmapId, this.token).then(function (webMap) {
                    var queryTasks = [], i = 0, iL = 0, task = null, opLayers, layerOpts;

                    if (webMap) {
                        topic.publish("Nearest::data-loaded", _this);

                        _this.webMap = webMap;
                        opLayers = webMap.operationalLayers;

                        // Get the details and pop up information for each layer
                        _this._getLayerDetails(opLayers);

                        // Run a query to get the features
                        // Go through operational layers and query each one
                        for (i = 0, iL = opLayers.length; i < iL; i++) {
                            layerOpts = _this._getlayerOptions(opLayers[i].itemId);

                            // check if layer has a url to be able to perform a query
                            if (!_this._isNullOrEmpty(opLayers[i].url)) {
                                task = new LayerInfoTask({
                                    currentPoint: _this.location,
                                    searchRadius: layerOpts.searchRadius,
                                    serviceUrl: _this._swapProtocol(opLayers[i].url),
                                    layerId: opLayers[i].id,
                                    itemId: opLayers[i].itemId
                                });

                                queryTasks.push(task.execute());
                            }
                        }

                        // Once all queries have finished do the find nearest
                        all(queryTasks).then(function (queryResults) {
                            var j = 0, jL = queryResults.length, nearestTask = null, nearestTasks = [], layerName = "", layerOpts;

                            topic.publish("Nearest::query-done", _this, queryResults);

                            for (j = 0; j < jL; j++) {
                                layerOpts = _this._getlayerOptions(queryResults[j].itemId);

                                // Perform find nearest on each set of features
                                if ((queryResults[j].error === null) && (queryResults[j].results) && (queryResults[j].results.features.length > 0)) {

                                    nearestTask = new ClientNearestTask({
                                        maxResults: layerOpts.maxResults,
                                        layerId: queryResults[j].id,
                                        itemId: queryResults[j].itemId,
                                        mode: _this.findNearestMode
                                    });

                                    nearestTasks.push(nearestTask.execute(_this.location, queryResults[j].results, queryResults[j].layerInfo));
                                }
                            }

                            // Once all of the find nearest tasks have finished display the results
                            all(nearestTasks).then(function (nearestResults) {
                                var k = 0, kL = nearestResults.length, lpInd = 0;

                                topic.publish("Nearest::nearest-task-done", _this, nearestResults);

                                // nearestResults is an array of arrays of the results
                                // So an array of layers, each layer has a set of results

                                for (k = 0; k < kL; k++) {
                                    if (nearestResults[k].error === null && nearestResults[k].result !== null) {
                                        if (nearestResults[k].result.limitExceeded) {

                                            //layerName = "";
                                            //for (lpInd = 0; lpInd < _this.layerPopUpFields.length; lpInd++) {
                                            //    if (_this.layerPopUpFields[lpInd].id === nearestResults[k].id) {
                                            //        layerName = _this.layerPopUpFields[lpInd].layerName;
                                            //        break;
                                            //    }
                                            //}

                                            //break;
                                        }
                                        _this._displayResults(nearestResults[k]);
                                    }
                                }

                                // Finished
                                topic.publish("Nearest::loaded", _this);

                                //displayResults
                            }, function (err) {

                            });
                        });
                    }
                });
            }
            else {
                topic.publish("Nearest::loaded", this);
            }
            // Output events
        },

        _getlayerOptions: function(itemId) {
            var i = 0, iL = 0, layerOpts = {
                webmapId: this.webmapId,
                maxResults: this.maxResults,
                searchRadius: this.searchRadius,
                showOnMap: this.showOnMap,
                showCounters: this.showCounters,
                display: this.display,
                showDistance: this.showDistance
            };

            if(this.layerOptions) {
                for (i = 0, iL = this.layerOptions.length; i < iL; i++) {
                    if (this.layerOptions[i].itemId === itemId) {
                        return lang.mixin({}, layerOpts, this.layerOptions[i]);
                    }
                }
            }
            return layerOpts;
        },

        _displayResults: function(results) {
            var lpInd = 0, currentLayerInd, layerInfo, layerDiv, layer, layerOpts;

            // Make sure there are some results
            if (!this._isNullOrEmpty(results) && !this._isNullOrEmpty(results.result)) {

                for (lpInd = 0; lpInd < this.layerPopUpFields.length; lpInd++) {
                    if (this.layerPopUpFields[lpInd].id === results.id) {
                        currentLayerInd = lpInd;
                        break;
                    }
                }

                layerInfo = this.layerPopUpFields[currentLayerInd];

                // layer node
                layerDiv = domConstruct.create("div", {
                    className: "panel-body"
                });
                domConstruct.place(layerDiv, this._layers, "last");

                layerOpts = this._getlayerOptions(results.itemId);

                layer = new NearestLayer({
                    results: results,
                    layerInfo: layerInfo,
                    maxFeatures: layerOpts.maxResults,
                    distance: layerOpts.searchRadius,
                    distanceUnits: "miles",
                    layerOptions: layerOpts
                }, layerDiv);

                layer.startup();
            }
        },

        _getLayerDetails: function (layers) {
            var _this = this, i = 0, iL = 0, popupInfo = null, fields = [], j = 0, jL = 0, layerFields = null;

            if (!this._isNullOrEmpty(layers)) {
                // Iterate through any operational layers
                for (i = 0, iL = layers.length; i < iL; i++) {

                    // check if it has any popups defined
                    if (layers[i].hasOwnProperty("popupInfo")) {
                        popupInfo = layers[i].popupInfo;
                        fields = [];

                        for (j = 0, jL = popupInfo.fieldInfos.length; j < jL; j++) {
                            // Check each field and see if it is visible in the popup
                            if (popupInfo.fieldInfos[j].visible) {
                                fields.push(popupInfo.fieldInfos[j].fieldName);
                            }
                        }

                        // If any fields are visible create an object to hold the fields and the layer name
                        layerFields = {
                            "layerName": layers[i].title,
                            "id": layers[i].id,
                            "fields": fields,
                            "popupInfo": popupInfo
                        };
                        this.layerPopUpFields.push(layerFields);

                    }
                    else {
                        // Might not have the popup info saved with the webmap
                        var _layer = layers[i];

                        (function (l, t) {
                            t._getItemData(l.itemId).then(function (data) {
                                if (data && data.layers) {
                                   var lFields = {
                                        "layerName": l.title,
                                        "id": l.id,
                                        "popupInfo": data.layers[0].popupInfo
                                    };

                                    t.layerPopUpFields.push(lFields);
                                }
                            });
                        })(_layer, _this);

                    }
                }
            }
        }

    });
});<commit_msg>Add support for layer name<commit_after>/*global define, console*/

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

define([
    'dojo/text!./templates/Nearest.html',
    'dojo/_base/declare',
    "dojo/_base/lang",
    "dojo/promise/all",
    'dijit/_Widget',
    'dijit/_TemplatedMixin',
    'dijit/_WidgetsInTemplateMixin',
    './_NearestBase',
    "dojo/dom-construct",
    "./tasks/ClientNearestTask",
    "./tasks/LayerInfoTask",
    "./NearestLayer",
    'dojo/topic'
],
function (
    template, declare, lang, all, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, _NearestBase, domConstruct, ClientNearestTask, LayerInfoTask, NearestLayer, topic) {

    return declare([_Widget, _NearestBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
        // description:
        //    Find the nearest features around a point

        templateString: template,
        baseClass: 'nearest',
        widgetsInTemplate: true,

        layerPopUpFields: [],

        // Properties to be sent into constructor

        constructor: function (options, srcRefNode) {
            this.options = {
                webmapId: "", // The id of the webmap to use.
                location: null, // The location to use as the centre point.
                maxResults: 10, // The maximum number of features to return.
                searchRadius: 5, // The search radius in miles.
                display: "expandable", // How to display the results. Expandable or fixed.
                layerOptions: [], // Options for each layer. These override the default radius and max results
                showOnMap: true, // Display the 'Show On Map' link
                showCounters: true, // Show the feature counts
                showDistance: true, // Show the distance
                findNearestMode: "geodesic"
            };

            /*
                layerOptions:[
                    {
                        itemId: ""
                        maxResults:
                        searchRadius:,
                        showOnMap:
                        showCounters:
                        display:
                    }
                ]
            */

            // mix in settings and defaults
            var defaults = lang.mixin({}, this.options, options);

            // Set properties
            this.set("webmapId", defaults.webmapId);
            this.set("location", defaults.location);
            this.set("maxResults", defaults.maxResults);
            this.set("searchRadius", defaults.searchRadius);
            this.set("display", defaults.display);
            this.set("layerOptions", defaults.layerOptions);
            this.set("showOnMap", defaults.showOnMap);
            this.set("showCounters", defaults.showCounters);
            this.set("showDistance", defaults.showDistance);
            this.set("findNearestMode", defaults.findNearestMode);

            // widget node
            this.domNode = srcRefNode;
        },

        buildRendering: function () {
            this.inherited(arguments);

        },

        postCreate: function() {
            // summary:
            //    Overrides method of same name in dijit._Widget.
            // tags:
            //    private
            //console.log('app.Nearest::postCreate', arguments);

            this.setupConnections();

            this.inherited(arguments);
        },

        // start widget. called by user
        startup: function () {
            this._init();
        },

        // connections/subscriptions will be cleaned up during the destroy() lifecycle phase
        destroy: function () {
            // call the superclass method of the same name.
            this.inherited(arguments);
        },

        setupConnections: function() {
            // summary:
            //    wire events, and such
            //
            //console.log('app.Nearest::setupConnections', arguments);

        },

        /* ---------------- */
        /* Public Functions */
        /* ---------------- */

        /* ---------------- */
        /* Private Functions */
        /* ---------------- */

        _init: function () {
            var _this = this;

            // Do query and build results
            if (!this._isNullOrEmpty(this.webmapId)) {
                this._getItemData(this.webmapId, this.token).then(function (webMap) {
                    var queryTasks = [], i = 0, iL = 0, task = null, opLayers, layerOpts;

                    if (webMap) {
                        topic.publish("Nearest::data-loaded", _this);

                        _this.webMap = webMap;
                        opLayers = webMap.operationalLayers;

                        // Get the details and pop up information for each layer
                        _this._getLayerDetails(opLayers);

                        // Run a query to get the features
                        // Go through operational layers and query each one
                        for (i = 0, iL = opLayers.length; i < iL; i++) {
                            layerOpts = _this._getlayerOptions(opLayers[i].itemId);

                            // check if layer has a url to be able to perform a query
                            if (!_this._isNullOrEmpty(opLayers[i].url)) {
                                task = new LayerInfoTask({
                                    currentPoint: _this.location,
                                    searchRadius: layerOpts.searchRadius,
                                    serviceUrl: _this._swapProtocol(opLayers[i].url),
                                    layerId: opLayers[i].id,
                                    itemId: opLayers[i].itemId
                                });

                                queryTasks.push(task.execute());
                            }
                        }

                        // Once all queries have finished do the find nearest
                        all(queryTasks).then(function (queryResults) {
                            var j = 0, jL = queryResults.length, nearestTask = null, nearestTasks = [], layerName = "", layerOpts;

                            topic.publish("Nearest::query-done", _this, queryResults);

                            for (j = 0; j < jL; j++) {
                                layerOpts = _this._getlayerOptions(queryResults[j].itemId);

                                // Perform find nearest on each set of features
                                if ((queryResults[j].error === null) && (queryResults[j].results) && (queryResults[j].results.features.length > 0)) {

                                    nearestTask = new ClientNearestTask({
                                        maxResults: layerOpts.maxResults,
                                        layerId: queryResults[j].id,
                                        itemId: queryResults[j].itemId,
                                        mode: _this.findNearestMode
                                    });

                                    nearestTasks.push(nearestTask.execute(_this.location, queryResults[j].results, queryResults[j].layerInfo));
                                }
                            }

                            // Once all of the find nearest tasks have finished display the results
                            all(nearestTasks).then(function (nearestResults) {
                                var k = 0, kL = nearestResults.length, lpInd = 0;

                                topic.publish("Nearest::nearest-task-done", _this, nearestResults);

                                // nearestResults is an array of arrays of the results
                                // So an array of layers, each layer has a set of results

                                for (k = 0; k < kL; k++) {
                                    if (nearestResults[k].error === null && nearestResults[k].result !== null) {
                                        if (nearestResults[k].result.limitExceeded) {

                                            //layerName = "";
                                            //for (lpInd = 0; lpInd < _this.layerPopUpFields.length; lpInd++) {
                                            //    if (_this.layerPopUpFields[lpInd].id === nearestResults[k].id) {
                                            //        layerName = _this.layerPopUpFields[lpInd].layerName;
                                            //        break;
                                            //    }
                                            //}

                                            //break;
                                        }
                                        _this._displayResults(nearestResults[k]);
                                    }
                                }

                                // Finished
                                topic.publish("Nearest::loaded", _this);

                                //displayResults
                            }, function (err) {

                            });
                        });
                    }
                });
            }
            else {
                topic.publish("Nearest::loaded", this);
            }
            // Output events
        },

        _getlayerOptions: function(itemId, id) {
            var i = 0, iL = 0, layerOpts = {
                webmapId: this.webmapId,
                maxResults: this.maxResults,
                searchRadius: this.searchRadius,
                showOnMap: this.showOnMap,
                showCounters: this.showCounters,
                display: this.display,
                showDistance: this.showDistance
            },
            field = "itemId", value = itemId;

            if (this.layerOptions) {
                // If we have an id then use that, otherwise use the item id. Item id could be the same for all items.
                field = (!this._isNullOrEmpty(id) && !this._isNullOrEmpty(this.layerOptions[0].id)) ? "id" : "itemId";
                value = (field === "id") ? id : itemId;

                for (i = 0, iL = this.layerOptions.length; i < iL; i++) {
                    if (this.layerOptions[i][field] === value) {
                        return lang.mixin({}, layerOpts, this.layerOptions[i]);
                    }
                }
            }
            return layerOpts;
        },

        _displayResults: function(results) {
            var lpInd = 0, currentLayerInd, layerInfo, layerDiv, layer, layerOpts;

            // Make sure there are some results
            if (!this._isNullOrEmpty(results) && !this._isNullOrEmpty(results.result)) {

                for (lpInd = 0; lpInd < this.layerPopUpFields.length; lpInd++) {
                    if (this.layerPopUpFields[lpInd].id === results.id) {
                        currentLayerInd = lpInd;
                        break;
                    }
                }

                layerInfo = this.layerPopUpFields[currentLayerInd];

                // layer node
                layerDiv = domConstruct.create("div", {
                    className: "panel-body"
                });
                domConstruct.place(layerDiv, this._layers, "last");

                layerOpts = this._getlayerOptions(results.itemId);

                layer = new NearestLayer({
                    results: results,
                    layerInfo: layerInfo,
                    maxFeatures: layerOpts.maxResults,
                    distance: layerOpts.searchRadius,
                    distanceUnits: "miles",
                    layerOptions: layerOpts
                }, layerDiv);

                layer.startup();
            }
        },

        _getLayerDetails: function (layers) {
            var _this = this, i = 0, iL = 0, popupInfo = null, fields = [], j = 0, jL = 0, layerFields = null;

            if (!this._isNullOrEmpty(layers)) {
                // Iterate through any operational layers
                for (i = 0, iL = layers.length; i < iL; i++) {

                    // check if it has any popups defined
                    if (layers[i].hasOwnProperty("popupInfo")) {
                        popupInfo = layers[i].popupInfo;
                        fields = [];

                        for (j = 0, jL = popupInfo.fieldInfos.length; j < jL; j++) {
                            // Check each field and see if it is visible in the popup
                            if (popupInfo.fieldInfos[j].visible) {
                                fields.push(popupInfo.fieldInfos[j].fieldName);
                            }
                        }

                        // If any fields are visible create an object to hold the fields and the layer name
                        layerFields = {
                            "layerName": layers[i].title,
                            "id": layers[i].id,
                            "fields": fields,
                            "popupInfo": popupInfo
                        };
                        this.layerPopUpFields.push(layerFields);

                    }
                    else {
                        // Might not have the popup info saved with the webmap
                        var _layer = layers[i];

                        (function (l, t) {
                            t._getItemData(l.itemId).then(function (data) {
                                if (data && data.layers) {
                                   var lFields = {
                                        "layerName": l.title,
                                        "id": l.id,
                                        "popupInfo": data.layers[0].popupInfo
                                    };

                                    t.layerPopUpFields.push(lFields);
                                }
                            });
                        }(_layer, _this));

                    }
                }
            }
        }

    });
});<|endoftext|>


<commit_before>const benchmark = require('benchmark')
const fs = require('fs')
const camaro = require('../')
const x2j = require('rapidx2j')
const xml2json = require('xml2json')
const xml2js = require('xml2js').parseString
const fastXmlParser = require('fast-xml-parser')

const suite = new benchmark.Suite()
const xml = fs.readFileSync('examples/ean.xml', 'utf-8')

suite.add('camaro', function() {
    const template = {
        cache_key: "/HotelListResponse/cacheKey",
        hotels: ["//HotelSummary", {
            hotel_id: "hotelId",
            name: "name",
            rooms: ["RoomRateDetailsList/RoomRateDetails", {
                rates: ["RateInfos/RateInfo", {
                    currency: "ChargeableRateInfo/@currencyCode",
                    non_refundable: "nonRefundable",
                    price: "ChargeableRateInfo/@total"
                }],
                room_name: "roomDescription",
                room_type_id: "roomTypeCode"
            }]
        }],
        session_id: "/HotelListResponse/customerSessionId"
    }
    camaro(xml, template)
})

suite.add('rapidx2j', function() {
    x2j.parse(xml)
})

suite.add('xml2json', function() {
    xml2json.toJson(xml)
})

suite.add('xml2js', function() {
    xml2js(xml, () => {})
})

suite.add('fast-xml-parser', function() {
    fastXmlParser.parse(xml)
})

suite.on('cycle', cycle)
suite.run()

function cycle(e) {
    console.log(e.target.toString())
}
<commit_msg>benchmark: add nkit4nodejs to bench script<commit_after>const benchmark = require('benchmark')
const fs = require('fs')
const camaro = require('../')
const x2j = require('rapidx2j')
const xml2json = require('xml2json')
const xml2js = require('xml2js').parseString
const fastXmlParser = require('fast-xml-parser')
const nkit = require('nkit4nodejs')

const suite = new benchmark.Suite()
const xml = fs.readFileSync('examples/ean.xml', 'utf-8')

suite.add('camaro', function() {
    const template = {
        cache_key: '/HotelListResponse/cacheKey',
        hotels: [
            '//HotelSummary',
            {
                hotel_id: 'hotelId',
                name: 'name',
                rooms: [
                    'RoomRateDetailsList/RoomRateDetails',
                    {
                        rates: [
                            'RateInfos/RateInfo',
                            {
                                currency: 'ChargeableRateInfo/@currencyCode',
                                non_refundable: 'nonRefundable',
                                price: 'ChargeableRateInfo/@total'
                            }
                        ],
                        room_name: 'roomDescription',
                        room_type_id: 'roomTypeCode'
                    }
                ]
            }
        ],
        session_id: '/HotelListResponse/customerSessionId'
    }
    camaro(xml, template)
})

suite.add('rapidx2j', function() {
    x2j.parse(xml)
})

suite.add('xml2json', function() {
    xml2json.toJson(xml)
})

suite.add('xml2js', function() {
    xml2js(xml, () => {})
})

suite.add('fast-xml-parser', function() {
    fastXmlParser.parse(xml)
})

suite.add('nkit4nodejs', function() {
    const options = {
        trim: true,
        attrkey: '$',
        textkey: '_',
        explicit_array: true
    }

    const builder = new nkit.AnyXml2VarBuilder(options)
    builder.feed(xml)
    const result = builder.end()
})

suite.on('cycle', cycle)
suite.run()

function cycle(e) {
    console.log(e.target.toString())
}
<|endoftext|>


<commit_before>var webpack = require('webpack');
module.exports = {
    entry: [
      'webpack/hot/only-dev-server',
      "./js/app.js",
      "./css/main.scss"
    ],
    output: {
        path: __dirname + '/build',
        filename: "bundle.js"
    },
    module: {
        preLoaders: [
          {
            test: /(\.js$|\.jsx$)/,
            exclude: /node_modules/,
            loader: "eslint-loader"
          }
        ],
        loaders: [
            { test: /\.js?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
            { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
            { test: /\.scss$/, loader: "style!css!sass" }
        ]
    },
    eslint: {
      configFile: '.eslintrc.yml'
    },
    plugins: [
      new webpack.NoErrorsPlugin()
    ]

};
<commit_msg>Fixed a minor issue in Webpack config<commit_after>var webpack = require('webpack');
module.exports = {
    entry: [
      'webpack/hot/only-dev-server',
      "./js/app.js",
      "./css/main.scss"
    ],
    output: {
        path: __dirname + '/build',
        filename: "bundle.js"
    },
    module: {
        preLoaders: [
          {
            test: /(\.js$|\.jsx$)/,
            exclude: /node_modules/,
            loader: "eslint-loader"
          }
        ],
        loaders: [
            { test: /\.jsx?$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
            { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
            { test: /\.scss$/, loader: "style!css!sass" }
        ]
    },
    eslint: {
      configFile: '.eslintrc.yml'
    },
    plugins: [
      new webpack.NoErrorsPlugin()
    ]

};
<|endoftext|>


<commit_before>function Network() {
    // To server functions and constants
    function sendGameRequest(numPlayers) {
        var message = {"NumPlayers": numPlayers}
        sendMessage(NEW_GAME_CMD, message)
    }

    function sendClientInfo(token) {
        var message = {"Token": token}
        sendMessage(CLIENT_INFO_CMD, message);
    }

    function sendViewWorld() {
        sendMessage(VIEW_WORLD_CMD, {});
    }

    function sendUnitMove(unit, move) {
        var message = {move: []};
        for (var i = 0; i < move.length; i++) {
            message.move.push(move[i].position);
        };

        sendMessage(MOVE_UNIT_CMD, message);
    }

    CLIENT_INFO_CMD = "clientInfo";
    NEW_GAME_CMD = "newGame";
    VIEW_WORLD_CMD = "view";
    MOVE_UNIT_CMD = "move";

    host = window.location.host.split(":")[0];
    port = getPortNum();
    ws_addr = "ws://" + host + ":" + port + "/ws";
    conn = new WebSocket(ws_addr);
    DELIM = ":";

    // This function expects the message as a javascript object
    function sendMessage(command, messageObj) {
        var jsonified = JSON.stringify(messageObj)
        packet = command + DELIM + jsonified;
        conn.send(packet)
    }

    // From server functions and constants
    this.packetHandlers = {
        "view": parseViewWorld.bind(this),
        "clientinfo": parseClientInfo.bind(this),
        "new": parseGameRequestSuccess.bind(this),
        "move": parseMoveResponse.bind(this)
    }

    function logTemplateComp(name, realResponse) {
        if (!verifyStructure(responseTemplates[name], realResponse)) {
            console.log("The", name, "template does not match. Proceed with caution");
        }
    }

    function parseViewWorld(status, viewWorld) {
        this.logTemplateComp("viewWorld", viewWorld);
        var terrain = viewWorld.terrain;
        if (game.world == null) {
            // TODO check if the terrain actually exists first
            game.world = new World(terrain.length, terrain[0].length);
            game.currentState = "CAMERA_CONTROL";
        }
        for (var x = 0; x < terrain.length; x++) {
            for (var y = 0; y < terrain[x].length; y++) {
                // TODO terrain cells may someday be the actual JSON
                terrain[x][y] = terrainLookup(terrain[x][y], x, y);
            }
        }
        game.world.initialize(terrain);

        var players = viewWorld.players;
        for (var i = players.length - 1; i >= 0; i--) {
            var player = players[i];
            game.world.addOrUpdatePlayer(player.id, player.nation,
                                         player.team);
        }
        game.currentPlayerId = viewWorld.turnOwner;

        var units = viewWorld.units;
        for (var i = units.length - 1; i >= 0; i--) {
            // this should be tank, but I've only got wizards right now
            // not sent movementType right now
            var unit = units[i];
            var position = unit.position;
            var movement = unit.movement;
            var unitnation = parseInt(unit.nation) + unit.name;
            var spriteName = UnitNationSprite[unitnation];
            if (!game.world.findUnit(position.x, position.y)) {
                game.world.addUnit(unit.nation, spriteName, position,
                                   movement.distance, movement.type,
                                   movement.speeds, unit.health,
                                   unit.nation, unit.name, unit.canMove);
            } else {
                console.log("Verifing the unit could be useful here");
            }
        }
    }

    function parseClientInfo(status) {
        console.log("Your client info has been received, sending game request");
        this.sendGameRequest(parseInt(desiredPlayers));
    }

    function parseGameRequestSuccess(status) {
        console.log("Congratulations, you've been matched to a game!");
        this.sendViewWorld();
    }

    function parseMoveResponse(status) {
        if (status == 0) {
            var unit = unitControlState.unit;
            var path = unitControlState.path;
            if (path) {
                // tell the renderer about the move
                var unitSprite = assets.spriteManager.getSprite(unit.spriteName);
                // unitSprite.movements = unitSprite.movements.concat(translatePathToMoves(path));
                var goal = path[path.length - 1];
                unit.pos.x = goal.position.x;
                unit.pos.y = goal.position.y;
                // shim, while the mac tab crash bug is still happening
                unitSprite.drawPos = goal.position;
                unit.canMove = false;
                unitControlState.reset();
            } else {
                console.log("Your path is null, man");
            }
        } else {
            console.log("Go a bad status from server:", status);
        }
    }

    conn.onopen = function () {
        this.sendClientInfo(getPlayerId());
    }.bind(this);

    // Log errors
    conn.onerror = function (error) {
        console.log('WebSocket Error ' + error);
    };

    // Log messages from the server
    conn.onmessage = function (e) {
        var cmds = trimSocketChars(e.data.actualSplit(DELIM, 2));
        if (cmds.length == 2) {
            var pkt_type = cmds[0];
            var response = JSON.parse(cmds[1]);
            var dataObj = reponse.payload;
            var status = response.status;
            // It's likely the individual handlers would be interested in the
            // failure condition
            if (status >= 0) {
                var handler = this.packetHandlers[pkt_type];
                if (handler != null) {
                    handler(status, dataObj);
                } else {
                    console.log("Recieved unknown command:", pkt_type);
                }
            } else {
                console.log("Received failure from server:", cmds);
            }
        } else {
            console.log("Received malformed command:", cmds);
        }
    }.bind(this);

    this.sendGameRequest = function(numPlayers) {
        sendGameRequest(numPlayers);
    }

    this.sendClientInfo = function(playerId) {
        var token = $.cookie("token");
        if (token) {
            sendClientInfo(token);
        } else {
            alert("You do not have a token, can't start game");
        }
    }

    this.sendViewWorld = function() {
        sendViewWorld();
    }

    this.sendUnitMove = function(unit, move) {
        sendUnitMove(unit, move);
    }

    this.logTemplateComp = function(name, realResponse) {
        logTemplateComp(name, realResponse);
    }
}

function trimSocketChars(cmds) {
    cmds[cmds.length - 1] = cmds[cmds.length - 1].replace(/\x00/gi, "");
    return cmds;
}

String.prototype.actualSplit = function(sep, maxsplit) {
    var split = this.split(sep);
    var excess = split.slice(maxsplit - 1, split.length).join(":");
    if (excess.length > 0) {
        return maxsplit ? split.slice(0, maxsplit - 1).concat(excess) : split;
    } else {
        return maxsplit ? split.slice(0, maxsplit - 1) : split;
    }
}
<commit_msg>Typos man<commit_after>function Network() {
    // To server functions and constants
    function sendGameRequest(numPlayers) {
        var message = {"NumPlayers": numPlayers}
        sendMessage(NEW_GAME_CMD, message)
    }

    function sendClientInfo(token) {
        var message = {"Token": token}
        sendMessage(CLIENT_INFO_CMD, message);
    }

    function sendViewWorld() {
        sendMessage(VIEW_WORLD_CMD, {});
    }

    function sendUnitMove(unit, move) {
        var message = {move: []};
        for (var i = 0; i < move.length; i++) {
            message.move.push(move[i].position);
        };

        sendMessage(MOVE_UNIT_CMD, message);
    }

    CLIENT_INFO_CMD = "clientInfo";
    NEW_GAME_CMD = "newGame";
    VIEW_WORLD_CMD = "view";
    MOVE_UNIT_CMD = "move";

    host = window.location.host.split(":")[0];
    port = getPortNum();
    ws_addr = "ws://" + host + ":" + port + "/ws";
    conn = new WebSocket(ws_addr);
    DELIM = ":";

    // This function expects the message as a javascript object
    function sendMessage(command, messageObj) {
        var jsonified = JSON.stringify(messageObj)
        packet = command + DELIM + jsonified;
        conn.send(packet)
    }

    // From server functions and constants
    this.packetHandlers = {
        "view": parseViewWorld.bind(this),
        "clientinfo": parseClientInfo.bind(this),
        "new": parseGameRequestSuccess.bind(this),
        "move": parseMoveResponse.bind(this)
    }

    function logTemplateComp(name, realResponse) {
        if (!verifyStructure(responseTemplates[name], realResponse)) {
            console.log("The", name, "template does not match. Proceed with caution");
        }
    }

    function parseViewWorld(status, viewWorld) {
        this.logTemplateComp("viewWorld", viewWorld);
        var terrain = viewWorld.terrain;
        if (game.world == null) {
            // TODO check if the terrain actually exists first
            game.world = new World(terrain.length, terrain[0].length);
            game.currentState = "CAMERA_CONTROL";
        }
        for (var x = 0; x < terrain.length; x++) {
            for (var y = 0; y < terrain[x].length; y++) {
                // TODO terrain cells may someday be the actual JSON
                terrain[x][y] = terrainLookup(terrain[x][y], x, y);
            }
        }
        game.world.initialize(terrain);

        var players = viewWorld.players;
        for (var i = players.length - 1; i >= 0; i--) {
            var player = players[i];
            game.world.addOrUpdatePlayer(player.id, player.nation,
                                         player.team);
        }
        game.currentPlayerId = viewWorld.turnOwner;

        var units = viewWorld.units;
        for (var i = units.length - 1; i >= 0; i--) {
            // this should be tank, but I've only got wizards right now
            // not sent movementType right now
            var unit = units[i];
            var position = unit.position;
            var movement = unit.movement;
            var unitnation = parseInt(unit.nation) + unit.name;
            var spriteName = UnitNationSprite[unitnation];
            if (!game.world.findUnit(position.x, position.y)) {
                game.world.addUnit(unit.nation, spriteName, position,
                                   movement.distance, movement.type,
                                   movement.speeds, unit.health,
                                   unit.nation, unit.name, unit.canMove);
            } else {
                console.log("Verifing the unit could be useful here");
            }
        }
    }

    function parseClientInfo(status) {
        console.log("Your client info has been received, sending game request");
        this.sendGameRequest(parseInt(desiredPlayers));
    }

    function parseGameRequestSuccess(status) {
        console.log("Congratulations, you've been matched to a game!");
        this.sendViewWorld();
    }

    function parseMoveResponse(status) {
        if (status == 0) {
            var unit = unitControlState.unit;
            var path = unitControlState.path;
            if (path) {
                // tell the renderer about the move
                var unitSprite = assets.spriteManager.getSprite(unit.spriteName);
                // unitSprite.movements = unitSprite.movements.concat(translatePathToMoves(path));
                var goal = path[path.length - 1];
                unit.pos.x = goal.position.x;
                unit.pos.y = goal.position.y;
                // shim, while the mac tab crash bug is still happening
                unitSprite.drawPos = goal.position;
                unit.canMove = false;
                unitControlState.reset();
            } else {
                console.log("Your path is null, man");
            }
        } else {
            console.log("Go a bad status from server:", status);
        }
    }

    conn.onopen = function () {
        this.sendClientInfo(getPlayerId());
    }.bind(this);

    // Log errors
    conn.onerror = function (error) {
        console.log('WebSocket Error ' + error);
    };

    // Log messages from the server
    conn.onmessage = function (e) {
        var cmds = trimSocketChars(e.data.actualSplit(DELIM, 2));
        if (cmds.length == 2) {
            var pkt_type = cmds[0];
            var response = JSON.parse(cmds[1]);
            var dataObj = response.payload;
            var status = response.status;
            // It's likely the individual handlers would be interested in the
            // failure condition
            if (status >= 0) {
                var handler = this.packetHandlers[pkt_type];
                if (handler != null) {
                    handler(status, dataObj);
                } else {
                    console.log("Recieved unknown command:", pkt_type);
                }
            } else {
                console.log("Received failure from server:", cmds);
            }
        } else {
            console.log("Received malformed command:", cmds);
        }
    }.bind(this);

    this.sendGameRequest = function(numPlayers) {
        sendGameRequest(numPlayers);
    }

    this.sendClientInfo = function(playerId) {
        var token = $.cookie("token");
        if (token) {
            sendClientInfo(token);
        } else {
            alert("You do not have a token, can't start game");
        }
    }

    this.sendViewWorld = function() {
        sendViewWorld();
    }

    this.sendUnitMove = function(unit, move) {
        sendUnitMove(unit, move);
    }

    this.logTemplateComp = function(name, realResponse) {
        logTemplateComp(name, realResponse);
    }
}

function trimSocketChars(cmds) {
    cmds[cmds.length - 1] = cmds[cmds.length - 1].replace(/\x00/gi, "");
    return cmds;
}

String.prototype.actualSplit = function(sep, maxsplit) {
    var split = this.split(sep);
    var excess = split.slice(maxsplit - 1, split.length).join(":");
    if (excess.length > 0) {
        return maxsplit ? split.slice(0, maxsplit - 1).concat(excess) : split;
    } else {
        return maxsplit ? split.slice(0, maxsplit - 1) : split;
    }
}
<|endoftext|>


<commit_before>const path = require('path');
const dotenv = require('dotenv');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
// require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { AureliaPlugin, ModuleDependenciesPlugin } = require('aurelia-webpack-plugin');
const { ProvidePlugin } = require('webpack');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const webpack = require('webpack');

// config helpers:
dotenv.config({ path: '.env' });
const ensureArray = config => config && (Array.isArray(config) ? config : [config]) || [];
const when = (condition, config, negativeConfig) => (condition ? ensureArray(config) : ensureArray(negativeConfig));

// primary config:
const title = 'Web Jam LLC';
const outDir = path.resolve(__dirname, 'dist');
const srcDir = path.resolve(__dirname, 'src');
const nodeModulesDir = path.resolve(__dirname, 'node_modules');
const baseUrl = '/';

const cssRules = [
  { loader: 'css-loader' }
];

module.exports = ({
  production, server, extractCss, coverage, analyze
} = {}) => ({
  resolve: {
    extensions: ['.js'],
    modules: [srcDir, 'node_modules'],
  },
  entry: {
    app: ['aurelia-bootstrapper'],
    vendor: ['bluebird', 'jquery', 'bootstrap', 'whatwg-fetch', 'isomorphic-fetch']
  },
  mode: production ? 'production' : 'development',
  output: {
    path: outDir,
    publicPath: baseUrl,
    filename: production ? '[name].[chunkhash].bundle.js' : '[name].[hash].bundle.js',
    sourceMapFilename: production ? '[name].[chunkhash].bundle.map' : '[name].[hash].bundle.map',
    chunkFilename: production ? '[name].[chunkhash].chunk.js' : '[name].[hash].chunk.js'
  },
  performance: { hints: false },
  devServer: {
    contentBase: outDir,
    // serve index.html for all 404 (required for push-state)
    historyApiFallback: true,
    port: parseInt(process.env.PORT, 10)
  },
  devtool: production ? 'nosources-source-map' : 'cheap-module-eval-source-map',
  module: {
    rules: [
      // CSS required in JS/TS files should use the style-loader that auto-injects it into the website
      // only when the issuer is a .js/.ts file, so the loaders are not applied inside html templates
      {
        test: /\.css$/i,
        issuer: [{ not: [{ test: /\.html$/i }] }],
        use: extractCss ? ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: cssRules
        }) : ['style-loader', ...cssRules],
      },
      {
        test: /\.css$/i,
        issuer: [{ test: /\.html$/i }],
        // CSS required in templates cannot be extracted safely
        // because Aurelia would try to require it again in runtime
        use: cssRules
      },
      { test: /\.html$/i, loader: 'html-loader' },
      {
        test: /\.js$/i,
        loader: 'babel-loader',
        exclude: nodeModulesDir,
        options: coverage ? { sourceMap: 'inline', plugins: ['istanbul'] } : {},
      },
      { test: /\.json$/i, loader: 'json-loader' },
      // use Bluebird as the global Promise implementation:
      { test: /[\/\\]node_modules[\/\\]bluebird[\/\\].+\.js$/, loader: 'expose-loader?Promise' },
      // embed small images and fonts as Data Urls and larger ones as files:
      { test: /\.(png|gif|jpg|cur)$/i, loader: 'url-loader', options: { limit: 8192 } },
      { test: /\.woff2(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff2' } },
      { test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff' } },
      // load these fonts normally, as files:
      { test: /\.(ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'file-loader' },
    ]
  },
  plugins: [
    new AureliaPlugin(),
    new ProvidePlugin({
      Promise: 'bluebird',
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery',
      Popper: ['popper.js', 'default']
    }),
    new ModuleDependenciesPlugin({
      'aurelia-testing': ['./compile-spy', './view-spy'],
      'aurelia-auth': ['./auth-filter'],
      'aurelia-config': ['./aurelia-config'],
      'au-table': ['./au-table', './au-table-select', './au-table-sort', './au-table-pagination'],
      'aurelia-validation': [
        './aurelia-validation',
        './controller-validate-result',
        './get-target-dom-element',
        './property-info',
        './validate-binding-behavior-base',
        './validate-binding-behavior',
        './validate-instruction',
        './validate-result',
        './validate-trigger',
        './validation-controller-factory',
        './validation-controller',
        './validation-errors-custom-attribute',
        './validation-renderer-custom-attribute',
        './validation-renderer',
        './validator'
      ]
    }),
    new HtmlWebpackPlugin({
      template: 'index.ejs',
      minify: production ? {
        removeComments: true,
        collapseWhitespace: true
      } : undefined,
      metadata: {
        // available in index.ejs //
        title, server, baseUrl
      }
    }),
    new CopyWebpackPlugin([
      { from: 'static/favicon.ico', to: 'favicon.ico' },
      { from: 'static/imgs', to: 'static/imgs' }]),
    new webpack.EnvironmentPlugin(['NODE_ENV', 'AuthProductionBaseURL', 'PORT', 'BackendUrl', 'GoogleClientId', 'userRoles']),
    new webpack.DefinePlugin({
      'process.env': Object.keys(process.env).reduce((o, k) => {
        o[k] = JSON.stringify(process.env[k]);
        return o;
      }, {})
    }),
    new CopyWebpackPlugin([
      { from: 'static/music/MRM.mp3', to: 'MRM.mp3' },
      { from: 'static/music/AT.mp3', to: 'AT.mp3' },
      { from: 'static/music/TTGA.mp3', to: 'TTGA.mp3' },
      { from: 'static/music/DITR.mp3', to: 'DITR.mp3' },
      { from: 'static/WebJamLLC_FactSheet.pdf', to: 'WebJamLLC_FactSheet.pdf' }
    ]),
    ...when(extractCss, new ExtractTextPlugin({
      filename: production ? '[md5:contenthash:hex:20].css' : '[id].css',
      allChunks: true
    })),
    ...when(production, new CopyWebpackPlugin([
      { from: 'static/favicon.ico', to: 'favicon.ico' }])),
    ...when(analyze, new BundleAnalyzerPlugin())
  ]
});
<commit_msg>json loader removed. webpack 4 has internal handling of json<commit_after>const path = require('path');
const dotenv = require('dotenv');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
// require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { AureliaPlugin, ModuleDependenciesPlugin } = require('aurelia-webpack-plugin');
const { ProvidePlugin } = require('webpack');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const webpack = require('webpack');

// config helpers:
dotenv.config({ path: '.env' });
const ensureArray = config => config && (Array.isArray(config) ? config : [config]) || [];
const when = (condition, config, negativeConfig) => (condition ? ensureArray(config) : ensureArray(negativeConfig));

// primary config:
const title = 'Web Jam LLC';
const outDir = path.resolve(__dirname, 'dist');
const srcDir = path.resolve(__dirname, 'src');
const nodeModulesDir = path.resolve(__dirname, 'node_modules');
const baseUrl = '/';

const cssRules = [
  { loader: 'css-loader' }
];

module.exports = ({
  production, server, extractCss, coverage, analyze
} = {}) => ({
  resolve: {
    extensions: ['.js'],
    modules: [srcDir, 'node_modules'],
  },
  entry: {
    app: ['aurelia-bootstrapper'],
    vendor: ['bluebird', 'jquery', 'bootstrap', 'whatwg-fetch', 'isomorphic-fetch']
  },
  mode: production ? 'production' : 'development',
  output: {
    path: outDir,
    publicPath: baseUrl,
    filename: production ? '[name].[chunkhash].bundle.js' : '[name].[hash].bundle.js',
    sourceMapFilename: production ? '[name].[chunkhash].bundle.map' : '[name].[hash].bundle.map',
    chunkFilename: production ? '[name].[chunkhash].chunk.js' : '[name].[hash].chunk.js'
  },
  performance: { hints: false },
  devServer: {
    contentBase: outDir,
    // serve index.html for all 404 (required for push-state)
    historyApiFallback: true,
    port: parseInt(process.env.PORT, 10)
  },
  devtool: production ? 'nosources-source-map' : 'cheap-module-eval-source-map',
  module: {
    rules: [
      // CSS required in JS/TS files should use the style-loader that auto-injects it into the website
      // only when the issuer is a .js/.ts file, so the loaders are not applied inside html templates
      {
        test: /\.css$/i,
        issuer: [{ not: [{ test: /\.html$/i }] }],
        use: extractCss ? ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: cssRules
        }) : ['style-loader', ...cssRules],
      },
      {
        test: /\.css$/i,
        issuer: [{ test: /\.html$/i }],
        // CSS required in templates cannot be extracted safely
        // because Aurelia would try to require it again in runtime
        use: cssRules
      },
      { test: /\.html$/i, loader: 'html-loader' },
      {
        test: /\.js$/i,
        loader: 'babel-loader',
        exclude: nodeModulesDir,
        options: coverage ? { sourceMap: 'inline', plugins: ['istanbul'] } : {},
      },
      { test: /[\/\\]node_modules[\/\\]bluebird[\/\\].+\.js$/, loader: 'expose-loader?Promise' },
      // embed small images and fonts as Data Urls and larger ones as files:
      { test: /\.(png|gif|jpg|cur)$/i, loader: 'url-loader', options: { limit: 8192 } },
      { test: /\.woff2(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff2' } },
      { test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff' } },
      // load these fonts normally, as files:
      { test: /\.(ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'file-loader' },
    ]
  },
  plugins: [
    new AureliaPlugin(),
    new ProvidePlugin({
      Promise: 'bluebird',
      $: 'jquery',
      jQuery: 'jquery',
      'window.jQuery': 'jquery',
      Popper: ['popper.js', 'default']
    }),
    new ModuleDependenciesPlugin({
      'aurelia-testing': ['./compile-spy', './view-spy'],
      'aurelia-auth': ['./auth-filter'],
      'aurelia-config': ['./aurelia-config'],
      'au-table': ['./au-table', './au-table-select', './au-table-sort', './au-table-pagination'],
      'aurelia-validation': [
        './aurelia-validation',
        './controller-validate-result',
        './get-target-dom-element',
        './property-info',
        './validate-binding-behavior-base',
        './validate-binding-behavior',
        './validate-instruction',
        './validate-result',
        './validate-trigger',
        './validation-controller-factory',
        './validation-controller',
        './validation-errors-custom-attribute',
        './validation-renderer-custom-attribute',
        './validation-renderer',
        './validator'
      ]
    }),
    new HtmlWebpackPlugin({
      template: 'index.ejs',
      minify: production ? {
        removeComments: true,
        collapseWhitespace: true
      } : undefined,
      metadata: {
        // available in index.ejs //
        title, server, baseUrl
      }
    }),
    new CopyWebpackPlugin([
      { from: 'static/favicon.ico', to: 'favicon.ico' },
      { from: 'static/imgs', to: 'static/imgs' }]),
    new webpack.EnvironmentPlugin(['NODE_ENV', 'AuthProductionBaseURL', 'PORT', 'BackendUrl', 'GoogleClientId', 'userRoles']),
    new webpack.DefinePlugin({
      'process.env': Object.keys(process.env).reduce((o, k) => {
        o[k] = JSON.stringify(process.env[k]);
        return o;
      }, {})
    }),
    new CopyWebpackPlugin([
      { from: 'static/music/MRM.mp3', to: 'MRM.mp3' },
      { from: 'static/music/AT.mp3', to: 'AT.mp3' },
      { from: 'static/music/TTGA.mp3', to: 'TTGA.mp3' },
      { from: 'static/music/DITR.mp3', to: 'DITR.mp3' },
      { from: 'static/WebJamLLC_FactSheet.pdf', to: 'WebJamLLC_FactSheet.pdf' }
    ]),
    ...when(extractCss, new ExtractTextPlugin({
      filename: production ? '[md5:contenthash:hex:20].css' : '[id].css',
      allChunks: true
    })),
    ...when(production, new CopyWebpackPlugin([
      { from: 'static/favicon.ico', to: 'favicon.ico' }])),
    ...when(analyze, new BundleAnalyzerPlugin())
  ]
});
<|endoftext|>


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

/**
 * PhET-iO wrapper type for phet's Events type.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Andrew Adare (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var assertInstanceOf = require( 'ifphetio!PHET_IO/assertions/assertInstanceOf' );
  var phetioInherit = require( 'ifphetio!PHET_IO/phetioInherit' );
  var axon = require( 'AXON/axon' );
  var TFunctionWrapper = require( 'ifphetio!PHET_IO/types/TFunctionWrapper' );
  var TObject = require( 'ifphetio!PHET_IO/types/TObject' );
  var TString = require( 'ifphetio!PHET_IO/types/TString' );
  var TVoid = require( 'ifphetio!PHET_IO/types/TVoid' );
  var phetioEvents = require( 'ifphetio!PHET_IO/phetioEvents' );

  /**
   * Parametric wrapper type constructor.  Given an events type, this function returns an appropriate events wrapper type.
   *
   * This is a good test to use:
   *     var events = new TEvents();
   *     phet-io && phetio.addInstance( 'concentrationScreen.testEvents', events );
   *     events.trigger( 'personBorn', 'larry', 123 );
   *     events.trigger( 'purchasedSolute', Solute.DRINK_MIX );
   *
   *     With this for the API file
   *     'concentrationScreen.testEvents': TEvents( {
   *      personBorn: [ { arg: 'name', phetioValueType: TString }, { arg: 'length', phetioValueType: TNumber } ],
   *      purchasedSolute: [ { arg: 'solute', type: Solute } ],
   *      personAteLunch: [] } )
   *
   * @param events {Object} - wrapper type of Events: {event1:[{argName:argName,argType:argType},{}},...}. If loaded by
   *                          phet (not phet-io) argTypes will be the function returned by the 'ifphetio!' plugin.
   * @constructor
   */
  function TEvents( events ) {

    /**
     * This type constructor is parameterized based on the instance of Events.
     * @param instance {Object} - Events
     * @param {string} phetioID - the full unique tandem name for the instance
     * @constructor
     */
    var TEventsImpl = function TEventsImpl( instance, phetioID ) {
      assertInstanceOf( instance, phet.axon.Events );
      TObject.call( this, instance, phetioID );

      // Add listeners for each event name
      for ( var eventName in events ) {
        if ( events.hasOwnProperty( eventName ) ) {
          (function( eventName ) {

            // Listen for each event
            instance.onStatic( eventName, function() {
              var args = Array.prototype.slice.call( arguments );
              var argNameType = events[ eventName ];
              var optionsForArch = {};
              for ( var i = 0; i < args.length; i++ ) {
                var arg = args[ i ];
                var argName = argNameType[ i ].arg;
                var argType = argNameType[ i ].type;

                var argValue = arg;
                if ( argType.toStateObject ) {
                  argValue = argType.toStateObject( argValue );
                }

                optionsForArch[ argName ] = argValue;
              }
              var messageIndex = phetioEvents.start( 'model', phetioID, TEvents, eventName, optionsForArch );
              phetioEvents.end( messageIndex );
            } );
          })( eventName );
        }
      }
    };
    return phetioInherit( TObject, 'TEvents', TEventsImpl, {

      addListener: {
        returnType: TVoid,
        parameterTypes: [ TString, TFunctionWrapper( TVoid, [ TObject ] ) ],
        implementation: function( eventName, callback ) {
          this.instance.onStatic( eventName, callback );
        },
        documentation: 'Adds a listener to the specified event channel'
      },

      removeListener: {
        returnType: TVoid,
        parameterTypes: [ TString, TFunctionWrapper( TVoid, [ TObject ] ) ],
        implementation: function( eventName, callback ) {
          this.instance.offStatic( eventName, callback );
        },
        documentation: 'Removes a listener that was added with addListener'
      }
    }, {
      events: _.keys( events ),
      documentation: 'Event system, with multiple channels defined by string keys'
    } );
  }

  axon.register( 'TEvents', TEvents );

  return TEvents;
} );

<commit_msg>Removed TEvents, see https://github.com/phetsims/axon/issues/133<commit_after><|endoftext|>


<commit_before>/**
 * This kind provides:
 * - the project toolbars (with create .. delete)
 * - the project list
 *
 * The project list is a simple kind that only holds project names. It does not
 * hold project objects or kinds.
 */
enyo.kind({
	name: "ProjectList",
	classes: "enyo-unselectable ares_projectList",
	events: {
		onCreateProject: "",
		onProjectSelected: "",
		onScanProject: "",
		onProjectRemoved: "",
		onModifySettings: "",
		onPhonegapBuild: ""
	},
	handlers: {
	},
	debug: false,
	components: [
		{kind: "onyx.MoreToolbar", classes: "onyx-menu-toolbar ares_harmonia_toolBar ares-no-padding", isContainer: true, name: "toolbar", components: [
			{kind: "onyx.MenuDecorator", onSelect: "aresMenuItemSelected", components: [
				{content: "Ares"},
				{kind: "onyx.Menu", components: [
					{value: "showAccountConfigurator", components: [
						{kind: "onyx.IconButton", src: "$project-view/assets/images/ares_accounts.png"},
						{content: "Accounts..."}
					]},
					{classes: "onyx-menu-divider"},
					{content: "Properties..."}
				]}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", src: "$project-view//assets/images/project_view_new.png", onclick: "doCreateProject"},
				{kind: "onyx.Tooltip", content: "Create or Import Project..."}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", src: "$project-view//assets/images/project_view_build.png", onclick: "doPhonegapBuild"},
				{kind: "onyx.Tooltip", content: "Phonegap build"}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", src: "$project-view//assets/images/project_preview.png", onclick: "doPreview"},
				{kind: "onyx.Tooltip", content: "Preview Project..."}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", classes: "ares-scale-background",
				 src: "$project-view/assets/images/project_settings.png", onclick: "doModifySettings"},
				{kind: "onyx.Tooltip", content: "Settings..."}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", src: "$project-view//assets/images/project_view_edit.png", onclick: "doScanProject"},
				{kind: "onyx.Tooltip", content: "Scan for Projects..."}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", src: "$project-view//assets/images/project_view_delete.png", onclick: "removeProjectAction"},
				// FIXME: tooltip goes under File Toolbar, there's an issue with z-index stuff
				{kind: "onyx.Tooltip", content: "Remove Project..."}
			]}
		]},
		{kind: "enyo.Scroller", components: [
			{kind: "enyo.Repeater", controlParentName: "client", fit: true, name: "projectList", onSetupItem: "projectListSetupItem", ontap: "projectListTap", components: [
				{kind: "ProjectList.Project", name: "item", classes: "enyo-children-inline ares_projectView_projectList_item"}
			]}
		]},
		{name: "removeProjectPopup", kind: "ProjectDeletePopup", onConfirmDeleteProject: "confirmRemoveProject"},
		{name: "errorPopup", kind: "Ares.ErrorPopup", msg: "unknown error"},
		{kind: "AccountsConfigurator"},
		{kind: "Signals", onServicesChange: "handleServicesChange"}
	],
	selected: null,
	create: function() {
		this.inherited(arguments);
		this.$.projectList.setCount(Ares.WorkspaceData.length);
		Ares.WorkspaceData.on("add remove reset", enyo.bind(this, this.projectCountChanged));
		} else
	},
	projectCountChanged: function() {
		var count = Ares.WorkspaceData.length;
		this.$.projectList.setCount(count);
		this.$.projectList.render();
		this.doProjectRemoved();		// To reset the Harmonia view
	},
	addProject: function(name, folderId, service) {
		var serviceId = service.getConfig().id || "";
		if (serviceId === "") {
			throw new Error("Cannot add a project in service=" + service);
		}
		var known = Ares.WorkspaceData.get(name);
			}
		if (known) {
			this.debug && this.log("Skipped project " + name + " as it is already listed") ;
		} else {
			Ares.WorkspaceData.createProject(name, folderId, serviceId);
		var old = this.selected.getProjectName;
		}
	},
	removeProjectAction: function(inSender, inEvent) {
		var popup = this.$.removeProjectPopup;
		if (this.selected) {
			popup.setName("Delete project '" + this.selected.getProjectName() + "' ?");
			popup.$.nukeFiles.setValue(false) ;
			popup.show();
		}
	},
	confirmRemoveProject: function(inSender, inEvent) {
		// use file system service to remove project files (which behaves like a 'rm -rf')
		// once done,  call removeSelectedProjectData to mop up the remains.
		var project, nukeFiles ;
		if (this.selected) {
			project = Ares.WorkspaceData.at(this.selected.index);
			nukeFiles = this.$.removeProjectPopup.$.nukeFiles.getValue() ;
			this.debug && this.log("removing project" +  project.getName() + ( nukeFiles ? " and its files" : "" )) ;
			this.debug && this.log(project);
			if (nukeFiles) {
				project.service.remove( project.folderId )
					.response(this, function(){this.removeSelectedProjectData();})
					.error(this, function(inError){
						this.showErrorPopup("Error removing files of project " + project.name + ": " + inError);
					}) ;
			}
			else {
				this.removeSelectedProjectData() ;
			}
		}
	},
	removeSelectedProjectData: function() {
		if (this.selected) {
			// remove the project from list of project config
			var name = Ares.WorkspaceData.at(this.selected.index).getName();
			Ares.WorkspaceData.removeProject(name);
			this.selected = null;
			this.doProjectRemoved();
		}
	},
	projectListSetupItem: function(inSender, inEvent) {
		var project = Ares.WorkspaceData.at(inEvent.index);
		var item = inEvent.item;
		// setup the controls for this item.
		item = item.$.item;
		item.setProjectName(project.getName());
		item.setIndex(inEvent.index);
	},
	projectListTap: function(inSender, inEvent) {
		var project, msg, service;
		// Un-highlight former selection, if any
		if (this.selected) {
			this.selected.removeClass("ares_projectView_projectList_item_selected");
		}

		// Highlight the new project item
		if (inEvent.originator.kind === 'ProjectList.Project') {
			this.selected = inEvent.originator;
		} else {
			this.selected = inEvent.originator.owner;
		}
		this.selected.addClass("ares_projectView_projectList_item_selected");

		project = Ares.WorkspaceData.at(inEvent.index);
		service = ServiceRegistry.instance.resolveServiceId(project.getServiceId());
		if (service !== undefined) {
			project.setService(service);
			this.doProjectSelected({project: project});
		} else {
			// ...otherwise let
			msg = "Service " + project.getServiceId() + " not found";
			this.showErrorPopup(msg);
			this.error(msg);
		}
	},
	showAccountConfigurator: function() {
		this.$.accountsConfigurator.show();
	},
	aresMenuItemSelected: function(inSender, inEvent) {
		if (this.debug) this.log("sender:", inSender, ", event:", inEvent);
		if (typeof this[inEvent.selected.value] === 'function') {
			this[inEvent.selected.value]();
		}
	},
	showErrorPopup : function(msg) {
		this.$.errorPopup.setErrorMsg(msg);
		this.$.errorPopup.show();
	},
	stringifyReplacer: function(key, value) {
		if (key === "originator") {
			return undefined;	// Exclude
		}
		return value;	// Accept
	},
	statics: {
		underTest: false
	}
});

enyo.kind({
	name: "ProjectList.Project",
	published: {
		projectName: "",
		index: -1
	},
	components: [
		{name: "name"}
	],
	projectNameChanged: function(inOldValue) {
		this.$.name.setContent(this.projectName);
	}
});

enyo.kind({
	name: "ProjectDeletePopup",
	kind: "Ares.ActionPopup",
	components: [
		{kind: "Control", tag: "h3", content: " ", name: "title"},
		{kind: "Control", tag: "br"},
		{kind: "onyx.Checkbox", checked: false, name: "nukeFiles"},
		{kind: "Control", tag: "span", style: "padding: 0 4px; vertical-align: middle;", content: "also delete files", fit: true},
		{kind: "FittableColumns", name: "buttons", components: [
			{kind: "onyx.Button", classes: "onyx-negative", content: "Cancel", name: "cancelButton", ontap: "actionCancel"},
			{kind: "onyx.Button", classes: "onyx-affirmative", content: "Delete", name: "actionButton", ontap: "actionConfirm"}
		]}
	]
});
<commit_msg>ENYO-992: removed merge artifacts<commit_after>/**
 * This kind provides:
 * - the project toolbars (with create .. delete)
 * - the project list
 *
 * The project list is a simple kind that only holds project names. It does not
 * hold project objects or kinds.
 */
enyo.kind({
	name: "ProjectList",
	classes: "enyo-unselectable ares_projectList",
	events: {
		onCreateProject: "",
		onProjectSelected: "",
		onScanProject: "",
		onProjectRemoved: "",
		onModifySettings: "",
		onPhonegapBuild: ""
	},
	handlers: {
	},
	debug: false,
	components: [
		{kind: "onyx.MoreToolbar", classes: "onyx-menu-toolbar ares_harmonia_toolBar ares-no-padding", isContainer: true, name: "toolbar", components: [
			{kind: "onyx.MenuDecorator", onSelect: "aresMenuItemSelected", components: [
				{content: "Ares"},
				{kind: "onyx.Menu", components: [
					{value: "showAccountConfigurator", components: [
						{kind: "onyx.IconButton", src: "$project-view/assets/images/ares_accounts.png"},
						{content: "Accounts..."}
					]},
					{classes: "onyx-menu-divider"},
					{content: "Properties..."}
				]}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", src: "$project-view//assets/images/project_view_new.png", onclick: "doCreateProject"},
				{kind: "onyx.Tooltip", content: "Create or Import Project..."}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", src: "$project-view//assets/images/project_view_build.png", onclick: "doPhonegapBuild"},
				{kind: "onyx.Tooltip", content: "Phonegap build"}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", src: "$project-view//assets/images/project_preview.png", onclick: "doPreview"},
				{kind: "onyx.Tooltip", content: "Preview Project..."}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", classes: "ares-scale-background",
				 src: "$project-view/assets/images/project_settings.png", onclick: "doModifySettings"},
				{kind: "onyx.Tooltip", content: "Settings..."}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", src: "$project-view//assets/images/project_view_edit.png", onclick: "doScanProject"},
				{kind: "onyx.Tooltip", content: "Scan for Projects..."}
			]},
			{kind: "onyx.TooltipDecorator", components: [
				{kind: "onyx.IconButton", src: "$project-view//assets/images/project_view_delete.png", onclick: "removeProjectAction"},
				// FIXME: tooltip goes under File Toolbar, there's an issue with z-index stuff
				{kind: "onyx.Tooltip", content: "Remove Project..."}
			]}
		]},
		{kind: "enyo.Scroller", components: [
			{kind: "enyo.Repeater", controlParentName: "client", fit: true, name: "projectList", onSetupItem: "projectListSetupItem", ontap: "projectListTap", components: [
				{kind: "ProjectList.Project", name: "item", classes: "enyo-children-inline ares_projectView_projectList_item"}
			]}
		]},
		{name: "removeProjectPopup", kind: "ProjectDeletePopup", onConfirmDeleteProject: "confirmRemoveProject"},
		{name: "errorPopup", kind: "Ares.ErrorPopup", msg: "unknown error"},
		{kind: "AccountsConfigurator"},
		{kind: "Signals", onServicesChange: "handleServicesChange"}
	],
	selected: null,
	create: function() {
		this.inherited(arguments);
		this.$.projectList.setCount(Ares.WorkspaceData.length);
		Ares.WorkspaceData.on("add remove reset", enyo.bind(this, this.projectCountChanged));
	},
	projectCountChanged: function() {
		var count = Ares.WorkspaceData.length;
		this.$.projectList.setCount(count);
		this.$.projectList.render();
		this.doProjectRemoved();		// To reset the Harmonia view
	},
	addProject: function(name, folderId, service) {
		var serviceId = service.getConfig().id || "";
		if (serviceId === "") {
			throw new Error("Cannot add a project in service=" + service);
		}
		var known = Ares.WorkspaceData.get(name);

		if (known) {
			this.debug && this.log("Skipped project " + name + " as it is already listed") ;
		} else {
			Ares.WorkspaceData.createProject(name, folderId, serviceId);
		}
	},
	removeProjectAction: function(inSender, inEvent) {
		var popup = this.$.removeProjectPopup;
		if (this.selected) {
			popup.setName("Delete project '" + this.selected.getProjectName() + "' ?");
			popup.$.nukeFiles.setValue(false) ;
			popup.show();
		}
	},
	confirmRemoveProject: function(inSender, inEvent) {
		// use file system service to remove project files (which behaves like a 'rm -rf')
		// once done,  call removeSelectedProjectData to mop up the remains.
		var project, nukeFiles ;
		if (this.selected) {
			project = Ares.WorkspaceData.at(this.selected.index);
			nukeFiles = this.$.removeProjectPopup.$.nukeFiles.getValue() ;
			this.debug && this.log("removing project" +  project.getName() + ( nukeFiles ? " and its files" : "" )) ;
			this.debug && this.log(project);
			if (nukeFiles) {
				project.service.remove( project.folderId )
					.response(this, function(){this.removeSelectedProjectData();})
					.error(this, function(inError){
						this.showErrorPopup("Error removing files of project " + project.name + ": " + inError);
					}) ;
			}
			else {
				this.removeSelectedProjectData() ;
			}
		}
	},
	removeSelectedProjectData: function() {
		if (this.selected) {
			// remove the project from list of project config
			var name = Ares.WorkspaceData.at(this.selected.index).getName();
			Ares.WorkspaceData.removeProject(name);
			this.selected = null;
			this.doProjectRemoved();
		}
	},
	projectListSetupItem: function(inSender, inEvent) {
		var project = Ares.WorkspaceData.at(inEvent.index);
		var item = inEvent.item;
		// setup the controls for this item.
		item = item.$.item;
		item.setProjectName(project.getName());
		item.setIndex(inEvent.index);
	},
	projectListTap: function(inSender, inEvent) {
		var project, msg, service;
		// Un-highlight former selection, if any
		if (this.selected) {
			this.selected.removeClass("ares_projectView_projectList_item_selected");
		}

		// Highlight the new project item
		if (inEvent.originator.kind === 'ProjectList.Project') {
			this.selected = inEvent.originator;
		} else {
			this.selected = inEvent.originator.owner;
		}
		this.selected.addClass("ares_projectView_projectList_item_selected");

		project = Ares.WorkspaceData.at(inEvent.index);
		service = ServiceRegistry.instance.resolveServiceId(project.getServiceId());
		if (service !== undefined) {
			project.setService(service);
			this.doProjectSelected({project: project});
		} else {
			// ...otherwise let
			msg = "Service " + project.getServiceId() + " not found";
			this.showErrorPopup(msg);
			this.error(msg);
		}
	},
	showAccountConfigurator: function() {
		this.$.accountsConfigurator.show();
	},
	aresMenuItemSelected: function(inSender, inEvent) {
		if (this.debug) this.log("sender:", inSender, ", event:", inEvent);
		if (typeof this[inEvent.selected.value] === 'function') {
			this[inEvent.selected.value]();
		}
	},
	showErrorPopup : function(msg) {
		this.$.errorPopup.setErrorMsg(msg);
		this.$.errorPopup.show();
	},
	stringifyReplacer: function(key, value) {
		if (key === "originator") {
			return undefined;	// Exclude
		}
		return value;	// Accept
	},
	statics: {
		underTest: false
	}
});

enyo.kind({
	name: "ProjectList.Project",
	published: {
		projectName: "",
		index: -1
	},
	components: [
		{name: "name"}
	],
	projectNameChanged: function(inOldValue) {
		this.$.name.setContent(this.projectName);
	}
});

enyo.kind({
	name: "ProjectDeletePopup",
	kind: "Ares.ActionPopup",
	components: [
		{kind: "Control", tag: "h3", content: " ", name: "title"},
		{kind: "Control", tag: "br"},
		{kind: "onyx.Checkbox", checked: false, name: "nukeFiles"},
		{kind: "Control", tag: "span", style: "padding: 0 4px; vertical-align: middle;", content: "also delete files", fit: true},
		{kind: "FittableColumns", name: "buttons", components: [
			{kind: "onyx.Button", classes: "onyx-negative", content: "Cancel", name: "cancelButton", ontap: "actionCancel"},
			{kind: "onyx.Button", classes: "onyx-affirmative", content: "Delete", name: "actionButton", ontap: "actionConfirm"}
		]}
	]
});
<|endoftext|>


<commit_before><commit_msg>minor style fixes<commit_after><|endoftext|>