diff --git a/guacamole/src/main/webapp/app/client/controllers/clientController.js b/guacamole/src/main/webapp/app/client/controllers/clientController.js index 74aea6220..b522568b7 100644 --- a/guacamole/src/main/webapp/app/client/controllers/clientController.js +++ b/guacamole/src/main/webapp/app/client/controllers/clientController.js @@ -36,6 +36,7 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams var guacClientManager = $injector.get('guacClientManager'); var guacNotification = $injector.get('guacNotification'); var preferenceService = $injector.get('preferenceService'); + var tunnelService = $injector.get('tunnelService'); var userPageService = $injector.get('userPageService'); /** @@ -235,6 +236,15 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams */ $scope.client = guacClientManager.getManagedClient($routeParams.id, $routeParams.params); + /** + * Map of all available sharing profiles for the current connection by + * their identifiers. If this information is not yet available, or no such + * sharing profiles exist, this will be an empty object. + * + * @type Object. + */ + $scope.sharingProfiles = {}; + /** * Map of all currently pressed keys by keysym. If a particular key is * currently pressed, the value stored under that key's keysym within this @@ -406,6 +416,63 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams }); + // Pull sharing profiles once the tunnel UUID is known + $scope.$watch('client.tunnel.uuid', function retrieveSharingProfiles(uuid) { + + // Only pull sharing profiles if tunnel UUID is actually available + if (!uuid) + return; + + // Pull sharing profiles for the current connection + tunnelService.getSharingProfiles(uuid) + .success(function sharingProfilesRetrieved(sharingProfiles) { + $scope.sharingProfiles = sharingProfiles; + }); + + }); + + /** + * Produces a sharing link for the current connection using the given + * sharing profile. The resulting sharing link, and any required login + * information, will be displayed to the user within the Guacamole menu. + * + * @param {SharingProfile} sharingProfile + * The sharing profile to use to generate the sharing link. + */ + $scope.share = function share(sharingProfile) { + ManagedClient.createShareLink($scope.client, sharingProfile); + }; + + /** + * Returns whether the current connection has any associated share links. + * + * @returns {Boolean} + * true if the current connection has at least one associated share + * link, false otherwise. + */ + $scope.isShared = function isShared() { + return ManagedClient.isShared($scope.client); + }; + + /** + * Returns the total number of share links associated with the current + * connection. + * + * @returns {Number} + * The total number of share links associated with the current + * connection. + */ + $scope.getShareLinkCount = function getShareLinkCount() { + + // Count total number of links within the ManagedClient's share link map + var linkCount = 0; + for (var dummy in $scope.client.shareLinks) + linkCount++; + + return linkCount; + + }; + // Track pressed keys, opening the Guacamole menu after Ctrl+Alt+Shift $scope.$on('guacKeydown', function keydownListener(event, keysym, keyboard) { @@ -762,6 +829,26 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams }; + /** + * Returns whether the current user can share the current connection with + * other users. A connection can be shared if and only if there is at least + * one associated sharing profile. + * + * @returns {Boolean} + * true if the current user can share the current connection with other + * users, false otherwise. + */ + $scope.canShareConnection = function canShareConnection() { + + // If there is at least one sharing profile, the connection can be shared + for (var dummy in $scope.sharingProfiles) + return true; + + // Otherwise, sharing is not possible + return false; + + }; + // Clean up when view destroyed $scope.$on('$destroy', function clientViewDestroyed() { diff --git a/guacamole/src/main/webapp/app/client/styles/client.css b/guacamole/src/main/webapp/app/client/styles/client.css index c110948e8..9ec74b6b2 100644 --- a/guacamole/src/main/webapp/app/client/styles/client.css +++ b/guacamole/src/main/webapp/app/client/styles/client.css @@ -116,7 +116,11 @@ body.client { } -.client .user-menu .options li a.disconnect { +.client .menu .header h2 { + text-transform: none; +} + +.client .user-menu .menu-contents li a.disconnect { background-repeat: no-repeat; background-size: 1em; background-position: 0.75em center; diff --git a/guacamole/src/main/webapp/app/client/styles/guac-menu.css b/guacamole/src/main/webapp/app/client/styles/guac-menu.css index bc96eb922..9e0fb7ca7 100644 --- a/guacamole/src/main/webapp/app/client/styles/guac-menu.css +++ b/guacamole/src/main/webapp/app/client/styles/guac-menu.css @@ -171,3 +171,31 @@ #guac-menu #devices .device.filesystem { background-image: url('images/drive.png'); } + +#guac-menu #share-links { + + padding: 1em; + border: 1px solid rgba(0, 0, 0, 0.125); + background: rgba(0, 0, 0, 0.04); + + font-size: 0.8em; + +} + +#guac-menu #share-links h3 { + padding-bottom: 0; +} + +#guac-menu #share-links th { + white-space: nowrap; +} + +#guac-menu #share-links a[href] { + + display: block; + padding: 0 1em; + + font-family: monospace; + font-weight: bold; + +} diff --git a/guacamole/src/main/webapp/app/client/styles/share-menu.css b/guacamole/src/main/webapp/app/client/styles/share-menu.css new file mode 100644 index 000000000..6d6659b01 --- /dev/null +++ b/guacamole/src/main/webapp/app/client/styles/share-menu.css @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.share-menu { + + /* IE10 */ + display: -ms-flexbox; + -ms-flex-align: stretch; + -ms-flex-direction: row; + + /* Ancient Mozilla */ + display: -moz-box; + -moz-box-align: stretch; + -moz-box-orient: horizontal; + + /* Ancient WebKit */ + display: -webkit-box; + -webkit-box-align: stretch; + -webkit-box-orient: horizontal; + + /* Old WebKit */ + display: -webkit-flex; + -webkit-align-items: stretch; + -webkit-flex-direction: row; + + /* W3C */ + display: flex; + align-items: stretch; + flex-direction: row; + +} + +.share-menu .menu-dropdown .menu-title { + + padding-left: 2em; + + background-repeat: no-repeat; + background-size: 1em; + background-position: 0.5em center; + background-image: url('images/share.png'); + +} diff --git a/guacamole/src/main/webapp/app/client/templates/client.html b/guacamole/src/main/webapp/app/client/templates/client.html index 8a4e7fea2..0580c8bbb 100644 --- a/guacamole/src/main/webapp/app/client/templates/client.html +++ b/guacamole/src/main/webapp/app/client/templates/client.html @@ -43,12 +43,35 @@

{{client.name}}

+