<commit_before>define([
	"dojo/_base/array", // array.forEach array.indexOf
	"dojo/_base/declare", // declare
	"dojo/dom-construct", // domConstruct.place
	"./registry"	// registry.byNode()
], function(array, declare, domConstruct, registry){

	// module:
	//		dijit/_Container

	return declare("dijit._Container", null, {
		// summary:
		//		Mixin for widgets that contain HTML and/or a set of widget children.

		buildRendering: function(){
			this.inherited(arguments);
			if(!this.containerNode){
				// all widgets with descendants must set containerNode
				this.containerNode = this.domNode;
			}
		},

		addChild: function(/*dijit/_WidgetBase*/ widget, /*int?*/ insertIndex){
			// summary:
			//		Makes the given widget a child of this widget.
			// description:
			//		Inserts specified child widget's dom node as a child of this widget's
			//		container node, and possibly does other processing (such as layout).
			//
			//		Functionality is undefined if this widget contains anything besides
			//		a list of child widgets (ie, if it contains arbitrary non-widget HTML).

			var refNode = this.containerNode;
			if(insertIndex && typeof insertIndex == "number"){
				var children = this.getChildren();
				if(children && children.length >= insertIndex){
					refNode = children[insertIndex-1].domNode;
					insertIndex = "after";
				}
			}
			domConstruct.place(widget.domNode, refNode, insertIndex);

			// If I've been started but the child widget hasn't been started,
			// start it now.  Make sure to do this after widget has been
			// inserted into the DOM tree, so it can see that it's being controlled by me,
			// so it doesn't try to size itself.
			if(this._started && !widget._started){
				widget.startup();
			}
		},

		removeChild: function(/*Widget|int*/ widget){
			// summary:
			//		Removes the passed widget instance from this widget but does
			//		not destroy it.  You can also pass in an integer indicating
			//		the index within the container to remove (ie, removeChild(5) removes the sixth widget).

			if(typeof widget == "number"){
				widget = this.getChildren()[widget];
			}

			if(widget){
				var node = widget.domNode;
				if(node && node.parentNode){
					node.parentNode.removeChild(node); // detach but don't destroy
				}
			}
		},

		hasChildren: function(){
			// summary:
			//		Returns true if widget has child widgets, i.e. if this.containerNode contains widgets.
			return this.getChildren().length > 0;	// Boolean
		},

		_getSiblingOfChild: function(/*dijit/_WidgetBase*/ child, /*int*/ dir){
			// summary:
			//		Get the next or previous widget sibling of child
			// dir:
			//		if 1, get the next sibling
			//		if -1, get the previous sibling
			// tags:
			//		private
			var children = this.getChildren(),
				idx = array.indexOf(this.getChildren(), child);	// int
			return children[idx + dir];
		},

		getIndexOfChild: function(/*dijit/_WidgetBase*/ child){
			// summary:
			//		Gets the index of the child in this container or -1 if not found
			return array.indexOf(this.getChildren(), child);	// int
		}
	});
});
<commit_msg>remove unused dependency, fixes #15588 !strict.<commit_after>define([
	"dojo/_base/array", // array.forEach array.indexOf
	"dojo/_base/declare", // declare
	"dojo/dom-construct" // domConstruct.place
], function(array, declare, domConstruct){

	// module:
	//		dijit/_Container

	return declare("dijit._Container", null, {
		// summary:
		//		Mixin for widgets that contain HTML and/or a set of widget children.

		buildRendering: function(){
			this.inherited(arguments);
			if(!this.containerNode){
				// all widgets with descendants must set containerNode
				this.containerNode = this.domNode;
			}
		},

		addChild: function(/*dijit/_WidgetBase*/ widget, /*int?*/ insertIndex){
			// summary:
			//		Makes the given widget a child of this widget.
			// description:
			//		Inserts specified child widget's dom node as a child of this widget's
			//		container node, and possibly does other processing (such as layout).
			//
			//		Functionality is undefined if this widget contains anything besides
			//		a list of child widgets (ie, if it contains arbitrary non-widget HTML).

			var refNode = this.containerNode;
			if(insertIndex && typeof insertIndex == "number"){
				var children = this.getChildren();
				if(children && children.length >= insertIndex){
					refNode = children[insertIndex-1].domNode;
					insertIndex = "after";
				}
			}
			domConstruct.place(widget.domNode, refNode, insertIndex);

			// If I've been started but the child widget hasn't been started,
			// start it now.  Make sure to do this after widget has been
			// inserted into the DOM tree, so it can see that it's being controlled by me,
			// so it doesn't try to size itself.
			if(this._started && !widget._started){
				widget.startup();
			}
		},

		removeChild: function(/*Widget|int*/ widget){
			// summary:
			//		Removes the passed widget instance from this widget but does
			//		not destroy it.  You can also pass in an integer indicating
			//		the index within the container to remove (ie, removeChild(5) removes the sixth widget).

			if(typeof widget == "number"){
				widget = this.getChildren()[widget];
			}

			if(widget){
				var node = widget.domNode;
				if(node && node.parentNode){
					node.parentNode.removeChild(node); // detach but don't destroy
				}
			}
		},

		hasChildren: function(){
			// summary:
			//		Returns true if widget has child widgets, i.e. if this.containerNode contains widgets.
			return this.getChildren().length > 0;	// Boolean
		},

		_getSiblingOfChild: function(/*dijit/_WidgetBase*/ child, /*int*/ dir){
			// summary:
			//		Get the next or previous widget sibling of child
			// dir:
			//		if 1, get the next sibling
			//		if -1, get the previous sibling
			// tags:
			//		private
			var children = this.getChildren(),
				idx = array.indexOf(this.getChildren(), child);	// int
			return children[idx + dir];
		},

		getIndexOfChild: function(/*dijit/_WidgetBase*/ child){
			// summary:
			//		Gets the index of the child in this container or -1 if not found
			return array.indexOf(this.getChildren(), child);	// int
		}
	});
});
<|endoftext|>


<commit_before>export function ValidationError(message, details = {}) {
    const {
        columns = {},
        value = null
    } = details;

    this.message = message;
    this.columns = columns;
    this.value = value;

    if (message instanceof Error) {
        this.message = message.message;
        this.stack = message.stack;
    } else if (Error.captureStackTrace) {
        Error.captureStackTrace(this, this.constructor);
    }
}

ValidationError.prototype = Object.create(Error);
ValidationError.prototype.constructor = ValidationError;

Object.defineProperty(ValidationError, 'name', {
    value: 'ValidationError'
});
<commit_msg>Fix toString implementation for ValidationError<commit_after>export function ValidationError(message, details = {}) {
    const {
        columns = {},
        value = null
    } = details;

    this.message = message;
    this.columns = columns;
    this.value = value;

    if (message instanceof Error) {
        this.message = message.message;
        this.stack = message.stack;
    } else if (Error.captureStackTrace) {
        Error.captureStackTrace(this, this.constructor);
    }
}

ValidationError.prototype = Object.create(Error);
ValidationError.prototype.constructor = ValidationError;
ValidationError.prototype.toString = Error.prototype.toString;

Object.defineProperty(ValidationError, 'name', {
    value: 'ValidationError'
});
<|endoftext|>


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

module.exports = function(RED) {
    "use strict";
    var os = require('os');
    var dgram = require('dgram');
    var udpInputPortsInUse = {};

    // The Input Node
    function UDPin(n) {
        RED.nodes.createNode(this,n);
        this.group = n.group;
        this.port = n.port;
        this.datatype = n.datatype;
        this.iface = n.iface || null;
        this.multicast = n.multicast;
        this.ipv = n.ipv || "udp4";
        var node = this;

        if (node.iface && node.iface.indexOf(".") === -1) {
            try {
                if ((os.networkInterfaces())[node.iface][0].hasOwnProperty("scopeid")) {
                    if (node.ipv === "udp4") {
                        node.iface = (os.networkInterfaces())[node.iface][1].address;
                    } else {
                        node.iface = (os.networkInterfaces())[node.iface][0].address;
                    }
                }
                else {
                    if (node.ipv === "udp4") {
                        node.iface = (os.networkInterfaces())[node.iface][0].address;
                    } else {
                        node.iface = (os.networkInterfaces())[node.iface][1].address;
                    }
                }
            }
            catch(e) {
                node.warn(RED._("udp.errors.ifnotfound",{iface:node.iface}));
                node.iface = null;
            }
        }

        var opts = {type:node.ipv, reuseAddr:true};
        if (process.version.indexOf("v0.10") === 0) { opts = node.ipv; }
        var server;

        if (!udpInputPortsInUse.hasOwnProperty(node.port)) {
            server = dgram.createSocket(opts);  // default to udp4
            server.bind(node.port, function() {
                if (node.multicast == "true") {
                    server.setBroadcast(true);
                    server.setMulticastLoopback(false);
                    try {
                        server.setMulticastTTL(128);
                        server.addMembership(node.group,node.iface);
                        if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
                        node.log(RED._("udp.status.mc-group",{group:node.group}));
                    } catch (e) {
                        if (e.errno == "EINVAL") {
                            node.error(RED._("udp.errors.bad-mcaddress"));
                        } else if (e.errno == "ENODEV") {
                            node.error(RED._("udp.errors.interface"));
                        } else {
                            node.error(RED._("udp.errors.error",{error:e.errno}));
                        }
                    }
                }
            });
            udpInputPortsInUse[node.port] = server;
        }
        else {
            node.log(RED._("udp.errors.alreadyused",{port:node.port}));
            server = udpInputPortsInUse[node.port];  // re-use existing
            if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
        }

        server.on("error", function (err) {
            if ((err.code == "EACCES") && (node.port < 1024)) {
                node.error(RED._("udp.errors.access-error"));
            } else {
                node.error(RED._("udp.errors.error",{error:err.code}));
            }
            server.close();
        });

        server.on('message', function (message, remote) {
            var msg;
            if (node.datatype =="base64") {
                msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
            } else if (node.datatype =="utf8") {
                msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
            } else {
                msg = { payload:message, fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
            }
            node.send(msg);
        });

        server.on('listening', function () {
            var address = server.address();
            node.log(RED._("udp.status.listener-at",{host:node.iface||address.address,port:address.port}));

        });

        node.on("close", function() {
            try {
                if (node.multicast == "true") { server.dropMembership(node.group); }
                server.close();
                node.log(RED._("udp.status.listener-stopped"));
            } catch (err) {
                //node.error(err);
            }
            if (udpInputPortsInUse.hasOwnProperty(node.port)) {
                delete udpInputPortsInUse[node.port];
            }
            node.status({});
        });

    }
    RED.httpAdmin.get('/udp-ports/:id', RED.auth.needsPermission('udp-ports.read'), function(req,res) {
        res.json(Object.keys(udpInputPortsInUse));
    });
    RED.nodes.registerType("udp in",UDPin);

    // The Output Node
    function UDPout(n) {
        RED.nodes.createNode(this,n);
        //this.group = n.group;
        this.port = n.port;
        this.outport = n.outport||"";
        this.base64 = n.base64;
        this.addr = n.addr;
        this.iface = n.iface || null;
        this.multicast = n.multicast;
        this.ipv = n.ipv || "udp4";
        var node = this;

        if (node.iface && node.iface.indexOf(".") === -1) {
            try {
                if ((os.networkInterfaces())[node.iface][0].hasOwnProperty("scopeid")) {
                    if (node.ipv === "udp4") {
                        node.iface = (os.networkInterfaces())[node.iface][1].address;
                    } else {
                        node.iface = (os.networkInterfaces())[node.iface][0].address;
                    }
                }
                else {
                    if (node.ipv === "udp4") {
                        node.iface = (os.networkInterfaces())[node.iface][0].address;
                    } else {
                        node.iface = (os.networkInterfaces())[node.iface][1].address;
                    }
                }
            }
            catch(e) {
                node.warn(RED._("udp.errors.ifnotfound",{iface:node.iface}));
                node.iface = null;
            }
        }

        var opts = {type:node.ipv, reuseAddr:true};

        var sock;
        var p = this.outport || this.port || "0";
        node.tout = setTimeout(function() {
            if (udpInputPortsInUse[p]) {
                sock = udpInputPortsInUse[p];
                node.log(RED._("udp.status.re-use",{outport:node.outport,host:node.addr,port:node.port}));
                if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
            }
            else {
                sock = dgram.createSocket(opts);  // default to udp4
                if (node.multicast != "false") {
                    sock.bind(node.outport, function() {    // have to bind before you can enable broadcast...
                        sock.setBroadcast(true);            // turn on broadcast
                        sock.setMulticastLoopback(false);   // turn off loopback
                        if (node.multicast == "multi") {
                            try {
                                sock.setMulticastTTL(128);
                                sock.addMembership(node.addr,node.iface);   // Add to the multicast group
                                if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
                                node.log(RED._("udp.status.mc-ready",{iface:node.iface,outport:node.outport,host:node.addr,port:node.port}));
                            } catch (e) {
                                if (e.errno == "EINVAL") {
                                    node.error(RED._("udp.errors.bad-mcaddress"));
                                } else if (e.errno == "ENODEV") {
                                    node.error(RED._("udp.errors.interface"));
                                } else {
                                    node.error(RED._("udp.errors.error",{error:e.errno}));
                                }
                            }
                        } else {
                            node.log(RED._("udp.status.bc-ready",{outport:node.outport,host:node.addr,port:node.port}));
                        }
                    });
                } else if ((node.outport !== "") && (!udpInputPortsInUse[node.outport])) {
                    sock.bind(node.outport);
                    node.log(RED._("udp.status.ready",{outport:node.outport,host:node.addr,port:node.port}));
                } else {
                    node.log(RED._("udp.status.ready-nolocal",{host:node.addr,port:node.port}));
                }
                sock.on("error", function(err) {
                    // Any async error will also get reported in the sock.send call.
                    // This handler is needed to ensure the error marked as handled to
                    // prevent it going to the global error handler and shutting node-red
                    // down.
                });
                udpInputPortsInUse[p] = sock;
            }
        }

            node.on("input", function(msg) {
                if (msg.hasOwnProperty("payload")) {
                    var add = node.addr || msg.ip || "";
                    var por = node.port || msg.port || 0;
                    if (add === "") {
                        node.warn(RED._("udp.errors.ip-notset"));
                    } else if (por === 0) {
                        node.warn(RED._("udp.errors.port-notset"));
                    } else if (isNaN(por) || (por < 1) || (por > 65535)) {
                        node.warn(RED._("udp.errors.port-invalid"));
                    } else {
                        var message;
                        if (node.base64) {
                            message = Buffer.from(msg.payload, 'base64');
                        } else if (msg.payload instanceof Buffer) {
                            message = msg.payload;
                        } else {
                            message = Buffer.from(""+msg.payload);
                        }
                        sock.send(message, 0, message.length, por, add, function(err, bytes) {
                            if (err) {
                                node.error("udp : "+err,msg);
                            }
                            message = null;
                        });
                    }
                }
            });
        }, 150);

        node.on("close", function() {
            if (node.tout) { clearTimeout(node.tout); }
            try {
                if (node.multicast == "multi") { sock.dropMembership(node.group); }
                sock.close();
                node.log(RED._("udp.status.output-stopped"));
            } catch (err) {
                //node.error(err);
            }
            if (udpInputPortsInUse.hasOwnProperty(p)) {
                delete udpInputPortsInUse[p];
            }
            node.status({});
        });
    }
    RED.nodes.registerType("udp out",UDPout);
}
<commit_msg>remove extraneous brace from udp node<commit_after>/**
 * Copyright JS Foundation and other contributors, http://js.foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

module.exports = function(RED) {
    "use strict";
    var os = require('os');
    var dgram = require('dgram');
    var udpInputPortsInUse = {};

    // The Input Node
    function UDPin(n) {
        RED.nodes.createNode(this,n);
        this.group = n.group;
        this.port = n.port;
        this.datatype = n.datatype;
        this.iface = n.iface || null;
        this.multicast = n.multicast;
        this.ipv = n.ipv || "udp4";
        var node = this;

        if (node.iface && node.iface.indexOf(".") === -1) {
            try {
                if ((os.networkInterfaces())[node.iface][0].hasOwnProperty("scopeid")) {
                    if (node.ipv === "udp4") {
                        node.iface = (os.networkInterfaces())[node.iface][1].address;
                    } else {
                        node.iface = (os.networkInterfaces())[node.iface][0].address;
                    }
                }
                else {
                    if (node.ipv === "udp4") {
                        node.iface = (os.networkInterfaces())[node.iface][0].address;
                    } else {
                        node.iface = (os.networkInterfaces())[node.iface][1].address;
                    }
                }
            }
            catch(e) {
                node.warn(RED._("udp.errors.ifnotfound",{iface:node.iface}));
                node.iface = null;
            }
        }

        var opts = {type:node.ipv, reuseAddr:true};
        if (process.version.indexOf("v0.10") === 0) { opts = node.ipv; }
        var server;

        if (!udpInputPortsInUse.hasOwnProperty(node.port)) {
            server = dgram.createSocket(opts);  // default to udp4
            server.bind(node.port, function() {
                if (node.multicast == "true") {
                    server.setBroadcast(true);
                    server.setMulticastLoopback(false);
                    try {
                        server.setMulticastTTL(128);
                        server.addMembership(node.group,node.iface);
                        if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
                        node.log(RED._("udp.status.mc-group",{group:node.group}));
                    } catch (e) {
                        if (e.errno == "EINVAL") {
                            node.error(RED._("udp.errors.bad-mcaddress"));
                        } else if (e.errno == "ENODEV") {
                            node.error(RED._("udp.errors.interface"));
                        } else {
                            node.error(RED._("udp.errors.error",{error:e.errno}));
                        }
                    }
                }
            });
            udpInputPortsInUse[node.port] = server;
        }
        else {
            node.log(RED._("udp.errors.alreadyused",{port:node.port}));
            server = udpInputPortsInUse[node.port];  // re-use existing
            if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
        }

        server.on("error", function (err) {
            if ((err.code == "EACCES") && (node.port < 1024)) {
                node.error(RED._("udp.errors.access-error"));
            } else {
                node.error(RED._("udp.errors.error",{error:err.code}));
            }
            server.close();
        });

        server.on('message', function (message, remote) {
            var msg;
            if (node.datatype =="base64") {
                msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
            } else if (node.datatype =="utf8") {
                msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
            } else {
                msg = { payload:message, fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
            }
            node.send(msg);
        });

        server.on('listening', function () {
            var address = server.address();
            node.log(RED._("udp.status.listener-at",{host:node.iface||address.address,port:address.port}));

        });

        node.on("close", function() {
            try {
                if (node.multicast == "true") { server.dropMembership(node.group); }
                server.close();
                node.log(RED._("udp.status.listener-stopped"));
            } catch (err) {
                //node.error(err);
            }
            if (udpInputPortsInUse.hasOwnProperty(node.port)) {
                delete udpInputPortsInUse[node.port];
            }
            node.status({});
        });

    }
    RED.httpAdmin.get('/udp-ports/:id', RED.auth.needsPermission('udp-ports.read'), function(req,res) {
        res.json(Object.keys(udpInputPortsInUse));
    });
    RED.nodes.registerType("udp in",UDPin);

    // The Output Node
    function UDPout(n) {
        RED.nodes.createNode(this,n);
        //this.group = n.group;
        this.port = n.port;
        this.outport = n.outport||"";
        this.base64 = n.base64;
        this.addr = n.addr;
        this.iface = n.iface || null;
        this.multicast = n.multicast;
        this.ipv = n.ipv || "udp4";
        var node = this;

        if (node.iface && node.iface.indexOf(".") === -1) {
            try {
                if ((os.networkInterfaces())[node.iface][0].hasOwnProperty("scopeid")) {
                    if (node.ipv === "udp4") {
                        node.iface = (os.networkInterfaces())[node.iface][1].address;
                    } else {
                        node.iface = (os.networkInterfaces())[node.iface][0].address;
                    }
                }
                else {
                    if (node.ipv === "udp4") {
                        node.iface = (os.networkInterfaces())[node.iface][0].address;
                    } else {
                        node.iface = (os.networkInterfaces())[node.iface][1].address;
                    }
                }
            }
            catch(e) {
                node.warn(RED._("udp.errors.ifnotfound",{iface:node.iface}));
                node.iface = null;
            }
        }

        var opts = {type:node.ipv, reuseAddr:true};

        var sock;
        var p = this.outport || this.port || "0";
        node.tout = setTimeout(function() {
            if (udpInputPortsInUse[p]) {
                sock = udpInputPortsInUse[p];
                node.log(RED._("udp.status.re-use",{outport:node.outport,host:node.addr,port:node.port}));
                if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
            }
            else {
                sock = dgram.createSocket(opts);  // default to udp4
                if (node.multicast != "false") {
                    sock.bind(node.outport, function() {    // have to bind before you can enable broadcast...
                        sock.setBroadcast(true);            // turn on broadcast
                        sock.setMulticastLoopback(false);   // turn off loopback
                        if (node.multicast == "multi") {
                            try {
                                sock.setMulticastTTL(128);
                                sock.addMembership(node.addr,node.iface);   // Add to the multicast group
                                if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
                                node.log(RED._("udp.status.mc-ready",{iface:node.iface,outport:node.outport,host:node.addr,port:node.port}));
                            } catch (e) {
                                if (e.errno == "EINVAL") {
                                    node.error(RED._("udp.errors.bad-mcaddress"));
                                } else if (e.errno == "ENODEV") {
                                    node.error(RED._("udp.errors.interface"));
                                } else {
                                    node.error(RED._("udp.errors.error",{error:e.errno}));
                                }
                            }
                        } else {
                            node.log(RED._("udp.status.bc-ready",{outport:node.outport,host:node.addr,port:node.port}));
                        }
                    });
                } else if ((node.outport !== "") && (!udpInputPortsInUse[node.outport])) {
                    sock.bind(node.outport);
                    node.log(RED._("udp.status.ready",{outport:node.outport,host:node.addr,port:node.port}));
                } else {
                    node.log(RED._("udp.status.ready-nolocal",{host:node.addr,port:node.port}));
                }
                sock.on("error", function(err) {
                    // Any async error will also get reported in the sock.send call.
                    // This handler is needed to ensure the error marked as handled to
                    // prevent it going to the global error handler and shutting node-red
                    // down.
                });
                udpInputPortsInUse[p] = sock;
            }

            node.on("input", function(msg) {
                if (msg.hasOwnProperty("payload")) {
                    var add = node.addr || msg.ip || "";
                    var por = node.port || msg.port || 0;
                    if (add === "") {
                        node.warn(RED._("udp.errors.ip-notset"));
                    } else if (por === 0) {
                        node.warn(RED._("udp.errors.port-notset"));
                    } else if (isNaN(por) || (por < 1) || (por > 65535)) {
                        node.warn(RED._("udp.errors.port-invalid"));
                    } else {
                        var message;
                        if (node.base64) {
                            message = Buffer.from(msg.payload, 'base64');
                        } else if (msg.payload instanceof Buffer) {
                            message = msg.payload;
                        } else {
                            message = Buffer.from(""+msg.payload);
                        }
                        sock.send(message, 0, message.length, por, add, function(err, bytes) {
                            if (err) {
                                node.error("udp : "+err,msg);
                            }
                            message = null;
                        });
                    }
                }
            });
        }, 150);

        node.on("close", function() {
            if (node.tout) { clearTimeout(node.tout); }
            try {
                if (node.multicast == "multi") { sock.dropMembership(node.group); }
                sock.close();
                node.log(RED._("udp.status.output-stopped"));
            } catch (err) {
                //node.error(err);
            }
            if (udpInputPortsInUse.hasOwnProperty(p)) {
                delete udpInputPortsInUse[p];
            }
            node.status({});
        });
    }
    RED.nodes.registerType("udp out",UDPout);
}
<|endoftext|>


<commit_before>const hbs = require('express-hbs');
const _ = require('lodash');
const debug = require('@tryghost/debug')('error-handler');
const errors = require('@tryghost/errors');
const tpl = require('@tryghost/tpl');
const config = require('../../../../shared/config');
const helpers = require('../../../../frontend/services/routing/helpers');
const sentry = require('../../../../shared/sentry');

const messages = {
    oopsErrorTemplateHasError: 'Oops, seems there is an error in the error template.',
    encounteredError: 'Encountered the error: ',
    whilstTryingToRender: 'whilst trying to render an error page for the error: ',
    pageNotFound: 'Page not found',
    resourceNotFound: 'Resource not found',
    actions: {
        images: {
            upload: 'upload image'
        }
    },
    userMessages: {
        BookshelfRelationsError: 'Database error, cannot {action}.',
        InternalServerError: 'Internal server error, cannot {action}.',
        IncorrectUsageError: 'Incorrect usage error, cannot {action}.',
        NotFoundError: 'Resource not found error, cannot {action}.',
        BadRequestError: 'Request not understood error, cannot {action}.',
        UnauthorizedError: 'Authorisation error, cannot {action}.',
        NoPermissionError: 'Permission error, cannot {action}.',
        ValidationError: 'Validation error, cannot {action}.',
        UnsupportedMediaTypeError: 'Unsupported media error, cannot {action}.',
        TooManyRequestsError: 'Too many requests error, cannot {action}.',
        MaintenanceError: 'Server down for maintenance, cannot {action}.',
        MethodNotAllowedError: 'Method not allowed, cannot {action}.',
        RequestEntityTooLargeError: 'Request too large, cannot {action}.',
        TokenRevocationError: 'Token is not available, cannot {action}.',
        VersionMismatchError: 'Version mismatch error, cannot {action}.',
        DataExportError: 'Error exporting content.',
        DataImportError: 'Duplicated entry, cannot save {action}.',
        DatabaseVersionError: 'Database version compatibility error, cannot {action}.',
        EmailError: 'Error sending email!',
        ThemeValidationError: 'Theme validation error, cannot {action}.',
        HostLimitError: 'Host Limit error, cannot {action}.',
        DisabledFeatureError: 'Theme validation error, the {{{helperName}}} helper is not available. Cannot {action}.',
        UpdateCollisionError: 'Saving failed! Someone else is editing this post.'
    }
};

const escapeExpression = hbs.Utils.escapeExpression;
const _private = {};
const errorHandler = {};

/**
 * This is a bare minimum setup, which allows us to render the error page
 * It uses the {{asset}} helper, and nothing more
 */
_private.createHbsEngine = () => {
    const engine = hbs.create();
    engine.registerHelper('asset', require('../../../../frontend/helpers/asset'));

    return engine.express4();
};

/**
 * Get an error ready to be shown the the user
 *
 * @TODO: support multiple errors within one single error, see https://github.com/TryGhost/Ghost/issues/7116#issuecomment-252231809
 */
_private.prepareError = (err, req, res, next) => {
    debug(err);

    if (Array.isArray(err)) {
        err = err[0];
    }

    if (!errors.utils.isIgnitionError(err)) {
        // We need a special case for 404 errors
        // @TODO look at adding this to the GhostError class
        if (err.statusCode && err.statusCode === 404) {
            err = new errors.NotFoundError({
                err: err
            });
        } else if (err.stack.match(/node_modules\/handlebars\//)) {
            // Temporary handling of theme errors from handlebars
            // @TODO remove this when #10496 is solved properly
            err = new errors.IncorrectUsageError({
                err: err,
                message: err.message,
                statusCode: err.statusCode
            });
        } else {
            err = new errors.GhostError({
                err: err,
                message: err.message,
                statusCode: err.statusCode
            });
        }
    }

    // used for express logging middleware see core/server/app.js
    req.err = err;

    // alternative for res.status();
    res.statusCode = err.statusCode;

    // never cache errors
    res.set({
        'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
    });

    next(err);
};

_private.JSONErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
    res.json({
        errors: [{
            message: err.message,
            context: err.context,
            help: err.help,
            errorType: err.errorType,
            errorDetails: err.errorDetails,
            ghostErrorCode: err.ghostErrorCode
        }]
    });
};

_private.prepareUserMessage = (err, res) => {
    const userError = {
        message: err.message,
        context: err.context
    };

    const docName = _.get(res, 'frameOptions.docName');
    const method = _.get(res, 'frameOptions.method');

    if (docName && method) {
        let action;

        const actionMap = {
            browse: 'list',
            read: 'read',
            add: 'save',
            edit: 'edit',
            destroy: 'delete'
        };

        if (_.get(messages.actions, [docName, method])) {
            action = tpl(messages.actions[docName][method]);
        } else if (Object.keys(actionMap).includes(method)) {
            let resource = docName;

            if (method !== 'browse') {
                resource = resource.replace(/s$/, '');
            }

            action = `${actionMap[method]} ${resource}`;
        }

        if (action) {
            if (err.context) {
                userError.context = `${err.message} ${err.context}`;
            } else {
                userError.context = err.message;
            }

            userError.message = tpl(messages.userMessages[err.name], {action: action});
        }
    }

    return userError;
};

_private.JSONErrorRendererV2 = (err, req, res, next) => { // eslint-disable-line no-unused-vars
    const userError = _private.prepareUserMessage(err, req);

    res.json({
        errors: [{
            message: userError.message || null,
            context: userError.context || null,
            type: err.errorType || null,
            details: err.errorDetails || null,
            property: err.property || null,
            help: err.help || null,
            code: err.code || null,
            id: err.id || null
        }]
    });
};

_private.ErrorFallbackMessage = err => `
${tpl(messages.oopsErrorTemplateHasError)}

${tpl(messages.encounteredError)}

${escapeExpression(err.message || err)}

${tpl(messages.whilstTryingToRender)}

     ${err.statusCode}
${escapeExpression(err.message || err)}
`;

_private.ThemeErrorRenderer = (err, req, res, next) => {
    // If the error code is explicitly set to STATIC_FILE_NOT_FOUND,
    // Skip trying to render an HTML error, and move on to the basic error renderer
    // We do this because customised 404 templates could reference the image that's missing
    // A better long term solution might be to do this based on extension
    if (err.code === 'STATIC_FILE_NOT_FOUND') {
        return next(err);
    }

    // Renderer begin
    // Format Data
    const data = {
        message: err.message,
        // @deprecated Remove in Ghost 5.0
        code: err.statusCode,
        statusCode: err.statusCode,
        errorDetails: err.errorDetails || []
    };

    // Template
    // @TODO: very dirty !!!!!!
    helpers.templates.setTemplate(req, res);

    // It can be that something went wrong with the theme or otherwise loading handlebars
    // This ensures that no matter what res.render will work here
    // @TODO: split the error handler for assets, admin & theme to refactor this away
    if (_.isEmpty(req.app.engines)) {
        res._template = 'error';
        req.app.engine('hbs', _private.createHbsEngine());
        req.app.set('view engine', 'hbs');
        req.app.set('views', config.get('paths').defaultViews);
    }

    // @TODO use renderer here?!
    // Render Call - featuring an error handler for what happens if rendering fails
    res.render(res._template, data, (_err, html) => {
        if (!_err) {
            return res.send(html);
        }

        // re-attach new error e.g. error template has syntax error or misusage
        req.err = _err;

        // And then try to explain things to the user...
        // Cheat and output the error using handlebars escapeExpression
        return res.status(500).send(_private.ErrorFallbackMessage(_err));
    });
};

_private.HTMLErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
    const data = {
        message: err.message,
        statusCode: err.statusCode,
        errorDetails: err.errorDetails || []
    };

    // e.g. if you serve the admin /ghost and Ghost returns a 503 because it generates the urls at the moment.
    // This ensures that no matter what res.render will work here
    // @TODO: put to prepare error function?
    if (_.isEmpty(req.app.engines)) {
        res._template = 'error';
        req.app.engine('hbs', _private.createHbsEngine());
        req.app.set('view engine', 'hbs');
        req.app.set('views', config.get('paths').defaultViews);
    }

    res.render('error', data, (_err, html) => {
        if (!_err) {
            return res.send(html);
        }

        // re-attach new error e.g. error template has syntax error or misusage
        req.err = _err;

        // And then try to explain things to the user...
        // Cheat and output the error using handlebars escapeExpression
        return res.status(500).send(_private.ErrorFallbackMessage(_err));
    });
};

_private.BasicErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
    return res.send(res.statusCode + ' ' + err.message);
};

errorHandler.resourceNotFound = (req, res, next) => {
    // TODO, handle unknown resources & methods differently, so that we can also produce
    // 405 Method Not Allowed
    next(new errors.NotFoundError({message: tpl(messages.resourceNotFound)}));
};

errorHandler.pageNotFound = (req, res, next) => {
    next(new errors.NotFoundError({message: tpl(messages.pageNotFound)}));
};

errorHandler.handleJSONResponse = [
    // Make sure the error can be served
    _private.prepareError,
    // Handle the error in Sentry
    sentry.errorHandler,
    // Render the error using JSON format
    _private.JSONErrorRenderer
];

errorHandler.handleJSONResponseV2 = [
    // Make sure the error can be served
    _private.prepareError,
    // Handle the error in Sentry
    sentry.errorHandler,
    // Render the error using JSON format
    _private.JSONErrorRendererV2
];

errorHandler.handleHTMLResponse = [
    // Make sure the error can be served
    _private.prepareError,
    // Handle the error in Sentry
    sentry.errorHandler,
    // Render the error using HTML format
    _private.HTMLErrorRenderer,
    // Fall back to basic if HTML is not explicitly accepted
    _private.BasicErrorRenderer
];

errorHandler.handleThemeResponse = [
    // Make sure the error can be served
    _private.prepareError,
    // Handle the error in Sentry
    sentry.errorHandler,
    // Render the error using theme template
    _private.ThemeErrorRenderer,
    // Fall back to basic if HTML is not explicitly accepted
    _private.BasicErrorRenderer
];

module.exports = errorHandler;
<commit_msg>Moved JSON error handlers next to each other<commit_after>const hbs = require('express-hbs');
const _ = require('lodash');
const debug = require('@tryghost/debug')('error-handler');
const errors = require('@tryghost/errors');
const tpl = require('@tryghost/tpl');
const config = require('../../../../shared/config');
const helpers = require('../../../../frontend/services/routing/helpers');
const sentry = require('../../../../shared/sentry');

const messages = {
    oopsErrorTemplateHasError: 'Oops, seems there is an error in the error template.',
    encounteredError: 'Encountered the error: ',
    whilstTryingToRender: 'whilst trying to render an error page for the error: ',
    pageNotFound: 'Page not found',
    resourceNotFound: 'Resource not found',
    actions: {
        images: {
            upload: 'upload image'
        }
    },
    userMessages: {
        BookshelfRelationsError: 'Database error, cannot {action}.',
        InternalServerError: 'Internal server error, cannot {action}.',
        IncorrectUsageError: 'Incorrect usage error, cannot {action}.',
        NotFoundError: 'Resource not found error, cannot {action}.',
        BadRequestError: 'Request not understood error, cannot {action}.',
        UnauthorizedError: 'Authorisation error, cannot {action}.',
        NoPermissionError: 'Permission error, cannot {action}.',
        ValidationError: 'Validation error, cannot {action}.',
        UnsupportedMediaTypeError: 'Unsupported media error, cannot {action}.',
        TooManyRequestsError: 'Too many requests error, cannot {action}.',
        MaintenanceError: 'Server down for maintenance, cannot {action}.',
        MethodNotAllowedError: 'Method not allowed, cannot {action}.',
        RequestEntityTooLargeError: 'Request too large, cannot {action}.',
        TokenRevocationError: 'Token is not available, cannot {action}.',
        VersionMismatchError: 'Version mismatch error, cannot {action}.',
        DataExportError: 'Error exporting content.',
        DataImportError: 'Duplicated entry, cannot save {action}.',
        DatabaseVersionError: 'Database version compatibility error, cannot {action}.',
        EmailError: 'Error sending email!',
        ThemeValidationError: 'Theme validation error, cannot {action}.',
        HostLimitError: 'Host Limit error, cannot {action}.',
        DisabledFeatureError: 'Theme validation error, the {{{helperName}}} helper is not available. Cannot {action}.',
        UpdateCollisionError: 'Saving failed! Someone else is editing this post.'
    }
};

const escapeExpression = hbs.Utils.escapeExpression;
const _private = {};
const errorHandler = {};

/**
 * This is a bare minimum setup, which allows us to render the error page
 * It uses the {{asset}} helper, and nothing more
 */
_private.createHbsEngine = () => {
    const engine = hbs.create();
    engine.registerHelper('asset', require('../../../../frontend/helpers/asset'));

    return engine.express4();
};

/**
 * Get an error ready to be shown the the user
 *
 * @TODO: support multiple errors within one single error, see https://github.com/TryGhost/Ghost/issues/7116#issuecomment-252231809
 */
_private.prepareError = (err, req, res, next) => {
    debug(err);

    if (Array.isArray(err)) {
        err = err[0];
    }

    if (!errors.utils.isIgnitionError(err)) {
        // We need a special case for 404 errors
        // @TODO look at adding this to the GhostError class
        if (err.statusCode && err.statusCode === 404) {
            err = new errors.NotFoundError({
                err: err
            });
        } else if (err.stack.match(/node_modules\/handlebars\//)) {
            // Temporary handling of theme errors from handlebars
            // @TODO remove this when #10496 is solved properly
            err = new errors.IncorrectUsageError({
                err: err,
                message: err.message,
                statusCode: err.statusCode
            });
        } else {
            err = new errors.GhostError({
                err: err,
                message: err.message,
                statusCode: err.statusCode
            });
        }
    }

    // used for express logging middleware see core/server/app.js
    req.err = err;

    // alternative for res.status();
    res.statusCode = err.statusCode;

    // never cache errors
    res.set({
        'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
    });

    next(err);
};

_private.JSONErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
    res.json({
        errors: [{
            message: err.message,
            context: err.context,
            help: err.help,
            errorType: err.errorType,
            errorDetails: err.errorDetails,
            ghostErrorCode: err.ghostErrorCode
        }]
    });
};

_private.JSONErrorRendererV2 = (err, req, res, next) => { // eslint-disable-line no-unused-vars
    const userError = _private.prepareUserMessage(err, req);

    res.json({
        errors: [{
            message: userError.message || null,
            context: userError.context || null,
            type: err.errorType || null,
            details: err.errorDetails || null,
            property: err.property || null,
            help: err.help || null,
            code: err.code || null,
            id: err.id || null
        }]
    });
};

_private.prepareUserMessage = (err, res) => {
    const userError = {
        message: err.message,
        context: err.context
    };

    const docName = _.get(res, 'frameOptions.docName');
    const method = _.get(res, 'frameOptions.method');

    if (docName && method) {
        let action;

        const actionMap = {
            browse: 'list',
            read: 'read',
            add: 'save',
            edit: 'edit',
            destroy: 'delete'
        };

        if (_.get(messages.actions, [docName, method])) {
            action = tpl(messages.actions[docName][method]);
        } else if (Object.keys(actionMap).includes(method)) {
            let resource = docName;

            if (method !== 'browse') {
                resource = resource.replace(/s$/, '');
            }

            action = `${actionMap[method]} ${resource}`;
        }

        if (action) {
            if (err.context) {
                userError.context = `${err.message} ${err.context}`;
            } else {
                userError.context = err.message;
            }

            userError.message = tpl(messages.userMessages[err.name], {action: action});
        }
    }

    return userError;
};

_private.ErrorFallbackMessage = err => `
${tpl(messages.oopsErrorTemplateHasError)}

${tpl(messages.encounteredError)}

${escapeExpression(err.message || err)}

${tpl(messages.whilstTryingToRender)}

     ${err.statusCode}
${escapeExpression(err.message || err)}
`;

_private.ThemeErrorRenderer = (err, req, res, next) => {
    // If the error code is explicitly set to STATIC_FILE_NOT_FOUND,
    // Skip trying to render an HTML error, and move on to the basic error renderer
    // We do this because customised 404 templates could reference the image that's missing
    // A better long term solution might be to do this based on extension
    if (err.code === 'STATIC_FILE_NOT_FOUND') {
        return next(err);
    }

    // Renderer begin
    // Format Data
    const data = {
        message: err.message,
        // @deprecated Remove in Ghost 5.0
        code: err.statusCode,
        statusCode: err.statusCode,
        errorDetails: err.errorDetails || []
    };

    // Template
    // @TODO: very dirty !!!!!!
    helpers.templates.setTemplate(req, res);

    // It can be that something went wrong with the theme or otherwise loading handlebars
    // This ensures that no matter what res.render will work here
    // @TODO: split the error handler for assets, admin & theme to refactor this away
    if (_.isEmpty(req.app.engines)) {
        res._template = 'error';
        req.app.engine('hbs', _private.createHbsEngine());
        req.app.set('view engine', 'hbs');
        req.app.set('views', config.get('paths').defaultViews);
    }

    // @TODO use renderer here?!
    // Render Call - featuring an error handler for what happens if rendering fails
    res.render(res._template, data, (_err, html) => {
        if (!_err) {
            return res.send(html);
        }

        // re-attach new error e.g. error template has syntax error or misusage
        req.err = _err;

        // And then try to explain things to the user...
        // Cheat and output the error using handlebars escapeExpression
        return res.status(500).send(_private.ErrorFallbackMessage(_err));
    });
};

_private.HTMLErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
    const data = {
        message: err.message,
        statusCode: err.statusCode,
        errorDetails: err.errorDetails || []
    };

    // e.g. if you serve the admin /ghost and Ghost returns a 503 because it generates the urls at the moment.
    // This ensures that no matter what res.render will work here
    // @TODO: put to prepare error function?
    if (_.isEmpty(req.app.engines)) {
        res._template = 'error';
        req.app.engine('hbs', _private.createHbsEngine());
        req.app.set('view engine', 'hbs');
        req.app.set('views', config.get('paths').defaultViews);
    }

    res.render('error', data, (_err, html) => {
        if (!_err) {
            return res.send(html);
        }

        // re-attach new error e.g. error template has syntax error or misusage
        req.err = _err;

        // And then try to explain things to the user...
        // Cheat and output the error using handlebars escapeExpression
        return res.status(500).send(_private.ErrorFallbackMessage(_err));
    });
};

_private.BasicErrorRenderer = (err, req, res, next) => { // eslint-disable-line no-unused-vars
    return res.send(res.statusCode + ' ' + err.message);
};

errorHandler.resourceNotFound = (req, res, next) => {
    // TODO, handle unknown resources & methods differently, so that we can also produce
    // 405 Method Not Allowed
    next(new errors.NotFoundError({message: tpl(messages.resourceNotFound)}));
};

errorHandler.pageNotFound = (req, res, next) => {
    next(new errors.NotFoundError({message: tpl(messages.pageNotFound)}));
};

errorHandler.handleJSONResponse = [
    // Make sure the error can be served
    _private.prepareError,
    // Handle the error in Sentry
    sentry.errorHandler,
    // Render the error using JSON format
    _private.JSONErrorRenderer
];

errorHandler.handleJSONResponseV2 = [
    // Make sure the error can be served
    _private.prepareError,
    // Handle the error in Sentry
    sentry.errorHandler,
    // Render the error using JSON format
    _private.JSONErrorRendererV2
];

errorHandler.handleHTMLResponse = [
    // Make sure the error can be served
    _private.prepareError,
    // Handle the error in Sentry
    sentry.errorHandler,
    // Render the error using HTML format
    _private.HTMLErrorRenderer,
    // Fall back to basic if HTML is not explicitly accepted
    _private.BasicErrorRenderer
];

errorHandler.handleThemeResponse = [
    // Make sure the error can be served
    _private.prepareError,
    // Handle the error in Sentry
    sentry.errorHandler,
    // Render the error using theme template
    _private.ThemeErrorRenderer,
    // Fall back to basic if HTML is not explicitly accepted
    _private.BasicErrorRenderer
];

module.exports = errorHandler;
<|endoftext|>


<commit_before>(function () { // to wrap use strict
	'use strict';

	var BloomLibraryApp = angular.module('BloomLibraryApp',
				['templates-app', 'templates-common', // Required for ng-boilerplate, to use templates from templates-app.js instead of copying individual files.
				'BloomLibraryApp.browse', 'BloomLibraryApp.detail', "BloomLibraryApp.login", "BloomLibraryApp.signup", "BloomLibraryApp.services", "BloomLibraryApp.datagrid",
					"BloomLibraryApp.ccdialog", "BloomLibraryApp.download", "BloomLibraryApp.staticPages",
					"BloomLibraryApp.deleteDialog", "BloomLibraryApp.inProgress", "BloomLibraryApp.pleaseLogIn", "BloomLibraryApp.mustAgree",
				"ui.bootstrap", 'ui.router', 'palaso.ui.listview', 'restangular', 'ngCookies'])

  .config(['$urlRouterProvider', '$stateProvider',
           function ($urlRouterProvider, $stateProvider) {

			//TODO when we have hosting that can do the url rewriting this requires
			//$locationProvider.html5Mode(true);
			//$locationProvider.hashPrefix('!');

			// For any unmatched url, redirect to /state1
			$urlRouterProvider.otherwise("/browse");

           } ])

.controller('HeaderCtrl', ['$scope', 'authService', '$location', '$state', 'silNoticeService', function ($scope, authService, $location, $state, silNoticeService) {
	$scope.location = $location.path();
	$scope.isLoggedIn = authService.isLoggedIn;

	$scope.logout = function () {
		authService.logout();
		silNoticeService.clear();
		$state.go('browse');
	};

	$scope.userName = authService.userName;
} ])
        .controller('FooterCtrl', ['$scope', function($scope) {
            $scope.year = new Date().getFullYear().toString();
        }])
		.controller('LeftSidebar', ['$scope', '$dialog', '$state', '$location', '$rootScope', 'bookService', 'authService',
            function ($scope, $dialog, $state, $location, $rootScope, bookService, authService) {
            $scope.currentLang = $location.$$search.lang;
            $scope.currentTag = $location.$$search.tag;
            $scope.currentShelf = $location.$$search.shelf;
            $scope.wantLeftBar = $location.$$path.substring(1, 7) == 'browse';
            $rootScope.$on('$locationChangeSuccess', function() {
                $scope.currentLang = $location.$$search.lang;
                $scope.currentTag = $location.$$search.tag;
                $scope.currentShelf = $location.$$search.shelf;
                $scope.wantLeftBar = $location.$$path.substring(1, 7) == 'browse';
            });
			$scope.showInProgress = function() {
				$dialog.dialog(
					{
						backdrop: true,
						keyboard: true, //make ESC close it
						backdropClick: true, //make clicking on the backdrop close it
						templateUrl: 'modules/inProgress/inProgress.tpl.html',
						controller: 'inProgress',
						dialogClass: 'modal ccmodal'
					}).open();
			};
            $scope.filterLanguage = function(language) {
                $state.go('browse', {lang:language}); // keep other params unchanged.
            };
            $scope.filterTag = function(tagName) {
                $state.go('browse', {tag:tagName}); // keep other params unchanged.
            };
            $scope.filterShelf = function(shelfName) {
                $state.go('browse', {search: '', shelf:shelfName}); // keep other params unchanged.
            };
            $scope.filterMyUploads = function() {
                if (authService.isLoggedIn()) {
                    $state.go('browse', {search: '', shelf: '$myUploads'}); // keep other params unchanged.
                } else {
                    $scope.showPleaseLogIn();
                }
            };

            // Sadly duplicated in detail controller
            $scope.showPleaseLogIn = function() {
                $dialog.dialog(
                    {
                        backdrop: true,
                        keyboard: true, //make ESC close it
                        backdropClick: true, //make clicking on the backdrop close it
                        templateUrl: 'modules/login/pleaseLogIn.tpl.html',
                        controller: 'pleaseLogIn',
                        dialogClass: 'modal ccmodal'
                    }).open();
            };

                // At some point, we may manually control topLanguages, and have a 'more' link to show them all.
//            $scope.topLanguages = [
//                {isoCode: 'en', name:'English'},
//                {isoCode: 'tpi', name:'Tok Pisin'},
//                {isoCode: 'th', name:'Thai'},
//                {isoCode: 'id', name:'Bahasia Indonesia'},
//                {isoCode: 'fr', name:'French'}
//            ];
                bookService.getLanguages().then(function(languages) {
                    $scope.topLanguages = languages;
                });
                // Replicated from Bloom.Book.RuntimeInformationInjector.AddUISettingsToDom().
                // Eventually this will be user-extensible and retrieved using a query on some new table.
                $scope.topTags = [
                    "Agriculture", "Animal Stories", "Business", "Culture", "Community Living", "Dictionary", "Environment", "Fiction", "Health", "How To", "Math", "Non Fiction", "Spiritual", "Personal Development", "Primer", "Science", "Traditional Story"
                ];
		}])
        .controller('CarouselCtrl', ['$scope',
            function ($scope) {
                $scope.myInterval = 5000;
                var slides = $scope.slides = [];
                slides.push({
                    image: 'assets/class.jpg',
                    text: 'Learning to read takes books. Learning to read well, and developing a love of reading, takes lots of books.  Books at all different skill levels. But how are low-literacy language communities ever to get all those books in their language?  They can do it with Bloom.'
                });
                slides.push({
                    image: 'assets/shellbook.png',
                    text: 'Bloom keeps things simple and efficient by offering a library of shell books. You just translate from a source language, and print.'
                });
        }]);

	//Angular provides a "limitTo" filter, this adds "startFrom" filter for use with pagination
	BloomLibraryApp.filter('startFrom', function () {
		return function (input, start) {
			start = +start; //parse to int
			if (input) {
				return input.slice(start);
			} else {
				return "";
			}
		};
	});

	//review: adding functions here is probably not angularjs best practice (but I haven't learned what the correct way would be, just yet)
	BloomLibraryApp.run(
   ['$rootScope', '$state', '$stateParams',
   function ($rootScope, $state, $stateParams) {

	//lets you write ng-click="log('testing')"
	$rootScope.log = function (variable) {
		console.log(variable);
	};

	//lets you write ng-click="alert('testing')"
	$rootScope.alert = function (text) {
		alert(text);
	};

	//Keeps the correct nav link active
	$('.navbar li').click(function(e) {
		$('.navbar li.active').removeClass('active');
		var $this = $(this);
		if (!$this.hasClass('active')) {
			$this.addClass('active');
		}
		e.preventDefault();
	});

	//Load the UserVoice widget
	var uvOptions = {};
	(function() {
		var uv = document.createElement('script'); uv.type = 'text/javascript'; uv.async = true;
		uv.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'widget.uservoice.com/xoQAlIzNrOFQpMmMnRcg7w.js';
		var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(uv, s);
	})();

	// It's very handy to add references to $state and $stateParams to the $rootScope
	// so that you can access them from any scope within your applications.For example,
	//
 will set the

	// to active whenever 'contacts.list' or one of its decendents is active.
	$rootScope.$state = $state;
	$rootScope.$stateParams = $stateParams;
   } ]);

	BloomLibraryApp.directive('pdfoverlay', function () {
		return {
			restrict: 'A',
			link: function (scope, element, attrs) {
				$(element).fancybox({
					'overlayShow': true,
					'type': 'iframe',
					iframe: {
						preload: false
					}
				});
			}
		};
	});
} ());  // end wrap-everything function<commit_msg>Slow carousel down from 5 seconds to 10 seconds<commit_after>(function () { // to wrap use strict
	'use strict';

	var BloomLibraryApp = angular.module('BloomLibraryApp',
				['templates-app', 'templates-common', // Required for ng-boilerplate, to use templates from templates-app.js instead of copying individual files.
				'BloomLibraryApp.browse', 'BloomLibraryApp.detail', "BloomLibraryApp.login", "BloomLibraryApp.signup", "BloomLibraryApp.services", "BloomLibraryApp.datagrid",
					"BloomLibraryApp.ccdialog", "BloomLibraryApp.download", "BloomLibraryApp.staticPages",
					"BloomLibraryApp.deleteDialog", "BloomLibraryApp.inProgress", "BloomLibraryApp.pleaseLogIn", "BloomLibraryApp.mustAgree",
				"ui.bootstrap", 'ui.router', 'palaso.ui.listview', 'restangular', 'ngCookies'])

  .config(['$urlRouterProvider', '$stateProvider',
           function ($urlRouterProvider, $stateProvider) {

			//TODO when we have hosting that can do the url rewriting this requires
			//$locationProvider.html5Mode(true);
			//$locationProvider.hashPrefix('!');

			// For any unmatched url, redirect to /state1
			$urlRouterProvider.otherwise("/browse");

           } ])

.controller('HeaderCtrl', ['$scope', 'authService', '$location', '$state', 'silNoticeService', function ($scope, authService, $location, $state, silNoticeService) {
	$scope.location = $location.path();
	$scope.isLoggedIn = authService.isLoggedIn;

	$scope.logout = function () {
		authService.logout();
		silNoticeService.clear();
		$state.go('browse');
	};

	$scope.userName = authService.userName;
} ])
        .controller('FooterCtrl', ['$scope', function($scope) {
            $scope.year = new Date().getFullYear().toString();
        }])
		.controller('LeftSidebar', ['$scope', '$dialog', '$state', '$location', '$rootScope', 'bookService', 'authService',
            function ($scope, $dialog, $state, $location, $rootScope, bookService, authService) {
            $scope.currentLang = $location.$$search.lang;
            $scope.currentTag = $location.$$search.tag;
            $scope.currentShelf = $location.$$search.shelf;
            $scope.wantLeftBar = $location.$$path.substring(1, 7) == 'browse';
            $rootScope.$on('$locationChangeSuccess', function() {
                $scope.currentLang = $location.$$search.lang;
                $scope.currentTag = $location.$$search.tag;
                $scope.currentShelf = $location.$$search.shelf;
                $scope.wantLeftBar = $location.$$path.substring(1, 7) == 'browse';
            });
			$scope.showInProgress = function() {
				$dialog.dialog(
					{
						backdrop: true,
						keyboard: true, //make ESC close it
						backdropClick: true, //make clicking on the backdrop close it
						templateUrl: 'modules/inProgress/inProgress.tpl.html',
						controller: 'inProgress',
						dialogClass: 'modal ccmodal'
					}).open();
			};
            $scope.filterLanguage = function(language) {
                $state.go('browse', {lang:language}); // keep other params unchanged.
            };
            $scope.filterTag = function(tagName) {
                $state.go('browse', {tag:tagName}); // keep other params unchanged.
            };
            $scope.filterShelf = function(shelfName) {
                $state.go('browse', {search: '', shelf:shelfName}); // keep other params unchanged.
            };
            $scope.filterMyUploads = function() {
                if (authService.isLoggedIn()) {
                    $state.go('browse', {search: '', shelf: '$myUploads'}); // keep other params unchanged.
                } else {
                    $scope.showPleaseLogIn();
                }
            };

            // Sadly duplicated in detail controller
            $scope.showPleaseLogIn = function() {
                $dialog.dialog(
                    {
                        backdrop: true,
                        keyboard: true, //make ESC close it
                        backdropClick: true, //make clicking on the backdrop close it
                        templateUrl: 'modules/login/pleaseLogIn.tpl.html',
                        controller: 'pleaseLogIn',
                        dialogClass: 'modal ccmodal'
                    }).open();
            };

                // At some point, we may manually control topLanguages, and have a 'more' link to show them all.
//            $scope.topLanguages = [
//                {isoCode: 'en', name:'English'},
//                {isoCode: 'tpi', name:'Tok Pisin'},
//                {isoCode: 'th', name:'Thai'},
//                {isoCode: 'id', name:'Bahasia Indonesia'},
//                {isoCode: 'fr', name:'French'}
//            ];
                bookService.getLanguages().then(function(languages) {
                    $scope.topLanguages = languages;
                });
                // Replicated from Bloom.Book.RuntimeInformationInjector.AddUISettingsToDom().
                // Eventually this will be user-extensible and retrieved using a query on some new table.
                $scope.topTags = [
                    "Agriculture", "Animal Stories", "Business", "Culture", "Community Living", "Dictionary", "Environment", "Fiction", "Health", "How To", "Math", "Non Fiction", "Spiritual", "Personal Development", "Primer", "Science", "Traditional Story"
                ];
		}])
        .controller('CarouselCtrl', ['$scope',
            function ($scope) {
                $scope.myInterval = 10000;
                var slides = $scope.slides = [];
                slides.push({
                    image: 'assets/class.jpg',
                    text: 'Learning to read takes books. Learning to read well, and developing a love of reading, takes lots of books.  Books at all different skill levels. But how are low-literacy language communities ever to get all those books in their language?  They can do it with Bloom.'
                });
                slides.push({
                    image: 'assets/shellbook.png',
                    text: 'Bloom keeps things simple and efficient by offering a library of shell books. You just translate from a source language, and print.'
                });
        }]);

	//Angular provides a "limitTo" filter, this adds "startFrom" filter for use with pagination
	BloomLibraryApp.filter('startFrom', function () {
		return function (input, start) {
			start = +start; //parse to int
			if (input) {
				return input.slice(start);
			} else {
				return "";
			}
		};
	});

	//review: adding functions here is probably not angularjs best practice (but I haven't learned what the correct way would be, just yet)
	BloomLibraryApp.run(
   ['$rootScope', '$state', '$stateParams',
   function ($rootScope, $state, $stateParams) {

	//lets you write ng-click="log('testing')"
	$rootScope.log = function (variable) {
		console.log(variable);
	};

	//lets you write ng-click="alert('testing')"
	$rootScope.alert = function (text) {
		alert(text);
	};

	//Keeps the correct nav link active
	$('.navbar li').click(function(e) {
		$('.navbar li.active').removeClass('active');
		var $this = $(this);
		if (!$this.hasClass('active')) {
			$this.addClass('active');
		}
		e.preventDefault();
	});

	//Load the UserVoice widget
	var uvOptions = {};
	(function() {
		var uv = document.createElement('script'); uv.type = 'text/javascript'; uv.async = true;
		uv.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'widget.uservoice.com/xoQAlIzNrOFQpMmMnRcg7w.js';
		var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(uv, s);
	})();

	// It's very handy to add references to $state and $stateParams to the $rootScope
	// so that you can access them from any scope within your applications.For example,
	//
 will set the

	// to active whenever 'contacts.list' or one of its decendents is active.
	$rootScope.$state = $state;
	$rootScope.$stateParams = $stateParams;
   } ]);

	BloomLibraryApp.directive('pdfoverlay', function () {
		return {
			restrict: 'A',
			link: function (scope, element, attrs) {
				$(element).fancybox({
					'overlayShow': true,
					'type': 'iframe',
					iframe: {
						preload: false
					}
				});
			}
		};
	});
} ());  // end wrap-everything function<|endoftext|>


<commit_before>/* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, object-shorthand, comma-dangle, prefer-arrow-callback, no-else-return, newline-per-chained-call, wrap-iife, max-len */

export default function initCompareAutocomplete() {
  $('.js-compare-dropdown').each(function() {
    var $dropdown, selected;
    $dropdown = $(this);
    selected = $dropdown.data('selected');
    const $dropdownContainer = $dropdown.closest('.dropdown');
    const $fieldInput = $(`input[name="${$dropdown.data('field-name')}"]`, $dropdownContainer);
    const $filterInput = $('input[type="search"]', $dropdownContainer);
    $dropdown.glDropdown({
      data: function(term, callback) {
        return $.ajax({
          url: $dropdown.data('refs-url'),
          data: {
            ref: $dropdown.data('ref'),
            search: term,
          }
        }).done(function(refs) {
          return callback(refs);
        });
      },
      selectable: true,
      filterable: true,
      filterRemote: true,
      fieldName: $dropdown.data('field-name'),
      filterInput: 'input[type="search"]',
      renderRow: function(ref) {
        var link;
        if (ref.header != null) {
          return $('<li />').addClass('dropdown-header').text(ref.header);
        } else {
          link = $('<a />').attr('href', '#').addClass(ref === selected ? 'is-active' : '').text(ref).attr('data-ref', escape(ref));
          return $('<li />').append(link);
        }
      },
      id: function(obj, $el) {
        return $el.attr('data-ref');
      },
      toggleLabel: function(obj, $el) {
        return $el.text().trim();
      }
    });
    $filterInput.on('keyup', (e) => {
      const keyCode = e.keyCode || e.which;
      if (keyCode !== 13) return;
      const text = $filterInput.val();
      $fieldInput.val(text);
      $('.dropdown-toggle-text', $dropdown).text(text);
      $dropdownContainer.removeClass('open');
    });

    $dropdownContainer.on('click', '.dropdown-content a', (e) => {
      $dropdown.prop('title', e.target.text.replace(/_+?/g, '-'));
      if ($dropdown.hasClass('has-tooltip')) {
        $dropdown.tooltip('fixTitle');
      }
    });
  });
}
<commit_msg>converted compare_autocomplete to axios<commit_after>/* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, object-shorthand, comma-dangle, prefer-arrow-callback, no-else-return, newline-per-chained-call, wrap-iife, max-len */
import axios from './lib/utils/axios_utils';
import flash from './flash';

export default function initCompareAutocomplete() {
  $('.js-compare-dropdown').each(function() {
    var $dropdown, selected;
    $dropdown = $(this);
    selected = $dropdown.data('selected');
    const $dropdownContainer = $dropdown.closest('.dropdown');
    const $fieldInput = $(`input[name="${$dropdown.data('field-name')}"]`, $dropdownContainer);
    const $filterInput = $('input[type="search"]', $dropdownContainer);
    $dropdown.glDropdown({
      data: function(term, callback) {
        axios.get($dropdown.data('refsUrl'), {
          params: {
            ref: $dropdown.data('ref'),
            search: term,
          },
        }).then(({ data }) => {
          callback(data);
        }).catch(() => flash('Error fetching refs'));
      },
      selectable: true,
      filterable: true,
      filterRemote: true,
      fieldName: $dropdown.data('field-name'),
      filterInput: 'input[type="search"]',
      renderRow: function(ref) {
        var link;
        if (ref.header != null) {
          return $('<li />').addClass('dropdown-header').text(ref.header);
        } else {
          link = $('<a />').attr('href', '#').addClass(ref === selected ? 'is-active' : '').text(ref).attr('data-ref', escape(ref));
          return $('<li />').append(link);
        }
      },
      id: function(obj, $el) {
        return $el.attr('data-ref');
      },
      toggleLabel: function(obj, $el) {
        return $el.text().trim();
      }
    });
    $filterInput.on('keyup', (e) => {
      const keyCode = e.keyCode || e.which;
      if (keyCode !== 13) return;
      const text = $filterInput.val();
      $fieldInput.val(text);
      $('.dropdown-toggle-text', $dropdown).text(text);
      $dropdownContainer.removeClass('open');
    });

    $dropdownContainer.on('click', '.dropdown-content a', (e) => {
      $dropdown.prop('title', e.target.text.replace(/_+?/g, '-'));
      if ($dropdown.hasClass('has-tooltip')) {
        $dropdown.tooltip('fixTitle');
      }
    });
  });
}
<|endoftext|>


<commit_before>import { createTranslator } from 'kolibri.utils.i18n';

export const learnStrings = createTranslator('CommonLearnStrings', {
  // Labels
  learnLabel: {
    message: 'Learn',
    context:
      "Each time a learner signs in to Kolibri, the first thing they see is the  'Learn' page with the list of all the classes they are enrolled to.",
  },
  libraryLabel: {
    message: 'Library',
    context:
      "The 'Library' section displays channels available on Kolibri server, and allows learners to browse, explore and filter topics and resources on their own.",
  },
  resumeLabel: {
    message: 'Resume',
    context: 'Label for links that go to content that has been started and can be resumed',
  },
  mostPopularLabel: {
    message: 'Most popular',
    context: 'Label for links that go to the most popular content',
  },
  popularLabel: {
    message: 'Popular',
    context: 'Label for links that go to the most popular content.',
  },
  nextStepsLabel: {
    message: 'Next steps',
    context: 'Label for links that go to post-requisites for content that has been completed.',
  },
  multipleLearningActivitiesLabel: {
    message: 'Multiple learning activities',
    context: '',
  },
  exploreResources: {
    message: 'Explore resources',
    context: "Heading in the 'Learn' section where users can view learning resources.\n",
  },
  logo: {
    message: 'From the channel {channelTitle}',
    context:
      'Added to create a complete alt-text description of a logo on a content card to indicate to the user what channel the resource belongs to. For example: From the channel Khan Academy - English',
  },
  resourceCompletedLabel: {
    message: 'Resource completed',
    context:
      'Message when the user successfully finishes a resource or marks a resource as complete',
  },
  dontShowThisAgainLabel: {
    message: 'Don’t show this again',
    context:
      'Option that allows the user to prevent this resource from displaying in the future while using category search',
  },
  markResourceAsCompleteLabel: {
    message: 'Mark resource as complete',
    context:
      'Title of the modal window where a user will confirm or cancel marking a resource as complete manually.',
  },
  resourceHidden: {
    message: 'Resource hidden',
    context:
      'Notification message indicating the resource has been marked as hidden for future category searches.',
  },
  suggestedTimeToComplete: {
    message: 'Suggested time to complete',
    context: 'Tooltip label indicating the approximate time needed to complete the resource.',
  },
  multipleLearningActivities: {
    message: 'Multiple learning activities',
    context: 'Label indicating the resource contains several different learning activities.',
  },

  // TODO - move these into diff sections as we make this a full feature in 0.16
  // Past Papers Project (12/2021) strings
  quizLabel: {
    message: 'Quiz',
    context: 'Label to show that the practice resource can be interacted with as a quiz.',
  },
  suggestedTime: {
    message: 'Suggested time',
    context: 'Time suggested by coach for how long an independent practice quiz should take',
  },
});

export default {
  methods: {
    learnString(key, args) {
      return learnStrings.$tr(key, args);
    },
  },
};
<commit_msg>export learnString getter alongside the common mixin<commit_after>import { createTranslator } from 'kolibri.utils.i18n';

export const learnStrings = createTranslator('CommonLearnStrings', {
  // Labels
  learnLabel: {
    message: 'Learn',
    context:
      "Each time a learner signs in to Kolibri, the first thing they see is the  'Learn' page with the list of all the classes they are enrolled to.",
  },
  libraryLabel: {
    message: 'Library',
    context:
      "The 'Library' section displays channels available on Kolibri server, and allows learners to browse, explore and filter topics and resources on their own.",
  },
  resumeLabel: {
    message: 'Resume',
    context: 'Label for links that go to content that has been started and can be resumed',
  },
  mostPopularLabel: {
    message: 'Most popular',
    context: 'Label for links that go to the most popular content',
  },
  popularLabel: {
    message: 'Popular',
    context: 'Label for links that go to the most popular content.',
  },
  nextStepsLabel: {
    message: 'Next steps',
    context: 'Label for links that go to post-requisites for content that has been completed.',
  },
  multipleLearningActivitiesLabel: {
    message: 'Multiple learning activities',
    context: '',
  },
  exploreResources: {
    message: 'Explore resources',
    context: "Heading in the 'Learn' section where users can view learning resources.\n",
  },
  logo: {
    message: 'From the channel {channelTitle}',
    context:
      'Added to create a complete alt-text description of a logo on a content card to indicate to the user what channel the resource belongs to. For example: From the channel Khan Academy - English',
  },
  resourceCompletedLabel: {
    message: 'Resource completed',
    context:
      'Message when the user successfully finishes a resource or marks a resource as complete',
  },
  dontShowThisAgainLabel: {
    message: 'Don’t show this again',
    context:
      'Option that allows the user to prevent this resource from displaying in the future while using category search',
  },
  markResourceAsCompleteLabel: {
    message: 'Mark resource as complete',
    context:
      'Title of the modal window where a user will confirm or cancel marking a resource as complete manually.',
  },
  resourceHidden: {
    message: 'Resource hidden',
    context:
      'Notification message indicating the resource has been marked as hidden for future category searches.',
  },
  suggestedTimeToComplete: {
    message: 'Suggested time to complete',
    context: 'Tooltip label indicating the approximate time needed to complete the resource.',
  },
  multipleLearningActivities: {
    message: 'Multiple learning activities',
    context: 'Label indicating the resource contains several different learning activities.',
  },

  // TODO - move these into diff sections as we make this a full feature in 0.16
  // Past Papers Project (12/2021) strings
  quizLabel: {
    message: 'Quiz',
    context: 'Label to show that the practice resource can be interacted with as a quiz.',
  },
  suggestedTime: {
    message: 'Suggested time',
    context: 'Time suggested by coach for how long an independent practice quiz should take',
  },
});

export function learnString(key, args) {
  return learnStrings.$tr(key, args);
}

export default {
  methods: { learnString },
};
<|endoftext|>


<commit_before>module.exports = {
	description: 'allows unknown binary operators'
};
<commit_msg>transpile exponentiation operator in old node<commit_after>module.exports = {
	description: 'allows unknown binary operators',
	buble: true
};
<|endoftext|>


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

/**
 * WordPress dependencies
 */
import { Fragment } from '@wordpress/element';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { useFeature } from '../../hooks/useFeature';
import { CORE_MODULES } from '../../googlesitekit/modules/datastore/constants';
import useQueryArg from '../../hooks/useQueryArg';
import SetupSuccessBannerNotification from './SetupSuccessBannerNotification';
import CoreSiteBannerNotifications from './CoreSiteBannerNotifications';
import ModuleRecoveryAlert from '../dashboard-sharing/ModuleRecoveryAlert';
import IdeaHubPromptBannerNotification from './IdeaHubPromptBannerNotification';
import UserInputPromptBannerNotification from './UserInputPromptBannerNotification';
import AdSenseAlerts from './AdSenseAlerts';
import ActivationBanner from '../../modules/analytics-4/components/dashboard/ActivationBanner';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
import useViewOnly from '../../hooks/useViewOnly';
import ZeroDataStateNotifications from './ZeroDataStateNotifications';
const { useSelect } = Data;

export default function BannerNotifications() {
	const dashboardSharingEnabled = useFeature( 'dashboardSharing' );
	const ideaHubModuleEnabled = useFeature( 'ideaHubModule' );
	const userInputEnabled = useFeature( 'userInput' );
	const ga4ActivationBannerEnabled = useFeature( 'ga4ActivationBanner' );

	const viewOnly = useViewOnly();

	const isAuthenticated = useSelect( ( select ) =>
		select( CORE_USER ).isAuthenticated()
	);
	const adSenseModuleActive = useSelect( ( select ) =>
		select( CORE_MODULES ).isModuleActive( 'adsense' )
	);

	const [ notification ] = useQueryArg( 'notification' );

	return (
		<Fragment>
			{ ! viewOnly && (
				<Fragment>
					{ ( 'authentication_success' === notification ||
						'user_input_success' === notification ) && (
						<SetupSuccessBannerNotification />
					) }
					{ isAuthenticated && <CoreSiteBannerNotifications /> }
					{ dashboardSharingEnabled && <ModuleRecoveryAlert /> }
					{ ga4ActivationBannerEnabled && <ActivationBanner /> }
				</Fragment>
			) }
			<ZeroDataStateNotifications />
			{ ! viewOnly && (
				<Fragment>
					{ userInputEnabled && (
						<UserInputPromptBannerNotification />
					) }
					{ ideaHubModuleEnabled && (
						<IdeaHubPromptBannerNotification />
					) }
					{ adSenseModuleActive && <AdSenseAlerts /> }
				</Fragment>
			) }
		</Fragment>
	);
}
<commit_msg>Render ThankWithGooglePromptSupporterWall component.<commit_after>/**
 * BannerNotifications component.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * WordPress dependencies
 */
import { Fragment } from '@wordpress/element';

/**
 * Internal dependencies
 */
import Data from 'googlesitekit-data';
import { useFeature } from '../../hooks/useFeature';
import { CORE_MODULES } from '../../googlesitekit/modules/datastore/constants';
import useQueryArg from '../../hooks/useQueryArg';
import SetupSuccessBannerNotification from './SetupSuccessBannerNotification';
import CoreSiteBannerNotifications from './CoreSiteBannerNotifications';
import ModuleRecoveryAlert from '../dashboard-sharing/ModuleRecoveryAlert';
import IdeaHubPromptBannerNotification from './IdeaHubPromptBannerNotification';
import UserInputPromptBannerNotification from './UserInputPromptBannerNotification';
import AdSenseAlerts from './AdSenseAlerts';
import ActivationBanner from '../../modules/analytics-4/components/dashboard/ActivationBanner';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
import useViewOnly from '../../hooks/useViewOnly';
import ZeroDataStateNotifications from './ZeroDataStateNotifications';
import ThankWithGooglePromptSupporterWall from './ThankWithGooglePromptSupporterWall';
const { useSelect } = Data;

export default function BannerNotifications() {
	const dashboardSharingEnabled = useFeature( 'dashboardSharing' );
	const ideaHubModuleEnabled = useFeature( 'ideaHubModule' );
	const userInputEnabled = useFeature( 'userInput' );
	const ga4ActivationBannerEnabled = useFeature( 'ga4ActivationBanner' );

	const viewOnly = useViewOnly();

	const isAuthenticated = useSelect( ( select ) =>
		select( CORE_USER ).isAuthenticated()
	);
	const adSenseModuleActive = useSelect( ( select ) =>
		select( CORE_MODULES ).isModuleActive( 'adsense' )
	);

	const [ notification ] = useQueryArg( 'notification' );

	return (
		<Fragment>
			{ ! viewOnly && (
				<Fragment>
					{ ( 'authentication_success' === notification ||
						'user_input_success' === notification ) && (
						<SetupSuccessBannerNotification />
					) }
					{ isAuthenticated && <CoreSiteBannerNotifications /> }
					{ dashboardSharingEnabled && <ModuleRecoveryAlert /> }
					{ ga4ActivationBannerEnabled && <ActivationBanner /> }
				</Fragment>
			) }
			<ThankWithGooglePromptSupporterWall />
			<ZeroDataStateNotifications />
			{ ! viewOnly && (
				<Fragment>
					{ userInputEnabled && (
						<UserInputPromptBannerNotification />
					) }
					{ ideaHubModuleEnabled && (
						<IdeaHubPromptBannerNotification />
					) }
					{ adSenseModuleActive && <AdSenseAlerts /> }
				</Fragment>
			) }
		</Fragment>
	);
}
<|endoftext|>