New: iCal calendar feed.

This commit is contained in:
Taloth Saldono 2014-03-14 21:30:49 +01:00 committed by Taloth
parent cf1e0a4946
commit 794c09c17a
7 changed files with 61 additions and 44 deletions

View File

@ -23,7 +23,7 @@ namespace NzbDrone.Api.Calendar
private Response GetCalendarFeed()
{
var start = DateTime.Today.Subtract(TimeSpan.FromDays(7));
var start = DateTime.Today.AddDays(-7);
var end = DateTime.Today.AddDays(28);
var queryStart = Request.Query.Start;
@ -35,28 +35,25 @@ namespace NzbDrone.Api.Calendar
var episodes = _episodeService.EpisodesBetweenDates(start, end);
var icalCalendar = new iCalendar();
foreach (var series in episodes.GroupBy(v => v.Series))
foreach (var episode in episodes.OrderBy(v => v.AirDateUtc.Value))
{
foreach (var episode in series)
var occurrence = icalCalendar.Create<Event>();
occurrence.UID = "NzbDrone_episode_" + episode.Id.ToString();
occurrence.Status = episode.HasFile ? EventStatus.Confirmed : EventStatus.Tentative;
occurrence.Start = new iCalDateTime(episode.AirDateUtc.Value);
occurrence.End = new iCalDateTime(episode.AirDateUtc.Value.AddMinutes(episode.Series.Runtime));
occurrence.Description = episode.Overview;
occurrence.Categories = new List<string>() { episode.Series.Network };
switch (episode.Series.SeriesType)
{
var occurrence = icalCalendar.Create<Event>();
occurrence.UID = "NzbDrone_episode_" + episode.Id.ToString();
occurrence.Status = episode.HasFile ? EventStatus.Confirmed : EventStatus.Tentative;
occurrence.Start = new iCalDateTime(episode.AirDateUtc.Value);
occurrence.End = new iCalDateTime(episode.AirDateUtc.Value.AddMinutes(episode.Series.Runtime));
occurrence.Description = episode.Overview;
occurrence.Categories = new List<string>() { episode.Series.Network };
case SeriesTypes.Daily:
occurrence.Summary = string.Format("{0} - {1}", episode.Series.Title, episode.Title);
break;
switch (episode.Series.SeriesType)
{
case SeriesTypes.Daily:
occurrence.Summary = string.Format("{0} - {1}", episode.Series.Title, episode.Title);
break;
default:
occurrence.Summary = string.Format("{0} - {1}x{2:00} - {3}", episode.Series.Title, episode.SeasonNumber, episode.EpisodeNumber, episode.Title);
break;
}
default:
occurrence.Summary = string.Format("{0} - {1}x{2:00} - {3}", episode.Series.Title, episode.SeasonNumber, episode.EpisodeNumber, episode.Title);
break;
}
}

View File

@ -2,15 +2,24 @@
define(
[
'marionette',
], function (Marionette) {
'System/StatusModel',
'Mixins/CopyToClipboard'
], function (Marionette, StatusModel) {
return Marionette.Layout.extend({
template: 'Calendar/CalendarFeedViewTemplate',
onRender: function() {
// hackish way to determine the correct url, as using urlBase seems to only work for reverse proxies or so
var ics = '//' + window.location.host + '/feed/calendar/NzbDrone.ics';
this.$('#ical-url').val(window.location.protocol + ics);
this.$('#ical-subscribe-button').attr('href', 'webcal:' + ics);
}
ui: {
icalUrl : '.x-ical-url',
icalCopy : '.x-ical-copy'
},
templateHelpers: {
icalHttpUrl : window.location.protocol + '//' + window.location.host + StatusModel.get('urlBase') + '/feed/calendar/NzbDrone.ics',
icalWebCalUrl : 'webcal://' + window.location.host + StatusModel.get('urlBase') + '/feed/calendar/NzbDrone.ics'
},
onShow: function () {
this.ui.icalCopy.copyToClipboard(this.ui.icalUrl);
}
});
});

View File

@ -7,14 +7,17 @@
<div>
<div class="form-horizontal">
<div class="control-group">
<label class="control-label" for="ical-url">iCal feed</label>
<label class="control-label">iCal feed</label>
<div class="controls">
<input type="text" id="ical-url" class="x-ical-url" value="/feed/calendar/NzbDrone.ics" name="ical-url">
<span class="help-inline">
<i class="icon-nd-form-info" title="copy this url into your clients subscription form or use the subscribe now link if you have a webcal protocol handler installed"/>
</span>
or <a href="webcal:///feed/calendar/NzbDrone.ics" id="ical-subscribe-button">subscribe now!</a>
<div class="controls ical-url">
<div class="input-append">
<input type="text" class="x-ical-url" value="{{icalHttpUrl}}" readonly="readonly" />
<button class="btn btn-icon-only x-ical-copy" title="Copy to clipboard"><i class="icon-copy"></i></button>
<a class="btn btn-icon-only no-router" title="Subscribe" href="{{icalWebCalUrl}}" target="_blank"><i class="icon-calendar-empty"></i></a>
</div>
<span class="help-inline">
<i class="icon-nd-form-info" title="Copy this url into your clients subscription form or use the subscribe button if your browser support webcal"/>
</span>
</div>
</div>
</div>

View File

@ -5,7 +5,7 @@
</div>
<div class="pull-right">
<h4>
<i class="icon-calendar-empty ical x-ical"></i>
<i class="icon-calendar-empty ical x-ical"></i>
</h4>
</div>
<div id="x-upcoming"/>

View File

@ -162,9 +162,13 @@
.ical
{
color: @btnInverseBackground;
cursor: pointer;
}
#ical-url
{
width: 370px;
.ical-url {
input {
width : 440px;
cursor : text;
}
}

View File

@ -24,7 +24,7 @@
<link rel="apple-touch-icon" sizes="144x144" href="/Content/Images/touch/144.png?v=2"/>
<link rel="icon" type="image/ico" href="/Content/Images/favicon.ico?v=2"/>
<link rel="alternate" type="text/calendar" title="iCalendar feed for NzbDrone" href="/feed/calendar/NzbDrone.ics" />
<link rel="alternate" type="text/calendar" title="iCalendar feed for NzbDrone" href="/feed/calendar/NzbDrone.ics" />
</head>
<body>
<div id="nav-region"></div>

View File

@ -29,17 +29,21 @@ define(
return;
}
event.preventDefault();
var href = event.target.getAttribute('href');
if (!href && $target.closest('a') && $target.closest('a')[0]) {
var linkElement = $target.closest('a')[0];
if ($(linkElement).hasClass('no-router')) {
return;
}
href = linkElement.getAttribute('href');
}
event.preventDefault();
if (!href) {
throw 'couldn\'t find route target';
}