vines-services 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +5 -5
- data/Rakefile +13 -11
- data/bin/vines-services +0 -1
- data/lib/vines/services/command/init.rb +156 -139
- data/lib/vines/services/controller/messages_controller.rb +8 -3
- data/lib/vines/services/controller/users_controller.rb +11 -11
- data/lib/vines/services/indexer.rb +1 -1
- data/lib/vines/services/priority_queue.rb +12 -12
- data/lib/vines/services/roster.rb +85 -46
- data/lib/vines/services/storage/couchdb/service.rb +1 -1
- data/lib/vines/services/storage/couchdb/system.rb +1 -1
- data/lib/vines/services/storage/couchdb/upload.rb +1 -1
- data/lib/vines/services/storage/couchdb/user.rb +13 -3
- data/lib/vines/services/storage/couchdb.rb +8 -12
- data/lib/vines/services/version.rb +1 -1
- data/test/priority_queue_test.rb +1 -1
- data/web/coffeescripts/api.coffee +6 -0
- data/web/coffeescripts/files.coffee +65 -39
- data/web/coffeescripts/services.coffee +5 -2
- data/web/coffeescripts/setup.coffee +35 -12
- data/web/coffeescripts/systems.coffee +115 -228
- data/web/javascripts/api.js +69 -0
- data/web/javascripts/app.js +2 -0
- data/web/javascripts/commands.js +28 -0
- data/web/javascripts/files.js +424 -0
- data/web/javascripts/init.js +27 -0
- data/web/javascripts/services.js +404 -0
- data/web/javascripts/setup.js +485 -0
- data/web/javascripts/systems.js +342 -0
- data/web/stylesheets/app.css +714 -0
- data/web/stylesheets/services.css +4 -14
- data/web/stylesheets/setup.css +1 -2
- data/web/stylesheets/systems.css +124 -108
- metadata +95 -92
@@ -0,0 +1,2 @@
|
|
1
|
+
var Api,__bind=function(a,b){return function(){return a.apply(b,arguments)}};Api=function(){function b(b){this.session=b,this.user=null,this.session.onRoster(__bind(function(){return this.get(a,{jid:this.session.bareJid()},__bind(function(a){return this.user=a},this))},this))}var a;return a="http://getvines.com/protocol/users",b.prototype.jid=function(){return"vines."+this.session.bareJid().split("@")[1]},b.prototype.get=function(a,b,c){var d,e,f;e=this.session.xml('<iq id="'+this.session.uniqueId()+'" to="'+this.jid()+'" type="get">\n <query xmlns="'+a+'"/>\n</iq>');for(d in b)f=b[d],$("query",e).attr(d,f);return this.session.sendIQ(e,__bind(function(a){var b;b=$(a).attr("type")==="result";if(!b)return;return c(JSON.parse($("query",a).text()))},this))},b.prototype.get2=function(a,b,c){var d;return d=this.session.xml('<iq id="'+this.session.uniqueId()+'" to="'+this.jid()+'" type="get">\n <query xmlns="'+a+'"/>\n</iq>'),$("query",d).text(b),this.session.sendIQ(d,__bind(function(a){var b;b=$(a).attr("type")==="result";if(!b)return;return c(JSON.parse($("query",a).text()))},this))},b.prototype.remove=function(a,b,c){var d;return d=this.session.xml('<iq id="'+this.session.uniqueId()+'" to="'+this.jid()+'" type="set">\n <query xmlns="'+a+'" action="delete" id=""/>\n</iq>'),$("query",d).attr("id",b),this.session.sendIQ(d,c)},b.prototype.save=function(a,b,c){var d;return d=this.session.xml('<iq id="'+this.session.uniqueId()+'" to="'+this.jid()+'" type="set">\n <query xmlns="'+a+'"/>\n</iq>'),$("query",d).text(JSON.stringify(b)),this.session.sendIQ(d,__bind(function(a){var b;b=$(a).attr("type")==="result";if(!b)return;return c(JSON.parse($("query",a).text()))},this))},b}();var Commands;Commands=function(){function a(){this.buf=[],this.index=0}return a.prototype.prev=function(){var a;return a=this.buf[--this.index],a||(this.index=-1),a||""},a.prototype.next=function(){var a;return a=this.buf[++this.index],a||(this.index=this.buf.length),a||""},a.prototype.push=function(a){return this.buf.push(a),this.index=this.buf.length},a}();var SystemsPage,__bind=function(a,b){return function(){return a.apply(b,arguments)}};SystemsPage=function(){function a(a){this.session=a,this.session.onRoster(__bind(function(){return this.roster()},this)),this.session.onMessage(__bind(function(a){return this.message(a)},this)),this.session.onPresence(__bind(function(a){return this.presence(a)},this)),this.commands=new Commands,this.chats={},this.currentContact=null,this.layout=null}return a.prototype.datef=function(a){var b,c,d,e;return b=new Date(a),d=b.getHours()<12?" am":" pm",c=b.getHours()>12?b.getHours()-12:b.getHours(),c===0&&(c=12),e=b.getMinutes()+"",e.length===1&&(e="0"+e),c+":"+e+d},a.prototype.groupContacts=function(){var a,b,c,d,e,f,g,h;c={},g=this.session.roster;for(d in g){a=g[d],h=a.groups;for(e=0,f=h.length;e<f;e++)b=h[e],(c[b]||(c[b]=[])).push(a)}return c},a.prototype.roster=function(){var a,b,c,d,e,f,g,h,i,j,k,l;d=this.groupContacts(),i=function(){var a;a=[];for(c in d)b=d[c],a.push(c);return a}(),i=i.sort(function(a,b){return a=a.toLowerCase(),b=b.toLowerCase(),a>b?1:a<b?-1:0}),e=$("#roster-items").empty(),l=[];for(j=0,k=i.length;j<k;j++)c=i[j],b=d[c],g=$('<li class="group"></li>').appendTo(e),g.text(c),g.attr("data-group",c),l.push(function(){var d,g,i;i=[];for(d=0,g=b.length;d<g;d++)a=b[d],h=$('<li data-jid="'+a.jid+'">\n <span class="text"></span>\n <span class="unread" style="display:none;"></span>\n</li>').appendTo(e),a.offline()&&h.addClass("offline"),h.click(__bind(function(a){return this.selectContact(a)},this)),f=a.name||a.jid.split("@")[0],h.attr("data-name",f),h.attr("data-group",c),i.push($(".text",h).text(f));return i}.call(this));return l},a.prototype.message=function(a){var b,c,d,e;this.queueMessage(a),e=a.from===this.session.jid(),d=a.from.split("/")[0];if(!e&&d!==this.currentContact)return c=this.chat(a.from),c.unread++,this.eachContact(d,function(a){return $(".unread",a).text(c.unread).show()});b=this.atBottom(),this.appendMessage(a);if(b)return this.scroll({animate:!0})},a.prototype.eachContact=function(a,b){var c,d,e,f,g;f=$("#roster-items li[data-jid='"+a+"']").get(),g=[];for(d=0,e=f.length;d<e;d++)c=f[d],g.push(b($(c)));return g},a.prototype.appendMessage=function(a){var b,c,d,e,f,g,h;d=a.from===this.session.jid(),h=$("jid",a.node).text(),c=(h||a.from).split("/")[0],b=this.session.roster[c],e=b?b.name||c:c,f=$('<li data-jid="'+c+'"><pre></pre></li>').appendTo("#messages"),g=d?"$ ":"",$("pre",f).text(g+a.text);if(!d)return f.append('<footer>\n <span class="author"></span> @\n <span class="time">'+this.datef(a.received)+"</span>\n</footer>"),$(".author",f).text(e)},a.prototype.queueMessage=function(a){var b,c,d;return d=a.from===this.session.jid(),c=a[d?"to":"from"],b=this.chat(c),b.jid=c,b.messages.push(a)},a.prototype.chat=function(a){var b,c;return b=a.split("/")[0],c=this.chats[b],c||(c={jid:a,messages:[],unread:0},this.chats[b]=c),c},a.prototype.presence=function(a){var b,c;c=a.from.split("/")[0];if(c===this.session.bareJid())return;if(!a.type||a.offline)b=this.session.roster[c],this.eachContact(c,function(a){return b.offline()?a.addClass("offline"):a.removeClass("offline")});if(a.offline)return this.chat(c).jid=c},a.prototype.selectContact=function(a){var b,c,d;$("#blank-slate").fadeOut(200,function(){return $(this).remove()}),$("#roster").hide(),d=$(a.currentTarget),c=d.attr("data-jid"),b=this.session.roster[c];if(this.currentContact===c)return;return this.currentContact=c,$("#message-label").text($(".text",d).text()),$("#messages").empty(),$("#message").focus(),this.layout.resize(),this.restoreChat(c)},a.prototype.restoreChat=function(a){var b,c,d,e,f;b=this.chats[a],c=[],b&&(c=b.messages,b.unread=0,this.eachContact(a,function(a){return $(".unread",a).text("").hide()}));for(e=0,f=c.length;e<f;e++)d=c[e],this.appendMessage(d);return this.scroll()},a.prototype.scroll=function(a){var b;return a||(a={}),b=$("#messages"),a.animate?b.animate({scrollTop:b.prop("scrollHeight")},400):b.scrollTop(b.prop("scrollHeight"))},a.prototype.atBottom=function(){var a,b;return b=$("#messages"),a=b.prop("scrollHeight")-b.outerHeight(),b.scrollTop()>=a},a.prototype.send=function(){var a,b,c,d;return this.currentContact?(b=$("#message"),d=b.val().trim(),d&&(a=this.chats[this.currentContact],c=a?a.jid:this.currentContact,this.message({from:this.session.jid(),text:d,to:c,received:new Date}),this.session.sendMessage(c,d),this.commands.push(d)),b.val(""),!1):!1},a.prototype.drawBlankSlate=function(){return $('<form id="blank-slate" class="float">\n <p>\n Services, and individual systems, can be controlled by sending\n them shell commands through this terminal. Select a system to chat with\n to get started.\n </p>\n <input type="submit" value="Select System"/>\n</form>').appendTo("#alpha"),$("#blank-slate").submit(__bind(function(){return $("#roster").show(),this.layout.resize(),!1},this))},a.prototype.draw=function(){var a,b;if(!this.session.connected()){window.location.hash="";return}return $("body").attr("id","systems-page"),$("#container").hide().empty(),$('<div id="alpha" class="primary column x-fill y-fill">\n <ul id="messages" class="scroll y-fill"></ul>\n <form id="message-form">\n <label id="message-label"></label>\n <input id="message" name="message" type="text" maxlength="1024" placeholder="Type a command and press enter to send"/>\n </form>\n <div id="roster" class="float" style="display:none;">\n <ul id="roster-items"></ul>\n <div id="roster-form"></div>\n </div>\n</div>').appendTo("#container"),$("#message-form").submit(__bind(function(){return this.send()},this)),$("#messages").click(function(){return $("#roster").hide()}),$("#message").focus(function(){return $("#roster").hide()}),this.roster(),$("#message-label").click(__bind(function(){return $("#roster").toggle()},this)),$("#message").keyup(__bind(function(a){switch(a.keyCode){case 38:return $("#message").val(this.commands.prev());case 40:return $("#message").val(this.commands.next())}},this)),this.currentContact?(this.currentContact&&this.restoreChat(this.currentContact),a=this.session.roster[this.currentContact],b=a.name||a.jid.split("@")[0],$("#message-label").text(b),$("#message").focus()):this.drawBlankSlate(),$("#container").show(),this.layout=this.resize(),this.scroll(),new Filter({list:"#roster-items",form:"#roster-form",attrs:["data-jid","data-name"]}),$("form","#roster-form").show()},a.prototype.resize=function(){var a,b,c,d,e,f,g;return a=$("#container"),g=$("#roster"),c=$("#roster-items"),f=$("#roster-form"),e=$("#message"),b=$("#message-form"),d=$("#message-label"),new Layout(function(){var h;return e.width(b.width()-d.width()-32),h=a.height()-b.height()-10,g.css("max-height",h),c.css("max-height",h-f.outerHeight()-10)})},a}();var ServicesPage,__bind=function(a,b){return function(){return a.apply(b,arguments)}};ServicesPage=function(){function f(a){this.session=a,this.api=new Api(this.session),this.selectedService=null,this.validateTimeout=null,this.layout=null,this.users=[]}var a,b,c,d,e;return c="http://getvines.com/protocol/services",b="http://getvines.com/protocol/services/members",d="http://getvines.com/protocol/systems",a="http://getvines.com/protocol/systems/attributes",e="http://getvines.com/protocol/users",f.prototype.deleteService=function(a){var b;return this.drawBlankSlate(),this.toggleForm("#remove-contact-form"),b=$("#services li[data-id='"+this.selectedService.id+"']"),this.api.remove(c,this.selectedService.id,__bind(function(a){return b.fadeOut(200,function(){return b.remove(),this.selectedService=null})},this)),!1},f.prototype.icon=function(a){var b,c;return c={darwin:"mac.png",linux:"linux.png",windows:"windows.png"},b=c[a.os]||"run.png","images/"+b},f.prototype.drawMember=function(a){var b;if(!this.editorVisible())return;return b=$('<li>\n <span class="icon"><img src="'+this.icon(a)+'"/></span>\n <span class="text"></span>\n</li>').appendTo("#members"),$(".text",b).text(a.name)},f.prototype.operators=function(){var a,b,c,d,e,f;e=["like","not like","starts with","ends with","is","is not",">",">=","<","<=","and","or"],f=[];for(c=0,d=e.length;c<d;c++)b=e[c],a=$('<li data-selector="'+b+'">\n '+b+"\n</li>").appendTo("#operators"),f.push(a.click(__bind(function(a){var b;return $("#syntax").focus(),b=$(a.currentTarget).attr("data-selector"),$("#syntax").val($("#syntax").val()+(" "+b+" ")),this.validateIn()},this)));return f},f.prototype.selectService=function(a){var b,d;return b=$(a).attr("data-id"),d=$(a).attr("data-name"),$("#services li").removeClass("selected"),$(a).addClass("selected"),$("#remove-service-msg").html("Are you sure you want to remove the "+("<strong>"+d+"</strong> service?")),$("#remove-service-form .buttons").fadeIn(200),this.api.get(c,{id:b},__bind(function(a){return this.selectedService=a,this.drawEditor(a)},this))},f.prototype.serviceNode=function(a){var b,c;return b=a.size===1?"system":"systems",c=$('<li data-id="'+a.id+'" data-name="" data-size="'+a.size+'">\n <span class="text">'+a.name+'</span>\n <span class="count">'+a.size+" "+b+"</span>\n</li>").appendTo("#services"),c.attr("data-name",a.name),$(".text",c).text(a.name),c.click(__bind(function(a){return this.selectService(a.currentTarget)},this)),c},f.prototype.findServices=function(){return this.api.get(c,{},__bind(function(a){var b,c,d,e,f;e=a.rows,f=[];for(c=0,d=e.length;c<d;c++)b=e[c],f.push(this.serviceNode(b));return f},this))},f.prototype.findMembers=function(a){return this.api.get(b,{id:a},__bind(function(a){var b,c,d,e,f;e=a.rows,f=[];for(c=0,d=e.length;c<d;c++)b=e[c],f.push(this.drawMember(b));return f},this))},f.prototype.findUsers=function(a){return this.api.get(e,{},__bind(function(a){var b;return this.users=function(){var c,d,e,f;e=a.rows,f=[];for(c=0,d=e.length;c<d;c++)b=e[c],b.system||f.push(b);return f}(),this.drawUsers()},this))},f.prototype.attributeNode=function(a){var b;return b=$('<li data-name=""></li>').appendTo("#attributes"),b.text(a),b.attr("data-name",a),b.click(__bind(function(a){var b;return $("#syntax").focus(),b=$(a.currentTarget).attr("data-name"),$("#syntax").val($("#syntax").val()+(" "+b+" ")),this.validateIn()},this))},f.prototype.findAttributes=function(b){return this.api.get(a,{},__bind(function(a){var b,c,d,e,f;e=a.rows,f=[];for(c=0,d=e.length;c<d;c++)b=e[c],f.push(this.attributeNode(b));return f},this))},f.prototype.validateIn=function(a){return clearTimeout(this.validateTimeout),this.validateTimeout=setTimeout(__bind(function(){return this.validate()},this),a||500)},f.prototype.validate=function(){var a,c;$("#syntax-status").text(""),c=$("#syntax").data("prev"),a=$.trim($("#syntax").val()),$("#syntax").data("prev",a);if(!a||a===c)return;return $("#syntax-status").text("Searching . . ."),$("#members").empty(),this.api.get2(b,a,__bind(function(a){var b,c,d,e,f;if(a.ok){$("#syntax-status").text(""),e=a.rows,f=[];for(c=0,d=e.length;c<d;c++)b=e[c],f.push(this.drawMember(b));return f}return $("#syntax-status").text(a.error)},this))},f.prototype.validateForm=function(){var a,b;return $("#name-error").empty(),b=!0,a=$.trim($("#name").val()),a===""&&($("#name-error").text("Name is required."),b=!1),b},f.prototype.save=function(){var a,b,d,e;if(!this.validateForm())return;return e=$("#users :checked").map(function(){return $(this).val()}).get(),a=$("#unix-users").val().split(","),a=function(){var b,c,e;e=[];for(b=0,c=a.length;b<c;b++)d=a[b],$.trim(d).length>0&&e.push($.trim(d));return e}(),b={name:$("#name").val(),code:$("#syntax").val(),accounts:a,users:e},$("#id").val().length>0&&(b.id=$("#id").val()),this.api.save(c,b,__bind(function(a){var b;return new Notification("Service saved successfully"),a.size=$("#members").length,$("#id").val(a.id),b=$("#services li[data-id='"+a.id+"']"),b.length===0?(b=this.serviceNode(a),this.selectService(b)):$(".text",b).text(a.name)},this)),!1},f.prototype.drawBlankSlate=function(){return $("#beta").empty(),$('<form id="blank-slate">\n <p>\n Services are dynamically updated groups of systems based on\n criteria you define. Send a command to the service and it runs\n on every system in the group.\n </p>\n <input type="submit" id="blank-slate-add" value="Add Service"/>\n</form>').appendTo("#beta"),this.api.user.permissions.services||$("#blank-slate-add").remove(),$("#blank-slate").submit(__bind(function(){return this.drawEditor(),!1},this))},f.prototype.draw=function(){var a;if(!this.session.connected()){window.location.hash="";return}return $("body").attr("id","services-page"),$("#container").hide().empty(),$('<div id="alpha" class="sidebar column y-fill">\n <h2>Services <div id="search-services-icon"></div></h2>\n <div id="search-services-form"></div>\n <ul id="services" class="selectable scroll y-fill"></ul>\n <div id="alpha-controls" class="controls">\n <div id="add-service"></div>\n <div id="remove-service"></div>\n </div>\n <form id="remove-service-form" class="overlay" style="display:none;">\n <h2>Remove Service</h2>\n <p id="remove-service-msg">Select a service in the list above to remove.</p>\n <fieldset class="buttons" style="display:none;">\n <input id="remove-service-cancel" type="button" value="Cancel"/>\n <input id="remove-service-ok" type="submit" value="Remove"/>\n </fieldset>\n </form>\n</div>\n<div id="beta" class="primary column x-fill y-fill"></div>\n<div id="charlie" class="sidebar column y-fill">\n <h2>Operators</h2>\n <ul id="operators"></ul>\n <h2>Attributes <div id="search-attributes-icon"></div></h2>\n <div id="search-attributes-form"></div>\n <ul id="attributes" class="y-fill scroll"></ul>\n</div>').appendTo("#container"),new Button("#add-service",ICONS.plus),new Button("#remove-service",ICONS.minus),this.api.user.permissions.services||$("#alpha-controls div").remove(),this.drawBlankSlate(),$("#add-service").click(__bind(function(){return this.drawEditor()},this)),$("#remove-service").click(__bind(function(){return this.toggleForm("#remove-service-form")},this)),$("#remove-service-cancel").click(__bind(function(){return this.toggleForm("#remove-service-form")},this)),$("#remove-service-form").submit(__bind(function(){return this.deleteService()},this)),this.operators(),this.findServices(),this.findAttributes(),this.findUsers(),$("#container").show(),this.layout=this.resize(),a=__bind(function(){return this.layout.resize(),this.layout.resize()},this),new Filter({list:"#services",icon:"#search-services-icon",form:"#search-services-form",attrs:["data-name"],open:a,close:a}),new Filter({list:"#attributes",icon:"#search-attributes-icon",form:"#search-attributes-form",attrs:["data-name"],open:a,close:a})},f.prototype.drawEditor=function(a){if(!this.pageVisible())return;return a||(this.selectedService=null,$("#services li").removeClass("selected")),$("#beta").empty(),$('<form id="editor-form" class="sections y-fill scroll">\n <input id="id" type="hidden"/>\n <div>\n <section>\n <h2>Service</h2>\n <fieldset>\n <label for="name">Name</label>\n <input id="name" type="text"/>\n <p id="name-error" class="error"></p>\n <label for="syntax">Criteria</label>\n <textarea id="syntax" placeholder="fqdn starts with \'www.\' and platform is \'mac_os_x\'"></textarea>\n <p id="syntax-status"></p>\n </fieldset>\n </section>\n <section>\n <h2>Members</h2>\n <fieldset id="service-preview">\n <ul id="members" class="scroll"></ul>\n </fieldset>\n </section>\n <section>\n <h2>Permissions</h2>\n <fieldset>\n <label>Users</label>\n <ul id="users" class="scroll"></ul>\n <label for="unix-users">Unix Accounts</label>\n <input id="unix-users" type="text"/>\n </fieldset>\n </section>\n </div>\n</form>\n<form id="editor-buttons">\n <input id="save" type="submit" value="Save"/>\n</form>').appendTo("#beta"),a&&(this.findMembers(a.id),$("#id").val(a.id),$("#name").val(a.name),$("#syntax").val(a.code),$("#unix-users").val(a.accounts.join(", "))),this.users.length>0&&this.drawUsers(),this.layout.resize(),$("#name").focus(),$("#syntax").change(__bind(function(){return this.validateIn()},this)),$("#syntax").keyup(__bind(function(){return this.validateIn()},this)),$("#editor-form").submit(__bind(function(){return this.save()},this)),$("#editor-buttons").submit(__bind(function(){return this.save()},this))},f.prototype.drawUsers=function(){var a,b,c,d,e;if(!this.editorVisible())return;$("#users").empty(),e=this.users;for(c=0,d=e.length;c<d;c++)b=e[c],a=$("<li>\n <input id='user-"+b.jid+"' type='checkbox' value='"+b.jid+"'/>\n <label for='user-"+b.jid+"'>"+b.jid+"</label>\n</li>").appendTo("#users"),b.jid===this.session.bareJid()&&$("input",a).prop("checked",!0);if(this.selectedService)return $('#users input[type="checkbox"]').val(this.selectedService.users)},f.prototype.toggleForm=function(a,b){return a=$(a),$("form.overlay").each(function(){if(this.id!==a.attr("id"))return $(this).hide()}),a.is(":hidden")?(b&&b(),a.fadeIn(100)):a.fadeOut(100,function(){a[0].reset();if(b)return b()})},f.prototype.pageVisible=function(){return $("#services-page").length>0},f.prototype.editorVisible=function(){return $("#services-page #editor-form").length>0},f.prototype.resize=function(){var a,b,c;return a=$("#alpha"),b=$("#beta"),c=$("#charlie"),new Layout(function(){return c.css("left",a.width()+b.width())})},f}();var FilesPage,__bind=function(a,b){return function(){return a.apply(b,arguments)}};FilesPage=function(){function d(a){this.session=a,this.api=new Api(this.session),this.uploads=new c({session:this.session,jid:this.api.jid,size:this.size,complete:__bind(function(a){return this.findFile(a.name)},this)})}var a,b,c;return a="http://getvines.com/protocol/files",b="http://getvines.com/protocol/files/labels",d.prototype.findLabels=function(){return $("#labels").empty(),this.api.get(b,{},__bind(function(a){var b,c,d,e,f;e=a.rows,f=[];for(c=0,d=e.length;c<d;c++)b=e[c],f.push(this.labelNodeList(b));return f},this))},d.prototype.labelNodeList=function(a){var b,c;return c=a.size===1?"file":"files",b=$('<li data-name="">\n <span class="text"></span>\n <span class="count">'+a.size+" "+c+"</span>\n</li>").appendTo("#labels"),$(".text",b).text(a.name),b.attr("data-name",a.name),b.click(__bind(function(a){return this.selectLabel(a)},this))},d.prototype.selectLabel=function(a){var b;return b=$(a.currentTarget).attr("data-name"),$("#labels li").removeClass("selected"),$(a.currentTarget).addClass("selected"),$("#files").empty(),this.findFiles({label:$(a.currentTarget).attr("data-name")})},d.prototype.findFiles=function(b){return this.api.get(a,b,__bind(function(a){var b,c,d,e,f;e=a.rows,f=[];for(c=0,d=e.length;c<d;c++)b=e[c],f.push(this.fileNode(b));return f},this))},d.prototype.findFile=function(b){return this.api.get(a,{name:b},__bind(function(a){return this.fileNode(a)},this))},d.prototype.updateFileNode=function(a){var b,c,d;return b=$("#files li[data-id='"+a.id+"']"),c=this.size(a.size),d=this.date(a.created_at),b.data("file",a),$("h2",b).text(a.name),$(".size",b).text(c),$(".time",b).text(d),b.attr("data-name",a.name),b.attr("data-size",c),b.attr("data-created",d)},d.prototype.fileNode=function(a){var b,c,d,e,f,g;if($("#files li[data-id='"+a.id+"']").length>0){this.updateFileNode(a);return}c=$('<li data-id="'+a.id+'">\n <div class="file-icon">\n <span class="size"></span>\n </div>\n <h2></h2>\n <footer>\n <span class="time"></span>\n <ul class="labels"></ul>\n <form class="add-label">\n <div class="add-label-button"></div>\n <input type="text" placeholder="Label" style="display:none;"/>\n </form>\n </footer>\n <form class="file-form">\n <fieldset>\n <input class="cancel" type="submit" value="Delete"/>\n </fieldset>\n </form>\n</li>').appendTo("#files"),new Button($(".file-icon",c).get(0),ICONS.page2,{scale:1,translation:"-2 0","stroke-width":.1,opacity:1}),new Button($(".add-label-button",c).get(0),ICONS.plus,{translation:"-10 -10",scale:.5}),$("form.file-form",c).submit(__bind(function(){return this.deleteFile(c)},this)),$("form.add-label",c).submit(__bind(function(){return this.addLabel(c)},this)),$(".add-label-button",c).click(function(){return $('form.add-label input[type="text"]',c).show()}),this.updateFileNode(a),f=a.labels,g=[];for(d=0,e=f.length;d<e;d++)b=f[d],g.push(this.labelNode(c,b));return g},d.prototype.labelNode=function(a,b){var c,d;return d=$(".labels",a),c=$('<li data-name="">\n <span class="text"></span>\n <div class="remove"></div>\n</li>').appendTo(d),$(".text",c).text(b),c.attr("data-name",b),new Button($(".remove",c).get(0),ICONS.cross,{translation:"-8 -8",scale:.5}),$(".remove",c).click(__bind(function(){return this.removeLabel(a,c)},this))},d.prototype.addLabel=function(b){var c,d,e,f,g,h,i,j,k;d=$('form.add-label input[type="text"]',b),d.hide(),f=function(){var a,b,c,e;c=d.val().split(/,/),e=[];for(a=0,b=c.length;a<b;a++)g=c[a],g&&e.push(g);return e}(),d.val(""),c=b.data("file");for(h=0,j=f.length;h<j;h++)e=f[h],c.labels.push(e);this.api.save(a,c,function(a){});for(i=0,k=f.length;i<k;i++)e=f[i],this.labelNode(b,e),this.updateLabelCount(e,1);return!1},d.prototype.removeLabel=function(b,c){var d,e,f;return d=b.data("file"),f=c.attr("data-name"),d.labels=function(){var a,b,c,g;c=d.labels,g=[];for(a=0,b=c.length;a<b;a++)e=c[a],e!==f&&g.push(e);return g}(),this.api.save(a,d,function(a){}),c.fadeOut(200,function(){return c.remove()}),this.updateLabelCount(f,-1)},d.prototype.updateLabelCount=function(a,b){var c,d,e;return d=$("#labels li[data-name='"+a+"'] .count"),d.length>0?(c=parseInt(d.text().split(" ")[0])+b,e=c===1?"file":"files",d.text(""+c+" "+e)):this.labelNodeList({name:a,size:1})},d.prototype.deleteFile=function(b){return this.api.remove(a,b.attr("data-id"),__bind(function(a){var c,d,e,f;f=b.data("file").labels;for(d=0,e=f.length;d<e;d++)c=f[d],this.updateLabelCount(c,-1);return b.fadeOut(200,function(){return b.remove()})},this)),!1},d.prototype.date=function(a){var b,c;return a=new Date(a),b="Sun Mon Tue Wed Thu Fri Sat".split(" ")[a.getDay()],c="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ")[a.getMonth()],""+b+", "+a.getDate()+" "+c+", "+a.getFullYear()+" @ "+a.getHours()+":"+a.getMinutes()},d.prototype.size=function(a){var b,c,d,e;return d=a/1024,e=d/1024,c=e/1024,b=function(a){return a<100?a.toFixed(1).replace(".0",""):Math.round(a)},d<1?""+a+" b":e<1?""+b(d)+" k":c<1?""+b(e)+" m":""+b(c)+" g"},d.prototype.draw=function(){var a,b;if(!this.session.connected()){window.location.hash="";return}return $("body").attr("id","files-page"),$("#container").hide().empty(),$('<div id="alpha" class="sidebar column y-fill">\n <h2>Labels</h2>\n <ul id="labels" class="selectable scroll y-fill"></ul>\n <div id="alpha-controls" class="controls"></div>\n</div>\n<div id="beta" class="primary column x-fill y-fill">\n <h2 id="files-title">Files <div id="search-files-icon"></div></h2>\n <div id="search-files-form"></div>\n <ul id="files" class="scroll y-fill"></ul>\n</div>\n<div id="charlie" class="sidebar column y-fill">\n <h2>Uploads</h2>\n <div id="upload-dnd" class="float">Drag files here to upload.</div>\n <ul id="uploads" class="scroll y-fill"></ul>\n <div id="charlie-controls" class="controls">\n <form id="file-form">\n <input id="open-file-chooser" type="submit" value="Select files to upload"/>\n <input id="file-chooser" type="file" multiple="true" />\n </form>\n </div>\n</div>').appendTo("#container"),this.api.user.permissions.files?($("#file-chooser").change(__bind(function(a){return this.uploads.queue(a.target.files),$("#file-chooser").val("")},this)),$("#file-form").submit(function(){return $("#file-chooser").click(),!1}),$("#upload-dnd").bind("dragenter",function(a){return a.stopPropagation(),a.preventDefault(),$("#upload-dnd").css("color","#444")}),$("#upload-dnd").bind("dragleave",function(a){return $("#upload-dnd").css("color","#ababab")}),$("#upload-dnd").bind("dragover",function(a){return a.stopPropagation(),a.preventDefault()}),$("#upload-dnd").bind("drop",__bind(function(a){return a.stopPropagation(),a.preventDefault(),$("#upload-dnd").css("color","#ababab"),this.uploads.queue(a.originalEvent.dataTransfer.files)},this))):($("#upload-dnd").text("Your account cannot upload files."),$("#file-form").remove()),this.findLabels(),this.findFiles(),$("#container").show(),b=this.resize(),a=function(){return b.resize(),b.resize()},new Filter({list:"#files",icon:"#search-files-icon",form:"#search-files-form",attrs:["data-name","data-created"],open:a,close:a})},d.prototype.resize=function(){var a,b,c,d,e;return a=$("#alpha"),b=$("#beta"),c=$("#charlie"),e=$("#uploads"),d=$("#upload-dnd"),new Layout(function(){return c.css("left",a.width()+b.width()),d.height(e.height()),d.css("line-height",e.height()+"px")})},c=function(){function a(a){this.session=a.session,this.serviceJid=a.jid,this.size=a.size,this.complete=a.complete,this.uploads=[],this.sending=null}return a.prototype.queue=function(a){var b,c,d;for(c=0,d=a.length;c<d;c++)b=a[c],this.find(b)||this.add(b);return this.process()},a.prototype.add=function(a){var b,c;return c=this.node(a),b=$(".meter",c),this.uploads.push(new Transfer({to:this.serviceJid(),file:a,session:this.session,progress:function(a){return b.css("width",a+"%")},complete:__bind(function(){return this.remove(a),this.complete&&this.complete(a),a.name===this.sending.name&&(this.sending=null),this.process()},this)}))},a.prototype.process=function(){var a;if(this.sending)return;return(a=this.uploads[0])?(this.sending=a.file,a.start()):this.sending=null},a.prototype.find=function(a){var b;return function(){var c,d,e,f;e=this.uploads,f=[];for(c=0,d=e.length;c<d;c++)b=e[c],b.file.name===a.name&&f.push(b);return f}.call(this).shift()},a.prototype.remove=function(a){var b,c;return this.uploads=function(){var b,d,e,f;e=this.uploads,f=[];for(b=0,d=e.length;b<d;b++)c=e[b],c.file.name!==a.name&&f.push(c);return f}.call(this),b=$("#uploads li[data-file='"+a.name+"']"),b.fadeOut(200,function(){return b.remove()})},a.prototype.node=function(a){var b;return b=$('<li data-file="" style="display:none;">\n <form class="inset">\n <h2></h2>\n <div class="progress">\n <div class="meter"></div>\n <span class="text">'+this.size(a.size)+'</span>\n <div class="cancel"></div>\n </div>\n </form>\n</li>').appendTo("#uploads"),b.fadeIn(200),$("h2",b).text(a.name),b.attr("data-file",a.name),new Button($(".cancel",b).get(0),ICONS.cross,{translation:"-8 -8",scale:.5}),$(".cancel",b).click(__bind(function(){return this.cancel(a)},this)),b},a.prototype.cancel=function(a){var b;if(b=this.find(a))return b.stop()},a}(),d}();var SetupPage,__bind=function(a,b){return function(){return a.apply(b,arguments)}};SetupPage=function(){function d(a){this.session=a,this.api=new Api(this.session),this.layout=null,this.selected=null,this.services=[],this.users=[]}var a,b,c;return a="http://getvines.com/protocol/services",b="http://getvines.com/protocol/systems",c="http://getvines.com/protocol/users",d.prototype.findSystem=function(a){return this.api.get(b,{name:a},__bind(function(a){return this.drawSystemInfo(a)},this))},d.prototype.findServices=function(){return this.api.get(a,{},__bind(function(a){return this.services=a.rows,this.drawServices()},this))},d.prototype.drawServices=function(){var a,b,c,d,e;if($("#setup-page #services").length===0)return;$("#services").empty(),e=this.services;for(c=0,d=e.length;c<d;c++)b=e[c],a=$("<li>\n <input id='service-"+b.id+"' type='checkbox' value='"+b.id+"'/>\n <label for='service-"+b.id+"'></label>\n</li>").appendTo("#services"),$("label",a).text(b.name);this.selected&&$('#services input[type="checkbox"]').val(this.selected.services);if(this.selected&&!this.api.user.permissions.services)return $('#services input[type="checkbox"]').prop("disabled",!0)},d.prototype.findUsers=function(){return this.api.get(c,{},__bind(function(a){return this.users=a.rows,this.drawUsers()},this))},d.prototype.drawUsers=function(){var a,b,c,d,e,f;if($("#setup-page #users").length===0)return;$("#users").empty(),a=$("#systems-nav").hasClass("selected"),e=this.users,f=[];for(c=0,d=e.length;c<d;c++)b=e[c],f.push(b.system===a?this.userNode(b):void 0);return f},d.prototype.userNode=function(a){var b,c;return c=$('<li data-name="" data-jid="'+a.jid+'" id="'+a.jid+'">\n <span class="text"></span>\n <span class="jid">'+a.jid+"</span>\n</li>").appendTo("#users"),b=this.userName(a),$(".text",c).text(b),c.attr("data-name",b),c.click(__bind(function(a){return this.selectUser(a.currentTarget)},this)),c},d.prototype.userName=function(a){return a.name||a.jid.split("@")[0]},d.prototype.selectUser=function(a){var b,d;return b=$(a).attr("data-jid"),d=$(a).attr("data-name"),$("#users li").removeClass("selected"),$(a).addClass("selected"),$("#remove-user-msg").html("Are you sure you want to remove "+("<strong>"+d+"</strong>?")),$("#remove-user-form .buttons").fadeIn(200),this.api.get(c,{jid:b},__bind(function(a){return this.selected=a,a.system?this.drawSystemEditor(a):this.drawUserEditor(a)},this))},d.prototype.removeUser=function(){var a;return this.toggleForm("#remove-user-form"),a=$("#users li[data-jid='"+this.selected.jid+"']"),this.api.remove(c,this.selected.jid,__bind(function(b){return a.fadeOut(200,__bind(function(){var b;return this.users=function(){var a,c,d,e;d=this.users,e=[];for(a=0,c=d.length;a<c;a++)b=d[a],b.jid!==this.selected.jid&&e.push(b);return e}.call(this),a.remove(),this.selected=null,$("#users-nav").hasClass("selected")?this.drawUserBlankSlate():this.drawSystemBlankSlate()},this))},this)),!1},d.prototype.selectTask=function(a){this.selected=null,$("#setup li").removeClass("selected secondary"),$(a.currentTarget).addClass("selected secondary");switch($(a.currentTarget).attr("id")){case"users-nav":return $("#beta-header").text("Users"),this.drawUsers(),this.drawUserBlankSlate(),this.api.user.permissions.users?$("#beta-controls div").show():$("#beta-controls div").hide();case"systems-nav":return $("#beta-header").text("Systems"),this.drawUsers(),this.drawSystemBlankSlate(),this.api.user.permissions.systems?$("#beta-controls div").show():$("#beta-controls div").hide()}},d.prototype.toggleForm=function(a,b){return a=$(a),$("form.overlay").each(function(){if(this.id!==a.attr("id"))return $(this).hide()}),a.is(":hidden")?(b&&b(),a.fadeIn(100)):a.fadeOut(100,function(){a[0].reset();if(b)return b()})},d.prototype.validateUser=function(){var a,b,c,d;$("#user-name-error").empty(),$("#password-error").empty(),d=!0,a=$.trim($("#user-name").val()),b=$.trim($("#password1").val()),c=$.trim($("#password2").val());if(this.selected)c.length>0&&c.length<8&&($("#password-error").text("Password must be at least 8 characters."
|
2
|
+
),d=!1),this.session.bareJid()!==this.selected.jid&&b!==c&&($("#password-error").text("Passwords must match."),d=!1);else{a===""&&($("#user-name-error").text("User name is required."),d=!1),a.match(/[\s"&'\/:<>@]/)&&($("#user-name-error").text("User name contains forbidden characters."),d=!1);if(b.length===0||c.length===0)$("#password-error").text("Password is required."),d=!1;b!==c&&($("#password-error").text("Passwords must match."),d=!1),c.length<8&&($("#password-error").text("Password must be at least 8 characters."),d=!1)}return d},d.prototype.saveUser=function(){var a;return this.validateUser()?(a={jid:$("#jid").val(),username:$("#user-name").val(),name:$("#name").val(),password1:$("#password1").val(),password2:$("#password2").val(),services:$("#services :checked").map(function(){return $(this).val()}).get(),permissions:{systems:$("#perm-systems").prop("checked"),services:$("#perm-services").prop("checked"),files:$("#perm-files").prop("checked"),users:$("#perm-users").prop("checked")}},this.api.save(c,a,__bind(function(a){var b;return new Notification("User saved successfully"),$("#jid").val(a.jid),b=$("#users li[data-jid='"+a.jid+"']"),b.length===0?(this.users.push(a),b=this.userNode(a),this.selectUser(b)):$(".text",b).text(this.userName(a))},this)),!1):!1},d.prototype.validateSystem=function(){var a,b;return $("#user-name-error").empty(),b=!0,a=$.trim($("#user-name").val()),this.selected||(a===""&&($("#user-name-error").text("Hostname is required."),b=!1),a.match(/[\s"&'\/:<>@]/)&&($("#user-name-error").text("Hostname contains forbidden characters."),b=!1)),b},d.prototype.saveSystem=function(){var a;return this.validateSystem()?(a={jid:$("#jid").val(),username:$("#user-name").val(),password1:$("#password1").val(),password2:$("#password1").val(),system:!0},this.api.save(c,a,__bind(function(a){var b;return new Notification("System saved successfully"),$("#jid").val(a.jid),b=$("#users li[data-jid='"+a.jid+"']"),b.length===0?(this.users.push(a),b=this.userNode(a),this.selectUser(b)):$(".text",b).text(a.name)},this)),!1):!1},d.prototype.rand=function(){return Math.floor(Math.random()*16)},d.prototype.token=function(){var a;return function(){var b;b=[];for(a=0;a<=127;a++)b.push(this.rand().toString(16));return b}.call(this).join("")},d.prototype.drawUserBlankSlate=function(){var a;return $("#charlie").empty(),a=this.api.user.permissions.users?"Select a user account to update or add a new user.":"Select a user account to update.",$('<form id="blank-slate">\n <p>'+a+'</p>\n <input type="submit" id="blank-slate-add" value="Add User"/>\n</form>').appendTo("#charlie"),this.api.user.permissions.users||$("#blank-slate-add").remove(),$("#blank-slate").submit(__bind(function(){return this.drawUserEditor(),!1},this))},d.prototype.drawSystemBlankSlate=function(){return $("#charlie").empty(),$('<form id="blank-slate">\n <p>\n Systems need a user account before they can connect and\n authenticate with the chat server.\n </p>\n <input type="submit" id="blank-slate-add" value="Add System"/>\n</form>').appendTo("#charlie"),this.api.user.permissions.systems||$("#blank-slate-add").remove(),$("#blank-slate").submit(__bind(function(){return this.drawSystemEditor(),!1},this))},d.prototype.draw=function(){var a;if(!this.session.connected()){window.location.hash="";return}return $("body").attr("id","setup-page"),$("#container").hide().empty(),$('<div id="alpha" class="sidebar column y-fill">\n <h2>Setup</h2>\n <ul id="setup" class="selectable scroll y-fill">\n <li id="users-nav" class=\'selected secondary\'>\n <span class="text">Users</span>\n </li>\n <li id="systems-nav">\n <span class="text">Systems</span>\n </li>\n </ul>\n <div id="alpha-controls" class="controls"></div>\n</div>\n<div id="beta" class="sidebar column y-fill">\n <h2><span id="beta-header">Users</span> <div id="search-users-icon"></div></h2>\n <div id="search-users-form"></div>\n <ul id="users" class="selectable scroll y-fill"></ul>\n <form id="remove-user-form" class="overlay" style="display:none;">\n <h2>Remove User</h2>\n <p id="remove-user-msg">Select a user to delete.</p>\n <fieldset class="buttons" style="display:none;">\n <input id="remove-user-cancel" type="button" value="Cancel"/>\n <input id="remove-user-ok" type="submit" value="Remove"/>\n </fieldset>\n </form>\n <div id="beta-controls" class="controls">\n <div id="add-user"></div>\n <div id="remove-user"></div>\n </div>\n</div>\n<div id="charlie" class="primary column x-fill y-fill"></div>').appendTo("#container"),this.drawUserBlankSlate(),$("#setup li").click(__bind(function(a){return this.selectTask(a)},this)),this.findUsers(),this.findServices(),$("#container").show(),this.layout=this.resize(),new Button("#add-user",ICONS.plus),new Button("#remove-user",ICONS.minus),this.api.user.permissions.users||$("#beta-controls div").hide(),this.api.user.permissions.systems||$("#systems-nav").hide(),$("#add-user").click(__bind(function(){return $("#users-nav").hasClass("selected")?this.drawUserEditor():this.drawSystemEditor()},this)),$("#remove-user").click(__bind(function(){return this.toggleForm("#remove-user-form")},this)),$("#remove-user-cancel").click(__bind(function(){return this.toggleForm("#remove-user-form")},this)),$("#remove-user-form").submit(__bind(function(){return this.removeUser()},this)),a=__bind(function(){return this.layout.resize(),this.layout.resize()},this),new Filter({list:"#users",icon:"#search-users-icon",form:"#search-users-form",attrs:["data-jid","data-name"],open:a,close:a})},d.prototype.drawUserEditor=function(a){var b,c,d,e;a||(this.selected=null,$("#users li").removeClass("selected")),$("#charlie").empty(),$('<form id="editor-form" class="sections y-fill scroll">\n <div>\n <section>\n <h2>User</h2>\n <fieldset id="jid-fields">\n <input id="jid" type="hidden" value=""/>\n <label for="name">Real Name</label>\n <input id="name" type="text" maxlength="1024"/>\n </fieldset>\n </section>\n <section>\n <h2>Password</h2>\n <fieldset>\n <label id="password1-label" for="password1">Current Password</label>\n <input id="password1" type="password" maxlength="1024"/>\n <label id="password2-label" for="password2">New Password</label>\n <input id="password2" type="password" maxlength="1024"/>\n <p id="password-error" class="error"></p>\n </fieldset>\n </section>\n <section>\n <h2>Permissions</h2>\n <fieldset>\n <label>Manage</label>\n <ul id="permissions">\n <li>\n <input id="perm-systems" type="checkbox" value="systems"/>\n <label for="perm-systems">Systems</label>\n </li>\n <li>\n <input id="perm-services" type="checkbox" value="services"/>\n <label for="perm-services">Services</label>\n </li>\n <li>\n <input id="perm-users" type="checkbox" value="users"/>\n <label for="perm-users">Users</label>\n </li>\n <li>\n <input id="perm-files" type="checkbox" value="files"/>\n <label for="perm-files">Files</label>\n </li>\n </ul>\n </fieldset>\n </section>\n <section>\n <h2>Services</h2>\n <fieldset>\n <label>Access To</label>\n <ul id="services" class="scroll"></ul>\n </fieldset>\n </section>\n </div>\n</form>\n<form id="editor-buttons">\n <input id="save" type="submit" value="Save"/>\n</form>').appendTo("#charlie");if(a){$("<label>Account Name</label>\n<p>"+a.jid+"</p>").prependTo("#jid-fields"),$("#name").focus(),this.session.bareJid()!==a.jid&&($("#password1-label").text("Password"),$("#password2-label").text("Password Again")),$("#jid").val(a.jid),$("#name").val(a.name),$("#user-name").val(a.jid.split("@")[0]),e="services systems files users".split(" ");for(c=0,d=e.length;c<d;c++)b=e[c],a.permissions[b]&&$("#perm-"+b).prop("checked",!0),this.session.bareJid()===a.jid&&$("#perm-"+b).prop("disabled",!0)}else $('<label for="user-name">User Name</label>\n<input id="user-name" type="text" maxlength="1023"/>\n<p id="user-name-error" class="error"></p>').prependTo("#jid-fields"),$("#password1-label").text("Password"),$("#password2-label").text("Password Again"),$("#user-name").focus();return this.services.length>0&&this.drawServices(),this.layout.resize(),$("#editor-form").submit(__bind(function(){return this.saveUser()},this)),$("#editor-buttons").submit(__bind(function(){return this.saveUser()},this))},d.prototype.drawSystemEditor=function(a){return a||(this.selected=null,$("#users li").removeClass("selected")),$("#charlie").empty(),$('<form id="editor-form" class="sections y-fill scroll">\n <div>\n <section>\n <h2>System</h2>\n <fieldset id="jid-fields">\n <input id="jid" type="hidden" value=""/>\n <label id="password1-label" for="password1">Authentication Token</label>\n <div id="token-container">\n <input id="password1" type="text" readonly placeholder="Press Generate to create a new token"/>\n <input id="new-token" type="button" value="Generate"/>\n </div>\n </fieldset>\n </section>\n <section id="info">\n <h2>Info</h2>\n <fieldset>\n <label>Platform</label>\n <p id="info-platform">-</p>\n <label>Hostname</label>\n <p id="info-fqdn">-</p>\n <label>IP Address</label>\n <p id="info-ip">-</p>\n <label>MAC Address</label>\n <p id="info-mac">-</p>\n </fieldset>\n </section>\n </div>\n</form>\n<form id="editor-buttons">\n <input id="save" type="submit" value="Save"/>\n</form>').appendTo("#charlie"),$("#new-token").click(__bind(function(){return $("#password1").val(this.token())},this)),a&&this.findSystem(a.jid.split("@")[0]),a?($("<label>Account Name</label>\n<p>"+a.jid+"</p>").prependTo("#jid-fields"),$("#jid").val(a.jid),$("#user-name").val(a.jid.split("@")[0])):($('<label for="user-name">Hostname</label>\n<input id="user-name" type="text" maxlength="1023"/>\n<p id="user-name-error" class="error"></p>').prependTo("#jid-fields"),$("#user-name").focus(),$("#password1").val(this.token())),this.layout.resize(),$("#editor-form").submit(__bind(function(){return this.saveSystem()},this)),$("#editor-buttons").submit(__bind(function(){return this.saveSystem()},this))},d.prototype.drawSystemInfo=function(a){return $("#info-platform").text(a.platform),$("#info-fqdn").text(a.fqdn),$("#info-ip").text(a.ipaddress),$("#info-mac").text(a.macaddress)},d.prototype.resize=function(){var a,b,c;return a=$("#alpha"),b=$("#beta"),c=$("#charlie"),new Layout(function(){return c.css("left",a.outerWidth()+b.outerWidth())})},d}(),$(function(){var a,b,c,d,e,f;f=new Session,d=new NavBar(f),d.draw(),a={Systems:ICONS.commandline,Services:ICONS.magic,Files:ICONS.page2,Setup:ICONS.gear2,Logout:ICONS.power};for(c in a)b=a[c],d.addButton(c,b);return e={"/systems":new SystemsPage(f),"/services":new ServicesPage(f),"/files":new FilesPage(f),"/setup":new SetupPage(f),"/logout":new LogoutPage(f),"default":new LoginPage(f,"/systems/")},(new Router(e)).draw(),d.select($("#nav-link-systems").parent())})
|
@@ -0,0 +1,28 @@
|
|
1
|
+
var Commands;
|
2
|
+
Commands = (function() {
|
3
|
+
function Commands() {
|
4
|
+
this.buf = [];
|
5
|
+
this.index = 0;
|
6
|
+
}
|
7
|
+
Commands.prototype.prev = function() {
|
8
|
+
var val;
|
9
|
+
val = this.buf[--this.index];
|
10
|
+
if (!val) {
|
11
|
+
this.index = -1;
|
12
|
+
}
|
13
|
+
return val || '';
|
14
|
+
};
|
15
|
+
Commands.prototype.next = function() {
|
16
|
+
var val;
|
17
|
+
val = this.buf[++this.index];
|
18
|
+
if (!val) {
|
19
|
+
this.index = this.buf.length;
|
20
|
+
}
|
21
|
+
return val || '';
|
22
|
+
};
|
23
|
+
Commands.prototype.push = function(cmd) {
|
24
|
+
this.buf.push(cmd);
|
25
|
+
return this.index = this.buf.length;
|
26
|
+
};
|
27
|
+
return Commands;
|
28
|
+
})();
|
@@ -0,0 +1,424 @@
|
|
1
|
+
var FilesPage;
|
2
|
+
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
3
|
+
FilesPage = (function() {
|
4
|
+
var FILES, LABELS, Uploads;
|
5
|
+
FILES = 'http://getvines.com/protocol/files';
|
6
|
+
LABELS = 'http://getvines.com/protocol/files/labels';
|
7
|
+
function FilesPage(session) {
|
8
|
+
this.session = session;
|
9
|
+
this.api = new Api(this.session);
|
10
|
+
this.uploads = new Uploads({
|
11
|
+
session: this.session,
|
12
|
+
jid: this.api.jid,
|
13
|
+
size: this.size,
|
14
|
+
complete: __bind(function(file) {
|
15
|
+
return this.findFile(file.name);
|
16
|
+
}, this)
|
17
|
+
});
|
18
|
+
}
|
19
|
+
FilesPage.prototype.findLabels = function() {
|
20
|
+
$('#labels').empty();
|
21
|
+
return this.api.get(LABELS, {}, __bind(function(result) {
|
22
|
+
var row, _i, _len, _ref, _results;
|
23
|
+
_ref = result.rows;
|
24
|
+
_results = [];
|
25
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
26
|
+
row = _ref[_i];
|
27
|
+
_results.push(this.labelNodeList(row));
|
28
|
+
}
|
29
|
+
return _results;
|
30
|
+
}, this));
|
31
|
+
};
|
32
|
+
FilesPage.prototype.labelNodeList = function(label) {
|
33
|
+
var node, text;
|
34
|
+
text = label.size === 1 ? 'file' : 'files';
|
35
|
+
node = $("<li data-name=\"\">\n <span class=\"text\"></span>\n <span class=\"count\">" + label.size + " " + text + "</span>\n</li>").appendTo('#labels');
|
36
|
+
$('.text', node).text(label.name);
|
37
|
+
node.attr('data-name', label.name);
|
38
|
+
return node.click(__bind(function(event) {
|
39
|
+
return this.selectLabel(event);
|
40
|
+
}, this));
|
41
|
+
};
|
42
|
+
FilesPage.prototype.selectLabel = function(event) {
|
43
|
+
var name;
|
44
|
+
name = $(event.currentTarget).attr('data-name');
|
45
|
+
$('#labels li').removeClass('selected');
|
46
|
+
$(event.currentTarget).addClass('selected');
|
47
|
+
$('#files').empty();
|
48
|
+
return this.findFiles({
|
49
|
+
label: $(event.currentTarget).attr('data-name')
|
50
|
+
});
|
51
|
+
};
|
52
|
+
FilesPage.prototype.findFiles = function(criteria) {
|
53
|
+
return this.api.get(FILES, criteria, __bind(function(result) {
|
54
|
+
var row, _i, _len, _ref, _results;
|
55
|
+
_ref = result.rows;
|
56
|
+
_results = [];
|
57
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
58
|
+
row = _ref[_i];
|
59
|
+
_results.push(this.fileNode(row));
|
60
|
+
}
|
61
|
+
return _results;
|
62
|
+
}, this));
|
63
|
+
};
|
64
|
+
FilesPage.prototype.findFile = function(name) {
|
65
|
+
return this.api.get(FILES, {
|
66
|
+
name: name
|
67
|
+
}, __bind(function(result) {
|
68
|
+
return this.fileNode(result);
|
69
|
+
}, this));
|
70
|
+
};
|
71
|
+
FilesPage.prototype.updateFileNode = function(file) {
|
72
|
+
var node, size, time;
|
73
|
+
node = $("#files li[data-id='" + file.id + "']");
|
74
|
+
size = this.size(file.size);
|
75
|
+
time = this.date(file.created_at);
|
76
|
+
node.data('file', file);
|
77
|
+
$('h2', node).text(file.name);
|
78
|
+
$('.size', node).text(size);
|
79
|
+
$('.time', node).text(time);
|
80
|
+
node.attr('data-name', file.name);
|
81
|
+
node.attr('data-size', size);
|
82
|
+
return node.attr('data-created', time);
|
83
|
+
};
|
84
|
+
FilesPage.prototype.fileNode = function(file) {
|
85
|
+
var label, node, _i, _len, _ref, _results;
|
86
|
+
if ($("#files li[data-id='" + file.id + "']").length > 0) {
|
87
|
+
this.updateFileNode(file);
|
88
|
+
return;
|
89
|
+
}
|
90
|
+
node = $("<li data-id=\"" + file.id + "\">\n <div class=\"file-icon\">\n <span class=\"size\"></span>\n </div>\n <h2></h2>\n <footer>\n <span class=\"time\"></span>\n <ul class=\"labels\"></ul>\n <form class=\"add-label\">\n <div class=\"add-label-button\"></div>\n <input type=\"text\" placeholder=\"Label\" style=\"display:none;\"/>\n </form>\n </footer>\n <form class=\"file-form\">\n <fieldset>\n <input class=\"cancel\" type=\"submit\" value=\"Delete\"/>\n </fieldset>\n </form>\n</li>").appendTo('#files');
|
91
|
+
new Button($('.file-icon', node).get(0), ICONS.page2, {
|
92
|
+
scale: 1.0,
|
93
|
+
translation: '-2 0',
|
94
|
+
'stroke-width': 0.1,
|
95
|
+
opacity: 1.0
|
96
|
+
});
|
97
|
+
new Button($('.add-label-button', node).get(0), ICONS.plus, {
|
98
|
+
translation: '-10 -10',
|
99
|
+
scale: 0.5
|
100
|
+
});
|
101
|
+
$('form.file-form', node).submit(__bind(function() {
|
102
|
+
return this.deleteFile(node);
|
103
|
+
}, this));
|
104
|
+
$('form.add-label', node).submit(__bind(function() {
|
105
|
+
return this.addLabel(node);
|
106
|
+
}, this));
|
107
|
+
$('.add-label-button', node).click(function() {
|
108
|
+
return $('form.add-label input[type="text"]', node).show();
|
109
|
+
});
|
110
|
+
this.updateFileNode(file);
|
111
|
+
_ref = file.labels;
|
112
|
+
_results = [];
|
113
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
114
|
+
label = _ref[_i];
|
115
|
+
_results.push(this.labelNode(node, label));
|
116
|
+
}
|
117
|
+
return _results;
|
118
|
+
};
|
119
|
+
FilesPage.prototype.labelNode = function(node, label) {
|
120
|
+
var item, labels;
|
121
|
+
labels = $('.labels', node);
|
122
|
+
item = $("<li data-name=\"\">\n <span class=\"text\"></span>\n <div class=\"remove\"></div>\n</li>").appendTo(labels);
|
123
|
+
$('.text', item).text(label);
|
124
|
+
item.attr('data-name', label);
|
125
|
+
new Button($('.remove', item).get(0), ICONS.cross, {
|
126
|
+
translation: '-8 -8',
|
127
|
+
scale: 0.5
|
128
|
+
});
|
129
|
+
return $('.remove', item).click(__bind(function() {
|
130
|
+
return this.removeLabel(node, item);
|
131
|
+
}, this));
|
132
|
+
};
|
133
|
+
FilesPage.prototype.addLabel = function(node) {
|
134
|
+
var file, input, label, labels, val, _i, _j, _len, _len2;
|
135
|
+
input = $('form.add-label input[type="text"]', node);
|
136
|
+
input.hide();
|
137
|
+
labels = (function() {
|
138
|
+
var _i, _len, _ref, _results;
|
139
|
+
_ref = input.val().split(/,/);
|
140
|
+
_results = [];
|
141
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
142
|
+
val = _ref[_i];
|
143
|
+
if (val) {
|
144
|
+
_results.push(val);
|
145
|
+
}
|
146
|
+
}
|
147
|
+
return _results;
|
148
|
+
})();
|
149
|
+
input.val('');
|
150
|
+
file = node.data('file');
|
151
|
+
for (_i = 0, _len = labels.length; _i < _len; _i++) {
|
152
|
+
label = labels[_i];
|
153
|
+
file.labels.push(label);
|
154
|
+
}
|
155
|
+
this.api.save(FILES, file, function(result) {});
|
156
|
+
for (_j = 0, _len2 = labels.length; _j < _len2; _j++) {
|
157
|
+
label = labels[_j];
|
158
|
+
this.labelNode(node, label);
|
159
|
+
this.updateLabelCount(label, 1);
|
160
|
+
}
|
161
|
+
return false;
|
162
|
+
};
|
163
|
+
FilesPage.prototype.removeLabel = function(node, item) {
|
164
|
+
var file, label, remove;
|
165
|
+
file = node.data('file');
|
166
|
+
remove = item.attr('data-name');
|
167
|
+
file.labels = (function() {
|
168
|
+
var _i, _len, _ref, _results;
|
169
|
+
_ref = file.labels;
|
170
|
+
_results = [];
|
171
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
172
|
+
label = _ref[_i];
|
173
|
+
if (label !== remove) {
|
174
|
+
_results.push(label);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
return _results;
|
178
|
+
})();
|
179
|
+
this.api.save(FILES, file, function(result) {});
|
180
|
+
item.fadeOut(200, function() {
|
181
|
+
return item.remove();
|
182
|
+
});
|
183
|
+
return this.updateLabelCount(remove, -1);
|
184
|
+
};
|
185
|
+
FilesPage.prototype.updateLabelCount = function(name, inc) {
|
186
|
+
var count, el, text;
|
187
|
+
el = $("#labels li[data-name='" + name + "'] .count");
|
188
|
+
if (el.length > 0) {
|
189
|
+
count = parseInt(el.text().split(' ')[0]) + inc;
|
190
|
+
text = count === 1 ? 'file' : 'files';
|
191
|
+
return el.text("" + count + " " + text);
|
192
|
+
} else {
|
193
|
+
return this.labelNodeList({
|
194
|
+
name: name,
|
195
|
+
size: 1
|
196
|
+
});
|
197
|
+
}
|
198
|
+
};
|
199
|
+
FilesPage.prototype.deleteFile = function(node) {
|
200
|
+
this.api.remove(FILES, node.attr('data-id'), __bind(function(result) {
|
201
|
+
var label, _i, _len, _ref;
|
202
|
+
_ref = node.data('file').labels;
|
203
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
204
|
+
label = _ref[_i];
|
205
|
+
this.updateLabelCount(label, -1);
|
206
|
+
}
|
207
|
+
return node.fadeOut(200, function() {
|
208
|
+
return node.remove();
|
209
|
+
});
|
210
|
+
}, this));
|
211
|
+
return false;
|
212
|
+
};
|
213
|
+
FilesPage.prototype.date = function(date) {
|
214
|
+
var day, month;
|
215
|
+
date = new Date(date);
|
216
|
+
day = 'Sun Mon Tue Wed Thu Fri Sat'.split(' ')[date.getDay()];
|
217
|
+
month = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' ')[date.getMonth()];
|
218
|
+
return "" + day + ", " + (date.getDate()) + " " + month + ", " + (date.getFullYear()) + " @ " + (date.getHours()) + ":" + (date.getMinutes());
|
219
|
+
};
|
220
|
+
FilesPage.prototype.size = function(bytes) {
|
221
|
+
var fmt, gb, kb, mb;
|
222
|
+
kb = bytes / 1024;
|
223
|
+
mb = kb / 1024;
|
224
|
+
gb = mb / 1024;
|
225
|
+
fmt = function(num) {
|
226
|
+
if (num >= 100) {
|
227
|
+
return Math.round(num);
|
228
|
+
} else {
|
229
|
+
return num.toFixed(1).replace('.0', '');
|
230
|
+
}
|
231
|
+
};
|
232
|
+
if (kb < 1) {
|
233
|
+
return "" + bytes + " b";
|
234
|
+
} else if (mb < 1) {
|
235
|
+
return "" + (fmt(kb)) + " k";
|
236
|
+
} else if (gb < 1) {
|
237
|
+
return "" + (fmt(mb)) + " m";
|
238
|
+
} else {
|
239
|
+
return "" + (fmt(gb)) + " g";
|
240
|
+
}
|
241
|
+
};
|
242
|
+
FilesPage.prototype.draw = function() {
|
243
|
+
var fn, layout;
|
244
|
+
if (!this.session.connected()) {
|
245
|
+
window.location.hash = '';
|
246
|
+
return;
|
247
|
+
}
|
248
|
+
$('body').attr('id', 'files-page');
|
249
|
+
$('#container').hide().empty();
|
250
|
+
$("<div id=\"alpha\" class=\"sidebar column y-fill\">\n <h2>Labels</h2>\n <ul id=\"labels\" class=\"selectable scroll y-fill\"></ul>\n <div id=\"alpha-controls\" class=\"controls\"></div>\n</div>\n<div id=\"beta\" class=\"primary column x-fill y-fill\">\n <h2 id=\"files-title\">Files <div id=\"search-files-icon\"></div></h2>\n <div id=\"search-files-form\"></div>\n <ul id=\"files\" class=\"scroll y-fill\"></ul>\n</div>\n<div id=\"charlie\" class=\"sidebar column y-fill\">\n <h2>Uploads</h2>\n <div id=\"upload-dnd\" class=\"float\">Drag files here to upload.</div>\n <ul id=\"uploads\" class=\"scroll y-fill\"></ul>\n <div id=\"charlie-controls\" class=\"controls\">\n <form id=\"file-form\">\n <input id=\"open-file-chooser\" type=\"submit\" value=\"Select files to upload\"/>\n <input id=\"file-chooser\" type=\"file\" multiple=\"true\" />\n </form>\n </div>\n</div>").appendTo('#container');
|
251
|
+
if (this.api.user.permissions.files) {
|
252
|
+
$('#file-chooser').change(__bind(function(event) {
|
253
|
+
this.uploads.queue(event.target.files);
|
254
|
+
return $('#file-chooser').val('');
|
255
|
+
}, this));
|
256
|
+
$('#file-form').submit(function() {
|
257
|
+
$('#file-chooser').click();
|
258
|
+
return false;
|
259
|
+
});
|
260
|
+
$('#upload-dnd').bind('dragenter', function(event) {
|
261
|
+
event.stopPropagation();
|
262
|
+
event.preventDefault();
|
263
|
+
return $('#upload-dnd').css('color', '#444');
|
264
|
+
});
|
265
|
+
$('#upload-dnd').bind('dragleave', function(event) {
|
266
|
+
return $('#upload-dnd').css('color', '#ababab');
|
267
|
+
});
|
268
|
+
$('#upload-dnd').bind('dragover', function(event) {
|
269
|
+
event.stopPropagation();
|
270
|
+
return event.preventDefault();
|
271
|
+
});
|
272
|
+
$('#upload-dnd').bind('drop', __bind(function(event) {
|
273
|
+
event.stopPropagation();
|
274
|
+
event.preventDefault();
|
275
|
+
$('#upload-dnd').css('color', '#ababab');
|
276
|
+
return this.uploads.queue(event.originalEvent.dataTransfer.files);
|
277
|
+
}, this));
|
278
|
+
} else {
|
279
|
+
$('#upload-dnd').text("Your account cannot upload files.");
|
280
|
+
$('#file-form').remove();
|
281
|
+
}
|
282
|
+
this.findLabels();
|
283
|
+
this.findFiles();
|
284
|
+
$('#container').show();
|
285
|
+
layout = this.resize();
|
286
|
+
fn = function() {
|
287
|
+
layout.resize();
|
288
|
+
return layout.resize();
|
289
|
+
};
|
290
|
+
return new Filter({
|
291
|
+
list: '#files',
|
292
|
+
icon: '#search-files-icon',
|
293
|
+
form: '#search-files-form',
|
294
|
+
attrs: ['data-name', 'data-created'],
|
295
|
+
open: fn,
|
296
|
+
close: fn
|
297
|
+
});
|
298
|
+
};
|
299
|
+
FilesPage.prototype.resize = function() {
|
300
|
+
var a, b, c, dnd, up;
|
301
|
+
a = $('#alpha');
|
302
|
+
b = $('#beta');
|
303
|
+
c = $('#charlie');
|
304
|
+
up = $('#uploads');
|
305
|
+
dnd = $('#upload-dnd');
|
306
|
+
return new Layout(function() {
|
307
|
+
c.css('left', a.width() + b.width());
|
308
|
+
dnd.height(up.height());
|
309
|
+
return dnd.css('line-height', up.height() + 'px');
|
310
|
+
});
|
311
|
+
};
|
312
|
+
Uploads = (function() {
|
313
|
+
function Uploads(options) {
|
314
|
+
this.session = options.session;
|
315
|
+
this.serviceJid = options.jid;
|
316
|
+
this.size = options.size;
|
317
|
+
this.complete = options.complete;
|
318
|
+
this.uploads = [];
|
319
|
+
this.sending = null;
|
320
|
+
}
|
321
|
+
Uploads.prototype.queue = function(files) {
|
322
|
+
var file, _i, _len;
|
323
|
+
for (_i = 0, _len = files.length; _i < _len; _i++) {
|
324
|
+
file = files[_i];
|
325
|
+
if (!this.find(file)) {
|
326
|
+
this.add(file);
|
327
|
+
}
|
328
|
+
}
|
329
|
+
return this.process();
|
330
|
+
};
|
331
|
+
Uploads.prototype.add = function(file) {
|
332
|
+
var meter, node;
|
333
|
+
node = this.node(file);
|
334
|
+
meter = $('.meter', node);
|
335
|
+
return this.uploads.push(new Transfer({
|
336
|
+
to: this.serviceJid(),
|
337
|
+
file: file,
|
338
|
+
session: this.session,
|
339
|
+
progress: function(pct) {
|
340
|
+
return meter.css('width', pct + '%');
|
341
|
+
},
|
342
|
+
complete: __bind(function() {
|
343
|
+
this.remove(file);
|
344
|
+
if (this.complete) {
|
345
|
+
this.complete(file);
|
346
|
+
}
|
347
|
+
if (file.name === this.sending.name) {
|
348
|
+
this.sending = null;
|
349
|
+
}
|
350
|
+
return this.process();
|
351
|
+
}, this)
|
352
|
+
}));
|
353
|
+
};
|
354
|
+
Uploads.prototype.process = function() {
|
355
|
+
var upload;
|
356
|
+
if (this.sending) {
|
357
|
+
return;
|
358
|
+
}
|
359
|
+
if (upload = this.uploads[0]) {
|
360
|
+
this.sending = upload.file;
|
361
|
+
return upload.start();
|
362
|
+
} else {
|
363
|
+
return this.sending = null;
|
364
|
+
}
|
365
|
+
};
|
366
|
+
Uploads.prototype.find = function(file) {
|
367
|
+
var up;
|
368
|
+
return ((function() {
|
369
|
+
var _i, _len, _ref, _results;
|
370
|
+
_ref = this.uploads;
|
371
|
+
_results = [];
|
372
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
373
|
+
up = _ref[_i];
|
374
|
+
if (up.file.name === file.name) {
|
375
|
+
_results.push(up);
|
376
|
+
}
|
377
|
+
}
|
378
|
+
return _results;
|
379
|
+
}).call(this)).shift();
|
380
|
+
};
|
381
|
+
Uploads.prototype.remove = function(file) {
|
382
|
+
var node, up;
|
383
|
+
this.uploads = (function() {
|
384
|
+
var _i, _len, _ref, _results;
|
385
|
+
_ref = this.uploads;
|
386
|
+
_results = [];
|
387
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
388
|
+
up = _ref[_i];
|
389
|
+
if (up.file.name !== file.name) {
|
390
|
+
_results.push(up);
|
391
|
+
}
|
392
|
+
}
|
393
|
+
return _results;
|
394
|
+
}).call(this);
|
395
|
+
node = $("#uploads li[data-file='" + file.name + "']");
|
396
|
+
return node.fadeOut(200, function() {
|
397
|
+
return node.remove();
|
398
|
+
});
|
399
|
+
};
|
400
|
+
Uploads.prototype.node = function(file) {
|
401
|
+
var node;
|
402
|
+
node = $("<li data-file=\"\" style=\"display:none;\">\n <form class=\"inset\">\n <h2></h2>\n <div class=\"progress\">\n <div class=\"meter\"></div>\n <span class=\"text\">" + (this.size(file.size)) + "</span>\n <div class=\"cancel\"></div>\n </div>\n </form>\n</li>").appendTo('#uploads');
|
403
|
+
node.fadeIn(200);
|
404
|
+
$('h2', node).text(file.name);
|
405
|
+
node.attr('data-file', file.name);
|
406
|
+
new Button($('.cancel', node).get(0), ICONS.cross, {
|
407
|
+
translation: '-8 -8',
|
408
|
+
scale: 0.5
|
409
|
+
});
|
410
|
+
$('.cancel', node).click(__bind(function() {
|
411
|
+
return this.cancel(file);
|
412
|
+
}, this));
|
413
|
+
return node;
|
414
|
+
};
|
415
|
+
Uploads.prototype.cancel = function(file) {
|
416
|
+
var upload;
|
417
|
+
if (upload = this.find(file)) {
|
418
|
+
return upload.stop();
|
419
|
+
}
|
420
|
+
};
|
421
|
+
return Uploads;
|
422
|
+
})();
|
423
|
+
return FilesPage;
|
424
|
+
})();
|
@@ -0,0 +1,27 @@
|
|
1
|
+
$(function() {
|
2
|
+
var buttons, icon, label, nav, pages, session;
|
3
|
+
session = new Session();
|
4
|
+
nav = new NavBar(session);
|
5
|
+
nav.draw();
|
6
|
+
buttons = {
|
7
|
+
Systems: ICONS.commandline,
|
8
|
+
Services: ICONS.magic,
|
9
|
+
Files: ICONS.page2,
|
10
|
+
Setup: ICONS.gear2,
|
11
|
+
Logout: ICONS.power
|
12
|
+
};
|
13
|
+
for (label in buttons) {
|
14
|
+
icon = buttons[label];
|
15
|
+
nav.addButton(label, icon);
|
16
|
+
}
|
17
|
+
pages = {
|
18
|
+
'/systems': new SystemsPage(session),
|
19
|
+
'/services': new ServicesPage(session),
|
20
|
+
'/files': new FilesPage(session),
|
21
|
+
'/setup': new SetupPage(session),
|
22
|
+
'/logout': new LogoutPage(session),
|
23
|
+
'default': new LoginPage(session, '/systems/')
|
24
|
+
};
|
25
|
+
new Router(pages).draw();
|
26
|
+
return nav.select($('#nav-link-systems').parent());
|
27
|
+
});
|