<commit_before>Array.prototype.fill = function(value) {
    var i = this.length;
    while (i-- > 0) {
        this[i] = value;
    }
}

function MineSweeper(width, height) {
    this.width = width;
    this.height = height;
    this.fieldCount = width*height;
    this.tileSize = 36;
    this.mineField = [];
    this.mineCounters = [];
    this.mineCount = 10;
    this.playing = false
    this.buttonsDown = 0;
    var self = this;

    this.checkWin = function () {
        if (this.playing == false) return false;
        for (var i = 0; i < height; ++i) {
            for (var j = 0; j < width; ++j) {
                var elem = document.getElementById(j+","+i);
                if (this.mineField[j][i] == 'mine') {
                    if (elem.className != 'flag') {
                        return false;
                    }
                } else
                if (elem.className == 'none') {
                    return false;
                }
            }
        }
        return true;
    }

    var fill = function () {
        var board = document.querySelector(".board");
        while(board.hasChildNodes()) board.removeChild(board.firstChild);
        this.mineField = [];
        this.mineCounters = new Array(this.height);
        var mines = 0;
        for (var i = 0; i < height; ++i) {
            this.mineCounters[i] = new Array(this.width);
            this.mineCounters[i].fill(0);

        }
        for (var i = 0; i < height; ++i) {
            this.mineField.push([]);
            this.mineCounters.push([]);
            var mf = this.mineField[this.mineField.length-1];
            for (var j = 0; j < width; ++j) {
                var elem = 'none';
                if (mines < this.mineCount && Math.random()*this.fieldCount <= this.mineCount) {
                    elem = 'mine';
                    mines++;
                    this.fillMineCount(i, j);
                }
                this.mineCounters[this.mineCounters.length - 1] = 0;
                mf.push(elem);
                var div = document.createElement("div");
                div.id = i+","+j;
                if (elem == 'mine') {
                    div.style.borderColor = 'red';
                }
//                div.className = elem;
                div.className = 'none';
                div.addEventListener('mousedown', this.clickHandler,false);
                div.addEventListener('mouseup', this.mouseUp,false);
                board.appendChild(div);
            }
        }
        document.querySelector(".score").innerHTML = "";
        document.querySelector(".header > .mineCount").innerHTML = mines;
        board.style.width = (this.width*this.tileSize)+ 'px';
        board.style.height = (this.height*this.tileSize)+ 'px';

    }

    this.clickHandler = function(event) {
        var coords = event.target.id.split(',');
        if (event.button == 0) {
            self.buttons |= 1;
        }
        if (event.button == 2) {
            self.buttons |= 2;
        }
        if (!self.playing) {
            event.preventDefault();
            return;
        }
        if (self.buttons == 2) {
            if (self.buttons == 2) {
                if (event.target.className == 'flag') {
                    event.target.className = 'none';
                } else {
                    event.target.className = 'flag';
                }
            }
        }
        if (self.buttons == 1) {
            if (event.target.className == "flag") {
                return false;
            }
            if (self.mineField[coords[0]][coords[1]] == 'mine') {
                document.querySelector(".score").innerHTML = "GAME OVER!";
                self.showMines();
                self.playing = false;
            } else {
                event.target.className = "visited";
                event.target.dataset.number = self.mineCounters[coords[0]][coords[1]];
                if (event.target.dataset.number > 0) {
                    event.target.className = "number";
                }
            }

        }
        if (self.buttons == 3) {
            if (event.target.className != 'none') {
        }
        }
        if (self.checkWin()) {
            document.querySelector(".score").innerHTML = "YOU WON";
            this.playing = false;
        }
    }
    this.mouseUp = function (event) {
        if (event.button == 0) {
            self.buttons ^= 1;
        }
        if (event.button == 2) {
            self.buttons ^= 2;
        }
    }

    this.revealAll = function(x, y) {
    //        var elem = document.getElementById(x+","+y);
    //        if (elem.className == 'none' && this.mineField[x][y] == 'none') {
    //            event.target.className = "visited";
    //            event.target.dataset.number = self.mineCounters[coords[0]][coords[1]];
    //            if (event.target.dataset.number > 0) {
    //                event.target.className = "number";
    //            }
    //        }
    //        if (x > 0) {
    //
    //        }
    //        if (x < this.width) {
    //
    //        }
    //        if (y > 0) {
    //
    //        }
    //        if (y < this.height) {
    //    }
    }

    this.showMines = function () {
        for (var i = 0; i < height; ++i) {
            for (var j = 0; j < width; ++j) {
                if (this.mineField[j][i] == 'mine') {
                    document.getElementById(j+","+i).className = 'mine';
                }
            }
        }
    }

    this.fillMineCount = function (x, y) {
        if (x > 0) {
            this.mineCounters[x-1][y-1]++;
            this.mineCounters[x-1][y]++;
            this.mineCounters[x-1][y+1]++;
        }
        this.mineCounters[x][y-1]++;
        this.mineCounters[x][y+1]++;
        if (x < this.width) {
            this.mineCounters[x+1][y-1]++;
            this.mineCounters[x+1][y]++;
            this.mineCounters[x+1][y+1]++;
        }
    }

    this.newGame = function () {
        fill.call(this);
        this.playing = true;

    }
    this.newGame();

}

<commit_msg>removed mine outlining for debug<commit_after>Array.prototype.fill = function(value) {
    var i = this.length;
    while (i-- > 0) {
        this[i] = value;
    }
}

function MineSweeper(width, height) {
    this.width = width;
    this.height = height;
    this.fieldCount = width*height;
    this.tileSize = 36;
    this.mineField = [];
    this.mineCounters = [];
    this.mineCount = 10;
    this.playing = false
    this.buttonsDown = 0;
    this.debug = false;
    var self = this;

    this.checkWin = function () {
        if (this.playing == false) return false;
        for (var i = 0; i < height; ++i) {
            for (var j = 0; j < width; ++j) {
                var elem = document.getElementById(j+","+i);
                if (this.mineField[j][i] == 'mine') {
                    if (elem.className != 'flag') {
                        return false;
                    }
                } else
                if (elem.className == 'none') {
                    return false;
                }
            }
        }
        return true;
    }

    var fill = function () {
        var board = document.querySelector(".board");
        while(board.hasChildNodes()) board.removeChild(board.firstChild);
        this.mineField = [];
        this.mineCounters = new Array(this.height);
        var mines = 0;
        for (var i = 0; i < height; ++i) {
            this.mineCounters[i] = new Array(this.width);
            this.mineCounters[i].fill(0);

        }
        for (var i = 0; i < height; ++i) {
            this.mineField.push([]);
            this.mineCounters.push([]);
            var mf = this.mineField[this.mineField.length-1];
            for (var j = 0; j < width; ++j) {
                var elem = 'none';
                if (mines < this.mineCount && Math.random()*this.fieldCount <= this.mineCount) {
                    elem = 'mine';
                    mines++;
                    this.fillMineCount(i, j);
                }
                this.mineCounters[this.mineCounters.length - 1] = 0;
                mf.push(elem);
                var div = document.createElement("div");
                div.id = i+","+j;
                if (self.debug && elem == 'mine') {
                    div.style.borderColor = 'red';
                }
//                div.className = elem;
                div.className = 'none';
                div.addEventListener('mousedown', this.clickHandler,false);
                div.addEventListener('mouseup', this.mouseUp,false);
                board.appendChild(div);
            }
        }
        document.querySelector(".score").innerHTML = "";
        document.querySelector(".header > .mineCount").innerHTML = mines;
        board.style.width = (this.width*this.tileSize)+ 'px';
        board.style.height = (this.height*this.tileSize)+ 'px';

    }

    this.clickHandler = function(event) {
        var coords = event.target.id.split(',');
        if (event.button == 0) {
            self.buttons |= 1;
        }
        if (event.button == 2) {
            self.buttons |= 2;
        }
        if (!self.playing) {
            event.preventDefault();
            return;
        }
        if (self.buttons == 2) {
            if (self.buttons == 2) {
                if (event.target.className == 'flag') {
                    event.target.className = 'none';
                } else {
                    event.target.className = 'flag';
                }
            }
        }
        if (self.buttons == 1) {
            if (event.target.className == "flag") {
                return false;
            }
            if (self.mineField[coords[0]][coords[1]] == 'mine') {
                document.querySelector(".score").innerHTML = "GAME OVER!";
                self.showMines();
                self.playing = false;
            } else {
                event.target.className = "visited";
                event.target.dataset.number = self.mineCounters[coords[0]][coords[1]];
                if (event.target.dataset.number > 0) {
                    event.target.className = "number";
                }
            }

        }
        if (self.buttons == 3) {
            if (event.target.className != 'none') {
        }
        }
        if (self.checkWin()) {
            document.querySelector(".score").innerHTML = "YOU WON";
            this.playing = false;
        }
    }
    this.mouseUp = function (event) {
        if (event.button == 0) {
            self.buttons ^= 1;
        }
        if (event.button == 2) {
            self.buttons ^= 2;
        }
    }

    this.revealAll = function(x, y) {
    //        var elem = document.getElementById(x+","+y);
    //        if (elem.className == 'none' && this.mineField[x][y] == 'none') {
    //            event.target.className = "visited";
    //            event.target.dataset.number = self.mineCounters[coords[0]][coords[1]];
    //            if (event.target.dataset.number > 0) {
    //                event.target.className = "number";
    //            }
    //        }
    //        if (x > 0) {
    //
    //        }
    //        if (x < this.width) {
    //
    //        }
    //        if (y > 0) {
    //
    //        }
    //        if (y < this.height) {
    //    }
    }

    this.showMines = function () {
        for (var i = 0; i < height; ++i) {
            for (var j = 0; j < width; ++j) {
                if (this.mineField[j][i] == 'mine') {
                    document.getElementById(j+","+i).className = 'mine';
                }
            }
        }
    }

    this.fillMineCount = function (x, y) {
        if (x > 0) {
            this.mineCounters[x-1][y-1]++;
            this.mineCounters[x-1][y]++;
            this.mineCounters[x-1][y+1]++;
        }
        this.mineCounters[x][y-1]++;
        this.mineCounters[x][y+1]++;
        if (x < this.width) {
            this.mineCounters[x+1][y-1]++;
            this.mineCounters[x+1][y]++;
            this.mineCounters[x+1][y+1]++;
        }
    }

    this.newGame = function () {
        fill.call(this);
        this.playing = true;

    }
    this.newGame();

}

<|endoftext|>


<commit_before>"use strict";

angular.module('arethusa.core').directive('navbarButtons', function() {
  return {
    restrict: 'A',
    replace: true,
    link: function(scope, element, attrs) {
      scope.$watch('windowWidth', function(newVal, oldVal) {
        var coll = newVal > 780 ? '' : '_collapsed';
        scope.bTemplate = 'templates/arethusa.core/navbar_buttons' + coll + '.html';
      });
    },
    template: '
'
  };
});
<commit_msg>Collapse buttons a little sooner<commit_after>"use strict";

angular.module('arethusa.core').directive('navbarButtons', function() {
  return {
    restrict: 'A',
    replace: true,
    link: function(scope, element, attrs) {
      scope.$watch('windowWidth', function(newVal, oldVal) {
        var coll = newVal > 800 ? '' : '_collapsed';
        scope.bTemplate = 'templates/arethusa.core/navbar_buttons' + coll + '.html';
      });
    },
    template: '
'
  };
});
<|endoftext|>


<commit_before>'use strict';

var page = require('../pages/applications.js');
var newApplicationModal = require('../pages/newApplicationModal.js');
var Q = require('q');

describe('applications view', function() {
  beforeEach(function() {
    this.openMenu = function() {
      browser.get(page.url);
      return page.menu.click();
    };
  });

  it('should redirect to /applications from /', function() {
    browser.get('/');
    expect(page.header.getText()).toEqual('Applications');
  });

  describe('the Actions menu', function() {

    describe('Create Application', function () {
      it('is accessed from the Actions menu', function(done) {
        this.openMenu().then(function() {
          done();
        });
      });

      it('launches the Create Application modal', function(done) {
        browser.wait(page.createApplicationMenuItem.isDisplayed,
          undefined,
          'Failed to open the Actions menu').then(function() {
          page.createApplicationMenuItem.click().then(function() {
            browser.wait(newApplicationModal.header.isDisplayed,
              undefined,
              'Failed to launch the new application modal').then(function() {
                done(); // done() fails when provided with an argument :(
              }, console.log);
          }, console.log);
        }, console.log);
      });

      it('takes a name, email, description and account', function(done) {
        Q.all([
          newApplicationModal.prod.click(),
        ]).then(function() {
          expect(newApplicationModal.submit.getAttribute('disabled')).not.toBe(null);
        });

        Q.all([
          newApplicationModal.name.sendKeys('deck-e2e-test'),
          newApplicationModal.description.sendKeys('a deck test'),
          newApplicationModal.email.sendKeys('delivery-engineering+deck-e2e@netflix.com'),
          newApplicationModal.prod.click(),
        ]).then(function() {
          expect(newApplicationModal.submit.getAttribute('disabled')).toBe(null);
          done();
        }, console.log);
      });

      it('creates the application', function(done) {
        // TODO: application creation is currently busted in prestaging
        newApplicationModal.submit.click().then(function() {
          done();
        }, console.log);
      });
    });
  });
});
<commit_msg>append browserName to created objects<commit_after>'use strict';

var page = require('../pages/applications.js');
var newApplicationModal = require('../pages/newApplicationModal.js');
var Q = require('q');

describe('applications view', function() {
  var browserName;

  beforeEach(function(done) {
    browser.getCapabilities().then(function(capabilities) {
      browserName = capabilities.caps_.browserName;
      done();
    });
  });

  beforeEach(function() {
    this.openMenu = function() {
      browser.get(page.url);
      return page.menu.click();
    };
  });

  it('should redirect to /applications from /', function() {
    browser.get('/');
    expect(page.header.getText()).toEqual('Applications');
  });

  describe('the Actions menu', function() {

    describe('Create Application', function () {
      it('is accessed from the Actions menu', function(done) {
        this.openMenu().then(function() {
          done();
        });
      });

      it('launches the Create Application modal', function(done) {
        browser.wait(page.createApplicationMenuItem.isDisplayed,
          undefined,
          'Failed to open the Actions menu').then(function() {
          page.createApplicationMenuItem.click().then(function() {
            browser.wait(newApplicationModal.header.isDisplayed,
              undefined,
              'Failed to launch the new application modal').then(function() {
                done(); // done() fails when provided with an argument :(
              }, console.log);
          }, console.log);
        }, console.log);
      });

      it('takes a name, email, description and account', function(done) {
        Q.all([
          newApplicationModal.prod.click(),
        ]).then(function() {
          expect(newApplicationModal.submit.getAttribute('disabled')).not.toBe(null);
        });

        Q.all([
          newApplicationModal.name.sendKeys('deck-e2e-test-'+browserName),
          newApplicationModal.description.sendKeys('a deck test'),
          newApplicationModal.email.sendKeys('delivery-engineering+deck-e2e@netflix.com'),
          newApplicationModal.prod.click(),
        ]).then(function() {
          expect(newApplicationModal.submit.getAttribute('disabled')).toBe(null);
          done();
        }, console.log);
      });

      it('creates the application', function(done) {
        // TODO: application creation is currently busted in prestaging
        newApplicationModal.submit.click().then(function() {
          done();
        }, console.log);
      });
    });
  });
});
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var SVGO = require('svgo');

// Initialize what will be used for automatic text measurement.
var Canvas = require('canvas');
var canvasElement = new Canvas(0, 0);   // Width and height are irrelevant.
var canvasContext = canvasElement.getContext('2d');
var CanvasFont = Canvas.Font;
var color = require('onecolor');
try {
  var opensans = new CanvasFont('Verdana',
      path.join(__dirname, 'Verdana.ttf'));
  canvasContext.addFont(opensans);
} catch(e) {}
canvasContext.font = '11px Verdana, "DejaVu Sans"';

// Template crafting action below.
var dot = require('dot');
var colorscheme = require(path.join(__dirname, 'colorscheme.json'));
var template = fs.readFileSync(path.join(__dirname, 'template.svg'));
var imageTemplate = dot.template(''+template);

function optimize(string, callback) {
  var svgo = new SVGO();
  svgo.optimize(string, callback);
}

function makeImage(data, cb) {
   data.colorscheme = data.colorscheme.split(",");
  if (data.colorscheme) {
    data.colorA = one.color(data.colorscheme[0]).hex();
    data.colorB = one.color(data.colorscheme[data.colorscheme - 1]).hex();
  }
  data.widths = [
    (canvasContext.measureText(data.text[0]).width|0) + 10,
    (canvasContext.measureText(data.text[1]).width|0) + 10,
  ];
  var result = imageTemplate(data);
  // Run the SVG through SVGO.
  optimize(result, function(object) { cb(object.data); });
}

module.exports = makeImage;
<commit_msg>Patching minor glitches in my code<commit_after>var fs = require('fs');
var path = require('path');
var SVGO = require('svgo');

// Initialize what will be used for automatic text measurement.
var Canvas = require('canvas');
var canvasElement = new Canvas(0, 0);   // Width and height are irrelevant.
var canvasContext = canvasElement.getContext('2d');
var CanvasFont = Canvas.Font;
var color = require('onecolor');
try {
  var opensans = new CanvasFont('Verdana',
      path.join(__dirname, 'Verdana.ttf'));
  canvasContext.addFont(opensans);
} catch(e) {}
canvasContext.font = '11px Verdana, "DejaVu Sans"';

// Template crafting action below.
var dot = require('dot');
var colorscheme = require(path.join(__dirname, 'colorscheme.json'));
var template = fs.readFileSync(path.join(__dirname, 'template.svg'));
var imageTemplate = dot.template(''+template);

function optimize(string, callback) {
  var svgo = new SVGO();
  svgo.optimize(string, callback);
}

function makeImage(data, cb) {
   data.colorscheme = data.colorscheme.split(",");
  if (data.colorscheme) {
    data.colorA = color(data.colorscheme[0]).hex();
    data.colorB = color(data.colorscheme[data.colorscheme - 1]).hex();
  }
  data.widths = [
    (canvasContext.measureText(data.text[0]).width|0) + 10,
    (canvasContext.measureText(data.text[1]).width|0) + 10,
  ];
  var result = imageTemplate(data);
  // Run the SVG through SVGO.
  optimize(result, function(object) { cb(object.data); });
}

module.exports = makeImage;
<|endoftext|>


<commit_before>export const STATE_UNAVAILABLE = 0 // component is loading (eg: getting data) or busy (eg: submitting data)
export const STATE_DEFAULT = 1 // initial, loaded state, eg: displaying a form
export const STATE_ERROR = 2 // component is not happy, ie: form validation (not .js errors)
export const STATE_SUCCESS = 3 // component is happy, ie: form submitted
export const STATE_ERROR_BOUNDARY = 4 // component has triggered a .js error or is completely messed up
<commit_msg>New constants: page, size, lang, col, type<commit_after>export const STATE_UNAVAILABLE = 0 // component is loading (eg: getting data) or busy (eg: submitting data)
export const STATE_DEFAULT = 1 // initial, loaded state, eg: displaying a form
export const STATE_ERROR = 2 // component is not happy, ie: form validation (not .js errors)
export const STATE_SUCCESS = 3 // component is happy, ie: form submitted
export const STATE_ERROR_BOUNDARY = 4 // component has triggered a .js error or is completely messed up

export const DEFAULT_PAGE = 1
export const DEFAULT_PAGE_SIZE = 100
export const DEFAULT_LANGUAGE = 'english'
export const DEFAULT_SORT_COL = 'dc:title'
export const DEFAULT_SORT_TYPE = 'asc'
<|endoftext|>


<commit_before>$(function() {
  var currentIndex = 0;
  var scrollOffset = -100;
  var searchMode = false;

  var targetLi = function(index) {
    return $($('#clips li')[index]);
  };

  var toggleClip = function(index) {
    var target = targetLi(index);
    $('.text', target).toggle();
    $.scrollTo(target, {offset: {left: 0, top: scrollOffset}});
  };

  var toggleAllClips = function() {
    if ($('.text:hidden').length > 0) {
      openAllClips();
    } else {
      closeAllClips();
    }
    $.scrollTo(targetLi(currentIndex), {offset: {top: scrollOffset}});
  };

  var openAllClips = function() {
    $('.text:hidden').show();
  };

  var closeAllClips = function(index) {
    $('.text:visible').hide();
  };

  var moveTo = function(index) {
    if (index < 0 || index >= $('#clips li').length) {
      return;
    }

    var oldIndex = currentIndex;
    currentIndex = index;

    targetLi(oldIndex).removeClass('selected');

    var target = targetLi(currentIndex)
    target.addClass('selected');
    $.scrollTo(target, {offset: {top: scrollOffset}});
  };

  $('input#search').focus(function(){
    searchMode = true;
  });

  $('input#search').blur(function(){
    searchMode = false;
  });

  $(window).keydown(function(e){
    console.log(e.keyCode);

    if (searchMode) {
      if (e.keyCode == 27) { // 'esc'
        $('input#search').blur();
        moveTo(currentIndex);
      }
    } else {
      if (e.keyCode == 74) { // 'j'
        moveTo(currentIndex + 1);
      }
      if (e.keyCode == 75) { // 'k'
        moveTo(currentIndex - 1);
      }

      if (e.keyCode == 191) { // '/'
        $('input#search').focus();
        e.preventDefault();
      }

      if (e.keyCode == 79) { // 'o'
        if (e.shiftKey) {
          toggleAllClips();
        } else {
          toggleClip(currentIndex);
        }
      }
    }
  });

  var search = function(query) {
  };

  var searchQuery = '';
  var searching = false;
  $.timer(500, function (timer) {
    if (searching) {
      return;
    }

    var inputText = $('input#search').val();
    if (inputText != searchQuery) {
      setTimeout(function() {
        var newInputText = $('input#search').val();
        if (inputText == newInputText) {
          searching = true;
          $('#loading').show();
          $.get('/search', {q: inputText}, function(data) {
            $('#clips').html(data);
            $('#loading').hide();
            searching = false;
          });
        }
      }, 100);
      searchQuery = inputText;
    }
  });

  moveTo(0);
});
<commit_msg>input#search に focus したときに select() するようにした<commit_after>$(function() {
  var currentIndex = 0;
  var scrollOffset = -100;
  var searchMode = false;

  var targetLi = function(index) {
    return $($('#clips li')[index]);
  };

  var toggleClip = function(index) {
    var target = targetLi(index);
    $('.text', target).toggle();
    $.scrollTo(target, {offset: {left: 0, top: scrollOffset}});
  };

  var toggleAllClips = function() {
    if ($('.text:hidden').length > 0) {
      openAllClips();
    } else {
      closeAllClips();
    }
    $.scrollTo(targetLi(currentIndex), {offset: {top: scrollOffset}});
  };

  var openAllClips = function() {
    $('.text:hidden').show();
  };

  var closeAllClips = function(index) {
    $('.text:visible').hide();
  };

  var moveTo = function(index) {
    if (index < 0 || index >= $('#clips li').length) {
      return;
    }

    var oldIndex = currentIndex;
    currentIndex = index;

    targetLi(oldIndex).removeClass('selected');

    var target = targetLi(currentIndex)
    target.addClass('selected');
    $.scrollTo(target, {offset: {top: scrollOffset}});
  };

  $('input#search').focus(function(){
    searchMode = true;
    $(this).select();
  });

  $('input#search').blur(function(){
    searchMode = false;
  });

  $(window).keydown(function(e){
    console.log(e.keyCode);

    if (searchMode) {
      if (e.keyCode == 27) { // 'esc'
        $('input#search').blur();
        moveTo(currentIndex);
      }
    } else {
      if (e.keyCode == 74) { // 'j'
        moveTo(currentIndex + 1);
      }
      if (e.keyCode == 75) { // 'k'
        moveTo(currentIndex - 1);
      }

      if (e.keyCode == 191) { // '/'
        $('input#search').focus();
        e.preventDefault();
      }

      if (e.keyCode == 79) { // 'o'
        if (e.shiftKey) {
          toggleAllClips();
        } else {
          toggleClip(currentIndex);
        }
      }
    }
  });

  var search = function(query) {
  };

  var searchQuery = '';
  var searching = false;
  $.timer(500, function (timer) {
    if (searching) {
      return;
    }

    var inputText = $('input#search').val();
    if (inputText != searchQuery) {
      setTimeout(function() {
        var newInputText = $('input#search').val();
        if (inputText == newInputText) {
          searching = true;
          $('#loading').show();
          $.get('/search', {q: inputText}, function(data) {
            $('#clips').html(data);
            $('#loading').hide();
            searching = false;
          });
        }
      }, 100);
      searchQuery = inputText;
    }
  });

  moveTo(0);
});
<|endoftext|>


<commit_before>; (function(){
  UT.Post = function(states){
    if(!states || !states.collections){
      throw new Error("ArgumentError", "Missing collections in state arguments");
    }
    // quicker than bind
    var self = this;

    // scoped properties

    var eventTypesBindings = {}; // handle event bindings for each event type
    var collectionStore = new UT.CollectionStore({
      data: states.collections,
      currentUserId: states.currentUserId,
      delegate: {
        save: function(name, items, callback) {
          UT.Expression._callAPI('collections.save', [name, items], callback);
        },
        authenticate: function(callback) {
          UT.Expression._callAPI('authenticate');
        }
      }
    });

    /**
     * Retrieve Parent Post Datas.
     *
     * This is available only during the first edition of a post
     * if the expression is created from another one.
     */
    var parentCollection;
    if(states.parentData){
      var items = [];
      for(var k in states.parentData){
        states.parentData[k]._key = k;
        items.push(states.parentData[k]);
      }
      parentCollection = new UT.Collection({
        data: {
          name: 'parent',
          items: items,
          count: items.length
        },
        delegate: {
          save: function(){
            throw new Error('ReadOnly collection');
          },
          authenticate: function(){
            throw new Error('ReadOnly collection');
          }
        },
        currentUserId: states.currentUserId
      });
    }

    // scoped functions

    var setNote = function(value){
      states.note = value;
      UT.Expression._callAPI('document.setNote', [states.note]);
      return value;
    };

    this.__defineGetter__('note', function() {
      return states.note;
    });
    this.__defineSetter__('note', function(value) {
      return setNote(value);
    });

    // Public Properties

    /**
     * context of the current editor
     * - player: true if in player mode
     * - editor: true if in editor mode
     * - thumbnail: true if in thumbnail mode
     * - privacy: one of 'private', 'unlisted' or 'public' the current state of the document publication.
     *
     * Those attributes should not be modified as the context is read-only.
     * read-only
     */
    var context = this.context = {
      player: false,
      editor: false,
      thumbnail: false,
      privacy: null
    };
    // set the proper context values
    if(states.mode == 'edit'){
      context.editor = true;
    } else if(states.mode == 'player'){
      context.player = true;
    }
    context.privacy = states.documentPrivacy;

    /**
     * Retrieve the public url of the document.
     *
     * read-only
     */
    var url = this.url = states.documentURL;

    /**
     * the expression outter dom node
     */
    var node = this.node = document.querySelector('.webdoc_expression_wrapper');
    if(!node){
      throw new Error('Missing wrapper node');
    }

    // Public Functions

    /**
     * Native text input for mobile.
     *
     * if options is passed, it might contains:
     * - value, the default value,
     * - max, the number of chars allowed,
     * - multiline, if true, allow for a multiline text input
     *
     * The callback will be passed the resulting string or null
     * if no value have been selected.
     *
     * XXX: Need to be supported on desktop as well
     */
    var textDialog = function(options, callback){
      if(typeof options == 'function'){
        callback = options;
        options = {};
      }
      UT.Expression._callAPI(
        'document.textInput',
        [options.value || null, options.max || null, options.multiline || false],
        callback
      );
    };

    var imageDialog = function(options, callback) {
      UT.Expression._callAPI(
        'medias.openImageChooser',
        [options],
        function(imageDescriptor) {
          var image = new UT.Image();
          image.init(imageDescriptor);
          callback.call(self, image);
      });
    };

    var soundDialog = function(options, callback) {
      UT.Expression._callAPI(
        'medias.openSoundChooser',
        [options],
        function(soundDecriptor) {
          var sound = new UT.Sound(soundDecriptor);
          callback.call(self, sound);
      });
      UT.Expression._callAPI('medias.openSoundChooser', [options], callback);
    };

    var videoDialog = function(options, callback) {
      UT.Expression._callAPI(
        'medias.openVideoChooser',
        [options],
        function(videoDescriptor) {
          var video = new UT.Video(videoDescriptor);
          callback.call(self, video);
      });
    };

    var cropDialog = function(options, callback) {
      if (options.image.descriptor) {
        options.image = options.image.descriptor;
      }
      UT.Expression._callAPI('medias.crop', [options],
        function(imageDescriptor) {
          var image = null;
          if (options.image.init) {
            options.image.init(imageDescriptor);
            image = options.image;
          }
          else {
            image = new UT.Image();
            image.init(imageDescriptor);
          }
          callback.call(self, image);
      });
    };

    // Handler for the various dialog type
    var dialogHandler = {
      text: textDialog,
      image: imageDialog,
      sound: soundDialog,
      video: videoDialog,
      crop: cropDialog
    };

    /**
     * Calls all fns in the list for a given eventName. Passes arguments
     * through to the caller.
     * @params {String} eventName The eventName to fire
     */
    var fire = this.fire = function(eventName) {
      var list = eventTypesBindings[eventName],
          promises = [],
          nextTrigger = 'after' + eventName.charAt(0).toUpperCase() + eventName.slice(1),
          listLength,
          listIndex,
          callbackFunction,
          callbackArgs,
          promise;

      // Nothing to fire
      if (!list) {
        return;
      }

      // We copy the list in case the original mutates while we're
      // looping over it. We take the arguments, lop of the first entry,
      // and pass the rest to the listeners when we call them.
      list = list.slice(0);
      listLength = list.length;
      listIndex = -1;
      callbackArgs = Array.prototype.slice.call(arguments, 1);
      callbackTarget = (callbackArgs.length !== 0 ? callbackArgs[0] : self);

      while (++listIndex < listLength) {
        callbackFunction = list[listIndex];
        promise = callbackFunction.apply(callbackTarget, callbackArgs);
        if(promise && typeof promise.then === 'function') {
          promises.push(promise);
        }
      }

      if(promises.length > 0) {
        when.all(promises).then(function() {
          fire(nextTrigger);
        });
      }
      else {
        fire(nextTrigger);
      }
    };

    /**
     * Register a listener for the given eventName.
     *
     * Available events:
     *
     * publish callback()
     * ------------------
     * Fired when the user wants to post his content. The callback
     * will be called on the Post instance and receive no argument.
     * It must be runnable synchronously as the current context
     * will be destroyed after all callbacks as been processed.
     *
     * scroll callback(ScrollDataEvent)
     * --------------------------------
     * Fired every time the visible part of the iframe
     * on the page change.
     * the callback is passed the scrolling data.
     * XXX what are the scrolling data?
     *
     * resize callback(ResizeEvent)
     * ----------------------------
     * Fired when the content box size changed. The callback is
     * called on the event and will be passed the ResizeEvent instance.
     *
     * media callback(MediaEvent)
     * --------------------------
     * Fired when a media is incoming from an external action
     * like a bookmarklet adding a resource or a drag and drop.
     * The callback is called on the event and will be passed a
     * the MediaEvent instance.
     */
    var on = this.on = function(eventName, callback) {
      var list = eventTypesBindings[eventName] || (eventTypesBindings[eventName] = []);

      // This callback is not a function
      if (typeof callback !== 'function') {
        return;
      }

      list.push(callback);
    };

    /**
     * Removes the given callback for the given eventName.
     *
     * @param {String} eventName
     * @param {Function} callback to remove
     */
    var off = this.off = function(eventName, callback) {
      var list = eventTypesBindings[eventName],
      l;

      // Nothing to unbind
      if (!list) {
        return;
      }

      // No function specified, so unbind all by removing the list
      if (!callback) {
        delete eventTypesBindings[eventName];
        return;
      }

      // Remove all occurences of this function from the list
      l = list ? list.indexOf(callback) : -1;

      while (l !== -1) {
        list.splice(l, 1);
        l = list.indexOf(callback);
      }
    };

    /**
     * Flag a post as being valid or not.
     * A valid document can be posted synchronously at any time.
     *
     * @param flag {boolean} if provided, set the current validity state.
     * @return {boolean} the current validity flag
     */
    var valid = this.valid = function(flag){
      if(flag !== undefined && flag != states.readyToPost ){
        states.readyToPost = !!flag;
        UT.Expression._callAPI('document.readyToPost', [states.readyToPost]);
      }
      return states.readyToPost;
    };

    /**
     * on the callback function to the scrollChanged event.
     * The function will receive the new scroll values.
     * @param {function} callback will be passed the new scrollvalues
     */
    var scrollChanged = this.scollChanged = function(callback) {
      on('scrollChanged', callback);
    };

    /**
     * on the callback function to the imageAdded event.
     * The function will receive the image and optional extraData param.
     * @param {Function} callback
     */
    var imageAdded = this.imageAdded = function(callback) {
      on('imageAdded', callback);
    };

    /**
     * Create the dialog of the given type using an options object and
     * retrieve the dialog output in the callback.
     */
    var dialog = this.dialog = function(type, options, callback) {
      if (callback === undefined && typeof(options) === 'function') {
        callback = options;
        options = {};
      }
      if(dialogHandler[type]){
        dialogHandler[type](options, callback);
      } else {
        throw new Error('InvalidArgument', 'unknown dialog type ' + type);
      }
    };

    /**
     * Ask the container to resize to the given parameters.
     *
     * The asynchronous result of this function can be listened on
     * the DOM node event.
     * size can be one of:
     * - {height: Number} an object containing the height in pixels
     * - {height: '133px'} an object continaing the height in a css string
     * - Number the height in pixel
     * - 'auto' automatically resize to the actual content size
     */
    var resize = this.resize = function(sizeInfo){
      var height;
      if(typeof sizeInfo === 'number'){ // 99
        height = sizeInfo;
      } else if(sizeInfo && sizeInfo == 'auto'){
        height = node.offsetHeight;
      } else if (sizeInfo && sizeInfo.height){
        if(typeof sizeInfo.height === "string" && sizeInfo.height.match &&
            sizeInfo.height.match(/^[0-9]+px$/)){ // {height: '99px'}
          height = sizeInfo.height.substring(0, sizeInfo.height.length-2);
        } else { // {height: 99}
          height = sizeInfo.height;
        }
      }
      UT.Expression._callAPI('container.resizeHeight', [height]);
    };

    var pushNavigation = this.pushNavigation = function(state, callback) {
      UT.Expression._callAPI('container.pushNavigation', [state], callback);
    };

    var popNavigation = this.popNavigation = function() {
      UT.Expression._callAPI('container.popNavigation');
    };

    var navigate = this.navigate = function(app) {
      var options = {};
      if (arguments.length >= 2) {
        options = arguments[1];
      }
      else if (arguments.length === 1) {
        options = app;
        app = 'browse';
      }
      var opt = {
        app : app,
        parameters : options
      };
      UT.Expression._callAPI('container.navigate', [opt]);
    };

    /**
     * Retrieve a collection given its name.
     *
     * The name can be any public collection defined in expression.json,
     * 'default' for the default collection (aka post.storage)
     * or parent for this post parent default collection (this is available
     * only during the first edition of a post if the expression is created
     * from another one.)
     *
     * @param {String} name the collection name
     */
    var collection = this.collection = function(name){
      if(name == 'parent'){
        return parentCollection || null;
      } else {
        return collectionStore.get(name);
      }
    };

    /**
     * Save data in all collections.
     */
    var save = this.save = function(){
      collectionStore.each(function(c){
        c.save();
      });
    };

    /**
     * The default, private collection
     */
    this.storage = collection('default');

    window.addEventListener('resize', function(){
      self.fire('resize', new UT.ResizeEvent(window.offsetWidth, window.offsetHeight));
    }, false);
  };
})();<commit_msg>Add User API<commit_after>; (function(){
  UT.Post = function(states){
    if(!states || !states.collections){
      throw new Error("ArgumentError", "Missing collections in state arguments");
    }
    // quicker than bind
    var self = this;

    // scoped properties

    var eventTypesBindings = {}; // handle event bindings for each event type
    var collectionStore = new UT.CollectionStore({
      data: states.collections,
      currentUserId: states.currentUserId,
      delegate: {
        save: function(name, items, callback) {
          UT.Expression._callAPI('collections.save', [name, items], callback);
        },
        authenticate: function(callback) {
          UT.Expression._callAPI('authenticate');
        }
      }
    });

    /**
     * Retrieve Parent Post Datas.
     *
     * This is available only during the first edition of a post
     * if the expression is created from another one.
     */
    var parentCollection;
    if(states.parentData){
      var items = [];
      for(var k in states.parentData){
        states.parentData[k]._key = k;
        items.push(states.parentData[k]);
      }
      parentCollection = new UT.Collection({
        data: {
          name: 'parent',
          items: items,
          count: items.length
        },
        delegate: {
          save: function(){
            throw new Error('ReadOnly collection');
          },
          authenticate: function(){
            throw new Error('ReadOnly collection');
          }
        },
        currentUserId: states.currentUserId
      });
    }

    // scoped functions

    var setNote = function(value){
      states.note = value;
      UT.Expression._callAPI('document.setNote', [states.note]);
      return value;
    };

    this.__defineGetter__('note', function() {
      return states.note;
    });
    this.__defineSetter__('note', function(value) {
      return setNote(value);
    });

    // Public Properties

    /**
     * context of the current editor
     * - player: true if in player mode
     * - editor: true if in editor mode
     * - thumbnail: true if in thumbnail mode
     * - privacy: one of 'private', 'unlisted' or 'public' the current state of the document publication.
     *
     * Those attributes should not be modified as the context is read-only.
     * read-only
     */
    var context = this.context = {
      player: false,
      editor: false,
      thumbnail: false,
      privacy: null
    };
    // set the proper context values
    if(states.mode == 'edit'){
      context.editor = true;
    } else if(states.mode == 'player'){
      context.player = true;
    }
    context.privacy = states.documentPrivacy;

    /**
     * Retrieve the public url of the document.
     *
     * read-only
     */
    var url = this.url = states.documentURL;

    /**
     * the expression outter dom node
     */
    var node = this.node = document.querySelector('.webdoc_expression_wrapper');
    if(!node){
      throw new Error('Missing wrapper node');
    }

    // Public Functions

    /**
     * Native text input for mobile.
     *
     * if options is passed, it might contains:
     * - value, the default value,
     * - max, the number of chars allowed,
     * - multiline, if true, allow for a multiline text input
     *
     * The callback will be passed the resulting string or null
     * if no value have been selected.
     *
     * XXX: Need to be supported on desktop as well
     */
    var textDialog = function(options, callback){
      if(typeof options == 'function'){
        callback = options;
        options = {};
      }
      UT.Expression._callAPI(
        'document.textInput',
        [options.value || null, options.max || null, options.multiline || false],
        callback
      );
    };

    var imageDialog = function(options, callback) {
      UT.Expression._callAPI(
        'medias.openImageChooser',
        [options],
        function(imageDescriptor) {
          var image = new UT.Image();
          image.init(imageDescriptor);
          callback.call(self, image);
      });
    };

    var soundDialog = function(options, callback) {
      UT.Expression._callAPI(
        'medias.openSoundChooser',
        [options],
        function(soundDecriptor) {
          var sound = new UT.Sound(soundDecriptor);
          callback.call(self, sound);
      });
      UT.Expression._callAPI('medias.openSoundChooser', [options], callback);
    };

    var videoDialog = function(options, callback) {
      UT.Expression._callAPI(
        'medias.openVideoChooser',
        [options],
        function(videoDescriptor) {
          var video = new UT.Video(videoDescriptor);
          callback.call(self, video);
      });
    };

    var cropDialog = function(options, callback) {
      if (options.image.descriptor) {
        options.image = options.image.descriptor;
      }
      UT.Expression._callAPI('medias.crop', [options],
        function(imageDescriptor) {
          var image = null;
          if (options.image.init) {
            options.image.init(imageDescriptor);
            image = options.image;
          }
          else {
            image = new UT.Image();
            image.init(imageDescriptor);
          }
          callback.call(self, image);
      });
    };

    // Handler for the various dialog type
    var dialogHandler = {
      text: textDialog,
      image: imageDialog,
      sound: soundDialog,
      video: videoDialog,
      crop: cropDialog
    };

    /**
     * Calls all fns in the list for a given eventName. Passes arguments
     * through to the caller.
     * @params {String} eventName The eventName to fire
     */
    var fire = this.fire = function(eventName) {
      var list = eventTypesBindings[eventName],
          promises = [],
          nextTrigger = 'after' + eventName.charAt(0).toUpperCase() + eventName.slice(1),
          listLength,
          listIndex,
          callbackFunction,
          callbackArgs,
          promise;

      // Nothing to fire
      if (!list) {
        return;
      }

      // We copy the list in case the original mutates while we're
      // looping over it. We take the arguments, lop of the first entry,
      // and pass the rest to the listeners when we call them.
      list = list.slice(0);
      listLength = list.length;
      listIndex = -1;
      callbackArgs = Array.prototype.slice.call(arguments, 1);
      callbackTarget = (callbackArgs.length !== 0 ? callbackArgs[0] : self);

      while (++listIndex < listLength) {
        callbackFunction = list[listIndex];
        promise = callbackFunction.apply(callbackTarget, callbackArgs);
        if(promise && typeof promise.then === 'function') {
          promises.push(promise);
        }
      }

      if(promises.length > 0) {
        when.all(promises).then(function() {
          fire(nextTrigger);
        });
      }
      else {
        fire(nextTrigger);
      }
    };

    /**
     * Register a listener for the given eventName.
     *
     * Available events:
     *
     * publish callback()
     * ------------------
     * Fired when the user wants to post his content. The callback
     * will be called on the Post instance and receive no argument.
     * It must be runnable synchronously as the current context
     * will be destroyed after all callbacks as been processed.
     *
     * scroll callback(ScrollDataEvent)
     * --------------------------------
     * Fired every time the visible part of the iframe
     * on the page change.
     * the callback is passed the scrolling data.
     * XXX what are the scrolling data?
     *
     * resize callback(ResizeEvent)
     * ----------------------------
     * Fired when the content box size changed. The callback is
     * called on the event and will be passed the ResizeEvent instance.
     *
     * media callback(MediaEvent)
     * --------------------------
     * Fired when a media is incoming from an external action
     * like a bookmarklet adding a resource or a drag and drop.
     * The callback is called on the event and will be passed a
     * the MediaEvent instance.
     */
    var on = this.on = function(eventName, callback) {
      var list = eventTypesBindings[eventName] || (eventTypesBindings[eventName] = []);

      // This callback is not a function
      if (typeof callback !== 'function') {
        return;
      }

      list.push(callback);
    };

    /**
     * Removes the given callback for the given eventName.
     *
     * @param {String} eventName
     * @param {Function} callback to remove
     */
    var off = this.off = function(eventName, callback) {
      var list = eventTypesBindings[eventName],
      l;

      // Nothing to unbind
      if (!list) {
        return;
      }

      // No function specified, so unbind all by removing the list
      if (!callback) {
        delete eventTypesBindings[eventName];
        return;
      }

      // Remove all occurences of this function from the list
      l = list ? list.indexOf(callback) : -1;

      while (l !== -1) {
        list.splice(l, 1);
        l = list.indexOf(callback);
      }
    };

    /**
     * Flag a post as being valid or not.
     * A valid document can be posted synchronously at any time.
     *
     * @param flag {boolean} if provided, set the current validity state.
     * @return {boolean} the current validity flag
     */
    var valid = this.valid = function(flag){
      if(flag !== undefined && flag != states.readyToPost ){
        states.readyToPost = !!flag;
        UT.Expression._callAPI('document.readyToPost', [states.readyToPost]);
      }
      return states.readyToPost;
    };

    /**
     * on the callback function to the scrollChanged event.
     * The function will receive the new scroll values.
     * @param {function} callback will be passed the new scrollvalues
     */
    var scrollChanged = this.scollChanged = function(callback) {
      on('scrollChanged', callback);
    };

    /**
     * on the callback function to the imageAdded event.
     * The function will receive the image and optional extraData param.
     * @param {Function} callback
     */
    var imageAdded = this.imageAdded = function(callback) {
      on('imageAdded', callback);
    };

    /**
     * Create the dialog of the given type using an options object and
     * retrieve the dialog output in the callback.
     */
    var dialog = this.dialog = function(type, options, callback) {
      if (callback === undefined && typeof(options) === 'function') {
        callback = options;
        options = {};
      }
      if(dialogHandler[type]){
        dialogHandler[type](options, callback);
      } else {
        throw new Error('InvalidArgument', 'unknown dialog type ' + type);
      }
    };

    /**
     * Ask the container to resize to the given parameters.
     *
     * The asynchronous result of this function can be listened on
     * the DOM node event.
     * size can be one of:
     * - {height: Number} an object containing the height in pixels
     * - {height: '133px'} an object continaing the height in a css string
     * - Number the height in pixel
     * - 'auto' automatically resize to the actual content size
     */
    var resize = this.resize = function(sizeInfo){
      var height;
      if(typeof sizeInfo === 'number'){ // 99
        height = sizeInfo;
      } else if(sizeInfo && sizeInfo == 'auto'){
        height = node.offsetHeight;
      } else if (sizeInfo && sizeInfo.height){
        if(typeof sizeInfo.height === "string" && sizeInfo.height.match &&
            sizeInfo.height.match(/^[0-9]+px$/)){ // {height: '99px'}
          height = sizeInfo.height.substring(0, sizeInfo.height.length-2);
        } else { // {height: 99}
          height = sizeInfo.height;
        }
      }
      UT.Expression._callAPI('container.resizeHeight', [height]);
    };

    var pushNavigation = this.pushNavigation = function(state, callback) {
      UT.Expression._callAPI('container.pushNavigation', [state], callback);
    };

    var popNavigation = this.popNavigation = function() {
      UT.Expression._callAPI('container.popNavigation');
    };

    var navigate = this.navigate = function(app) {
      var options = {};
      if (arguments.length >= 2) {
        options = arguments[1];
      }
      else if (arguments.length === 1) {
        options = app;
        app = 'browse';
      }
      var opt = {
        app : app,
        parameters : options
      };
      UT.Expression._callAPI('container.navigate', [opt]);
    };

    /**
     * Retrieve a collection given its name.
     *
     * The name can be any public collection defined in expression.json,
     * 'default' for the default collection (aka post.storage)
     * or parent for this post parent default collection (this is available
     * only during the first edition of a post if the expression is created
     * from another one.)
     *
     * @param {String} name the collection name
     */
    var collection = this.collection = function(name){
      if(name == 'parent'){
        return parentCollection || null;
      } else {
        return collectionStore.get(name);
      }
    };

    /**
     * Save data in all collections.
     */
    var save = this.save = function(){
      collectionStore.each(function(c){
        c.save();
      });
    };

    /**
     * Request an user data object containing informations on
     * current user
     * @param  {Function} callback a callback called with the user datas
     */
    var getUserData = this.getUserData = function(callback) {
      UT.Expression._callAPI('document.getUserData', [], callback);
    }

    /**
     * The default, private collection
     */
    this.storage = collection('default');

    window.addEventListener('resize', function(){
      self.fire('resize', new UT.ResizeEvent(window.offsetWidth, window.offsetHeight));
    }, false);
  };
})();<|endoftext|>


<commit_before>#!/usr/bin/env node --harmony
'use strict';

process.env.NODE_ENV = 'development';

const scriptsPackagename = 'react-boilerplate-app-scripts';

const path = require('path');
const fs = require('fs-extra');
const chalk = require('chalk');
const openBrowser = require('react-dev-utils/openBrowser');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const detect = require('detect-port');
const util = require('react-boilerplate-app-utils');
const paths = require(util.pathResolve('config/paths.js',__dirname,scriptsPackagename));
var proxy;
var proxyPath = util.pathResolve('config/proxy.js',__dirname,scriptsPackagename);
if(proxyPath){
  proxy = require(proxyPath);
}
var historyApiFallbackPath = util.pathResolve('config/historyApiFallback.js',__dirname,scriptsPackagename);
var historyApiFallback;
if(historyApiFallbackPath){
  historyApiFallback = require(historyApiFallbackPath);
}
const config = require(paths.webpackDevConfig);
const compiler = webpack(config);
const cwdPackageJsonConfig = util.getDefaultCwdPackageJsonConfig(scriptsPackagename);
const host = cwdPackageJsonConfig.host;
//port 可以被修改，会被占用
var port = cwdPackageJsonConfig.port;
//经过转换后的historyApiFallback rewrites
if(cwdPackageJsonConfig.historyApiFallback){
  var rewrites = util.historyApiFallbackRewiriteAdapter(cwdPackageJsonConfig.historyApiFallback.rewrites);
  cwdPackageJsonConfig.historyApiFallback.rewrites = rewrites;
}

function runDevServer(host, port) {
  var devServer = new WebpackDevServer(compiler, {
    //开启HTML5 History API，所有请求都重定向到index.html（地址重写）
    historyApiFallback: historyApiFallback || cwdPackageJsonConfig.historyApiFallback || true,
    // 开启gzip功能
    compress: true,
    // 关闭WebpackDevServer繁琐的输出信息
    // 但警告和错误信息不会被关闭
    clientLogLevel: 'none',
    //静态文件
    contentBase: paths.appPublic,
    //开启热替换server
    hot: true,
    //跟webpack.config中publicPath相等，内存文件输出目录
    publicPath: config.output.publicPath,
    //会关闭WebpackDevServer编译后所有的信息（包括错误警告信息），后续通过compiler.plugin('done',null)自定义信息
    quiet: true,
    //watch设置
    watchOptions: {
      ignored: [
        /node_modules/,
        '**/*.swp',
        '**/*.swo',
        '**/*.xlsx',
      ]
    },
    host: host || "localhost",
    //packageJson中的proxy只能是字符串，无法使用函数
    proxy: proxy || cwdPackageJsonConfig.proxy || { },
  });

  // 启动WebpackDevServer.
  devServer.listen(port, err => {
    if (err) {
      return console.log(err);
    }
    console.log()
  });
}

var isFirstCompile = true;
compiler.plugin('done', function(stats) {
  var messages = stats.toJson({}, true);
  var isError = messages.errors.length || messages.warnings.length;
  if(!isError){
    console.log(chalk.green('Compiled successfully!'));
    console.log();
  }

  if (!isError && isFirstCompile) {
    console.info(chalk.cyan("==> 🌎  Listening on port %s. Open up http://"+host+":%s/ in your browser."), port, port);
    console.log();
    console.log('Production building,please use ' + chalk.cyan("`npm || yarn" + ' run build`') + '.');
    console.log();
    isFirstCompile = false;
    openBrowser(`http://${ host }:${ port }/${ cwdPackageJsonConfig.prefixURL }`);
  }

  // 展示错误信息
  if (messages.errors.length) {
    console.log(chalk.red('faild to compile!'));
    console.log();
    messages.errors.forEach(message => {
      console.log(message);
      console.log();
    });
    return;
  }

  //展示警告信息
  if (messages.warnings.length) {
    console.log(chalk.yellow('Compiled with warnings.'));
    console.log();
    messages.warnings.forEach(message => {
      console.log(message);
      console.log();
    });
  }
});
// "invalid" 是 "bundle invalidated" 缩写
// 不意味有错误
// 只要保存监控文件，就会触发重编译
// 重编译就是触发”invalid“事件
//compiler.plugin('invalid', () => {
  //console.log('Compiling...');
//});

detect(port, (err, _port) => {
  if (err) {
    console.log(err);
  }
  if (port == _port) {
    runDevServer(host,port);
  } else {
    console.log(chalk.yellow(`port: ${port} was occupied, try port: ${_port}`));
    console.log()
    console.log(chalk.cyan(`It's recommended to add 'port: ${ _port }' in package.json's field 'react-boilerplate-app-scripts'.`));
    console.log()
    port = _port;
    runDevServer(host,_port);
  }
});

<commit_msg>warning 也是成功的<commit_after>#!/usr/bin/env node --harmony
'use strict';

process.env.NODE_ENV = 'development';

const scriptsPackagename = 'react-boilerplate-app-scripts';

const path = require('path');
const fs = require('fs-extra');
const chalk = require('chalk');
const openBrowser = require('react-dev-utils/openBrowser');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const detect = require('detect-port');
const util = require('react-boilerplate-app-utils');
const paths = require(util.pathResolve('config/paths.js',__dirname,scriptsPackagename));
var proxy;
var proxyPath = util.pathResolve('config/proxy.js',__dirname,scriptsPackagename);
if(proxyPath){
  proxy = require(proxyPath);
}
var historyApiFallbackPath = util.pathResolve('config/historyApiFallback.js',__dirname,scriptsPackagename);
var historyApiFallback;
if(historyApiFallbackPath){
  historyApiFallback = require(historyApiFallbackPath);
}
const config = require(paths.webpackDevConfig);
const compiler = webpack(config);
const cwdPackageJsonConfig = util.getDefaultCwdPackageJsonConfig(scriptsPackagename);
const host = cwdPackageJsonConfig.host;
//port 可以被修改，会被占用
var port = cwdPackageJsonConfig.port;
//经过转换后的historyApiFallback rewrites
if(cwdPackageJsonConfig.historyApiFallback){
  var rewrites = util.historyApiFallbackRewiriteAdapter(cwdPackageJsonConfig.historyApiFallback.rewrites);
  cwdPackageJsonConfig.historyApiFallback.rewrites = rewrites;
}

function runDevServer(host, port) {
  var devServer = new WebpackDevServer(compiler, {
    //开启HTML5 History API，所有请求都重定向到index.html（地址重写）
    historyApiFallback: historyApiFallback || cwdPackageJsonConfig.historyApiFallback || true,
    // 开启gzip功能
    compress: true,
    // 关闭WebpackDevServer繁琐的输出信息
    // 但警告和错误信息不会被关闭
    clientLogLevel: 'none',
    //静态文件
    contentBase: paths.appPublic,
    //开启热替换server
    hot: true,
    //跟webpack.config中publicPath相等，内存文件输出目录
    publicPath: config.output.publicPath,
    //会关闭WebpackDevServer编译后所有的信息（包括错误警告信息），后续通过compiler.plugin('done',null)自定义信息
    quiet: true,
    //watch设置
    watchOptions: {
      ignored: [
        /node_modules/,
        '**/*.swp',
        '**/*.swo',
        '**/*.xlsx',
      ]
    },
    host: host || "localhost",
    //packageJson中的proxy只能是字符串，无法使用函数
    proxy: proxy || cwdPackageJsonConfig.proxy || { },
  });

  // 启动WebpackDevServer.
  devServer.listen(port, err => {
    if (err) {
      return console.log(err);
    }
    console.log()
  });
}

var isFirstCompile = true;
compiler.plugin('done', function(stats) {
  var messages = stats.toJson({}, true);
  var isError = messages.errors.length;
  if(!isError){
    console.log(chalk.green('Compiled successfully!'));
    console.log();
  }

  if (!isError && isFirstCompile) {
    console.info(chalk.cyan("==> 🌎  Listening on port %s. Open up http://"+host+":%s/ in your browser."), port, port);
    console.log();
    console.log('Production building,please use ' + chalk.cyan("`npm || yarn" + ' run build`') + '.');
    console.log();
    isFirstCompile = false;
    openBrowser(`http://${ host }:${ port }/${ cwdPackageJsonConfig.prefixURL }`);
  }

  // 展示错误信息
  if (messages.errors.length) {
    console.log(chalk.red('faild to compile!'));
    console.log();
    messages.errors.forEach(message => {
      console.log(message);
      console.log();
    });
    return;
  }

  //展示警告信息
  if (messages.warnings.length) {
    console.log(chalk.yellow('Compiled with warnings.'));
    console.log();
    messages.warnings.forEach(message => {
      console.log(message);
      console.log();
    });
  }
});
// "invalid" 是 "bundle invalidated" 缩写
// 不意味有错误
// 只要保存监控文件，就会触发重编译
// 重编译就是触发”invalid“事件
//compiler.plugin('invalid', () => {
  //console.log('Compiling...');
//});

detect(port, (err, _port) => {
  if (err) {
    console.log(err);
  }
  if (port == _port) {
    runDevServer(host,port);
  } else {
    console.log(chalk.yellow(`port: ${port} was occupied, try port: ${_port}`));
    console.log()
    console.log(chalk.cyan(`It's recommended to add 'port: ${ _port }' in package.json's field 'react-boilerplate-app-scripts'.`));
    console.log()
    port = _port;
    runDevServer(host,_port);
  }
});

<|endoftext|>


<commit_before>/**
 * Created by hapresto on 2/14/17.
 */

app.constant('demos', [
    {
        "status": "active",
        "name": "Cisco Health Report & ONline Information Collector (CHROnIC)",
        "github": "https://github.com/imapex/CHROnIC",
        "youtube": "https://www.youtube.com/embed/VEXby7V8Szs",
        "devs": [
            {
                "name": "Josh Anderson",
                "github": "https://github.com/joshand"
            },
            {
                "name": "Chad Peterson",
                "github": "https://github.com/chapeter"
            },
            {
                "name": "Loy Evans",
                "github": "https://github.com/loyevans"
            }
        ],
        "description": "This is an application designed to interact with Cisco Infrastructure components and key software elements, and perform an online analysis of their compliance to set standards.",
        "image": "demoresources/chronic/chronic.png"
    },
    {
        "status": "active",
        "name": "Cisco Kiddie Kounter (C2K-IoX)",
        "github": "https://github.com/imapex/c2k_demo",
        "youtube": "https://www.youtube.com/embed/uacr-M5RM-g",
        "devs": [
            {
                "name": "Ryan Criss",
                "github": "https://github.com/rcriss"
            },
            {
                "name": "Chuck Wood",
                "github": "https://github.com/cw082195"
            },
            {
                "name": "Harish Chawla",
                "github": "https://github.com/"
            }
        ],
        "description": "An application to count kids on a school bus and provide notifications via Spark and/or Tropo/SMS.",
        "image": "demoresources/c2k_iox/c2k-diagram.png"
    },
    {
        "status": "active",
        "name": "Automated Infrastructure Configuration",
        "github": "https://github.com/imapex/aic_app",
        "youtube": "https://www.youtube.com/embed/n-mJIbw-1Uw",
        "devs": [
            {
                "name": "Michael Bonnett Jr",
                "github": "https://github.com/michaelbonnettjr"
            },
            {
                "name": "Rusty Pesselato",
                "github": "https://github.com/opessela"
            },
            {
                "name": "Dan Williams",
                "github": "https://github.com/danwms3"
            }
        ],
        "description": "AIC is an application that monitors for infrastructure changes, such as HBA hardware replacement, and automatically reconfigures the affected systems to account for the change.",
        "image": "demoresources/aic/aic_logical_arch.png"
    },
    {
        "status": "active",
        "name": "All Hands On Deck (AHOD)",
        "github": "https://github.com/imapex/ahod_home",
        "youtube": "https://www.youtube.com/embed/ytXI272kDxg",
        "devs": [
            {
                "name": "Dan Behrens",
                "github": "https://github.com/danbehrens1"
            },
            {
                "name": "Peter Fincher",
                "github": "https://github.com/pfincher99"
            }
        ],
        "description": "An IOx Application that gathers data from PLC, monitors for specific events, and alerts via Cisco Spark when a monitored event occurs.",
        "image": "demoresources/ahod/AHOD_Overview-Phase1.jpg"
    },
    {
        "status": "active",
        "name": "Cisco Heat Indication Visualization Explorer (CHIVE)",
        "github": "https://github.com/imapex/chive_demo",

        "devs": [
            {
                "name": "Justin Barksdale",
                "github": "https://github.com/3pings"
            },
            {
                "name": "Clint Mann",
                "github": "https://github.com/clintmann"
            }
        ],
        "description": "Cisco Heat Indication Visualization Explorer (An application to visualize hot spots in a data center on a map and over time using standard API calls on sensors in Cisco Data Center Products.)"
    },
    {
        "status": "active",
        "name": "ACI Migration Wizard",
        "github": "https://github.com/imapex/acimigrate",
        "youtube": "https://www.youtube.com/embed/SzjwplFwkL8",
        "devs": [
            {
                "name": "Kevin Corbin",
                "github": "https://github.com/kecorbin"
            },
            {
                "name": "Chad Peterson",
                "github": "https://github.com/chapeter"
            }
        ],
        "description": "A migration wizard which will migrate VLAN configuration from Legacy Nexus environments to an ACI fabric",
        "image": "demoresources/acimigrate/acimigrate.png"
    },
    {
        "status": "active",
        "name": "Giant Ball of String (GBoS)",
        "github": "https://github.com/imapex/gbos_demo",
        "youtube": "https://www.youtube.com/embed/ySjgylacZDU",
        "devs": [
            {
                "name": "Hank Preston",
                "github": "https://github.com/hpreston",
                "twitter": "hfpreston"
            },
            {
                "name": "Kevin Corbin",
                "github": "https://github.com/kecorbin",
            }
        ],
        "description": "Giant Ball of String (GBoS) is a sample demonstration application for road side attraction management.  It demonstrates the integration of several Cisco technologies (IOx, Cisco Zeus, Spark, and Tropo) with non-Cisco techologies such as cloud platforms and micro-controllers to solve business problems.",
        "image": "demoresources/gbos/gbos_site.jpg",
        "live_demo": [
            {
                "name": "Demo Link (Kiosk)",
                "link": "http://gbos.apps.imapex.io/"
            }
        ]
    },
    {
        "status": "active",
        "name": "Event Driven QoS",
        "github": "https://github.com/imapex/ed-qos",
        "youtube": "https://www.youtube.com/embed/cxmlz4XkV24",
        "devs": [
            {
                "name": "Steve Luzynski",
                "github": "https://github.com/sluzynsk"
            },
            {
                "name": "Matt Brainard",
                "github": "https://github.com/mbrainar"
            }
        ],
        "description": "Event Driven QoS is a simple demo application illustrating programmatic control of APIC-EM to change QoS parameters in an attached network. This is driven by an external event. In the initial implementation, the external event source is changes in the weather; other event sources are planned."
    },
    {
        "status": "active",
        "name": "CMX Spark Alert (csalert)",
        "github": "https://github.com/imapex/csalert",
        "youtube": "https://www.youtube.com/embed/sFghP0lqdv4",
        "devs": [
            {
                "name": "Bryan Adams",
                "github": "https://github.com/bmadams0"
            },
            {
                "name": "Paul Lewis",
                "github": "https://github.com/paullewi"
            }
        ],
        "description": "The goal is to create an application that will take location-based event triggers from CMX and output a Spark message to a specific room or user. The CMX input could be device tracking, congestion thresholds, geo-fencing alerts, etc.
 Our use case is a retail store that will detect shopper congestion (by tracking client count on a nearby AP) and send an alert message to the manager or employee in that department so that they can assist the shoppers.
 We would like to keep the app modular to adjust both the CMX inputs and the Spark output.",
        "image": "demoresources/csalert/csalert.png"
    },
    {
        "status": "active",
        "name": "AppRegistry",
        "github": "https://github.com/imapex/appregistry",

        "devs": [
            {
                "name": "Kevin Corbin",
                "github": "https://github.com/kecorbin"
            }
        ],
        "description": "This is a simple frontend for APIC-EM which allows business owners to register applications in a portal with a minimal amount of technical details about the application, and transfer that information to APIC-EM to be consumed in EasyQos policies",
        "image": "demoresources/appregistry/screenshot.png",
        "live_demo": [
            {
                "name": "Demo Link",
                "link": "http://appregistry.apps.imapex.io/"
            }
        ]
    },
    {
        "status": "active",
        "name": "ioxduino",
        "github": "https://github.com/imapex/ioxduino",
        "youtube": "https://www.youtube.com/embed/KFQw7loxLJ0",
        "devs": [
            {
                "name": "Hank Preston",
                "github": "https://github.com/hpreston",
                "twitter": "hfpreston"

            }
        ],
        "description": "IOx Proof of Concept to integrate a Cisco Router with an Arduino Microcontroller.",
        "image": "demoresources/ioxduino/arduino_diagram.jpg"
    },
    {
        "status": "active",
        "name": "MyHero",
        "github": "https://github.com/hpreston/myhero_demo",

        "devs": [
            {
                "name": "Hank Preston",
                "github": "https://github.com/hpreston",
                "twitter": "hfpreston"

            }
        ],
        "description": "MyHero is a very simple sample application developed using a \"Cloud Native\" design method to be used for demonstration and education purposes. It is composed of several microservices, each leveraging standard API interaction. The minimal deployment of MyHero consists of just three services, and when deployed with all features, it can be as many as ten different services.",
        "image": "demoresources/myhero/myhero-demo-i2.png",
        "live_demo": [
            {
                "name": "Demo Link",
                "link": "http://myhero.apps.imapex.io/#/demos"
            }
        ]
    },
    {
        "status": "beta",
        "name": "Gomorrah Automated Distributed Defense (GADD)",
        "github": "https://github.com/imapex/gadd",
        "youtube": "https://www.youtube.com/embed/Nxex1kpwRYA",
        "devs": [
            {
                "name": "Chet Puskarz",
                "github": "https://github.com/cpuskarz"
            },
            {
                "name": "Ryan Shoemaker",
                "github": "https://github.com/rshoemak"
            }
        ],
        "description": "Using Spark and NFVIS along with ACI and NGIPS* The idea of the demo is based on an event/alert in the datacenter, dynamically deploy a FW at offending remote brach. Phase 1 will be simulating an event/alert without an IPS."
    },
    {
        "status": "beta",
        "name": "DC Jeeves",
        "github": "https://github.com/imapex/dcjeeves_demo",
        "youtube": "https://www.youtube.com/embed/3vpalwCzRCw",
        "devs": [
            {
                "name": "Mike Tokarz",
                "github": "https://github.com/myTokarz"
            },
            {
                "name": "Russel Wilkinson",
                "github": "https://github.com/virtualrussel"
            }
        ],
        "description": "DC Jeeves is your adaptable datacenter butler. His goal is to make your life easier by providing an interactive interface through tools like Spark & Tropo and turning your requests into actionable functions in your datacenter. Jeeves, provision a server for me!"
    },
    {
        "status": "beta",
        "name": "IOT Notification Agent",
        "github": "https://github.com/imapex/IOTEventNotification",
        "youtube": "https://www.youtube.com/embed/FheCN6B42N4",
        "devs": [
            {
                "name": "Kevin Corbin",
                "github": "https://github.com/kecorbin"
            },
            {
                "name": "Chris Bogdon",
                "github": "https://github.com/chrisbog"
            }
        ],
        "description": "This application serves as a generic event notification engine for IOT enabled routers. The engine will react to any external event and perform some type of notification."
    },
    {
        "status": "beta",
        "name": "Spark Trak",
        "github": "https://github.com/imapex/spark-trak",

        "devs": [
            {
                "name": "Blair Hicks",
                "github": "https://github.com/blairhicks"
            },
            {
                "name": "Tim Wittbrod",
                "github": "https://github.com/twittbrod"
            }
        ],
        "description": "Spark Trak is a professional collaboration application leveraging Cisco Spark to provide secure communication.  Intended to be used by health care professionals, laywers, insurance agents, etc - any professional that needs to share information pertaining to a client.  By entering into Spark Room, the professionals are able to discuss and access confidential records. While in the Spark Room, they are able to initiate actions relevant to the client - order procedures, prescribe medication, set appointments.  Upon exiting the Spark room, the collaboration session is archived and can generate a billing record for the client."
    }
]);<commit_msg>Added twitter info for folks.<commit_after>/**
 * Created by hapresto on 2/14/17.
 */

app.constant('demos', [
    {
        "status": "active",
        "name": "Cisco Health Report & ONline Information Collector (CHROnIC)",
        "github": "https://github.com/imapex/CHROnIC",
        "youtube": "https://www.youtube.com/embed/VEXby7V8Szs",
        "devs": [
            {
                "name": "Josh Anderson",
                "github": "https://github.com/joshand",
                "twitter": "josh_l_anderson"
            },
            {
                "name": "Chad Peterson",
                "github": "https://github.com/chapeter"
            },
            {
                "name": "Loy Evans",
                "github": "https://github.com/loyevans"
            }
        ],
        "description": "This is an application designed to interact with Cisco Infrastructure components and key software elements, and perform an online analysis of their compliance to set standards.",
        "image": "demoresources/chronic/chronic.png"
    },
    {
        "status": "active",
        "name": "Cisco Kiddie Kounter (C2K-IoX)",
        "github": "https://github.com/imapex/c2k_demo",
        "youtube": "https://www.youtube.com/embed/uacr-M5RM-g",
        "devs": [
            {
                "name": "Ryan Criss",
                "github": "https://github.com/rcriss"
            },
            {
                "name": "Chuck Wood",
                "github": "https://github.com/cw082195"
            },
            {
                "name": "Harish Chawla",
                "github": "https://github.com/"
            }
        ],
        "description": "An application to count kids on a school bus and provide notifications via Spark and/or Tropo/SMS.",
        "image": "demoresources/c2k_iox/c2k-diagram.png"
    },
    {
        "status": "active",
        "name": "Automated Infrastructure Configuration",
        "github": "https://github.com/imapex/aic_app",
        "youtube": "https://www.youtube.com/embed/n-mJIbw-1Uw",
        "devs": [
            {
                "name": "Michael Bonnett Jr",
                "github": "https://github.com/michaelbonnettjr"
            },
            {
                "name": "Rusty Pesselato",
                "github": "https://github.com/opessela"
            },
            {
                "name": "Dan Williams",
                "github": "https://github.com/danwms3"
            }
        ],
        "description": "AIC is an application that monitors for infrastructure changes, such as HBA hardware replacement, and automatically reconfigures the affected systems to account for the change.",
        "image": "demoresources/aic/aic_logical_arch.png"
    },
    {
        "status": "active",
        "name": "All Hands On Deck (AHOD)",
        "github": "https://github.com/imapex/ahod_home",
        "youtube": "https://www.youtube.com/embed/ytXI272kDxg",
        "devs": [
            {
                "name": "Dan Behrens",
                "github": "https://github.com/danbehrens1",
                "twitter": "danielrbehrens"
            },
            {
                "name": "Peter Fincher",
                "github": "https://github.com/pfincher99"
            }
        ],
        "description": "An IOx Application that gathers data from PLC, monitors for specific events, and alerts via Cisco Spark when a monitored event occurs.",
        "image": "demoresources/ahod/AHOD_Overview-Phase1.jpg"
    },
    {
        "status": "active",
        "name": "Cisco Heat Indication Visualization Explorer (CHIVE)",
        "github": "https://github.com/imapex/chive_demo",

        "devs": [
            {
                "name": "Justin Barksdale",
                "github": "https://github.com/3pings",
                "twitter": "3Pings"
            },
            {
                "name": "Clint Mann",
                "github": "https://github.com/clintmann",
                "twitter": "CiscoMann_SE"
            }
        ],
        "description": "Cisco Heat Indication Visualization Explorer (An application to visualize hot spots in a data center on a map and over time using standard API calls on sensors in Cisco Data Center Products.)"
    },
    {
        "status": "active",
        "name": "ACI Migration Wizard",
        "github": "https://github.com/imapex/acimigrate",
        "youtube": "https://www.youtube.com/embed/SzjwplFwkL8",
        "devs": [
            {
                "name": "Kevin Corbin",
                "github": "https://github.com/kecorbin"
            },
            {
                "name": "Chad Peterson",
                "github": "https://github.com/chapeter"
            }
        ],
        "description": "A migration wizard which will migrate VLAN configuration from Legacy Nexus environments to an ACI fabric",
        "image": "demoresources/acimigrate/acimigrate.png"
    },
    {
        "status": "active",
        "name": "Giant Ball of String (GBoS)",
        "github": "https://github.com/imapex/gbos_demo",
        "youtube": "https://www.youtube.com/embed/ySjgylacZDU",
        "devs": [
            {
                "name": "Hank Preston",
                "github": "https://github.com/hpreston",
                "twitter": "hfpreston"
            },
            {
                "name": "Kevin Corbin",
                "github": "https://github.com/kecorbin",
            }
        ],
        "description": "Giant Ball of String (GBoS) is a sample demonstration application for road side attraction management.  It demonstrates the integration of several Cisco technologies (IOx, Cisco Zeus, Spark, and Tropo) with non-Cisco techologies such as cloud platforms and micro-controllers to solve business problems.",
        "image": "demoresources/gbos/gbos_site.jpg",
        "live_demo": [
            {
                "name": "Demo Link (Kiosk)",
                "link": "http://gbos.apps.imapex.io/"
            }
        ]
    },
    {
        "status": "active",
        "name": "Event Driven QoS",
        "github": "https://github.com/imapex/ed-qos",
        "youtube": "https://www.youtube.com/embed/cxmlz4XkV24",
        "devs": [
            {
                "name": "Steve Luzynski",
                "github": "https://github.com/sluzynsk",
                "twitter": "SteveLuzynski"
            },
            {
                "name": "Matt Brainard",
                "github": "https://github.com/mbrainar"
            }
        ],
        "description": "Event Driven QoS is a simple demo application illustrating programmatic control of APIC-EM to change QoS parameters in an attached network. This is driven by an external event. In the initial implementation, the external event source is changes in the weather; other event sources are planned."
    },
    {
        "status": "active",
        "name": "CMX Spark Alert (csalert)",
        "github": "https://github.com/imapex/csalert",
        "youtube": "https://www.youtube.com/embed/sFghP0lqdv4",
        "devs": [
            {
                "name": "Bryan Adams",
                "github": "https://github.com/bmadams0"
            },
            {
                "name": "Paul Lewis",
                "github": "https://github.com/paullewi"
            }
        ],
        "description": "The goal is to create an application that will take location-based event triggers from CMX and output a Spark message to a specific room or user. The CMX input could be device tracking, congestion thresholds, geo-fencing alerts, etc.
 Our use case is a retail store that will detect shopper congestion (by tracking client count on a nearby AP) and send an alert message to the manager or employee in that department so that they can assist the shoppers.
 We would like to keep the app modular to adjust both the CMX inputs and the Spark output.",
        "image": "demoresources/csalert/csalert.png"
    },
    {
        "status": "active",
        "name": "AppRegistry",
        "github": "https://github.com/imapex/appregistry",

        "devs": [
            {
                "name": "Kevin Corbin",
                "github": "https://github.com/kecorbin"
            }
        ],
        "description": "This is a simple frontend for APIC-EM which allows business owners to register applications in a portal with a minimal amount of technical details about the application, and transfer that information to APIC-EM to be consumed in EasyQos policies",
        "image": "demoresources/appregistry/screenshot.png",
        "live_demo": [
            {
                "name": "Demo Link",
                "link": "http://appregistry.apps.imapex.io/"
            }
        ]
    },
    {
        "status": "active",
        "name": "ioxduino",
        "github": "https://github.com/imapex/ioxduino",
        "youtube": "https://www.youtube.com/embed/KFQw7loxLJ0",
        "devs": [
            {
                "name": "Hank Preston",
                "github": "https://github.com/hpreston",
                "twitter": "hfpreston"

            }
        ],
        "description": "IOx Proof of Concept to integrate a Cisco Router with an Arduino Microcontroller.",
        "image": "demoresources/ioxduino/arduino_diagram.jpg"
    },
    {
        "status": "active",
        "name": "MyHero",
        "github": "https://github.com/hpreston/myhero_demo",

        "devs": [
            {
                "name": "Hank Preston",
                "github": "https://github.com/hpreston",
                "twitter": "hfpreston"

            }
        ],
        "description": "MyHero is a very simple sample application developed using a \"Cloud Native\" design method to be used for demonstration and education purposes. It is composed of several microservices, each leveraging standard API interaction. The minimal deployment of MyHero consists of just three services, and when deployed with all features, it can be as many as ten different services.",
        "image": "demoresources/myhero/myhero-demo-i2.png",
        "live_demo": [
            {
                "name": "Demo Link",
                "link": "http://myhero.apps.imapex.io/#/demos"
            }
        ]
    },
    {
        "status": "beta",
        "name": "Gomorrah Automated Distributed Defense (GADD)",
        "github": "https://github.com/imapex/gadd",
        "youtube": "https://www.youtube.com/embed/Nxex1kpwRYA",
        "devs": [
            {
                "name": "Chet Puskarz",
                "github": "https://github.com/cpuskarz"
            },
            {
                "name": "Ryan Shoemaker",
                "github": "https://github.com/rshoemak"
            }
        ],
        "description": "Using Spark and NFVIS along with ACI and NGIPS* The idea of the demo is based on an event/alert in the datacenter, dynamically deploy a FW at offending remote brach. Phase 1 will be simulating an event/alert without an IPS."
    },
    {
        "status": "beta",
        "name": "DC Jeeves",
        "github": "https://github.com/imapex/dcjeeves_demo",
        "youtube": "https://www.youtube.com/embed/3vpalwCzRCw",
        "devs": [
            {
                "name": "Mike Tokarz",
                "github": "https://github.com/myTokarz",
                "twitter": "myTokarz"
            },
            {
                "name": "Russel Wilkinson",
                "github": "https://github.com/virtualrussel"
            }
        ],
        "description": "DC Jeeves is your adaptable datacenter butler. His goal is to make your life easier by providing an interactive interface through tools like Spark & Tropo and turning your requests into actionable functions in your datacenter. Jeeves, provision a server for me!"
    },
    {
        "status": "beta",
        "name": "IOT Notification Agent",
        "github": "https://github.com/imapex/IOTEventNotification",
        "youtube": "https://www.youtube.com/embed/FheCN6B42N4",
        "devs": [
            {
                "name": "Kevin Corbin",
                "github": "https://github.com/kecorbin"
            },
            {
                "name": "Chris Bogdon",
                "github": "https://github.com/chrisbog",
                "twitter": "ChrisBogDog"
            }
        ],
        "description": "This application serves as a generic event notification engine for IOT enabled routers. The engine will react to any external event and perform some type of notification."
    },
    {
        "status": "beta",
        "name": "Spark Trak",
        "github": "https://github.com/imapex/spark-trak",

        "devs": [
            {
                "name": "Blair Hicks",
                "github": "https://github.com/blairhicks",
                "twitter": "tuxdbird"
            },
            {
                "name": "Tim Wittbrod",
                "github": "https://github.com/twittbrod"
            }
        ],
        "description": "Spark Trak is a professional collaboration application leveraging Cisco Spark to provide secure communication.  Intended to be used by health care professionals, laywers, insurance agents, etc - any professional that needs to share information pertaining to a client.  By entering into Spark Room, the professionals are able to discuss and access confidential records. While in the Spark Room, they are able to initiate actions relevant to the client - order procedures, prescribe medication, set appointments.  Upon exiting the Spark room, the collaboration session is archived and can generate a billing record for the client."
    }
]);<|endoftext|>


<commit_before>let path = require('path');
let File = require('./File');
let Paths = require('./Paths');
let Concat = require('./Concat');
let options = require('./Options');
let Manifest = require('./Manifest');
let Versioning = require('./Versioning');
let Dispatcher = require('./Dispatcher');
let EntryBuilder = require('./EntryBuilder');

class Mix {
    /**
     * Create a new Laravel Mix instance.
     */
    constructor() {
        this.File = File;
        this.Paths = new Paths;
        this.js = [];
        this.entryBuilder = new EntryBuilder(this);
        this.events = new Dispatcher;
        this.concat = new Concat(this.events);
        this.options = options;
        this.inProduction = this.options.production;
        this.publicPath = this.options.publicPath;
    }

    /**
     * Initialize the user's webpack.mix.js configuration file.
     */
    initialize() {
        if (this.isUsingLaravel()) this.options.publicPath = 'public';

        // This is where we load the user's webpack.mix.js config.
        this.File.exists(this.Paths.mix() + '.js') && require(this.Paths.mix());

        this.manifest = new Manifest(this.options.publicPath).listen(this.events);

        if (this.concat.any()) this.concat.watch();
        if (this.options.versioning) this.enableVersioning();

        this.detectHotReloading();
    }

    /**
     * Enable file versioning for the build.
     */
    enableVersioning() {
        this.versioning = new Versioning(
            this.version, this.manifest, this.options.publicPath
        ).watch();

        this.events.listen(
            ['build', 'combined'], () => this.versioning.prune()
        );

        this.concat.enableVersioning();
    }

    /**
     * Prepare the Webpack entry object.
     */
    entry() {
        return this.entryBuilder.build();
    }

    /**
     * Determine the Webpack output path.
     */
    output() {
        let filename = this.options.versioning ? '[name].[chunkhash].js' : '[name].js';
        let chunkFilename = path.join(
            this.js.base || '', (this.options.versioning ? '[name].[chunkhash].js' : '[name].js')
        );

        return {
            path: path.resolve(this.options.hmr ? '/' : this.options.publicPath),
            filename: filename,
            chunkFilename: chunkFilename.replace(/^\//, ''),
            publicPath: this.options.hmr ? 'http://localhost:8080' : ''
        };
    }

    /**
     * Detect if the user desires hot reloading.
     *
     * @param {boolean} force
     */
    detectHotReloading(force = false) {
        let file = new this.File(this.options.publicPath + '/hot');

        file.delete();

        // If the user wants hot module replacement, we'll create
        // a temporary file, so that Laravel can detect it, and
        // reference the proper base URL for any assets.
        if (this.options.hmr || force) {
            this.options.hmr = true;

            file.write('hot reloading');
        }
    }

    /**
     * Fetch the appropriate Babel config for babel-loader.
     */
    babelConfig() {
        if (this.File.exists(this.Paths.root('.babelrc'))) return '?cacheDirectory';

        // If the user doesn't have a .babelrc, we'll use our config.
        if (this.react) {
            this.options.babel.presets.push('react');
        }

        return '?' + JSON.stringify(this.options.babel);
    }

    /**
     * Determine if we are working with a Laravel project.
     */
    isUsingLaravel() {
        return this.File.exists('./artisan');
    }

    /**
     * Fetch the Vue-specific ExtractTextPlugin.
     */
    vueExtractTextPlugin() {
        let VueExtractTextPluginFactory = require('./Vue/ExtractTextPluginFactory');

        return new VueExtractTextPluginFactory(this, this.options.extractVueStyles).build();
    }
};

module.exports = Mix;
<commit_msg>Set publicPath on Mix as well<commit_after>let path = require('path');
let File = require('./File');
let Paths = require('./Paths');
let Concat = require('./Concat');
let options = require('./Options');
let Manifest = require('./Manifest');
let Versioning = require('./Versioning');
let Dispatcher = require('./Dispatcher');
let EntryBuilder = require('./EntryBuilder');

class Mix {
    /**
     * Create a new Laravel Mix instance.
     */
    constructor() {
        this.File = File;
        this.Paths = new Paths;
        this.js = [];
        this.entryBuilder = new EntryBuilder(this);
        this.events = new Dispatcher;
        this.concat = new Concat(this.events);
        this.options = options;
        this.inProduction = this.options.production;
        this.publicPath = this.options.publicPath;
    }

    /**
     * Initialize the user's webpack.mix.js configuration file.
     */
    initialize() {
        if (this.isUsingLaravel()) {
            this.publicPath = this.options.publicPath = 'public';
        }

        // This is where we load the user's webpack.mix.js config.
        this.File.exists(this.Paths.mix() + '.js') && require(this.Paths.mix());

        this.manifest = new Manifest(this.options.publicPath).listen(this.events);

        if (this.concat.any()) this.concat.watch();
        if (this.options.versioning) this.enableVersioning();

        this.detectHotReloading();
    }

    /**
     * Enable file versioning for the build.
     */
    enableVersioning() {
        this.versioning = new Versioning(
            this.version, this.manifest, this.options.publicPath
        ).watch();

        this.events.listen(
            ['build', 'combined'], () => this.versioning.prune()
        );

        this.concat.enableVersioning();
    }

    /**
     * Prepare the Webpack entry object.
     */
    entry() {
        return this.entryBuilder.build();
    }

    /**
     * Determine the Webpack output path.
     */
    output() {
        let filename = this.options.versioning ? '[name].[chunkhash].js' : '[name].js';
        let chunkFilename = path.join(
            this.js.base || '', (this.options.versioning ? '[name].[chunkhash].js' : '[name].js')
        );

        return {
            path: path.resolve(this.options.hmr ? '/' : this.options.publicPath),
            filename: filename,
            chunkFilename: chunkFilename.replace(/^\//, ''),
            publicPath: this.options.hmr ? 'http://localhost:8080' : ''
        };
    }

    /**
     * Detect if the user desires hot reloading.
     *
     * @param {boolean} force
     */
    detectHotReloading(force = false) {
        let file = new this.File(this.options.publicPath + '/hot');

        file.delete();

        // If the user wants hot module replacement, we'll create
        // a temporary file, so that Laravel can detect it, and
        // reference the proper base URL for any assets.
        if (this.options.hmr || force) {
            this.options.hmr = true;

            file.write('hot reloading');
        }
    }

    /**
     * Fetch the appropriate Babel config for babel-loader.
     */
    babelConfig() {
        if (this.File.exists(this.Paths.root('.babelrc'))) return '?cacheDirectory';

        // If the user doesn't have a .babelrc, we'll use our config.
        if (this.react) {
            this.options.babel.presets.push('react');
        }

        return '?' + JSON.stringify(this.options.babel);
    }

    /**
     * Determine if we are working with a Laravel project.
     */
    isUsingLaravel() {
        return this.File.exists('./artisan');
    }

    /**
     * Fetch the Vue-specific ExtractTextPlugin.
     */
    vueExtractTextPlugin() {
        let VueExtractTextPluginFactory = require('./Vue/ExtractTextPluginFactory');

        return new VueExtractTextPluginFactory(this, this.options.extractVueStyles).build();
    }
};

module.exports = Mix;
<|endoftext|>