From 9df0ad0bf7c2c96bcfb076d23361153f2184b01b Mon Sep 17 00:00:00 2001 From: Taloth Saldono Date: Sat, 1 Feb 2014 23:09:22 +0100 Subject: [PATCH] System.Logs view can now be filtered by severity. --- src/NzbDrone.Api/Logs/LogModule.cs | 25 +++++++++ src/NzbDrone.Api/PagingResource.cs | 2 + src/NzbDrone.Api/REST/RestModule.cs | 10 ++++ .../Datastore/BasicRepository.cs | 18 ++++--- .../History/HistoryRepository.cs | 18 ++----- src/UI/System/Logs/LogsCollection.js | 15 +++++- src/UI/System/Logs/Table/LogsTableLayout.js | 53 ++++++++++++++++++- 7 files changed, 116 insertions(+), 25 deletions(-) diff --git a/src/NzbDrone.Api/Logs/LogModule.cs b/src/NzbDrone.Api/Logs/LogModule.cs index 59ea4975d..8684e3250 100644 --- a/src/NzbDrone.Api/Logs/LogModule.cs +++ b/src/NzbDrone.Api/Logs/LogModule.cs @@ -23,6 +23,31 @@ namespace NzbDrone.Api.Logs pageSpec.SortKey = "id"; } + if (pagingResource.FilterKey == "level") + { + switch (pagingResource.FilterValue) + { + case "Fatal": + pageSpec.FilterExpression = h => h.Level == "Fatal"; + break; + case "Error": + pageSpec.FilterExpression = h => h.Level == "Fatal" || h.Level == "Error"; + break; + case "Warn": + pageSpec.FilterExpression = h => h.Level == "Fatal" || h.Level == "Error" || h.Level == "Warn"; + break; + case "Info": + pageSpec.FilterExpression = h => h.Level == "Fatal" || h.Level == "Error" || h.Level == "Warn" || h.Level == "Info"; + break; + case "Debug": + pageSpec.FilterExpression = h => h.Level == "Fatal" || h.Level == "Error" || h.Level == "Warn" || h.Level == "Info" || h.Level == "Debug"; + break; + case "Trace": + pageSpec.FilterExpression = h => h.Level == "Fatal" || h.Level == "Error" || h.Level == "Warn" || h.Level == "Info" || h.Level == "Debug" || h.Level == "Trace"; + break; + } + } + return ApplyToPage(_logService.Paged, pageSpec); } } diff --git a/src/NzbDrone.Api/PagingResource.cs b/src/NzbDrone.Api/PagingResource.cs index ab53c24cd..96eeb7c48 100644 --- a/src/NzbDrone.Api/PagingResource.cs +++ b/src/NzbDrone.Api/PagingResource.cs @@ -9,6 +9,8 @@ namespace NzbDrone.Api public int PageSize { get; set; } public string SortKey { get; set; } public SortDirection SortDirection { get; set; } + public string FilterKey { get; set; } + public string FilterValue { get; set; } public int TotalRecords { get; set; } public List Records { get; set; } } diff --git a/src/NzbDrone.Api/REST/RestModule.cs b/src/NzbDrone.Api/REST/RestModule.cs index 1efcf0b3a..49cd14fa9 100644 --- a/src/NzbDrone.Api/REST/RestModule.cs +++ b/src/NzbDrone.Api/REST/RestModule.cs @@ -241,6 +241,16 @@ namespace NzbDrone.Api.REST } } + if (Request.Query.FilterKey != null) + { + pagingResource.FilterKey = Request.Query.FilterKey.ToString(); + + if (Request.Query.FilterValue != null) + { + pagingResource.FilterValue = Request.Query.FilterValue.ToString(); + } + } + return pagingResource; } } diff --git a/src/NzbDrone.Core/Datastore/BasicRepository.cs b/src/NzbDrone.Core/Datastore/BasicRepository.cs index f82a68354..f4125c0f2 100644 --- a/src/NzbDrone.Core/Datastore/BasicRepository.cs +++ b/src/NzbDrone.Core/Datastore/BasicRepository.cs @@ -210,18 +210,20 @@ namespace NzbDrone.Core.Datastore public virtual PagingSpec GetPaged(PagingSpec pagingSpec) { - var pagingQuery = Query.OrderBy(pagingSpec.OrderByClause(), pagingSpec.ToSortDirection()) - .Skip(pagingSpec.PagingOffset()) - .Take(pagingSpec.PageSize); - - pagingSpec.Records = pagingQuery.ToList(); - - //TODO: Use the same query for count and records - pagingSpec.TotalRecords = Count(); + pagingSpec.Records = GetPagedQuery(Query, pagingSpec).ToList(); + pagingSpec.TotalRecords = GetPagedQuery(Query, pagingSpec).GetRowCount(); return pagingSpec; } + protected virtual SortBuilder GetPagedQuery(QueryBuilder query, PagingSpec pagingSpec) + { + return query.Where(pagingSpec.FilterExpression) + .OrderBy(pagingSpec.OrderByClause(), pagingSpec.ToSortDirection()) + .Skip(pagingSpec.PagingOffset()) + .Take(pagingSpec.PageSize); + } + public void DeleteAll() { DataMapper.Delete(c => c.Id > 0); diff --git a/src/NzbDrone.Core/History/HistoryRepository.cs b/src/NzbDrone.Core/History/HistoryRepository.cs index 59d54c745..b1fdcad7a 100644 --- a/src/NzbDrone.Core/History/HistoryRepository.cs +++ b/src/NzbDrone.Core/History/HistoryRepository.cs @@ -67,22 +67,12 @@ namespace NzbDrone.Core.History .FirstOrDefault(); } - public override PagingSpec GetPaged(PagingSpec pagingSpec) + protected override SortBuilder GetPagedQuery(QueryBuilder query, PagingSpec pagingSpec) { - pagingSpec.Records = GetPagedQuery(pagingSpec).ToList(); - pagingSpec.TotalRecords = GetPagedQuery(pagingSpec).GetRowCount(); + var baseQuery = query.Join(JoinType.Inner, h => h.Series, (h, s) => h.SeriesId == s.Id) + .Join(JoinType.Inner, h => h.Episode, (h, e) => h.EpisodeId == e.Id); - return pagingSpec; - } - - private SortBuilder GetPagedQuery(PagingSpec pagingSpec) - { - return Query.Join(JoinType.Inner, h => h.Series, (h, s) => h.SeriesId == s.Id) - .Join(JoinType.Inner, h => h.Episode, (h, e) => h.EpisodeId == e.Id) - .Where(pagingSpec.FilterExpression) - .OrderBy(pagingSpec.OrderByClause(), pagingSpec.ToSortDirection()) - .Skip(pagingSpec.PagingOffset()) - .Take(pagingSpec.PageSize); + return base.GetPagedQuery(baseQuery, pagingSpec); } } } \ No newline at end of file diff --git a/src/UI/System/Logs/LogsCollection.js b/src/UI/System/Logs/LogsCollection.js index 350ed1522..045675796 100644 --- a/src/UI/System/Logs/LogsCollection.js +++ b/src/UI/System/Logs/LogsCollection.js @@ -4,9 +4,10 @@ define( [ 'backbone.pageable', 'System/Logs/LogsModel', + 'Mixins/AsFilteredCollection', 'Mixins/AsPersistedStateCollection' ], - function (PagableCollection, LogsModel, AsPersistedStateCollection) { + function (PagableCollection, LogsModel, AsFilteredCollection, AsPersistedStateCollection) { var collection = PagableCollection.extend({ url : window.NzbDrone.ApiRoot + '/log', model: LogsModel, @@ -30,6 +31,14 @@ define( } }, + // Filter Modes + filterModes: { + 'all' : [null, null], + 'info' : ['level', 'Info'], + 'warn' : ['level', 'Warn'], + 'error' : ['level', 'Error'] + }, + parseState: function (resp, queryParams, state) { return {totalRecords: resp.totalRecords}; }, @@ -43,5 +52,7 @@ define( } }); - return AsPersistedStateCollection.call(collection); + collection = AsFilteredCollection.apply(collection); + + return AsPersistedStateCollection.apply(collection); }); diff --git a/src/UI/System/Logs/Table/LogsTableLayout.js b/src/UI/System/Logs/Table/LogsTableLayout.js index 219ebfc1b..9de384d68 100644 --- a/src/UI/System/Logs/Table/LogsTableLayout.js +++ b/src/UI/System/Logs/Table/LogsTableLayout.js @@ -66,7 +66,6 @@ define( onRender: function () { this.grid.show(new LoadingView()); - this.collection.fetch(); }, onShow: function () { @@ -88,6 +87,44 @@ define( }, _showToolbar: function () { + var filterButtons = { + type : 'radio', + storeState : true, + menuKey : 'logs.filterMode', + defaultAction: 'all', + items : + [ + { + key : 'all', + title : '', + tooltip : 'All', + icon : 'icon-circle-blank', + callback : this._setFilter + }, + { + key : 'info', + title : '', + tooltip : 'Info', + icon : 'icon-info', + callback : this._setFilter + }, + { + key : 'warn', + title : '', + tooltip : 'Warn', + icon : 'icon-warn', + callback : this._setFilter + }, + { + key : 'error', + title : '', + tooltip : 'Error', + icon : 'icon-error', + callback : this._setFilter + } + ] + }; + var rightSideButtons = { type : 'default', storeState: false, @@ -111,6 +148,7 @@ define( this.toolbar.show(new ToolbarLayout({ right : [ + filterButtons, rightSideButtons ], context: this @@ -125,6 +163,19 @@ define( buttonContext.ui.icon.spinForPromise(promise); } }, + + _setFilter: function(buttonContext) { + var mode = buttonContext.model.get('key'); + + this.collection.setFilterMode(mode, { reset: false }); + + this.collection.state.currentPage = 1; + var promise = this.collection.fetch({ reset: true }); + + if (buttonContext) { + buttonContext.ui.icon.spinForPromise(promise); + } + }, _commandComplete: function (options) { if (options.command.get('name') === 'clearlog') {