Episode Activity added

New: Activity tab added to Episode Details
pull/4/head
Mark McDowall 11 years ago
parent d0d65db4f2
commit c0b7612053

@ -169,35 +169,35 @@ module.exports = function (grunt) {
tasks: ['handlebars']
},
copyIndex : {
files: '<%= copy.index.src %>',
files: '<%= copy.index.cwd %><%= copy.index.src %>',
tasks: ['copy:index']
},
copyScripts: {
files: '<%= copy.scripts.src %>',
files: '<%= copy.scripts.cwd %><%= copy.scripts.src %>',
tasks: ['copy:scripts']
},
copyStyles : {
files: '<%= copy.styles.src %>',
files: '<%= copy.styles.cwd %><%= copy.styles.src %>',
tasks: ['copy:styles']
},
copyImages : {
files: '<%= copy.images.src %>',
files: '<%= copy.images.cwd %><%= copy.images.src %>',
tasks: ['copy:images']
},
copyJpg : {
files: '<%= copy.jpg.src %>',
files: '<%= copy.jpg.cwd %><%= copy.jpg.src %>',
tasks: ['copy:jpg']
},
copyIcon : {
files: '<%= copy.icon.src %>',
files: '<%= copy.icon.cwd %><%= copy.icon.src %>',
tasks: ['copy:icon']
},
copyFontAwesome : {
files: '<%= copy.fontAwesome.src %>',
files: '<%= copy.fontAwesome.cwd %><%= copy.fontAwesome.src %>',
tasks: ['copy:fontAwesome']
},
copyFonts : {
files: '<%= copy.fonts.src %>',
files: '<%= copy.fonts.cwd %><%= copy.fonts.src %>',
tasks: ['copy:fonts']
}
}

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using NzbDrone.Api.History;
using NzbDrone.Api.Mapping;
using NzbDrone.Api.REST;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.Download;
using NzbDrone.Core.History;
using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Episodes
{
public class EpisodeActivityModule : NzbDroneRestModule<HistoryResource>
{
private readonly IHistoryService _historyService;
public EpisodeActivityModule(IHistoryService historyService)
: base("episodes/activity")
{
_historyService = historyService;
GetResourceAll = GetActivity;
}
private List<HistoryResource> GetActivity()
{
var episodeId = (int?)Request.Query.EpisodeId;
if (episodeId == null)
{
throw new BadRequestException("episodeId is missing");
}
return ToListResource(() => _historyService.ByEpisode(episodeId.Value));
}
}
}

@ -91,6 +91,7 @@
<Compile Include="EpisodeFiles\EpisodeFileResource.cs" />
<Compile Include="Directories\DirectoryLookupService.cs" />
<Compile Include="Directories\DirectoryModule.cs" />
<Compile Include="Episodes\EpisodeActivityModule.cs" />
<Compile Include="Episodes\EpisodeModule.cs" />
<Compile Include="Episodes\EpisodeResource.cs" />
<Compile Include="Extensions\Pipelines\CacheHeaderPipeline.cs" />

@ -12,6 +12,7 @@ namespace NzbDrone.Core.History
{
void Trim();
List<QualityModel> GetEpisodeHistory(int episodeId);
List<History> ByEpisode(int episodeId);
}
public class HistoryRepository : BasicRepository<History>, IHistoryRepository
@ -37,6 +38,11 @@ namespace NzbDrone.Core.History
return history.Select(h => h.Quality).ToList();
}
public List<History> ByEpisode(int episodeId)
{
return Query.Where(h => h.EpisodeId == episodeId).ToList();
}
public override PagingSpec<History> GetPaged(PagingSpec<History> pagingSpec)
{
var pagingQuery = Query.Join<History, Series>(JoinType.Inner, h => h.Series, (h, s) => h.SeriesId == s.Id)

@ -17,6 +17,7 @@ namespace NzbDrone.Core.History
void Trim();
QualityModel GetBestQualityInHistory(int episodeId);
PagingSpec<History> Paged(PagingSpec<History> pagingSpec);
List<History> ByEpisode(int episodeId);
}
public class HistoryService : IHistoryService, IHandle<EpisodeGrabbedEvent>, IHandle<EpisodeImportedEvent>
@ -40,6 +41,11 @@ namespace NzbDrone.Core.History
return _historyRepository.GetPaged(pagingSpec);
}
public List<History> ByEpisode(int episodeId)
{
return _historyRepository.ByEpisode(episodeId);
}
public void Purge()
{
_historyRepository.Purge();

@ -35,7 +35,7 @@ define(
}
this.$el.html('<i class="{0}" title="{1}"/>'.format(icon, toolTip));
this.$el.html('<i class="{0}" title="{1}" data-placement="right"/>'.format(icon, toolTip));
}
return this;

@ -0,0 +1,31 @@
'use strict';
define(
[
'backbone',
'Episode/Activity/EpisodeActivityModel'
], function (Backbone, EpisodeActivityModel) {
return Backbone.Collection.extend({
url : window.NzbDrone.ApiRoot + '/episodes/activity',
model: EpisodeActivityModel,
originalFetch: Backbone.Collection.prototype.fetch,
initialize: function (options) {
this.episodeId = options.episodeId;
},
fetch: function (options) {
if (!this.episodeId) {
throw 'episodeId is required';
}
if (!options) {
options = {};
}
options.data = { episodeId: this.episodeId };
return this.originalFetch.call(this, options);
}
});
});

@ -0,0 +1,72 @@
'use strict';
define(
[
'app',
'marionette',
'backgrid',
'Episode/Activity/EpisodeActivityCollection',
'Cells/EventTypeCell',
'Cells/QualityCell',
'Cells/RelativeDateCell',
'Shared/LoadingView'
], function (App, Marionette, Backgrid, EpisodeActivityCollection, EventTypeCell, QualityCell, RelativeDateCell, LoadingView) {
return Marionette.Layout.extend({
template: 'Episode/Activity/EpisodeActivityLayoutTemplate',
regions: {
activityTable: '.activity-table'
},
columns:
[
{
name : 'eventType',
label : '',
cell : EventTypeCell,
cellValue: 'this'
},
{
name : 'sourceTitle',
label: 'Source Title',
cell : 'string'
},
{
name : 'quality',
label: 'Quality',
cell : QualityCell
},
{
name : 'date',
label: 'Date',
cell : RelativeDateCell
}
],
initialize: function (options) {
this.model = options.model;
this.series = options.series;
this.collection = new EpisodeActivityCollection({ episodeId: this.model.id });
},
onShow: function () {
var self = this;
this.activityTable.show(new LoadingView());
var promise = this.collection.fetch();
promise.done(function () {
self._showTable();
});
},
_showTable: function () {
this.activityTable.show(new Backgrid.Grid({
collection: this.collection,
columns : this.columns,
className : 'table table-hover table-condensed'
}));
}
});
});

@ -0,0 +1 @@
<div class="activity-table"></div>

@ -0,0 +1,9 @@
'use strict';
define(
[
'backbone'
], function (Backbone) {
return Backbone.Model.extend({
});
});

@ -4,8 +4,9 @@ define(
'marionette',
'Episode/Summary/EpisodeSummaryLayout',
'Episode/Search/EpisodeSearchLayout',
'Episode/Activity/EpisodeActivityLayout',
'Series/SeriesCollection'
], function (Marionette, SummaryLayout, SearchLayout, SeriesCollection) {
], function (Marionette, SummaryLayout, SearchLayout, EpisodeActivityLayout, SeriesCollection) {
return Marionette.Layout.extend({
template: 'Episode/EpisodeDetailsLayoutTemplate',
@ -38,7 +39,7 @@ define(
this.series = SeriesCollection.find({ id: this.model.get('seriesId') });
this.templateHelpers.series = this.series.toJSON();
this.openingTab = options.openingTab || 'summary'
this.openingTab = options.openingTab || 'summary';
},
onShow: function () {
@ -71,6 +72,7 @@ define(
}
this.ui.activity.tab('show');
this.activity.show(new EpisodeActivityLayout({model: this.model, series: this.series}));
},
_showSearch: function (e) {

@ -15,12 +15,12 @@
<div class="modal-body">
<ul class="nav nav-tabs" id="myTab">
<li><a href="#episode-summary" class="x-episode-summary">Summary</a></li>
<!-- <li><a href="#episode-activity" class="x-episode-activity">Activity</a></li>-->
<li><a href="#episode-activity" class="x-episode-activity">Activity</a></li>
<li><a href="#episode-search" class="x-episode-search">Search</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane" id="episode-summary"/>
<!--<div class="tab-pane" id="episode-activity"/>-->
<div class="tab-pane" id="episode-activity"/>
<div class="tab-pane" id="episode-search"/>
</div>
</div>

@ -58,7 +58,7 @@ define(
if (App.reqres.hasHandler(App.Reqres.GetEpisodeFileById)) {
var episodeFile = App.request(App.Reqres.GetEpisodeFileById, episodeFileId);
var episodeFileCollection = new EpisodeFileCollection(episodeFile, { seriesId: this.model.get('seriesId') });
this._showTable(episodeFileCollection)
this._showTable(episodeFileCollection);
}
else {

@ -4,7 +4,7 @@ define(
'marionette',
'backgrid',
'History/HistoryCollection',
'History/Table/EventTypeCell',
'Cells/EventTypeCell',
'Cells/SeriesTitleCell',
'Cells/EpisodeNumberCell',
'Cells/EpisodeTitleCell',

Loading…
Cancel
Save