mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-334: Merge ability to download connection history results as csv.
This commit is contained in:
@@ -39,8 +39,10 @@ angular.module('settings').directive('guacSettingsConnectionHistory', [function
|
||||
var SortOrder = $injector.get('SortOrder');
|
||||
|
||||
// Get required services
|
||||
var $filter = $injector.get('$filter');
|
||||
var $routeParams = $injector.get('$routeParams');
|
||||
var $translate = $injector.get('$translate');
|
||||
var csvService = $injector.get('csvService');
|
||||
var historyService = $injector.get('historyService');
|
||||
|
||||
/**
|
||||
@@ -178,6 +180,53 @@ angular.module('settings').directive('guacSettingsConnectionHistory', [function
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Initiates a download of a CSV version of the displayed history
|
||||
* search results.
|
||||
*/
|
||||
$scope.downloadCSV = function downloadCSV() {
|
||||
|
||||
// Translate CSV header
|
||||
$translate([
|
||||
'SETTINGS_CONNECTION_HISTORY.TABLE_HEADER_SESSION_USERNAME',
|
||||
'SETTINGS_CONNECTION_HISTORY.TABLE_HEADER_SESSION_STARTDATE',
|
||||
'SETTINGS_CONNECTION_HISTORY.TABLE_HEADER_SESSION_DURATION',
|
||||
'SETTINGS_CONNECTION_HISTORY.TABLE_HEADER_SESSION_CONNECTION_NAME',
|
||||
'SETTINGS_CONNECTION_HISTORY.FILENAME_HISTORY_CSV'
|
||||
]).then(function headerTranslated(translations) {
|
||||
|
||||
// Initialize records with translated header row
|
||||
var records = [[
|
||||
translations['SETTINGS_CONNECTION_HISTORY.TABLE_HEADER_SESSION_USERNAME'],
|
||||
translations['SETTINGS_CONNECTION_HISTORY.TABLE_HEADER_SESSION_STARTDATE'],
|
||||
translations['SETTINGS_CONNECTION_HISTORY.TABLE_HEADER_SESSION_DURATION'],
|
||||
translations['SETTINGS_CONNECTION_HISTORY.TABLE_HEADER_SESSION_CONNECTION_NAME']
|
||||
]];
|
||||
|
||||
// Add rows for all history entries, using the same sort
|
||||
// order as the displayed table
|
||||
angular.forEach(
|
||||
$filter('orderBy')(
|
||||
$scope.historyEntryWrappers,
|
||||
$scope.order.predicate
|
||||
),
|
||||
function pushRecord(historyEntryWrapper) {
|
||||
records.push([
|
||||
historyEntryWrapper.username,
|
||||
$filter('date')(historyEntryWrapper.startDate, $scope.dateFormat),
|
||||
historyEntryWrapper.duration / 1000,
|
||||
historyEntryWrapper.connectionName
|
||||
]);
|
||||
}
|
||||
);
|
||||
|
||||
// Save the result
|
||||
saveAs(csvService.toBlob(records), translations['SETTINGS_CONNECTION_HISTORY.FILENAME_HISTORY_CSV']);
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// Initialize search results
|
||||
$scope.search();
|
||||
|
||||
|
106
guacamole/src/main/webapp/app/settings/services/csvService.js
Normal file
106
guacamole/src/main/webapp/app/settings/services/csvService.js
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A service for generating downloadable CSV links given arbitrary data.
|
||||
*/
|
||||
angular.module('settings').factory('csvService', [function csvService() {
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Encodes an arbitrary value for inclusion in a CSV file as an individual
|
||||
* field. With the exception of null and undefined (which are both
|
||||
* interpreted as equivalent to an empty string), all values are coerced to
|
||||
* a string and, if non-numeric, included within double quotes. If the
|
||||
* value itself includes double quotes, those quotes will be properly
|
||||
* escaped.
|
||||
*
|
||||
* @param {*} field
|
||||
* The arbitrary value to encode.
|
||||
*
|
||||
* @return {String}
|
||||
* The provided value, coerced to a string and properly escaped for
|
||||
* CSV.
|
||||
*/
|
||||
var encodeField = function encodeField(field) {
|
||||
|
||||
// Coerce field to string
|
||||
if (field === null || field === undefined)
|
||||
field = '';
|
||||
else
|
||||
field = '' + field;
|
||||
|
||||
// Do not quote numeric fields
|
||||
if (/^[0-9.]*$/.test(field))
|
||||
return field;
|
||||
|
||||
// Enclose all other fields in quotes, escaping any quotes therein
|
||||
return '"' + field.replace(/"/g, '""') + '"';
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Encodes each of the provided values for inclusion in a CSV file as
|
||||
* fields within the same record (in the manner specified by
|
||||
* encodeField()), separated by commas.
|
||||
*
|
||||
* @param {*[]} fields
|
||||
* An array of arbitrary values which make up the record.
|
||||
*
|
||||
* @return {String}
|
||||
* A CSV record containing the each value in the given array.
|
||||
*/
|
||||
var encodeRecord = function encodeRecord(fields) {
|
||||
return fields.map(encodeField).join(',');
|
||||
};
|
||||
|
||||
/**
|
||||
* Encodes an entire array of records as properly-formatted CSV, where each
|
||||
* entry in the provided array is an array of arbitrary fields.
|
||||
*
|
||||
* @param {Array.<*[]>} records
|
||||
* An array of all records making up the desired CSV.
|
||||
*
|
||||
* @return {String}
|
||||
* An entire CSV containing each provided record, separated by CR+LF
|
||||
* line terminators.
|
||||
*/
|
||||
var encodeCSV = function encodeCSV(records) {
|
||||
return records.map(encodeRecord).join('\r\n');
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new Blob containing properly-formatted CSV generated from the
|
||||
* given array of records, where each entry in the provided array is an
|
||||
* array of arbitrary fields.
|
||||
*
|
||||
* @param {Array.<*[]>} records
|
||||
* An array of all records making up the desired CSV.
|
||||
*
|
||||
* @returns {Blob}
|
||||
* A new Blob containing each provided record in CSV format.
|
||||
*/
|
||||
service.toBlob = function toBlob(records) {
|
||||
return new Blob([ encodeCSV(records) ], { type : 'text/csv' });
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}]);
|
@@ -46,9 +46,26 @@
|
||||
|
||||
}
|
||||
|
||||
.settings.connectionHistory .filter .search-button {
|
||||
.settings.connectionHistory .filter .search-string {
|
||||
-ms-flex: 1 1 auto;
|
||||
-moz-box-flex: 1;
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-flex: 1 1 auto;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.settings.connectionHistory .filter .search-button,
|
||||
.settings.connectionHistory .filter button {
|
||||
|
||||
-ms-flex: 0 0 auto;
|
||||
-moz-box-flex: 0;
|
||||
-webkit-box-flex: 0;
|
||||
-webkit-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
|
||||
}
|
||||
|
||||
.settings.connectionHistory .history-list {
|
||||
|
@@ -7,6 +7,7 @@
|
||||
<form class="filter" ng-submit="search()">
|
||||
<input class="search-string" type="text" placeholder="{{'SETTINGS_CONNECTION_HISTORY.FIELD_PLACEHOLDER_FILTER' | translate}}" ng-model="searchString" />
|
||||
<input class="search-button" type="submit" value="{{'SETTINGS_CONNECTION_HISTORY.ACTION_SEARCH' | translate}}" />
|
||||
<button type="button" ng-click="downloadCSV()">{{'SETTINGS_CONNECTION_HISTORY.ACTION_DOWNLOAD' | translate}}</button>
|
||||
</form>
|
||||
|
||||
<!-- Search results -->
|
||||
|
@@ -13,6 +13,7 @@
|
||||
"ACTION_CONTINUE" : "Continue",
|
||||
"ACTION_DELETE" : "Delete",
|
||||
"ACTION_DELETE_SESSIONS" : "Kill Sessions",
|
||||
"ACTION_DOWNLOAD" : "Download",
|
||||
"ACTION_LOGIN" : "Login",
|
||||
"ACTION_LOGOUT" : "Logout",
|
||||
"ACTION_MANAGE_CONNECTIONS" : "Connections",
|
||||
@@ -578,10 +579,13 @@
|
||||
|
||||
"SETTINGS_CONNECTION_HISTORY" : {
|
||||
|
||||
"ACTION_SEARCH" : "@:APP.ACTION_SEARCH",
|
||||
"ACTION_DOWNLOAD" : "@:APP.ACTION_DOWNLOAD",
|
||||
"ACTION_SEARCH" : "@:APP.ACTION_SEARCH",
|
||||
|
||||
"FIELD_PLACEHOLDER_FILTER" : "@:APP.FIELD_PLACEHOLDER_FILTER",
|
||||
|
||||
"FILENAME_HISTORY_CSV" : "history.csv",
|
||||
|
||||
"FORMAT_DATE" : "@:APP.FORMAT_DATE_TIME_PRECISE",
|
||||
|
||||
"HELP_CONNECTION_HISTORY" : "History records for past connections are listed here and can be sorted by clicking the column headers. To search for specific records, enter a filter string and click \"Search\". Only records which match the provided filter string will be listed.",
|
||||
|
Reference in New Issue
Block a user