mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-07 13:41:21 +00:00
GUAC-586: Restore management of active sessions.
This commit is contained in:
@@ -44,10 +44,21 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
// Required services
|
// Required services
|
||||||
var $filter = $injector.get('$filter');
|
var $filter = $injector.get('$filter');
|
||||||
var $translate = $injector.get('$translate');
|
var $translate = $injector.get('$translate');
|
||||||
|
var $q = $injector.get('$q');
|
||||||
var activeConnectionService = $injector.get('activeConnectionService');
|
var activeConnectionService = $injector.get('activeConnectionService');
|
||||||
|
var authenticationService = $injector.get('authenticationService');
|
||||||
var connectionGroupService = $injector.get('connectionGroupService');
|
var connectionGroupService = $injector.get('connectionGroupService');
|
||||||
|
var dataSourceService = $injector.get('dataSourceService');
|
||||||
var guacNotification = $injector.get('guacNotification');
|
var guacNotification = $injector.get('guacNotification');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The identifiers of all data sources accessible by the current
|
||||||
|
* user.
|
||||||
|
*
|
||||||
|
* @type String[]
|
||||||
|
*/
|
||||||
|
var dataSources = authenticationService.getAvailableDataSources();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ActiveConnectionWrappers of all active sessions accessible
|
* The ActiveConnectionWrappers of all active sessions accessible
|
||||||
* by the current user, or null if the active sessions have not yet
|
* by the current user, or null if the active sessions have not yet
|
||||||
@@ -83,20 +94,22 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All active connections, if known, or null if active connections
|
* All active connections, if known, grouped by corresponding data
|
||||||
* have not yet been loaded.
|
* source identifier, or null if active connections have not yet
|
||||||
|
* been loaded.
|
||||||
*
|
*
|
||||||
* @type ActiveConnection
|
* @type Object.<String, Object.<String, ActiveConnection>>
|
||||||
*/
|
*/
|
||||||
var activeConnections = null;
|
var allActiveConnections = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of all visible connections by object identifier, or null if
|
* Map of all visible connections by data source identifier and
|
||||||
* visible connections have not yet been loaded.
|
* object identifier, or null if visible connections have not yet
|
||||||
|
* been loaded.
|
||||||
*
|
*
|
||||||
* @type Object.<String, Connection>
|
* @type Object.<String, Object.<String, Connection>>
|
||||||
*/
|
*/
|
||||||
var connections = null;
|
var allConnections = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The date format for use for session-related dates.
|
* The date format for use for session-related dates.
|
||||||
@@ -107,24 +120,28 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of all currently-selected active connection wrappers by
|
* Map of all currently-selected active connection wrappers by
|
||||||
* identifier.
|
* data source and identifier.
|
||||||
*
|
*
|
||||||
* @type Object.<String, ActiveConnectionWrapper>
|
* @type Object.<String, Object.<String, ActiveConnectionWrapper>>
|
||||||
*/
|
*/
|
||||||
var selectedWrappers = {};
|
var allSelectedWrappers = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the given connection to the internal set of visible
|
* Adds the given connection to the internal set of visible
|
||||||
* connections.
|
* connections.
|
||||||
*
|
*
|
||||||
|
* @param {String} dataSource
|
||||||
|
* The identifier of the data source associated with the given
|
||||||
|
* connection.
|
||||||
|
*
|
||||||
* @param {Connection} connection
|
* @param {Connection} connection
|
||||||
* The connection to add to the internal set of visible
|
* The connection to add to the internal set of visible
|
||||||
* connections.
|
* connections.
|
||||||
*/
|
*/
|
||||||
var addConnection = function addConnection(connection) {
|
var addConnection = function addConnection(dataSource, connection) {
|
||||||
|
|
||||||
// Add given connection to set of visible connections
|
// Add given connection to set of visible connections
|
||||||
connections[connection.identifier] = connection;
|
allConnections[dataSource][connection.identifier] = connection;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -132,19 +149,25 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
* Adds all descendant connections of the given connection group to
|
* Adds all descendant connections of the given connection group to
|
||||||
* the internal set of connections.
|
* the internal set of connections.
|
||||||
*
|
*
|
||||||
|
* @param {String} dataSource
|
||||||
|
* The identifier of the data source associated with the given
|
||||||
|
* connection group.
|
||||||
|
*
|
||||||
* @param {ConnectionGroup} connectionGroup
|
* @param {ConnectionGroup} connectionGroup
|
||||||
* The connection group whose descendant connections should be
|
* The connection group whose descendant connections should be
|
||||||
* added to the internal set of connections.
|
* added to the internal set of connections.
|
||||||
*/
|
*/
|
||||||
var addDescendantConnections = function addDescendantConnections(connectionGroup) {
|
var addDescendantConnections = function addDescendantConnections(dataSource, connectionGroup) {
|
||||||
|
|
||||||
// Add all child connections
|
// Add all child connections
|
||||||
if (connectionGroup.childConnections)
|
angular.forEach(connectionGroup.childConnections, function addConnectionForDataSource(connection) {
|
||||||
connectionGroup.childConnections.forEach(addConnection);
|
addConnection(dataSource, connection);
|
||||||
|
});
|
||||||
|
|
||||||
// Add all child connection groups
|
// Add all child connection groups
|
||||||
if (connectionGroup.childConnectionGroups)
|
angular.forEach(connectionGroup.childConnectionGroups, function addConnectionGroupForDataSource(connectionGroup) {
|
||||||
connectionGroup.childConnectionGroups.forEach(addDescendantConnections);
|
addDescendantConnections(dataSource, connectionGroup);
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -153,50 +176,66 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
* within the scope. If required data has not yet finished loading,
|
* within the scope. If required data has not yet finished loading,
|
||||||
* this function has no effect.
|
* this function has no effect.
|
||||||
*/
|
*/
|
||||||
var wrapActiveConnections = function wrapActiveConnections() {
|
var wrapAllActiveConnections = function wrapAllActiveConnections() {
|
||||||
|
|
||||||
// Abort if not all required data is available
|
// Abort if not all required data is available
|
||||||
if (!activeConnections || !connections || !sessionDateFormat)
|
if (!allActiveConnections || !allConnections || !sessionDateFormat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Wrap all active connections for sake of display
|
// Wrap all active connections for sake of display
|
||||||
$scope.wrappers = [];
|
$scope.wrappers = [];
|
||||||
for (var identifier in activeConnections) {
|
angular.forEach(allActiveConnections, function wrapActiveConnections(activeConnections, dataSource) {
|
||||||
|
angular.forEach(activeConnections, function wrapActiveConnection(activeConnection, identifier) {
|
||||||
|
|
||||||
var activeConnection = activeConnections[identifier];
|
// Retrieve corresponding connection
|
||||||
var connection = connections[activeConnection.connectionIdentifier];
|
var connection = allConnections[dataSource][activeConnection.connectionIdentifier];
|
||||||
|
|
||||||
$scope.wrappers.push(new ActiveConnectionWrapper(
|
// Add wrapper
|
||||||
connection.name,
|
$scope.wrappers.push(new ActiveConnectionWrapper({
|
||||||
$filter('date')(activeConnection.startDate, sessionDateFormat),
|
dataSource : dataSource,
|
||||||
activeConnection
|
name : connection.name,
|
||||||
));
|
startDate : $filter('date')(activeConnection.startDate, sessionDateFormat),
|
||||||
|
activeConnection : activeConnection
|
||||||
|
}));
|
||||||
|
|
||||||
}
|
});
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Retrieve all connections
|
// Retrieve all connections
|
||||||
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER)
|
dataSourceService.apply(
|
||||||
.success(function connectionGroupReceived(retrievedRootGroup) {
|
connectionGroupService.getConnectionGroupTree,
|
||||||
|
dataSources,
|
||||||
|
ConnectionGroup.ROOT_IDENTIFIER
|
||||||
|
)
|
||||||
|
.then(function connectionGroupsReceived(rootGroups) {
|
||||||
|
|
||||||
// Load connections from retrieved group tree
|
allConnections = {};
|
||||||
connections = {};
|
|
||||||
addDescendantConnections(retrievedRootGroup);
|
// Load connections from each received root group
|
||||||
|
angular.forEach(rootGroups, function connectionGroupReceived(rootGroup, dataSource) {
|
||||||
|
allConnections[dataSource] = {};
|
||||||
|
addDescendantConnections(dataSource, rootGroup);
|
||||||
|
});
|
||||||
|
|
||||||
// Attempt to produce wrapped list of active connections
|
// Attempt to produce wrapped list of active connections
|
||||||
wrapActiveConnections();
|
wrapAllActiveConnections();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Query active sessions
|
// Query active sessions
|
||||||
activeConnectionService.getActiveConnections().success(function sessionsRetrieved(retrievedActiveConnections) {
|
dataSourceService.apply(
|
||||||
|
activeConnectionService.getActiveConnections,
|
||||||
|
dataSources
|
||||||
|
)
|
||||||
|
.then(function sessionsRetrieved(retrievedActiveConnections) {
|
||||||
|
|
||||||
// Store received list
|
// Store received map of active connections
|
||||||
activeConnections = retrievedActiveConnections;
|
allActiveConnections = retrievedActiveConnections;
|
||||||
|
|
||||||
// Attempt to produce wrapped list of active connections
|
// Attempt to produce wrapped list of active connections
|
||||||
wrapActiveConnections();
|
wrapAllActiveConnections();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -207,7 +246,7 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
sessionDateFormat = retrievedSessionDateFormat;
|
sessionDateFormat = retrievedSessionDateFormat;
|
||||||
|
|
||||||
// Attempt to produce wrapped list of active connections
|
// Attempt to produce wrapped list of active connections
|
||||||
wrapActiveConnections();
|
wrapAllActiveConnections();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -219,10 +258,7 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
* to be useful, false otherwise.
|
* to be useful, false otherwise.
|
||||||
*/
|
*/
|
||||||
$scope.isLoaded = function isLoaded() {
|
$scope.isLoaded = function isLoaded() {
|
||||||
|
return $scope.wrappers !== null;
|
||||||
return $scope.wrappers !== null
|
|
||||||
&& $scope.sessionDateFormat !== null;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -259,7 +295,7 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
className : "danger",
|
className : "danger",
|
||||||
// Handle action
|
// Handle action
|
||||||
callback : function deleteCallback() {
|
callback : function deleteCallback() {
|
||||||
deleteSessionsImmediately();
|
deleteAllSessionsImmediately();
|
||||||
guacNotification.showStatus(false);
|
guacNotification.showStatus(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -268,24 +304,36 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
* Immediately deletes the selected sessions, without prompting the
|
* Immediately deletes the selected sessions, without prompting the
|
||||||
* user for confirmation.
|
* user for confirmation.
|
||||||
*/
|
*/
|
||||||
var deleteSessionsImmediately = function deleteSessionsImmediately() {
|
var deleteAllSessionsImmediately = function deleteAllSessionsImmediately() {
|
||||||
|
|
||||||
// Perform deletion
|
var deletionRequests = [];
|
||||||
activeConnectionService.deleteActiveConnections(Object.keys(selectedWrappers))
|
|
||||||
.success(function activeConnectionsDeleted() {
|
// Perform deletion for each relevant data source
|
||||||
|
angular.forEach(allSelectedWrappers, function deleteSessionsImmediately(selectedWrappers, dataSource) {
|
||||||
|
|
||||||
|
// Delete sessions, if any are selected
|
||||||
|
var identifiers = Object.keys(selectedWrappers);
|
||||||
|
if (identifiers.length)
|
||||||
|
deletionRequests.push(activeConnectionService.deleteActiveConnections(dataSource, identifiers));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update interface
|
||||||
|
$q.all(deletionRequests)
|
||||||
|
.then(function activeConnectionsDeleted() {
|
||||||
|
|
||||||
// Remove deleted connections from wrapper array
|
// Remove deleted connections from wrapper array
|
||||||
$scope.wrappers = $scope.wrappers.filter(function activeConnectionStillExists(wrapper) {
|
$scope.wrappers = $scope.wrappers.filter(function activeConnectionStillExists(wrapper) {
|
||||||
return !(wrapper.activeConnection.identifier in selectedWrappers);
|
return !(wrapper.activeConnection.identifier in (allSelectedWrappers[wrapper.dataSource] || {}));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clear selection
|
// Clear selection
|
||||||
selectedWrappers = {};
|
allSelectedWrappers = {};
|
||||||
|
|
||||||
})
|
},
|
||||||
|
|
||||||
// Notify of any errors
|
// Notify of any errors
|
||||||
.error(function activeConnectionDeletionFailed(error) {
|
function activeConnectionDeletionFailed(error) {
|
||||||
guacNotification.showStatus({
|
guacNotification.showStatus({
|
||||||
'className' : 'error',
|
'className' : 'error',
|
||||||
'title' : 'SETTINGS_SESSIONS.DIALOG_HEADER_ERROR',
|
'title' : 'SETTINGS_SESSIONS.DIALOG_HEADER_ERROR',
|
||||||
@@ -318,8 +366,10 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
$scope.canDeleteSessions = function canDeleteSessions() {
|
$scope.canDeleteSessions = function canDeleteSessions() {
|
||||||
|
|
||||||
// We can delete sessions if at least one is selected
|
// We can delete sessions if at least one is selected
|
||||||
for (var identifier in selectedWrappers)
|
for (var dataSource in allSelectedWrappers) {
|
||||||
return true;
|
for (var identifier in allSelectedWrappers[dataSource])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -334,6 +384,11 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
*/
|
*/
|
||||||
$scope.wrapperSelectionChange = function wrapperSelectionChange(wrapper) {
|
$scope.wrapperSelectionChange = function wrapperSelectionChange(wrapper) {
|
||||||
|
|
||||||
|
// Get selection map for associated data source, creating if necessary
|
||||||
|
var selectedWrappers = allSelectedWrappers[wrapper.dataSource];
|
||||||
|
if (!selectedWrappers)
|
||||||
|
selectedWrappers = allSelectedWrappers[wrapper.dataSource] = {};
|
||||||
|
|
||||||
// Add wrapper to map if selected
|
// Add wrapper to map if selected
|
||||||
if (wrapper.checked)
|
if (wrapper.checked)
|
||||||
selectedWrappers[wrapper.activeConnection.identifier] = wrapper;
|
selectedWrappers[wrapper.activeConnection.identifier] = wrapper;
|
||||||
|
@@ -31,44 +31,47 @@ angular.module('settings').factory('ActiveConnectionWrapper', [
|
|||||||
* properties, such as a checked option.
|
* properties, such as a checked option.
|
||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {String} name
|
* @param {ActiveConnectionWrapper|Object} template
|
||||||
* The display name of the active connection.
|
* The object whose properties should be copied within the new
|
||||||
*
|
* ActiveConnectionWrapper.
|
||||||
* @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, startDate, activeConnection) {
|
var ActiveConnectionWrapper = function ActiveConnectionWrapper(template) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The identifier of the data source associate dwith the
|
||||||
|
* ActiveConnection wrapped by this ActiveConnectionWrapper.
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
this.dataSource = template.dataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The display name of this connection.
|
* The display name of this connection.
|
||||||
*
|
*
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
this.name = name;
|
this.name = template.name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The date and time this session began, pre-formatted for display.
|
* The date and time this session began, pre-formatted for display.
|
||||||
*
|
*
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
this.startDate = startDate;
|
this.startDate = template.startDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The wrapped ActiveConnection.
|
* The wrapped ActiveConnection.
|
||||||
*
|
*
|
||||||
* @type ActiveConnection
|
* @type ActiveConnection
|
||||||
*/
|
*/
|
||||||
this.activeConnection = activeConnection;
|
this.activeConnection = template.activeConnection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A flag indicating that the active connection has been selected.
|
* A flag indicating that the active connection has been selected.
|
||||||
*
|
*
|
||||||
* @type Boolean
|
* @type Boolean
|
||||||
*/
|
*/
|
||||||
this.checked = false;
|
this.checked = template.checked || false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user