#22 adds possibility to edit own comments

Mon, 02 Aug 2021 17:04:17 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 02 Aug 2021 17:04:17 +0200
changeset 207
479dd7993ef9
parent 206
fe4de34822a5
child 208
785820da6485

#22 adds possibility to edit own comments

src/main/kotlin/de/uapcore/lightpit/Constants.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/entities/IssueComment.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt file | annotate | diff | comparison | revisions
src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.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/changelogs/changelog-de.jspf file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/changelogs/changelog.jspf file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jsp/issue-view.jsp file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jsp/site.jsp file | annotate | diff | comparison | revisions
src/main/webapp/issue-editor.js file | annotate | diff | comparison | revisions
src/main/webapp/lightpit.css file | annotate | diff | comparison | revisions
src/main/webapp/projects.css file | annotate | diff | comparison | revisions
     1.1 --- a/src/main/kotlin/de/uapcore/lightpit/Constants.kt	Mon Aug 02 15:13:04 2021 +0200
     1.2 +++ b/src/main/kotlin/de/uapcore/lightpit/Constants.kt	Mon Aug 02 17:04:17 2021 +0200
     1.3 @@ -92,6 +92,11 @@
     1.4      const val REQ_ATTR_STYLESHEET = "extraCss"
     1.5  
     1.6      /**
     1.7 +     * Key for the name of the optional java script file.
     1.8 +     */
     1.9 +    const val REQ_ATTR_JAVASCRIPT = "javascriptFile"
    1.10 +
    1.11 +    /**
    1.12       * Key for a location the page shall redirect to.
    1.13       * Will be used in a meta element.
    1.14       */
     2.1 --- a/src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt	Mon Aug 02 15:13:04 2021 +0200
     2.2 +++ b/src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt	Mon Aug 02 17:04:17 2021 +0200
     2.3 @@ -60,7 +60,7 @@
     2.4      /**
     2.5       * The name of the content page.
     2.6       *
     2.7 -     * @see Constants#REQ_ATTR_CONTENT_PAGE
     2.8 +     * @see Constants#REQ_ATTR_PAGE_TITLE
     2.9       */
    2.10      var pageTitle = ""
    2.11          set(value) {
    2.12 @@ -82,6 +82,19 @@
    2.13          }
    2.14  
    2.15      /**
    2.16 +     * A list of additional style sheets.
    2.17 +     *
    2.18 +     * @see Constants#REQ_ATTR_JAVASCRIPT
    2.19 +     */
    2.20 +    var javascript = ""
    2.21 +        set(value) {
    2.22 +            field = value
    2.23 +            request.setAttribute(Constants.REQ_ATTR_JAVASCRIPT,
    2.24 +                value.withExt(".js")
    2.25 +            )
    2.26 +        }
    2.27 +
    2.28 +    /**
    2.29       * The name of the navigation menu JSP.
    2.30       *
    2.31       * @see Constants#REQ_ATTR_NAVIGATION
     3.1 --- a/src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt	Mon Aug 02 15:13:04 2021 +0200
     3.2 +++ b/src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt	Mon Aug 02 17:04:17 2021 +0200
     3.3 @@ -75,5 +75,7 @@
     3.4      fun updateIssue(issue: Issue)
     3.5  
     3.6      fun listComments(issue: Issue): List<IssueComment>
     3.7 +    fun findComment(id: Int): IssueComment?
     3.8      fun insertComment(issueComment: IssueComment)
     3.9 +    fun updateComment(issueComment: IssueComment)
    3.10  }
    3.11 \ No newline at end of file
     4.1 --- a/src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt	Mon Aug 02 15:13:04 2021 +0200
     4.2 +++ b/src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt	Mon Aug 02 17:04:17 2021 +0200
     4.3 @@ -658,6 +658,12 @@
     4.4              queryAll { it.extractIssueComment() }
     4.5          }
     4.6  
     4.7 +    override fun findComment(id: Int): IssueComment? =
     4.8 +        withStatement("select * from lpit_issue_comment left join lpit_user using (userid) where commentid = ?") {
     4.9 +            setInt(1, id)
    4.10 +            querySingle { it.extractIssueComment() }
    4.11 +        }
    4.12 +
    4.13      override fun insertComment(issueComment: IssueComment) {
    4.14          useStatement("update lpit_issue set updated = now() where issueid = ?") { updateIssueDate ->
    4.15              withStatement("insert into lpit_issue_comment (issueid, comment, userid) values (?, ? ,?)") {
    4.16 @@ -672,5 +678,19 @@
    4.17              }
    4.18          }
    4.19      }
    4.20 +
    4.21 +    override fun updateComment(issueComment: IssueComment) {
    4.22 +        useStatement("update lpit_issue set updated = now() where issueid = ?") { updateIssueDate ->
    4.23 +            withStatement("update lpit_issue_comment set comment = ?, updatecount = updatecount + 1, updated = now() where commentid = ?") {
    4.24 +                with(issueComment) {
    4.25 +                    updateIssueDate.setInt(1, issueid)
    4.26 +                    setStringSafe(1, comment)
    4.27 +                    setInt(2, id)
    4.28 +                }
    4.29 +                executeUpdate()
    4.30 +                updateIssueDate.executeUpdate()
    4.31 +            }
    4.32 +        }
    4.33 +    }
    4.34  //</editor-fold>
    4.35  }
    4.36 \ No newline at end of file
     5.1 --- a/src/main/kotlin/de/uapcore/lightpit/entities/IssueComment.kt	Mon Aug 02 15:13:04 2021 +0200
     5.2 +++ b/src/main/kotlin/de/uapcore/lightpit/entities/IssueComment.kt	Mon Aug 02 17:04:17 2021 +0200
     5.3 @@ -30,6 +30,7 @@
     5.4  
     5.5  data class IssueComment(override val id: Int, val issueid: Int) : Entity {
     5.6      var author: User? = null
     5.7 +    var commentFormatted: String = ""
     5.8      var comment: String = ""
     5.9      var created: Timestamp = Timestamp.from(Instant.now())
    5.10      var updated: Timestamp = Timestamp.from(Instant.now())
     6.1 --- a/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt	Mon Aug 02 15:13:04 2021 +0200
     6.2 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt	Mon Aug 02 17:04:17 2021 +0200
     6.3 @@ -441,7 +441,6 @@
     6.4              with(http) {
     6.5                  pageTitle = "${projectInfo.project.name}: #${issue.id} ${issue.subject}"
     6.6                  view = IssueDetailView(issue, comments, project, version, component)
     6.7 -                // TODO: feed path for this particular issue
     6.8                  feedPath = feedPath(projectInfo.project)
     6.9                  navigationMenu = activeProjectNavMenu(
    6.10                      dao.listProjects(),
    6.11 @@ -450,6 +449,7 @@
    6.12                      component
    6.13                  )
    6.14                  styleSheets = listOf("projects")
    6.15 +                javascript = "issue-editor"
    6.16                  render("issue-view")
    6.17              }
    6.18          }
    6.19 @@ -492,6 +492,7 @@
    6.20                      component
    6.21                  )
    6.22                  styleSheets = listOf("projects")
    6.23 +                javascript = "issue-editor"
    6.24                  render("issue-form")
    6.25              }
    6.26          }
    6.27 @@ -506,13 +507,26 @@
    6.28              }
    6.29  
    6.30              // TODO: throw validator exception instead of using a default
    6.31 -            val comment = IssueComment(-1, issue.id).apply {
    6.32 -                author = http.remoteUser?.let { dao.findUserByName(it) }
    6.33 -                comment = http.param("comment") ?: ""
    6.34 +
    6.35 +            val commentId = http.param("commentid")?.toIntOrNull() ?: -1
    6.36 +            if (commentId > 0) {
    6.37 +                val comment = dao.findComment(commentId)
    6.38 +                val originalAuthor = comment?.author?.username
    6.39 +                if (originalAuthor != null && originalAuthor == http.remoteUser) {
    6.40 +                    comment.comment = http.param("comment") ?: ""
    6.41 +                    dao.updateComment(comment)
    6.42 +                } else {
    6.43 +                    http.response.sendError(403)
    6.44 +                    return
    6.45 +                }
    6.46 +            } else {
    6.47 +                val comment = IssueComment(-1, issue.id).apply {
    6.48 +                    author = http.remoteUser?.let { dao.findUserByName(it) }
    6.49 +                    comment = http.param("comment") ?: ""
    6.50 +                }
    6.51 +                dao.insertComment(comment)
    6.52              }
    6.53  
    6.54 -            dao.insertComment(comment)
    6.55 -
    6.56              http.renderCommit("${issuesHref}${issue.id}")
    6.57          }
    6.58      }
     7.1 --- a/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt	Mon Aug 02 15:13:04 2021 +0200
     7.2 +++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt	Mon Aug 02 17:04:17 2021 +0200
     7.3 @@ -78,7 +78,7 @@
     7.4  
     7.5          issue.description = process(issue.description?:"")
     7.6          for (comment in comments) {
     7.7 -            comment.comment = process(comment.comment)
     7.8 +            comment.commentFormatted = process(comment.comment)
     7.9          }
    7.10      }
    7.11  }
     8.1 --- a/src/main/resources/localization/strings.properties	Mon Aug 02 15:13:04 2021 +0200
     8.2 +++ b/src/main/resources/localization/strings.properties	Mon Aug 02 17:04:17 2021 +0200
     8.3 @@ -25,6 +25,7 @@
     8.4  app.license.title=License
     8.5  app.name=Lightweight Project and Issue Tracking
     8.6  button.cancel=Cancel
     8.7 +button.comment.edit=Edit Comment
     8.8  button.comment=Comment
     8.9  button.component.create=New Component
    8.10  button.component.edit=Edit Component
    8.11 @@ -70,6 +71,8 @@
    8.12  issue.category.Test=Test
    8.13  issue.category=Category
    8.14  issue.comments.anonauthor=Anonymous Author
    8.15 +issue.comments.lastupdate=Last edited:
    8.16 +issue.comments.updateCount=total edits
    8.17  issue.comments=Comments
    8.18  issue.created=Created
    8.19  issue.description=Description
     9.1 --- a/src/main/resources/localization/strings_de.properties	Mon Aug 02 15:13:04 2021 +0200
     9.2 +++ b/src/main/resources/localization/strings_de.properties	Mon Aug 02 17:04:17 2021 +0200
     9.3 @@ -24,6 +24,7 @@
     9.4  app.changelog=Versionshistorie
     9.5  app.license.title=Lizenz (Englisch)
     9.6  button.cancel=Abbrechen
     9.7 +button.comment.edit=Absenden
     9.8  button.comment=Kommentieren
     9.9  button.component.create=Neue Komponente
    9.10  button.component.edit=Komponente Bearbeiten
    9.11 @@ -55,11 +56,11 @@
    9.12  error.message = Server Nachricht
    9.13  error.returnLink = Kehre zurück zu
    9.14  error.timestamp = Zeitstempel
    9.15 -feed=Feed
    9.16  feed.issues.created=Vorgang wurde erstellt.
    9.17  feed.issues.description=Feed \u00fcber k\u00fcrzlich aktualisierte Vorg\u00e4nge.
    9.18  feed.issues.title=LightPIT Vorg\u00e4nge
    9.19  feed.issues.updated=Vorgang wurde aktualisiert.
    9.20 +feed=Feed
    9.21  issue.affected-versions=Betroffene Versionen
    9.22  issue.assignee=Zugewiesen
    9.23  issue.category.Bug=Fehler
    9.24 @@ -69,6 +70,8 @@
    9.25  issue.category.Test=Test
    9.26  issue.category=Kategorie
    9.27  issue.comments.anonauthor=Anonymer Autor
    9.28 +issue.comments.lastupdate=Zuletzt bearbeitet:
    9.29 +issue.comments.updateCount=mal bearbeitet
    9.30  issue.comments=Kommentare
    9.31  issue.created=Erstellt
    9.32  issue.description=Beschreibung
    10.1 --- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Mon Aug 02 15:13:04 2021 +0200
    10.2 +++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf	Mon Aug 02 17:04:17 2021 +0200
    10.3 @@ -28,6 +28,7 @@
    10.4  
    10.5  <ul>
    10.6      <li>Infoseite hinzugefügt.</li>
    10.7 +    <li>Eigene Kommentare können nun bearbeitet werden.</li>
    10.8      <li>Sortierreihenfolge der Versionen in der Übersicht an die Sortierreihenfolge im Seitenmenü angeglichen.</li>
    10.9      <li>Duplikate in Komponenten- und Versionslisten behoben.</li>
   10.10      <li>Fehler behoben, bei dem vorbereitete Datenbankabfragen nicht geschlossen wurden.</li>
    11.1 --- a/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Mon Aug 02 15:13:04 2021 +0200
    11.2 +++ b/src/main/webapp/WEB-INF/changelogs/changelog.jspf	Mon Aug 02 17:04:17 2021 +0200
    11.3 @@ -28,6 +28,7 @@
    11.4  
    11.5  <ul>
    11.6      <li>Adds about page.</li>
    11.7 +    <li>Adds possibility to edit own comments.</li>
    11.8      <li>Changes sort order of versions in the versions overview to be the same as in the left menu.</li>
    11.9      <li>Fixes duplicates in the components and versions lists.</li>
   11.10      <li>Fixes leaking prepared statements.</li>
    12.1 --- a/src/main/webapp/WEB-INF/jsp/issue-view.jsp	Mon Aug 02 15:13:04 2021 +0200
    12.2 +++ b/src/main/webapp/WEB-INF/jsp/issue-view.jsp	Mon Aug 02 17:04:17 2021 +0200
    12.3 @@ -175,15 +175,18 @@
    12.4  </form>
    12.5      <c:forEach var="comment" items="${viewmodel.comments}">
    12.6          <div class="comment">
    12.7 -            <div class="caption">
    12.8 +            <div class="comment-author">
    12.9                  <c:if test="${not empty comment.author}">
   12.10                      <c:if test="${not empty comment.author.mail}">
   12.11 -                        <a href="mailto:${comment.author.mail}">
   12.12 +                        <a class="comment-author-name" href="mailto:${comment.author.mail}">
   12.13                      </c:if>
   12.14                      <c:out value="${comment.author.displayname}"/>
   12.15                      <c:if test="${not empty comment.author.mail}">
   12.16                          </a>
   12.17                      </c:if>
   12.18 +                    <c:if test="${comment.author.username eq pageContext.request.remoteUser}">
   12.19 +                        <a class="comment-edit-icon" onclick="showCommentEditor(${comment.id})">&#x270e;</a>
   12.20 +                    </c:if>
   12.21                  </c:if>
   12.22                  <c:if test="${empty comment.author}">
   12.23                      <fmt:message key="issue.comments.anonauthor"/>
   12.24 @@ -192,11 +195,34 @@
   12.25              <div class="smalltext">
   12.26                  <fmt:formatDate type="BOTH" value="${comment.created}" />
   12.27                  <c:if test="${comment.updateCount gt 0}">
   12.28 -                    <!-- TODO: update count -->
   12.29 +                <span class="comment-edit-info">
   12.30 +                    (<fmt:message key="issue.comments.lastupdate"/> <fmt:formatDate type="BOTH" value="${comment.updated}" />, ${comment.updateCount} <fmt:message key="issue.comments.updateCount"/>)
   12.31 +                </span>
   12.32                  </c:if>
   12.33              </div>
   12.34 -            <div class="medskip markdown-styled">
   12.35 -                ${comment.comment}
   12.36 +            <div id="comment-view-${comment.id}" class="medskip markdown-styled">
   12.37 +                ${comment.commentFormatted}
   12.38 +            </div>
   12.39 +            <div id="comment-editor-${comment.id}" style="display: none">
   12.40 +                <form id="comment-form-${comment.id}" action="${issuesHref}${issue.id}/comment" method="post">
   12.41 +                    <input type="hidden" name="commentid" value="${comment.id}">
   12.42 +                    <table class="formtable fullwidth">
   12.43 +                        <tbody>
   12.44 +                        <tr>
   12.45 +                            <td>
   12.46 +                                <textarea rows="5" name="comment" required><c:out value="${comment.comment}"/></textarea>
   12.47 +                            </td>
   12.48 +                        </tr>
   12.49 +                        </tbody>
   12.50 +                        <tfoot>
   12.51 +                        <tr>
   12.52 +                            <td>
   12.53 +                                <button type="submit"><fmt:message key="button.comment.edit"/></button>
   12.54 +                            </td>
   12.55 +                        </tr>
   12.56 +                        </tfoot>
   12.57 +                    </table>
   12.58 +                </form>
   12.59              </div>
   12.60          </div>
   12.61      </c:forEach>
    13.1 --- a/src/main/webapp/WEB-INF/jsp/site.jsp	Mon Aug 02 15:13:04 2021 +0200
    13.2 +++ b/src/main/webapp/WEB-INF/jsp/site.jsp	Mon Aug 02 17:04:17 2021 +0200
    13.3 @@ -30,6 +30,9 @@
    13.4  <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    13.5  <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
    13.6  
    13.7 +<%-- Version suffix for forcing browsers to update the CSS / JS files --%>
    13.8 +<c:set scope="page" var="versionSuffix" value="20210802"/>
    13.9 +
   13.10  <%-- Make the base href easily available at request scope --%>
   13.11  <c:set scope="page" var="baseHref" value="${requestScope[Constants.REQ_ATTR_BASE_HREF]}"/>
   13.12  
   13.13 @@ -54,6 +57,9 @@
   13.14  <%-- Define an alias for the additional stylesheet --%>
   13.15  <c:set scope="page" var="extraCss" value="${requestScope[Constants.REQ_ATTR_STYLESHEET]}"/>
   13.16  
   13.17 +<%-- Define an alias for the optional JS file --%>
   13.18 +<c:set scope="page" var="javascriptFile" value="${requestScope[Constants.REQ_ATTR_JAVASCRIPT]}"/>
   13.19 +
   13.20  <%-- Load resource bundle --%>
   13.21  <fmt:setLocale scope="request" value="${pageContext.response.locale}"/>
   13.22  <fmt:setBundle scope="request" basename="localization.strings"/>
   13.23 @@ -70,15 +76,18 @@
   13.24      <c:if test="${not empty redirectLocation}">
   13.25          <meta http-equiv="refresh" content="0; URL=${redirectLocation}">
   13.26      </c:if>
   13.27 -    <link rel="stylesheet" href="lightpit.css" type="text/css">
   13.28 +    <link rel="stylesheet" href="lightpit.css?v=${versionSuffix}" type="text/css">
   13.29      <c:if test="${not empty feedHref}">
   13.30          <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="${feedHref}"/>
   13.31      </c:if>
   13.32      <c:if test="${not empty extraCss}">
   13.33          <c:forEach items="${extraCss}" var="cssFile">
   13.34 -            <link rel="stylesheet" href="${cssFile}" type="text/css">
   13.35 +            <link rel="stylesheet" href="${cssFile}?v=${versionSuffix}" type="text/css">
   13.36          </c:forEach>
   13.37      </c:if>
   13.38 +    <c:if test="${not empty javascriptFile}">
   13.39 +        <script src="${javascriptFile}?v=${versionSuffix}" type="text/javascript"></script>
   13.40 +    </c:if>
   13.41  </head>
   13.42  <body>
   13.43  <div id="mainMenu">
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/main/webapp/issue-editor.js	Mon Aug 02 17:04:17 2021 +0200
    14.3 @@ -0,0 +1,36 @@
    14.4 +/*
    14.5 + * Copyright 2021 Mike Becker. All rights reserved.
    14.6 + *
    14.7 + * Redistribution and use in source and binary forms, with or without
    14.8 + * modification, are permitted provided that the following conditions are met:
    14.9 + *
   14.10 + * 1. Redistributions of source code must retain the above copyright
   14.11 + * notice, this list of conditions and the following disclaimer.
   14.12 + *
   14.13 + * 2. Redistributions in binary form must reproduce the above copyright
   14.14 + * notice, this list of conditions and the following disclaimer in the
   14.15 + * documentation and/or other materials provided with the distribution.
   14.16 + *
   14.17 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   14.18 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   14.19 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   14.20 + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
   14.21 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   14.22 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   14.23 + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   14.24 + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   14.25 + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   14.26 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   14.27 + */
   14.28 +
   14.29 +/**
   14.30 + * Replaces the formatted comment text with an text area.
   14.31 + *
   14.32 + * @param {number} id the ID of the comment
   14.33 + */
   14.34 +function showCommentEditor(id) {
   14.35 +    const editor = document.getElementById(`comment-editor-${id}`)
   14.36 +    const view = document.getElementById(`comment-view-${id}`)
   14.37 +    editor.style.display='block'
   14.38 +    view.style.display='none'
   14.39 +}
    15.1 --- a/src/main/webapp/lightpit.css	Mon Aug 02 15:13:04 2021 +0200
    15.2 +++ b/src/main/webapp/lightpit.css	Mon Aug 02 17:04:17 2021 +0200
    15.3 @@ -43,6 +43,7 @@
    15.4  }
    15.5  
    15.6  a {
    15.7 +    cursor: pointer;
    15.8      color: #3060f8;
    15.9      text-decoration: none;
   15.10  }
    16.1 --- a/src/main/webapp/projects.css	Mon Aug 02 15:13:04 2021 +0200
    16.2 +++ b/src/main/webapp/projects.css	Mon Aug 02 17:04:17 2021 +0200
    16.3 @@ -147,9 +147,30 @@
    16.4  }
    16.5  
    16.6  div.comment {
    16.7 +    padding-left: .25rem;
    16.8      margin-bottom: 1.25em;
    16.9  }
   16.10  
   16.11 +.comment-author {
   16.12 +    color: #3060f8;
   16.13 +    background: #e7e7ef;
   16.14 +    margin-left: -.25rem;
   16.15 +    padding: .25rem;
   16.16 +}
   16.17 +
   16.18 +.comment-author-name {
   16.19 +    color: inherit;
   16.20 +}
   16.21 +
   16.22 +.comment-edit-icon {
   16.23 +    margin-left: 1ex;
   16.24 +}
   16.25 +
   16.26 +span.comment-edit-info {
   16.27 +    margin-left: 1ex;
   16.28 +    color: #556080;
   16.29 +}
   16.30 +
   16.31  span.eta-overdue {
   16.32      color: red;
   16.33  }
   16.34 \ No newline at end of file

mercurial