Merge branch 'series-sorttitle' of https://github.com/Taloth/NzbDrone into develop

Conflicts:
	src/NzbDrone.Api/Series/SeriesResource.cs
	src/NzbDrone.Core/Tv/SeriesService.cs
pull/6/head
Mark McDowall 10 years ago
commit bd0392a376

@ -28,7 +28,7 @@ namespace NzbDrone.Api.Blacklist
//This is a hack to deal with backgrid setting the sortKey to the column name instead of sortValue //This is a hack to deal with backgrid setting the sortKey to the column name instead of sortValue
if (pagingSpec.SortKey.Equals("series", StringComparison.InvariantCultureIgnoreCase)) if (pagingSpec.SortKey.Equals("series", StringComparison.InvariantCultureIgnoreCase))
{ {
pagingSpec.SortKey = "series.title"; pagingSpec.SortKey = "series.sortTitle";
} }
return ApplyToPage(_blacklistService.Paged, pagingSpec); return ApplyToPage(_blacklistService.Paged, pagingSpec);

@ -36,7 +36,7 @@ namespace NzbDrone.Api.History
//This is a hack to deal with backgrid setting the sortKey to the column name instead of sortValue //This is a hack to deal with backgrid setting the sortKey to the column name instead of sortValue
if (pagingSpec.SortKey.Equals("series", StringComparison.InvariantCultureIgnoreCase)) if (pagingSpec.SortKey.Equals("series", StringComparison.InvariantCultureIgnoreCase))
{ {
pagingSpec.SortKey = "series.title"; pagingSpec.SortKey = "series.sortTitle";
} }
if (pagingResource.FilterKey == "eventType") if (pagingResource.FilterKey == "eventType")

@ -163,6 +163,7 @@ namespace NzbDrone.Api.Series
resource.EpisodeCount = seriesStatistics.EpisodeCount; resource.EpisodeCount = seriesStatistics.EpisodeCount;
resource.EpisodeFileCount = seriesStatistics.EpisodeFileCount; resource.EpisodeFileCount = seriesStatistics.EpisodeFileCount;
resource.NextAiring = seriesStatistics.NextAiring; resource.NextAiring = seriesStatistics.NextAiring;
resource.PreviousAiring = seriesStatistics.PreviousAiring;
} }
private void PopulateAlternateTitles(List<SeriesResource> resources) private void PopulateAlternateTitles(List<SeriesResource> resources)

@ -16,6 +16,7 @@ namespace NzbDrone.Api.Series
//View Only //View Only
public String Title { get; set; } public String Title { get; set; }
public List<AlternateTitleResource> AlternateTitles { get; set; } public List<AlternateTitleResource> AlternateTitles { get; set; }
public String SortTitle { get; set; }
public Int32 SeasonCount public Int32 SeasonCount
{ {
@ -33,6 +34,7 @@ namespace NzbDrone.Api.Series
public String QualityProfileName { get; set; } public String QualityProfileName { get; set; }
public String Overview { get; set; } public String Overview { get; set; }
public DateTime? NextAiring { get; set; } public DateTime? NextAiring { get; set; }
public DateTime? PreviousAiring { get; set; }
public String Network { get; set; } public String Network { get; set; }
public String AirTime { get; set; } public String AirTime { get; set; }
public List<MediaCover> Images { get; set; } public List<MediaCover> Images { get; set; }

@ -1,4 +1,5 @@
using System.Linq; using System;
using System.Linq;
using NzbDrone.Api.Episodes; using NzbDrone.Api.Episodes;
using NzbDrone.Api.Extensions; using NzbDrone.Api.Extensions;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
@ -30,6 +31,12 @@ namespace NzbDrone.Api.Wanted
SortDirection = pagingResource.SortDirection SortDirection = pagingResource.SortDirection
}; };
//This is a hack to deal with backgrid setting the sortKey to the column name instead of sortValue
if (pagingSpec.SortKey.Equals("series", StringComparison.InvariantCultureIgnoreCase))
{
pagingSpec.SortKey = "series.sortTitle";
}
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false") if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
{ {
pagingSpec.FilterExpression = v => v.Monitored == false || v.Series.Monitored == false; pagingSpec.FilterExpression = v => v.Monitored == false || v.Series.Monitored == false;

@ -1,4 +1,5 @@
using System.Linq; using System;
using System.Linq;
using NzbDrone.Api.Episodes; using NzbDrone.Api.Episodes;
using NzbDrone.Api.Extensions; using NzbDrone.Api.Extensions;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
@ -30,6 +31,12 @@ namespace NzbDrone.Api.Wanted
SortDirection = pagingResource.SortDirection SortDirection = pagingResource.SortDirection
}; };
//This is a hack to deal with backgrid setting the sortKey to the column name instead of sortValue
if (pagingSpec.SortKey.Equals("series", StringComparison.InvariantCultureIgnoreCase))
{
pagingSpec.SortKey = "series.sortTitle";
}
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false") if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
{ {
pagingSpec.FilterExpression = v => v.Monitored == false || v.Series.Monitored == false; pagingSpec.FilterExpression = v => v.Monitored == false || v.Series.Monitored == false;

@ -40,6 +40,7 @@ namespace NzbDrone.Core.Test.MetadataSourceTests
[TestCase(75978)] [TestCase(75978)]
[TestCase(83462)] [TestCase(83462)]
[TestCase(266189)]
public void should_be_able_to_get_series_detail(int tvdbId) public void should_be_able_to_get_series_detail(int tvdbId)
{ {
var details = Subject.GetSeriesInfo(tvdbId); var details = Subject.GetSeriesInfo(tvdbId);
@ -69,6 +70,7 @@ namespace NzbDrone.Core.Test.MetadataSourceTests
series.Should().NotBeNull(); series.Should().NotBeNull();
series.Title.Should().NotBeBlank(); series.Title.Should().NotBeBlank();
series.CleanTitle.Should().Be(Parser.Parser.CleanSeriesTitle(series.Title)); series.CleanTitle.Should().Be(Parser.Parser.CleanSeriesTitle(series.Title));
series.SortTitle.Should().Be(Parser.Parser.NormalizeEpisodeTitle(series.Title));
series.Overview.Should().NotBeBlank(); series.Overview.Should().NotBeBlank();
series.AirTime.Should().NotBeBlank(); series.AirTime.Should().NotBeBlank();
series.FirstAired.Should().HaveValue(); series.FirstAired.Should().HaveValue();

@ -39,6 +39,11 @@ namespace NzbDrone.Core.Test.SeriesStatsTests
_episode.EpisodeFileId = 1; _episode.EpisodeFileId = 1;
} }
private void GivenOldEpisode()
{
_episode.AirDateUtc = DateTime.Now.AddSeconds(-10);
}
private void GivenMonitoredEpisode() private void GivenMonitoredEpisode()
{ {
_episode.Monitored = true; _episode.Monitored = true;
@ -59,6 +64,7 @@ namespace NzbDrone.Core.Test.SeriesStatsTests
stats.Should().HaveCount(1); stats.Should().HaveCount(1);
stats.First().NextAiring.Should().Be(_episode.AirDateUtc); stats.First().NextAiring.Should().Be(_episode.AirDateUtc);
stats.First().PreviousAiring.Should().NotHaveValue();
} }
[Test] [Test]
@ -73,6 +79,47 @@ namespace NzbDrone.Core.Test.SeriesStatsTests
stats.First().NextAiring.Should().NotHaveValue(); stats.First().NextAiring.Should().NotHaveValue();
} }
[Test]
public void should_have_previous_airing_for_old_episode_with_file()
{
GivenEpisodeWithFile();
GivenOldEpisode();
GivenFile();
var stats = Subject.SeriesStatistics();
stats.Should().HaveCount(1);
stats.First().NextAiring.Should().NotHaveValue();
stats.First().PreviousAiring.Should().Be(_episode.AirDateUtc);
}
[Test]
public void should_have_previous_airing_for_old_episode_without_file_monitored()
{
GivenMonitoredEpisode();
GivenOldEpisode();
GivenFile();
var stats = Subject.SeriesStatistics();
stats.Should().HaveCount(1);
stats.First().NextAiring.Should().NotHaveValue();
stats.First().PreviousAiring.Should().Be(_episode.AirDateUtc);
}
[Test]
public void should_not_have_previous_airing_for_old_episode_without_file_unmonitored()
{
GivenOldEpisode();
GivenFile();
var stats = Subject.SeriesStatistics();
stats.Should().HaveCount(1);
stats.First().NextAiring.Should().NotHaveValue();
stats.First().PreviousAiring.Should().NotHaveValue();
}
[Test] [Test]
public void should_not_include_unmonitored_episode_in_episode_count() public void should_not_include_unmonitored_episode_in_episode_count()
{ {

@ -0,0 +1,53 @@
using System;
using System.IO;
using System.Data;
using System.Linq;
using System.Collections.Generic;
using FluentMigrator;
using Newtonsoft.Json;
using NzbDrone.Common;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(53)]
public class add_series_sorttitle : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Create.Column("SortTitle").OnTable("Series").AsString().Nullable();
Execute.WithConnection(SetSortTitles);
}
private void SetSortTitles(IDbConnection conn, IDbTransaction tran)
{
using (IDbCommand getSeriesCmd = conn.CreateCommand())
{
getSeriesCmd.Transaction = tran;
getSeriesCmd.CommandText = @"SELECT Id, Title FROM Series";
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
{
while (seriesReader.Read())
{
var id = seriesReader.GetInt32(0);
var title = seriesReader.GetString(1);
var sortTitle = Parser.Parser.NormalizeEpisodeTitle(title).ToLower();
using (IDbCommand updateCmd = conn.CreateCommand())
{
updateCmd.Transaction = tran;
updateCmd.CommandText = "UPDATE Series SET SortTitle = ? WHERE Id = ?";
updateCmd.AddParameter(sortTitle);
updateCmd.AddParameter(id);
updateCmd.ExecuteNonQuery();
}
}
}
}
}
}
}

@ -105,6 +105,7 @@ namespace NzbDrone.Core.MetadataSource
series.ImdbId = show.imdb_id; series.ImdbId = show.imdb_id;
series.Title = show.title; series.Title = show.title;
series.CleanTitle = Parser.Parser.CleanSeriesTitle(show.title); series.CleanTitle = Parser.Parser.CleanSeriesTitle(show.title);
series.SortTitle = Parser.Parser.NormalizeEpisodeTitle(show.title).ToLower();
series.Year = GetYear(show.year, show.first_aired); series.Year = GetYear(show.year, show.first_aired);
series.FirstAired = FromIso(show.first_aired_iso); series.FirstAired = FromIso(show.first_aired_iso);
series.Overview = show.overview; series.Overview = show.overview;

@ -201,6 +201,7 @@
<Compile Include="Datastore\Migration\050_add_hash_to_metadata_files.cs" /> <Compile Include="Datastore\Migration\050_add_hash_to_metadata_files.cs" />
<Compile Include="Datastore\Migration\051_download_client_import.cs" /> <Compile Include="Datastore\Migration\051_download_client_import.cs" />
<Compile Include="Datastore\Migration\052_add_columns_for_anime.cs" /> <Compile Include="Datastore\Migration\052_add_columns_for_anime.cs" />
<Compile Include="Datastore\Migration\053_add_series_sorttitle.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" /> <Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" /> <Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" /> <Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />

@ -7,6 +7,7 @@ namespace NzbDrone.Core.SeriesStats
{ {
public int SeriesId { get; set; } public int SeriesId { get; set; }
public string NextAiringString { get; set; } public string NextAiringString { get; set; }
public string PreviousAiringString { get; set; }
public int EpisodeFileCount { get; set; } public int EpisodeFileCount { get; set; }
public int EpisodeCount { get; set; } public int EpisodeCount { get; set; }
@ -21,5 +22,17 @@ namespace NzbDrone.Core.SeriesStats
return nextAiring; return nextAiring;
} }
} }
public DateTime? PreviousAiring
{
get
{
DateTime previousAiring;
if (!DateTime.TryParse(PreviousAiringString, out previousAiring)) return null;
return previousAiring;
}
}
} }
} }

@ -56,7 +56,8 @@ namespace NzbDrone.Core.SeriesStats
SeriesId, SeriesId,
SUM(CASE WHEN (Monitored = 1 AND AirdateUtc <= @currentDate) OR EpisodeFileId > 0 THEN 1 ELSE 0 END) AS EpisodeCount, SUM(CASE WHEN (Monitored = 1 AND AirdateUtc <= @currentDate) OR EpisodeFileId > 0 THEN 1 ELSE 0 END) AS EpisodeCount,
SUM(CASE WHEN EpisodeFileId > 0 THEN 1 ELSE 0 END) AS EpisodeFileCount, SUM(CASE WHEN EpisodeFileId > 0 THEN 1 ELSE 0 END) AS EpisodeFileCount,
MIN(CASE WHEN AirDateUtc < @currentDate OR EpisodeFileId > 0 OR Monitored = 0 THEN NULL ELSE AirDateUtc END) AS NextAiringString MIN(CASE WHEN AirDateUtc < @currentDate OR EpisodeFileId > 0 OR Monitored = 0 THEN NULL ELSE AirDateUtc END) AS NextAiringString,
MAX(CASE WHEN AirDateUtc >= @currentDate OR EpisodeFileId = 0 AND Monitored = 0 THEN NULL ELSE AirDateUtc END) AS PreviousAiringString
FROM Episodes"; FROM Episodes";
} }

@ -59,6 +59,7 @@ namespace NzbDrone.Core.Tv
series.Overview = seriesInfo.Overview; series.Overview = seriesInfo.Overview;
series.Status = seriesInfo.Status; series.Status = seriesInfo.Status;
series.CleanTitle = seriesInfo.CleanTitle; series.CleanTitle = seriesInfo.CleanTitle;
series.SortTitle = seriesInfo.SortTitle;
series.LastInfoSync = DateTime.UtcNow; series.LastInfoSync = DateTime.UtcNow;
series.Runtime = seriesInfo.Runtime; series.Runtime = seriesInfo.Runtime;
series.Images = seriesInfo.Images; series.Images = seriesInfo.Images;

@ -22,6 +22,7 @@ namespace NzbDrone.Core.Tv
public string ImdbId { get; set; } public string ImdbId { get; set; }
public string Title { get; set; } public string Title { get; set; }
public string CleanTitle { get; set; } public string CleanTitle { get; set; }
public string SortTitle { get; set; }
public SeriesStatusType Status { get; set; } public SeriesStatusType Status { get; set; }
public string Overview { get; set; } public string Overview { get; set; }
public String AirTime { get; set; } public String AirTime { get; set; }

@ -79,6 +79,7 @@ namespace NzbDrone.Core.Tv
newSeries.Monitored = true; newSeries.Monitored = true;
newSeries.CleanTitle = newSeries.Title.CleanSeriesTitle(); newSeries.CleanTitle = newSeries.Title.CleanSeriesTitle();
newSeries.SortTitle = Parser.Parser.NormalizeEpisodeTitle(newSeries.Title).ToLower();
_seriesRepository.Insert(newSeries); _seriesRepository.Insert(newSeries);
_eventAggregator.PublishEvent(new SeriesAddedEvent(GetSeries(newSeries.Id))); _eventAggregator.PublishEvent(new SeriesAddedEvent(GetSeries(newSeries.Id)));

@ -35,33 +35,33 @@ define(
columns: columns:
[ [
{ {
name : 'series', name : 'series',
label: 'Series', label : 'Series',
cell : SeriesTitleCell, cell : SeriesTitleCell,
sortValue: 'series.title' sortValue : 'series.sortTitle'
}, },
{ {
name : 'sourceTitle', name : 'sourceTitle',
label: 'Source Title', label : 'Source Title',
cell : 'string', cell : 'string',
sortValue: 'sourceTitle' sortValue : 'sourceTitle'
}, },
{ {
name : 'quality', name : 'quality',
label : 'Quality', label : 'Quality',
cell : QualityCell, cell : QualityCell,
sortable: false sortable : false
}, },
{ {
name : 'date', name : 'date',
label: 'Date', label : 'Date',
cell : RelativeDateCell cell : RelativeDateCell
}, },
{ {
name : 'this', name : 'this',
label : '', label : '',
cell : BlacklistActionsCell, cell : BlacklistActionsCell,
sortable: false sortable : false
} }
], ],

@ -32,33 +32,34 @@ define(
columns: columns:
[ [
{ {
name : 'status', name : 'status',
label: '', label : '',
cell : QueueStatusCell, cell : QueueStatusCell,
cellValue: 'this' cellValue : 'this'
}, },
{ {
name : 'series', name : 'series',
label: 'Series', label : 'Series',
cell : SeriesTitleCell cell : SeriesTitleCell,
sortable : false
}, },
{ {
name : 'episode', name : 'episode',
label : 'Episode', label : 'Episode',
sortable: false, cell : EpisodeNumberCell,
cell : EpisodeNumberCell sortable : false
}, },
{ {
name : 'episode', name : 'episode',
label : 'Episode Title', label : 'Episode Title',
sortable: false, cell : EpisodeTitleCell,
cell : EpisodeTitleCell sortable : false
}, },
{ {
name : 'quality', name : 'quality',
label : 'Quality', label : 'Quality',
cell : QualityCell, cell : QualityCell,
sortable: false sortable : false
}, },
{ {
name : 'timeleft', name : 'timeleft',

@ -39,45 +39,45 @@ define(
columns: columns:
[ [
{ {
name : 'eventType', name : 'eventType',
label : '', label : '',
cell : EventTypeCell, cell : EventTypeCell,
cellValue: 'this' cellValue : 'this'
}, },
{ {
name : 'series', name : 'series',
label: 'Series', label : 'Series',
cell : SeriesTitleCell, cell : SeriesTitleCell,
sortValue: 'series.title' sortValue : 'series.sortTitle'
}, },
{ {
name : 'episode', name : 'episode',
label : 'Episode', label : 'Episode',
sortable: false, cell : EpisodeNumberCell,
cell : EpisodeNumberCell sortable : false
}, },
{ {
name : 'episode', name : 'episode',
label : 'Episode Title', label : 'Episode Title',
sortable: false, cell : EpisodeTitleCell,
cell : EpisodeTitleCell sortable : false
}, },
{ {
name : 'quality', name : 'quality',
label : 'Quality', label : 'Quality',
cell : QualityCell, cell : QualityCell,
sortable: false sortable : false
}, },
{ {
name : 'date', name : 'date',
label: 'Date', label : 'Date',
cell : RelativeDateCell cell : RelativeDateCell
}, },
{ {
name : 'this', name : 'this',
label : '', label : '',
cell : HistoryDetailsCell, cell : HistoryDetailsCell,
sortable: false sortable : false
} }
], ],

@ -57,25 +57,26 @@ define(
cell : SeriesStatusCell cell : SeriesStatusCell
}, },
{ {
name : 'title', name : 'title',
label : 'Title', label : 'Title',
cell : SeriesTitleCell, cell : SeriesTitleCell,
cellValue: 'this' cellValue : 'this',
sortValue : 'sortTitle'
}, },
{ {
name : 'qualityProfileId', name : 'qualityProfileId',
label: 'Quality', label : 'Quality',
cell : QualityProfileCell cell : QualityProfileCell
}, },
{ {
name : 'seasonFolder', name : 'seasonFolder',
label: 'Season Folder', label : 'Season Folder',
cell : SeasonFolderCell cell : SeasonFolderCell
}, },
{ {
name : 'path', name : 'path',
label: 'Path', label : 'Path',
cell : 'string' cell : 'string'
} }
], ],

@ -53,25 +53,26 @@ define(
cell : SeriesStatusCell cell : SeriesStatusCell
}, },
{ {
name : 'title', name : 'title',
label : 'Title', label : 'Title',
cell : SeriesTitleCell, cell : SeriesTitleCell,
cellValue: 'this' cellValue : 'this',
sortValue : 'sortTitle'
}, },
{ {
name : 'seasonCount', name : 'seasonCount',
label: 'Seasons', label : 'Seasons',
cell : 'integer' cell : 'integer'
}, },
{ {
name : 'qualityProfileId', name : 'qualityProfileId',
label: 'Quality', label : 'Quality',
cell : QualityProfileCell cell : QualityProfileCell
}, },
{ {
name : 'network', name : 'network',
label: 'Network', label : 'Network',
cell : 'string' cell : 'string'
}, },
{ {
name : 'nextAiring', name : 'nextAiring',
@ -80,16 +81,16 @@ define(
sortValue : SeriesCollection.nextAiring sortValue : SeriesCollection.nextAiring
}, },
{ {
name : 'percentOfEpisodes', name : 'percentOfEpisodes',
label : 'Episodes', label : 'Episodes',
cell : EpisodeProgressCell, cell : EpisodeProgressCell,
className: 'episode-progress-cell' className : 'episode-progress-cell'
}, },
{ {
name : 'this', name : 'this',
label : '', label : '',
sortable: false, sortable : false,
cell : SeriesActionsCell cell : SeriesActionsCell
} }
], ],

@ -59,12 +59,18 @@ define(
//Sorters //Sorters
nextAiring: function (model, attr) { nextAiring: function (model, attr) {
var nextAiring = model.get(attr); var nextAiring = model.get(attr);
if (!nextAiring) { if (nextAiring) {
return Number.MAX_VALUE; return Moment(nextAiring).unix();
}
var previousAiring = model.get(attr.replace('nextAiring', 'previousAiring'));
if (previousAiring) {
return 10000000000 - Moment(previousAiring).unix();
} }
return Moment(nextAiring).unix(); return Number.MAX_VALUE;
} }
}); });

@ -45,39 +45,39 @@ define([
columns : [ columns : [
{ {
name : '', name : '',
cell : 'select-row', cell : 'select-row',
headerCell : 'select-all', headerCell: 'select-all',
sortable : false sortable : false
}, },
{ {
name : 'series', name : 'series',
label : 'Series Title', label : 'Series Title',
sortable : false, cell : SeriesTitleCell,
cell : SeriesTitleCell sortValue : 'series.sortTitle'
}, },
{ {
name : 'this', name : 'this',
label : 'Episode', label : 'Episode',
sortable : false, cell : EpisodeNumberCell,
cell : EpisodeNumberCell sortable : false
}, },
{ {
name : 'this', name : 'this',
label : 'Episode Title', label : 'Episode Title',
sortable : false, cell : EpisodeTitleCell,
cell : EpisodeTitleCell sortable : false
}, },
{ {
name : 'airDateUtc', name : 'airDateUtc',
label : 'Air Date', label : 'Air Date',
cell : RelativeDateCell cell : RelativeDateCell
}, },
{ {
name : 'status', name : 'status',
label : 'Status', label : 'Status',
cell : EpisodeStatusCell, cell : EpisodeStatusCell,
sortable : false sortable : false
} }
], ],

@ -45,39 +45,39 @@ define([
columns : [ columns : [
{ {
name : '', name : '',
cell : 'select-row', cell : 'select-row',
headerCell : 'select-all', headerCell: 'select-all',
sortable : false sortable : false
}, },
{ {
name : 'series', name : 'series',
label : 'Series Title', label : 'Series Title',
sortable : false, cell : SeriesTitleCell,
cell : SeriesTitleCell sortValue : 'series.sortTitle'
}, },
{ {
name : 'this', name : 'this',
label : 'Episode', label : 'Episode',
sortable : false, cell : EpisodeNumberCell,
cell : EpisodeNumberCell sortable : false
}, },
{ {
name : 'this', name : 'this',
label : 'Episode Title', label : 'Episode Title',
sortable : false, cell : EpisodeTitleCell,
cell : EpisodeTitleCell sortable : false
}, },
{ {
name : 'airDateUtc', name : 'airDateUtc',
label : 'Air Date', label : 'Air Date',
cell : RelativeDateCell cell : RelativeDateCell
}, },
{ {
name : 'status', name : 'status',
label : 'Status', label : 'Status',
cell : EpisodeStatusCell, cell : EpisodeStatusCell,
sortable : false sortable : false
} }
], ],

Loading…
Cancel
Save