adds issue summaries

Sat, 30 May 2020 15:26:15 +0200

author
Mike Becker <universe@uap-core.de>
date
Sat, 30 May 2020 15:26:15 +0200
changeset 81
1a2e7b5d48f7
parent 80
27a25f32048e
child 82
4ec7f2600c83

adds issue summaries

setup/postgres/psql_create_tables.sql file | annotate | diff | comparison | revisions
setup/postgres/psql_default_data.sql file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/entities/Issue.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/entities/IssueStatus.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/entities/Project.java file | annotate | diff | comparison | revisions
src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java file | annotate | diff | comparison | revisions
src/main/resources/localization/projects.properties file | annotate | diff | comparison | revisions
src/main/resources/localization/projects_de.properties file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jsp/issue-form.jsp file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jsp/issues.jsp file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jsp/project-details.jsp file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jsp/project-form.jsp file | annotate | diff | comparison | revisions
src/main/webapp/WEB-INF/jsp/projects.jsp file | annotate | diff | comparison | revisions
src/main/webapp/projects.css file | annotate | diff | comparison | revisions
     1.1 --- a/setup/postgres/psql_create_tables.sql	Sun May 24 15:30:43 2020 +0200
     1.2 +++ b/setup/postgres/psql_create_tables.sql	Sat May 30 15:26:15 2020 +0200
     1.3 @@ -41,7 +41,8 @@
     1.4      'InReview',
     1.5      'Done',
     1.6      'Rejected',
     1.7 -    'Withdrawn'
     1.8 +    'Withdrawn',
     1.9 +    'Duplicate'
    1.10  );
    1.11  
    1.12  create type issue_category as enum (
    1.13 @@ -52,6 +53,11 @@
    1.14      'Test'
    1.15  );
    1.16  
    1.17 +create table lpit_issue_phases (
    1.18 +    status          issue_status    primary key,
    1.19 +    phase           integer         not null
    1.20 +);
    1.21 +
    1.22  create table lpit_issue (
    1.23      issueid         serial          primary key,
    1.24      project         integer         not null references lpit_project(projectid),
     2.1 --- a/setup/postgres/psql_default_data.sql	Sun May 24 15:30:43 2020 +0200
     2.2 +++ b/setup/postgres/psql_default_data.sql	Sat May 30 15:26:15 2020 +0200
     2.3 @@ -0,0 +1,10 @@
     2.4 +insert into lpit_issue_phases (status, phase) values
     2.5 +    ('InSpecification', 0),
     2.6 +    ('ToDo', 0),
     2.7 +    ('Scheduled', 1),
     2.8 +    ('InProgress', 1),
     2.9 +    ('InReview', 1),
    2.10 +    ('Done', 2),
    2.11 +    ('Rejected', 2),
    2.12 +    ('Withdrawn', 2),
    2.13 +    ('Duplicate', 2);
     3.1 --- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java	Sun May 24 15:30:43 2020 +0200
     3.2 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java	Sat May 30 15:26:15 2020 +0200
     3.3 @@ -46,6 +46,7 @@
     3.4  public final class PGProjectDao implements ProjectDao {
     3.5  
     3.6      private final PreparedStatement insert, update, list, find;
     3.7 +    private final PreparedStatement issue_summary;
     3.8  
     3.9      public PGProjectDao(Connection connection) throws SQLException {
    3.10          list = connection.prepareStatement(
    3.11 @@ -62,6 +63,14 @@
    3.12                          "left join lpit_user owner on lpit_project.owner = owner.userid " +
    3.13                          "where projectid = ?");
    3.14  
    3.15 +        issue_summary = connection.prepareStatement(
    3.16 +                "select phase, count(*) as total "+
    3.17 +                        "from lpit_issue " +
    3.18 +                        "join lpit_issue_phases using(status) " +
    3.19 +                        "where project = ? "+
    3.20 +                        "group by phase "
    3.21 +        );
    3.22 +
    3.23          insert = connection.prepareStatement(
    3.24                  "insert into lpit_project (name, description, repourl, owner) values (?, ?, ?, ?)"
    3.25          );
    3.26 @@ -89,6 +98,26 @@
    3.27          return proj;
    3.28      }
    3.29  
    3.30 +    private void mapIssueSummary(Project proj) throws SQLException {
    3.31 +        issue_summary.setInt(1, proj.getId());
    3.32 +        final var result = issue_summary.executeQuery();
    3.33 +        while (result.next()) {
    3.34 +            final var phase = result.getInt("phase");
    3.35 +            final var total = result.getInt("total");
    3.36 +            switch(phase) {
    3.37 +                case 0:
    3.38 +                    proj.setOpenIssues(total);
    3.39 +                    break;
    3.40 +                case 1:
    3.41 +                    proj.setActiveIssues(total);
    3.42 +                    break;
    3.43 +                case 2:
    3.44 +                    proj.setDoneIssues(total);
    3.45 +                    break;
    3.46 +            }
    3.47 +        }
    3.48 +    }
    3.49 +
    3.50      @Override
    3.51      public void save(Project instance) throws SQLException {
    3.52          Objects.requireNonNull(instance.getName());
    3.53 @@ -116,7 +145,9 @@
    3.54          List<Project> projects = new ArrayList<>();
    3.55          try (var result = list.executeQuery()) {
    3.56              while (result.next()) {
    3.57 -                projects.add(mapColumns(result));
    3.58 +                final var project = mapColumns(result);
    3.59 +                mapIssueSummary(project);
    3.60 +                projects.add(project);
    3.61              }
    3.62          }
    3.63          return projects;
    3.64 @@ -127,7 +158,9 @@
    3.65          find.setInt(1, id);
    3.66          try (var result = find.executeQuery()) {
    3.67              if (result.next()) {
    3.68 -                return mapColumns(result);
    3.69 +                final var project = mapColumns(result);
    3.70 +                mapIssueSummary(project);
    3.71 +                return project;
    3.72              } else {
    3.73                  return null;
    3.74              }
     4.1 --- a/src/main/java/de/uapcore/lightpit/entities/Issue.java	Sun May 24 15:30:43 2020 +0200
     4.2 +++ b/src/main/java/de/uapcore/lightpit/entities/Issue.java	Sat May 30 15:26:15 2020 +0200
     4.3 @@ -84,6 +84,10 @@
     4.4          this.status = status;
     4.5      }
     4.6  
     4.7 +    public int getPhase() {
     4.8 +        return this.status.getPhase();
     4.9 +    }
    4.10 +
    4.11      public IssueCategory getCategory() {
    4.12          return category;
    4.13      }
     5.1 --- a/src/main/java/de/uapcore/lightpit/entities/IssueStatus.java	Sun May 24 15:30:43 2020 +0200
     5.2 +++ b/src/main/java/de/uapcore/lightpit/entities/IssueStatus.java	Sat May 30 15:26:15 2020 +0200
     5.3 @@ -39,6 +39,10 @@
     5.4      Withdrawn(2),
     5.5      Duplicate(2);
     5.6  
     5.7 +    public static final int PHASE_OPEN = 0;
     5.8 +    public static final int PHASE_WIP = 1;
     5.9 +    public static final int PHASE_DONE = 2;
    5.10 +
    5.11      private int phase;
    5.12  
    5.13      IssueStatus(int phase) {
     6.1 --- a/src/main/java/de/uapcore/lightpit/entities/Project.java	Sun May 24 15:30:43 2020 +0200
     6.2 +++ b/src/main/java/de/uapcore/lightpit/entities/Project.java	Sat May 30 15:26:15 2020 +0200
     6.3 @@ -38,6 +38,10 @@
     6.4      private String repoUrl;
     6.5      private User owner;
     6.6  
     6.7 +    private int openIssues;
     6.8 +    private int activeIssues;
     6.9 +    private int doneIssues;
    6.10 +
    6.11      public Project(int id) {
    6.12          this.id = id;
    6.13      }
    6.14 @@ -78,6 +82,30 @@
    6.15          this.owner = owner;
    6.16      }
    6.17  
    6.18 +    public int getOpenIssues() {
    6.19 +        return openIssues;
    6.20 +    }
    6.21 +
    6.22 +    public void setOpenIssues(int openIssues) {
    6.23 +        this.openIssues = openIssues;
    6.24 +    }
    6.25 +
    6.26 +    public int getActiveIssues() {
    6.27 +        return activeIssues;
    6.28 +    }
    6.29 +
    6.30 +    public void setActiveIssues(int activeIssues) {
    6.31 +        this.activeIssues = activeIssues;
    6.32 +    }
    6.33 +
    6.34 +    public int getDoneIssues() {
    6.35 +        return doneIssues;
    6.36 +    }
    6.37 +
    6.38 +    public void setDoneIssues(int doneIssues) {
    6.39 +        this.doneIssues = doneIssues;
    6.40 +    }
    6.41 +
    6.42      @Override
    6.43      public boolean equals(Object o) {
    6.44          if (this == o) return true;
     7.1 --- a/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java	Sun May 24 15:30:43 2020 +0200
     7.2 +++ b/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java	Sat May 30 15:26:15 2020 +0200
     7.3 @@ -303,6 +303,7 @@
     7.4  
     7.5          setAttributeHideZeros(req);
     7.6  
     7.7 +        req.setAttribute("project", sessionSelection.project);
     7.8          req.setAttribute("versions", versions);
     7.9          req.setAttribute("statsAffected", statsAffected);
    7.10          req.setAttribute("statsScheduled", statsScheduled);
    7.11 @@ -429,9 +430,8 @@
    7.12              getParameter(req, Date.class, "eta").ifPresent(issue::setEta);
    7.13              dao.getIssueDao().saveOrUpdate(issue);
    7.14  
    7.15 -            // TODO: redirect to issue overview
    7.16              // specifying the issue parameter keeps the edited issue as breadcrumb
    7.17 -            setRedirectLocation(req, "./projects/view?issue="+issue.getId());
    7.18 +            setRedirectLocation(req, "./projects/issues/?issue="+issue.getId());
    7.19              setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
    7.20              LOG.debug("Successfully updated issue {} for project {}", issue.getId(), sessionSelection.project.getName());
    7.21          } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
     8.1 --- a/src/main/resources/localization/projects.properties	Sun May 24 15:30:43 2020 +0200
     8.2 +++ b/src/main/resources/localization/projects.properties	Sat May 30 15:26:15 2020 +0200
     8.3 @@ -39,6 +39,9 @@
     8.4  thead.description=Description
     8.5  thead.repoUrl=Repository
     8.6  thead.owner=Project Lead
     8.7 +thead.issues.open=Open
     8.8 +thead.issues.active=In Progress
     8.9 +thead.issues.done=Done
    8.10  
    8.11  thead.version.project=Project
    8.12  thead.version.name=Version
     9.1 --- a/src/main/resources/localization/projects_de.properties	Sun May 24 15:30:43 2020 +0200
     9.2 +++ b/src/main/resources/localization/projects_de.properties	Sat May 30 15:26:15 2020 +0200
     9.3 @@ -39,6 +39,9 @@
     9.4  thead.description=Beschreibung
     9.5  thead.repoUrl=Repository
     9.6  thead.owner=Projektleitung
     9.7 +thead.issues.open=Offen
     9.8 +thead.issues.active=In Arbeit
     9.9 +thead.issues.done=Erledigt
    9.10  
    9.11  thead.version.project=Projekt
    9.12  thead.version.name=Version
    10.1 --- a/src/main/webapp/WEB-INF/jsp/issue-form.jsp	Sun May 24 15:30:43 2020 +0200
    10.2 +++ b/src/main/webapp/WEB-INF/jsp/issue-form.jsp	Sat May 30 15:26:15 2020 +0200
    10.3 @@ -162,7 +162,7 @@
    10.4                  <input type="hidden" name="id" value="${issue.id}"/>
    10.5                  <c:choose>
    10.6                      <c:when test="${not empty issue.project and issue.project.id ge 0}">
    10.7 -                        <c:set var="cancelUrl">./projects/view?pid=${issue.project.id}</c:set>
    10.8 +                        <c:set var="cancelUrl">./projects/issues/?pid=${issue.project.id}</c:set>
    10.9                      </c:when>
   10.10                      <c:otherwise>
   10.11                          <c:set var="cancelUrl">./projects/</c:set>
    11.1 --- a/src/main/webapp/WEB-INF/jsp/issues.jsp	Sun May 24 15:30:43 2020 +0200
    11.2 +++ b/src/main/webapp/WEB-INF/jsp/issues.jsp	Sat May 30 15:26:15 2020 +0200
    11.3 @@ -52,9 +52,11 @@
    11.4      <c:forEach var="issue" items="${issues}">
    11.5          <tr>
    11.6              <td>
    11.7 -                <a href="./projects/issues/edit?id=${issue.id}">
    11.8 -                    <c:out value="${issue.subject}" />
    11.9 -                </a>
   11.10 +                <span class="phase-${issue.status.phase}">
   11.11 +                    <a href="./projects/issues/edit?id=${issue.id}">
   11.12 +                        <c:out value="${issue.subject}" />
   11.13 +                    </a>
   11.14 +                </span>
   11.15              </td>
   11.16              <td>
   11.17                  <c:if test="${not empty issue.assignee}">
    12.1 --- a/src/main/webapp/WEB-INF/jsp/project-details.jsp	Sun May 24 15:30:43 2020 +0200
    12.2 +++ b/src/main/webapp/WEB-INF/jsp/project-details.jsp	Sat May 30 15:26:15 2020 +0200
    12.3 @@ -28,6 +28,7 @@
    12.4  <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    12.5  <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    12.6  
    12.7 +<jsp:useBean id="project" type="de.uapcore.lightpit.entities.Project" scope="request" />
    12.8  <jsp:useBean id="versions" type="java.util.List<de.uapcore.lightpit.entities.Version>" scope="request"/>
    12.9  <jsp:useBean id="statsAffected" type="java.util.List<de.uapcore.lightpit.entities.VersionStatistics>" scope="request"/>
   12.10  <jsp:useBean id="statsScheduled" type="java.util.List<de.uapcore.lightpit.entities.VersionStatistics>" scope="request"/>
   12.11 @@ -36,6 +37,28 @@
   12.12  <jsp:useBean id="issueCategoryEnum" type="de.uapcore.lightpit.entities.IssueCategory[]" scope="request"/>
   12.13  <jsp:useBean id="statsHideZeros" type="java.lang.Boolean" scope="request"/>
   12.14  
   12.15 +<div id="project-attributes">
   12.16 +    <div class="row">
   12.17 +        <div class="caption"><fmt:message key="thead.name"/>:</div>
   12.18 +        <div><c:out value="${project.name}"/></div>
   12.19 +        <div class="caption"><fmt:message key="thead.description"/>:</div>
   12.20 +        <div><c:out value="${project.description}"/></div>
   12.21 +    </div>
   12.22 +    <div class="row">
   12.23 +        <div class="caption"><fmt:message key="thead.owner"/>:</div>
   12.24 +        <div>
   12.25 +            <c:if test="${not empty project.owner}"><c:out value="${project.owner.displayname}"/></c:if>
   12.26 +        </div>
   12.27 +        <div class="caption"><fmt:message key="thead.repoUrl"/>:</div>
   12.28 +        <div>
   12.29 +            <c:if test="${not empty project.repoUrl}">
   12.30 +                <a target="_blank" href="<c:out value="${project.repoUrl}"/>"><c:out
   12.31 +                        value="${project.repoUrl}"/></a>
   12.32 +            </c:if>
   12.33 +        </div>
   12.34 +    </div>
   12.35 +</div>
   12.36 +
   12.37  <div id="tool-area">
   12.38      <a href="./projects/versions/edit" class="button"><fmt:message key="button.version.create"/></a>
   12.39      <a href="./projects/issues/edit" class="button"><fmt:message key="button.issue.create"/></a>
    13.1 --- a/src/main/webapp/WEB-INF/jsp/project-form.jsp	Sun May 24 15:30:43 2020 +0200
    13.2 +++ b/src/main/webapp/WEB-INF/jsp/project-form.jsp	Sat May 30 15:26:15 2020 +0200
    13.3 @@ -43,7 +43,7 @@
    13.4              <td><input name="name" type="text" maxlength="20" required value="<c:out value="${project.name}"/>" /></td>
    13.5          </tr>
    13.6          <tr>
    13.7 -            <th class="vtop"><fmt:message key="thead.description"/></th>
    13.8 +            <th><fmt:message key="thead.description"/></th>
    13.9              <td><input type="text" name="description" maxlength="200" value="<c:out value="${project.description}"/>" /></td>
   13.10          </tr>
   13.11          <tr>
    14.1 --- a/src/main/webapp/WEB-INF/jsp/projects.jsp	Sun May 24 15:30:43 2020 +0200
    14.2 +++ b/src/main/webapp/WEB-INF/jsp/projects.jsp	Sat May 30 15:26:15 2020 +0200
    14.3 @@ -44,21 +44,23 @@
    14.4  </div>
    14.5  
    14.6  <c:if test="${not empty projects}">
    14.7 -    <table id="project-list" class="datatable medskip fullwidth">
    14.8 +    <table id="project-list" class="datatable medskip">
    14.9          <colgroup>
   14.10              <col>
   14.11 -            <col style="width: 10%">
   14.12 -            <col style="width: 35%">
   14.13 -            <col style="width: 30%">
   14.14 -            <col style="width: 25%">
   14.15 +            <col width="20%">
   14.16 +            <col width="50%">
   14.17 +            <col width="10%">
   14.18 +            <col width="10%">
   14.19 +            <col width="10%">
   14.20          </colgroup>
   14.21          <thead>
   14.22          <tr>
   14.23              <th></th>
   14.24              <th><fmt:message key="thead.name"/></th>
   14.25 -            <th><fmt:message key="thead.description"/></th>
   14.26              <th><fmt:message key="thead.repoUrl"/></th>
   14.27 -            <th><fmt:message key="thead.owner"/></th>
   14.28 +            <th><fmt:message key="thead.issues.open"/></th>
   14.29 +            <th><fmt:message key="thead.issues.active"/></th>
   14.30 +            <th><fmt:message key="thead.issues.done"/></th>
   14.31          </tr>
   14.32          </thead>
   14.33          <tbody>
   14.34 @@ -67,17 +69,15 @@
   14.35                  <td style="width: 2em;"><a href="./projects/edit?id=${project.id}">&#x270e;</a></td>
   14.36                  <td><a href="./projects/view?pid=${project.id}"><c:out value="${project.name}"/></a>
   14.37                  </td>
   14.38 -                <td><c:out value="${project.description}"/></td>
   14.39                  <td>
   14.40                      <c:if test="${not empty project.repoUrl}">
   14.41                          <a target="_blank" href="<c:out value="${project.repoUrl}"/>"><c:out
   14.42                                  value="${project.repoUrl}"/></a>
   14.43                      </c:if>
   14.44                  </td>
   14.45 -                <td>
   14.46 -                    <c:if test="${not empty project.owner}"><c:out value="${project.owner.displayname}"/></c:if>
   14.47 -                    <c:if test="${empty project.owner}"><fmt:message key="placeholder.null-owner"/></c:if>
   14.48 -                </td>
   14.49 +                <td>${project.openIssues}</td>
   14.50 +                <td>${project.activeIssues}</td>
   14.51 +                <td>${project.doneIssues}</td>
   14.52              </tr>
   14.53          </c:forEach>
   14.54          </tbody>
    15.1 --- a/src/main/webapp/projects.css	Sun May 24 15:30:43 2020 +0200
    15.2 +++ b/src/main/webapp/projects.css	Sat May 30 15:26:15 2020 +0200
    15.3 @@ -37,4 +37,29 @@
    15.4  
    15.5  #version-stats td {
    15.6      text-align: right;
    15.7 -}
    15.8 \ No newline at end of file
    15.9 +}
   15.10 +
   15.11 +#project-attributes {
   15.12 +    margin-bottom: 2em;
   15.13 +    display: table;
   15.14 +}
   15.15 +
   15.16 +.row {
   15.17 +    display: table-row;
   15.18 +}
   15.19 +
   15.20 +.caption {
   15.21 +    font-weight: bold;
   15.22 +}
   15.23 +
   15.24 +.row > div {
   15.25 +    display: table-cell;
   15.26 +}
   15.27 +
   15.28 +.row > div + div {
   15.29 +    padding-left: 2em;
   15.30 +}
   15.31 +
   15.32 +span.phase-2 {
   15.33 +    text-decoration: line-through;
   15.34 +}

mercurial