New: Anime support
New: pull alternate names from thexem.de
New: Search using all alternate names (if rage ID is unavailable)
New: Show scene mapping information when hovering over episode number
New: Full season searching for anime (searches for each episode)
New: animezb.com anime indexer
New: Treat BD as bluray

Fixed: Parsing of 2 digit absolute episode numbers
Fixed: Loading series details page for series that start with period
Fixed: Return 0 results when manual search fails, instead of an error
Fixed: animezb URL
This commit is contained in:
Mark McDowall
2014-05-19 12:14:41 -07:00
parent 828dd5f5ad
commit 193672b652
105 changed files with 1901 additions and 364 deletions

View File

@@ -32,12 +32,13 @@ define(
template: 'AddSeries/SearchResultViewTemplate',
ui: {
qualityProfile: '.x-quality-profile',
rootFolder : '.x-root-folder',
seasonFolder : '.x-season-folder',
addButton : '.x-add',
overview : '.x-overview',
startingSeason: '.x-starting-season'
qualityProfile : '.x-quality-profile',
rootFolder : '.x-root-folder',
seasonFolder : '.x-season-folder',
seriesType : '.x-series-type',
startingSeason : '.x-starting-season',
addButton : '.x-add',
overview : '.x-overview'
},
events: {
@@ -151,12 +152,14 @@ define(
var quality = this.ui.qualityProfile.val();
var rootFolderPath = this.ui.rootFolder.children(':selected').text();
var startingSeason = this.ui.startingSeason.val();
var seriesType = this.ui.seriesType.val();
var seasonFolder = this.ui.seasonFolder.prop('checked');
this.model.set('qualityProfileId', quality);
this.model.set('rootFolderPath', rootFolderPath);
this.model.setSeasonPass(startingSeason);
this.model.set('seasonFolder', seasonFolder);
this.model.set('seriesType', seriesType);
this.model.setSeasonPass(startingSeason);
var self = this;
var promise = this.model.save();

View File

@@ -33,14 +33,22 @@
{{> RootFolderSelectionPartial rootFolders}}
</div>
{{/unless}}
<div class="form-group col-md-2">
<label>Starting Season</label>
{{> StartingSeasonSelectionPartial seasons}}
</div>
<div class="form-group col-md-2">
<label>Quality Profile</label>
{{> QualityProfileSelectionPartial qualityProfiles}}
</div>
<div class="form-group col-md-2">
<label>Series Type</label>
{{> SeriesTypeSelectionPartial}}
</div>
<div class="form-group col-md-2">
<label>Season Folders</label>
@@ -55,20 +63,23 @@
</label>
</div>
</div>
<div class="form-group col-md-1 pull-right">
<label>&nbsp;</label>
<button class="btn btn-success x-add add-series pull-right pull-none-xs"> Add
{{/unless}}
</div>
<div class="row">
{{#unless existing}}
<div class="form-group col-md-2 col-md-offset-10">
<!--Uncomment if we need to add even more controls to add series-->
<!--<label>&nbsp;</label>-->
<button class="btn btn-success x-add"> Add
<i class="icon-plus"></i>
</button>
</div>
{{else}}
<div class="col-md-1 col-md-offset-11">
<button class="btn add-series disabled pull-right pull-none-xs">
<div class="col-md-2 col-md-offset-10">
<button class="btn add-series disabled">
Already Exists
</button>
</div>
{{/unless}}
</div>
</div>

View File

@@ -0,0 +1,5 @@
<select class="form-control col-md-2 x-series-type" name="seriesType">
<option value="standard">Standard</option>
<option value="daily">Daily</option>
<option value="anime">Anime</option>
</select>

View File

@@ -1,4 +1,4 @@
<select class="form-control md-col-2 starting-season x-starting-season">
<select class="form-control col-md-2 starting-season x-starting-season">
{{#each this}}
{{#if_eq seasonNumber compare="0"}}
<option value="{{seasonNumber}}">Specials</option>

View File

@@ -85,21 +85,9 @@
font-size : 16px;
}
.add-series {
margin-left : 20px;
}
.checkbox {
margin-top : 0px;
}
.starting-season {
width: 140px;
&.starting-season-label {
display: inline-block;
margin-top : 0px;
}
}
i {
&:before {

View File

@@ -11,7 +11,6 @@ define(
className: 'approval-status-cell',
template : 'Cells/ApprovalStatusCellTemplate',
render: function () {
var rejections = this.model.get(this.column.get('name'));

View File

@@ -164,3 +164,7 @@ td.delete-episode-file-cell {
.series-status-cell {
width: 16px;
}
.episode-number-cell {
cursor : default;
}

View File

@@ -1,4 +1,4 @@
<div class="form-group">
<div class="form-group {{#if advanced}}advanced-setting{{/if}}">
<label class="col-sm-3 control-label">{{label}}</label>
<div class="col-sm-5">

View File

@@ -1,4 +1,4 @@
<div class="form-group">
<div class="form-group {{#if advanced}}advanced-setting{{/if}}">
<label class="col-sm-3 control-label">{{label}}</label>
<div class="col-sm-5">

View File

@@ -1,4 +1,4 @@
<div class="form-group">
<div class="form-group {{#if advanced}}advanced-setting{{/if}}">
<label class="col-sm-3 control-label">{{label}}</label>
<div class="col-sm-5">

View File

@@ -1,4 +1,4 @@
<div class="form-group">
<div class="form-group {{#if advanced}}advanced-setting{{/if}}">
<label class="col-sm-3 control-label">{{label}}</label>
<div class="col-sm-5">

View File

@@ -1,4 +1,4 @@
<div class="form-group">
<div class="form-group {{#if advanced}}advanced-setting{{/if}}">
<label class="col-sm-3 control-label">{{label}}</label>
<div class="col-sm-5">

View File

@@ -0,0 +1,62 @@
'use strict';
define(
[
'marionette',
'Cells/NzbDroneCell',
'reqres'
], function (Marionette, NzbDroneCell, reqres) {
return NzbDroneCell.extend({
className: 'episode-number-cell',
template : 'Series/Details/EpisodeNumberCellTemplate',
render: function () {
this.$el.empty();
this.$el.html(this.model.get('episodeNumber'));
var alternateTitles = [];
if (reqres.hasHandler(reqres.Requests.GetAlternateNameBySeasonNumber)) {
if (this.model.get('sceneSeasonNumber') > 0) {
alternateTitles = reqres.request(reqres.Requests.GetAlternateNameBySeasonNumber,
this.model.get('seriesId'),
this.model.get('sceneSeasonNumber'));
}
if (alternateTitles.length === 0) {
alternateTitles = reqres.request(reqres.Requests.GetAlternateNameBySeasonNumber,
this.model.get('seriesId'),
this.model.get('seasonNumber'));
}
}
if (this.model.get('sceneSeasonNumber') > 0 ||
this.model.get('sceneEpisodeNumber') > 0 ||
(this.model.has('sceneAbsoluteEpisodeNumber') && this.model.get('sceneAbsoluteEpisodeNumber') > 0) ||
alternateTitles.length > 0)
{
this.templateFunction = Marionette.TemplateCache.get(this.template);
var json = this.model.toJSON();
json.alternateTitles = alternateTitles;
var html = this.templateFunction(json);
this.$el.popover({
content : html,
html : true,
trigger : 'hover',
title : 'Scene Information',
placement: 'right',
container: this.$el
});
}
this.delegateEvents();
return this;
}
});
});

View File

@@ -0,0 +1,39 @@
<div class="scene-info">
{{#if sceneSeasonNumber}}
<div class="row">
<div class="key">Season</div>
<div class="value">{{sceneSeasonNumber}}</div>
</div>
{{/if}}
{{#if sceneEpisodeNumber}}
<div class="row">
<div class="key">Episode</div>
<div class="value">{{sceneEpisodeNumber}}</div>
</div>
{{/if}}
{{#if sceneAbsoluteEpisodeNumber}}
<div class="row">
<div class="key">Absolute</div>
<div class="value">{{sceneAbsoluteEpisodeNumber}}</div>
</div>
{{/if}}
{{#if alternateTitles}}
<div class="row">
{{#if_gt alternateTitles.length compare="1"}}
<div class="key">Titles</div>
{{else}}
<div class="key">Title</div>
{{/if_gt}}
<div class="value">
<ul>
{{#each alternateTitles}}
<li>{{title}}</li>
{{/each}}
</ul>
</div>
</div>
{{/if}}
</div>

View File

@@ -30,8 +30,10 @@
</div>
<div class="row">
<div class="col-md-12">
{{#each alternativeTitles}}
<span class="label label-default">{{this}}</span>
{{#each alternateTitles}}
{{#if_eq seasonNumber compare="-1"}}
<span class="label label-default">{{title}}</span>
{{/if_eq}}
{{/each}}
</div>
</div>

View File

@@ -9,6 +9,7 @@ define(
'Cells/RelativeDateCell',
'Cells/EpisodeStatusCell',
'Cells/EpisodeActionsCell',
'Series/Details/EpisodeNumberCell',
'Commands/CommandController',
'moment',
'underscore',
@@ -21,6 +22,7 @@ define(
RelativeDateCell,
EpisodeStatusCell,
EpisodeActionsCell,
EpisodeNumberCell,
CommandController,
Moment,
_,
@@ -58,11 +60,9 @@ define(
sortable : false
},
{
name : 'episodeNumber',
name : 'this',
label: '#',
cell : Backgrid.IntegerCell.extend({
className: 'episode-number-cell'
})
cell : EpisodeNumberCell
},
{
name : 'this',

View File

@@ -191,6 +191,14 @@ define(
return self.episodeFileCollection.get(episodeFileId);
});
reqres.setHandler(reqres.Requests.GetAlternateNameBySeasonNumber, function (seriesId, seasonNumber) {
if (self.model.get('id') !== seriesId) {
return [];
}
return _.where(self.model.get('alternateTitles'), { seasonNumber: seasonNumber });
});
$.when(this.episodeCollection.fetch(), this.episodeFileCollection.fetch()).done(function () {
var seasonCollectionView = new SeasonCollectionView({
collection : self.seasonCollection,

View File

@@ -58,10 +58,10 @@
</div>
<div class="form-group">
<label class="col-sm-4 control-label" for="inputQualityProfile">Quality Profile</label>
<label class="col-sm-4 control-label">Quality Profile</label>
<div class="col-sm-4">
<select class="form-control x-quality-profile" id="inputQualityProfile" name="qualityProfileId">
<select class="form-control x-quality-profile" name="qualityProfileId">
{{#each qualityProfiles.models}}
<option value="{{id}}">{{attributes.name}}</option>
{{/each}}
@@ -71,10 +71,17 @@
</div>
<div class="form-group">
<label class="col-sm-4 control-label" for="inputPath">Path</label>
<label class="col-sm-4 control-label">Series Type</label>
<div class="col-sm-4">
{{> SeriesTypeSelectionPartial}}
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">Path</label>
<div class="col-sm-6">
<input type="text" id="inputPath" class="form-control x-path" placeholder="Path" name="path">
<input type="text" class="form-control x-path" placeholder="Path" name="path">
</div>
</div>
</div>

View File

@@ -404,4 +404,26 @@
margin-top : 5px;
}
}
}
}
.scene-info {
.key, .value {
display : inline-block;
}
.key {
width : 80px;
margin-left : 10px;
vertical-align : top;
}
.value {
margin-right : 10px;
max-width : 170px;
}
ul {
padding-left : 0px;
list-style-type : none;
}
}

View File

@@ -18,6 +18,7 @@ define(
singleEpisodeExample : '.x-single-episode-example',
multiEpisodeExample : '.x-multi-episode-example',
dailyEpisodeExample : '.x-daily-episode-example',
animeEpisodeExample : '.x-anime-episode-example',
namingTokenHelper : '.x-naming-token-helper',
multiEpisodeStyle : '.x-multi-episode-style',
seriesFolderExample : '.x-series-folder-example',
@@ -68,6 +69,7 @@ define(
this.ui.singleEpisodeExample.html(this.namingSampleModel.get('singleEpisodeExample'));
this.ui.multiEpisodeExample.html(this.namingSampleModel.get('multiEpisodeExample'));
this.ui.dailyEpisodeExample.html(this.namingSampleModel.get('dailyEpisodeExample'));
this.ui.animeEpisodeExample.html(this.namingSampleModel.get('animeEpisodeExample'));
this.ui.seriesFolderExample.html(this.namingSampleModel.get('seriesFolderExample'));
this.ui.seasonFolderExample.html(this.namingSampleModel.get('seasonFolderExample'));
},

View File

@@ -87,6 +87,37 @@
</div>
</div>
</div>
<div class="form-group advanced-setting">
<label class="col-sm-3 control-label">Anime Episode Format</label>
<div class="col-sm-1 col-sm-push-8 help-inline">
<i class="icon-nd-form-info" title="" data-original-title="All caps or all lower-case can also be used"></i>
<a href="https://github.com/NzbDrone/NzbDrone/wiki/Sorting-and-Renaming" class="help-link" title="More information"><i class="icon-nd-form-info-link"/></a>
</div>
<div class="col-sm-8 col-sm-pull-1">
<div class="input-group x-helper-input">
<input type="text" class="form-control naming-format" name="animeEpisodeFormat" data-onkeyup="true" />
<div class="input-group-btn btn-group x-naming-token-helper">
<button class="btn btn-icon-only dropdown-toggle" data-toggle="dropdown">
<i class="icon-plus"></i>
</button>
<ul class="dropdown-menu">
{{> SeriesTitleNamingPartial}}
{{> AbsoluteEpisodeNamingPartial}}
{{> SeasonNamingPartial}}
{{> EpisodeNamingPartial}}
{{> EpisodeTitleNamingPartial}}
{{> QualityTitleNamingPartial}}
{{> ReleaseGroupNamingPartial}}
{{> OriginalTitleNamingPartial}}
{{> SeparatorNamingPartial}}
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="form-group advanced-setting">
@@ -170,6 +201,14 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Anime Episode Example</label>
<div class="col-sm-8">
<p class="form-control-static x-anime-episode-example naming-example"></p>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Series Folder Example</label>

View File

@@ -0,0 +1,8 @@
<li class="dropdown-submenu">
<a href="#" tabindex="-1" data-token="absolute">Absolute</a>
<ul class="dropdown-menu">
<li><a href="#" data-token="absolute">1</a></li>
<li><a href="#" data-token="absolute:00">01</a></li>
<li><a href="#" data-token="absolute:000">001</a></li>
</ul>
</li>

View File

@@ -7,7 +7,8 @@ define(
var reqres = new Backbone.Wreqr.RequestResponse();
reqres.Requests = {
GetEpisodeFileById: 'GetEpisodeFileById'
GetEpisodeFileById : 'GetEpisodeFileById',
GetAlternateNameBySeasonNumber : 'GetAlternateNameBySeasonNumber'
};
return reqres;