1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-12-16 11:37:58 +02:00

UI Cleanup - Updated Shared and Shims subtrees.

This commit is contained in:
Taloth Saldono 2015-02-14 11:17:53 +01:00
parent 019525dd9d
commit d6079a701c
39 changed files with 686 additions and 448 deletions

View File

@ -1,15 +1,15 @@
var $ = require('jquery');
module.exports = {
get : function(resource){
get : function(resource) {
var url = window.NzbDrone.ApiRoot + '/' + resource;
var _data;
$.ajax({
url : url,
async : false
}).done(function(data){
}).done(function(data) {
_data = data;
}).error(function(xhr, status, error){
}).error(function(xhr, status, error) {
throw error;
});
return _data;

View File

@ -3,14 +3,16 @@ var AppLayout = require('../../AppLayout');
var Marionette = require('marionette');
module.exports = Marionette.AppRouter.extend({
initialize : function(){
initialize : function() {
vent.on(vent.Commands.OpenControlPanelCommand, this._openControlPanel, this);
vent.on(vent.Commands.CloseControlPanelCommand, this._closeControlPanel, this);
},
_openControlPanel : function(view){
_openControlPanel : function(view) {
AppLayout.controlPanelRegion.show(view);
},
_closeControlPanel : function(){
_closeControlPanel : function() {
AppLayout.controlPanelRegion.closePanel();
}
});

View File

@ -1,39 +1,41 @@
var $ = require('jquery');
var Backbone = require('backbone');
var Marionette = require('marionette');
var region = Marionette.Region.extend({
el : '#control-panel-region',
module.exports = (function(){
var region = Marionette.Region.extend({
el : '#control-panel-region',
constructor : function(){
Backbone.Marionette.Region.prototype.constructor.apply(this, arguments);
this.on('show', this.showPanel, this);
},
getEl : function(selector){
var $el = $(selector);
return $el;
},
showPanel : function(){
$('body').addClass('control-panel-visible');
this.$el.animate({
"margin-bottom" : 0,
"opacity" : 1
}, {
queue : false,
duration : 300
});
},
closePanel : function(){
$('body').removeClass('control-panel-visible');
this.$el.animate({
"margin-bottom" : -100,
"opacity" : 0
}, {
queue : false,
duration : 300
});
this.reset();
}
});
return region;
}).call(this);
constructor : function() {
Backbone.Marionette.Region.prototype.constructor.apply(this, arguments);
this.on('show', this.showPanel, this);
},
getEl : function(selector) {
var $el = $(selector);
return $el;
},
showPanel : function() {
$('body').addClass('control-panel-visible');
this.$el.animate({
'margin-bottom' : 0,
'opacity' : 1
}, {
queue : false,
duration : 300
});
},
closePanel : function() {
$('body').removeClass('control-panel-visible');
this.$el.animate({
'margin-bottom' : -100,
'opacity' : 0
}, {
queue : false,
duration : 300
});
this.reset();
}
});
module.exports = region;

View File

@ -1,3 +1,5 @@
var Marionette = require('marionette');
module.exports = Marionette.CompositeView.extend({template : 'Shared/FileBrowser/EmptyViewTemplate'});
module.exports = Marionette.CompositeView.extend({
template : 'Shared/FileBrowser/EmptyViewTemplate'
});

View File

@ -5,12 +5,13 @@ var FileBrowserModel = require('./FileBrowserModel');
module.exports = Backbone.Collection.extend({
model : FileBrowserModel,
url : window.NzbDrone.ApiRoot + '/filesystem',
parse : function(response){
parse : function(response) {
var contents = [];
if(response.parent || response.parent === '') {
if (response.parent || response.parent === '') {
var type = 'parent';
var name = '...';
if(response.parent === '') {
if (response.parent === '') {
type = 'computer';
name = 'My Computer';
}

View File

@ -1,4 +1,4 @@
var _ = require('underscore');
var _ = require('underscore');
var vent = require('vent');
var Marionette = require('marionette');
var Backgrid = require('backgrid');
@ -13,19 +13,25 @@ var LoadingView = require('../LoadingView');
require('../../Mixins/DirectoryAutoComplete');
module.exports = Marionette.Layout.extend({
template : "Shared/FileBrowser/FileBrowserLayoutTemplate",
regions : {browser : "#x-browser"},
ui : {
path : ".x-path",
indicator : ".x-indicator"
template : 'Shared/FileBrowser/FileBrowserLayoutTemplate',
regions : {
browser : '#x-browser'
},
events : {
"typeahead:selected .x-path" : "_pathChanged",
"typeahead:autocompleted .x-path" : "_pathChanged",
"keyup .x-path" : "_inputChanged",
"click .x-ok" : "_selectPath"
ui : {
path : '.x-path',
indicator : '.x-indicator'
},
initialize : function(options){
events : {
'typeahead:selected .x-path' : '_pathChanged',
'typeahead:autocompleted .x-path' : '_pathChanged',
'keyup .x-path' : '_inputChanged',
'click .x-ok' : '_selectPath'
},
initialize : function(options) {
this.collection = new FileBrowserCollection();
this.collection.showFiles = options.showFiles || false;
this.collection.showLastModified = options.showLastModified || false;
@ -34,25 +40,30 @@ module.exports = Marionette.Layout.extend({
this.listenTo(this.collection, "sync", this._showGrid);
this.listenTo(this.collection, "filebrowser:folderselected", this._rowSelected);
},
onRender : function(){
onRender : function() {
this.browser.show(new LoadingView());
this.ui.path.directoryAutoComplete();
this._fetchCollection(this.input.val());
this._updatePath(this.input.val());
},
_setColumns : function(){
this.columns = [{
name : "type",
label : "",
sortable : false,
cell : FileBrowserTypeCell
}, {
name : "name",
label : "Name",
sortable : false,
cell : FileBrowserNameCell
}];
if(this.collection.showLastModified) {
_setColumns : function() {
this.columns = [
{
name : "type",
label : "",
sortable : false,
cell : FileBrowserTypeCell
},
{
name : "name",
label : "Name",
sortable : false,
cell : FileBrowserNameCell
}
];
if (this.collection.showLastModified) {
this.columns.push({
name : "lastModified",
label : "Last Modified",
@ -60,7 +71,7 @@ module.exports = Marionette.Layout.extend({
cell : RelativeDateCell
});
}
if(this.collection.showFiles) {
if (this.collection.showFiles) {
this.columns.push({
name : "size",
label : "Size",
@ -69,17 +80,19 @@ module.exports = Marionette.Layout.extend({
});
}
},
_fetchCollection : function(path){
_fetchCollection : function(path) {
this.ui.indicator.show();
var data = {includeFiles : this.collection.showFiles};
if(path) {
var data = { includeFiles : this.collection.showFiles };
if (path) {
data.path = path;
}
this.collection.fetch({data : data});
this.collection.fetch({ data : data });
},
_showGrid : function(){
_showGrid : function() {
this.ui.indicator.hide();
if(this.collection.models.length === 0) {
if (this.collection.models.length === 0) {
this.browser.show(new EmptyView());
return;
}
@ -91,27 +104,32 @@ module.exports = Marionette.Layout.extend({
});
this.browser.show(grid);
},
_rowSelected : function(model){
_rowSelected : function(model) {
var path = model.get("path");
this._updatePath(path);
this._fetchCollection(path);
},
_pathChanged : function(e, path){
_pathChanged : function(e, path) {
this._fetchCollection(path.value);
this._updatePath(path.value);
},
_inputChanged : function(){
_inputChanged : function() {
var path = this.ui.path.val();
if(path === "" || path.endsWith("\\") || path.endsWith("/")) {
if (path === "" || path.endsWith("\\") || path.endsWith("/")) {
this._fetchCollection(path);
}
},
_updatePath : function(path){
if(path !== undefined || path !== null) {
_updatePath : function(path) {
if (path !== undefined || path !== null) {
this.ui.path.val(path);
}
},
_selectPath : function(){
_selectPath : function() {
this.input.val(this.ui.path.val());
this.input.trigger("change");
vent.trigger(vent.Commands.CloseFileBrowser);

View File

@ -3,44 +3,48 @@ var Backbone = require('backbone');
var Marionette = require('marionette');
require('bootstrap');
module.exports = (function(){
var region = Marionette.Region.extend({
el : '#file-browser-modal-region',
constructor : function(){
Backbone.Marionette.Region.prototype.constructor.apply(this, arguments);
this.on('show', this.showModal, this);
},
getEl : function(selector){
var $el = $(selector);
$el.on('hidden', this.close);
return $el;
},
showModal : function(){
this.$el.addClass('modal fade');
this.$el.attr('tabindex', '-1');
this.$el.css('z-index', '1060');
this.$el.modal({
show : true,
keyboard : true,
backdrop : true
});
this.$el.on('hide.bs.modal', $.proxy(this._closing, this));
this.$el.on('shown.bs.modal', function(){
$('.modal-backdrop:last').css('z-index', 1059);
});
this.currentView.$el.addClass('modal-dialog');
},
closeModal : function(){
$(this.el).modal('hide');
this.reset();
},
_closing : function(){
if(this.$el) {
this.$el.off('hide.bs.modal');
this.$el.off('shown.bs.modal');
}
this.reset();
var region = Marionette.Region.extend({
el : '#file-browser-modal-region',
constructor : function() {
Backbone.Marionette.Region.prototype.constructor.apply(this, arguments);
this.on('show', this.showModal, this);
},
getEl : function(selector) {
var $el = $(selector);
$el.on('hidden', this.close);
return $el;
},
showModal : function() {
this.$el.addClass('modal fade');
this.$el.attr('tabindex', '-1');
this.$el.css('z-index', '1060');
this.$el.modal({
show : true,
keyboard : true,
backdrop : true
});
this.$el.on('hide.bs.modal', $.proxy(this._closing, this));
this.$el.on('shown.bs.modal', function() {
$('.modal-backdrop:last').css('z-index', 1059);
});
this.currentView.$el.addClass('modal-dialog');
},
closeModal : function() {
$(this.el).modal('hide');
this.reset();
},
_closing : function() {
if (this.$el) {
this.$el.off('hide.bs.modal');
this.$el.off('shown.bs.modal');
}
});
return region;
}).call(this);
this.reset();
}
});
module.exports = region;

View File

@ -3,11 +3,16 @@ var NzbDroneCell = require('../../Cells/NzbDroneCell');
module.exports = NzbDroneCell.extend({
className : 'file-browser-name-cell',
render : function(){
render : function() {
this.$el.empty();
var name = this.model.get(this.column.get('name'));
this.$el.html(name);
this.delegateEvents();
return this;
}
});

View File

@ -2,17 +2,22 @@ var _ = require('underscore');
var Backgrid = require('backgrid');
module.exports = Backgrid.Row.extend({
className : 'file-browser-row',
events : {"click" : '_selectRow'},
className : 'file-browser-row',
events : {
'click' : '_selectRow'
},
_originalInit : Backgrid.Row.prototype.initialize,
initialize : function(){
initialize : function() {
this._originalInit.apply(this, arguments);
},
_selectRow : function(){
if(this.model.get('type') === 'file') {
_selectRow : function() {
if (this.model.get('type') === 'file') {
this.model.collection.trigger('filebrowser:fileselected', this.model);
}
else {
} else {
this.model.collection.trigger('filebrowser:folderselected', this.model);
}
}

View File

@ -3,24 +3,26 @@ var NzbDroneCell = require('../../Cells/NzbDroneCell');
module.exports = NzbDroneCell.extend({
className : 'file-browser-type-cell',
render : function(){
render : function() {
this.$el.empty();
var type = this.model.get(this.column.get('name'));
var icon = 'icon-hdd';
if(type === 'computer') {
if (type === 'computer') {
icon = 'icon-desktop';
}
else if(type === 'parent') {
} else if (type === 'parent') {
icon = 'icon-level-up';
}
else if(type === 'folder') {
} else if (type === 'folder') {
icon = 'icon-folder-close-alt';
}
else if(type === 'file') {
} else if (type === 'file') {
icon = 'icon-file-alt';
}
this.$el.html('<i class="{0}"></i>'.format(icon));
this.delegateEvents();
return this;
}
});

View File

@ -3,43 +3,56 @@ var filesize = require('filesize');
var UiSettings = require('./UiSettingsModel');
module.exports = {
bytes : function(sourceSize){
bytes : function(sourceSize) {
var size = Number(sourceSize);
if(isNaN(size)) {
if (isNaN(size)) {
return '';
}
return filesize(size, {
base : 2,
round : 1
});
},
relativeDate : function(sourceDate){
if(!sourceDate) {
relativeDate : function(sourceDate) {
if (!sourceDate) {
return '';
}
var date = moment(sourceDate);
var calendarDate = date.calendar();
//TODO: It would be nice to not have to hack this...
var strippedCalendarDate = calendarDate.substring(0, calendarDate.indexOf(' at '));
if(strippedCalendarDate) {
if (strippedCalendarDate) {
return strippedCalendarDate;
}
if(date.isAfter(moment())) {
if (date.isAfter(moment())) {
return date.fromNow(true);
}
if(date.isBefore(moment().add('years', -1))) {
if (date.isBefore(moment().add('years', -1))) {
return date.format(UiSettings.get('shortDateFormat'));
}
return date.fromNow();
},
pad : function(n, width, z){
pad : function(n, width, z) {
z = z || '0';
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
},
number : function(input){
if(!input) {
number : function(input) {
if (!input) {
return '0';
}
return input.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
};

View File

@ -1,116 +1,144 @@
module.exports = function() {
var backgrid = this;
var Backgrid = this;
backgrid.SonarrHeaderCell = backgrid.HeaderCell.extend({
events : {
Backgrid.SonarrHeaderCell = Backgrid.HeaderCell.extend({
events : {
'click' : 'onClick'
},
_originalInit : backgrid.HeaderCell.prototype.initialize,
initialize : function(options){
_originalInit : Backgrid.HeaderCell.prototype.initialize,
initialize : function(options) {
this._originalInit.call(this, options);
this.listenTo(this.collection, 'drone:sort', this.render);
},
render : function(){
render : function() {
this.$el.empty();
this.$el.append(this.column.get('label'));
var column = this.column;
var sortable = backgrid.callByNeed(column.sortable(), column, this.collection);
if(sortable) {
var sortable = Backgrid.callByNeed(column.sortable(), column, this.collection);
if (sortable) {
this.$el.addClass('sortable');
this.$el.append(' <i class="pull-right"></i>');
}
//Do we need this?
this.$el.addClass(column.get('name'));
if(column.has('className')) {
if (column.has('className')) {
this.$el.addClass(column.get('className'));
}
this.delegateEvents();
this.direction(column.get('direction'));
if(this.collection.state) {
if (this.collection.state) {
var name = this._getSortMapping().name;
var order = this.collection.state.order;
if(name === column.get('name')) {
if (name === column.get('name')) {
this._setSortIcon(order);
}
else {
} else {
this._removeSortIcon();
}
}
return this;
},
direction : function(dir){
direction : function(dir) {
this.$el.children('i').removeClass('icon-sort-up icon-sort-down');
if(arguments.length) {
if(dir) {
if (arguments.length) {
if (dir) {
this._setSortIcon(dir);
}
this.column.set('direction', dir);
}
var columnDirection = this.column.get('direction');
if(!columnDirection && this.collection.state) {
if (!columnDirection && this.collection.state) {
var name = this._getSortMapping().name;
var order = this.collection.state.order;
if(name === this.column.get('name')) {
if (name === this.column.get('name')) {
columnDirection = order;
}
}
return columnDirection;
},
_getSortMapping : function(){
_getSortMapping : function() {
var sortKey = this.collection.state.sortKey;
if(this.collection._getSortMapping) {
if (this.collection._getSortMapping) {
return this.collection._getSortMapping(sortKey);
}
return {
name : sortKey,
sortKey : sortKey
};
},
onClick : function(e){
onClick : function(e) {
e.preventDefault();
var collection = this.collection;
var event = 'backgrid:sort';
var column = this.column;
var sortable = backgrid.callByNeed(column.sortable(), column, collection);
if(sortable) {
var sortable = Backgrid.callByNeed(column.sortable(), column, collection);
if (sortable) {
var direction = collection.state.order;
if(direction === 'ascending' || direction === -1) {
if (direction === 'ascending' || direction === -1) {
direction = 'descending';
}
else {
} else {
direction = 'ascending';
}
if(collection.setSorting) {
if (collection.setSorting) {
collection.setSorting(column.get('name'), direction);
}
else {
} else {
collection.state.sortKey = column.get('name');
collection.state.order = direction;
}
collection.trigger(event, column, direction);
}
},
_resetCellDirection : function(columnToSort, direction){
if(columnToSort !== this.column) {
_resetCellDirection : function(columnToSort, direction) {
if (columnToSort !== this.column) {
this.direction(null);
}
else {
} else {
this.direction(direction);
}
},
_convertDirectionToIcon : function(dir){
if(dir === 'ascending' || dir === -1) {
_convertDirectionToIcon : function(dir) {
if (dir === 'ascending' || dir === -1) {
return 'icon-sort-up';
}
return 'icon-sort-down';
},
_setSortIcon : function(dir){
_setSortIcon : function(dir) {
this._removeSortIcon();
this.$el.children('i').addClass(this._convertDirectionToIcon(dir));
},
_removeSortIcon : function(){
_removeSortIcon : function() {
this.$el.children('i').removeClass('icon-sort-up icon-sort-down');
}
});
return backgrid.SonarrHeaderCell;
return Backgrid.SonarrHeaderCell;
};

View File

@ -3,42 +3,52 @@ var Marionette = require('marionette');
var Paginator = require('backgrid.paginator');
module.exports = Paginator.extend({
template : 'Shared/Grid/PagerTemplate',
events : {
"click .pager-btn" : 'changePage',
"click .x-page-number" : '_showPageJumper',
"change .x-page-select" : '_jumpToPage',
"blur .x-page-select" : 'render'
template : 'Shared/Grid/PagerTemplate',
events : {
'click .pager-btn' : 'changePage',
'click .x-page-number' : '_showPageJumper',
'change .x-page-select' : '_jumpToPage',
'blur .x-page-select' : 'render'
},
windowSize : 1,
windowSize : 1,
fastForwardHandleLabels : {
first : 'icon-fast-backward',
prev : 'icon-backward',
next : 'icon-forward',
last : 'icon-fast-forward'
},
changePage : function(e){
changePage : function(e) {
e.preventDefault();
var target = this.$(e.target);
if(target.closest('li').hasClass('disabled')) {
if (target.closest('li').hasClass('disabled')) {
return;
}
target.closest('li i').addClass('icon-spinner icon-spin');
var label = target.attr('data-action');
var ffLabels = this.fastForwardHandleLabels;
var collection = this.collection;
if(ffLabels) {
if (ffLabels) {
switch (label) {
case 'first':
collection.getFirstPage();
return;
case 'prev':
if(collection.hasPrevious()) {
if (collection.hasPrevious()) {
collection.getPreviousPage();
}
return;
case 'next':
if(collection.hasNext()) {
if (collection.hasNext()) {
collection.getNextPage();
}
return;
@ -47,14 +57,19 @@ module.exports = Paginator.extend({
return;
}
}
var state = collection.state;
var pageIndex = target.text();
collection.getPage(state.firstPage === 0 ? pageIndex - 1 : pageIndex);
},
makeHandles : function(){
makeHandles : function() {
var handles = [];
var collection = this.collection;
var state = collection.state;
// convert all indices to 0-based here
var firstPage = state.firstPage;
var lastPage = +state.lastPage;
lastPage = Math.max(0, firstPage ? lastPage - 1 : lastPage);
@ -62,7 +77,8 @@ module.exports = Paginator.extend({
currentPage = firstPage ? currentPage - 1 : currentPage;
var windowStart = Math.floor(currentPage / this.windowSize) * this.windowSize;
var windowEnd = Math.min(lastPage + 1, windowStart + this.windowSize);
if(collection.mode !== 'infinite') {
if (collection.mode !== 'infinite') {
for (var i = windowStart; i < windowEnd; i++) {
handles.push({
label : i + 1,
@ -73,30 +89,34 @@ module.exports = Paginator.extend({
});
}
}
var ffLabels = this.fastForwardHandleLabels;
if(ffLabels) {
if(ffLabels.prev) {
if (ffLabels) {
if (ffLabels.prev) {
handles.unshift({
label : ffLabels.prev,
className : collection.hasPrevious() ? void 0 : 'disabled',
action : 'prev'
});
}
if(ffLabels.first) {
if (ffLabels.first) {
handles.unshift({
label : ffLabels.first,
className : collection.hasPrevious() ? void 0 : 'disabled',
action : 'first'
});
}
if(ffLabels.next) {
if (ffLabels.next) {
handles.push({
label : ffLabels.next,
className : collection.hasNext() ? void 0 : 'disabled',
action : 'next'
});
}
if(ffLabels.last) {
if (ffLabels.last) {
handles.push({
label : ffLabels.last,
className : collection.hasNext() ? void 0 : 'disabled',
@ -104,44 +124,59 @@ module.exports = Paginator.extend({
});
}
}
return handles;
},
render : function(){
render : function() {
this.$el.empty();
var templateFunction = Marionette.TemplateCache.get(this.template);
this.$el.html(templateFunction({
handles : this.makeHandles(),
state : this.collection.state
}));
this.delegateEvents();
return this;
},
_showPageJumper : function(e){
if($(e.target).is('select')) {
_showPageJumper : function(e) {
if ($(e.target).is('select')) {
return;
}
var templateFunction = Marionette.TemplateCache.get('Shared/Grid/JumpToPageTemplate');
var state = this.collection.state;
var currentPage = Math.max(state.currentPage, state.firstPage);
currentPage = state.firstPage ? currentPage - 1 : currentPage;
var pages = [];
for (var i = 0; i < this.collection.state.lastPage; i++) {
if(i === currentPage) {
if (i === currentPage) {
pages.push({
page : i + 1,
current : true
});
}
else {
pages.push({page : i + 1});
} else {
pages.push({ page : i + 1 });
}
}
this.$el.find('.x-page-number').html(templateFunction({pages : pages}));
this.$el.find('.x-page-number').html(templateFunction({ pages : pages }));
},
_jumpToPage : function(){
_jumpToPage : function() {
var target = this.$el.find('.x-page-select');
//Remove event handlers so the blur event is not triggered
this.undelegateEvents();
var selectedPage = parseInt(target.val(), 10);
this.$el.find('.x-page-number').html('<i class="icon-spinner icon-spin"></i>');
this.collection.getPage(selectedPage);
}

View File

@ -2,23 +2,28 @@ require('messenger');
var messenger = require('messenger');
module.exports = {
show : function(options){
if(!options.type) {
show : function(options) {
if (!options.type) {
options.type = 'info';
}
if(options.hideAfter === undefined) {
if (options.hideAfter === undefined) {
switch (options.type) {
case 'info':
options.hideAfter = 5;
break;
case 'success':
options.hideAfter = 5;
break;
default:
options.hideAfter = 5;
}
}
options.hideOnNavigate = options.hideOnNavigate || false;
return messenger().post({
message : options.message,
type : options.type,
@ -29,26 +34,33 @@ module.exports = {
hideOnNavigate : options.hideOnNavigate
});
},
monitor : function(options){
if(!options.promise) {
monitor : function(options) {
if (!options.promise) {
throw 'promise is required';
}
if(!options.successMessage) {
if (!options.successMessage) {
throw 'success message is required';
}
if(!options.errorMessage) {
if (!options.errorMessage) {
throw 'error message is required';
}
var self = this;
options.promise.done(function(){
self.show({message : options.successMessage});
options.promise.done(function() {
self.show({ message : options.successMessage });
});
options.promise.fail(function(){
options.promise.fail(function() {
self.show({
message : options.errorMessage,
type : 'error'
});
});
return options.promise;
}
};

View File

@ -10,7 +10,7 @@ var RenamePreviewLayout = require('../../Rename/RenamePreviewLayout');
var FileBrowserLayout = require('../FileBrowser/FileBrowserLayout');
module.exports = Marionette.AppRouter.extend({
initialize : function(){
initialize : function() {
vent.on(vent.Commands.OpenModalCommand, this._openModal, this);
vent.on(vent.Commands.CloseModalCommand, this._closeModal, this);
vent.on(vent.Commands.EditSeriesCommand, this._editSeries, this);
@ -22,21 +22,26 @@ module.exports = Marionette.AppRouter.extend({
vent.on(vent.Commands.ShowFileBrowser, this._showFileBrowser, this);
vent.on(vent.Commands.CloseFileBrowser, this._closeFileBrowser, this);
},
_openModal : function(view){
_openModal : function(view) {
AppLayout.modalRegion.show(view);
},
_closeModal : function(){
_closeModal : function() {
AppLayout.modalRegion.closeModal();
},
_editSeries : function(options){
var view = new EditSeriesView({model : options.series});
_editSeries : function(options) {
var view = new EditSeriesView({ model : options.series });
AppLayout.modalRegion.show(view);
},
_deleteSeries : function(options){
var view = new DeleteSeriesView({model : options.series});
_deleteSeries : function(options) {
var view = new DeleteSeriesView({ model : options.series });
AppLayout.modalRegion.show(view);
},
_showEpisode : function(options){
_showEpisode : function(options) {
var view = new EpisodeDetailsLayout({
model : options.episode,
hideSeriesLink : options.hideSeriesLink,
@ -44,23 +49,28 @@ module.exports = Marionette.AppRouter.extend({
});
AppLayout.modalRegion.show(view);
},
_showHistory : function(options){
var view = new HistoryDetailsLayout({model : options.model});
_showHistory : function(options) {
var view = new HistoryDetailsLayout({ model : options.model });
AppLayout.modalRegion.show(view);
},
_showLogDetails : function(options){
var view = new LogDetailsView({model : options.model});
_showLogDetails : function(options) {
var view = new LogDetailsView({ model : options.model });
AppLayout.modalRegion.show(view);
},
_showRenamePreview : function(options){
_showRenamePreview : function(options) {
var view = new RenamePreviewLayout(options);
AppLayout.modalRegion.show(view);
},
_showFileBrowser : function(options){
_showFileBrowser : function(options) {
var view = new FileBrowserLayout(options);
AppLayout.fileBrowserModalRegion.show(view);
},
_closeFileBrowser : function(){
_closeFileBrowser : function(options) {
AppLayout.fileBrowserModalRegion.closeModal();
}
});

View File

@ -2,40 +2,49 @@ var $ = require('jquery');
var Backbone = require('backbone');
var Marionette = require('marionette');
require('bootstrap');
var region = Marionette.Region.extend({
el : '#modal-region',
module.exports = (function(){
var region = Marionette.Region.extend({
el : '#modal-region',
constructor : function(){
Backbone.Marionette.Region.prototype.constructor.apply(this, arguments);
this.on('show', this.showModal, this);
},
getEl : function(selector){
var $el = $(selector);
$el.on('hidden', this.close);
return $el;
},
showModal : function(){
this.$el.addClass('modal fade');
this.$el.attr('tabindex', '-1');
this.$el.modal({
show : true,
keyboard : true,
backdrop : true
});
this.$el.on('hide.bs.modal', $.proxy(this._closing, this));
this.currentView.$el.addClass('modal-dialog');
},
closeModal : function(){
$(this.el).modal('hide');
this.reset();
},
_closing : function(){
if(this.$el) {
this.$el.off('hide.bs.modal');
}
this.reset();
constructor : function() {
Backbone.Marionette.Region.prototype.constructor.apply(this, arguments);
this.on('show', this.showModal, this);
},
getEl : function(selector) {
var $el = $(selector);
$el.on('hidden', this.close);
return $el;
},
showModal : function() {
this.$el.addClass('modal fade');
//need tab index so close on escape works
//https://github.com/twitter/bootstrap/issues/4663
this.$el.attr('tabindex', '-1');
this.$el.modal({
show : true,
keyboard : true,
backdrop : true
});
this.$el.on('hide.bs.modal', $.proxy(this._closing, this));
this.currentView.$el.addClass('modal-dialog');
},
closeModal : function() {
$(this.el).modal('hide');
this.reset();
},
_closing : function() {
if (this.$el) {
this.$el.off('hide.bs.modal');
}
});
return region;
}).call(this);
this.reset();
}
});
module.exports = region;

View File

@ -1,3 +1,5 @@
var Marionette = require('marionette');
module.exports = Marionette.ItemView.extend({template : 'Shared/NotFoundViewTemplate'});
module.exports = Marionette.ItemView.extend({
template : 'Shared/NotFoundViewTemplate'
});

View File

@ -1,27 +1,28 @@
var vent = require('vent');
var vent = require('vent');
var AppLayout = require('../AppLayout');
var Marionette = require('marionette');
var NotFoundView = require('./NotFoundView');
var Messenger = require('messenger');
module.exports = Marionette.AppRouter.extend({
initialize : function(){
initialize : function() {
this.listenTo(vent, vent.Events.ServerUpdated, this._onServerUpdated);
},
showNotFound : function(){
showNotFound : function() {
this.setTitle('Not Found');
this.showMainRegion(new NotFoundView(this));
},
setTitle : function(title){
setTitle : function(title) {
title = title;
if(title === 'Sonarr') {
if (title === 'Sonarr') {
document.title = 'Sonarr';
}
else {
} else {
document.title = title + ' - Sonarr';
}
if(window.NzbDrone.Analytics && window.Piwik) {
if (window.NzbDrone.Analytics && window.Piwik) {
try {
var piwik = window.Piwik.getTracker('http://piwik.nzbdrone.com/piwik.php', 1);
piwik.setReferrerUrl('');
@ -35,7 +36,8 @@ module.exports = Marionette.AppRouter.extend({
}
}
},
_onServerUpdated : function(){
_onServerUpdated : function() {
Messenger.show({
message : 'Sonarr has been updated',
hideAfter : 0,
@ -43,7 +45,7 @@ module.exports = Marionette.AppRouter.extend({
actions : {
viewChanges : {
label : 'View Changes',
action : function(){
action : function() {
window.location = window.NzbDrone.UrlBase + '/system/updates';
}
}
@ -52,11 +54,11 @@ module.exports = Marionette.AppRouter.extend({
this.pendingUpdate = true;
},
showMainRegion : function(view){
if(this.pendingUpdate) {
showMainRegion : function(view) {
if (this.pendingUpdate) {
window.location.reload();
}
else {
} else {
AppLayout.mainRegion.show(view);
}
}

View File

@ -5,9 +5,10 @@ var StatusModel = require('../System/StatusModel');
require('signalR');
module.exports = {
appInitializer : function(){
appInitializer : function() {
console.log('starting signalR');
var getStatus = function(status){
var getStatus = function(status) {
switch (status) {
case 0:
return 'connecting';
@ -21,27 +22,36 @@ module.exports = {
throw 'invalid status ' + status;
}
};
var tryingToReconnect = false;
var messengerId = 'signalR';
this.signalRconnection = $.connection(StatusModel.get('urlBase') + '/signalr');
this.signalRconnection.stateChanged(function(change){
this.signalRconnection.stateChanged(function(change) {
console.debug('SignalR: [{0}]'.format(getStatus(change.newState)));
});
this.signalRconnection.received(function(message){
this.signalRconnection.received(function(message) {
vent.trigger('server:' + message.name, message.body);
});
this.signalRconnection.reconnecting(function(){
if(window.NzbDrone.unloading) {
this.signalRconnection.reconnecting(function() {
if (window.NzbDrone.unloading) {
return;
}
tryingToReconnect = true;
});
this.signalRconnection.reconnected(function(){
this.signalRconnection.reconnected(function() {
tryingToReconnect = false;
});
this.signalRconnection.disconnected(function(){
if(tryingToReconnect) {
this.signalRconnection.disconnected(function() {
if (tryingToReconnect) {
$('<div class="modal-backdrop fade in"></div>').appendTo(document.body);
Messenger.show({
id : messengerId,
type : 'error',
@ -50,7 +60,7 @@ module.exports = {
actions : {
cancel : {
label : 'Reload',
action : function(){
action : function() {
window.location.reload();
}
}
@ -58,7 +68,9 @@ module.exports = {
});
}
});
this.signalRconnection.start({transport : ['longPolling']});
this.signalRconnection.start({ transport : ['longPolling'] });
return this;
}
};

View File

@ -2,17 +2,20 @@ var Marionette = require('marionette');
var ButtonView = require('./ButtonView');
module.exports = Marionette.CollectionView.extend({
className : 'btn-group',
itemView : ButtonView,
initialize : function(options){
className : 'btn-group',
itemView : ButtonView,
initialize : function(options) {
this.menu = options.menu;
this.className = 'btn-group';
if(options.menu.collapse) {
if (options.menu.collapse) {
this.className += ' btn-group-collapse';
}
},
onRender : function(){
if(this.menu.collapse) {
onRender : function() {
if (this.menu.collapse) {
this.$el.addClass('btn-group-collapse');
}
}

View File

@ -4,59 +4,77 @@ var _ = require('underscore');
var CommandController = require('../../../Commands/CommandController');
module.exports = Marionette.ItemView.extend({
template : 'Shared/Toolbar/ButtonTemplate',
className : 'btn btn-default btn-icon-only-xs',
ui : {icon : 'i'},
events : {"click" : 'onClick'},
initialize : function(){
template : 'Shared/Toolbar/ButtonTemplate',
className : 'btn btn-default btn-icon-only-xs',
ui : {
icon : 'i'
},
events : {
'click' : 'onClick'
},
initialize : function() {
this.storageKey = this.model.get('menuKey') + ':' + this.model.get('key');
},
onRender : function(){
if(this.model.get('active')) {
onRender : function() {
if (this.model.get('active')) {
this.$el.addClass('active');
this.invokeCallback();
}
if(!this.model.get('title')) {
if (!this.model.get('title')) {
this.$el.addClass('btn-icon-only');
}
if(this.model.get('className')) {
if (this.model.get('className')) {
this.$el.addClass(this.model.get('className'));
}
var command = this.model.get('command');
if(command) {
var properties = _.extend({name : command}, this.model.get('properties'));
if (command) {
var properties = _.extend({ name : command }, this.model.get('properties'));
CommandController.bindToCommand({
command : properties,
element : this.$el
});
}
},
onClick : function(){
if(this.$el.hasClass('disabled')) {
onClick : function() {
if (this.$el.hasClass('disabled')) {
return;
}
this.invokeCallback();
this.invokeRoute();
this.invokeCommand();
},
invokeCommand : function(){
invokeCommand : function() {
var command = this.model.get('command');
if(command) {
if (command) {
CommandController.Execute(command, this.model.get('properties'));
}
},
invokeRoute : function(){
invokeRoute : function() {
var route = this.model.get('route');
if(route) {
Backbone.history.navigate(route, {trigger : true});
if (route) {
Backbone.history.navigate(route, { trigger : true });
}
},
invokeCallback : function(){
if(!this.model.ownerContext) {
invokeCallback : function() {
if (!this.model.ownerContext) {
throw 'ownerContext must be set.';
}
var callback = this.model.get('callback');
if(callback) {
if (callback) {
callback.call(this.model.ownerContext, this);
}
}

View File

@ -1,4 +1,6 @@
var Backbone = require('backbone');
var ButtonModel = require('./ButtonModel');
module.exports = Backbone.Collection.extend({model : ButtonModel});
module.exports = Backbone.Collection.extend({
model : ButtonModel
});

View File

@ -3,9 +3,9 @@ var Backbone = require('backbone');
module.exports = Backbone.Model.extend({
defaults : {
"target" : '/nzbdrone/route',
"title" : '',
"active" : false,
"tooltip" : undefined
'target' : '/nzbdrone/route',
'title' : '',
'active' : false,
'tooltip' : undefined
}
});

View File

@ -3,26 +3,33 @@ var RadioButtonView = require('./RadioButtonView');
var Config = require('../../../Config');
module.exports = Marionette.CollectionView.extend({
className : 'btn-group',
itemView : RadioButtonView,
attributes : {"data-toggle" : 'buttons'},
initialize : function(options){
className : 'btn-group',
itemView : RadioButtonView,
attributes : {
'data-toggle' : 'buttons'
},
initialize : function(options) {
this.menu = options.menu;
this.setActive();
},
setActive : function(){
setActive : function() {
var storedKey = this.menu.defaultAction;
if(this.menu.storeState) {
if (this.menu.storeState) {
storedKey = Config.getValue(this.menu.menuKey, storedKey);
}
if(!storedKey) {
if (!storedKey) {
return;
}
this.collection.each(function(model){
if(model.get('key').toLocaleLowerCase() === storedKey.toLowerCase()) {
this.collection.each(function(model) {
if (model.get('key').toLocaleLowerCase() === storedKey.toLowerCase()) {
model.set('active', true);
}
else {
} else {
model.set('active, false');
}
});

View File

@ -2,35 +2,48 @@ var Marionette = require('marionette');
var Config = require('../../../Config');
module.exports = Marionette.ItemView.extend({
template : 'Shared/Toolbar/RadioButtonTemplate',
className : 'btn btn-default',
ui : {icon : 'i'},
events : {"click" : 'onClick'},
initialize : function(){
template : 'Shared/Toolbar/RadioButtonTemplate',
className : 'btn btn-default',
ui : {
icon : 'i'
},
events : {
'click' : 'onClick'
},
initialize : function() {
this.storageKey = this.model.get('menuKey') + ':' + this.model.get('key');
},
onRender : function(){
if(this.model.get('active')) {
onRender : function() {
if (this.model.get('active')) {
this.$el.addClass('active');
this.invokeCallback();
}
if(!this.model.get('title')) {
if (!this.model.get('title')) {
this.$el.addClass('btn-icon-only');
}
if(this.model.get('tooltip')) {
if (this.model.get('tooltip')) {
this.$el.attr('title', this.model.get('tooltip'));
}
},
onClick : function(){
onClick : function() {
Config.setValue(this.model.get('menuKey'), this.model.get('key'));
this.invokeCallback();
},
invokeCallback : function(){
if(!this.model.ownerContext) {
invokeCallback : function() {
if (!this.model.ownerContext) {
throw 'ownerContext must be set.';
}
var callback = this.model.get('callback');
if(callback) {
if (callback) {
callback.call(this.model.ownerContext, this);
}
}

View File

@ -6,27 +6,33 @@ module.exports = Marionette.CompositeView.extend({
itemView : ButtonView,
template : 'Shared/Toolbar/Sorting/SortingButtonCollectionViewTemplate',
itemViewContainer : '.dropdown-menu',
initialize : function(options){
initialize : function(options) {
this.viewCollection = options.viewCollection;
this.listenTo(this.viewCollection, 'drone:sort', this.sort);
},
itemViewOptions : function(){
return {viewCollection : this.viewCollection};
itemViewOptions : function() {
return {
viewCollection : this.viewCollection
};
},
sort : function(sortModel, sortDirection){
sort : function(sortModel, sortDirection) {
var collection = this.viewCollection;
var order;
if(sortDirection === 'ascending') {
if (sortDirection === 'ascending') {
order = -1;
}
else if(sortDirection === 'descending') {
} else if (sortDirection === 'descending') {
order = 1;
}
else {
} else {
order = null;
}
collection.setSorting(sortModel.get('name'), order);
collection.fullCollection.sort();
return this;
}
});

View File

@ -3,53 +3,68 @@ var Marionette = require('marionette');
var _ = require('underscore');
module.exports = Marionette.ItemView.extend({
template : 'Shared/Toolbar/Sorting/SortingButtonViewTemplate',
tagName : 'li',
ui : {icon : 'i'},
events : {"click" : 'onClick'},
initialize : function(options){
template : 'Shared/Toolbar/Sorting/SortingButtonViewTemplate',
tagName : 'li',
ui : {
icon : 'i'
},
events : {
'click' : 'onClick'
},
initialize : function(options) {
this.viewCollection = options.viewCollection;
this.listenTo(this.viewCollection, 'drone:sort', this.render);
this.listenTo(this.viewCollection, 'backgrid:sort', this.render);
},
onRender : function(){
if(this.viewCollection.state) {
onRender : function() {
if (this.viewCollection.state) {
var sortKey = this.viewCollection.state.sortKey;
var name = this.viewCollection._getSortMapping(sortKey).name;
var order = this.viewCollection.state.order;
if(name === this.model.get('name')) {
if (name === this.model.get('name')) {
this._setSortIcon(order);
}
else {
} else {
this._removeSortIcon();
}
}
},
onClick : function(e){
onClick : function(e) {
e.preventDefault();
var collection = this.viewCollection;
var event = 'drone:sort';
var direction = collection.state.order;
if(direction === 'ascending' || direction === -1) {
if (direction === 'ascending' || direction === -1) {
direction = 'descending';
}
else {
} else {
direction = 'ascending';
}
collection.setSorting(this.model.get('name'), direction);
collection.trigger(event, this.model, direction);
},
_convertDirectionToIcon : function(dir){
if(dir === 'ascending' || dir === -1) {
_convertDirectionToIcon : function(dir) {
if (dir === 'ascending' || dir === -1) {
return 'icon-sort-up';
}
return 'icon-sort-down';
},
_setSortIcon : function(dir){
_setSortIcon : function(dir) {
this._removeSortIcon();
this.ui.icon.addClass(this._convertDirectionToIcon(dir));
},
_removeSortIcon : function(){
_removeSortIcon : function() {
this.ui.icon.removeClass('icon-sort-up icon-sort-down');
}
});

View File

@ -7,49 +7,61 @@ var SortingButtonCollectionView = require('./Sorting/SortingButtonCollectionView
var _ = require('underscore');
module.exports = Marionette.Layout.extend({
template : 'Shared/Toolbar/ToolbarLayoutTemplate',
className : 'toolbar',
ui : {
template : 'Shared/Toolbar/ToolbarLayoutTemplate',
className : 'toolbar',
ui : {
left_x : '.x-toolbar-left',
right_x : '.x-toolbar-right'
},
initialize : function(options){
if(!options) {
initialize : function(options) {
if (!options) {
throw 'options needs to be passed';
}
if(!options.context) {
if (!options.context) {
throw 'context needs to be passed';
}
this.left = options.left;
this.right = options.right;
this.toolbarContext = options.context;
},
onShow : function(){
if(this.left) {
onShow : function() {
if (this.left) {
_.each(this.left, this._showToolbarLeft, this);
}
if(this.right) {
if (this.right) {
_.each(this.right, this._showToolbarRight, this);
}
},
_showToolbarLeft : function(element, index){
_showToolbarLeft : function(element, index) {
this._showToolbar(element, index, 'left');
},
_showToolbarRight : function(element, index){
_showToolbarRight : function(element, index) {
this._showToolbar(element, index, 'right');
},
_showToolbar : function(buttonGroup, index, position){
_showToolbar : function(buttonGroup, index, position) {
var groupCollection = new ButtonCollection();
_.each(buttonGroup.items, function(button){
if(buttonGroup.storeState && !button.key) {
_.each(buttonGroup.items, function(button) {
if (buttonGroup.storeState && !button.key) {
throw 'must provide key for all buttons when storSstate is enabled';
}
var model = new ButtonModel(button);
model.set('menuKey', buttonGroup.menuKey);
model.ownerContext = this.toolbarContext;
groupCollection.add(model);
}, this);
var buttonGroupView;
switch (buttonGroup.type) {
case 'radio':
{
@ -77,13 +89,16 @@ module.exports = Marionette.Layout.extend({
break;
}
}
var regionId = position + '_' + (index + 1);
var region = this[regionId];
if(!region) {
if (!region) {
var regionClassName = 'x-toolbar-' + position + '-' + (index + 1);
this.ui[position + '_x'].append('<div class="toolbar-group ' + regionClassName + '" />\r\n');
region = this.addRegion(regionId, '.' + regionClassName);
}
region.show(buttonGroupView);
}
});

View File

@ -22,7 +22,7 @@ Tooltip.prototype.getOptions = function(options) {
module.exports = {
appInitializer : function() {
$('body').tooltip({selector : '[title]'});
$('body').tooltip({ selector : '[title]' });
return this;
}

View File

@ -1,25 +1,29 @@
var Backbone = require('backbone');
var ApiData = require('./ApiData');
module.exports = (function(){
var UiSettings = Backbone.Model.extend({
url : window.NzbDrone.ApiRoot + '/config/ui',
shortDateTime : function(includeSeconds){
return this.get('shortDateFormat') + ' ' + this.time(true, includeSeconds);
},
longDateTime : function(includeSeconds){
return this.get('longDateFormat') + ' ' + this.time(true, includeSeconds);
},
time : function(includeMinuteZero, includeSeconds){
if(includeSeconds) {
return this.get('timeFormat').replace(/\(?\:mm\)?/, ':mm:ss');
}
if(includeMinuteZero) {
return this.get('timeFormat').replace('(', '').replace(')', '');
}
return this.get('timeFormat').replace(/\(\:mm\)/, '');
var UiSettings = Backbone.Model.extend({
url : window.NzbDrone.ApiRoot + '/config/ui',
shortDateTime : function(includeSeconds) {
return this.get('shortDateFormat') + ' ' + this.time(true, includeSeconds);
},
longDateTime : function(includeSeconds) {
return this.get('longDateFormat') + ' ' + this.time(true, includeSeconds);
},
time : function(includeMinuteZero, includeSeconds) {
if (includeSeconds) {
return this.get('timeFormat').replace(/\(?\:mm\)?/, ':mm:ss');
}
});
var instance = new UiSettings(ApiData.get('config/ui'));
return instance;
}).call(this);
if (includeMinuteZero) {
return this.get('timeFormat').replace('(', '').replace(')', '');
}
return this.get('timeFormat').replace(/\(\:mm\)/, '');
}
});
var instance = new UiSettings(ApiData.get('config/ui'));
module.exports = instance;

View File

@ -1,13 +1,13 @@
var $ = require('jquery');
var vent = require('vent');
$(document).ajaxSuccess(function(event, xhr){
$(document).ajaxSuccess(function(event, xhr) {
var version = xhr.getResponseHeader('X-ApplicationVersion');
if(!version || !window.NzbDrone || !window.NzbDrone.Version) {
if (!version || !window.NzbDrone || !window.NzbDrone.Version) {
return;
}
if(version !== window.NzbDrone.Version) {
if (version !== window.NzbDrone.Version) {
vent.trigger(vent.Events.ServerUpdated);
}
});

View File

@ -1,6 +1,4 @@
require('backgrid');
require('../JsLibraries/backbone.backgrid.selectall');
var backgrid = require('backgrid');
require('../JsLibraries/backbone.backgrid.selectall');
module.exports = backgrid.Extension.SelectRowCell;

View File

@ -1,6 +1,4 @@
require('backbone');
require('../JsLibraries/backbone.collectionview');
window.Backbone = require('backbone');
require('../JsLibraries/backbone.collectionview');
module.exports = window.Backbone.CollectionView;

View File

@ -1,7 +1,7 @@
var jquery = require('jquery');
var Backbone = require('../JsLibraries/backbone');
var backbone = require('../JsLibraries/backbone');
window.Backbone = backbone;
backbone.$ = jquery;
window.Backbone = Backbone;
Backbone.$ = jquery;
module.exports = backbone;
module.exports = Backbone;

View File

@ -7,5 +7,4 @@ var asNamedView = require('../Mixins/AsNamedView');
templateMixin.call(window.Marionette.TemplateCache);
asNamedView.call(window.Marionette.ItemView.prototype);
module.exports = window.Marionette;

View File

@ -1,6 +1,7 @@
require('backbone');
require('../JsLibraries/backbone.validation');
var $ = require('jquery');
var jqueryValidation = require('../jQuery/jquery.validation');
jqueryValidation.call($);

View File

@ -1,6 +1,4 @@
require('../JsLibraries/jquery.signalR');
require('jquery');
require('jquery');
var signalR = require('../JsLibraries/jquery.signalR');
module.exports = signalR;

View File

@ -1,7 +1,6 @@
require('../JsLibraries/messenger');
require('jquery');
require('jquery');
var m = require('../JsLibraries/messenger');
window.Messenger.options = {theme : 'flat'};
window.Messenger.options = { theme : 'flat' };
module.exports = window.Messenger;

View File

@ -1,6 +1,4 @@
require('../JsLibraries/moment');
require('backbone');
require('backbone');
var backgrid = require('../JsLibraries/moment');
module.exports = backgrid;