diff --git a/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs b/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs index 50831a45c..2d5c19f0f 100644 --- a/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs +++ b/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs @@ -40,7 +40,6 @@ namespace NzbDrone.Api.Test.MappingTests [TestCase(typeof(DownloadDecision), typeof(ReleaseResource))] [TestCase(typeof(Core.History.History), typeof(HistoryResource))] [TestCase(typeof(UpdatePackage), typeof(UpdateResource))] - [TestCase(typeof(QualityProfile), typeof(QualityProfileResource))] [TestCase(typeof(Quality), typeof(QualityResource))] [TestCase(typeof(Log), typeof(LogResource))] public void matching_fields(Type modelType, Type resourceType) diff --git a/NzbDrone.Api/Indexers/ReleaseResource.cs b/NzbDrone.Api/Indexers/ReleaseResource.cs index fbe121cbb..2ddac98f3 100644 --- a/NzbDrone.Api/Indexers/ReleaseResource.cs +++ b/NzbDrone.Api/Indexers/ReleaseResource.cs @@ -2,11 +2,13 @@ using System.Collections.Generic; using NzbDrone.Api.REST; using NzbDrone.Core.Parser; +using NzbDrone.Core.Tv; namespace NzbDrone.Api.Indexers { public class ReleaseResource : RestResource { + public QualityModel Quality { get; set; } public Int32 Age { get; set; } public Int64 Size { get; set; } public String Indexer { get; set; } diff --git a/NzbDrone.Api/Mapping/MappingValidation.cs b/NzbDrone.Api/Mapping/MappingValidation.cs index 00cf1f681..13e657b13 100644 --- a/NzbDrone.Api/Mapping/MappingValidation.cs +++ b/NzbDrone.Api/Mapping/MappingValidation.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Reflection; using NzbDrone.Api.REST; using NzbDrone.Common.Reflection; -using NzbDrone.Core.Datastore; namespace NzbDrone.Api.Mapping { @@ -11,7 +10,7 @@ namespace NzbDrone.Api.Mapping { public static void ValidateMapping(Type modelType, Type resourceType) { - var errors = modelType.GetSimpleProperties().Select(p => GetError(resourceType, p)).Where(c => c != null).ToList(); + var errors = modelType.GetSimpleProperties().Where(c=>!c.GetGetMethod().IsStatic).Select(p => GetError(resourceType, p)).Where(c => c != null).ToList(); if (errors.Any()) { @@ -48,9 +47,9 @@ namespace NzbDrone.Api.Mapping return string.Format("public {0} {1} {{ get; set; }}", modelProperty.PropertyType.Name, modelProperty.Name); } - if (resourceProperty.PropertyType != modelProperty.PropertyType) + if (resourceProperty.PropertyType != modelProperty.PropertyType && !typeof(RestResource).IsAssignableFrom(resourceProperty.PropertyType)) { - return string.Format("Excpected {0}.{1} to have type of {2} but found {3}", resourceType.Name, resourceProperty.Name, modelProperty.PropertyType, resourceProperty.PropertyType); + return string.Format("Expected {0}.{1} to have type of {2} but found {3}", resourceType.Name, resourceProperty.Name, modelProperty.PropertyType, resourceProperty.PropertyType); } return null; diff --git a/NzbDrone.Common/Reflection/ReflectionExtensions.cs b/NzbDrone.Common/Reflection/ReflectionExtensions.cs index 98ff9ff12..c04da73fc 100644 --- a/NzbDrone.Common/Reflection/ReflectionExtensions.cs +++ b/NzbDrone.Common/Reflection/ReflectionExtensions.cs @@ -33,7 +33,8 @@ namespace NzbDrone.Common.Reflection || type == typeof(string) || type == typeof(DateTime) || type == typeof(Version) - || type == typeof(Decimal); + || type == typeof(Decimal) + || type.GetInterface("IEmbeddedDocument") != null; } public static bool IsReadable(this PropertyInfo propertyInfo) diff --git a/NzbDrone.ncrunchsolution b/NzbDrone.ncrunchsolution index 969da6dd4..444b34b1d 100644 --- a/NzbDrone.ncrunchsolution +++ b/NzbDrone.ncrunchsolution @@ -1,6 +1,6 @@ 1 - True + False true true UseDynamicAnalysis diff --git a/UI/.idea/dictionaries/Keivan.xml b/UI/.idea/dictionaries/Keivan.xml index 6089d177c..a57f1692c 100644 --- a/UI/.idea/dictionaries/Keivan.xml +++ b/UI/.idea/dictionaries/Keivan.xml @@ -8,6 +8,7 @@ rootfolder rootfolders signalr + templated thetvdb trakt tvdb diff --git a/UI/Cells/AirDateCell.js b/UI/Cells/AirDateCell.js new file mode 100644 index 000000000..702afbb7c --- /dev/null +++ b/UI/Cells/AirDateCell.js @@ -0,0 +1,15 @@ +"use strict"; +define(['app', 'Shared/FormatHelpers'], function () { + NzbDrone.Cells.AirDateCell = Backgrid.Cell.extend({ + className: "air-date-cell", + + render: function () { + + this.$el.empty(); + var airDate = this.model.get(this.column.get("name")); + this.$el.html(NzbDrone.Shared.FormatHelpers.DateHelper(airDate)); + return this; + + } + }); +}); diff --git a/UI/Cells/EpisodeNumberCell.js b/UI/Cells/EpisodeNumberCell.js new file mode 100644 index 000000000..6e20c1cd0 --- /dev/null +++ b/UI/Cells/EpisodeNumberCell.js @@ -0,0 +1,34 @@ +"use strict"; + +define(['app', 'Cells/NzbDroneCell'], function () { + NzbDrone.Cells.EpisodeNumberCell = NzbDrone.Cells.NzbDroneCell.extend({ + + className: "episode-number-cell", + + render: function () { + + var airDate = this.cellValue.get('airDate') || this.get(this.column.get("airDate")); + var seasonNumber = this.cellValue.get('seasonNumber') || this.model.get(this.column.get("seasonNumber")); + var episodes = this.cellValue.get('episodeNumber') || this.model.get(this.column.get("episodes")); + + var result = 'Unknown'; + + if (airDate) { + + result = new Date(airDate).toLocaleDateString(); + } + else { + + var paddedEpisodes = _.map(episodes, function (episodeNumber) { + return episodeNumber.pad(2); + }); + + result = 'S{0}-E{1}'.format(seasonNumber, paddedEpisodes.join()); + } + + this.$el.html(result); + this.delegateEvents(); + return this; + } + }); +}); diff --git a/UI/Series/Details/EpisodeStatusCell.js b/UI/Cells/EpisodeStatusCell.js similarity index 85% rename from UI/Series/Details/EpisodeStatusCell.js rename to UI/Cells/EpisodeStatusCell.js index 478326345..4401eeb4c 100644 --- a/UI/Series/Details/EpisodeStatusCell.js +++ b/UI/Cells/EpisodeStatusCell.js @@ -1,7 +1,7 @@ "use strict"; -define(['app', 'Episode/Layout'], function () { - NzbDrone.Series.Details.EpisodeStatusCell = Backgrid.Cell.extend({ +define(['app' ], function () { + NzbDrone.Cells.EpisodeStatusCell = Backgrid.Cell.extend({ className: 'episode-status-cell', diff --git a/UI/Series/Details/EpisodeTitleCell.js b/UI/Cells/EpisodeTitleCell.js similarity index 52% rename from UI/Series/Details/EpisodeTitleCell.js rename to UI/Cells/EpisodeTitleCell.js index 5e2983ee8..0d2731a9a 100644 --- a/UI/Series/Details/EpisodeTitleCell.js +++ b/UI/Cells/EpisodeTitleCell.js @@ -1,7 +1,7 @@ "use strict"; -define(['app', 'Episode/Layout'], function () { - NzbDrone.Series.Details.EpisodeTitleCell = Backgrid.StringCell.extend({ +define(['app', 'Cells/NzbDroneCell'], function () { + NzbDrone.Cells.EpisodeTitleCell = NzbDrone.Cells.NzbDroneCell.extend({ className: 'episode-title-cell', @@ -10,8 +10,13 @@ define(['app', 'Episode/Layout'], function () { }, showDetails: function () { - var view = new NzbDrone.Episode.Layout({ model: this.model }); + var view = new NzbDrone.Episode.Layout({ model: this.cellValue }); NzbDrone.modalRegion.show(view); + }, + + render: function () { + this.$el.html(this.cellValue.get('title')); + return this; } }); }); diff --git a/UI/Cells/FileSizeCell.js b/UI/Cells/FileSizeCell.js new file mode 100644 index 000000000..b80ec579d --- /dev/null +++ b/UI/Cells/FileSizeCell.js @@ -0,0 +1,15 @@ +"use strict"; + +define(['app', 'Shared/FormatHelpers'], function () { + NzbDrone.Cells.FileSizeCell = Backgrid.Cell.extend({ + + className: "file-size-cell", + + render: function () { + var size = this.model.get(this.column.get("name")); + this.$el.html(NzbDrone.Shared.FormatHelpers.FileSizeHelper(size)); + this.delegateEvents(); + return this; + } + }); +}); diff --git a/UI/Cells/IndexerCell.js b/UI/Cells/IndexerCell.js new file mode 100644 index 000000000..485e32fd3 --- /dev/null +++ b/UI/Cells/IndexerCell.js @@ -0,0 +1,13 @@ +"use strict"; +define(['app'], function () { + NzbDrone.Cells.IndexerCell = Backgrid.Cell.extend({ + + class : 'indexer-cell', + + render: function () { + var indexer = this.model.get(this.column.get('name')); + this.$el.html(indexer); + return this; + } + }); +}); diff --git a/UI/Cells/NzbDroneCell.js b/UI/Cells/NzbDroneCell.js new file mode 100644 index 000000000..3decea035 --- /dev/null +++ b/UI/Cells/NzbDroneCell.js @@ -0,0 +1,40 @@ +"use strict"; + +define(['app'], function () { + NzbDrone.Cells.NzbDroneCell = Backgrid.Cell.extend({ + + _originalInit: Backgrid.Cell.prototype.initialize, + + + initialize: function () { + this._originalInit.apply(this, arguments); + this.cellValue = this._getValue(); + + this.model.on('change', this._refresh, this); + }, + + _refresh: function () { + this.cellValue = this._getValue(); + this.render(); + }, + + _getValue: function () { + + var name = this.column.get('name'); + + if(name === 'this'){ + return this.model; + } + + var value = this.model.get(name); + + //if not a model + if (!value.get) { + return value = new Backbone.Model(value); + } + + return value; + } + + }); +}); diff --git a/UI/Cells/QualityCell.js b/UI/Cells/QualityCell.js new file mode 100644 index 000000000..cbc2c74c7 --- /dev/null +++ b/UI/Cells/QualityCell.js @@ -0,0 +1,9 @@ +"use strict"; +define(['app', 'Cells/TemplatedCell'], function () { + NzbDrone.Cells.QualityCell = NzbDrone.Cells.TemplatedCell.extend({ + + className: 'quality-cell', + template : 'Cells/QualityTemplate' + + }); +}); diff --git a/UI/History/QualityTemplate.html b/UI/Cells/QualityTemplate.html similarity index 100% rename from UI/History/QualityTemplate.html rename to UI/Cells/QualityTemplate.html diff --git a/UI/Cells/RelativeDateCell.js b/UI/Cells/RelativeDateCell.js new file mode 100644 index 000000000..6db0cc95c --- /dev/null +++ b/UI/Cells/RelativeDateCell.js @@ -0,0 +1,13 @@ +"use strict"; +define(['app'], function () { + NzbDrone.Cells.RelativeDateCell = Backgrid.Cell.extend({ + + render: function () { + + var date = this.model.get(this.column.get('name')); + this.$el.html(Date.create(date).relative()); + + return this; + } + }); +}); diff --git a/UI/Cells/SeriesTitleCell.js b/UI/Cells/SeriesTitleCell.js new file mode 100644 index 000000000..8d86eb5e1 --- /dev/null +++ b/UI/Cells/SeriesTitleCell.js @@ -0,0 +1,9 @@ +"use strict"; +define(['app', 'Cells/TemplatedCell'], function () { + NzbDrone.Cells.SeriesTitleCell = NzbDrone.Cells.TemplatedCell.extend({ + + className: 'series-title', + template : 'Cells/SeriesTitleTemplate' + + }); +}); diff --git a/UI/Cells/SeriesTitleTemplate.html b/UI/Cells/SeriesTitleTemplate.html new file mode 100644 index 000000000..4b65dc63a --- /dev/null +++ b/UI/Cells/SeriesTitleTemplate.html @@ -0,0 +1,2 @@ +{{title}} +{{debug}} diff --git a/UI/Cells/TemplatedCell.js b/UI/Cells/TemplatedCell.js new file mode 100644 index 000000000..d7ccd820f --- /dev/null +++ b/UI/Cells/TemplatedCell.js @@ -0,0 +1,19 @@ +"use strict"; + +define(['app','Cells/NzbDroneCell'], function () { + NzbDrone.Cells.TemplatedCell = NzbDrone.Cells.NzbDroneCell.extend({ + + + render: function () { + + var templateName = this.column.get('template') || this.template; + + this.templateFunction = Marionette.TemplateCache.get(templateName); + var data = this.cellValue.toJSON(); + var html = this.templateFunction(data); + this.$el.html(html); + + return this; + } + }); +}); diff --git a/UI/Shared/Cells/ToggleCell.js b/UI/Cells/ToggleCell.js similarity index 92% rename from UI/Shared/Cells/ToggleCell.js rename to UI/Cells/ToggleCell.js index d0c60aeba..4c8b8ce65 100644 --- a/UI/Shared/Cells/ToggleCell.js +++ b/UI/Cells/ToggleCell.js @@ -1,7 +1,7 @@ "use strict"; define(['app', 'Episode/Layout'], function () { - NzbDrone.Shared.Cells.ToggleCell = Backgrid.Cell.extend({ + NzbDrone.Cells.ToggleCell = Backgrid.Cell.extend({ className: 'toggle-cell clickable', diff --git a/UI/Cells/cells.less b/UI/Cells/cells.less new file mode 100644 index 000000000..1bf0b98a1 --- /dev/null +++ b/UI/Cells/cells.less @@ -0,0 +1,7 @@ +@import "../content/Bootstrap/mixins"; +@import "../content/Bootstrap/variables"; +@import "../content/Bootstrap/buttons"; + +.episode-title-cell { + .btn-link; +} diff --git a/UI/Episode/Search/Layout.js b/UI/Episode/Search/Layout.js index cb4cf9fac..a129f093e 100644 --- a/UI/Episode/Search/Layout.js +++ b/UI/Episode/Search/Layout.js @@ -1,5 +1,5 @@ "use strict"; -define(['app', 'Shared/Cells/FileSizeCell', 'Shared/Cells/ApprovalStatusCell'], function () { +define(['app', 'Cells/FileSizeCell', 'Release/ApprovalStatusCell', 'Release/DownloadReportCell' ], function () { NzbDrone.Episode.Search.Layout = Backbone.Marionette.Layout.extend({ template: 'Episode/Search/LayoutTemplate', @@ -19,7 +19,7 @@ define(['app', 'Shared/Cells/FileSizeCell', 'Shared/Cells/ApprovalStatusCell'], name : 'size', label : 'Size', sortable: true, - cell : NzbDrone.Shared.Cells.FileSizeCell + cell : NzbDrone.Cells.FileSizeCell }, { name : 'title', @@ -30,7 +30,12 @@ define(['app', 'Shared/Cells/FileSizeCell', 'Shared/Cells/ApprovalStatusCell'], { name : 'rejections', label: 'decision', - cell : NzbDrone.Shared.Cells.ApprovalStatusCell + cell : NzbDrone.Release.ApprovalStatusCell + }, + { + name : 'download', + label: '', + cell : NzbDrone.Release.DownloadReportCell } ], diff --git a/UI/History/EpisodeTitleTemplate.html b/UI/History/EpisodeTitleTemplate.html deleted file mode 100644 index 616580cbe..000000000 --- a/UI/History/EpisodeTitleTemplate.html +++ /dev/null @@ -1 +0,0 @@ -{{episode.title}} \ No newline at end of file diff --git a/UI/History/HistoryLayout.js b/UI/History/HistoryLayout.js index 66ec7c34d..2610a2b06 100644 --- a/UI/History/HistoryLayout.js +++ b/UI/History/HistoryLayout.js @@ -2,7 +2,13 @@ define([ 'app', 'History/Collection', - 'Series/Index/Table/AirDateCell', + 'Cells/RelativeDateCell', + 'Cells/IndexerCell', + 'Cells/TemplatedCell', + 'Cells/SeriesTitleCell', + 'Cells/EpisodeNumberCell', + 'Cells/EpisodeTitleCell', + 'Cells/QualityCell', 'Shared/Toolbar/ToolbarLayout', 'Shared/LoadingView' ], @@ -18,42 +24,36 @@ define([ columns: [ { - name : 'indexer', - label : '', - cell : Backgrid.TemplateBackedCell.extend({ template: 'History/IndexerTemplate' }) + name : 'indexer', + label: '', + cell : NzbDrone.Cells.IndexerCell }, { - name : 'Series.Title', - label : 'Series Title', - cell : Backgrid.TemplateBackedCell.extend({ template: 'Missing/SeriesTitleTemplate' }) + name : 'series', + label : 'Series', + cell : NzbDrone.Cells.SeriesTitleCell }, { - name : 'episode', - label : 'Episode', - sortable : false, - cell : Backgrid.TemplateBackedCell.extend({ template: 'Missing/EpisodeColumnTemplate' }) + name : 'episode', + label : 'Episode', + sortable: false, + cell : NzbDrone.Cells.EpisodeNumberCell }, { - name : 'Episode.Title', - label : 'Episode Title', - sortable : false, - cell : Backgrid.TemplateBackedCell.extend({ template: 'History/EpisodeTitleTemplate' }) + name : 'episode', + label : 'Episode Title', + sortable: false, + cell : NzbDrone.Cells.EpisodeTitleCell }, { - name : 'quality', - label : 'Quality', - cell : Backgrid.TemplateBackedCell.extend({ template: 'History/QualityTemplate' }) + name : 'quality', + label: 'Quality', + cell : NzbDrone.Cells.QualityCell }, { - name : 'date', - label : 'Grabbed', - cell : 'airDate' - }, - { - name : 'edit', - label : '', - sortable : false, - cell : Backgrid.TemplateBackedCell.extend({ template: 'History/ControlsColumnTemplate' }) + name : 'date', + label: 'Date', + cell : NzbDrone.Cells.RelativeDateCell } ], @@ -68,7 +68,7 @@ define([ })); this.pager.show(new Backgrid.NzbDronePaginator({ - columns: this.columns, + columns : this.columns, collection: this.historyCollection })); }, @@ -80,9 +80,9 @@ define([ this.historyCollection = new NzbDrone.History.Collection(); this.historyCollection.fetch() - .done(function () { - self._showTable(); - }); + .done(function () { + self._showTable(); + }); //this.toolbar.show(new NzbDrone.Shared.Toolbar.ToolbarLayout({right: [ viewButtons], context: this})); } diff --git a/UI/History/Model.js b/UI/History/Model.js index 8931767d8..3db750b81 100644 --- a/UI/History/Model.js +++ b/UI/History/Model.js @@ -1,5 +1,5 @@ "use strict"; -define(['app'], function (app) { +define(['app','Series/SeriesModel', 'Series/EpisodeModel'], function () { NzbDrone.History.Model = Backbone.Model.extend({ mutators: { seasonNumber: function () { @@ -9,6 +9,14 @@ define(['app'], function (app) { paddedEpisodeNumber: function () { return this.get('episode').episodeNumber.pad(2); } + }, + + parse: function (model) { + model.series = new NzbDrone.Series.SeriesModel(model.series); + model.episode = new NzbDrone.Series.EpisodeModel(model.episode); + return model; } + + }); }); diff --git a/UI/Index.html b/UI/Index.html index 8b507f8b3..b6710d195 100644 --- a/UI/Index.html +++ b/UI/Index.html @@ -9,6 +9,7 @@ + @@ -84,7 +85,6 @@ - diff --git a/UI/Missing/EpisodeColumnTemplate.html b/UI/Missing/EpisodeColumnTemplate.html deleted file mode 100644 index 30ab0a188..000000000 --- a/UI/Missing/EpisodeColumnTemplate.html +++ /dev/null @@ -1,2 +0,0 @@ - -{{seasonNumber}}x{{paddedEpisodeNumber}} \ No newline at end of file diff --git a/UI/Missing/MissingLayout.js b/UI/Missing/MissingLayout.js index 6a1411400..fdd4e32d8 100644 --- a/UI/Missing/MissingLayout.js +++ b/UI/Missing/MissingLayout.js @@ -2,9 +2,14 @@ define([ 'app', 'Missing/Collection', - 'Series/Index/Table/AirDateCell', + 'Missing/Row', + 'Cells/AirDateCell', 'Series/Index/Table/SeriesStatusCell', 'Shared/Toolbar/ToolbarLayout', + 'Cells/SeriesTitleCell', + 'Cells/EpisodeNumberCell', + 'Cells/EpisodeTitleCell', + 'Cells/AirDateCell', 'Shared/LoadingView' ], function () { @@ -19,33 +24,27 @@ define([ columns: [ { - name : 'series.Title', - label : 'Series Title', - sortable : false, - cell : Backgrid.TemplateBackedCell.extend({ template: 'Missing/SeriesTitleTemplate' }) + name : 'series', + label : 'Series Title', + sortable: false, + cell : NzbDrone.Cells.SeriesTitleCell }, { - name : 'episode', - label : 'Episode', - sortable : false, - cell : Backgrid.TemplateBackedCell.extend({ template: 'Missing/EpisodeColumnTemplate' }) + name : 'this', + label : 'Episode', + sortable: false, + cell : NzbDrone.Cells.EpisodeNumberCell }, { - name : 'title', - label : 'Episode Title', - sortable : false, - cell : 'string' + name : 'this', + label : 'Episode Title', + sortable: false, + cell : NzbDrone.Cells.EpisodeTitleCell }, { - name : 'airDate', - label : 'Air Date', - cell : 'airDate' - }, - { - name : 'edit', - label : '', - sortable : false, - cell : Backgrid.TemplateBackedCell.extend({ template: 'Missing/ControlsColumnTemplate' }) + name : 'airDate', + label: 'Air Date', + cell : NzbDrone.Cells.AirDateCell } ], @@ -59,7 +58,7 @@ define([ })); this.pager.show(new Backgrid.NzbDronePaginator({ - columns: this.columns, + columns : this.columns, collection: this.missingCollection })); }, @@ -71,9 +70,9 @@ define([ this.missingCollection = new NzbDrone.Missing.Collection(); this.missingCollection.fetch() - .done(function () { - self._showTable(); - }); + .done(function () { + self._showTable(); + }); } }); }); diff --git a/UI/Missing/SeriesTitleTemplate.html b/UI/Missing/SeriesTitleTemplate.html deleted file mode 100644 index aac503f3d..000000000 --- a/UI/Missing/SeriesTitleTemplate.html +++ /dev/null @@ -1,2 +0,0 @@ -{{! TODO: Should use route instead of hard coding link }} -{{series.title}} diff --git a/UI/Mixins/backbone.Backgrid.mixin.js b/UI/Mixins/backbone.Backgrid.mixin.js index 5975999c1..fe3572a42 100644 --- a/UI/Mixins/backbone.Backgrid.mixin.js +++ b/UI/Mixins/backbone.Backgrid.mixin.js @@ -11,19 +11,6 @@ Backgrid.Column.prototype.defaults = { headerCell: 'nzbDrone' }; -Backgrid.TemplateBackedCell = Backgrid.Cell.extend({ - className: '', - template : 'Series/Index/Table/ControlsColumnTemplate', - - render: function () { - var data = this.model.toJSON(); - var templateFunction = Marionette.TemplateCache.get(this.template); - var html = templateFunction(data); - this.$el.html(html); - - return this; - } -}); Backgrid.NzbDroneHeaderCell = Backgrid.HeaderCell.extend({ events: { diff --git a/UI/Shared/Cells/ApprovalStatusCell.js b/UI/Release/ApprovalStatusCell.js similarity index 84% rename from UI/Shared/Cells/ApprovalStatusCell.js rename to UI/Release/ApprovalStatusCell.js index 9062ac52b..b5662bdb6 100644 --- a/UI/Shared/Cells/ApprovalStatusCell.js +++ b/UI/Release/ApprovalStatusCell.js @@ -1,5 +1,5 @@ "use strict"; -NzbDrone.Shared.Cells.ApprovalStatusCell = Backgrid.Cell.extend({ +NzbDrone.Release.ApprovalStatusCell = Backgrid.Cell.extend({ className: "approval-status-cell", diff --git a/UI/Release/DownloadReportCell.js b/UI/Release/DownloadReportCell.js new file mode 100644 index 000000000..da996bbb0 --- /dev/null +++ b/UI/Release/DownloadReportCell.js @@ -0,0 +1,27 @@ +"use strict"; +NzbDrone.Release.DownloadReportCell = Backgrid.Cell.extend({ + + className: "download-report-cell", + + events: { + 'click': '_onClick' + }, + + _onClick: function () { + + var self = this; + + this.$el.html(''); + this.model.save() + .always(function () { + self.$el.html(''); + }); + }, + + render: function () { + + this.$el.html(''); + return this; + + } +}); diff --git a/UI/Release/Layout.js b/UI/Release/Layout.js index 998e89c5e..62155ec6a 100644 --- a/UI/Release/Layout.js +++ b/UI/Release/Layout.js @@ -2,11 +2,12 @@ define([ 'app', 'Release/Collection', + 'Release/ApprovalStatusCell', 'Shared/SpinnerView', 'Shared/Toolbar/ToolbarLayout', - 'Shared/Cells/EpisodeNumberCell', - 'Shared/Cells/FileSizeCell', - 'Shared/Cells/ApprovalStatusCell' + 'Cells/EpisodeNumberCell', + 'Cells/FileSizeCell', + 'Cells/IndexerCell' ], function () { NzbDrone.Release.Layout = Backbone.Marionette.Layout.extend({ @@ -22,13 +23,13 @@ define([ name : 'indexer', label : 'Indexer', sortable: true, - cell : Backgrid.StringCell + cell : NzbDrone.Cells.IndexerCell }, { name : 'size', label : 'Size', sortable: true, - cell : NzbDrone.Shared.Cells.FileSizeCell + cell : NzbDrone.Cells.FileSizeCell }, { name : 'title', @@ -38,16 +39,14 @@ define([ }, { name : 'episodeNumbers', - season : 'seasonNumber', - airDate : 'airDate', episodes: 'episodeNumbers', label : 'season', - cell : NzbDrone.Shared.Cells.EpisodeNumberCell + cell : NzbDrone.Cells.EpisodeNumberCell }, { name : 'rejections', label: 'decision', - cell : NzbDrone.Shared.Cells.ApprovalStatusCell + cell : NzbDrone.Release.ApprovalStatusCell } ], diff --git a/UI/Series/Details/SeasonLayout.js b/UI/Series/Details/SeasonLayout.js index aab574bd8..343242d09 100644 --- a/UI/Series/Details/SeasonLayout.js +++ b/UI/Series/Details/SeasonLayout.js @@ -1,64 +1,68 @@ 'use strict'; -define(['app', 'Series/Details/EpisodeStatusCell', 'Series/Details/EpisodeTitleCell','Shared/Cells/ToggleCell'], function () { - NzbDrone.Series.Details.SeasonLayout = Backbone.Marionette.Layout.extend({ - template: 'Series/Details/SeasonLayoutTemplate', +define([ + 'app', + 'Cells/EpisodeStatusCell', + 'Cells/EpisodeTitleCell', + 'Cells/AirDateCell', + 'Cells/ToggleCell'], + function () { + NzbDrone.Series.Details.SeasonLayout = Backbone.Marionette.Layout.extend({ + template: 'Series/Details/SeasonLayoutTemplate', - regions: { - episodeGrid: '#x-episode-grid' - }, + regions: { + episodeGrid: '#x-episode-grid' + }, - columns: [ + columns: [ - { - name : 'ignored', - label: '', - cell : NzbDrone.Shared.Cells.ToggleCell, - trueClass : 'icon-bookmark-empty', - falseClass :'icon-bookmark' - }, - { - name : 'episodeNumber', - label: '#', - cell : Backgrid.IntegerCell.extend({ - className: 'episode-number-cell' - }) - }, + { + name : 'ignored', + label : '', + cell : NzbDrone.Cells.ToggleCell, + trueClass : 'icon-bookmark-empty', + falseClass: 'icon-bookmark' + }, + { + name : 'episodeNumber', + label: '#', + cell : Backgrid.IntegerCell.extend({ + className: 'episode-number-cell' + }) + }, - { - name : 'title', - label: 'Title', - cell : NzbDrone.Series.Details.EpisodeTitleCell - }, - { - name : 'airDate', - label: 'Air Date', - cell : Backgrid.DateCell.extend({ - className: 'episode-air-date-cell' - }) - } , - { - name : 'status', - label: 'Status', - cell : NzbDrone.Series.Details.EpisodeStatusCell - } - ], + { + name : 'this', + label: 'Title', + cell : NzbDrone.Cells.EpisodeTitleCell + }, + { + name : 'airDate', + label: 'Air Date', + cell : NzbDrone.Cells.AirDateCell + } , + { + name : 'status', + label: 'Status', + cell : NzbDrone.Cells.EpisodeStatusCell + } + ], - initialize: function (options) { + initialize: function (options) { - if (!options.episodeCollection) { - throw 'episodeCollection is needed'; - } + if (!options.episodeCollection) { + throw 'episodeCollection is needed'; + } - this.episodeCollection = options.episodeCollection.bySeason(this.model.get('seasonNumber')); - }, + this.episodeCollection = options.episodeCollection.bySeason(this.model.get('seasonNumber')); + }, - onShow: function () { - this.episodeGrid.show(new Backgrid.Grid( - { - columns : this.columns, - collection: this.episodeCollection, - className : 'table table-hover season-grid' - })); - } + onShow: function () { + this.episodeGrid.show(new Backgrid.Grid( + { + columns : this.columns, + collection: this.episodeCollection, + className : 'table table-hover season-grid' + })); + } + }); }); -}); diff --git a/UI/Series/Edit/EditSeriesView.js b/UI/Series/Edit/EditSeriesView.js index c47dd53e1..1d2600c7d 100644 --- a/UI/Series/Edit/EditSeriesView.js +++ b/UI/Series/Edit/EditSeriesView.js @@ -1,5 +1,5 @@ 'use strict'; -define(['app', 'Series/SeriesModel', 'Series/Delete/DeleteSeriesView', 'Quality/QualityProfileCollection'], function () { +define(['app', 'Series/SeriesModel', 'Series/Delete/DeleteSeriesView', 'Quality/QualityProfileCollection'], function (app, seriesModel, deleteSeriesView, qualityProfiles) { NzbDrone.Series.Edit.EditSeriesView = Backbone.Marionette.ItemView.extend({ template : 'Series/Edit/EditSeriesTemplate', @@ -16,6 +16,13 @@ define(['app', 'Series/SeriesModel', 'Series/Delete/DeleteSeriesView', 'Quality/ }, + initialize : function(){ + + this.model.set('qualityProfiles',qualityProfiles); + + }, + + saveSeries: function () { //Todo: Get qualityProfile + backlog setting from UI var qualityProfile = this.ui.qualityProfile.val(); @@ -35,4 +42,4 @@ define(['app', 'Series/SeriesModel', 'Series/Delete/DeleteSeriesView', 'Quality/ } }); -}); \ No newline at end of file +}); diff --git a/UI/Series/EpisodeModel.js b/UI/Series/EpisodeModel.js index ebe0059fb..da86988c6 100644 --- a/UI/Series/EpisodeModel.js +++ b/UI/Series/EpisodeModel.js @@ -1,5 +1,5 @@ "use strict"; -define(['app'], function () { +define(['app','Series/SeriesModel'], function () { NzbDrone.Series.EpisodeModel = Backbone.Model.extend({ mutators: { @@ -55,6 +55,13 @@ define(['app'], function () { } }, + + parse: function (model) { + model.series = new NzbDrone.Series.SeriesModel(model.series); + + return model; + }, + defaults: { seasonNumber: 0, status : 0 diff --git a/UI/Series/Index/SeriesIndexLayout.js b/UI/Series/Index/SeriesIndexLayout.js index 8352c44a6..923156f6b 100644 --- a/UI/Series/Index/SeriesIndexLayout.js +++ b/UI/Series/Index/SeriesIndexLayout.js @@ -4,7 +4,9 @@ define([ 'Series/Index/List/CollectionView', 'Series/Index/Posters/CollectionView', 'Series/Index/EmptyView', - 'Series/Index/Table/AirDateCell', + 'Cells/AirDateCell', + 'Cells/SeriesTitleCell', + 'Cells/TemplatedCell', 'Series/Index/Table/SeriesStatusCell', 'Shared/Toolbar/ToolbarLayout', 'Config', @@ -21,46 +23,48 @@ define([ columns: [ { - name : 'status', - label : '', - cell : 'seriesStatus' + name : 'status', + label: '', + cell : 'seriesStatus' }, { - name : 'title', - label : 'Title', - cell : Backgrid.TemplateBackedCell.extend({ template: 'Series/Index/Table/SeriesTitleTemplate' }) + name : 'this', + label: 'Title', + cell : NzbDrone.Cells.SeriesTitleCell }, { - name : 'seasonCount', - label : 'Seasons', - cell : 'integer' + name : 'seasonCount', + label: 'Seasons', + cell : 'integer' }, { - name : 'quality', - label : 'Quality', - cell : 'integer' + name : 'quality', + label: 'Quality', + cell : 'integer' }, { - name : 'network', - label : 'Network', - cell : 'string' + name : 'network', + label: 'Network', + cell : 'string' }, { - name : 'nextAiring', - label : 'Next Airing', - cell : 'airDate' + name : 'nextAiring', + label: 'Next Airing', + cell : NzbDrone.Cells.AirDateCell }, { - name : 'episodes', - label : 'Episodes', - sortable : false, - cell : Backgrid.TemplateBackedCell.extend({ template: 'Series/EpisodeProgressTemplate' }) + name : 'this', + label : 'Episodes', + sortable: false, + template: 'Series/EpisodeProgressTemplate', + cell : NzbDrone.Cells.TemplatedCell }, { - name : 'edit', - label : '', - sortable : false, - cell : Backgrid.TemplateBackedCell.extend({ template: 'Series/Index/Table/ControlsColumnTemplate' }) + name : 'this', + label : '', + sortable: false, + template: 'Series/Index/Table/ControlsColumnTemplate', + cell : NzbDrone.Cells.TemplatedCell } ], @@ -92,12 +96,12 @@ define([ _showTable: function () { var view = new Backgrid.Grid( - { - row : NzbDrone.Series.Index.Table.Row, - columns : this.columns, - collection: this.seriesCollection, - className : 'table table-hover' - }); + { + row : NzbDrone.Series.Index.Table.Row, + columns : this.columns, + collection: this.seriesCollection, + className : 'table table-hover' + }); this._fetchCollection(view); }, @@ -149,10 +153,10 @@ define([ //TODO: Move this outside of the function - 'this' is not available for the call back though (use string like events?) var viewButtons = { type : 'radio', - storeState : true, - menuKey : 'seriesViewMode', - defaultAction: 'listView', - items : [ + storeState : true, + menuKey : 'seriesViewMode', + defaultAction: 'listView', + items : [ { key : 'tableView', title : '', diff --git a/UI/Series/Index/Table/AirDateCell.js b/UI/Series/Index/Table/AirDateCell.js deleted file mode 100644 index 8d1ddbd27..000000000 --- a/UI/Series/Index/Table/AirDateCell.js +++ /dev/null @@ -1,13 +0,0 @@ -"use strict"; -Backgrid.AirDateCell = Backgrid.Cell.extend({ - className: "air-date-cell", - - render: function () { - this.$el.empty(); - var airDate = this.model.get(this.column.get("name")); - - this.$el.html(NzbDrone.Shared.FormatHelpers.DateHelper(airDate)); - - return this; - } -}); diff --git a/UI/Shared/BackgridPaginatorTemplate.html b/UI/Shared/BackgridPaginatorTemplate.html index a87372c56..40a21f3e2 100644 --- a/UI/Shared/BackgridPaginatorTemplate.html +++ b/UI/Shared/BackgridPaginatorTemplate.html @@ -1,5 +1,4 @@ 
    - {{debug}} {{#each handles}}
  • {{#if pageNumber}} @@ -9,4 +8,4 @@ {{/if}}
  • {{/each}} -
\ No newline at end of file + diff --git a/UI/Shared/Cells/EpisodeNumberCell.js b/UI/Shared/Cells/EpisodeNumberCell.js deleted file mode 100644 index cca9a5b5c..000000000 --- a/UI/Shared/Cells/EpisodeNumberCell.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; -NzbDrone.Shared.Cells.EpisodeNumberCell = Backgrid.Cell.extend({ - - className: "episode-number-cell", - - render: function () { - - var airDate = this.model.get(this.column.get("airDate")); - - var result = 'Unknown'; - - if (airDate) { - - result = new Date(airDate).toLocaleDateString(); - } - else { - var season = this.model.get(this.column.get("season")).pad(2); - - var episodes = _.map(this.model.get(this.column.get("episodes")), function (episodeNumber) { - return episodeNumber.pad(2); - }); - - result = 'S{0}-E{1}'.format(season, episodes.join()); - } - - this.$el.html(result); - this.delegateEvents(); - return this; - } -}); diff --git a/UI/Shared/Cells/FileSizeCell.js b/UI/Shared/Cells/FileSizeCell.js deleted file mode 100644 index f1d8d4fab..000000000 --- a/UI/Shared/Cells/FileSizeCell.js +++ /dev/null @@ -1,12 +0,0 @@ -"use strict"; -NzbDrone.Shared.Cells.FileSizeCell = Backgrid.Cell.extend({ - - className: "file-size-cell", - - render: function () { - var size = this.model.get(this.column.get("name")); - this.$el.html(NzbDrone.Shared.FormatHelpers.FileSizeHelper(size)); - this.delegateEvents(); - return this; - } -}); diff --git a/UI/app.js b/UI/app.js index 95ffdc33d..434a43268 100644 --- a/UI/app.js +++ b/UI/app.js @@ -62,12 +62,14 @@ define('app', ['shared/modal/region'], function (ModalRegion) { window.NzbDrone.Commands = {}; window.NzbDrone.Shared = { - Toolbar : {}, - Messenger: {}, - Cells: {}, + Toolbar : {}, + Messenger : {}, FormatHelpers: {} }; + + window.NzbDrone.Cells = {}; + window.NzbDrone.Calendar = {}; window.NzbDrone.Settings = { @@ -79,7 +81,7 @@ define('app', ['shared/modal/region'], function (ModalRegion) { Indexers : {}, DownloadClient: {}, Notifications : {}, - General : {}, + General : {}, Misc : {} };