diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/APIConnection.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/APIConnection.java index 57bf4a9c8..7eda11740 100644 --- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/APIConnection.java +++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/connection/APIConnection.java @@ -22,10 +22,12 @@ package org.glyptodon.guacamole.net.basic.rest.connection; +import java.util.List; import java.util.Map; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.glyptodon.guacamole.GuacamoleException; import org.glyptodon.guacamole.net.auth.Connection; +import org.glyptodon.guacamole.net.auth.ConnectionRecord; import org.glyptodon.guacamole.net.basic.rest.connectiongroup.APIConnectionGroup; import org.glyptodon.guacamole.protocol.GuacamoleConfiguration; @@ -62,6 +64,11 @@ public class APIConnection { */ private Map parameters; + /** + * The count of currently active users for this connection. + */ + private int activeUsers; + /** * Create an empty APIConnection. */ @@ -86,6 +93,14 @@ public class APIConnection { this.parentIdentifier = connection.getParentIdentifier(); if (this.parentIdentifier == null) this.parentIdentifier = APIConnectionGroup.ROOT_IDENTIFIER; + + // Set the number of currently active users + this.activeUsers = 0; + + for (ConnectionRecord history : connection.getHistory()) { + if (history.isActive()) + this.activeUsers++; + } // Set protocol from configuration GuacamoleConfiguration configuration = connection.getConfiguration(); @@ -173,5 +188,21 @@ public class APIConnection { public void setProtocol(String protocol) { this.protocol = protocol; } + + /** + * Returns the number of currently active users for this connection. + * @return The number of currently active users for this connection. + */ + public int getActiveUsers() { + return activeUsers; + } + + /** + * Set the number of currently active users for this connection. + * @param activeUsers The number of currently active users for this connection. + */ + public void setActiveUsers(int activeUsers) { + this.activeUsers = activeUsers; + } } diff --git a/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js b/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js index 08a78b949..3f5260359 100644 --- a/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js +++ b/guacamole/src/main/webapp/app/groupList/types/GroupListItem.js @@ -100,6 +100,14 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio * @type Boolean */ this.isExpanded = template.isExpanded; + + /** + * The number of currently active users for this connection. This field + * has no meaning for a connection group, and may be null or undefined. + * + * @type Number + */ + this.activeUsers = template.activeUsers; /** * The connection or connection group whose data is exposed within @@ -134,6 +142,9 @@ angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', functio // Type information isConnection : true, isConnectionGroup : false, + + // Count of currently active users + activeUsers : connection.activeUsers, // Wrapped item wrappedItem : connection diff --git a/guacamole/src/main/webapp/app/home/templates/connection.html b/guacamole/src/main/webapp/app/home/templates/connection.html index f9fc9c554..6e8bfcc28 100644 --- a/guacamole/src/main/webapp/app/home/templates/connection.html +++ b/guacamole/src/main/webapp/app/home/templates/connection.html @@ -21,7 +21,7 @@ THE SOFTWARE. --> -
+
@@ -30,6 +30,11 @@ {{item.name}} + + + + {{'HOME.INFO_ACTIVE_USER_COUNT' | translate:'{USERS: item.activeUsers}'}} +
diff --git a/guacamole/src/main/webapp/app/index/styles/font-carlito.css b/guacamole/src/main/webapp/app/index/styles/font-carlito.css index 43ccaaba5..1b54466c0 100644 --- a/guacamole/src/main/webapp/app/index/styles/font-carlito.css +++ b/guacamole/src/main/webapp/app/index/styles/font-carlito.css @@ -41,3 +41,10 @@ font-style: normal; src: url('fonts/carlito/Carlito-Bold.woff') format('woff'); } + +@font-face { + font-family: 'Carlito'; + font-weight: normal; + font-style: italic; + src: url('fonts/carlito/Carlito-Italic.woff') format('woff'); +} diff --git a/guacamole/src/main/webapp/app/index/styles/ui.css b/guacamole/src/main/webapp/app/index/styles/ui.css index 7f839ab01..bba2c9970 100644 --- a/guacamole/src/main/webapp/app/index/styles/ui.css +++ b/guacamole/src/main/webapp/app/index/styles/ui.css @@ -140,6 +140,16 @@ div.section { background: #DEB; } +.caption.active * { + opacity: 0.5; +} + +.caption .activeUserCount { + font-style: italic; + position: absolute; + right: 1em; +} + .list-item:not(.selected) .caption:hover { background: #CDA; } diff --git a/guacamole/src/main/webapp/app/manage/templates/connection.html b/guacamole/src/main/webapp/app/manage/templates/connection.html index b92988048..a1daded4e 100644 --- a/guacamole/src/main/webapp/app/manage/templates/connection.html +++ b/guacamole/src/main/webapp/app/manage/templates/connection.html @@ -21,7 +21,7 @@ THE SOFTWARE. --> -
+
@@ -31,5 +31,10 @@ {{item.name}} + + + {{'MANAGE.INFO_ACTIVE_USER_COUNT' | translate:'{USERS: item.activeUsers}'}} + +
diff --git a/guacamole/src/main/webapp/app/rest/types/Connection.js b/guacamole/src/main/webapp/app/rest/types/Connection.js index 656cf3fab..1a0459d7a 100644 --- a/guacamole/src/main/webapp/app/rest/types/Connection.js +++ b/guacamole/src/main/webapp/app/rest/types/Connection.js @@ -79,6 +79,15 @@ angular.module('rest').factory('Connection', [function defineConnection() { * @type Object. */ this.parameters = template.parameters; + + /** + * The count of currently active users for this connection. This field + * will be returned from the REST API during a get operation, + * but may not be set when doing an update or create operation. + * + * @type Number + */ + this.activeUsers = template.activeUsers; }; diff --git a/guacamole/src/main/webapp/fonts/carlito/Carlito-Italic.woff b/guacamole/src/main/webapp/fonts/carlito/Carlito-Italic.woff new file mode 100644 index 000000000..379b05319 Binary files /dev/null and b/guacamole/src/main/webapp/fonts/carlito/Carlito-Italic.woff differ diff --git a/guacamole/src/main/webapp/translations/en_US.json b/guacamole/src/main/webapp/translations/en_US.json index ec73b5a31..1010cabe9 100644 --- a/guacamole/src/main/webapp/translations/en_US.json +++ b/guacamole/src/main/webapp/translations/en_US.json @@ -11,6 +11,8 @@ "ACTION_NAVIGATE_BACK" : "Back", "ACTION_NAVIGATE_HOME" : "Home", "ACTION_SAVE" : "Save", + + "INFO_ACTIVE_USER_COUNT" : "Currently in use by {USERS} {USERS, plural, one{user} other{users}}.", "NAME" : "Guacamole ${project.version}" @@ -105,6 +107,8 @@ "ACTION_LOGOUT" : "@:APP.ACTION_LOGOUT", "ACTION_MANAGE" : "@:APP.ACTION_MANAGE", + + "INFO_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT", "INFO_NO_RECENT_CONNECTIONS" : "No recent connections.", @@ -139,6 +143,8 @@ "HELP_SHOW_PASSWORD" : "Click to show password", "HELP_HIDE_PASSWORD" : "Click to hide password", "HELP_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.", + + "INFO_ACTIVE_USER_COUNT" : "@:APP.INFO_ACTIVE_USER_COUNT", "SECTION_HEADER_ADMINISTRATION" : "Administration", "SECTION_HEADER_CONNECTIONS" : "Connections",