Sun, 23 Aug 2020 15:10:49 +0200
cleanup ProjectsModule
1.1 --- a/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java Sat Aug 22 18:34:36 2020 +0200 1.2 +++ b/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java Sun Aug 23 15:10:49 2020 +0200 1.3 @@ -39,14 +39,13 @@ 1.4 import javax.servlet.annotation.WebServlet; 1.5 import javax.servlet.http.HttpServletRequest; 1.6 import javax.servlet.http.HttpServletResponse; 1.7 -import javax.servlet.http.HttpSession; 1.8 import java.io.IOException; 1.9 import java.sql.Date; 1.10 import java.sql.SQLException; 1.11 import java.util.ArrayList; 1.12 import java.util.List; 1.13 import java.util.NoSuchElementException; 1.14 -import java.util.Objects; 1.15 +import java.util.Optional; 1.16 import java.util.stream.Collectors; 1.17 import java.util.stream.Stream; 1.18 1.19 @@ -60,178 +59,43 @@ 1.20 1.21 private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class); 1.22 1.23 - public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project"); 1.24 - public static final String SESSION_ATTR_SELECTED_ISSUE = fqn(ProjectsModule.class, "selected_issue"); 1.25 - public static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected_version"); 1.26 - 1.27 - // TODO: try to get rid of this shit 1.28 - private class SessionSelection { 1.29 - final HttpSession session; 1.30 - final HttpServletRequest req; 1.31 - final DataAccessObjects dao; 1.32 - Project project; 1.33 - Version version; 1.34 - Issue issue; 1.35 - 1.36 - SessionSelection(HttpServletRequest req, DataAccessObjects dao) { 1.37 - this.req = req; 1.38 - this.dao = dao; 1.39 - session = req.getSession(); 1.40 - } 1.41 - 1.42 - void newProject() { 1.43 - project = null; 1.44 - version = null; 1.45 - issue = null; 1.46 - updateAttributes(); 1.47 - project = new Project(-1); 1.48 - updateAttributes(); 1.49 - } 1.50 - 1.51 - void newVersion() throws SQLException { 1.52 - project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT); 1.53 - syncProject(); 1.54 - version = null; 1.55 - issue = null; 1.56 - updateAttributes(); 1.57 - version = new Version(-1); 1.58 - version.setProject(project); 1.59 - updateAttributes(); 1.60 - } 1.61 - 1.62 - void newIssue() throws SQLException { 1.63 - project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT); 1.64 - syncProject(); 1.65 - version = null; 1.66 - issue = null; 1.67 - updateAttributes(); 1.68 - issue = new Issue(-1); 1.69 - issue.setProject(project); 1.70 - updateAttributes(); 1.71 - } 1.72 - 1.73 - void selectVersion(Version selectedVersion) throws SQLException { 1.74 - issue = null; 1.75 - version = selectedVersion; 1.76 - if (!version.getProject().equals(project)) { 1.77 - project = dao.getProjectDao().find(version.getProject().getId()); 1.78 - } 1.79 - // our object contains more details 1.80 - version.setProject(project); 1.81 - updateAttributes(); 1.82 - } 1.83 - 1.84 - void selectIssue(Issue selectedIssue) throws SQLException { 1.85 - issue = selectedIssue; 1.86 - if (!issue.getProject().equals(project)) { 1.87 - project = dao.getProjectDao().find(issue.getProject().getId()); 1.88 - } 1.89 - // our object contains more details 1.90 - issue.setProject(project); 1.91 - if (!issue.getResolvedVersions().contains(version) 1.92 - && !issue.getAffectedVersions().contains(version)) { 1.93 - version = null; 1.94 - } 1.95 - updateAttributes(); 1.96 - } 1.97 - 1.98 - void syncProject() throws SQLException { 1.99 - final var projectSelection = getParameter(req, Integer.class, "pid"); 1.100 - if (projectSelection.isPresent()) { 1.101 - final var selectedProject = dao.getProjectDao().find(projectSelection.get()); 1.102 - if (!Objects.equals(selectedProject, project)) { 1.103 - // reset version and issue if project changed 1.104 - version = null; 1.105 - issue = null; 1.106 - } 1.107 - project = selectedProject; 1.108 - } else { 1.109 - project = project == null ? null : dao.getProjectDao().find(project.getId()); 1.110 - } 1.111 - } 1.112 - 1.113 - void syncVersion() throws SQLException { 1.114 - final var versionSelection = getParameter(req, Integer.class, "vid"); 1.115 - if (versionSelection.isPresent()) { 1.116 - if (versionSelection.get() < 0) { 1.117 - version = null; 1.118 - } else { 1.119 - final var selectedVersion = dao.getVersionDao().find(versionSelection.get()); 1.120 - if (!Objects.equals(selectedVersion, version)) { 1.121 - issue = null; 1.122 - } 1.123 - selectVersion(selectedVersion); 1.124 - } 1.125 - } else { 1.126 - version = version == null ? null : dao.getVersionDao().find(version.getId()); 1.127 - } 1.128 - } 1.129 - 1.130 - void syncIssue() throws SQLException { 1.131 - final var issueSelection = getParameter(req, Integer.class, "issue"); 1.132 - if (issueSelection.isPresent()) { 1.133 - if (issueSelection.get() < 0) { 1.134 - issue = null; 1.135 - } else { 1.136 - final var selectedIssue = dao.getIssueDao().find(issueSelection.get()); 1.137 - dao.getIssueDao().joinVersionInformation(selectedIssue); 1.138 - selectIssue(selectedIssue); 1.139 - } 1.140 - } else { 1.141 - issue = issue == null ? null : dao.getIssueDao().find(issue.getId()); 1.142 - } 1.143 - } 1.144 - 1.145 - void sync() throws SQLException { 1.146 - project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT); 1.147 - version = (Version) session.getAttribute(SESSION_ATTR_SELECTED_VERSION); 1.148 - issue = (Issue) session.getAttribute(SESSION_ATTR_SELECTED_ISSUE); 1.149 - 1.150 - syncProject(); 1.151 - syncVersion(); 1.152 - syncIssue(); 1.153 - 1.154 - updateAttributes(); 1.155 - } 1.156 - 1.157 - private void updateAttributes() { 1.158 - session.setAttribute(SESSION_ATTR_SELECTED_PROJECT, project); 1.159 - session.setAttribute(SESSION_ATTR_SELECTED_VERSION, version); 1.160 - session.setAttribute(SESSION_ATTR_SELECTED_ISSUE, issue); 1.161 - } 1.162 - } 1.163 + private static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project"); 1.164 + private static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected_version"); 1.165 + private static final String PARAMETER_SELECTED_PROJECT = "pid"; 1.166 + private static final String PARAMETER_SELECTED_VERSION = "vid"; 1.167 1.168 @Override 1.169 protected String getResourceBundleName() { 1.170 return "localization.projects"; 1.171 } 1.172 1.173 - private String queryParams(Project p, Version v, Issue i) { 1.174 - return String.format("pid=%d&vid=%d&issue=%d", 1.175 + private String queryParams(Project p, Version v) { 1.176 + return String.format("pid=%d&vid=%d", 1.177 p == null ? -1 : p.getId(), 1.178 - v == null ? -1 : v.getId(), 1.179 - i == null ? -1 : i.getId() 1.180 + v == null ? -1 : v.getId() 1.181 ); 1.182 } 1.183 1.184 /** 1.185 * Creates the navigation menu. 1.186 * 1.187 - * @param projects the list of projects 1.188 - * @param selection the currently selected objects 1.189 - * @param projInfo info about the currently selected project or null 1.190 - * @return a dynamic navigation menu trying to display as many levels as possible 1.191 + * @param req the servlet request 1.192 + * @param viewModel the current view model 1.193 */ 1.194 - private List<MenuEntry> getNavMenu(List<Project> projects, SessionSelection selection, ProjectInfo projInfo) { 1.195 + private void setNavigationMenu(HttpServletRequest req, ProjectView viewModel) { 1.196 + final Project selectedProject = Optional.ofNullable(viewModel.getProjectInfo()).map(ProjectInfo::getProject).orElse(null); 1.197 + 1.198 final var navigation = new ArrayList<MenuEntry>(); 1.199 1.200 - for (Project proj : projects) { 1.201 + for (ProjectInfo plistInfo : viewModel.getProjectList()) { 1.202 + final var proj = plistInfo.getProject(); 1.203 final var projEntry = new MenuEntry( 1.204 proj.getName(), 1.205 - "projects/view?pid=" + proj.getId() 1.206 + "projects/view?" + queryParams(proj, null) 1.207 ); 1.208 navigation.add(projEntry); 1.209 - if (proj.equals(selection.project)) { 1.210 + if (proj.equals(selectedProject)) { 1.211 + final var projInfo = viewModel.getProjectInfo(); 1.212 projEntry.setActive(true); 1.213 1.214 // **************** 1.215 @@ -239,8 +103,8 @@ 1.216 // **************** 1.217 { 1.218 final var entry = new MenuEntry(1, 1.219 - new ResourceKey("localization.projects", "menu.versions"), 1.220 - "projects/view?" + queryParams(proj, null, null) 1.221 + new ResourceKey(getResourceBundleName(), "menu.versions"), 1.222 + "projects/view?" + queryParams(proj, null) 1.223 ); 1.224 navigation.add(entry); 1.225 } 1.226 @@ -248,19 +112,19 @@ 1.227 final var level2 = new ArrayList<MenuEntry>(); 1.228 { 1.229 final var entry = new MenuEntry( 1.230 - new ResourceKey("localization.projects", "filter.all"), 1.231 - "projects/view?" + queryParams(proj, null, null) 1.232 + new ResourceKey(getResourceBundleName(), "filter.all"), 1.233 + "projects/view?" + queryParams(proj, null) 1.234 ); 1.235 - if (selection.version == null) entry.setActive(true); 1.236 + if (viewModel.getVersionFilter() == null) entry.setActive(true); 1.237 level2.add(entry); 1.238 } 1.239 1.240 for (Version version : projInfo.getVersions()) { 1.241 final var entry = new MenuEntry( 1.242 version.getName(), 1.243 - "projects/versions/view?" + queryParams(proj, version, null) 1.244 + "projects/view?" + queryParams(proj, version) 1.245 ); 1.246 - if (version.equals(selection.version)) entry.setActive(true); 1.247 + if (version.equals(viewModel.getVersionFilter())) entry.setActive(true); 1.248 level2.add(entry); 1.249 } 1.250 1.251 @@ -269,69 +133,85 @@ 1.252 } 1.253 } 1.254 1.255 - return navigation; 1.256 + setNavigationMenu(req, navigation); 1.257 + } 1.258 + 1.259 + private int syncParamWithSession(HttpServletRequest req, String param, String attr) { 1.260 + final var session = req.getSession(); 1.261 + final var idParam = getParameter(req, Integer.class, param); 1.262 + final int id; 1.263 + if (idParam.isPresent()) { 1.264 + id = idParam.get(); 1.265 + session.setAttribute(attr, id); 1.266 + } else { 1.267 + id = Optional.ofNullable(session.getAttribute(attr)).map(x->(Integer)x).orElse(-1); 1.268 + } 1.269 + return id; 1.270 + } 1.271 + 1.272 + private void populate(ProjectView viewModel, HttpServletRequest req, DataAccessObjects dao) throws SQLException { 1.273 + final var projectDao = dao.getProjectDao(); 1.274 + final var versionDao = dao.getVersionDao(); 1.275 + 1.276 + projectDao.list().stream().map(ProjectInfo::new).forEach(viewModel.getProjectList()::add); 1.277 + 1.278 + // Select Project 1.279 + final int pid = syncParamWithSession(req, PARAMETER_SELECTED_PROJECT, SESSION_ATTR_SELECTED_PROJECT); 1.280 + if (pid >= 0) { 1.281 + final var project = projectDao.find(pid); 1.282 + final var info = new ProjectInfo(project); 1.283 + info.setVersions(versionDao.list(project)); 1.284 + info.setIssueSummary(projectDao.getIssueSummary(project)); 1.285 + viewModel.setProjectInfo(info); 1.286 + } 1.287 + 1.288 + // Select Version 1.289 + final int vid = syncParamWithSession(req, PARAMETER_SELECTED_VERSION, SESSION_ATTR_SELECTED_VERSION); 1.290 + if (vid >= 0) { 1.291 + viewModel.setVersionFilter(versionDao.find(vid)); 1.292 + } 1.293 + } 1.294 + 1.295 + private ResponseType forwardView(HttpServletRequest req, ProjectView viewModel, String name) { 1.296 + setViewModel(req, viewModel); 1.297 + setContentPage(req, name); 1.298 + setStylesheet(req, "projects"); 1.299 + setNavigationMenu(req, viewModel); 1.300 + return ResponseType.HTML; 1.301 } 1.302 1.303 @RequestMapping(method = HttpMethod.GET) 1.304 public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 1.305 - final var sessionSelection = new SessionSelection(req, dao); 1.306 - sessionSelection.sync(); 1.307 + final var viewModel = new ProjectView(); 1.308 + populate(viewModel, req, dao); 1.309 1.310 final var projectDao = dao.getProjectDao(); 1.311 final var versionDao = dao.getVersionDao(); 1.312 1.313 - final var projectList = projectDao.list(); 1.314 - 1.315 - final var viewModel = new ProjectIndexView(); 1.316 - for (var project : projectList) { 1.317 - final var info = new ProjectInfo(project); 1.318 - info.setVersions(versionDao.list(project)); 1.319 - info.setIssueSummary(projectDao.getIssueSummary(project)); 1.320 - viewModel.getProjects().add(info); 1.321 + for (var info : viewModel.getProjectList()) { 1.322 + info.setVersions(versionDao.list(info.getProject())); 1.323 + info.setIssueSummary(projectDao.getIssueSummary(info.getProject())); 1.324 } 1.325 1.326 - setViewModel(req, viewModel); 1.327 - setContentPage(req, "projects"); 1.328 - setStylesheet(req, "projects"); 1.329 - 1.330 - setNavigationMenu(req, getNavMenu(projectList, sessionSelection, currentProjectInfo(dao, sessionSelection.project))); 1.331 - 1.332 - return ResponseType.HTML; 1.333 + return forwardView(req, viewModel, "projects"); 1.334 } 1.335 1.336 - private ProjectInfo currentProjectInfo(DataAccessObjects dao, Project project) throws SQLException { 1.337 - if (project == null) return null; 1.338 - final var projectDao = dao.getProjectDao(); 1.339 - final var versionDao = dao.getVersionDao(); 1.340 - 1.341 - final var info = new ProjectInfo(project); 1.342 - info.setVersions(versionDao.list(project)); 1.343 - info.setIssueSummary(projectDao.getIssueSummary(project)); 1.344 - return info; 1.345 - } 1.346 - 1.347 - private ProjectEditView configureEditForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { 1.348 - final var viewModel = new ProjectEditView(); 1.349 - viewModel.setProject(selection.project); 1.350 + private void configure(ProjectEditView viewModel, Project project, DataAccessObjects dao) throws SQLException { 1.351 + viewModel.setProject(project); 1.352 viewModel.setUsers(dao.getUserDao().list()); 1.353 - setNavigationMenu(req, getNavMenu(dao.getProjectDao().list(), selection, currentProjectInfo(dao, selection.project))); 1.354 - setViewModel(req, viewModel); 1.355 - setContentPage(req, "project-form"); 1.356 - return viewModel; 1.357 } 1.358 1.359 @RequestMapping(requestPath = "edit", method = HttpMethod.GET) 1.360 public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 1.361 - final var selection = new SessionSelection(req, dao); 1.362 - if (getParameter(req, Integer.class, "pid").isEmpty()) { 1.363 - selection.newProject(); 1.364 - } else { 1.365 - selection.sync(); 1.366 - } 1.367 + final var viewModel = new ProjectEditView(); 1.368 + populate(viewModel, req, dao); 1.369 1.370 - configureEditForm(req, dao, selection); 1.371 + final var project = Optional.ofNullable(viewModel.getProjectInfo()) 1.372 + .map(ProjectInfo::getProject) 1.373 + .orElse(new Project(-1)); 1.374 + configure(viewModel, project, dao); 1.375 1.376 - return ResponseType.HTML; 1.377 + return forwardView(req, viewModel, "project-form"); 1.378 } 1.379 1.380 @RequestMapping(requestPath = "commit", method = HttpMethod.POST) 1.381 @@ -339,7 +219,7 @@ 1.382 1.383 Project project = new Project(-1); 1.384 try { 1.385 - project = new Project(getParameter(req, Integer.class, "id").orElseThrow()); 1.386 + project = new Project(getParameter(req, Integer.class, "pid").orElseThrow()); 1.387 project.setName(getParameter(req, String.class, "name").orElseThrow()); 1.388 getParameter(req, String.class, "description").ifPresent(project::setDescription); 1.389 getParameter(req, String.class, "repoUrl").ifPresent(project::setRepoUrl); 1.390 @@ -349,99 +229,61 @@ 1.391 1.392 dao.getProjectDao().saveOrUpdate(project); 1.393 1.394 - setRedirectLocation(req, "./projects/"); 1.395 + setRedirectLocation(req, "./projects/view?pid="+project.getId()); 1.396 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); 1.397 LOG.debug("Successfully updated project {}", project.getName()); 1.398 + 1.399 + return ResponseType.HTML; 1.400 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { 1.401 LOG.warn("Form validation failure: {}", ex.getMessage()); 1.402 LOG.debug("Details:", ex); 1.403 - final var selection = new SessionSelection(req, dao); 1.404 - selection.project = project; 1.405 - final var vm = configureEditForm(req, dao, selection); 1.406 - vm.setErrorText(ex.getMessage()); // TODO: error text 1.407 + final var viewModel = new ProjectEditView(); 1.408 + populate(viewModel, req, dao); 1.409 + configure(viewModel, project, dao); 1.410 + // TODO: error text 1.411 + return forwardView(req, viewModel, "project-form"); 1.412 } 1.413 - 1.414 - return ResponseType.HTML; 1.415 } 1.416 1.417 @RequestMapping(requestPath = "view", method = HttpMethod.GET) 1.418 public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { 1.419 - final var selection = new SessionSelection(req, dao); 1.420 - selection.sync(); 1.421 + final var viewModel = new ProjectDetailsView(); 1.422 + populate(viewModel, req, dao); 1.423 1.424 - if (selection.project == null) { 1.425 + if (viewModel.getProjectInfo() == null) { 1.426 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected."); 1.427 return ResponseType.NONE; 1.428 } 1.429 1.430 - final var projectDao = dao.getProjectDao(); 1.431 - final var versionDao = dao.getVersionDao(); 1.432 final var issueDao = dao.getIssueDao(); 1.433 1.434 - final var viewModel = new ProjectView(selection.project); 1.435 - final var issues = issueDao.list(selection.project); 1.436 + final var project = viewModel.getProjectInfo().getProject(); 1.437 + 1.438 + final var detailView = viewModel.getProjectDetails(); 1.439 + if (viewModel.getVersionFilter() != null) { 1.440 + detailView.updateVersionInfo(List.of(viewModel.getVersionFilter())); 1.441 + } else { 1.442 + detailView.updateVersionInfo(viewModel.getProjectInfo().getVersions()); 1.443 + } 1.444 + final var issues = issueDao.list(project); 1.445 for (var issue : issues) issueDao.joinVersionInformation(issue); 1.446 - viewModel.setIssues(issues); 1.447 - // TODO: fix duplicated selection of versions (projectInfo also contains these infos) 1.448 - viewModel.setVersions(versionDao.list(selection.project)); 1.449 - viewModel.updateVersionInfo(); 1.450 - setViewModel(req, viewModel); 1.451 + detailView.setIssues(issues); 1.452 1.453 - setNavigationMenu(req, getNavMenu(projectDao.list(), selection, currentProjectInfo(dao, selection.project))); 1.454 - setContentPage(req, "project-details"); 1.455 - setStylesheet(req, "projects"); 1.456 - 1.457 - return ResponseType.HTML; 1.458 - } 1.459 - 1.460 - @RequestMapping(requestPath = "versions/view", method = HttpMethod.GET) 1.461 - public ResponseType viewVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { 1.462 - final var selection = new SessionSelection(req, dao); 1.463 - selection.sync(); 1.464 - if (selection.version == null) { 1.465 - resp.sendError(HttpServletResponse.SC_NOT_FOUND); 1.466 - return ResponseType.NONE; 1.467 - } 1.468 - 1.469 - final var projectDao = dao.getProjectDao(); 1.470 - final var issueDao = dao.getIssueDao(); 1.471 - 1.472 - final var viewModel = new VersionView(selection.version); 1.473 - final var issues = issueDao.list(selection.version); 1.474 - for (var issue : issues) issueDao.joinVersionInformation(issue); 1.475 - viewModel.setIssues(issues); 1.476 - setViewModel(req, viewModel); 1.477 - 1.478 - setNavigationMenu(req, getNavMenu(projectDao.list(), selection, currentProjectInfo(dao, selection.project))); 1.479 - setContentPage(req, "version"); 1.480 - setStylesheet(req, "projects"); 1.481 - 1.482 - return ResponseType.HTML; 1.483 - } 1.484 - 1.485 - private VersionEditView configureEditVersionForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { 1.486 - final var viewModel = new VersionEditView(selection.version); 1.487 - if (selection.version.getProject() == null) { 1.488 - viewModel.setProjects(dao.getProjectDao().list()); 1.489 - } 1.490 - setViewModel(req, viewModel); 1.491 - setContentPage(req, "version-form"); 1.492 - setNavigationMenu(req, getNavMenu(dao.getProjectDao().list(), selection, currentProjectInfo(dao, selection.project))); 1.493 - return viewModel; 1.494 + return forwardView(req, viewModel, "project-details"); 1.495 } 1.496 1.497 @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET) 1.498 public ResponseType editVersion(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 1.499 - final var selection = new SessionSelection(req, dao); 1.500 - if (getParameter(req, Integer.class, "vid").isEmpty()) { 1.501 - selection.newVersion(); 1.502 + final var viewModel = new VersionEditView(); 1.503 + populate(viewModel, req, dao); 1.504 + 1.505 + if (viewModel.getVersionFilter() == null) { 1.506 + viewModel.setVersion(new Version(-1)); 1.507 } else { 1.508 - selection.sync(); 1.509 + viewModel.setVersion(viewModel.getVersionFilter()); 1.510 } 1.511 1.512 - configureEditVersionForm(req, dao, selection); 1.513 - 1.514 - return ResponseType.HTML; 1.515 + return forwardView(req, viewModel, "version-form"); 1.516 } 1.517 1.518 @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST) 1.519 @@ -462,77 +304,43 @@ 1.520 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { 1.521 LOG.warn("Form validation failure: {}", ex.getMessage()); 1.522 LOG.debug("Details:", ex); 1.523 - final var selection = new SessionSelection(req, dao); 1.524 - selection.selectVersion(version); 1.525 - final var viewModel = configureEditVersionForm(req, dao, selection); 1.526 + final var viewModel = new VersionEditView(); 1.527 + populate(viewModel, req, dao); 1.528 + viewModel.setVersion(version); 1.529 // TODO: set Error Text 1.530 + return forwardView(req, viewModel, "version-form"); 1.531 } 1.532 1.533 return ResponseType.HTML; 1.534 } 1.535 1.536 - private IssueEditView configureEditIssueForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { 1.537 - final var viewModel = new IssueEditView(selection.issue); 1.538 - 1.539 - if (selection.issue.getProject() == null) { 1.540 - viewModel.setProjects(dao.getProjectDao().list()); 1.541 - } else { 1.542 - viewModel.setVersions(dao.getVersionDao().list(selection.issue.getProject())); 1.543 - } 1.544 + private void configure(IssueEditView viewModel, Issue issue, DataAccessObjects dao) throws SQLException { 1.545 + issue.setProject(viewModel.getProjectInfo().getProject()); 1.546 + viewModel.setIssue(issue); 1.547 + viewModel.configureVersionSelectors(viewModel.getProjectInfo().getVersions()); 1.548 viewModel.setUsers(dao.getUserDao().list()); 1.549 - setViewModel(req, viewModel); 1.550 - 1.551 - setContentPage(req, "issue-form"); 1.552 - setNavigationMenu(req, getNavMenu(dao.getProjectDao().list(), selection, currentProjectInfo(dao, selection.project))); 1.553 - return viewModel; 1.554 - } 1.555 - 1.556 - @RequestMapping(requestPath = "issues/", method = HttpMethod.GET) 1.557 - public ResponseType issues(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { 1.558 - final var selection = new SessionSelection(req, dao); 1.559 - selection.sync(); 1.560 - if (selection.project == null) { 1.561 - resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected."); 1.562 - return ResponseType.NONE; 1.563 - } 1.564 - 1.565 - final var projectDao = dao.getProjectDao(); 1.566 - final var issueDao = dao.getIssueDao(); 1.567 - 1.568 - final var viewModel = new IssuesView(); 1.569 - viewModel.setProject(selection.project); 1.570 - if (selection.version == null) { 1.571 - viewModel.setIssues(issueDao.list(selection.project)); 1.572 - } else { 1.573 - viewModel.setVersion(selection.version); 1.574 - viewModel.setIssues(issueDao.list(selection.version)); 1.575 - } 1.576 - setViewModel(req, viewModel); 1.577 - 1.578 - setNavigationMenu(req, getNavMenu(projectDao.list(), selection, currentProjectInfo(dao, selection.project))); 1.579 - setContentPage(req, "issues"); 1.580 - setStylesheet(req, "projects"); 1.581 - 1.582 - return ResponseType.HTML; 1.583 } 1.584 1.585 @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET) 1.586 public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { 1.587 - final var selection = new SessionSelection(req, dao); 1.588 - if (getParameter(req, Integer.class, "issue").isEmpty()) { 1.589 - selection.newIssue(); 1.590 + final var viewModel = new IssueEditView(); 1.591 + 1.592 + final var issueParam = getParameter(req, Integer.class, "issue"); 1.593 + if (issueParam.isPresent()) { 1.594 + final var issue = dao.getIssueDao().find(issueParam.get()); 1.595 + req.getSession().setAttribute(SESSION_ATTR_SELECTED_PROJECT, issue.getProject().getId()); 1.596 + populate(viewModel, req, dao); 1.597 + configure(viewModel, issue, dao); 1.598 } else { 1.599 - selection.sync(); 1.600 + populate(viewModel, req, dao); 1.601 + configure(viewModel, new Issue(-1), dao); 1.602 } 1.603 1.604 - configureEditIssueForm(req, dao, selection); 1.605 - 1.606 - return ResponseType.HTML; 1.607 + return forwardView(req, viewModel, "issue-form"); 1.608 } 1.609 1.610 @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST) 1.611 public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { 1.612 - 1.613 Issue issue = new Issue(-1); 1.614 try { 1.615 issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow()); 1.616 @@ -560,16 +368,16 @@ 1.617 dao.getIssueDao().saveOrUpdate(issue); 1.618 1.619 // specifying the issue parameter keeps the edited issue as menu item 1.620 - setRedirectLocation(req, "./projects/issues/?issue=" + issue.getId()); 1.621 + setRedirectLocation(req, "./projects/view/?pid=" + issue.getProject().getId()); 1.622 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); 1.623 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { 1.624 // TODO: set request attribute with error text 1.625 LOG.warn("Form validation failure: {}", ex.getMessage()); 1.626 LOG.debug("Details:", ex); 1.627 - final var selection = new SessionSelection(req, dao); 1.628 - selection.selectIssue(issue); 1.629 - final var viewModel = configureEditIssueForm(req, dao, selection); 1.630 + final var viewModel = new IssueEditView(); 1.631 + configure(viewModel, issue, dao); 1.632 // TODO: set Error Text 1.633 + return forwardView(req, viewModel, "issue-form"); 1.634 } 1.635 1.636 return ResponseType.HTML;
2.1 --- a/src/main/java/de/uapcore/lightpit/viewmodel/IssueEditView.java Sat Aug 22 18:34:36 2020 +0200 2.2 +++ b/src/main/java/de/uapcore/lightpit/viewmodel/IssueEditView.java Sun Aug 23 15:10:49 2020 +0200 2.3 @@ -4,15 +4,15 @@ 2.4 2.5 import java.util.*; 2.6 2.7 -public class IssueEditView { 2.8 - private final Issue issue; 2.9 +public class IssueEditView extends ProjectView { 2.10 + private Issue issue; 2.11 2.12 private List<Project> projects = Collections.emptyList(); 2.13 private Set<Version> versionsUpcoming = new HashSet<>(); 2.14 private Set<Version> versionsRecent = new HashSet<>(); 2.15 private List<User> users; 2.16 2.17 - public IssueEditView(Issue issue) { 2.18 + public void setIssue(Issue issue) { 2.19 this.issue = issue; 2.20 } 2.21 2.22 @@ -36,7 +36,7 @@ 2.23 return versionsRecent; 2.24 } 2.25 2.26 - public void setVersions(List<Version> versions) { 2.27 + public void configureVersionSelectors(List<Version> versions) { 2.28 versionsRecent.clear(); 2.29 versionsUpcoming.clear(); 2.30 // keep the current selection, if any
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/main/java/de/uapcore/lightpit/viewmodel/ProjectDetails.java Sun Aug 23 15:10:49 2020 +0200 3.3 @@ -0,0 +1,57 @@ 3.4 +package de.uapcore.lightpit.viewmodel; 3.5 + 3.6 +import de.uapcore.lightpit.entities.Issue; 3.7 +import de.uapcore.lightpit.entities.IssueSummary; 3.8 +import de.uapcore.lightpit.entities.Version; 3.9 + 3.10 +import java.util.ArrayList; 3.11 +import java.util.Collection; 3.12 +import java.util.Collections; 3.13 +import java.util.List; 3.14 + 3.15 +public class ProjectDetails { 3.16 + 3.17 + private List<VersionInfo> versionInfos = Collections.emptyList(); 3.18 + 3.19 + private List<Issue> issues = Collections.emptyList(); 3.20 + private List<Issue> issuesWithoutVersion; 3.21 + private IssueSummary issuesWithoutVersionTotal; 3.22 + 3.23 + public List<Issue> getIssues() { 3.24 + return issues; 3.25 + } 3.26 + 3.27 + public void setIssues(List<Issue> issues) { 3.28 + this.issues = issues; 3.29 + issuesWithoutVersion = new ArrayList<>(); 3.30 + issuesWithoutVersionTotal = new IssueSummary(); 3.31 + for (Issue issue : issues) { 3.32 + // we want to list all issues that do not have a target version 3.33 + if (issue.getResolvedVersions().isEmpty()) { 3.34 + issuesWithoutVersion.add(issue); 3.35 + issuesWithoutVersionTotal.add(issue); 3.36 + } 3.37 + } 3.38 + } 3.39 + 3.40 + public void updateVersionInfo(Collection<Version> versions) { 3.41 + versionInfos = new ArrayList<>(); 3.42 + for (Version version : versions) { 3.43 + final var info = new VersionInfo(version); 3.44 + info.collectIssues(issues); 3.45 + versionInfos.add(info); 3.46 + } 3.47 + } 3.48 + 3.49 + public List<Issue> getIssuesWithoutVersion() { 3.50 + return issuesWithoutVersion; 3.51 + } 3.52 + 3.53 + public IssueSummary getIssuesWithoutVersionTotal() { 3.54 + return issuesWithoutVersionTotal; 3.55 + } 3.56 + 3.57 + public List<VersionInfo> getVersionInfos() { 3.58 + return versionInfos; 3.59 + } 3.60 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/main/java/de/uapcore/lightpit/viewmodel/ProjectDetailsView.java Sun Aug 23 15:10:49 2020 +0200 4.3 @@ -0,0 +1,10 @@ 4.4 +package de.uapcore.lightpit.viewmodel; 4.5 + 4.6 +public class ProjectDetailsView extends ProjectView { 4.7 + 4.8 + private final ProjectDetails projectDetails = new ProjectDetails(); 4.9 + 4.10 + public ProjectDetails getProjectDetails() { 4.11 + return projectDetails; 4.12 + } 4.13 +}
5.1 --- a/src/main/java/de/uapcore/lightpit/viewmodel/ProjectEditView.java Sat Aug 22 18:34:36 2020 +0200 5.2 +++ b/src/main/java/de/uapcore/lightpit/viewmodel/ProjectEditView.java Sun Aug 23 15:10:49 2020 +0200 5.3 @@ -5,7 +5,7 @@ 5.4 5.5 import java.util.List; 5.6 5.7 -public class ProjectEditView { 5.8 +public class ProjectEditView extends ProjectView { 5.9 5.10 private Project project; 5.11 private List<User> users;
6.1 --- a/src/main/java/de/uapcore/lightpit/viewmodel/ProjectIndexView.java Sat Aug 22 18:34:36 2020 +0200 6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 6.3 @@ -1,17 +0,0 @@ 6.4 -package de.uapcore.lightpit.viewmodel; 6.5 - 6.6 -import java.util.ArrayList; 6.7 -import java.util.List; 6.8 - 6.9 -public class ProjectIndexView { 6.10 - 6.11 - private List<ProjectInfo> projects = new ArrayList<>(); 6.12 - 6.13 - public List<ProjectInfo> getProjects() { 6.14 - return projects; 6.15 - } 6.16 - 6.17 - public void setProjects(List<ProjectInfo> projects) { 6.18 - this.projects = projects; 6.19 - } 6.20 -}
7.1 --- a/src/main/java/de/uapcore/lightpit/viewmodel/ProjectView.java Sat Aug 22 18:34:36 2020 +0200 7.2 +++ b/src/main/java/de/uapcore/lightpit/viewmodel/ProjectView.java Sun Aug 23 15:10:49 2020 +0200 7.3 @@ -1,82 +1,33 @@ 7.4 package de.uapcore.lightpit.viewmodel; 7.5 7.6 -import de.uapcore.lightpit.entities.Issue; 7.7 -import de.uapcore.lightpit.entities.IssueSummary; 7.8 -import de.uapcore.lightpit.entities.Project; 7.9 import de.uapcore.lightpit.entities.Version; 7.10 7.11 import java.util.ArrayList; 7.12 -import java.util.Collections; 7.13 import java.util.List; 7.14 7.15 public class ProjectView { 7.16 7.17 - private final Project project; 7.18 - private List<Version> versions = Collections.emptyList(); 7.19 - private List<Issue> issues = Collections.emptyList(); 7.20 + private final List<ProjectInfo> projectList = new ArrayList<>(); 7.21 + private ProjectInfo projectInfo; 7.22 + private Version versionFilter; 7.23 7.24 - private IssueSummary issuesTotal; 7.25 - private List<Issue> issuesWithoutVersion; 7.26 - private IssueSummary issuesWithoutVersionTotal; 7.27 - private List<VersionInfo> versionInfos = Collections.emptyList(); 7.28 - 7.29 - public ProjectView(Project project) { 7.30 - this.project = project; 7.31 + public List<ProjectInfo> getProjectList() { 7.32 + return projectList; 7.33 } 7.34 7.35 - public Project getProject() { 7.36 - return project; 7.37 + public ProjectInfo getProjectInfo() { 7.38 + return projectInfo; 7.39 } 7.40 7.41 - public List<Issue> getIssues() { 7.42 - return issues; 7.43 + public void setProjectInfo(ProjectInfo projectInfo) { 7.44 + this.projectInfo = projectInfo; 7.45 } 7.46 7.47 - public void setIssues(List<Issue> issues) { 7.48 - this.issues = issues; 7.49 - issuesTotal = new IssueSummary(); 7.50 - issuesWithoutVersion = new ArrayList<>(); 7.51 - issuesWithoutVersionTotal = new IssueSummary(); 7.52 - for (Issue issue : issues) { 7.53 - issuesTotal.add(issue); 7.54 - // we want to list all issues that do not have a target version 7.55 - if (issue.getResolvedVersions().isEmpty()) { 7.56 - issuesWithoutVersion.add(issue); 7.57 - issuesWithoutVersionTotal.add(issue); 7.58 - } 7.59 - } 7.60 + public Version getVersionFilter() { 7.61 + return versionFilter; 7.62 } 7.63 7.64 - public List<Version> getVersions() { 7.65 - return versions; 7.66 - } 7.67 - 7.68 - public void setVersions(List<Version> versions) { 7.69 - this.versions = versions; 7.70 - } 7.71 - 7.72 - public void updateVersionInfo() { 7.73 - versionInfos = new ArrayList<>(); 7.74 - for (Version version : versions) { 7.75 - final var info = new VersionInfo(version); 7.76 - info.collectIssues(issues); 7.77 - versionInfos.add(info); 7.78 - } 7.79 - } 7.80 - 7.81 - public IssueSummary getIssuesTotal() { 7.82 - return issuesTotal; 7.83 - } 7.84 - 7.85 - public List<Issue> getIssuesWithoutVersion() { 7.86 - return issuesWithoutVersion; 7.87 - } 7.88 - 7.89 - public IssueSummary getIssuesWithoutVersionTotal() { 7.90 - return issuesWithoutVersionTotal; 7.91 - } 7.92 - 7.93 - public List<VersionInfo> getVersionInfos() { 7.94 - return versionInfos; 7.95 + public void setVersionFilter(Version versionFilter) { 7.96 + this.versionFilter = versionFilter; 7.97 } 7.98 }
8.1 --- a/src/main/java/de/uapcore/lightpit/viewmodel/VersionEditView.java Sat Aug 22 18:34:36 2020 +0200 8.2 +++ b/src/main/java/de/uapcore/lightpit/viewmodel/VersionEditView.java Sun Aug 23 15:10:49 2020 +0200 8.3 @@ -1,18 +1,13 @@ 8.4 package de.uapcore.lightpit.viewmodel; 8.5 8.6 -import de.uapcore.lightpit.entities.Project; 8.7 import de.uapcore.lightpit.entities.Version; 8.8 import de.uapcore.lightpit.entities.VersionStatus; 8.9 8.10 -import java.util.Collections; 8.11 -import java.util.List; 8.12 - 8.13 -public class VersionEditView { 8.14 - private final Version version; 8.15 - private List<Project> projects = Collections.emptyList(); 8.16 +public class VersionEditView extends ProjectView { 8.17 + private Version version; 8.18 private String errorText; 8.19 8.20 - public VersionEditView(Version version) { 8.21 + public void setVersion(Version version) { 8.22 this.version = version; 8.23 } 8.24 8.25 @@ -20,14 +15,6 @@ 8.26 return version; 8.27 } 8.28 8.29 - public List<Project> getProjects() { 8.30 - return projects; 8.31 - } 8.32 - 8.33 - public void setProjects(List<Project> projects) { 8.34 - this.projects = projects; 8.35 - } 8.36 - 8.37 public VersionStatus[] getVersionStatus() { 8.38 return VersionStatus.values(); 8.39 }
9.1 --- a/src/main/java/de/uapcore/lightpit/viewmodel/VersionView.java Sat Aug 22 18:34:36 2020 +0200 9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 9.3 @@ -1,23 +0,0 @@ 9.4 -package de.uapcore.lightpit.viewmodel; 9.5 - 9.6 -import de.uapcore.lightpit.entities.Issue; 9.7 -import de.uapcore.lightpit.entities.Version; 9.8 - 9.9 -import java.util.List; 9.10 - 9.11 -public class VersionView { 9.12 - 9.13 - private final VersionInfo versionInfo; 9.14 - 9.15 - public VersionView(Version version) { 9.16 - this.versionInfo = new VersionInfo(version); 9.17 - } 9.18 - 9.19 - public VersionInfo getVersionInfo() { 9.20 - return versionInfo; 9.21 - } 9.22 - 9.23 - public void setIssues(List<Issue> issues) { 9.24 - versionInfo.collectIssues(issues); 9.25 - } 9.26 -}
10.1 --- a/src/main/resources/localization/projects.properties Sat Aug 22 18:34:36 2020 +0200 10.2 +++ b/src/main/resources/localization/projects.properties Sun Aug 23 15:10:49 2020 +0200 10.3 @@ -70,7 +70,7 @@ 10.4 version.status.Deprecated=Deprecated 10.5 10.6 10.7 -issue.without-version=Issues w/o Assigned Version 10.8 +issue.without-version=No Assigned Version 10.9 issue.project=Project 10.10 issue.subject=Subject 10.11 issue.description=Description
11.1 --- a/src/main/resources/localization/projects_de.properties Sat Aug 22 18:34:36 2020 +0200 11.2 +++ b/src/main/resources/localization/projects_de.properties Sun Aug 23 15:10:49 2020 +0200 11.3 @@ -69,7 +69,7 @@ 11.4 version.status.LTS=Langzeitsupport 11.5 version.status.Deprecated=Veraltet 11.6 11.7 -issue.without-version=Vorg\u00e4nge ohne Version 11.8 +issue.without-version=Keine Version zugeordnet 11.9 issue.project=Projekt 11.10 issue.subject=Thema 11.11 issue.description=Beschreibung
12.1 --- a/src/main/webapp/WEB-INF/jsp/issue-form.jsp Sat Aug 22 18:34:36 2020 +0200 12.2 +++ b/src/main/webapp/WEB-INF/jsp/issue-form.jsp Sun Aug 23 15:10:49 2020 +0200 12.3 @@ -148,7 +148,7 @@ 12.4 <input type="hidden" name="id" value="${issue.id}"/> 12.5 <c:choose> 12.6 <c:when test="${not empty issue.project}"> 12.7 - <c:set var="cancelUrl">./projects/issues/?pid=${issue.project.id}</c:set> 12.8 + <c:set var="cancelUrl">./projects/view?pid=${issue.project.id}</c:set> 12.9 </c:when> 12.10 <c:otherwise> 12.11 <c:set var="cancelUrl">./projects/</c:set>
13.1 --- a/src/main/webapp/WEB-INF/jsp/project-details.jsp Sat Aug 22 18:34:36 2020 +0200 13.2 +++ b/src/main/webapp/WEB-INF/jsp/project-details.jsp Sun Aug 23 15:10:49 2020 +0200 13.3 @@ -28,9 +28,9 @@ 13.4 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 13.5 <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 13.6 13.7 -<jsp:useBean id="viewmodel" type="de.uapcore.lightpit.viewmodel.ProjectView" scope="request" /> 13.8 +<jsp:useBean id="viewmodel" type="de.uapcore.lightpit.viewmodel.ProjectDetailsView" scope="request" /> 13.9 13.10 -<c:set var="project" scope="page" value="${viewmodel.project}"/> 13.11 +<c:set var="project" scope="page" value="${viewmodel.projectInfo.project}"/> 13.12 <%@include file="../jspf/project-header.jsp"%> 13.13 13.14 <div id="tool-area"> 13.15 @@ -40,27 +40,34 @@ 13.16 13.17 <h2><fmt:message key="progress" /></h2> 13.18 13.19 -<c:set var="summary" value="${viewmodel.issuesTotal}" /> 13.20 +<c:set var="summary" value="${viewmodel.projectInfo.issueSummary}" /> 13.21 <%@include file="../jspf/issue-summary.jsp"%> 13.22 13.23 <h2><fmt:message key="issue.without-version" /></h2> 13.24 13.25 -<c:set var="issues" value="${viewmodel.issuesWithoutVersion}"/> 13.26 -<c:set var="summary" value="${viewmodel.issuesWithoutVersionTotal}" /> 13.27 +<c:set var="issues" value="${viewmodel.projectDetails.issuesWithoutVersion}"/> 13.28 +<c:set var="summary" value="${viewmodel.projectDetails.issuesWithoutVersionTotal}" /> 13.29 <%@include file="../jspf/issue-summary.jsp"%> 13.30 <%@include file="../jspf/issue-list.jsp"%> 13.31 13.32 -<c:forEach var="versionInfo" items="${viewmodel.versionInfos}"> 13.33 +<c:forEach var="versionInfo" items="${viewmodel.projectDetails.versionInfos}"> 13.34 <h2> 13.35 <fmt:message key="version.label" /> <c:out value="${versionInfo.version.name}" /> - <fmt:message key="version.status.${versionInfo.version.status}"/> 13.36 - (<a href="./projects/versions/view?vid=${versionInfo.version.id}"><fmt:message key="version.open" /></a>) 13.37 </h2> 13.38 13.39 <h3><fmt:message key="issues.resolved"/> </h3> 13.40 <c:set var="summary" value="${versionInfo.resolvedTotal}"/> 13.41 + <%@include file="../jspf/issue-summary.jsp"%> 13.42 <c:set var="issues" value="${versionInfo.resolved}"/> 13.43 + <c:if test="${not empty issues}"> 13.44 + <%@include file="../jspf/issue-list.jsp"%> 13.45 + </c:if> 13.46 + 13.47 + <h3><fmt:message key="issues.reported"/> </h3> 13.48 + <c:set var="summary" value="${versionInfo.reportedTotal}"/> 13.49 <%@include file="../jspf/issue-summary.jsp"%> 13.50 + <c:set var="issues" value="${versionInfo.reported}"/> 13.51 <c:if test="${not empty issues}"> 13.52 - <%@include file="../jspf/issue-list.jsp"%> 13.53 + <%@include file="../jspf/issue-list.jsp"%> 13.54 </c:if> 13.55 </c:forEach> 13.56 \ No newline at end of file
14.1 --- a/src/main/webapp/WEB-INF/jsp/project-form.jsp Sat Aug 22 18:34:36 2020 +0200 14.2 +++ b/src/main/webapp/WEB-INF/jsp/project-form.jsp Sun Aug 23 15:10:49 2020 +0200 14.3 @@ -67,7 +67,7 @@ 14.4 <tfoot> 14.5 <tr> 14.6 <td colspan="2"> 14.7 - <input type="hidden" name="id" value="${project.id}"/> 14.8 + <input type="hidden" name="pid" value="${project.id}"/> 14.9 <a href="./projects/" class="button"> 14.10 <fmt:message bundle="${lightpit_bundle}" key="button.cancel"/> 14.11 </a>
15.1 --- a/src/main/webapp/WEB-INF/jsp/projects.jsp Sat Aug 22 18:34:36 2020 +0200 15.2 +++ b/src/main/webapp/WEB-INF/jsp/projects.jsp Sun Aug 23 15:10:49 2020 +0200 15.3 @@ -28,9 +28,9 @@ 15.4 <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 15.5 <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 15.6 15.7 -<jsp:useBean id="viewmodel" type="de.uapcore.lightpit.viewmodel.ProjectIndexView" scope="request"/> 15.8 +<jsp:useBean id="viewmodel" type="de.uapcore.lightpit.viewmodel.ProjectView" scope="request"/> 15.9 15.10 -<c:if test="${empty viewmodel.projects}"> 15.11 +<c:if test="${empty viewmodel.projectList}"> 15.12 <div class="info-box"> 15.13 <fmt:message key="no-projects"/> 15.14 </div> 15.15 @@ -40,7 +40,7 @@ 15.16 <a href="./projects/edit" class="button"><fmt:message key="button.create"/></a> 15.17 </div> 15.18 15.19 -<c:if test="${not empty viewmodel.projects}"> 15.20 +<c:if test="${not empty viewmodel.projectList}"> 15.21 <table id="project-list" class="datatable medskip"> 15.22 <colgroup> 15.23 <col> 15.24 @@ -65,7 +65,7 @@ 15.25 </tr> 15.26 </thead> 15.27 <tbody> 15.28 - <c:forEach var="projectInfo" items="${viewmodel.projects}"> 15.29 + <c:forEach var="projectInfo" items="${viewmodel.projectList}"> 15.30 <c:set var="project" scope="page" value="${projectInfo.project}"/> 15.31 <tr class="nowrap"> 15.32 <td style="width: 2em;"><a href="./projects/edit?pid=${project.id}">✎</a></td> 15.33 @@ -79,12 +79,12 @@ 15.34 </td> 15.35 <td class="hright"> 15.36 <c:if test="${not empty projectInfo.latestVersion}"> 15.37 - <a href="./projects/versions/view?vid=${projectInfo.latestVersion.id}"><c:out value="${projectInfo.latestVersion.name}"/></a> 15.38 + <a href="./projects/view?pid=${project.id}&vid=${projectInfo.latestVersion.id}"><c:out value="${projectInfo.latestVersion.name}"/></a> 15.39 </c:if> 15.40 </td> 15.41 <td class="hright"> 15.42 <c:if test="${not empty projectInfo.nextVersion}"> 15.43 - <a href="./projects/versions/view?vid=${projectInfo.nextVersion.id}"><c:out value="${projectInfo.nextVersion.name}"/></a> 15.44 + <a href="./projects/view?pid=${project.id}&vid=${projectInfo.nextVersion.id}"><c:out value="${projectInfo.nextVersion.name}"/></a> 15.45 </c:if> 15.46 </td> 15.47 <td class="hright">${projectInfo.issueSummary.open}</td>
16.1 --- a/src/main/webapp/WEB-INF/jsp/version-form.jsp Sat Aug 22 18:34:36 2020 +0200 16.2 +++ b/src/main/webapp/WEB-INF/jsp/version-form.jsp Sun Aug 23 15:10:49 2020 +0200 16.3 @@ -41,21 +41,8 @@ 16.4 <tr> 16.5 <th><fmt:message key="version.project"/></th> 16.6 <td> 16.7 - <c:choose> 16.8 - <c:when test="${not empty version.project}"> 16.9 - <c:out value="${version.project.name}" /> 16.10 - <input type="hidden" name="pid" value="${version.project.id}" /> 16.11 - </c:when> 16.12 - <c:otherwise> 16.13 - <select name="pid" required> 16.14 - <c:forEach var="project" items="${viewmodel.projects}"> 16.15 - <option value="${project.id}"> 16.16 - <c:out value="${project.name}" /> 16.17 - </option> 16.18 - </c:forEach> 16.19 - </select> 16.20 - </c:otherwise> 16.21 - </c:choose> 16.22 + <c:out value="${version.project.name}" /> 16.23 + <input type="hidden" name="pid" value="${version.project.id}" /> 16.24 </td> 16.25 </tr> 16.26 <tr> 16.27 @@ -85,15 +72,7 @@ 16.28 <tr> 16.29 <td colspan="2"> 16.30 <input type="hidden" name="id" value="${version.id}"/> 16.31 - <c:choose> 16.32 - <c:when test="${not empty version.project}"> 16.33 - <c:set var="cancelUrl">./projects/view?pid=${version.project.id}</c:set> 16.34 - </c:when> 16.35 - <c:otherwise> 16.36 - <c:set var="cancelUrl">./projects/</c:set> 16.37 - </c:otherwise> 16.38 - </c:choose> 16.39 - <a href="${cancelUrl}" class="button"> 16.40 + <a href="./projects/view?pid=${version.project.id}" class="button"> 16.41 <fmt:message bundle="${lightpit_bundle}" key="button.cancel"/> 16.42 </a> 16.43 <button type="submit"><fmt:message bundle="${lightpit_bundle}" key="button.okay"/></button>