<commit_before> var nav,
    loader,
    LoaderInstance,
    utils,
    dateutils,
    LunchState,
    currentLunchState,
    cart,
    lunches;

/**
 *  Constructor
 */
(function constructor(args) {
    LunchState = {
        Student: 0,
        Employee: 1
    };

    currentLunchState = LunchState.Student;
    cart = Alloy.Models.cart;
    utils = require("/utils");
    dateutils = require("/dateutils");

    $.footer.onSettingsUpdated(onSettingsUpdated);

    cart.on("update", function(summary) {
        $.footer.updateTotalSummary(summary);
    });

    cart.on("reset", setUI);

    Ti.App.addEventListener("shortcut:canteenSelected", function(e) {
        $.footer.updateCurrentCanteen(e.title);
        onSettingsUpdated(e);
    });

    if (OS_IOS) {
        nav = createNavigationWindow();
        $.listView.setPreviewContext(createPreviewContext());
    } else if (OS_ANDROID) {
        /**
         * FIXME: Crashes for some reason?
        var swipeRefreshModule = require('com.rkam.swiperefreshlayout');
        var swipeRefresh = swipeRefreshModule.createSwipeRefresh({
            view: $.listView,
            height: Ti.UI.FILL,
            width: Ti.UI.FILL
        });

        $.window.add(swipeRefresh);
        */
    }

    initializeLoader();
    initializeDate();

})(arguments[0] || {});

function createPreviewContext() {

    if (!OS_IOS || Ti.UI.iOS.forceTouchSupported === false) {
        return;
    }

    var previewContext = Ti.UI.iOS.createPreviewContext({
		preview: createPreviewView(),
		contentHeight: 400
	});

	previewContext.addEventListener("peek", function(e) {
        var product = _.findWhere(lunches, {id: e.itemId});
		var images = product ? product.images : null;
		var preview = $.listView.getPreviewContext().preview;

		if (images && images.length > 0) {
			preview.children[0].setImage(images[0]);
		} else {
            preview.children[0].setImage("/images/noImage.png");
        }
	});

	previewContext.addEventListener("pop", function(e) {
        openDetails(e.itemId, false);
	});

    return previewContext;
}

function createPreviewView() {
    var preview = Ti.UI.createView({
		borderRadius: 20,
		backgroundColor: "#fff",
		height: Ti.UI.SIZE
	});

	preview.add(Ti.UI.createImageView({
        borderRadius: 20,
        defaultImage: "/images/noImage.png"
    }));

    return preview;
}

function onSettingsUpdated(e) {
    switch (e.action) {
        case "selectCanteen":
            fetchData({
                force: false
            });
            break;
        case "changePreference":
            currentLunchState = Ti.App.Properties.getInt('currentPersonID', 0);
            setUI();
            break;
    }
}

function initializeLoader() {
    LoaderInstance = require("/loader");
    loader = new LoaderInstance($.window);
}

function initializeDate() {
    $.window.setTitle(dateutils.getFormattedDate());
}

function createNavigationWindow() {
    return Ti.UI.iOS.createNavigationWindow({
        window: $.window
    });
}

function onRefreshStart() {
    fetchData({
        force: true
    });
}

function toggleNextDay() {
    dateutils.increment();
    fetchData({
        force: false
    });
}

function togglePreviousDay() {
    dateutils.decrement();
    fetchData({
        force: false
    });
}

function handleListItemClick(e) {
    openDetails(e.itemId, true);
}

function openDetails(itemId, animated) {
    // TODO: Move all products to Models
    var product = null

    // FIXME: Use better underscore-method to find the ID. Problem was Android here
    _.each(lunches, function(lunch) {
        if (lunch.id == itemId) {
            product = lunch;
        }
    });

    if (!product) {
        Ti.API.error("Could not find product with ID = " + itemId);
        Ti.API.error(JSON.stringify(lunches));
        return;
    }

    Alloy.createController("/lunches/details/index", {
        product: product,
        onRatingUpdated: onRatingUpdated
    }).open(animated);
}

function onRatingUpdated(e) {
    fetchData({
        force: true
    });
}

function fetchData(args) {
    !args.force && loader.show();
    $.window.setTitle(L("loading"));

    var api = require("/api");
    api.getLunches({
        date: dateutils.getCurrentDateSlug(),
        location: Ti.App.Properties.getInt("currentLocationID", Alloy.CFG.defaultCanteen.id)
    }, function(e) {
        lunches = e;
        setUI();
        !args.force && loader.hide();
    });
}

function setUI() {
    if (OS_IOS) {
        $.refresh.endRefreshing();
    }

    var showAdditives = Ti.App.Properties.getBool("showAdditives", true);
    var showRatings = Ti.App.Properties.getBool("showRatings", true);

    var categories = [L("Hauptgericht"), L("Beilagen"), L("Dessert"), L("Tagessalat"), L("Essen_Hochschulbedienstete", "Essen Hochschulbedienstete"), L("Eintopf_Teller", "Eintopf Teller")];
    var sections = [];

    cart.resetTotal(false);

    _.each(categories, function(category, index) {
        var section = Alloy.createController("/lunches/section", {
            title: category,
            index: index
        }).getView();

        var cells = [];

        _.each(lunches, function(lunch) {
            if (L(lunch.category, lunch.category) != category) {
                return;
            }

            var hasAdditives = lunch.additives && lunch.additives.length;
            var price = currentLunchState == LunchState.Student ? lunch.priceStudent.split(" €")[0] : lunch.priceOfficial.split(" €")[0];

            var attr = {
                itemId: lunch.id,
                count: 0,
                price: price,
                properties: {
                    itemId: lunch.id,
                    height: Ti.UI.SIZE,
                    backgroundColor: "#fff",
                    selectionStyle : (OS_IOS) ? Ti.UI.iOS.ListViewCellSelectionStyle.NONE : null,
                },
                buttonRemove: {
                    visible: false
                },
                lunchTitle: {
                    left: lunch.images.length > 0 ? 4 : 2,
                    text: ((lunch.images.length ? "📷" : "") + lunch.name)
                },
                lunchCountContainer: {
                    visible: false
                },
                lunchCount: {
                    text: 0
                },
                lunchPriceContainer: {

                },
                lunchPrice: {
                    text: price
                }
            };

            if (showAdditives) {
                attr["lunchAdditives"] = {
                    text: formattedAdditives(hasAdditives ? lunch.additives.length : 0)
                };
            } else {
                attr["lunchAdditives"] = null;
            }

            if (showRatings) {
                attr["fullStars"] = {
                    image: utils.formattedStars(lunch.rating)
                };
                attr["scoreOfRating"] = {
                    text: lunch.rating ? lunch.rating.value : 0
                };
                attr["numberOfRating"] = {
                    text: lunch.rating ? lunch.rating.count : 0
                };
            } else {
                attr["fullStars"] = null;
                attr["scoreOfRating"] = null;
                attr["numberOfRating"] = null;
            }

            cells.push(attr);
        });
        section.setItems(cells);
        section.getItems().length > 0 && sections.push(section);
    });

    $.listView.setSections(sections);
    $.window.setTitle(dateutils.getFormattedDate());
    $.placeholder[sections.length > 0 ? "hide" : "show"]();
}

function formattedAdditives(count) {
    if (count == 0) {
        return L('no_additives');
    } else if (count == 1) {
        return L('one_additive');
    }
    return count + ' ' + L('additives');
}

function open() {
    if (OS_IOS) {
        nav.open();
    } else {
        $.window.open();
    }
}

function incrementPrice(e) {
    var item = e.section.getItemAt(e.itemIndex);

    item.count++;
    item.lunchCount.text = item.count;
    cart.increment(item.price);

    // First Increment
    if (item.count == 1) {
        item.buttonRemove.visible = true;
        item.lunchCountContainer.visible = true;
        item.lunchPriceContainer.backgroundImage = "/images/priceBgSelected.png";
        item.properties.backgroundColor = "#f3fdff";
    }

    e.section.updateItemAt(e.itemIndex, item);
    utils.selectionChanged();
}

function decrementPrice(e) {
    var item = e.section.getItemAt(e.itemIndex);

    item.count--;
    item.lunchCount.text = item.count;
    cart.decrement(item.price);

    // Last Decrement
    if (item.count == 0) {
        item.buttonRemove.visible = false;
        item.lunchCountContainer.visible = false;
        item.lunchPriceContainer.backgroundImage = "/images/priceBg.png";
        item.properties.backgroundColor = "#fff";
    }

    e.section.updateItemAt(e.itemIndex, item);
    utils.selectionChanged();
}

exports.open = open
<commit_msg>Hide placeholder on reload<commit_after> var nav,
    loader,
    LoaderInstance,
    utils,
    dateutils,
    LunchState,
    currentLunchState,
    cart,
    lunches;

/**
 *  Constructor
 */
(function constructor(args) {
    LunchState = {
        Student: 0,
        Employee: 1
    };

    currentLunchState = LunchState.Student;
    cart = Alloy.Models.cart;
    utils = require("/utils");
    dateutils = require("/dateutils");

    $.footer.onSettingsUpdated(onSettingsUpdated);

    cart.on("update", function(summary) {
        $.footer.updateTotalSummary(summary);
    });

    cart.on("reset", setUI);

    Ti.App.addEventListener("shortcut:canteenSelected", function(e) {
        $.footer.updateCurrentCanteen(e.title);
        onSettingsUpdated(e);
    });

    if (OS_IOS) {
        nav = createNavigationWindow();
        $.listView.setPreviewContext(createPreviewContext());
    } else if (OS_ANDROID) {
        /**
         * FIXME: Crashes for some reason?
        var swipeRefreshModule = require('com.rkam.swiperefreshlayout');
        var swipeRefresh = swipeRefreshModule.createSwipeRefresh({
            view: $.listView,
            height: Ti.UI.FILL,
            width: Ti.UI.FILL
        });

        $.window.add(swipeRefresh);
        */
    }

    initializeLoader();
    initializeDate();

})(arguments[0] || {});

function createPreviewContext() {

    if (!OS_IOS || Ti.UI.iOS.forceTouchSupported === false) {
        return;
    }

    var previewContext = Ti.UI.iOS.createPreviewContext({
		preview: createPreviewView(),
		contentHeight: 400
	});

	previewContext.addEventListener("peek", function(e) {
        var product = _.findWhere(lunches, {id: e.itemId});
		var images = product ? product.images : null;
		var preview = $.listView.getPreviewContext().preview;

		if (images && images.length > 0) {
			preview.children[0].setImage(images[0]);
		} else {
            preview.children[0].setImage("/images/noImage.png");
        }
	});

	previewContext.addEventListener("pop", function(e) {
        openDetails(e.itemId, false);
	});

    return previewContext;
}

function createPreviewView() {
    var preview = Ti.UI.createView({
		borderRadius: 20,
		backgroundColor: "#fff",
		height: Ti.UI.SIZE
	});

	preview.add(Ti.UI.createImageView({
        borderRadius: 20,
        defaultImage: "/images/noImage.png"
    }));

    return preview;
}

function onSettingsUpdated(e) {
    switch (e.action) {
        case "selectCanteen":
            fetchData({
                force: false
            });
            break;
        case "changePreference":
            currentLunchState = Ti.App.Properties.getInt('currentPersonID', 0);
            setUI();
            break;
    }
}

function initializeLoader() {
    LoaderInstance = require("/loader");
    loader = new LoaderInstance($.window);
}

function initializeDate() {
    $.window.setTitle(dateutils.getFormattedDate());
}

function createNavigationWindow() {
    return Ti.UI.iOS.createNavigationWindow({
        window: $.window
    });
}

function onRefreshStart() {
    fetchData({
        force: true
    });
}

function toggleNextDay() {
    dateutils.increment();
    fetchData({
        force: false
    });
}

function togglePreviousDay() {
    dateutils.decrement();
    fetchData({
        force: false
    });
}

function handleListItemClick(e) {
    openDetails(e.itemId, true);
}

function openDetails(itemId, animated) {
    // TODO: Move all products to Models
    var product = null

    // FIXME: Use better underscore-method to find the ID. Problem was Android here
    _.each(lunches, function(lunch) {
        if (lunch.id == itemId) {
            product = lunch;
        }
    });

    if (!product) {
        Ti.API.error("Could not find product with ID = " + itemId);
        Ti.API.error(JSON.stringify(lunches));
        return;
    }

    Alloy.createController("/lunches/details/index", {
        product: product,
        onRatingUpdated: onRatingUpdated
    }).open(animated);
}

function onRatingUpdated(e) {
    fetchData({
        force: true
    });
}

function fetchData(args) {
    if (!args.force) {
        $.placeholder.hide();
        loader.show();
    }

    $.window.setTitle(L("loading"));

    var api = require("/api");
    api.getLunches({
        date: dateutils.getCurrentDateSlug(),
        location: Ti.App.Properties.getInt("currentLocationID", Alloy.CFG.defaultCanteen.id)
    }, function(e) {
        lunches = e;
        setUI();
        !args.force && loader.hide();
    });
}

function setUI() {
    if (OS_IOS) {
        $.refresh.endRefreshing();
    }

    var showAdditives = Ti.App.Properties.getBool("showAdditives", true);
    var showRatings = Ti.App.Properties.getBool("showRatings", true);

    var categories = [L("Hauptgericht"), L("Beilagen"), L("Dessert"), L("Tagessalat"), L("Essen_Hochschulbedienstete", "Essen Hochschulbedienstete"), L("Eintopf_Teller", "Eintopf Teller")];
    var sections = [];

    cart.resetTotal(false);

    _.each(categories, function(category, index) {
        var section = Alloy.createController("/lunches/section", {
            title: category,
            index: index
        }).getView();

        var cells = [];

        _.each(lunches, function(lunch) {
            if (L(lunch.category, lunch.category) != category) {
                return;
            }

            var hasAdditives = lunch.additives && lunch.additives.length;
            var price = currentLunchState == LunchState.Student ? lunch.priceStudent.split(" €")[0] : lunch.priceOfficial.split(" €")[0];

            var attr = {
                itemId: lunch.id,
                count: 0,
                price: price,
                properties: {
                    itemId: lunch.id,
                    height: Ti.UI.SIZE,
                    backgroundColor: "#fff",
                    selectionStyle : (OS_IOS) ? Ti.UI.iOS.ListViewCellSelectionStyle.NONE : null,
                },
                buttonRemove: {
                    visible: false
                },
                lunchTitle: {
                    left: lunch.images.length > 0 ? 4 : 2,
                    text: ((lunch.images.length ? "📷" : "") + lunch.name)
                },
                lunchCountContainer: {
                    visible: false
                },
                lunchCount: {
                    text: 0
                },
                lunchPriceContainer: {

                },
                lunchPrice: {
                    text: price
                }
            };

            if (showAdditives) {
                attr["lunchAdditives"] = {
                    text: formattedAdditives(hasAdditives ? lunch.additives.length : 0)
                };
            } else {
                attr["lunchAdditives"] = null;
            }

            if (showRatings) {
                attr["fullStars"] = {
                    image: utils.formattedStars(lunch.rating)
                };
                attr["scoreOfRating"] = {
                    text: lunch.rating ? lunch.rating.value : 0
                };
                attr["numberOfRating"] = {
                    text: lunch.rating ? lunch.rating.count : 0
                };
            } else {
                attr["fullStars"] = null;
                attr["scoreOfRating"] = null;
                attr["numberOfRating"] = null;
            }

            cells.push(attr);
        });
        section.setItems(cells);
        section.getItems().length > 0 && sections.push(section);
    });

    $.listView.setSections(sections);
    $.window.setTitle(dateutils.getFormattedDate());
    $.placeholder[sections.length > 0 ? "hide" : "show"]();
}

function formattedAdditives(count) {
    if (count == 0) {
        return L('no_additives');
    } else if (count == 1) {
        return L('one_additive');
    }
    return count + ' ' + L('additives');
}

function open() {
    if (OS_IOS) {
        nav.open();
    } else {
        $.window.open();
    }
}

function incrementPrice(e) {
    var item = e.section.getItemAt(e.itemIndex);

    item.count++;
    item.lunchCount.text = item.count;
    cart.increment(item.price);

    // First Increment
    if (item.count == 1) {
        item.buttonRemove.visible = true;
        item.lunchCountContainer.visible = true;
        item.lunchPriceContainer.backgroundImage = "/images/priceBgSelected.png";
        item.properties.backgroundColor = "#f3fdff";
    }

    e.section.updateItemAt(e.itemIndex, item);
    utils.selectionChanged();
}

function decrementPrice(e) {
    var item = e.section.getItemAt(e.itemIndex);

    item.count--;
    item.lunchCount.text = item.count;
    cart.decrement(item.price);

    // Last Decrement
    if (item.count == 0) {
        item.buttonRemove.visible = false;
        item.lunchCountContainer.visible = false;
        item.lunchPriceContainer.backgroundImage = "/images/priceBg.png";
        item.properties.backgroundColor = "#fff";
    }

    e.section.updateItemAt(e.itemIndex, item);
    utils.selectionChanged();
}

exports.open = open
<|endoftext|>


<commit_before>var fs = require('fs'),
	sys = require('sys'),
    exec = require('child_process').exec;

var deployer = exports.deployer = function (project, callback) {
	var tempFile = __dirname + '/tmp/' + Math.random() + '.js';
	fs.writeFile(tempFile, project.lastHandler.code, function(err) {
		if (err) throw err;
		node = exec('node ' + tempFile, function (error, stdout, stderr) {
			if (error !== null) {
				console.log('exec error: ' + error);
			}
			fs.unlink(tempFile, function (err) {
				if (err)
					console.log("Unable to delete " + tempFile + ".");
				callback(stdout, stderr);
			});
		});
	});

}

<commit_msg>Added timeoute to kill spawned processes if they run for too long<commit_after>var fs = require('fs'),
	sys = require('sys'),
    exec = require('child_process').exec;

var deployer = exports.deployer = function (project, callback) {
	var tempFile = __dirname + '/tmp/' + Math.random() + '.js';
	fs.writeFile(tempFile, project.lastHandler.code, function(err) {
		if (err) throw err;
		var options = {
		    encoding: 'utf-8',
            timeout: 60000,
            maxBuffer: 200*1024,
            killSignal: 'SIGKILL',
            cwd: null,
            env: null
		};
		var node = exec('node ' + tempFile, options, function (error, stdout, stderr) {
			if (error !== null) {
				console.log('exec error: ' + error);
			}
			fs.unlink(tempFile, function (err) {
				if (err)
					console.log("Unable to delete " + tempFile + ".");
				callback(stdout, stderr);
			});
		});
	});

}

<|endoftext|>


<commit_before>/**
 * @fileoverview Soundworks server side performance base class module
 * @author Sebastien.Robaszkiewicz@ircam.fr, Norbert.Schnell@ircam.fr
 */
'use strict';

var ServerModule = require('./ServerModule');

class ServerPerformance extends ServerModule {
  constructor(options = {}) {
    super(options.name || 'performance');

    this.clients = [];
    this.entered = false;
  }

  connect(client) {
    super.connect(client);

    client.receive('performance:start', () => {
      this.enter(client);
    });

    client.receive('performance:done', () => {
      this.exit(client);
    });
  }

  disconnect(client) {
    super.disconnect(client);

    if (this.entered)
      this.exit(client);
  }

  enter(client) {
    this.clients.push(client);
    this.entered = true;
  }

  exit(client) {
    let index = this.clients.indexOf(client);

    this.entered = false;

    if (index >= 0)
      this.clients.splice(index, 1);
  }
}

module.exports = ServerPerformance;<commit_msg>Performance bug fixed<commit_after>/**
 * @fileoverview Soundworks server side performance base class module
 * @author Sebastien.Robaszkiewicz@ircam.fr, Norbert.Schnell@ircam.fr
 */
'use strict';

var ServerModule = require('./ServerModule');

class ServerPerformance extends ServerModule {
  constructor(options = {}) {
    super(options.name || 'performance');

    this.clients = [];
  }

  connect(client) {
    super.connect(client);

    client.receive('performance:start', () => {
      this.enter(client);
    });

    client.receive('performance:done', () => {
      this.exit(client);
    });
  }

  disconnect(client) {
    super.disconnect(client);

    if (client.modules.performance.entered)
      this.exit(client);
  }

  enter(client) {
    this.clients.push(client);
    client.modules.performance.entered = true;
  }

  exit(client) {
    let index = this.clients.indexOf(client);

    client.modules.performance.entered = false;

    if (index >= 0)
      this.clients.splice(index, 1);
  }
}

module.exports = ServerPerformance;<|endoftext|>


<commit_before>this.discogsEmbed=this.discogsEmbed||{},this.discogsEmbed.templates=this.discogsEmbed.templates||{},this.discogsEmbed.templates.error=Handlebars.template({compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f="function",g=b.helperMissing,h=this.escapeExpression;return'
\n
Discogs Embed - Ooooops!
\n
Seems like something went wrong when loading resource with id '+h((e=null!=(e=b.id||(null!=a?a.id:a))?e:g,typeof e===f?e.call(a,{name:"id",hash:{},data:d}):e))+' : ((
\n
Please reload!
\n
'},useData:!0}),this.discogsEmbed.templates.main=Handlebars.template({1:function(a,b,c,d){var e,f="function",g=b.helperMissing,h=this.escapeExpression;return'      '+h((e=null!=(e=b.name||(null!=a?a.name:a))?e:g,typeof e===f?e.call(a,{name:"name",hash:{},data:d}):e))+"\n"},3:function(a,b,c,d){var e,f='
\n';return e=b.each.call(a,null!=(e=null!=a?a.data:a)?e.formats:e,{name:"each",hash:{},fn:this.program(4,d),inverse:this.noop,data:d}),null!=e&&(f+=e),f+"
\n"},4:function(a,b,c,d){var e,f="        ";return e=b.each.call(a,null!=a?a.descriptions:a,{name:"each",hash:{},fn:this.program(5,d),inverse:this.noop,data:d}),null!=e&&(f+=e),f+"\n"},5:function(a){var b=this.lambda,c=this.escapeExpression;return"
"+c(b(a,a))+"
"},7:function(a){var b,c=this.lambda,d=this.escapeExpression;return'    / '+d(c(null!=(b=null!=(b=null!=(b=null!=a?a.data:a)?b.labels:b)?b[0]:b)?b.name:b,a))+' ('+d(c(null!=(b=null!=(b=null!=(b=null!=a?a.data:a)?b.labels:b)?b[0]:b)?b.catno:b,a))+")\n"},9:function(){return" collapsed"},11:function(){return" ellipsed"},13:function(a,b,c,d){var e,f=b.helperMissing,g="";return e=(b.isTrack||a&&a.isTrack||f).call(a,a,{name:"isTrack",hash:{},fn:this.program(14,d),inverse:this.program(18,d),data:d}),null!=e&&(g+=e),g},14:function(a,b,c,d){var e,f,g="function",h=b.helperMissing,i=this.escapeExpression,j='
\n        '+i((f=null!=(f=b.position||(null!=a?a.position:a))?f:h,typeof f===g?f.call(a,{name:"position",hash:{},data:d}):f))+"\n";return e=b["if"].call(a,null!=a?a.artists:a,{name:"if",hash:{},fn:this.program(15,d),inverse:this.noop,data:d}),null!=e&&(j+=e),j+'        '+i((f=null!=(f=b.title||(null!=a?a.title:a))?f:h,typeof f===g?f.call(a,{name:"title",hash:{},data:d}):f))+'\n        '+i((f=null!=(f=b.duration||(null!=a?a.duration:a))?f:h,typeof f===g?f.call(a,{name:"duration",hash:{},data:d}):f))+"\n
\n"},15:function(a,b,c,d){var e,f="          ";return e=b.each.call(a,null!=a?a.artists:a,{name:"each",hash:{},fn:this.program(16,d),inverse:this.noop,data:d}),null!=e&&(f+=e),f+"\n          - \n"},16:function(a,b,c,d){var e,f="function",g=b.helperMissing,h=this.escapeExpression;return''+h((e=null!=(e=b.name||(null!=a?a.name:a))?e:g,typeof e===f?e.call(a,{name:"name",hash:{},data:d}):e))+""},18:function(a,b,c,d){var e,f="function",g=b.helperMissing,h=this.escapeExpression;return'
'+h((e=null!=(e=b.title||(null!=a?a.title:a))?e:g,typeof e===f?e.call(a,{name:"title",hash:{},data:d}):e))+"
\n"},20:function(){return'
\n      \n        more\n        less\n      \n
\n'},compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f=this.lambda,g=this.escapeExpression,h=b.helperMissing,i='\n
\n';return e=b.each.call(a,null!=(e=null!=a?a.data:a)?e.artists:e,{name:"each",hash:{},fn:this.program(1,d),inverse:this.noop,data:d}),null!=e&&(i+=e),i+="    - "+g(f(null!=(e=null!=a?a.data:a)?e.title:e,a))+'\n    '+g(f(null!=(e=null!=a?a.data:a)?e.year:e,a))+'\n
\n
\n    '+g(f(null!=(e=null!=a?a.data:a)?e.country:e,a))+" / \n",e=b["if"].call(a,null!=(e=null!=a?a.data:a)?e.formats:e,{name:"if",hash:{},fn:this.program(3,d),inverse:this.noop,data:d}),null!=e&&(i+=e),e=b["if"].call(a,null!=(e=null!=a?a.data:a)?e.labels:e,{name:"if",hash:{},fn:this.program(7,d),inverse:this.noop,data:d}),null!=e&&(i+=e),i+='
\n\n
\n
\n    \n      \n    \n
\n
\n
\n',e=b.each.call(a,null!=(e=null!=a?a.data:a)?e.tracklist:e,{name:"each",hash:{},fn:this.program(13,d),inverse:this.noop,data:d}),null!=e&&(i+=e),i+="
\n",e=(b.isCollapsed||a&&a.isCollapsed||h).call(a,null!=(e=null!=a?a.data:a)?e.tracklist:e,{name:"isCollapsed",hash:{},fn:this.program(20,d),inverse:this.noop,data:d}),null!=e&&(i+=e),i+'
\n
\n\n  \n    This data comes from  Discogs. Found any error? Go edit the original entry!\n  \n'},useData:!0}),function(a){var b,c,d;d=function(a,b){return function(){return a.apply(b,arguments)}},c={api:{baseUrl:"https://api.discogs.com"},imageCacheUrl:"/images/discogs",ui:{collapseThreshold:10}},defaultDiscogsOptions={releaseType:"releases",id:1990898},b=function(){function b(b,e){var f=this;this.handler=b,a.extend(!0,this,c,e),this.init=d(this.init,this),this.load=d(this.load,this),this.clear=d(this.clear,this),this.expand=d(this.expand,this),this.reload=d(this.reload,this),this._done=d(this._done,this),this._fail=d(this._fail,this),this._always=d(this._always,this),this.templates=window.discogsEmbed.templates,Handlebars.registerHelper("isCollapsed",function(a,b){return a.length>f.ui.collapseThreshold?b.fn(this):null}),Handlebars.registerHelper("isTrack",function(a,b){return"track"==a.type_?b.fn(this):b.inverse(this)});var f=this;this._done=function(a){a.data.image=f.imageCacheUrl+"/"+data.id+".jpeg",f.handler.toggleClass("error",!1).html(f.templates.main({data:a.data}))},this._fail=function(){f.handler.toggleClass("error",!0).html(f.templates.error({id:f.discogsData.id}))},this._always=function(){f.handler.toggleClass("loading",!1)}}return b.prototype.expand=function(a){a.preventDefault();var b=this.$tracklist||(this.$tracklist=this.handler.find(".tracklist"));b.toggleClass("collapsed",!b.is(".collapsed")).find("ul").toggleClass("ellipsed",!!b.is(".collapsed"))},b.prototype.reload=function(a){a.preventDefault(),this.load()},b.prototype.load=function(){return this.handler.toggleClass("loading",!0),a.getJSON(this.api.baseUrl+"/"+this.discogsData.releaseType+"/"+this.discogsData.id+"?callback=?").done(this._done).fail(this._fail).always(this._always)},b.prototype.init=function(){this.discogsData=a.extend(!0,defaultDiscogsOptions,this.handler.data()),this.handler.on("click",".more",this.expand),this.handler.on("click",".reload",this.reload),this.handler.addClass("discogs-embed"),this.load()},b.prototype.clear=function(){this.handler.off("click")},b}(),a.fn.discogs=function(a){return this.myPluginInstance?this.myPluginInstance.update(a||{}):this.myPluginInstance=new b(this,a||{}),this.myPluginInstance.init(),this.show()}}(jQuery);<commit_msg>Build dist.<commit_after>this.discogsEmbed=this.discogsEmbed||{},this.discogsEmbed.templates=this.discogsEmbed.templates||{},this.discogsEmbed.templates.error=Handlebars.template({compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f="function",g=b.helperMissing,h=this.escapeExpression;return'
\n
Discogs Embed - Ooooops!
\n
Seems like something went wrong when loading resource with id '+h((e=null!=(e=b.id||(null!=a?a.id:a))?e:g,typeof e===f?e.call(a,{name:"id",hash:{},data:d}):e))+' : ((
\n
Please reload!
\n
'},useData:!0}),this.discogsEmbed.templates.main=Handlebars.template({1:function(a,b,c,d){var e,f="function",g=b.helperMissing,h=this.escapeExpression;return'      '+h((e=null!=(e=b.name||(null!=a?a.name:a))?e:g,typeof e===f?e.call(a,{name:"name",hash:{},data:d}):e))+"\n"},3:function(a,b,c,d){var e,f='
\n';return e=b.each.call(a,null!=(e=null!=a?a.data:a)?e.formats:e,{name:"each",hash:{},fn:this.program(4,d),inverse:this.noop,data:d}),null!=e&&(f+=e),f+"
\n"},4:function(a,b,c,d){var e,f="        ";return e=b.each.call(a,null!=a?a.descriptions:a,{name:"each",hash:{},fn:this.program(5,d),inverse:this.noop,data:d}),null!=e&&(f+=e),f+"\n"},5:function(a){var b=this.lambda,c=this.escapeExpression;return"
"+c(b(a,a))+"
"},7:function(a){var b,c=this.lambda,d=this.escapeExpression;return'    / '+d(c(null!=(b=null!=(b=null!=(b=null!=a?a.data:a)?b.labels:b)?b[0]:b)?b.name:b,a))+' ('+d(c(null!=(b=null!=(b=null!=(b=null!=a?a.data:a)?b.labels:b)?b[0]:b)?b.catno:b,a))+")\n"},9:function(){return" collapsed"},11:function(){return" ellipsed"},13:function(a,b,c,d){var e,f=b.helperMissing,g="";return e=(b.isTrack||a&&a.isTrack||f).call(a,a,{name:"isTrack",hash:{},fn:this.program(14,d),inverse:this.program(18,d),data:d}),null!=e&&(g+=e),g},14:function(a,b,c,d){var e,f,g="function",h=b.helperMissing,i=this.escapeExpression,j='
\n        '+i((f=null!=(f=b.position||(null!=a?a.position:a))?f:h,typeof f===g?f.call(a,{name:"position",hash:{},data:d}):f))+"\n";return e=b["if"].call(a,null!=a?a.artists:a,{name:"if",hash:{},fn:this.program(15,d),inverse:this.noop,data:d}),null!=e&&(j+=e),j+'        '+i((f=null!=(f=b.title||(null!=a?a.title:a))?f:h,typeof f===g?f.call(a,{name:"title",hash:{},data:d}):f))+'\n        '+i((f=null!=(f=b.duration||(null!=a?a.duration:a))?f:h,typeof f===g?f.call(a,{name:"duration",hash:{},data:d}):f))+"\n
\n"},15:function(a,b,c,d){var e,f="          ";return e=b.each.call(a,null!=a?a.artists:a,{name:"each",hash:{},fn:this.program(16,d),inverse:this.noop,data:d}),null!=e&&(f+=e),f+"\n          - \n"},16:function(a,b,c,d){var e,f="function",g=b.helperMissing,h=this.escapeExpression;return''+h((e=null!=(e=b.name||(null!=a?a.name:a))?e:g,typeof e===f?e.call(a,{name:"name",hash:{},data:d}):e))+""},18:function(a,b,c,d){var e,f="function",g=b.helperMissing,h=this.escapeExpression;return'
'+h((e=null!=(e=b.title||(null!=a?a.title:a))?e:g,typeof e===f?e.call(a,{name:"title",hash:{},data:d}):e))+"
\n"},20:function(){return'
\n      \n        more\n        less\n      \n
\n'},compiler:[6,">= 2.0.0-beta.1"],main:function(a,b,c,d){var e,f=this.lambda,g=this.escapeExpression,h=b.helperMissing,i='\n
\n';return e=b.each.call(a,null!=(e=null!=a?a.data:a)?e.artists:e,{name:"each",hash:{},fn:this.program(1,d),inverse:this.noop,data:d}),null!=e&&(i+=e),i+="    - "+g(f(null!=(e=null!=a?a.data:a)?e.title:e,a))+'\n    '+g(f(null!=(e=null!=a?a.data:a)?e.year:e,a))+'\n
\n
\n    '+g(f(null!=(e=null!=a?a.data:a)?e.country:e,a))+" / \n",e=b["if"].call(a,null!=(e=null!=a?a.data:a)?e.formats:e,{name:"if",hash:{},fn:this.program(3,d),inverse:this.noop,data:d}),null!=e&&(i+=e),e=b["if"].call(a,null!=(e=null!=a?a.data:a)?e.labels:e,{name:"if",hash:{},fn:this.program(7,d),inverse:this.noop,data:d}),null!=e&&(i+=e),i+='
\n\n
\n
\n    \n      \n    \n
\n
\n
\n',e=b.each.call(a,null!=(e=null!=a?a.data:a)?e.tracklist:e,{name:"each",hash:{},fn:this.program(13,d),inverse:this.noop,data:d}),null!=e&&(i+=e),i+="
\n",e=(b.isCollapsed||a&&a.isCollapsed||h).call(a,null!=(e=null!=a?a.data:a)?e.tracklist:e,{name:"isCollapsed",hash:{},fn:this.program(20,d),inverse:this.noop,data:d}),null!=e&&(i+=e),i+'
\n
\n\n  \n    This data comes from  Discogs. Found any error? Go edit the original entry!\n  \n'},useData:!0}),function(a){var b,c,d;d=function(a,b){return function(){return a.apply(b,arguments)}},c={api:{baseUrl:"https://api.discogs.com"},imageCacheUrl:"/images/discogs",ui:{collapseThreshold:10}},defaultDiscogsOptions={releaseType:"releases",id:1990898},b=function(){function b(b,e){var f=this;this.handler=b,a.extend(!0,this,c,e),this.init=d(this.init,this),this.load=d(this.load,this),this.clear=d(this.clear,this),this.expand=d(this.expand,this),this.reload=d(this.reload,this),this._done=d(this._done,this),this._fail=d(this._fail,this),this._always=d(this._always,this),this.templates=window.discogsEmbed.templates,Handlebars.registerHelper("isCollapsed",function(a,b){return a.length>f.ui.collapseThreshold?b.fn(this):null}),Handlebars.registerHelper("isTrack",function(a,b){return"track"==a.type_?b.fn(this):b.inverse(this)});var f=this;this._done=function(a){a.data.image=f.imageCacheUrl+"/"+a.data.id+".jpeg",f.handler.toggleClass("error",!1).html(f.templates.main({data:a.data}))},this._fail=function(){f.handler.toggleClass("error",!0).html(f.templates.error({id:f.discogsData.id}))},this._always=function(){f.handler.toggleClass("loading",!1)}}return b.prototype.expand=function(a){a.preventDefault();var b=this.$tracklist||(this.$tracklist=this.handler.find(".tracklist"));b.toggleClass("collapsed",!b.is(".collapsed")).find("ul").toggleClass("ellipsed",!!b.is(".collapsed"))},b.prototype.reload=function(a){a.preventDefault(),this.load()},b.prototype.load=function(){return this.handler.toggleClass("loading",!0),a.getJSON(this.api.baseUrl+"/"+this.discogsData.releaseType+"/"+this.discogsData.id+"?callback=?").done(this._done).fail(this._fail).always(this._always)},b.prototype.init=function(){this.discogsData=a.extend(!0,defaultDiscogsOptions,this.handler.data()),this.handler.on("click",".more",this.expand),this.handler.on("click",".reload",this.reload),this.handler.addClass("discogs-embed"),this.load()},b.prototype.clear=function(){this.handler.off("click")},b}(),a.fn.discogs=function(a){return this.myPluginInstance?this.myPluginInstance.update(a||{}):this.myPluginInstance=new b(this,a||{}),this.myPluginInstance.init(),this.show()}}(jQuery);<|endoftext|>


<commit_before>class PerfectNumbers{

  /**
  * Classifies numbers to either perfect, abundant or deficient base on their
  aliquot sum
  @param {Number} number to classify
  @returns {String} whether the number is perfect, abundant or deficient
  */
  classify(number){
    // classify perfect numbers

    //classify abundant numbers

    // classify deficient numbers
  }

  /**
  Gets the aliquot sum

  @param {Number} num the number to derive the aliquot sum
  @returns {Number} the sum of the factors of the provided number
  */
  getAliquotSum(num){
    // ensures a whole number, total = 1, 1 will be part of the solution
    var half = Math.floor(num / 2), total = 1, i, j;

    // determine the increment value for the loop and starting point
    num % 2 === 0 ? (i = 2, j = 1) : (i = 3, j = 2);

    for(i; i <= half;i += j){
      num % i === 0 ? total += i: false;
    }

    // include the original number
    total += num;
    return total;
  }
}

module.exports = PerfectNumbers;
<commit_msg>Change implementation for classify method<commit_after>class PerfectNumbers{

  /**
  * Classifies numbers to either perfect, abundant or deficient base on their
  aliquot sum
  @param {Number} number to classify
  @returns {String} whether the number is perfect, abundant or deficient
  */
  classify(number){
    if(number <= 0){
      return "Classification is only possible for natural numbers."
    }
    // classify deficient numbers
    if(this.getAliquotSum(number) < number || number === 1){
      return "deficient";
    }
    // classify perfect numbers
    if(this.getAliquotSum(number) == number){
      return "perfect";
    }
    //classify abundant numbers
    if(this.getAliquotSum(number) > number){
      return "abundant";
    }

  }

  /**
  Gets the aliquot sum

  @param {Number} num the number to derive the aliquot sum
  @returns {Number} the sum of the factors of the provided number
  */
  getAliquotSum(num){
    // ensures a whole number, total = 1, 1 will be part of the solution
    var half = Math.floor(num / 2), total = 1, i, j;

    // determine the increment value for the loop and starting point
    num % 2 === 0 ? (i = 2, j = 1) : (i = 3, j = 2);

    for(i; i <= half;i += j){
      num % i === 0 ? total += i: false;
    }

    return total;
  }
}

module.exports = PerfectNumbers;
<|endoftext|>


<commit_before>/*
WYSIWYG arguments

enableKeyboardExtras {boolean} enable creating new components on enter, and appending text to previous components on delete, etc
buttons {array} array of button names (strings) for tooltip
styled {boolean} apply input styles to contenteditable element
 */

var _ = require('lodash'),
  select = require('selection-range'),
  MediumEditor = require('medium-editor'),
  MediumButton = require('../services/medium-button'),
  dom = require('../services/dom'),
  db = require('../services/db'),
  render = require('../services/render'),
  focus = require('../decorators/focus'),
  references = require('../services/references'),
  edit = require('../services/edit'),
  model = require('../services/model-text'),
  refAttr = references.referenceAttribute;

/**
 * toggle the tiered toolbar
 * this is the action for the tieredToolbar extension
 * @param {Element} html
 * @returns {Element}
 */
function toggleTieredToolbar(html) {
  // note: this element doesn't exist before it's instantiated, so we need to grab it afterwards
  var toolbar = dom.find('.medium-editor-toolbar'),
    toolbarClasses = toolbar.classList;

  if (toolbarClasses.contains('show-none')) {
    toolbarClasses.remove('show-none');
  } else if (toolbarClasses.contains('show-all')) {
    toolbarClasses.add('show-none');
  } else {
    toolbarClasses.add('show-all');
  }
  return html;
}

/**
 * create new medium editor
 * @param {Element} field
 * @param {array} buttons
 * @returns {Element}
 */
function createEditor(field, buttons) {
  return new MediumEditor(field, {
    toolbar: {
      // buttons that go in the toolbar
      buttons: buttons,
      standardizeSelectionStart: true,
      allowMultiParagraphSelection: false
    },
    delay: 200, // wait a bit for the toolbar and link previews to display
    paste: {
      forcePlainText: false,
      cleanPastedHTML: true, // clean html from sources like google docs
      cleanTags: [ // remove these tags when pasting
        'meta',
        'script',
        'style',
        'img',
        'object',
        'iframe'
      ],
      cleanReplacements: [
        [/<h[1-9]>/ig, '
'],
        [/<\/h[1-9]>/ig, '
'], // force all headers to the same level
        [/
/ig, ''], // get rid of
 tags
        [/<\/p>/ig, '']
      ]
    },
    autoLink: true, // create links automatically when urls are entered
    imageDragging: false, // disallow dragging inline images
    targetBlank: true,
    disableReturn: true,
    placeholder: false, // the placeholder isn't native
    extensions: {
      tieredToolbar: new MediumButton({
        label: '…',
        action: toggleTieredToolbar
      })
    }
  });
}

/**
 * get elements and data for the current component
 * @param {Element} el
 * @returns {object}
 */
function getCurrent(el) {
  var currentComponent = dom.closest(el, '[' + refAttr + ']'),
    currentComponentRef = currentComponent.getAttribute(refAttr);

  return {
    field: el.getAttribute(references.fieldAttribute),
    component: currentComponent,
    ref: currentComponentRef,
    name: references.getComponentNameFromReference(currentComponentRef)
  };
}

/**
 * get elements and data for the parent component
 * @param {Element} el of the current component
 * @returns {object}
 */
function getParent(el) {
  var parentNode = el.parentNode,
    parentComponent = dom.closest(parentNode, '[' + refAttr + ']'),
    parentComponentRef = parentComponent.getAttribute(refAttr);

  return {
    field: dom.closest(parentNode, '[' + references.editableAttribute + ']').getAttribute(references.editableAttribute),
    component: parentComponent,
    ref: parentComponentRef,
    name: references.getComponentNameFromReference(parentComponentRef)
  };
}

/**
 * get previous component in list, if any
 * @param {object} current
 * @param {object} parent
 * @returns {Promise} with {_ref: previous ref} or undefined
 */
function getPrev(current, parent) {
  return edit.getDataOnly(parent.ref).then(function (parentData) {
    var index = _.findIndex(parentData[parent.field], { _ref: current.ref }),
      before = _.take(parentData[parent.field], index),
      prev = _.findLast(before, function (component) {
        return references.getComponentNameFromReference(component._ref) === current.name;
      });

    if (prev) {
      return {
        field: current.field,
        component: dom.find(parent.component, '[' + refAttr + '="' + prev._ref + '"]'),
        ref: prev._ref,
        name: current.name
      };
    }
  });
}

/**
 * get the contents of a wysiwyg field
 * note: if we want to remove / parse / sanitize contents when doing operations,
 * this is the place we should do it
 * @param {Element} el
 * @returns {string}
 */
function getFieldContents(el) {
  return el.innerHTML;
}

/**
 * append text/html to previous component's field
 * @param {string} html
 * @param {object} prev
 * @returns {Promise}
 */
function appendToPrev(html, prev) {
  // note: get fresh data from the server
  return db.getComponentJSONFromReference(prev.ref).then(function (prevData) {
    var prevFieldData = _.get(prevData, prev.field);

    // add current field's html to the end of the previous field
    prevFieldData += html;
    // then put it back into the previous component's data
    _.set(prevData, prev.field, prevFieldData);
    return db.putToReference(prev.ref, prevData);
  });
}

/**
 * remove current component from parent
 * @param {object} current
 * @param {object} parent
 * @returns {Function}
 */
function removeCurrentFromParent(current, parent) {
  return function () {
    return edit.removeFromParentList({el: current.component, ref: current.ref, parentField: parent.field, parentRef: parent.ref});
  };
}

/**
 * reload previous component
 * note: this differs from the reload / render function in that it only reloads
 * a single instance of that component on the page
 * @param {object} prev
 * @returns {Function}
 */
function reloadPreviousComponent(prev) {
  return function () {
    return db.getComponentHTMLFromReference(prev.ref)
      .then(function (updatedEl) {
        render.addComponentsHandlers(updatedEl);
        dom.replaceElement(prev.component, updatedEl);
        return updatedEl;
      });
  };
}

/**
 * focus on the previous component's field
 * @param {object} parent
 * @param  {object} prev
 * @param {number} textLength
 * @returns {Function}
 */
function focusPreviousComponent(parent, prev, textLength) {
  return function (newEl) {
    return focus.focus(newEl, { ref: prev.ref, path: prev.field }).then(function () {
      var prevField = dom.find('[data-ref="' + prev.ref + '"] [data-field]');

      // focus on the new wysiwyg field
      prevField.focus();
      // set caret right before the new text we added
      select(prevField, { start: prevField.textContent.length - textLength });
    });
  };
}

/**
 * remove current component, append text to previous component (of the same name)
 * @param {Element} el
 * @returns {Promise|undefined}
 */
function removeComponent(el) {
  var current = getCurrent(el),
    parent = getParent(current.component),
    textLength = el.innerText.length;

  // find the previous component, if any
  return getPrev(current, parent).then(function (prev) {
    if (prev) {
      // there's a previous component with the same name!
      // get the contents of the current field, and append them to the previous component
      return appendToPrev(getFieldContents(el), prev)
        .then(removeCurrentFromParent(current, parent))
        .then(reloadPreviousComponent(prev))
        .then(focusPreviousComponent(parent, prev, textLength));
    }
  });
}

/**
 * add component after current component
 * @param {Element} el
 * @returns {Promise}
 */
function addComponent(el) {
  var current = getCurrent(el);

  // create a new component
  return db.postToReference('/components/' + current.name + '/instances', {}).then(function (res) {
    var newRef = res._ref;

    // get the html of that new component
    return db.getComponentHTMLFromReference(newRef).then(function (newEl) {
      // add the handlers for the new component
      render.addComponentsHandlers(newEl);
      // then add it after the current one
      dom.insertAfter(current.component, newEl);
      // then focus() the new field that's the same as the current field
      focus.focus(newEl, { ref: newRef, path: current.field }).then(function () {
        dom.find('[data-ref="' + newRef + '"] [data-field]').focus();
      });

      return newRef;
    });
  }).then(function (ref) { // update the parent component's component list
    var parent = getParent(current.component);

    return edit.getDataOnly(parent.ref).then(function (parentData) {
      var index = _.findIndex(parentData[parent.field], { _ref: current.ref }) + 1;

      parentData[parent.field].splice(index, 0, { _ref: ref }); // splice the new component into the array after the current one
      return db.putToReference(parent.ref, parentData);
    });
  });
}

/**
 * remove current component if we're at the beginning of the field
 * and there's a previous component to append it to
 * @param {Element} el
 * @param {KeyboardEvent} e
 * @returns {undefined|Promise}
 */
function handleComponentDeletion(el, e) {
  var caretPos = select(el);

  if (caretPos.start === 0) {
    e.preventDefault(); // stop page reload
    return removeComponent(el);
  }
}

/**
 * create new component if we're at the end of the field
 * @param {Element} el
 * @returns {false|Promise}
 */
function handleComponentCreation(el) {
  var caretPos = select(el); // get text after the cursor, if any

  // if there's stuff after the caret, get it
  if (caretPos.start < el.textContent.length - 1) {
    console.log(el.innerText.substr(caretPos.start));
    // todo: split paragraphs, add new component with text after caret
    return false; // don't do anything if you're not at the end
  } else {
    return addComponent(el);
  }
}

function isStyled(styled) {
  return styled ? ' styled' : ''; // note the preeeding space!
}

function addLineBreak() {
  var selection = window.getSelection(),
    range = selection.getRangeAt(0),
    br = document.createElement('br');

  // woah, crazy stuff!
  // this creates a range, inserts the
 tag, then sets the caret after it
  range.deleteContents();
  range.insertNode(br);
  range.setStartAfter(br);
  range.setEndAfter(br);
  range.collapse(false);
  selection.removeAllRanges();
  selection.addRange(range);
}

module.exports = function (result, args) {
  var rivets = result.rivets,
    buttons = args.buttons,
    styled = args.styled,
    enableKeyboardExtras = args.enableKeyboardExtras,
    textInput = dom.find(result.el, 'input') || dom.find(result.el, 'textarea'),
    field = dom.create(`<p class="wysiwyg-input${ isStyled(styled) }" data-field="${result.bindings.name}" rv-wysiwyg="data.value"></p>`);

  // if more than 5 buttons, put the rest on the second tier
  if (buttons.length > 5) {
    buttons.splice(5, 0, 'tieredToolbar'); // clicking this expands the toolbar with a second tier
  }

  // put the rich text field after the input
  dom.replaceElement(textInput, field);

  rivets.binders.wysiwyg = {
    publish: true,
    bind: function (el) {
      // this is called when the binder initializes
      var observer = this.observer,
        data = observer.value() || '', // don't print 'undefined' if there's no data
        editor = createEditor(field, buttons);

      // put the initial data into the editor
      el.innerHTML = data;

      // hide the tier2 buttons when closing the toolbar
      editor.subscribe('hideToolbar', function () {
        dom.find('.medium-editor-toolbar').classList.remove('show-all');
        dom.find('.medium-editor-toolbar').classList.remove('show-none');
      });

      // persist editor data to data model on input
      editor.subscribe('editableInput', function (e, editable) {
        observer.setValue(editable.innerHTML);
      });

      // persist editor data to data model on paste
      editor.subscribe('editablePaste', function (e, editable) {
        var textmodel = model.fromElement(dom.create(editable.innerHTML)),
          fragment = model.toElement(textmodel);

        dom.clearChildren(editable); // clear the current children
        editable.appendChild(fragment); // add the cleaned dom fragment
        observer.setValue(editable.innerHTML);
      });

      editor.subscribe('editableKeydownDelete', function (e, editable) {
        if (enableKeyboardExtras) {
          handleComponentDeletion(editable, e);
        }
      });

      editor.subscribe('editableKeydownEnter', function (e, editable) {
        if (enableKeyboardExtras && e.shiftKey) {
          // shift+enter was pressed. add a line break
          addLineBreak();
        } else if (enableKeyboardExtras) {
          // enter was pressed. create a new component if certain conditions are met
          handleComponentCreation(editable);
        } else {
          // close the form?
          focus.unfocus();
        }
      });
    }
  };

  return result;
};
<commit_msg>comments<commit_after>/*
WYSIWYG arguments

enableKeyboardExtras {boolean} enable creating new components on enter, and appending text to previous components on delete, etc
buttons {array} array of button names (strings) for tooltip
styled {boolean} apply input styles to contenteditable element
 */

var _ = require('lodash'),
  select = require('selection-range'),
  MediumEditor = require('medium-editor'),
  MediumButton = require('../services/medium-button'),
  dom = require('../services/dom'),
  db = require('../services/db'),
  render = require('../services/render'),
  focus = require('../decorators/focus'),
  references = require('../services/references'),
  edit = require('../services/edit'),
  model = require('../services/model-text'),
  refAttr = references.referenceAttribute;

/**
 * toggle the tiered toolbar
 * this is the action for the tieredToolbar extension
 * @param {Element} html
 * @returns {Element}
 */
function toggleTieredToolbar(html) {
  // note: this element doesn't exist before it's instantiated, so we need to grab it afterwards
  var toolbar = dom.find('.medium-editor-toolbar'),
    toolbarClasses = toolbar.classList;

  if (toolbarClasses.contains('show-none')) {
    toolbarClasses.remove('show-none');
  } else if (toolbarClasses.contains('show-all')) {
    toolbarClasses.add('show-none');
  } else {
    toolbarClasses.add('show-all');
  }
  return html;
}

/**
 * create new medium editor
 * @param {Element} field
 * @param {array} buttons
 * @returns {Element}
 */
function createEditor(field, buttons) {
  return new MediumEditor(field, {
    toolbar: {
      // buttons that go in the toolbar
      buttons: buttons,
      standardizeSelectionStart: true,
      allowMultiParagraphSelection: false
    },
    delay: 200, // wait a bit for the toolbar and link previews to display
    paste: {
      forcePlainText: false,
      cleanPastedHTML: true, // clean html from sources like google docs
      cleanTags: [ // remove these tags when pasting
        'meta',
        'script',
        'style',
        'img',
        'object',
        'iframe'
      ],
      cleanReplacements: [
        [/<h[1-9]>/ig, '
'],
        [/<\/h[1-9]>/ig, '
'], // force all headers to the same level
        [/
/ig, ''], // get rid of
 tags
        [/<\/p>/ig, '']
      ]
    },
    autoLink: true, // create links automatically when urls are entered
    imageDragging: false, // disallow dragging inline images
    targetBlank: true,
    disableReturn: true,
    placeholder: false, // the placeholder isn't native
    extensions: {
      tieredToolbar: new MediumButton({
        label: '…',
        action: toggleTieredToolbar
      })
    }
  });
}

/**
 * get elements and data for the current component
 * @param {Element} el
 * @returns {object}
 */
function getCurrent(el) {
  var currentComponent = dom.closest(el, '[' + refAttr + ']'),
    currentComponentRef = currentComponent.getAttribute(refAttr);

  return {
    field: el.getAttribute(references.fieldAttribute),
    component: currentComponent,
    ref: currentComponentRef,
    name: references.getComponentNameFromReference(currentComponentRef)
  };
}

/**
 * get elements and data for the parent component
 * @param {Element} el of the current component
 * @returns {object}
 */
function getParent(el) {
  var parentNode = el.parentNode,
    parentComponent = dom.closest(parentNode, '[' + refAttr + ']'),
    parentComponentRef = parentComponent.getAttribute(refAttr);

  return {
    field: dom.closest(parentNode, '[' + references.editableAttribute + ']').getAttribute(references.editableAttribute),
    component: parentComponent,
    ref: parentComponentRef,
    name: references.getComponentNameFromReference(parentComponentRef)
  };
}

/**
 * get previous component in list, if any
 * @param {object} current
 * @param {object} parent
 * @returns {Promise} with {_ref: previous ref} or undefined
 */
function getPrev(current, parent) {
  return edit.getDataOnly(parent.ref).then(function (parentData) {
    var index = _.findIndex(parentData[parent.field], { _ref: current.ref }),
      before = _.take(parentData[parent.field], index),
      prev = _.findLast(before, function (component) {
        return references.getComponentNameFromReference(component._ref) === current.name;
      });

    if (prev) {
      return {
        field: current.field,
        component: dom.find(parent.component, '[' + refAttr + '="' + prev._ref + '"]'),
        ref: prev._ref,
        name: current.name
      };
    }
  });
}

/**
 * get the contents of a wysiwyg field
 * note: if we want to remove / parse / sanitize contents when doing operations,
 * this is the place we should do it
 * @param {Element} el
 * @returns {string}
 */
function getFieldContents(el) {
  return el.innerHTML;
}

/**
 * append text/html to previous component's field
 * @param {string} html
 * @param {object} prev
 * @returns {Promise}
 */
function appendToPrev(html, prev) {
  // note: get fresh data from the server
  return db.getComponentJSONFromReference(prev.ref).then(function (prevData) {
    var prevFieldData = _.get(prevData, prev.field);

    // add current field's html to the end of the previous field
    prevFieldData += html;
    // then put it back into the previous component's data
    _.set(prevData, prev.field, prevFieldData);
    return db.putToReference(prev.ref, prevData);
  });
}

/**
 * remove current component from parent
 * @param {object} current
 * @param {object} parent
 * @returns {Function}
 */
function removeCurrentFromParent(current, parent) {
  return function () {
    return edit.removeFromParentList({el: current.component, ref: current.ref, parentField: parent.field, parentRef: parent.ref});
  };
}

/**
 * reload previous component
 * note: this differs from the reload / render function in that it only reloads
 * a single instance of that component on the page
 * @param {object} prev
 * @returns {Function}
 */
function reloadPreviousComponent(prev) {
  return function () {
    return db.getComponentHTMLFromReference(prev.ref)
      .then(function (updatedEl) {
        render.addComponentsHandlers(updatedEl);
        dom.replaceElement(prev.component, updatedEl);
        return updatedEl;
      });
  };
}

/**
 * focus on the previous component's field
 * @param {object} parent
 * @param  {object} prev
 * @param {number} textLength
 * @returns {Function}
 */
function focusPreviousComponent(parent, prev, textLength) {
  return function (newEl) {
    return focus.focus(newEl, { ref: prev.ref, path: prev.field }).then(function () {
      var prevField = dom.find('[data-ref="' + prev.ref + '"] [data-field]');

      // focus on the new wysiwyg field
      prevField.focus();
      // set caret right before the new text we added
      select(prevField, { start: prevField.textContent.length - textLength });
    });
  };
}

/**
 * remove current component, append text to previous component (of the same name)
 * @param {Element} el
 * @returns {Promise|undefined}
 */
function removeComponent(el) {
  var current = getCurrent(el),
    parent = getParent(current.component),
    textLength = el.innerText.length;

  // find the previous component, if any
  return getPrev(current, parent).then(function (prev) {
    if (prev) {
      // there's a previous component with the same name!
      // get the contents of the current field, and append them to the previous component
      return appendToPrev(getFieldContents(el), prev)
        .then(removeCurrentFromParent(current, parent))
        .then(reloadPreviousComponent(prev))
        .then(focusPreviousComponent(parent, prev, textLength));
    }
  });
}

/**
 * add component after current component
 * @param {Element} el
 * @returns {Promise}
 */
function addComponent(el) {
  var current = getCurrent(el);

  // create a new component
  return db.postToReference('/components/' + current.name + '/instances', {}).then(function (res) {
    var newRef = res._ref;

    // get the html of that new component
    return db.getComponentHTMLFromReference(newRef).then(function (newEl) {
      // add the handlers for the new component
      render.addComponentsHandlers(newEl);
      // then add it after the current one
      dom.insertAfter(current.component, newEl);
      // then focus() the new field that's the same as the current field
      focus.focus(newEl, { ref: newRef, path: current.field }).then(function () {
        dom.find('[data-ref="' + newRef + '"] [data-field]').focus();
      });

      return newRef;
    });
  }).then(function (ref) { // update the parent component's component list
    var parent = getParent(current.component);

    return edit.getDataOnly(parent.ref).then(function (parentData) {
      var index = _.findIndex(parentData[parent.field], { _ref: current.ref }) + 1;

      parentData[parent.field].splice(index, 0, { _ref: ref }); // splice the new component into the array after the current one
      return db.putToReference(parent.ref, parentData);
    });
  });
}

/**
 * remove current component if we're at the beginning of the field
 * and there's a previous component to append it to
 * @param {Element} el
 * @param {KeyboardEvent} e
 * @returns {undefined|Promise}
 */
function handleComponentDeletion(el, e) {
  var caretPos = select(el);

  if (caretPos.start === 0) {
    e.preventDefault(); // stop page reload
    return removeComponent(el);
  }
}

/**
 * create new component if we're at the end of the field
 * @param {Element} el
 * @returns {false|Promise}
 */
function handleComponentCreation(el) {
  var caretPos = select(el); // get text after the cursor, if any

  // if there's stuff after the caret, get it
  if (caretPos.start < el.textContent.length - 1) {
    console.log(el.innerText.substr(caretPos.start));
    // todo: split paragraphs, add new component with text after caret
    return false; // don't do anything if you're not at the end
  } else {
    return addComponent(el);
  }
}

function isStyled(styled) {
  return styled ? ' styled' : ''; // note the preeeding space!
}

function addLineBreak() {
  var selection = window.getSelection(),
    range = selection.getRangeAt(0),
    br = document.createElement('br');

  // woah, crazy stuff!
  // this creates a range, inserts the
 tag, then sets the caret after it
  range.deleteContents();
  range.insertNode(br);
  range.setStartAfter(br);
  range.setEndAfter(br);
  range.collapse(false);
  selection.removeAllRanges();
  selection.addRange(range);
}

module.exports = function (result, args) {
  var rivets = result.rivets,
    buttons = args.buttons,
    styled = args.styled,
    enableKeyboardExtras = args.enableKeyboardExtras,
    textInput = dom.find(result.el, 'input') || dom.find(result.el, 'textarea'),
    field = dom.create(`<p class="wysiwyg-input${ isStyled(styled) }" data-field="${result.bindings.name}" rv-wysiwyg="data.value"></p>`);

  // if more than 5 buttons, put the rest on the second tier
  if (buttons.length > 5) {
    buttons.splice(5, 0, 'tieredToolbar'); // clicking this expands the toolbar with a second tier
  }

  // put the rich text field after the input
  dom.replaceElement(textInput, field);

  rivets.binders.wysiwyg = {
    publish: true,
    bind: function (el) {
      // this is called when the binder initializes
      var observer = this.observer,
        data = observer.value() || '', // don't print 'undefined' if there's no data
        editor = createEditor(field, buttons);

      // put the initial data into the editor
      el.innerHTML = data;

      // hide the tier2 buttons when closing the toolbar
      editor.subscribe('hideToolbar', function () {
        dom.find('.medium-editor-toolbar').classList.remove('show-all');
        dom.find('.medium-editor-toolbar').classList.remove('show-none');
      });

      // persist editor data to data model on input
      editor.subscribe('editableInput', function (e, editable) {
        observer.setValue(editable.innerHTML);
      });

      // persist editor data to data model on paste
      editor.subscribe('editablePaste', function (e, editable) {
        var textmodel = model.fromElement(dom.create(editable.innerHTML)),
          fragment = model.toElement(textmodel);

        // note: we're using the model-text service to clean up and standardize html
        // this is in addition to the cleanup that medium-editor does by default,
        // as well as the options we specified in the cleanTags / cleanReplacements paste config

        dom.clearChildren(editable); // clear the current children
        editable.appendChild(fragment); // add the cleaned dom fragment
        observer.setValue(editable.innerHTML);
      });

      editor.subscribe('editableKeydownDelete', function (e, editable) {
        if (enableKeyboardExtras) {
          handleComponentDeletion(editable, e);
        }
      });

      editor.subscribe('editableKeydownEnter', function (e, editable) {
        if (enableKeyboardExtras && e.shiftKey) {
          // shift+enter was pressed. add a line break
          addLineBreak();
        } else if (enableKeyboardExtras) {
          // enter was pressed. create a new component if certain conditions are met
          handleComponentCreation(editable);
        } else {
          // close the form?
          focus.unfocus();
        }
      });
    }
  };

  return result;
};
<|endoftext|>


<commit_before>var dataset = [ 5, 10, 15, 20, 25 ];

var exampleInput = { "queues":[
                        {
                          "name": "name1",
                          "occupancy": 5,
                          "target-size": 10
                        },
                        {
                          "queue-name": "name2",
                          "occupancy": 7,
                          "target-size": 12
                        }
                    ]
                  }

//d3.select("body").selectAll("div")
//    .data(dataset)
//    .enter()
//    .append("div")
//    .attr("class", "bar");

// Your beautiful D3 code will go here
var svg = d3.select("body").append("svg");
svg.style("width", "100%")
var mySquare=svg.selectAll("rect")
    .data(dataset)
    .enter()
    .append("rect")
    .attr("x",function(d, i) { return (i * 50) + 25; })
    .attr("y",svg.height / 2)
    .attr("width",30)
    .attr("height",30)
    .transition()
    .attr("x",function(d, i) { return (i * 50) + 25 + 1000; })
    .duration(2000)
    .delay(100)<commit_msg>now reading the queues data snapshot<commit_after>var dataset = [ 5, 10, 15, 20, 25 ];

var queuesSnapshotJson =
                        [
                            {
                              "name": "name1",
                              "occupancy": 5,
                              "target-size": 10
                            }, {
                              "name": "name1",
                              "occupancy": 5,
                              "target-size": 10
                            }, {
                              "name": "name1",
                              "occupancy": 5,
                              "target-size": 10
                            }, {
                              "name": "name1",
                              "occupancy": 5,
                              "target-size": 10
                            }
                        ];

//d3.select("body").selectAll("div")
//    .data(dataset)
//    .enter()
//    .append("div")
//    .attr("class", "bar");

// Your beautiful D3 code will go here
var svg = d3.select("body").append("svg");
svg.style("width", "100%")
var mySquare=svg.selectAll("rect")
    .data(queuesSnapshotJson)
    .enter()
    .append("rect")
    .attr("x",function(d, i) { return (i * 50) + 25; })
    .attr("y",svg.height / 2)
    .attr("width",30)
    .attr("height",30)
    .transition()
    .attr("x",function(d, i) { return (i * 50) + 25 + 1000; })
    .duration(2000)
    .delay(100)<|endoftext|>


<commit_before>import React from "react";
import { compose, withProps } from "recompose";
import _ from "lodash";
import {
  Nav,
  NavItem,
  Panel,
  Button,
  ButtonGroup,
  ButtonToolbar
} from "react-bootstrap";

import ApplicationForm from "./application_form.js";
import ApplicationTerminal from "./application_terminal.js";
import OpenUrl from "./open_url.js";
import OpenBlob from "./open_blob.js";
import withUIState from "./with_ui_state.js";

export default compose(
  withProps({ handleMessages: true }),
  withUIState
)(
  class LocalhostDConsole extends React.Component {
    state = {
      activeApplicationIndex: -1,
      creatingApplication: false,
      tab: "terminal"
    };

    render() {
      const { uiState, doAction } = this.props;

      const uiApplication = uiState.applications.find(
        a =>
          a.domain === window.location.hostname ||
          window.location.hostname.endsWith(`.${a.domain}`)
      );

      if (uiApplication && !uiApplication.locked && uiApplication.running)
        window.location.reload();

      const activeApplication =
        uiApplication ||
        uiState.applications[this.state.activeApplicationIndex];

      return (
        <>
          {!uiApplication && (

                {_.sortBy(
                  uiState.applications.map((a, index) => ({
                    ...a,
                    index
                  })),
                  a => a.name
                ).map(application => (
                  <NavItem
                    key={application.name}
                    active={
                      this.state.activeApplicationIndex === application.index
                    }
                    onClick={() =>
                      this.setState({
                        activeApplicationIndex: application.index,
                        creatingApplication: false
                      })
                    }
                  >

                    {application.name}
                  </NavItem>
                ))}
                <NavItem
                  active={this.state.creatingApplication}
                  onClick={() =>
                    this.setState({
                      creatingApplication: true,
                      activeApplicationIndex: -1
                    })
                  }
                >

                  New application
                </NavItem>
                <NavItem
                  active={!this.state.creatingApplication && !activeApplication}
                  onClick={() =>
                    this.setState({
                      creatingApplication: false,
                      activeApplicationIndex: -1
                    })
                  }
                >

                  Tips
                </NavItem>

          )}

            {this.state.creatingApplication && (

                <Panel>
                  <Panel.Heading>New application</Panel.Heading>
                  <Panel.Body>
                    <ApplicationForm
                      application={{
                        dir: uiState.homedir,
                        env: {},
                        timeout: 600
                      }}
                      creating
                      onSubmit={applicationData => {
                        doAction("CreateApplication", {
                          applicationData
                        });

                        this.setState({
                          creatingApplication: false
                        });
                      }}
                    >
                      <Button
                        onClick={ev =>
                          this.setState({
                            creatingApplication: false
                          })
                        }
                      >
                        Cancel
                      </Button>
                    </ApplicationForm>
                  </Panel.Body>
                </Panel>

            )}
            {!this.state.creatingApplication && !!activeApplication && (
              <React.Fragment key={activeApplication.name}>
                <Panel
                  style={{
                    flex: "0 0 auto",
                    margin: 0,
                    borderRadius: 0
                  }}
                >
                  <Panel.Body>
                    <ButtonToolbar>
                      {!uiApplication && (
                        <Button
                          onClick={() => OpenUrl(activeApplication.origin)}
                        >

                          {activeApplication.origin}
                        </Button>
                      )}
                      {uiApplication && (
                        <Button
                          onClick={() => OpenUrl(`http://${uiState.uiHost}`)}
                        >

                          View all applications
                        </Button>
                      )}
                      <Button
                        disabled={activeApplication.locked}
                        onClick={() =>
                          doAction(
                            activeApplication.running
                              ? "StopApplication"
                              : "StartApplication",
                            {
                              applicationName: activeApplication.name
                            }
                          )
                        }
                      >

                      </Button>
                      {!uiApplication && (
                        <Button
                          disabled={
                            activeApplication.locked ||
                            !activeApplication.running
                          }
                          onClick={() =>
                            doAction("RestartApplication", {
                              applicationName: activeApplication.name
                            })
                          }
                        >

                        </Button>
                      )}
                      <ButtonGroup>
                        <Button
                          active={this.state.tab === "terminal"}
                          onClick={() =>
                            this.setState({
                              tab: "terminal"
                            })
                          }
                        >

                          Terminal
                        </Button>
                        <Button
                          active={this.state.tab === "details"}
                          onClick={() =>
                            this.setState({
                              tab: "details"
                            })
                          }
                        >

                          Details
                        </Button>
                      </ButtonGroup>
                    </ButtonToolbar>
                  </Panel.Body>
                </Panel>
                {this.state.tab === "details" && (

                    <Panel>
                      <Panel.Heading>Details</Panel.Heading>
                      <Panel.Body>
                        <ApplicationForm
                          application={activeApplication}
                          onSubmit={applicationData => {
                            doAction("CreateApplication", {
                              applicationData
                            });
                          }}
                        >
                          <Button
                            bsStyle="danger"
                            onClick={() =>
                              doAction("DeleteApplication", {
                                applicationName: activeApplication.name
                              })
                            }
                          >
                            Delete
                          </Button>
                        </ApplicationForm>
                      </Panel.Body>
                    </Panel>

                )}
                {this.state.tab === "terminal" && (

                    <ApplicationTerminal
                      applicationName={activeApplication.name}
                    />

                )}
              </React.Fragment>
            )}
            {!this.state.creatingApplication && !activeApplication && (

                <Panel>
                  <Panel.Heading>Tips:</Panel.Heading>
                  <Panel.Body>

{uiState.usageMessage}

                      You can also download the self-signed CA for signing SSL
                      connections.
                       {
                          event.preventDefault();
                          OpenBlob(
                            "localhostd.ca.crt",
                            new Blob([uiState.caCertificate])
                          );
                        }}
                      >

                        SSL CA certificate

                  </Panel.Body>
                </Panel>

            )}

        </>
      );
    }
  }
);
<commit_msg>change default application timeout to 3600<commit_after>import React from "react";
import { compose, withProps } from "recompose";
import _ from "lodash";
import {
  Nav,
  NavItem,
  Panel,
  Button,
  ButtonGroup,
  ButtonToolbar
} from "react-bootstrap";

import ApplicationForm from "./application_form.js";
import ApplicationTerminal from "./application_terminal.js";
import OpenUrl from "./open_url.js";
import OpenBlob from "./open_blob.js";
import withUIState from "./with_ui_state.js";

export default compose(
  withProps({ handleMessages: true }),
  withUIState
)(
  class LocalhostDConsole extends React.Component {
    state = {
      activeApplicationIndex: -1,
      creatingApplication: false,
      tab: "terminal"
    };

    render() {
      const { uiState, doAction } = this.props;

      const uiApplication = uiState.applications.find(
        a =>
          a.domain === window.location.hostname ||
          window.location.hostname.endsWith(`.${a.domain}`)
      );

      if (uiApplication && !uiApplication.locked && uiApplication.running)
        window.location.reload();

      const activeApplication =
        uiApplication ||
        uiState.applications[this.state.activeApplicationIndex];

      return (
        <>
          {!uiApplication && (

                {_.sortBy(
                  uiState.applications.map((a, index) => ({
                    ...a,
                    index
                  })),
                  a => a.name
                ).map(application => (
                  <NavItem
                    key={application.name}
                    active={
                      this.state.activeApplicationIndex === application.index
                    }
                    onClick={() =>
                      this.setState({
                        activeApplicationIndex: application.index,
                        creatingApplication: false
                      })
                    }
                  >

                    {application.name}
                  </NavItem>
                ))}
                <NavItem
                  active={this.state.creatingApplication}
                  onClick={() =>
                    this.setState({
                      creatingApplication: true,
                      activeApplicationIndex: -1
                    })
                  }
                >

                  New application
                </NavItem>
                <NavItem
                  active={!this.state.creatingApplication && !activeApplication}
                  onClick={() =>
                    this.setState({
                      creatingApplication: false,
                      activeApplicationIndex: -1
                    })
                  }
                >

                  Tips
                </NavItem>

          )}

            {this.state.creatingApplication && (

                <Panel>
                  <Panel.Heading>New application</Panel.Heading>
                  <Panel.Body>
                    <ApplicationForm
                      application={{
                        dir: uiState.homedir,
                        env: {},
                        timeout: 3600
                      }}
                      creating
                      onSubmit={applicationData => {
                        doAction("CreateApplication", {
                          applicationData
                        });

                        this.setState({
                          creatingApplication: false
                        });
                      }}
                    >
                      <Button
                        onClick={ev =>
                          this.setState({
                            creatingApplication: false
                          })
                        }
                      >
                        Cancel
                      </Button>
                    </ApplicationForm>
                  </Panel.Body>
                </Panel>

            )}
            {!this.state.creatingApplication && !!activeApplication && (
              <React.Fragment key={activeApplication.name}>
                <Panel
                  style={{
                    flex: "0 0 auto",
                    margin: 0,
                    borderRadius: 0
                  }}
                >
                  <Panel.Body>
                    <ButtonToolbar>
                      {!uiApplication && (
                        <Button
                          onClick={() => OpenUrl(activeApplication.origin)}
                        >

                          {activeApplication.origin}
                        </Button>
                      )}
                      {uiApplication && (
                        <Button
                          onClick={() => OpenUrl(`http://${uiState.uiHost}`)}
                        >

                          View all applications
                        </Button>
                      )}
                      <Button
                        disabled={activeApplication.locked}
                        onClick={() =>
                          doAction(
                            activeApplication.running
                              ? "StopApplication"
                              : "StartApplication",
                            {
                              applicationName: activeApplication.name
                            }
                          )
                        }
                      >

                      </Button>
                      {!uiApplication && (
                        <Button
                          disabled={
                            activeApplication.locked ||
                            !activeApplication.running
                          }
                          onClick={() =>
                            doAction("RestartApplication", {
                              applicationName: activeApplication.name
                            })
                          }
                        >

                        </Button>
                      )}
                      <ButtonGroup>
                        <Button
                          active={this.state.tab === "terminal"}
                          onClick={() =>
                            this.setState({
                              tab: "terminal"
                            })
                          }
                        >

                          Terminal
                        </Button>
                        <Button
                          active={this.state.tab === "details"}
                          onClick={() =>
                            this.setState({
                              tab: "details"
                            })
                          }
                        >

                          Details
                        </Button>
                      </ButtonGroup>
                    </ButtonToolbar>
                  </Panel.Body>
                </Panel>
                {this.state.tab === "details" && (

                    <Panel>
                      <Panel.Heading>Details</Panel.Heading>
                      <Panel.Body>
                        <ApplicationForm
                          application={activeApplication}
                          onSubmit={applicationData => {
                            doAction("CreateApplication", {
                              applicationData
                            });
                          }}
                        >
                          <Button
                            bsStyle="danger"
                            onClick={() =>
                              doAction("DeleteApplication", {
                                applicationName: activeApplication.name
                              })
                            }
                          >
                            Delete
                          </Button>
                        </ApplicationForm>
                      </Panel.Body>
                    </Panel>

                )}
                {this.state.tab === "terminal" && (

                    <ApplicationTerminal
                      applicationName={activeApplication.name}
                    />

                )}
              </React.Fragment>
            )}
            {!this.state.creatingApplication && !activeApplication && (

                <Panel>
                  <Panel.Heading>Tips:</Panel.Heading>
                  <Panel.Body>

{uiState.usageMessage}

                      You can also download the self-signed CA for signing SSL
                      connections.
                       {
                          event.preventDefault();
                          OpenBlob(
                            "localhostd.ca.crt",
                            new Blob([uiState.caCertificate])
                          );
                        }}
                      >

                        SSL CA certificate

                  </Panel.Body>
                </Panel>

            )}

        </>
      );
    }
  }
);
<|endoftext|>


<commit_before>import { Feature } from 'core/feature';

export class ImportNotification extends Feature {
  injectCSS() { return require('./index.css'); }

  constructor() {
    super();
    this.isActive = false;
    this.importClass = 'import-notification';
    this.invoke = this.invoke.bind(this);
  }

  willInvoke() {
    if (this.settings.enabled !== '0') {
      if (this.settings.enabled === '2') {
        this.importClass += '-red';
      }

      // Hook transaction imports so that we can run our stuff when things change
      ynab.YNABSharedLib.defaultInstance.entityManager._transactionEntityPropertyChanged.addHandler(this.invoke);
    }
  }

  shouldInvoke() {
    return this.settings.enabled !== '0';
  }

  invoke() {
    if (!this.isActive) {
      this.checkImportTransactions();
    }
  }

  observe(changedNodes) {
    if (!this.shouldInvoke()) return;

    // Don't call invoke() if the changed node is a result of us adding or removing
    // the notification class in checkImportTransactions().
    if (!changedNodes.has('nav-account-notification') && !this.isActive) {
      this.invoke();
    }
  }

  checkImportTransactions() {
    this.isActive = true;

    $('.' + this.importClass).remove();
    $('.nav-account-row').each((index, row) => {
      let account = ynabToolKit.shared.getEmberView($(row).attr('id')).get('data');

      // Check for both functions should be temporary until all users have been switched to new bank data
      // provider but of course we have no good way of knowing when that has occurred.
      if (typeof account.getDirectConnectEnabled === 'function' && account.getDirectConnectEnabled() ||
          typeof account.getIsDirectImportActive === 'function' && account.getIsDirectImportActive()) {
        let t = new ynab.managers.DirectImportManager(ynab.YNABSharedLib.defaultInstance.entityManager, account);
        let transactions = t.getImportTransactionsForAccount(account);
        if (transactions.length >= 1) {
          $(row)
            .find('.nav-account-notification')
            .append('' + transactions.length + '');
        }
      }
    });

    this.isActive = false;
  }
}
<commit_msg>Reduce the number of times that we checked for imported transactions<commit_after>import { Feature } from 'core/feature';

export class ImportNotification extends Feature {
  injectCSS() { return require('./index.css'); }

  constructor() {
    super();
    this.isActive = false;
    this.importClass = 'import-notification';
    this.invoke = this.invoke.bind(this);
  }

  willInvoke() {
    if (this.settings.enabled !== '0') {
      if (this.settings.enabled === '2') {
        this.importClass += '-red';
      }

      // Hook transaction imports so that we can run our stuff when things change. The idea is for our code to
      // run when new imports show up while the user isn't doin ganythiing in the app. The down side is the
      // handler being called when the user does something like "approve a transaction". That's why this feature
      // has a blocking mechanism (the isActive flag).
      ynab.YNABSharedLib.defaultInstance.entityManager._transactionEntityPropertyChanged.addHandler(this.invoke);
    }
  }

  shouldInvoke() {
    return this.settings.enabled !== '0';
  }

  invoke() {
    if (!this.isActive) {
      this.checkImportTransactions();
    }
  }

  observe(changedNodes) {
    if (!this.shouldInvoke()) return;
    // To minimize checking for imported transactions, only do it if the changed nodes includes ynab-grid-body
    // if we're not already actively check.
    if (changedNodes.has('ynab-grid-body') && !this.isActive) {
      this.invoke();
    }
  }

  checkImportTransactions() {
    this.isActive = true;

    $('.' + this.importClass).remove();
    $('.nav-account-row').each((index, row) => {
      let account = ynabToolKit.shared.getEmberView($(row).attr('id')).get('data');

      // Check for both functions should be temporary until all users have been switched to new bank data
      // provider but of course we have no good way of knowing when that has occurred.
      if (typeof account.getDirectConnectEnabled === 'function' && account.getDirectConnectEnabled() ||
          typeof account.getIsDirectImportActive === 'function' && account.getIsDirectImportActive()) {
        let t = new ynab.managers.DirectImportManager(ynab.YNABSharedLib.defaultInstance.entityManager, account);
        let transactions = t.getImportTransactionsForAccount(account);

        if (transactions.length >= 1) {
          $(row)
            .find('.nav-account-notification')
            .append('' + transactions.length + '');
        }
      }
    });
    this.isActive = false;
  }
}
<|endoftext|>


<commit_before>

var ballContactsPaddle = function(ball, paddle){
  if( ball.bottomEdge().y == paddle.topSide()){
    if (ball.x >= paddle.surfaceRange()[0] && ball.x <= paddle.surfaceRange()[1]){
      return true;
    }
  }
  return false
}

var paddleBounce = function(ball, paddle){
    if ( ball.x.isBetween(paddle.leftEdge()[0],paddle.leftEdge()[1])){
      sharpBounce('left', ball);
    } else if ( ball.x.isBetween(paddle.rightEdge()[1],paddle.rightEdge()[0])){
      sharpBounce('right', ball);
  } else {
    ball.reverseYVelocity()
  }
};

var sharpBounce = function (side, ball) {
  if (side == 'left'){
    console.log('sharp left')
    if ( ball.velocityX > 0 ){
      ball.velocityX += 3
      ball.velocityX = -ball.velocityX
      ball.reverseYVelocity()
    } else {
      ball.velocityX += -3
      ball.reverseYVelocity()
    }
  } else if (side == 'right'){
    console.log('sharp right')
    if ( ball.velocityX > 0 ){
      ball.velocityX += 3
      ball.reverseYVelocity()
    } else {
      ball.velocityX += -3
      ball.velocityX = -ball.velocityX
      ball.reverseYVelocity()
    }
  }
}

var ballContactsBrick = function(ball, bricks){
  // debugger;
  for (var layer in bricks){
    bricks[layer].map(function(brick){
      if ( ball.topEdge().y == brick.verticalRange()[1]){
        if ( ball.topEdge().x >= brick.horizontalRange()[0] && ball.topEdge().x <= brick.horizontalRange()[1]){
          return true;
        };
      };
    })
  };
}
<commit_msg>Create brick ball bounce function<commit_after>

var ballContactsPaddle = function(ball, paddle){
  if( ball.bottomEdge().y == paddle.topSide()){
    if (ball.x >= paddle.surfaceRange()[0] && ball.x <= paddle.surfaceRange()[1]){
      return true;
    }
  }
  return false
}

var paddleBounce = function(ball, paddle){
    if ( ball.x.isBetween(paddle.leftEdge()[0],paddle.leftEdge()[1])){
      sharpBounce('left', ball);
    } else if ( ball.x.isBetween(paddle.rightEdge()[1],paddle.rightEdge()[0])){
      sharpBounce('right', ball);
  } else {
    ball.reverseYVelocity()
  }
};

var sharpBounce = function (side, ball) {
  if (side == 'left'){
    console.log('sharp left')
    if ( ball.velocityX > 0 ){
      ball.velocityX += 3
      ball.velocityX = -ball.velocityX
      ball.reverseYVelocity()
    } else {
      ball.velocityX += -3
      ball.reverseYVelocity()
    }
  } else if (side == 'right'){
    console.log('sharp right')
    if ( ball.velocityX > 0 ){
      ball.velocityX += 3
      ball.reverseYVelocity()
    } else {
      ball.velocityX += -3
      ball.velocityX = -ball.velocityX
      ball.reverseYVelocity()
    }
  }
}

var ballContactsBrick = function(ball, bricks){
  // debugger;
  for (var layer in bricks){
    bricks[layer].map(function(brick){
      if ( ball.topEdge().y == brick.verticalRange()[1]){
        if ( ball.topEdge().x >= brick.horizontalRange()[0] && ball.topEdge().x <= brick.horizontalRange()[1]){
          return true;
        };
      };
    })
  };
}

var brickBounce = function(ball, brick){

}
<|endoftext|>