#109 - add RSS feed

Thu, 13 May 2021 11:28:50 +0200

author
Mike Becker <universe@uap-core.de>
date
Thu, 13 May 2021 11:28:50 +0200
changeset 195
9c7aff3cbb14
parent 194
2b3b7d0a885e
child 196
74682d8dce56

#109 - add RSS feed

src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/servlet/FeedServlet.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/viewmodel/Feeds.kt file | annotate | diff | comparison | revisions
src/main/resources/localization/strings.properties file | annotate | diff | comparison | revisions
src/main/resources/localization/strings_de.properties file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jsp/issues-feed.jsp file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jsp/site.jsp file | annotate | diff | comparison | revisions
     1.1 --- a/src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt	Thu May 13 10:23:37 2021 +0200
     1.2 +++ b/src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt	Thu May 13 11:28:50 2021 +0200
     1.3 @@ -108,9 +108,13 @@
     1.4      fun param(name: String): String? = request.getParameter(name)
     1.5      fun paramArray(name: String): Array<String> = request.getParameterValues(name) ?: emptyArray()
     1.6  
     1.7 +    fun forward(jsp: String) {
     1.8 +        request.getRequestDispatcher(jspPath(jsp)).forward(request, response)
     1.9 +    }
    1.10 +
    1.11      fun render(page: String? = null) {
    1.12          page?.let { contentPage = it }
    1.13 -        request.getRequestDispatcher(jspPath("site")).forward(request, response)
    1.14 +        forward("site")
    1.15      }
    1.16  
    1.17      fun renderCommit(location: String? = null) {
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/FeedServlet.kt	Thu May 13 11:28:50 2021 +0200
     2.3 @@ -0,0 +1,51 @@
     2.4 +/*
     2.5 + * Copyright 2021 Mike Becker. All rights reserved.
     2.6 + *
     2.7 + * Redistribution and use in source and binary forms, with or without
     2.8 + * modification, are permitted provided that the following conditions are met:
     2.9 + *
    2.10 + * 1. Redistributions of source code must retain the above copyright
    2.11 + * notice, this list of conditions and the following disclaimer.
    2.12 + *
    2.13 + * 2. Redistributions in binary form must reproduce the above copyright
    2.14 + * notice, this list of conditions and the following disclaimer in the
    2.15 + * documentation and/or other materials provided with the distribution.
    2.16 + *
    2.17 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    2.18 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    2.19 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    2.20 + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    2.21 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    2.22 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    2.23 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    2.24 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    2.25 + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    2.26 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2.27 + */
    2.28 +
    2.29 +package de.uapcore.lightpit.servlet
    2.30 +
    2.31 +import de.uapcore.lightpit.AbstractServlet
    2.32 +import de.uapcore.lightpit.HttpRequest
    2.33 +import de.uapcore.lightpit.dao.DataAccessObject
    2.34 +import de.uapcore.lightpit.entities.Issue
    2.35 +import de.uapcore.lightpit.util.IssueFilter
    2.36 +import de.uapcore.lightpit.util.IssueSorter
    2.37 +import de.uapcore.lightpit.viewmodel.IssueFeed
    2.38 +import javax.servlet.annotation.WebServlet
    2.39 +
    2.40 +@WebServlet(urlPatterns = ["/feed/*"])
    2.41 +class FeedServlet : AbstractServlet() {
    2.42 +
    2.43 +    init {
    2.44 +        get("/issues.rss", this::issues)
    2.45 +    }
    2.46 +
    2.47 +    private fun issues(http: HttpRequest, dao: DataAccessObject) {
    2.48 +
    2.49 +        val issues = dao.listIssues(IssueFilter()).sortedWith(IssueSorter.DEFAULT_ISSUE_SORTER)
    2.50 +
    2.51 +        http.view = IssueFeed(issues.groupBy(Issue::project))
    2.52 +        http.forward("issues-feed")
    2.53 +    }
    2.54 +}
    2.55 \ No newline at end of file
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/Feeds.kt	Thu May 13 11:28:50 2021 +0200
     3.3 @@ -0,0 +1,33 @@
     3.4 +/*
     3.5 + * Copyright 2021 Mike Becker. All rights reserved.
     3.6 + *
     3.7 + * Redistribution and use in source and binary forms, with or without
     3.8 + * modification, are permitted provided that the following conditions are met:
     3.9 + *
    3.10 + * 1. Redistributions of source code must retain the above copyright
    3.11 + * notice, this list of conditions and the following disclaimer.
    3.12 + *
    3.13 + * 2. Redistributions in binary form must reproduce the above copyright
    3.14 + * notice, this list of conditions and the following disclaimer in the
    3.15 + * documentation and/or other materials provided with the distribution.
    3.16 + *
    3.17 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    3.18 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    3.19 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    3.20 + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    3.21 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    3.22 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    3.23 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    3.24 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    3.25 + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    3.26 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    3.27 + */
    3.28 +
    3.29 +package de.uapcore.lightpit.viewmodel
    3.30 +
    3.31 +import de.uapcore.lightpit.entities.Issue
    3.32 +import de.uapcore.lightpit.entities.Project
    3.33 +
    3.34 +class IssueFeed(
    3.35 +    val issues: Map<Project, List<Issue>>
    3.36 +) : View()
    3.37 \ No newline at end of file
     4.1 --- a/src/main/resources/localization/strings.properties	Thu May 13 10:23:37 2021 +0200
     4.2 +++ b/src/main/resources/localization/strings.properties	Thu May 13 11:28:50 2021 +0200
     4.3 @@ -126,4 +126,6 @@
     4.4  version.status.Released=Released
     4.5  version.status.Unreleased=Unreleased
     4.6  version.status=Status
     4.7 -version=Version
     4.8 \ No newline at end of file
     4.9 +version=Version
    4.10 +feed.issues.title=LightPIT - Issues
    4.11 +feed.issues.description=Feed about recently updated issues.
    4.12 \ No newline at end of file
     5.1 --- a/src/main/resources/localization/strings_de.properties	Thu May 13 10:23:37 2021 +0200
     5.2 +++ b/src/main/resources/localization/strings_de.properties	Thu May 13 11:28:50 2021 +0200
     5.3 @@ -99,7 +99,7 @@
     5.4  no-users=Bislang wurden keine Entwickler hinterlegt.
     5.5  node.tooltip=Name, der zur Konstruktion der URL genutzt werden soll.
     5.6  node=Pfadname
     5.7 -ordinal.tooltip=Use to override lexicographic ordering.=\u00dcbersteuert die lexikographische Sortierung.
     5.8 +ordinal.tooltip=Use to override lexicographic ordering. \u00dcbersteuert die lexikographische Sortierung.
     5.9  ordinal=Sequenznummer
    5.10  placeholder.auto-assignee.tooltip=Weist, wenn m\u00f6glich, den Vorgang dem Leiter der Komponente.
    5.11  placeholder.auto-assignee=Automatisch
    5.12 @@ -127,3 +127,5 @@
    5.13  version.status.Unreleased=Unver\u00f6ffentlicht
    5.14  version.status=Status 
    5.15  version=Version
    5.16 +feed.issues.title=LightPIT - Vorg\u00e4nge
    5.17 +feed.issues.description=Feed \u00fcber k\u00fcrzlich aktualisierte Vorg\u00e4nge.
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/main/webapp/WEB-INF/jsp/issues-feed.jsp	Thu May 13 11:28:50 2021 +0200
     6.3 @@ -0,0 +1,60 @@
     6.4 +<%--
     6.5 +  ~ Copyright 2021 Mike Becker. All rights reserved.
     6.6 +  ~
     6.7 +  ~ Redistribution and use in source and binary forms, with or without
     6.8 +  ~ modification, are permitted provided that the following conditions are met:
     6.9 +  ~
    6.10 +  ~ 1. Redistributions of source code must retain the above copyright
    6.11 +  ~ notice, this list of conditions and the following disclaimer.
    6.12 +  ~
    6.13 +  ~ 2. Redistributions in binary form must reproduce the above copyright
    6.14 +  ~ notice, this list of conditions and the following disclaimer in the
    6.15 +  ~ documentation and/or other materials provided with the distribution.
    6.16 +  ~
    6.17 +  ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    6.18 +  ~ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    6.19 +  ~ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    6.20 +  ~ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    6.21 +  ~ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    6.22 +  ~ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    6.23 +  ~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    6.24 +  ~ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    6.25 +  ~ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    6.26 +  ~ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    6.27 +  --%>
    6.28 +<%@ page contentType="application/rss+xml;charset=UTF-8" trimDirectiveWhitespaces="true" %>
    6.29 +<%@page import="de.uapcore.lightpit.Constants" %>
    6.30 +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    6.31 +<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    6.32 +<jsp:useBean id="viewmodel" type="de.uapcore.lightpit.viewmodel.IssueFeed" scope="request"/>
    6.33 +<c:set scope="page" var="baseHref" value="${requestScope[Constants.REQ_ATTR_BASE_HREF]}"/>
    6.34 +<fmt:setLocale scope="request" value="${pageContext.response.locale}"/>
    6.35 +<fmt:setBundle scope="request" basename="localization.strings"/>
    6.36 +<?xml version="1.0" encoding="utf-8"?>
    6.37 +<rss version="2.0">
    6.38 +    <c:forEach items="${viewmodel.issues}" var="feed">
    6.39 +        <c:set var="project" value="${feed.key}"/>
    6.40 +        <c:set var="issues" value="${feed.value}"/>
    6.41 +        <channel>
    6.42 +            <title>
    6.43 +                <fmt:message key="feed.issues.title"/> - <c:out value="${project.name}"/>
    6.44 +            </title>
    6.45 +            <link>${baseHref}projects/${project.node}/</link>
    6.46 +            <description><fmt:message key="feed.issues.description"/></description>
    6.47 +            <language>${pageContext.response.locale.language}</language>
    6.48 +
    6.49 +            <c:forEach items="${issues}" var="issue">
    6.50 +                <item>
    6.51 +                    <title><c:if test="${not empty issue.component}"><c:out value="${issue.component.name}"/> - </c:if><c:out value="${issue.subject}"/></title>
    6.52 +                    <description>
    6.53 +                        <c:out value="${issue.description}"/>
    6.54 +                    </description>
    6.55 +                    <category><fmt:message key="issue.category.${issue.category}"/></category>
    6.56 +                    <link>${baseHref}projects/${issue.project.node}/issues/-/${empty issue.component ? '-' : issue.component.node}/${issue.id}</link>
    6.57 +                    <guid isPermaLink="true">${baseHref}projects/${issue.project.node}/issues/-/-/${issue.id}</guid>
    6.58 +                    <pubDate><fmt:formatDate value="${issue.updated}" pattern="EEE, dd MMM yyyy HH:mm:ss zzz" /></pubDate>
    6.59 +                </item>
    6.60 +            </c:forEach>
    6.61 +        </channel>
    6.62 +    </c:forEach>
    6.63 +</rss>
    6.64 \ No newline at end of file
     7.1 --- a/src/main/webapp/WEB-INF/jsp/site.jsp	Thu May 13 10:23:37 2021 +0200
     7.2 +++ b/src/main/webapp/WEB-INF/jsp/site.jsp	Thu May 13 11:28:50 2021 +0200
     7.3 @@ -48,12 +48,8 @@
     7.4  <%-- Define an alias for the additional stylesheet --%>
     7.5  <c:set scope="page" var="extraCss" value="${requestScope[Constants.REQ_ATTR_STYLESHEET]}"/>
     7.6  
     7.7 -<%-- Apply the session locale (should always be present, but check nevertheless) --%>
     7.8 -<c:if test="${not empty sessionScope[Constants.SESSION_ATTR_LANGUAGE]}">
     7.9 -    <fmt:setLocale scope="request" value="${sessionScope[Constants.SESSION_ATTR_LANGUAGE]}"/>
    7.10 -</c:if>
    7.11 -
    7.12  <%-- Load resource bundle --%>
    7.13 +<fmt:setLocale scope="request" value="${pageContext.response.locale}"/>
    7.14  <fmt:setBundle scope="request" basename="localization.strings"/>
    7.15  
    7.16  <!DOCTYPE html>
    7.17 @@ -66,6 +62,8 @@
    7.18          <meta http-equiv="refresh" content="0; URL=${redirectLocation}">
    7.19      </c:if>
    7.20      <link rel="stylesheet" href="lightpit.css" type="text/css">
    7.21 +    <link rel="alternate" type="application/rss+xml"
    7.22 +          title="RSS" href="${baseHref}feed/issues.rss" />
    7.23      <c:if test="${not empty extraCss}">
    7.24          <c:forEach items="${extraCss}" var="cssFile">
    7.25          <link rel="stylesheet" href="${cssFile}" type="text/css">

mercurial