src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java

changeset 131
67df332e3146
parent 129
a09d5c59351a
child 133
ef075cd7ce55
     1.1 --- a/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java	Thu Oct 15 18:36:05 2020 +0200
     1.2 +++ b/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java	Thu Oct 15 20:02:30 2020 +0200
     1.3 @@ -44,12 +44,9 @@
     1.4  import java.sql.Date;
     1.5  import java.sql.SQLException;
     1.6  import java.util.NoSuchElementException;
     1.7 -import java.util.Optional;
     1.8  import java.util.stream.Collectors;
     1.9  import java.util.stream.Stream;
    1.10  
    1.11 -import static de.uapcore.lightpit.Functions.fqn;
    1.12 -
    1.13  @WebServlet(
    1.14          name = "ProjectsModule",
    1.15          urlPatterns = "/projects/*"
    1.16 @@ -58,45 +55,26 @@
    1.17  
    1.18      private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class);
    1.19  
    1.20 -    private static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project");
    1.21 -    private static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected_version");
    1.22 -    private static final String SESSION_ATTR_SELECTED_COMPONENT = fqn(ProjectsModule.class, "selected_component");
    1.23 -    private static final String PARAMETER_SELECTED_PROJECT = "pid";
    1.24 -    private static final String PARAMETER_SELECTED_VERSION = "vid";
    1.25 -    private static final String PARAMETER_SELECTED_COMPONENT = "cid";
    1.26 -
    1.27      @Override
    1.28      protected String getResourceBundleName() {
    1.29          return "localization.projects";
    1.30      }
    1.31  
    1.32 -    private int syncParamWithSession(HttpServletRequest req, String param, String attr) {
    1.33 -        final var session = req.getSession();
    1.34 -        final var idParam = getParameter(req, Integer.class, param);
    1.35 -        final int id;
    1.36 -        if (idParam.isPresent()) {
    1.37 -            id = idParam.get();
    1.38 -            session.setAttribute(attr, id);
    1.39 -        } else {
    1.40 -            id = Optional.ofNullable(session.getAttribute(attr)).map(x->(Integer)x).orElse(-1);
    1.41 -        }
    1.42 -        return id;
    1.43 -    }
    1.44 -
    1.45 -    private void populate(ProjectView viewModel, HttpServletRequest req, DataAccessObjects dao) throws SQLException {
    1.46 +    private void populate(ProjectView viewModel, PathParameters pathParameters, DataAccessObjects dao) throws SQLException {
    1.47          final var projectDao = dao.getProjectDao();
    1.48          final var versionDao = dao.getVersionDao();
    1.49          final var componentDao = dao.getComponentDao();
    1.50  
    1.51          projectDao.list().stream().map(ProjectInfo::new).forEach(viewModel.getProjectList()::add);
    1.52  
    1.53 +        if (pathParameters == null)
    1.54 +            return;
    1.55 +
    1.56          // Select Project
    1.57 -        final int pid = syncParamWithSession(req, PARAMETER_SELECTED_PROJECT, SESSION_ATTR_SELECTED_PROJECT);
    1.58 -        if (pid >= 0) {
    1.59 +        final int pid = Functions.parseIntOrZero(pathParameters.get("project"));
    1.60 +        if (pid > 0) {
    1.61              final var project = projectDao.find(pid);
    1.62 -            if (project == null) {
    1.63 -                req.setAttribute(SESSION_ATTR_SELECTED_PROJECT, -1);
    1.64 -            } else {
    1.65 +            if (project != null) {
    1.66                  final var info = new ProjectInfo(project);
    1.67                  info.setVersions(versionDao.list(project));
    1.68                  info.setComponents(componentDao.list(project));
    1.69 @@ -106,22 +84,19 @@
    1.70          }
    1.71  
    1.72          // Select Version
    1.73 -        final int vid = syncParamWithSession(req, PARAMETER_SELECTED_VERSION, SESSION_ATTR_SELECTED_VERSION);
    1.74 +        final int vid = Functions.parseIntOrZero(pathParameters.get("version"));
    1.75          if (vid > 0) {
    1.76              viewModel.setVersionFilter(versionDao.find(vid));
    1.77 -        } else {
    1.78 -            // NULL for version means: show all unassigned
    1.79 -            viewModel.setVersionFilter(null);
    1.80 +        }
    1.81 +        // TODO: don't treat unknown == unassigned - send 404 for unknown and introduce special word for unassigned
    1.82 +
    1.83 +        // Select Component
    1.84 +        final int cid = Functions.parseIntOrZero(pathParameters.get("component"));
    1.85 +        if (cid > 0) {
    1.86 +            viewModel.setComponentFilter(componentDao.find(cid));
    1.87          }
    1.88  
    1.89 -        // Select Component
    1.90 -        final int cid = syncParamWithSession(req, PARAMETER_SELECTED_COMPONENT, SESSION_ATTR_SELECTED_COMPONENT);
    1.91 -        if (cid > 0) {
    1.92 -            viewModel.setComponentFilter(componentDao.find(cid));
    1.93 -        } else if (cid <= 0) {
    1.94 -            // -1 means: filter for unassigned, null means: show all
    1.95 -            viewModel.setComponentFilter(new Component(-1));
    1.96 -        }
    1.97 +        // TODO: distinguish all/unassigned for components
    1.98      }
    1.99  
   1.100      private ResponseType forwardView(HttpServletRequest req, ProjectView viewModel, String name) {
   1.101 @@ -135,7 +110,7 @@
   1.102      @RequestMapping(method = HttpMethod.GET)
   1.103      public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
   1.104          final var viewModel = new ProjectView();
   1.105 -        populate(viewModel, req, dao);
   1.106 +        populate(viewModel, null, dao);
   1.107  
   1.108          final var projectDao = dao.getProjectDao();
   1.109          final var versionDao = dao.getVersionDao();
   1.110 @@ -148,30 +123,38 @@
   1.111          return forwardView(req, viewModel, "projects");
   1.112      }
   1.113  
   1.114 -    private void configure(ProjectEditView viewModel, Project project, DataAccessObjects dao) throws SQLException {
   1.115 +    private void configureProjectEditor(ProjectEditView viewModel, Project project, DataAccessObjects dao) throws SQLException {
   1.116          viewModel.setProject(project);
   1.117          viewModel.setUsers(dao.getUserDao().list());
   1.118      }
   1.119  
   1.120 -    @RequestMapping(requestPath = "edit", method = HttpMethod.GET)
   1.121 -    public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
   1.122 +    @RequestMapping(requestPath = "$project/edit", method = HttpMethod.GET)
   1.123 +    public ResponseType edit(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParams, DataAccessObjects dao) throws IOException, SQLException {
   1.124          final var viewModel = new ProjectEditView();
   1.125 -        populate(viewModel, req, dao);
   1.126 +        populate(viewModel, pathParams, dao);
   1.127  
   1.128 -        final var project = Optional.ofNullable(viewModel.getProjectInfo())
   1.129 -                .map(ProjectInfo::getProject)
   1.130 -                .orElse(new Project(-1));
   1.131 -        configure(viewModel, project, dao);
   1.132 +        if (viewModel.getProjectInfo() == null) {
   1.133 +            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   1.134 +            return ResponseType.NONE;
   1.135 +        }
   1.136  
   1.137 +        configureProjectEditor(viewModel, viewModel.getProjectInfo().getProject(), dao);
   1.138 +        return forwardView(req, viewModel, "project-form");
   1.139 +    }
   1.140 +
   1.141 +    @RequestMapping(requestPath = "create", method = HttpMethod.GET)
   1.142 +    public ResponseType create(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
   1.143 +        final var viewModel = new ProjectEditView();
   1.144 +        populate(viewModel, null, dao);
   1.145 +        configureProjectEditor(viewModel, new Project(-1), dao);
   1.146          return forwardView(req, viewModel, "project-form");
   1.147      }
   1.148  
   1.149      @RequestMapping(requestPath = "commit", method = HttpMethod.POST)
   1.150 -    public ResponseType commit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
   1.151 +    public ResponseType commit(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException {
   1.152  
   1.153 -        Project project = new Project(-1);
   1.154          try {
   1.155 -            project = new Project(getParameter(req, Integer.class, "pid").orElseThrow());
   1.156 +            final var project = new Project(getParameter(req, Integer.class, "pid").orElseThrow());
   1.157              project.setName(getParameter(req, String.class, "name").orElseThrow());
   1.158              getParameter(req, String.class, "description").ifPresent(project::setDescription);
   1.159              getParameter(req, String.class, "repoUrl").ifPresent(project::setRepoUrl);
   1.160 @@ -187,30 +170,25 @@
   1.161  
   1.162              return ResponseType.HTML;
   1.163          } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
   1.164 -            LOG.warn("Form validation failure: {}", ex.getMessage());
   1.165 -            LOG.debug("Details:", ex);
   1.166 -            final var viewModel = new ProjectEditView();
   1.167 -            populate(viewModel, req, dao);
   1.168 -            configure(viewModel, project, dao);
   1.169 -            // TODO: error text
   1.170 -            return forwardView(req, viewModel, "project-form");
   1.171 +            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   1.172 +            // TODO: implement - fix issue #21
   1.173 +            return ResponseType.NONE;
   1.174          }
   1.175      }
   1.176  
   1.177 -    @RequestMapping(requestPath = "view", method = HttpMethod.GET)
   1.178 -    public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
   1.179 +    @RequestMapping(requestPath = "$project/versions/$version", method = HttpMethod.GET)
   1.180 +    public ResponseType view(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParams, DataAccessObjects dao) throws SQLException, IOException {
   1.181          final var viewModel = new ProjectDetailsView();
   1.182 -        populate(viewModel, req, dao);
   1.183 +        populate(viewModel, pathParams, dao);
   1.184 +        final var version = viewModel.getVersionFilter();
   1.185  
   1.186 -        if (viewModel.getProjectInfo() == null) {
   1.187 -            resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
   1.188 +        if (viewModel.getProjectInfo() == null || version == null) {
   1.189 +            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   1.190              return ResponseType.NONE;
   1.191          }
   1.192  
   1.193          final var issueDao = dao.getIssueDao();
   1.194  
   1.195 -        final var version = viewModel.getVersionFilter();
   1.196 -
   1.197          final var detailView = viewModel.getProjectDetails();
   1.198          final var issues = issueDao.list(version);
   1.199          for (var issue : issues) issueDao.joinVersionInformation(issue);
   1.200 @@ -224,15 +202,14 @@
   1.201          return forwardView(req, viewModel, "project-details");
   1.202      }
   1.203  
   1.204 -    @RequestMapping(requestPath = "versions", method = HttpMethod.GET)
   1.205 -    public ResponseType versions(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException {
   1.206 +    @RequestMapping(requestPath = "$project/versions/", method = HttpMethod.GET)
   1.207 +    public ResponseType versions(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DataAccessObjects dao) throws IOException, SQLException {
   1.208          final var viewModel = new VersionsView();
   1.209 -        populate(viewModel, req, dao);
   1.210 -        viewModel.setVersionFilter(null);
   1.211 +        populate(viewModel, pathParameters, dao);
   1.212  
   1.213          final var projectInfo = viewModel.getProjectInfo();
   1.214          if (projectInfo == null) {
   1.215 -            resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
   1.216 +            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   1.217              return ResponseType.NONE;
   1.218          }
   1.219  
   1.220 @@ -244,49 +221,60 @@
   1.221          return forwardView(req, viewModel, "versions");
   1.222      }
   1.223  
   1.224 -    @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET)
   1.225 -    public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException {
   1.226 +    @RequestMapping(requestPath = "$project/versions/$version/edit", method = HttpMethod.GET)
   1.227 +    public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DataAccessObjects dao) throws IOException, SQLException {
   1.228          final var viewModel = new VersionEditView();
   1.229 -        populate(viewModel, req, dao);
   1.230 +        populate(viewModel, pathParameters, dao);
   1.231  
   1.232 -        if (viewModel.getProjectInfo() == null) {
   1.233 -            resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
   1.234 +        if (viewModel.getProjectInfo() == null || viewModel.getVersionFilter() == null) {
   1.235 +            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   1.236              return ResponseType.NONE;
   1.237          }
   1.238  
   1.239 -        viewModel.setVersion(Optional.ofNullable(viewModel.getVersionFilter()).orElse(new Version(-1)));
   1.240 +        viewModel.setVersion(viewModel.getVersionFilter());
   1.241  
   1.242          return forwardView(req, viewModel, "version-form");
   1.243      }
   1.244  
   1.245 -    @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST)
   1.246 -    public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
   1.247 +    @RequestMapping(requestPath = "$project/create-version", method = HttpMethod.GET)
   1.248 +    public ResponseType createVersion(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DataAccessObjects dao) throws IOException, SQLException {
   1.249 +        final var viewModel = new VersionEditView();
   1.250 +        populate(viewModel, pathParameters, dao);
   1.251  
   1.252 -        var version = new Version(-1);
   1.253 +        if (viewModel.getProjectInfo() == null) {
   1.254 +            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   1.255 +            return ResponseType.NONE;
   1.256 +        }
   1.257 +
   1.258 +        viewModel.setVersion(viewModel.getVersionFilter());
   1.259 +
   1.260 +        return forwardView(req, viewModel, "version-form");
   1.261 +    }
   1.262 +
   1.263 +    @RequestMapping(requestPath = "commit-version", method = HttpMethod.POST)
   1.264 +    public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException {
   1.265 +
   1.266          try {
   1.267              final var project = new Project(getParameter(req, Integer.class, "pid").orElseThrow());
   1.268 -            version = new Version(getParameter(req, Integer.class, "id").orElseThrow());
   1.269 +            final var version = new Version(getParameter(req, Integer.class, "id").orElseThrow());
   1.270              version.setName(getParameter(req, String.class, "name").orElseThrow());
   1.271              getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal);
   1.272              version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow()));
   1.273              dao.getVersionDao().saveOrUpdate(version, project);
   1.274  
   1.275 -            setRedirectLocation(req, "./projects/versions?pid=" + project.getId());
   1.276 +            // TODO: improve building the redirect location
   1.277 +            setRedirectLocation(req, "./projects/" + project.getId() + "/versions/");
   1.278              setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   1.279          } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
   1.280 -            LOG.warn("Form validation failure: {}", ex.getMessage());
   1.281 -            LOG.debug("Details:", ex);
   1.282 -            final var viewModel = new VersionEditView();
   1.283 -            populate(viewModel, req, dao);
   1.284 -            viewModel.setVersion(version);
   1.285 -            // TODO: set Error Text
   1.286 -            return forwardView(req, viewModel, "version-form");
   1.287 +            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   1.288 +            // TODO: implement - fix issue #21
   1.289 +            return ResponseType.NONE;
   1.290          }
   1.291  
   1.292          return ResponseType.HTML;
   1.293      }
   1.294  
   1.295 -    private void configure(IssueEditView viewModel, Issue issue, DataAccessObjects dao) throws SQLException {
   1.296 +    private void configureProjectEditor(IssueEditView viewModel, Issue issue, DataAccessObjects dao) throws SQLException {
   1.297          issue.setProject(viewModel.getProjectInfo().getProject());
   1.298          viewModel.setIssue(issue);
   1.299          viewModel.configureVersionSelectors(viewModel.getProjectInfo().getVersions());
   1.300 @@ -296,30 +284,52 @@
   1.301          }
   1.302      }
   1.303  
   1.304 -    @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET)
   1.305 -    public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
   1.306 +    @RequestMapping(requestPath = "$project/issues/$issue/edit", method = HttpMethod.GET)
   1.307 +    public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DataAccessObjects dao) throws IOException, SQLException {
   1.308          final var viewModel = new IssueEditView();
   1.309 -        populate(viewModel, req, dao);
   1.310 +        populate(viewModel, pathParameters, dao);
   1.311  
   1.312 -        final var issueParam = getParameter(req, Integer.class, "issue");
   1.313 -        if (issueParam.isPresent()) {
   1.314 -            final var issueDao = dao.getIssueDao();
   1.315 -            final var issue = issueDao.find(issueParam.get());
   1.316 -            issueDao.joinVersionInformation(issue);
   1.317 -            req.getSession().setAttribute(SESSION_ATTR_SELECTED_PROJECT, issue.getProject().getId());
   1.318 -            configure(viewModel, issue, dao);
   1.319 -        } else {
   1.320 -            configure(viewModel, new Issue(-1), dao);
   1.321 +        final var projectInfo = viewModel.getProjectInfo();
   1.322 +        if (projectInfo == null) {
   1.323 +            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   1.324 +            return ResponseType.NONE;
   1.325          }
   1.326  
   1.327 +        final var issueDao = dao.getIssueDao();
   1.328 +        final var issue = issueDao.find(Functions.parseIntOrZero(pathParameters.get("issue")));
   1.329 +        if (issue == null) {
   1.330 +            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   1.331 +            return ResponseType.NONE;
   1.332 +        }
   1.333 +
   1.334 +        issueDao.joinVersionInformation(issue);
   1.335 +        configureProjectEditor(viewModel, issue, dao);
   1.336 +
   1.337          return forwardView(req, viewModel, "issue-form");
   1.338      }
   1.339  
   1.340 -    @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST)
   1.341 -    public ResponseType commitIssue(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
   1.342 -        Issue issue = new Issue(-1);
   1.343 +    @RequestMapping(requestPath = "$project/create-issue", method = HttpMethod.GET)
   1.344 +    public ResponseType createIssue(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DataAccessObjects dao) throws IOException, SQLException {
   1.345 +        final var viewModel = new IssueEditView();
   1.346 +        populate(viewModel, pathParameters, dao);
   1.347 +
   1.348 +        final var projectInfo = viewModel.getProjectInfo();
   1.349 +        if (projectInfo == null) {
   1.350 +            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
   1.351 +            return ResponseType.NONE;
   1.352 +        }
   1.353 +
   1.354 +        final var issue = new Issue(-1);
   1.355 +        issue.setProject(projectInfo.getProject());
   1.356 +        configureProjectEditor(viewModel, issue, dao);
   1.357 +
   1.358 +        return forwardView(req, viewModel, "issue-form");
   1.359 +    }
   1.360 +
   1.361 +    @RequestMapping(requestPath = "commit-issue", method = HttpMethod.POST)
   1.362 +    public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException {
   1.363          try {
   1.364 -            issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow());
   1.365 +            final var issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow());
   1.366              issue.setProject(new Project(getParameter(req, Integer.class, "pid").orElseThrow()));
   1.367              getParameter(req, String.class, "category").map(IssueCategory::valueOf).ifPresent(issue::setCategory);
   1.368              getParameter(req, String.class, "status").map(IssueStatus::valueOf).ifPresent(issue::setStatus);
   1.369 @@ -343,24 +353,19 @@
   1.370  
   1.371              dao.getIssueDao().saveOrUpdate(issue, issue.getProject());
   1.372  
   1.373 -            // specifying the issue parameter keeps the edited issue as menu item
   1.374 -            setRedirectLocation(req, "./projects/view?pid=" + issue.getProject().getId());
   1.375 +            // TODO: fix issue #14
   1.376 +            setRedirectLocation(req, "./projects/" + issue.getProject().getId() + "/versions/");
   1.377              setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   1.378  
   1.379              return ResponseType.HTML;
   1.380          } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
   1.381 -            // TODO: set request attribute with error text
   1.382 -            LOG.warn("Form validation failure: {}", ex.getMessage());
   1.383 -            LOG.debug("Details:", ex);
   1.384 -            final var viewModel = new IssueEditView();
   1.385 -            populate(viewModel, req, dao);
   1.386 -            configure(viewModel, issue, dao);
   1.387 -            // TODO: set Error Text
   1.388 -            return forwardView(req, viewModel, "issue-form");
   1.389 +            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   1.390 +            // TODO: implement - fix issue #21
   1.391 +            return ResponseType.NONE;
   1.392          }
   1.393      }
   1.394  
   1.395 -    @RequestMapping(requestPath = "issues/comment", method = HttpMethod.POST)
   1.396 +    @RequestMapping(requestPath = "commit-issue-comment", method = HttpMethod.POST)
   1.397      public ResponseType commentIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
   1.398          final var issueIdParam = getParameter(req, Integer.class, "issueid");
   1.399          if (issueIdParam.isEmpty()) {
   1.400 @@ -383,20 +388,15 @@
   1.401  
   1.402              dao.getIssueDao().saveComment(issueComment);
   1.403  
   1.404 -            // specifying the issue parameter keeps the edited issue as menu item
   1.405 -            setRedirectLocation(req, "./projects/issues/edit?issue=" + issue.getId());
   1.406 +            // TODO: fix redirect location (e.g. after fixing #24)
   1.407 +            setRedirectLocation(req, "./projects/" + issue.getProject().getId()+"/issues/"+issue.getId()+"/edit");
   1.408              setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   1.409  
   1.410              return ResponseType.HTML;
   1.411          } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
   1.412 -            // TODO: set request attribute with error text
   1.413 -            LOG.warn("Form validation failure: {}", ex.getMessage());
   1.414 -            LOG.debug("Details:", ex);
   1.415 -            final var viewModel = new IssueEditView();
   1.416 -            populate(viewModel, req, dao);
   1.417 -            configure(viewModel, issue, dao);
   1.418 -            // TODO: set Error Text
   1.419 -            return forwardView(req, viewModel, "issue-form");
   1.420 +            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
   1.421 +            // TODO: implement - fix issue #21
   1.422 +            return ResponseType.NONE;
   1.423          }
   1.424      }
   1.425  }

mercurial