more backbone changes.

This commit is contained in:
Keivan Beigi 2013-01-25 09:54:45 -08:00 committed by kay.one
parent 13194704b4
commit e720094f9c
14 changed files with 9087 additions and 5 deletions

View File

@ -137,7 +137,7 @@ namespace NzbDrone.Core.Datastore
return;
}
logger.WarnException(
"Safe recovery failed. will attempts a more aggressive strategy. might case loss of data.",
"Safe recovery failed. will attempts a more aggressive strategy. might cause loss of data.",
e);
sqlEngine.Repair(connectionString, RepairOption.DeleteCorruptedRows);
logger.Warn("Database was recovered. some data might have been lost");

View File

@ -271,6 +271,8 @@
<Content Include="_backboneApp\Content\Images\spinner.gif" />
<Content Include="_backboneApp\Content\Images\thetvdb.png" />
<Content Include="_backboneApp\Content\Menu.css" />
<Content Include="_backboneApp\JsLibraries\backbone.mutators.js" />
<Content Include="_backboneApp\JsLibraries\backbone.shortcuts.js" />
<Content Include="_backboneApp\JsLibraries\bootstrap.js" />
<Content Include="Content\DataTables-NzbDrone\media\images\sort_both.png" />
<Content Include="Content\DataTables-NzbDrone\media\images\sort_desc_disabled.png" />
@ -388,6 +390,7 @@
<Content Include="_backboneApp\JsLibraries\backbone.debug.js" />
<Content Include="_backboneApp\JsLibraries\jquery.js" />
<Content Include="_backboneApp\JsLibraries\jquery-ui-1.9.0.js" />
<Content Include="_backboneApp\JsLibraries\sugar.js" />
<Content Include="_backboneApp\JsLibraries\underscore.js" />
<Content Include="Views\System\Index.cshtml" />
<Content Include="Views\System\Logs.cshtml" />

View File

@ -1,5 +1,7 @@
<td name="Path" class="span10" />
<td name="FreeSpace" class="span3" />
<td class="span3">
<span name="FreeSpaceString"></span>
</td>
<td class="span1 nz-row-action">
<div id="remove-dir" class="btn btn-danger icon-minus">
</div>

View File

@ -1,4 +1,14 @@
/// <reference path="../../app.js" />
/// <reference path="../../app.js" />
NzbDrone.AddSeries.RootDirModel = Backbone.Model.extend({
idAttribute: 'Id',
mutators: {
FreeSpaceString: function () {
return this.get('FreeSpace').bytes(2) + " Free";
}
},
defaults: {
FreeSpace: 0,
}
});

View File

@ -1,7 +1,7 @@
<div class="tab-pane" id="root-dir">
<div class="input-prepend input-append nz-input-large path">
<i class="add-on icon-folder-open"></i>
<input type="text" class="span10" placeholder="Path of the root folder you would like to add">
<input type="text" class="span10" placeholder="Path of the folder to add ...">
<div id="add-dir" class="btn icon-plus btn-success" />
</div>
<div class="span15 offset2 result-list" id="current-dirs" />

View File

@ -45,6 +45,10 @@ NzbDrone.AddSeries.RootDirView = Backbone.Marionette.Layout.extend({
'click #add-dir': 'addDir',
},
shortcuts: {
'enter': 'addDir'
},
collection: new NzbDrone.AddSeries.RootDirCollection(),

View File

@ -4,7 +4,7 @@
<ul class="nav nav-tabs" id="myTab">
<li class="active"><a href="#add-new">Add New Series</a></li>
<li><a href="#import-existing">Import Existing Series</a></li>
<li><a href="#root-folders">Root Folders</a></li>
<li><a href="#root-folders">TV Folders</a></li>
</ul>
<div class="tab-content nz-center">
<div class="tab-pane active" id="add-new">Add new series.</div>

View File

@ -9,6 +9,7 @@
jQuery.ajax({
url: '_backboneApp//' + templateId + '.html',
cache:false,
async: false
}).done(function (data) {

View File

@ -0,0 +1,174 @@
(function (root, define, require, exports, module, factory, undef) {
'use strict';
if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like enviroments that support module.exports,
// like Node.
module.exports = factory(require('underscore'), require('backbone'));
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['underscore', 'backbone'], function (_, Backbone) {
// Check if we use the AMD branch of Back
_ = _ === undef ? root._ : _;
Backbone = Backbone === undef ? root.Backbone : Backbone;
return (root.returnExportsGlobal = factory(_, Backbone, root));
});
} else {
// Browser globals
root.returnExportsGlobal = factory(root._, root.Backbone);
}
// Usage:
//
// Note: This plugin is UMD compatible, you can use it in node, amd and vanilla js envs
//
// Vanilla JS:
// <script src="underscore.js"></script>
// <script src="backbone.js"></script>
// <script src="backbone.mutators.js"></script>
//
// Node:
// var _ = require('underscore');
// var Backbone = require('backbone');
// var Mutators = require('backbone.mutators');
//
//
// AMD:
// define(['underscore', 'backbone', 'backbone.mutators'], function (_, Backbone, Mutators) {
// // insert sample from below
// return User;
// });
//
// var User = Backbone.Model.extend({
// mutators: {
// fullname: function () {
// return this.firstname + ' ' + this.lastname;
// }
// },
//
// defaults: {
// firstname: 'Sebastian',
// lastname: 'Golasch'
// }
// });
//
// var user = new User();
// user.get('fullname') // returns 'Sebastian Golasch'
// user.toJSON() // return '{firstname: 'Sebastian', lastname: 'Golasch', fullname: 'Sebastian Golasch'}'
}(this, this.define, this.require, this.exports, this.module, function (_, Backbone, root, undef) {
'use strict';
// check if we use the amd branch of backbone and underscore
Backbone = Backbone === undef ? root.Backbone : Backbone;
_ = _ === undef ? root._ : _;
// extend backbones model prototype with the mutator functionality
var Mutator = function () { },
oldGet = Backbone.Model.prototype.get,
oldSet = Backbone.Model.prototype.set,
oldToJson = Backbone.Model.prototype.toJSON;
// This is necessary to ensure that Models declared without the mutators object do not throw and error
Mutator.prototype.mutators = {};
// override get functionality to fetch the mutator props
Mutator.prototype.get = function (attr) {
var isMutator = this.mutators !== undef;
// check if we have a getter mutation
if (isMutator === true && _.isFunction(this.mutators[attr]) === true) {
return this.mutators[attr].call(this);
}
// check if we have a deeper nested getter mutation
if (isMutator === true && _.isObject(this.mutators[attr]) === true && _.isFunction(this.mutators[attr].get) === true) {
return this.mutators[attr].get.call(this);
}
return oldGet.call(this, attr);
};
// override set functionality to set the mutator props
Mutator.prototype.set = function (key, value, options) {
var isMutator = this.mutators !== undef,
ret = null,
attrs = null,
attr = null;
// seamleassly stolen from backbone core
// check if the setter action is triggered
// using key <-> value or object
if (_.isObject(key) || key === null) {
attrs = key;
options = value;
} else {
attrs = {};
attrs[key] = value;
}
// check if we have a deeper nested setter mutation
if (isMutator === true && _.isObject(this.mutators[key]) === true) {
// check if we need to set a single value
if (_.isFunction(this.mutators[key].set) === true) {
ret = this.mutators[key].set.call(this, key, attrs[key], options, _.bind(oldSet, this));
} else if (_.isFunction(this.mutators[key])) {
ret = this.mutators[key].call(this, key, attrs[key], options, _.bind(oldSet, this));
}
}
if (_.isObject(attrs)) {
_.each(attrs, _.bind(function (attr, attrKey) {
if (isMutator === true && _.isObject(this.mutators[attrKey]) === true) {
// check if we need to set a single value
var meth = this.mutators[attrKey];
if (_.isFunction(meth.set)) {
meth = meth.set;
}
if (_.isFunction(meth)) {
if (options === undef || (_.isObject(options) === true && options.silent !== true && (options.mutators !== undef && options.mutators.silent !== true))) {
this.trigger('mutators:set:' + attrKey);
}
ret = meth.call(this, attrKey, attr, options, _.bind(oldSet, this));
}
}
}, this));
}
//validation purposes
if (ret !== null) {
return ret;
}
return oldSet.call(this, key, value, options);
};
// override toJSON functionality to serialize mutator properties
Mutator.prototype.toJSON = function () {
// fetch ye olde values
var attr = oldToJson.call(this);
// iterate over all mutators (if there are some)
_.each(this.mutators, _.bind(function (mutator, name) {
// check if we have some getter mutations (nested or )
if (_.isObject(this.mutators[name]) === true && _.isFunction(this.mutators[name].get)) {
attr[name] = _.bind(this.mutators[name].get, this)();
} else {
attr[name] = _.bind(this.mutators[name], this)();
}
}, this));
return attr;
};
// extend the models prototype
_.extend(Backbone.Model.prototype, Mutator.prototype);
// make mutators globally available under the Backbone namespace
Backbone.Mutators = Mutator;
return Mutator;
}));

View File

@ -0,0 +1,35 @@
(function() {
var Shortcuts;
Shortcuts = function(options) {
this.cid = _.uniqueId("backbone.shortcuts");
this.initialize.apply(this, arguments);
return this.delegateShortcuts();
};
_.extend(Shortcuts.prototype, Backbone.Events, {
initialize: function() {},
delegateShortcuts: function() {
var callback, match, method, scope, shortcut, shortcutKey, _ref, _results;
if (!this.shortcuts) return;
_ref = this.shortcuts;
_results = [];
for (shortcut in _ref) {
callback = _ref[shortcut];
if (!_.isFunction(callback)) method = this[callback];
if (!method) throw new Error("Method " + callback + " does not exist");
match = shortcut.match(/^(\S+)\s*(.*)$/);
shortcutKey = match[1];
scope = match[2] === "" ? "all" : match[2];
method = _.bind(method, this);
_results.push(key(shortcutKey, scope, method));
}
return _results;
}
});
Backbone.Shortcuts = Shortcuts;
Backbone.Shortcuts.extend = Backbone.View.extend;
}).call(this);

View File

@ -0,0 +1,212 @@
https://github.com/marionettejs/backbone.marionette/blob/viewswap/docs/marionette.viewswapper.md
// View Swapper
// ------------
//
// Switch out views based on events that are triggered
// by the currently displayed view. Enables easy "edit in
// place" features, "loading" screens, and more.
Marionette.ViewSwapper = Marionette.View.extend({
constructor: function (options) {
this._swapperViews = {};
this._swapperBindings = new Marionette.EventBinder();
this._currentViewBindings = new Marionette.EventBinder();
Marionette.View.prototype.constructor.apply(this, arguments);
this.views = Marionette.getOption(this, "views");
this.swapOn = Marionette.getOption(this, "swapOn");
this.initialView = Marionette.getOption(this, "initialView");
this._setupViewEvents("swapper", this, this._swapperBindings);
},
// Render the current view. If no current view is set, it
// will render the `initialView` that was configured.
render: function () {
// set up the initial view to display, on first render
if (!this.currentView) {
var initialViewName = Marionette.getOption(this, "initialView");
this._swapView(initialViewName);
}
// render and show the new view
this.currentView.render();
this.$el.append(this.currentView.$el);
// setup a callback for the showView call to recieve
var done = _.bind(function () {
// trigger show/onShow on the previous view
if (this.currentView) {
Marionette.triggerMethod.call(this.currentView, "show");
Marionette.triggerMethod.call(this, "swap:in", this.currentView);
}
}, this);
// show the view, passing it the done callback
this.showView(this.currentView, done);
},
// Show a view that is being swapped in. Override this method to
// set up your own custom fade in / show method
showView: function (view, done) {
view.$el.show();
done();
},
// Hide a view that is being swapped out. Override this method to
// set up your own custom fade out / hide method
hideView: function (view, done) {
view.$el.hide();
done();
},
// Ensure the views that were configured for this view swapper get closed
close: function () {
// Close all of the configured views that we are swapping between
_.each(this.views, function (view, name) {
view.close();
});
// unbind all the events, and clean up any decorator views
this._swapperViews = {};
this._currentViewBindings.unbindAll();
this._swapperBindings.unbindAll();
// Close the base view that we extended from
Marionette.View.prototype.close.apply(this, arguments);
},
// Get a view by name, throwing an exception if the view instance
// is not found.
_getView: function (viewName) {
var originalView, error, views;
var swapperView = this._swapperViews[viewName];
// Do not allow the name "swapper" to be used as a target view
// or initial view. This is reserved for the ViewSwapper instance,
// when configuring `swapOn` events
if (viewName === "swapper") {
error = new Error("Cannot display 'swapper' as a view.");
error.name = "InvalidViewName";
throw error;
}
// Do we have a view with the specified name?
if (!swapperView) {
originalView = this.views[viewName];
// No view, so throw an exception
if (!originalView) {
error = new Error("Cannot show view in ViewSwapper. View '" + viewName + "' not found.");
error.name = "ViewNotFoundError";
throw error;
}
// Found the view, so build a Decorator around it
swapperView = this._buildSwapperView(originalView, viewName);
this._swapperViews[viewName] = swapperView;
}
return swapperView;
},
// Decorate the configured view with information that the view swapper
// needs, to keep track of the view's current state.
_buildSwapperView: function (originalView, viewName) {
var swapperView = Marionette.createObject(originalView);
_.extend(swapperView, {
viewName: viewName,
originalView: originalView,
// Prevent the underlying view from being rendered more than once
render: function () {
var value;
if (this._hasBeenRendered) {
return this;
} else {
// prevent any more rendering
this._hasBeenRendered = true;
// do the render
value = originalView.render.apply(originalView, arguments);
// trigger render/onRender
Marionette.triggerMethod.call(this, "render");
// return whatever was sent back to us
return value;
}
}
});
return swapperView;
},
// Set up the event handlers for the individual views, so that the
// swapping can happen when a view event is triggered
_setupViewEvents: function (viewName, view, bindings) {
if (!this.swapOn || !this.swapOn[viewName]) { return; }
var that = this;
// default to current view bindings, unless otherwise specified
if (!bindings) {
bindings = this._currentViewBindings;
}
// close the previous event bindings
bindings.unbindAll();
// set up the new view's event bindings
_.each(this.swapOn[viewName], function (targetViewName, eventName) {
bindings.bindTo(view, eventName, function () {
that._swapView(targetViewName);
});
});
},
// Do the swapping of the views to the new view, by name
_swapView: function (viewName) {
// only swap views if the target view is not the same
// as the current view
var view = this._getView(viewName);
if (view === this.currentView) {
return;
}
// Provide a callback function that will switch over to
// the new view, when called
var done = _.bind(function () {
// trigger hide/onHide on the previous view
if (this.currentView) {
Marionette.triggerMethod.call(this.currentView, "hide");
Marionette.triggerMethod.call(this, "swap:out", this.currentView);
}
// get the next view, configure it's events and render it
this._setupViewEvents(viewName, view);
this.currentView = view;
this.render();
}, this);
if (this.currentView) {
// if we have a current view, hide it so that the new
// view can be show in it's place
this.hideView(this.currentView, done);
} else {
// no current view, so just switch to the new view
done();
}
}
});

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,10 @@
/// <reference path="JsLibraries/jquery.js" />
/// <reference path="JsLibraries/underscore.js" />
/// <reference path="JsLibraries/sugar.js" />
/// <reference path="JsLibraries/backbone.js" />
/// <reference path="JsLibraries/backbone.modelbinder.js" />
/// <reference path="JsLibraries/backbone.mutators.js" />
/// <reference path="JsLibraries/backbone.shortcuts.js" />
/// <reference path="JsLibraries/backbone.marionette.js" />
/// <reference path="JsLibraries/backbone.marionette.extend.js" />
/// <reference path="JsLibraries/backbone.modelbinder.js" />

View File

@ -23,6 +23,7 @@ xcopy NzbDrone.Web\App_GlobalResources\*.* %TARGET%\NzbDrone.Web\App_GlobalReso
xcopy NzbDrone.Web\Content\*.* %TARGET%\NzbDrone.Web\Content\ /E /V /I /Y
xcopy NzbDrone.Web\Scripts\*.* %TARGET%\NzbDrone.Web\Scripts\ /E /V /I /Y
xcopy NzbDrone.Web\Views\*.* %TARGET%\NzbDrone.Web\Views\ /E /V /I /Y
xcopy NzbDrone.Web\_backboneApp\*.* %TARGET%\NzbDrone.Web\_backboneApp\ /E /V /I /Y
del %TARGET%\NzbDrone.Web\bin\*.xml /Q /F