mirror of
https://github.com/Radarr/Radarr.git
synced 2026-04-18 21:35:51 -04:00
New: Drone now uses the Download Client API to determine if a download is ready for import. (User configuration is required to replace the drone factory with this feature)
This commit is contained in:
@@ -26,6 +26,11 @@ define(
|
||||
title = 'Queued';
|
||||
}
|
||||
|
||||
if (status === 'completed') {
|
||||
icon = 'icon-inbox';
|
||||
title = 'Downloaded';
|
||||
}
|
||||
|
||||
this.$el.html('<i class="{0}" title="{1}"></i>'.format(icon, title));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'marionette',
|
||||
'Settings/ThingyAddCollectionView',
|
||||
'Settings/ThingyHeaderGroupView',
|
||||
'Settings/DownloadClient/Add/DownloadClientAddItemView'
|
||||
], function (Marionette, AddItemView) {
|
||||
], function (ThingyAddCollectionView, ThingyHeaderGroupView, AddItemView) {
|
||||
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : AddItemView,
|
||||
return ThingyAddCollectionView.extend({
|
||||
itemView : ThingyHeaderGroupView.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;
|
||||
}
|
||||
template : 'Settings/DownloadClient/Add/DownloadClientAddCollectionViewTemplate'
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Edit/DownloadClientEditView'
|
||||
], function (AppLayout, Marionette, EditView) {
|
||||
], function ($, AppLayout, Marionette, EditView) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Add/DownloadClientAddItemViewTemplate',
|
||||
@@ -15,7 +16,7 @@ define([
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.downloadClientCollection = options.downloadClientCollection;
|
||||
this.targetCollection = options.targetCollection;
|
||||
},
|
||||
|
||||
_add: function (e) {
|
||||
@@ -25,11 +26,11 @@ define([
|
||||
|
||||
this.model.set({
|
||||
id : undefined,
|
||||
name : this.model.get('implementationName'),
|
||||
name : this.model.get('implementation'),
|
||||
enable : true
|
||||
});
|
||||
|
||||
var editView = new EditView({ model: this.model, downloadClientCollection: this.downloadClientCollection });
|
||||
var editView = new EditView({ model: this.model, targetCollection: this.targetCollection });
|
||||
AppLayout.modalRegion.show(editView);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'underscore',
|
||||
'AppLayout',
|
||||
'backbone',
|
||||
'Settings/DownloadClient/DownloadClientCollection',
|
||||
'Settings/DownloadClient/Add/DownloadClientAddCollectionView'
|
||||
], function (_, AppLayout, Backbone, SchemaCollection, AddCollectionView) {
|
||||
return ({
|
||||
|
||||
open: function (collection) {
|
||||
var schemaCollection = new SchemaCollection();
|
||||
var originalUrl = schemaCollection.url;
|
||||
schemaCollection.url = schemaCollection.url + '/schema';
|
||||
schemaCollection.fetch();
|
||||
schemaCollection.url = originalUrl;
|
||||
|
||||
var groupedSchemaCollection = new Backbone.Collection();
|
||||
|
||||
schemaCollection.on('sync', function() {
|
||||
|
||||
var groups = schemaCollection.groupBy(function(model, iterator) { return model.get('protocol'); });
|
||||
|
||||
var modelCollection = _.map(groups, function(values, key, list) {
|
||||
return { 'header': key, collection: values };
|
||||
});
|
||||
|
||||
groupedSchemaCollection.reset(modelCollection);
|
||||
});
|
||||
|
||||
var view = new AddCollectionView({ collection: groupedSchemaCollection, targetCollection: collection });
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
'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,23 +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'
|
||||
},
|
||||
define([
|
||||
'vent',
|
||||
'marionette'
|
||||
], function (vent, Marionette) {
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Delete/DownloadClientDeleteViewTemplate',
|
||||
|
||||
_delete: function () {
|
||||
this.model.destroy({
|
||||
wait : true,
|
||||
success: function () {
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
events: {
|
||||
'click .x-confirm-delete': '_delete'
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
this.model.destroy({
|
||||
wait : true,
|
||||
success: function () {
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,31 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'Settings/DownloadClient/DownloadClientModel'
|
||||
], function (Backbone, DownloadClientModel) {
|
||||
|
||||
return Backbone.Collection.extend({
|
||||
model: DownloadClientModel,
|
||||
url : window.NzbDrone.ApiRoot + '/downloadclient'
|
||||
});
|
||||
define([
|
||||
'backbone',
|
||||
'Settings/DownloadClient/DownloadClientModel'
|
||||
], function (Backbone, DownloadClientModel) {
|
||||
|
||||
return Backbone.Collection.extend({
|
||||
model: DownloadClientModel,
|
||||
url : window.NzbDrone.ApiRoot + '/downloadclient',
|
||||
|
||||
comparator : function(left, right, collection) {
|
||||
|
||||
var result = 0;
|
||||
|
||||
if (left.get('protocol')) {
|
||||
result = -left.get('protocol').localeCompare(right.get('protocol'));
|
||||
}
|
||||
|
||||
if (result === 0 && left.get('name')) {
|
||||
result = left.get('name').localeCompare(right.get('name'));
|
||||
}
|
||||
|
||||
if (result === 0) {
|
||||
result = left.get('implementation').localeCompare(right.get('implementation'));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,31 +1,29 @@
|
||||
'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'
|
||||
},
|
||||
define([
|
||||
'marionette',
|
||||
'Settings/DownloadClient/DownloadClientItemView',
|
||||
'Settings/DownloadClient/Add/DownloadClientSchemaModal'
|
||||
], function (Marionette, ItemView, SchemaModal) {
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : ItemView,
|
||||
itemViewContainer: '.download-client-list',
|
||||
template : 'Settings/DownloadClient/DownloadClientCollectionViewTemplate',
|
||||
|
||||
events: {
|
||||
'click .x-add-card': '_openSchemaModal'
|
||||
},
|
||||
ui: {
|
||||
'addCard': '.x-add-card'
|
||||
},
|
||||
|
||||
appendHtml: function (collectionView, itemView, index) {
|
||||
collectionView.ui.addCard.parent('li').before(itemView.el);
|
||||
},
|
||||
events: {
|
||||
'click .x-add-card': '_openSchemaModal'
|
||||
},
|
||||
|
||||
_openSchemaModal: function () {
|
||||
SchemaModal.open(this.collection);
|
||||
}
|
||||
});
|
||||
appendHtml: function (collectionView, itemView, index) {
|
||||
collectionView.ui.addCard.parent('li').before(itemView.el);
|
||||
},
|
||||
|
||||
_openSchemaModal: function () {
|
||||
SchemaModal.open(this.collection);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<legend>Download Clients</legend>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<ul id="x-download-clients" class="download-client-list thingies">
|
||||
<ul class="download-client-list thingies">
|
||||
<li>
|
||||
<div class="download-client-item thingy add-card x-add-card">
|
||||
<span class="center well">
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Edit/DownloadClientEditView'
|
||||
], function (AppLayout, Marionette, EditView) {
|
||||
define([
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Edit/DownloadClientEditView'
|
||||
], function (AppLayout, Marionette, EditView) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/DownloadClientItemViewTemplate',
|
||||
tagName : 'li',
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/DownloadClientItemViewTemplate',
|
||||
tagName : 'li',
|
||||
|
||||
events: {
|
||||
'click' : '_edit'
|
||||
},
|
||||
events: {
|
||||
'click' : '_edit'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.listenTo(this.model, 'sync', this.render);
|
||||
},
|
||||
initialize: function () {
|
||||
this.listenTo(this.model, 'sync', this.render);
|
||||
},
|
||||
|
||||
_edit: function () {
|
||||
var view = new EditView({ model: this.model, downloadClientCollection: this.model.collection });
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
_edit: function () {
|
||||
var view = new EditView({ model: this.model, targetCollection: this.model.collection});
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Settings/DownloadClient/DownloadClientCollection',
|
||||
'Settings/DownloadClient/DownloadClientCollectionView',
|
||||
'Settings/DownloadClient/Options/DownloadClientOptionsView',
|
||||
'Settings/DownloadClient/FailedDownloadHandling/FailedDownloadHandlingView'
|
||||
], function (Marionette, DownloadClientCollection, DownloadClientCollectionView, DownloadClientOptionsView, FailedDownloadHandlingView) {
|
||||
define([
|
||||
'marionette',
|
||||
'Settings/DownloadClient/DownloadClientCollection',
|
||||
'Settings/DownloadClient/DownloadClientCollectionView',
|
||||
'Settings/DownloadClient/DroneFactory/DroneFactoryView',
|
||||
'Settings/DownloadClient/DownloadHandling/DownloadHandlingView'
|
||||
], function (Marionette, DownloadClientCollection, CollectionView, DroneFactoryView, DownloadHandlingView) {
|
||||
|
||||
return Marionette.Layout.extend({
|
||||
template : 'Settings/DownloadClient/DownloadClientLayoutTemplate',
|
||||
return Marionette.Layout.extend({
|
||||
template : 'Settings/DownloadClient/DownloadClientLayoutTemplate',
|
||||
|
||||
regions: {
|
||||
downloadClients : '#x-download-clients-region',
|
||||
downloadClientOptions : '#x-download-client-options-region',
|
||||
failedDownloadHandling : '#x-failed-download-handling-region'
|
||||
},
|
||||
regions: {
|
||||
downloadClients : '#x-download-clients-region',
|
||||
downloadHandling : '#x-download-handling-region',
|
||||
droneFactory : '#x-dronefactory-region'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.downloadClientCollection = new DownloadClientCollection();
|
||||
this.downloadClientCollection.fetch();
|
||||
},
|
||||
initialize: function () {
|
||||
this.downloadClientsCollection = new DownloadClientCollection();
|
||||
this.downloadClientsCollection.fetch();
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.downloadClients.show(new DownloadClientCollectionView({ collection: this.downloadClientCollection }));
|
||||
this.downloadClientOptions.show(new DownloadClientOptionsView({ model: this.model }));
|
||||
this.failedDownloadHandling.show(new FailedDownloadHandlingView({ model: this.model }));
|
||||
}
|
||||
});
|
||||
});
|
||||
onShow: function () {
|
||||
this.downloadClients.show(new CollectionView({ collection: this.downloadClientsCollection }));
|
||||
this.downloadHandling.show(new DownloadHandlingView({ model: this.model }));
|
||||
this.droneFactory.show(new DroneFactoryView({ model: this.model }));
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,5 @@
|
||||
<div id="x-download-clients-region"></div>
|
||||
<div class="form-horizontal">
|
||||
<div id="x-download-client-options-region"></div>
|
||||
<div id="x-failed-download-handling-region"></div>
|
||||
<div id="x-download-handling-region"></div>
|
||||
<div id="x-dronefactory-region"></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone.deepmodel'
|
||||
], function (DeepModel) {
|
||||
return DeepModel.DeepModel.extend({
|
||||
|
||||
});
|
||||
define([
|
||||
'backbone.deepmodel'
|
||||
], function (DeepModel) {
|
||||
return DeepModel.DeepModel.extend({
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'Settings/SettingsModelBase'
|
||||
], function (SettingsModelBase) {
|
||||
return SettingsModelBase.extend({
|
||||
url : window.NzbDrone.ApiRoot + '/config/downloadclient',
|
||||
successMessage: 'Download client settings saved',
|
||||
errorMessage : 'Failed to save download client settings'
|
||||
});
|
||||
|
||||
define([
|
||||
'Settings/SettingsModelBase'
|
||||
], function (SettingsModelBase) {
|
||||
return SettingsModelBase.extend({
|
||||
url : window.NzbDrone.ApiRoot + '/config/downloadclient',
|
||||
successMessage: 'Download client settings saved',
|
||||
errorMessage : 'Failed to save download client settings'
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AsValidatedView'
|
||||
], function (Marionette, AsModelBoundView, AsValidatedView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/DownloadHandling/DownloadHandlingViewTemplate',
|
||||
|
||||
ui: {
|
||||
completedDownloadHandlingCheckbox : '.x-completed-download-handling',
|
||||
completedDownloadOptions : '.x-completed-download-options',
|
||||
failedDownloadHandlingCheckbox : '.x-failed-download-handling',
|
||||
failedDownloadOptions : '.x-failed-download-options'
|
||||
},
|
||||
|
||||
events: {
|
||||
'change .x-completed-download-handling' : '_setCompletedDownloadOptionsVisibility',
|
||||
'change .x-failed-download-handling' : '_setFailedDownloadOptionsVisibility'
|
||||
},
|
||||
|
||||
onRender: function () {
|
||||
if (!this.ui.completedDownloadHandlingCheckbox.prop('checked')) {
|
||||
this.ui.completedDownloadOptions.hide();
|
||||
}
|
||||
if (!this.ui.failedDownloadHandlingCheckbox.prop('checked')) {
|
||||
this.ui.failedDownloadOptions.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_setCompletedDownloadOptionsVisibility: function () {
|
||||
var checked = this.ui.completedDownloadHandlingCheckbox.prop('checked');
|
||||
if (checked) {
|
||||
this.ui.completedDownloadOptions.slideDown();
|
||||
}
|
||||
|
||||
else {
|
||||
this.ui.completedDownloadOptions.slideUp();
|
||||
}
|
||||
},
|
||||
|
||||
_setFailedDownloadOptionsVisibility: function () {
|
||||
var checked = this.ui.failedDownloadHandlingCheckbox.prop('checked');
|
||||
if (checked) {
|
||||
this.ui.failedDownloadOptions.slideDown();
|
||||
}
|
||||
|
||||
else {
|
||||
this.ui.failedDownloadOptions.slideUp();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AsModelBoundView.call(view);
|
||||
AsValidatedView.call(view);
|
||||
|
||||
return view;
|
||||
});
|
||||
@@ -1,6 +1,56 @@
|
||||
<fieldset class="advanced-setting">
|
||||
<legend>Failed Download Handling</legend>
|
||||
<fieldset>
|
||||
<legend>Download Client Import Handling</legend>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Enable</label>
|
||||
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group">
|
||||
<label class="checkbox toggle well">
|
||||
<input type="checkbox" name="enableCompletedDownloadHandling" class="x-completed-download-handling"/>
|
||||
<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="Import completed downloads in download client history"/>
|
||||
<i class="icon-nd-form-warning" title="Download client history items that are stored in the drone factory will be ignored. Configure the Drone Factory for a different path"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="x-completed-download-options advanced-setting"">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Remove</label>
|
||||
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group">
|
||||
<label class="checkbox toggle well">
|
||||
<input type="checkbox" name="removeCompletedDownloads"/>
|
||||
<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="Remove imported downloads from download client history"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="advanced-setting">
|
||||
<legend>Download Client Failed Handling</legend>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Enable</label>
|
||||
|
||||
@@ -40,7 +90,7 @@
|
||||
</label>
|
||||
|
||||
<span class="help-inline-checkbox">
|
||||
<i class="icon-nd-form-info" title="Automatically search for and attempt to download another release when a download fails?"/>
|
||||
<i class="icon-nd-form-info" title="Automatically search for and attempt to download another release"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -62,7 +112,7 @@
|
||||
</label>
|
||||
|
||||
<span class="help-inline-checkbox">
|
||||
<i class="icon-nd-form-info" title="Automatically remove failed downloads from history and encrypted downloads from queue?"/>
|
||||
<i class="icon-nd-form-info" title="Remove failed downloads from download client history"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -8,7 +8,7 @@ define(
|
||||
], function (Marionette, AsModelBoundView, AsValidatedView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Options/DownloadClientOptionsViewTemplate',
|
||||
template: 'Settings/DownloadClient/DroneFactory/DroneFactoryViewTemplate',
|
||||
|
||||
ui: {
|
||||
droneFactory : '.x-path'
|
||||
@@ -1,10 +1,10 @@
|
||||
<fieldset>
|
||||
<legend>Options</legend>
|
||||
<legend>Drone Factory Options</legend>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Drone Factory</label>
|
||||
|
||||
<div class="col-sm-1 col-sm-push-8 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-info" title="Optional folder to periodically scan for available imports"/>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
@@ -1,97 +1,96 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'vent',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Delete/DownloadClientDeleteView',
|
||||
'Commands/CommandController',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AsValidatedView',
|
||||
'underscore',
|
||||
'Form/FormBuilder',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (vent, AppLayout, Marionette, DeleteView, CommandController, AsModelBoundView, AsValidatedView, _) {
|
||||
define([
|
||||
'vent',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/DownloadClient/Delete/DownloadClientDeleteView',
|
||||
'Commands/CommandController',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AsValidatedView',
|
||||
'underscore',
|
||||
'Form/FormBuilder',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (vent, AppLayout, Marionette, DeleteView, CommandController, AsModelBoundView, AsValidatedView, _) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Edit/DownloadClientEditViewTemplate',
|
||||
var view = Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/Edit/DownloadClientEditViewTemplate',
|
||||
|
||||
ui: {
|
||||
path : '.x-path',
|
||||
modalBody : '.modal-body'
|
||||
},
|
||||
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'
|
||||
},
|
||||
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;
|
||||
},
|
||||
initialize: function (options) {
|
||||
this.targetCollection = options.targetCollection;
|
||||
},
|
||||
|
||||
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);
|
||||
onShow: function () {
|
||||
//Hack to deal with modals not overflowing
|
||||
if (this.ui.path.length > 0) {
|
||||
this.ui.modalBody.addClass('modal-overflow');
|
||||
}
|
||||
});
|
||||
|
||||
AsModelBoundView.call(view);
|
||||
AsValidatedView.call(view);
|
||||
this.ui.path.autoComplete('/directories');
|
||||
},
|
||||
|
||||
return view;
|
||||
_save: function () {
|
||||
var self = this;
|
||||
var promise = this.model.save();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.targetCollection.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.targetCollection.add(self.model, { merge: true });
|
||||
|
||||
require('Settings/DownloadClient/Add/DownloadClientSchemaModal').open(self.targetCollection);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
var view = new DeleteView({ model: this.model });
|
||||
AppLayout.modalRegion.show(view);
|
||||
},
|
||||
|
||||
_back: function () {
|
||||
require('Settings/DownloadClient/Add/DownloadClientSchemaModal').open(this.targetCollection);
|
||||
},
|
||||
|
||||
_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);
|
||||
}
|
||||
});
|
||||
|
||||
AsModelBoundView.call(view);
|
||||
AsValidatedView.call(view);
|
||||
|
||||
return view;
|
||||
});
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AsValidatedView'
|
||||
], function (Marionette, AsModelBoundView, AsValidatedView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template: 'Settings/DownloadClient/FailedDownloadHandling/FailedDownloadHandlingViewTemplate',
|
||||
|
||||
ui: {
|
||||
failedDownloadHandlingCheckbox: '.x-failed-download-handling',
|
||||
failedDownloadOptions : '.x-failed-download-options'
|
||||
},
|
||||
|
||||
events: {
|
||||
'change .x-failed-download-handling': '_setFailedDownloadOptionsVisibility'
|
||||
},
|
||||
|
||||
_setFailedDownloadOptionsVisibility: function () {
|
||||
var checked = this.ui.failedDownloadHandlingCheckbox.prop('checked');
|
||||
if (checked) {
|
||||
this.ui.failedDownloadOptions.slideDown();
|
||||
}
|
||||
|
||||
else {
|
||||
this.ui.failedDownloadOptions.slideUp();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AsModelBoundView.call(view);
|
||||
AsValidatedView.call(view);
|
||||
|
||||
return view;
|
||||
});
|
||||
14
src/UI/Settings/Indexers/Add/IndexerAddCollectionView.js
Normal file
14
src/UI/Settings/Indexers/Add/IndexerAddCollectionView.js
Normal file
@@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'Settings/ThingyAddCollectionView',
|
||||
'Settings/ThingyHeaderGroupView',
|
||||
'Settings/Indexers/Add/IndexerAddItemView'
|
||||
], function (ThingyAddCollectionView, ThingyHeaderGroupView, AddItemView) {
|
||||
|
||||
return ThingyAddCollectionView.extend({
|
||||
itemView : ThingyHeaderGroupView.extend({ itemView: AddItemView }),
|
||||
itemViewContainer: '.add-indexer .items',
|
||||
template : 'Settings/Indexers/Add/IndexerAddCollectionViewTemplate'
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Add Indexer</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="add-indexer add-thingies">
|
||||
<ul class="items"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal">close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
37
src/UI/Settings/Indexers/Add/IndexerAddItemView.js
Normal file
37
src/UI/Settings/Indexers/Add/IndexerAddItemView.js
Normal file
@@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/Indexers/Edit/IndexerEditView'
|
||||
], function ($, AppLayout, Marionette, EditView) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/Indexers/Add/IndexerAddItemViewTemplate',
|
||||
tagName : 'li',
|
||||
|
||||
events: {
|
||||
'click': '_add'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.targetCollection = options.targetCollection;
|
||||
},
|
||||
|
||||
_add: function (e) {
|
||||
if (this.$(e.target).hasClass('icon-info-sign')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.set({
|
||||
id : undefined,
|
||||
name : this.model.get('implementation'),
|
||||
enable : true
|
||||
});
|
||||
|
||||
var editView = new EditView({ model: this.model, targetCollection: this.targetCollection });
|
||||
AppLayout.modalRegion.show(editView);
|
||||
}
|
||||
});
|
||||
});
|
||||
36
src/UI/Settings/Indexers/Add/IndexerSchemaModal.js
Normal file
36
src/UI/Settings/Indexers/Add/IndexerSchemaModal.js
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'underscore',
|
||||
'AppLayout',
|
||||
'backbone',
|
||||
'Settings/Indexers/IndexerCollection',
|
||||
'Settings/Indexers/Add/IndexerAddCollectionView'
|
||||
], function (_, AppLayout, Backbone, SchemaCollection, AddCollectionView) {
|
||||
return ({
|
||||
|
||||
open: function (collection) {
|
||||
var schemaCollection = new SchemaCollection();
|
||||
var originalUrl = schemaCollection.url;
|
||||
schemaCollection.url = schemaCollection.url + '/schema';
|
||||
schemaCollection.fetch();
|
||||
schemaCollection.url = originalUrl;
|
||||
|
||||
var groupedSchemaCollection = new Backbone.Collection();
|
||||
|
||||
schemaCollection.on('sync', function() {
|
||||
|
||||
var groups = schemaCollection.groupBy(function(model, iterator) { return model.get('protocol'); });
|
||||
|
||||
var modelCollection = _.map(groups, function(values, key, list) {
|
||||
return { 'header': key, collection: values };
|
||||
});
|
||||
|
||||
groupedSchemaCollection.reset(modelCollection);
|
||||
});
|
||||
|
||||
var view = new AddCollectionView({ collection: groupedSchemaCollection, targetCollection: collection });
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'Settings/Indexers/Model',
|
||||
], function (Backbone, IndexerModel) {
|
||||
return Backbone.Collection.extend({
|
||||
url : window.NzbDrone.ApiRoot + '/indexer',
|
||||
model: IndexerModel
|
||||
});
|
||||
});
|
||||
@@ -1,52 +0,0 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/Indexers/ItemView',
|
||||
'Settings/Indexers/EditView',
|
||||
'Settings/Indexers/Collection',
|
||||
'underscore'
|
||||
], function (AppLayout, Marionette, IndexerItemView, IndexerEditView, IndexerCollection, _) {
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : IndexerItemView,
|
||||
itemViewContainer: '#x-indexers',
|
||||
template : 'Settings/Indexers/CollectionTemplate',
|
||||
|
||||
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 () {
|
||||
var self = this;
|
||||
var schemaCollection = new IndexerCollection();
|
||||
var originalUrl = schemaCollection.url;
|
||||
|
||||
schemaCollection.url = schemaCollection.url + '/schema';
|
||||
|
||||
schemaCollection.fetch({
|
||||
success: function (collection) {
|
||||
collection.url = originalUrl;
|
||||
var model = _.first(collection.models);
|
||||
|
||||
model.set({
|
||||
id : undefined,
|
||||
name : '',
|
||||
enable: true
|
||||
});
|
||||
|
||||
var view = new IndexerEditView({ model: model, indexerCollection: self.collection});
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
23
src/UI/Settings/Indexers/Delete/IndexerDeleteView.js
Normal file
23
src/UI/Settings/Indexers/Delete/IndexerDeleteView.js
Normal file
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'vent',
|
||||
'marionette'
|
||||
], function (vent, Marionette) {
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/Indexers/Delete/IndexerDeleteViewTemplate',
|
||||
|
||||
events: {
|
||||
'click .x-confirm-delete': '_delete'
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
this.model.destroy({
|
||||
wait : true,
|
||||
success: function () {
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'vent',
|
||||
'marionette'
|
||||
], function (vent, Marionette) {
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/Indexers/DeleteViewTemplate',
|
||||
|
||||
events: {
|
||||
'click .x-confirm-delete': '_removeNotification'
|
||||
},
|
||||
|
||||
_removeNotification: function () {
|
||||
this.model.destroy({
|
||||
wait : true,
|
||||
success: function () {
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
86
src/UI/Settings/Indexers/Edit/IndexerEditView.js
Normal file
86
src/UI/Settings/Indexers/Edit/IndexerEditView.js
Normal file
@@ -0,0 +1,86 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'vent',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/Indexers/Delete/IndexerDeleteView',
|
||||
'Commands/CommandController',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AsValidatedView',
|
||||
'underscore',
|
||||
'Form/FormBuilder',
|
||||
'Mixins/AutoComplete',
|
||||
'bootstrap'
|
||||
], function (vent, AppLayout, Marionette, DeleteView, CommandController, AsModelBoundView, AsValidatedView, _) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template: 'Settings/Indexers/Edit/IndexerEditViewTemplate',
|
||||
|
||||
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.targetCollection = options.targetCollection;
|
||||
},
|
||||
|
||||
_save: function () {
|
||||
var self = this;
|
||||
var promise = this.model.save();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.targetCollection.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.targetCollection.add(self.model, { merge: true });
|
||||
|
||||
require('Settings/Indexers/Add/IndexerSchemaModal').open(self.targetCollection);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
var view = new DeleteView({ model: this.model });
|
||||
AppLayout.modalRegion.show(view);
|
||||
},
|
||||
|
||||
_back: function () {
|
||||
if (this.model.isNew()) {
|
||||
this.model.destroy();
|
||||
}
|
||||
|
||||
require('Settings/Indexers/Add/IndexerSchemaModal').open(this.targetCollection);
|
||||
},
|
||||
|
||||
_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);
|
||||
}
|
||||
});
|
||||
|
||||
AsModelBoundView.call(view);
|
||||
AsValidatedView.call(view);
|
||||
|
||||
return view;
|
||||
});
|
||||
@@ -1,14 +1,14 @@
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close x-cancel"aria-hidden="true">×</button>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
{{#if id}}
|
||||
<h3>Edit</h3>
|
||||
<h3>Edit - {{implementation}}</h3>
|
||||
{{else}}
|
||||
<h3>Add Newznab</h3>
|
||||
<h3>Add - {{implementation}}</h3>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-body indexer-modal">
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Name</label>
|
||||
@@ -41,12 +41,14 @@
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
{{#if id}}
|
||||
<button class="btn btn-danger pull-left x-remove">delete</button>
|
||||
<button class="btn btn-danger pull-left x-delete">delete</button>
|
||||
{{else}}
|
||||
<button class="btn pull-left x-back">back</button>
|
||||
{{/if}}
|
||||
|
||||
<span class="x-activity"></span>
|
||||
|
||||
<button class="btn x-cancel">cancel</button>
|
||||
<!-- Testing is currently not yet supported for indexers, but leaving the infrastructure for later -->
|
||||
<!-- <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>
|
||||
@@ -1,86 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'vent',
|
||||
'marionette',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AsValidatedView',
|
||||
'underscore'
|
||||
], function (vent, Marionette, AsModelBoundView, AsValidatedView, _) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template: 'Settings/Indexers/EditTemplate',
|
||||
|
||||
ui: {
|
||||
activity: '.x-activity'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-save' : '_save',
|
||||
'click .x-save-and-add': '_saveAndAdd',
|
||||
'click .x-cancel' : '_cancel'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.indexerCollection = options.indexerCollection;
|
||||
},
|
||||
|
||||
_save: function () {
|
||||
this.ui.activity.html('<i class="icon-nd-spinner"></i>');
|
||||
|
||||
var self = this;
|
||||
var promise = this.model.saveSettings();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.indexerCollection.add(self.model, { merge: true });
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
});
|
||||
|
||||
promise.fail(function () {
|
||||
self.ui.activity.empty();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_saveAndAdd: function () {
|
||||
this.ui.activity.html('<i class="icon-nd-spinner"></i>');
|
||||
|
||||
var self = this;
|
||||
var promise = this.model.saveSettings();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.indexerCollection.add(self.model, { merge: true });
|
||||
|
||||
self.model.set({
|
||||
id : undefined,
|
||||
name : '',
|
||||
enable: false
|
||||
});
|
||||
|
||||
_.each(self.model.get('fields'), function (value, key, list) {
|
||||
self.model.set('fields.' + key + '.value', '');
|
||||
});
|
||||
});
|
||||
|
||||
promise.fail(function () {
|
||||
self.ui.activity.empty();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_cancel: function () {
|
||||
if (this.model.isNew()) {
|
||||
this.model.destroy();
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AsModelBoundView.call(view);
|
||||
AsValidatedView.call(view);
|
||||
|
||||
return view;
|
||||
});
|
||||
31
src/UI/Settings/Indexers/IndexerCollection.js
Normal file
31
src/UI/Settings/Indexers/IndexerCollection.js
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'Settings/Indexers/IndexerModel'
|
||||
], function (Backbone, IndexerModel) {
|
||||
|
||||
return Backbone.Collection.extend({
|
||||
model: IndexerModel,
|
||||
url : window.NzbDrone.ApiRoot + '/indexer',
|
||||
|
||||
comparator : function(left, right, collection) {
|
||||
|
||||
var result = 0;
|
||||
|
||||
if (left.get('protocol')) {
|
||||
result = -left.get('protocol').localeCompare(right.get('protocol'));
|
||||
}
|
||||
|
||||
if (result === 0 && left.get('name')) {
|
||||
result = left.get('name').localeCompare(right.get('name'));
|
||||
}
|
||||
|
||||
if (result === 0) {
|
||||
result = left.get('implementation').localeCompare(right.get('implementation'));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
});
|
||||
29
src/UI/Settings/Indexers/IndexerCollectionView.js
Normal file
29
src/UI/Settings/Indexers/IndexerCollectionView.js
Normal file
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'marionette',
|
||||
'Settings/Indexers/IndexerItemView',
|
||||
'Settings/Indexers/Add/IndexerSchemaModal'
|
||||
], function (Marionette, ItemView, SchemaModal) {
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : ItemView,
|
||||
itemViewContainer: '.indexer-list',
|
||||
template : 'Settings/Indexers/IndexerCollectionViewTemplate',
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -2,11 +2,11 @@
|
||||
<legend>Indexers</legend>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<ul id="x-indexers" class="indexer-list thingies">
|
||||
<ul class="indexer-list thingies">
|
||||
<li>
|
||||
<div class="indexer-settings-item add-card x-add-card">
|
||||
<div class="indexer-item thingy add-card x-add-card">
|
||||
<span class="center well">
|
||||
<i class="icon-plus" title="Add Newznab"/>
|
||||
<i class="icon-plus" title="Add Indexer"/>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
26
src/UI/Settings/Indexers/IndexerItemView.js
Normal file
26
src/UI/Settings/Indexers/IndexerItemView.js
Normal file
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/Indexers/Edit/IndexerEditView'
|
||||
], function (AppLayout, Marionette, EditView) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/Indexers/IndexerItemViewTemplate',
|
||||
tagName : 'li',
|
||||
|
||||
events: {
|
||||
'click' : '_edit'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.listenTo(this.model, 'sync', this.render);
|
||||
},
|
||||
|
||||
_edit: function () {
|
||||
var view = new EditView({ model: this.model, targetCollection: this.model.collection });
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
});
|
||||
13
src/UI/Settings/Indexers/IndexerItemViewTemplate.html
Normal file
13
src/UI/Settings/Indexers/IndexerItemViewTemplate.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<div class="indexer-item thingy" title="Click to edit">
|
||||
<div>
|
||||
<h3>{{name}}</h3>
|
||||
</div>
|
||||
|
||||
<div class="settings">
|
||||
{{#if enable}}
|
||||
<span class="label label-success">Enabled</span>
|
||||
{{else}}
|
||||
<span class="label label-default">Not Enabled</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,28 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'marionette',
|
||||
'Settings/Indexers/CollectionView',
|
||||
'Settings/Indexers/Options/IndexerOptionsView'
|
||||
], function (Marionette, CollectionView, OptionsView) {
|
||||
return Marionette.Layout.extend({
|
||||
template: 'Settings/Indexers/IndexerLayoutTemplate',
|
||||
define([
|
||||
'marionette',
|
||||
'Settings/Indexers/IndexerCollection',
|
||||
'Settings/Indexers/IndexerCollectionView',
|
||||
'Settings/Indexers/Options/IndexerOptionsView'
|
||||
], function (Marionette, IndexerCollection, CollectionView, OptionsView) {
|
||||
|
||||
regions: {
|
||||
indexersRegion : '#indexers-collection',
|
||||
indexerOptions : '#indexer-options'
|
||||
},
|
||||
return Marionette.Layout.extend({
|
||||
template: 'Settings/Indexers/IndexerLayoutTemplate',
|
||||
|
||||
initialize: function (options) {
|
||||
this.settings = options.settings;
|
||||
this.indexersCollection = options.indexersCollection;
|
||||
},
|
||||
regions: {
|
||||
indexers : '#x-indexers-region',
|
||||
indexerOptions : '#x-indexer-options-region'
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.indexersRegion.show(new CollectionView({ collection: this.indexersCollection }));
|
||||
this.indexerOptions.show(new OptionsView({ model: this.settings }));
|
||||
}
|
||||
});
|
||||
initialize: function (options) {
|
||||
this.indexersCollection = new IndexerCollection();
|
||||
this.indexersCollection.fetch();
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
this.indexers.show(new CollectionView({ collection: this.indexersCollection }));
|
||||
this.indexerOptions.show(new OptionsView({ model: this.model }));
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<div id="indexers-collection"></div>
|
||||
|
||||
<div id="x-indexers-region"></div>
|
||||
<div class="form-horizontal">
|
||||
<div id="indexer-options"></div>
|
||||
<div id="x-indexer-options-region"></div>
|
||||
</div>
|
||||
|
||||
9
src/UI/Settings/Indexers/IndexerModel.js
Normal file
9
src/UI/Settings/Indexers/IndexerModel.js
Normal file
@@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone.deepmodel'
|
||||
], function (DeepModel) {
|
||||
return DeepModel.DeepModel.extend({
|
||||
|
||||
});
|
||||
});
|
||||
@@ -1,11 +1,11 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'Settings/SettingsModelBase'
|
||||
], function (SettingsModelBase) {
|
||||
return SettingsModelBase.extend({
|
||||
url : window.NzbDrone.ApiRoot + '/config/indexer',
|
||||
successMessage: 'Indexer settings saved',
|
||||
errorMessage : 'Failed to save indexer settings'
|
||||
});
|
||||
|
||||
define([
|
||||
'Settings/SettingsModelBase'
|
||||
], function (SettingsModelBase) {
|
||||
return SettingsModelBase.extend({
|
||||
url : window.NzbDrone.ApiRoot + '/config/indexer',
|
||||
successMessage: 'Indexer settings saved',
|
||||
errorMessage : 'Failed to save indexer settings'
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
<div class="indexer-settings-item thingy">
|
||||
<div>
|
||||
<h3>{{name}}</h3>
|
||||
{{#if_eq implementation compare="Newznab"}}
|
||||
<span class="btn-group pull-right">
|
||||
<button class="btn btn-xs btn-icon-only x-delete">
|
||||
<i class="icon-nd-delete"/>
|
||||
</button>
|
||||
</span>
|
||||
{{/if_eq}}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label">Enable</label>
|
||||
|
||||
<div class="input-group">
|
||||
<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}}
|
||||
|
||||
{{#if_eq name compare="WomblesIndex"}}
|
||||
<div class="alert">
|
||||
<i class="icon-nd-warning"></i>
|
||||
Does not support searching
|
||||
</div>
|
||||
{{/if_eq}}
|
||||
</div>
|
||||
@@ -1,29 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/Indexers/DeleteView',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AsValidatedView'
|
||||
], function (AppLayout, Marionette, DeleteView, AsModelBoundView, AsValidatedView) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template: 'Settings/Indexers/ItemTemplate',
|
||||
tagName : 'li',
|
||||
|
||||
events: {
|
||||
'click .x-delete': '_deleteIndexer'
|
||||
},
|
||||
|
||||
_deleteIndexer: function () {
|
||||
var view = new DeleteView({ model: this.model});
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
|
||||
AsModelBoundView.call(view);
|
||||
return AsValidatedView.call(view);
|
||||
|
||||
});
|
||||
@@ -1,24 +0,0 @@
|
||||
'use strict';
|
||||
define([
|
||||
'Settings/SettingsModelBase'], function (ModelBase) {
|
||||
return ModelBase.extend({
|
||||
|
||||
baseInitialize: ModelBase.prototype.initialize,
|
||||
|
||||
initialize: function () {
|
||||
var name = this.get('name');
|
||||
|
||||
if (name) {
|
||||
this.successMessage = 'Saved indexer: ' + name;
|
||||
this.errorMessage = 'Couldn\'t save indexer: ' + name;
|
||||
}
|
||||
|
||||
else {
|
||||
this.successMessage = 'Saved indexer';
|
||||
this.errorMessage = 'Couldn\'t save indexer';
|
||||
}
|
||||
|
||||
this.baseInitialize.call(this);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,29 +1,33 @@
|
||||
.indexer-settings-item {
|
||||
@import "../../Shared/Styles/clickable.less";
|
||||
|
||||
width: 220px;
|
||||
height: 295px;
|
||||
.indexer-list {
|
||||
li {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.indexer-item {
|
||||
|
||||
.clickable;
|
||||
|
||||
width: 290px;
|
||||
height: 90px;
|
||||
padding: 10px 15px;
|
||||
|
||||
h3 {
|
||||
width: 175px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
&.add-card {
|
||||
margin-top: 10px;
|
||||
margin-left: 10px;
|
||||
|
||||
.center {
|
||||
margin-top: 90px;
|
||||
margin-top: -3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Super hack to keep using form builder, this should be dead when we do proper modals for editing */
|
||||
.col-sm-1, .col-sm-3, .col-sm-5 {
|
||||
display : block;
|
||||
width : 100%;
|
||||
padding: 0px;
|
||||
float: none;
|
||||
position: inherit;
|
||||
.modal-overflow {
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
.add-indexer {
|
||||
li {
|
||||
width: 33%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'Settings/ThingyAddCollectionView',
|
||||
'Settings/Notifications/Add/NotificationAddItemView'
|
||||
], function (ThingyAddCollectionView, AddItemView) {
|
||||
|
||||
return ThingyAddCollectionView.extend({
|
||||
itemView : AddItemView,
|
||||
itemViewContainer: '.add-notifications .items',
|
||||
template : 'Settings/Notifications/Add/NotificationAddCollectionViewTemplate'
|
||||
});
|
||||
});
|
||||
@@ -1,37 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/Notifications/NotificationEditView'
|
||||
], function (AppLayout, Marionette, EditView) {
|
||||
'Settings/Notifications/Edit/NotificationEditView'
|
||||
], function ($, AppLayout, Marionette, EditView) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/Notifications/AddItemTemplate',
|
||||
template: 'Settings/Notifications/Add/NotificationAddItemViewTemplate',
|
||||
tagName : 'li',
|
||||
|
||||
events: {
|
||||
'click': 'addNotification'
|
||||
'click': '_add'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.notificationCollection = options.notificationCollection;
|
||||
this.targetCollection = options.targetCollection;
|
||||
},
|
||||
|
||||
addNotification: function (e) {
|
||||
_add: function (e) {
|
||||
if (this.$(e.target).hasClass('icon-info-sign')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.set({
|
||||
id : undefined,
|
||||
name : this.model.get('implementationName'),
|
||||
name : this.model.get('implementation'),
|
||||
onGrab : true,
|
||||
onDownload : true,
|
||||
onUpgrade : true
|
||||
});
|
||||
|
||||
var editView = new EditView({ model: this.model, notificationCollection: this.notificationCollection });
|
||||
var editView = new EditView({ model: this.model, targetCollection: this.targetCollection });
|
||||
AppLayout.modalRegion.show(editView);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
<div class="add-thingy">
|
||||
{{implementation}}
|
||||
{{#if link}}
|
||||
<a href="{{link}}"><i class="icon-info-sign"/></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
21
src/UI/Settings/Notifications/Add/NotificationSchemaModal.js
Normal file
21
src/UI/Settings/Notifications/Add/NotificationSchemaModal.js
Normal file
@@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'AppLayout',
|
||||
'Settings/Notifications/NotificationCollection',
|
||||
'Settings/Notifications/Add/NotificationAddCollectionView'
|
||||
], function (AppLayout, SchemaCollection, AddCollectionView) {
|
||||
return ({
|
||||
|
||||
open: function (collection) {
|
||||
var schemaCollection = new SchemaCollection();
|
||||
var originalUrl = schemaCollection.url;
|
||||
schemaCollection.url = schemaCollection.url + '/schema';
|
||||
schemaCollection.fetch();
|
||||
schemaCollection.url = originalUrl;
|
||||
|
||||
var view = new AddCollectionView({ collection: schemaCollection, targetCollection: collection});
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'marionette',
|
||||
'Settings/Notifications/AddItemView'
|
||||
], function (Marionette, AddItemView) {
|
||||
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : AddItemView,
|
||||
itemViewContainer: '.add-notifications .items',
|
||||
template : 'Settings/Notifications/AddTemplate',
|
||||
|
||||
itemViewOptions: function () {
|
||||
return {
|
||||
notificationCollection: this.notificationCollection
|
||||
};
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.notificationCollection = options.notificationCollection;
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'backbone',
|
||||
'Settings/Notifications/Model'
|
||||
], function (Backbone, NotificationModel) {
|
||||
return Backbone.Collection.extend({
|
||||
url : window.NzbDrone.ApiRoot + '/notification',
|
||||
model: NotificationModel
|
||||
});
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<ul class="notifications thingies">
|
||||
<li>
|
||||
<div class="notification-item thingy add-card x-add-card">
|
||||
<span class="center well">
|
||||
<i class="icon-plus" title="Add Connection"/>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,28 +0,0 @@
|
||||
'use strict';
|
||||
define([
|
||||
'marionette',
|
||||
'Settings/Notifications/NotificationsItemView',
|
||||
'Settings/Notifications/SchemaModal'
|
||||
], function (Marionette, NotificationItemView, SchemaModal) {
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : NotificationItemView,
|
||||
itemViewContainer: '.notifications',
|
||||
template : 'Settings/Notifications/CollectionTemplate',
|
||||
|
||||
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,23 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'vent',
|
||||
'marionette'
|
||||
], function (vent, Marionette) {
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/Notifications/Delete/NotificationDeleteViewTemplate',
|
||||
|
||||
events: {
|
||||
'click .x-confirm-delete': '_delete'
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
this.model.destroy({
|
||||
wait : true,
|
||||
success: function () {
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
'use strict';
|
||||
define(
|
||||
[
|
||||
'vent',
|
||||
'marionette'
|
||||
], function (vent, Marionette) {
|
||||
return Marionette.ItemView.extend({
|
||||
template: 'Settings/Notifications/DeleteTemplate',
|
||||
|
||||
events: {
|
||||
'click .x-confirm-delete': '_removeNotification'
|
||||
},
|
||||
|
||||
_removeNotification: function () {
|
||||
this.model.destroy({
|
||||
wait : true,
|
||||
success: function () {
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
113
src/UI/Settings/Notifications/Edit/NotificationEditView.js
Normal file
113
src/UI/Settings/Notifications/Edit/NotificationEditView.js
Normal file
@@ -0,0 +1,113 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'vent',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/Notifications/Delete/NotificationDeleteView',
|
||||
'Commands/CommandController',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AsValidatedView',
|
||||
'underscore',
|
||||
'Form/FormBuilder'
|
||||
], function (vent, AppLayout, Marionette, DeleteView, CommandController, AsModelBoundView, AsValidatedView, _) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template: 'Settings/Notifications/Edit/NotificationEditViewTemplate',
|
||||
|
||||
ui: {
|
||||
onDownloadToggle: '.x-on-download',
|
||||
onUpgradeSection: '.x-on-upgrade'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-save' : '_save',
|
||||
'click .x-save-and-add': '_saveAndAdd',
|
||||
'click .x-delete' : '_delete',
|
||||
'click .x-back' : '_back',
|
||||
'click .x-cancel' : '_cancel',
|
||||
'click .x-test' : '_test',
|
||||
'change .x-on-download': '_onDownloadChanged'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.targetCollection = options.targetCollection;
|
||||
},
|
||||
|
||||
onRender: function () {
|
||||
this._onDownloadChanged();
|
||||
},
|
||||
|
||||
_save: function () {
|
||||
var self = this;
|
||||
var promise = this.model.save();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.targetCollection.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.targetCollection.add(self.model, { merge: true });
|
||||
|
||||
require('Settings/Notifications/Add/NotificationSchemaModal').open(self.targetCollection);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_delete: function () {
|
||||
var view = new DeleteView({ model: this.model });
|
||||
AppLayout.modalRegion.show(view);
|
||||
},
|
||||
|
||||
_back: function () {
|
||||
if (this.model.isNew()) {
|
||||
this.model.destroy();
|
||||
}
|
||||
|
||||
require('Settings/Notifications/Add/NotificationSchemaModal').open(this.targetCollection);
|
||||
},
|
||||
|
||||
_cancel: function () {
|
||||
if (this.model.isNew()) {
|
||||
this.model.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
_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);
|
||||
},
|
||||
|
||||
_onDownloadChanged: function () {
|
||||
var checked = this.ui.onDownloadToggle.prop('checked');
|
||||
|
||||
if (checked) {
|
||||
this.ui.onUpgradeSection.show();
|
||||
}
|
||||
|
||||
else {
|
||||
this.ui.onUpgradeSection.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AsModelBoundView.call(view);
|
||||
AsValidatedView.call(view);
|
||||
|
||||
return view;
|
||||
});
|
||||
@@ -1,14 +1,14 @@
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close x-cancel" aria-hidden="true">×</button>
|
||||
<button type="button" class="close x-cancel" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
{{#if id}}
|
||||
<h3>Edit - {{implementation}}</h3>
|
||||
{{else}}
|
||||
<h3>Add - {{implementation}}</h3>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-body notification-modal">
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Name</label>
|
||||
@@ -95,7 +95,7 @@
|
||||
{{/if}}
|
||||
|
||||
<button class="btn x-test">test <i class="x-test-icon icon-nd-test"/></button>
|
||||
<button class="btn x-cancel">cancel</button>
|
||||
<button class="btn x-cancel" data-dismiss="modal">cancel</button>
|
||||
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-primary x-save">save</button>
|
||||
13
src/UI/Settings/Notifications/NotificationCollection.js
Normal file
13
src/UI/Settings/Notifications/NotificationCollection.js
Normal file
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'Settings/Notifications/NotificationModel'
|
||||
], function (Backbone, NotificationModel) {
|
||||
|
||||
return Backbone.Collection.extend({
|
||||
model: NotificationModel,
|
||||
url : window.NzbDrone.ApiRoot + '/notification'
|
||||
|
||||
});
|
||||
});
|
||||
29
src/UI/Settings/Notifications/NotificationCollectionView.js
Normal file
29
src/UI/Settings/Notifications/NotificationCollectionView.js
Normal file
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'marionette',
|
||||
'Settings/Notifications/NotificationItemView',
|
||||
'Settings/Notifications/Add/NotificationSchemaModal'
|
||||
], function (Marionette, ItemView, SchemaModal) {
|
||||
return Marionette.CompositeView.extend({
|
||||
itemView : ItemView,
|
||||
itemViewContainer: '.notification-list',
|
||||
template : 'Settings/Notifications/NotificationCollectionViewTemplate',
|
||||
|
||||
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>Connections</legend>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<ul class="notification-list thingies">
|
||||
<li>
|
||||
<div class="notification-item thingy add-card x-add-card">
|
||||
<span class="center well">
|
||||
<i class="icon-plus" title="Add Connection"/>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
@@ -1,113 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
define(
|
||||
[
|
||||
'vent',
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/Notifications/DeleteView',
|
||||
'Commands/CommandController',
|
||||
'Mixins/AsModelBoundView',
|
||||
'underscore',
|
||||
'Form/FormBuilder'
|
||||
|
||||
], function (vent, AppLayout, Marionette, DeleteView, CommandController, AsModelBoundView, _) {
|
||||
|
||||
var model = Marionette.ItemView.extend({
|
||||
template: 'Settings/Notifications/NotificationEditViewTemplate',
|
||||
|
||||
ui: {
|
||||
onDownloadToggle: '.x-on-download',
|
||||
onUpgradeSection: '.x-on-upgrade'
|
||||
},
|
||||
|
||||
events: {
|
||||
'click .x-save' : '_saveClient',
|
||||
'click .x-save-and-add': '_saveAndAddNotification',
|
||||
'click .x-delete' : '_deleteNotification',
|
||||
'click .x-back' : '_back',
|
||||
'click .x-test' : '_test',
|
||||
'click .x-cancel' : '_cancel',
|
||||
'change .x-on-download': '_onDownloadChanged'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.notificationCollection = options.notificationCollection;
|
||||
},
|
||||
|
||||
onRender: function () {
|
||||
this._onDownloadChanged();
|
||||
},
|
||||
|
||||
_saveClient: function () {
|
||||
var self = this;
|
||||
var promise = this.model.saveSettings();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.notificationCollection.add(self.model, { merge: true });
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_saveAndAddNotification: function () {
|
||||
var self = this;
|
||||
var promise = this.model.saveSettings();
|
||||
|
||||
if (promise) {
|
||||
promise.done(function () {
|
||||
self.notificationCollection.add(self.model, { merge: true });
|
||||
|
||||
require('Settings/Notifications/SchemaModal').open(self.notificationCollection);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_cancel: function () {
|
||||
if (this.model.isNew()) {
|
||||
this.model.destroy();
|
||||
}
|
||||
|
||||
vent.trigger(vent.Commands.CloseModalCommand);
|
||||
},
|
||||
|
||||
_deleteNotification: function () {
|
||||
var view = new DeleteView({ model: this.model });
|
||||
AppLayout.modalRegion.show(view);
|
||||
},
|
||||
|
||||
_back: function () {
|
||||
if (this.model.isNew()) {
|
||||
this.model.destroy();
|
||||
}
|
||||
|
||||
require('Settings/Notifications/SchemaModal').open(this.notificationCollection);
|
||||
},
|
||||
|
||||
_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);
|
||||
},
|
||||
|
||||
_onDownloadChanged: function () {
|
||||
var checked = this.ui.onDownloadToggle.prop('checked');
|
||||
|
||||
if (checked) {
|
||||
this.ui.onUpgradeSection.show();
|
||||
}
|
||||
|
||||
else {
|
||||
this.ui.onUpgradeSection.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return AsModelBoundView.call(model);
|
||||
});
|
||||
@@ -3,8 +3,7 @@
|
||||
define([
|
||||
'AppLayout',
|
||||
'marionette',
|
||||
'Settings/Notifications/NotificationEditView'
|
||||
|
||||
'Settings/Notifications/Edit/NotificationEditView'
|
||||
], function (AppLayout, Marionette, EditView) {
|
||||
|
||||
return Marionette.ItemView.extend({
|
||||
@@ -12,15 +11,15 @@ define([
|
||||
tagName : 'li',
|
||||
|
||||
events: {
|
||||
'click' : '_editNotification'
|
||||
'click' : '_edit'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.listenTo(this.model, 'sync', this.render);
|
||||
},
|
||||
|
||||
_editNotification: function () {
|
||||
var view = new EditView({ model: this.model, notificationCollection: this.model.collection});
|
||||
_edit: function () {
|
||||
var view = new EditView({ model: this.model, targetCollection: this.model.collection});
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
define([
|
||||
'Settings/SettingsModelBase'], function (ModelBase) {
|
||||
'Settings/SettingsModelBase'
|
||||
], function (ModelBase) {
|
||||
return ModelBase.extend({
|
||||
|
||||
successMessage: 'Notification Saved',
|
||||
@@ -1,20 +0,0 @@
|
||||
'use strict';
|
||||
define([
|
||||
'AppLayout',
|
||||
'Settings/Notifications/Collection',
|
||||
'Settings/Notifications/AddView'
|
||||
], function (AppLayout, NotificationCollection, AddSelectionNotificationView) {
|
||||
return ({
|
||||
|
||||
open: function (collection) {
|
||||
var schemaCollection = new NotificationCollection();
|
||||
var orginalUrl = schemaCollection.url;
|
||||
schemaCollection.url = schemaCollection.url + '/schema';
|
||||
schemaCollection.fetch();
|
||||
schemaCollection.url = orginalUrl;
|
||||
|
||||
var view = new AddSelectionNotificationView({ collection: schemaCollection, notificationCollection: collection});
|
||||
AppLayout.modalRegion.show(view);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -12,12 +12,12 @@ define(
|
||||
'Settings/MediaManagement/MediaManagementSettingsModel',
|
||||
'Settings/Quality/QualityLayout',
|
||||
'Settings/Indexers/IndexerLayout',
|
||||
'Settings/Indexers/Collection',
|
||||
'Settings/Indexers/IndexerCollection',
|
||||
'Settings/Indexers/IndexerSettingsModel',
|
||||
'Settings/DownloadClient/DownloadClientLayout',
|
||||
'Settings/DownloadClient/DownloadClientSettingsModel',
|
||||
'Settings/Notifications/CollectionView',
|
||||
'Settings/Notifications/Collection',
|
||||
'Settings/Notifications/NotificationCollectionView',
|
||||
'Settings/Notifications/NotificationCollection',
|
||||
'Settings/Metadata/MetadataLayout',
|
||||
'Settings/General/GeneralView',
|
||||
'Shared/LoadingView',
|
||||
@@ -93,7 +93,6 @@ define(
|
||||
this.mediaManagementSettings = new MediaManagementSettingsModel();
|
||||
this.namingSettings = new NamingModel();
|
||||
this.indexerSettings = new IndexerSettingsModel();
|
||||
this.indexerCollection = new IndexerCollection();
|
||||
this.downloadClientSettings = new DownloadClientSettingsModel();
|
||||
this.notificationCollection = new NotificationCollection();
|
||||
this.generalSettings = new GeneralSettingsModel();
|
||||
@@ -102,7 +101,6 @@ define(
|
||||
this.mediaManagementSettings.fetch(),
|
||||
this.namingSettings.fetch(),
|
||||
this.indexerSettings.fetch(),
|
||||
this.indexerCollection.fetch(),
|
||||
this.downloadClientSettings.fetch(),
|
||||
this.notificationCollection.fetch(),
|
||||
this.generalSettings.fetch()
|
||||
@@ -112,7 +110,7 @@ define(
|
||||
self.loading.$el.hide();
|
||||
self.mediaManagement.show(new MediaManagementLayout({ settings: self.mediaManagementSettings, namingSettings: self.namingSettings }));
|
||||
self.quality.show(new QualityLayout());
|
||||
self.indexers.show(new IndexerLayout({ settings: self.indexerSettings, indexersCollection: self.indexerCollection }));
|
||||
self.indexers.show(new IndexerLayout({ model: self.indexerSettings }));
|
||||
self.downloadClient.show(new DownloadClientLayout({ model: self.downloadClientSettings }));
|
||||
self.notifications.show(new NotificationCollectionView({ collection: self.notificationCollection }));
|
||||
self.metadata.show(new MetadataLayout());
|
||||
|
||||
18
src/UI/Settings/ThingyAddCollectionView.js
Normal file
18
src/UI/Settings/ThingyAddCollectionView.js
Normal file
@@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'marionette'
|
||||
], function (Marionette) {
|
||||
|
||||
return Marionette.CompositeView.extend({
|
||||
itemViewOptions : function () {
|
||||
return {
|
||||
targetCollection: this.targetCollection || this.options.targetCollection
|
||||
};
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.targetCollection = options.targetCollection;
|
||||
}
|
||||
});
|
||||
});
|
||||
23
src/UI/Settings/ThingyHeaderGroupView.js
Normal file
23
src/UI/Settings/ThingyHeaderGroupView.js
Normal file
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'backbone',
|
||||
'marionette'
|
||||
], function (Backbone, Marionette) {
|
||||
|
||||
return Marionette.CompositeView.extend({
|
||||
itemViewContainer: '.item-list',
|
||||
template: 'Settings/ThingyHeaderGroupViewTemplate',
|
||||
tagName : 'div',
|
||||
|
||||
itemViewOptions: function () {
|
||||
return {
|
||||
targetCollection: this.targetCollection || this.options.targetCollection
|
||||
};
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.collection = new Backbone.Collection(this.model.get('collection'));
|
||||
}
|
||||
});
|
||||
});
|
||||
2
src/UI/Settings/ThingyHeaderGroupViewTemplate.html
Normal file
2
src/UI/Settings/ThingyHeaderGroupViewTemplate.html
Normal file
@@ -0,0 +1,2 @@
|
||||
<legend>{{header}}</legend>
|
||||
<ul class="item-list" />
|
||||
@@ -25,6 +25,11 @@
|
||||
.add-thingies {
|
||||
text-align: center;
|
||||
|
||||
legend {
|
||||
text-align: left;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.items {
|
||||
list-style-type: none;
|
||||
margin: 0px;
|
||||
|
||||
Reference in New Issue
Block a user