You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
9.5 KiB
251 lines
9.5 KiB
'use strict';
|
|
|
|
define(
|
|
[
|
|
'jquery',
|
|
'vent',
|
|
'marionette',
|
|
'moment',
|
|
'Calendar/Collection',
|
|
'Shared/UiSettingsModel',
|
|
'Activity/Queue/QueueCollection',
|
|
'Config',
|
|
'Mixins/backbone.signalr.mixin',
|
|
'fullcalendar',
|
|
'jquery.easypiechart'
|
|
], function ($, vent, Marionette, moment, CalendarCollection, UiSettings, QueueCollection, Config) {
|
|
|
|
return Marionette.ItemView.extend({
|
|
storageKey: 'calendar.view',
|
|
|
|
initialize: function () {
|
|
this.collection = new CalendarCollection().bindSignalR({ updateOnly: true });
|
|
this.listenTo(this.collection, 'change', this._reloadCalendarEvents);
|
|
this.listenTo(QueueCollection, 'sync', this._reloadCalendarEvents);
|
|
},
|
|
|
|
render : function () {
|
|
this.$el.empty().fullCalendar(this._getOptions());
|
|
},
|
|
|
|
onShow: function () {
|
|
this.$('.fc-button-today').click();
|
|
},
|
|
|
|
_viewRender: function (view) {
|
|
|
|
if ($(window).width() < 768) {
|
|
this.$('.fc-header-title').show();
|
|
this.$('.calendar-title').remove();
|
|
|
|
var title = this.$('.fc-header-title').text();
|
|
var titleDiv = '<div class="calendar-title"><h2>{0}</h2></div>'.format(title);
|
|
|
|
this.$('.fc-header').before(titleDiv);
|
|
this.$('.fc-header-title').hide();
|
|
}
|
|
|
|
if (Config.getValue(this.storageKey) !== view.name) {
|
|
Config.setValue(this.storageKey, view.name);
|
|
}
|
|
|
|
this._getEvents(view);
|
|
},
|
|
|
|
_eventRender: function (event, element) {
|
|
this.$(element).addClass(event.statusLevel);
|
|
this.$(element).children('.fc-event-inner').addClass(event.statusLevel);
|
|
|
|
if (event.downloading) {
|
|
var progress = 100 - (event.downloading.get('sizeleft') / event.downloading.get('size') * 100);
|
|
var releaseTitle = event.downloading.get('title');
|
|
var estimatedCompletionTime = moment(event.downloading.get('estimatedCompletionTime')).fromNow();
|
|
var status = event.downloading.get('status').toLocaleLowerCase();
|
|
var errorMessage = event.downloading.get('errorMessage');
|
|
|
|
if (status === 'pending') {
|
|
this._addStatusIcon(element, 'icon-time', 'Release will be processed {0}'.format(estimatedCompletionTime));
|
|
}
|
|
|
|
else if (errorMessage) {
|
|
if (status === 'completed') {
|
|
this._addStatusIcon(element, 'icon-nd-import-failed', 'Import failed: {0}'.format(errorMessage));
|
|
}
|
|
else {
|
|
this._addStatusIcon(element, 'icon-nd-download-failed', 'Download failed: {0}'.format(errorMessage));
|
|
}
|
|
}
|
|
|
|
else if (status === 'failed') {
|
|
this._addStatusIcon(element, 'icon-nd-download-failed', 'Download failed: check download client for more details');
|
|
}
|
|
|
|
else if (status === 'warning') {
|
|
this._addStatusIcon(element, 'icon-nd-download-warning', 'Download warning: check download client for more details');
|
|
}
|
|
|
|
else {
|
|
this.$(element).find('.fc-event-time')
|
|
.after('<span class="chart pull-right" data-percent="{0}"></span>'.format(progress));
|
|
|
|
this.$(element).find('.chart').easyPieChart({
|
|
barColor : '#ffffff',
|
|
trackColor: false,
|
|
scaleColor: false,
|
|
lineWidth : 2,
|
|
size : 14,
|
|
animate : false
|
|
});
|
|
|
|
this.$(element).find('.chart').tooltip({
|
|
title: 'Episode is downloading - {0}% {1}'.format(progress.toFixed(1), releaseTitle),
|
|
container: '.fc-content'
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
_getEvents: function (view) {
|
|
var start = view.start.toISOString();
|
|
var end = view.end.toISOString();
|
|
|
|
this.$el.fullCalendar('removeEvents');
|
|
|
|
this.collection.fetch({
|
|
data : { start: start, end: end },
|
|
success: this._setEventData.bind(this)
|
|
});
|
|
},
|
|
|
|
_setEventData: function (collection) {
|
|
var events = [];
|
|
|
|
var self = this;
|
|
|
|
collection.each(function (model) {
|
|
var seriesTitle = model.get('series').title;
|
|
var start = model.get('airDateUtc');
|
|
var runtime = model.get('series').runtime;
|
|
var end = moment(start).add('minutes', runtime).toISOString();
|
|
|
|
var event = {
|
|
title : seriesTitle,
|
|
start : moment(start),
|
|
end : moment(end),
|
|
allDay : false,
|
|
statusLevel : self._getStatusLevel(model, end),
|
|
downloading : QueueCollection.findEpisode(model.get('id')),
|
|
model : model
|
|
};
|
|
|
|
events.push(event);
|
|
});
|
|
|
|
this.$el.fullCalendar('addEventSource', events);
|
|
},
|
|
|
|
_getStatusLevel: function (element, endTime) {
|
|
var hasFile = element.get('hasFile');
|
|
var downloading = QueueCollection.findEpisode(element.get('id')) || element.get('grabbed');
|
|
var currentTime = moment();
|
|
var start = moment(element.get('airDateUtc'));
|
|
var end = moment(endTime);
|
|
|
|
var statusLevel = 'primary';
|
|
|
|
if (hasFile) {
|
|
statusLevel = 'success';
|
|
}
|
|
|
|
else if (downloading) {
|
|
statusLevel = 'purple';
|
|
}
|
|
|
|
else if (currentTime.isAfter(start) && currentTime.isBefore(end)) {
|
|
statusLevel = 'warning';
|
|
}
|
|
|
|
else if (start.isBefore(currentTime) && !hasFile) {
|
|
statusLevel = 'danger';
|
|
}
|
|
|
|
else if (element.get('episodeNumber') === 1) {
|
|
statusLevel = 'premiere';
|
|
}
|
|
|
|
if (end.isBefore(currentTime.startOf('day'))) {
|
|
statusLevel += ' past';
|
|
}
|
|
|
|
return statusLevel;
|
|
},
|
|
|
|
_reloadCalendarEvents: function () {
|
|
this.$el.fullCalendar('removeEvents');
|
|
this._setEventData(this.collection);
|
|
},
|
|
|
|
_getOptions: function () {
|
|
var options = {
|
|
allDayDefault : false,
|
|
weekMode : 'variable',
|
|
firstDay : UiSettings.get('firstDayOfWeek'),
|
|
timeFormat : 'h(:mm)a',
|
|
viewRender : this._viewRender.bind(this),
|
|
eventRender : this._eventRender.bind(this),
|
|
eventClick : function (event) {
|
|
vent.trigger(vent.Commands.ShowEpisodeDetails, {episode: event.model});
|
|
}
|
|
};
|
|
|
|
if ($(window).width() < 768) {
|
|
options.defaultView = Config.getValue(this.storageKey, 'basicDay');
|
|
|
|
options.header = {
|
|
left : 'prev,next today',
|
|
center: 'title',
|
|
right : 'basicWeek,basicDay'
|
|
};
|
|
}
|
|
|
|
else {
|
|
options.defaultView = Config.getValue(this.storageKey, 'basicWeek');
|
|
|
|
options.header = {
|
|
left : 'prev,next today',
|
|
center: 'title',
|
|
right : 'month,basicWeek,basicDay'
|
|
};
|
|
}
|
|
|
|
options.titleFormat = {
|
|
month : 'MMMM YYYY',
|
|
week : UiSettings.get('shortDateFormat'),
|
|
day : UiSettings.get('longDateFormat')
|
|
};
|
|
|
|
options.columnFormat = {
|
|
month : 'ddd', // Mon
|
|
week : UiSettings.get('calendarWeekColumnHeader'),
|
|
day : 'dddd' // Monday
|
|
};
|
|
|
|
options.timeFormat = {
|
|
'default': UiSettings.get('timeFormat')
|
|
};
|
|
|
|
return options;
|
|
},
|
|
|
|
_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('.status').tooltip({
|
|
title: tooltip,
|
|
container: '.fc-content'
|
|
});
|
|
}
|
|
});
|
|
});
|