1.1 --- a/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java Tue May 19 19:34:57 2020 +0200 1.2 +++ b/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java Fri May 22 16:21:31 2020 +0200 1.3 @@ -40,7 +40,10 @@ 1.4 import javax.servlet.http.HttpServletResponse; 1.5 import java.io.IOException; 1.6 import java.sql.SQLException; 1.7 +import java.util.ArrayList; 1.8 +import java.util.List; 1.9 import java.util.NoSuchElementException; 1.10 +import java.util.Optional; 1.11 1.12 import static de.uapcore.lightpit.Functions.fqn; 1.13 1.14 @@ -63,14 +66,44 @@ 1.15 final var projectDao = dao.getProjectDao(); 1.16 final var session = req.getSession(); 1.17 final var projectSelection = getParameter(req, Integer.class, "pid"); 1.18 + final Project selectedProject; 1.19 if (projectSelection.isPresent()) { 1.20 - final var selectedId = projectSelection.get(); 1.21 - final var selectedProject = projectDao.find(selectedId); 1.22 - session.setAttribute(SESSION_ATTR_SELECTED_PROJECT, selectedProject); 1.23 - return selectedProject; 1.24 + selectedProject = projectDao.find(projectSelection.get()); 1.25 } else { 1.26 - return (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT); 1.27 + final var sessionProject = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT); 1.28 + selectedProject = sessionProject == null ? null : projectDao.find(sessionProject.getId()); 1.29 } 1.30 + session.setAttribute(SESSION_ATTR_SELECTED_PROJECT, selectedProject); 1.31 + return selectedProject; 1.32 + } 1.33 + 1.34 + 1.35 + /** 1.36 + * Creates the breadcrumb menu. 1.37 + * 1.38 + * @param level the current active level 1.39 + * @param selectedProject the selected project, if any, or null 1.40 + * @return a dynamic breadcrumb menu trying to display as many levels as possible 1.41 + */ 1.42 + private List<MenuEntry> getBreadcrumbs(int level, 1.43 + Project selectedProject) { 1.44 + MenuEntry entry; 1.45 + 1.46 + final var breadcrumbs = new ArrayList<MenuEntry>(); 1.47 + entry = new MenuEntry(new ResourceKey("localization.projects", "menuLabel"), 1.48 + "projects/", 0); 1.49 + breadcrumbs.add(entry); 1.50 + if (level == 0) entry.setActive(true); 1.51 + 1.52 + if (selectedProject == null) 1.53 + return breadcrumbs; 1.54 + 1.55 + entry = new MenuEntry(selectedProject.getName(), 1.56 + "projects/view?pid=" + selectedProject.getId(), 1); 1.57 + if (level == 1) entry.setActive(true); 1.58 + 1.59 + breadcrumbs.add(entry); 1.60 + return breadcrumbs; 1.61 } 1.62 1.63 @RequestMapping(method = HttpMethod.GET) 1.64 @@ -81,20 +114,33 @@ 1.65 setDynamicFragment(req, "projects"); 1.66 setStylesheet(req, "projects"); 1.67 1.68 - if (getSelectedProject(req, dao) == null) { 1.69 - projectList.stream().findFirst().ifPresent(proj -> req.getSession().setAttribute(SESSION_ATTR_SELECTED_PROJECT, proj)); 1.70 - } 1.71 + final var selectedProject = getSelectedProject(req, dao); 1.72 + setBreadcrumbs(req, getBreadcrumbs(0, selectedProject)); 1.73 1.74 return ResponseType.HTML; 1.75 } 1.76 1.77 + private void configureEditForm(HttpServletRequest req, DataAccessObjects dao, Optional<Project> project) throws SQLException { 1.78 + if (project.isPresent()) { 1.79 + req.setAttribute("project", project.get()); 1.80 + setBreadcrumbs(req, getBreadcrumbs(1, project.get())); 1.81 + } else { 1.82 + req.setAttribute("project", new Project(-1)); 1.83 + setBreadcrumbs(req, getBreadcrumbs(0, null)); 1.84 + } 1.85 + 1.86 + req.setAttribute("users", dao.getUserDao().list()); 1.87 + setDynamicFragment(req, "project-form"); 1.88 + } 1.89 + 1.90 @RequestMapping(requestPath = "edit", method = HttpMethod.GET) 1.91 public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 1.92 - req.setAttribute("project", findByParameter(req, Integer.class, "id", 1.93 - dao.getProjectDao()::find).orElse(new Project(-1))); 1.94 - req.setAttribute("users", dao.getUserDao().list()); 1.95 1.96 - setDynamicFragment(req, "project-form"); 1.97 + Optional<Project> project = findByParameter(req, Integer.class, "id", dao.getProjectDao()::find); 1.98 + configureEditForm(req, dao, project); 1.99 + if (project.isPresent()) { 1.100 + req.getSession().setAttribute(SESSION_ATTR_SELECTED_PROJECT, project.get()); 1.101 + } 1.102 1.103 return ResponseType.HTML; 1.104 } 1.105 @@ -102,7 +148,7 @@ 1.106 @RequestMapping(requestPath = "commit", method = HttpMethod.POST) 1.107 public ResponseType commit(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 1.108 1.109 - Project project = new Project(-1); 1.110 + Project project = null; 1.111 try { 1.112 project = new Project(getParameter(req, Integer.class, "id").orElseThrow()); 1.113 project.setName(getParameter(req, String.class, "name").orElseThrow()); 1.114 @@ -119,11 +165,9 @@ 1.115 LOG.debug("Successfully updated project {}", project.getName()); 1.116 } catch (NoSuchElementException | NumberFormatException | SQLException ex) { 1.117 // TODO: set request attribute with error text 1.118 - req.setAttribute("project", project); 1.119 - req.setAttribute("users", dao.getUserDao().list()); 1.120 - setDynamicFragment(req, "project-form"); 1.121 LOG.warn("Form validation failure: {}", ex.getMessage()); 1.122 LOG.debug("Details:", ex); 1.123 + configureEditForm(req, dao, Optional.ofNullable(project)); 1.124 } 1.125 1.126 return ResponseType.HTML; 1.127 @@ -140,11 +184,21 @@ 1.128 req.setAttribute("versions", dao.getVersionDao().list(selectedProject)); 1.129 req.setAttribute("issues", dao.getIssueDao().list(selectedProject)); 1.130 1.131 + // TODO: add more levels depending on last visited location 1.132 + setBreadcrumbs(req, getBreadcrumbs(1, selectedProject)); 1.133 + 1.134 setDynamicFragment(req, "project-details"); 1.135 1.136 return ResponseType.HTML; 1.137 } 1.138 1.139 + private void configureEditVersionForm(HttpServletRequest req, Optional<Version> version, Project selectedProject) { 1.140 + req.setAttribute("version", version.orElse(new Version(-1, selectedProject))); 1.141 + req.setAttribute("versionStatusEnum", VersionStatus.values()); 1.142 + 1.143 + setDynamicFragment(req, "version-form"); 1.144 + } 1.145 + 1.146 @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET) 1.147 public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { 1.148 final var selectedProject = getSelectedProject(req, dao); 1.149 @@ -153,11 +207,9 @@ 1.150 return ResponseType.NONE; 1.151 } 1.152 1.153 - req.setAttribute("version", findByParameter(req, Integer.class, "id", 1.154 - dao.getVersionDao()::find).orElse(new Version(-1, selectedProject))); 1.155 - req.setAttribute("versionStatusEnum", VersionStatus.values()); 1.156 - 1.157 - setDynamicFragment(req, "version-form"); 1.158 + configureEditVersionForm(req, 1.159 + findByParameter(req, Integer.class, "id", dao.getVersionDao()::find), 1.160 + selectedProject); 1.161 1.162 return ResponseType.HTML; 1.163 } 1.164 @@ -170,7 +222,7 @@ 1.165 return ResponseType.NONE; 1.166 } 1.167 1.168 - Version version = new Version(-1, selectedProject); 1.169 + Version version = null; 1.170 try { 1.171 version = new Version(getParameter(req, Integer.class, "id").orElseThrow(), selectedProject); 1.172 version.setName(getParameter(req, String.class, "name").orElseThrow()); 1.173 @@ -183,16 +235,24 @@ 1.174 LOG.debug("Successfully updated version {} for project {}", version.getName(), selectedProject.getName()); 1.175 } catch (NoSuchElementException | NumberFormatException | SQLException ex) { 1.176 // TODO: set request attribute with error text 1.177 - req.setAttribute("version", version); 1.178 - req.setAttribute("versionStatusEnum", VersionStatus.values()); 1.179 - setDynamicFragment(req, "version-form"); 1.180 LOG.warn("Form validation failure: {}", ex.getMessage()); 1.181 LOG.debug("Details:", ex); 1.182 + configureEditVersionForm(req, Optional.ofNullable(version), selectedProject); 1.183 } 1.184 1.185 return ResponseType.HTML; 1.186 } 1.187 1.188 + private void configureEditIssueForm(HttpServletRequest req, DataAccessObjects dao, Optional<Issue> issue, Project selectedProject) throws SQLException { 1.189 + 1.190 + req.setAttribute("issue", issue.orElse(new Issue(-1, selectedProject))); 1.191 + req.setAttribute("issueStatusEnum", IssueStatus.values()); 1.192 + req.setAttribute("issueCategoryEnum", IssueCategory.values()); 1.193 + req.setAttribute("versions", dao.getVersionDao().list(selectedProject)); 1.194 + 1.195 + setDynamicFragment(req, "issue-form"); 1.196 + } 1.197 + 1.198 @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET) 1.199 public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { 1.200 final var selectedProject = getSelectedProject(req, dao); 1.201 @@ -201,12 +261,9 @@ 1.202 return ResponseType.NONE; 1.203 } 1.204 1.205 - req.setAttribute("issue", findByParameter(req, Integer.class, "id", 1.206 - dao.getIssueDao()::find).orElse(new Issue(-1, selectedProject))); 1.207 - req.setAttribute("issueStatusEnum", IssueStatus.values()); 1.208 - req.setAttribute("issueCategoryEnum", IssueCategory.values()); 1.209 - 1.210 - setDynamicFragment(req, "issue-form"); 1.211 + configureEditIssueForm(req, dao, 1.212 + findByParameter(req, Integer.class, "id", dao.getIssueDao()::find), 1.213 + selectedProject); 1.214 1.215 return ResponseType.HTML; 1.216 } 1.217 @@ -219,7 +276,7 @@ 1.218 return ResponseType.NONE; 1.219 } 1.220 1.221 - Issue issue = new Issue(-1, selectedProject); 1.222 + Issue issue = null; 1.223 try { 1.224 issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow(), selectedProject); 1.225 1.226 @@ -232,12 +289,9 @@ 1.227 LOG.debug("Successfully updated issue {} for project {}", issue.getId(), selectedProject.getName()); 1.228 } catch (NoSuchElementException | NumberFormatException | SQLException ex) { 1.229 // TODO: set request attribute with error text 1.230 - req.setAttribute("issue", issue); 1.231 - req.setAttribute("issueStatusEnum", IssueStatus.values()); 1.232 - req.setAttribute("issueCategoryEnum", IssueCategory.values()); 1.233 - setDynamicFragment(req, "issue-form"); 1.234 LOG.warn("Form validation failure: {}", ex.getMessage()); 1.235 LOG.debug("Details:", ex); 1.236 + configureEditIssueForm(req, dao, Optional.ofNullable(issue), selectedProject); 1.237 } 1.238 1.239 return ResponseType.HTML;