From 18655f80a781cca1bbdc1e02c65a269b05fc125f Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 5 Feb 2013 13:05:59 -0800 Subject: [PATCH] #268: Admin UI mockup, additional styling and images. Refactor naming and JS. --- guacamole/src/main/webapp/admin.xhtml | 143 ++++++++ .../images/action-icons/guac-config.png | Bin 0 -> 1063 bytes .../images/action-icons/guac-delete.png | Bin 0 -> 611 bytes .../images/action-icons/guac-monitor-add.png | Bin 0 -> 703 bytes .../images/action-icons/guac-user-add.png | Bin 0 -> 971 bytes .../webapp/images/user-icons/guac-user.png | Bin 0 -> 1049 bytes guacamole/src/main/webapp/scripts/guac-ui.js | 243 ++++++++++++- guacamole/src/main/webapp/scripts/root-ui.js | 102 ------ .../src/main/webapp/styles/animation.css | 35 ++ guacamole/src/main/webapp/styles/ui.css | 328 ++++++++++++++++++ 10 files changed, 748 insertions(+), 103 deletions(-) create mode 100644 guacamole/src/main/webapp/admin.xhtml create mode 100644 guacamole/src/main/webapp/images/action-icons/guac-config.png create mode 100644 guacamole/src/main/webapp/images/action-icons/guac-delete.png create mode 100644 guacamole/src/main/webapp/images/action-icons/guac-monitor-add.png create mode 100644 guacamole/src/main/webapp/images/action-icons/guac-user-add.png create mode 100644 guacamole/src/main/webapp/images/user-icons/guac-user.png create mode 100644 guacamole/src/main/webapp/styles/animation.css create mode 100644 guacamole/src/main/webapp/styles/ui.css diff --git a/guacamole/src/main/webapp/admin.xhtml b/guacamole/src/main/webapp/admin.xhtml new file mode 100644 index 000000000..df6661b05 --- /dev/null +++ b/guacamole/src/main/webapp/admin.xhtml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + Guacamole ${project.version} + + + + +

Administration

+ +

Users

+
+ +

+ Click or tap on a user below to manage that user. Depending + on your access level, users can be added and deleted, and their + passwords can be changed. +

+ +
+
+
+ +
+ +

Connections

+
+ +

+ Click or tap on a connection below to manage that connection. + Depending on your access level, connections can be added and + deleted, and their properties (protocol, hostname, port, etc.) + can be changed. +

+ +
+
+
+ +
+
Another connection
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Protocol: + +
Hostname:
Password:
Port:
Read-only:
Swap red/blue:
+
+
+ + + +
+
+ +
+ +
+ Guacamole ${project.version} +
+ + + + + + + + + + + diff --git a/guacamole/src/main/webapp/images/action-icons/guac-config.png b/guacamole/src/main/webapp/images/action-icons/guac-config.png new file mode 100644 index 0000000000000000000000000000000000000000..eb91fc0a09ffb074b11a9f07a7a257d9bbb87757 GIT binary patch literal 1063 zcmV+?1laqDP)D(RKgK%+Br_cMlxUyJx=hoo{w$ zW_Na#)|x6?qih0YTP;A@1j@DtMJH5BO#&+Bu-01d6w0T_K~O0*4SY-qd!e=dR0JO= z{t|fODaM->b_OV=dVwS0VM^$4U`T6ynm?;z&wzQ-i$`MSbLMhoMGCNxQ*1WVT01%L z7?=gR6Ji>`9IydsOW%;TjRgE|;qchGjts?r6QX~B7D2BK%JBhU2{>>lJnRR8H6Yl7 zlB*@TwQz9~A#3qrZv)%Fxrf5TelFPUnBz_&_$>Y|xU~rPsdy(5Y-WL{z?emRSvE$% z)yRw&LQ1J_;3v@Q#_P&{0K34UIKVJ41WW*rGUA^S448k7qAkaO7H+5IG0+5NNS@Xj z64R76F1cEH4uT7oWX^yUpwD5p>65l+mN^&l6kw3}X(;Slz=&<(5jjT$%OqzTS&QT% zfDqa?AhHVd7-01S{RVM8f|-_g+qxdh;s;1yASSX=&HlVjrv?bAd! zM^=n^39w{v+TZGVpbJ9J| zBJf5?9vBZum}#;IFqcAjC8qcbhvGYa5hKD%O1rr{1W3B2Jtj2O$!YJ>^HFC)R|vb0 z_D($G--PxwM-ic08CnvJ0>*f5KL#jitqSh#Gq`uT%HWq8+A7rw`mb)yISjZ=(p#V z7$$ZDQ*wT_#JE+PkB6d%5x+h2fNO$zloiyw07|KTVAKO{*hU3AHn)paesk1^0K?b+ z(OUlk_C4T+ZC|isbGw*#0mQaE;F@3#Wd)5AKwDxwQA&kzK0ESBvKyF^bHWnic5U@S zs9p-!H$$cZRQ`6j+7Cn|d37I&34v-q6crMcek@+?jS=dtvHQ0qW_s2><=7vPHfwzX`lF z4F90Dew8PmjurV>{9R75nXLX`qKG5_Qqa0V=z3AbL-9L9?>)tMvqHZbgNlDPcNeYR h94(tb*;aW0{sBL^OvHYxG3WpQ002ovPDHLkV1mBe*6#oS literal 0 HcmV?d00001 diff --git a/guacamole/src/main/webapp/images/action-icons/guac-delete.png b/guacamole/src/main/webapp/images/action-icons/guac-delete.png new file mode 100644 index 0000000000000000000000000000000000000000..925e958319ca538f8466ed012f93fc42957c3b23 GIT binary patch literal 611 zcmV-p0-XJcP)&i(c77RiG&1 z#-cv;CCdbK3PkZeCxJ~%$;>cwJgEy%$0G^iB_RTyDxnhop@gkP*UAMc5=ihrV=WQDT-YU{RSoh2)N6NB zh-%Hgu7*N*FJDOo{B8l!1*+hS1Vk08gfA8lAmK9)3A{@{fCL%5TR>+L>h3nZ6FZSm z{k%~nKrDgtuvMEtB!Tw0O%c#o0=L(|O4LXKz1u_;5G*04)y7WvO9JZ#$8xTaX6y9t z2G5_sAn^VF2{wQakuVxOUBZa)R0*TP(e6<8M{8%k9GW=Lg(a1uT66Ek| z30=S|C3FL?TCq(j2-w#pVrIPPZY9TJYeUH%^l^BkDCBVqU>Gbtx3j(kw*)f_iD x%*Y3~p3UsVHQy`XC^7xJ!Bc>`0Ch|+;0yH|yZa)&SRw!b002ovPDHLkV1oYC{7wJ> literal 0 HcmV?d00001 diff --git a/guacamole/src/main/webapp/images/action-icons/guac-monitor-add.png b/guacamole/src/main/webapp/images/action-icons/guac-monitor-add.png new file mode 100644 index 0000000000000000000000000000000000000000..0c9ea962c03ae16d487742d6330e9e59b327f9f7 GIT binary patch literal 703 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4tkr$zs*;lae(sq!GdFxb5Yle>`P}JqGw0ql^yHa&EV{w`DnmZw zy%6R-tQE%3brYh_ys;@*q`F5v(^%_$;7zu(Ig&dr3&l+@QC55ZV7i0p0hkV+dku@W zIT}ZEw}>}R*4-HUzC(?r8`; zmTfG$yx}$HXW6a^jLHdtm%?5-o_!G3D(drnU&Pjg~>VxuNj%pzMO zxCZP-sRz0TW@j~QXUIo#xRgN0+_M(%cJ}N{SNdZ6VAV`p=6lBfvgUMMJ}|lECtqve zg^MMJygk4FmRfTS6qF_h^z#LO-*{WRq3xso@<|nUzc+XvkbYpkZ~u{f%>Fa)M7>=7 zcehe<+VPKTIjbiHC0&c8S~Yk3eNWY5}RK3`i{?H4Se-T^)mxIt#kz08?}NegLlv#%|BMC)Aq(vBbq&+DkGW3Y&-9F9bkM?lgX zpbcmNo&a5D))ym}FTo6uv>iA|Ht}ggy89))0B!&$%&a$5UT@6Is{vDhvw)Rs-M}V? zJeLb%cDm~K+5;qQ0G-qz}Wyv(|}9BY?tA{VPL;&{!lm{gOV-+ zyFK&w0;|ld+cSDcN!Cv;rh`0V@LP*kWck1I8;&&CW||0+t2V zu{LnL(zqyHq3SX>Nv z99#uFj1aRFE(W{;z6I7XdJHhL0pM;x4FkZPfbnX=^#*nb2vy&oHnW$3V%3gE8GMBD zC2(GQ1x)ZQ$$gqnF*F9a4QzDuegN2LX7?S(2f?`r`MVeF0M0uMe+z6)J$beJLw2oQ11u$5VLfEW+(Y1oncWMLFc49`3rK1KmIKW| z7x2!^eg;nz051b1Eh76^(FRNhW&o{ZZ-oc%FMYtLLG3l!272AhJ~|5sK+Oh7S^~5K z+ko}Jc#r&jzyshGaLvpfdBk#~hK+6|a25EC|M~yF)(>0&=8xniSa$M9fiICJKD70a z{nJw)1^_3?E-fQ5`G4&z(4O1?VDAV|d~kaMOpa|p?oCkAMBsQ{{|K-EI1oEY(N%ae zurRiOVOSSCL6HGVVka-b;@Am_3}}v>yadrT6d5oOJ9!DBYbY`xe34K)(KS>nAZ79r tR0hOO(C`KneUIw^j>Q%*4AFnB`vWgkjnxI44G#bS002ovPDHLkV1l$am#_c; literal 0 HcmV?d00001 diff --git a/guacamole/src/main/webapp/images/user-icons/guac-user.png b/guacamole/src/main/webapp/images/user-icons/guac-user.png new file mode 100644 index 0000000000000000000000000000000000000000..5270040402ee65977a7f0a83d4acbdb0ff136481 GIT binary patch literal 1049 zcmV+!1m^pRP)~s~KzZ7LYgU2IMUuZ>+0iVD^1^{iq zv}5v1F%7hN>y;?l1tPK^7y-7pk^YX)K)b3=dJ(!!gCf!h43S;(MDC&3mJ2-B0fRun zkuM2_*p?5Rp8GERpZR}9S5=GwBC-aU0FIi7O2-r6xT-E%NIV{aZYrNVvCVEPiH89f z95`}o+w=&Ch!EECJFG&=#5=+Qsq7@IJ>UTOB~NVofQ7(nz%FBb512Gq4cKX{?*Wqr zs{zf%`W`T8up02mSlqg(=04~Pxl zw{RG7-;zA|EQRknaOBpu$J^j$Ub#Z6WlJmy=^>2DS>rp<c#?g^^uW1x?)U6mCS=!uI$ZoyQWG!$8=m1Uw?f4y(E&!9j zc#MatI_^R2@iKG*xCC6Ja+{=!ghBEya8p&M%4RZ*?!CZ0!T?t3gVE*j1GoVktjIJ7 z9KmOP_l_^XHDGHd1`ysGt^i-FAlbB-1dh2HK)6phSOv+gG~NImE(Q>;yWOgSq)Lrh z;FN~}*Q+3za^r!?0K$OxtqKycM6bnw+f|T&H73$>Ok4m&GG0lKHufBL=ds0D~0mTQ0+C*Y5X$F`sAXXU? zb6NHOGgR*ZDV6GDKn6ncLcIqh71RwVr&0}~Za`8&+S}ks!ruP>fDu)FRIK0^?->wD TbN@Ht00000NkvXXu0mjf^)beV literal 0 HcmV?d00001 diff --git a/guacamole/src/main/webapp/scripts/guac-ui.js b/guacamole/src/main/webapp/scripts/guac-ui.js index f543a86ee..a84e8a956 100644 --- a/guacamole/src/main/webapp/scripts/guac-ui.js +++ b/guacamole/src/main/webapp/scripts/guac-ui.js @@ -392,4 +392,245 @@ GuacUI.DraggableComponent = function(element) { */ this.onmove = null; -}; \ No newline at end of file +}; + +/** + * A connection UI object which can be easily added to a list of connections + * for sake of display. + */ +GuacUI.Connection = function(connection) { + + /** + * The actual connection associated with this connection UI element. + */ + this.connection = connection; + + function createElement(tagname, classname) { + var new_element = document.createElement(tagname); + new_element.className = classname; + return new_element; + } + + // Create connection display elements + var element = createElement("div", "connection"); + var caption = createElement("div", "caption"); + var protocol = createElement("div", "protocol"); + var name = createElement("span", "name"); + var protocol_icon = createElement("div", "icon " + connection.protocol); + var thumbnail = createElement("div", "thumbnail"); + var thumb_img; + + // Get URL + var url = "client.xhtml?id=" + encodeURIComponent(connection.id); + + // Create link to client + element.onclick = function() { + + // Attempt to focus existing window + var current = window.open(null, connection.id); + + // If window did not already exist, set up as + // Guacamole client + if (!current.GuacUI) + window.open(url, connection.id); + + }; + + // Add icon + protocol.appendChild(protocol_icon); + + // Set name + name.textContent = connection.id; + + // Assemble caption + caption.appendChild(protocol); + caption.appendChild(name); + + // Assemble connection icon + element.appendChild(thumbnail); + element.appendChild(caption); + + // Add screenshot if available + var thumbnail_url = GuacamoleHistory.get(connection.id).thumbnail; + if (thumbnail_url) { + + // Create thumbnail element + thumb_img = document.createElement("img"); + thumb_img.src = thumbnail_url; + thumbnail.appendChild(thumb_img); + + } + + /** + * Returns the DOM element representing this connection. + */ + this.getElement = function() { + return element; + }; + + /** + * Returns whether this connection has an associated thumbnail. + */ + this.hasThumbnail = function() { + return thumb_img && true; + }; + + /** + * Sets the thumbnail URL of this existing connection. Note that this will + * only work if the connection already had a thumbnail associated with it. + */ + this.setThumbnail = function(url) { + + // If no image element, create it + if (!thumb_img) { + thumb_img = document.createElement("img"); + thumb_img.src = url; + thumbnail.appendChild(thumb_img); + } + + // Otherwise, set source of existing + else + thumb_img.src = url; + + }; + +}; + +/** + * An arbitrary table-based form. + */ +GuacUI.Form = function() { + + var element = GuacUI.createElement("table"); + + /** + * Returns the DOM element representing this form. + */ + this.getElement = function() { + return element; + }; + + this.addField = function(title, type, value) { + + // Add elements + var row = GuacUI.createChildElement(element, "tr"); + var header = GuacUI.createChildElement(row, "th"); + var cell = GuacUI.createChildElement(row, "td"); + var input = GuacUI.createChildElement(cell, "input"); + + // Set title + header.textContent = title; + + // Set type and value + input.setAttribute("type", type); + if (value) input.setAttribute("value", value); + + }; + +}; + +/** + * A user UI object. + */ +GuacUI.User = function(username) { + + /** + * This user's username. + */ + this.username = username; + + var user_type = "normal"; + + // Create connection display elements + var element = GuacUI.createElement("div", "user"); + var caption = GuacUI.createChildElement(element ,"div", "caption"); + var type = GuacUI.createChildElement(caption, "div", "type"); + var name = GuacUI.createChildElement(caption, "span", "name"); + GuacUI.createChildElement(type, "div", "icon " + user_type); + + // Get URL + var url = "user.xhtml?name=" + encodeURIComponent(username); + + // Create link to client + element.onclick = function() { + + // Attempt to focus existing window + var current = window.open(null, username); + + // If window did not already exist, set up as + // Guacamole client + if (!current.GuacUI) + window.open(url, username); + + }; + + // Set name + name.textContent = username; + + /** + * Returns the DOM element representing this connection. + */ + this.getElement = function() { + return element; + }; + +}; + + +/** + * An editable user UI object. + */ +GuacUI.EditableUser = function(username) { + + /** + * This user's username. + */ + this.username = username; + + /** + * Current status of edit mode. + */ + this.edit = false; + + // Create contained user + var user = new GuacUI.User(username); + var element = user.getElement(); + GuacUI.addClass(element, "editable"); + + // Fields + var fields = GuacUI.createChildElement(element, "div", "fields"); + var form = new GuacUI.Form(); + + // Add form + fields.appendChild(form.getElement()); + + // Add fields + form.addField("Password:", "password", "123412341234"); + form.addField("Re-enter Password:", "password", "123412341234"); + + /** + * Returns the DOM element representing this connection. + */ + this.getElement = function() { + return element; + }; + + /** + * Sets/unsets edit mode. When edit mode is on, the user's properties + * will be visible and editable. + */ + this.setEditMode = function(enabled) { + + // Set edit mode + this.edit = enabled; + + // Alter class accordingly + if (enabled) + GuacUI.addClass(element, "edit"); + else + GuacUI.removeClass(element, "edit"); + + }; + +}; + diff --git a/guacamole/src/main/webapp/scripts/root-ui.js b/guacamole/src/main/webapp/scripts/root-ui.js index 5beb8cd90..51ba19e27 100644 --- a/guacamole/src/main/webapp/scripts/root-ui.js +++ b/guacamole/src/main/webapp/scripts/root-ui.js @@ -91,108 +91,6 @@ GuacamoleRootUI.login = function(username, password) { }; -/** - * A connection UI object which can be easily added to a list of connections - * for sake of display. - */ -GuacamoleRootUI.Connection = function(connection) { - - /** - * The actual connection associated with this connection UI element. - */ - this.connection = connection; - - function createElement(tagname, classname) { - var new_element = document.createElement(tagname); - new_element.className = classname; - return new_element; - } - - // Create connection display elements - var element = createElement("div", "connection"); - var caption = createElement("div", "caption"); - var protocol = createElement("div", "protocol"); - var name = createElement("span", "name"); - var protocol_icon = createElement("div", "icon " + connection.protocol); - var thumbnail = createElement("div", "thumbnail"); - var thumb_img; - - // Get URL - var url = "client.xhtml?id=" + encodeURIComponent(connection.id); - - // Create link to client - element.onclick = function() { - - // Attempt to focus existing window - var current = window.open(null, connection.id); - - // If window did not already exist, set up as - // Guacamole client - if (!current.GuacUI) - window.open(url, connection.id); - - }; - - // Add icon - protocol.appendChild(protocol_icon); - - // Set name - name.textContent = connection.id; - - // Assemble caption - caption.appendChild(protocol); - caption.appendChild(name); - - // Assemble connection icon - element.appendChild(thumbnail); - element.appendChild(caption); - - // Add screenshot if available - var thumbnail_url = GuacamoleHistory.get(connection.id).thumbnail; - if (thumbnail_url) { - - // Create thumbnail element - thumb_img = document.createElement("img"); - thumb_img.src = thumbnail_url; - thumbnail.appendChild(thumb_img); - - } - - /** - * Returns the DOM element representing this connection. - */ - this.getElement = function() { - return element; - }; - - /** - * Returns whether this connection has an associated thumbnail. - */ - this.hasThumbnail = function() { - return thumb_img && true; - }; - - /** - * Sets the thumbnail URL of this existing connection. Note that this will - * only work if the connection already had a thumbnail associated with it. - */ - this.setThumbnail = function(url) { - - // If no image element, create it - if (!thumb_img) { - thumb_img = document.createElement("img"); - thumb_img.src = url; - thumbnail.appendChild(thumb_img); - } - - // Otherwise, set source of existing - else - thumb_img.src = url; - - }; - -}; - /** * Set of all thumbnailed connections, indexed by ID. */ diff --git a/guacamole/src/main/webapp/styles/animation.css b/guacamole/src/main/webapp/styles/animation.css new file mode 100644 index 000000000..80bb237a4 --- /dev/null +++ b/guacamole/src/main/webapp/styles/animation.css @@ -0,0 +1,35 @@ + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * fadein: Fade from fully transparent to fully opaque. + */ +@keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} +@-moz-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} +@-webkit-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + diff --git a/guacamole/src/main/webapp/styles/ui.css b/guacamole/src/main/webapp/styles/ui.css new file mode 100644 index 000000000..f7e99f23c --- /dev/null +++ b/guacamole/src/main/webapp/styles/ui.css @@ -0,0 +1,328 @@ + +/* + * Guacamole - Clientless Remote Desktop + * Copyright (C) 2010 Michael Jumper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +@import url('animation.css'); + +* { + -webkit-tap-highlight-color: rgba(0,0,0,0); +} + +input[type=checkbox], input[type=text], textarea { + -webkit-tap-highlight-color: rgba(128,192,128,0.5); +} + +input[type=submit], button { + -webkit-appearance: none; +} + +input[type=text], input[type=password] { + border: 1px solid #777; + -moz-border-radius: 0.2em; + -webkit-border-radius: 0.2em; + -khtml-border-radius: 0.2em; + border-radius: 0.2em; + width: 100%; +} + +button { + + background: #8A6; + border: 1px solid rgba(0, 0, 0, 0.4); + -moz-border-radius: 0.6em; + -webkit-border-radius: 0.6em; + -khtml-border-radius: 0.6em; + border-radius: 0.6em; + + color: white; + text-shadow: -1px -1px rgba(0, 0, 0, 0.3); + font-weight: bold; + font-size: 1.125em; + + box-shadow: inset -1px -1px 0.25em rgba(0, 0, 0, 0.25), + inset 1px 1px 0.25em rgba(255, 255, 255, 0.25), + -1px -1px 0.25em rgba(0, 0, 0, 0.25), + 1px 1px 0.25em rgba(255, 255, 255, 0.25); + + padding: 0.35em; + padding-right: 1em; + padding-left: 1em; + min-width: 5em; + +} + +button:hover { + background: #9C7; +} + +button:active { + + padding-left: 1.1em; + padding-right: 0.9em; + padding-top: 0.45em; + padding-bottom: 0.25em; + + box-shadow: + inset 1px 1px 0.25em rgba(0, 0, 0, 0.25), + -1px -1px 0.25em rgba(0, 0, 0, 0.25), + 1px 1px 0.25em rgba(255, 255, 255, 0.25); +} + +button.danger { + background: #A43; +} + +button.danger:hover { + background: #C54; +} + +body { + background: #EEE; + font-family: FreeSans, Helvetica, Arial, sans-serif; + padding: 0; + margin: 0; +} + +img { + border: none; + vertical-align: middle; +} + +div#version-dialog { + position: fixed; + right: 0; + bottom: 0; + text-align: right; + + font-style: italic; + font-size: 0.75em; + color: black; + opacity: 0.5; + + padding: 0.5em; +} + +h2 { + + padding: 0.5em; + margin: 0; + font-size: 1.5em; + + font-weight: lighter; + text-shadow: 1px 1px white; + + border-top: 1px solid #AAA; + border-bottom: 1px solid #AAA; + background: #DDD; + +} + +h1 { + + margin: 0; + padding: 0.5em; + + font-size: 2em; + vertical-align: middle; + text-align: center; + +} + +div.section { + margin: 0; + padding: 1em; +} + +/* + * List elements + */ + +.user, +.connection { + + display: block; + text-align: left; + padding: 0.1em; + cursor: pointer; + + -moz-border-radius: 0.2em; + -webkit-border-radius: 0.2em; + -khtml-border-radius: 0.2em; + border-radius: 0.2em; + border: 1px solid rgba(0, 0, 0, 0); + + position: relative; + +} + +.connection .thumbnail { + margin: 0.5em; + display: none; +} + +.connection .thumbnail img { + border: 1px solid black; + box-shadow: 1px 1px 5px black; + max-width: 75%; +} + +.user .type, +.connection .protocol { + display: inline-block; +} + +.user .icon, +.connection .icon { + width: 24px; + height: 24px; + background-size: 16px 16px; + -moz-background-size: 16px 16px; + -webkit-background-size: 16px 16px; + -khtml-background-size: 16px 16px; + background-repeat: no-repeat; + background-position: center center; + opacity: 0.5; +} + +.user .caption, +.connection .caption { + display: inline-block; + vertical-align: top; +} + +.user .caption *, +.connection .caption * { + vertical-align: middle; +} + +.user .name, +.connection .name { + color: black; + font-weight: normal; + padding: 0.1em; + margin-left: 0.25em; +} + +/* + * List element edit / non-edit styling + */ + +.user.edit, +.connection.edit { + background: #DEB; + border: 1px solid rgba(0, 0, 0, 0.25); +} + +.user.edit .icon, +.connection.edit .icon { + opacity: 1.0; +} + +.user:not(.edit):hover, +.connection:not(.edit):hover { + background: #CDA; +} + +/* + * List element fields (editing) + */ + +.user .fields, +.connection .fields { + + position: absolute; + display: inline-block; + vertical-align: top; + z-index: 1; + + border: 1px solid rgba(0, 0, 0, 0.1); + background: #DDD; + padding: 0.25em; + margin: 0.25em; + + -moz-border-radius: 0.2em; + -webkit-border-radius: 0.2em; + -khtml-border-radius: 0.2em; + border-radius: 0.2em; + + box-shadow: 0.1em 0.1em 0.2em rgba(0, 0, 0, 0.6); + +} + +.user .fields th, +.connection .fields th { + font-weight: normal; + font-size: 0.8em; +} + +.user:not(.edit) .fields, +.connection:not(.edit) .fields { + display: none; +} + +.user.edit .fields, +.connection.edit .fields { + animation-name: fadein; + -webkit-animation-name: fadein; + animation-duration: 0.125s; + -webkit-animation-duration: 0.125s; +} + +/* + * List element icons + */ + +.user .icon { + background-image: url('../images/user-icons/guac-user.png'); +} + +.user .icon.add { + background-image: url('../images/action-icons/guac-user-add.png'); +} + +.protocol .icon { + background-image: url('../images/protocol-icons/guac-plug.png'); +} + +.protocol .icon.ssh { + background-image: url('../images/protocol-icons/guac-text.png'); +} + +.protocol .icon.add{ + background-image: url('../images/action-icons/guac-monitor-add.png'); +} + +.protocol .icon.vnc, +.protocol .icon.rdp { + background-image: url('../images/protocol-icons/guac-monitor.png'); +} + +/* + * Settings formatting + */ + +.settings dt { + border-bottom: 1px dotted #AAA; + padding-bottom: 0.25em; +} + +.settings dd { + margin: 1.5em; + margin-left: 2.5em; + font-size: 0.75em; +}