mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-31 04:00:18 -07:00
Download clients now use thingy provider
This commit is contained in:
parent
ba22600412
commit
606d78f5e1
123 changed files with 2076 additions and 1820 deletions
4
src/UI/.idea/jsLinters/jshint.xml
generated
4
src/UI/.idea/jsLinters/jshint.xml
generated
|
@ -8,16 +8,16 @@
|
|||
<option es3="false" />
|
||||
<option forin="true" />
|
||||
<option immed="true" />
|
||||
<option latedef="true" />
|
||||
<option newcap="true" />
|
||||
<option noarg="true" />
|
||||
<option noempty="false" />
|
||||
<option nonew="true" />
|
||||
<option plusplus="false" />
|
||||
<option undef="true" />
|
||||
<option unused="true" />
|
||||
<option strict="true" />
|
||||
<option trailing="false" />
|
||||
<option latedef="true" />
|
||||
<option unused="true" />
|
||||
<option quotmark="single" />
|
||||
<option maxdepth="3" />
|
||||
<option asi="false" />
|
||||
|
|
|
@ -35,6 +35,13 @@ define(
|
|||
]);
|
||||
}
|
||||
|
||||
if (field.type === 'path') {
|
||||
return _templateRenderer.apply(field,
|
||||
[
|
||||
'Form/PathTemplate'
|
||||
]);
|
||||
}
|
||||
|
||||
return _templateRenderer.apply(field,
|
||||
[
|
||||
'Form/TextboxTemplate'
|
||||
|
|
12
src/UI/Form/PathTemplate.html
Normal file
12
src/UI/Form/PathTemplate.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div class="control-group">
|
||||
<label class="control-label">{{label}}</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="fields.{{order}}.value" validation-name="{{name}}" class="x-path"/>
|
||||
{{#if helpText}}
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="{{helpText}}"/>
|
||||
</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
|
||||
define([
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Add/DownloadClientAddItemView'
|
||||
], function (Marionette, AddItemView) {
|
||||
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : AddItemView,
|
||||
itemViewContainer: '.add-download-client .items',
|
||||
template : 'Settings/DownloadClient/Add/DownloadClientAddCollectionViewTemplate',
|
||||
|
||||
itemViewOptions: function () {
|
||||
return {
|
||||
downloadClientCollection: this.downloadClientCollection
|
||||
};
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.downloadClientCollection = options.downloadClientCollection;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Add Download Client</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="add-download-client add-thingies">
|
||||
<ul class="items"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal">close</button>
|
||||
</div>
|
|
@ -0,0 +1,38 @@
|
|||
'use strict';
|
||||
|
||||
define([
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Edit/DownloadClientEditView'
|
||||
], function (AppLayout, Marionette, EditView) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Add/DownloadClientAddItemViewTemplate',
|
||||
tagName : 'li',
|
||||
|
||||
events: {
|
||||
'click': '_add'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.downloadClientCollection = options.downloadClientCollection;
|
||||
},
|
||||
|
||||
_add: function (e) {
|
||||
if (this.$(e.target).hasClass('icon-info-sign')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.set({
|
||||
id : undefined,
|
||||
name : this.model.get('implementationName'),
|
||||
onGrab : true,
|
||||
onDownload : true,
|
||||
onUpgrade : true
|
||||
});
|
||||
|
||||
var editView = new EditView({ model: this.model, downloadClientCollection: this.downloadClientCollection });
|
||||
AppLayout.modalRegion.show(editView);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
<div class="add-thingy span3">
|
||||
<div class="row">
|
||||
<div class="span3">
|
||||
{{implementation}}
|
||||
{{#if link}}
|
||||
<a href="{{link}}"><i class="icon-info-sign"/></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
20
src/UI/Settings/DownloadClient/Add/SchemaModal.js
Normal file
20
src/UI/Settings/DownloadClient/Add/SchemaModal.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
define([
|
||||
'AppLayout',
|
||||
'Settings/DownloadClient/DownloadClientCollection',
|
||||
'Settings/DownloadClient/Add/DownloadClientAddCollectionView'
|
||||
], function (AppLayout, DownloadClientCollection, DownloadClientAddCollectionView) {
|
||||
return ({
|
||||
|
||||
open: function (collection) {
|
||||
var schemaCollection = new DownloadClientCollection();
|
||||
var originalUrl = schemaCollection.url;
|
||||
schemaCollection.url = schemaCollection.url + '/schema';
|
||||
schemaCollection.fetch();
|
||||
schemaCollection.url = originalUrl;
|
||||
|
||||
var view = new DownloadClientAddCollectionView({ collection: schemaCollection, downloadClientCollection: collection});
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (Marionette, AsModelBoundView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template : 'Settings/DownloadClient/BlackholeViewTemplate',
|
||||
|
||||
ui: {
|
||||
'blackholeFolder': '.x-path'
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.ui.blackholeFolder.autoComplete('/directories');
|
||||
}
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(view);
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
<fieldset>
|
||||
<legend>Blackhole</legend>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Blackhole Folder</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="blackholeFolder" class="x-path"/>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="The folder where your download client will pickup .nzb files"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
define(
|
||||
[
|
||||
'vent',
|
||||
'marionette'
|
||||
], function (vent, Marionette) {
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Delete/DownloadClientDeleteViewTemplate',
|
||||
|
||||
events: {
|
||||
'click .x-confirm-delete': '_delete'
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
this.model.destroy({
|
||||
wait : true,
|
||||
success: function () {
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Delete Download Client</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Are you sure you want to delete '{{name}}'?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal">cancel</button>
|
||||
<button class="btn btn-danger x-confirm-delete">delete</button>
|
||||
</div>
|
12
src/UI/Settings/DownloadClient/DownloadClientCollection.js
Normal file
12
src/UI/Settings/DownloadClient/DownloadClientCollection.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'Settings/DownloadClient/DownloadClientModel'
|
||||
], function (Backbone, DownloadClientModel) {
|
||||
|
||||
return Backbone.Collection.extend({
|
||||
model: DownloadClientModel,
|
||||
url : window.NzbDrone.ApiRoot + '/downloadclient'
|
||||
});
|
||||
});
|
|
@ -0,0 +1,31 @@
|
|||
'use strict';
|
||||
define(
|
||||
[
|
||||
'underscore',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/DownloadClientItemView',
|
||||
'Settings/DownloadClient/Add/SchemaModal'
|
||||
], function (_, AppLayout, Marionette, DownloadClientItemView, SchemaModal) {
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : DownloadClientItemView,
|
||||
itemViewContainer: '#x-download-clients',
|
||||
template : 'Settings/DownloadClient/DownloadClientCollectionViewTemplate',
|
||||
|
||||
ui: {
|
||||
'addCard': '.x-add-card'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-add-card': '_openSchemaModal'
|
||||
},
|
||||
|
||||
appendHtml: function (collectionView, itemView, index) {
|
||||
collectionView.ui.addCard.parent('li').before(itemView.el);
|
||||
},
|
||||
|
||||
_openSchemaModal: function () {
|
||||
SchemaModal.open(this.collection);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
<fieldset>
|
||||
<legend>Download Clients</legend>
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<ul id="x-download-clients" class="download-client-list">
|
||||
<li>
|
||||
<div class="download-client-item thingy add-card x-add-card">
|
||||
<span class="center well">
|
||||
<i class="icon-plus" title="Add Download Client"/>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
34
src/UI/Settings/DownloadClient/DownloadClientItemView.js
Normal file
34
src/UI/Settings/DownloadClient/DownloadClientItemView.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Edit/DownloadClientEditView',
|
||||
'Settings/DownloadClient/Delete/DownloadClientDeleteView'
|
||||
], function (AppLayout, Marionette, EditView, DeleteView) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/DownloadClientItemViewTemplate',
|
||||
tagName : 'li',
|
||||
|
||||
events: {
|
||||
'click .x-edit' : '_edit',
|
||||
'click .x-delete' : '_delete'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.listenTo(this.model, 'sync', this.render);
|
||||
},
|
||||
|
||||
_edit: function () {
|
||||
var view = new EditView({ model: this.model});
|
||||
AppLayout.modalRegion.show(view);
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
var view = new DeleteView({ model: this.model});
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
<div class="download-client-item thingy">
|
||||
<div>
|
||||
<h3>{{name}}</h3>
|
||||
<span class="btn-group pull-right">
|
||||
<button class="btn btn-mini btn-icon-only x-edit"><i class="icon-nd-edit"/></button>
|
||||
<button class="btn btn-mini btn-icon-only x-delete"><i class="icon-nd-delete"/></button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="settings">
|
||||
{{#if enable}}
|
||||
<span class="label label-success">Enabled</span>
|
||||
{{else}}
|
||||
<span class="label">Not Enabled</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
40
src/UI/Settings/DownloadClient/DownloadClientLayout.js
Normal file
40
src/UI/Settings/DownloadClient/DownloadClientLayout.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Settings/DownloadClient/DownloadClientCollection',
|
||||
'Settings/DownloadClient/DownloadClientCollectionView',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (Marionette, DownloadClientCollection, DownloadClientCollectionView, AsModelBoundView) {
|
||||
|
||||
var view = Marionette.Layout.extend({
|
||||
template : 'Settings/DownloadClient/DownloadClientLayoutTemplate',
|
||||
|
||||
regions: {
|
||||
downloadClients: '#x-download-clients-region'
|
||||
},
|
||||
|
||||
ui: {
|
||||
droneFactory: '.x-path'
|
||||
},
|
||||
|
||||
events: {
|
||||
'change .x-download-client': 'downloadClientChanged'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.downloadClientCollection = new DownloadClientCollection();
|
||||
this.downloadClientCollection.fetch();
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.downloadClients.show(new DownloadClientCollectionView({ collection: this.downloadClientCollection }));
|
||||
this.ui.droneFactory.autoComplete('/directories');
|
||||
}
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(view);
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
<div id="x-download-clients-region"></div>
|
||||
|
||||
<fieldset class="form-horizontal">
|
||||
<legend>Options</legend>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Drone Factory</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="downloadedEpisodesFolder" class="x-path"/>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="The folder where your download client downloads TV shows to (Completed Download Directory)"/>
|
||||
<i class="icon-nd-form-warning" title="Do not use the folder that contains some or all of your sorted and named TV shows - doing so could cause data loss"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
10
src/UI/Settings/DownloadClient/DownloadClientModel.js
Normal file
10
src/UI/Settings/DownloadClient/DownloadClientModel.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone.deepmodel'
|
||||
], function (DeepModel) {
|
||||
return DeepModel.DeepModel.extend({
|
||||
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'vent',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Delete/DownloadClientDeleteView',
|
||||
'Commands/CommandController',
|
||||
'Mixins/AsModelBoundView',
|
||||
'underscore',
|
||||
'Form/FormBuilder',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (vent, AppLayout, Marionette, DeleteView, CommandController, AsModelBoundView, _) {
|
||||
|
||||
var model = Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Edit/DownloadClientEditViewTemplate',
|
||||
|
||||
ui: {
|
||||
path : '.x-path',
|
||||
modalBody : '.modal-body'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-save' : '_save',
|
||||
'click .x-save-and-add': '_saveAndAdd',
|
||||
'click .x-delete' : '_delete',
|
||||
'click .x-back' : '_back',
|
||||
'click .x-test' : '_test'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.downloadClientCollection = options.downloadClientCollection;
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
//Hack to deal with modals not overflowing
|
||||
if (this.ui.path.length > 0) {
|
||||
this.ui.modalBody.addClass('modal-overflow');
|
||||
}
|
||||
|
||||
this.ui.path.autoComplete('/directories');
|
||||
},
|
||||
|
||||
_save: function () {
|
||||
var self = this;
|
||||
var promise = this.model.save();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.downloadClientCollection.add(self.model, { merge: true });
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_saveAndAdd: function () {
|
||||
var self = this;
|
||||
var promise = this.model.save();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.notificationCollection.add(self.model, { merge: true });
|
||||
|
||||
require('Settings/DownloadClient/Add/SchemaModal').open(self.downloadClientCollection);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
var view = new DeleteView({ model: this.model });
|
||||
AppLayout.modalRegion.show(view);
|
||||
},
|
||||
|
||||
_back: function () {
|
||||
require('Settings/DownloadClient/Add/SchemaModal').open(this.downloadClientCollection);
|
||||
},
|
||||
|
||||
_test: function () {
|
||||
var testCommand = 'test{0}'.format(this.model.get('implementation'));
|
||||
var properties = {};
|
||||
|
||||
_.each(this.model.get('fields'), function (field) {
|
||||
properties[field.name] = field.value;
|
||||
});
|
||||
|
||||
CommandController.Execute(testCommand, properties);
|
||||
}
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(model);
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
{{#if id}}
|
||||
<h3>Edit - {{implementation}}</h3>
|
||||
{{else}}
|
||||
<h3>Add - {{implementation}}</h3>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="modal-body download-client-modal">
|
||||
<div class="form-horizontal">
|
||||
<div class="control-group">
|
||||
<label class="control-label">Name</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="name"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Enable</label>
|
||||
|
||||
<div class="controls">
|
||||
<label class="checkbox toggle well">
|
||||
<input type="checkbox" name="enable"/>
|
||||
<p>
|
||||
<span>Yes</span>
|
||||
<span>No</span>
|
||||
</p>
|
||||
|
||||
<div class="btn btn-primary slide-button"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{formBuilder}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
{{#if id}}
|
||||
<button class="btn btn-danger pull-left x-delete">delete</button>
|
||||
{{else}}
|
||||
<button class="btn pull-left x-back">back</button>
|
||||
{{/if}}
|
||||
|
||||
<button class="btn x-test">test <i class="x-test-icon icon-nd-test"/></button>
|
||||
<button class="btn" data-dismiss="modal">cancel</button>
|
||||
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-primary x-save">save</button>
|
||||
<button class="btn btn-icon-only btn-primary dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="save-and-add x-save-and-add">
|
||||
save and add
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
|
@ -1,78 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Settings/DownloadClient/SabView',
|
||||
'Settings/DownloadClient/BlackholeView',
|
||||
'Settings/DownloadClient/PneumaticView',
|
||||
'Settings/DownloadClient/NzbgetView',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (Marionette, SabView, BlackholeView, PneumaticView, NzbgetView, AsModelBoundView) {
|
||||
|
||||
var view = Marionette.Layout.extend({
|
||||
template : 'Settings/DownloadClient/LayoutTemplate',
|
||||
|
||||
regions: {
|
||||
downloadClient: '#download-client-settings-region'
|
||||
},
|
||||
|
||||
ui: {
|
||||
downloadClientSelect: '.x-download-client',
|
||||
downloadedEpisodesFolder: '.x-path'
|
||||
},
|
||||
|
||||
events: {
|
||||
'change .x-download-client': 'downloadClientChanged'
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.sabView = new SabView({ model: this.model});
|
||||
this.blackholeView = new BlackholeView({ model: this.model});
|
||||
this.pneumaticView = new PneumaticView({ model: this.model});
|
||||
this.nzbgetView = new NzbgetView({ model: this.model});
|
||||
|
||||
this.ui.downloadedEpisodesFolder.autoComplete('/directories');
|
||||
|
||||
var client = this.model.get('downloadClient');
|
||||
this.refreshUIVisibility(client);
|
||||
},
|
||||
|
||||
downloadClientChanged: function () {
|
||||
var clientId = this.ui.downloadClientSelect.val();
|
||||
this.refreshUIVisibility(clientId);
|
||||
},
|
||||
|
||||
refreshUIVisibility: function (clientId) {
|
||||
|
||||
if (!clientId) {
|
||||
clientId = 'sabnzbd';
|
||||
}
|
||||
|
||||
switch (clientId.toString()) {
|
||||
case 'sabnzbd':
|
||||
this.downloadClient.show(this.sabView);
|
||||
break;
|
||||
|
||||
case 'blackhole':
|
||||
this.downloadClient.show(this.blackholeView);
|
||||
break;
|
||||
|
||||
case 'pneumatic':
|
||||
this.downloadClient.show(this.pneumaticView);
|
||||
break;
|
||||
|
||||
case 'nzbget':
|
||||
this.downloadClient.show(this.nzbgetView);
|
||||
break;
|
||||
|
||||
default :
|
||||
throw 'unknown download client id' + clientId;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(view);
|
||||
});
|
|
@ -1,29 +0,0 @@
|
|||
<fieldset class="form-horizontal">
|
||||
<legend>General</legend>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Download Client</label>
|
||||
|
||||
<div class="controls">
|
||||
<select class="inputClass x-download-client" name="downloadClient">
|
||||
<option value="sabnzbd">SABnzbd</option>
|
||||
<option value="blackhole">Blackhole</option>
|
||||
<option value="pneumatic">Pneumatic</option>
|
||||
<option value="nzbget">NZBGet</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Drone Factory</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="downloadedEpisodesFolder" class="x-path"/>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="The folder where your download client downloads TV shows to (Completed Download Directory)"/>
|
||||
<i class="icon-nd-form-warning" title="Do not use the folder that contains some or all of your sorted and named TV shows - doing so could cause data loss"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div id="download-client-settings-region" class="form-horizontal"></div>
|
|
@ -1,15 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Mixins/AsModelBoundView',
|
||||
'bootstrap'
|
||||
], function (Marionette, AsModelBoundView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template : 'Settings/DownloadClient/NzbgetViewTemplate'
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(view);
|
||||
});
|
|
@ -1,86 +0,0 @@
|
|||
<fieldset>
|
||||
<legend>NZBGet</legend>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Host</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="nzbgetHost"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Port</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="nzbgetPort"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">API Key</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="nzbgetApiKey"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Username</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="nzbgetUsername"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Password</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="password" name="nzbgetPassword"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">TV Category</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="nzbgetTvCategory"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Download Priority</label>
|
||||
|
||||
<div class="controls">
|
||||
<select name="nzbgetRecentTvPriority">
|
||||
<option value="default">Default</option>
|
||||
<option value="pasued">Paused</option>
|
||||
<option value="low">Low</option>
|
||||
<option value="normal">Normal</option>
|
||||
<option value="high">High</option>
|
||||
<option value="force">Force</option>
|
||||
</select>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="Priority to use when sending episodes that aired within the last 14 days"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Older Download Priority</label>
|
||||
|
||||
<div class="controls">
|
||||
<select name="nzbgetOlderTvPriority">
|
||||
<option value="default">Default</option>
|
||||
<option value="pasued">Paused</option>
|
||||
<option value="low">Low</option>
|
||||
<option value="normal">Normal</option>
|
||||
<option value="high">High</option>
|
||||
<option value="force">Force</option>
|
||||
</select>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="Priority to use when sending episodes that aired over 14 days ago"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
|
@ -1,24 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (Marionette, AsModelBoundView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template : 'Settings/DownloadClient/PneumaticViewTemplate',
|
||||
|
||||
ui: {
|
||||
'pneumaticFolder': '.x-path'
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.ui.pneumaticFolder.autoComplete('/directories');
|
||||
}
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(view);
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
<fieldset>
|
||||
<legend>Pneumatic</legend>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Nzb Folder</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="pneumaticFolder" class="x-path"/>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="Folder to save NZBs for Pneumatic<br/>must be accessible from XBMC"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
|
@ -1,15 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Mixins/AsModelBoundView',
|
||||
'bootstrap'
|
||||
], function (Marionette, AsModelBoundView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template : 'Settings/DownloadClient/SabViewTemplate'
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(view);
|
||||
});
|
|
@ -1,120 +0,0 @@
|
|||
<fieldset>
|
||||
<legend>SABnzbd</legend>
|
||||
|
||||
{{!<div class="control-group">
|
||||
<label class="control-label">Auto-Configure</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="button" value="Auto-Configure" class="btn btn-inverse"/>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info"
|
||||
title="(Windows only) If access to SABnzbd doesn't require a username & password and it is on the same system as NzbDrone, you can auto-configure it"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>}}
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Host</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="sabHost"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Port</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="sabPort"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">API Key</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="sabApiKey"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Username</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="sabUsername"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Password</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="password" name="sabPassword"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">TV Category</label>
|
||||
|
||||
<div class="controls">
|
||||
<input type="text" name="sabTvCategory" placeholder="This is not the dropdownlist you're looking for"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Download Priority</label>
|
||||
|
||||
<div class="controls">
|
||||
<select name="sabRecentTvPriority">
|
||||
<option value="default">Default</option>
|
||||
<option value="paused">Paused</option>
|
||||
<option value="low">Low</option>
|
||||
<option value="normal">Normal</option>
|
||||
</option> <option value="high">High</option>
|
||||
<option value="force">Force</option>
|
||||
</select>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="Priority to use when sending episodes that aired within the last 14 days"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Older Download Priority</label>
|
||||
|
||||
<div class="controls">
|
||||
<select name="sabOlderTvPriority">
|
||||
<option value="default">Default</option>
|
||||
<option value="paused">Paused</option>
|
||||
<option value="low">Low</option>
|
||||
<option value="normal">Normal</option>
|
||||
<option value="high">High</option>
|
||||
<option value="force">Force</option>
|
||||
</select>
|
||||
<span class="help-inline">
|
||||
<i class="icon-nd-form-info" title="Priority to use when sending episodes that aired over 14 days ago"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Use SSL</label>
|
||||
|
||||
<div class="controls">
|
||||
<label class="checkbox toggle well">
|
||||
<input type="checkbox" name="sabUseSsl" class="x-ssl"/>
|
||||
|
||||
<p>
|
||||
<span>Yes</span>
|
||||
<span>No</span>
|
||||
</p>
|
||||
|
||||
<div class="btn btn-primary slide-button"/>
|
||||
</label>
|
||||
|
||||
<span class="help-inline-checkbox">
|
||||
<i class="icon-nd-form-info" title="Connect to SABnzbd over SSL"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
27
src/UI/Settings/DownloadClient/downloadclient.less
Normal file
27
src/UI/Settings/DownloadClient/downloadclient.less
Normal file
|
@ -0,0 +1,27 @@
|
|||
.download-client-list {
|
||||
li {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.download-client-item {
|
||||
|
||||
width: 290px;
|
||||
height: 90px;
|
||||
padding: 10px 15px;
|
||||
|
||||
h3 {
|
||||
width: 230px;
|
||||
}
|
||||
|
||||
&.add-card {
|
||||
.center {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-overflow {
|
||||
overflow-y: visible;
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
<legend>Indexers</legend>
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<ul id="x-indexers" class="indexer-list">
|
||||
<ul id="x-indexers" class="indexer-list thingies">
|
||||
<li>
|
||||
<div class="indexer-settings-item add-card x-add-card">
|
||||
<span class="center well">
|
||||
|
|
|
@ -6,9 +6,8 @@ define(
|
|||
'Settings/Indexers/ItemView',
|
||||
'Settings/Indexers/EditView',
|
||||
'Settings/Indexers/Collection',
|
||||
'System/StatusModel',
|
||||
'underscore'
|
||||
], function (AppLayout, Marionette, IndexerItemView, IndexerEditView, IndexerCollection, StatusModel, _) {
|
||||
], function (AppLayout, Marionette, IndexerItemView, IndexerEditView, IndexerCollection, _) {
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : IndexerItemView,
|
||||
itemViewContainer: '#x-indexers',
|
||||
|
@ -28,12 +27,14 @@ define(
|
|||
|
||||
_openSchemaModal: function () {
|
||||
var self = this;
|
||||
//TODO: Is there a better way to deal with changing URLs?
|
||||
var schemaCollection = new IndexerCollection();
|
||||
schemaCollection.url = StatusModel.get('urlBase') + '/api/indexer/schema';
|
||||
var originalUrl = schemaCollection.url;
|
||||
|
||||
schemaCollection.url = schemaCollection.url + '/schema';
|
||||
|
||||
schemaCollection.fetch({
|
||||
success: function (collection) {
|
||||
collection.url = StatusModel.get('urlBase') + '/api/indexer';
|
||||
collection.url = originalUrl;
|
||||
var model = _.first(collection.models);
|
||||
|
||||
model.set({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="indexer-settings-item">
|
||||
<div class="indexer-settings-item thingy">
|
||||
<div>
|
||||
<h3>{{name}}</h3>
|
||||
{{#if_eq implementation compare="Newznab"}}
|
||||
|
|
|
@ -1,31 +1,11 @@
|
|||
@import "../../Shared/Styles/card";
|
||||
|
||||
.indexer-list {
|
||||
li {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.indexer-settings-item {
|
||||
|
||||
.card;
|
||||
|
||||
width: 220px;
|
||||
height: 260px;
|
||||
padding: 10px 15px;
|
||||
|
||||
h3 {
|
||||
margin-top: 0px;
|
||||
display: inline-block;
|
||||
width: 190px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
&.add-card {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="add-notification-item span3">
|
||||
<div class="add-thingy span3">
|
||||
<div class="row">
|
||||
<div class="span3">
|
||||
{{implementation}}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<h3>Add Notification</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="add-notifications">
|
||||
<div class="add-notifications add-thingies">
|
||||
<ul class="items"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<div class="row">
|
||||
<div class="span12">
|
||||
<ul class="notifications">
|
||||
<ul class="notifications thingies">
|
||||
<li>
|
||||
<div class="notification-item add-card x-add-card">
|
||||
<div class="notification-item thingy add-card x-add-card">
|
||||
<span class="center well">
|
||||
<i class="icon-plus" title="Add Connection"/>
|
||||
</span>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="notification-item">
|
||||
<div class="notification-item thingy">
|
||||
<div>
|
||||
<h3>{{name}}</h3>
|
||||
<span class="btn-group pull-right">
|
||||
|
|
|
@ -22,7 +22,7 @@ define(
|
|||
},
|
||||
|
||||
events: {
|
||||
'click .x-save' : '_saveNotification',
|
||||
'click .x-save' : '_saveClient',
|
||||
'click .x-save-and-add': '_saveAndAddNotification',
|
||||
'click .x-delete' : '_deleteNotification',
|
||||
'click .x-back' : '_back',
|
||||
|
@ -38,7 +38,7 @@ define(
|
|||
this._onDownloadChanged();
|
||||
},
|
||||
|
||||
_saveNotification: function () {
|
||||
_saveClient: function () {
|
||||
var self = this;
|
||||
var promise = this.model.saveSettings();
|
||||
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
define([
|
||||
'AppLayout',
|
||||
'Settings/Notifications/Collection',
|
||||
'Settings/Notifications/AddView',
|
||||
'System/StatusModel'
|
||||
], function (AppLayout, NotificationCollection, AddSelectionNotificationView, StatusModel) {
|
||||
'Settings/Notifications/AddView'
|
||||
], function (AppLayout, NotificationCollection, AddSelectionNotificationView) {
|
||||
return ({
|
||||
|
||||
open: function (collection) {
|
||||
var schemaCollection = new NotificationCollection();
|
||||
schemaCollection.url = StatusModel.get('urlBase') + '/api/notification/schema';
|
||||
var orginalUrl = schemaCollection.url;
|
||||
schemaCollection.url = schemaCollection.url + '/schema';
|
||||
schemaCollection.fetch();
|
||||
schemaCollection.url = StatusModel.get('urlBase') + '/api/notification';
|
||||
schemaCollection.url = orginalUrl;
|
||||
|
||||
var view = new AddSelectionNotificationView({ collection: schemaCollection, notificationCollection: collection});
|
||||
AppLayout.modalRegion.show(view);
|
||||
|
|
|
@ -1,70 +1,17 @@
|
|||
@import "../../Shared/Styles/card.less";
|
||||
@import "../../Shared/Styles/clickable.less";
|
||||
|
||||
.add-notification-item {
|
||||
.card;
|
||||
cursor: pointer;
|
||||
font-size: 24px;
|
||||
font-weight: lighter;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
font-size: 16px;
|
||||
color: #595959;
|
||||
|
||||
i {
|
||||
.clickable;
|
||||
}
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.add-notifications {
|
||||
text-align: center;
|
||||
|
||||
.items {
|
||||
list-style-type: none;
|
||||
margin: 0px;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notifications {
|
||||
width: -webkit-fit-content;
|
||||
width: -moz-fit-content;
|
||||
width: fit-content;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
.notification-item {
|
||||
|
||||
.card;
|
||||
.notification-item {
|
||||
|
||||
width: 290px;
|
||||
height: 90px;
|
||||
padding: 20px 20px;
|
||||
|
||||
h3 {
|
||||
margin-top: 0px;
|
||||
display: inline-block;
|
||||
width: 230px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.settings {
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
<legend>Quality Profiles</legend>
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<ul class="quality-profiles">
|
||||
<ul class="quality-profiles thingies">
|
||||
<li>
|
||||
<div class="quality-profile-item add-card x-add-card">
|
||||
<div class="quality-profile-item thingy add-card x-add-card">
|
||||
<span class="center well">
|
||||
<i class="icon-plus" title="Add Profile"/>
|
||||
</span>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="quality-profile-item">
|
||||
<div class="quality-profile-item thingy">
|
||||
<div>
|
||||
<h3 name="name"></h3>
|
||||
<span class="btn-group pull-right">
|
||||
|
|
|
@ -1,33 +1,14 @@
|
|||
@import "../../Shared/Styles/card";
|
||||
@import "../../Content/Bootstrap/mixins";
|
||||
@import "../../Content/FontAwesome/font-awesome";
|
||||
|
||||
.quality-profiles {
|
||||
li {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.quality-profile-item {
|
||||
|
||||
.card;
|
||||
|
||||
width: 300px;
|
||||
height: 120px;
|
||||
padding: 10px 15px;
|
||||
|
||||
h3 {
|
||||
margin-top: 0px;
|
||||
display: inline-block;
|
||||
width: 240px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
&.add-card {
|
||||
|
|
|
@ -12,7 +12,7 @@ define(
|
|||
'Settings/Quality/QualityLayout',
|
||||
'Settings/Indexers/IndexerLayout',
|
||||
'Settings/Indexers/Collection',
|
||||
'Settings/DownloadClient/Layout',
|
||||
'Settings/DownloadClient/DownloadClientLayout',
|
||||
'Settings/Notifications/CollectionView',
|
||||
'Settings/Notifications/Collection',
|
||||
'Settings/Metadata/MetadataLayout',
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
@import "Quality/quality";
|
||||
@import "Notifications/notifications";
|
||||
@import "Metadata/metadata";
|
||||
@import "DownloadClient/downloadclient";
|
||||
@import "thingy";
|
||||
|
||||
li.save-and-add {
|
||||
.clickable;
|
||||
|
|
65
src/UI/Settings/thingy.less
Normal file
65
src/UI/Settings/thingy.less
Normal file
|
@ -0,0 +1,65 @@
|
|||
@import "../Shared/Styles/card";
|
||||
@import "../Shared/Styles/clickable";
|
||||
|
||||
.add-thingy {
|
||||
.card;
|
||||
cursor: pointer;
|
||||
font-size: 24px;
|
||||
font-weight: lighter;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
font-size: 16px;
|
||||
color: #595959;
|
||||
|
||||
i {
|
||||
.clickable;
|
||||
}
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.add-thingies {
|
||||
text-align: center;
|
||||
|
||||
.items {
|
||||
list-style-type: none;
|
||||
margin: 0px;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.thingy {
|
||||
|
||||
.card;
|
||||
|
||||
h3 {
|
||||
margin-top: 0px;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.settings {
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.thingies {
|
||||
li {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue