diff --git a/guacamole/src/main/webapp/app/index/config/indexRouteConfig.js b/guacamole/src/main/webapp/app/index/config/indexRouteConfig.js index db16fc1dc..c980705ea 100644 --- a/guacamole/src/main/webapp/app/index/config/indexRouteConfig.js +++ b/guacamole/src/main/webapp/app/index/config/indexRouteConfig.js @@ -29,31 +29,37 @@ angular.module('index').config(['$routeProvider', '$locationProvider', // Disable HTML5 mode (use # for routing) $locationProvider.html5Mode(false); - $routeProvider. - when('/', { + $routeProvider + .when('/', { title: 'application.title', bodyClassName: 'home', templateUrl: 'app/home/templates/home.html', controller: 'homeController' - }). - when('/manage/', { + }) + .when('/manage/', { title: 'application.title', bodyClassName: 'manage', templateUrl: 'app/manage/templates/manage.html', controller: 'manageController' - }). - when('/login/', { + }) + .when('/manage/connections/:id?', { + title: 'application.title', + bodyClassName: 'manage-connection', + templateUrl: 'app/manage/templates/manageConnection.html', + controller: 'manageConnectionController' + }) + .when('/login/', { title: 'application.title', bodyClassName: 'login', templateUrl: 'app/login/templates/login.html', controller: 'loginController' - }). - when('/client/:type/:id/:params?', { + }) + .when('/client/:type/:id/:params?', { bodyClassName: 'client', templateUrl: 'app/client/templates/client.html', controller: 'clientController' - }). - otherwise({ + }) + .otherwise({ redirectTo: '/' }); }]); diff --git a/guacamole/src/main/webapp/app/index/styles/dialog.css b/guacamole/src/main/webapp/app/index/styles/dialog.css index e514eaf5b..bad31104a 100644 --- a/guacamole/src/main/webapp/app/index/styles/dialog.css +++ b/guacamole/src/main/webapp/app/index/styles/dialog.css @@ -92,23 +92,6 @@ z-index: 1; } -.dialog .dropdown { - - position: absolute; - z-index: 2; - margin-top: -1px; - - width: 3in; - max-height: 2in; - overflow: auto; - - border: 1px solid rgba(0, 0, 0, 0.5); - background: white; - - font-size: 10pt; - -} - .dialog .footer { text-align: center; } diff --git a/guacamole/src/main/webapp/app/manage/controllers/connectionEditModalController.js b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js similarity index 67% rename from guacamole/src/main/webapp/app/manage/controllers/connectionEditModalController.js rename to guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js index 5df9da58c..eca91e8a7 100644 --- a/guacamole/src/main/webapp/app/manage/controllers/connectionEditModalController.js +++ b/guacamole/src/main/webapp/app/manage/controllers/manageConnectionController.js @@ -23,51 +23,65 @@ /** * The controller for the connection edit modal. */ -angular.module('manage').controller('connectionEditModalController', ['$scope', '$injector', - function connectionEditModalController($scope, $injector) { - - var connectionEditModal = $injector.get('connectionEditModal'); +angular.module('manage').controller('manageConnectionController', ['$scope', '$injector', + function manageConnectionController($scope, $injector) { + + var $routeParams = $injector.get('$routeParams'); var connectionService = $injector.get('connectionService'); + var connectionGroupService = $injector.get('connectionGroupService'); + var protocolService = $injector.get('protocolService'); var Connection = $injector.get('Connection'); + var ConnectionGroup = $injector.get('ConnectionGroup'); + var PermissionSet = $injector.get('PermissionSet'); var HistoryEntryWrapper = $injector.get('HistoryEntryWrapper'); - + + var identifier = $routeParams.id; + // Make a copy of the old connection so that we can copy over the changes when done var oldConnection = $scope.connection; - - // Copy data into a new conection object in case the user doesn't want to save - $scope.connection = new Connection($scope.connection); - - var newConnection = !$scope.connection.identifier; - - // Set it to VNC by default - if(!$scope.connection.protocol) - $scope.connection.protocol = "vnc"; - - // Wrap all the history entries - if (!newConnection) { - connectionService.getConnectionHistory($scope.connection.identifier).success(function wrapHistoryEntries(historyEntries) { + connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER, PermissionSet.ObjectPermissionType.UPDATE) + .success(function connectionGroupReceived(rootGroup) { + $scope.rootGroup = rootGroup; + $scope.loadingConnections = false; + }); + + // Get the protocol information from the server and copy it into the scope + protocolService.getProtocols().success(function fetchProtocols(protocols) { + $scope.protocols = protocols; + }); + + // Wrap all the history entries + if (identifier) { + + // Copy data into a new conection object in case the user doesn't want to save + connectionService.getConnection(identifier).success(function connectionRetrieved(connection) { + $scope.connection = connection; + }); + + connectionService.getConnectionHistory(identifier).success(function wrapHistoryEntries(historyEntries) { $scope.historyEntryWrappers = []; historyEntries.forEach(function wrapHistoryEntry(historyEntry) { $scope.historyEntryWrappers.push(new HistoryEntryWrapper(historyEntry)); }); }); - connectionService.getConnectionParameters($scope.connection.identifier).success(function setParameters(parameters) { - $scope.connection.parameters = parameters; + connectionService.getConnectionParameters(identifier).success(function setParameters(parameters) { + $scope.parameters = parameters; }); } else { + $scope.connection = new Connection({ protocol: 'vnc' }); $scope.historyEntryWrappers = []; - $scope.connection.parameters = {}; + $scope.parameters = {}; } /** * Close the modal. */ $scope.close = function close() { - connectionEditModal.deactivate(); + //connectionEditModal.deactivate(); }; /** @@ -95,7 +109,7 @@ angular.module('manage').controller('connectionEditModalController', ['$scope', } // Close the modal - connectionEditModal.deactivate(); + //connectionEditModal.deactivate(); }); }; @@ -108,7 +122,7 @@ angular.module('manage').controller('connectionEditModalController', ['$scope', var newConnection = !$scope.connection.identifier; if(newConnection) { // Close the modal - connectionEditModal.deactivate(); + //connectionEditModal.deactivate(); return; } @@ -119,7 +133,7 @@ angular.module('manage').controller('connectionEditModalController', ['$scope', $scope.moveItem($scope.connection, oldParentID); // Close the modal - connectionEditModal.deactivate(); + //connectionEditModal.deactivate(); }); }; diff --git a/guacamole/src/main/webapp/app/manage/controllers/manageController.js b/guacamole/src/main/webapp/app/manage/controllers/manageController.js index 1efcde5d4..7fc5e0a08 100644 --- a/guacamole/src/main/webapp/app/manage/controllers/manageController.js +++ b/guacamole/src/main/webapp/app/manage/controllers/manageController.js @@ -32,7 +32,6 @@ angular.module('manage').controller('manageController', ['$scope', '$injector', // Required services var connectionGroupService = $injector.get('connectionGroupService'); - var connectionEditModal = $injector.get('connectionEditModal'); var connectionGroupEditModal = $injector.get('connectionGroupEditModal'); var userEditModal = $injector.get('userEditModal'); var protocolService = $injector.get('protocolService'); diff --git a/guacamole/src/main/webapp/app/manage/directives/locationChooser.js b/guacamole/src/main/webapp/app/manage/directives/locationChooser.js index 9b0961bbf..9f4b912d3 100644 --- a/guacamole/src/main/webapp/app/manage/directives/locationChooser.js +++ b/guacamole/src/main/webapp/app/manage/directives/locationChooser.js @@ -72,13 +72,6 @@ angular.module('manage').directive('locationChooser', [function locationChooser( }; - // Map all known groups - mapConnectionGroups($scope.rootGroup); - - // If no value is specified, default to the root identifier - if (!$scope.value || !($scope.value in connectionGroups)) - $scope.value = $scope.rootGroup.identifier; - /** * Whether the group list menu is currently open. * @@ -92,7 +85,7 @@ angular.module('manage').directive('locationChooser', [function locationChooser( * * @type String */ - $scope.chosenConnectionGroupName = connectionGroups[$scope.value].name; + $scope.chosenConnectionGroupName = null; /** * Toggle the current state of the menu listing connection groups. @@ -125,6 +118,24 @@ angular.module('manage').directive('locationChooser', [function locationChooser( }; + $scope.$watch('rootGroup', function setRootGroup(rootGroup) { + + connectionGroups = {}; + + if (!rootGroup) + return; + + // Map all known groups + mapConnectionGroups(rootGroup); + + // If no value is specified, default to the root identifier + if (!$scope.value || !($scope.value in connectionGroups)) + $scope.value = rootGroup.identifier; + + $scope.chosenConnectionGroupName = connectionGroups[$scope.value].name; + + }); + }] }; diff --git a/guacamole/src/main/webapp/app/manage/styles/buttons.css b/guacamole/src/main/webapp/app/manage/styles/buttons.css index 20f2ce3f0..ca5c5665a 100644 --- a/guacamole/src/main/webapp/app/manage/styles/buttons.css +++ b/guacamole/src/main/webapp/app/manage/styles/buttons.css @@ -31,7 +31,7 @@ button.add-user { } -button.add-connection { +a.button.add-connection { background-image: url('images/action-icons/guac-monitor-add.png'); background-repeat: no-repeat; diff --git a/guacamole/src/main/webapp/app/manage/services/connectionEditModal.js b/guacamole/src/main/webapp/app/manage/styles/locationChooser.css similarity index 71% rename from guacamole/src/main/webapp/app/manage/services/connectionEditModal.js rename to guacamole/src/main/webapp/app/manage/styles/locationChooser.css index cc251798a..836142270 100644 --- a/guacamole/src/main/webapp/app/manage/services/connectionEditModal.js +++ b/guacamole/src/main/webapp/app/manage/styles/locationChooser.css @@ -20,16 +20,19 @@ * THE SOFTWARE. */ -/** - * A modal for editing a connection. - */ -angular.module('manage').factory('connectionEditModal', ['btfModal', - function connectionEditModal(btfModal) { - - // Create the modal object to be used later to actually create the modal - return btfModal({ - controller: 'connectionEditModalController', - controllerAs: 'modal', - templateUrl: 'app/manage/templates/editableConnection.html', - }); -}]); +.location-chooser .dropdown { + + position: absolute; + z-index: 2; + margin-top: -1px; + + width: 3in; + max-height: 2in; + overflow: auto; + + border: 1px solid rgba(0, 0, 0, 0.5); + background: white; + + font-size: 10pt; + +} diff --git a/guacamole/src/main/webapp/app/manage/styles/manageConnection.css b/guacamole/src/main/webapp/app/manage/styles/manageConnection.css new file mode 100644 index 000000000..8df3ede5c --- /dev/null +++ b/guacamole/src/main/webapp/app/manage/styles/manageConnection.css @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 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. + */ + +.manage-connection .info table, +.manage-connection .parameters table { + margin: 1em; +} + +.manage-connection .info table th, +.manage-connection .parameters table th { + text-align: left; + font-weight: normal; + padding-right: 1em; +} + +.manage-connection .action-buttons { + text-align: center; + margin-bottom: 1em; +} diff --git a/guacamole/src/main/webapp/app/manage/templates/connection.html b/guacamole/src/main/webapp/app/manage/templates/connection.html index 578c8b654..b92988048 100644 --- a/guacamole/src/main/webapp/app/manage/templates/connection.html +++ b/guacamole/src/main/webapp/app/manage/templates/connection.html @@ -1,4 +1,4 @@ -
+ - - - -
-
- - -
-

{{connection.name}}

-
- - -
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - -
{{'manage.edit.connection.name' | translate}}
{{'manage.edit.connection.location' | translate}} - -
{{'manage.edit.connection.protocol' | translate}} - -
-
- - -
{{'manage.edit.connection.parameters' | translate}}
- -
- - - - - - - -
{{'protocol.' + connection.protocol + '.parameters.' + parameter.name + '.label' | translate}}: - -
-
- - -
{{'manage.edit.connection.history.usageHistory' | translate}}
- - -
-

{{'manage.edit.connection.history.connectionNotUsed' | translate}}

- - - - - - - - - - - - - -
{{'manage.edit.connection.history.username' | translate}}{{'manage.edit.connection.history.startTime' | translate}}{{'manage.edit.connection.history.duration' | translate}}
{{wrapper.entry.username}}{{wrapper.entry.startDate | date:'short'}}{{wrapper.durationText | translate:"{VALUE: wrapper.duration.value, UNIT: wrapper.duration.unit}"}}
-
-
-
-
-
- - - -
-
\ No newline at end of file diff --git a/guacamole/src/main/webapp/app/manage/templates/locationChooser.html b/guacamole/src/main/webapp/app/manage/templates/locationChooser.html index 8f7b793d5..967e9a36b 100644 --- a/guacamole/src/main/webapp/app/manage/templates/locationChooser.html +++ b/guacamole/src/main/webapp/app/manage/templates/locationChooser.html @@ -1,4 +1,4 @@ -
+
- +
{{chosenConnectionGroupName}}
- + +
diff --git a/guacamole/src/main/webapp/app/manage/templates/manage.html b/guacamole/src/main/webapp/app/manage/templates/manage.html index 9a428e58d..231b02dda 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manage.html +++ b/guacamole/src/main/webapp/app/manage/templates/manage.html @@ -57,7 +57,7 @@ THE SOFTWARE.
diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html new file mode 100644 index 000000000..80255b148 --- /dev/null +++ b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html @@ -0,0 +1,107 @@ + + + + + +

{{'manage.edit.connection.title' | translate}}

+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
{{'manage.edit.connection.name' | translate}}
{{'manage.edit.connection.location' | translate}} + +
{{'manage.edit.connection.protocol' | translate}} + +
+
+ + +

{{'manage.edit.connection.parameters' | translate}}

+ +
+ + + + + + + +
{{'protocol.' + connection.protocol + '.parameters.' + parameter.name + '.label' | translate}}: + +
+
+ + +
+ + + +
+ + +

{{'manage.edit.connection.history.usageHistory' | translate}}

+ + +
+

{{'manage.edit.connection.history.connectionNotUsed' | translate}}

+ + + + + + + + + + + + + + + +
{{'manage.edit.connection.history.username' | translate}}{{'manage.edit.connection.history.startTime' | translate}}{{'manage.edit.connection.history.duration' | translate}}
{{wrapper.entry.username}}{{wrapper.entry.startDate | date:'short'}}{{wrapper.durationText | translate:"{VALUE: wrapper.duration.value, UNIT: wrapper.duration.unit}"}}
+
diff --git a/guacamole/src/main/webapp/translations/en_US.json b/guacamole/src/main/webapp/translations/en_US.json index 2d8a236d3..9fa497063 100644 --- a/guacamole/src/main/webapp/translations/en_US.json +++ b/guacamole/src/main/webapp/translations/en_US.json @@ -39,6 +39,7 @@ "newGroup" : "New Group", "edit": { "connection": { + "title" : "Edit Connection", "cancel" : "Cancel", "save" : "Save", "delete" : "Delete", @@ -46,10 +47,10 @@ "root" : "ROOT", "location" : "Location:", "name" : "Name:", - "parameters" : "Parameters:", + "parameters" : "Parameters", "history" : { "connectionNotUsed" : "This connection has not yet been used.", - "usageHistory" : "Usage History:", + "usageHistory" : "Usage History", "username" : "Username", "startTime" : "Start Time", "duration" : "Duration",