mirror of
https://github.com/Radarr/Radarr.git
synced 2026-04-17 21:26:22 -04:00
Moved source code under src folder - massive change
This commit is contained in:
26
src/UI/AddSeries/AddSeriesCollection.js
Normal file
26
src/UI/AddSeries/AddSeriesCollection.js
Normal file
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'Series/SeriesModel'
|
||||
], function (Backbone, SeriesModel) {
|
||||
return Backbone.Collection.extend({
|
||||
url : window.NzbDrone.ApiRoot + '/series/lookup',
|
||||
model: SeriesModel,
|
||||
|
||||
parse: function (response) {
|
||||
|
||||
var self = this;
|
||||
|
||||
_.each(response, function (model) {
|
||||
model.id = undefined;
|
||||
|
||||
if (self.unmappedFolderModel) {
|
||||
model.path = self.unmappedFolderModel.get('folder').path;
|
||||
}
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
});
|
||||
});
|
||||
62
src/UI/AddSeries/AddSeriesLayout.js
Normal file
62
src/UI/AddSeries/AddSeriesLayout.js
Normal file
@@ -0,0 +1,62 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'app',
|
||||
'marionette',
|
||||
'AddSeries/RootFolders/Layout',
|
||||
'AddSeries/Existing/AddExistingSeriesCollectionView',
|
||||
'AddSeries/AddSeriesView',
|
||||
'Quality/QualityProfileCollection',
|
||||
'AddSeries/RootFolders/Collection',
|
||||
'Series/SeriesCollection'
|
||||
], function (App,
|
||||
Marionette,
|
||||
RootFolderLayout,
|
||||
ExistingSeriesCollectionView,
|
||||
AddSeriesView,
|
||||
QualityProfileCollection,
|
||||
RootFolderCollection) {
|
||||
|
||||
return Marionette.Layout.extend({
|
||||
template: 'AddSeries/AddSeriesLayoutTemplate',
|
||||
|
||||
regions: {
|
||||
workspace: '#add-series-workspace'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-import': '_importSeries',
|
||||
'click .x-add-new': '_addSeries'
|
||||
},
|
||||
|
||||
attributes: {
|
||||
id: 'add-series-screen'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
QualityProfileCollection.fetch();
|
||||
RootFolderCollection.promise = RootFolderCollection.fetch();
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.workspace.show(new AddSeriesView());
|
||||
},
|
||||
|
||||
_folderSelected: function (options) {
|
||||
App.vent.trigger(App.Commands.CloseModalCommand);
|
||||
|
||||
this.workspace.show(new ExistingSeriesCollectionView({model: options.model}));
|
||||
},
|
||||
|
||||
_importSeries: function () {
|
||||
this.rootFolderLayout = new RootFolderLayout();
|
||||
this.rootFolderLayout.on('folderSelected', this._folderSelected, this);
|
||||
App.modalRegion.show(this.rootFolderLayout);
|
||||
},
|
||||
|
||||
_addSeries: function () {
|
||||
this.workspace.show(new AddSeriesView());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
22
src/UI/AddSeries/AddSeriesLayoutTemplate.html
Normal file
22
src/UI/AddSeries/AddSeriesLayoutTemplate.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<div class="row operations-row">
|
||||
<div class="btn-group btn-block">
|
||||
<div class="btn btn-large add-series-import-btn x-import">
|
||||
<i class="icon-hdd"/>
|
||||
Import existing series on disk
|
||||
</div>
|
||||
<button class="btn btn-large btn-icon-only dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="add-new x-add-new">
|
||||
Add new series
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!--<div class="btn btn-block btn-large add-series-import-btn x-import">-->
|
||||
<!--<i class="icon-hdd"/>-->
|
||||
<!--Import existing series on disk-->
|
||||
<!--</div>-->
|
||||
</div>
|
||||
<div id="add-series-workspace"/>
|
||||
139
src/UI/AddSeries/AddSeriesView.js
Normal file
139
src/UI/AddSeries/AddSeriesView.js
Normal file
@@ -0,0 +1,139 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'app',
|
||||
'marionette',
|
||||
'AddSeries/AddSeriesCollection',
|
||||
'AddSeries/SearchResultCollectionView',
|
||||
'AddSeries/NotFoundView',
|
||||
'Shared/LoadingView',
|
||||
'underscore'
|
||||
], function (App, Marionette, AddSeriesCollection, SearchResultCollectionView, NotFoundView, LoadingView, _) {
|
||||
return Marionette.Layout.extend({
|
||||
template: 'AddSeries/AddSeriesViewTemplate',
|
||||
|
||||
regions: {
|
||||
searchResult: '#search-result'
|
||||
},
|
||||
|
||||
ui: {
|
||||
seriesSearch: '.x-series-search',
|
||||
searchBar : '.x-search-bar',
|
||||
loadMore : '.x-load-more'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-load-more': '_onLoadMore'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.isExisting = options.isExisting;
|
||||
this.collection = new AddSeriesCollection();
|
||||
|
||||
if (this.isExisting) {
|
||||
this.collection.unmappedFolderModel = this.model;
|
||||
}
|
||||
|
||||
if (this.isExisting) {
|
||||
this.className = 'existing-series';
|
||||
}
|
||||
else {
|
||||
this.className = 'new-series';
|
||||
}
|
||||
|
||||
this.listenTo(App.vent, App.Events.SeriesAdded, this._onSeriesAdded);
|
||||
this.listenTo(this.collection, 'sync', this._showResults);
|
||||
|
||||
this.resultCollectionView = new SearchResultCollectionView({
|
||||
collection: this.collection,
|
||||
isExisting: this.isExisting
|
||||
});
|
||||
|
||||
this.throttledSearch = _.debounce(this.search, 1000, {trailing: true}).bind(this);
|
||||
},
|
||||
|
||||
onRender: function () {
|
||||
var self = this;
|
||||
|
||||
this.$el.addClass(this.className);
|
||||
|
||||
this.ui.seriesSearch.keyup(function () {
|
||||
self.searchResult.close();
|
||||
self._abortExistingSearch();
|
||||
self.throttledSearch({
|
||||
term: self.ui.seriesSearch.val()
|
||||
});
|
||||
});
|
||||
|
||||
if (this.isExisting) {
|
||||
this.ui.searchBar.hide();
|
||||
}
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.searchResult.show(this.resultCollectionView);
|
||||
this.ui.seriesSearch.focus();
|
||||
},
|
||||
|
||||
search: function (options) {
|
||||
|
||||
this.collection.reset();
|
||||
|
||||
if (!options.term || options.term === this.collection.term) {
|
||||
return $.Deferred().resolve();
|
||||
}
|
||||
|
||||
this.searchResult.show(new LoadingView());
|
||||
this.collection.term = options.term;
|
||||
this.currentSearchPromise = this.collection.fetch({
|
||||
data: { term: options.term }
|
||||
});
|
||||
|
||||
return this.currentSearchPromise;
|
||||
},
|
||||
|
||||
_onSeriesAdded: function (options) {
|
||||
if (this.isExisting && options.series.get('path') === this.model.get('folder').path) {
|
||||
this.close();
|
||||
}
|
||||
|
||||
else if (!this.isExisting) {
|
||||
this.collection.reset();
|
||||
this.searchResult.close();
|
||||
this.ui.seriesSearch.val('');
|
||||
this.ui.seriesSearch.focus();
|
||||
}
|
||||
},
|
||||
|
||||
_onLoadMore: function () {
|
||||
var showingAll = this.resultCollectionView.showMore();
|
||||
this.ui.searchBar.show();
|
||||
|
||||
if (showingAll) {
|
||||
this.ui.loadMore.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_showResults: function () {
|
||||
if (!this.isClosed) {
|
||||
|
||||
if (this.collection.length === 0) {
|
||||
this.searchResult.show(new NotFoundView({term: this.collection.term}));
|
||||
}
|
||||
else {
|
||||
this.searchResult.show(this.resultCollectionView);
|
||||
if (!this.showingAll && this.isExisting) {
|
||||
this.ui.loadMore.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_abortExistingSearch: function () {
|
||||
if (this.currentSearchPromise && this.currentSearchPromise.readyState > 0 && this.currentSearchPromise.readyState < 4) {
|
||||
console.log('aborting previous pending search request.');
|
||||
this.currentSearchPromise.abort();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
23
src/UI/AddSeries/AddSeriesViewTemplate.html
Normal file
23
src/UI/AddSeries/AddSeriesViewTemplate.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{{#if folder.path}}
|
||||
<div class="row unmapped-folder-path">
|
||||
<div class="span11">
|
||||
{{folder.path}}
|
||||
</div>
|
||||
</div>{{/if}}
|
||||
<div class="row x-search-bar">
|
||||
<div class="input-prepend nz-input-large add-series-search span11">
|
||||
<i class="add-on icon-search"/>
|
||||
{{#if folder}}
|
||||
<input type="text" class="input-block-level x-series-search" value="{{folder.name}}">
|
||||
{{else}}
|
||||
<input type="text" class="input-block-level x-series-search" placeholder="Start typing the name of series you want to add ...">
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div id="search-result" class="result-list span12"/>
|
||||
</div>
|
||||
<div class="btn btn-block text-center new-series-loadmore x-load-more" style="display: none;">
|
||||
<i class="icon-angle-down"/>
|
||||
more
|
||||
</div>{{debug}}
|
||||
45
src/UI/AddSeries/Existing/AddExistingSeriesCollectionView.js
Normal file
45
src/UI/AddSeries/Existing/AddExistingSeriesCollectionView.js
Normal file
@@ -0,0 +1,45 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'AddSeries/AddSeriesView',
|
||||
'AddSeries/Existing/UnmappedFolderCollection'
|
||||
], function (Marionette, AddSeriesView, UnmappedFolderCollection) {
|
||||
|
||||
return Marionette.CollectionView.extend({
|
||||
|
||||
itemView: AddSeriesView,
|
||||
|
||||
initialize: function () {
|
||||
this.collection = new UnmappedFolderCollection();
|
||||
this.collection.importItems(this.model);
|
||||
},
|
||||
|
||||
showCollection: function () {
|
||||
this._showAndSearch(0);
|
||||
},
|
||||
|
||||
_showAndSearch: function (index) {
|
||||
var self = this;
|
||||
var model = this.collection.at(index);
|
||||
|
||||
if (model) {
|
||||
var currentIndex = index;
|
||||
var folderName = model.get('folder').name;
|
||||
this.addItemView(model, this.getItemView(), index);
|
||||
this.children.findByModel(model)
|
||||
.search({term: folderName})
|
||||
.always(function () {
|
||||
if (!self.isClosed) {
|
||||
self._showAndSearch(currentIndex + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
itemViewOptions: {
|
||||
isExisting: true
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
23
src/UI/AddSeries/Existing/UnmappedFolderCollection.js
Normal file
23
src/UI/AddSeries/Existing/UnmappedFolderCollection.js
Normal file
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'AddSeries/Existing/UnmappedFolderModel'
|
||||
], function (Backbone, UnmappedFolderModel) {
|
||||
return Backbone.Collection.extend({
|
||||
model: UnmappedFolderModel,
|
||||
|
||||
importItems: function (rootFolderModel) {
|
||||
|
||||
this.reset();
|
||||
var rootFolder = rootFolderModel;
|
||||
|
||||
_.each(rootFolderModel.get('unmappedFolders'), function (folder) {
|
||||
this.push(new UnmappedFolderModel({
|
||||
rootFolder: rootFolder,
|
||||
folder : folder
|
||||
}));
|
||||
}, this);
|
||||
}
|
||||
});
|
||||
});
|
||||
10
src/UI/AddSeries/Existing/UnmappedFolderModel.js
Normal file
10
src/UI/AddSeries/Existing/UnmappedFolderModel.js
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'backbone'
|
||||
], function (Backbone) {
|
||||
return Backbone.Model.extend({
|
||||
|
||||
});
|
||||
});
|
||||
8
src/UI/AddSeries/NotFoundTemplate.html
Normal file
8
src/UI/AddSeries/NotFoundTemplate.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<div class="text-center span12">
|
||||
<h3>
|
||||
Sorry. We couldn't find any series matching '{{term}}'
|
||||
</h3>
|
||||
<a href="https://github.com/NzbDrone/NzbDrone/wiki/FAQ#why-cant-i-add-a-new-show-to-nzbdrone-its-on-thetvdb">Why can't I find my show?</a>
|
||||
|
||||
</div>
|
||||
{{debug}}
|
||||
20
src/UI/AddSeries/NotFoundView.js
Normal file
20
src/UI/AddSeries/NotFoundView.js
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette'
|
||||
], function (Marionette) {
|
||||
|
||||
return Marionette.CompositeView.extend({
|
||||
template: 'AddSeries/NotFoundTemplate',
|
||||
|
||||
initialize: function (options) {
|
||||
this.options = options;
|
||||
},
|
||||
|
||||
templateHelpers: function () {
|
||||
return this.options;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
17
src/UI/AddSeries/RootFolders/Collection.js
Normal file
17
src/UI/AddSeries/RootFolders/Collection.js
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'AddSeries/RootFolders/Model',
|
||||
'Mixins/backbone.signalr.mixin'
|
||||
], function (Backbone, RootFolderModel) {
|
||||
|
||||
var RootFolderCollection = Backbone.Collection.extend({
|
||||
url : window.NzbDrone.ApiRoot + '/rootfolder',
|
||||
model: RootFolderModel
|
||||
});
|
||||
|
||||
//var collection = new RootFolderCollection().bindSignalR();
|
||||
|
||||
return new RootFolderCollection();
|
||||
});
|
||||
16
src/UI/AddSeries/RootFolders/CollectionView.js
Normal file
16
src/UI/AddSeries/RootFolders/CollectionView.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'AddSeries/RootFolders/ItemView'
|
||||
], function (Marionette, RootFolderItemView) {
|
||||
|
||||
|
||||
return Marionette.CollectionView.extend({
|
||||
itemView: RootFolderItemView,
|
||||
|
||||
tagName : 'table',
|
||||
className: 'table table-hover'
|
||||
});
|
||||
});
|
||||
37
src/UI/AddSeries/RootFolders/ItemView.js
Normal file
37
src/UI/AddSeries/RootFolders/ItemView.js
Normal file
@@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette'
|
||||
], function (Marionette) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
|
||||
template: 'AddSeries/RootFolders/ItemViewTemplate',
|
||||
tagName : 'tr',
|
||||
|
||||
initialize: function () {
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
},
|
||||
|
||||
|
||||
events: {
|
||||
'click .x-delete': 'removeFolder',
|
||||
'click .x-folder': 'folderSelected'
|
||||
},
|
||||
|
||||
removeFolder: function () {
|
||||
|
||||
var self = this;
|
||||
|
||||
this.model.destroy()
|
||||
.success(function(){
|
||||
self.close();
|
||||
});
|
||||
},
|
||||
|
||||
folderSelected: function () {
|
||||
this.trigger('folderSelected', this.model);
|
||||
}
|
||||
});
|
||||
});
|
||||
10
src/UI/AddSeries/RootFolders/ItemViewTemplate.html
Normal file
10
src/UI/AddSeries/RootFolders/ItemViewTemplate.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<td class="span10 x-folder folder-path">
|
||||
{{path}}
|
||||
</td>
|
||||
<td class="span3 x-folder folder-free-space">
|
||||
<span>{{Bytes freeSpace}}</span>
|
||||
</td>
|
||||
<td class="span1 nz-row-action">
|
||||
<div class="btn btn-small btn-icon-only icon-nd-delete x-delete">
|
||||
</div>
|
||||
</td>
|
||||
71
src/UI/AddSeries/RootFolders/Layout.js
Normal file
71
src/UI/AddSeries/RootFolders/Layout.js
Normal file
@@ -0,0 +1,71 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'AddSeries/RootFolders/CollectionView',
|
||||
'AddSeries/RootFolders/Collection',
|
||||
'AddSeries/RootFolders/Model',
|
||||
'Shared/LoadingView',
|
||||
'Mixins/AsValidatedView',
|
||||
'Mixins/AutoComplete'
|
||||
], function (Marionette, RootFolderCollectionView, RootFolderCollection, RootFolderModel, LoadingView, AsValidatedView) {
|
||||
|
||||
var layout = Marionette.Layout.extend({
|
||||
template: 'AddSeries/RootFolders/LayoutTemplate',
|
||||
|
||||
ui: {
|
||||
pathInput: '.x-path input'
|
||||
},
|
||||
|
||||
regions: {
|
||||
currentDirs: '#current-dirs'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-add': '_addFolder'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.collection = RootFolderCollection;
|
||||
this.rootfolderListView = new RootFolderCollectionView({ collection: RootFolderCollection });
|
||||
|
||||
this.listenTo(this.rootfolderListView, 'itemview:folderSelected', this._onFolderSelected);
|
||||
},
|
||||
|
||||
onRender: function () {
|
||||
var self = this;
|
||||
this.currentDirs.show(new LoadingView());
|
||||
|
||||
RootFolderCollection.promise.done(function () {
|
||||
self.currentDirs.show(self.rootfolderListView);
|
||||
});
|
||||
|
||||
this.ui.pathInput.autoComplete('/directories');
|
||||
},
|
||||
|
||||
_onFolderSelected: function (options) {
|
||||
this.trigger('folderSelected', options);
|
||||
},
|
||||
|
||||
_addFolder: function () {
|
||||
|
||||
var self = this;
|
||||
|
||||
var newDir = new RootFolderModel({
|
||||
Path: this.ui.pathInput.val()
|
||||
});
|
||||
|
||||
this.bindToModelValidation(newDir);
|
||||
|
||||
newDir.save().done(function () {
|
||||
RootFolderCollection.add(newDir);
|
||||
self.trigger('folderSelected', {model: newDir});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return AsValidatedView.apply(layout);
|
||||
|
||||
});
|
||||
21
src/UI/AddSeries/RootFolders/LayoutTemplate.html
Normal file
21
src/UI/AddSeries/RootFolders/LayoutTemplate.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Select Folder</h3>
|
||||
</div>
|
||||
<div class="modal-body root-folders-modal">
|
||||
<div class="validation-errors"></div>
|
||||
<div class="input-prepend input-append x-path control-group">
|
||||
<span class="add-on"> <i class="icon-folder-open"></i></span>
|
||||
<input class="span9" type="text" validation-name="path" placeholder="Enter path to folder that contains your shows">
|
||||
<button class="btn btn-success x-add">
|
||||
<i class="icon-ok"/>
|
||||
</button>
|
||||
</div>
|
||||
{{#if items}}
|
||||
<h4>Recent Folders</h4>
|
||||
{{/if}}
|
||||
<div id="current-dirs" class="root-folders-list"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal">close</button>
|
||||
</div>
|
||||
12
src/UI/AddSeries/RootFolders/Model.js
Normal file
12
src/UI/AddSeries/RootFolders/Model.js
Normal file
@@ -0,0 +1,12 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone'
|
||||
], function (Backbone) {
|
||||
return Backbone.Model.extend({
|
||||
urlRoot : window.NzbDrone.ApiRoot + '/rootfolder',
|
||||
defaults: {
|
||||
freeSpace: 0
|
||||
}
|
||||
});
|
||||
});
|
||||
12
src/UI/AddSeries/RootFolders/RootFolderSelectionPartial.html
Normal file
12
src/UI/AddSeries/RootFolders/RootFolderSelectionPartial.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<div>
|
||||
<select class="span4 x-root-folder" validation-name="RootFolderPath">
|
||||
{{#if this}}
|
||||
{{#each this}}
|
||||
<option value="{{id}}">{{path}}</option>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<option value="">Select Path</option>
|
||||
{{/if}}
|
||||
<option value="addNew">Add a different path</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
<select class="span2 x-starting-season">
|
||||
{{#each this}}
|
||||
{{#if_eq seasonNumber compare="0"}}
|
||||
<option value="{{seasonNumber}}">Specials</option>
|
||||
{{else}}
|
||||
<option value="{{seasonNumber}}">Season {{seasonNumber}}</option>
|
||||
{{/if_eq}}
|
||||
{{/each}}
|
||||
</select>
|
||||
35
src/UI/AddSeries/SearchResultCollectionView.js
Normal file
35
src/UI/AddSeries/SearchResultCollectionView.js
Normal file
@@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'AddSeries/SearchResultView'
|
||||
], function (Marionette, SearchResultView) {
|
||||
|
||||
return Marionette.CollectionView.extend({
|
||||
|
||||
itemView: SearchResultView,
|
||||
|
||||
initialize: function (options) {
|
||||
this.isExisting = options.isExisting;
|
||||
this.showing = 1;
|
||||
},
|
||||
|
||||
showAll: function () {
|
||||
this.showingAll = true;
|
||||
this.render();
|
||||
},
|
||||
|
||||
showMore: function () {
|
||||
this.showing += 5;
|
||||
this.render();
|
||||
|
||||
return this.showing >= this.collection.length;
|
||||
},
|
||||
|
||||
appendHtml: function (collectionView, itemView, index) {
|
||||
if (!this.isExisting || index < this.showing || index === 0) {
|
||||
collectionView.$el.append(itemView.el);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
161
src/UI/AddSeries/SearchResultView.js
Normal file
161
src/UI/AddSeries/SearchResultView.js
Normal file
@@ -0,0 +1,161 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'app',
|
||||
'underscore',
|
||||
'marionette',
|
||||
'Quality/QualityProfileCollection',
|
||||
'AddSeries/RootFolders/Collection',
|
||||
'AddSeries/RootFolders/Layout',
|
||||
'Series/SeriesCollection',
|
||||
'Config',
|
||||
'Shared/Messenger',
|
||||
'Mixins/AsValidatedView',
|
||||
'jquery.dotdotdot'
|
||||
], function (App, _, Marionette, QualityProfiles, RootFolders, RootFolderLayout, SeriesCollection, Config, Messenger, AsValidatedView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
|
||||
template: 'AddSeries/SearchResultViewTemplate',
|
||||
|
||||
ui: {
|
||||
qualityProfile: '.x-quality-profile',
|
||||
rootFolder : '.x-root-folder',
|
||||
addButton : '.x-add',
|
||||
overview : '.x-overview',
|
||||
startingSeason: '.x-starting-season'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-add' : '_addSeries',
|
||||
'change .x-quality-profile': '_qualityProfileChanged',
|
||||
'change .x-root-folder' : '_rootFolderChanged'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
|
||||
if (!this.model) {
|
||||
throw 'model is required';
|
||||
}
|
||||
|
||||
this.templateHelpers = {};
|
||||
this._configureTemplateHelpers();
|
||||
|
||||
this.listenTo(App.vent, Config.Events.ConfigUpdatedEvent, this._onConfigUpdated);
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
this.listenTo(RootFolders, 'all', this.render);
|
||||
|
||||
this.rootFolderLayout = new RootFolderLayout();
|
||||
this.listenTo(this.rootFolderLayout, 'folderSelected', this._setRootFolder);
|
||||
},
|
||||
|
||||
onRender: function () {
|
||||
|
||||
var defaultQuality = Config.getValue(Config.Keys.DefaultQualityProfileId);
|
||||
var defaultRoot = Config.getValue(Config.Keys.DefaultRootFolderId);
|
||||
|
||||
if (QualityProfiles.get(defaultQuality)) {
|
||||
this.ui.qualityProfile.val(defaultQuality);
|
||||
}
|
||||
|
||||
if (RootFolders.get(defaultRoot)) {
|
||||
this.ui.rootFolder.val(defaultRoot);
|
||||
}
|
||||
|
||||
var minSeasonNotZero = _.min(_.reject(this.model.get('seasons'), { seasonNumber: 0 }), 'seasonNumber');
|
||||
|
||||
if (minSeasonNotZero) {
|
||||
this.ui.startingSeason.val(minSeasonNotZero.seasonNumber);
|
||||
}
|
||||
|
||||
//TODO: make this work via onRender, FM?
|
||||
//works with onShow, but stops working after the first render
|
||||
this.ui.overview.dotdotdot({
|
||||
height: 120
|
||||
});
|
||||
},
|
||||
|
||||
_configureTemplateHelpers: function () {
|
||||
var existingSeries = SeriesCollection.where({tvdbId: this.model.get('tvdbId')});
|
||||
|
||||
if (existingSeries.length > 0) {
|
||||
this.templateHelpers.existing = existingSeries[0].toJSON();
|
||||
}
|
||||
|
||||
this.templateHelpers.qualityProfiles = QualityProfiles.toJSON();
|
||||
|
||||
if (!this.model.get('isExisting')) {
|
||||
this.templateHelpers.rootFolders = RootFolders.toJSON();
|
||||
}
|
||||
},
|
||||
|
||||
_onConfigUpdated: function (options) {
|
||||
if (options.key === Config.Keys.DefaultQualityProfileId) {
|
||||
this.ui.qualityProfile.val(options.value);
|
||||
}
|
||||
else if (options.key === Config.Keys.DefaultRootFolderId) {
|
||||
this.ui.rootFolder.val(options.value);
|
||||
}
|
||||
},
|
||||
|
||||
_qualityProfileChanged: function () {
|
||||
Config.setValue(Config.Keys.DefaultQualityProfileId, this.ui.qualityProfile.val());
|
||||
},
|
||||
|
||||
_rootFolderChanged: function () {
|
||||
var rootFolderValue = this.ui.rootFolder.val();
|
||||
if (rootFolderValue === 'addNew') {
|
||||
App.modalRegion.show(this.rootFolderLayout);
|
||||
}
|
||||
else {
|
||||
Config.setValue(Config.Keys.DefaultRootFolderId, rootFolderValue);
|
||||
}
|
||||
},
|
||||
|
||||
_setRootFolder: function (options) {
|
||||
App.vent.trigger(App.Commands.CloseModalCommand);
|
||||
this.ui.rootFolder.val(options.model.id);
|
||||
this._rootFolderChanged();
|
||||
},
|
||||
|
||||
_addSeries: function () {
|
||||
var icon = this.ui.addButton.find('icon');
|
||||
icon.removeClass('icon-plus').addClass('icon-spin icon-spinner disabled');
|
||||
|
||||
var quality = this.ui.qualityProfile.val();
|
||||
var rootFolderPath = this.ui.rootFolder.children(':selected').text();
|
||||
var startingSeason = this.ui.startingSeason.val();
|
||||
|
||||
this.model.set('qualityProfileId', quality);
|
||||
this.model.set('rootFolderPath', rootFolderPath);
|
||||
this.model.setSeasonPass(startingSeason);
|
||||
|
||||
var self = this;
|
||||
|
||||
SeriesCollection.add(this.model);
|
||||
|
||||
|
||||
var promise = this.model.save();
|
||||
|
||||
promise.done(function () {
|
||||
self.close();
|
||||
icon.removeClass('icon-spin icon-spinner disabled').addClass('icon-search');
|
||||
|
||||
Messenger.show({
|
||||
message: 'Added: ' + self.model.get('title')
|
||||
});
|
||||
|
||||
App.vent.trigger(App.Events.SeriesAdded, { series: self.model });
|
||||
});
|
||||
|
||||
promise.fail(function () {
|
||||
icon.removeClass('icon-spin icon-spinner disabled').addClass('icon-search');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
AsValidatedView.apply(view);
|
||||
|
||||
return view;
|
||||
});
|
||||
38
src/UI/AddSeries/SearchResultViewTemplate.html
Normal file
38
src/UI/AddSeries/SearchResultViewTemplate.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<div class="search-item {{#unless isExisting}}search-item-new{{/unless}}">
|
||||
<div class="row">
|
||||
<div class="span2">
|
||||
<a href="{{traktUrl}}" target="_blank">
|
||||
<img class="new-series-poster" src="{{remotePoster}}"
|
||||
{{defaultImg}} >
|
||||
</a>
|
||||
</div>
|
||||
<div class="span9">
|
||||
|
||||
<div class="row">
|
||||
<h2>{{titleWithYear}}</h2>
|
||||
</div>
|
||||
<div class="row new-series-overview x-overview">
|
||||
{{overview}}
|
||||
</div>
|
||||
<div class="row">
|
||||
<form class="form-inline">
|
||||
{{#if existing}}
|
||||
<div class="btn add-series disabled pull-right">
|
||||
Already Exists
|
||||
</div>
|
||||
{{else}}
|
||||
{{#unless path}}
|
||||
{{> RootFolderSelectionPartial rootFolders}}
|
||||
{{/unless}}
|
||||
|
||||
{{> StartingSeasonSelectionPartial seasons}}
|
||||
{{> QualityProfileSelectionPartial qualityProfiles}}
|
||||
<span class="btn btn-success x-add add-series pull-right"> Add
|
||||
<i class="icon-plus"></i>
|
||||
</span>
|
||||
{{/if}}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
125
src/UI/AddSeries/addSeries.less
Normal file
125
src/UI/AddSeries/addSeries.less
Normal file
@@ -0,0 +1,125 @@
|
||||
@import "../Shared/Styles/card.less";
|
||||
@import "../Shared/Styles/clickable.less";
|
||||
|
||||
#add-series-screen {
|
||||
|
||||
.operations-row {
|
||||
margin-left : 0px;
|
||||
}
|
||||
|
||||
.existing-series {
|
||||
|
||||
.card();
|
||||
margin : 30px 0px;
|
||||
|
||||
.add-series-search {
|
||||
width : 970px;
|
||||
}
|
||||
|
||||
.unmapped-folder-path {
|
||||
padding: 20px;
|
||||
margin-left : 0px;
|
||||
font-weight : 100;
|
||||
font-size : 25px;
|
||||
text-align : center;
|
||||
}
|
||||
|
||||
.new-series-loadmore {
|
||||
font-size : 30px;
|
||||
font-weight : 300;
|
||||
padding-top : 10px;
|
||||
padding-bottom : 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.new-series {
|
||||
.search-item {
|
||||
.card();
|
||||
margin : 40px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.add-series-search {
|
||||
margin-top : 20px;
|
||||
margin-bottom : 20px;
|
||||
padding-left : 20px;
|
||||
|
||||
*[class*='icon-'] {
|
||||
font-size : 28px;
|
||||
height : 30px;
|
||||
width : 40px;
|
||||
padding-top : 14px;
|
||||
}
|
||||
input {
|
||||
height : 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-item {
|
||||
|
||||
.new-series-overview {
|
||||
overflow : hidden;
|
||||
height : 120px;
|
||||
}
|
||||
|
||||
.new-series-poster {
|
||||
min-width : 138px;
|
||||
min-height : 203px;
|
||||
max-width : 138px;
|
||||
max-height : 203px;
|
||||
margin : 10px;
|
||||
}
|
||||
|
||||
padding-bottom : 20px;
|
||||
a {
|
||||
color : #343434;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration : none;
|
||||
}
|
||||
select {
|
||||
font-size : 16px;
|
||||
}
|
||||
|
||||
.add-series {
|
||||
margin-left : 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li.add-new {
|
||||
.clickable;
|
||||
|
||||
display: block;
|
||||
padding: 3px 20px;
|
||||
clear: both;
|
||||
font-weight: normal;
|
||||
line-height: 20px;
|
||||
color: rgb(51, 51, 51);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
li.add-new:hover {
|
||||
text-decoration: none;
|
||||
color: rgb(255, 255, 255);
|
||||
background-color: rgb(0, 129, 194);
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
.dropdown-menu {
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.add-series-import-btn {
|
||||
width: 93.3%;
|
||||
}
|
||||
}
|
||||
|
||||
.root-folders-modal {
|
||||
overflow: visible;
|
||||
|
||||
.root-folders-list {
|
||||
overflow: auto;
|
||||
max-height: 300px;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user