57 private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class); |
61 private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class); |
58 |
62 |
59 public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project"); |
63 public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project"); |
60 public static final String SESSION_ATTR_SELECTED_ISSUE = fqn(ProjectsModule.class, "selected_issue"); |
64 public static final String SESSION_ATTR_SELECTED_ISSUE = fqn(ProjectsModule.class, "selected_issue"); |
61 public 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"); |
62 public static final String SESSION_ATTR_HIDE_ZEROS = fqn(ProjectsModule.class, "stats_hide_zeros"); |
|
63 |
66 |
64 private class SessionSelection { |
67 private class SessionSelection { |
65 final HttpSession session; |
68 final HttpSession session; |
|
69 final HttpServletRequest req; |
|
70 final DataAccessObjects dao; |
66 Project project; |
71 Project project; |
67 Version version; |
72 Version version; |
68 Issue issue; |
73 Issue issue; |
69 |
74 |
70 SessionSelection(HttpServletRequest req, Project project) { |
75 SessionSelection(HttpServletRequest req, DataAccessObjects dao) { |
71 this.session = req.getSession(); |
76 this.req = req; |
72 this.project = project; |
77 this.dao = dao; |
|
78 session = req.getSession(); |
|
79 } |
|
80 |
|
81 void newProject() { |
|
82 project = null; |
73 version = null; |
83 version = null; |
74 issue = null; |
84 issue = null; |
75 updateAttributes(); |
85 updateAttributes(); |
76 } |
86 project = new Project(-1); |
77 |
87 updateAttributes(); |
78 SessionSelection(HttpServletRequest req, DataAccessObjects dao) throws SQLException { |
88 } |
79 this.session = req.getSession(); |
89 |
80 final var issueDao = dao.getIssueDao(); |
90 void newVersion() throws SQLException { |
81 final var projectDao = dao.getProjectDao(); |
91 project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT); |
82 final var issueSelection = getParameter(req, Integer.class, "issue"); |
92 syncProject(); |
83 if (issueSelection.isPresent()) { |
93 version = null; |
84 issue = issueDao.find(issueSelection.get()); |
94 issue = null; |
85 } else { |
95 updateAttributes(); |
86 final var issue = (Issue) session.getAttribute(SESSION_ATTR_SELECTED_ISSUE); |
96 version = new Version(-1); |
87 this.issue = issue == null ? null : issueDao.find(issue.getId()); |
97 version.setProject(project); |
88 } |
98 updateAttributes(); |
89 if (issue != null) { |
99 } |
90 version = null; // show the issue globally |
100 |
91 project = projectDao.find(issue.getProject().getId()); |
101 void newIssue() throws SQLException { |
92 } |
102 project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT); |
93 |
103 syncProject(); |
|
104 version = null; |
|
105 issue = null; |
|
106 updateAttributes(); |
|
107 issue = new Issue(-1); |
|
108 issue.setProject(project); |
|
109 updateAttributes(); |
|
110 } |
|
111 |
|
112 void selectVersion(Version selectedVersion) throws SQLException { |
|
113 issue = null; |
|
114 version = selectedVersion; |
|
115 if (!version.getProject().equals(project)) { |
|
116 project = dao.getProjectDao().find(version.getProject().getId()); |
|
117 } |
|
118 // our object contains more details |
|
119 version.setProject(project); |
|
120 updateAttributes(); |
|
121 } |
|
122 |
|
123 void selectIssue(Issue selectedIssue) throws SQLException { |
|
124 issue = selectedIssue; |
|
125 if (!issue.getProject().equals(project)) { |
|
126 project = dao.getProjectDao().find(issue.getProject().getId()); |
|
127 } |
|
128 // our object contains more details |
|
129 issue.setProject(project); |
|
130 if (!issue.getResolvedVersions().contains(version) && !issue.getScheduledVersions().contains(version) |
|
131 && !issue.getAffectedVersions().contains(version)) { |
|
132 version = null; |
|
133 } |
|
134 updateAttributes(); |
|
135 } |
|
136 |
|
137 void syncProject() throws SQLException { |
94 final var projectSelection = getParameter(req, Integer.class, "pid"); |
138 final var projectSelection = getParameter(req, Integer.class, "pid"); |
95 if (projectSelection.isPresent()) { |
139 if (projectSelection.isPresent()) { |
96 final var selectedProject = projectDao.find(projectSelection.get()); |
140 final var selectedProject = dao.getProjectDao().find(projectSelection.get()); |
97 if (!Objects.equals(selectedProject, project)) { |
141 if (!Objects.equals(selectedProject, project)) { |
98 // reset version and issue if project changed |
142 // reset version and issue if project changed |
99 version = null; |
143 version = null; |
100 issue = null; |
144 issue = null; |
101 } |
145 } |
102 project = selectedProject; |
146 project = selectedProject; |
103 } else { |
147 } else { |
104 final var sessionProject = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT); |
148 project = project == null ? null : dao.getProjectDao().find(project.getId()); |
105 project = sessionProject == null ? null : projectDao.find(sessionProject.getId()); |
149 } |
106 } |
150 } |
107 updateAttributes(); |
151 |
108 } |
152 void syncVersion() throws SQLException { |
109 |
153 final var versionSelection = getParameter(req, Integer.class, "vid"); |
110 void selectVersion(Version version) { |
154 if (versionSelection.isPresent()) { |
111 this.project = version.getProject(); |
155 if (versionSelection.get() < 0) { |
112 this.version = version; |
156 version = null; |
113 this.issue = null; |
157 } else { |
114 updateAttributes(); |
158 final var selectedVersion = dao.getVersionDao().find(versionSelection.get()); |
115 } |
159 if (!Objects.equals(selectedVersion, version)) { |
116 |
160 issue = null; |
117 void selectIssue(Issue issue) { |
161 } |
118 this.project = issue.getProject(); |
162 selectVersion(selectedVersion); |
119 this.issue = issue; |
163 } |
120 this.version = null; |
164 } else { |
121 updateAttributes(); |
165 version = version == null ? null : dao.getVersionDao().find(version.getId()); |
122 } |
166 } |
123 |
167 } |
124 void updateAttributes() { |
168 |
|
169 void syncIssue() throws SQLException { |
|
170 final var issueSelection = getParameter(req, Integer.class, "issue"); |
|
171 if (issueSelection.isPresent()) { |
|
172 final var selectedIssue = dao.getIssueDao().find(issueSelection.get()); |
|
173 dao.getIssueDao().joinVersionInformation(selectedIssue); |
|
174 selectIssue(selectedIssue); |
|
175 } else { |
|
176 issue = issue == null ? null : dao.getIssueDao().find(issue.getId()); |
|
177 } |
|
178 } |
|
179 |
|
180 void sync() throws SQLException { |
|
181 project = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT); |
|
182 version = (Version) session.getAttribute(SESSION_ATTR_SELECTED_VERSION); |
|
183 issue = (Issue) session.getAttribute(SESSION_ATTR_SELECTED_ISSUE); |
|
184 |
|
185 syncProject(); |
|
186 syncVersion(); |
|
187 syncIssue(); |
|
188 |
|
189 updateAttributes(); |
|
190 } |
|
191 |
|
192 private void updateAttributes() { |
125 session.setAttribute(SESSION_ATTR_SELECTED_PROJECT, project); |
193 session.setAttribute(SESSION_ATTR_SELECTED_PROJECT, project); |
126 session.setAttribute(SESSION_ATTR_SELECTED_VERSION, version); |
194 session.setAttribute(SESSION_ATTR_SELECTED_VERSION, version); |
127 session.setAttribute(SESSION_ATTR_SELECTED_ISSUE, issue); |
195 session.setAttribute(SESSION_ATTR_SELECTED_ISSUE, issue); |
128 } |
196 } |
129 } |
|
130 |
|
131 private void setAttributeHideZeros(HttpServletRequest req) { |
|
132 final Boolean value; |
|
133 final var param = getParameter(req, Boolean.class, "reduced"); |
|
134 if (param.isPresent()) { |
|
135 value = param.get(); |
|
136 req.getSession().setAttribute(SESSION_ATTR_HIDE_ZEROS, value); |
|
137 } else { |
|
138 final var sessionValue = req.getSession().getAttribute(SESSION_ATTR_HIDE_ZEROS); |
|
139 if (sessionValue != null) { |
|
140 value = (Boolean) sessionValue; |
|
141 } else { |
|
142 value = false; |
|
143 req.getSession().setAttribute(SESSION_ATTR_HIDE_ZEROS, value); |
|
144 } |
|
145 } |
|
146 req.setAttribute("statsHideZeros", value); |
|
147 } |
197 } |
148 |
198 |
149 @Override |
199 @Override |
150 protected String getResourceBundleName() { |
200 protected String getResourceBundleName() { |
151 return "localization.projects"; |
201 return "localization.projects"; |
160 |
210 |
161 /** |
211 /** |
162 * Creates the breadcrumb menu. |
212 * Creates the breadcrumb menu. |
163 * |
213 * |
164 * @param level the current active level (0: root, 1: project, 2: version, 3: issue list, 4: issue) |
214 * @param level the current active level (0: root, 1: project, 2: version, 3: issue list, 4: issue) |
165 * @param sessionSelection the currently selected objects |
215 * @param selection the currently selected objects |
166 * @return a dynamic breadcrumb menu trying to display as many levels as possible |
216 * @return a dynamic breadcrumb menu trying to display as many levels as possible |
167 */ |
217 */ |
168 private List<MenuEntry> getBreadcrumbs(int level, SessionSelection sessionSelection) { |
218 private List<MenuEntry> getBreadcrumbs(int level, SessionSelection selection) { |
169 MenuEntry entry; |
219 MenuEntry entry; |
170 |
220 |
171 final var breadcrumbs = new ArrayList<MenuEntry>(); |
221 final var breadcrumbs = new ArrayList<MenuEntry>(); |
172 entry = new MenuEntry(new ResourceKey("localization.lightpit", "menu.projects"), |
222 entry = new MenuEntry(new ResourceKey("localization.lightpit", "menu.projects"), |
173 "projects/"); |
223 "projects/"); |
174 breadcrumbs.add(entry); |
224 breadcrumbs.add(entry); |
175 if (level == BREADCRUMB_LEVEL_ROOT) entry.setActive(true); |
225 if (level == BREADCRUMB_LEVEL_ROOT) entry.setActive(true); |
176 |
226 |
177 if (sessionSelection.project != null) { |
227 if (selection.project != null) { |
178 if (sessionSelection.project.getId() < 0) { |
228 if (selection.project.getId() < 0) { |
179 entry = new MenuEntry(new ResourceKey("localization.projects", "button.create"), |
229 entry = new MenuEntry(new ResourceKey("localization.projects", "button.create"), |
180 "projects/edit"); |
230 "projects/edit"); |
181 } else { |
231 } else { |
182 entry = new MenuEntry(sessionSelection.project.getName(), |
232 entry = new MenuEntry(selection.project.getName(), |
183 "projects/view?pid=" + sessionSelection.project.getId()); |
233 "projects/view?pid=" + selection.project.getId()); |
184 } |
234 } |
185 if (level == BREADCRUMB_LEVEL_PROJECT) entry.setActive(true); |
235 if (level == BREADCRUMB_LEVEL_PROJECT) entry.setActive(true); |
186 breadcrumbs.add(entry); |
236 breadcrumbs.add(entry); |
187 } |
237 } |
188 |
238 |
189 if (sessionSelection.version != null) { |
239 if (selection.version != null) { |
190 if (sessionSelection.version.getId() < 0) { |
240 if (selection.version.getId() < 0) { |
191 entry = new MenuEntry(new ResourceKey("localization.projects", "button.version.create"), |
241 entry = new MenuEntry(new ResourceKey("localization.projects", "button.version.create"), |
192 "projects/versions/edit"); |
242 "projects/versions/edit"); |
193 } else { |
243 } else { |
194 entry = new MenuEntry(sessionSelection.version.getName(), |
244 entry = new MenuEntry(selection.version.getName(), |
195 // TODO: change link to issue overview for that version |
245 "projects/versions/view?vid=" + selection.version.getId()); |
196 "projects/versions/edit?id=" + sessionSelection.version.getId()); |
|
197 } |
246 } |
198 if (level == BREADCRUMB_LEVEL_VERSION) entry.setActive(true); |
247 if (level == BREADCRUMB_LEVEL_VERSION) entry.setActive(true); |
199 breadcrumbs.add(entry); |
248 breadcrumbs.add(entry); |
200 } |
249 } |
201 |
250 |
202 if (sessionSelection.project != null) { |
251 if (selection.project != null) { |
|
252 String path = "projects/issues/?pid=" + selection.project.getId(); |
|
253 if (selection.version != null) { |
|
254 path += "&vid="+selection.version.getId(); |
|
255 } |
203 entry = new MenuEntry(new ResourceKey("localization.projects", "menu.issues"), |
256 entry = new MenuEntry(new ResourceKey("localization.projects", "menu.issues"), |
204 // TODO: maybe also add selected version |
257 path); |
205 "projects/issues/?pid=" + sessionSelection.project.getId()); |
|
206 if (level == BREADCRUMB_LEVEL_ISSUE_LIST) entry.setActive(true); |
258 if (level == BREADCRUMB_LEVEL_ISSUE_LIST) entry.setActive(true); |
207 breadcrumbs.add(entry); |
259 breadcrumbs.add(entry); |
208 } |
260 } |
209 |
261 |
210 if (sessionSelection.issue != null) { |
262 if (selection.issue != null) { |
211 if (sessionSelection.issue.getId() < 0) { |
263 if (selection.issue.getId() < 0) { |
212 entry = new MenuEntry(new ResourceKey("localization.projects", "button.issue.create"), |
264 entry = new MenuEntry(new ResourceKey("localization.projects", "button.issue.create"), |
213 "projects/issues/edit"); |
265 "projects/issues/edit"); |
214 } else { |
266 } else { |
215 entry = new MenuEntry("#" + sessionSelection.issue.getId(), |
267 entry = new MenuEntry("#" + selection.issue.getId(), |
216 // TODO: maybe change link to a view rather than directly opening the editor |
268 // TODO: maybe change link to a view rather than directly opening the editor |
217 "projects/issues/edit?id=" + sessionSelection.issue.getId()); |
269 "projects/issues/edit?issue=" + selection.issue.getId()); |
218 } |
270 } |
219 if (level == BREADCRUMB_LEVEL_ISSUE) entry.setActive(true); |
271 if (level == BREADCRUMB_LEVEL_ISSUE) entry.setActive(true); |
220 breadcrumbs.add(entry); |
272 breadcrumbs.add(entry); |
221 } |
273 } |
222 |
274 |
224 } |
276 } |
225 |
277 |
226 @RequestMapping(method = HttpMethod.GET) |
278 @RequestMapping(method = HttpMethod.GET) |
227 public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException { |
279 public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException { |
228 final var sessionSelection = new SessionSelection(req, dao); |
280 final var sessionSelection = new SessionSelection(req, dao); |
229 final var projectList = dao.getProjectDao().list(); |
281 sessionSelection.sync(); |
230 req.setAttribute("projects", projectList); |
282 |
|
283 final var projectDao = dao.getProjectDao(); |
|
284 final var versionDao = dao.getVersionDao(); |
|
285 |
|
286 final var projectList = projectDao.list(); |
|
287 |
|
288 final var viewModel = new ProjectIndexView(); |
|
289 for (var project : projectList) { |
|
290 final var info = new ProjectInfo(project); |
|
291 info.setVersions(versionDao.list(project)); |
|
292 info.setIssueSummary(projectDao.getIssueSummary(project)); |
|
293 viewModel.getProjects().add(info); |
|
294 } |
|
295 |
|
296 setViewModel(req, viewModel); |
231 setContentPage(req, "projects"); |
297 setContentPage(req, "projects"); |
232 setStylesheet(req, "projects"); |
298 setStylesheet(req, "projects"); |
233 |
299 |
234 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ROOT, sessionSelection)); |
300 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ROOT, sessionSelection)); |
235 |
301 |
236 return ResponseType.HTML; |
302 return ResponseType.HTML; |
237 } |
303 } |
238 |
304 |
239 private void configureEditForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { |
305 private ProjectEditView configureEditForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { |
240 req.setAttribute("project", selection.project); |
306 final var viewModel = new ProjectEditView(); |
241 req.setAttribute("users", dao.getUserDao().list()); |
307 viewModel.setProject(selection.project); |
|
308 viewModel.setUsers(dao.getUserDao().list()); |
|
309 setViewModel(req, viewModel); |
242 setContentPage(req, "project-form"); |
310 setContentPage(req, "project-form"); |
243 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_PROJECT, selection)); |
311 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_PROJECT, selection)); |
|
312 return viewModel; |
244 } |
313 } |
245 |
314 |
246 @RequestMapping(requestPath = "edit", method = HttpMethod.GET) |
315 @RequestMapping(requestPath = "edit", method = HttpMethod.GET) |
247 public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException { |
316 public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException { |
248 final var selection = new SessionSelection(req, findByParameter(req, Integer.class, "id", |
317 final var selection = new SessionSelection(req, dao); |
249 dao.getProjectDao()::find).orElse(new Project(-1))); |
318 if (getParameter(req, Integer.class, "pid").isEmpty()) { |
|
319 selection.newProject(); |
|
320 } else { |
|
321 selection.sync(); |
|
322 } |
250 |
323 |
251 configureEditForm(req, dao, selection); |
324 configureEditForm(req, dao, selection); |
252 |
325 |
253 return ResponseType.HTML; |
326 return ResponseType.HTML; |
254 } |
327 } |
270 |
343 |
271 setRedirectLocation(req, "./projects/"); |
344 setRedirectLocation(req, "./projects/"); |
272 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); |
345 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); |
273 LOG.debug("Successfully updated project {}", project.getName()); |
346 LOG.debug("Successfully updated project {}", project.getName()); |
274 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { |
347 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { |
275 // TODO: set request attribute with error text |
|
276 LOG.warn("Form validation failure: {}", ex.getMessage()); |
348 LOG.warn("Form validation failure: {}", ex.getMessage()); |
277 LOG.debug("Details:", ex); |
349 LOG.debug("Details:", ex); |
278 configureEditForm(req, dao, new SessionSelection(req, project)); |
350 final var selection = new SessionSelection(req, dao); |
|
351 selection.project = project; |
|
352 final var vm = configureEditForm(req, dao, selection); |
|
353 vm.setErrorText(ex.getMessage()); // TODO: error text |
279 } |
354 } |
280 |
355 |
281 return ResponseType.HTML; |
356 return ResponseType.HTML; |
282 } |
357 } |
283 |
358 |
284 @RequestMapping(requestPath = "view", method = HttpMethod.GET) |
359 @RequestMapping(requestPath = "view", method = HttpMethod.GET) |
285 public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { |
360 public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { |
286 final var sessionSelection = new SessionSelection(req, dao); |
361 final var selection = new SessionSelection(req, dao); |
287 if (sessionSelection.project == null) { |
362 selection.sync(); |
|
363 |
|
364 if (selection.project == null) { |
288 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected."); |
365 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected."); |
289 return ResponseType.NONE; |
366 return ResponseType.NONE; |
290 } |
367 } |
291 |
368 |
292 final var versionDao = dao.getVersionDao(); |
369 final var versionDao = dao.getVersionDao(); |
293 final var versions = versionDao.list(sessionSelection.project); |
370 final var issueDao = dao.getIssueDao(); |
294 final var statsAffected = new ArrayList<VersionStatistics>(); |
371 |
295 final var statsScheduled = new ArrayList<VersionStatistics>(); |
372 final var viewModel = new ProjectView(selection.project); |
296 final var statsResolved = new ArrayList<VersionStatistics>(); |
373 final var issues = issueDao.list(selection.project); |
297 for (Version version : versions) { |
374 for (var issue : issues) issueDao.joinVersionInformation(issue); |
298 statsAffected.add(versionDao.statsOpenedIssues(version)); |
375 viewModel.setIssues(issues); |
299 statsScheduled.add(versionDao.statsScheduledIssues(version)); |
376 viewModel.setVersions(versionDao.list(selection.project)); |
300 statsResolved.add(versionDao.statsResolvedIssues(version)); |
377 viewModel.updateVersionInfo(); |
301 } |
378 setViewModel(req, viewModel); |
302 |
379 |
303 setAttributeHideZeros(req); |
380 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_PROJECT, selection)); |
304 |
|
305 req.setAttribute("project", sessionSelection.project); |
|
306 req.setAttribute("versions", versions); |
|
307 req.setAttribute("statsAffected", statsAffected); |
|
308 req.setAttribute("statsScheduled", statsScheduled); |
|
309 req.setAttribute("statsResolved", statsResolved); |
|
310 |
|
311 req.setAttribute("issueStatusEnum", IssueStatus.values()); |
|
312 req.setAttribute("issueCategoryEnum", IssueCategory.values()); |
|
313 |
|
314 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_PROJECT, sessionSelection)); |
|
315 setContentPage(req, "project-details"); |
381 setContentPage(req, "project-details"); |
316 setStylesheet(req, "projects"); |
382 setStylesheet(req, "projects"); |
317 |
383 |
318 return ResponseType.HTML; |
384 return ResponseType.HTML; |
319 } |
385 } |
320 |
386 |
321 private void configureEditVersionForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { |
387 @RequestMapping(requestPath = "versions/view", method = HttpMethod.GET) |
322 final var versionDao = dao.getVersionDao(); |
388 public ResponseType viewVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { |
323 req.setAttribute("projects", dao.getProjectDao().list()); |
389 final var selection = new SessionSelection(req, dao); |
324 req.setAttribute("version", selection.version); |
390 selection.sync(); |
325 req.setAttribute("versionStatusEnum", VersionStatus.values()); |
391 if (selection.version == null) { |
326 |
392 resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
327 req.setAttribute("issueStatusEnum", IssueStatus.values()); |
393 return ResponseType.NONE; |
328 req.setAttribute("issueCategoryEnum", IssueCategory.values()); |
394 } |
329 req.setAttribute("statsAffected", versionDao.statsOpenedIssues(selection.version)); |
395 |
330 req.setAttribute("statsScheduled", versionDao.statsScheduledIssues(selection.version)); |
396 final var issueDao = dao.getIssueDao(); |
331 req.setAttribute("statsResolved", versionDao.statsResolvedIssues(selection.version)); |
397 final var viewModel = new VersionView(selection.version); |
332 setAttributeHideZeros(req); |
398 final var issues = issueDao.list(selection.version); |
333 |
399 for (var issue : issues) issueDao.joinVersionInformation(issue); |
|
400 viewModel.setIssues(issues); |
|
401 setViewModel(req, viewModel); |
|
402 |
|
403 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_VERSION, selection)); |
|
404 setContentPage(req, "version"); |
|
405 setStylesheet(req, "projects"); |
|
406 |
|
407 return ResponseType.HTML; |
|
408 } |
|
409 |
|
410 private VersionEditView configureEditVersionForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { |
|
411 final var viewModel = new VersionEditView(selection.version); |
|
412 if (selection.version.getProject() == null) { |
|
413 viewModel.setProjects(dao.getProjectDao().list()); |
|
414 } |
|
415 setViewModel(req, viewModel); |
334 setContentPage(req, "version-form"); |
416 setContentPage(req, "version-form"); |
335 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_VERSION, selection)); |
417 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_VERSION, selection)); |
|
418 return viewModel; |
336 } |
419 } |
337 |
420 |
338 @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET) |
421 @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET) |
339 public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { |
422 public ResponseType editVersion(HttpServletRequest req, DataAccessObjects dao) throws SQLException { |
340 final var sessionSelection = new SessionSelection(req, dao); |
423 final var selection = new SessionSelection(req, dao); |
341 |
424 if (getParameter(req, Integer.class, "vid").isEmpty()) { |
342 sessionSelection.selectVersion(findByParameter(req, Integer.class, "id", dao.getVersionDao()::find) |
425 selection.newVersion(); |
343 .orElse(new Version(-1, sessionSelection.project))); |
426 } else { |
344 configureEditVersionForm(req, dao, sessionSelection); |
427 selection.sync(); |
|
428 } |
|
429 |
|
430 configureEditVersionForm(req, dao, selection); |
345 |
431 |
346 return ResponseType.HTML; |
432 return ResponseType.HTML; |
347 } |
433 } |
348 |
434 |
349 @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST) |
435 @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST) |
350 public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { |
436 public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { |
351 final var sessionSelection = new SessionSelection(req, dao); |
437 |
352 |
438 var version = new Version(-1); |
353 var version = new Version(-1, sessionSelection.project); |
|
354 try { |
439 try { |
355 version = new Version(getParameter(req, Integer.class, "id").orElseThrow(), sessionSelection.project); |
440 version = new Version(getParameter(req, Integer.class, "id").orElseThrow()); |
|
441 version.setProject(new Project(getParameter(req, Integer.class, "pid").orElseThrow())); |
356 version.setName(getParameter(req, String.class, "name").orElseThrow()); |
442 version.setName(getParameter(req, String.class, "name").orElseThrow()); |
357 getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal); |
443 getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal); |
358 version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow())); |
444 version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow())); |
359 dao.getVersionDao().saveOrUpdate(version); |
445 dao.getVersionDao().saveOrUpdate(version); |
360 |
446 |
361 // specifying the pid parameter will purposely reset the session selected version! |
447 // specifying the pid parameter will purposely reset the session selected version! |
362 setRedirectLocation(req, "./projects/view?pid="+sessionSelection.project.getId()); |
448 setRedirectLocation(req, "./projects/view?pid="+version.getProject().getId()); |
363 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); |
449 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); |
364 LOG.debug("Successfully updated version {} for project {}", version.getName(), sessionSelection.project.getName()); |
|
365 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { |
450 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { |
366 // TODO: set request attribute with error text |
|
367 LOG.warn("Form validation failure: {}", ex.getMessage()); |
451 LOG.warn("Form validation failure: {}", ex.getMessage()); |
368 LOG.debug("Details:", ex); |
452 LOG.debug("Details:", ex); |
369 sessionSelection.selectVersion(version); |
453 final var selection = new SessionSelection(req, dao); |
370 configureEditVersionForm(req, dao, sessionSelection); |
454 selection.selectVersion(version); |
371 } |
455 final var viewModel = configureEditVersionForm(req, dao, selection); |
372 |
456 // TODO: set Error Text |
373 return ResponseType.HTML; |
457 } |
374 } |
458 |
375 |
459 return ResponseType.HTML; |
376 private void configureEditIssueForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { |
460 } |
377 |
461 |
378 if (selection.issue.getProject() == null || selection.issue.getProject().getId() < 0) { |
462 private IssueEditView configureEditIssueForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { |
379 req.setAttribute("projects", dao.getProjectDao().list()); |
463 final var viewModel = new IssueEditView(selection.issue); |
380 req.setAttribute("versions", Collections.<Version>emptyList()); |
464 |
|
465 if (selection.issue.getProject() == null) { |
|
466 viewModel.setProjects(dao.getProjectDao().list()); |
381 } else { |
467 } else { |
382 req.setAttribute("projects", Collections.<Project>emptyList()); |
468 viewModel.setVersions(dao.getVersionDao().list(selection.issue.getProject())); |
383 req.setAttribute("versions", dao.getVersionDao().list(selection.issue.getProject())); |
469 } |
384 } |
470 viewModel.setUsers(dao.getUserDao().list()); |
385 |
471 setViewModel(req, viewModel); |
386 dao.getIssueDao().joinVersionInformation(selection.issue); |
|
387 req.setAttribute("issue", selection.issue); |
|
388 req.setAttribute("issueStatusEnum", IssueStatus.values()); |
|
389 req.setAttribute("issueCategoryEnum", IssueCategory.values()); |
|
390 req.setAttribute("users", dao.getUserDao().list()); |
|
391 |
472 |
392 setContentPage(req, "issue-form"); |
473 setContentPage(req, "issue-form"); |
393 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ISSUE, selection)); |
474 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ISSUE, selection)); |
|
475 return viewModel; |
394 } |
476 } |
395 |
477 |
396 @RequestMapping(requestPath = "issues/", method = HttpMethod.GET) |
478 @RequestMapping(requestPath = "issues/", method = HttpMethod.GET) |
397 public ResponseType issues(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { |
479 public ResponseType issues(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { |
398 final var sessionSelection = new SessionSelection(req, dao); |
480 final var selection = new SessionSelection(req, dao); |
399 if (sessionSelection.project == null) { |
481 selection.sync(); |
|
482 if (selection.project == null) { |
400 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected."); |
483 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected."); |
401 return ResponseType.NONE; |
484 return ResponseType.NONE; |
402 } |
485 } |
403 |
486 |
404 req.setAttribute("issues", dao.getIssueDao().list(sessionSelection.project)); |
487 final var viewModel = new IssuesView(); |
405 |
488 viewModel.setProject(selection.project); |
406 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ISSUE_LIST, sessionSelection)); |
489 if (selection.version == null) { |
|
490 viewModel.setIssues(dao.getIssueDao().list(selection.project)); |
|
491 } else { |
|
492 viewModel.setVersion(selection.version); |
|
493 viewModel.setIssues(dao.getIssueDao().list(selection.version)); |
|
494 } |
|
495 setViewModel(req, viewModel); |
|
496 |
|
497 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ISSUE_LIST, selection)); |
407 setContentPage(req, "issues"); |
498 setContentPage(req, "issues"); |
408 setStylesheet(req, "projects"); |
499 setStylesheet(req, "projects"); |
409 |
500 |
410 return ResponseType.HTML; |
501 return ResponseType.HTML; |
411 } |
502 } |
412 |
503 |
413 @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET) |
504 @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET) |
414 public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { |
505 public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { |
415 final var sessionSelection = new SessionSelection(req, dao); |
506 final var selection = new SessionSelection(req, dao); |
416 |
507 if (getParameter(req, Integer.class, "issue").isEmpty()) { |
417 sessionSelection.selectIssue(findByParameter(req, Integer.class, "id", |
508 selection.newIssue(); |
418 dao.getIssueDao()::find).orElse(new Issue(-1, sessionSelection.project))); |
509 } else { |
419 configureEditIssueForm(req, dao, sessionSelection); |
510 selection.sync(); |
|
511 } |
|
512 |
|
513 configureEditIssueForm(req, dao, selection); |
420 |
514 |
421 return ResponseType.HTML; |
515 return ResponseType.HTML; |
422 } |
516 } |
423 |
517 |
424 @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST) |
518 @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST) |
425 public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { |
519 public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { |
426 final var sessionSelection = new SessionSelection(req, dao); |
520 |
427 |
521 Issue issue = new Issue(-1); |
428 Issue issue = new Issue(-1, sessionSelection.project); |
|
429 try { |
522 try { |
430 issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow(), sessionSelection.project); |
523 issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow()); |
|
524 issue.setProject(new Project(getParameter(req, Integer.class, "pid").orElseThrow())); |
431 getParameter(req, String.class, "category").map(IssueCategory::valueOf).ifPresent(issue::setCategory); |
525 getParameter(req, String.class, "category").map(IssueCategory::valueOf).ifPresent(issue::setCategory); |
432 getParameter(req, String.class, "status").map(IssueStatus::valueOf).ifPresent(issue::setStatus); |
526 getParameter(req, String.class, "status").map(IssueStatus::valueOf).ifPresent(issue::setStatus); |
433 issue.setSubject(getParameter(req, String.class, "subject").orElseThrow()); |
527 issue.setSubject(getParameter(req, String.class, "subject").orElseThrow()); |
434 getParameter(req, Integer.class, "assignee").map( |
528 getParameter(req, Integer.class, "assignee").map( |
435 userid -> userid >= 0 ? new User(userid) : null |
529 userid -> userid >= 0 ? new User(userid) : null |