mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-08 06:01:22 +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() {
|
$scope.applyParameterChanges = function applyParameterChanges() {
|
||||||
angular.forEach($scope.menu.connectionParameters, function sendArgv(value, name) {
|
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
|
* The set of clients that should be attached to the client UI. This will
|
||||||
* be immediately initialized by a call to updateAttachedClients() below.
|
* be immediately initialized by a call to updateAttachedClients() below.
|
||||||
@@ -173,6 +183,11 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
|||||||
*/
|
*/
|
||||||
$scope.getName = ManagedClientGroup.getName;
|
$scope.getName = ManagedClientGroup.getName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @borrows ManagedClientGroup.getTitle
|
||||||
|
*/
|
||||||
|
$scope.getTitle = ManagedClientGroup.getTitle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads the contents of $scope.clientGroup to reflect the client IDs
|
* Reloads the contents of $scope.clientGroup to reflect the client IDs
|
||||||
* currently listed in the URL.
|
* currently listed in the URL.
|
||||||
@@ -231,6 +246,27 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
|||||||
// reloading the route
|
// reloading the route
|
||||||
$scope.$on('$routeUpdate', updateAttachedClients);
|
$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
|
* The root connection groups of the connection hierarchy that should be
|
||||||
* presented to the user for selecting a different connection, as a map of
|
* 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();
|
$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
|
// Disable client keyboard if the menu is shown
|
||||||
angular.forEach($scope.clientGroup.clients, function updateKeyboardEnabled(client) {
|
angular.forEach($scope.clientGroup.clients, function updateKeyboardEnabled(client) {
|
||||||
client.clientProperties.keyboardEnabled = !menuShown;
|
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
|
// 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);
|
iconService.setIcons(canvas);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -487,7 +535,7 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Pull sharing profiles once the tunnel UUID is known
|
// 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
|
// Only pull sharing profiles if tunnel UUID is actually available
|
||||||
if (!uuid)
|
if (!uuid)
|
||||||
@@ -510,7 +558,8 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
|||||||
* The sharing profile to use to generate the sharing link.
|
* The sharing profile to use to generate the sharing link.
|
||||||
*/
|
*/
|
||||||
$scope.share = function share(sharingProfile) {
|
$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.
|
* link, false otherwise.
|
||||||
*/
|
*/
|
||||||
$scope.isShared = function isShared() {
|
$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() {
|
$scope.getShareLinkCount = function getShareLinkCount() {
|
||||||
|
|
||||||
|
if (!$scope.focusedClient)
|
||||||
|
return 0;
|
||||||
|
|
||||||
// Count total number of links within the ManagedClient's share link map
|
// Count total number of links within the ManagedClient's share link map
|
||||||
var linkCount = 0;
|
var linkCount = 0;
|
||||||
for (var dummy in $scope.client.shareLinks)
|
for (var dummy in $scope.focusedClient.shareLinks)
|
||||||
linkCount++;
|
linkCount++;
|
||||||
|
|
||||||
return linkCount;
|
return linkCount;
|
||||||
@@ -625,7 +677,7 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Update page title when client title changes
|
// 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;
|
$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() {
|
$scope.disconnect = function disconnect() {
|
||||||
|
|
||||||
// Disconnect if client is available
|
// Disconnect if client is available
|
||||||
if ($scope.client)
|
if ($scope.clientGroup) {
|
||||||
$scope.client.client.disconnect();
|
$scope.clientGroup.clients.forEach(client => {
|
||||||
|
if (client.clientProperties.focused)
|
||||||
|
client.client.disconnect();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Hide menu
|
// Hide menu
|
||||||
$scope.menu.shown = false;
|
$scope.menu.shown = false;
|
||||||
@@ -804,13 +860,9 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams
|
|||||||
*/
|
*/
|
||||||
$scope.uploadFiles = function uploadFiles(files) {
|
$scope.uploadFiles = function uploadFiles(files) {
|
||||||
|
|
||||||
// Ignore file uploads if no attached client
|
|
||||||
if (!$scope.client)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Upload each file
|
// Upload each file
|
||||||
for (var i = 0; i < files.length; i++)
|
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,
|
replace: true,
|
||||||
scope: {
|
scope: {
|
||||||
|
|
||||||
/**
|
|
||||||
* The client whose file transfers should be managed by this
|
|
||||||
* directive.
|
|
||||||
*
|
|
||||||
* @type ManagedClient
|
|
||||||
*/
|
|
||||||
client : '=',
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type ManagedFilesystem
|
* @type ManagedFilesystem
|
||||||
*/
|
*/
|
||||||
@@ -116,7 +108,7 @@ angular.module('client').directive('guacFileBrowser', [function guacFileBrowser(
|
|||||||
* The file to download.
|
* The file to download.
|
||||||
*/
|
*/
|
||||||
$scope.downloadFile = function downloadFile(file) {
|
$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="CLIENT.HELP_SHARE_LINK"
|
||||||
translate-values="{LINKS : getShareLinkCount()}"></p>
|
translate-values="{LINKS : getShareLinkCount()}"></p>
|
||||||
<table>
|
<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>
|
<th>{{link.value.name}}</th>
|
||||||
<td><a href="{{link.value.href}}" target="_blank">{{link.value.href}}</a></td>
|
<td><a href="{{link.value.href}}" target="_blank">{{link.value.href}}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -105,19 +105,19 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Devices -->
|
<!-- 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>
|
<h3>{{'CLIENT.SECTION_HEADER_DEVICES' | translate}}</h3>
|
||||||
<div class="content">
|
<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}}
|
{{filesystem.name}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Connection parameters which may be modified while the connection is open -->
|
<!-- Connection parameters which may be modified while the connection is open -->
|
||||||
<div class="menu-section connection-parameters" id="connection-settings" ng-show="client.protocol">
|
<div class="menu-section connection-parameters" id="connection-settings" ng-if="focusedClient.protocol">
|
||||||
<guac-form namespace="getProtocolNamespace(client.protocol)"
|
<guac-form namespace="getProtocolNamespace(focusedClient.protocol)"
|
||||||
content="client.forms"
|
content="focusedClient.forms"
|
||||||
model="menu.connectionParameters"
|
model="menu.connectionParameters"
|
||||||
model-only="true"></guac-form>
|
model-only="true"></guac-form>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
/**
|
/**
|
||||||
* Provides the ManagedClientGroup class used by the guacClientManager service.
|
* 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
|
* Object which serves as a grouping of ManagedClients. Each
|
||||||
@@ -201,7 +201,15 @@ angular.module('client').factory('ManagedClientGroup', [function defineManagedCl
|
|||||||
* ManagedClientGroup.
|
* ManagedClientGroup.
|
||||||
*/
|
*/
|
||||||
ManagedClientGroup.getName = function getName(group) {
|
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;
|
return ManagedClientGroup;
|
||||||
|
@@ -42,6 +42,14 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector'
|
|||||||
// Use empty object by default
|
// Use empty object by default
|
||||||
template = template || {};
|
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"
|
* The Guacamole filesystem object, as received via a "filesystem"
|
||||||
* instruction.
|
* instruction.
|
||||||
@@ -171,10 +179,11 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector'
|
|||||||
* @returns {ManagedFilesystem}
|
* @returns {ManagedFilesystem}
|
||||||
* The newly-created ManagedFilesystem.
|
* The newly-created ManagedFilesystem.
|
||||||
*/
|
*/
|
||||||
ManagedFilesystem.getInstance = function getInstance(object, name) {
|
ManagedFilesystem.getInstance = function getInstance(client, object, name) {
|
||||||
|
|
||||||
// Init new filesystem object
|
// Init new filesystem object
|
||||||
var managedFilesystem = new ManagedFilesystem({
|
var managedFilesystem = new ManagedFilesystem({
|
||||||
|
client : client,
|
||||||
object : object,
|
object : object,
|
||||||
name : name,
|
name : name,
|
||||||
root : new ManagedFilesystem.File({
|
root : new ManagedFilesystem.File({
|
||||||
@@ -196,9 +205,6 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector'
|
|||||||
* client and filesystem. The browser will automatically start the
|
* client and filesystem. The browser will automatically start the
|
||||||
* download upon completion of this function.
|
* download upon completion of this function.
|
||||||
*
|
*
|
||||||
* @param {ManagedClient} managedClient
|
|
||||||
* The ManagedClient from which the file is to be downloaded.
|
|
||||||
*
|
|
||||||
* @param {ManagedFilesystem} managedFilesystem
|
* @param {ManagedFilesystem} managedFilesystem
|
||||||
* The ManagedFilesystem from which the file is to be downloaded. Any
|
* The ManagedFilesystem from which the file is to be downloaded. Any
|
||||||
* path information provided must be relative to this filesystem.
|
* path information provided must be relative to this filesystem.
|
||||||
@@ -206,7 +212,7 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector'
|
|||||||
* @param {String} path
|
* @param {String} path
|
||||||
* The full, absolute path of the file to download.
|
* The full, absolute path of the file to download.
|
||||||
*/
|
*/
|
||||||
ManagedFilesystem.downloadFile = function downloadFile(managedClient, managedFilesystem, path) {
|
ManagedFilesystem.downloadFile = function downloadFile(managedFilesystem, path) {
|
||||||
|
|
||||||
// Request download
|
// Request download
|
||||||
managedFilesystem.object.requestInputStream(path, function downloadStreamReceived(stream, mimetype) {
|
managedFilesystem.object.requestInputStream(path, function downloadStreamReceived(stream, mimetype) {
|
||||||
@@ -215,7 +221,7 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector'
|
|||||||
var filename = path.match(/(.*[\\/])?(.*)/)[2];
|
var filename = path.match(/(.*[\\/])?(.*)/)[2];
|
||||||
|
|
||||||
// Start download
|
// 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