Download clients now use thingy provider

This commit is contained in:
Mark McDowall
2014-02-13 21:31:49 -08:00
parent ba22600412
commit 606d78f5e1
123 changed files with 2076 additions and 1820 deletions
@@ -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">&times;</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>
@@ -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">&times;</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>
@@ -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>
@@ -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>
@@ -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>
@@ -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">&times;</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>
-78
View File
@@ -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>
-15
View File
@@ -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>
@@ -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;
}