# HG changeset patch # User Mike Becker # Date 1589725419 -7200 # Node ID c759c60507a2be683e6ed0835ea44a7b9d564819 # Parent 8d3047f781909792849c30537714044919f1d284 adds version management diff -r 8d3047f78190 -r c759c60507a2 src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java --- 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(); } diff -r 8d3047f78190 -r c759c60507a2 src/main/java/de/uapcore/lightpit/dao/VersionDao.java --- /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 list(Project project) throws SQLException; +} diff -r 8d3047f78190 -r c759c60507a2 src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java --- 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; + } } diff -r 8d3047f78190 -r c759c60507a2 src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java --- 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 { +public final class PGProjectDao implements ProjectDao { private final PreparedStatement insert, update, list, find; diff -r 8d3047f78190 -r c759c60507a2 src/main/java/de/uapcore/lightpit/dao/postgres/PGUserDao.java --- 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 { +public final class PGUserDao implements UserDao { private final PreparedStatement insert, update, list, find; diff -r 8d3047f78190 -r c759c60507a2 src/main/java/de/uapcore/lightpit/dao/postgres/PGVersionDao.java --- /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 list(Project project) throws SQLException { + list.setInt(1, project.getId()); + List 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; + } + } + } +} diff -r 8d3047f78190 -r c759c60507a2 src/main/java/de/uapcore/lightpit/entities/Version.java --- 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 { 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; } diff -r 8d3047f78190 -r c759c60507a2 src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java --- 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 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; } diff -r 8d3047f78190 -r c759c60507a2 src/main/java/de/uapcore/lightpit/modules/UsersModule.java --- 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; diff -r 8d3047f78190 -r c759c60507a2 src/main/resources/localization/projects.properties --- 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 diff -r 8d3047f78190 -r c759c60507a2 src/main/resources/localization/projects_de.properties --- 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 diff -r 8d3047f78190 -r c759c60507a2 src/main/webapp/WEB-INF/dynamic_fragments/project-form.jsp --- 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 @@ - + diff -r 8d3047f78190 -r c759c60507a2 src/main/webapp/WEB-INF/dynamic_fragments/projects.jsp --- 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 @@ - +
@@ -67,7 +67,7 @@ data-selected > - + diff -r 8d3047f78190 -r c759c60507a2 src/main/webapp/WEB-INF/dynamic_fragments/users.jsp --- 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 @@ -
diff -r 8d3047f78190 -r c759c60507a2 src/main/webapp/WEB-INF/dynamic_fragments/user-form.jsp --- 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 @@
- +
+
diff -r 8d3047f78190 -r c759c60507a2 src/main/webapp/WEB-INF/dynamic_fragments/version-form.jsp --- /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" %> + + + + + + + +
+
+ + + + + + + + + + + + + + "> + + + + + + + + + +
+ +
+ +
+ + + +
+ diff -r 8d3047f78190 -r c759c60507a2 src/main/webapp/WEB-INF/dynamic_fragments/versions.jsp --- /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" %> + + + + + + + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+
+
diff -r 8d3047f78190 -r c759c60507a2 src/main/webapp/lightpit.css --- a/src/main/webapp/lightpit.css Sun May 17 16:00:13 2020 +0200 +++ b/src/main/webapp/lightpit.css Sun May 17 16:23:39 2020 +0200 @@ -117,7 +117,7 @@ } table.datatable { - width: 100%; + width: auto; border-style: solid; border-width: 1pt; border-color: black;