GUAC-1053: Create session management tab.

This commit is contained in:
Michael Jumper
2015-04-17 17:03:45 -07:00
parent ed984da8d1
commit 3fa3d1ba2b
8 changed files with 456 additions and 439 deletions

View File

@@ -1,349 +0,0 @@
/*
* Copyright (C) 2015 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* The controller for the user session administration page.
*/
angular.module('manage').controller('manageSessionsController', ['$scope', '$injector',
function manageSessionsController($scope, $injector) {
// Required types
var ActiveConnectionWrapper = $injector.get('ActiveConnectionWrapper');
var ConnectionGroup = $injector.get('ConnectionGroup');
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');
var guacNotification = $injector.get('guacNotification');
var permissionService = $injector.get('permissionService');
/**
* All permissions associated with the current user, or null if the user's
* permissions have not yet been loaded.
*
* @type PermissionSet
*/
$scope.permissions = null;
/**
* The ActiveConnectionWrappers of all active sessions accessible by the
* current user, or null if the active sessions have not yet been loaded.
*
* @type ActiveConnectionWrapper[]
*/
$scope.wrappers = null;
/**
* SortOrder instance which maintains the sort order of the visible
* connection wrappers.
*
* @type SortOrder
*/
$scope.wrapperOrder = new SortOrder([
'activeConnection.username',
'startDate',
'activeConnection.remoteHost',
'name'
]);
/**
* Array of all wrapper properties that are filterable.
*
* @type String[]
*/
$scope.filteredWrapperProperties = [
'activeConnection.username',
'startDate',
'activeConnection.remoteHost',
'name'
];
/**
* All active connections, if known, or null if active connections have not
* yet been loaded.
*
* @type ActiveConnection
*/
var activeConnections = null;
/**
* Map of all visible connections by object identifier, or null if visible
* connections have not yet been loaded.
*
* @type Object.<String, Connection>
*/
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>
*/
var selectedWrappers = {};
/**
* Adds the given connection to the internal set of visible
* connections.
*
* @param {Connection} connection
* The connection to add to the internal set of visible connections.
*/
var addConnection = function addConnection(connection) {
// Add given connection to set of visible connections
connections[connection.identifier] = connection;
};
/**
* Adds all descendant connections of the given connection group to the
* internal set of connections.
*
* @param {ConnectionGroup} connectionGroup
* The connection group whose descendant connections should be added to
* the internal set of connections.
*/
var addDescendantConnections = function addDescendantConnections(connectionGroup) {
// Add all child connections
if (connectionGroup.childConnections)
connectionGroup.childConnections.forEach(addConnection);
// Add all child connection groups
if (connectionGroup.childConnectionGroups)
connectionGroup.childConnectionGroups.forEach(addDescendantConnections);
};
/**
* Wraps all loaded active connections, storing the resulting array within
* the scope. If required data has not yet finished loading, this function
* has no effect.
*/
var wrapActiveConnections = function wrapActiveConnections() {
// Abort if not all required data is available
if (!activeConnections || !connections || !sessionDateFormat)
return;
// Wrap all active connections for sake of display
$scope.wrappers = [];
for (var identifier in activeConnections) {
var activeConnection = activeConnections[identifier];
var connection = connections[activeConnection.connectionIdentifier];
$scope.wrappers.push(new ActiveConnectionWrapper(
connection.name,
$filter('date')(activeConnection.startDate, sessionDateFormat),
activeConnection
));
}
};
// Query the user's permissions
permissionService.getPermissions(authenticationService.getCurrentUserID())
.success(function permissionsReceived(retrievedPermissions) {
$scope.permissions = retrievedPermissions;
});
// Retrieve all connections
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER)
.success(function connectionGroupReceived(retrievedRootGroup) {
// Load connections from retrieved group tree
connections = {};
addDescendantConnections(retrievedRootGroup);
// Attempt to produce wrapped list of active connections
wrapActiveConnections();
});
// Query active sessions
activeConnectionService.getActiveConnections().success(function sessionsRetrieved(retrievedActiveConnections) {
// Store received list
activeConnections = retrievedActiveConnections;
// Attempt to produce wrapped list of active connections
wrapActiveConnections();
});
// 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.
*
* @returns {Boolean}
* true if enough data has been loaded for the user interface to be
* useful, false otherwise.
*/
$scope.isLoaded = function isLoaded() {
return $scope.wrappers !== null
&& $scope.sessionDateFormat !== null
&& $scope.permissions !== null;
};
/**
* An action to be provided along with the object sent to showStatus which
* closes the currently-shown status dialog.
*/
var ACKNOWLEDGE_ACTION = {
name : "MANAGE_SESSION.ACTION_ACKNOWLEDGE",
// Handle action
callback : function acknowledgeCallback() {
guacNotification.showStatus(false);
}
};
/**
* An action to be provided along with the object sent to showStatus which
* closes the currently-shown status dialog.
*/
var CANCEL_ACTION = {
name : "MANAGE_SESSION.ACTION_CANCEL",
// Handle action
callback : function cancelCallback() {
guacNotification.showStatus(false);
}
};
/**
* An action to be provided along with the object sent to showStatus which
* immediately deletes the currently selected sessions.
*/
var DELETE_ACTION = {
name : "MANAGE_SESSION.ACTION_DELETE",
className : "danger",
// Handle action
callback : function deleteCallback() {
deleteSessionsImmediately();
guacNotification.showStatus(false);
}
};
/**
* Immediately deletes the selected sessions, without prompting the user for
* confirmation.
*/
var deleteSessionsImmediately = function deleteSessionsImmediately() {
// Perform deletion
activeConnectionService.deleteActiveConnections(Object.keys(selectedWrappers))
.success(function activeConnectionsDeleted() {
// Remove deleted connections from wrapper array
$scope.wrappers = $scope.wrappers.filter(function activeConnectionStillExists(wrapper) {
return !(wrapper.activeConnection.identifier in selectedWrappers);
});
// Clear selection
selectedWrappers = {};
})
// Notify of any errors
.error(function activeConnectionDeletionFailed(error) {
guacNotification.showStatus({
'className' : 'error',
'title' : 'MANAGE_SESSION.DIALOG_HEADER_ERROR',
'text' : error.message,
'actions' : [ ACKNOWLEDGE_ACTION ]
});
});
};
/**
* Delete all selected sessions, prompting the user first to confirm that
* deletion is desired.
*/
$scope.deleteSessions = function deleteSessions() {
// Confirm deletion request
guacNotification.showStatus({
'title' : 'MANAGE_SESSION.DIALOG_HEADER_CONFIRM_DELETE',
'text' : 'MANAGE_SESSION.TEXT_CONFIRM_DELETE',
'actions' : [ DELETE_ACTION, CANCEL_ACTION]
});
};
/**
* Returns whether the selected sessions can be deleted.
*
* @returns {Boolean}
* true if selected sessions can be deleted, false otherwise.
*/
$scope.canDeleteSessions = function canDeleteSessions() {
// We can delete sessions if at least one is selected
for (var identifier in selectedWrappers)
return true;
return false;
};
/**
* Called whenever an active connection wrapper changes selected status.
*
* @param {ActiveConnectionWrapper} wrapper
* The wrapper whose selected status has changed.
*/
$scope.wrapperSelectionChange = function wrapperSelectionChange(wrapper) {
// Add wrapper to map if selected
if (wrapper.checked)
selectedWrappers[wrapper.activeConnection.identifier] = wrapper;
// Otherwise, remove wrapper from map
else
delete selectedWrappers[wrapper.activeConnection.identifier];
};
}]);

View File

@@ -1,86 +0,0 @@
<!--
Copyright 2015 Glyptodon LLC.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<div class="view" ng-class="{loading: !isLoaded()}">
<div class="header">
<h2>{{'MANAGE_SESSION.SECTION_HEADER_SESSIONS' | translate}}</h2>
<guac-user-menu></guac-user-menu>
</div>
<!-- User Session management -->
<div class="settings section sessions">
<p>{{'MANAGE_SESSION.HELP_SESSIONS' | translate}}</p>
<!-- Form action buttons -->
<div class="action-buttons">
<button class="delete-sessions danger" ng-disabled="!canDeleteSessions()" ng-click="deleteSessions()">{{'MANAGE_SESSION.ACTION_DELETE' | translate}}</button>
</div>
<!-- Session filter -->
<guac-filter filtered-items="filteredWrappers" items="wrappers"
placeholder="'MANAGE_SESSION.FIELD_PLACEHOLDER_FILTER' | translate"
properties="filteredWrapperProperties"></guac-filter>
<!-- List of current user sessions -->
<table class="sorted session-list">
<thead>
<tr>
<th class="select-session"></th>
<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="'startDate'">
{{'MANAGE_SESSION.TABLE_HEADER_SESSION_STARTDATE' | translate}}
</th>
<th guac-sort-order="wrapperOrder" guac-sort-property="'activeConnection.remoteHost'">
{{'MANAGE_SESSION.TABLE_HEADER_SESSION_REMOTEHOST' | translate}}
</th>
<th guac-sort-order="wrapperOrder" guac-sort-property="'name'">
{{'MANAGE_SESSION.TABLE_HEADER_SESSION_CONNECTION_NAME' | translate}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="wrapper in wrapperPage" class="session">
<td class="select-session">
<input ng-change="wrapperSelectionChange(wrapper)" type="checkbox" ng-model="wrapper.checked" />
</td>
<td>{{wrapper.activeConnection.username}}</td>
<td>{{wrapper.startDate}}</td>
<td>{{wrapper.activeConnection.remoteHost}}</td>
<td>{{wrapper.name}}</td>
</tr>
</tbody>
</table>
<!-- Text displayed if no sessions exist -->
<p class="placeholder" ng-hide="wrapperPage.length">
{{'MANAGE_SESSION.INFO_NO_SESSIONS' | translate}}
</p>
<!-- Pager for session list -->
<guac-pager page="wrapperPage" page-size="25"
items="filteredWrappers | orderBy : wrapperOrder.predicate"></guac-pager>
</div>
</div>

View File

@@ -0,0 +1,363 @@
/*
* Copyright (C) 2015 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* A directive for managing all active Guacamole sessions.
*/
angular.module('settings').directive('guacManageSessions', [function guacManageSessions() {
return {
// Element only
restrict: 'E',
replace: true,
scope: {
},
templateUrl: 'app/settings/templates/manageSessions.html',
controller: ['$scope', '$injector',
function manageSessionsController($scope, $injector) {
// Required types
var ActiveConnectionWrapper = $injector.get('ActiveConnectionWrapper');
var ConnectionGroup = $injector.get('ConnectionGroup');
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');
var guacNotification = $injector.get('guacNotification');
var permissionService = $injector.get('permissionService');
/**
* All permissions associated with the current user, or null if the user's
* permissions have not yet been loaded.
*
* @type PermissionSet
*/
$scope.permissions = null;
/**
* The ActiveConnectionWrappers of all active sessions accessible by the
* current user, or null if the active sessions have not yet been loaded.
*
* @type ActiveConnectionWrapper[]
*/
$scope.wrappers = null;
/**
* SortOrder instance which maintains the sort order of the visible
* connection wrappers.
*
* @type SortOrder
*/
$scope.wrapperOrder = new SortOrder([
'activeConnection.username',
'startDate',
'activeConnection.remoteHost',
'name'
]);
/**
* Array of all wrapper properties that are filterable.
*
* @type String[]
*/
$scope.filteredWrapperProperties = [
'activeConnection.username',
'startDate',
'activeConnection.remoteHost',
'name'
];
/**
* All active connections, if known, or null if active connections have not
* yet been loaded.
*
* @type ActiveConnection
*/
var activeConnections = null;
/**
* Map of all visible connections by object identifier, or null if visible
* connections have not yet been loaded.
*
* @type Object.<String, Connection>
*/
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>
*/
var selectedWrappers = {};
/**
* Adds the given connection to the internal set of visible
* connections.
*
* @param {Connection} connection
* The connection to add to the internal set of visible connections.
*/
var addConnection = function addConnection(connection) {
// Add given connection to set of visible connections
connections[connection.identifier] = connection;
};
/**
* Adds all descendant connections of the given connection group to the
* internal set of connections.
*
* @param {ConnectionGroup} connectionGroup
* The connection group whose descendant connections should be added to
* the internal set of connections.
*/
var addDescendantConnections = function addDescendantConnections(connectionGroup) {
// Add all child connections
if (connectionGroup.childConnections)
connectionGroup.childConnections.forEach(addConnection);
// Add all child connection groups
if (connectionGroup.childConnectionGroups)
connectionGroup.childConnectionGroups.forEach(addDescendantConnections);
};
/**
* Wraps all loaded active connections, storing the resulting array within
* the scope. If required data has not yet finished loading, this function
* has no effect.
*/
var wrapActiveConnections = function wrapActiveConnections() {
// Abort if not all required data is available
if (!activeConnections || !connections || !sessionDateFormat)
return;
// Wrap all active connections for sake of display
$scope.wrappers = [];
for (var identifier in activeConnections) {
var activeConnection = activeConnections[identifier];
var connection = connections[activeConnection.connectionIdentifier];
$scope.wrappers.push(new ActiveConnectionWrapper(
connection.name,
$filter('date')(activeConnection.startDate, sessionDateFormat),
activeConnection
));
}
};
// Query the user's permissions
permissionService.getPermissions(authenticationService.getCurrentUserID())
.success(function permissionsReceived(retrievedPermissions) {
$scope.permissions = retrievedPermissions;
});
// Retrieve all connections
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER)
.success(function connectionGroupReceived(retrievedRootGroup) {
// Load connections from retrieved group tree
connections = {};
addDescendantConnections(retrievedRootGroup);
// Attempt to produce wrapped list of active connections
wrapActiveConnections();
});
// Query active sessions
activeConnectionService.getActiveConnections().success(function sessionsRetrieved(retrievedActiveConnections) {
// Store received list
activeConnections = retrievedActiveConnections;
// Attempt to produce wrapped list of active connections
wrapActiveConnections();
});
// 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.
*
* @returns {Boolean}
* true if enough data has been loaded for the user interface to be
* useful, false otherwise.
*/
$scope.isLoaded = function isLoaded() {
return $scope.wrappers !== null
&& $scope.sessionDateFormat !== null
&& $scope.permissions !== null;
};
/**
* An action to be provided along with the object sent to showStatus which
* closes the currently-shown status dialog.
*/
var ACKNOWLEDGE_ACTION = {
name : "MANAGE_SESSION.ACTION_ACKNOWLEDGE",
// Handle action
callback : function acknowledgeCallback() {
guacNotification.showStatus(false);
}
};
/**
* An action to be provided along with the object sent to showStatus which
* closes the currently-shown status dialog.
*/
var CANCEL_ACTION = {
name : "MANAGE_SESSION.ACTION_CANCEL",
// Handle action
callback : function cancelCallback() {
guacNotification.showStatus(false);
}
};
/**
* An action to be provided along with the object sent to showStatus which
* immediately deletes the currently selected sessions.
*/
var DELETE_ACTION = {
name : "MANAGE_SESSION.ACTION_DELETE",
className : "danger",
// Handle action
callback : function deleteCallback() {
deleteSessionsImmediately();
guacNotification.showStatus(false);
}
};
/**
* Immediately deletes the selected sessions, without prompting the user for
* confirmation.
*/
var deleteSessionsImmediately = function deleteSessionsImmediately() {
// Perform deletion
activeConnectionService.deleteActiveConnections(Object.keys(selectedWrappers))
.success(function activeConnectionsDeleted() {
// Remove deleted connections from wrapper array
$scope.wrappers = $scope.wrappers.filter(function activeConnectionStillExists(wrapper) {
return !(wrapper.activeConnection.identifier in selectedWrappers);
});
// Clear selection
selectedWrappers = {};
})
// Notify of any errors
.error(function activeConnectionDeletionFailed(error) {
guacNotification.showStatus({
'className' : 'error',
'title' : 'MANAGE_SESSION.DIALOG_HEADER_ERROR',
'text' : error.message,
'actions' : [ ACKNOWLEDGE_ACTION ]
});
});
};
/**
* Delete all selected sessions, prompting the user first to confirm that
* deletion is desired.
*/
$scope.deleteSessions = function deleteSessions() {
// Confirm deletion request
guacNotification.showStatus({
'title' : 'MANAGE_SESSION.DIALOG_HEADER_CONFIRM_DELETE',
'text' : 'MANAGE_SESSION.TEXT_CONFIRM_DELETE',
'actions' : [ DELETE_ACTION, CANCEL_ACTION]
});
};
/**
* Returns whether the selected sessions can be deleted.
*
* @returns {Boolean}
* true if selected sessions can be deleted, false otherwise.
*/
$scope.canDeleteSessions = function canDeleteSessions() {
// We can delete sessions if at least one is selected
for (var identifier in selectedWrappers)
return true;
return false;
};
/**
* Called whenever an active connection wrapper changes selected status.
*
* @param {ActiveConnectionWrapper} wrapper
* The wrapper whose selected status has changed.
*/
$scope.wrapperSelectionChange = function wrapperSelectionChange(wrapper) {
// Add wrapper to map if selected
if (wrapper.checked)
selectedWrappers[wrapper.activeConnection.identifier] = wrapper;
// Otherwise, remove wrapper from map
else
delete selectedWrappers[wrapper.activeConnection.identifier];
};
}]
};
}]);

View File

@@ -20,15 +20,15 @@
* THE SOFTWARE.
*/
.manage table.session-list {
.settings table.session-list {
width: 100%;
}
.manage table.session-list tr.session:hover {
.settings table.session-list tr.session:hover {
background: #CDA;
}
.manage table.session-list .select-session {
.settings table.session-list .select-session {
min-width: 2em;
text-align: center;
}

View File

@@ -24,6 +24,17 @@
margin-bottom: 0;
}
.settings table.properties th {
text-align: left;
font-weight: normal;
padding-right: 1em;
}
.settings .action-buttons {
text-align: center;
margin-bottom: 1em;
}
.settings-tabs .page-list {
margin: 0;
padding: 0;

View File

@@ -0,0 +1,77 @@
<div class="settings section sessions" ng-class="{loading: !isLoaded()}">
<!--
Copyright 2015 Glyptodon LLC.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<!-- User Session management -->
<p>{{'MANAGE_SESSION.HELP_SESSIONS' | translate}}</p>
<!-- Form action buttons -->
<div class="action-buttons">
<button class="delete-sessions danger" ng-disabled="!canDeleteSessions()" ng-click="deleteSessions()">{{'MANAGE_SESSION.ACTION_DELETE' | translate}}</button>
</div>
<!-- Session filter -->
<guac-filter filtered-items="filteredWrappers" items="wrappers"
placeholder="'MANAGE_SESSION.FIELD_PLACEHOLDER_FILTER' | translate"
properties="filteredWrapperProperties"></guac-filter>
<!-- List of current user sessions -->
<table class="sorted session-list">
<thead>
<tr>
<th class="select-session"></th>
<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="'startDate'">
{{'MANAGE_SESSION.TABLE_HEADER_SESSION_STARTDATE' | translate}}
</th>
<th guac-sort-order="wrapperOrder" guac-sort-property="'activeConnection.remoteHost'">
{{'MANAGE_SESSION.TABLE_HEADER_SESSION_REMOTEHOST' | translate}}
</th>
<th guac-sort-order="wrapperOrder" guac-sort-property="'name'">
{{'MANAGE_SESSION.TABLE_HEADER_SESSION_CONNECTION_NAME' | translate}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="wrapper in wrapperPage" class="session">
<td class="select-session">
<input ng-change="wrapperSelectionChange(wrapper)" type="checkbox" ng-model="wrapper.checked" />
</td>
<td>{{wrapper.activeConnection.username}}</td>
<td>{{wrapper.startDate}}</td>
<td>{{wrapper.activeConnection.remoteHost}}</td>
<td>{{wrapper.name}}</td>
</tr>
</tbody>
</table>
<!-- Text displayed if no sessions exist -->
<p class="placeholder" ng-hide="wrapperPage.length">
{{'MANAGE_SESSION.INFO_NO_SESSIONS' | translate}}
</p>
<!-- Pager for session list -->
<guac-pager page="wrapperPage" page-size="25"
items="filteredWrappers | orderBy : wrapperOrder.predicate"></guac-pager>
</div>

View File

@@ -35,5 +35,6 @@ THE SOFTWARE.
<!-- Selected tab -->
<guac-manage-users ng-if="activeTab === 'users'"></guac-manage-users>
<guac-manage-connections ng-if="activeTab === 'connections'"></guac-manage-connections>
<guac-manage-sessions ng-if="activeTab === 'sessions'"></guac-manage-sessions>
</div>

View File

@@ -23,7 +23,7 @@
/**
* A service for defining the ActiveConnectionWrapper class.
*/
angular.module('manage').factory('ActiveConnectionWrapper', [
angular.module('settings').factory('ActiveConnectionWrapper', [
function defineActiveConnectionWrapper() {
/**