<commit_before>var MS = (function (MS) {
  var widgets = MS.widgets = MS.widgets || {};
  widgets.SuggestPicker = Class.create({

  options : {
    'showKey' : true,
    'showTooltip' : true,
    'showDeleteTool' : true,
    'showClearTool' : true
  },
  initialize: function(element, suggest, options) {
    this.options = Object.extend(Object.clone(this.options), options || { });
    this.input = element;
    this.suggest = suggest;
    this.inputName = this.input.name;
    this.input.name = this.input.name + "__suggested";
    this.suggest.options.callback = this.acceptSuggestion.bind(this);
    this.list = new Element('ul', {'class' : 'accepted-suggestions'});
    this.input.insert({'after' : this.list});
    if (this.options.showClearTool) {
      this.clearTool = new Element('span', {'class' : 'clear-tool delete-tool invisible', 'title' : 'Clear the list of selected suggestions'}).update('Delete all ✖');
      this.clearTool.observe('click', this.clearAcceptedList.bindAsEventListener(this));
      this.list.insert({'after': this.clearTool});
    }
  },

  acceptSuggestion : function(obj) {
    this.addItem(obj.id || obj.value, obj.value, obj.info);
    this.input.value = "";
    return false;
  },

  addItem : function(key, value, info) {
    if (!key) {
      return;
    }
    var listItem = new Element("li");
    var displayedValue = new Element("span", {"class": "accepted-suggestion"});
    if (this.options.showKey) {
      displayedValue.insert({'bottom' : new Element("span", {"class": "key"}).update("[" + key.escapeHTML() + "]")});
      displayedValue.insert({'bottom' : new Element("span", {"class": "sep"}).update(" ")});
    }
    displayedValue.insert({'bottom' : new Element("span", {"class": "value"}).update(value.escapeHTML())});
    listItem.appendChild(displayedValue);
    if (this.options.showDeleteTool) {
      var deleteTool = new Element("span", {'class': "delete-tool", "title" : "Delete this term"}).update('✖');
      deleteTool.observe('click', this.removeItem.bindAsEventListener(this));
      listItem.appendChild(deleteTool);
    }
    var hiddenInput = new Element("input", {"type" : "hidden", "name" : this.inputName, "value" : key});
    listItem.appendChild(hiddenInput);
    if (this.options.showTooltip && info) {
      listItem.appendChild(new Element("div", {class : "tooltip"}).update(info));
    }
    this.list.appendChild(listItem);
    this.updateClearTool();
  },

  removeItem : function(event) {
    var item = event.findElement('li');
    item.remove();
    this.input.value = "";
    this.updateClearTool();
  },

  clearAcceptedList : function () {
    this.list.update("");
    this.updateClearTool();
  },

  updateClearTool : function () {
    if (this.list.select('li .accepted-suggestion').length > 0) {
      this.clearTool.removeClassName('invisible');
    } else {
      this.clearTool.addClassName('invisible');
    }
  }
});
  return MS;
}(MS || {}));
<commit_msg>- added options for non-default inserion point of the accepted suggestion list - fixed bug which showed up when showClearTool was disabled - added a hook for custom operations before inserting an accepted suggestion<commit_after>var MS = (function (MS) {
  var widgets = MS.widgets = MS.widgets || {};
  widgets.SuggestPicker = Class.create({

  options : {
    'showKey' : true,
    'showTooltip' : true,
    'showDeleteTool' : true,
    'enableSort' : true,
    'showClearTool' : true,
    'inputType': 'hidden',
    'listInsertionEltSelector' : null,
    'listInsertionPosition' : 'after',
  },
  initialize: function(element, suggest, options) {
    this.options = Object.extend(Object.clone(this.options), options || { });
    this.input = element;
    this.suggest = suggest;
    this.inputName = this.input.name;
    this.input.name = this.input.name + "__suggested";
    this.suggest.options.callback = this.acceptSuggestion.bind(this);
    this.list = new Element('ul', {'class' : 'accepted-suggestions'});
    var listInsertionElement;
    if (!this.options.listInsertionEltSelector || !(listInsertionElement = this.input.up().down(this.options.listInsertionEltSelector))) {
      listInsertionElement = this.input;
    }
    var insertion = {};
    insertion[this.options.listInsertionPosition] = this.list;
    listInsertionElement.insert(insertion);
    if (this.options.showClearTool) {
      this.clearTool = new Element('span', {'class' : 'clear-tool delete-tool invisible', 'title' : 'Clear the list of selected suggestions'}).update('Delete all ✖');
      this.clearTool.observe('click', this.clearAcceptedList.bindAsEventListener(this));
      this.list.insert({'after': this.clearTool});
    }
    if (typeof(this.options.acceptAddItem) == "function") {
      this.acceptAddItem = this.options.acceptAddItem;
    }
  },

  acceptAddItem : function (key, value, info) {
    return true;
  },

  acceptSuggestion : function(obj) {
    if (this.acceptAddItem(obj.id || obj.value, obj.value, obj.info)) {
      this.addItem(obj.id || obj.value, obj.value, obj.info);
    }
    this.input.value = "";
    return false;
  },

  addItem : function(key, value, info) {
    if (!key) {
      return;
    }
    var listItem = new Element("li");
    var displayedValue = new Element("label", {"class": "accepted-suggestion"});
    // insert input
    var inputOptions = {"type" : this.options.inputType, "name" : this.inputName, "value" : key};
    if (this.options.inputType == 'checkbox') {
      inputOptions.checked = 'checked';
    }
    displayedValue.insert({'bottom' : new Element("input", inputOptions)});
    // if the key should be displayed, insert it
    if (this.options.showKey) {
      displayedValue.insert({'bottom' : new Element("span", {"class": "key"}).update("[" + key.escapeHTML() + "]")});
      displayedValue.insert({'bottom' : new Element("span", {"class": "sep"}).update(" ")});
    }
    // insert the displayed value
    displayedValue.insert({'bottom' : new Element("span", {"class": "value"}).update(value.escapeHTML())});
    listItem.appendChild(displayedValue);
    // delete tool
    if (this.options.showDeleteTool) {
      var deleteTool = new Element("span", {'class': "delete-tool", "title" : "Delete this term"}).update('✖');
      deleteTool.observe('click', this.removeItem.bindAsEventListener(this));
      listItem.appendChild(deleteTool);
    }
    // tooltip, if information exists and the options state there should be a tooltip
    if (this.options.showTooltip && info) {
      listItem.appendChild(new Element("div", {class : "tooltip"}).update(info));
    }
    this.list.appendChild(listItem);
    this.updateListTools();
  },

  removeItem : function(event) {
    var item = event.findElement('li');
    item.remove();
    this.input.value = "";
    this.updateListTools();
  },

  clearAcceptedList : function () {
    this.list.update("");
    this.updateListTools();
  },

  updateListTools : function () {
    if (this.clearTool) {
      if (this.list.select('li .accepted-suggestion').length > 0) {
        this.clearTool.removeClassName('invisible');
      } else {
        this.clearTool.addClassName('invisible');
      }
    }
    if (this.options.enableSort && this.list.select('li .accepted-suggestion').length > 0 && typeof(Sortable) != "undefined") {
      Sortable.create(this.list);
    }
  }
});
  return MS;
}(MS || {}));
<|endoftext|>


<commit_before>/*
 * Extends L.Map to handle panning animations.
 */

L.Map.include({

	setView: function (center, zoom, options) {

		zoom = this._limitZoom(zoom);
		center = L.latLng(center);
		options = options || {};

		if (this._panAnim) {
			this._panAnim.stop();
		}

		if (this._loaded && !options.reset) {

			// try animating pan or zoom
			var animated = (this._zoom !== zoom) ?
				this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) :
				this._tryAnimatedPan(center, options.pan);

			if (animated) {
				// prevent resize handler call, the view will refresh after animation anyway
				clearTimeout(this._sizeTimer);
				return this;
			}
		}

		// animation didn't start, just reset the map view
		this._resetView(center, zoom);

		return this;
	},

	panBy: function (offset, options) {
		offset = L.point(offset).round();
		options = options || {};

		if (!offset.x && !offset.y) {
			return this;
		}

		if (!this._panAnim) {
			this._panAnim = new L.PosAnimation();

			this._panAnim.on({
				'step': this._onPanTransitionStep,
				'end': this._onPanTransitionEnd
			}, this);
		}

		// don't fire movestart if animating inertia
		if (!options.noMoveStart) {
			this.fire('movestart');
		}

		// animate pan unless animate: false specified
		if (options.animate !== false) {
			L.DomUtil.addClass(this._mapPane, 'leaflet-pan-anim');

			var newPos = this._getMapPanePos().subtract(offset);
			this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity);
		} else {
			this._rawPanBy(offset);
			this.fire('move').fire('moveend');
		}

		return this;
	},

	_onPanTransitionStep: function () {
		this.fire('move');
	},

	_onPanTransitionEnd: function () {
		L.DomUtil.removeClass(this._mapPane, 'leaflet-pan-anim');
		this.fire('moveend');
	},

	_tryAnimatedPan: function (center, options) {
		// difference between the new and current centers in pixels
		var offset = this._getCenterOffset(center)._floor();

		// don't animate too far unless animate: true specified in options
		if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; }

		this.panBy(offset, options);

		return true;
	}
});
<commit_msg>accept global animate option in setView<commit_after>/*
 * Extends L.Map to handle panning animations.
 */

L.Map.include({

	setView: function (center, zoom, options) {

		zoom = this._limitZoom(zoom);
		center = L.latLng(center);
		options = options || {};

		if (this._panAnim) {
			this._panAnim.stop();
		}

		if (this._loaded && !options.reset) {

			if (options.animate !== undefined) {
				options.zoom = L.extend({}, {animate: options.animate}, options.zoom);
				options.pan = L.extend({}, {animate: options.animate}, options.pan);
			}

			// try animating pan or zoom
			var animated = (this._zoom !== zoom) ?
				this._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) :
				this._tryAnimatedPan(center, options.pan);

			if (animated) {
				// prevent resize handler call, the view will refresh after animation anyway
				clearTimeout(this._sizeTimer);
				return this;
			}
		}

		// animation didn't start, just reset the map view
		this._resetView(center, zoom);

		return this;
	},

	panBy: function (offset, options) {
		offset = L.point(offset).round();
		options = options || {};

		if (!offset.x && !offset.y) {
			return this;
		}

		if (!this._panAnim) {
			this._panAnim = new L.PosAnimation();

			this._panAnim.on({
				'step': this._onPanTransitionStep,
				'end': this._onPanTransitionEnd
			}, this);
		}

		// don't fire movestart if animating inertia
		if (!options.noMoveStart) {
			this.fire('movestart');
		}

		// animate pan unless animate: false specified
		if (options.animate !== false) {
			L.DomUtil.addClass(this._mapPane, 'leaflet-pan-anim');

			var newPos = this._getMapPanePos().subtract(offset);
			this._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity);
		} else {
			this._rawPanBy(offset);
			this.fire('move').fire('moveend');
		}

		return this;
	},

	_onPanTransitionStep: function () {
		this.fire('move');
	},

	_onPanTransitionEnd: function () {
		L.DomUtil.removeClass(this._mapPane, 'leaflet-pan-anim');
		this.fire('moveend');
	},

	_tryAnimatedPan: function (center, options) {
		// difference between the new and current centers in pixels
		var offset = this._getCenterOffset(center)._floor();

		// don't animate too far unless animate: true specified in options
		if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; }

		this.panBy(offset, options);

		return true;
	}
});
<|endoftext|>


<commit_before>var helper = require("../../helper");
var validator = require('dl-models').validator.master;
var validatorPurchasing = require('dl-models').validator.purchasing;
var UnitReceiptNoteManager = require("../../../src/managers/purchasing/unit-receipt-note-manager");
var unitReceiptNoteManager = null;
var unitReceiptNote = require("../../data-util/purchasing/unit-receipt-note-data-util");
require("should");

before('#00. connect db', function (done) {
    helper.getDb()
        .then(db => {
            unitReceiptNoteManager = new UnitReceiptNoteManager(db, {
                username: 'unit-test'
            });
            done();
        })
        .catch(e => {
            done(e);
        })
});

var createdData;
it('#01. should success when create new data', function (done) {
    unitReceiptNote.getNewData()
        .then((data) => unitReceiptNoteManager.create(data))
        .then((id) => {
            id.should.be.Object();
            createdId = id;
            done();
        })
        .catch((e) => {
            done(e);
        });
});

it('#02. should error when create new data with same code', function (done) {
    var data = Object.assign({}, createdData);
    delete data._id;
    unitReceiptNoteManager.create(data)
        .then(id => {
            id.should.be.Object();
            done();
        })
        .catch(e => {
            try {
                done();
            }
            catch (ex) {
                done(ex);
            }
        })
});
it('#03. should error when create new blank data', function (done) {
    unitReceiptNoteManager.create({})
        .then(id => {
            id.should.be.Object();
            done();
        })
        .catch(e => {
            try {
                done();
            }
            catch (ex) {
                done(ex);
            }
        })
});

it("#04. should success when search data with filter", function (done) {
    unitReceiptNoteManager.read({
        keyword: unitReceiptNoteManager.supplier.name
    })
        .then((documents) => {
            //process documents
            documents.should.have.property("data");
            documents.data.should.be.instanceof(Array);
            documents.data.length.should.not.equal(0);
            done();
        })
        .catch((e) => {
            done(e);
        });
});<commit_msg>fix unit test<commit_after>var helper = require("../../helper");
var validator = require('dl-models').validator.master;
var validatorPurchasing = require('dl-models').validator.purchasing;
var UnitReceiptNoteManager = require("../../../src/managers/purchasing/unit-receipt-note-manager");
var unitReceiptNoteManager = null;
var unitReceiptNote = require("../../data-util/purchasing/unit-receipt-note-data-util");
require("should");

before('#00. connect db', function (done) {
    helper.getDb()
        .then(db => {
            unitReceiptNoteManager = new UnitReceiptNoteManager(db, {
                username: 'unit-test'
            });
            done();
        })
        .catch(e => {
            done(e);
        })
});

var createdData;var createdId;
it('#01. should success when create new data', function (done) {
    unitReceiptNote.getNewData()
        .then((data) => {unitReceiptNoteManager.create(data); createdData=data;})
        .then((id) => {
            id.should.be.Object();
            createdId = id;
            done();
        })
        .catch((e) => {
            done(e);
        });
});

it('#02. should error when create new data with same code', function (done) {
    var data = Object.assign({}, createdData);
    delete data._id;
    unitReceiptNoteManager.create(data)
        .then(id => {
            id.should.be.Object();
            done();
        })
        .catch(e => {
            try {
                done();
            }
            catch (ex) {
                done(ex);
            }
        })
});
it('#03. should error when create new blank data', function (done) {
    unitReceiptNoteManager.create({})
        .then(id => {
            id.should.be.Object();
            done();
        })
        .catch(e => {
            try {
                done();
            }
            catch (ex) {
                done(ex);
            }
        })
});

it("#04. should success when search data with filter", function (done) {
    unitReceiptNoteManager.read({
        keyword: createdData.supplier.name
    })
        .then((documents) => {
            //process documents
            documents.should.have.property("data");
            documents.data.should.be.instanceof(Array);
            documents.data.length.should.not.equal(0);
            done();
        })
        .catch((e) => {
            done(e);
        });
});<|endoftext|>


<commit_before>/*global jsobj, describe, xdescribe, it, xit, expect, beforeEach */
/*jslint plusplus: true */

(function () {
	"use strict";

	describe("rule-restricted-possible-value member", function () {
		it("exists in jsobj namespace", function () {
			expect(jsobj.rules.restrictedPossibleValue).toBeDefined();
		});

		it("is a function", function () {
			expect(typeof jsobj.rules.restrictedPossibleValue).toBe("function");
		});
	});

	describe("rule-restricted-possible-value function", function () {
		function listSolved(grid) {
			var solved = [], row, cell, rowCells;
			for (row = 0; row < 9; row++) {
				rowCells = grid.hRow(row).cells();
				for (cell = 0; cell < 9; cell++) {
					if (rowCells[cell].value() !== undefined) {
						solved.push(rowCells[cell]);
					}
				}
			}
			return solved;
		}

		function countPossibles(grid) {
			var allrows, row, cells, cell, posscount = 0;

			for (row = 0; row < grid.rows.length; row++) {
				cells = grid.rows[row].cells();
				for (cell = 0; cell < cells.length; cell++) {
					posscount += cells[cell].possibleValues().length;
				}
			}
			return posscount;
		}

		it("does nothing to an empty grid", function () {
			var grid = new jsobj.Grid().addSeeds([]);

			jsobj.rules.restrictedPossibleValue(grid);

			expect(listSolved(grid).length).toBe(0);
			expect(countPossibles(grid)).toBe(9 * 9 * 9);
		});

		it("removes possible values from elswhere in block when restricted to a row", function () {
			var grid = new jsobj.Grid(), solved, possible, poss70, poss71, poss72;

			grid.hRow(6).cells()[4].setValue(9);							//    012 345 678
			grid.hRow(8).cells()[2].setValue(1);
			grid.hRow(8).cells()[3].setValue(2);		                    // 0  --- --- ---
			grid.hRow(8).cells()[5].setValue(3);                            // 1  --- --- ---
			grid.hRow(8).cells()[6].setValue(4);                            // 2  --- --- ---
			grid.hRow(8).cells()[7].setValue(5);
			grid.hRow(8).cells()[8].setValue(6);                            // 3  --- --- ---
														                    // 4  --- --- ---
			solved = listSolved(grid).length;                               // 5  --- --- ---
			possible = countPossibles(grid);
			poss70 = grid.rows[7].cells()[0].possibleValues().length;       // 6  --- -9- ---
			poss71 = grid.rows[7].cells()[1].possibleValues().length;       // 7  ~~~ --- ---
			poss72 = grid.rows[7].cells()[2].possibleValues().length;       // 8  --1 2-3 456

			jsobj.rules.restrictedPossibleValue(grid);

			expect(listSolved(grid).length).toBe(solved);
			expect(countPossibles(grid)).toBe(possible - 3);
			expect(grid.rows[7].cells()[0].possibleValues().length).toBe(poss70 - 1);
			expect(grid.rows[7].cells()[1].possibleValues().length).toBe(poss71 - 1);
			expect(grid.rows[7].cells()[2].possibleValues().length).toBe(poss72 - 1);
			// value 9 is removed from row 7 first three cells
			expect(grid.rows[7].cells()[0].possibleValues()).toEqual([2, 3, 4, 5, 6, 7, 8]);
			expect(grid.rows[7].cells()[1].possibleValues()).toEqual([2, 3, 4, 5, 6, 7, 8]);
			expect(grid.rows[7].cells()[2].possibleValues()).toEqual([2, 3, 4, 5, 6, 7, 8]);
		});
	});
}());<commit_msg>add test for col in block to rule-restricted-possible-value<commit_after>/*global jsobj, describe, xdescribe, it, xit, expect, beforeEach */
/*jslint plusplus: true */

(function () {
	"use strict";

	describe("rule-restricted-possible-value member", function () {
		it("exists in jsobj namespace", function () {
			expect(jsobj.rules.restrictedPossibleValue).toBeDefined();
		});

		it("is a function", function () {
			expect(typeof jsobj.rules.restrictedPossibleValue).toBe("function");
		});
	});

	describe("rule-restricted-possible-value function", function () {
		function listSolved(grid) {
			var solved = [], row, cell, rowCells;
			for (row = 0; row < 9; row++) {
				rowCells = grid.hRow(row).cells();
				for (cell = 0; cell < 9; cell++) {
					if (rowCells[cell].value() !== undefined) {
						solved.push(rowCells[cell]);
					}
				}
			}
			return solved;
		}

		function countPossibles(grid) {
			var allrows, row, cells, cell, posscount = 0;

			for (row = 0; row < grid.rows.length; row++) {
				cells = grid.rows[row].cells();
				for (cell = 0; cell < cells.length; cell++) {
					posscount += cells[cell].possibleValues().length;
				}
			}
			return posscount;
		}

		it("does nothing to an empty grid", function () {
			var grid = new jsobj.Grid().addSeeds([]);

			jsobj.rules.restrictedPossibleValue(grid);

			expect(listSolved(grid).length).toBe(0);
			expect(countPossibles(grid)).toBe(9 * 9 * 9);
		});

		it("removes possible values from elswhere in block when restricted to a row in that block", function () {
			var grid = new jsobj.Grid(), solved, possible, poss70, poss71, poss72;

			grid.hRow(6).cells()[4].setValue(9);							//    012 345 678
			grid.hRow(8).cells()[2].setValue(1);
			grid.hRow(8).cells()[3].setValue(2);		                    // 0  --- --- ---
			grid.hRow(8).cells()[5].setValue(3);                            // 1  --- --- ---
			grid.hRow(8).cells()[6].setValue(4);                            // 2  --- --- ---
			grid.hRow(8).cells()[7].setValue(5);
			grid.hRow(8).cells()[8].setValue(6);                            // 3  --- --- ---
														                    // 4  --- --- ---
			solved = listSolved(grid).length;                               // 5  --- --- ---
			possible = countPossibles(grid);
			poss70 = grid.rows[7].cells()[0].possibleValues().length;       // 6  --- -9- ---
			poss71 = grid.rows[7].cells()[1].possibleValues().length;       // 7  ~~~ --- ---
			poss72 = grid.rows[7].cells()[2].possibleValues().length;       // 8  --1 2-3 456

			jsobj.rules.restrictedPossibleValue(grid);

			expect(listSolved(grid).length).toBe(solved);
			expect(countPossibles(grid)).toBe(possible - 3);
			expect(grid.rows[7].cells()[0].possibleValues().length).toBe(poss70 - 1);
			expect(grid.rows[7].cells()[1].possibleValues().length).toBe(poss71 - 1);
			expect(grid.rows[7].cells()[2].possibleValues().length).toBe(poss72 - 1);
			// value 9 is removed from row 7 first three cells
			expect(grid.rows[7].cells()[0].possibleValues()).toEqual([2, 3, 4, 5, 6, 7, 8]);
			expect(grid.rows[7].cells()[1].possibleValues()).toEqual([2, 3, 4, 5, 6, 7, 8]);
			expect(grid.rows[7].cells()[2].possibleValues()).toEqual([2, 3, 4, 5, 6, 7, 8]);
		});

		it("removes possible values from elswhere in col when restricted to a block in that col", function () {
			var grid = new jsobj.Grid(), solved, possible, poss65, poss75, poss85;

			grid.hRow(1).cells()[3].setValue(9);							//    012 345 678
			grid.hRow(3).cells()[3].setValue(1);
			grid.hRow(3).cells()[4].setValue(2);		                    // 0  --- --- ---
			grid.hRow(4).cells()[4].setValue(3);                            // 1  --- 9-- ---
			grid.hRow(4).cells()[5].setValue(4);                            // 2  --- --- ---
			grid.hRow(5).cells()[3].setValue(5);
			grid.hRow(5).cells()[4].setValue(6);                            // 3  --- 12- ---
														                    // 4  --- -34 ---
			solved = listSolved(grid).length;                               // 5  --- 56- ---
			possible = countPossibles(grid);
			poss65 = grid.rows[6].cells()[5].possibleValues().length;       // 6  --- --~ ---
			poss75 = grid.rows[7].cells()[5].possibleValues().length;       // 7  --- --~ ---
			poss85 = grid.rows[8].cells()[5].possibleValues().length;       // 8  --- --~ ---
2
			jsobj.rules.restrictedPossibleValue(grid);

			expect(listSolved(grid).length).toBe(solved);
			expect(countPossibles(grid)).toBe(possible - 3);
			expect(grid.rows[6].cells()[5].possibleValues().length).toBe(poss65 - 1);
			expect(grid.rows[7].cells()[5].possibleValues().length).toBe(poss75 - 1);
			expect(grid.rows[8].cells()[5].possibleValues().length).toBe(poss85 - 1);
			// value 9 is removed from col 5 last three cells
			expect(grid.rows[6].cells()[5].possibleValues()).toEqual([1, 2, 3, 5, 6, 7, 8]);
			expect(grid.rows[7].cells()[5].possibleValues()).toEqual([1, 2, 3, 5, 6, 7, 8]);
			expect(grid.rows[8].cells()[5].possibleValues()).toEqual([1, 2, 3, 5, 6, 7, 8]);
		});
	});
}());<|endoftext|>


<commit_before>function Rubik(element, background) {
  background = background || 0x303030;

  var debug = false;

  var width = element.innerWidth(),
      height = element.innerHeight();

  /*** three.js boilerplate ***/
  var scene = new THREE.Scene(),
      camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000),
      renderer = new THREE.WebGLRenderer({ antialias: true });

  renderer.setClearColor(background, 1.0);
  renderer.setSize(width, height);
  renderer.shadowMapEnabled = true;
  element.append(renderer.domElement);

  camera.position = new THREE.Vector3(-30, 40, 30);
  camera.lookAt(scene.position);
  THREE.Object3D._threexDomEvent.camera(camera);

  /*** Lights ***/
  scene.add(new THREE.AmbientLight(0xffffff));
  //TODO: add a spotlight that takes the orbitcontrols into account to stay "static"

  /*** Camera controls ***/
  var orbitControl = new THREE.OrbitControls(camera, renderer.domElement);

  function enableCameraControl() {
    orbitControl.noRotate = false;
  }

  function disableCameraControl() {
    orbitControl.noRotate = true;
  }

  /*** Debug aids ***/
  if(debug) {
    scene.add(new THREE.AxisHelper( 20 ));
  }

  /*** Click handling ***/
  //Return the axis which has the greatest maginitude for the vector v
  function principalComponent(v) {
    var maxAxis = 'x',
        max = Math.abs(v.x);
    if(Math.abs(v.y) > max) {
      maxAxis = 'y';
      max = Math.abs(v.y);
    }
    if(Math.abs(v.z) > max) {
      maxAxis = 'z';
      max = Math.abs(v.z);
    }
    return maxAxis;
  }

  //The currently clicked cube's position
  // and the axis we will rotate around
  var clickVector, clickFace;

  var onCubeMouseDown = function(e, cube) {
    disableCameraControl();

    clickVector = cube.rubikPosition.clone();

    var centroid = e.targetFace.centroid.clone();
    centroid.applyMatrix4(cube.matrixWorld);

    //Which face (of the overall cube) did we click on?
    if(nearlyEqual(Math.abs(centroid.x), maxExtent))
      clickFace = 'x';
    else if(nearlyEqual(Math.abs(centroid.y), maxExtent))
      clickFace = 'y';
    else if(nearlyEqual(Math.abs(centroid.z), maxExtent))
      clickFace = 'z';
  };

  //Matrix of the axis that we should rotate for
  // each face-drag action
  //    F a c e
  // D    X Y Z
  // r  X - Z Y
  // a  Y Z - X
  // g  Z Y X -
  var transitions = {
    'x': {'y': 'z', 'z': 'y'},
    'y': {'x': 'z', 'z': 'x'},
    'z': {'x': 'y', 'y': 'x'}
  }

  //TODO: handle "exit cube whilst dragging" events too
  var onCubeMouseUp = function(e, cube) {

    //TODO: use the actual mouse end coordinates for finer drag control
    var dragVector = cube.rubikPosition.clone();
    dragVector.sub(clickVector);

    //Don't move if the "drag" was too small, to allow for
    // click-and-change-mind.
    if(dragVector.length() > cubeSize) {
      //Rorate with the most significant component of the drag vector
      var maxAxis = principalComponent(dragVector),
          rotateAxis = transitions[clickFace][maxAxis],
          direction = dragVector[maxAxis] >= 0 ? 1 : -1;

      //Reverse direction of some rotations for intuitive control
      //TODO: find a general solution!
      if(clickFace == 'z' && rotateAxis == 'x' ||
         clickFace == 'x' && rotateAxis == 'z' ||
         clickFace == 'y' && rotateAxis == 'z')
        direction *= -1;

      if(clickFace == 'x' && clickVector.x > 0 ||
         clickFace == 'y' && clickVector.y < 0 ||
         clickFace == 'z' && clickVector.z < 0)
        direction *= -1;

      //startMove(rotateAxis, direction);
      pushMove(cube, clickVector.clone(), rotateAxis, direction);
      startNextMove();
      enableCameraControl();
    } else {
      console.log("Drag me some more please!");
    }
  };

  /*** Build 27 cubes ***/
  //TODO: colour the insides of all of the faces black
  // (probably colour all faces black to begin with, then "whitelist" exterior faces)
  var colours = [0xC41E3A, 0x009E60, 0x0051BA, 0xFF5800, 0xFFD500, 0xFFFFFF],
      faceMaterials = colours.map(function(c) {
        return new THREE.MeshLambertMaterial({ color: c , ambient: c });
      }),
      cubeMaterials = new THREE.MeshFaceMaterial(faceMaterials);

  var cubeSize = 3,
      dimensions = 3,
      spacing = 0.5;

  var increment = cubeSize + spacing,
      maxExtent = (cubeSize * dimensions + spacing * (dimensions - 1)) / 2,
      allCubes = [];

  function newCube(x, y, z) {
    var cubeGeometry = new THREE.CubeGeometry(cubeSize, cubeSize, cubeSize);
    var cube = new THREE.Mesh(cubeGeometry, cubeMaterials);
    cube.castShadow = true;

    cube.position = new THREE.Vector3(x, y, z);
    cube.rubikPosition = cube.position.clone();

    cube.on('mousedown', function(e) {
      onCubeMouseDown(e, cube);
    });

    cube.on('mouseup', function(e) {
      onCubeMouseUp(e, cube);
    });

    scene.add(cube);
    allCubes.push(cube);
  }

  for(var i = 0; i < dimensions; i ++) {
    for(var j = 0; j < dimensions; j ++) {
      for(var k = 0; k < dimensions; k ++) {

        //TODO - generalise the -1 offset to work with any size RC (-1 is for 3*3*3). I think it's (n-1)/2.
        var x = (i - 1) * increment,
            y = (j - 1) * increment,
            z = (k - 1) * increment;

        newCube(x, y, z);
      }
    }
  }

  /*** Manage transition states ***/

  //TODO: encapsulate each transition into a "Move" object, and keep a stack of moves
  // - that will allow us to easily generalise to other states like a "hello" state which
  // could animate the cube, or a "complete" state which could do an animation to celebrate
  // solving.
  var moveQueue = [],
      completedMoveStack = [],
      currentMove;

  //Are we in the middle of a transition?
  var isMoving = false;
  var moveAxis, moveN, moveDirection;
  var rotationSpeed = 0.1;

  //http://stackoverflow.com/questions/20089098/three-js-adding-and-removing-children-of-rotated-objects
  var pivot = new THREE.Object3D(),
      activeGroup = [];

  function nearlyEqual(a, b, d) {
    d = d || 0.001;
    return Math.abs(a - b) <= d;
  }

  //Select the plane of cubes that aligns with clickVector
  // on the given axis
  function setActiveGroup(axis) {
    if(clickVector) {
      activeGroup = [];

      allCubes.forEach(function(cube) {
        if(nearlyEqual(cube.rubikPosition[axis], clickVector[axis])) {
          activeGroup.push(cube);
        }
      });
    } else {
      console.log("Nothing to move!");
    }
  }

  var pushMove = function(cube, clickVector, axis, direction) {
    moveQueue.push({ cube: cube, vector: clickVector, axis: axis, direction: direction });
  }

  var startNextMove = function() {
    var nextMove = moveQueue.pop();

    if(nextMove) {
      clickVector = nextMove.vector;

      var direction = nextMove.direction || 1,
          axis = nextMove.axis;

      if(clickVector) {

        if(!isMoving) {
          isMoving = true;
          moveAxis = axis;
          moveDirection = direction;

          setActiveGroup(axis);

          pivot.rotation.set(0,0,0);
          pivot.updateMatrixWorld();
          scene.add(pivot);

          activeGroup.forEach(function(e) {
            THREE.SceneUtils.attach(e, scene, pivot);
          });

          currentMove = nextMove;

        } else {
          console.log("Already moving!");
        }
      } else {
        console.log("Nothing to move!");
      }
    }
  }

  function doMove() {
    //Move a quarter turn then stop
    if(pivot.rotation[moveAxis] >= Math.PI / 2) {
      //Compensate for overshoot. TODO: use a tweening library
      pivot.rotation[moveAxis] = Math.PI / 2;
      moveComplete();
    } else if(pivot.rotation[moveAxis] <= Math.PI / -2) {
      pivot.rotation[moveAxis] = Math.PI / -2;
      moveComplete()
    } else {
      pivot.rotation[moveAxis] += (moveDirection * rotationSpeed);
    }
  }

  var moveComplete = function() {
    isMoving = false;
    moveAxis, moveN, moveDirection = undefined;
    clickVector = undefined;

    pivot.updateMatrixWorld();
    scene.remove(pivot);
    activeGroup.forEach(function(cube) {
      cube.updateMatrixWorld();

      cube.rubikPosition = cube.position.clone();
      cube.rubikPosition.applyMatrix4(pivot.matrixWorld);

      THREE.SceneUtils.detach(cube, pivot, scene);
    });

    completedMoveStack.push(currentMove);
    // console.log(completedMoveStack);

    //Are there any more queued moves?
    startNextMove();
  }

  function render() {

    //States
    //TODO: generalise to something like "activeState.tick()" - see comments
    // on encapsulation above
    if(isMoving) {
      doMove();
    }

    renderer.render(scene, camera);
    requestAnimationFrame(render);
  }

  /*** Util ***/
  function randomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
  }

  //Go!
  render();

  //Public API
  return {
    shuffle: function() {
      function randomAxis() {
        return ['x', 'y', 'z'][randomInt(0,2)];
      }

      function randomDirection() {
        var x = randomInt(0,1);
        if(x == 0) x = -1;
        return x;
      }

      function randomCube() {
        //TODO: generalise
        var i = randomInt(0, 26);
        //TODO: don't return a centre cube
        return allCubes[i];
      }

      var nMoves = randomInt(10, 40);
      for(var i = 0; i < nMoves; i ++) {
        //TODO: don't reselect the same axis?
        var cube = randomCube();
        pushMove(cube, cube.position.clone(), randomAxis(), randomDirection());
      }

      startNextMove();
    },

    //A naive solver - step backwards through all completed steps
    solve: function() {
      completedMoveStack.forEach(function(move) {
        pushMove(move.cube, move.vector, move.axis, move.direction * -1);
      });

      completedMoveStack = [];
      startNextMove();

      //TODO: we should clear the completed move stack after all of the moves complete
      // - fire an event for moveQueue depleted?
    }
  }
}

<commit_msg>Solver tweak<commit_after>function Rubik(element, background) {
  background = background || 0x303030;

  var debug = false;

  var width = element.innerWidth(),
      height = element.innerHeight();

  /*** three.js boilerplate ***/
  var scene = new THREE.Scene(),
      camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000),
      renderer = new THREE.WebGLRenderer({ antialias: true });

  renderer.setClearColor(background, 1.0);
  renderer.setSize(width, height);
  renderer.shadowMapEnabled = true;
  element.append(renderer.domElement);

  camera.position = new THREE.Vector3(-30, 40, 30);
  camera.lookAt(scene.position);
  THREE.Object3D._threexDomEvent.camera(camera);

  /*** Lights ***/
  scene.add(new THREE.AmbientLight(0xffffff));
  //TODO: add a spotlight that takes the orbitcontrols into account to stay "static"

  /*** Camera controls ***/
  var orbitControl = new THREE.OrbitControls(camera, renderer.domElement);

  function enableCameraControl() {
    orbitControl.noRotate = false;
  }

  function disableCameraControl() {
    orbitControl.noRotate = true;
  }

  /*** Debug aids ***/
  if(debug) {
    scene.add(new THREE.AxisHelper( 20 ));
  }

  /*** Click handling ***/
  //Return the axis which has the greatest maginitude for the vector v
  function principalComponent(v) {
    var maxAxis = 'x',
        max = Math.abs(v.x);
    if(Math.abs(v.y) > max) {
      maxAxis = 'y';
      max = Math.abs(v.y);
    }
    if(Math.abs(v.z) > max) {
      maxAxis = 'z';
      max = Math.abs(v.z);
    }
    return maxAxis;
  }

  //The currently clicked cube's position
  // and the axis we will rotate around
  var clickVector, clickFace;

  var onCubeMouseDown = function(e, cube) {
    disableCameraControl();

    clickVector = cube.rubikPosition.clone();

    var centroid = e.targetFace.centroid.clone();
    centroid.applyMatrix4(cube.matrixWorld);

    //Which face (of the overall cube) did we click on?
    if(nearlyEqual(Math.abs(centroid.x), maxExtent))
      clickFace = 'x';
    else if(nearlyEqual(Math.abs(centroid.y), maxExtent))
      clickFace = 'y';
    else if(nearlyEqual(Math.abs(centroid.z), maxExtent))
      clickFace = 'z';
  };

  //Matrix of the axis that we should rotate for
  // each face-drag action
  //    F a c e
  // D    X Y Z
  // r  X - Z Y
  // a  Y Z - X
  // g  Z Y X -
  var transitions = {
    'x': {'y': 'z', 'z': 'y'},
    'y': {'x': 'z', 'z': 'x'},
    'z': {'x': 'y', 'y': 'x'}
  }

  //TODO: handle "exit cube whilst dragging" events too
  var onCubeMouseUp = function(e, cube) {

    //TODO: use the actual mouse end coordinates for finer drag control
    var dragVector = cube.rubikPosition.clone();
    dragVector.sub(clickVector);

    //Don't move if the "drag" was too small, to allow for
    // click-and-change-mind.
    if(dragVector.length() > cubeSize) {
      //Rorate with the most significant component of the drag vector
      var maxAxis = principalComponent(dragVector),
          rotateAxis = transitions[clickFace][maxAxis],
          direction = dragVector[maxAxis] >= 0 ? 1 : -1;

      //Reverse direction of some rotations for intuitive control
      //TODO: find a general solution!
      if(clickFace == 'z' && rotateAxis == 'x' ||
         clickFace == 'x' && rotateAxis == 'z' ||
         clickFace == 'y' && rotateAxis == 'z')
        direction *= -1;

      if(clickFace == 'x' && clickVector.x > 0 ||
         clickFace == 'y' && clickVector.y < 0 ||
         clickFace == 'z' && clickVector.z < 0)
        direction *= -1;

      //startMove(rotateAxis, direction);
      pushMove(cube, clickVector.clone(), rotateAxis, direction);
      startNextMove();
      enableCameraControl();
    } else {
      console.log("Drag me some more please!");
    }
  };

  /*** Build 27 cubes ***/
  //TODO: colour the insides of all of the faces black
  // (probably colour all faces black to begin with, then "whitelist" exterior faces)
  var colours = [0xC41E3A, 0x009E60, 0x0051BA, 0xFF5800, 0xFFD500, 0xFFFFFF],
      faceMaterials = colours.map(function(c) {
        return new THREE.MeshLambertMaterial({ color: c , ambient: c });
      }),
      cubeMaterials = new THREE.MeshFaceMaterial(faceMaterials);

  var cubeSize = 3,
      dimensions = 3,
      spacing = 0.5;

  var increment = cubeSize + spacing,
      maxExtent = (cubeSize * dimensions + spacing * (dimensions - 1)) / 2,
      allCubes = [];

  function newCube(x, y, z) {
    var cubeGeometry = new THREE.CubeGeometry(cubeSize, cubeSize, cubeSize);
    var cube = new THREE.Mesh(cubeGeometry, cubeMaterials);
    cube.castShadow = true;

    cube.position = new THREE.Vector3(x, y, z);
    cube.rubikPosition = cube.position.clone();

    cube.on('mousedown', function(e) {
      onCubeMouseDown(e, cube);
    });

    cube.on('mouseup', function(e) {
      onCubeMouseUp(e, cube);
    });

    scene.add(cube);
    allCubes.push(cube);
  }

  for(var i = 0; i < dimensions; i ++) {
    for(var j = 0; j < dimensions; j ++) {
      for(var k = 0; k < dimensions; k ++) {

        //TODO - generalise the -1 offset to work with any size RC (-1 is for 3*3*3). I think it's (n-1)/2.
        var x = (i - 1) * increment,
            y = (j - 1) * increment,
            z = (k - 1) * increment;

        newCube(x, y, z);
      }
    }
  }

  /*** Manage transition states ***/

  //TODO: encapsulate each transition into a "Move" object, and keep a stack of moves
  // - that will allow us to easily generalise to other states like a "hello" state which
  // could animate the cube, or a "complete" state which could do an animation to celebrate
  // solving.
  var moveQueue = [],
      completedMoveStack = [],
      currentMove,
      clearStackAfterThisQueue = false;

  //Are we in the middle of a transition?
  var isMoving = false,
      moveAxis, moveN, moveDirection,
      rotationSpeed = 0.1;

  //http://stackoverflow.com/questions/20089098/three-js-adding-and-removing-children-of-rotated-objects
  var pivot = new THREE.Object3D(),
      activeGroup = [];

  function nearlyEqual(a, b, d) {
    d = d || 0.001;
    return Math.abs(a - b) <= d;
  }

  //Select the plane of cubes that aligns with clickVector
  // on the given axis
  function setActiveGroup(axis) {
    if(clickVector) {
      activeGroup = [];

      allCubes.forEach(function(cube) {
        if(nearlyEqual(cube.rubikPosition[axis], clickVector[axis])) {
          activeGroup.push(cube);
        }
      });
    } else {
      console.log("Nothing to move!");
    }
  }

  var pushMove = function(cube, clickVector, axis, direction) {
    moveQueue.push({ cube: cube, vector: clickVector, axis: axis, direction: direction });
  }

  var startNextMove = function() {
    var nextMove = moveQueue.pop();

    if(nextMove) {
      clickVector = nextMove.vector;

      var direction = nextMove.direction || 1,
          axis = nextMove.axis;

      if(clickVector) {

        if(!isMoving) {
          isMoving = true;
          moveAxis = axis;
          moveDirection = direction;

          setActiveGroup(axis);

          pivot.rotation.set(0,0,0);
          pivot.updateMatrixWorld();
          scene.add(pivot);

          activeGroup.forEach(function(e) {
            THREE.SceneUtils.attach(e, scene, pivot);
          });

          currentMove = nextMove;
        } else {
          console.log("Already moving!");
        }
      } else {
        console.log("Nothing to move!");
      }
    } else {
      if(clearStackAfterThisQueue) {
        completedMoveStack = [];
        clearStackAfterThisQueue = false;
      }
    }
  }

  function doMove() {
    //Move a quarter turn then stop
    if(pivot.rotation[moveAxis] >= Math.PI / 2) {
      //Compensate for overshoot. TODO: use a tweening library
      pivot.rotation[moveAxis] = Math.PI / 2;
      moveComplete();
    } else if(pivot.rotation[moveAxis] <= Math.PI / -2) {
      pivot.rotation[moveAxis] = Math.PI / -2;
      moveComplete()
    } else {
      pivot.rotation[moveAxis] += (moveDirection * rotationSpeed);
    }
  }

  var moveComplete = function() {
    isMoving = false;
    moveAxis, moveN, moveDirection = undefined;
    clickVector = undefined;

    pivot.updateMatrixWorld();
    scene.remove(pivot);
    activeGroup.forEach(function(cube) {
      cube.updateMatrixWorld();

      cube.rubikPosition = cube.position.clone();
      cube.rubikPosition.applyMatrix4(pivot.matrixWorld);

      THREE.SceneUtils.detach(cube, pivot, scene);
    });

    completedMoveStack.push(currentMove);

    //Are there any more queued moves?
    startNextMove();
  }

  function render() {

    //States
    //TODO: generalise to something like "activeState.tick()" - see comments
    // on encapsulation above
    if(isMoving) {
      doMove();
    }

    renderer.render(scene, camera);
    requestAnimationFrame(render);
  }

  /*** Util ***/
  function randomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1) + min);
  }

  //Go!
  render();

  //Public API
  return {
    shuffle: function() {
      function randomAxis() {
        return ['x', 'y', 'z'][randomInt(0,2)];
      }

      function randomDirection() {
        var x = randomInt(0,1);
        if(x == 0) x = -1;
        return x;
      }

      function randomCube() {
        var i = randomInt(0, allCubes.length - 1);
        //TODO: don't return a centre cube
        return allCubes[i];
      }

      var nMoves = randomInt(10, 40);
      for(var i = 0; i < nMoves; i ++) {
        //TODO: don't reselect the same axis?
        var cube = randomCube();
        pushMove(cube, cube.position.clone(), randomAxis(), randomDirection());
      }

      startNextMove();
    },

    //A naive solver - step backwards through all completed steps
    solve: function() {
      //Don't remember the moves we're making whilst solving
      clearStackAfterThisQueue = true;
      completedMoveStack.forEach(function(move) {
        pushMove(move.cube, move.vector, move.axis, move.direction * -1);
      });

      completedMoveStack = [];
      startNextMove();

      //TODO: we should clear the completed move stack after all of the moves complete
      // - fire an event for moveQueue depleted?
    }
  }
}

<|endoftext|>


<commit_before>/**
 * Publications are highly app specific and as such Maka doesn't try
 * to implement any logic out of the box.  This file is simply to
 * provide a friendly reminder that you MAY need to have publications.
 */

import { Meteor } from 'meteor/meteor';
import { Harvests } from '../harvests.js';

Meteor.publish('harvests.public', function makasFunction() {
  return Harvests.find({});
});
<commit_msg>Use annonymous function<commit_after>/**
 * Publications are highly app specific and as such Maka doesn't try
 * to implement any logic out of the box.  This file is simply to
 * provide a friendly reminder that you MAY need to have publications.
 */

import { Meteor } from 'meteor/meteor';
import { Harvests } from '../harvests.js';

Meteor.publish('harvests.public', function() {
  return Harvests.find({});
});
<|endoftext|>


<commit_before>// @todo: add publications
<commit_msg>Add publications<commit_after>import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import { Projects } from './../Projects.js';

const limitQueryToUserProjects = (userId, query) => {
    const user = Meteor.users.findOne(userId);
    const { isAdmin } = user;
    query = isAdmin ? query : query.members = user._id;
    return query;
};

Meteor.publish('projectList', function publishProjectList() {
    if (!this.userId) {
        return this.ready();
    }
    const query = {};
    limitQueryToUserProjects(this.userId, query);

    const options = {
        fields: {
            name: 1,
        },
    };

    return Projects.find(query, options);
});

Meteor.publish('singleProject', function publishSingleProject(projectId) {
    check(projectId, String);

    if (!this.userId) {
        return this.ready();
    }

    const query = {
        _id: projectId,
    };

    limitQueryToUserProjects(this.userId, query);

    const options = {};

    return Projects.find(query, options);
});
<|endoftext|>


<commit_before>module.exports = {

    mixins: [
        require('../lib/package')
    ],

    data: function () {

        return _.extend({
            package: {},
            view: false,
            updates: null,
            search: this.$session.get(this.$options.name + '.search', ''),
            status: ''
        }, window.$data);
    },

    ready: function () {
        this.load();
    },

    watch: {
        search: function (search) {
            this.$session.set(this.$options.name + '.search', search);
        }
    },

    methods: {

        load: function () {
            this.$set('status', 'loading');

            this.queryUpdates(this.packages).then(function (res) {
                var data = res.data;
                this.$set('updates', data.packages.length ? _.indexBy(data.packages, 'name') : null);
                this.$set('status', '');
            }, function () {
                this.$set('status', 'error');
            });
        },

        icon: function (pkg) {

            if (pkg.extra && pkg.extra.icon) {
                return pkg.url + '/' + pkg.extra.icon;
            } else {
                return this.$url('app/system/assets/images/placeholder-icon.svg');
            }

        },

        image: function (pkg) {

            if (pkg.extra && pkg.extra.image) {
                return pkg.url + '/' + pkg.extra.image;
            } else {
                return this.$url('app/system/assets/images/placeholder-800x600.svg');
            }

        },

        details: function (pkg) {
            this.$set('package', pkg);
            this.$refs.details.open();
        },

        settings: function (pkg) {

            if (!pkg.settings) {
                return;
            }

            var view, options;

            _.forIn(this.$options.components, function (component, name) {

                options = component.options || {};

                if (options.settings && pkg.settings === name) {
                    view = name;
                }

            });

            if (view) {

                this.$set('package', pkg);
                this.$set('view', view);
                this.$refs.settings.open();

            } else {
                window.location = pkg.settings;
            }

        },

        update: function (pkg) {
            var vm = this;

            this.install(pkg, this.packages, function (output) {
                if (output.status === 'success') {
                    vm.updates.$delete(pkg.name);
                }

                setTimeout(function () {
                    location.reload();
                }, 300);
            });
        }

    },

    filters: {

        empty: function (packages) {
            return Vue.filter('filterBy')(packages, this.search, 'title').length === 0;
        }

    },

    components: {

        'package-upload': require('./package-upload.vue'),
        'package-details': require('./package-details.vue')

    }

};
<commit_msg>packages - only check for updates if packages present<commit_after>module.exports = {

    mixins: [
        require('../lib/package')
    ],

    data: function () {

        return _.extend({
            package: {},
            view: false,
            updates: null,
            search: this.$session.get(this.$options.name + '.search', ''),
            status: ''
        }, window.$data);
    },

    ready: function () {
        this.load();
    },

    watch: {
        search: function (search) {
            this.$session.set(this.$options.name + '.search', search);
        }
    },

    methods: {

        load: function () {
            this.$set('status', 'loading');

            if (this.packages) {
                this.queryUpdates(this.packages).then(function (res) {
                    var data = res.data;
                    this.$set('updates', data.packages.length ? _.indexBy(data.packages, 'name') : null);
                    this.$set('status', '');
                }, function () {
                    this.$set('status', 'error');
                });
            }
        },

        icon: function (pkg) {

            if (pkg.extra && pkg.extra.icon) {
                return pkg.url + '/' + pkg.extra.icon;
            } else {
                return this.$url('app/system/assets/images/placeholder-icon.svg');
            }

        },

        image: function (pkg) {

            if (pkg.extra && pkg.extra.image) {
                return pkg.url + '/' + pkg.extra.image;
            } else {
                return this.$url('app/system/assets/images/placeholder-800x600.svg');
            }

        },

        details: function (pkg) {
            this.$set('package', pkg);
            this.$refs.details.open();
        },

        settings: function (pkg) {

            if (!pkg.settings) {
                return;
            }

            var view, options;

            _.forIn(this.$options.components, function (component, name) {

                options = component.options || {};

                if (options.settings && pkg.settings === name) {
                    view = name;
                }

            });

            if (view) {

                this.$set('package', pkg);
                this.$set('view', view);
                this.$refs.settings.open();

            } else {
                window.location = pkg.settings;
            }

        },

        update: function (pkg) {
            var vm = this;

            this.install(pkg, this.packages, function (output) {
                if (output.status === 'success') {
                    vm.updates.$delete(pkg.name);
                }

                setTimeout(function () {
                    location.reload();
                }, 300);
            });
        }

    },

    filters: {

        empty: function (packages) {
            return Vue.filter('filterBy')(packages, this.search, 'title').length === 0;
        }

    },

    components: {

        'package-upload': require('./package-upload.vue'),
        'package-details': require('./package-details.vue')

    }

};
<|endoftext|>


<commit_before>import React, { useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';

import Notification from 'components/Notification';
import Cover from './Cover';
import HomePage from './HomePage';
import StaticPage from './StaticPage';

export default function AdminPreviewStatic({ siteSettings, homepage, opencontent }) {
  const [isHomepage, setIsHomepage] = useState(true);

  const onClickHomepage = useCallback(() => setIsHomepage(true), [setIsHomepage]);
  const onClickOpenContent = useCallback(() => setIsHomepage(false), [setIsHomepage]);

  const clickHandler = useCallback(() => {
    setIsHomepage(!isHomepage);
  }, [isHomepage, setIsHomepage]);

  const StaticHeader = () => {
    const countryColorsSetting = siteSettings.find(setting => setting.name === 'header-country-colours');
    const countryColors = countryColorsSetting ? countryColorsSetting.value.split(' ') : [];
    return (

                <button type="button" onClick={clickHandler}>Open Content</button>

                Sample menu

                    Level 1 Page

                <form method="get" action="/search_results">

                    <input type="input" placeholder="Search" name="search" />
                    <button type="submit">Search</button>

                </form>

            <button type="button" className="logo" onClick={onClickHomepage}>
              Logo
            </button>

            <button type="button" className="logo" onClick={onClickHomepage}>
              Logo
            </button>

                  <button type="button" onClick={clickHandler}>Open Content</button>

                  Sample menu

                      Level 1 Page

                  <button type="button" className="search-button js-search-button">Search</button>

                  {!isHomepage && (
                    <>

                        <button type="button" onClick={onClickHomepage}>Home</button>

                        <button type="button" onClick={onClickOpenContent}>Open Content</button>

                    </>
                  )}

          {countryColors.map(color =>
)}

    );
  };

  return (

      <Notification
        type="warning"
        content="The content of this preview is not representative of the real content of the site."
        additionalContent={(
          <>
            Click here to preview the{' '}
            <button
              type="button"
              className={classnames({
                'c-button': true,
                '-monochrome': true,
                '-mini': true,
                '-outline': !isHomepage
              })}
              aria-pressed={isHomepage}
              onClick={onClickHomepage}
            >
              Homepage
            </button>{' '}
            or an{' '}
            <button
              type="button"
              className={classnames({
                'c-button': true,
                '-monochrome': true,
                '-mini': true,
                '-outline': isHomepage
              })}
              aria-pressed={!isHomepage}
              onClick={onClickOpenContent}
            >
              Open Content
            </button>{' '}
            page.
          </>
        )}
        closeable={false}
        onClose={() => {}}
      />
      <StaticHeader />
      <Cover {...(isHomepage ? homepage.cover : opencontent.cover)} />
      {isHomepage ? <HomePage {...homepage} /> : <StaticPage {...opencontent} />}

  );
}

AdminPreviewStatic.propTypes = {
  siteSettings: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  homepage: PropTypes.shape({}).isRequired,
  opencontent: PropTypes.shape({}).isRequired,
};
<commit_msg>Add the preview of the Show login setting<commit_after>import React, { useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';

import Notification from 'components/Notification';
import Cover from './Cover';
import HomePage from './HomePage';
import StaticPage from './StaticPage';

export default function AdminPreviewStatic({ siteSettings, homepage, opencontent }) {
  const [isHomepage, setIsHomepage] = useState(true);

  const onClickHomepage = useCallback(() => setIsHomepage(true), [setIsHomepage]);
  const onClickOpenContent = useCallback(() => setIsHomepage(false), [setIsHomepage]);

  const clickHandler = useCallback(() => {
    setIsHomepage(!isHomepage);
  }, [isHomepage, setIsHomepage]);

  const StaticHeader = () => {
    const countryColorsSetting = siteSettings.find(setting => setting.name === 'header-country-colours');
    const showLoginSetting = siteSettings.find(setting => setting.name === 'header_login_enabled');

    const countryColors = countryColorsSetting ? countryColorsSetting.value.split(' ') : [];
    const showLogin = showLoginSetting ? showLoginSetting.value === 'true' : true;

    return (

                <button type="button" onClick={clickHandler}>Open Content</button>

                Sample menu

                    Level 1 Page

                <form method="get" action="/search_results">

                    <input type="input" placeholder="Search" name="search" />
                    <button type="submit">Search</button>

                </form>

            <button type="button" className="logo" onClick={onClickHomepage}>
              Logo
            </button>

            <button type="button" className="logo" onClick={onClickHomepage}>
              Logo
            </button>

                  <button type="button" onClick={clickHandler}>Open Content</button>

                  Sample menu

                      Level 1 Page

                  <button type="button" className="search-button js-search-button">Search</button>

                {showLogin ?
Login
 : null}

                  {!isHomepage && (
                    <>

                        <button type="button" onClick={onClickHomepage}>Home</button>

                        <button type="button" onClick={onClickOpenContent}>Open Content</button>

                    </>
                  )}

          {countryColors.map(color =>
)}

    );
  };

  return (

      <Notification
        type="warning"
        content="The content of this preview is not representative of the real content of the site."
        additionalContent={(
          <>
            Click here to preview the{' '}
            <button
              type="button"
              className={classnames({
                'c-button': true,
                '-monochrome': true,
                '-mini': true,
                '-outline': !isHomepage
              })}
              aria-pressed={isHomepage}
              onClick={onClickHomepage}
            >
              Homepage
            </button>{' '}
            or an{' '}
            <button
              type="button"
              className={classnames({
                'c-button': true,
                '-monochrome': true,
                '-mini': true,
                '-outline': isHomepage
              })}
              aria-pressed={!isHomepage}
              onClick={onClickOpenContent}
            >
              Open Content
            </button>{' '}
            page.
          </>
        )}
        closeable={false}
        onClose={() => {}}
      />
      <StaticHeader />
      <Cover {...(isHomepage ? homepage.cover : opencontent.cover)} />
      {isHomepage ? <HomePage {...homepage} /> : <StaticPage {...opencontent} />}

  );
}

AdminPreviewStatic.propTypes = {
  siteSettings: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  homepage: PropTypes.shape({}).isRequired,
  opencontent: PropTypes.shape({}).isRequired,
};
<|endoftext|>


<commit_before>'use strict';

// Intrinsic modules.
var url = require('url');
var fs = require('fs');
var path = require('path');

// NPM modules
var Promise = require('bluebird');
var _ = require('lodash');

// "Constants"
var PLUGIN_NAME = 'kalabox-plugin-pantheon';

module.exports = function(kbox) {

  kbox.whenApp(function(app) {

    // Grab the terminus client
    var Terminus = require('./terminus.js');
    var terminus = new Terminus(kbox, app);

    // Grab delegated helpers
    var pathToRoot = path.resolve(__dirname, '..', '..', '..');
    var pathToNode = path.join(pathToRoot, 'node_modules');
    var Git = require(pathToNode + '/kalabox-plugin-git/lib/git.js');
    var git = new Git(kbox, app);
    var Rsync = require(pathToNode + '/kalabox-plugin-rsync/lib/rsync.js');
    var rsync = new Rsync(kbox, app);

    // Grab some kalabox modules
    var events = kbox.core.events;
    var engine = kbox.engine;

    // Nobody expects the Spanish Inquisition!
    var inquirer = require('inquirer');

    /*
     * Pull down our sites code
     */
    var pullCode = function(site, env, type) {

      // the pantheon site UUID
      var siteid = null;
      var repo = null;

      // Check to see what our connection mode is
      return terminus.getConnectionMode(site, env)
        // Set the connection mode to git if needed
        // and then try again
        .then(function(connectionMode) {
          var modeSplit = connectionMode.split(':');
          var mode = modeSplit[1].trim().toLowerCase();
          if (mode !== 'git') {
            // @todo: actually test this part
            return terminus.setConnectionMode(site, env)
              .then(function(data) {
                pullCode(site, env);
              });
          }
        })
        // Grab the sites UUID from teh machinename
        .then(function() {
          return terminus.getUUID(site)
            .then(function(uuid) {
              /*
               * bcauldwell: Sometimes terminus won't just return a UUID,
               * sometimes it can be a warning about a newer version of
               * terminus and then the UUID separated by a comma.
               */
              // Split uuid by commas and clean up parts with a trim.
              var parts = _.map(uuid.split(','), function(part) {
                return part.trim();
              });
              if (parts.length === 1) {
                // Default case where just uuid is returned.
                siteid = parts[0];
              } else if (parts.length === 2 &&
                _.startsWith(parts[0]), 'Warning:') {
                // Case where a warning is provided, such as newer version
                // being available etc...
                sideid = parts[1];
              } else {
                // Unexpected condition.
                throw new Error('Unexpected terminus UUID: [' + uuid + ']');
              }
            });
        })
        // Generate our code repo URL and CUT THAT MEAT!
        // errr PULL THAT CODE!
        .then(function() {
          // @todo: better way to generate this?
          // @todo: is 'dev' the only thing that
          var build = {
            protocol: 'ssh',
            slashes: true,
            auth: ['codeserver', 'dev', siteid].join('.'),
            hostname: ['codeserver', 'dev', siteid, 'drush', 'in'].join('.'),
            port: 2222,
            pathname: ['~', 'repository.git'].join('/')
          };
          repo = url.format(build);
          if (type === 'clone') {
            return git.cmd(['clone', repo, './'], [])
              .then(function() {
                if (env !== 'dev') {
                  return git.cmd(['fetch', 'origin'], []);
                }
              })
              .then(function() {
                if (env !== 'dev') {
                  return git.cmd(['checkout', env], []);
                }
              });
          }
          else {
            var branch = (env === 'dev') ? 'master' : env;
            return git.cmd(['pull', 'origin', branch], []);
          }
        });
    };

    /*
     * Pull down our sites database
     */
    var pullDB = function(site, env) {
      // Get the cid of this apps database
      // @todo: this looks gross
      var dbID = _.result(_.find(app.components, function(cmp) {
        return cmp.name === 'db';
      }), 'containerId');
      var wasRunning = null;
      var defaults = {
        PublishAllPorts: true,
        Binds: [app.rootBind + ':/src:rw']
      };

      return engine.isRunning(dbID)
        .then(function(status) {
          wasRunning = status;
          if (!wasRunning) {
            return engine.start(dbID, defaults);
          }
        })
        .then(function() {
          return terminus.getUUID(site);
        })
        .then(function(uuid) {
          return terminus.hasDBBackup(uuid.trim(), env);
        })
        .then(function(hasBackup) {
          if (!hasBackup) {
            return terminus.createDBBackup(site, env);
          }
        })
        .then(function() {
          return terminus.downloadDBBackup(site, env);
        })
        .then(function(data) {
          var downloadSplit = data.split('Downloaded');
          var dbFile = downloadSplit[1].trim();
          // Perform a container run.
          var payload = ['import-mysql', 'localhost', null, '3306', dbFile];
          return engine.queryData(dbID, payload);
        })
        .then(function(data) {
          // @todo: use real logger
          console.log(data);
        })
        // Stop the DB
        .then(function() {
          if (!wasRunning) {
            return engine.stop(dbID);
          }
        });
    };

    /*
     * Pull down our sites database
     */
    var pullFiles = function(site, env) {
      // the pantheon site UUID
      var siteid = null;
      // Get our UUID
      // @todo: cache this
      return terminus.getUUID(site)
        .then(function(uuid) {
          siteid = uuid.trim();
        })
        // Generate our code repo URL and CUT THAT MEAT!
        // errr PULL THAT CODE!
        .then(function() {
          // @todo: lots of cleanup here
          // /kbox rsync -rlvz --size-only --ipv4 --progress -e 'ssh -p 2222'
          var envSite = [env, siteid].join('.');
          var fileBox = envSite + '@appserver.' + envSite + '.drush.in:files/';
          var fileMount = 'sites/default/files';
          var opts = '-rlvz --size-only --ipv4 --progress -e \'ssh -p 2222\'';

          return rsync.cmd([opts, fileBox, fileMount], true);
        });
    };

    // Events
    // Install the terminus container for our things and also
    // pull down a site or create a new site
    events.on('post-install', function(app, done) {
      // Make sure we install the terminus container for this app
      var opts = {
        name: 'terminus',
        srcRoot: path.resolve(__dirname, '..', '..', '..'),
      };
      // Our pantheon config for later on
      var pantheonConf = app.config.pluginConf['kalabox-plugin-pantheon'];
      // @todo: fs.existsSync is not recommended and pending deprecation
      var firstTime = !fs.existsSync(app.config.codeRoot);
      // Install the terminus container and then do install things if
      // this is the first time
      return engine.build(opts)
        .then(function() {
          return terminus.getSiteAliases();
        })
        .then(function() {
          if (firstTime) {
            if (pantheonConf.action === 'create') {
              var repo = pantheonConf.upstream.url;
              return git.cmd(['clone', repo, './'], []);
            }
            else {
              return pullCode(pantheonConf.site, pantheonConf.env, 'clone');
            }
          }
        })
        .then(function() {
          if (firstTime && pantheonConf.action === 'pull') {
            return pullDB(pantheonConf.site, pantheonConf.env);
          }
        })
        .then(function() {
          if (firstTime && pantheonConf.action === 'pull') {
            return pullFiles(pantheonConf.site, pantheonConf.env);
          }
        })
        .nodeify(done);
    });

    // kbox appname pull COMMAND
    kbox.tasks.add(function(task) {

      var pantheonConf = app.config.pluginConf['kalabox-plugin-pantheon'];
      // @todo: notions of this for start states?
      // no files/db options, just a git pull?
      task.path = [app.name, 'pull'];
      task.description = 'Pull down new code and optionally data and files.';
      task.kind = 'delegate';

      // Only want these options for pull sites
      if (pantheonConf.action === 'pull') {
        task.options.push({
          name: 'database',
          kind: 'boolean',
          description: 'Import latest database backup.'
        });
        task.options.push({
          name: 'files',
          kind: 'boolean',
          description: 'Import latest files.'
        });
      }

      task.func = function(done) {

        // Only need questions on pull sites
        if (pantheonConf.action === 'pull') {
          // Grab the CLI options that are available
          var options = this.options;
          var questions = [
            {
              type: 'confirm',
              name: 'database',
              message: 'Also refresh from latest database backup?',
            },
            {
              type: 'confirm',
              name: 'files',
              message: 'Also grab latest files?',
            },
          ];

          // Filter out interactive questions based on passed in options
          questions = _.filter(questions, function(question) {

            var option = options[question.name];

            if (question.filter) {
              options[question.name] = question.filter(options[question.name]);
            }

            if (option === false || option === undefined) {
              return true;
            }

            else {
              return !_.includes(Object.keys(options), question.name);
            }
          });

          // Launch the inquiry
          inquirer.prompt(questions, function(answers) {
            var choices = _.merge({}, options, answers);
            return terminus.getSiteAliases()
            .then(function() {
              return pullCode(pantheonConf.site, pantheonConf.env, 'pull');
            })
            .then(function() {
              if (choices.database) {
                return pullDB(pantheonConf.site, pantheonConf.env);
              }
            })
            .then(function() {
              if (choices.files) {
                return pullFiles(pantheonConf.site, pantheonConf.env);
              }
            })
            .nodeify(done);
          });
        }
        // Just straight refresh the code if its a start state
        else {
          return git.cmd(['pull', 'origin', 'master'], []).nodeify(done);
        }
      };
    });
  });
};
<commit_msg>Fixing typo s/sideid/siteid/.<commit_after>'use strict';

// Intrinsic modules.
var url = require('url');
var fs = require('fs');
var path = require('path');

// NPM modules
var Promise = require('bluebird');
var _ = require('lodash');

// "Constants"
var PLUGIN_NAME = 'kalabox-plugin-pantheon';

module.exports = function(kbox) {

  kbox.whenApp(function(app) {

    // Grab the terminus client
    var Terminus = require('./terminus.js');
    var terminus = new Terminus(kbox, app);

    // Grab delegated helpers
    var pathToRoot = path.resolve(__dirname, '..', '..', '..');
    var pathToNode = path.join(pathToRoot, 'node_modules');
    var Git = require(pathToNode + '/kalabox-plugin-git/lib/git.js');
    var git = new Git(kbox, app);
    var Rsync = require(pathToNode + '/kalabox-plugin-rsync/lib/rsync.js');
    var rsync = new Rsync(kbox, app);

    // Grab some kalabox modules
    var events = kbox.core.events;
    var engine = kbox.engine;

    // Nobody expects the Spanish Inquisition!
    var inquirer = require('inquirer');

    /*
     * Pull down our sites code
     */
    var pullCode = function(site, env, type) {

      // the pantheon site UUID
      var siteid = null;
      var repo = null;

      // Check to see what our connection mode is
      return terminus.getConnectionMode(site, env)
        // Set the connection mode to git if needed
        // and then try again
        .then(function(connectionMode) {
          var modeSplit = connectionMode.split(':');
          var mode = modeSplit[1].trim().toLowerCase();
          if (mode !== 'git') {
            // @todo: actually test this part
            return terminus.setConnectionMode(site, env)
              .then(function(data) {
                pullCode(site, env);
              });
          }
        })
        // Grab the sites UUID from teh machinename
        .then(function() {
          return terminus.getUUID(site)
            .then(function(uuid) {
              /*
               * bcauldwell: Sometimes terminus won't just return a UUID,
               * sometimes it can be a warning about a newer version of
               * terminus and then the UUID separated by a comma.
               */
              // Split uuid by commas and clean up parts with a trim.
              var parts = _.map(uuid.split(','), function(part) {
                return part.trim();
              });
              if (parts.length === 1) {
                // Default case where just uuid is returned.
                siteid = parts[0];
              } else if (parts.length === 2 &&
                _.startsWith(parts[0]), 'Warning:') {
                // Case where a warning is provided, such as newer version
                // being available etc...
                siteid = parts[1];
              } else {
                // Unexpected condition.
                throw new Error('Unexpected terminus UUID: [' + uuid + ']');
              }
            });
        })
        // Generate our code repo URL and CUT THAT MEAT!
        // errr PULL THAT CODE!
        .then(function() {
          // @todo: better way to generate this?
          // @todo: is 'dev' the only thing that
          var build = {
            protocol: 'ssh',
            slashes: true,
            auth: ['codeserver', 'dev', siteid].join('.'),
            hostname: ['codeserver', 'dev', siteid, 'drush', 'in'].join('.'),
            port: 2222,
            pathname: ['~', 'repository.git'].join('/')
          };
          repo = url.format(build);
          if (type === 'clone') {
            return git.cmd(['clone', repo, './'], [])
              .then(function() {
                if (env !== 'dev') {
                  return git.cmd(['fetch', 'origin'], []);
                }
              })
              .then(function() {
                if (env !== 'dev') {
                  return git.cmd(['checkout', env], []);
                }
              });
          }
          else {
            var branch = (env === 'dev') ? 'master' : env;
            return git.cmd(['pull', 'origin', branch], []);
          }
        });
    };

    /*
     * Pull down our sites database
     */
    var pullDB = function(site, env) {
      // Get the cid of this apps database
      // @todo: this looks gross
      var dbID = _.result(_.find(app.components, function(cmp) {
        return cmp.name === 'db';
      }), 'containerId');
      var wasRunning = null;
      var defaults = {
        PublishAllPorts: true,
        Binds: [app.rootBind + ':/src:rw']
      };

      return engine.isRunning(dbID)
        .then(function(status) {
          wasRunning = status;
          if (!wasRunning) {
            return engine.start(dbID, defaults);
          }
        })
        .then(function() {
          return terminus.getUUID(site);
        })
        .then(function(uuid) {
          return terminus.hasDBBackup(uuid.trim(), env);
        })
        .then(function(hasBackup) {
          if (!hasBackup) {
            return terminus.createDBBackup(site, env);
          }
        })
        .then(function() {
          return terminus.downloadDBBackup(site, env);
        })
        .then(function(data) {
          var downloadSplit = data.split('Downloaded');
          var dbFile = downloadSplit[1].trim();
          // Perform a container run.
          var payload = ['import-mysql', 'localhost', null, '3306', dbFile];
          return engine.queryData(dbID, payload);
        })
        .then(function(data) {
          // @todo: use real logger
          console.log(data);
        })
        // Stop the DB
        .then(function() {
          if (!wasRunning) {
            return engine.stop(dbID);
          }
        });
    };

    /*
     * Pull down our sites database
     */
    var pullFiles = function(site, env) {
      // the pantheon site UUID
      var siteid = null;
      // Get our UUID
      // @todo: cache this
      return terminus.getUUID(site)
        .then(function(uuid) {
          siteid = uuid.trim();
        })
        // Generate our code repo URL and CUT THAT MEAT!
        // errr PULL THAT CODE!
        .then(function() {
          // @todo: lots of cleanup here
          // /kbox rsync -rlvz --size-only --ipv4 --progress -e 'ssh -p 2222'
          var envSite = [env, siteid].join('.');
          var fileBox = envSite + '@appserver.' + envSite + '.drush.in:files/';
          var fileMount = 'sites/default/files';
          var opts = '-rlvz --size-only --ipv4 --progress -e \'ssh -p 2222\'';

          return rsync.cmd([opts, fileBox, fileMount], true);
        });
    };

    // Events
    // Install the terminus container for our things and also
    // pull down a site or create a new site
    events.on('post-install', function(app, done) {
      // Make sure we install the terminus container for this app
      var opts = {
        name: 'terminus',
        srcRoot: path.resolve(__dirname, '..', '..', '..'),
      };
      // Our pantheon config for later on
      var pantheonConf = app.config.pluginConf['kalabox-plugin-pantheon'];
      // @todo: fs.existsSync is not recommended and pending deprecation
      var firstTime = !fs.existsSync(app.config.codeRoot);
      // Install the terminus container and then do install things if
      // this is the first time
      return engine.build(opts)
        .then(function() {
          return terminus.getSiteAliases();
        })
        .then(function() {
          if (firstTime) {
            if (pantheonConf.action === 'create') {
              var repo = pantheonConf.upstream.url;
              return git.cmd(['clone', repo, './'], []);
            }
            else {
              return pullCode(pantheonConf.site, pantheonConf.env, 'clone');
            }
          }
        })
        .then(function() {
          if (firstTime && pantheonConf.action === 'pull') {
            return pullDB(pantheonConf.site, pantheonConf.env);
          }
        })
        .then(function() {
          if (firstTime && pantheonConf.action === 'pull') {
            return pullFiles(pantheonConf.site, pantheonConf.env);
          }
        })
        .nodeify(done);
    });

    // kbox appname pull COMMAND
    kbox.tasks.add(function(task) {

      var pantheonConf = app.config.pluginConf['kalabox-plugin-pantheon'];
      // @todo: notions of this for start states?
      // no files/db options, just a git pull?
      task.path = [app.name, 'pull'];
      task.description = 'Pull down new code and optionally data and files.';
      task.kind = 'delegate';

      // Only want these options for pull sites
      if (pantheonConf.action === 'pull') {
        task.options.push({
          name: 'database',
          kind: 'boolean',
          description: 'Import latest database backup.'
        });
        task.options.push({
          name: 'files',
          kind: 'boolean',
          description: 'Import latest files.'
        });
      }

      task.func = function(done) {

        // Only need questions on pull sites
        if (pantheonConf.action === 'pull') {
          // Grab the CLI options that are available
          var options = this.options;
          var questions = [
            {
              type: 'confirm',
              name: 'database',
              message: 'Also refresh from latest database backup?',
            },
            {
              type: 'confirm',
              name: 'files',
              message: 'Also grab latest files?',
            },
          ];

          // Filter out interactive questions based on passed in options
          questions = _.filter(questions, function(question) {

            var option = options[question.name];

            if (question.filter) {
              options[question.name] = question.filter(options[question.name]);
            }

            if (option === false || option === undefined) {
              return true;
            }

            else {
              return !_.includes(Object.keys(options), question.name);
            }
          });

          // Launch the inquiry
          inquirer.prompt(questions, function(answers) {
            var choices = _.merge({}, options, answers);
            return terminus.getSiteAliases()
            .then(function() {
              return pullCode(pantheonConf.site, pantheonConf.env, 'pull');
            })
            .then(function() {
              if (choices.database) {
                return pullDB(pantheonConf.site, pantheonConf.env);
              }
            })
            .then(function() {
              if (choices.files) {
                return pullFiles(pantheonConf.site, pantheonConf.env);
              }
            })
            .nodeify(done);
          });
        }
        // Just straight refresh the code if its a start state
        else {
          return git.cmd(['pull', 'origin', 'master'], []).nodeify(done);
        }
      };
    });
  });
};
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'

import * as Paths from './../../../../Paths'
import * as WidgetActions from './../../../actions'
import { Loading } from './../../../../components'
import FormWidget from '../'
import { Menu } from '../components'
import { SettingsPageLayout, SettingsPageContentLayout } from '../../../../../components/Layout'

class Fields extends Component {
  constructor(props, context) {
    super(props, context)
    this.state = { loading: false, hasNewField: false }
  }

  componentWillReceiveProps(nextProps) {
    const { widget } = this.props
    if (this.state.loading && widget != this.widget(nextProps)) {
      this.setState({ loading: false, hasNewField: true })
    } else {
      this.setState({ hasNewField: false })
    }
  }

  handleAddTextField() {
    this.addField('text')
  }

  widget(props = this.props) {
    const { widgets } = props
    return widgets.data[widgets.data.map((widget) => { return widget.id.toString()}).indexOf(this.props.params.widget_id)]
  }

  fields() {
    const { widget: { settings } } = this.props
    return (settings && settings.fields ? settings.fields : [])
  }

  addField(kind) {
    const { mobilization, widget, credentials, editWidgetAsync, dispatch, ...props } = this.props
    const { settings } = widget
    const fields = this.fields()
    this.setState({ loading: true })

    const data = {
      ...widget,
      settings: {
        ...settings,
        fields: [
          ...fields,
          {
            uid: ('field-' + Date.now().toString() + '-' + Math.floor((Math.random() * 100) + 1)),
            kind: 'text',
            label: '',
            placeholder: '',
            required: 'false'
          }
        ]
      }
    }
    editWidgetAsync(data)
  }

  renderFields() {
    const { widget, ...props } = this.props
    return (
      <SettingsPageLayout>
        <Menu widget={widget} {...props} />
        <button
          className="btn white bg-pagenta caps p2 rounded"
          onClick={::this.handleAddTextField}
          style={{
            position: 'absolute',
            top: '1.45rem',
            right: '2rem',
            textTransform: 'uppercase',
            margin: '0',
            padding: '.7rem 1.6rem'
          }}
        >

          Adicionar um campo
        </button>
        <SettingsPageContentLayout>

            {
              this.fields().length == 0 ?
              'Seu formulário ainda não possui nenhum campo. Clique abaixo para começar a'
                + ' adicionar campos.' :
              'Adicione, remova, edite e ordene os campos do formulário de acordo com as'
                + ' necessidades da sua ação.'
            }

          <FormWidget
            {...props}
            widget={widget}
            configurable={true}
            hasNewField={this.state.hasNewField}
          />
          </SettingsPageContentLayout>
        {this.renderLoading()}
      </SettingsPageLayout>
    )
  }

  renderLoading(){
    const { loading } = this.state
    const { widget } = this.props
    return loading || widget === undefined ? <Loading /> : null
  }

  render() {
    const { widget, ...props } = this.props
    return(widget !== undefined ? this.renderFields() : this.renderLoading())
  }
}

Fields.propTypes = {
  mobilization: PropTypes.object.isRequired,
  widget: PropTypes.object.isRequired,
  credentials: PropTypes.object.isRequired,
  editWidgetAsync: PropTypes.func.isRequired
}

export default connect(
(state, ownProps) => {
  return {
    credentials: state.auth.credentials,
  }
}, { ...WidgetActions })(Fields)
<commit_msg>Fix FormWidget fields page submit button style. #212<commit_after>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'

import * as Paths from './../../../../Paths'
import * as WidgetActions from './../../../actions'
import { Loading } from './../../../../components'
import FormWidget from '../'
import { Menu } from '../components'
import { SettingsPageLayout, SettingsPageContentLayout } from '../../../../../components/Layout'

class Fields extends Component {
  constructor(props, context) {
    super(props, context)
    this.state = { loading: false, hasNewField: false }
  }

  componentWillReceiveProps(nextProps) {
    const { widget } = this.props
    if (this.state.loading && widget != this.widget(nextProps)) {
      this.setState({ loading: false, hasNewField: true })
    } else {
      this.setState({ hasNewField: false })
    }
  }

  handleAddTextField() {
    this.addField('text')
  }

  widget(props = this.props) {
    const { widgets } = props
    return widgets.data[widgets.data.map((widget) => { return widget.id.toString()}).indexOf(this.props.params.widget_id)]
  }

  fields() {
    const { widget: { settings } } = this.props
    return (settings && settings.fields ? settings.fields : [])
  }

  addField(kind) {
    const { mobilization, widget, credentials, editWidgetAsync, dispatch, ...props } = this.props
    const { settings } = widget
    const fields = this.fields()
    this.setState({ loading: true })

    const data = {
      ...widget,
      settings: {
        ...settings,
        fields: [
          ...fields,
          {
            uid: ('field-' + Date.now().toString() + '-' + Math.floor((Math.random() * 100) + 1)),
            kind: 'text',
            label: '',
            placeholder: '',
            required: 'false'
          }
        ]
      }
    }
    editWidgetAsync(data)
  }

  renderFields() {
    const { widget, ...props } = this.props
    return (
      <SettingsPageLayout>
        <Menu widget={widget} {...props} />
        <button
          className="btn white bg-pagenta caps p2 rounded"
          onClick={::this.handleAddTextField}
          style={{
            position: 'fixed',
            top: '2rem',
            right: '4rem',
            width: 'inherit',
            textTransform: 'uppercase',
            margin: '0',
            fontSize: '1.1rem',
            padding: '.7rem 1.6rem'
          }}
        >
          Adicionar um campo
        </button>
        <SettingsPageContentLayout>

            {
              this.fields().length == 0 ?
              'Seu formulário ainda não possui nenhum campo. Clique abaixo para começar a'
                + ' adicionar campos.' :
              'Adicione, remova, edite e ordene os campos do formulário de acordo com as'
                + ' necessidades da sua ação.'
            }

          <FormWidget
            {...props}
            widget={widget}
            configurable={true}
            hasNewField={this.state.hasNewField}
          />
          </SettingsPageContentLayout>
        {this.renderLoading()}
      </SettingsPageLayout>
    )
  }

  renderLoading(){
    const { loading } = this.state
    const { widget } = this.props
    return loading || widget === undefined ? <Loading /> : null
  }

  render() {
    const { widget, ...props } = this.props
    return(widget !== undefined ? this.renderFields() : this.renderLoading())
  }
}

Fields.propTypes = {
  mobilization: PropTypes.object.isRequired,
  widget: PropTypes.object.isRequired,
  credentials: PropTypes.object.isRequired,
  editWidgetAsync: PropTypes.func.isRequired
}

export default connect(
(state, ownProps) => {
  return {
    credentials: state.auth.credentials,
  }
}, { ...WidgetActions })(Fields)
<|endoftext|>