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

Sun, 21 Jun 2020 11:38:16 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 21 Jun 2020 11:38:16 +0200
changeset 88
1438e5a22c55
parent 86
0a658e53177c
child 96
b7b685f31e39
permissions
-rw-r--r--

simplifies version overviews by removing "scheduled issues"

universe@41 1 /*
universe@41 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@41 3 *
universe@41 4 * Copyright 2018 Mike Becker. All rights reserved.
universe@41 5 *
universe@41 6 * Redistribution and use in source and binary forms, with or without
universe@41 7 * modification, are permitted provided that the following conditions are met:
universe@41 8 *
universe@41 9 * 1. Redistributions of source code must retain the above copyright
universe@41 10 * notice, this list of conditions and the following disclaimer.
universe@41 11 *
universe@41 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@41 13 * notice, this list of conditions and the following disclaimer in the
universe@41 14 * documentation and/or other materials provided with the distribution.
universe@41 15 *
universe@41 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@41 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@41 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@41 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@41 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@41 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@41 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@41 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@41 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@41 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@41 26 * POSSIBILITY OF SUCH DAMAGE.
universe@41 27 *
universe@41 28 */
universe@41 29 package de.uapcore.lightpit.modules;
universe@41 30
universe@41 31
universe@41 32 import de.uapcore.lightpit.*;
universe@41 33 import de.uapcore.lightpit.dao.DataAccessObjects;
universe@64 34 import de.uapcore.lightpit.entities.*;
universe@86 35 import de.uapcore.lightpit.viewmodel.*;
universe@59 36 import org.slf4j.Logger;
universe@59 37 import org.slf4j.LoggerFactory;
universe@41 38
universe@41 39 import javax.servlet.annotation.WebServlet;
universe@41 40 import javax.servlet.http.HttpServletRequest;
universe@59 41 import javax.servlet.http.HttpServletResponse;
universe@75 42 import javax.servlet.http.HttpSession;
universe@59 43 import java.io.IOException;
universe@75 44 import java.sql.Date;
universe@47 45 import java.sql.SQLException;
universe@86 46 import java.util.ArrayList;
universe@86 47 import java.util.List;
universe@86 48 import java.util.NoSuchElementException;
universe@86 49 import java.util.Objects;
universe@83 50 import java.util.stream.Collectors;
universe@83 51 import java.util.stream.Stream;
universe@41 52
universe@52 53 import static de.uapcore.lightpit.Functions.fqn;
universe@52 54
universe@41 55 @WebServlet(
universe@41 56 name = "ProjectsModule",
universe@41 57 urlPatterns = "/projects/*"
universe@41 58 )
universe@41 59 public final class ProjectsModule extends AbstractLightPITServlet {
universe@41 60
universe@59 61 private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class);
universe@59 62
universe@80 63 public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project");
universe@80 64 public static final String SESSION_ATTR_SELECTED_ISSUE = fqn(ProjectsModule.class, "selected_issue");
universe@80 65 public static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected_version");
universe@52 66
universe@75 67 private class SessionSelection {
universe@75 68 final HttpSession session;
universe@86 69 final HttpServletRequest req;
universe@86 70 final DataAccessObjects dao;
universe@75 71 Project project;
universe@75 72 Version version;
universe@75 73 Issue issue;
universe@75 74
universe@86 75 SessionSelection(HttpServletRequest req, DataAccessObjects dao) {
universe@86 76 this.req = req;
universe@86 77 this.dao = dao;
universe@86 78 session = req.getSession();
universe@86 79 }
universe@86 80
universe@86 81 void newProject() {
universe@86 82 project = null;
universe@75 83 version = null;
universe@75 84 issue = null;
universe@75 85 updateAttributes();
universe@86 86 project = new Project(-1);
universe@86 87 updateAttributes();
universe@64 88 }
universe@75 89
universe@86 90 void newVersion() throws SQLException {
universe@86 91 project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT);
universe@86 92 syncProject();
universe@86 93 version = null;
universe@86 94 issue = null;
universe@86 95 updateAttributes();
universe@86 96 version = new Version(-1);
universe@86 97 version.setProject(project);
universe@86 98 updateAttributes();
universe@86 99 }
universe@86 100
universe@86 101 void newIssue() throws SQLException {
universe@86 102 project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT);
universe@86 103 syncProject();
universe@86 104 version = null;
universe@86 105 issue = null;
universe@86 106 updateAttributes();
universe@86 107 issue = new Issue(-1);
universe@86 108 issue.setProject(project);
universe@86 109 updateAttributes();
universe@86 110 }
universe@86 111
universe@86 112 void selectVersion(Version selectedVersion) throws SQLException {
universe@86 113 issue = null;
universe@86 114 version = selectedVersion;
universe@86 115 if (!version.getProject().equals(project)) {
universe@86 116 project = dao.getProjectDao().find(version.getProject().getId());
universe@75 117 }
universe@86 118 // our object contains more details
universe@86 119 version.setProject(project);
universe@86 120 updateAttributes();
universe@86 121 }
universe@86 122
universe@86 123 void selectIssue(Issue selectedIssue) throws SQLException {
universe@86 124 issue = selectedIssue;
universe@86 125 if (!issue.getProject().equals(project)) {
universe@86 126 project = dao.getProjectDao().find(issue.getProject().getId());
universe@75 127 }
universe@86 128 // our object contains more details
universe@86 129 issue.setProject(project);
universe@88 130 if (!issue.getResolvedVersions().contains(version)
universe@86 131 && !issue.getAffectedVersions().contains(version)) {
universe@86 132 version = null;
universe@86 133 }
universe@86 134 updateAttributes();
universe@86 135 }
universe@75 136
universe@86 137 void syncProject() throws SQLException {
universe@75 138 final var projectSelection = getParameter(req, Integer.class, "pid");
universe@75 139 if (projectSelection.isPresent()) {
universe@86 140 final var selectedProject = dao.getProjectDao().find(projectSelection.get());
universe@75 141 if (!Objects.equals(selectedProject, project)) {
universe@75 142 // reset version and issue if project changed
universe@75 143 version = null;
universe@75 144 issue = null;
universe@75 145 }
universe@75 146 project = selectedProject;
universe@75 147 } else {
universe@86 148 project = project == null ? null : dao.getProjectDao().find(project.getId());
universe@75 149 }
universe@86 150 }
universe@86 151
universe@86 152 void syncVersion() throws SQLException {
universe@86 153 final var versionSelection = getParameter(req, Integer.class, "vid");
universe@86 154 if (versionSelection.isPresent()) {
universe@86 155 if (versionSelection.get() < 0) {
universe@86 156 version = null;
universe@86 157 } else {
universe@86 158 final var selectedVersion = dao.getVersionDao().find(versionSelection.get());
universe@86 159 if (!Objects.equals(selectedVersion, version)) {
universe@86 160 issue = null;
universe@86 161 }
universe@86 162 selectVersion(selectedVersion);
universe@86 163 }
universe@86 164 } else {
universe@86 165 version = version == null ? null : dao.getVersionDao().find(version.getId());
universe@86 166 }
universe@86 167 }
universe@86 168
universe@86 169 void syncIssue() throws SQLException {
universe@86 170 final var issueSelection = getParameter(req, Integer.class, "issue");
universe@86 171 if (issueSelection.isPresent()) {
universe@86 172 final var selectedIssue = dao.getIssueDao().find(issueSelection.get());
universe@86 173 dao.getIssueDao().joinVersionInformation(selectedIssue);
universe@86 174 selectIssue(selectedIssue);
universe@86 175 } else {
universe@86 176 issue = issue == null ? null : dao.getIssueDao().find(issue.getId());
universe@86 177 }
universe@86 178 }
universe@86 179
universe@86 180 void sync() throws SQLException {
universe@86 181 project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT);
universe@86 182 version = (Version) session.getAttribute(SESSION_ATTR_SELECTED_VERSION);
universe@86 183 issue = (Issue) session.getAttribute(SESSION_ATTR_SELECTED_ISSUE);
universe@86 184
universe@86 185 syncProject();
universe@86 186 syncVersion();
universe@86 187 syncIssue();
universe@86 188
universe@75 189 updateAttributes();
universe@75 190 }
universe@75 191
universe@86 192 private void updateAttributes() {
universe@75 193 session.setAttribute(SESSION_ATTR_SELECTED_PROJECT, project);
universe@75 194 session.setAttribute(SESSION_ATTR_SELECTED_VERSION, version);
universe@75 195 session.setAttribute(SESSION_ATTR_SELECTED_ISSUE, issue);
universe@75 196 }
universe@71 197 }
universe@71 198
universe@78 199 @Override
universe@78 200 protected String getResourceBundleName() {
universe@78 201 return "localization.projects";
universe@78 202 }
universe@71 203
universe@80 204
universe@80 205 private static final int BREADCRUMB_LEVEL_ROOT = 0;
universe@80 206 private static final int BREADCRUMB_LEVEL_PROJECT = 1;
universe@80 207 private static final int BREADCRUMB_LEVEL_VERSION = 2;
universe@80 208 private static final int BREADCRUMB_LEVEL_ISSUE_LIST = 3;
universe@80 209 private static final int BREADCRUMB_LEVEL_ISSUE = 4;
universe@80 210
universe@71 211 /**
universe@71 212 * Creates the breadcrumb menu.
universe@71 213 *
universe@80 214 * @param level the current active level (0: root, 1: project, 2: version, 3: issue list, 4: issue)
universe@86 215 * @param selection the currently selected objects
universe@71 216 * @return a dynamic breadcrumb menu trying to display as many levels as possible
universe@71 217 */
universe@86 218 private List<MenuEntry> getBreadcrumbs(int level, SessionSelection selection) {
universe@71 219 MenuEntry entry;
universe@71 220
universe@71 221 final var breadcrumbs = new ArrayList<MenuEntry>();
universe@79 222 entry = new MenuEntry(new ResourceKey("localization.lightpit", "menu.projects"),
universe@79 223 "projects/");
universe@71 224 breadcrumbs.add(entry);
universe@80 225 if (level == BREADCRUMB_LEVEL_ROOT) entry.setActive(true);
universe@71 226
universe@86 227 if (selection.project != null) {
universe@86 228 if (selection.project.getId() < 0) {
universe@75 229 entry = new MenuEntry(new ResourceKey("localization.projects", "button.create"),
universe@79 230 "projects/edit");
universe@75 231 } else {
universe@86 232 entry = new MenuEntry(selection.project.getName(),
universe@86 233 "projects/view?pid=" + selection.project.getId());
universe@75 234 }
universe@80 235 if (level == BREADCRUMB_LEVEL_PROJECT) entry.setActive(true);
universe@75 236 breadcrumbs.add(entry);
universe@75 237 }
universe@71 238
universe@86 239 if (selection.version != null) {
universe@86 240 if (selection.version.getId() < 0) {
universe@75 241 entry = new MenuEntry(new ResourceKey("localization.projects", "button.version.create"),
universe@79 242 "projects/versions/edit");
universe@75 243 } else {
universe@86 244 entry = new MenuEntry(selection.version.getName(),
universe@86 245 "projects/versions/view?vid=" + selection.version.getId());
universe@75 246 }
universe@80 247 if (level == BREADCRUMB_LEVEL_VERSION) entry.setActive(true);
universe@80 248 breadcrumbs.add(entry);
universe@80 249 }
universe@80 250
universe@86 251 if (selection.project != null) {
universe@86 252 String path = "projects/issues/?pid=" + selection.project.getId();
universe@86 253 if (selection.version != null) {
universe@86 254 path += "&vid="+selection.version.getId();
universe@86 255 }
universe@80 256 entry = new MenuEntry(new ResourceKey("localization.projects", "menu.issues"),
universe@86 257 path);
universe@80 258 if (level == BREADCRUMB_LEVEL_ISSUE_LIST) entry.setActive(true);
universe@75 259 breadcrumbs.add(entry);
universe@75 260 }
universe@71 261
universe@86 262 if (selection.issue != null) {
universe@86 263 if (selection.issue.getId() < 0) {
universe@75 264 entry = new MenuEntry(new ResourceKey("localization.projects", "button.issue.create"),
universe@79 265 "projects/issues/edit");
universe@75 266 } else {
universe@86 267 entry = new MenuEntry("#" + selection.issue.getId(),
universe@75 268 // TODO: maybe change link to a view rather than directly opening the editor
universe@86 269 "projects/issues/edit?issue=" + selection.issue.getId());
universe@75 270 }
universe@80 271 if (level == BREADCRUMB_LEVEL_ISSUE) entry.setActive(true);
universe@75 272 breadcrumbs.add(entry);
universe@75 273 }
universe@75 274
universe@71 275 return breadcrumbs;
universe@64 276 }
universe@64 277
universe@61 278 @RequestMapping(method = HttpMethod.GET)
universe@47 279 public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
universe@75 280 final var sessionSelection = new SessionSelection(req, dao);
universe@86 281 sessionSelection.sync();
universe@86 282
universe@86 283 final var projectDao = dao.getProjectDao();
universe@86 284 final var versionDao = dao.getVersionDao();
universe@86 285
universe@86 286 final var projectList = projectDao.list();
universe@86 287
universe@86 288 final var viewModel = new ProjectIndexView();
universe@86 289 for (var project : projectList) {
universe@86 290 final var info = new ProjectInfo(project);
universe@86 291 info.setVersions(versionDao.list(project));
universe@86 292 info.setIssueSummary(projectDao.getIssueSummary(project));
universe@86 293 viewModel.getProjects().add(info);
universe@86 294 }
universe@86 295
universe@86 296 setViewModel(req, viewModel);
universe@74 297 setContentPage(req, "projects");
universe@52 298 setStylesheet(req, "projects");
universe@52 299
universe@80 300 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ROOT, sessionSelection));
universe@45 301
universe@45 302 return ResponseType.HTML;
universe@45 303 }
universe@45 304
universe@86 305 private ProjectEditView configureEditForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException {
universe@86 306 final var viewModel = new ProjectEditView();
universe@86 307 viewModel.setProject(selection.project);
universe@86 308 viewModel.setUsers(dao.getUserDao().list());
universe@86 309 setViewModel(req, viewModel);
universe@74 310 setContentPage(req, "project-form");
universe@80 311 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_PROJECT, selection));
universe@86 312 return viewModel;
universe@71 313 }
universe@71 314
universe@47 315 @RequestMapping(requestPath = "edit", method = HttpMethod.GET)
universe@51 316 public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
universe@86 317 final var selection = new SessionSelection(req, dao);
universe@86 318 if (getParameter(req, Integer.class, "pid").isEmpty()) {
universe@86 319 selection.newProject();
universe@86 320 } else {
universe@86 321 selection.sync();
universe@86 322 }
universe@47 323
universe@75 324 configureEditForm(req, dao, selection);
universe@47 325
universe@47 326 return ResponseType.HTML;
universe@47 327 }
universe@47 328
universe@47 329 @RequestMapping(requestPath = "commit", method = HttpMethod.POST)
universe@68 330 public ResponseType commit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
universe@47 331
universe@75 332 Project project = new Project(-1);
universe@47 333 try {
universe@47 334 project = new Project(getParameter(req, Integer.class, "id").orElseThrow());
universe@47 335 project.setName(getParameter(req, String.class, "name").orElseThrow());
universe@47 336 getParameter(req, String.class, "description").ifPresent(project::setDescription);
universe@47 337 getParameter(req, String.class, "repoUrl").ifPresent(project::setRepoUrl);
universe@47 338 getParameter(req, Integer.class, "owner").map(
universe@47 339 ownerId -> ownerId >= 0 ? new User(ownerId) : null
universe@47 340 ).ifPresent(project::setOwner);
universe@47 341
universe@47 342 dao.getProjectDao().saveOrUpdate(project);
universe@47 343
universe@70 344 setRedirectLocation(req, "./projects/");
universe@74 345 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
universe@59 346 LOG.debug("Successfully updated project {}", project.getName());
universe@75 347 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
universe@59 348 LOG.warn("Form validation failure: {}", ex.getMessage());
universe@59 349 LOG.debug("Details:", ex);
universe@86 350 final var selection = new SessionSelection(req, dao);
universe@86 351 selection.project = project;
universe@86 352 final var vm = configureEditForm(req, dao, selection);
universe@86 353 vm.setErrorText(ex.getMessage()); // TODO: error text
universe@47 354 }
universe@47 355
universe@47 356 return ResponseType.HTML;
universe@47 357 }
universe@47 358
universe@70 359 @RequestMapping(requestPath = "view", method = HttpMethod.GET)
universe@80 360 public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
universe@86 361 final var selection = new SessionSelection(req, dao);
universe@86 362 selection.sync();
universe@86 363
universe@86 364 if (selection.project == null) {
universe@80 365 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
universe@80 366 return ResponseType.NONE;
universe@80 367 }
universe@47 368
universe@80 369 final var versionDao = dao.getVersionDao();
universe@86 370 final var issueDao = dao.getIssueDao();
universe@70 371
universe@86 372 final var viewModel = new ProjectView(selection.project);
universe@86 373 final var issues = issueDao.list(selection.project);
universe@86 374 for (var issue : issues) issueDao.joinVersionInformation(issue);
universe@86 375 viewModel.setIssues(issues);
universe@86 376 viewModel.setVersions(versionDao.list(selection.project));
universe@86 377 viewModel.updateVersionInfo();
universe@86 378 setViewModel(req, viewModel);
universe@80 379
universe@86 380 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_PROJECT, selection));
universe@74 381 setContentPage(req, "project-details");
universe@80 382 setStylesheet(req, "projects");
universe@59 383
universe@59 384 return ResponseType.HTML;
universe@59 385 }
universe@59 386
universe@86 387 @RequestMapping(requestPath = "versions/view", method = HttpMethod.GET)
universe@86 388 public ResponseType viewVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
universe@86 389 final var selection = new SessionSelection(req, dao);
universe@86 390 selection.sync();
universe@86 391 if (selection.version == null) {
universe@86 392 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
universe@86 393 return ResponseType.NONE;
universe@86 394 }
universe@71 395
universe@86 396 final var issueDao = dao.getIssueDao();
universe@86 397 final var viewModel = new VersionView(selection.version);
universe@86 398 final var issues = issueDao.list(selection.version);
universe@86 399 for (var issue : issues) issueDao.joinVersionInformation(issue);
universe@86 400 viewModel.setIssues(issues);
universe@86 401 setViewModel(req, viewModel);
universe@80 402
universe@86 403 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_VERSION, selection));
universe@86 404 setContentPage(req, "version");
universe@86 405 setStylesheet(req, "projects");
universe@86 406
universe@86 407 return ResponseType.HTML;
universe@86 408 }
universe@86 409
universe@86 410 private VersionEditView configureEditVersionForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException {
universe@86 411 final var viewModel = new VersionEditView(selection.version);
universe@86 412 if (selection.version.getProject() == null) {
universe@86 413 viewModel.setProjects(dao.getProjectDao().list());
universe@86 414 }
universe@86 415 setViewModel(req, viewModel);
universe@74 416 setContentPage(req, "version-form");
universe@80 417 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_VERSION, selection));
universe@86 418 return viewModel;
universe@71 419 }
universe@71 420
universe@59 421 @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET)
universe@86 422 public ResponseType editVersion(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
universe@86 423 final var selection = new SessionSelection(req, dao);
universe@86 424 if (getParameter(req, Integer.class, "vid").isEmpty()) {
universe@86 425 selection.newVersion();
universe@86 426 } else {
universe@86 427 selection.sync();
universe@86 428 }
universe@59 429
universe@86 430 configureEditVersionForm(req, dao, selection);
universe@59 431
universe@59 432 return ResponseType.HTML;
universe@59 433 }
universe@59 434
universe@59 435 @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST)
universe@80 436 public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
universe@59 437
universe@86 438 var version = new Version(-1);
universe@59 439 try {
universe@86 440 version = new Version(getParameter(req, Integer.class, "id").orElseThrow());
universe@86 441 version.setProject(new Project(getParameter(req, Integer.class, "pid").orElseThrow()));
universe@59 442 version.setName(getParameter(req, String.class, "name").orElseThrow());
universe@59 443 getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal);
universe@59 444 version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow()));
universe@59 445 dao.getVersionDao().saveOrUpdate(version);
universe@59 446
universe@75 447 // specifying the pid parameter will purposely reset the session selected version!
universe@86 448 setRedirectLocation(req, "./projects/view?pid="+version.getProject().getId());
universe@74 449 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
universe@75 450 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
universe@59 451 LOG.warn("Form validation failure: {}", ex.getMessage());
universe@59 452 LOG.debug("Details:", ex);
universe@86 453 final var selection = new SessionSelection(req, dao);
universe@86 454 selection.selectVersion(version);
universe@86 455 final var viewModel = configureEditVersionForm(req, dao, selection);
universe@86 456 // TODO: set Error Text
universe@59 457 }
universe@41 458
universe@43 459 return ResponseType.HTML;
universe@41 460 }
universe@64 461
universe@86 462 private IssueEditView configureEditIssueForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException {
universe@86 463 final var viewModel = new IssueEditView(selection.issue);
universe@83 464
universe@86 465 if (selection.issue.getProject() == null) {
universe@86 466 viewModel.setProjects(dao.getProjectDao().list());
universe@83 467 } else {
universe@86 468 viewModel.setVersions(dao.getVersionDao().list(selection.issue.getProject()));
universe@83 469 }
universe@86 470 viewModel.setUsers(dao.getUserDao().list());
universe@86 471 setViewModel(req, viewModel);
universe@71 472
universe@74 473 setContentPage(req, "issue-form");
universe@80 474 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ISSUE, selection));
universe@86 475 return viewModel;
universe@80 476 }
universe@80 477
universe@80 478 @RequestMapping(requestPath = "issues/", method = HttpMethod.GET)
universe@80 479 public ResponseType issues(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
universe@86 480 final var selection = new SessionSelection(req, dao);
universe@86 481 selection.sync();
universe@86 482 if (selection.project == null) {
universe@80 483 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
universe@80 484 return ResponseType.NONE;
universe@80 485 }
universe@80 486
universe@86 487 final var viewModel = new IssuesView();
universe@86 488 viewModel.setProject(selection.project);
universe@86 489 if (selection.version == null) {
universe@86 490 viewModel.setIssues(dao.getIssueDao().list(selection.project));
universe@86 491 } else {
universe@86 492 viewModel.setVersion(selection.version);
universe@86 493 viewModel.setIssues(dao.getIssueDao().list(selection.version));
universe@86 494 }
universe@86 495 setViewModel(req, viewModel);
universe@80 496
universe@86 497 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ISSUE_LIST, selection));
universe@80 498 setContentPage(req, "issues");
universe@80 499 setStylesheet(req, "projects");
universe@80 500
universe@80 501 return ResponseType.HTML;
universe@71 502 }
universe@71 503
universe@64 504 @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET)
universe@80 505 public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
universe@86 506 final var selection = new SessionSelection(req, dao);
universe@86 507 if (getParameter(req, Integer.class, "issue").isEmpty()) {
universe@86 508 selection.newIssue();
universe@86 509 } else {
universe@86 510 selection.sync();
universe@86 511 }
universe@64 512
universe@86 513 configureEditIssueForm(req, dao, selection);
universe@64 514
universe@64 515 return ResponseType.HTML;
universe@64 516 }
universe@64 517
universe@64 518 @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST)
universe@80 519 public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
universe@64 520
universe@86 521 Issue issue = new Issue(-1);
universe@64 522 try {
universe@86 523 issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow());
universe@86 524 issue.setProject(new Project(getParameter(req, Integer.class, "pid").orElseThrow()));
universe@75 525 getParameter(req, String.class, "category").map(IssueCategory::valueOf).ifPresent(issue::setCategory);
universe@75 526 getParameter(req, String.class, "status").map(IssueStatus::valueOf).ifPresent(issue::setStatus);
universe@75 527 issue.setSubject(getParameter(req, String.class, "subject").orElseThrow());
universe@75 528 getParameter(req, Integer.class, "assignee").map(
universe@75 529 userid -> userid >= 0 ? new User(userid) : null
universe@75 530 ).ifPresent(issue::setAssignee);
universe@75 531 getParameter(req, String.class, "description").ifPresent(issue::setDescription);
universe@75 532 getParameter(req, Date.class, "eta").ifPresent(issue::setEta);
universe@83 533
universe@83 534 getParameter(req, Integer[].class, "affected")
universe@83 535 .map(Stream::of)
universe@83 536 .map(stream ->
universe@86 537 stream.map(Version::new).collect(Collectors.toList())
universe@83 538 ).ifPresent(issue::setAffectedVersions);
universe@83 539 getParameter(req, Integer[].class, "resolved")
universe@83 540 .map(Stream::of)
universe@83 541 .map(stream ->
universe@86 542 stream.map(Version::new).collect(Collectors.toList())
universe@83 543 ).ifPresent(issue::setResolvedVersions);
universe@83 544
universe@64 545 dao.getIssueDao().saveOrUpdate(issue);
universe@64 546
universe@75 547 // specifying the issue parameter keeps the edited issue as breadcrumb
universe@81 548 setRedirectLocation(req, "./projects/issues/?issue="+issue.getId());
universe@74 549 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
universe@75 550 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
universe@64 551 // TODO: set request attribute with error text
universe@64 552 LOG.warn("Form validation failure: {}", ex.getMessage());
universe@64 553 LOG.debug("Details:", ex);
universe@86 554 final var selection = new SessionSelection(req, dao);
universe@86 555 selection.selectIssue(issue);
universe@86 556 final var viewModel = configureEditIssueForm(req, dao, selection);
universe@86 557 // TODO: set Error Text
universe@64 558 }
universe@64 559
universe@64 560 return ResponseType.HTML;
universe@64 561 }
universe@41 562 }

mercurial