UI Cleanup - Updated Calendar subtree.

pull/3113/head
Taloth Saldono 10 years ago
parent f5118fc430
commit 83b8ab8fe9

@ -3,16 +3,19 @@ var StatusModel = require('../System/StatusModel');
require('../Mixins/CopyToClipboard'); require('../Mixins/CopyToClipboard');
module.exports = Marionette.Layout.extend({ module.exports = Marionette.Layout.extend({
template : 'Calendar/CalendarFeedViewTemplate', template : 'Calendar/CalendarFeedViewTemplate',
ui : {
ui : {
icalUrl : '.x-ical-url', icalUrl : '.x-ical-url',
icalCopy : '.x-ical-copy' icalCopy : '.x-ical-copy'
}, },
templateHelpers : { templateHelpers : {
icalHttpUrl : window.location.protocol + '//' + window.location.host + StatusModel.get('urlBase') + '/feed/calendar/NzbDrone.ics?apikey=' + window.NzbDrone.ApiKey, icalHttpUrl : window.location.protocol + '//' + window.location.host + StatusModel.get('urlBase') + '/feed/calendar/NzbDrone.ics?apikey=' + window.NzbDrone.ApiKey,
icalWebCalUrl : 'webcal://' + window.location.host + StatusModel.get('urlBase') + '/feed/calendar/NzbDrone.ics?apikey=' + window.NzbDrone.ApiKey icalWebCalUrl : 'webcal://' + window.location.host + StatusModel.get('urlBase') + '/feed/calendar/NzbDrone.ics?apikey=' + window.NzbDrone.ApiKey
}, },
onShow : function(){
onShow : function() {
this.ui.icalCopy.copyToClipboard(this.ui.icalUrl); this.ui.icalCopy.copyToClipboard(this.ui.icalUrl);
} }
}); });

@ -5,23 +5,31 @@ var CalendarView = require('./CalendarView');
var CalendarFeedView = require('./CalendarFeedView'); var CalendarFeedView = require('./CalendarFeedView');
module.exports = Marionette.Layout.extend({ module.exports = Marionette.Layout.extend({
template : 'Calendar/CalendarLayoutTemplate', template : 'Calendar/CalendarLayoutTemplate',
regions : {
regions : {
upcoming : '#x-upcoming', upcoming : '#x-upcoming',
calendar : '#x-calendar' calendar : '#x-calendar'
}, },
events : {"click .x-ical" : '_showiCal'},
onShow : function(){ events : {
'click .x-ical' : '_showiCal'
},
onShow : function() {
this._showUpcoming(); this._showUpcoming();
this._showCalendar(); this._showCalendar();
}, },
_showUpcoming : function(){
_showUpcoming : function() {
this.upcoming.show(new UpcomingCollectionView()); this.upcoming.show(new UpcomingCollectionView());
}, },
_showCalendar : function(){
_showCalendar : function() {
this.calendar.show(new CalendarView()); this.calendar.show(new CalendarView());
}, },
_showiCal : function(){
_showiCal : function() {
var view = new CalendarFeedView(); var view = new CalendarFeedView();
AppLayout.modalRegion.show(view); AppLayout.modalRegion.show(view);
} }

@ -11,60 +11,75 @@ require('fullcalendar');
require('jquery.easypiechart'); require('jquery.easypiechart');
module.exports = Marionette.ItemView.extend({ module.exports = Marionette.ItemView.extend({
storageKey : 'calendar.view', storageKey : 'calendar.view',
initialize : function(){
this.collection = new CalendarCollection().bindSignalR({updateOnly : true}); initialize : function() {
this.collection = new CalendarCollection().bindSignalR({ updateOnly : true });
this.listenTo(this.collection, 'change', this._reloadCalendarEvents); this.listenTo(this.collection, 'change', this._reloadCalendarEvents);
this.listenTo(QueueCollection, 'sync', this._reloadCalendarEvents); this.listenTo(QueueCollection, 'sync', this._reloadCalendarEvents);
}, },
render : function(){
render : function() {
this.$el.empty().fullCalendar(this._getOptions()); this.$el.empty().fullCalendar(this._getOptions());
}, },
onShow : function(){
onShow : function() {
this.$('.fc-button-today').click(); this.$('.fc-button-today').click();
}, },
_viewRender : function(view){
if($(window).width() < 768) { _viewRender : function(view) {
if ($(window).width() < 768) {
this.$('.fc-header-title').show(); this.$('.fc-header-title').show();
this.$('.calendar-title').remove(); this.$('.calendar-title').remove();
var title = this.$('.fc-header-title').text(); var title = this.$('.fc-header-title').text();
var titleDiv = '<div class="calendar-title"><h2>{0}</h2></div>'.format(title); var titleDiv = '<div class="calendar-title"><h2>{0}</h2></div>'.format(title);
this.$('.fc-header').before(titleDiv); this.$('.fc-header').before(titleDiv);
this.$('.fc-header-title').hide(); this.$('.fc-header-title').hide();
} }
if(Config.getValue(this.storageKey) !== view.name) {
if (Config.getValue(this.storageKey) !== view.name) {
Config.setValue(this.storageKey, view.name); Config.setValue(this.storageKey, view.name);
} }
this._getEvents(view); this._getEvents(view);
}, },
_eventRender : function(event, element){
_eventRender : function(event, element) {
this.$(element).addClass(event.statusLevel); this.$(element).addClass(event.statusLevel);
this.$(element).children('.fc-event-inner').addClass(event.statusLevel); this.$(element).children('.fc-event-inner').addClass(event.statusLevel);
if(event.downloading) {
if (event.downloading) {
var progress = 100 - event.downloading.get('sizeleft') / event.downloading.get('size') * 100; var progress = 100 - event.downloading.get('sizeleft') / event.downloading.get('size') * 100;
var releaseTitle = event.downloading.get('title'); var releaseTitle = event.downloading.get('title');
var estimatedCompletionTime = moment(event.downloading.get('estimatedCompletionTime')).fromNow(); var estimatedCompletionTime = moment(event.downloading.get('estimatedCompletionTime')).fromNow();
var status = event.downloading.get('status').toLocaleLowerCase(); var status = event.downloading.get('status').toLocaleLowerCase();
var errorMessage = event.downloading.get('errorMessage'); var errorMessage = event.downloading.get('errorMessage');
if(status === 'pending') {
if (status === 'pending') {
this._addStatusIcon(element, 'icon-time', 'Release will be processed {0}'.format(estimatedCompletionTime)); this._addStatusIcon(element, 'icon-time', 'Release will be processed {0}'.format(estimatedCompletionTime));
} }
else if(errorMessage) {
if(status === 'completed') { else if (errorMessage) {
if (status === 'completed') {
this._addStatusIcon(element, 'icon-nd-import-failed', 'Import failed: {0}'.format(errorMessage)); this._addStatusIcon(element, 'icon-nd-import-failed', 'Import failed: {0}'.format(errorMessage));
} } else {
else {
this._addStatusIcon(element, 'icon-nd-download-failed', 'Download failed: {0}'.format(errorMessage)); this._addStatusIcon(element, 'icon-nd-download-failed', 'Download failed: {0}'.format(errorMessage));
} }
} }
else if(status === 'failed') {
else if (status === 'failed') {
this._addStatusIcon(element, 'icon-nd-download-failed', 'Download failed: check download client for more details'); this._addStatusIcon(element, 'icon-nd-download-failed', 'Download failed: check download client for more details');
} }
else if(status === 'warning') {
else if (status === 'warning') {
this._addStatusIcon(element, 'icon-nd-download-warning', 'Download warning: check download client for more details'); this._addStatusIcon(element, 'icon-nd-download-warning', 'Download warning: check download client for more details');
} }
else { else {
this.$(element).find('.fc-event-time').after('<span class="chart pull-right" data-percent="{0}"></span>'.format(progress)); this.$(element).find('.fc-event-time').after('<span class="chart pull-right" data-percent="{0}"></span>'.format(progress));
this.$(element).find('.chart').easyPieChart({ this.$(element).find('.chart').easyPieChart({
barColor : '#ffffff', barColor : '#ffffff',
trackColor : false, trackColor : false,
@ -73,6 +88,7 @@ module.exports = Marionette.ItemView.extend({
size : 14, size : 14,
animate : false animate : false
}); });
this.$(element).find('.chart').tooltip({ this.$(element).find('.chart').tooltip({
title : 'Episode is downloading - {0}% {1}'.format(progress.toFixed(1), releaseTitle), title : 'Episode is downloading - {0}% {1}'.format(progress.toFixed(1), releaseTitle),
container : '.fc-content' container : '.fc-content'
@ -80,10 +96,13 @@ module.exports = Marionette.ItemView.extend({
} }
} }
}, },
_getEvents : function(view){
_getEvents : function(view) {
var start = view.start.toISOString(); var start = view.start.toISOString();
var end = view.end.toISOString(); var end = view.end.toISOString();
this.$el.fullCalendar('removeEvents'); this.$el.fullCalendar('removeEvents');
this.collection.fetch({ this.collection.fetch({
data : { data : {
start : start, start : start,
@ -92,14 +111,18 @@ module.exports = Marionette.ItemView.extend({
success : this._setEventData.bind(this) success : this._setEventData.bind(this)
}); });
}, },
_setEventData : function(collection){
_setEventData : function(collection) {
var events = []; var events = [];
var self = this; var self = this;
collection.each(function(model){
collection.each(function(model) {
var seriesTitle = model.get('series').title; var seriesTitle = model.get('series').title;
var start = model.get('airDateUtc'); var start = model.get('airDateUtc');
var runtime = model.get('series').runtime; var runtime = model.get('series').runtime;
var end = moment(start).add('minutes', runtime).toISOString(); var end = moment(start).add('minutes', runtime).toISOString();
var event = { var event = {
title : seriesTitle, title : seriesTitle,
start : moment(start), start : moment(start),
@ -109,42 +132,55 @@ module.exports = Marionette.ItemView.extend({
downloading : QueueCollection.findEpisode(model.get('id')), downloading : QueueCollection.findEpisode(model.get('id')),
model : model model : model
}; };
events.push(event); events.push(event);
}); });
this.$el.fullCalendar('addEventSource', events); this.$el.fullCalendar('addEventSource', events);
}, },
_getStatusLevel : function(element, endTime){
_getStatusLevel : function(element, endTime) {
var hasFile = element.get('hasFile'); var hasFile = element.get('hasFile');
var downloading = QueueCollection.findEpisode(element.get('id')) || element.get('grabbed'); var downloading = QueueCollection.findEpisode(element.get('id')) || element.get('grabbed');
var currentTime = moment(); var currentTime = moment();
var start = moment(element.get('airDateUtc')); var start = moment(element.get('airDateUtc'));
var end = moment(endTime); var end = moment(endTime);
var statusLevel = 'primary'; var statusLevel = 'primary';
if(hasFile) {
if (hasFile) {
statusLevel = 'success'; statusLevel = 'success';
} }
else if(downloading) {
else if (downloading) {
statusLevel = 'purple'; statusLevel = 'purple';
} }
else if(currentTime.isAfter(start) && currentTime.isBefore(end)) {
else if (currentTime.isAfter(start) && currentTime.isBefore(end)) {
statusLevel = 'warning'; statusLevel = 'warning';
} }
else if(start.isBefore(currentTime) && !hasFile) {
else if (start.isBefore(currentTime) && !hasFile) {
statusLevel = 'danger'; statusLevel = 'danger';
} }
else if(element.get('episodeNumber') === 1) {
else if (element.get('episodeNumber') === 1) {
statusLevel = 'premiere'; statusLevel = 'premiere';
} }
if(end.isBefore(currentTime.startOf('day'))) {
if (end.isBefore(currentTime.startOf('day'))) {
statusLevel += ' past'; statusLevel += ' past';
} }
return statusLevel; return statusLevel;
}, },
_reloadCalendarEvents : function(){
_reloadCalendarEvents : function() {
this.$el.fullCalendar('removeEvents'); this.$el.fullCalendar('removeEvents');
this._setEventData(this.collection); this._setEventData(this.collection);
}, },
_getOptions : function(){
_getOptions : function() {
var options = { var options = {
allDayDefault : false, allDayDefault : false,
weekMode : 'variable', weekMode : 'variable',
@ -152,40 +188,50 @@ module.exports = Marionette.ItemView.extend({
timeFormat : 'h(:mm)a', timeFormat : 'h(:mm)a',
viewRender : this._viewRender.bind(this), viewRender : this._viewRender.bind(this),
eventRender : this._eventRender.bind(this), eventRender : this._eventRender.bind(this),
eventClick : function(event){ eventClick : function(event) {
vent.trigger(vent.Commands.ShowEpisodeDetails, {episode : event.model}); vent.trigger(vent.Commands.ShowEpisodeDetails, { episode : event.model });
} }
}; };
if($(window).width() < 768) {
if ($(window).width() < 768) {
options.defaultView = Config.getValue(this.storageKey, 'basicDay'); options.defaultView = Config.getValue(this.storageKey, 'basicDay');
options.header = { options.header = {
left : 'prev,next today', left : 'prev,next today',
center : 'title', center : 'title',
right : 'basicWeek,basicDay' right : 'basicWeek,basicDay'
}; };
} }
else { else {
options.defaultView = Config.getValue(this.storageKey, 'basicWeek'); options.defaultView = Config.getValue(this.storageKey, 'basicWeek');
options.header = { options.header = {
left : 'prev,next today', left : 'prev,next today',
center : 'title', center : 'title',
right : 'month,basicWeek,basicDay' right : 'month,basicWeek,basicDay'
}; };
} }
options.titleFormat = { options.titleFormat = {
month : 'MMMM YYYY', month : 'MMMM YYYY',
week : UiSettings.get('shortDateFormat'), week : UiSettings.get('shortDateFormat'),
day : UiSettings.get('longDateFormat') day : UiSettings.get('longDateFormat')
}; };
options.columnFormat = { options.columnFormat = {
month : 'ddd', month : 'ddd',
week : UiSettings.get('calendarWeekColumnHeader'), week : UiSettings.get('calendarWeekColumnHeader'),
day : 'dddd' day : 'dddd'
}; };
options.timeFormat = {"default" : UiSettings.get('timeFormat')};
options.timeFormat = {
'default' : UiSettings.get('timeFormat')
};
return options; return options;
}, },
_addStatusIcon : function(element, icon, tooltip){ _addStatusIcon : function(element, icon, tooltip) {
this.$(element).find('.fc-event-time').after('<span class="status pull-right"><i class="{0}"></i></span>'.format(icon)); this.$(element).find('.fc-event-time').after('<span class="status pull-right"><i class="{0}"></i></span>'.format(icon));
this.$(element).find('.status').tooltip({ this.$(element).find('.status').tooltip({
title : tooltip, title : tooltip,

@ -2,9 +2,10 @@ var Backbone = require('backbone');
var EpisodeModel = require('../Series/EpisodeModel'); var EpisodeModel = require('../Series/EpisodeModel');
module.exports = Backbone.Collection.extend({ module.exports = Backbone.Collection.extend({
url : window.NzbDrone.ApiRoot + '/calendar', url : window.NzbDrone.ApiRoot + '/calendar',
model : EpisodeModel, model : EpisodeModel,
comparator : function(model){
comparator : function(model) {
var date = new Date(model.get('airDateUtc')); var date = new Date(model.get('airDateUtc'));
var time = date.getTime(); var time = date.getTime();
return time; return time;

@ -3,21 +3,26 @@ var moment = require('moment');
var EpisodeModel = require('../Series/EpisodeModel'); var EpisodeModel = require('../Series/EpisodeModel');
module.exports = Backbone.Collection.extend({ module.exports = Backbone.Collection.extend({
url : window.NzbDrone.ApiRoot + '/calendar', url : window.NzbDrone.ApiRoot + '/calendar',
model : EpisodeModel, model : EpisodeModel,
comparator : function(model1, model2){
comparator : function(model1, model2) {
var airDate1 = model1.get('airDateUtc'); var airDate1 = model1.get('airDateUtc');
var date1 = moment(airDate1); var date1 = moment(airDate1);
var time1 = date1.unix(); var time1 = date1.unix();
var airDate2 = model2.get('airDateUtc'); var airDate2 = model2.get('airDateUtc');
var date2 = moment(airDate2); var date2 = moment(airDate2);
var time2 = date2.unix(); var time2 = date2.unix();
if(time1 < time2) {
if (time1 < time2) {
return -1; return -1;
} }
if(time1 > time2) {
if (time1 > time2) {
return 1; return 1;
} }
return 0; return 0;
} }
}); });

@ -5,17 +5,21 @@ var UpcomingItemView = require('./UpcomingItemView');
require('../Mixins/backbone.signalr.mixin'); require('../Mixins/backbone.signalr.mixin');
module.exports = Marionette.CollectionView.extend({ module.exports = Marionette.CollectionView.extend({
itemView : UpcomingItemView, itemView : UpcomingItemView,
initialize : function(){
this.collection = new UpcomingCollection().bindSignalR({updateOnly : true}); initialize : function() {
this.collection = new UpcomingCollection().bindSignalR({ updateOnly : true });
this.collection.fetch(); this.collection.fetch();
this._fetchCollection = _.bind(this._fetchCollection, this); this._fetchCollection = _.bind(this._fetchCollection, this);
this.timer = window.setInterval(this._fetchCollection, 60 * 60 * 1000); this.timer = window.setInterval(this._fetchCollection, 60 * 60 * 1000);
}, },
onClose : function(){
onClose : function() {
window.clearInterval(this.timer); window.clearInterval(this.timer);
}, },
_fetchCollection : function(){
_fetchCollection : function() {
this.collection.fetch(); this.collection.fetch();
} }
}); });

@ -3,17 +3,26 @@ var Marionette = require('marionette');
var moment = require('moment'); var moment = require('moment');
module.exports = Marionette.ItemView.extend({ module.exports = Marionette.ItemView.extend({
template : 'Calendar/UpcomingItemViewTemplate', template : 'Calendar/UpcomingItemViewTemplate',
tagName : 'div', tagName : 'div',
events : {"click .x-episode-title" : '_showEpisodeDetails'},
initialize : function(){ events : {
'click .x-episode-title' : '_showEpisodeDetails'
},
initialize : function() {
var start = this.model.get('airDateUtc'); var start = this.model.get('airDateUtc');
var runtime = this.model.get('series').runtime; var runtime = this.model.get('series').runtime;
var end = moment(start).add('minutes', runtime); var end = moment(start).add('minutes', runtime);
this.model.set({end : end.toISOString()});
this.model.set({
end : end.toISOString()
});
this.listenTo(this.model, 'change', this.render); this.listenTo(this.model, 'change', this.render);
}, },
_showEpisodeDetails : function(){
vent.trigger(vent.Commands.ShowEpisodeDetails, {episode : this.model}); _showEpisodeDetails : function() {
vent.trigger(vent.Commands.ShowEpisodeDetails, { episode : this.model });
} }
}); });
Loading…
Cancel
Save