").html($("").text(UI.format.dateTime(a[c][0],"long")).css("white-space","nowrap")).append($(" ").html(ra(a[c][1])).css("text-align","center")).append($(" ").html(b).css("text-align","left")))}}};ca();break;case "Statistics":var C=$("").text("Loading..");d.append(C);var n={graph:"new"},w=mist.stored.get().graphs?
+$.extend(!0,{},mist.stored.get().graphs):{},O={};for(g in mist.data.streams)O[g]=!0;for(g in mist.data.active_streams)O[mist.data.active_streams[g]]=!0;var O=Object.keys(O).sort(),da=[];for(g in mist.data.config.protocols)da.push(mist.data.config.protocols[g].connector);da.sort();mist.send(function(){UI.plot.datatype.templates.cpuload.cores=0;for(var a in mist.data.capabilities.cpu)UI.plot.datatype.templates.cpuload.cores=UI.plot.datatype.templates.cpuload.cores+mist.data.capabilities.cpu[a].cores;
+C.html(UI.buildUI([{type:"help",help:"Here you will find the MistServer stream statistics, you can select various categories yourself. All statistics are live: up to five minutes are saved."},$("").text("Select the data to display"),{label:"Add to",type:"select",select:[["new","New graph"]],pointer:{main:n,index:"graph"},classes:["graph_ids"],"function":function(){if($(this).val()){var a=C.find(".graph_xaxis"),c=C.find(".graph_id");if($(this).val()=="new"){a.children("option").prop("disabled",
+false);c.setval("Graph "+(Object.keys(w).length+1)).closest("label").show()}else{var b=w[$(this).val()].xaxis;a.children("option").prop("disabled",true).filter('[value="'+b+'"]').prop("disabled",false);c.closest("label").hide()}a.children('option[value="'+a.val()+'"]:disabled').length&&a.val(a.children("option:enabled").first().val());a.trigger("change")}}},{label:"Graph id",type:"str",pointer:{main:n,index:"id"},classes:["graph_id"],validate:[function(a){return a in w?{msg:"This graph id has already been used. Please enter something else.",
+classes:["red"]}:false}]},{label:"Axis type",type:"select",select:[["time","Time line"]],pointer:{main:n,index:"xaxis"},value:"time",classes:["graph_xaxis"],"function":function(){$s=C.find(".graph_datatype");switch($(this).getval()){case "coords":$s.children("option").prop("disabled",true).filter('[value="coords"]').prop("disabled",false);break;case "time":$s.children("option").prop("disabled",false).filter('[value="coords"]').prop("disabled",true)}if(!$s.val()||$s.children('option[value="'+$s.val()+
+'"]:disabled').length){$s.val($s.children("option:enabled").first().val());$s.trigger("change")}}},{label:"Data type",type:"select",select:[["clients","Connections"],["upbps","Bandwidth (up)"],["downbps","Bandwidth (down)"],["cpuload","CPU use"],["memload","Memory load"],["coords","Client location"]],pointer:{main:n,index:"datatype"},classes:["graph_datatype"],"function":function(){$s=C.find(".graph_origin");switch($(this).getval()){case "cpuload":case "memload":$s.find("input[type=radio]").not('[value="total"]').prop("disabled",
+true);$s.find('input[type=radio][value="total"]').prop("checked",true);break;default:$s.find("input[type=radio]").prop("disabled",false)}}},{label:"Data origin",type:"radioselect",radioselect:[["total","All"],["stream","The stream:",O],["protocol","The protocol:",da]],pointer:{main:n,index:"origin"},value:["total"],classes:["graph_origin"]},{type:"buttons",buttons:[{label:"Add data set",type:"save","function":function(){var a;if(n.graph=="new"){a=UI.plot.addGraph(n,c);w[a.id]=a;C.find("input.graph_id").val("");
+C.find("select.graph_ids").append($("").text(a.id)).val(a.id).trigger("change")}else a=w[n.graph];var b=UI.plot.datatype.getOptions({datatype:n.datatype,origin:n.origin});a.datasets.push(b);UI.plot.save(a);UI.plot.go(w)}}]}]));var c=$("").addClass("graph_container");d.append(c);var b=C.find("select.graph_ids");for(a in w){var f=UI.plot.addGraph(w[a],c);b.append($("
").text(f.id)).val(f.id);var e=[],g;for(g in w[a].datasets){var h=UI.plot.datatype.getOptions({datatype:w[a].datasets[g].datatype,
+origin:w[a].datasets[g].origin});e.push(h)}f.datasets=e;w[f.id]=f}b.trigger("change");UI.plot.go(w);UI.interval.set(function(){UI.plot.go(w)},1E4)},{active_streams:!0,capabilities:!0});break;case "Server Stats":if("undefined"==typeof mist.data.capabilities){mist.send(function(){UI.navto(a)},{capabilities:!0});d.append("Loading..");return}var ea=$(""),E=$(""),f={vheader:"CPUs",labels:["Model","Processor speed","Amount of cores","Amount of threads"],content:[]};for(g in mist.data.capabilities.cpu)e=
+mist.data.capabilities.cpu[g],f.content.push({header:"CPU #"+(Number(g)+1),body:[e.model,UI.format.addUnit(UI.format.number(e.mhz),"MHz"),e.cores,e.threads]});g=UI.buildVheaderTable(f);var qa=function(){var a=mist.data.capabilities.mem,c=mist.data.capabilities.load,a={vheader:"Memory",labels:["Used","Cached","Available","Total"],content:[{header:"Physical memory",body:[UI.format.bytes(a.used*1048576)+" ("+UI.format.addUnit(c.memory,"%")+")",UI.format.bytes(a.cached*1048576),UI.format.bytes(a.free*
+1048576),UI.format.bytes(a.total*1048576)]},{header:"Swap memory",body:[UI.format.bytes((a.swaptotal-a.swapfree)*1048576),UI.format.addUnit("","N/A"),UI.format.bytes(a.swapfree*1048576),UI.format.bytes(a.swaptotal*1048576)]}]},a=UI.buildVheaderTable(a);ea.replaceWith(a);ea=a;c={vheader:"Load average",labels:["CPU use","1 minute","5 minutes","15 minutes"],content:[{header:" ",body:[UI.format.addUnit(UI.format.number(mist.data.capabilities.cpu_use/10),"%"),UI.format.number(c.one/100),UI.format.number(c.five/
+100),UI.format.number(c.fifteen/100)]}]};c=UI.buildVheaderTable(c);E.replaceWith(c);E=c};qa();d.append(UI.buildUI([{type:"help",help:"You can find general server statistics here. Note that memory and CPU usage is for your entire machine, not just MistServer."}])).append($("").css("width","auto").addClass("nolay").append($("").append($("").append(ea)).append($(" ").append(E))).append($(" ").append($("").append(g).attr("colspan",2))));UI.interval.set(function(){mist.send(function(){qa()},
+{capabilities:true})},3E4);break;case "Email for Help":g=$.extend({},mist.data);delete g.statistics;delete g.totals;delete g.clients;delete g.capabilities;g=JSON.stringify(g);g="Version: "+mist.data.config.version+"\n\nConfig:\n"+g;n={};d.append(UI.buildUI([{type:"help",help:"You can use this form to email MistServer support if you're having difficulties. A copy of your server config file will automatically be included."},{type:"str",label:"Your name",validate:["required"],pointer:{main:n,index:"name"},
+value:mist.user.name},{type:"email",label:"Your email address",validate:["required"],pointer:{main:n,index:"email"}},{type:"hidden",value:"Integrated Help",pointer:{main:n,index:"subject"}},{type:"hidden",value:"-",pointer:{main:n,index:"company"}},{type:"textarea",rows:20,label:"Your message",validate:["required"],pointer:{main:n,index:"message"}},{type:"textarea",rows:20,label:"Your config file",readonly:!0,value:g,pointer:{main:n,index:"configfile"}},{type:"buttons",buttons:[{type:"save",label:"Send",
+"function":function(a){$(a).text("Sending..");$.ajax({type:"POST",url:"http://mistserver.org/contact?skin=plain",data:n,success:function(a){a=$("").html(a);a.find("script").remove();d.html(a[0].innerHTML)}})}}]}]));break;case "Disconnect":mist.user.password="";delete mist.user.authstring;delete mist.user.loggedin;sessionStorage.removeItem("mistLogin");UI.navto("Login");break;default:d.append($("").text("This tab does not exist."))}d.find(".field").filter(function(){var a=$(this).getval();
+return a==""||a==null?true:false}).each(function(){var a=[];$(this).is("input, select, textarea")?a.push($(this)):a=$(this).find("input, select, textarea");if(a.length){$(a[0]).focus();return false}});!navigator.doNotTrack&&mist.user.loggedin&&d.append($(" ").attr("src","https://www.google-analytics.com/collect?v=1&tid=UA-32426932-1&cid="+mist.data.config.iid+"&t=pageview&dp="+encodeURIComponent("/MI/"+a)+"&dh=MI."+(mist.data.LTS?"Pro":"OS")).css({width:"1px",height:"1px","min-width":"1px",opacity:0.1,
+position:"absolute",left:"-1000px"}))}}};"origin"in location||(location.origin=location.protocol+"//");var host;host="file://"==location.origin?"http://localhost:4242/api":location.origin+location.pathname.replace(/\/+$/,"")+"/api";
var mist={data:{},user:{name:"",password:"",host:host},send:function(a,c,d){var c=c||{},d=d||{},d=$.extend(true,{timeOut:3E4,sendData:c},d),b={authorize:{password:mist.user.authstring?MD5(mist.user.password+mist.user.authstring):"",username:mist.user.name}};$.extend(true,b,c);log("Send",$.extend(true,{},c));b={url:mist.user.host,type:"POST",data:{command:JSON.stringify(b)},dataType:"jsonp",crossDomain:true,timeout:d.timeout*1E3,async:true,error:function(b,e){delete mist.user.loggedin;if(!d.hide){switch(e){case "timeout":e=
$("").text("The connection timed out. ");break;case "abort":e=$("").text("The connection was aborted. ");break;default:e=$("").text(e+". ").css("text-transform","capitalize")}$("#message").addClass("red").text("An error occurred while attempting to communicate with MistServer:").append($(" ")).append(e).append($("").text("Send server request again").click(function(){mist.send(a,c,d)}))}UI.navto("Login")},success:function(b){log("Receive",$.extend(true,{},b),"as reply to",d.sendData);
delete mist.user.loggedin;switch(b.authorize.status){case "OK":if("streams"in b)if(b.streams)if("incomplete list"in b.streams){delete b.streams["incomplete list"];$.extend(mist.data.streams,b.streams)}else mist.data.streams=b.streams;else mist.data.streams={};var e=$.extend({},b),h=["config","capabilities","ui_settings","LTS","active_streams","browse","log","totals"],q;for(q in e)h.indexOf(q)==-1&&delete e[q];$.extend(mist.data,e);mist.user.loggedin=true;UI.elements.connection.status.text("Connected").removeClass("red").addClass("green");
diff --git a/lsp/mist.js b/lsp/mist.js
index e549506e..bdb37b61 100644
--- a/lsp/mist.js
+++ b/lsp/mist.js
@@ -4904,6 +4904,9 @@ var UI = {
params: saveas.params,
'default': saveas['default']
};
+ if (!("triggers" in mist.data.config)) {
+ mist.data.config.triggers = {};
+ }
if (!(saveas.triggeron in mist.data.config.triggers)) {
mist.data.config.triggers[saveas.triggeron] = [];
}