mirror of https://github.com/Radarr/Radarr
SeriesGrid now has sorting.
This commit is contained in:
parent
89dba91f3a
commit
d68ae8f3f3
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
|
using System.Web.Script.Serialization;
|
||||||
using MvcMiniProfiler;
|
using MvcMiniProfiler;
|
||||||
using NzbDrone.Common.Model;
|
using NzbDrone.Common.Model;
|
||||||
using NzbDrone.Core;
|
using NzbDrone.Core;
|
||||||
|
@ -37,8 +38,10 @@ namespace NzbDrone.Web.Controllers
|
||||||
|
|
||||||
public ActionResult Index()
|
public ActionResult Index()
|
||||||
{
|
{
|
||||||
var series = GetSeriesModels(_seriesProvider.GetAllSeriesWithEpisodeCount()).OrderBy(o => SortHelper.SkipArticles(o.Title)).ToList();
|
var series = GetSeriesModels(_seriesProvider.GetAllSeriesWithEpisodeCount());
|
||||||
return View(series);
|
var serialized = new JavaScriptSerializer().Serialize(series);
|
||||||
|
|
||||||
|
return View((object)serialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult SeriesEditor(int seriesId)
|
public ActionResult SeriesEditor(int seriesId)
|
||||||
|
@ -191,6 +194,7 @@ namespace NzbDrone.Web.Controllers
|
||||||
{
|
{
|
||||||
SeriesId = s.SeriesId,
|
SeriesId = s.SeriesId,
|
||||||
Title = s.Title,
|
Title = s.Title,
|
||||||
|
TitleSorter = SortHelper.SkipArticles(s.Title),
|
||||||
AirsDayOfWeek = s.AirsDayOfWeek.ToString(),
|
AirsDayOfWeek = s.AirsDayOfWeek.ToString(),
|
||||||
Monitored = s.Monitored,
|
Monitored = s.Monitored,
|
||||||
Overview = s.Overview,
|
Overview = s.Overview,
|
||||||
|
@ -203,7 +207,8 @@ namespace NzbDrone.Web.Controllers
|
||||||
SeasonsCount = s.SeasonCount,
|
SeasonsCount = s.SeasonCount,
|
||||||
EpisodeCount = s.EpisodeCount,
|
EpisodeCount = s.EpisodeCount,
|
||||||
EpisodeFileCount = s.EpisodeFileCount,
|
EpisodeFileCount = s.EpisodeFileCount,
|
||||||
NextAiring = s.NextAiring == null ? String.Empty : s.NextAiring.Value.ToBestDateString()
|
NextAiring = s.NextAiring == null ? String.Empty : s.NextAiring.Value.ToBestDateString(),
|
||||||
|
NextAiringSorter = s.NextAiring == null ? "12/31/9999" : s.NextAiring.Value.ToString("MM/dd/yyyy")
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
return series;
|
return series;
|
||||||
|
|
|
@ -7,12 +7,13 @@ using NzbDrone.Core.Repository;
|
||||||
|
|
||||||
namespace NzbDrone.Web.Models
|
namespace NzbDrone.Web.Models
|
||||||
{
|
{
|
||||||
public class SeriesModel
|
public class SeriesModel
|
||||||
{
|
{
|
||||||
public int SeriesId { get; set; }
|
public int SeriesId { get; set; }
|
||||||
|
|
||||||
//View Only
|
//View Only
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
public string TitleSorter { get; set; }
|
||||||
public int SeasonsCount { get; set; }
|
public int SeasonsCount { get; set; }
|
||||||
public int EpisodeCount { get; set; }
|
public int EpisodeCount { get; set; }
|
||||||
public int EpisodeFileCount { get; set; }
|
public int EpisodeFileCount { get; set; }
|
||||||
|
@ -23,6 +24,8 @@ namespace NzbDrone.Web.Models
|
||||||
public int Episodes { get; set; }
|
public int Episodes { get; set; }
|
||||||
public bool HasBanner { get; set; }
|
public bool HasBanner { get; set; }
|
||||||
public string NextAiring { get; set; }
|
public string NextAiring { get; set; }
|
||||||
|
public string NextAiringSorter { get; set; }
|
||||||
|
public string Details { get; set; }
|
||||||
|
|
||||||
public IList<int> Seasons { get; set; }
|
public IList<int> Seasons { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@using NzbDrone.Common
|
@using NzbDrone.Common
|
||||||
@using NzbDrone.Web.Helpers
|
@using NzbDrone.Web.Helpers
|
||||||
@using NzbDrone.Web.Models;
|
@using NzbDrone.Web.Models;
|
||||||
@model List<NzbDrone.Web.Models.SeriesModel>
|
@model string
|
||||||
@{ViewBag.Title = "NzbDrone";}
|
@{ViewBag.Title = "NzbDrone";}
|
||||||
|
|
||||||
@section HeaderContent
|
@section HeaderContent
|
||||||
|
@ -79,48 +79,24 @@
|
||||||
</ul>
|
</ul>
|
||||||
}
|
}
|
||||||
|
|
||||||
<table class="seriesTable">
|
<table id="seriesGrid" class="dataTablesGrid seriesTable">
|
||||||
|
|
||||||
<colgroup>
|
|
||||||
<col style="width: 10px"/>
|
|
||||||
<col style="width:auto" />
|
|
||||||
<col style="width:100px" />
|
|
||||||
<col style="width:100px" />
|
|
||||||
<col style="width:140px" />
|
|
||||||
<col style="width:100px" />
|
|
||||||
<col style="width:80px"/>
|
|
||||||
</colgroup>
|
|
||||||
<thead>
|
<thead>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Status</th>
|
<th style="width: 10px">Status</th>
|
||||||
<th>Title</th>
|
<th style="width: auto">Title</th>
|
||||||
<th>Seasons</th>
|
<th style="width: 100px">Seasons</th>
|
||||||
<th>Quality</th>
|
<th style="width: 100px">Quality</th>
|
||||||
<th>Next Airing</th>
|
<th style="width: 140px">Next Airing</th>
|
||||||
<th>Episodes</th>
|
<th style="width: 100px">Episodes</th>
|
||||||
|
|
||||||
@*Commands Column*@
|
@*Commands Column*@
|
||||||
<th>
|
<th style="width: 80px">
|
||||||
|
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@for (int i = 0; i < Model.Count; i++)
|
|
||||||
{
|
|
||||||
var series = Model[i];
|
|
||||||
|
|
||||||
if (i % 2 == 0)
|
|
||||||
{
|
|
||||||
Html.RenderPartial("Series", series);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Html.RenderPartial("Series", series, new ViewDataDictionary { new KeyValuePair<string, object>("AltRow", true) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -134,8 +110,97 @@
|
||||||
var seriesEditorUrl = './Series/SeriesEditor';
|
var seriesEditorUrl = './Series/SeriesEditor';
|
||||||
var saveSeriesEditorUrl = './Series/SaveSeriesEditor';
|
var saveSeriesEditorUrl = './Series/SaveSeriesEditor';
|
||||||
var seriesDeleteUrl = './Series/DeleteSeries';
|
var seriesDeleteUrl = './Series/DeleteSeries';
|
||||||
|
var pauseImage = '<img src="../../Content/Images/pause.png" width="24" height="24" alt="Paused" title="Not monitored" />';
|
||||||
|
var stopImage = '<img src="../../Content/Images/stop.png" width="24" height="24" alt="Ended" title="Ended" />';
|
||||||
|
var playImage = '<img src="../../Content/Images/play.png" width="24" height="24" alt="Active" title="Continuing" />';
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
$('#seriesGrid').removeClass('hidden-grid');
|
||||||
|
|
||||||
|
oTable = $('.dataTablesGrid').dataTable({
|
||||||
|
"bShowAll": false,
|
||||||
|
"aaData": @Html.Raw(Model),
|
||||||
|
"bPaginate": false,
|
||||||
|
"bLengthChange": false,
|
||||||
|
"bFilter": false,
|
||||||
|
"bSort": true,
|
||||||
|
"bInfo": false,
|
||||||
|
"bAutoWidth": false,
|
||||||
|
"aoColumns": [
|
||||||
|
{ sWidth: '70px',
|
||||||
|
"sClass": "statusColumn",
|
||||||
|
"mDataProp": function (source, type, val) {
|
||||||
|
// 'display' and 'filter' use our fancy naming
|
||||||
|
if (type === 'display' || type === 'filter') {
|
||||||
|
var monitored = source["Monitored"];
|
||||||
|
var status = source["Status"];
|
||||||
|
|
||||||
|
if (!monitored) {
|
||||||
|
return pauseImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
if (status === "Ended"){
|
||||||
|
return stopImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
return playImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 'sort' and 'type' both just use the raw data
|
||||||
|
return source["Status"];
|
||||||
|
}
|
||||||
|
}, //Status
|
||||||
|
{ sWidth: 'auto', "mDataProp": function (source, type, val) {
|
||||||
|
// 'display' and 'filter' use our fancy naming
|
||||||
|
if (type === 'display' || type === 'filter') {
|
||||||
|
return source["Title"];
|
||||||
|
}
|
||||||
|
// 'sort' and 'type' both just use the raw data
|
||||||
|
return source["TitleSorter"];
|
||||||
|
}
|
||||||
|
}, //Title
|
||||||
|
{ sWidth: '100px', "mDataProp": "SeasonsCount", "bSortable": false }, //Seasons
|
||||||
|
{ sWidth: '100px', "mDataProp": "QualityProfileName" }, //Quality
|
||||||
|
{ sWidth: '120px', "mDataProp": function (source, type, val) {
|
||||||
|
// 'display' and 'filter' use our fancy naming
|
||||||
|
if (type === 'display' || type === 'filter') {
|
||||||
|
return source["NextAiring"];
|
||||||
|
}
|
||||||
|
// 'sort' and 'type' both just use the raw data
|
||||||
|
return source["NextAiringSorter"];
|
||||||
|
}
|
||||||
|
}, //Next Airing
|
||||||
|
{ sWidth: '140px', "mDataProp": "Episodes", "bSortable": false, "fnRender": function (row) {
|
||||||
|
var progress = row.aData["EpisodeFileCount"] / row.aData["EpisodeCount"] * 100;
|
||||||
|
|
||||||
|
var result = "<div class='progressBar' rel='" + progress + "'>" +
|
||||||
|
"<span class='progressBarText'>" + row.aData["EpisodeFileCount"] + " / " + row.aData["EpisodeCount"] +"</span>" +
|
||||||
|
"</div>";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}, //Episodes
|
||||||
|
{ sWidth: '50px', "mDataProp": "HasBanner", "bSortable": false, "fnRender": function (row) {
|
||||||
|
return "<img src='../../Content/Images/settings.png' class='editButton' value='" + row.aData["SeriesId"] + "' rel='" + row.aData["Title"] + "' />" +
|
||||||
|
"<img src='../../Content/Images/close.png' class='deleteButton' value='" + row.aData["SeriesId"] + "' rel='" + row.aData["Title"] + "'/>";
|
||||||
|
}
|
||||||
|
}, //Commands
|
||||||
|
{ sWidth: '60px', "mDataProp": "Details", "bSortable": false, "bVisible": false, "fnRender": function (row) {
|
||||||
|
var result = "<b>Airs Day of Week: </b>" + row.aData["AirsDayOfWeek"] + "<br/>" +
|
||||||
|
"<b>Overview: </b>" + row.aData["Overview"] + "<br/>";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} //Details
|
||||||
|
],
|
||||||
|
"aaSorting": [[1, 'asc']],
|
||||||
|
"fnCreatedRow": function( nRow, aData, iDataIndex ) {
|
||||||
|
$(nRow).addClass(aData["SeriesId"].toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$(".progressBar").each(function () {
|
$(".progressBar").each(function () {
|
||||||
var element = this;
|
var element = this;
|
||||||
|
|
||||||
|
@ -197,11 +262,8 @@
|
||||||
width: 450,
|
width: 450,
|
||||||
modal: true,
|
modal: true,
|
||||||
buttons: {
|
buttons: {
|
||||||
|
|
||||||
"Delete": function () {
|
"Delete": function () {
|
||||||
|
|
||||||
var seriesId = $('.seriesId').val();
|
var seriesId = $('.seriesId').val();
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: seriesDeleteUrl,
|
url: seriesDeleteUrl,
|
||||||
|
@ -221,7 +283,6 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".editButton")
|
$(".editButton")
|
||||||
//.button()
|
|
||||||
.live('click', function () {
|
.live('click', function () {
|
||||||
//Get the SeriesId and Title
|
//Get the SeriesId and Title
|
||||||
var seriesId = parseInt($(this).attr("value"));
|
var seriesId = parseInt($(this).attr("value"));
|
||||||
|
@ -246,8 +307,7 @@
|
||||||
$("#seriesEditor").dialog("open");
|
$("#seriesEditor").dialog("open");
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".deleteButton")
|
$(".deleteButton")
|
||||||
//.button()
|
|
||||||
.live('click', function () {
|
.live('click', function () {
|
||||||
//Get the SeriesId and Title
|
//Get the SeriesId and Title
|
||||||
var seriesId = parseInt($(this).attr("value"));
|
var seriesId = parseInt($(this).attr("value"));
|
||||||
|
@ -267,25 +327,20 @@
|
||||||
function updateStatus() {
|
function updateStatus() {
|
||||||
var monitored = $('#Monitored').attr('checked');
|
var monitored = $('#Monitored').attr('checked');
|
||||||
var seriesId = $('#SeriesId').val();
|
var seriesId = $('#SeriesId').val();
|
||||||
var img = $('.' + seriesId).children('.statusColumn').children('img');
|
var status = $('#Status').val();
|
||||||
var state = img.attr('alt');
|
var imgContainer = $('.' + seriesId).children('.statusColumn');
|
||||||
|
|
||||||
if (state == "Ended")
|
if (!monitored) {
|
||||||
return;
|
imgContainer.html(pauseImage);
|
||||||
|
|
||||||
if (state == "Active") {
|
|
||||||
if (!monitored) {
|
|
||||||
img.attr('title', 'Not monitored');
|
|
||||||
img.attr('alt', 'Paused');
|
|
||||||
img.attr('src', '../../Content/Images/pause.png');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == "Paused") {
|
else {
|
||||||
if (monitored) {
|
if (status === "Ended"){
|
||||||
img.attr('title', 'Continuing');
|
imgContainer.html(stopImage);
|
||||||
img.attr('alt', 'Active');
|
}
|
||||||
img.attr('src', '../../Content/Images/play.png');
|
|
||||||
|
else {
|
||||||
|
imgContainer.html(playImage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
@using (Html.BeginForm("SaveSeriesEditor", "Series", FormMethod.Post, new { id = "SeriesEditorForm", name = "SeriesEditorForm", @class = "settingsForm" }))
|
@using (Html.BeginForm("SaveSeriesEditor", "Series", FormMethod.Post, new { id = "SeriesEditorForm", name = "SeriesEditorForm", @class = "settingsForm" }))
|
||||||
{
|
{
|
||||||
@Html.HiddenFor(m => m.SeriesId)
|
@Html.HiddenFor(m => m.SeriesId)
|
||||||
|
@Html.HiddenFor(m => m.Status)
|
||||||
<label class="labelClass">@Html.LabelFor(m => m.Monitored)
|
<label class="labelClass">@Html.LabelFor(m => m.Monitored)
|
||||||
<span class="small">@Html.DescriptionFor(m => m.Monitored)</span>
|
<span class="small">@Html.DescriptionFor(m => m.Monitored)</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
Loading…
Reference in New Issue