mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-724: Control only the currently-focused client with client-specific menu options.
This commit is contained in:
@@ -156,10 +156,20 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
*/
|
||||
$scope.applyParameterChanges = function applyParameterChanges() {
|
||||
angular.forEach($scope.menu.connectionParameters, function sendArgv(value, name) {
|
||||
ManagedClient.setArgument($scope.client, name, value);
|
||||
if ($scope.focusedClient)
|
||||
ManagedClient.setArgument($scope.focusedClient, name, value);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* The currently-focused client within the current ManagedClientGroup. If
|
||||
* there is no current group, no client is focused, or multiple clients are
|
||||
* focused, this will be null.
|
||||
*
|
||||
* @type ManagedClient
|
||||
*/
|
||||
$scope.focusedClient = null;
|
||||
|
||||
/**
|
||||
* The set of clients that should be attached to the client UI. This will
|
||||
* be immediately initialized by a call to updateAttachedClients() below.
|
||||
@@ -173,6 +183,11 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
*/
|
||||
$scope.getName = ManagedClientGroup.getName;
|
||||
|
||||
/**
|
||||
* @borrows ManagedClientGroup.getTitle
|
||||
*/
|
||||
$scope.getTitle = ManagedClientGroup.getTitle;
|
||||
|
||||
/**
|
||||
* Reloads the contents of $scope.clientGroup to reflect the client IDs
|
||||
* currently listed in the URL.
|
||||
@@ -231,6 +246,27 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
// reloading the route
|
||||
$scope.$on('$routeUpdate', updateAttachedClients);
|
||||
|
||||
/**
|
||||
* Returns the currently-focused ManagedClient. If there is no such client,
|
||||
* or multiple clients are focused, null is returned.
|
||||
*
|
||||
* @returns {ManagedClient}
|
||||
* The currently-focused client, or null if there are no focused
|
||||
* clients or if multiple clients are focused.
|
||||
*/
|
||||
$scope.getFocusedClient = function getFocusedClient() {
|
||||
|
||||
var managedClientGroup = $scope.clientGroup;
|
||||
if (managedClientGroup) {
|
||||
var focusedClients = _.filter(managedClientGroup.clients, client => client.clientProperties.focused);
|
||||
if (focusedClients.length === 1)
|
||||
return focusedClients[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The root connection groups of the connection hierarchy that should be
|
||||
* presented to the user for selecting a different connection, as a map of
|
||||
@@ -456,11 +492,6 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
$scope.applyParameterChanges();
|
||||
}
|
||||
|
||||
// Obtain snapshot of current editable connection parameters when menu
|
||||
// is opened
|
||||
else if (menuShown)
|
||||
$scope.menu.connectionParameters = ManagedClient.getArgumentModel($scope.client);
|
||||
|
||||
// Disable client keyboard if the menu is shown
|
||||
angular.forEach($scope.clientGroup.clients, function updateKeyboardEnabled(client) {
|
||||
client.clientProperties.keyboardEnabled = !menuShown;
|
||||
@@ -468,8 +499,25 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
|
||||
});
|
||||
|
||||
// Automatically track and cache the currently-focused client
|
||||
$scope.$watch('getFocusedClient()', function focusedClientChanged(client) {
|
||||
|
||||
// Apply any parameter changes when focus is changing (as
|
||||
// applyParameterChanges() depends on the value of focusedClient, this
|
||||
// must be called BEFORE updating focusedClient
|
||||
$scope.applyParameterChanges();
|
||||
|
||||
$scope.focusedClient = client;
|
||||
|
||||
// Update available connection parameters, if there is a focused
|
||||
// client
|
||||
$scope.menu.connectionParameters = $scope.focusedClient ?
|
||||
ManagedClient.getArgumentModel($scope.focusedClient) : {};
|
||||
|
||||
});
|
||||
|
||||
// Update page icon when thumbnail changes
|
||||
$scope.$watch('client.thumbnail.canvas', function thumbnailChanged(canvas) {
|
||||
$scope.$watch('focusedClient.thumbnail.canvas', function thumbnailChanged(canvas) {
|
||||
iconService.setIcons(canvas);
|
||||
});
|
||||
|
||||
@@ -487,7 +535,7 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
});
|
||||
|
||||
// Pull sharing profiles once the tunnel UUID is known
|
||||
$scope.$watch('client.tunnel.uuid', function retrieveSharingProfiles(uuid) {
|
||||
$scope.$watch('focusedClient.tunnel.uuid', function retrieveSharingProfiles(uuid) {
|
||||
|
||||
// Only pull sharing profiles if tunnel UUID is actually available
|
||||
if (!uuid)
|
||||
@@ -510,7 +558,8 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
* The sharing profile to use to generate the sharing link.
|
||||
*/
|
||||
$scope.share = function share(sharingProfile) {
|
||||
ManagedClient.createShareLink($scope.client, sharingProfile);
|
||||
if ($scope.focusedClient)
|
||||
ManagedClient.createShareLink($scope.focusedClient, sharingProfile);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -521,7 +570,7 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
* link, false otherwise.
|
||||
*/
|
||||
$scope.isShared = function isShared() {
|
||||
return ManagedClient.isShared($scope.client);
|
||||
return !!$scope.focusedClient && ManagedClient.isShared($scope.focusedClient);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -534,9 +583,12 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
*/
|
||||
$scope.getShareLinkCount = function getShareLinkCount() {
|
||||
|
||||
if (!$scope.focusedClient)
|
||||
return 0;
|
||||
|
||||
// Count total number of links within the ManagedClient's share link map
|
||||
var linkCount = 0;
|
||||
for (var dummy in $scope.client.shareLinks)
|
||||
for (var dummy in $scope.focusedClient.shareLinks)
|
||||
linkCount++;
|
||||
|
||||
return linkCount;
|
||||
@@ -625,7 +677,7 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
});
|
||||
|
||||
// Update page title when client title changes
|
||||
$scope.$watch('client.title', function clientTitleChanged(title) {
|
||||
$scope.$watch('getTitle(clientGroup)', function clientTitleChanged(title) {
|
||||
$scope.page.title = title;
|
||||
});
|
||||
|
||||
@@ -678,13 +730,17 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
};
|
||||
|
||||
/**
|
||||
* Immediately disconnects the currently-connected client, if any.
|
||||
* Immediately disconnects all currently-focused clients, if any.
|
||||
*/
|
||||
$scope.disconnect = function disconnect() {
|
||||
|
||||
// Disconnect if client is available
|
||||
if ($scope.client)
|
||||
$scope.client.client.disconnect();
|
||||
if ($scope.clientGroup) {
|
||||
$scope.clientGroup.clients.forEach(client => {
|
||||
if (client.clientProperties.focused)
|
||||
client.client.disconnect();
|
||||
});
|
||||
}
|
||||
|
||||
// Hide menu
|
||||
$scope.menu.shown = false;
|
||||
@@ -804,13 +860,9 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
||||
*/
|
||||
$scope.uploadFiles = function uploadFiles(files) {
|
||||
|
||||
// Ignore file uploads if no attached client
|
||||
if (!$scope.client)
|
||||
return;
|
||||
|
||||
// Upload each file
|
||||
for (var i = 0; i < files.length; i++)
|
||||
ManagedClient.uploadFile($scope.client, files[i], $scope.filesystemMenuContents);
|
||||
ManagedClient.uploadFile($scope.filesystemMenuContents.client, files[i], $scope.filesystemMenuContents);
|
||||
|
||||
};
|
||||
|
||||
|
@@ -28,14 +28,6 @@ angular.module('client').directive('guacFileBrowser', [function guacFileBrowser(
|
||||
replace: true,
|
||||
scope: {
|
||||
|
||||
/**
|
||||
* The client whose file transfers should be managed by this
|
||||
* directive.
|
||||
*
|
||||
* @type ManagedClient
|
||||
*/
|
||||
client : '=',
|
||||
|
||||
/**
|
||||
* @type ManagedFilesystem
|
||||
*/
|
||||
@@ -116,7 +108,7 @@ angular.module('client').directive('guacFileBrowser', [function guacFileBrowser(
|
||||
* The file to download.
|
||||
*/
|
||||
$scope.downloadFile = function downloadFile(file) {
|
||||
ManagedFilesystem.downloadFile($scope.client, $scope.filesystem, file.streamName);
|
||||
ManagedFilesystem.downloadFile($scope.filesystem, file.streamName);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -87,7 +87,7 @@
|
||||
translate="CLIENT.HELP_SHARE_LINK"
|
||||
translate-values="{LINKS : getShareLinkCount()}"></p>
|
||||
<table>
|
||||
<tr ng-repeat="link in client.shareLinks | toArray | orderBy: value.name">
|
||||
<tr ng-repeat="link in focusedClient.shareLinks | toArray | orderBy: value.name">
|
||||
<th>{{link.value.name}}</th>
|
||||
<td><a href="{{link.value.href}}" target="_blank">{{link.value.href}}</a></td>
|
||||
</tr>
|
||||
@@ -105,19 +105,19 @@
|
||||
</div>
|
||||
|
||||
<!-- Devices -->
|
||||
<div class="menu-section" id="devices" ng-show="client.filesystems.length">
|
||||
<div class="menu-section" id="devices" ng-if="focusedClient.filesystems.length">
|
||||
<h3>{{'CLIENT.SECTION_HEADER_DEVICES' | translate}}</h3>
|
||||
<div class="content">
|
||||
<div class="device filesystem" ng-repeat="filesystem in client.filesystems" ng-click="showFilesystemMenu(filesystem)">
|
||||
<div class="device filesystem" ng-repeat="filesystem in focusedClient.filesystems" ng-click="showFilesystemMenu(filesystem)">
|
||||
{{filesystem.name}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Connection parameters which may be modified while the connection is open -->
|
||||
<div class="menu-section connection-parameters" id="connection-settings" ng-show="client.protocol">
|
||||
<guac-form namespace="getProtocolNamespace(client.protocol)"
|
||||
content="client.forms"
|
||||
<div class="menu-section connection-parameters" id="connection-settings" ng-if="focusedClient.protocol">
|
||||
<guac-form namespace="getProtocolNamespace(focusedClient.protocol)"
|
||||
content="focusedClient.forms"
|
||||
model="menu.connectionParameters"
|
||||
model-only="true"></guac-form>
|
||||
</div>
|
||||
|
@@ -20,7 +20,7 @@
|
||||
/**
|
||||
* Provides the ManagedClientGroup class used by the guacClientManager service.
|
||||
*/
|
||||
angular.module('client').factory('ManagedClientGroup', [function defineManagedClientGroup() {
|
||||
angular.module('client').factory('ManagedClientGroup', ['$injector', function defineManagedClientGroup($injector) {
|
||||
|
||||
/**
|
||||
* Object which serves as a grouping of ManagedClients. Each
|
||||
@@ -201,7 +201,15 @@ angular.module('client').factory('ManagedClientGroup', [function defineManagedCl
|
||||
* ManagedClientGroup.
|
||||
*/
|
||||
ManagedClientGroup.getName = function getName(group) {
|
||||
return _.filter(group.clients, (client => !!client.name)).map(client => client.name).join(', ') || '...';
|
||||
|
||||
// Generate a name from ONLY the focused clients, unless there are no
|
||||
// focused clients
|
||||
var relevantClients = _.filter(group.clients, client => client.clientProperties.focused);
|
||||
if (!relevantClients.length)
|
||||
relevantClients = group.clients;
|
||||
|
||||
return _.filter(relevantClients, (client => !!client.name)).map(client => client.name).join(', ') || '...';
|
||||
|
||||
};
|
||||
|
||||
return ManagedClientGroup;
|
||||
|
@@ -42,6 +42,14 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector'
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The client that originally received the "filesystem" instruction
|
||||
* that resulted in the creation of this ManagedFilesystem.
|
||||
*
|
||||
* @type ManagedClient
|
||||
*/
|
||||
this.client = template.client;
|
||||
|
||||
/**
|
||||
* The Guacamole filesystem object, as received via a "filesystem"
|
||||
* instruction.
|
||||
@@ -171,10 +179,11 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector'
|
||||
* @returns {ManagedFilesystem}
|
||||
* The newly-created ManagedFilesystem.
|
||||
*/
|
||||
ManagedFilesystem.getInstance = function getInstance(object, name) {
|
||||
ManagedFilesystem.getInstance = function getInstance(client, object, name) {
|
||||
|
||||
// Init new filesystem object
|
||||
var managedFilesystem = new ManagedFilesystem({
|
||||
client : client,
|
||||
object : object,
|
||||
name : name,
|
||||
root : new ManagedFilesystem.File({
|
||||
@@ -196,9 +205,6 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector'
|
||||
* client and filesystem. The browser will automatically start the
|
||||
* download upon completion of this function.
|
||||
*
|
||||
* @param {ManagedClient} managedClient
|
||||
* The ManagedClient from which the file is to be downloaded.
|
||||
*
|
||||
* @param {ManagedFilesystem} managedFilesystem
|
||||
* The ManagedFilesystem from which the file is to be downloaded. Any
|
||||
* path information provided must be relative to this filesystem.
|
||||
@@ -206,7 +212,7 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector'
|
||||
* @param {String} path
|
||||
* The full, absolute path of the file to download.
|
||||
*/
|
||||
ManagedFilesystem.downloadFile = function downloadFile(managedClient, managedFilesystem, path) {
|
||||
ManagedFilesystem.downloadFile = function downloadFile(managedFilesystem, path) {
|
||||
|
||||
// Request download
|
||||
managedFilesystem.object.requestInputStream(path, function downloadStreamReceived(stream, mimetype) {
|
||||
@@ -215,7 +221,7 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector'
|
||||
var filename = path.match(/(.*[\\/])?(.*)/)[2];
|
||||
|
||||
// Start download
|
||||
tunnelService.downloadStream(managedClient.tunnel.uuid, stream, mimetype, filename);
|
||||
tunnelService.downloadStream(managedFilesystem.client.tunnel.uuid, stream, mimetype, filename);
|
||||
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user