mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-16 21:16:24 -04:00
Episode grid will show downloading on grab
New: Update episode status in UI on grab and download
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
|
||||
@@ -3,15 +3,25 @@
|
||||
define(
|
||||
[
|
||||
'app',
|
||||
'underscore',
|
||||
'Cells/NzbDroneCell',
|
||||
'History/Queue/QueueCollection',
|
||||
'moment',
|
||||
'Shared/FormatHelpers'
|
||||
], function (App, NzbDroneCell, Moment, FormatHelpers) {
|
||||
], function (App, _, NzbDroneCell, QueueCollection, Moment, FormatHelpers) {
|
||||
return NzbDroneCell.extend({
|
||||
|
||||
className: 'episode-status-cell',
|
||||
|
||||
render: function () {
|
||||
this.listenTo(QueueCollection, 'sync', this._renderCell);
|
||||
|
||||
this._renderCell();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_renderCell: function () {
|
||||
this.$el.empty();
|
||||
|
||||
if (this.model) {
|
||||
@@ -41,10 +51,17 @@ define(
|
||||
this.$el.html('<span class="badge badge-inverse" title="{0}">{1}</span>'.format(title, quality.quality.name));
|
||||
}
|
||||
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
else {
|
||||
if (this.model.get('downloading')) {
|
||||
var model = this.model;
|
||||
|
||||
var downloading = _.find(QueueCollection.models, function (queueModel) {
|
||||
return queueModel.get('episode').id === model.get('id');
|
||||
});
|
||||
|
||||
if (downloading || this.model.get('downloading')) {
|
||||
icon = 'icon-nd-downloading';
|
||||
tooltip = 'Episode is downloading';
|
||||
}
|
||||
@@ -66,8 +83,6 @@ define(
|
||||
|
||||
this.$el.html('<i class="{0}" title="{1}"/>'.format(icon, tooltip));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,10 +73,10 @@ define(
|
||||
App.mainRegion.show(new MissingLayout());
|
||||
},
|
||||
|
||||
history: function () {
|
||||
history: function (action) {
|
||||
this._setTitle('History');
|
||||
|
||||
App.mainRegion.show(new HistoryLayout());
|
||||
App.mainRegion.show(new HistoryLayout({ action: action }));
|
||||
},
|
||||
|
||||
rss: function () {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'History/Model',
|
||||
'History/HistoryModel',
|
||||
'backbone.pageable'
|
||||
], function (HistoryModel, PageableCollection) {
|
||||
return PageableCollection.extend({
|
||||
@@ -1,108 +1,74 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'app',
|
||||
'marionette',
|
||||
'backgrid',
|
||||
'History/Collection',
|
||||
'History/EventTypeCell',
|
||||
'Cells/SeriesTitleCell',
|
||||
'Cells/EpisodeNumberCell',
|
||||
'Cells/EpisodeTitleCell',
|
||||
'Cells/QualityCell',
|
||||
'Cells/RelativeDateCell',
|
||||
'History/HistoryDetailsCell',
|
||||
'Shared/Grid/Pager',
|
||||
'Shared/LoadingView'
|
||||
], function (Marionette,
|
||||
'History/Table/HistoryTableLayout',
|
||||
'History/Queue/QueueLayout'
|
||||
], function (App,
|
||||
Marionette,
|
||||
Backgrid,
|
||||
HistoryCollection,
|
||||
EventTypeCell,
|
||||
SeriesTitleCell,
|
||||
EpisodeNumberCell,
|
||||
EpisodeTitleCell,
|
||||
QualityCell,
|
||||
RelativeDateCell,
|
||||
HistoryDetailsCell,
|
||||
GridPager,
|
||||
LoadingView) {
|
||||
HistoryTableLayout,
|
||||
QueueLayout) {
|
||||
return Marionette.Layout.extend({
|
||||
template: 'History/HistoryLayoutTemplate',
|
||||
|
||||
regions: {
|
||||
history: '#x-history',
|
||||
toolbar: '#x-toolbar',
|
||||
pager : '#x-pager'
|
||||
history: '#history',
|
||||
queueRegion : '#queue'
|
||||
},
|
||||
|
||||
columns:
|
||||
[
|
||||
{
|
||||
name : 'eventType',
|
||||
label : '',
|
||||
cell : EventTypeCell,
|
||||
cellValue: 'this'
|
||||
},
|
||||
{
|
||||
name : 'series',
|
||||
label: 'Series',
|
||||
cell : SeriesTitleCell
|
||||
},
|
||||
{
|
||||
name : 'episode',
|
||||
label : 'Episode',
|
||||
sortable: false,
|
||||
cell : EpisodeNumberCell
|
||||
},
|
||||
{
|
||||
name : 'episode',
|
||||
label : 'Episode Title',
|
||||
sortable: false,
|
||||
cell : EpisodeTitleCell
|
||||
},
|
||||
{
|
||||
name : 'quality',
|
||||
label : 'Quality',
|
||||
cell : QualityCell,
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
name : 'date',
|
||||
label: 'Date',
|
||||
cell : RelativeDateCell
|
||||
},
|
||||
{
|
||||
name : 'this',
|
||||
label : '',
|
||||
cell : HistoryDetailsCell,
|
||||
sortable: false
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
initialize: function () {
|
||||
this.collection = new HistoryCollection();
|
||||
this.listenTo(this.collection, 'sync', this._showTable);
|
||||
ui: {
|
||||
historyTab: '.x-history-tab',
|
||||
queueTab : '.x-queue-tab'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-history-tab' : '_showHistory',
|
||||
'click .x-queue-tab' : '_showQueue'
|
||||
},
|
||||
|
||||
_showTable: function (collection) {
|
||||
|
||||
this.history.show(new Backgrid.Grid({
|
||||
columns : this.columns,
|
||||
collection: collection,
|
||||
className : 'table table-hover'
|
||||
}));
|
||||
|
||||
this.pager.show(new GridPager({
|
||||
columns : this.columns,
|
||||
collection: collection
|
||||
}));
|
||||
initialize: function (options) {
|
||||
if (options.action) {
|
||||
this.action = options.action.toLowerCase();
|
||||
}
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.history.show(new LoadingView());
|
||||
this.collection.fetch();
|
||||
}
|
||||
switch (this.action) {
|
||||
case 'queue':
|
||||
this._showQueue();
|
||||
break;
|
||||
default:
|
||||
this._showHistory();
|
||||
}
|
||||
},
|
||||
|
||||
_navigate:function(route){
|
||||
require(['Router'], function(){
|
||||
App.Router.navigate(route);
|
||||
});
|
||||
},
|
||||
|
||||
_showHistory: function (e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
this.history.show(new HistoryTableLayout());
|
||||
this.ui.historyTab.tab('show');
|
||||
this._navigate('/history');
|
||||
},
|
||||
|
||||
_showQueue: function (e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
this.queueRegion.show(new QueueLayout());
|
||||
this.ui.queueTab.tab('show');
|
||||
this._navigate('/history/queue');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<div id="x-toolbar"/>
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<div id="x-history"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<div id="x-pager"/>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="#history" class="x-history-tab no-router">History</a></li>
|
||||
<li><a href="#queue" class="x-queue-tab no-router">Queue</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane" id="history"></div>
|
||||
<div class="tab-pane" id="queue"></div>
|
||||
</div>
|
||||
@@ -1 +0,0 @@
|
||||
<img src="favicon.ico" alt="{{indexer}}"/>
|
||||
17
UI/History/Queue/QueueCollection.js
Normal file
17
UI/History/Queue/QueueCollection.js
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'History/Queue/QueueModel',
|
||||
'Mixins/backbone.signalr.mixin'
|
||||
], function (Backbone, QueueModel) {
|
||||
var QueueCollection = Backbone.Collection.extend({
|
||||
url : window.NzbDrone.ApiRoot + '/queue',
|
||||
model: QueueModel
|
||||
});
|
||||
|
||||
var collection = new QueueCollection().bindSignalR();
|
||||
collection.fetch();
|
||||
|
||||
return collection;
|
||||
});
|
||||
77
UI/History/Queue/QueueLayout.js
Normal file
77
UI/History/Queue/QueueLayout.js
Normal file
@@ -0,0 +1,77 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'backgrid',
|
||||
'History/Queue/QueueCollection',
|
||||
'Cells/SeriesTitleCell',
|
||||
'Cells/EpisodeNumberCell',
|
||||
'Cells/EpisodeTitleCell',
|
||||
'Cells/QualityCell',
|
||||
'History/Queue/TimeleftCell'
|
||||
], function (Marionette,
|
||||
Backgrid,
|
||||
QueueCollection,
|
||||
SeriesTitleCell,
|
||||
EpisodeNumberCell,
|
||||
EpisodeTitleCell,
|
||||
QualityCell,
|
||||
TimeleftCell) {
|
||||
return Marionette.Layout.extend({
|
||||
template: 'History/Queue/QueueLayoutTemplate',
|
||||
|
||||
regions: {
|
||||
table: '#x-queue'
|
||||
},
|
||||
|
||||
columns:
|
||||
[
|
||||
{
|
||||
name : 'series',
|
||||
label: 'Series',
|
||||
cell : SeriesTitleCell
|
||||
},
|
||||
{
|
||||
name : 'episode',
|
||||
label : 'Episode',
|
||||
sortable: false,
|
||||
cell : EpisodeNumberCell
|
||||
},
|
||||
{
|
||||
name : 'episode',
|
||||
label : 'Episode Title',
|
||||
sortable: false,
|
||||
cell : EpisodeTitleCell
|
||||
},
|
||||
{
|
||||
name : 'quality',
|
||||
label : 'Quality',
|
||||
cell : QualityCell,
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
name : 'timeleft',
|
||||
label : 'Timeleft',
|
||||
cell : TimeleftCell,
|
||||
cellValue : 'this'
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
initialize: function () {
|
||||
this.listenTo(QueueCollection, 'sync', this._showTable);
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this._showTable();
|
||||
},
|
||||
|
||||
_showTable: function () {
|
||||
this.table.show(new Backgrid.Grid({
|
||||
columns : this.columns,
|
||||
collection: QueueCollection,
|
||||
className : 'table table-hover'
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
5
UI/History/Queue/QueueLayoutTemplate.html
Normal file
5
UI/History/Queue/QueueLayoutTemplate.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<div id="x-queue"/>
|
||||
</div>
|
||||
</div>
|
||||
16
UI/History/Queue/QueueModel.js
Normal file
16
UI/History/Queue/QueueModel.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'Series/SeriesModel',
|
||||
'Series/EpisodeModel'
|
||||
], function (Backbone, SeriesModel, EpisodeModel) {
|
||||
return Backbone.Model.extend({
|
||||
parse: function (model) {
|
||||
model.series = new SeriesModel(model.series);
|
||||
model.episode = new EpisodeModel(model.episode);
|
||||
model.episode.set('series', model.series);
|
||||
return model;
|
||||
}
|
||||
});
|
||||
});
|
||||
27
UI/History/Queue/TimeleftCell.js
Normal file
27
UI/History/Queue/TimeleftCell.js
Normal file
@@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'Cells/NzbDroneCell'
|
||||
], function (NzbDroneCell) {
|
||||
return NzbDroneCell.extend({
|
||||
|
||||
className: 'history-event-type-cell',
|
||||
|
||||
render: function () {
|
||||
this.$el.empty();
|
||||
|
||||
if (this.cellValue) {
|
||||
|
||||
var timeleft = this.cellValue.get('timeleft');
|
||||
var size = this.cellValue.get('size');
|
||||
var sizeLeft = this.cellValue.get('sizeLeft');
|
||||
|
||||
this.$el.html(timeleft);
|
||||
this.$el.attr('title', '{0} MB / {1} MB'.format(sizeLeft, size));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
});
|
||||
108
UI/History/Table/HistoryTableLayout.js
Normal file
108
UI/History/Table/HistoryTableLayout.js
Normal file
@@ -0,0 +1,108 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'backgrid',
|
||||
'History/HistoryCollection',
|
||||
'History/Table/EventTypeCell',
|
||||
'Cells/SeriesTitleCell',
|
||||
'Cells/EpisodeNumberCell',
|
||||
'Cells/EpisodeTitleCell',
|
||||
'Cells/QualityCell',
|
||||
'Cells/RelativeDateCell',
|
||||
'History/Table/HistoryDetailsCell',
|
||||
'Shared/Grid/Pager',
|
||||
'Shared/LoadingView'
|
||||
], function (Marionette,
|
||||
Backgrid,
|
||||
HistoryCollection,
|
||||
EventTypeCell,
|
||||
SeriesTitleCell,
|
||||
EpisodeNumberCell,
|
||||
EpisodeTitleCell,
|
||||
QualityCell,
|
||||
RelativeDateCell,
|
||||
HistoryDetailsCell,
|
||||
GridPager,
|
||||
LoadingView) {
|
||||
return Marionette.Layout.extend({
|
||||
template: 'History/Table/HistoryTableLayoutTemplate',
|
||||
|
||||
regions: {
|
||||
history: '#x-history',
|
||||
toolbar: '#x-toolbar',
|
||||
pager : '#x-pager'
|
||||
},
|
||||
|
||||
columns:
|
||||
[
|
||||
{
|
||||
name : 'eventType',
|
||||
label : '',
|
||||
cell : EventTypeCell,
|
||||
cellValue: 'this'
|
||||
},
|
||||
{
|
||||
name : 'series',
|
||||
label: 'Series',
|
||||
cell : SeriesTitleCell
|
||||
},
|
||||
{
|
||||
name : 'episode',
|
||||
label : 'Episode',
|
||||
sortable: false,
|
||||
cell : EpisodeNumberCell
|
||||
},
|
||||
{
|
||||
name : 'episode',
|
||||
label : 'Episode Title',
|
||||
sortable: false,
|
||||
cell : EpisodeTitleCell
|
||||
},
|
||||
{
|
||||
name : 'quality',
|
||||
label : 'Quality',
|
||||
cell : QualityCell,
|
||||
sortable: false
|
||||
},
|
||||
{
|
||||
name : 'date',
|
||||
label: 'Date',
|
||||
cell : RelativeDateCell
|
||||
},
|
||||
{
|
||||
name : 'this',
|
||||
label : '',
|
||||
cell : HistoryDetailsCell,
|
||||
sortable: false
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
initialize: function () {
|
||||
this.collection = new HistoryCollection();
|
||||
this.listenTo(this.collection, 'sync', this._showTable);
|
||||
},
|
||||
|
||||
|
||||
_showTable: function (collection) {
|
||||
|
||||
this.history.show(new Backgrid.Grid({
|
||||
columns : this.columns,
|
||||
collection: collection,
|
||||
className : 'table table-hover'
|
||||
}));
|
||||
|
||||
this.pager.show(new GridPager({
|
||||
columns : this.columns,
|
||||
collection: collection
|
||||
}));
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.history.show(new LoadingView());
|
||||
this.collection.fetch();
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
11
UI/History/Table/HistoryTableLayoutTemplate.html
Normal file
11
UI/History/Table/HistoryTableLayoutTemplate.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<div id="x-toolbar"/>
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<div id="x-history"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<div id="x-pager"/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -13,6 +13,13 @@ define(
|
||||
|
||||
var processMessage = function (options) {
|
||||
|
||||
if (options.action === 'sync') {
|
||||
console.log('sync received, refetching collection');
|
||||
collection.fetch();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var model = new collection.model(options.resource, {parse: true});
|
||||
collection.add(model, {merge: true});
|
||||
console.log(options.action + ': {0}}'.format(options.resource));
|
||||
|
||||
@@ -8,6 +8,7 @@ require(
|
||||
'Series/SeriesCollection',
|
||||
'ProgressMessaging/ProgressMessageCollection',
|
||||
'Commands/CommandMessengerCollectionView',
|
||||
'History/Queue/QueueCollection',
|
||||
'Navbar/NavbarView',
|
||||
'jQuery/RouteBinder',
|
||||
'jquery'
|
||||
@@ -18,6 +19,7 @@ require(
|
||||
SeriesCollection,
|
||||
ProgressMessageCollection,
|
||||
CommandMessengerCollectionView,
|
||||
QueueCollection,
|
||||
NavbarView,
|
||||
RouterBinder,
|
||||
$) {
|
||||
@@ -36,6 +38,7 @@ require(
|
||||
'settings/:action(/:query)' : 'settings',
|
||||
'missing' : 'missing',
|
||||
'history' : 'history',
|
||||
'history/:action' : 'history',
|
||||
'rss' : 'rss',
|
||||
'system' : 'system',
|
||||
'system/:action' : 'system',
|
||||
|
||||
@@ -150,7 +150,6 @@ define(
|
||||
},
|
||||
|
||||
_renameSeries: function () {
|
||||
|
||||
CommandController.Execute('renameSeries', {
|
||||
name : 'renameSeries',
|
||||
seriesId: this.model.id
|
||||
@@ -172,7 +171,7 @@ define(
|
||||
|
||||
this.seasonCollection = new SeasonCollection(this.model.get('seasons'));
|
||||
this.episodeCollection = new EpisodeCollection({ seriesId: this.model.id }).bindSignalR();
|
||||
this.episodeFileCollection = new EpisodeFileCollection({ seriesId: this.model.id });
|
||||
this.episodeFileCollection = new EpisodeFileCollection({ seriesId: this.model.id }).bindSignalR();
|
||||
|
||||
$.when(this.episodeCollection.fetch(), this.episodeFileCollection.fetch()).done(function () {
|
||||
var seasonCollectionView = new SeasonCollectionView({
|
||||
|
||||
Reference in New Issue
Block a user