Upcoming/Index now uses .ToBestDateString() for Dates, only showing on FutureForecast grid (instead of all grids). Status is shown on grid and option to search for episode.

Series/Details season grids won't be as tall now, due to reduced padding.
This commit is contained in:
Mark McDowall 2011-09-28 17:20:29 -07:00
parent 6736afbeab
commit 9714a96437
5 changed files with 141 additions and 94 deletions

View File

@ -1,6 +1,7 @@
// ReSharper disable RedundantUsingDirective
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMoq;
using FizzWare.NBuilder;
using FluentAssertions;
@ -15,50 +16,27 @@ namespace NzbDrone.Core.Test
// ReSharper disable InconsistentNaming
public class UpcomingEpisodesProviderTest : TestBase
{
private Episode yesterday;
private Episode today;
private Episode tomorrow;
private Episode twoDays;
private Episode sevenDays;
private IList<Episode> episodes;
private Series series;
[SetUp]
public new void Setup()
{
yesterday = Builder<Episode>.CreateNew()
.With(c => c.AirDate = DateTime.Today.AddDays(-1))
.With(c => c.Title = "Yesterday")
.With(c => c.SeriesId = 1)
.Build();
today = Builder<Episode>.CreateNew()
.With(c => c.AirDate = DateTime.Today)
.With(c => c.Title = "Today")
.With(c => c.SeriesId = 1)
.Build();
tomorrow = Builder<Episode>.CreateNew()
.With(c => c.AirDate = DateTime.Today.AddDays(1))
.With(c => c.Title = "Tomorrow")
.With(c => c.SeriesId = 1)
.Build();
twoDays = Builder<Episode>.CreateNew()
.With(c => c.AirDate = DateTime.Today.AddDays(2))
.With(c => c.Title = "Two Days")
.With(c => c.SeriesId = 1)
.Build();
sevenDays = Builder<Episode>.CreateNew()
.With(c => c.AirDate = DateTime.Today.AddDays(7))
.With(c => c.Title = "Seven Days")
.With(c => c.SeriesId = 1)
.Build();
sevenDays = Builder<Episode>.CreateNew()
.With(c => c.AirDate = DateTime.Today.AddDays(8))
.With(c => c.Title = "Eight Days")
.With(c => c.SeriesId = 1)
episodes = Builder<Episode>.CreateListOfSize(6)
.WhereAll()
.Have(e => e.SeriesId = 1)
.WhereTheFirst(1)
.Has(e => e.AirDate = DateTime.Today.AddDays(-1))
.AndTheNext(1)
.Has(e => e.AirDate = DateTime.Today)
.AndTheNext(1)
.Has(e => e.AirDate = DateTime.Today.AddDays(1))
.AndTheNext(1)
.Has(e => e.AirDate = DateTime.Today.AddDays(2))
.AndTheNext(1)
.Has(e => e.AirDate = DateTime.Today.AddDays(7))
.AndTheNext(1)
.Has(e => e.AirDate = DateTime.Today.AddDays(9))
.Build();
series = Builder<Series>.CreateNew().With(s => s.SeriesId = 1).Build();
@ -74,21 +52,17 @@ namespace NzbDrone.Core.Test
var mocker = new AutoMoqer();
mocker.SetConstant(database);
database.Insert(yesterday);
database.Insert(today);
database.Insert(tomorrow);
database.Insert(twoDays);
database.Insert(sevenDays);
database.InsertMany(episodes);
database.Insert(series);
//Act
var result = mocker.Resolve<UpcomingEpisodesProvider>().Yesterday();
//Assert
Assert.AreEqual(1, result.Count);
Assert.AreEqual(yesterday.Title, result[0].Title);
result[0].Series.Should().NotBeNull();
result[0].Series.SeriesId.Should().NotBe(0);
result.Should().HaveCount(1);
result.First().Title.Should().Be(episodes.Where(e => e.AirDate == DateTime.Today.AddDays(-1)).First().Title);
result.First().Series.Should().NotBeNull();
result.First().Series.SeriesId.Should().NotBe(0);
}
[Test]
@ -99,21 +73,17 @@ namespace NzbDrone.Core.Test
var mocker = new AutoMoqer();
mocker.SetConstant(database);
database.Insert(yesterday);
database.Insert(today);
database.Insert(tomorrow);
database.Insert(twoDays);
database.Insert(sevenDays);
database.InsertMany(episodes);
database.Insert(series);
//Act
var result = mocker.Resolve<UpcomingEpisodesProvider>().Today();
//Assert
Assert.AreEqual(1, result.Count);
Assert.AreEqual(today.Title, result[0].Title);
result[0].Series.Should().NotBeNull();
result[0].Series.SeriesId.Should().NotBe(0);
result.Should().HaveCount(1);
result.First().Title.Should().Be(episodes.Where(e => e.AirDate == DateTime.Today).First().Title);
result.First().Series.Should().NotBeNull();
result.First().Series.SeriesId.Should().NotBe(0);
}
[Test]
@ -124,21 +94,17 @@ namespace NzbDrone.Core.Test
var mocker = new AutoMoqer();
mocker.SetConstant(database);
database.Insert(yesterday);
database.Insert(today);
database.Insert(tomorrow);
database.Insert(twoDays);
database.Insert(sevenDays);
database.InsertMany(episodes);
database.Insert(series);
//Act
var result = mocker.Resolve<UpcomingEpisodesProvider>().Tomorrow();
//Assert
Assert.AreEqual(1, result.Count);
Assert.AreEqual(tomorrow.Title, result[0].Title);
result[0].Series.Should().NotBeNull();
result[0].Series.SeriesId.Should().NotBe(0);
result.Should().HaveCount(1);
result.First().Title.Should().Be(episodes.Where(e => e.AirDate == DateTime.Today.AddDays(1)).First().Title);
result.First().Series.Should().NotBeNull();
result.First().Series.SeriesId.Should().NotBe(0);
}
[Test]
@ -149,22 +115,18 @@ namespace NzbDrone.Core.Test
var mocker = new AutoMoqer();
mocker.SetConstant(database);
database.Insert(yesterday);
database.Insert(today);
database.Insert(tomorrow);
database.Insert(twoDays);
database.Insert(sevenDays);
database.InsertMany(episodes);
database.Insert(series);
//Act
var result = mocker.Resolve<UpcomingEpisodesProvider>().Week();
//Assert
Assert.AreEqual(2, result.Count);
result[0].Series.Should().NotBeNull();
result[0].Series.SeriesId.Should().NotBe(0);
result[1].Series.Should().NotBeNull();
result[1].Series.SeriesId.Should().NotBe(0);
result.Should().HaveCount(2);
result.First().Series.Should().NotBeNull();
result.First().Series.SeriesId.Should().NotBe(0);
result.Last().Series.Should().NotBeNull();
result.Last().Series.SeriesId.Should().NotBe(0);
}
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using NzbDrone.Core;
using NzbDrone.Core.Providers;
using NzbDrone.Web.Models;
using Telerik.Web.Mvc;
@ -37,7 +38,10 @@ namespace NzbDrone.Web.Controllers
EpisodeNumber = u.EpisodeNumber,
Title = u.Title,
Overview = u.Overview,
AirDate = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay)
AirDateTime = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay),
AirDate = u.AirDate.Value.ToBestDateString(),
AirTime = Convert.ToDateTime(u.Series.AirTimes).ToShortTimeString(),
Status = u.Status.ToString()
});
return View(new GridModel(upcoming));
@ -55,7 +59,10 @@ namespace NzbDrone.Web.Controllers
EpisodeNumber = u.EpisodeNumber,
Title = u.Title,
Overview = u.Overview,
AirDate = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay)
AirDateTime = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay),
AirDate = u.AirDate.Value.ToBestDateString(),
AirTime = Convert.ToDateTime(u.Series.AirTimes).ToShortTimeString(),
Status = u.Status.ToString()
});
return View(new GridModel(upcoming));
@ -73,7 +80,10 @@ namespace NzbDrone.Web.Controllers
EpisodeNumber = u.EpisodeNumber,
Title = u.Title,
Overview = u.Overview,
AirDate = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay)
AirDateTime = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay),
AirDate = u.AirDate.Value.ToBestDateString(),
AirTime = Convert.ToDateTime(u.Series.AirTimes).ToShortTimeString(),
Status = u.Status.ToString()
});
return View(new GridModel(upcoming));
@ -91,7 +101,10 @@ namespace NzbDrone.Web.Controllers
EpisodeNumber = u.EpisodeNumber,
Title = u.Title,
Overview = u.Overview,
AirDate = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay)
AirDateTime = u.AirDate.Value.Add(Convert.ToDateTime(u.Series.AirTimes).TimeOfDay),
AirDate = u.AirDate.Value.ToBestDateString(),
AirTime = Convert.ToDateTime(u.Series.AirTimes).ToShortTimeString(),
Status = u.Status.ToString()
});
return View(new GridModel(upcoming));

View File

@ -1,4 +1,5 @@
using System;
using NzbDrone.Core.Model;
namespace NzbDrone.Web.Models
{
@ -11,6 +12,9 @@ namespace NzbDrone.Web.Models
public int EpisodeNumber { get; set; }
public string Title { get; set; }
public string Overview { get; set; }
public DateTime AirDate { get; set; }
public DateTime AirDateTime { get; set; }
public string AirDate { get; set; }
public string AirTime { get; set; }
public string Status { get; set; }
}
}

View File

@ -69,16 +69,16 @@
padding: 0.3em 0.9em 1.0em 0.6em;
}
.t-grid .t-alt
{
/*background: #E5ECF9;*/
}
.t-grid .t-detail-cell
{
line-height: 1.5em;
}
.t-grid td
{
padding: 0 0.6em;
}
#banner-container
{
width: 758px;

View File

@ -3,6 +3,50 @@
@section TitleContent{
Upcoming
}
<style>
.statusImage, .searchImage, .renameImage, .ignoreEpisode, .ignoreEpisodesMaster
{
width: 18px;
height: 18px;
padding: 1px;
margin: 2px;
border-width: 1px;
border-style: dashed;
border-color: lightgray;
}
.searchImage:hover, .renameImage:hover, .ignoreEpisode:hover, .ignoreEpisodesMaster:hover
{
background-color: #065EFE;
}
.t-grid td
{
line-height: 0.6em;
}
.t-grid .t-header
{
line-height: 1.8em;
}
.t-grid-header .t-header .t-link
{
padding: 0.3em 0.9em 1.0em 0.6em;
}
.t-grid .t-detail-cell
{
line-height: 1.5em;
}
.t-grid td
{
padding: 0 0.6em;
}
</style>
@section ActionMenu{
<ul class="sub-menu">
<li>@Ajax.ActionLink("Start RSS Sync", "RssSync", "Command", null, null)</li>
@ -25,7 +69,13 @@ Upcoming
columns.Bound(c => c.SeasonNumber).Title("Season #").Width(40);
columns.Bound(c => c.EpisodeNumber).Title("Episode #").Width(40);
columns.Bound(c => c.Title).Title("Episode Title");
columns.Bound(c => c.AirDate).Title("Air Date").Width(160);
columns.Bound(c => c.AirDateTime).Title("Air Time")
.ClientTemplate("<#= AirTime #>")
.Width(160);
columns.Bound(c => c.Status)
.ClientTemplate("<img src='../../Content/Images/<#= Status #>.png' alt='<#= Status #>' title='<#= Status #>' class='statusImage status-<#= Status #>' />" +
"<a href=\"../Episode/Season?episodeId=<#= EpisodeId #>\" onclick=\"searchForEpisode('<#= EpisodeId #>'); return false;\"><img src='../../Content/Images/Search.png' alt='Search' title='Search for episode' class='searchImage' /></a>"
);
})
.DetailView(detailView => detailView.ClientTemplate(
"<fieldset>" +
@ -33,7 +83,7 @@ Upcoming
"</fieldset>"
))
.DataBinding(data => data.Ajax().Select("_AjaxBindingYesterday", "Upcoming"))
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.AirDate).Ascending()).Enabled(true))
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.AirDateTime).Ascending()).Enabled(true))
//.Pageable(c => c.PageSize(20).Position(GridPagerPosition.Both).Style(GridPagerStyles.PageInput | GridPagerStyles.NextPreviousAndNumeric))
//.Filterable()
//.ClientEvents(c => c.OnRowDataBound("onRowDataBound"))
@ -56,7 +106,13 @@ Upcoming
columns.Bound(c => c.SeasonNumber).Title("Season #").Width(40);
columns.Bound(c => c.EpisodeNumber).Title("Episode #").Width(40);
columns.Bound(c => c.Title).Title("Episode Title");
columns.Bound(c => c.AirDate).Title("Air Date").Width(160);
columns.Bound(c => c.AirDateTime).Title("Air Time")
.ClientTemplate("<#= AirTime #>")
.Width(160);
columns.Bound(c => c.Status)
.ClientTemplate("<img src='../../Content/Images/<#= Status #>.png' alt='<#= Status #>' title='<#= Status #>' class='statusImage status-<#= Status #>' />" +
"<a href=\"../Episode/Season?episodeId=<#= EpisodeId #>\" onclick=\"searchForEpisode('<#= EpisodeId #>'); return false;\"><img src='../../Content/Images/Search.png' alt='Search' title='Search for episode' class='searchImage' /></a>"
);
})
.DetailView(detailView => detailView.ClientTemplate(
"<fieldset>" +
@ -64,7 +120,7 @@ Upcoming
"</fieldset>"
))
.DataBinding(data => data.Ajax().Select("_AjaxBindingToday", "Upcoming"))
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.AirDate).Ascending()).Enabled(true))
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.AirDateTime).Ascending()).Enabled(true))
.Render();}
</div>
</div>
@ -85,7 +141,13 @@ Upcoming
columns.Bound(c => c.SeasonNumber).Title("Season #").Width(40);
columns.Bound(c => c.EpisodeNumber).Title("Episode #").Width(40);
columns.Bound(c => c.Title).Title("Episode Title");
columns.Bound(c => c.AirDate).Title("Air Date").Width(160);
columns.Bound(c => c.AirDateTime).Title("Air Time")
.ClientTemplate("<#= AirTime #>")
.Width(160);
columns.Bound(c => c.Status)
.ClientTemplate("<img src='../../Content/Images/<#= Status #>.png' alt='<#= Status #>' title='<#= Status #>' class='statusImage status-<#= Status #>' />" +
"<a href=\"../Episode/Season?episodeId=<#= EpisodeId #>\" onclick=\"searchForEpisode('<#= EpisodeId #>'); return false;\"><img src='../../Content/Images/Search.png' alt='Search' title='Search for episode' class='searchImage' /></a>"
);
})
.DetailView(detailView => detailView.ClientTemplate(
"<fieldset>" +
@ -94,7 +156,7 @@ Upcoming
))
.DataBinding(data => data.Ajax().Select("_AjaxBindingTomorrow", "Upcoming"))
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.AirDate).Ascending()).Enabled(true))
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.AirDateTime).Ascending()).Enabled(true))
.Render();}
</div>
</div>
@ -115,7 +177,13 @@ Upcoming
columns.Bound(c => c.SeasonNumber).Title("Season #").Width(40);
columns.Bound(c => c.EpisodeNumber).Title("Episode #").Width(40);
columns.Bound(c => c.Title).Title("Episode Title");
columns.Bound(c => c.AirDate).Title("Air Date").Width(160);
columns.Bound(c => c.AirDateTime).Title("Air Date/Time")
.ClientTemplate("<#= AirDate #> at <#= AirTime #>")
.Width(160);
columns.Bound(c => c.Status)
.ClientTemplate("<img src='../../Content/Images/<#= Status #>.png' alt='<#= Status #>' title='<#= Status #>' class='statusImage status-<#= Status #>' />" +
"<a href=\"../Episode/Season?episodeId=<#= EpisodeId #>\" onclick=\"searchForEpisode('<#= EpisodeId #>'); return false;\"><img src='../../Content/Images/Search.png' alt='Search' title='Search for episode' class='searchImage' /></a>"
);
})
.DetailView(detailView => detailView.ClientTemplate(
"<fieldset>" +
@ -123,7 +191,7 @@ Upcoming
"</fieldset>"
))
.DataBinding(data => data.Ajax().Select("_AjaxBindingWeek", "Upcoming"))
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.AirDate).Ascending()).Enabled(true))
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.AirDateTime).Ascending()).Enabled(true))
.Render();}
</div>
</div>