Merge pull request #127 from glyptodon/filter-token

GUAC-1138: Add filter pattern tokenizer.
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js
index 9d59149..fda9e28 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js
@@ -35,6 +35,7 @@
     // Required services
     var $location                = $injector.get('$location');
     var $routeParams             = $injector.get('$routeParams');
+    var $translate               = $injector.get('$translate');
     var authenticationService    = $injector.get('authenticationService');
     var guacNotification         = $injector.get('guacNotification');
     var connectionService        = $injector.get('connectionService');
@@ -101,6 +102,13 @@
     $scope.parameters = null;
 
     /**
+     * The date format for use within the connection history.
+     *
+     * @type String
+     */
+    $scope.historyDateFormat = null;
+
+    /**
      * The usage history of the connection being modified.
      *
      * @type HistoryEntryWrapper[]
@@ -150,6 +158,7 @@
             && $scope.rootGroup            !== null
             && $scope.connection           !== null
             && $scope.parameters           !== null
+            && $scope.historyDateFormat    !== null
             && $scope.historyEntryWrappers !== null
             && $scope.permissions          !== null
             && $scope.canSaveConnection    !== null
@@ -199,7 +208,12 @@
     protocolService.getProtocols().success(function protocolsReceived(protocols) {
         $scope.protocols = protocols;
     });
-   
+
+    // Get history date format
+    $translate('MANAGE_CONNECTION.FORMAT_HISTORY_START').then(function historyDateFormatReceived(historyDateFormat) {
+        $scope.historyDateFormat = historyDateFormat;
+    });
+
     // If we are editing an existing connection, pull its data
     if (identifier) {
 
diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageSessionsController.js b/guacamole/src/main/webapp/app/manage/controllers/manageSessionsController.js
index ac56335..f89f19a 100644
--- a/guacamole/src/main/webapp/app/manage/controllers/manageSessionsController.js
+++ b/guacamole/src/main/webapp/app/manage/controllers/manageSessionsController.js
@@ -32,6 +32,8 @@
     var SortOrder               = $injector.get('SortOrder');
 
     // Required services
+    var $filter                 = $injector.get('$filter');
+    var $translate              = $injector.get('$translate');
     var activeConnectionService = $injector.get('activeConnectionService');
     var authenticationService   = $injector.get('authenticationService');
     var connectionGroupService  = $injector.get('connectionGroupService');
@@ -62,7 +64,7 @@
      */
     $scope.wrapperOrder = new SortOrder([
         'activeConnection.username',
-        'activeConnection.startDate',
+        'startDate',
         'activeConnection.remoteHost',
         'name'
     ]);
@@ -74,6 +76,7 @@
      */
     $scope.filteredWrapperProperties = [
         'activeConnection.username',
+        'startDate',
         'activeConnection.remoteHost',
         'name'
     ];
@@ -95,6 +98,13 @@
     var connections = null;
 
     /**
+     * The date format for use for session-related dates.
+     *
+     * @type String
+     */
+    var sessionDateFormat = null;
+
+    /**
      * Map of all currently-selected active connection wrappers by identifier.
      * 
      * @type Object.<String, ActiveConnectionWrapper>
@@ -143,7 +153,7 @@
     var wrapActiveConnections = function wrapActiveConnections() {
 
         // Abort if not all required data is available
-        if (!activeConnections || !connections)
+        if (!activeConnections || !connections || !sessionDateFormat)
             return;
 
         // Wrap all active connections for sake of display
@@ -155,6 +165,7 @@
 
             $scope.wrappers.push(new ActiveConnectionWrapper(
                 connection.name,
+                $filter('date')(activeConnection.startDate, sessionDateFormat),
                 activeConnection
             )); 
 
@@ -192,6 +203,17 @@
 
     });
 
+    // Get session date format
+    $translate('MANAGE_SESSION.FORMAT_STARTDATE').then(function sessionDateFormatReceived(retrievedSessionDateFormat) {
+
+        // Store received date format
+        sessionDateFormat = retrievedSessionDateFormat;
+
+        // Attempt to produce wrapped list of active connections
+        wrapActiveConnections();
+
+    });
+
     /**
      * Returns whether critical data has completed being loaded.
      *
@@ -201,8 +223,9 @@
      */
     $scope.isLoaded = function isLoaded() {
 
-        return $scope.wrappers    !== null
-            && $scope.permissions !== null;
+        return $scope.wrappers          !== null
+            && $scope.sessionDateFormat !== null
+            && $scope.permissions       !== null;
 
     };
 
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html
index 41c8db3..7cdfabe 100644
--- a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html
+++ b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html
@@ -97,7 +97,7 @@
             <tbody>
                 <tr ng-repeat="wrapper in wrapperPage">
                     <td class="username">{{wrapper.entry.username}}</td>
-                    <td class="start">{{wrapper.entry.startDate | date:'short'}}</td>
+                    <td class="start">{{wrapper.entry.startDate | date:historyDateFormat}}</td>
                     <td class="duration">{{wrapper.durationText | translate:"{VALUE: wrapper.duration.value, UNIT: wrapper.duration.unit}"}}</td>
                 </tr>
             </tbody>
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageSessions.html b/guacamole/src/main/webapp/app/manage/templates/manageSessions.html
index 41a49f7..5b50f5f 100644
--- a/guacamole/src/main/webapp/app/manage/templates/manageSessions.html
+++ b/guacamole/src/main/webapp/app/manage/templates/manageSessions.html
@@ -49,7 +49,7 @@
                     <th guac-sort-order="wrapperOrder" guac-sort-property="'activeConnection.username'">
                         {{'MANAGE_SESSION.TABLE_HEADER_SESSION_USERNAME' | translate}}
                     </th>
-                    <th guac-sort-order="wrapperOrder" guac-sort-property="'activeConnection.startDate'">
+                    <th guac-sort-order="wrapperOrder" guac-sort-property="'startDate'">
                         {{'MANAGE_SESSION.TABLE_HEADER_SESSION_STARTDATE' | translate}}
                     </th>
                     <th guac-sort-order="wrapperOrder" guac-sort-property="'activeConnection.remoteHost'">
@@ -66,7 +66,7 @@
                         <input ng-change="wrapperSelectionChange(wrapper)" type="checkbox" ng-model="wrapper.checked" />
                     </td>
                     <td>{{wrapper.activeConnection.username}}</td>
-                    <td>{{wrapper.activeConnection.startDate | date:'short'}}</td>
+                    <td>{{wrapper.startDate}}</td>
                     <td>{{wrapper.activeConnection.remoteHost}}</td>
                     <td>{{wrapper.name}}</td>
                 </tr>
diff --git a/guacamole/src/main/webapp/app/manage/types/ActiveConnectionWrapper.js b/guacamole/src/main/webapp/app/manage/types/ActiveConnectionWrapper.js
index 92130c2..cb2c43e 100644
--- a/guacamole/src/main/webapp/app/manage/types/ActiveConnectionWrapper.js
+++ b/guacamole/src/main/webapp/app/manage/types/ActiveConnectionWrapper.js
@@ -33,11 +33,14 @@
      * @constructor
      * @param {String} name
      *     The display name of the active connection.
+     *     
+     * @param {String} startDate
+     *     The date and time this session began, pre-formatted for display.
      *
      * @param {ActiveConnection} activeConnection
      *     The ActiveConnection to wrap.
      */
-    var ActiveConnectionWrapper = function ActiveConnectionWrapper(name, activeConnection) {
+    var ActiveConnectionWrapper = function ActiveConnectionWrapper(name, startDate, activeConnection) {
 
         /**
          * The display name of this connection.
@@ -47,6 +50,13 @@
         this.name = name;
 
         /**
+         * The date and time this session began, pre-formatted for display.
+         *
+         * @type String
+         */
+        this.startDate = startDate;
+
+        /**
          * The wrapped ActiveConnection.
          *
          * @type ActiveConnection
diff --git a/guacamole/src/main/webapp/translations/en_US.json b/guacamole/src/main/webapp/translations/en_US.json
index 46876aa..da003fd 100644
--- a/guacamole/src/main/webapp/translations/en_US.json
+++ b/guacamole/src/main/webapp/translations/en_US.json
@@ -23,7 +23,9 @@
         
         "FIELD_HEADER_PASSWORD"       : "Password:",
         "FIELD_HEADER_PASSWORD_AGAIN" : "Re-enter Password:",
-        
+
+        "FORMAT_DATE_TIME_PRECISE" : "yyyy-MM-dd HH:mm:ss",
+
         "INFO_ACTIVE_USER_COUNT" : "Currently in use by {USERS} {USERS, plural, one{user} other{users}}.",
 
         "NAME" : "Guacamole ${project.version}"
@@ -155,7 +157,9 @@
         "FIELD_HEADER_LOCATION" : "Location:",
         "FIELD_HEADER_NAME"     : "Name:",
         "FIELD_HEADER_PROTOCOL" : "Protocol:",
-        
+
+        "FORMAT_HISTORY_START" : "@:APP.FORMAT_DATE_TIME_PRECISE",
+
         "HELP_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.",
         "HELP_SHOW_PASSWORD" : "Click to show password",
         "HELP_HIDE_PASSWORD" : "Click to hide password",
@@ -245,6 +249,8 @@
         
         "FIELD_PLACEHOLDER_FILTER" : "Filter",
         
+        "FORMAT_STARTDATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
+
         "HELP_SESSIONS" : "All currently-active Guacamole sessions are listed here. If you wish to kill one or more sessions, check the box next to those sessions and click \"Kill Sessions\". Killing a session will immediately disconnect the user from the associated connection.",
         
         "INFO_NO_SESSIONS" : "No active sessions",