summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2016-07-19 13:50:32 +0200
committerGitHub <noreply@github.com>2016-07-19 13:50:32 +0200
commit47c80ae1cfaf90c90755d5b5a7d7ada0700b3402 (patch)
tree649ae00570746e3772403b957641f4a8539bf9e6
parent13a25535d2c5c6b181ec31a41f76f825414a26f4 (diff)
parentdf2dffaf7c5dd7c912e981a7c0bc29f853123551 (diff)
downloadnextcloud-server-47c80ae1cfaf90c90755d5b5a7d7ada0700b3402.tar.gz
nextcloud-server-47c80ae1cfaf90c90755d5b5a7d7ada0700b3402.zip
Merge pull request #438 from nextcloud/sessions-list-format
format current and sync client sessions in Personal
-rw-r--r--settings/Controller/AuthSettingsController.php1
-rw-r--r--settings/js/authtoken_view.js130
2 files changed, 97 insertions, 34 deletions
diff --git a/settings/Controller/AuthSettingsController.php b/settings/Controller/AuthSettingsController.php
index e7fc2d916bc..47ab1fc03fd 100644
--- a/settings/Controller/AuthSettingsController.php
+++ b/settings/Controller/AuthSettingsController.php
@@ -98,6 +98,7 @@ class AuthSettingsController extends Controller {
$data = $token->jsonSerialize();
if ($sessionToken->getId() === $token->getId()) {
$data['canDelete'] = false;
+ $data['current'] = true;
} else {
$data['canDelete'] = true;
}
diff --git a/settings/js/authtoken_view.js b/settings/js/authtoken_view.js
index 472b841c230..2ebedb4131c 100644
--- a/settings/js/authtoken_view.js
+++ b/settings/js/authtoken_view.js
@@ -20,14 +20,14 @@
*
*/
-(function(OC, _, $, Handlebars, moment) {
+(function (OC, _, $, Handlebars, moment) {
'use strict';
OC.Settings = OC.Settings || {};
var TEMPLATE_TOKEN =
'<tr data-id="{{id}}">'
- + '<td class="has-tooltip" title="{{name}}"><span class="token-name">{{name}}</span></td>'
+ + '<td class="has-tooltip" title="{{title}}"><span class="token-name">{{name}}</span></td>'
+ '<td><span class="last-activity has-tooltip" title="{{lastActivityTime}}">{{lastActivity}}</span></td>'
+ '{{#if canDelete}}'
+ '<td><a class="icon-delete has-tooltip" title="' + t('core', 'Disconnect') + '"></a></td>'
@@ -50,7 +50,7 @@
_template: undefined,
- template: function(data) {
+ template: function (data) {
if (_.isUndefined(this._template)) {
this._template = Handlebars.compile(TEMPLATE_TOKEN);
}
@@ -58,18 +58,18 @@
return this._template(data);
},
- initialize: function(options) {
+ initialize: function (options) {
this.type = options.type;
this.collection = options.collection;
this.on(this.collection, 'change', this.render);
},
- render: function() {
+ render: function () {
var _this = this;
var list = this.$('.token-list');
- var tokens = this.collection.filter(function(token) {
+ var tokens = this.collection.filter(function (token) {
return parseInt(token.get('type'), 10) === _this.type;
});
list.html('');
@@ -77,24 +77,86 @@
// Show header only if there are tokens to show
this._toggleHeader(tokens.length > 0);
- tokens.forEach(function(token) {
- var viewData = token.toJSON();
- var ts = viewData.lastActivity * 1000;
- viewData.lastActivity = OC.Util.relativeModifiedDate(ts);
- viewData.lastActivityTime = OC.Util.formatDate(ts, 'LLL');
+ tokens.forEach(function (token) {
+ var viewData = this._formatViewData(token.toJSON());
var html = _this.template(viewData);
var $html = $(html);
$html.find('.has-tooltip').tooltip({container: 'body'});
list.append($html);
- });
+ }.bind(this));
},
- toggleLoading: function(state) {
+ toggleLoading: function (state) {
this.$('.token-list').toggleClass('icon-loading', state);
},
- _toggleHeader: function(show) {
+ _toggleHeader: function (show) {
this.$('.hidden-when-empty').toggleClass('hidden', !show);
+ },
+
+ _formatViewData: function (viewData) {
+ var ts = viewData.lastActivity * 1000;
+ viewData.lastActivity = OC.Util.relativeModifiedDate(ts);
+ viewData.lastActivityTime = OC.Util.formatDate(ts, 'LLL');
+
+ // preserve title for cases where we format it further
+ viewData.title = viewData.name;
+
+ // pretty format sync client user agent
+ var matches = viewData.name.match(/Mozilla\/5\.0 \((\w+)\) (?:mirall|csyncoC)\/(\d+\.\d+\.\d+)/);
+
+ var userAgentMap = {
+ ie: /(?:MSIE|Trident) (\d+)/,
+ // Microsoft Edge User Agent from https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
+ edge: /^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Chrome\/[0-9.]+ (?:Mobile Safari|Safari)\/[0-9.]+ Edge\/[0-9.]+$/,
+ // Firefox User Agent from https://developer.mozilla.org/en-US/docs/Web/HTTP/Gecko_user_agent_string_reference
+ firefox: /^Mozilla\/5\.0 \([^)]*(Windows|OS X|Linux)[^)]+\) Gecko\/[0-9.]+ Firefox\/(\d+)(?:\.\d)?$/,
+ // Chrome User Agent from https://developer.chrome.com/multidevice/user-agent
+ chrome: /^Mozilla\/5\.0 \([^)]*(Windows|OS X|Linux)[^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Chrome\/(\d+)[0-9.]+ (?:Mobile Safari|Safari)\/[0-9.]+$/,
+ // Safari User Agent from http://www.useragentstring.com/pages/Safari/
+ safari: /^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Version\/([0-9]+)[0-9.]+ Safari\/[0-9.A-Z]+$/,
+ // Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent
+ androidChrome: /Android.*(?:; (.*) Build\/).*Chrome\/(\d+)[0-9.]+/,
+ iphone: / *CPU +iPhone +OS +(\d+)_\d+ +like +Mac +OS +X */,
+ iosClient: /^Mozilla\/5\.0 \(iOS\) ownCloud\-iOS.*$/,
+ androidClient:/^Mozilla\/5\.0 \(Android\) ownCloud\-android.*$/,
+ // DAVdroid/1.2 (2016/07/03; dav4android; okhttp3) Android/6.0.1
+ davDroid: /DAVdroid\/([0-9.]+)/
+ };
+ var nameMap = {
+ ie: t('setting', 'Internet Explorer'),
+ edge: t('setting', 'Edge'),
+ firefox: t('setting', 'Firefox'),
+ chrome: t('setting', 'Google Chrome'),
+ safari: t('setting', 'Safari'),
+ androidChrome: t('setting', 'Google Chrome for Android'),
+ iphone: t('setting', 'iPhone'),
+ iosClient: t('setting', 'iOS Client'),
+ androidClient: t('setting', 'Android Client'),
+ davDroid: 'DAVdroid'
+ };
+
+ if (matches) {
+ viewData.name = t('settings', 'Sync client - {os}', {
+ os: matches[1],
+ version: matches[2]
+ });
+ }
+ for (var client in userAgentMap) {
+ if (matches = viewData.title.match(userAgentMap[client])) {
+ if (matches[2] && matches[1]) { // version number and os
+ viewData.name = nameMap[client] + ' ' + matches[2] + ' - ' + matches[1];
+ }else if (matches[1]) { // only version number
+ viewData.name = nameMap[client] + ' ' + matches[1];
+ } else {
+ viewData.name = nameMap[client];
+ }
+ }
+ }
+ if (viewData.current) {
+ viewData.name = t('settings', 'This session');
+ }
+ return viewData;
}
});
@@ -119,12 +181,12 @@
_addingToken: false,
- initialize: function(options) {
+ initialize: function (options) {
this.collection = options.collection;
var tokenTypes = [0, 1];
var _this = this;
- _.each(tokenTypes, function(type) {
+ _.each(tokenTypes, function (type) {
var el = type === 0 ? '#sessions' : '#apppasswords';
_this._views.push(new SubView({
el: el,
@@ -150,31 +212,31 @@
this._hideAppPasswordBtn.click(_.bind(this._hideToken, this));
},
- render: function() {
- _.each(this._views, function(view) {
+ render: function () {
+ _.each(this._views, function (view) {
view.render();
view.toggleLoading(false);
});
},
- reload: function() {
+ reload: function () {
var _this = this;
- _.each(this._views, function(view) {
+ _.each(this._views, function (view) {
view.toggleLoading(true);
});
var loadingTokens = this.collection.fetch();
- $.when(loadingTokens).done(function() {
+ $.when(loadingTokens).done(function () {
_this.render();
});
- $.when(loadingTokens).fail(function() {
+ $.when(loadingTokens).fail(function () {
OC.Notification.showTemporary(t('core', 'Error while loading browser sessions and device tokens'));
});
},
- _addAppPassword: function() {
+ _addAppPassword: function () {
var _this = this;
this._toggleAddingToken(true);
@@ -186,7 +248,7 @@
}
});
- $.when(creatingToken).done(function(resp) {
+ $.when(creatingToken).done(function (resp) {
_this.collection.add(resp.deviceToken);
_this.render();
_this._newAppLoginName.val(resp.loginName);
@@ -195,32 +257,32 @@
_this._newAppPassword.select();
_this._tokenName.val('');
});
- $.when(creatingToken).fail(function() {
+ $.when(creatingToken).fail(function () {
OC.Notification.showTemporary(t('core', 'Error while creating device token'));
});
- $.when(creatingToken).always(function() {
+ $.when(creatingToken).always(function () {
_this._toggleAddingToken(false);
});
},
- _onNewTokenLoginNameFocus: function() {
+ _onNewTokenLoginNameFocus: function () {
this._newAppLoginName.select();
},
- _onNewTokenFocus: function() {
+ _onNewTokenFocus: function () {
this._newAppPassword.select();
},
- _hideToken: function() {
+ _hideToken: function () {
this._toggleFormResult(true);
},
- _toggleAddingToken: function(state) {
+ _toggleAddingToken: function (state) {
this._addingToken = state;
this._addAppPasswordBtn.toggleClass('icon-loading-small', state);
},
- _onDeleteToken: function(event) {
+ _onDeleteToken: function (event) {
var $target = $(event.target);
var $row = $target.closest('tr');
var id = $row.data('id');
@@ -236,15 +298,15 @@
$row.find('.icon-delete').tooltip('hide');
var _this = this;
- $.when(destroyingToken).fail(function() {
+ $.when(destroyingToken).fail(function () {
OC.Notification.showTemporary(t('core', 'Error while deleting the token'));
});
- $.when(destroyingToken).always(function() {
+ $.when(destroyingToken).always(function () {
_this.render();
});
},
- _toggleFormResult: function(showForm) {
+ _toggleFormResult: function (showForm) {
this._form.toggleClass('hidden', !showForm);
this._result.toggleClass('hidden', showForm);
}