Upcoming view working under backbone

This commit is contained in:
Mark McDowall 2013-02-19 23:45:52 -08:00
parent bc490c6bf7
commit cf1a067b3b
20 changed files with 304 additions and 2 deletions

View File

@ -4,7 +4,9 @@ using NzbDrone.Api.QualityProfiles;
using NzbDrone.Api.QualityType;
using NzbDrone.Api.Resolvers;
using NzbDrone.Api.Series;
using NzbDrone.Api.Upcoming;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api
{
@ -40,6 +42,12 @@ namespace NzbDrone.Api
.ForMember(dest => dest.CustomStartDate, opt => opt.ResolveUsing<NullableDatetimeToString>().FromMember(src => src.CustomStartDate))
.ForMember(dest => dest.BacklogSetting, opt => opt.MapFrom(src => (Int32)src.BacklogSetting))
.ForMember(dest => dest.NextAiring, opt => opt.ResolveUsing<NextAiringResolver>());
//Upcoming
Mapper.CreateMap<Episode, UpcomingResource>()
.ForMember(dest => dest.SeriesTitle, opt => opt.MapFrom(src => src.Series.Title))
.ForMember(dest => dest.EpisodeTitle, opt => opt.MapFrom(src => src.Title))
.ForMember(dest => dest.AirTime, opt => opt.ResolveUsing<AirTimeResolver>());
}
}
}

View File

@ -115,6 +115,7 @@
<Compile Include="FrontendModule\IndexModule.cs" />
<Compile Include="FrontendModule\BootstrapModule.cs" />
<Compile Include="FrontendModule\LessService.cs" />
<Compile Include="Resolvers\AirTimeResolver.cs" />
<Compile Include="Resolvers\NextAiringResolver.cs" />
<Compile Include="Resolvers\NullableDatetimeToString.cs" />
<Compile Include="RootFolders\RootFolderModule.cs" />
@ -138,6 +139,8 @@
<Compile Include="Resolvers\AllowedToQualitiesResolver.cs" />
<Compile Include="Resolvers\QualitiesToAllowedResolver.cs" />
<Compile Include="Resolvers\QualityTypesToIntResolver.cs" />
<Compile Include="Upcoming\UpcomingModule.cs" />
<Compile Include="Upcoming\UpcomingResource.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using NzbDrone.Api.QualityProfiles;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Resolvers
{
public class AirTimeResolver : ValueResolver<Episode, DateTime?>
{
protected override DateTime? ResolveCore(Episode source)
{
if(String.IsNullOrWhiteSpace(source.Series.AirTime) || !source.AirDate.HasValue)
return source.AirDate;
return source.AirDate.Value.Add(Convert.ToDateTime(source.Series.AirTime).TimeOfDay)
.AddHours(source.Series.UtcOffset * -1);
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using AutoMapper;
using FluentValidation;
using Nancy;
using NzbDrone.Api.Extentions;
using NzbDrone.Api.Series;
using NzbDrone.Common;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Upcoming
{
public class UpcomingModule : NzbDroneApiModule
{
private readonly UpcomingEpisodesProvider _upcomingEpisodesProvider;
public UpcomingModule(UpcomingEpisodesProvider upcomingEpisodesProvider)
: base("/Upcoming")
{
_upcomingEpisodesProvider = upcomingEpisodesProvider;
Get["/"] = x => Upcoming();
}
private Response Upcoming()
{
var upcoming = _upcomingEpisodesProvider.UpcomingEpisodes();
return Mapper.Map<List<Episode>, List<UpcomingResource>>(upcoming).AsResponse();
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NzbDrone.Api.QualityProfiles;
using NzbDrone.Core.Model;
namespace NzbDrone.Api.Upcoming
{
public class UpcomingResource
{
public Int32 SeriesId { get; set; }
public String SeriesTitle { get; set; }
public Int32 EpisodeId { get; set; }
public String EpisodeTitle { get; set; }
public Int32 SeasonNumber { get; set; }
public Int32 EpisodeNumber { get; set; }
public DateTime? AirTime { get; set; }
public Int32 Status { get; set; }
public String Overview { get; set; }
}
}

View File

@ -1,4 +1,4 @@
define(['app', 'Shared/ModalRegion', 'AddSeries/AddSeriesLayout', 'Series/SeriesCollectionView', 'Shared/NotificationView', 'Shared/NotFoundView'], function (app, modalRegion) {
define(['app', 'Shared/ModalRegion', 'AddSeries/AddSeriesLayout', 'Series/SeriesCollectionView', 'Upcoming/UpcomingCollectionView', 'Shared/NotificationView', 'Shared/NotFoundView'], function (app, modalRegion) {
var controller = Backbone.Marionette.Controller.extend({
@ -12,6 +12,11 @@
NzbDrone.mainRegion.show(new NzbDrone.Series.SeriesCollectionView(this, action, query));
},
upcoming: function (action, query) {
this.setTitle('Upcoming');
NzbDrone.mainRegion.show(new NzbDrone.Upcoming.UpcomingCollectionView(this, action, query));
},
notFound: function () {
this.setTitle('Not Found');
NzbDrone.mainRegion.show(new NzbDrone.Shared.NotFoundView(this));

View File

@ -121,6 +121,12 @@
<Content Include="Shared\NotificationView.js" />
<Content Include="Shared\SpinnerTemplate.html" />
<Content Include="Shared\SpinnerView.js" />
<Content Include="Upcoming\UpcomingCollection.js" />
<Content Include="Upcoming\UpcomingCollectionTemplate.html" />
<Content Include="Upcoming\UpcomingCollectionView.js" />
<Content Include="Upcoming\UpcomingGroupTemplate.html" />
<Content Include="Upcoming\UpcomingGroupView.js" />
<Content Include="Upcoming\UpcomingModel.js" />
</ItemGroup>
<ItemGroup>
<Content Include="Content\Bootstrap\accordion.less" />

View File

@ -9,6 +9,8 @@
'series/index': 'series',
'series/add': 'addSeries',
'series/add/:action(/:query)': 'addSeries',
'upcoming': 'upcoming',
'upcoming/index': 'upcoming',
':whatever': 'notFound'
}
});

View File

@ -12,7 +12,6 @@
if (date.isYesterday()) return 'Yesterday';
if (date.isToday()) return 'Today';
if (date.isTomorrow()) return 'Tomorrow';
if (date.isToday()) return 'Today';
if (date.isBefore(Date.create().addDays(7))) return date.format('{Weekday}');
return date.format('{MM}/{dd}/{yyyy}');

View File

@ -0,0 +1,6 @@
define(['app', 'Upcoming/UpcomingModel'], function () {
NzbDrone.Upcoming.UpcomingCollection = Backbone.Collection.extend({
url: NzbDrone.Constants.ApiRoot + '/upcoming',
model: NzbDrone.Upcoming.UpcomingModel
});
});

View File

@ -0,0 +1,65 @@
<table class="table table-striped">
<thead>
<tr>
<th>Series Title</th>
<th>Episode</th>
<th>Episode Title</th>
<th>Air Time</th>
<th>Status</th>
</tr>
</thead>
<tbody id="yesterday">
<tr>
<td colspan="5">Yesterday</td>
</tr>
</tbody>
<tbody id="today">
<tr>
<td colspan="5">Today</td>
</tr>
</tbody>
<tbody id="tomorrow">
<tr>
<td colspan="5">Tomorrow</td>
</tr>
</tbody>
<tbody id="two_days">
<tr>
<td colspan="5">{{two_days}}</td>
</tr>
</tbody>
<tbody id="three_days">
<tr>
<td colspan="5">{{three_days}}</td>
</tr>
</tbody>
<tbody id="four_days">
<tr>
<td colspan="5">{{four_days}}</td>
</tr>
</tbody>
<tbody id="five_days">
<tr>
<td colspan="5">{{five_days}}</td>
</tr>
</tbody>
<tbody id="six_days">
<tr>
<td colspan="5">{{six_days}}</td>
</tr>
</tbody>
<tbody id="later">
<tr>
<td colspan="5">Later</td>
</tr>
</tbody>
</table>

View File

@ -0,0 +1,89 @@
'use strict';
define(['app', 'Upcoming/UpcomingItemView'], function (app) {
NzbDrone.Upcoming.UpcomingCollectionView = Backbone.Marionette.CompositeView.extend({
itemView: NzbDrone.Upcoming.UpcomingItemView,
template: 'Upcoming/UpcomingCollectionTemplate',
itemViewContainer: 'table',
ui: {
yesterday: 'tbody#yesterday',
today: 'tbody#today',
tomorrow: 'tbody#tomorrow',
two_days: 'tbody#two_days',
three_days: 'tbody#three_days',
four_days: 'tbody#four_days',
five_days: 'tbody#five_days',
six_days: 'tbody#six_days',
later: 'tbody#later'
},
initialize: function () {
this.collection = new NzbDrone.Upcoming.UpcomingCollection();
this.collection.fetch();
},
serializeData: function() {
var viewData = {};
viewData.two_days = Date.create().addDays(2).format('{Weekday}');
viewData.three_days = Date.create().addDays(3).format('{Weekday}');
viewData.four_days = Date.create().addDays(4).format('{Weekday}');
viewData.five_days = Date.create().addDays(5).format('{Weekday}');
viewData.six_days = Date.create().addDays(6).format('{Weekday}');
return viewData;
},
appendHtml: function(collectionView, itemView, index){
var date = Date.create(itemView.model.get('airTime'));
if (date.isYesterday()){
collectionView.$(this.ui.yesterday).append(itemView.el);
return;
}
if (date.isToday()){
collectionView.$(this.ui.today).append(itemView.el);
return;
}
if (date.isTomorrow()){
collectionView.$(this.ui.tomorrow).append(itemView.el);
return;
}
if (date.is(Date.create().addDays(2).short())){
collectionView.$(this.ui.two_days).append(itemView.el);
return;
}
if (date.is(Date.create().addDays(3).short())){
collectionView.$(this.ui.three_days).append(itemView.el);
return;
}
if (date.is(Date.create().addDays(4).short())){
collectionView.$(this.ui.four_days).append(itemView.el);
return;
}
if (date.is(Date.create().addDays(5).short())){
collectionView.$(this.ui.five_days).append(itemView.el);
return;
}
if (date.is(Date.create().addDays(6).short())){
collectionView.$(this.ui.six_days).append(itemView.el);
return;
}
collectionView.$(this.ui.later).append(itemView.el);
//if (date.isBefore(Date.create().addDays(7))) return date.format('{Weekday}');
},
onCompositeCollectionRendered: function()
{
//Might not need this :D
}
});
});

View File

@ -0,0 +1,5 @@
<td>{{seriesTitle}}</td>
<td>{{seasonNumber}}x{{episodeNumber}}</td>
<td>{{episodeTitle}}</td>
<td>{{airTime}}</td>
<td>{{status}}</td>

View File

@ -0,0 +1,16 @@
'use strict';
define([
'app',
'Upcoming/UpcomingCollection'
], function () {
NzbDrone.Upcoming.UpcomingItemView = Backbone.Marionette.ItemView.extend({
template: 'Upcoming/UpcomingItemTemplate',
tagName: 'tr',
onRender: function () {
NzbDrone.ModelBinder.bind(this.model, this.el);
}
})
})

View File

@ -0,0 +1,10 @@
define(['app'], function (app) {
NzbDrone.Upcoming.UpcomingModel = Backbone.Model.extend({
mutators: {
},
defaults: {
status: 0
}
});
});

View File

@ -38,6 +38,7 @@ define('app', function () {
window.NzbDrone.AddSeries.RootFolders = {};
window.NzbDrone.Quality = {};
window.NzbDrone.Shared = {};
window.NzbDrone.Upcoming = {};
window.NzbDrone.Events = {
OpenModalDialog :'openModal',

View File

@ -15,6 +15,7 @@
/// <summary>
/// Episode has aired, but no episode
/// files are avilable
/// Todo: We shouldn't set missing until the episode has past the actual airtime + runtime, including UtcOffset
/// </summary>
Missing,

View File

@ -17,6 +17,7 @@ namespace NzbDrone.Core.Providers
_database = database;
}
//Todo: Might be best if this is part of episode repo (when its there)
public virtual List<Episode> UpcomingEpisodes()
{
return _database.Fetch<Episode, Series>(@"SELECT * FROM Episodes

View File

@ -15,6 +15,8 @@ namespace NzbDrone.Core.Tv
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
public string Title { get; set; }
//Todo: Since we're displaying next airing relative to the user's timezone we may want to store this as UTC (with airtime + UTC offset)
public DateTime? AirDate { get; set; }
public string Overview { get; set; }
public Boolean Ignored { get; set; }
@ -23,6 +25,7 @@ namespace NzbDrone.Core.Tv
public int SceneSeasonNumber { get; set; }
public int SceneEpisodeNumber { get; set; }
//Todo: This should be UTC
public DateTime? GrabDate { get; set; }
public EpisodeStatusType Status

View File

@ -2,6 +2,7 @@
using System;
using NzbDrone.Core.Model;
using NzbDrone.Core.Repository.Quality;
using PetaPoco;
namespace NzbDrone.Core.Tv
{
@ -19,6 +20,7 @@ namespace NzbDrone.Core.Tv
public DayOfWeek? AirsDayOfWeek { get; set; }
[Column("AirTimes")]
public String AirTime { get; set; }
public string Language { get; set; }