Permalink
Browse files

Allow the user to select a feed if a Web page exports more than one.

  • Loading branch information...
tmiw committed Nov 17, 2013
1 parent 7bcfc0d commit a77e02f2eb04c7e0c9ade12bc032ce4ecfd9c23e
@@ -26,6 +26,7 @@ NR.API.AuthenticationFailed = "auth_failed"
NR.API.ValidationFailed = "validation_failed"
NR.API.ServerError = "server_error"
NR.API.NotAFeedError = "not_a_feed"
+NR.API.MultipleFeedsFoundError = "multiple_feeds_found"
NR.API.httpErrorCodeList = {
401: NR.API.AuthenticationFailed
@@ -5,6 +5,9 @@ else
NR.Models = {}
+class NR.Models.MultipleFeedEntry extends SimpleMVC.Model
+ @fields "title", "url"
+
class NR.Models.CreateFeedModel extends SimpleMVC.Model
@fields "baseUrl", "baseHtml", "xpathTitle", "xpathLink", "xpathBody"
@@ -172,6 +172,34 @@ class NR.Views.NewsFeedListing extends SimpleMVC.CollectionView
window.app.deselectFeed()
e.preventDefault()
+class NR.Views.MultipleFeedEntry extends SimpleMVC.View
+ @tag "div"
+ @class "radio"
+ this.prototype.template = Mustache.compile $("#template-multipleFeedEntry").html()
+
+class NR.Views.MultipleFeedsFoundWindow extends SimpleMVC.CollectionView
+ @hideOnStart true
+ @id "multipleFeedsFound"
+ @listClass "multipleFeedList"
+ @viewType NR.Views.MultipleFeedEntry
+ this.prototype.template = Mustache.compile $("#template-multipleFeedsListing").html()
+
+ @event "click", "#addMultipleFeedButton", () ->
+ if not $("#addMultipleFeedButton").hasClass "disabled"
+ selectedUrl = $('input:radio[name=aMultipleFeedEntry]:checked').val();
+ window.app.addFeed selectedUrl
+ this.hide()
+
+ @event "click", "input:radio[name=aMultipleFeedEntry]", () ->
+ # Enable Add button.
+ $("#addMultipleFeedButton").removeClass "disabled"
+
+ show: () =>
+ this.domObject.modal()
+
+ hide: () =>
+ this.domObject.modal('hide')
+
class NR.Views.CreateFeedWindow extends SimpleMVC.View
@id "createFeed"
@hideOnStart true
@@ -28,10 +28,19 @@ class NR.Application extends SimpleMVC.Controller
feedModel.baseUrl = $("#addFeedUrl").val()
this._createFeedView.model = feedModel
this._createFeedView.show()
+ else if desc == NR.API.MultipleFeedsFoundError
+ foundList = new SimpleMVC.Collection
+ this._multipleFeedFoundView = new NR.Views.MultipleFeedsFoundWindow foundList
+ this._multipleFeedFoundView.show()
+ for i in data
+ entry = new NR.Models.MultipleFeedEntry
+ entry.title = i.title
+ entry.url = i.url
+ foundList.add entry
else
errorText = "The server encountered an error while processing the request. Please try again."
- if desc != NR.API.NotAFeedError
+ if desc != NR.API.NotAFeedError && desc != NR.API.MultipleFeedsFoundError
noty({ text: errorText, layout: "topRight", timeout: 2000, dismissQueue: true, type: "error" });
@route "saved/:uid", (uid) ->
@@ -35,13 +35,16 @@ object Constants {
class ApiResult(success: Boolean, error_string: Option[String])
case class StringDataApiResult(success: Boolean, error_string: Option[String], data: String)
- extends ApiResult(success, error_string)
+ extends ApiResult(success, error_string)
+
+case class AddFeedListApiResult(success: Boolean, error_string: Option[String], data: List[AddFeedEntry])
+ extends ApiResult(success, error_string)
case class NoDataApiResult(success: Boolean, error_string: Option[String])
extends ApiResult(success, error_string)
case class FeedInfoApiResult(success: Boolean, error_string: Option[String], data: NewsFeedInfo)
- extends ApiResult(success, error_string)
+ extends ApiResult(success, error_string)
case class FeedListApiResult(success: Boolean, error_string: Option[String], data: List[NewsFeedInfo])
extends ApiResult(success, error_string)
@@ -159,6 +159,11 @@ class ManualCloseBufferedStream(s: java.io.InputStream) extends java.io.Buffered
}
class HasNoFeedsException(text: String) extends Exception(text) { }
+case class AddFeedEntry(title: String, url: String)
+class MultipleFeedsException(feedList: List[AddFeedEntry]) extends Exception
+{
+ def getFeedList = feedList
+}
object XmlFeedFactory {
val parser = XML.withSAXParser(new org.ccil.cowan.tagsoup.jaxp.SAXFactoryImpl().newSAXParser())
@@ -375,10 +380,19 @@ object XmlFeedFactory {
val feedLinks = (xmlDoc \\ "link").filter(attributeEquals("rel", "alternate")(_))
.filter(x => attributeEquals("type", "application/rss+xml")(x) ||
attributeEquals("type", "application/atom+xml")(x))
- if (feedLinks.count(_ => true) > 0 && !feedLinks.head.attribute("href").map(_.text).head.equals(url))
+ val feedCount = feedLinks.count(_ => true)
+ if (feedCount == 1 && !feedLinks.head.attribute("href").map(_.text).head.equals(url))
{
load(new java.net.URL(new java.net.URL(currentUrl), feedLinks.head.attribute("href").map(_.text).head).toString())
}
+ else if (feedCount > 1)
+ {
+ // Return list of RSS feeds for user to choose from.
+ throw new MultipleFeedsException(
+ feedLinks.map(p => AddFeedEntry(
+ p.attribute("title").map(_.text).head,
+ p.attribute("href").map(_.text).head)).toList)
+ }
else
{
val feed =
@@ -240,6 +240,9 @@ class FeedServlet(dao: DataTables, db: Database, implicit val swagger: Swagger)
// need to do this because of XSS restrictions on the client side.
StringDataApiResult(false, Some("not_a_feed"), e.getMessage())
}
+ case e:MultipleFeedsException => {
+ AddFeedListApiResult(false, Some("multiple_feeds_found"), e.getFeedList)
+ }
}
}
}, {
@@ -91,6 +91,10 @@
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
+ <div class="modal fade" id="multipleFeedsFound" tabindex="-1" role="dialog" aria-labelledby="multipleFeedsFound" aria-hidden="true">
+
+ </div><!-- /.modal -->
+
<div class="modal fade" id="createFeed" tabindex="-1" role="dialog" aria-labelledby="createFeedLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
@@ -167,7 +171,36 @@
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
-
+
+<script type="text/template" id="template-multipleFeedsListing">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+ <h4 class="modal-title">Multiple Feeds Found</h4>
+ </div>
+ <div class="modal-body">
+ <p>
+ The Web page provided exports multiple feeds. Please choose one below to add:
+ </p>
+ <p class="multipleFeedList">
+ </p>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ <button type="button" class="btn btn-primary disabled" id="addMultipleFeedButton">Add</button>
+ </div>
+ </div><!-- /.modal-content -->
+ </div><!-- /.modal-dialog -->
+</script>
+
+<script type="text/template" id="template-multipleFeedEntry">
+ <label>
+ <input type="radio" name="aMultipleFeedEntry" value="{{url}}" />
+ {{title}}
+ </label>
+</script>
+
<script type="text/template" id="template-topNavBar">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">

0 comments on commit a77e02f

Please sign in to comment.