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 @@