vines-services 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
});
|