Sun, 17 May 2020 16:23:39 +0200
adds version management
1.1 --- a/src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java Sun May 17 16:00:13 2020 +0200 1.2 +++ b/src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java Sun May 17 16:23:39 2020 +0200 1.3 @@ -30,6 +30,6 @@ 1.4 1.5 public interface DataAccessObjects { 1.6 UserDao getUserDao(); 1.7 - 1.8 ProjectDao getProjectDao(); 1.9 + VersionDao getVersionDao(); 1.10 }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/main/java/de/uapcore/lightpit/dao/VersionDao.java Sun May 17 16:23:39 2020 +0200 2.3 @@ -0,0 +1,53 @@ 2.4 +/* 2.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 2.6 + * 2.7 + * Copyright 2018 Mike Becker. All rights reserved. 2.8 + * 2.9 + * Redistribution and use in source and binary forms, with or without 2.10 + * modification, are permitted provided that the following conditions are met: 2.11 + * 2.12 + * 1. Redistributions of source code must retain the above copyright 2.13 + * notice, this list of conditions and the following disclaimer. 2.14 + * 2.15 + * 2. Redistributions in binary form must reproduce the above copyright 2.16 + * notice, this list of conditions and the following disclaimer in the 2.17 + * documentation and/or other materials provided with the distribution. 2.18 + * 2.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2.29 + * POSSIBILITY OF SUCH DAMAGE. 2.30 + * 2.31 + */ 2.32 +package de.uapcore.lightpit.dao; 2.33 + 2.34 +import de.uapcore.lightpit.entities.Project; 2.35 +import de.uapcore.lightpit.entities.Version; 2.36 + 2.37 +import java.sql.SQLException; 2.38 +import java.util.List; 2.39 + 2.40 +public interface VersionDao { 2.41 + 2.42 + Version find(int id) throws SQLException; 2.43 + void save(Version instance) throws SQLException; 2.44 + boolean update(Version instance) throws SQLException; 2.45 + default void saveOrUpdate(Version instance) throws SQLException { 2.46 + if (!update(instance)) save(instance); 2.47 + } 2.48 + 2.49 + /** 2.50 + * Lists all versions for the specified project. 2.51 + * @param project the project 2.52 + * @return a list of versions 2.53 + * @throws SQLException on any kind of SQL error 2.54 + */ 2.55 + List<Version> list(Project project) throws SQLException; 2.56 +}
3.1 --- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java Sun May 17 16:00:13 2020 +0200 3.2 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java Sun May 17 16:23:39 2020 +0200 3.3 @@ -31,6 +31,7 @@ 3.4 import de.uapcore.lightpit.dao.DataAccessObjects; 3.5 import de.uapcore.lightpit.dao.ProjectDao; 3.6 import de.uapcore.lightpit.dao.UserDao; 3.7 +import de.uapcore.lightpit.dao.VersionDao; 3.8 3.9 import java.sql.Connection; 3.10 import java.sql.SQLException; 3.11 @@ -39,10 +40,12 @@ 3.12 3.13 private final UserDao userDao; 3.14 private final ProjectDao projectDao; 3.15 + private final VersionDao versionDao; 3.16 3.17 public PGDataAccessObjects(Connection connection) throws SQLException { 3.18 userDao = new PGUserDao(connection); 3.19 projectDao = new PGProjectDao(connection); 3.20 + versionDao = new PGVersionDao(connection); 3.21 } 3.22 3.23 @Override 3.24 @@ -54,4 +57,9 @@ 3.25 public ProjectDao getProjectDao() { 3.26 return projectDao; 3.27 } 3.28 + 3.29 + @Override 3.30 + public VersionDao getVersionDao() { 3.31 + return versionDao; 3.32 + } 3.33 }
4.1 --- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java Sun May 17 16:00:13 2020 +0200 4.2 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java Sun May 17 16:23:39 2020 +0200 4.3 @@ -28,7 +28,6 @@ 4.4 */ 4.5 package de.uapcore.lightpit.dao.postgres; 4.6 4.7 -import de.uapcore.lightpit.dao.GenericDao; 4.8 import de.uapcore.lightpit.dao.ProjectDao; 4.9 import de.uapcore.lightpit.entities.Project; 4.10 import de.uapcore.lightpit.entities.User; 4.11 @@ -44,7 +43,7 @@ 4.12 import static de.uapcore.lightpit.dao.Functions.setForeignKeyOrNull; 4.13 import static de.uapcore.lightpit.dao.Functions.setStringOrNull; 4.14 4.15 -public final class PGProjectDao implements ProjectDao, GenericDao<Project> { 4.16 +public final class PGProjectDao implements ProjectDao { 4.17 4.18 private final PreparedStatement insert, update, list, find; 4.19
5.1 --- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGUserDao.java Sun May 17 16:00:13 2020 +0200 5.2 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGUserDao.java Sun May 17 16:23:39 2020 +0200 5.3 @@ -28,7 +28,6 @@ 5.4 */ 5.5 package de.uapcore.lightpit.dao.postgres; 5.6 5.7 -import de.uapcore.lightpit.dao.GenericDao; 5.8 import de.uapcore.lightpit.dao.UserDao; 5.9 import de.uapcore.lightpit.entities.User; 5.10 5.11 @@ -42,7 +41,7 @@ 5.12 5.13 import static de.uapcore.lightpit.dao.Functions.setStringOrNull; 5.14 5.15 -public final class PGUserDao implements UserDao, GenericDao<User> { 5.16 +public final class PGUserDao implements UserDao { 5.17 5.18 private final PreparedStatement insert, update, list, find; 5.19
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGVersionDao.java Sun May 17 16:23:39 2020 +0200 6.3 @@ -0,0 +1,120 @@ 6.4 +/* 6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 6.6 + * 6.7 + * Copyright 2018 Mike Becker. All rights reserved. 6.8 + * 6.9 + * Redistribution and use in source and binary forms, with or without 6.10 + * modification, are permitted provided that the following conditions are met: 6.11 + * 6.12 + * 1. Redistributions of source code must retain the above copyright 6.13 + * notice, this list of conditions and the following disclaimer. 6.14 + * 6.15 + * 2. Redistributions in binary form must reproduce the above copyright 6.16 + * notice, this list of conditions and the following disclaimer in the 6.17 + * documentation and/or other materials provided with the distribution. 6.18 + * 6.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 6.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 6.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 6.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 6.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 6.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 6.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 6.29 + * POSSIBILITY OF SUCH DAMAGE. 6.30 + * 6.31 + */ 6.32 +package de.uapcore.lightpit.dao.postgres; 6.33 + 6.34 +import de.uapcore.lightpit.dao.VersionDao; 6.35 +import de.uapcore.lightpit.entities.Project; 6.36 +import de.uapcore.lightpit.entities.Version; 6.37 +import de.uapcore.lightpit.entities.VersionStatus; 6.38 + 6.39 +import java.sql.Connection; 6.40 +import java.sql.PreparedStatement; 6.41 +import java.sql.ResultSet; 6.42 +import java.sql.SQLException; 6.43 +import java.util.ArrayList; 6.44 +import java.util.List; 6.45 +import java.util.Objects; 6.46 + 6.47 +public final class PGVersionDao implements VersionDao { 6.48 + 6.49 + private final PreparedStatement insert, update, list, find; 6.50 + 6.51 + public PGVersionDao(Connection connection) throws SQLException { 6.52 + list = connection.prepareStatement( 6.53 + "select id, project, name, ordinal, status " + 6.54 + "from lpit_version " + 6.55 + "where project = ? " + 6.56 + "order by ordinal, name"); 6.57 + 6.58 + find = connection.prepareStatement( 6.59 + "select id, project, name, ordinal, status " + 6.60 + "from lpit_version " + 6.61 + "where id = ?"); 6.62 + 6.63 + insert = connection.prepareStatement( 6.64 + "insert into lpit_version (project, name, ordinal, status) values (?, ?, ?, ?::version_status)" 6.65 + ); 6.66 + update = connection.prepareStatement( 6.67 + "update lpit_version set name = ?, ordinal = ?, status = ?::version_status where id = ?" 6.68 + ); 6.69 + } 6.70 + 6.71 + public Version mapColumns(ResultSet result) throws SQLException { 6.72 + final var version = new Version(result.getInt("id"), new Project(result.getInt("project"))); 6.73 + version.setName(result.getString("name")); 6.74 + version.setOrdinal(result.getInt("ordinal")); 6.75 + version.setStatus(VersionStatus.valueOf(result.getString("status"))); 6.76 + return version; 6.77 + } 6.78 + 6.79 + @Override 6.80 + public void save(Version instance) throws SQLException { 6.81 + Objects.requireNonNull(instance.getName()); 6.82 + Objects.requireNonNull(instance.getProject()); 6.83 + insert.setInt(1, instance.getProject().getId()); 6.84 + insert.setString(2, instance.getName()); 6.85 + insert.setInt(3, instance.getOrdinal()); 6.86 + insert.setString(4, instance.getStatus().name()); 6.87 + insert.executeUpdate(); 6.88 + } 6.89 + 6.90 + @Override 6.91 + public boolean update(Version instance) throws SQLException { 6.92 + Objects.requireNonNull(instance.getName()); 6.93 + update.setString(1, instance.getName()); 6.94 + update.setInt(2, instance.getOrdinal()); 6.95 + update.setString(3, instance.getStatus().name()); 6.96 + update.setInt(4, instance.getId()); 6.97 + return update.executeUpdate() > 0; 6.98 + } 6.99 + 6.100 + @Override 6.101 + public List<Version> list(Project project) throws SQLException { 6.102 + list.setInt(1, project.getId()); 6.103 + List<Version> versions = new ArrayList<>(); 6.104 + try (var result = list.executeQuery()) { 6.105 + while (result.next()) { 6.106 + versions.add(mapColumns(result)); 6.107 + } 6.108 + } 6.109 + return versions; 6.110 + } 6.111 + 6.112 + @Override 6.113 + public Version find(int id) throws SQLException { 6.114 + find.setInt(1, id); 6.115 + try (var result = find.executeQuery()) { 6.116 + if (result.next()) { 6.117 + return mapColumns(result); 6.118 + } else { 6.119 + return null; 6.120 + } 6.121 + } 6.122 + } 6.123 +}
7.1 --- a/src/main/java/de/uapcore/lightpit/entities/Version.java Sun May 17 16:00:13 2020 +0200 7.2 +++ b/src/main/java/de/uapcore/lightpit/entities/Version.java Sun May 17 16:23:39 2020 +0200 7.3 @@ -33,21 +33,27 @@ 7.4 public class Version implements Comparable<Version> { 7.5 7.6 private final int id; 7.7 + private final Project project; 7.8 private String name; 7.9 /** 7.10 * If we do not want versions to be ordered lexicographically we may specify an order. 7.11 */ 7.12 - private int ordinal; 7.13 - private VersionStatus status; 7.14 + private int ordinal = 0; 7.15 + private VersionStatus status = VersionStatus.Future; 7.16 7.17 - public Version(int id) { 7.18 + public Version(int id, Project project) { 7.19 this.id = id; 7.20 + this.project = project; 7.21 } 7.22 7.23 public int getId() { 7.24 return id; 7.25 } 7.26 7.27 + public Project getProject() { 7.28 + return project; 7.29 + } 7.30 + 7.31 public String getName() { 7.32 return name; 7.33 }
8.1 --- a/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java Sun May 17 16:00:13 2020 +0200 8.2 +++ b/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java Sun May 17 16:23:39 2020 +0200 8.3 @@ -33,10 +33,17 @@ 8.4 import de.uapcore.lightpit.dao.DataAccessObjects; 8.5 import de.uapcore.lightpit.entities.Project; 8.6 import de.uapcore.lightpit.entities.User; 8.7 +import de.uapcore.lightpit.entities.Version; 8.8 +import de.uapcore.lightpit.entities.VersionStatus; 8.9 +import org.slf4j.Logger; 8.10 +import org.slf4j.LoggerFactory; 8.11 8.12 import javax.servlet.annotation.WebServlet; 8.13 import javax.servlet.http.HttpServletRequest; 8.14 +import javax.servlet.http.HttpServletResponse; 8.15 +import java.io.IOException; 8.16 import java.sql.SQLException; 8.17 +import java.util.NoSuchElementException; 8.18 import java.util.Optional; 8.19 8.20 import static de.uapcore.lightpit.Functions.fqn; 8.21 @@ -52,9 +59,11 @@ 8.22 ) 8.23 public final class ProjectsModule extends AbstractLightPITServlet { 8.24 8.25 + private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class); 8.26 + 8.27 public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected-project"); 8.28 8.29 - @RequestMapping(method = HttpMethod.GET) 8.30 + @RequestMapping(method = HttpMethod.GET, menuKey = "menu.index") 8.31 public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 8.32 final var projectList = dao.getProjectDao().list(); 8.33 req.setAttribute("projects", projectList); 8.34 @@ -115,18 +124,80 @@ 8.35 8.36 setRedirectLocation(req, "./projects/"); 8.37 setDynamicFragment(req, Constants.DYN_FRAGMENT_COMMIT_SUCCESSFUL); 8.38 - } catch (NullPointerException | NumberFormatException | SQLException ex) { 8.39 + LOG.debug("Successfully updated project {}", project.getName()); 8.40 + } catch (NoSuchElementException | NumberFormatException | SQLException ex) { 8.41 // TODO: set request attribute with error text 8.42 req.setAttribute("project", project); 8.43 setDynamicFragment(req, "project-form"); 8.44 + LOG.warn("Form validation failure: {}", ex.getMessage()); 8.45 + LOG.debug("Details:", ex); 8.46 } 8.47 8.48 return ResponseType.HTML; 8.49 } 8.50 8.51 + @RequestMapping(requestPath = "versions", method = HttpMethod.GET, menuKey = "menu.versions") 8.52 + public ResponseType versions(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { 8.53 + final var selectedProject = (Project)req.getSession().getAttribute(SESSION_ATTR_SELECTED_PROJECT); 8.54 + if (selectedProject == null) { 8.55 + resp.sendError(HttpServletResponse.SC_FORBIDDEN); 8.56 + return ResponseType.NONE; 8.57 + } 8.58 8.59 - @RequestMapping(requestPath = "versions", method = HttpMethod.GET, menuKey = "menu.versions") 8.60 - public ResponseType versions(HttpServletRequest req, DataAccessObjects dao) { 8.61 + req.setAttribute("versions", dao.getVersionDao().list(selectedProject)); 8.62 + setDynamicFragment(req, "versions"); 8.63 + 8.64 + return ResponseType.HTML; 8.65 + } 8.66 + 8.67 + @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET) 8.68 + public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { 8.69 + final var selectedProject = (Project)req.getSession().getAttribute(SESSION_ATTR_SELECTED_PROJECT); 8.70 + if (selectedProject == null) { 8.71 + resp.sendError(HttpServletResponse.SC_FORBIDDEN); 8.72 + return ResponseType.NONE; 8.73 + } 8.74 + 8.75 + Optional<Integer> id = getParameter(req, Integer.class, "id"); 8.76 + if (id.isPresent()) { 8.77 + req.setAttribute("version", Optional.ofNullable(dao.getVersionDao().find(id.get())).orElse(new Version(-1, selectedProject))); 8.78 + } else { 8.79 + req.setAttribute("version", new Version(-1, selectedProject)); 8.80 + } 8.81 + req.setAttribute("versionStatusEnum", VersionStatus.values()); 8.82 + 8.83 + setDynamicFragment(req, "version-form"); 8.84 + 8.85 + return ResponseType.HTML; 8.86 + } 8.87 + 8.88 + @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST) 8.89 + public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException { 8.90 + final var selectedProject = (Project)req.getSession().getAttribute(SESSION_ATTR_SELECTED_PROJECT); 8.91 + if (selectedProject == null) { 8.92 + resp.sendError(HttpServletResponse.SC_FORBIDDEN); 8.93 + return ResponseType.NONE; 8.94 + } 8.95 + 8.96 + Version version = new Version(-1, selectedProject); 8.97 + try { 8.98 + version = new Version(getParameter(req, Integer.class, "id").orElseThrow(), selectedProject); 8.99 + version.setName(getParameter(req, String.class, "name").orElseThrow()); 8.100 + getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal); 8.101 + version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow())); 8.102 + dao.getVersionDao().saveOrUpdate(version); 8.103 + 8.104 + setRedirectLocation(req, "./projects/versions/"); 8.105 + setDynamicFragment(req, Constants.DYN_FRAGMENT_COMMIT_SUCCESSFUL); 8.106 + LOG.debug("Successfully updated version {} for project {}", version.getName(), selectedProject.getName()); 8.107 + } catch (NoSuchElementException | NumberFormatException | SQLException ex) { 8.108 + // TODO: set request attribute with error text 8.109 + req.setAttribute("version", version); 8.110 + req.setAttribute("versionStatusEnum", VersionStatus.values()); 8.111 + setDynamicFragment(req, "version-form"); 8.112 + LOG.warn("Form validation failure: {}", ex.getMessage()); 8.113 + LOG.debug("Details:", ex); 8.114 + } 8.115 8.116 return ResponseType.HTML; 8.117 }
9.1 --- a/src/main/java/de/uapcore/lightpit/modules/UsersModule.java Sun May 17 16:00:13 2020 +0200 9.2 +++ b/src/main/java/de/uapcore/lightpit/modules/UsersModule.java Sun May 17 16:23:39 2020 +0200 9.3 @@ -32,10 +32,13 @@ 9.4 import de.uapcore.lightpit.*; 9.5 import de.uapcore.lightpit.dao.DataAccessObjects; 9.6 import de.uapcore.lightpit.entities.User; 9.7 +import org.slf4j.Logger; 9.8 +import org.slf4j.LoggerFactory; 9.9 9.10 import javax.servlet.annotation.WebServlet; 9.11 import javax.servlet.http.HttpServletRequest; 9.12 import java.sql.SQLException; 9.13 +import java.util.NoSuchElementException; 9.14 import java.util.Optional; 9.15 9.16 @LightPITModule( 9.17 @@ -49,6 +52,8 @@ 9.18 ) 9.19 public final class UsersModule extends AbstractLightPITServlet { 9.20 9.21 + private static final Logger LOG = LoggerFactory.getLogger(UsersModule.class); 9.22 + 9.23 @RequestMapping(method = HttpMethod.GET) 9.24 public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 9.25 final var userDao = dao.getUserDao(); 9.26 @@ -90,10 +95,14 @@ 9.27 9.28 setRedirectLocation(req, "./teams/"); 9.29 setDynamicFragment(req, Constants.DYN_FRAGMENT_COMMIT_SUCCESSFUL); 9.30 - } catch (NullPointerException | NumberFormatException | SQLException ex) { 9.31 + 9.32 + LOG.debug("Successfully updated user {}", user.getUsername()); 9.33 + } catch (NoSuchElementException | NumberFormatException | SQLException ex) { 9.34 // TODO: set request attribute with error text 9.35 req.setAttribute("user", user); 9.36 setDynamicFragment(req, "user-form"); 9.37 + LOG.warn("Form validation failure: {}", ex.getMessage()); 9.38 + LOG.debug("Details:", ex); 9.39 } 9.40 9.41 return ResponseType.HTML;
10.1 --- a/src/main/resources/localization/projects.properties Sun May 17 16:00:13 2020 +0200 10.2 +++ b/src/main/resources/localization/projects.properties Sun May 17 16:23:39 2020 +0200 10.3 @@ -23,9 +23,11 @@ 10.4 10.5 menuLabel=Projects 10.6 10.7 +menu.index=Index 10.8 menu.versions=Versions 10.9 10.10 button.create=New Project 10.11 +button.version.create=New Version 10.12 10.13 no-projects=Welcome to LightPIT. Start off by creating a new project! 10.14 10.15 @@ -34,4 +36,15 @@ 10.16 thead.repoUrl=Repository 10.17 thead.owner=Project Lead 10.18 10.19 +thead.version.name=Version 10.20 +thead.version.status=Status 10.21 +thead.version.ordinal=Custom Ordering 10.22 +tooltip.ordinal=Use to override lexicographic ordering. 10.23 + 10.24 placeholder.null-owner=Unassigned 10.25 + 10.26 +version.status.Future=Future 10.27 +version.status.Unreleased=Unreleased 10.28 +version.status.Released=Released 10.29 +version.status.LTS=LTS 10.30 +version.status.Deprecated=Deprecated 10.31 \ No newline at end of file
11.1 --- a/src/main/resources/localization/projects_de.properties Sun May 17 16:00:13 2020 +0200 11.2 +++ b/src/main/resources/localization/projects_de.properties Sun May 17 16:23:39 2020 +0200 11.3 @@ -23,9 +23,11 @@ 11.4 11.5 menuLabel=Projekte 11.6 11.7 +menu.index=Index 11.8 menu.versions=Versionen 11.9 11.10 button.create=Neues Projekt 11.11 +button.version.create=Neue Version 11.12 11.13 no-projects=Wilkommen bei LightPIT. Beginnen Sie mit der Erstellung eines Projektes! 11.14 11.15 @@ -34,4 +36,15 @@ 11.16 thead.repoUrl=Repository 11.17 thead.owner=Projektleitung 11.18 11.19 +thead.version.name=Version 11.20 +thead.version.status=Status 11.21 +thead.version.ordinal=Sequenznummer 11.22 +tooltip.ordinal=\u00dcbersteuert die lexikographische Sortierung. 11.23 + 11.24 placeholder.null-owner=Nicht Zugewiesen 11.25 + 11.26 +version.status.Future=Geplant 11.27 +version.status.Unreleased=Unver\u00f6ffentlicht 11.28 +version.status.Released=Ver\u00f6ffentlicht 11.29 +version.status.LTS=Langzeitsupport 11.30 +version.status.Deprecated=Veraltet
12.1 --- a/src/main/webapp/WEB-INF/dynamic_fragments/project-form.jsp Sun May 17 16:00:13 2020 +0200 12.2 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/project-form.jsp Sun May 17 16:23:39 2020 +0200 12.3 @@ -69,7 +69,7 @@ 12.4 <tr> 12.5 <td colspan="2"> 12.6 <input type="hidden" name="id" value="${project.id}" /> 12.7 - <a href="./${moduleInfo.modulePath}" class="button"><fmt:message bundle="${lightpit_bundle}" key="button.cancel"/></a> 12.8 + <a href="./${moduleInfo.modulePath}/" class="button"><fmt:message bundle="${lightpit_bundle}" key="button.cancel"/></a> 12.9 <button type="submit"><fmt:message bundle="${lightpit_bundle}" key="button.okay" /></button> 12.10 </td> 12.11 </tr>
13.1 --- a/src/main/webapp/WEB-INF/dynamic_fragments/projects.jsp Sun May 17 16:00:13 2020 +0200 13.2 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/projects.jsp Sun May 17 16:23:39 2020 +0200 13.3 @@ -46,7 +46,7 @@ 13.4 </div> 13.5 13.6 <c:if test="${not empty projects}"> 13.7 -<table id="project-list" class="datatable medskip"> 13.8 +<table id="project-list" class="datatable medskip fullwidth"> 13.9 <colgroup> 13.10 <col> 13.11 <col style="width: 10%"> 13.12 @@ -67,7 +67,7 @@ 13.13 <c:forEach var="project" items="${projects}"> 13.14 <tr class="nowrap" <c:if test="${project eq selectedProject}">data-selected</c:if> > 13.15 <td style="width: 2em;"><a href="./${moduleInfo.modulePath}/edit?id=${project.id}">✎</a></td> 13.16 - <td><a href="./${moduleInfo.modulePath}?select=${project.id}"><c:out value="${project.name}"/></a></td> 13.17 + <td><a href="./${moduleInfo.modulePath}/?select=${project.id}"><c:out value="${project.name}"/></a></td> 13.18 <td><c:out value="${project.description}"/></td> 13.19 <td> 13.20 <c:if test="${not empty project.repoUrl}">
14.1 --- a/src/main/webapp/WEB-INF/dynamic_fragments/user-form.jsp Sun May 17 16:00:13 2020 +0200 14.2 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/user-form.jsp Sun May 17 16:23:39 2020 +0200 14.3 @@ -61,7 +61,7 @@ 14.4 <tr> 14.5 <td colspan="2"> 14.6 <input type="hidden" name="userid" value="${user.id}" /> 14.7 - <a href="./${moduleInfo.modulePath}" class="button"><fmt:message bundle="${lightpit_bundle}" key="button.cancel"/></a> 14.8 + <a href="./${moduleInfo.modulePath}/" class="button"><fmt:message bundle="${lightpit_bundle}" key="button.cancel"/></a> 14.9 <button type="submit"><fmt:message bundle="${lightpit_bundle}" key="button.okay" /></button> 14.10 </td> 14.11 </tr>
15.1 --- a/src/main/webapp/WEB-INF/dynamic_fragments/users.jsp Sun May 17 16:00:13 2020 +0200 15.2 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/users.jsp Sun May 17 16:23:39 2020 +0200 15.3 @@ -44,7 +44,7 @@ 15.4 </div> 15.5 15.6 <c:if test="${not empty users}"> 15.7 - <table class="datatable medskip" style="width: auto"> 15.8 + <table class="datatable medskip"> 15.9 <thead> 15.10 <tr> 15.11 <th></th>
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/version-form.jsp Sun May 17 16:23:39 2020 +0200 16.3 @@ -0,0 +1,76 @@ 16.4 +<%-- 16.5 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 16.6 + 16.7 +Copyright 2018 Mike Becker. All rights reserved. 16.8 + 16.9 +Redistribution and use in source and binary forms, with or without 16.10 +modification, are permitted provided that the following conditions are met: 16.11 + 16.12 +1. Redistributions of source code must retain the above copyright 16.13 +notice, this list of conditions and the following disclaimer. 16.14 + 16.15 +2. Redistributions in binary form must reproduce the above copyright 16.16 +notice, this list of conditions and the following disclaimer in the 16.17 +documentation and/or other materials provided with the distribution. 16.18 + 16.19 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16.20 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16.21 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16.22 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 16.23 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 16.24 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 16.25 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 16.26 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 16.27 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 16.28 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16.29 +--%> 16.30 +<%@page pageEncoding="UTF-8" %> 16.31 +<%@page import="de.uapcore.lightpit.Constants" %> 16.32 +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 16.33 +<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 16.34 + 16.35 +<c:set scope="page" var="moduleInfo" value="${requestScope[Constants.REQ_ATTR_MODULE_INFO]}"/> 16.36 +<c:set scope="page" var="selectedProject" value="${sessionScope[ProjectsModule.SESSION_ATTR_SELECTED_PROJECT]}"/> 16.37 + 16.38 +<jsp:useBean id="version" type="de.uapcore.lightpit.entities.Version" scope="request"/> 16.39 +<jsp:useBean id="versionStatusEnum" type="de.uapcore.lightpit.entities.VersionStatus[]" scope="request" /> 16.40 + 16.41 +<form action="./${moduleInfo.modulePath}/versions/commit" method="post"> 16.42 + <table class="formtable" style="width: 35ch"> 16.43 + <colgroup> 16.44 + <col> 16.45 + <col style="width: 100%"> 16.46 + </colgroup> 16.47 + <tbody> 16.48 + <tr> 16.49 + <th><fmt:message key="thead.version.name"/></th> 16.50 + <td><input name="name" type="text" maxlength="20" required value="${version.name}" /> </td> 16.51 + </tr> 16.52 + <tr> 16.53 + <th><fmt:message key="thead.version.status"/></th> 16.54 + <td> 16.55 + <select name="status" required> 16.56 + <c:forEach var="elem" items="${versionStatusEnum}"> 16.57 + <option value="${elem}"><fmt:message key="version.status.${elem}" /> </option> 16.58 + </c:forEach> 16.59 + </select> 16.60 + </td> 16.61 + </tr> 16.62 + <tr title="<fmt:message key="tooltip.ordinal" />"> 16.63 + <th><fmt:message key="thead.version.ordinal"/></th> 16.64 + <td> 16.65 + <input name="ordinal" type="number" min="0" value="${version.ordinal}" /> 16.66 + </td> 16.67 + </tr> 16.68 + </tbody> 16.69 + <tfoot> 16.70 + <tr> 16.71 + <td colspan="2"> 16.72 + <input type="hidden" name="id" value="${version.id}" /> 16.73 + <a href="./${moduleInfo.modulePath}/versions/" class="button"><fmt:message bundle="${lightpit_bundle}" key="button.cancel"/></a> 16.74 + <button type="submit"><fmt:message bundle="${lightpit_bundle}" key="button.okay" /></button> 16.75 + </td> 16.76 + </tr> 16.77 + </tfoot> 16.78 + </table> 16.79 +</form>
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/versions.jsp Sun May 17 16:23:39 2020 +0200 17.3 @@ -0,0 +1,68 @@ 17.4 +<%-- 17.5 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 17.6 + 17.7 +Copyright 2018 Mike Becker. All rights reserved. 17.8 + 17.9 +Redistribution and use in source and binary forms, with or without 17.10 +modification, are permitted provided that the following conditions are met: 17.11 + 17.12 +1. Redistributions of source code must retain the above copyright 17.13 +notice, this list of conditions and the following disclaimer. 17.14 + 17.15 +2. Redistributions in binary form must reproduce the above copyright 17.16 +notice, this list of conditions and the following disclaimer in the 17.17 +documentation and/or other materials provided with the distribution. 17.18 + 17.19 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17.20 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17.21 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17.22 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17.23 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17.24 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 17.25 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 17.26 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 17.27 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 17.28 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 17.29 +--%> 17.30 +<%@page pageEncoding="UTF-8" %> 17.31 +<%@page import="de.uapcore.lightpit.Constants" %> 17.32 +<%@page import="de.uapcore.lightpit.modules.ProjectsModule" %> 17.33 +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 17.34 +<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 17.35 + 17.36 +<c:set scope="page" var="moduleInfo" value="${requestScope[Constants.REQ_ATTR_MODULE_INFO]}"/> 17.37 +<c:set scope="page" var="selectedProject" value="${sessionScope[ProjectsModule.SESSION_ATTR_SELECTED_PROJECT]}"/> 17.38 + 17.39 +<jsp:useBean id="versions" type="java.util.List<de.uapcore.lightpit.entities.Version>" scope="request"/> 17.40 + 17.41 +<c:if test="${empty selectedProject}"> 17.42 + <div class="info-box"> 17.43 + <fmt:message key="no-projects" /> 17.44 + </div> 17.45 +</c:if> 17.46 +<c:if test="${not empty selectedProject}"> 17.47 +<div id="tool-area"> 17.48 + <a href="./${moduleInfo.modulePath}/versions/edit" class="button"><fmt:message key="button.version.create" /></a> 17.49 +</div> 17.50 + 17.51 +<c:if test="${not empty versions}"> 17.52 +<table id="project-list" class="datatable medskip"> 17.53 + <thead> 17.54 + <tr> 17.55 + <th></th> 17.56 + <th><fmt:message key="thead.version.name"/></th> 17.57 + <th><fmt:message key="thead.version.status"/></th> 17.58 + </tr> 17.59 + </thead> 17.60 + <tbody> 17.61 + <c:forEach var="version" items="${versions}"> 17.62 + <tr class="nowrap" > 17.63 + <td style="width: 2em;"><a href="./${moduleInfo.modulePath}/versions/edit?id=${version.id}">✎</a></td> 17.64 + <td><c:out value="${version.name}"/></td> 17.65 + <td><fmt:message key="version.status.${version.status}" /></td> 17.66 + </tr> 17.67 + </c:forEach> 17.68 + </tbody> 17.69 +</table> 17.70 +</c:if> 17.71 +</c:if>
18.1 --- a/src/main/webapp/lightpit.css Sun May 17 16:00:13 2020 +0200 18.2 +++ b/src/main/webapp/lightpit.css Sun May 17 16:23:39 2020 +0200 18.3 @@ -117,7 +117,7 @@ 18.4 } 18.5 18.6 table.datatable { 18.7 - width: 100%; 18.8 + width: auto; 18.9 border-style: solid; 18.10 border-width: 1pt; 18.11 border-color: black;