Sun, 17 May 2020 16:23:39 +0200
adds version management
--- a/src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java Sun May 17 16:00:13 2020 +0200 +++ b/src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java Sun May 17 16:23:39 2020 +0200 @@ -30,6 +30,6 @@ public interface DataAccessObjects { UserDao getUserDao(); - ProjectDao getProjectDao(); + VersionDao getVersionDao(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/uapcore/lightpit/dao/VersionDao.java Sun May 17 16:23:39 2020 +0200 @@ -0,0 +1,53 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2018 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +package de.uapcore.lightpit.dao; + +import de.uapcore.lightpit.entities.Project; +import de.uapcore.lightpit.entities.Version; + +import java.sql.SQLException; +import java.util.List; + +public interface VersionDao { + + Version find(int id) throws SQLException; + void save(Version instance) throws SQLException; + boolean update(Version instance) throws SQLException; + default void saveOrUpdate(Version instance) throws SQLException { + if (!update(instance)) save(instance); + } + + /** + * Lists all versions for the specified project. + * @param project the project + * @return a list of versions + * @throws SQLException on any kind of SQL error + */ + List<Version> list(Project project) throws SQLException; +}
--- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java Sun May 17 16:00:13 2020 +0200 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java Sun May 17 16:23:39 2020 +0200 @@ -31,6 +31,7 @@ import de.uapcore.lightpit.dao.DataAccessObjects; import de.uapcore.lightpit.dao.ProjectDao; import de.uapcore.lightpit.dao.UserDao; +import de.uapcore.lightpit.dao.VersionDao; import java.sql.Connection; import java.sql.SQLException; @@ -39,10 +40,12 @@ private final UserDao userDao; private final ProjectDao projectDao; + private final VersionDao versionDao; public PGDataAccessObjects(Connection connection) throws SQLException { userDao = new PGUserDao(connection); projectDao = new PGProjectDao(connection); + versionDao = new PGVersionDao(connection); } @Override @@ -54,4 +57,9 @@ public ProjectDao getProjectDao() { return projectDao; } + + @Override + public VersionDao getVersionDao() { + return versionDao; + } }
--- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java Sun May 17 16:00:13 2020 +0200 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java Sun May 17 16:23:39 2020 +0200 @@ -28,7 +28,6 @@ */ package de.uapcore.lightpit.dao.postgres; -import de.uapcore.lightpit.dao.GenericDao; import de.uapcore.lightpit.dao.ProjectDao; import de.uapcore.lightpit.entities.Project; import de.uapcore.lightpit.entities.User; @@ -44,7 +43,7 @@ import static de.uapcore.lightpit.dao.Functions.setForeignKeyOrNull; import static de.uapcore.lightpit.dao.Functions.setStringOrNull; -public final class PGProjectDao implements ProjectDao, GenericDao<Project> { +public final class PGProjectDao implements ProjectDao { private final PreparedStatement insert, update, list, find;
--- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGUserDao.java Sun May 17 16:00:13 2020 +0200 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGUserDao.java Sun May 17 16:23:39 2020 +0200 @@ -28,7 +28,6 @@ */ package de.uapcore.lightpit.dao.postgres; -import de.uapcore.lightpit.dao.GenericDao; import de.uapcore.lightpit.dao.UserDao; import de.uapcore.lightpit.entities.User; @@ -42,7 +41,7 @@ import static de.uapcore.lightpit.dao.Functions.setStringOrNull; -public final class PGUserDao implements UserDao, GenericDao<User> { +public final class PGUserDao implements UserDao { private final PreparedStatement insert, update, list, find;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGVersionDao.java Sun May 17 16:23:39 2020 +0200 @@ -0,0 +1,120 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2018 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +package de.uapcore.lightpit.dao.postgres; + +import de.uapcore.lightpit.dao.VersionDao; +import de.uapcore.lightpit.entities.Project; +import de.uapcore.lightpit.entities.Version; +import de.uapcore.lightpit.entities.VersionStatus; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public final class PGVersionDao implements VersionDao { + + private final PreparedStatement insert, update, list, find; + + public PGVersionDao(Connection connection) throws SQLException { + list = connection.prepareStatement( + "select id, project, name, ordinal, status " + + "from lpit_version " + + "where project = ? " + + "order by ordinal, name"); + + find = connection.prepareStatement( + "select id, project, name, ordinal, status " + + "from lpit_version " + + "where id = ?"); + + insert = connection.prepareStatement( + "insert into lpit_version (project, name, ordinal, status) values (?, ?, ?, ?::version_status)" + ); + update = connection.prepareStatement( + "update lpit_version set name = ?, ordinal = ?, status = ?::version_status where id = ?" + ); + } + + public Version mapColumns(ResultSet result) throws SQLException { + final var version = new Version(result.getInt("id"), new Project(result.getInt("project"))); + version.setName(result.getString("name")); + version.setOrdinal(result.getInt("ordinal")); + version.setStatus(VersionStatus.valueOf(result.getString("status"))); + return version; + } + + @Override + public void save(Version instance) throws SQLException { + Objects.requireNonNull(instance.getName()); + Objects.requireNonNull(instance.getProject()); + insert.setInt(1, instance.getProject().getId()); + insert.setString(2, instance.getName()); + insert.setInt(3, instance.getOrdinal()); + insert.setString(4, instance.getStatus().name()); + insert.executeUpdate(); + } + + @Override + public boolean update(Version instance) throws SQLException { + Objects.requireNonNull(instance.getName()); + update.setString(1, instance.getName()); + update.setInt(2, instance.getOrdinal()); + update.setString(3, instance.getStatus().name()); + update.setInt(4, instance.getId()); + return update.executeUpdate() > 0; + } + + @Override + public List<Version> list(Project project) throws SQLException { + list.setInt(1, project.getId()); + List<Version> versions = new ArrayList<>(); + try (var result = list.executeQuery()) { + while (result.next()) { + versions.add(mapColumns(result)); + } + } + return versions; + } + + @Override + public Version find(int id) throws SQLException { + find.setInt(1, id); + try (var result = find.executeQuery()) { + if (result.next()) { + return mapColumns(result); + } else { + return null; + } + } + } +}
--- a/src/main/java/de/uapcore/lightpit/entities/Version.java Sun May 17 16:00:13 2020 +0200 +++ b/src/main/java/de/uapcore/lightpit/entities/Version.java Sun May 17 16:23:39 2020 +0200 @@ -33,21 +33,27 @@ public class Version implements Comparable<Version> { private final int id; + private final Project project; private String name; /** * If we do not want versions to be ordered lexicographically we may specify an order. */ - private int ordinal; - private VersionStatus status; + private int ordinal = 0; + private VersionStatus status = VersionStatus.Future; - public Version(int id) { + public Version(int id, Project project) { this.id = id; + this.project = project; } public int getId() { return id; } + public Project getProject() { + return project; + } + public String getName() { return name; }
--- a/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java Sun May 17 16:00:13 2020 +0200 +++ b/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java Sun May 17 16:23:39 2020 +0200 @@ -33,10 +33,17 @@ import de.uapcore.lightpit.dao.DataAccessObjects; import de.uapcore.lightpit.entities.Project; import de.uapcore.lightpit.entities.User; +import de.uapcore.lightpit.entities.Version; +import de.uapcore.lightpit.entities.VersionStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.sql.SQLException; +import java.util.NoSuchElementException; import java.util.Optional; import static de.uapcore.lightpit.Functions.fqn; @@ -52,9 +59,11 @@ ) public final class ProjectsModule extends AbstractLightPITServlet { + private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class); + public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected-project"); - @RequestMapping(method = HttpMethod.GET) + @RequestMapping(method = HttpMethod.GET, menuKey = "menu.index") public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException { final var projectList = dao.getProjectDao().list(); req.setAttribute("projects", projectList); @@ -115,18 +124,80 @@ setRedirectLocation(req, "./projects/"); setDynamicFragment(req, Constants.DYN_FRAGMENT_COMMIT_SUCCESSFUL); - } catch (NullPointerException | NumberFormatException | SQLException ex) { + LOG.debug("Successfully updated project {}", project.getName()); + } catch (NoSuchElementException | NumberFormatException | SQLException ex) { // TODO: set request attribute with error text req.setAttribute("project", project); setDynamicFragment(req, "project-form"); + LOG.warn("Form validation failure: {}", ex.getMessage()); + LOG.debug("Details:", ex); } return ResponseType.HTML; } + @RequestMapping(requestPath = "versions", method = HttpMethod.GET, menuKey = "menu.versions") + public ResponseType versions(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { + final var selectedProject = (Project)req.getSession().getAttribute(SESSION_ATTR_SELECTED_PROJECT); + if (selectedProject == null) { + resp.sendError(HttpServletResponse.SC_FORBIDDEN); + return ResponseType.NONE; + } - @RequestMapping(requestPath = "versions", method = HttpMethod.GET, menuKey = "menu.versions") - public ResponseType versions(HttpServletRequest req, DataAccessObjects dao) { + req.setAttribute("versions", dao.getVersionDao().list(selectedProject)); + setDynamicFragment(req, "versions"); + + return ResponseType.HTML; + } + + @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET) + public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { + final var selectedProject = (Project)req.getSession().getAttribute(SESSION_ATTR_SELECTED_PROJECT); + if (selectedProject == null) { + resp.sendError(HttpServletResponse.SC_FORBIDDEN); + return ResponseType.NONE; + } + + Optional<Integer> id = getParameter(req, Integer.class, "id"); + if (id.isPresent()) { + req.setAttribute("version", Optional.ofNullable(dao.getVersionDao().find(id.get())).orElse(new Version(-1, selectedProject))); + } else { + req.setAttribute("version", new Version(-1, selectedProject)); + } + req.setAttribute("versionStatusEnum", VersionStatus.values()); + + setDynamicFragment(req, "version-form"); + + return ResponseType.HTML; + } + + @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST) + public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException { + final var selectedProject = (Project)req.getSession().getAttribute(SESSION_ATTR_SELECTED_PROJECT); + if (selectedProject == null) { + resp.sendError(HttpServletResponse.SC_FORBIDDEN); + return ResponseType.NONE; + } + + Version version = new Version(-1, selectedProject); + try { + version = new Version(getParameter(req, Integer.class, "id").orElseThrow(), selectedProject); + version.setName(getParameter(req, String.class, "name").orElseThrow()); + getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal); + version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow())); + dao.getVersionDao().saveOrUpdate(version); + + setRedirectLocation(req, "./projects/versions/"); + setDynamicFragment(req, Constants.DYN_FRAGMENT_COMMIT_SUCCESSFUL); + LOG.debug("Successfully updated version {} for project {}", version.getName(), selectedProject.getName()); + } catch (NoSuchElementException | NumberFormatException | SQLException ex) { + // TODO: set request attribute with error text + req.setAttribute("version", version); + req.setAttribute("versionStatusEnum", VersionStatus.values()); + setDynamicFragment(req, "version-form"); + LOG.warn("Form validation failure: {}", ex.getMessage()); + LOG.debug("Details:", ex); + } return ResponseType.HTML; }
--- a/src/main/java/de/uapcore/lightpit/modules/UsersModule.java Sun May 17 16:00:13 2020 +0200 +++ b/src/main/java/de/uapcore/lightpit/modules/UsersModule.java Sun May 17 16:23:39 2020 +0200 @@ -32,10 +32,13 @@ import de.uapcore.lightpit.*; import de.uapcore.lightpit.dao.DataAccessObjects; import de.uapcore.lightpit.entities.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import java.sql.SQLException; +import java.util.NoSuchElementException; import java.util.Optional; @LightPITModule( @@ -49,6 +52,8 @@ ) public final class UsersModule extends AbstractLightPITServlet { + private static final Logger LOG = LoggerFactory.getLogger(UsersModule.class); + @RequestMapping(method = HttpMethod.GET) public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException { final var userDao = dao.getUserDao(); @@ -90,10 +95,14 @@ setRedirectLocation(req, "./teams/"); setDynamicFragment(req, Constants.DYN_FRAGMENT_COMMIT_SUCCESSFUL); - } catch (NullPointerException | NumberFormatException | SQLException ex) { + + LOG.debug("Successfully updated user {}", user.getUsername()); + } catch (NoSuchElementException | NumberFormatException | SQLException ex) { // TODO: set request attribute with error text req.setAttribute("user", user); setDynamicFragment(req, "user-form"); + LOG.warn("Form validation failure: {}", ex.getMessage()); + LOG.debug("Details:", ex); } return ResponseType.HTML;
--- a/src/main/resources/localization/projects.properties Sun May 17 16:00:13 2020 +0200 +++ b/src/main/resources/localization/projects.properties Sun May 17 16:23:39 2020 +0200 @@ -23,9 +23,11 @@ menuLabel=Projects +menu.index=Index menu.versions=Versions button.create=New Project +button.version.create=New Version no-projects=Welcome to LightPIT. Start off by creating a new project! @@ -34,4 +36,15 @@ thead.repoUrl=Repository thead.owner=Project Lead +thead.version.name=Version +thead.version.status=Status +thead.version.ordinal=Custom Ordering +tooltip.ordinal=Use to override lexicographic ordering. + placeholder.null-owner=Unassigned + +version.status.Future=Future +version.status.Unreleased=Unreleased +version.status.Released=Released +version.status.LTS=LTS +version.status.Deprecated=Deprecated \ No newline at end of file
--- a/src/main/resources/localization/projects_de.properties Sun May 17 16:00:13 2020 +0200 +++ b/src/main/resources/localization/projects_de.properties Sun May 17 16:23:39 2020 +0200 @@ -23,9 +23,11 @@ menuLabel=Projekte +menu.index=Index menu.versions=Versionen button.create=Neues Projekt +button.version.create=Neue Version no-projects=Wilkommen bei LightPIT. Beginnen Sie mit der Erstellung eines Projektes! @@ -34,4 +36,15 @@ thead.repoUrl=Repository thead.owner=Projektleitung +thead.version.name=Version +thead.version.status=Status +thead.version.ordinal=Sequenznummer +tooltip.ordinal=\u00dcbersteuert die lexikographische Sortierung. + placeholder.null-owner=Nicht Zugewiesen + +version.status.Future=Geplant +version.status.Unreleased=Unver\u00f6ffentlicht +version.status.Released=Ver\u00f6ffentlicht +version.status.LTS=Langzeitsupport +version.status.Deprecated=Veraltet
--- a/src/main/webapp/WEB-INF/dynamic_fragments/project-form.jsp Sun May 17 16:00:13 2020 +0200 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/project-form.jsp Sun May 17 16:23:39 2020 +0200 @@ -69,7 +69,7 @@ <tr> <td colspan="2"> <input type="hidden" name="id" value="${project.id}" /> - <a href="./${moduleInfo.modulePath}" class="button"><fmt:message bundle="${lightpit_bundle}" key="button.cancel"/></a> + <a href="./${moduleInfo.modulePath}/" class="button"><fmt:message bundle="${lightpit_bundle}" key="button.cancel"/></a> <button type="submit"><fmt:message bundle="${lightpit_bundle}" key="button.okay" /></button> </td> </tr>
--- a/src/main/webapp/WEB-INF/dynamic_fragments/projects.jsp Sun May 17 16:00:13 2020 +0200 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/projects.jsp Sun May 17 16:23:39 2020 +0200 @@ -46,7 +46,7 @@ </div> <c:if test="${not empty projects}"> -<table id="project-list" class="datatable medskip"> +<table id="project-list" class="datatable medskip fullwidth"> <colgroup> <col> <col style="width: 10%"> @@ -67,7 +67,7 @@ <c:forEach var="project" items="${projects}"> <tr class="nowrap" <c:if test="${project eq selectedProject}">data-selected</c:if> > <td style="width: 2em;"><a href="./${moduleInfo.modulePath}/edit?id=${project.id}">✎</a></td> - <td><a href="./${moduleInfo.modulePath}?select=${project.id}"><c:out value="${project.name}"/></a></td> + <td><a href="./${moduleInfo.modulePath}/?select=${project.id}"><c:out value="${project.name}"/></a></td> <td><c:out value="${project.description}"/></td> <td> <c:if test="${not empty project.repoUrl}">
--- a/src/main/webapp/WEB-INF/dynamic_fragments/user-form.jsp Sun May 17 16:00:13 2020 +0200 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/user-form.jsp Sun May 17 16:23:39 2020 +0200 @@ -61,7 +61,7 @@ <tr> <td colspan="2"> <input type="hidden" name="userid" value="${user.id}" /> - <a href="./${moduleInfo.modulePath}" class="button"><fmt:message bundle="${lightpit_bundle}" key="button.cancel"/></a> + <a href="./${moduleInfo.modulePath}/" class="button"><fmt:message bundle="${lightpit_bundle}" key="button.cancel"/></a> <button type="submit"><fmt:message bundle="${lightpit_bundle}" key="button.okay" /></button> </td> </tr>
--- a/src/main/webapp/WEB-INF/dynamic_fragments/users.jsp Sun May 17 16:00:13 2020 +0200 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/users.jsp Sun May 17 16:23:39 2020 +0200 @@ -44,7 +44,7 @@ </div> <c:if test="${not empty users}"> - <table class="datatable medskip" style="width: auto"> + <table class="datatable medskip"> <thead> <tr> <th></th>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/version-form.jsp Sun May 17 16:23:39 2020 +0200 @@ -0,0 +1,76 @@ +<%-- +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + +Copyright 2018 Mike Becker. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--%> +<%@page pageEncoding="UTF-8" %> +<%@page import="de.uapcore.lightpit.Constants" %> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + +<c:set scope="page" var="moduleInfo" value="${requestScope[Constants.REQ_ATTR_MODULE_INFO]}"/> +<c:set scope="page" var="selectedProject" value="${sessionScope[ProjectsModule.SESSION_ATTR_SELECTED_PROJECT]}"/> + +<jsp:useBean id="version" type="de.uapcore.lightpit.entities.Version" scope="request"/> +<jsp:useBean id="versionStatusEnum" type="de.uapcore.lightpit.entities.VersionStatus[]" scope="request" /> + +<form action="./${moduleInfo.modulePath}/versions/commit" method="post"> + <table class="formtable" style="width: 35ch"> + <colgroup> + <col> + <col style="width: 100%"> + </colgroup> + <tbody> + <tr> + <th><fmt:message key="thead.version.name"/></th> + <td><input name="name" type="text" maxlength="20" required value="${version.name}" /> </td> + </tr> + <tr> + <th><fmt:message key="thead.version.status"/></th> + <td> + <select name="status" required> + <c:forEach var="elem" items="${versionStatusEnum}"> + <option value="${elem}"><fmt:message key="version.status.${elem}" /> </option> + </c:forEach> + </select> + </td> + </tr> + <tr title="<fmt:message key="tooltip.ordinal" />"> + <th><fmt:message key="thead.version.ordinal"/></th> + <td> + <input name="ordinal" type="number" min="0" value="${version.ordinal}" /> + </td> + </tr> + </tbody> + <tfoot> + <tr> + <td colspan="2"> + <input type="hidden" name="id" value="${version.id}" /> + <a href="./${moduleInfo.modulePath}/versions/" class="button"><fmt:message bundle="${lightpit_bundle}" key="button.cancel"/></a> + <button type="submit"><fmt:message bundle="${lightpit_bundle}" key="button.okay" /></button> + </td> + </tr> + </tfoot> + </table> +</form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/webapp/WEB-INF/dynamic_fragments/versions.jsp Sun May 17 16:23:39 2020 +0200 @@ -0,0 +1,68 @@ +<%-- +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + +Copyright 2018 Mike Becker. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--%> +<%@page pageEncoding="UTF-8" %> +<%@page import="de.uapcore.lightpit.Constants" %> +<%@page import="de.uapcore.lightpit.modules.ProjectsModule" %> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + +<c:set scope="page" var="moduleInfo" value="${requestScope[Constants.REQ_ATTR_MODULE_INFO]}"/> +<c:set scope="page" var="selectedProject" value="${sessionScope[ProjectsModule.SESSION_ATTR_SELECTED_PROJECT]}"/> + +<jsp:useBean id="versions" type="java.util.List<de.uapcore.lightpit.entities.Version>" scope="request"/> + +<c:if test="${empty selectedProject}"> + <div class="info-box"> + <fmt:message key="no-projects" /> + </div> +</c:if> +<c:if test="${not empty selectedProject}"> +<div id="tool-area"> + <a href="./${moduleInfo.modulePath}/versions/edit" class="button"><fmt:message key="button.version.create" /></a> +</div> + +<c:if test="${not empty versions}"> +<table id="project-list" class="datatable medskip"> + <thead> + <tr> + <th></th> + <th><fmt:message key="thead.version.name"/></th> + <th><fmt:message key="thead.version.status"/></th> + </tr> + </thead> + <tbody> + <c:forEach var="version" items="${versions}"> + <tr class="nowrap" > + <td style="width: 2em;"><a href="./${moduleInfo.modulePath}/versions/edit?id=${version.id}">✎</a></td> + <td><c:out value="${version.name}"/></td> + <td><fmt:message key="version.status.${version.status}" /></td> + </tr> + </c:forEach> + </tbody> +</table> +</c:if> +</c:if>