<commit_before>var bufferUtils = require("../buffer_utils");

// Some common functionality shared amongst record types.
module.exports = {
	calculateNameValuePairsLength: function(pairs) {
		var size = 0;

		pairs.forEach(function(pair) {
			if(!Array.isArray(pair)) {
				pair = [pair, ""];
			}

			size += pair[0].length;
			size += pair[1].length;
			size += (pair[0].length > 127) ? 4 : 1;
			size += (pair[1].length > 127) ? 4 : 1;
		});

		return size;
	},

	writeNameValuePairs: function(buffer, pairs) {
		var index = 0;
		pairs.forEach(function(pair) {
			if(!Array.isArray(pair)) {
				pair = [pair, ""];
			}

			if(pair[0].length > 127) {
				bufferUtils.setInt32(buffer, index, pair[0].length + 2147483648);
				index += 4;
			}
			else {
				buffer[index++] = pair[0].length;
			}

			if(pair[1].length > 127) {
				bufferUtils.setInt32(buffer, index, pair[1].length + 2147483648);
				index += 4;
			}
			else {
				buffer[index++] = pair[1].length;
			}

			buffer.write(pair[0], index);
			index += pair[0].length;
			buffer.write(pair[1], index);
			index += pair[1].length;
		});
	},

	readNameValuePairs: function(buffer) {
		var offset = 0, len = buffer.length, pairs = [], pair, keyLength, valueLength, key, value;

		while(offset < len) {
			keyLength = buffer[offset++];
			if(keyLength & 0x80) {
				keyLength = ((keyLength - 128) << 24) | (buffer[offset++] << 16) | (buffer[offset++] << 8) | buffer[offset++];
			}

			valueLength = buffer[offset++];
			if(valueLength & 0x80) {
				valueLength = ((valueLength - 128) << 24) | (buffer[offset++] << 16) | (buffer[offset++] << 8) | buffer[offset++];
			}

			key = buffer.toString("utf8", offset, offset + keyLength);
			offset += keyLength;
			if(valueLength) {
				value = buffer.toString("utf8", offset, offset + valueLength);
				offset += valueLength;
			}

			if(valueLength) {
				pairs.push([key, value]);
			}
			else
				pairs.push(key);
		}

		return pairs;
	}
};<commit_msg>Params length calculation fixed<commit_after>var bufferUtils = require("../buffer_utils");

// Some common functionality shared amongst record types.
module.exports = {
	calculateNameValuePairsLength: function(pairs) {
		var size = 0;

		pairs.forEach(function(pair) {
			if(!Array.isArray(pair)) {
				pair = [pair, ""];
			}

			size += Buffer.byteLength(pair[0]);
			size += Buffer.byteLength(pair[1]);
			size += (pair[0].length > 127) ? 4 : 1;
			size += (pair[1].length > 127) ? 4 : 1;
		});

		return size;
	},

	writeNameValuePairs: function(buffer, pairs) {
		var index = 0;
		pairs.forEach(function(pair) {
			if(!Array.isArray(pair)) {
				pair = [pair, ""];
			}

			if(pair[0].length > 127) {
				bufferUtils.setInt32(buffer, index, pair[0].length + 2147483648);
				index += 4;
			}
			else {
				buffer[index++] = pair[0].length;
			}

			if(pair[1].length > 127) {
				bufferUtils.setInt32(buffer, index, pair[1].length + 2147483648);
				index += 4;
			}
			else {
				buffer[index++] = pair[1].length;
			}

			buffer.write(pair[0], index);
			index += pair[0].length;
			buffer.write(pair[1], index);
			index += pair[1].length;
		});
	},

	readNameValuePairs: function(buffer) {
		var offset = 0, len = buffer.length, pairs = [], pair, keyLength, valueLength, key, value;

		while(offset < len) {
			keyLength = buffer[offset++];
			if(keyLength & 0x80) {
				keyLength = ((keyLength - 128) << 24) | (buffer[offset++] << 16) | (buffer[offset++] << 8) | buffer[offset++];
			}

			valueLength = buffer[offset++];
			if(valueLength & 0x80) {
				valueLength = ((valueLength - 128) << 24) | (buffer[offset++] << 16) | (buffer[offset++] << 8) | buffer[offset++];
			}

			key = buffer.toString("utf8", offset, offset + keyLength);
			offset += keyLength;
			if(valueLength) {
				value = buffer.toString("utf8", offset, offset + valueLength);
				offset += valueLength;
			}

			if(valueLength) {
				pairs.push([key, value]);
			}
			else
				pairs.push(key);
		}

		return pairs;
	}
};
<|endoftext|>


<commit_before>//
// Copyright (C) 2006 rPath, Inc
// All Rights Reserved
//

var labelsCache = {};
var versionCache = {};

var staticPath = '';

var green = {'style': 'color: green; font-weight: bold;'};
var gray = {'style': 'color: gray;'};

var spinnerImg = 'apps/mint/images/circle-ball-dark-antialiased.gif';
var nextImg = 'apps/mint/images/next.gif';
var prevImg = 'apps/mint/images/prev.gif';
var prevImgDisabled = 'apps/mint/images/prev_disabled.gif';

//
// some DOM helper functions
//
function forwardLink(attrs, text) {
    return LI(null, A(attrs, IMG({'src': staticPath + nextImg}), " " + text));
}

function returnImg() {
    return IMG({'src': staticPath + prevImg});
}

function disabledReturn() {
    return DIV(gray, IMG({'src': staticPath + prevImgDisabled}), " Back");
}

function buildTroveSpec(n, v, f) {
    return n + "=" + v + "[" + f + "]";
}

function trailingRevision(v) {
    var parts = v.split(":");
    var revision = parts[parts.length-1];
    return revision;
}

// ctor
function TrovePicker(projectId, serverName, troveName, pickerId, mintStaticPath, allowNone) {
    this.projectId = projectId;
    this.serverName = serverName;
    this.troveName = troveName;
    this.elId = pickerId;
    staticPath = mintStaticPath;
    this.allowNone = allowNone;

    if(troveName) {
        this.allowNameChoice = false;
    }

    this.buildTrovePicker();
}

TrovePicker.prototype.troveName = null;
TrovePicker.prototype.serverName = null;
TrovePicker.prototype.label = null;
TrovePicker.prototype.version = null;
TrovePicker.prototype.flavorCache = null;
TrovePicker.prototype.domCache = {};
TrovePicker.prototype.allowNameChoice = true;
TrovePicker.prototype.aloowNone = false;

TrovePicker.prototype.working = function(isWorking) {
    if(isWorking) {
        showElement(this.elId + 'spinnerList');
        hideElement(this.elId + 'selectionList');
    }
    else {
        hideElement(this.elId + 'spinnerList');
        showElement(this.elId + 'selectionList');
    }
}

// Build the initial DOM for the trove picker and
// begin retrieving all leaves for a given
// trove name on a server.
TrovePicker.prototype.buildTrovePicker = function() {
    oldEl = $(this.elId);
    picker = DIV({'id': this.elId, 'class': 'trovePicker'});
    spinner = UL({'id': this.elId + 'spinnerList'},
        LI(null, "Loading...", IMG({'src': staticPath + spinnerImg}))
    );
    appendChildNodes(picker, SPAN({'id': this.elId + 'prompt', 'class': 'prompt'}),
        P({'id': this.elId + 'return'}),
        spinner,
        UL({'id': this.elId + 'selectionList'}),
        INPUT({'id': this.elId.replace("-", "_") + 'Spec', 'name': this.elId + 'Spec', 'type': 'hidden'})
    );
    swapDOM(oldEl, picker);

    if(this.troveName) {
        this.getAllTroveLabels();
    } else {
        this.getGroupTroves();
    }
}

// A flavor has been chosen--continue on
TrovePicker.prototype.pickFlavor = function(e) {
    var n = e.src().name;
    var v = e.src().version;
    var shortv = trailingRevision(v);
    var f = e.src().flavor;
    var shortf = e.src().shortFlavor;

    var troveSpec = buildTroveSpec(n, v, f);
    setNodeAttribute($(this.elId.replace("-", "_") + 'Spec'), 'value', troveSpec);

    oldEl = $(this.elId + 'selectionList');
    newEl = DIV({'id': this.elId + 'selectionList'},
        SPAN({'style': 'font-weight: bold;'}, 'Group: '),
        SPAN(null, n + "=" + shortv + " [" + shortf + "]")
    );
    swapDOM(oldEl, newEl);

    // return to getTroveVersions
    returnLink = A(null, returnImg(), " Back");
    returnLink.troveName = n;
    returnLink.version = e.src().version;
    returnLink.label = e.src().label;
    connect(returnLink, "onclick", this, "showTroveFlavors");
    replaceChildNodes($(this.elId + 'return'), returnLink);
    replaceChildNodes($(this.elId + 'prompt'), "Selected group:");

    if(this.elId == "distTrove") {
        var sb = $('submitButton');
        sb.disabled = false;
        handleBuildTypes(f);
    }
}

TrovePicker.prototype.pickNoTrove = function(e) {
    setNodeAttribute($(this.elId.replace("-", "_") + 'Spec'), 'value', 'NONE');
    var n = e.src().troveName;

    oldEl = $(this.elId + 'selectionList');
    newEl = DIV({'id': this.elId + 'selectionList'},
        SPAN({'style': 'font-weight: bold;'}, 'Group: '),
        SPAN(null, "No " + n + " will be used for this build.")
    );
    swapDOM(oldEl, newEl);

    // return to getTroveVersions
    returnLink = A(null, returnImg(), " Back");
    returnLink.troveName = n;
    connect(returnLink, "onclick", this, "getAllTroveLabels");
    replaceChildNodes($(this.elId + 'return'), returnLink);
}

// Show all flavors available for a given trove and version
TrovePicker.prototype.showTroveFlavors = function(e) {
    this.version = e.src().version;
    this.label = e.src().label;

    oldList = $(this.elId + 'selectionList');
    ul = UL({ 'id': this.elId + 'selectionList' });

    for(var i in this.flavorCache[this.version]) {
        flavor = this.flavorCache[this.version][i];
        var myId = "flavorId" + i;
        link = forwardLink({'id': myId}, flavor[0]);
        link.name = this.troveName;
        link.version = this.version;
        link.flavor = flavor[1];
        link.shortFlavor = flavor[0];
        link.label = this.label;
        connect(link, "onclick", this, "pickFlavor");
        appendChildNodes(ul, link);
    }
    // return to getTroveVersions
    returnLink = A(null, returnImg(), " Back");
    returnLink.label = this.label;
    connect(returnLink, "onclick", this, "getTroveVersions");
    replaceChildNodes($(this.elId + 'return'), returnLink);

    swapDOM(oldList, ul);
    this.working(false);
    replaceChildNodes($(this.elId + 'prompt'), "Please choose a flavor:");
}

// Show all versions of a trove on a given label
TrovePicker.prototype.getTroveVersions = function(e) {
    this.label = e.src().label;
    var par = this;
    var key = this.label + "=" + this.troveName;

    var setupList = function(req) {
        var versionDict = req[0];
        var versionList = req[1];
        oldList = $(par.elId + 'selectionList');

        par.flavorCache = versionDict;

        if(!par.domCache[key]) {
            ul = UL({ 'id': par.elId + 'selectionList' });
            for(var i in versionList) {
                link = forwardLink(null, trailingRevision(versionList[i]));
                link.version = versionList[i];
                link.label = par.label;
                connect(link, "onclick", par, "showTroveFlavors");
                appendChildNodes(ul, link);
            }
            par.domCache[key] = ul;
        }
        swapDOM(oldList, par.domCache[key]);

        par.working(false);
        replaceChildNodes($(par.elId + 'prompt'), "Please choose a version:");

        // return to getAllTroveLabels
        returnLink = A(null, returnImg(), " Back");
        returnLink.troveName = par.troveName;
        connect(returnLink, "onclick", par, "getAllTroveLabels");
        replaceChildNodes($(par.elId + 'return'), returnLink);
    };

    var callback = function(aReq) {
        logDebug("[JSON] response: ", aReq.responseText);

        req = evalJSONRequest(aReq);
        versionCache[key] = req;
        setupList(req);
    };

    if(!versionCache[key]) {
        this.working(true);
        var req = new JsonRpcRequest("jsonrpc/", "getTroveVersions");
        req.setAuth(getCookieValue("pysid"));
        req.setCallback(callback);
        req.send(true, [this.projectId, this.label, this.troveName]);
    } else {
        setupList(versionCache[key]);
    }
}

// Fetch all labels a trove exists on a given server
TrovePicker.prototype.getAllTroveLabels = function(e) {
    if(e) {
        this.troveName = e.src().troveName;
    }
    var key = this.serverName + "=" + this.troveName;
    var par = this; // save the parent for the subfunction's use

    var setupList = function(labelList) {
        oldList = $(par.elId + 'selectionList');
        ul = UL({ 'id': par.elId + 'selectionList' });

        if(labelList.length < 1) {
            appendChildNodes(ul, LI(null, "No " + par.troveName + " packages found"));
        }
        for(var i in labelList) {
            link = forwardLink(null, labelList[i]);
            link.label = labelList[i];
            connect(link, "onclick", par, "getTroveVersions");
            appendChildNodes(ul, link);
        }
        if(labelList.length > 0 && par.allowNone) {
            link = forwardLink(null, "Do not use " + par.troveName + " for this build.");
            link.troveName = par.troveName;
            connect(link, "onclick", par, "pickNoTrove");
            appendChildNodes(ul, link);
        }
        swapDOM(oldList, ul);
        par.working(false);
        replaceChildNodes($(par.elId + 'prompt'), "Please choose a label:");

        if(par.allowNameChoice) {
            // return to getGroupTroves
            returnLink = A(null, returnImg(), " Back");
            connect(returnLink, "onclick", par, "getGroupTroves");
            replaceChildNodes($(par.elId + 'return'), returnLink);
        } else {
            replaceChildNodes($(par.elId + 'return'), disabledReturn());
        }
    };

    var callback = function(aReq) {
        logDebug("[JSON] response: ", aReq.responseText);

        labelList = evalJSONRequest(aReq);
        labelsCache[key] = labelList;
        setupList(labelList);
    };

    if(!labelsCache[key]) {
        this.working(true);
        var req = new JsonRpcRequest("jsonrpc/", "getAllTroveLabels");
        req.setAuth(getCookieValue("pysid"));
        req.setCallback(callback);
        req.send(true, [this.projectId, this.serverName, this.troveName]);
    } else {
        setupList(labelsCache[key]);
    }
}

TrovePicker.prototype.getGroupTroves = function() {
    var par = this;

    var setupList = function(troveList) {
        oldList = $(par.elId + 'selectionList');
        ul = UL({'id': par.elId + 'selectionList'});

        if(troveList.length < 1) {
            appendChildNodes(ul, LI(null, "No groups found. Cook a group with the Group Builder and try again."));
        }
        for(var i in troveList) {
            link = forwardLink(null, troveList[i]);
            link.troveName = troveList[i];
            connect(link, "onclick", par, "getAllTroveLabels");
            appendChildNodes(ul, link);
        }
        swapDOM(oldList, ul);
        par.working(false);
        replaceChildNodes($(par.elId + 'prompt'), "Please choose a group:");
        replaceChildNodes($(par.elId + 'return'), disabledReturn());
    };

    var callback = function(aReq) {
        logDebug(aReq.responseText);
        troveList = evalJSONRequest(aReq);
        par.troveList = troveList;
        setupList(troveList);
    };

    this.working(true);
    var req = new JsonRpcRequest("jsonrpc/", "getGroupTroves");
    req.setAuth(getCookieValue("pysid"));
    req.setCallback(callback);
    req.send(true, [this.projectId]);
}

TrovePicker.prototype.handleError = function() {
    this.working(false);
    oldList = $(this.elId + 'spinnerList');
    ul = UL({'id': this.elId + 'spinnerList'}, LI({'style': 'color: red;'}, "Error connecting to server"));
    swapDOM(oldList, ul);
}

var allTypes = map(parseInt, keys(buildTypeNames));

var defaultType = INSTALLABLE_ISO;
if(x86_64)
    var x86_64Types = allTypes;
else
    var x86_64Types = [INSTALLABLE_ISO];

var xenTypes = [RAW_FS_IMAGE, RAW_HD_IMAGE, TARBALL];

function handleBuildTypes(flavor) {
    forEach(allTypes, function(x) {
        var el = $('buildtype_' + x);
        var elLabel = $('buildtype_' + x + '_label');
        if(el) {
            el.disabled = false;
            setOpacity(elLabel, 1.0);
        }
        if(x == defaultType) {
            el.checked = true;
            onBuildTypeChange("formgroup_" + x);
        }
    });

    if(flavor) {
        // bootableTypes are not currently compatible with x86_64
        // so, if that arch was selected, disable it:
        selectiveDisable(flavor, "x86_64", x86_64Types);

        // only allow a few build types to be built from a xen flavor:
        selectiveDisable(flavor, ",domU", xenTypes);
    }
}

function selectiveDisable(flavor, flavorMatch, allowed) {
    if(flavor.match(flavorMatch)) {
        one = iter(allTypes);
        forEach(one, function (x) {
            var el = $('buildtype_'+x);
            var elLabel = $('buildtype_' + x + '_label');
            if(el) {
                if (findValue(allowed, x) == -1) {
                    el.disabled = true;
                    setOpacity(elLabel, 0.5);
                }
                else {
                    el.disabled = false;
                    setOpacity(elLabel, 1.0);
                    if(x == allowed[0]) {
                        el.checked = true;
                        onBuildTypeChange("formgroup_" + x);
                    }
                }
            }
        });
    }
}
<commit_msg>add Xen OVA to allowed Xen build types<commit_after>//
// Copyright (C) 2006 rPath, Inc
// All Rights Reserved
//

var labelsCache = {};
var versionCache = {};

var staticPath = '';

var green = {'style': 'color: green; font-weight: bold;'};
var gray = {'style': 'color: gray;'};

var spinnerImg = 'apps/mint/images/circle-ball-dark-antialiased.gif';
var nextImg = 'apps/mint/images/next.gif';
var prevImg = 'apps/mint/images/prev.gif';
var prevImgDisabled = 'apps/mint/images/prev_disabled.gif';

//
// some DOM helper functions
//
function forwardLink(attrs, text) {
    return LI(null, A(attrs, IMG({'src': staticPath + nextImg}), " " + text));
}

function returnImg() {
    return IMG({'src': staticPath + prevImg});
}

function disabledReturn() {
    return DIV(gray, IMG({'src': staticPath + prevImgDisabled}), " Back");
}

function buildTroveSpec(n, v, f) {
    return n + "=" + v + "[" + f + "]";
}

function trailingRevision(v) {
    var parts = v.split(":");
    var revision = parts[parts.length-1];
    return revision;
}

// ctor
function TrovePicker(projectId, serverName, troveName, pickerId, mintStaticPath, allowNone) {
    this.projectId = projectId;
    this.serverName = serverName;
    this.troveName = troveName;
    this.elId = pickerId;
    staticPath = mintStaticPath;
    this.allowNone = allowNone;

    if(troveName) {
        this.allowNameChoice = false;
    }

    this.buildTrovePicker();
}

TrovePicker.prototype.troveName = null;
TrovePicker.prototype.serverName = null;
TrovePicker.prototype.label = null;
TrovePicker.prototype.version = null;
TrovePicker.prototype.flavorCache = null;
TrovePicker.prototype.domCache = {};
TrovePicker.prototype.allowNameChoice = true;
TrovePicker.prototype.aloowNone = false;

TrovePicker.prototype.working = function(isWorking) {
    if(isWorking) {
        showElement(this.elId + 'spinnerList');
        hideElement(this.elId + 'selectionList');
    }
    else {
        hideElement(this.elId + 'spinnerList');
        showElement(this.elId + 'selectionList');
    }
}

// Build the initial DOM for the trove picker and
// begin retrieving all leaves for a given
// trove name on a server.
TrovePicker.prototype.buildTrovePicker = function() {
    oldEl = $(this.elId);
    picker = DIV({'id': this.elId, 'class': 'trovePicker'});
    spinner = UL({'id': this.elId + 'spinnerList'},
        LI(null, "Loading...", IMG({'src': staticPath + spinnerImg}))
    );
    appendChildNodes(picker, SPAN({'id': this.elId + 'prompt', 'class': 'prompt'}),
        P({'id': this.elId + 'return'}),
        spinner,
        UL({'id': this.elId + 'selectionList'}),
        INPUT({'id': this.elId.replace("-", "_") + 'Spec', 'name': this.elId + 'Spec', 'type': 'hidden'})
    );
    swapDOM(oldEl, picker);

    if(this.troveName) {
        this.getAllTroveLabels();
    } else {
        this.getGroupTroves();
    }
}

// A flavor has been chosen--continue on
TrovePicker.prototype.pickFlavor = function(e) {
    var n = e.src().name;
    var v = e.src().version;
    var shortv = trailingRevision(v);
    var f = e.src().flavor;
    var shortf = e.src().shortFlavor;

    var troveSpec = buildTroveSpec(n, v, f);
    setNodeAttribute($(this.elId.replace("-", "_") + 'Spec'), 'value', troveSpec);

    oldEl = $(this.elId + 'selectionList');
    newEl = DIV({'id': this.elId + 'selectionList'},
        SPAN({'style': 'font-weight: bold;'}, 'Group: '),
        SPAN(null, n + "=" + shortv + " [" + shortf + "]")
    );
    swapDOM(oldEl, newEl);

    // return to getTroveVersions
    returnLink = A(null, returnImg(), " Back");
    returnLink.troveName = n;
    returnLink.version = e.src().version;
    returnLink.label = e.src().label;
    connect(returnLink, "onclick", this, "showTroveFlavors");
    replaceChildNodes($(this.elId + 'return'), returnLink);
    replaceChildNodes($(this.elId + 'prompt'), "Selected group:");

    if(this.elId == "distTrove") {
        var sb = $('submitButton');
        sb.disabled = false;
        handleBuildTypes(f);
    }
}

TrovePicker.prototype.pickNoTrove = function(e) {
    setNodeAttribute($(this.elId.replace("-", "_") + 'Spec'), 'value', 'NONE');
    var n = e.src().troveName;

    oldEl = $(this.elId + 'selectionList');
    newEl = DIV({'id': this.elId + 'selectionList'},
        SPAN({'style': 'font-weight: bold;'}, 'Group: '),
        SPAN(null, "No " + n + " will be used for this build.")
    );
    swapDOM(oldEl, newEl);

    // return to getTroveVersions
    returnLink = A(null, returnImg(), " Back");
    returnLink.troveName = n;
    connect(returnLink, "onclick", this, "getAllTroveLabels");
    replaceChildNodes($(this.elId + 'return'), returnLink);
}

// Show all flavors available for a given trove and version
TrovePicker.prototype.showTroveFlavors = function(e) {
    this.version = e.src().version;
    this.label = e.src().label;

    oldList = $(this.elId + 'selectionList');
    ul = UL({ 'id': this.elId + 'selectionList' });

    for(var i in this.flavorCache[this.version]) {
        flavor = this.flavorCache[this.version][i];
        var myId = "flavorId" + i;
        link = forwardLink({'id': myId}, flavor[0]);
        link.name = this.troveName;
        link.version = this.version;
        link.flavor = flavor[1];
        link.shortFlavor = flavor[0];
        link.label = this.label;
        connect(link, "onclick", this, "pickFlavor");
        appendChildNodes(ul, link);
    }
    // return to getTroveVersions
    returnLink = A(null, returnImg(), " Back");
    returnLink.label = this.label;
    connect(returnLink, "onclick", this, "getTroveVersions");
    replaceChildNodes($(this.elId + 'return'), returnLink);

    swapDOM(oldList, ul);
    this.working(false);
    replaceChildNodes($(this.elId + 'prompt'), "Please choose a flavor:");
}

// Show all versions of a trove on a given label
TrovePicker.prototype.getTroveVersions = function(e) {
    this.label = e.src().label;
    var par = this;
    var key = this.label + "=" + this.troveName;

    var setupList = function(req) {
        var versionDict = req[0];
        var versionList = req[1];
        oldList = $(par.elId + 'selectionList');

        par.flavorCache = versionDict;

        if(!par.domCache[key]) {
            ul = UL({ 'id': par.elId + 'selectionList' });
            for(var i in versionList) {
                link = forwardLink(null, trailingRevision(versionList[i]));
                link.version = versionList[i];
                link.label = par.label;
                connect(link, "onclick", par, "showTroveFlavors");
                appendChildNodes(ul, link);
            }
            par.domCache[key] = ul;
        }
        swapDOM(oldList, par.domCache[key]);

        par.working(false);
        replaceChildNodes($(par.elId + 'prompt'), "Please choose a version:");

        // return to getAllTroveLabels
        returnLink = A(null, returnImg(), " Back");
        returnLink.troveName = par.troveName;
        connect(returnLink, "onclick", par, "getAllTroveLabels");
        replaceChildNodes($(par.elId + 'return'), returnLink);
    };

    var callback = function(aReq) {
        logDebug("[JSON] response: ", aReq.responseText);

        req = evalJSONRequest(aReq);
        versionCache[key] = req;
        setupList(req);
    };

    if(!versionCache[key]) {
        this.working(true);
        var req = new JsonRpcRequest("jsonrpc/", "getTroveVersions");
        req.setAuth(getCookieValue("pysid"));
        req.setCallback(callback);
        req.send(true, [this.projectId, this.label, this.troveName]);
    } else {
        setupList(versionCache[key]);
    }
}

// Fetch all labels a trove exists on a given server
TrovePicker.prototype.getAllTroveLabels = function(e) {
    if(e) {
        this.troveName = e.src().troveName;
    }
    var key = this.serverName + "=" + this.troveName;
    var par = this; // save the parent for the subfunction's use

    var setupList = function(labelList) {
        oldList = $(par.elId + 'selectionList');
        ul = UL({ 'id': par.elId + 'selectionList' });

        if(labelList.length < 1) {
            appendChildNodes(ul, LI(null, "No " + par.troveName + " packages found"));
        }
        for(var i in labelList) {
            link = forwardLink(null, labelList[i]);
            link.label = labelList[i];
            connect(link, "onclick", par, "getTroveVersions");
            appendChildNodes(ul, link);
        }
        if(labelList.length > 0 && par.allowNone) {
            link = forwardLink(null, "Do not use " + par.troveName + " for this build.");
            link.troveName = par.troveName;
            connect(link, "onclick", par, "pickNoTrove");
            appendChildNodes(ul, link);
        }
        swapDOM(oldList, ul);
        par.working(false);
        replaceChildNodes($(par.elId + 'prompt'), "Please choose a label:");

        if(par.allowNameChoice) {
            // return to getGroupTroves
            returnLink = A(null, returnImg(), " Back");
            connect(returnLink, "onclick", par, "getGroupTroves");
            replaceChildNodes($(par.elId + 'return'), returnLink);
        } else {
            replaceChildNodes($(par.elId + 'return'), disabledReturn());
        }
    };

    var callback = function(aReq) {
        logDebug("[JSON] response: ", aReq.responseText);

        labelList = evalJSONRequest(aReq);
        labelsCache[key] = labelList;
        setupList(labelList);
    };

    if(!labelsCache[key]) {
        this.working(true);
        var req = new JsonRpcRequest("jsonrpc/", "getAllTroveLabels");
        req.setAuth(getCookieValue("pysid"));
        req.setCallback(callback);
        req.send(true, [this.projectId, this.serverName, this.troveName]);
    } else {
        setupList(labelsCache[key]);
    }
}

TrovePicker.prototype.getGroupTroves = function() {
    var par = this;

    var setupList = function(troveList) {
        oldList = $(par.elId + 'selectionList');
        ul = UL({'id': par.elId + 'selectionList'});

        if(troveList.length < 1) {
            appendChildNodes(ul, LI(null, "No groups found. Cook a group with the Group Builder and try again."));
        }
        for(var i in troveList) {
            link = forwardLink(null, troveList[i]);
            link.troveName = troveList[i];
            connect(link, "onclick", par, "getAllTroveLabels");
            appendChildNodes(ul, link);
        }
        swapDOM(oldList, ul);
        par.working(false);
        replaceChildNodes($(par.elId + 'prompt'), "Please choose a group:");
        replaceChildNodes($(par.elId + 'return'), disabledReturn());
    };

    var callback = function(aReq) {
        logDebug(aReq.responseText);
        troveList = evalJSONRequest(aReq);
        par.troveList = troveList;
        setupList(troveList);
    };

    this.working(true);
    var req = new JsonRpcRequest("jsonrpc/", "getGroupTroves");
    req.setAuth(getCookieValue("pysid"));
    req.setCallback(callback);
    req.send(true, [this.projectId]);
}

TrovePicker.prototype.handleError = function() {
    this.working(false);
    oldList = $(this.elId + 'spinnerList');
    ul = UL({'id': this.elId + 'spinnerList'}, LI({'style': 'color: red;'}, "Error connecting to server"));
    swapDOM(oldList, ul);
}

var allTypes = map(parseInt, keys(buildTypeNames));

var defaultType = INSTALLABLE_ISO;
if(x86_64)
    var x86_64Types = allTypes;
else
    var x86_64Types = [INSTALLABLE_ISO];

var xenTypes = [RAW_FS_IMAGE, RAW_HD_IMAGE, TARBALL, XEN_OVA];

function handleBuildTypes(flavor) {
    forEach(allTypes, function(x) {
        var el = $('buildtype_' + x);
        var elLabel = $('buildtype_' + x + '_label');
        if(el) {
            el.disabled = false;
            setOpacity(elLabel, 1.0);
        }
        if(x == defaultType) {
            el.checked = true;
            onBuildTypeChange("formgroup_" + x);
        }
    });

    if(flavor) {
        // bootableTypes are not currently compatible with x86_64
        // so, if that arch was selected, disable it:
        selectiveDisable(flavor, "x86_64", x86_64Types);

        // only allow a few build types to be built from a xen flavor:
        selectiveDisable(flavor, ",domU", xenTypes);
    }
}

function selectiveDisable(flavor, flavorMatch, allowed) {
    if(flavor.match(flavorMatch)) {
        one = iter(allTypes);
        forEach(one, function (x) {
            var el = $('buildtype_'+x);
            var elLabel = $('buildtype_' + x + '_label');
            if(el) {
                if (findValue(allowed, x) == -1) {
                    el.disabled = true;
                    setOpacity(elLabel, 0.5);
                }
                else {
                    el.disabled = false;
                    setOpacity(elLabel, 1.0);
                    if(x == allowed[0]) {
                        el.checked = true;
                        onBuildTypeChange("formgroup_" + x);
                    }
                }
            }
        });
    }
}
<|endoftext|>


<commit_before>/**
 * @param {number[]} A
 * @return {number}
 */
var removeDuplicates = function(A) {

    if (A.length <= 1) return A;

    var pre;
    for (var i = 0; i < A.length;) {
        if (pre === A[i]) {
            A.splice(i, 1);
        } else {
            pre = A[i];
            i ++;
        }
    }
};

var t = [1,2,3,4,4,5,5,5,6];
removeDuplicates(t);
console.log(t)
<commit_msg>remove duplicates from sorted array: refactor<commit_after>/**
 * @param {number[]} A
 * @return {number}
 */
var removeDuplicates = function(A) {

    if (A.length <= 1) return A.length;

    var pre;
    for (var i = 0; i < A.length;) {
        if (pre === A[i]) {
            A.splice(i, 1);
        } else {
            pre = A[i];
            i ++;
        }
    }

    return A.length;
};

var eq = require('assert').equal;

var t = [1,2,3,4,4,5,5,5,6];
eq(removeDuplicates(t), 6);
eq(removeDuplicates([]), 0);
eq(removeDuplicates([1,1,1,1]), 1);
<|endoftext|>


<commit_before>/**
 * --------------------------------------------------------------------------
 * Licensed under MIT https://github.com/sitevision/envision/blob/master/LICENSE
 * --------------------------------------------------------------------------
 */

import jQuery from 'jquery';
import Util from './util';

const Collapse = (($) => {
   const ARIA_EXPANDED = 'aria-expanded';
   const MODIFIER_BASE = 'env-collapse--';
   const DURATION_CUSTOM_PROP = '--env-collapse-toggle-duration';
   const NAME = 'envCollapse';
   const NO_CONFLICT = $.fn[NAME];
   const EXPANDED = MODIFIER_BASE + 'expanded';
   const SHOW = MODIFIER_BASE + 'show';

   class Collapse {
      constructor(element) {
         this.el = element;
         this.$el = $(element);
         this.$trigger = $(
            `[data-env-collapse][href="#${element.id}"], [data-env-collapse][data-target="#${element.id}"]`
         );
         this.speed = Util.getToggleSpeed(
            this.$trigger[0],
            DURATION_CUSTOM_PROP
         );
      }

      toggle() {
         if (this.$el.hasClass(SHOW)) {
            this.hide();
         } else {
            this.show();
         }
      }

      show() {
         if (this.$trigger.length) {
            this.$trigger.addClass(EXPANDED).attr(ARIA_EXPANDED, true);
         }
         this.$el.stop().slideDown(this.speed).addClass(SHOW);
      }

      hide() {
         if (this.$trigger.length) {
            this.$trigger.removeClass(EXPANDED).attr(ARIA_EXPANDED, false);
         }
         this.$el.stop().slideUp(this.speed).removeClass(SHOW);
      }

      static _jQuery(config) {
         return this.each(function () {
            const data = new Collapse(this);

            if (typeof config === 'string') {
               if (data[config] === undefined) {
                  throw new Error(`No method named "${config}"`);
               }
               data[config]();
               return;
            }

            data.toggle();
         });
      }
   }

   $.fn[NAME] = Collapse._jQuery;
   $.fn[NAME].Constructor = Collapse;
   $.fn[NAME].noConflict = () => {
      $.fn[NAME] = NO_CONFLICT;
      return Collapse._jQuery;
   };

   $(document).on('click', '[data-env-collapse]', function (e) {
      e.preventDefault();

      const $this = $(this);
      const target = $this.attr('href') || $this.attr('data-target');
      const $target = $(target);

      $target[NAME]();
   });

   return Collapse;
})(jQuery);

export default Collapse;
<commit_msg>Ignore calls during animation<commit_after>/**
 * --------------------------------------------------------------------------
 * Licensed under MIT https://github.com/sitevision/envision/blob/master/LICENSE
 * --------------------------------------------------------------------------
 */

import jQuery from 'jquery';
import Util from './util';

const Collapse = (($) => {
   const ARIA_EXPANDED = 'aria-expanded';
   const MODIFIER_BASE = 'env-collapse--';
   const DURATION_CUSTOM_PROP = '--env-collapse-toggle-duration';
   const NAME = 'envCollapse';
   const NO_CONFLICT = $.fn[NAME];
   const EXPANDED = MODIFIER_BASE + 'expanded';
   const SHOW = MODIFIER_BASE + 'show';

   class Collapse {
      constructor(element) {
         this.el = element;
         this.$el = $(element);
         this.$trigger = $(
            `[data-env-collapse][href="#${element.id}"], [data-env-collapse][data-target="#${element.id}"]`
         );
         this.speed = Util.getToggleSpeed(
            this.$trigger[0],
            DURATION_CUSTOM_PROP
         );
      }

      toggle() {
         if (this.$el.is(':animated')) {
            return;
         } else if (this.$el.hasClass(SHOW)) {
            this.hide();
         } else {
            this.show();
         }
      }

      show() {
         if (this.$trigger.length) {
            this.$trigger.addClass(EXPANDED).attr(ARIA_EXPANDED, true);
         }
         this.$el.stop().slideDown(this.speed).addClass(SHOW);
      }

      hide() {
         if (this.$trigger.length) {
            this.$trigger.removeClass(EXPANDED).attr(ARIA_EXPANDED, false);
         }
         this.$el.stop().slideUp(this.speed).removeClass(SHOW);
      }

      static _jQuery(config) {
         return this.each(function () {
            const data = new Collapse(this);

            if (typeof config === 'string') {
               if (data[config] === undefined) {
                  throw new Error(`No method named "${config}"`);
               }
               data[config]();
               return;
            }

            data.toggle();
         });
      }
   }

   $.fn[NAME] = Collapse._jQuery;
   $.fn[NAME].Constructor = Collapse;
   $.fn[NAME].noConflict = () => {
      $.fn[NAME] = NO_CONFLICT;
      return Collapse._jQuery;
   };

   $(document).on('click', '[data-env-collapse]', function (e) {
      e.preventDefault();

      const $this = $(this);
      const target = $this.attr('href') || $this.attr('data-target');
      const $target = $(target);

      if ($target.is(':animated')) {
         return;
      }

      $target[NAME]();
   });

   return Collapse;
})(jQuery);

export default Collapse;
<|endoftext|>


<commit_before>import {SKILL_LEVEL} from '../../skill-levels';
import * as tag from '../../tags';
import {toUtcDate}  from '../../date';
import * as date from '../../date';

const OBJECT_FROMENTRIES = 1;

export const all = {
  name: 'ES10 Katas',
  groups: {
    'Object API': {
      items: {
        [OBJECT_FROMENTRIES]: {
          name: 'basics',
          description: '',
          path: 'object-api/fromEntries',
          level: SKILL_LEVEL.BEGINNER,
          requiresKnowledgeFrom: [],
          publishDateUTC: toUtcDate(2019, date.JUNE, 25, 19, 55),
          links: [
            {
              url: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries',
              comment: 'Description of Object.fromEntries() on MDN.',
              tags: [tag.MDN, tag.DOCS]
            },
            {
              url: 'https://www.ecma-international.org/ecma-262/10.0/#sec-object.fromentries',
              comment: 'The specification describing `Object.fromEntries()`.',
              tags: [tag.SPECIFICATION]
            },
            {
              url: 'https://github.com/tc39/proposal-object-from-entries',
              comment: 'The (now archived) proposal, before it went into the spec, interesting read if you wanna go deep.',
              tags: [tag.DISCUSSION, tag.DOCS]
            },
            {
              url: 'https://github.com/tc39/proposal-object-from-entries/blob/master/DETAILS.md',
              comment: 'Very interesting details about some decisions on this method.',
              tags: [tag.DISCUSSION, tag.DOCS]
            },
          ],
        },
      },
    },
  },
};
<commit_msg>Fix the metadata.<commit_after>import {SKILL_LEVEL} from '../../skill-levels';
import * as tag from '../../tags';
import {toUtcDate}  from '../../date';
import * as date from '../../date';

const OBJECT_FROMENTRIES = 1;

export const all = {
  name: 'ES10 Katas',
  groups: {
    'Object API': {
      items: {
        [OBJECT_FROMENTRIES]: {
          name: '`Object.fromEntries()`',
          description: '`Object.fromEntries()` converts key-value pairs into an object',
          path: 'object-api/fromEntries',
          level: SKILL_LEVEL.BEGINNER,
          requiresKnowledgeFrom: [],
          publishDateUTC: toUtcDate(2019, date.JUNE, 25, 19, 55),
          links: [
            {
              url: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/fromEntries',
              comment: 'Description of Object.fromEntries() on MDN.',
              tags: [tag.MDN, tag.DOCS]
            },
            {
              url: 'https://www.ecma-international.org/ecma-262/10.0/#sec-object.fromentries',
              comment: 'The specification describing `Object.fromEntries()`.',
              tags: [tag.SPECIFICATION]
            },
            {
              url: 'https://github.com/tc39/proposal-object-from-entries',
              comment: 'The (now archived) proposal, before it went into the spec, interesting read if you wanna go deep.',
              tags: [tag.DISCUSSION, tag.DOCS]
            },
            {
              url: 'https://github.com/tc39/proposal-object-from-entries/blob/master/DETAILS.md',
              comment: 'Very interesting details about some decisions on this method.',
              tags: [tag.DISCUSSION, tag.DOCS]
            },
          ],
        },
      },
    },
  },
};
<|endoftext|>


<commit_before>/**
 * We.js metatag feature, set res.locals.metatag variable
 *
 */

module.exports = {
  /**
   * add one middleware with name
   *
   * @param {String} name       Express.js middleware
   * @param {Function} middleware Express.js middleware
   */
  add: function add(name, middleware) {
    this.middlewares[name] = middleware;
  },

  /**
   * Metadata middlware how select one  metatag middleware handler
   *
   * @param  {Object}   req  Express.js request
   * @param  {Object}   res  Express.js response
   * @param  {Function} next callback
   */
  middleware: function metatagMiddleware(req, res, next) {
    if (res.locals.metatagHandler) {
      if (typeof res.locals.metatagHandler === 'function') {
        return res.locals.metatagHandler(req, res, next);
      } else if (req.we.router.metatag.middlewares[res.locals.metatagHandler]) {
        return req.we.router.metatag.middlewares[res.locals.metatagHandler](req, res, next);
      }
    }
    // else use the default
    req.we.router.metatag.middlewares.default(req, res, next);
  },

  /**
   * Middleware handlers
   *
   * @type {Object}
   */
  middlewares: {

    /**
     * Default middleware
     */
    default: function defaultMiddleware(req, res, next) {
      res.locals.metatag +=
        '<meta property="og:url" content="'+req.we.config.hostname+req.urlBeforeAlias+'" />'+
        '<meta property="og:title" content="'+res.locals.title+'" />' +
        '<meta property="og:site_name" content="'+res.locals.appName+'" />'+
        '<meta property="og:type" content="website" />';
      next();
    },

    /**
     * User findOne action metatag middleware
     */
    userFindOne: function userFindOne(req, res, next) {
      var hostname = req.we.hostname;

      res.locals.metatag +=
        '<meta property="og:url" content="'+hostname+req.urlBeforeAlias+'" />'+
        '<meta property="og:title" content="'+res.locals.title+'" />' +
        '<meta property="og:site_name" content="'+res.locals.appName+'" />'+
        '<meta property="og:type" content="profile" />';

        if (res.locals.data.biography) {
          res.locals.metatag += '<meta property="og:description" content="'+
            req.we.utils.string(res.locals.data.biography).stripTags().truncate(200).s+
          '" />';
        }

        if (res.locals.data.avatar && res.locals.data.avatar[0]) {
          var img = res.locals.data.avatar[0];

          res.locals.metatag +=
            '<meta property="og:image" content="'+hostname+img.urls.large+'" />'+
            '<meta property="og:image:type" content="'+img.mime+'" />'+
            '<meta property="og:image:width" content="'+img.width+'" />'+
            '<meta property="og:image:height" content="'+img.height+'" />';
        }

      next();
    }
  }
}<commit_msg>fix user findOne hostname var<commit_after>/**
 * We.js metatag feature, set res.locals.metatag variable
 *
 */

module.exports = {
  /**
   * add one middleware with name
   *
   * @param {String} name       Express.js middleware
   * @param {Function} middleware Express.js middleware
   */
  add: function add(name, middleware) {
    this.middlewares[name] = middleware;
  },

  /**
   * Metadata middlware how select one  metatag middleware handler
   *
   * @param  {Object}   req  Express.js request
   * @param  {Object}   res  Express.js response
   * @param  {Function} next callback
   */
  middleware: function metatagMiddleware(req, res, next) {
    if (res.locals.metatagHandler) {
      if (typeof res.locals.metatagHandler === 'function') {
        return res.locals.metatagHandler(req, res, next);
      } else if (req.we.router.metatag.middlewares[res.locals.metatagHandler]) {
        return req.we.router.metatag.middlewares[res.locals.metatagHandler](req, res, next);
      }
    }
    // else use the default
    req.we.router.metatag.middlewares.default(req, res, next);
  },

  /**
   * Middleware handlers
   *
   * @type {Object}
   */
  middlewares: {

    /**
     * Default middleware
     */
    default: function defaultMiddleware(req, res, next) {
      res.locals.metatag +=
        '<meta property="og:url" content="'+req.we.config.hostname+req.urlBeforeAlias+'" />'+
        '<meta property="og:title" content="'+res.locals.title+'" />' +
        '<meta property="og:site_name" content="'+res.locals.appName+'" />'+
        '<meta property="og:type" content="website" />';
      next();
    },

    /**
     * User findOne action metatag middleware
     */
    userFindOne: function userFindOne(req, res, next) {
      var hostname = req.we.config.hostname;

      res.locals.metatag +=
        '<meta property="og:url" content="'+hostname+req.urlBeforeAlias+'" />'+
        '<meta property="og:title" content="'+res.locals.title+'" />' +
        '<meta property="og:site_name" content="'+res.locals.appName+'" />'+
        '<meta property="og:type" content="profile" />';

        if (res.locals.data.biography) {
          res.locals.metatag += '<meta property="og:description" content="'+
            req.we.utils.string(res.locals.data.biography).stripTags().truncate(200).s+
          '" />';
        }

        if (res.locals.data.avatar && res.locals.data.avatar[0]) {
          var img = res.locals.data.avatar[0];

          res.locals.metatag +=
            '<meta property="og:image" content="'+hostname+img.urls.large+'" />'+
            '<meta property="og:image:type" content="'+img.mime+'" />'+
            '<meta property="og:image:width" content="'+img.width+'" />'+
            '<meta property="og:image:height" content="'+img.height+'" />';
        }

      next();
    }
  }
}<|endoftext|>


<commit_before>// 39: iterator - custom. Iterable is a protocol, when implemented allows objects
// to customize their iteration behavior, such as what values are looped over in a for..of construct.
// read more at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols

// To do: make all tests pass, leave the assert lines unchanged!

describe('A simple iterable without items inside, implementing the right protocol', () => {

  function iteratorFunction() {}

  describe('the iterator function needs to comply to the iterator protocol', function() {
    it('must return an object', function() {
      assert.equal(typeof iteratorFunction(), 'object');
    });
    it('the object must have a key `next` which must be a function', function() {
      assert.equal(typeof iteratorFunction().next, 'function');
    });
    it('calling `next()` must return an object with `{done: true}`', function() {
      assert.deepEqual(iteratorFunction().next(), {done: true});
    });
  });

  let iterable;
  beforeEach(function() {
    iterable;
  });

  describe('the iterable', function() {
    it('must be an object', function() {
      assert.equal(typeof iterable, 'object');
    });
    it('must have the iterator function assigned to the key `Symbol.iterator`', function() {
      assert.equal(iterable[Symbol.iterator], iteratorFunction);
    });
  });

  describe('using the iterable', function() {
    it('it contains no values', function() {
      let numberOfValues = 0;
      for (let value of iterable) {
        numberOfValues++;
      }
      assert.equal(numberOfValues, 0);
    });

    it('has no `.length` property', function() {
      assert.equal('length' in iterable, false);
    });

    describe('can be converted to an array', function() {
      it('using `Array.from()`', function() {
        const arr = Array.from(iterable);
        assert.equal(Array.isArray(arr), true);
      });

      it('which length is still 0', function() {
        const arr = Array.from(iterable);
        assert.equal(arr.length, 0);
      });
    });
  });

});
<commit_msg>Everything fails now.<commit_after>// 39: iterator - custom. Iterable is a protocol, when implemented allows objects
// to customize their iteration behavior, such as what values are looped over in a for..of construct.
// read more at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols

// To do: make all tests pass, leave the assert lines unchanged!

describe('A simple iterable without items inside, implementing the right protocol', () => {

  function iteratorFunction() {}

  describe('the iterator function needs to comply to the iterator protocol', function() {
    it('must return an object', function() {
      assert.equal(typeof iteratorFunction(), 'object');
    });
    it('the object must have a key `next` which must be a function', function() {
      assert.equal(typeof iteratorFunction().next, 'function');
    });
    it('calling `next()` must return an object with `{done: true}`', function() {
      assert.deepEqual(iteratorFunction().next(), {done: true});
    });
  });

  let iterable;
  beforeEach(function() {
    iterable;
  });

  describe('the iterable', function() {
    it('must be an object', function() {
      assert.equal(typeof iterable, 'object');
    });
    it('must have the iterator function assigned to the key `Symbol.iterator`', function() {
      assert.equal(iterable[Symbol.iterator], iteratorFunction);
    });
  });

  describe('using the iterable', function() {
    it('it contains no values', function() {
      let values;
      for (let value of iterable) {
        values += value;
      }
      assert.equal(values, '');
    });

    it('has no `.length` property', function() {
      const hasLengthProperty = iterable;
      assert.equal(hasLengthProperty, false);
    });

    describe('can be converted to an array', function() {
      it('using `Array.from()`', function() {
        const arr = iterable;
        assert.equal(Array.isArray(arr), true);
      });

      it('where `.length` is still 0', function() {
        const arr = iterable;
        const length = arr.length;
        assert.equal(length, 0);
      });
    });
  });

});
<|endoftext|>


<commit_before>import puppeteer from 'puppeteer';
import fse from 'fs-extra';
import http from 'http';
import path from 'path';
import express from 'express';
import expect from 'expect-puppeteer';
import { addTeardown, shutdown } from 'modules/handleKillSignals';
import log from 'modules/log';

const port = 3090;
const host = '0.0.0.0';

function startServer(app) {
  return new Promise((resolve, reject) => {
    const server = http.createServer(app);
    server.listen(port, host, err => {
      if (err) {
        reject(err);
        return;
      }

      log.info({
        name: 'http',
        msg: `ready on http://${server.address().address}:${server.address().port}`,
      });

      resolve();
    });

    addTeardown({
      callback: () => {
        log.info({
          name: 'http',
          msg: 'server is stopping',
        });
        return new Promise((resolve2, reject2) => {
          server.close(err => {
            if (err) {
              reject2(err);
              return;
            }
            resolve2();
          });
        });
      },
      nice: 1, // Do it first.
    });
  });
}

async function createApp() {
  const app = express();
  const rootPath = path.join(__dirname, '../../../../');
  const umdPath = '/umd.js';

  let index = await fse.readFile(path.join(rootPath, 'examples/cdn/index.html'), 'utf8');
  index = index.replace(
    'https://unpkg.com/@material-ui/core/umd/material-ui.development.js',
    umdPath,
  );
  app.get('/', (req, res) => {
    res.send(index);
  });

  const umd = await fse.readFile(
    path.join(rootPath, 'packages/material-ui/build/umd/material-ui.development.js'),
    'utf8',
  );
  app.get(umdPath, (req, res) => {
    res.send(umd);
  });

  return app;
}

async function startBrowser() {
  log.info({
    name: 'browser',
    msg: 'start',
  });
  const browser = await puppeteer.launch({
    args: ['--single-process'],
  });
  const page = await browser.newPage();
  page.on('pageerror', err => {
    throw err;
  });

  addTeardown({
    callback: () => {
      log.info({
        name: 'browser',
        msg: 'server is stopping',
      });
      return browser.close();
    },
    nice: 2,
  });

  return page;
}

process.on('unhandledRejection', (reason, promise) => {
  log.fatal({
    name: 'unhandledRejection',
    msg: { reason, promise },
  });
  process.exit(1);
});

async function run() {
  try {
    const app = await createApp();
    await startServer(app);

    const page = await startBrowser();
    await page.goto(`http://${host}:${port}`);
    await expect(page).toClick('button', { text: 'Super Secret Password' });
    await expect(page).toMatch('1-2-3-4-5');
  } catch (err) {
    log.fatal({
      name: 'test',
      msg: { err },
    });
    process.exit(1);
  }

  shutdown('SIGINT', 'done');
}

run();
<commit_msg>[test] Fix CDN test (#14324)<commit_after>import puppeteer from 'puppeteer';
import fse from 'fs-extra';
import http from 'http';
import path from 'path';
import express from 'express';
import expect from 'expect-puppeteer';
import { addTeardown, shutdown } from 'modules/handleKillSignals';
import log from 'modules/log';

const port = 3090;
const host = '0.0.0.0';

function startServer(app) {
  return new Promise((resolve, reject) => {
    const server = http.createServer(app);
    server.listen(port, host, err => {
      if (err) {
        reject(err);
        return;
      }

      log.info({
        name: 'http',
        msg: `ready on http://${server.address().address}:${server.address().port}`,
      });

      resolve();
    });

    addTeardown({
      callback: () => {
        log.info({
          name: 'http',
          msg: 'server is stopping',
        });
        return new Promise((resolve2, reject2) => {
          server.close(err => {
            if (err) {
              reject2(err);
              return;
            }
            resolve2();
          });
        });
      },
      nice: 1, // Do it first.
    });
  });
}

async function createApp() {
  const app = express();
  const rootPath = path.join(__dirname, '../../../../');
  const umdPath = '/umd.js';

  let index = await fse.readFile(path.join(rootPath, 'examples/cdn/index.html'), 'utf8');
  index = index.replace(
    'https://unpkg.com/@material-ui/core/umd/material-ui.development.js',
    umdPath,
  );
  app.get('/', (req, res) => {
    res.send(index);
  });

  const umd = await fse.readFile(
    path.join(rootPath, 'packages/material-ui/build/umd/material-ui.development.js'),
    'utf8',
  );
  app.get(umdPath, (req, res) => {
    res.send(umd);
  });

  return app;
}

async function startBrowser() {
  log.info({
    name: 'browser',
    msg: 'start',
  });
  const browser = await puppeteer.launch({
    args: [
      '--single-process', // Solve mono-thread issue on CircleCI
      '--disable-web-security', // Solve weird crossorigin anonymous issue on CircleCI
    ],
  });
  const page = await browser.newPage();
  page.on('pageerror', err => {
    throw err;
  });

  addTeardown({
    callback: () => {
      log.info({
        name: 'browser',
        msg: 'server is stopping',
      });
      return browser.close();
    },
    nice: 2,
  });

  return page;
}

process.on('unhandledRejection', (reason, promise) => {
  log.fatal({
    name: 'unhandledRejection',
    msg: { reason, promise },
  });
  process.exit(1);
});

async function run() {
  try {
    const app = await createApp();
    await startServer(app);

    const page = await startBrowser();
    await page.goto(`http://${host}:${port}`);
    await expect(page).toClick('button', { text: 'Super Secret Password' });
    await expect(page).toMatch('1-2-3-4-5');
  } catch (err) {
    log.fatal({
      name: 'test',
      msg: { err },
    });
    process.exit(1);
  }

  shutdown('SIGINT', 'done');
}

run();
<|endoftext|>


<commit_before><commit_msg>field is optional<commit_after><|endoftext|>


<commit_before>angular.module('proximate.services', [])

.factory('PubNub', function(pubNubKeys) {
  var pubNub = PUBNUB.init({
    publish_key: pubNubKeys.pub,
    subscribe_key: pubNubKeys.sub
  });

  var subscribe = function(channel, callback) {
    pubNub.subscribe({
      channel: channel,
      callback: callback
    });
  };

  var publish = function(channel, message) {
    var info = {
      channel: channel,
      message: message
    };

    pubNub.publish(info);
  };

  return {
    subscribe: subscribe,
    publish: publish
  };

})

.factory('Populate', function($http) {

  var adminId = 1;
  // get event participants for a given eventID
  var getParticipants = function(eventID) {
    var url = 'api/events/' + eventID + '/participants';
    return $http({
      method: 'GET',
      url: url,
    });
  };

  // get current event ID
  var getCurrentEvent = function(adminId) {
    var url = '/api/admins/' + adminId + '/events/current';
    return $http({
      method: 'GET',
      url: url,
    });
  };

  var getAdminName = function(adminId) {
    var url = '/api/admins/' + adminId;
    return $http({
      method: 'GET',
      url: url,
    });
  };

  var getEventsByAdminId = function(adminId) {
    var url = 'api/admins/' + adminId + '/events';
    return $http({
      method: 'GET',
      url: url,
    });
  };

  var getBeaconsByAdminId = function(adminId) {
    var url = '/api/admins/' + adminId + '/beacons';
    return $http({
      method: 'GET',
      url: url
    });
  };

  var postNewBeacon = function(adminId, identifier, uuid, major, minor) {
    return $http({
      method: 'POST',
      url: '/api/beacon/upsert',
      data: {
        adminId: adminId,
        identifier: identifier,
        uuid: uuid,
        major: major,
        minor: minor
      },
    });
  };

  var updateParticipantStatus = function(participantId, eventId, status) {
    return $http({
      method: 'Post',
      url: '/api/participant/updateStatus',
      data: {
        participantId: participantId,
        eventId: eventId,
        status: status
      },
    });
  };

  return {
    adminId: adminId,
    getParticipants: getParticipants,
    getCurrentEvent: getCurrentEvent,
    getAdminName: getAdminName,
    getEventsByAdminId: getEventsByAdminId,
    getBeaconsByAdminId: getBeaconsByAdminId,
    postNewBeacon: postNewBeacon,
    updateParticipantStatus: updateParticipantStatus
  };

})

.filter('fromNow', function($rootScope) {
  return function(startTime, endTime) {
    $rootScope.timeDiffLessThanHourBefore = false;
    $rootScope.timeDiffMoreThanHourBefore = false;
    $rootScope.timeDiffAfter = false;
    a = moment(startTime);
    b = moment(endTime);
    if (Math.abs(a.diff(b, 'minutes')) <= 60 && a.diff(b, 'minutes') > 0) {
      $rootScope.timeDiffLessThanHourBefore = true;
    } else if (Math.abs(a.diff(b, 'minutes')) > 60 && a.diff(b, 'minutes') > 0) {
      $rootScope.timeDiffMoreThanHourBefore = true;
    } else {
      $rootScope.timeDiffAfter = true;
    }
    return moment.duration(a - b).humanize(true);
  };
})

.filter('CurrentEvents', function($rootScope) {
  return function(events, current) {
    var filteredResults = [];
    var now = moment();
    if (events) {
      events.forEach(function(event) {
        for (var i = 0; i < $rootScope.eventsData.length; i++) {
          if (current) {
            if (moment(event.start_time).diff(now) < 0) {
              return;
            }
          } else {
            if (moment(event.start_time).diff(now) >= 0) {
              return;
            }
          }
        }
        filteredResults.push(event);
      });
    }
    return filteredResults;
  };
})

.filter('removeArrivedParticipants', function($rootScope) {
  return function(participants) {
    var filteredResults = [];
    if (participants) {
      participants.forEach(function(participant) {
        if (participant._pivot_status === "ontime") {
          return;
        }
        filteredResults.push(participant);
      });
    }
    return filteredResults;
  };
});
<commit_msg>Fixed gulp error in services.js<commit_after>angular.module('proximate.services', [])

.factory('PubNub', function(pubNubKeys) {
  var pubNub = PUBNUB.init({
    publish_key: pubNubKeys.pub,
    subscribe_key: pubNubKeys.sub
  });

  var subscribe = function(channel, callback) {
    pubNub.subscribe({
      channel: channel,
      callback: callback
    });
  };

  var publish = function(channel, message) {
    var info = {
      channel: channel,
      message: message
    };

    pubNub.publish(info);
  };

  return {
    subscribe: subscribe,
    publish: publish
  };

})

.factory('Populate', function($http) {

  var adminId = 1;
  // get event participants for a given eventID
  var getParticipants = function(eventID) {
    var url = 'api/events/' + eventID + '/participants';
    return $http({
      method: 'GET',
      url: url,
    });
  };

  // get current event ID
  var getCurrentEvent = function(adminId) {
    var url = '/api/admins/' + adminId + '/events/current';
    return $http({
      method: 'GET',
      url: url,
    });
  };

  var getAdminName = function(adminId) {
    var url = '/api/admins/' + adminId;
    return $http({
      method: 'GET',
      url: url,
    });
  };

  var getEventsByAdminId = function(adminId) {
    var url = 'api/admins/' + adminId + '/events';
    return $http({
      method: 'GET',
      url: url,
    });
  };

  var getBeaconsByAdminId = function(adminId) {
    var url = '/api/admins/' + adminId + '/beacons';
    return $http({
      method: 'GET',
      url: url
    });
  };

  var postNewBeacon = function(adminId, identifier, uuid, major, minor) {
    return $http({
      method: 'POST',
      url: '/api/beacon/upsert',
      data: {
        adminId: adminId,
        identifier: identifier,
        uuid: uuid,
        major: major,
        minor: minor
      },
    });
  };

  var updateParticipantStatus = function(participantId, eventId, status) {
    return $http({
      method: 'Post',
      url: '/api/participant/updateStatus',
      data: {
        participantId: participantId,
        eventId: eventId,
        status: status
      },
    });
  };

  return {
    adminId: adminId,
    getParticipants: getParticipants,
    getCurrentEvent: getCurrentEvent,
    getAdminName: getAdminName,
    getEventsByAdminId: getEventsByAdminId,
    getBeaconsByAdminId: getBeaconsByAdminId,
    postNewBeacon: postNewBeacon,
    updateParticipantStatus: updateParticipantStatus
  };

})

.filter('fromNow', function($rootScope) {
  return function(startTime, endTime) {
    $rootScope.timeDiffLessThanHourBefore = false;
    $rootScope.timeDiffMoreThanHourBefore = false;
    $rootScope.timeDiffAfter = false;
    a = moment(startTime);
    b = moment(endTime);
    if (Math.abs(a.diff(b, 'minutes')) <= 60 && a.diff(b, 'minutes') > 0) {
      $rootScope.timeDiffLessThanHourBefore = true;
    } else if (Math.abs(a.diff(b, 'minutes')) > 60 && a.diff(b, 'minutes') > 0) {
      $rootScope.timeDiffMoreThanHourBefore = true;
    } else {
      $rootScope.timeDiffAfter = true;
    }
    return moment.duration(a - b).humanize(true);
  };
})

.filter('CurrentEvents', function($rootScope) {
  return function(events, current) {
    var filteredResults = [];
    var now = moment();
    if (events) {
      events.forEach(function(event) {
        for (var i = 0; i < $rootScope.eventsData.length; i++) {
          if (current) {
            if (moment(event.start_time).diff(now) < 0) {
              return;
            }
          } else {
            if (moment(event.start_time).diff(now) >= 0) {
              return;
            }
          }
        }
        filteredResults.push(event);
      });
    }
    return filteredResults;
  };
})

.filter('removeArrivedParticipants', function($rootScope) {
  return function(participants) {
    var filteredResults = [];
    if (participants) {
      participants.forEach(function(participant) {
        if (participant._pivot_status === 'ontime') {
          return;
        }
        filteredResults.push(participant);
      });
    }
    return filteredResults;
  };
});
<|endoftext|>


<commit_before><commit_msg>fix candidate sort<commit_after><|endoftext|>


<commit_before>import Telescope from 'meteor/nova:lib';
import Users from './collection.js';
import marked from 'marked';
import Events from "meteor/nova:events";
import NovaEmail from 'meteor/nova:email';

//////////////////////////////////////////////////////
// Collection Hooks                                 //
//////////////////////////////////////////////////////

// /**
//  * @summary Generate HTML body from Markdown on user bio insert
//  */
// Users.after.insert(function (userId, user) {

//   // run create user async callbacks
//   Telescope.callbacks.runAsync("users.new.async", user);

//   // check if all required fields have been filled in. If so, run profile completion callbacks
//   if (Users.hasCompletedProfile(user)) {
//     Telescope.callbacks.runAsync("users.profileCompleted.async", user);
//   }

// });

// /**
//  * @summary Generate HTML body from Markdown when user bio is updated
//  */
// Users.before.update(function (userId, doc, fieldNames, modifier) {
//   // if bio is being modified, update htmlBio too
//   if (Meteor.isServer && modifier.$set && modifier.$set["__bio"]) {
//     modifier.$set["__htmlBio"] = Telescope.utils.sanitize(marked(modifier.$set["__bio"]));
//   }
// });

// /**
//  * @summary Disallow $rename
//  */
// Users.before.update(function (userId, doc, fieldNames, modifier) {
//   if (!!modifier.$rename) {
//     throw new Meteor.Error("illegal $rename operator detected!");
//   }
// });

// /**
//  * @summary If user.__email has changed, check for existing emails and change user.emails and email hash if needed
//  */
//  if (Meteor.isServer) {
//   Users.before.update(function (userId, doc, fieldNames, modifier) {

//     var user = doc;

//     // if email is being modified, update user.emails too
//     if (Meteor.isServer && modifier.$set && modifier.$set["__email"]) {

//       var newEmail = modifier.$set["__email"];

//       // check for existing emails and throw error if necessary
//       var userWithSameEmail = Users.findByEmail(newEmail);
//       if (userWithSameEmail && userWithSameEmail._id !== doc._id) {
//         throw new Meteor.Error("email_taken2", "this_email_is_already_taken" + " (" + newEmail + ")");
//       }

//       // if user.emails exists, change it too
//       if (!!user.emails) {
//         user.emails[0].address = newEmail;
//         modifier.$set.emails = user.emails;
//       }

//       // update email hash
//       modifier.$set["__emailHash"] = Gravatar.hash(newEmail);

//     }
//   });
// }

//////////////////////////////////////////////////////
// Callbacks                                        //
//////////////////////////////////////////////////////

/**
 * @summary Set up user object on creation
 * @param {Object} user – the user object being iterated on and returned
 * @param {Object} options – user options
 */
function setupUser (user, options) {
  // ------------------------------ Properties ------------------------------ //
  var userProperties = {
    profile: options.profile || {},
    __karma: 0,
    __isInvited: false,
    __postCount: 0,
    __commentCount: 0,
    __invitedCount: 0,
    __upvotedPosts: [],
    __downvotedPosts: [],
    __upvotedComments: [],
    __downvotedComments: []
  };
  user = _.extend(user, userProperties);

  // look in a few places for the user email
  if (options.email) {
    user.__email = options.email;
  } else if (user.services['meteor-developer'] && user.services['meteor-developer'].emails) {
    user.__email = _.findWhere(user.services['meteor-developer'].emails, { primary: true }).address;
  } else if (user.services.facebook && user.services.facebook.email) {
    user.__email = user.services.facebook.email;
  } else if (user.services.github && user.services.github.email) {
    user.__email = user.services.github.email;
  } else if (user.services.google && user.services.google.email) {
    user.__email = user.services.google.email;
  } else if (user.services.linkedin && user.services.linkedin.emailAddress) {
    user.__email = user.services.linkedin.emailAddress;
  }

  // generate email hash
  if (!!user.__email) {
    user.__emailHash = Gravatar.hash(user.__email);
  }

  // look in a few places for the displayName
  if (user.profile.username) {
    user.__displayName = user.profile.username;
  } else if (user.profile.name) {
    user.__displayName = user.profile.name;
  } else if (user.services.linkedin && user.services.linkedin.firstName) {
    user.__displayName = user.services.linkedin.firstName + " " + user.services.linkedin.lastName;
  } else {
    user.__displayName = user.username;
  }

  // create a basic slug from display name and then modify it if this slugs already exists;
  const basicSlug = Telescope.utils.slugify(user.__displayName);
  user.__slug = Telescope.utils.getUnusedSlug(Users, basicSlug);

  // if this is not a dummy account, and is the first user ever, make them an admin
  user.isAdmin = (!user.profile.isDummy && Users.find({'profile.isDummy': {$ne: true}}).count() === 0) ? true : false;

  Events.track('new user', {username: user.__displayName, email: user.__email});

  return user;
}
Telescope.callbacks.add("users.new.sync", setupUser);

function hasCompletedProfile (user) {
  return Users.hasCompletedProfile(user);
}
Telescope.callbacks.add("users.profileCompleted.sync", hasCompletedProfile);

function usersNewAdminUserCreationNotification (user) {
  // send notifications to admins
  const admins = Users.adminUsers();
  admins.forEach(function(admin) {
    if (Users.getSetting(admin, "notifications_users", false)) {
      const emailProperties = Users.getNotificationProperties(user);
      const html = NovaEmail.getTemplate('newUser')(emailProperties);
      NovaEmail.send(Users.getEmail(admin), `New user account: ${emailProperties.displayName}`, NovaEmail.buildTemplate(html));
    }
  });
  return user;
}
Telescope.callbacks.add("users.new.sync", usersNewAdminUserCreationNotification);

function usersEditGenerateHtmlBio (modifier) {
  if (modifier.$set && modifier.$set.__bio) {
    modifier.$set.__htmlBio = Telescope.utils.sanitize(marked(modifier.$set.__bio));
  }
  return modifier;
}
Telescope.callbacks.add("users.edit.sync", usersEditGenerateHtmlBio);

function usersEditCheckEmail (modifier) {
  // if email is being modified, update user.emails too
  if (modifier.$set && modifier.$set.__email) {

    var newEmail = modifier.$set.__email;

    // check for existing emails and throw error if necessary
    var userWithSameEmail = Users.findByEmail(newEmail);
    if (userWithSameEmail && userWithSameEmail._id !== doc._id) {
      throw new Meteor.Error("email_taken2", "this_email_is_already_taken" + " (" + newEmail + ")");
    }

    // if user.emails exists, change it too
    if (!!user.emails) {
      user.emails[0].address = newEmail;
      modifier.$set.emails = user.emails;
    }

    // update email hash
    modifier.$set.__emailHash = Gravatar.hash(newEmail);

  }
  return modifier;
}
Telescope.callbacks.add("users.edit.sync", usersEditCheckEmail);
<commit_msg>callback fix on users.edit.sync<commit_after>import Telescope from 'meteor/nova:lib';
import Users from './collection.js';
import marked from 'marked';
import Events from "meteor/nova:events";
import NovaEmail from 'meteor/nova:email';

//////////////////////////////////////////////////////
// Collection Hooks                                 //
//////////////////////////////////////////////////////

// /**
//  * @summary Generate HTML body from Markdown on user bio insert
//  */
// Users.after.insert(function (userId, user) {

//   // run create user async callbacks
//   Telescope.callbacks.runAsync("users.new.async", user);

//   // check if all required fields have been filled in. If so, run profile completion callbacks
//   if (Users.hasCompletedProfile(user)) {
//     Telescope.callbacks.runAsync("users.profileCompleted.async", user);
//   }

// });

// /**
//  * @summary Generate HTML body from Markdown when user bio is updated
//  */
// Users.before.update(function (userId, doc, fieldNames, modifier) {
//   // if bio is being modified, update htmlBio too
//   if (Meteor.isServer && modifier.$set && modifier.$set["__bio"]) {
//     modifier.$set["__htmlBio"] = Telescope.utils.sanitize(marked(modifier.$set["__bio"]));
//   }
// });

// /**
//  * @summary Disallow $rename
//  */
// Users.before.update(function (userId, doc, fieldNames, modifier) {
//   if (!!modifier.$rename) {
//     throw new Meteor.Error("illegal $rename operator detected!");
//   }
// });

// /**
//  * @summary If user.__email has changed, check for existing emails and change user.emails and email hash if needed
//  */
//  if (Meteor.isServer) {
//   Users.before.update(function (userId, doc, fieldNames, modifier) {

//     var user = doc;

//     // if email is being modified, update user.emails too
//     if (Meteor.isServer && modifier.$set && modifier.$set["__email"]) {

//       var newEmail = modifier.$set["__email"];

//       // check for existing emails and throw error if necessary
//       var userWithSameEmail = Users.findByEmail(newEmail);
//       if (userWithSameEmail && userWithSameEmail._id !== doc._id) {
//         throw new Meteor.Error("email_taken2", "this_email_is_already_taken" + " (" + newEmail + ")");
//       }

//       // if user.emails exists, change it too
//       if (!!user.emails) {
//         user.emails[0].address = newEmail;
//         modifier.$set.emails = user.emails;
//       }

//       // update email hash
//       modifier.$set["__emailHash"] = Gravatar.hash(newEmail);

//     }
//   });
// }

//////////////////////////////////////////////////////
// Callbacks                                        //
//////////////////////////////////////////////////////

/**
 * @summary Set up user object on creation
 * @param {Object} user – the user object being iterated on and returned
 * @param {Object} options – user options
 */
function setupUser (user, options) {
  // ------------------------------ Properties ------------------------------ //
  var userProperties = {
    profile: options.profile || {},
    __karma: 0,
    __isInvited: false,
    __postCount: 0,
    __commentCount: 0,
    __invitedCount: 0,
    __upvotedPosts: [],
    __downvotedPosts: [],
    __upvotedComments: [],
    __downvotedComments: []
  };
  user = _.extend(user, userProperties);

  // look in a few places for the user email
  if (options.email) {
    user.__email = options.email;
  } else if (user.services['meteor-developer'] && user.services['meteor-developer'].emails) {
    user.__email = _.findWhere(user.services['meteor-developer'].emails, { primary: true }).address;
  } else if (user.services.facebook && user.services.facebook.email) {
    user.__email = user.services.facebook.email;
  } else if (user.services.github && user.services.github.email) {
    user.__email = user.services.github.email;
  } else if (user.services.google && user.services.google.email) {
    user.__email = user.services.google.email;
  } else if (user.services.linkedin && user.services.linkedin.emailAddress) {
    user.__email = user.services.linkedin.emailAddress;
  }

  // generate email hash
  if (!!user.__email) {
    user.__emailHash = Gravatar.hash(user.__email);
  }

  // look in a few places for the displayName
  if (user.profile.username) {
    user.__displayName = user.profile.username;
  } else if (user.profile.name) {
    user.__displayName = user.profile.name;
  } else if (user.services.linkedin && user.services.linkedin.firstName) {
    user.__displayName = user.services.linkedin.firstName + " " + user.services.linkedin.lastName;
  } else {
    user.__displayName = user.username;
  }

  // create a basic slug from display name and then modify it if this slugs already exists;
  const basicSlug = Telescope.utils.slugify(user.__displayName);
  user.__slug = Telescope.utils.getUnusedSlug(Users, basicSlug);

  // if this is not a dummy account, and is the first user ever, make them an admin
  user.isAdmin = (!user.profile.isDummy && Users.find({'profile.isDummy': {$ne: true}}).count() === 0) ? true : false;

  Events.track('new user', {username: user.__displayName, email: user.__email});

  return user;
}
Telescope.callbacks.add("users.new.sync", setupUser);

function hasCompletedProfile (user) {
  return Users.hasCompletedProfile(user);
}
Telescope.callbacks.add("users.profileCompleted.sync", hasCompletedProfile);

function usersNewAdminUserCreationNotification (user) {
  // send notifications to admins
  const admins = Users.adminUsers();
  admins.forEach(function(admin) {
    if (Users.getSetting(admin, "notifications_users", false)) {
      const emailProperties = Users.getNotificationProperties(user);
      const html = NovaEmail.getTemplate('newUser')(emailProperties);
      NovaEmail.send(Users.getEmail(admin), `New user account: ${emailProperties.displayName}`, NovaEmail.buildTemplate(html));
    }
  });
  return user;
}
Telescope.callbacks.add("users.new.sync", usersNewAdminUserCreationNotification);

function usersEditGenerateHtmlBio (modifier) {
  if (modifier.$set && modifier.$set.__bio) {
    modifier.$set.__htmlBio = Telescope.utils.sanitize(marked(modifier.$set.__bio));
  }
  return modifier;
}
Telescope.callbacks.add("users.edit.sync", usersEditGenerateHtmlBio);

function usersEditCheckEmail (modifier, user) {
  // if email is being modified, update user.emails too
  if (modifier.$set && modifier.$set.__email) {

    var newEmail = modifier.$set.__email;

    // check for existing emails and throw error if necessary
    var userWithSameEmail = Users.findByEmail(newEmail);
    if (userWithSameEmail && userWithSameEmail._id !== user._id) {
      throw new Meteor.Error("email_taken2", "this_email_is_already_taken" + " (" + newEmail + ")");
    }

    // if user.emails exists, change it too
    if (!!user.emails) {
      user.emails[0].address = newEmail;
      modifier.$set.emails = user.emails;
    }

    // update email hash
    modifier.$set.__emailHash = Gravatar.hash(newEmail);

  }
  return modifier;
}
Telescope.callbacks.add("users.edit.sync", usersEditCheckEmail);
<|endoftext|>