mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 21:27:40 +00:00
GUAC-933 Fixed connection history formatting, connection parameter saving, and create new connection view.
This commit is contained in:
@@ -29,12 +29,14 @@ angular.module('manage').controller('connectionEditModalController', ['$scope',
|
|||||||
var connectionEditModal = $injector.get('connectionEditModal');
|
var connectionEditModal = $injector.get('connectionEditModal');
|
||||||
var connectionService = $injector.get('connectionService');
|
var connectionService = $injector.get('connectionService');
|
||||||
var displayObjectPreparationService = $injector.get('displayObjectPreparationService');
|
var displayObjectPreparationService = $injector.get('displayObjectPreparationService');
|
||||||
|
var Connection = $injector.get('Connection');
|
||||||
|
var HistoryEntryWrapper = $injector.get('HistoryEntryWrapper');
|
||||||
|
|
||||||
// Make a copy of the old connection so that we can copy over the changes when done
|
// Make a copy of the old connection so that we can copy over the changes when done
|
||||||
var oldConnection = $scope.connection;
|
var oldConnection = $scope.connection;
|
||||||
|
|
||||||
// Copy data into a new conection object in case the user doesn't want to save
|
// Copy data into a new conection object in case the user doesn't want to save
|
||||||
$scope.connection = angular.copy($scope.connection);
|
$scope.connection = new Connection($scope.connection);
|
||||||
|
|
||||||
var newConnection = !$scope.connection.identifier;
|
var newConnection = !$scope.connection.identifier;
|
||||||
if(newConnection)
|
if(newConnection)
|
||||||
@@ -45,6 +47,13 @@ angular.module('manage').controller('connectionEditModalController', ['$scope',
|
|||||||
if(!$scope.connection.protocol)
|
if(!$scope.connection.protocol)
|
||||||
$scope.connection.protocol = "vnc";
|
$scope.connection.protocol = "vnc";
|
||||||
|
|
||||||
|
$scope.historyEntryWrappers = [];
|
||||||
|
|
||||||
|
// Wrap all the history entries
|
||||||
|
$scope.connection.history.forEach(function wrapHistoryEntry(historyEntry) {
|
||||||
|
$scope.historyEntryWrappers.push(new HistoryEntryWrapper(historyEntry));
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the modal.
|
* Close the modal.
|
||||||
*/
|
*/
|
||||||
@@ -103,7 +112,8 @@ angular.module('manage').controller('connectionEditModalController', ['$scope',
|
|||||||
// Close the modal
|
// Close the modal
|
||||||
connectionEditModal.deactivate();
|
connectionEditModal.deactivate();
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* A directive that allows editing of a connection parameter.
|
* A directive that allows editing of a connection parameter.
|
||||||
*/
|
*/
|
||||||
angular.module('manage').directive('guacConnectionParameter', [function locationChooser() {
|
angular.module('manage').directive('guacConnectionParameter', [function connectionParameter() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// Element only
|
// Element only
|
||||||
@@ -41,14 +41,44 @@ angular.module('manage').directive('guacConnectionParameter', [function location
|
|||||||
$scope.parameterName = $scope.parameter.name;
|
$scope.parameterName = $scope.parameter.name;
|
||||||
|
|
||||||
// Coerce numeric strings to numbers
|
// Coerce numeric strings to numbers
|
||||||
if($scope.parameterType === 'NUMERIC') {
|
if ($scope.parameterType === 'NUMERIC') {
|
||||||
$scope.connectionParameters[$scope.parameterName] =
|
|
||||||
Number($scope.connectionParameters[$scope.parameterName]) || 0;
|
// If a value exists, coerce it to a number
|
||||||
// Coerce boolean strings to boolean values
|
if ($scope.connectionParameters[$scope.parameterName])
|
||||||
} else if($scope.parameterType === 'BOOLEAN') {
|
$scope.parameterValue = Number($scope.connectionParameters[$scope.parameterName]);
|
||||||
$scope.connectionParameters[$scope.parameterName] =
|
else
|
||||||
$scope.connectionParameters[$scope.parameterName] === 'true';
|
$scope.parameterValue = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Coerce boolean strings to boolean values
|
||||||
|
else if ($scope.parameterType === 'BOOLEAN') {
|
||||||
|
// TODO: Use defined checked value from protocol description
|
||||||
|
$scope.parameterValue = $scope.connectionParameters[$scope.parameterName] === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other parameter types are represented internally as strings
|
||||||
|
else
|
||||||
|
$scope.parameterValue = $scope.connectionParameters[$scope.parameterName];
|
||||||
|
|
||||||
|
// Update internal representation as model is changed
|
||||||
|
$scope.$watch('parameterValue', function parameterValueChanges(value) {
|
||||||
|
|
||||||
|
// Convert numeric values back into strings
|
||||||
|
if ($scope.parameterType === 'NUMERIC') {
|
||||||
|
if (value === null || typeof value === 'undefined')
|
||||||
|
$scope.connectionParameters[$scope.parameterName] = '';
|
||||||
|
else
|
||||||
|
$scope.connectionParameters[$scope.parameterName] = value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Transform BOOLEAN input fields back into strings based on protocol description
|
||||||
|
|
||||||
|
// All other parameter types are already strings
|
||||||
|
else
|
||||||
|
$scope.connectionParameters[$scope.parameterName] = value;
|
||||||
|
|
||||||
|
});
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -23,5 +23,5 @@
|
|||||||
/**
|
/**
|
||||||
* The module for the administration functionality.
|
* The module for the administration functionality.
|
||||||
*/
|
*/
|
||||||
angular.module('manage', ['btford.modal', 'protocol', 'connectionGroup', 'util']);
|
angular.module('manage', ['btford.modal', 'protocol', 'connection', 'connectionGroup', 'util']);
|
||||||
|
|
||||||
|
@@ -20,10 +20,10 @@
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
-->
|
-->
|
||||||
<input ng-show="parameterType === 'TEXT'" type="text" ng-model="connectionParameters[parameterName]"/>
|
<input ng-show="parameterType === 'TEXT'" type="text" ng-model="parameterValue"/>
|
||||||
<input ng-show="parameterType === 'NUMERIC'" type="number" ng-model="connectionParameters[parameterName]"/>
|
<input ng-show="parameterType === 'NUMERIC'" type="number" ng-model="parameterValue"/>
|
||||||
<input ng-show="parameterType === 'USERNAME'" type="text" ng-model="connectionParameters[parameterName]"/>
|
<input ng-show="parameterType === 'USERNAME'" type="text" ng-model="parameterValue"/>
|
||||||
<input ng-show="parameterType === 'PASSWORD'" type="password" ng-model="connectionParameters[parameterName]"/>
|
<input ng-show="parameterType === 'PASSWORD'" type="password" ng-model="parameterValue"/>
|
||||||
<input ng-show="parameterType === 'BOOLEAN'" type="checkbox" ng-model="connectionParameters[parameterName]"/>
|
<input ng-show="parameterType === 'BOOLEAN'" type="checkbox" ng-model="parameterValue"/>
|
||||||
<select ng-show="parameterType === 'ENUM'" ng-model="connectionParameters[parameterName]" ng-options="option.value as 'protocol.' + connection.protocol + '.parameters.' + parameter.name + '.options.' + (option.value || 'empty') | translate for option in parameter.options | orderBy: value"></select>
|
<select ng-show="parameterType === 'ENUM'" ng-model="parameterValue" ng-options="option.value as 'protocol.' + connection.protocol + '.parameters.' + parameter.name + '.options.' + (option.value || 'empty') | translate for option in parameter.options | orderBy: value"></select>
|
||||||
</span>
|
</span>
|
@@ -94,12 +94,12 @@ THE SOFTWARE.
|
|||||||
<th>{{'manage.edit.connection.history.duration' | translate}}</th>
|
<th>{{'manage.edit.connection.history.duration' | translate}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="record in connection.history">
|
<tr ng-repeat="wrapper in historyEntryWrappers">
|
||||||
<td class="username">{{record.username}}</td>
|
<td class="username">{{wrapper.entry.username}}</td>
|
||||||
<td class="start">{{record.startDate | date:'short'}}</td>
|
<td class="start">{{wrapper.entry.startDate | date:'short'}}</td>
|
||||||
<td ng-show="record.endDate && !record.active" class="duration">{{record.endDate - record.startDate}}</td>
|
<td ng-show="wrapper.entry.endDate && !wrapper.entry.active" class="duration">{{'manage.edit.connection.history.formattedDuration' | translate:"{VALUE: wrapper.duration.value, UNIT: wrapper.duration.unit}"}}</td>
|
||||||
<td ng-show="!record.endDate && !record.active" class="duration">{{'manage.edit.connection.history.unknownEnd' | translate}}</td>
|
<td ng-show="!wrapper.entry.endDate && !wrapper.entry.active" class="duration">{{'manage.edit.connection.history.unknownEnd' | translate}}</td>
|
||||||
<td ng-show="record.active" class="duration">{{'manage.edit.connection.history.activeNow' | translate}}</td>
|
<td ng-show="wrapper.entry.active" class="duration">{{'manage.edit.connection.history.activeNow' | translate}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A service for generating new guacClient properties objects.
|
||||||
|
*/
|
||||||
|
angular.module('manage').factory('HistoryEntryWrapper', [function defineHistoryEntryWrapper() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a number of milliseconds, returns an object containing a unit and value
|
||||||
|
* for that history entry duration.
|
||||||
|
*
|
||||||
|
* @param {Number} milliseconds The number of milliseconds.
|
||||||
|
* @return {Object} A unit and value pair representing a history entry duration.
|
||||||
|
*/
|
||||||
|
var formatMilliseconds = function formatMilliseconds(milliseconds) {
|
||||||
|
|
||||||
|
var seconds = milliseconds / 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rounds the given value to the nearest tenth.
|
||||||
|
*
|
||||||
|
* @param {Number} value The value to round.
|
||||||
|
* @returns {Number} The given value, rounded to the nearest tenth.
|
||||||
|
*/
|
||||||
|
var round = function round(value) {
|
||||||
|
return Math.round(value * 10) / 10;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Seconds
|
||||||
|
if (seconds < 60) {
|
||||||
|
return {
|
||||||
|
value : round(seconds),
|
||||||
|
unit : "second"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minutes
|
||||||
|
if (seconds < 3600) {
|
||||||
|
return {
|
||||||
|
value : round(seconds / 60 ),
|
||||||
|
unit : "minute"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hours
|
||||||
|
if (seconds < 86400) {
|
||||||
|
return {
|
||||||
|
value : round(seconds / 3600),
|
||||||
|
unit : "hour"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Days
|
||||||
|
return {
|
||||||
|
value : round(seconds / 86400),
|
||||||
|
unit : "day"
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for ConnectionHistoryEntry which adds display-specific
|
||||||
|
* properties, such as the connection duration.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {ConnectionHistoryEntry} historyEntry
|
||||||
|
* The history entry to wrap.
|
||||||
|
*/
|
||||||
|
var HistoryEntryWrapper = function HistoryEntryWrapper(historyEntry) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The wrapped ConnectionHistoryEntry.
|
||||||
|
*
|
||||||
|
* @type ConnectionHistoryEntry
|
||||||
|
*/
|
||||||
|
this.entry = historyEntry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object providing value and unit properties, denoting the duration
|
||||||
|
* and its corresponding units.
|
||||||
|
*
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
this.duration = null;
|
||||||
|
|
||||||
|
// Set the duration if the necessary information is present
|
||||||
|
if (historyEntry.endDate && historyEntry.startDate)
|
||||||
|
this.duration = formatMilliseconds(historyEntry.endDate - historyEntry.startDate);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return HistoryEntryWrapper;
|
||||||
|
|
||||||
|
}]);
|
@@ -53,7 +53,8 @@
|
|||||||
"startTime" : "Start Time",
|
"startTime" : "Start Time",
|
||||||
"duration" : "Duration",
|
"duration" : "Duration",
|
||||||
"activeNow" : "Active Now",
|
"activeNow" : "Active Now",
|
||||||
"unknownEnd" : "--"
|
"unknownEnd" : "--",
|
||||||
|
"formattedDuration" : "{VALUE} {UNIT, select, second{{VALUE, plural, one{second} other{seconds}}} minute{{VALUE, plural, one{minute} other{minutes}}} hour{{VALUE, plural, one{hour} other{hours}}} day{{VALUE, plural, one{day} other{days}}} other{}}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"connectionGroup": {
|
"connectionGroup": {
|
||||||
|
Reference in New Issue
Block a user