mirror of
https://github.com/Readarr/Readarr.git
synced 2026-03-29 18:14:28 -04:00
Anime!
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:
@@ -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();
|
||||
|
||||
@@ -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> </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> </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>
|
||||
|
||||
5
src/UI/AddSeries/SeriesTypeSelectionPartial.html
Normal file
5
src/UI/AddSeries/SeriesTypeSelectionPartial.html
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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 {
|
||||
|
||||
@@ -11,7 +11,6 @@ define(
|
||||
className: 'approval-status-cell',
|
||||
template : 'Cells/ApprovalStatusCellTemplate',
|
||||
|
||||
|
||||
render: function () {
|
||||
|
||||
var rejections = this.model.get(this.column.get('name'));
|
||||
|
||||
@@ -164,3 +164,7 @@ td.delete-episode-file-cell {
|
||||
.series-status-cell {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.episode-number-cell {
|
||||
cursor : default;
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
62
src/UI/Series/Details/EpisodeNumberCell.js
Normal file
62
src/UI/Series/Details/EpisodeNumberCell.js
Normal 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;
|
||||
}
|
||||
});
|
||||
});
|
||||
39
src/UI/Series/Details/EpisodeNumberCellTemplate.html
Normal file
39
src/UI/Series/Details/EpisodeNumberCellTemplate.html
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'));
|
||||
},
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -7,7 +7,8 @@ define(
|
||||
var reqres = new Backbone.Wreqr.RequestResponse();
|
||||
|
||||
reqres.Requests = {
|
||||
GetEpisodeFileById: 'GetEpisodeFileById'
|
||||
GetEpisodeFileById : 'GetEpisodeFileById',
|
||||
GetAlternateNameBySeasonNumber : 'GetAlternateNameBySeasonNumber'
|
||||
};
|
||||
|
||||
return reqres;
|
||||
|
||||
Reference in New Issue
Block a user