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

changeset 99
a369fb1b3aa2
parent 97
602f75801644
child 100
7e3c61c340d3
equal deleted inserted replaced
98:5c406eef0e5c 99:a369fb1b3aa2
37 import org.slf4j.LoggerFactory; 37 import org.slf4j.LoggerFactory;
38 38
39 import javax.servlet.annotation.WebServlet; 39 import javax.servlet.annotation.WebServlet;
40 import javax.servlet.http.HttpServletRequest; 40 import javax.servlet.http.HttpServletRequest;
41 import javax.servlet.http.HttpServletResponse; 41 import javax.servlet.http.HttpServletResponse;
42 import javax.servlet.http.HttpSession;
43 import java.io.IOException; 42 import java.io.IOException;
44 import java.sql.Date; 43 import java.sql.Date;
45 import java.sql.SQLException; 44 import java.sql.SQLException;
46 import java.util.ArrayList; 45 import java.util.ArrayList;
47 import java.util.List; 46 import java.util.List;
48 import java.util.NoSuchElementException; 47 import java.util.NoSuchElementException;
49 import java.util.Objects; 48 import java.util.Optional;
50 import java.util.stream.Collectors; 49 import java.util.stream.Collectors;
51 import java.util.stream.Stream; 50 import java.util.stream.Stream;
52 51
53 import static de.uapcore.lightpit.Functions.fqn; 52 import static de.uapcore.lightpit.Functions.fqn;
54 53
58 ) 57 )
59 public final class ProjectsModule extends AbstractLightPITServlet { 58 public final class ProjectsModule extends AbstractLightPITServlet {
60 59
61 private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class); 60 private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class);
62 61
63 public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project"); 62 private static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project");
64 public static final String SESSION_ATTR_SELECTED_ISSUE = fqn(ProjectsModule.class, "selected_issue"); 63 private static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected_version");
65 public static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected_version"); 64 private static final String PARAMETER_SELECTED_PROJECT = "pid";
66 65 private static final String PARAMETER_SELECTED_VERSION = "vid";
67 // TODO: try to get rid of this shit
68 private class SessionSelection {
69 final HttpSession session;
70 final HttpServletRequest req;
71 final DataAccessObjects dao;
72 Project project;
73 Version version;
74 Issue issue;
75
76 SessionSelection(HttpServletRequest req, DataAccessObjects dao) {
77 this.req = req;
78 this.dao = dao;
79 session = req.getSession();
80 }
81
82 void newProject() {
83 project = null;
84 version = null;
85 issue = null;
86 updateAttributes();
87 project = new Project(-1);
88 updateAttributes();
89 }
90
91 void newVersion() throws SQLException {
92 project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT);
93 syncProject();
94 version = null;
95 issue = null;
96 updateAttributes();
97 version = new Version(-1);
98 version.setProject(project);
99 updateAttributes();
100 }
101
102 void newIssue() throws SQLException {
103 project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT);
104 syncProject();
105 version = null;
106 issue = null;
107 updateAttributes();
108 issue = new Issue(-1);
109 issue.setProject(project);
110 updateAttributes();
111 }
112
113 void selectVersion(Version selectedVersion) throws SQLException {
114 issue = null;
115 version = selectedVersion;
116 if (!version.getProject().equals(project)) {
117 project = dao.getProjectDao().find(version.getProject().getId());
118 }
119 // our object contains more details
120 version.setProject(project);
121 updateAttributes();
122 }
123
124 void selectIssue(Issue selectedIssue) throws SQLException {
125 issue = selectedIssue;
126 if (!issue.getProject().equals(project)) {
127 project = dao.getProjectDao().find(issue.getProject().getId());
128 }
129 // our object contains more details
130 issue.setProject(project);
131 if (!issue.getResolvedVersions().contains(version)
132 && !issue.getAffectedVersions().contains(version)) {
133 version = null;
134 }
135 updateAttributes();
136 }
137
138 void syncProject() throws SQLException {
139 final var projectSelection = getParameter(req, Integer.class, "pid");
140 if (projectSelection.isPresent()) {
141 final var selectedProject = dao.getProjectDao().find(projectSelection.get());
142 if (!Objects.equals(selectedProject, project)) {
143 // reset version and issue if project changed
144 version = null;
145 issue = null;
146 }
147 project = selectedProject;
148 } else {
149 project = project == null ? null : dao.getProjectDao().find(project.getId());
150 }
151 }
152
153 void syncVersion() throws SQLException {
154 final var versionSelection = getParameter(req, Integer.class, "vid");
155 if (versionSelection.isPresent()) {
156 if (versionSelection.get() < 0) {
157 version = null;
158 } else {
159 final var selectedVersion = dao.getVersionDao().find(versionSelection.get());
160 if (!Objects.equals(selectedVersion, version)) {
161 issue = null;
162 }
163 selectVersion(selectedVersion);
164 }
165 } else {
166 version = version == null ? null : dao.getVersionDao().find(version.getId());
167 }
168 }
169
170 void syncIssue() throws SQLException {
171 final var issueSelection = getParameter(req, Integer.class, "issue");
172 if (issueSelection.isPresent()) {
173 if (issueSelection.get() < 0) {
174 issue = null;
175 } else {
176 final var selectedIssue = dao.getIssueDao().find(issueSelection.get());
177 dao.getIssueDao().joinVersionInformation(selectedIssue);
178 selectIssue(selectedIssue);
179 }
180 } else {
181 issue = issue == null ? null : dao.getIssueDao().find(issue.getId());
182 }
183 }
184
185 void sync() throws SQLException {
186 project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT);
187 version = (Version) session.getAttribute(SESSION_ATTR_SELECTED_VERSION);
188 issue = (Issue) session.getAttribute(SESSION_ATTR_SELECTED_ISSUE);
189
190 syncProject();
191 syncVersion();
192 syncIssue();
193
194 updateAttributes();
195 }
196
197 private void updateAttributes() {
198 session.setAttribute(SESSION_ATTR_SELECTED_PROJECT, project);
199 session.setAttribute(SESSION_ATTR_SELECTED_VERSION, version);
200 session.setAttribute(SESSION_ATTR_SELECTED_ISSUE, issue);
201 }
202 }
203 66
204 @Override 67 @Override
205 protected String getResourceBundleName() { 68 protected String getResourceBundleName() {
206 return "localization.projects"; 69 return "localization.projects";
207 } 70 }
208 71
209 private String queryParams(Project p, Version v, Issue i) { 72 private String queryParams(Project p, Version v) {
210 return String.format("pid=%d&vid=%d&issue=%d", 73 return String.format("pid=%d&vid=%d",
211 p == null ? -1 : p.getId(), 74 p == null ? -1 : p.getId(),
212 v == null ? -1 : v.getId(), 75 v == null ? -1 : v.getId()
213 i == null ? -1 : i.getId()
214 ); 76 );
215 } 77 }
216 78
217 /** 79 /**
218 * Creates the navigation menu. 80 * Creates the navigation menu.
219 * 81 *
220 * @param projects the list of projects 82 * @param req the servlet request
221 * @param selection the currently selected objects 83 * @param viewModel the current view model
222 * @param projInfo info about the currently selected project or null
223 * @return a dynamic navigation menu trying to display as many levels as possible
224 */ 84 */
225 private List<MenuEntry> getNavMenu(List<Project> projects, SessionSelection selection, ProjectInfo projInfo) { 85 private void setNavigationMenu(HttpServletRequest req, ProjectView viewModel) {
86 final Project selectedProject = Optional.ofNullable(viewModel.getProjectInfo()).map(ProjectInfo::getProject).orElse(null);
87
226 final var navigation = new ArrayList<MenuEntry>(); 88 final var navigation = new ArrayList<MenuEntry>();
227 89
228 for (Project proj : projects) { 90 for (ProjectInfo plistInfo : viewModel.getProjectList()) {
91 final var proj = plistInfo.getProject();
229 final var projEntry = new MenuEntry( 92 final var projEntry = new MenuEntry(
230 proj.getName(), 93 proj.getName(),
231 "projects/view?pid=" + proj.getId() 94 "projects/view?" + queryParams(proj, null)
232 ); 95 );
233 navigation.add(projEntry); 96 navigation.add(projEntry);
234 if (proj.equals(selection.project)) { 97 if (proj.equals(selectedProject)) {
98 final var projInfo = viewModel.getProjectInfo();
235 projEntry.setActive(true); 99 projEntry.setActive(true);
236 100
237 // **************** 101 // ****************
238 // Versions Section 102 // Versions Section
239 // **************** 103 // ****************
240 { 104 {
241 final var entry = new MenuEntry(1, 105 final var entry = new MenuEntry(1,
242 new ResourceKey("localization.projects", "menu.versions"), 106 new ResourceKey(getResourceBundleName(), "menu.versions"),
243 "projects/view?" + queryParams(proj, null, null) 107 "projects/view?" + queryParams(proj, null)
244 ); 108 );
245 navigation.add(entry); 109 navigation.add(entry);
246 } 110 }
247 111
248 final var level2 = new ArrayList<MenuEntry>(); 112 final var level2 = new ArrayList<MenuEntry>();
249 { 113 {
250 final var entry = new MenuEntry( 114 final var entry = new MenuEntry(
251 new ResourceKey("localization.projects", "filter.all"), 115 new ResourceKey(getResourceBundleName(), "filter.all"),
252 "projects/view?" + queryParams(proj, null, null) 116 "projects/view?" + queryParams(proj, null)
253 ); 117 );
254 if (selection.version == null) entry.setActive(true); 118 if (viewModel.getVersionFilter() == null) entry.setActive(true);
255 level2.add(entry); 119 level2.add(entry);
256 } 120 }
257 121
258 for (Version version : projInfo.getVersions()) { 122 for (Version version : projInfo.getVersions()) {
259 final var entry = new MenuEntry( 123 final var entry = new MenuEntry(
260 version.getName(), 124 version.getName(),
261 "projects/versions/view?" + queryParams(proj, version, null) 125 "projects/view?" + queryParams(proj, version)
262 ); 126 );
263 if (version.equals(selection.version)) entry.setActive(true); 127 if (version.equals(viewModel.getVersionFilter())) entry.setActive(true);
264 level2.add(entry); 128 level2.add(entry);
265 } 129 }
266 130
267 level2.forEach(e -> e.setLevel(2)); 131 level2.forEach(e -> e.setLevel(2));
268 navigation.addAll(level2); 132 navigation.addAll(level2);
269 } 133 }
270 } 134 }
271 135
272 return navigation; 136 setNavigationMenu(req, navigation);
273 } 137 }
274 138
275 @RequestMapping(method = HttpMethod.GET) 139 private int syncParamWithSession(HttpServletRequest req, String param, String attr) {
276 public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 140 final var session = req.getSession();
277 final var sessionSelection = new SessionSelection(req, dao); 141 final var idParam = getParameter(req, Integer.class, param);
278 sessionSelection.sync(); 142 final int id;
279 143 if (idParam.isPresent()) {
144 id = idParam.get();
145 session.setAttribute(attr, id);
146 } else {
147 id = Optional.ofNullable(session.getAttribute(attr)).map(x->(Integer)x).orElse(-1);
148 }
149 return id;
150 }
151
152 private void populate(ProjectView viewModel, HttpServletRequest req, DataAccessObjects dao) throws SQLException {
280 final var projectDao = dao.getProjectDao(); 153 final var projectDao = dao.getProjectDao();
281 final var versionDao = dao.getVersionDao(); 154 final var versionDao = dao.getVersionDao();
282 155
283 final var projectList = projectDao.list(); 156 projectDao.list().stream().map(ProjectInfo::new).forEach(viewModel.getProjectList()::add);
284 157
285 final var viewModel = new ProjectIndexView(); 158 // Select Project
286 for (var project : projectList) { 159 final int pid = syncParamWithSession(req, PARAMETER_SELECTED_PROJECT, SESSION_ATTR_SELECTED_PROJECT);
160 if (pid >= 0) {
161 final var project = projectDao.find(pid);
287 final var info = new ProjectInfo(project); 162 final var info = new ProjectInfo(project);
288 info.setVersions(versionDao.list(project)); 163 info.setVersions(versionDao.list(project));
289 info.setIssueSummary(projectDao.getIssueSummary(project)); 164 info.setIssueSummary(projectDao.getIssueSummary(project));
290 viewModel.getProjects().add(info); 165 viewModel.setProjectInfo(info);
291 } 166 }
292 167
168 // Select Version
169 final int vid = syncParamWithSession(req, PARAMETER_SELECTED_VERSION, SESSION_ATTR_SELECTED_VERSION);
170 if (vid >= 0) {
171 viewModel.setVersionFilter(versionDao.find(vid));
172 }
173 }
174
175 private ResponseType forwardView(HttpServletRequest req, ProjectView viewModel, String name) {
293 setViewModel(req, viewModel); 176 setViewModel(req, viewModel);
294 setContentPage(req, "projects"); 177 setContentPage(req, name);
295 setStylesheet(req, "projects"); 178 setStylesheet(req, "projects");
296 179 setNavigationMenu(req, viewModel);
297 setNavigationMenu(req, getNavMenu(projectList, sessionSelection, currentProjectInfo(dao, sessionSelection.project)));
298
299 return ResponseType.HTML; 180 return ResponseType.HTML;
300 } 181 }
301 182
302 private ProjectInfo currentProjectInfo(DataAccessObjects dao, Project project) throws SQLException { 183 @RequestMapping(method = HttpMethod.GET)
303 if (project == null) return null; 184 public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
185 final var viewModel = new ProjectView();
186 populate(viewModel, req, dao);
187
304 final var projectDao = dao.getProjectDao(); 188 final var projectDao = dao.getProjectDao();
305 final var versionDao = dao.getVersionDao(); 189 final var versionDao = dao.getVersionDao();
306 190
307 final var info = new ProjectInfo(project); 191 for (var info : viewModel.getProjectList()) {
308 info.setVersions(versionDao.list(project)); 192 info.setVersions(versionDao.list(info.getProject()));
309 info.setIssueSummary(projectDao.getIssueSummary(project)); 193 info.setIssueSummary(projectDao.getIssueSummary(info.getProject()));
310 return info; 194 }
311 } 195
312 196 return forwardView(req, viewModel, "projects");
313 private ProjectEditView configureEditForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { 197 }
314 final var viewModel = new ProjectEditView(); 198
315 viewModel.setProject(selection.project); 199 private void configure(ProjectEditView viewModel, Project project, DataAccessObjects dao) throws SQLException {
200 viewModel.setProject(project);
316 viewModel.setUsers(dao.getUserDao().list()); 201 viewModel.setUsers(dao.getUserDao().list());
317 setNavigationMenu(req, getNavMenu(dao.getProjectDao().list(), selection, currentProjectInfo(dao, selection.project)));
318 setViewModel(req, viewModel);
319 setContentPage(req, "project-form");
320 return viewModel;
321 } 202 }
322 203
323 @RequestMapping(requestPath = "edit", method = HttpMethod.GET) 204 @RequestMapping(requestPath = "edit", method = HttpMethod.GET)
324 public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 205 public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
325 final var selection = new SessionSelection(req, dao); 206 final var viewModel = new ProjectEditView();
326 if (getParameter(req, Integer.class, "pid").isEmpty()) { 207 populate(viewModel, req, dao);
327 selection.newProject(); 208
328 } else { 209 final var project = Optional.ofNullable(viewModel.getProjectInfo())
329 selection.sync(); 210 .map(ProjectInfo::getProject)
330 } 211 .orElse(new Project(-1));
331 212 configure(viewModel, project, dao);
332 configureEditForm(req, dao, selection); 213
333 214 return forwardView(req, viewModel, "project-form");
334 return ResponseType.HTML;
335 } 215 }
336 216
337 @RequestMapping(requestPath = "commit", method = HttpMethod.POST) 217 @RequestMapping(requestPath = "commit", method = HttpMethod.POST)
338 public ResponseType commit(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 218 public ResponseType commit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
339 219
340 Project project = new Project(-1); 220 Project project = new Project(-1);
341 try { 221 try {
342 project = new Project(getParameter(req, Integer.class, "id").orElseThrow()); 222 project = new Project(getParameter(req, Integer.class, "pid").orElseThrow());
343 project.setName(getParameter(req, String.class, "name").orElseThrow()); 223 project.setName(getParameter(req, String.class, "name").orElseThrow());
344 getParameter(req, String.class, "description").ifPresent(project::setDescription); 224 getParameter(req, String.class, "description").ifPresent(project::setDescription);
345 getParameter(req, String.class, "repoUrl").ifPresent(project::setRepoUrl); 225 getParameter(req, String.class, "repoUrl").ifPresent(project::setRepoUrl);
346 getParameter(req, Integer.class, "owner").map( 226 getParameter(req, Integer.class, "owner").map(
347 ownerId -> ownerId >= 0 ? new User(ownerId) : null 227 ownerId -> ownerId >= 0 ? new User(ownerId) : null
348 ).ifPresent(project::setOwner); 228 ).ifPresent(project::setOwner);
349 229
350 dao.getProjectDao().saveOrUpdate(project); 230 dao.getProjectDao().saveOrUpdate(project);
351 231
352 setRedirectLocation(req, "./projects/"); 232 setRedirectLocation(req, "./projects/view?pid="+project.getId());
353 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); 233 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
354 LOG.debug("Successfully updated project {}", project.getName()); 234 LOG.debug("Successfully updated project {}", project.getName());
235
236 return ResponseType.HTML;
355 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { 237 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
356 LOG.warn("Form validation failure: {}", ex.getMessage()); 238 LOG.warn("Form validation failure: {}", ex.getMessage());
357 LOG.debug("Details:", ex); 239 LOG.debug("Details:", ex);
358 final var selection = new SessionSelection(req, dao); 240 final var viewModel = new ProjectEditView();
359 selection.project = project; 241 populate(viewModel, req, dao);
360 final var vm = configureEditForm(req, dao, selection); 242 configure(viewModel, project, dao);
361 vm.setErrorText(ex.getMessage()); // TODO: error text 243 // TODO: error text
362 } 244 return forwardView(req, viewModel, "project-form");
363 245 }
364 return ResponseType.HTML;
365 } 246 }
366 247
367 @RequestMapping(requestPath = "view", method = HttpMethod.GET) 248 @RequestMapping(requestPath = "view", method = HttpMethod.GET)
368 public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { 249 public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
369 final var selection = new SessionSelection(req, dao); 250 final var viewModel = new ProjectDetailsView();
370 selection.sync(); 251 populate(viewModel, req, dao);
371 252
372 if (selection.project == null) { 253 if (viewModel.getProjectInfo() == null) {
373 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected."); 254 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
374 return ResponseType.NONE; 255 return ResponseType.NONE;
375 } 256 }
376 257
377 final var projectDao = dao.getProjectDao();
378 final var versionDao = dao.getVersionDao();
379 final var issueDao = dao.getIssueDao(); 258 final var issueDao = dao.getIssueDao();
380 259
381 final var viewModel = new ProjectView(selection.project); 260 final var project = viewModel.getProjectInfo().getProject();
382 final var issues = issueDao.list(selection.project); 261
262 final var detailView = viewModel.getProjectDetails();
263 if (viewModel.getVersionFilter() != null) {
264 detailView.updateVersionInfo(List.of(viewModel.getVersionFilter()));
265 } else {
266 detailView.updateVersionInfo(viewModel.getProjectInfo().getVersions());
267 }
268 final var issues = issueDao.list(project);
383 for (var issue : issues) issueDao.joinVersionInformation(issue); 269 for (var issue : issues) issueDao.joinVersionInformation(issue);
384 viewModel.setIssues(issues); 270 detailView.setIssues(issues);
385 // TODO: fix duplicated selection of versions (projectInfo also contains these infos) 271
386 viewModel.setVersions(versionDao.list(selection.project)); 272 return forwardView(req, viewModel, "project-details");
387 viewModel.updateVersionInfo();
388 setViewModel(req, viewModel);
389
390 setNavigationMenu(req, getNavMenu(projectDao.list(), selection, currentProjectInfo(dao, selection.project)));
391 setContentPage(req, "project-details");
392 setStylesheet(req, "projects");
393
394 return ResponseType.HTML;
395 }
396
397 @RequestMapping(requestPath = "versions/view", method = HttpMethod.GET)
398 public ResponseType viewVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
399 final var selection = new SessionSelection(req, dao);
400 selection.sync();
401 if (selection.version == null) {
402 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
403 return ResponseType.NONE;
404 }
405
406 final var projectDao = dao.getProjectDao();
407 final var issueDao = dao.getIssueDao();
408
409 final var viewModel = new VersionView(selection.version);
410 final var issues = issueDao.list(selection.version);
411 for (var issue : issues) issueDao.joinVersionInformation(issue);
412 viewModel.setIssues(issues);
413 setViewModel(req, viewModel);
414
415 setNavigationMenu(req, getNavMenu(projectDao.list(), selection, currentProjectInfo(dao, selection.project)));
416 setContentPage(req, "version");
417 setStylesheet(req, "projects");
418
419 return ResponseType.HTML;
420 }
421
422 private VersionEditView configureEditVersionForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException {
423 final var viewModel = new VersionEditView(selection.version);
424 if (selection.version.getProject() == null) {
425 viewModel.setProjects(dao.getProjectDao().list());
426 }
427 setViewModel(req, viewModel);
428 setContentPage(req, "version-form");
429 setNavigationMenu(req, getNavMenu(dao.getProjectDao().list(), selection, currentProjectInfo(dao, selection.project)));
430 return viewModel;
431 } 273 }
432 274
433 @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET) 275 @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET)
434 public ResponseType editVersion(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 276 public ResponseType editVersion(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
435 final var selection = new SessionSelection(req, dao); 277 final var viewModel = new VersionEditView();
436 if (getParameter(req, Integer.class, "vid").isEmpty()) { 278 populate(viewModel, req, dao);
437 selection.newVersion(); 279
280 if (viewModel.getVersionFilter() == null) {
281 viewModel.setVersion(new Version(-1));
438 } else { 282 } else {
439 selection.sync(); 283 viewModel.setVersion(viewModel.getVersionFilter());
440 } 284 }
441 285
442 configureEditVersionForm(req, dao, selection); 286 return forwardView(req, viewModel, "version-form");
443
444 return ResponseType.HTML;
445 } 287 }
446 288
447 @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST) 289 @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST)
448 public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { 290 public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
449 291
460 setRedirectLocation(req, "./projects/view?pid=" + version.getProject().getId()); 302 setRedirectLocation(req, "./projects/view?pid=" + version.getProject().getId());
461 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); 303 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
462 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { 304 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
463 LOG.warn("Form validation failure: {}", ex.getMessage()); 305 LOG.warn("Form validation failure: {}", ex.getMessage());
464 LOG.debug("Details:", ex); 306 LOG.debug("Details:", ex);
465 final var selection = new SessionSelection(req, dao); 307 final var viewModel = new VersionEditView();
466 selection.selectVersion(version); 308 populate(viewModel, req, dao);
467 final var viewModel = configureEditVersionForm(req, dao, selection); 309 viewModel.setVersion(version);
468 // TODO: set Error Text 310 // TODO: set Error Text
311 return forwardView(req, viewModel, "version-form");
469 } 312 }
470 313
471 return ResponseType.HTML; 314 return ResponseType.HTML;
472 } 315 }
473 316
474 private IssueEditView configureEditIssueForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { 317 private void configure(IssueEditView viewModel, Issue issue, DataAccessObjects dao) throws SQLException {
475 final var viewModel = new IssueEditView(selection.issue); 318 issue.setProject(viewModel.getProjectInfo().getProject());
476 319 viewModel.setIssue(issue);
477 if (selection.issue.getProject() == null) { 320 viewModel.configureVersionSelectors(viewModel.getProjectInfo().getVersions());
478 viewModel.setProjects(dao.getProjectDao().list());
479 } else {
480 viewModel.setVersions(dao.getVersionDao().list(selection.issue.getProject()));
481 }
482 viewModel.setUsers(dao.getUserDao().list()); 321 viewModel.setUsers(dao.getUserDao().list());
483 setViewModel(req, viewModel);
484
485 setContentPage(req, "issue-form");
486 setNavigationMenu(req, getNavMenu(dao.getProjectDao().list(), selection, currentProjectInfo(dao, selection.project)));
487 return viewModel;
488 }
489
490 @RequestMapping(requestPath = "issues/", method = HttpMethod.GET)
491 public ResponseType issues(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
492 final var selection = new SessionSelection(req, dao);
493 selection.sync();
494 if (selection.project == null) {
495 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
496 return ResponseType.NONE;
497 }
498
499 final var projectDao = dao.getProjectDao();
500 final var issueDao = dao.getIssueDao();
501
502 final var viewModel = new IssuesView();
503 viewModel.setProject(selection.project);
504 if (selection.version == null) {
505 viewModel.setIssues(issueDao.list(selection.project));
506 } else {
507 viewModel.setVersion(selection.version);
508 viewModel.setIssues(issueDao.list(selection.version));
509 }
510 setViewModel(req, viewModel);
511
512 setNavigationMenu(req, getNavMenu(projectDao.list(), selection, currentProjectInfo(dao, selection.project)));
513 setContentPage(req, "issues");
514 setStylesheet(req, "projects");
515
516 return ResponseType.HTML;
517 } 322 }
518 323
519 @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET) 324 @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET)
520 public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { 325 public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
521 final var selection = new SessionSelection(req, dao); 326 final var viewModel = new IssueEditView();
522 if (getParameter(req, Integer.class, "issue").isEmpty()) { 327
523 selection.newIssue(); 328 final var issueParam = getParameter(req, Integer.class, "issue");
329 if (issueParam.isPresent()) {
330 final var issue = dao.getIssueDao().find(issueParam.get());
331 req.getSession().setAttribute(SESSION_ATTR_SELECTED_PROJECT, issue.getProject().getId());
332 populate(viewModel, req, dao);
333 configure(viewModel, issue, dao);
524 } else { 334 } else {
525 selection.sync(); 335 populate(viewModel, req, dao);
526 } 336 configure(viewModel, new Issue(-1), dao);
527 337 }
528 configureEditIssueForm(req, dao, selection); 338
529 339 return forwardView(req, viewModel, "issue-form");
530 return ResponseType.HTML;
531 } 340 }
532 341
533 @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST) 342 @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST)
534 public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { 343 public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
535
536 Issue issue = new Issue(-1); 344 Issue issue = new Issue(-1);
537 try { 345 try {
538 issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow()); 346 issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow());
539 issue.setProject(new Project(getParameter(req, Integer.class, "pid").orElseThrow())); 347 issue.setProject(new Project(getParameter(req, Integer.class, "pid").orElseThrow()));
540 getParameter(req, String.class, "category").map(IssueCategory::valueOf).ifPresent(issue::setCategory); 348 getParameter(req, String.class, "category").map(IssueCategory::valueOf).ifPresent(issue::setCategory);
558 ).ifPresent(issue::setResolvedVersions); 366 ).ifPresent(issue::setResolvedVersions);
559 367
560 dao.getIssueDao().saveOrUpdate(issue); 368 dao.getIssueDao().saveOrUpdate(issue);
561 369
562 // specifying the issue parameter keeps the edited issue as menu item 370 // specifying the issue parameter keeps the edited issue as menu item
563 setRedirectLocation(req, "./projects/issues/?issue=" + issue.getId()); 371 setRedirectLocation(req, "./projects/view/?pid=" + issue.getProject().getId());
564 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); 372 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
565 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { 373 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
566 // TODO: set request attribute with error text 374 // TODO: set request attribute with error text
567 LOG.warn("Form validation failure: {}", ex.getMessage()); 375 LOG.warn("Form validation failure: {}", ex.getMessage());
568 LOG.debug("Details:", ex); 376 LOG.debug("Details:", ex);
569 final var selection = new SessionSelection(req, dao); 377 final var viewModel = new IssueEditView();
570 selection.selectIssue(issue); 378 configure(viewModel, issue, dao);
571 final var viewModel = configureEditIssueForm(req, dao, selection);
572 // TODO: set Error Text 379 // TODO: set Error Text
380 return forwardView(req, viewModel, "issue-form");
573 } 381 }
574 382
575 return ResponseType.HTML; 383 return ResponseType.HTML;
576 } 384 }
577 } 385 }

mercurial