diff --git a/src/index.html b/src/index.html
index 3ff3754..e92ff3f 100644
--- a/src/index.html
+++ b/src/index.html
@@ -385,12 +385,14 @@
+
+
diff --git a/src/langs/zh_Hans.txt b/src/langs/zh_Hans.txt
index fd24c1f..e13705b 100644
--- a/src/langs/zh_Hans.txt
+++ b/src/langs/zh_Hans.txt
@@ -10,6 +10,10 @@ Cancel=取消
Close=关闭
True=是
False=否
+DEBUG=调试 (Debug)
+INFO=普通 (Info)
+WARN=警告 (Warn)
+ERROR=错误 (Error)
Connecting=连接中
Connected=已连接
Disconnected=未连接
@@ -256,6 +260,12 @@ Always=始终
Never=从不
BitTorrent=BitTorrent
Changes to the settings take effect after refreshing page.=设置将在页面刷新后生效.
+Logging Time=记录时间
+Log Level=日志级别
+Auto Refresh=自动刷新
+Refresh Now=立即刷新
+Clear Logs=清空日志
+Are you sure you want to clear debug logs?=您是否要清除调试日志?
Show Detail=显示详情
Log Detail=日志详情
Type is illegal!=类型错误!
diff --git a/src/langs/zh_Hant.txt b/src/langs/zh_Hant.txt
index 1411168..75f030a 100644
--- a/src/langs/zh_Hant.txt
+++ b/src/langs/zh_Hant.txt
@@ -10,6 +10,10 @@ Cancel=取消
Close=關閉
True=是
False=否
+DEBUG=偵錯 (Debug)
+INFO=普通 (Info)
+WARN=警告 (Warn)
+ERROR=錯誤 (Error)
Connecting=連線中
Connected=已連線
Disconnected=未連線
@@ -256,6 +260,12 @@ Always=始終
Never=從不
BitTorrent=BitTorrent
Changes to the settings take effect after refreshing page.=設定將在頁面重新整理後生效.
+Logging Time=記錄時間
+Log Level=記錄層級
+Auto Refresh=自動刷新
+Refresh Now=立即刷新
+Clear Logs=清除記錄
+Are you sure you want to clear debug logs?=您是否要清除偵錯記錄?
Show Detail=顯示詳情
Log Detail=記錄詳情
Type is illegal!=類型錯誤!
diff --git a/src/scripts/config/defaultLanguage.js b/src/scripts/config/defaultLanguage.js
index ec1bdd1..5cfb655 100644
--- a/src/scripts/config/defaultLanguage.js
+++ b/src/scripts/config/defaultLanguage.js
@@ -14,6 +14,10 @@
'Close': 'Close',
'True': 'True',
'False': 'False',
+ 'DEBUG': 'Debug',
+ 'INFO': 'Info',
+ 'WARN': 'Warn',
+ 'ERROR': 'Error',
'Connecting': 'Connecting',
'Connected': 'Connected',
'Disconnected': 'Disconnected',
@@ -261,6 +265,12 @@
'BitTorrent': 'BitTorrent',
'Changes to the settings take effect after refreshing page.': 'Changes to the settings take effect after refreshing page.',
'Latest {{count}} Logs': 'Latest {{count}} Logs',
+ 'Logging Time': 'Logging Time',
+ 'Log Level': 'Log Level',
+ 'Auto Refresh': 'Auto Refresh',
+ 'Refresh Now': 'Refresh Now',
+ 'Clear Logs': 'Clear Logs',
+ 'Are you sure you want to clear debug logs?': 'Are you sure you want to clear debug logs?',
'Show Detail': 'Show Detail',
'Log Detail': 'Log Detail',
'Type is illegal!': 'Type is illegal!',
diff --git a/src/scripts/controllers/debug.js b/src/scripts/controllers/debug.js
index 359f0f1..12ca28f 100644
--- a/src/scripts/controllers/debug.js
+++ b/src/scripts/controllers/debug.js
@@ -1,27 +1,158 @@
(function () {
'use strict';
- angular.module('ariaNg').controller('AriaNgDebugController', ['$rootScope', '$scope', '$location', '$timeout', 'ariaNgConstants', 'ariaNgCommonService', 'ariaNgLogService', 'ariaNgSettingService', function ($rootScope, $scope, $location, $timeout, ariaNgConstants, ariaNgCommonService, ariaNgLogService, ariaNgSettingService) {
- $scope.logMaxCount = ariaNgConstants.cachedDebugLogsLimit;
- $scope.currentLog = null;
+ angular.module('ariaNg').controller('AriaNgDebugController', ['$rootScope', '$scope', '$location', '$interval', '$timeout', 'ariaNgConstants', 'ariaNgCommonService', 'ariaNgLocalizationService', 'ariaNgLogService', 'ariaNgSettingService', function ($rootScope, $scope, $location, $interval, $timeout, ariaNgConstants, ariaNgCommonService, ariaNgLocalizationService, ariaNgLogService, ariaNgSettingService) {
+ var tabStatusItems = [
+ {
+ name: 'logs',
+ show: true
+ }
+ ];
+ var debugLogRefreshPromise = null;
+
+ var getVisibleTabOrders = function () {
+ var items = [];
+
+ for (var i = 0; i < tabStatusItems.length; i++) {
+ if (tabStatusItems[i].show) {
+ items.push(tabStatusItems[i].name);
+ }
+ }
+
+ return items;
+ };
+
+ $scope.context = {
+ currentTab: 'logs',
+ logMaxCount: ariaNgConstants.cachedDebugLogsLimit,
+ logAutoRefreshAvailableInterval: ariaNgCommonService.getTimeOptions([100, 200, 500, 1000, 2000], true),
+ logAutoRefreshInterval: 0,
+ logListDisplayOrder: 'time:desc',
+ logLevelFilter: 'DEBUG',
+ logs: [],
+ currentLog: null
+ };
$scope.enableDebugMode = function () {
return ariaNgSettingService.isEnableDebugMode();
};
+ $scope.changeTab = function (tabName) {
+ $scope.context.currentTab = tabName;
+ };
+
+ $scope.changeLogListDisplayOrder = function (type) {
+ var oldType = ariaNgCommonService.parseOrderType($scope.context.logListDisplayOrder);
+ var newType = ariaNgCommonService.parseOrderType(type);
+
+ if (newType.type === oldType.type) {
+ newType.reverse = !oldType.reverse;
+ }
+
+ $scope.context.logListDisplayOrder = newType.getValue();
+ };
+
+ $scope.isLogListSetDisplayOrder = function (type) {
+ var orderType = ariaNgCommonService.parseOrderType($scope.context.logListDisplayOrder);
+ var targetType = ariaNgCommonService.parseOrderType(type);
+
+ return orderType.equals(targetType);
+ };
+
+ $scope.getLogListOrderType = function () {
+ return $scope.context.logListDisplayOrder;
+ };
+
+ $scope.filterLog = function (log) {
+ if (!log || !angular.isString(log.level)) {
+ return false;
+ }
+
+ if (!$scope.context.logLevelFilter) {
+ return true;
+ }
+
+ return ariaNgLogService.compareLogLevel(log.level, $scope.context.logLevelFilter) >= 0;
+ };
+
+ $scope.setLogLevelFilter = function (filter) {
+ $scope.context.logLevelFilter = filter;
+ };
+
+ $scope.isSetLogLevelFilter = function (filter) {
+ return $scope.context.logLevelFilter === filter;
+ };
+
+ $scope.getLogLevelFilter = function () {
+ return $scope.context.logLevelFilter;
+ };
+
+ $scope.setAutoRefreshInterval = function (interval) {
+ $scope.context.logAutoRefreshInterval = interval;
+
+ if (debugLogRefreshPromise) {
+ $interval.cancel(debugLogRefreshPromise);
+ }
+
+ if (interval > 0) {
+ $scope.reloadLogs();
+
+ debugLogRefreshPromise = $interval(function () {
+ $scope.reloadLogs();
+ }, $scope.context.logAutoRefreshInterval);
+ }
+ };
+
$scope.reloadLogs = function () {
- $scope.logs = ariaNgLogService.getDebugLogs().slice();
+ $scope.context.logs = ariaNgLogService.getDebugLogs().slice();
+ };
+
+ $scope.clearDebugLogs = function () {
+ ariaNgCommonService.confirm('Confirm Clear', 'Are you sure you want to clear debug logs?', 'warning', function () {
+ ariaNgLogService.clearDebugLogs();
+ $scope.reloadLogs();
+ }, false);
};
$scope.showLogDetail = function (log) {
- $scope.currentLog = log;
+ $scope.context.currentLog = log;
angular.element('#log-detail-modal').modal();
};
$('#log-detail-modal').on('hide.bs.modal', function (e) {
- $scope.currentLog = null;
+ $scope.context.currentLog = null;
});
+ $scope.$on('$destroy', function () {
+ if (debugLogRefreshPromise) {
+ $interval.cancel(debugLogRefreshPromise);
+ }
+ });
+
+ $rootScope.swipeActions.extendLeftSwipe = function () {
+ var tabItems = getVisibleTabOrders();
+ var tabIndex = tabItems.indexOf($scope.context.currentTab);
+
+ if (tabIndex < tabItems.length - 1) {
+ $scope.changeTab(tabItems[tabIndex + 1]);
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ $rootScope.swipeActions.extendRightSwipe = function () {
+ var tabItems = getVisibleTabOrders();
+ var tabIndex = tabItems.indexOf($scope.context.currentTab);
+
+ if (tabIndex > 0) {
+ $scope.changeTab(tabItems[tabIndex - 1]);
+ return true;
+ } else {
+ return false;
+ }
+ };
+
$rootScope.loadPromise = $timeout(function () {
if (!ariaNgSettingService.isEnableDebugMode()) {
ariaNgCommonService.showError('Access Denied!', function () {
diff --git a/src/scripts/filters/logOrderBy.js b/src/scripts/filters/logOrderBy.js
new file mode 100644
index 0000000..d52c01d
--- /dev/null
+++ b/src/scripts/filters/logOrderBy.js
@@ -0,0 +1,23 @@
+(function () {
+ 'use strict';
+
+ angular.module('ariaNg').filter('logOrderBy', ['$filter', 'ariaNgCommonService', function ($filter, ariaNgCommonService) {
+ return function (array, type) {
+ if (!angular.isArray(array) || !type) {
+ return array;
+ }
+
+ var orderType = ariaNgCommonService.parseOrderType(type);
+
+ if (orderType === null) {
+ return array;
+ }
+
+ if (orderType.type === 'time') {
+ return $filter('orderBy')(array, ['time'], orderType.reverse);
+ } else {
+ return array;
+ }
+ };
+ }]);
+}());
diff --git a/src/scripts/filters/timeDisplayName.js b/src/scripts/filters/timeDisplayName.js
new file mode 100644
index 0000000..05f2bf8
--- /dev/null
+++ b/src/scripts/filters/timeDisplayName.js
@@ -0,0 +1,17 @@
+(function () {
+ 'use strict';
+
+ angular.module('ariaNg').filter('timeDisplayName', ['ariaNgCommonService', 'ariaNgLocalizationService', function (ariaNgCommonService, ariaNgLocalizationService) {
+ return function (time, defaultName) {
+ if (!time) {
+ return ariaNgLocalizationService.getLocalizedText(defaultName);
+ }
+
+ var option = ariaNgCommonService.getTimeOption(time);
+
+ return ariaNgLocalizationService.getLocalizedText(option.name, {
+ value: option.value
+ });
+ };
+ }]);
+}());
diff --git a/src/scripts/services/ariaNgCommonService.js b/src/scripts/services/ariaNgCommonService.js
index 317d18d..9c51dad 100644
--- a/src/scripts/services/ariaNgCommonService.js
+++ b/src/scripts/services/ariaNgCommonService.js
@@ -2,6 +2,31 @@
'use strict';
angular.module('ariaNg').factory('ariaNgCommonService', ['$location', '$timeout', 'base64', 'moment', 'SweetAlert', 'ariaNgConstants', 'ariaNgLocalizationService', function ($location, $timeout, base64, moment, SweetAlert, ariaNgConstants, ariaNgLocalizationService) {
+ var getTimeOption = function (time) {
+ var name = '';
+ var value = time;
+
+ if (time < 1000) {
+ value = time;
+ name = (value === 1 ? 'format.time.millisecond' : 'format.time.milliseconds');
+ } else if (time < 1000 * 60) {
+ value = time / 1000;
+ name = (value === 1 ? 'format.time.second' : 'format.time.seconds');
+ } else if (time < 1000 * 60 * 24) {
+ value = time / 1000 / 60;
+ name = (value === 1 ? 'format.time.minute' : 'format.time.minutes');
+ } else {
+ value = time / 1000 / 60 / 24;
+ name = (value === 1 ? 'format.time.hour' : 'format.time.hours');
+ }
+
+ return {
+ name: name,
+ value: value,
+ optionValue: time
+ };
+ };
+
var showDialog = function (title, text, type, callback, options) {
$timeout(function () {
SweetAlert.swal({
@@ -273,6 +298,9 @@
formatDateTime: function (datetime, format) {
return moment(datetime).format(format);
},
+ getTimeOption: function (time) {
+ return getTimeOption(time);
+ },
getTimeOptions: function (timeList, withDisabled) {
var options = [];
@@ -290,28 +318,9 @@
for (var i = 0; i < timeList.length; i++) {
var time = timeList[i];
- var name = '';
- var value = time;
+ var option = getTimeOption(time);
- if (time < 1000) {
- value = time;
- name = (value === 1 ? 'format.time.millisecond' : 'format.time.milliseconds');
- } else if (time < 1000 * 60) {
- value = time / 1000;
- name = (value === 1 ? 'format.time.second' : 'format.time.seconds');
- } else if (time < 1000 * 60 * 24) {
- value = time / 1000 / 60;
- name = (value === 1 ? 'format.time.minute' : 'format.time.minutes');
- } else {
- value = time / 1000 / 60 / 24;
- name = (value === 1 ? 'format.time.hour' : 'format.time.hours');
- }
-
- options.push({
- name: name,
- value: value,
- optionValue: time
- });
+ options.push(option);
}
return options;
diff --git a/src/scripts/services/ariaNgLogService.js b/src/scripts/services/ariaNgLogService.js
index 4de501e..6d8d62c 100644
--- a/src/scripts/services/ariaNgLogService.js
+++ b/src/scripts/services/ariaNgLogService.js
@@ -2,11 +2,19 @@
'use strict';
angular.module('ariaNg').factory('ariaNgLogService', ['$log', 'ariaNgConstants', function ($log, ariaNgConstants) {
+ var logLevels = {
+ DEBUG: 1,
+ INFO: 2,
+ WARN: 3,
+ ERROR: 4
+ };
+ var logIndex = 0;
var enableDebugLog = false;
var cachedDebugLogs = [];
var createNewCacheLogItem = function (msg, level, obj) {
return {
+ id: ++logIndex,
time: new Date(),
level: level,
content: msg,
@@ -30,6 +38,26 @@
setEnableDebugLog: function (value) {
enableDebugLog = value;
},
+ compareLogLevel: function (level1, level2) {
+ var level1Val = logLevels[level1];
+ var level2Val = logLevels[level2];
+
+ if (!level1Val) {
+ level1Val = 0;
+ }
+
+ if (!level2Val) {
+ level2Val = 0;
+ }
+
+ if (level1Val > level2Val) {
+ return 1;
+ } else if (level1Val < level2Val) {
+ return -1;
+ } else {
+ return 0;
+ }
+ },
debug: function (msg, obj) {
if (enableDebugLog) {
if (obj) {
@@ -74,6 +102,10 @@
} else {
return [];
}
+ },
+ clearDebugLogs: function () {
+ logIndex = 0;
+ cachedDebugLogs.length = 0;
}
};
}]);
diff --git a/src/styles/controls/settings-table.css b/src/styles/controls/settings-table.css
index cc30dc8..cff38f1 100644
--- a/src/styles/controls/settings-table.css
+++ b/src/styles/controls/settings-table.css
@@ -19,6 +19,12 @@
.settings-table .settings-table-title a {
color: #000;
+ cursor: pointer;
+}
+
+.settings-table .settings-table-title .settings-table-title-toolbar {
+ display: inline-block;
+ margin-left: 10px;
}
.settings-table > div.row {
diff --git a/src/views/debug.html b/src/views/debug.html
index 4ebefcb..2a06349 100644
--- a/src/views/debug.html
+++ b/src/views/debug.html
@@ -1,24 +1,84 @@