82 viewModel.setProjectInfo(info); |
84 viewModel.setProjectInfo(info); |
83 } |
85 } |
84 } |
86 } |
85 |
87 |
86 // Select Version |
88 // Select Version |
87 final int vid = Functions.parseIntOrZero(pathParameters.get("version")); |
89 final var pathParamVersion = pathParameters.get("version"); |
88 if (vid > 0) { |
90 if ("no-version".equals(pathParamVersion)) { |
89 viewModel.setVersionFilter(versionDao.find(vid)); |
91 viewModel.setVersionFilter(ProjectView.NO_VERSION); |
90 } |
92 } else if ("all-versions".equals(pathParamVersion)) { |
91 // TODO: don't treat unknown == unassigned - send 404 for unknown and introduce special word for unassigned |
93 viewModel.setVersionFilter(ProjectView.ALL_VERSIONS); |
|
94 } else { |
|
95 final int vid = Functions.parseIntOrZero(pathParamVersion); |
|
96 if (vid > 0) { |
|
97 viewModel.setVersionFilter(versionDao.find(vid)); |
|
98 } |
|
99 } |
92 |
100 |
93 // Select Component |
101 // Select Component |
94 final int cid = Functions.parseIntOrZero(pathParameters.get("component")); |
102 final var pathParamComponent = pathParameters.get("component"); |
95 if (cid > 0) { |
103 if ("no-component".equals(pathParamComponent)) { |
96 viewModel.setComponentFilter(componentDao.find(cid)); |
104 viewModel.setComponentFilter(ProjectView.NO_COMPONENT); |
97 } |
105 } else if ("all-components".equals(pathParamComponent)) { |
98 |
106 viewModel.setComponentFilter(ProjectView.ALL_COMPONENTS); |
99 // TODO: distinguish all/unassigned for components |
107 } else { |
|
108 final int cid = Functions.parseIntOrZero(pathParamComponent); |
|
109 if (cid > 0) { |
|
110 viewModel.setComponentFilter(componentDao.find(cid)); |
|
111 } |
|
112 } |
100 } |
113 } |
101 |
114 |
102 private ResponseType forwardView(HttpServletRequest req, ProjectView viewModel, String name) { |
115 private ResponseType forwardView(HttpServletRequest req, ProjectView viewModel, String name) { |
103 setViewModel(req, viewModel); |
116 setViewModel(req, viewModel); |
104 setContentPage(req, name); |
117 setContentPage(req, name); |
131 @RequestMapping(requestPath = "$project/edit", method = HttpMethod.GET) |
144 @RequestMapping(requestPath = "$project/edit", method = HttpMethod.GET) |
132 public ResponseType edit(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParams, DataAccessObjects dao) throws IOException, SQLException { |
145 public ResponseType edit(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParams, DataAccessObjects dao) throws IOException, SQLException { |
133 final var viewModel = new ProjectEditView(); |
146 final var viewModel = new ProjectEditView(); |
134 populate(viewModel, pathParams, dao); |
147 populate(viewModel, pathParams, dao); |
135 |
148 |
136 if (viewModel.getProjectInfo() == null) { |
149 if (!viewModel.isProjectInfoPresent()) { |
137 resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
150 resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
138 return ResponseType.NONE; |
151 return ResponseType.NONE; |
139 } |
152 } |
140 |
153 |
141 configureProjectEditor(viewModel, viewModel.getProjectInfo().getProject(), dao); |
154 configureProjectEditor(viewModel, viewModel.getProjectInfo().getProject(), dao); |
174 // TODO: implement - fix issue #21 |
187 // TODO: implement - fix issue #21 |
175 return ResponseType.NONE; |
188 return ResponseType.NONE; |
176 } |
189 } |
177 } |
190 } |
178 |
191 |
179 @RequestMapping(requestPath = "$project/versions/$version", method = HttpMethod.GET) |
192 @RequestMapping(requestPath = "$project/$component/$version/issues/", method = HttpMethod.GET) |
180 public ResponseType view(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParams, DataAccessObjects dao) throws SQLException, IOException { |
193 public ResponseType issues(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParams, DataAccessObjects dao) throws SQLException, IOException { |
181 final var viewModel = new ProjectDetailsView(); |
194 final var viewModel = new ProjectDetailsView(); |
182 populate(viewModel, pathParams, dao); |
195 populate(viewModel, pathParams, dao); |
|
196 |
|
197 if (!viewModel.isEveryFilterValid()) { |
|
198 resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
|
199 return ResponseType.NONE; |
|
200 } |
|
201 |
|
202 final var project = viewModel.getProjectInfo().getProject(); |
183 final var version = viewModel.getVersionFilter(); |
203 final var version = viewModel.getVersionFilter(); |
184 |
204 final var component = viewModel.getComponentFilter(); |
185 if (viewModel.getProjectInfo() == null || version == null) { |
|
186 resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
|
187 return ResponseType.NONE; |
|
188 } |
|
189 |
205 |
190 final var issueDao = dao.getIssueDao(); |
206 final var issueDao = dao.getIssueDao(); |
191 |
207 |
192 final var detailView = viewModel.getProjectDetails(); |
208 final List<Issue> issues; |
193 final var issues = issueDao.list(version); |
209 if (version.equals(ProjectView.NO_VERSION)) { |
|
210 if (component.equals(ProjectView.ALL_COMPONENTS)) { |
|
211 issues = issueDao.list(project, (Version) null); |
|
212 } else if (component.equals(ProjectView.NO_COMPONENT)) { |
|
213 issues = issueDao.list(project, null, null); |
|
214 } else { |
|
215 issues = issueDao.list(project, component, null); |
|
216 } |
|
217 } else if (version.equals(ProjectView.ALL_VERSIONS)) { |
|
218 if (component.equals(ProjectView.ALL_COMPONENTS)) { |
|
219 issues = issueDao.list(project); |
|
220 } else if (component.equals(ProjectView.NO_COMPONENT)) { |
|
221 issues = issueDao.list(project, (Component)null); |
|
222 } else { |
|
223 issues = issueDao.list(project, component); |
|
224 } |
|
225 } else { |
|
226 if (component.equals(ProjectView.ALL_COMPONENTS)) { |
|
227 issues = issueDao.list(project, version); |
|
228 } else if (component.equals(ProjectView.NO_COMPONENT)) { |
|
229 issues = issueDao.list(project, null, version); |
|
230 } else { |
|
231 issues = issueDao.list(project, component, version); |
|
232 } |
|
233 } |
|
234 |
194 for (var issue : issues) issueDao.joinVersionInformation(issue); |
235 for (var issue : issues) issueDao.joinVersionInformation(issue); |
195 issues.sort(new IssueSorter( |
236 issues.sort(new IssueSorter( |
196 new IssueSorter.Criteria(IssueSorter.Field.PHASE, true), |
237 new IssueSorter.Criteria(IssueSorter.Field.PHASE, true), |
197 new IssueSorter.Criteria(IssueSorter.Field.ETA, true), |
238 new IssueSorter.Criteria(IssueSorter.Field.ETA, true), |
198 new IssueSorter.Criteria(IssueSorter.Field.UPDATED, false) |
239 new IssueSorter.Criteria(IssueSorter.Field.UPDATED, false) |
199 )); |
240 )); |
200 detailView.updateDetails(issues, version); |
241 |
|
242 |
|
243 viewModel.getProjectDetails().updateDetails(issues); |
|
244 if (version.getId() > 0) |
|
245 viewModel.getProjectDetails().updateVersionInfo(version); |
201 |
246 |
202 return forwardView(req, viewModel, "project-details"); |
247 return forwardView(req, viewModel, "project-details"); |
203 } |
248 } |
204 |
249 |
205 @RequestMapping(requestPath = "$project/versions/", method = HttpMethod.GET) |
250 @RequestMapping(requestPath = "$project/versions/", method = HttpMethod.GET) |
260 version.setName(getParameter(req, String.class, "name").orElseThrow()); |
305 version.setName(getParameter(req, String.class, "name").orElseThrow()); |
261 getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal); |
306 getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal); |
262 version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow())); |
307 version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow())); |
263 dao.getVersionDao().saveOrUpdate(version, project); |
308 dao.getVersionDao().saveOrUpdate(version, project); |
264 |
309 |
265 // TODO: improve building the redirect location |
|
266 setRedirectLocation(req, "./projects/" + project.getId() + "/versions/"); |
310 setRedirectLocation(req, "./projects/" + project.getId() + "/versions/"); |
267 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); |
311 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); |
268 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { |
312 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { |
269 resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED); |
313 resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED); |
270 // TODO: implement - fix issue #21 |
314 // TODO: implement - fix issue #21 |
272 } |
316 } |
273 |
317 |
274 return ResponseType.HTML; |
318 return ResponseType.HTML; |
275 } |
319 } |
276 |
320 |
|
321 @RequestMapping(requestPath = "$project/components/", method = HttpMethod.GET) |
|
322 public ResponseType components(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DataAccessObjects dao) throws IOException, SQLException { |
|
323 final var viewModel = new ComponentsView(); |
|
324 populate(viewModel, pathParameters, dao); |
|
325 |
|
326 final var projectInfo = viewModel.getProjectInfo(); |
|
327 if (projectInfo == null) { |
|
328 resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
|
329 return ResponseType.NONE; |
|
330 } |
|
331 |
|
332 final var issueDao = dao.getIssueDao(); |
|
333 final var issues = issueDao.list(projectInfo.getProject()); |
|
334 viewModel.update(projectInfo.getComponents(), issues); |
|
335 |
|
336 return forwardView(req, viewModel, "components"); |
|
337 } |
|
338 |
|
339 @RequestMapping(requestPath = "$project/components/$component/edit", method = HttpMethod.GET) |
|
340 public ResponseType editComponent(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DataAccessObjects dao) throws IOException, SQLException { |
|
341 final var viewModel = new ComponentEditView(); |
|
342 populate(viewModel, pathParameters, dao); |
|
343 |
|
344 if (viewModel.getProjectInfo() == null || viewModel.getComponentFilter() == null) { |
|
345 resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
|
346 return ResponseType.NONE; |
|
347 } |
|
348 |
|
349 viewModel.setComponent(viewModel.getComponentFilter()); |
|
350 viewModel.setUsers(dao.getUserDao().list()); |
|
351 |
|
352 return forwardView(req, viewModel, "component-form"); |
|
353 } |
|
354 |
|
355 @RequestMapping(requestPath = "$project/create-component", method = HttpMethod.GET) |
|
356 public ResponseType createComponent(HttpServletRequest req, HttpServletResponse resp, PathParameters pathParameters, DataAccessObjects dao) throws IOException, SQLException { |
|
357 final var viewModel = new ComponentEditView(); |
|
358 populate(viewModel, pathParameters, dao); |
|
359 |
|
360 if (viewModel.getProjectInfo() == null) { |
|
361 resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
|
362 return ResponseType.NONE; |
|
363 } |
|
364 |
|
365 viewModel.setComponent(new Component(-1)); |
|
366 viewModel.setUsers(dao.getUserDao().list()); |
|
367 |
|
368 return forwardView(req, viewModel, "component-form"); |
|
369 } |
|
370 |
|
371 @RequestMapping(requestPath = "commit-component", method = HttpMethod.POST) |
|
372 public ResponseType commitComponent(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException { |
|
373 |
|
374 try { |
|
375 final var project = new Project(getParameter(req, Integer.class, "pid").orElseThrow()); |
|
376 final var component = new Component(getParameter(req, Integer.class, "id").orElseThrow()); |
|
377 component.setName(getParameter(req, String.class, "name").orElseThrow()); |
|
378 component.setColor(getParameter(req, WebColor.class, "color").orElseThrow()); |
|
379 getParameter(req, Integer.class, "ordinal").ifPresent(component::setOrdinal); |
|
380 getParameter(req, Integer.class, "lead").map( |
|
381 userid -> userid >= 0 ? new User(userid) : null |
|
382 ).ifPresent(component::setLead); |
|
383 getParameter(req, String.class, "description").ifPresent(component::setDescription); |
|
384 |
|
385 dao.getComponentDao().saveOrUpdate(component, project); |
|
386 |
|
387 setRedirectLocation(req, "./projects/" + project.getId() + "/components/"); |
|
388 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); |
|
389 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { |
|
390 resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED); |
|
391 // TODO: implement - fix issue #21 |
|
392 return ResponseType.NONE; |
|
393 } |
|
394 |
|
395 return ResponseType.HTML; |
|
396 } |
|
397 |
277 private void configureIssueEditor(IssueEditView viewModel, Issue issue, DataAccessObjects dao) throws SQLException { |
398 private void configureIssueEditor(IssueEditView viewModel, Issue issue, DataAccessObjects dao) throws SQLException { |
278 issue.setProject(viewModel.getProjectInfo().getProject()); |
399 final var project = viewModel.getProjectInfo().getProject(); |
|
400 issue.setProject(project); |
279 viewModel.setIssue(issue); |
401 viewModel.setIssue(issue); |
280 viewModel.configureVersionSelectors(viewModel.getProjectInfo().getVersions()); |
402 viewModel.configureVersionSelectors(viewModel.getProjectInfo().getVersions()); |
281 viewModel.setUsers(dao.getUserDao().list()); |
403 viewModel.setUsers(dao.getUserDao().list()); |
|
404 viewModel.setComponents(dao.getComponentDao().list(project)); |
282 if (issue.getId() >= 0) { |
405 if (issue.getId() >= 0) { |
283 viewModel.setComments(dao.getIssueDao().listComments(issue)); |
406 viewModel.setComments(dao.getIssueDao().listComments(issue)); |
284 } |
407 } |
285 } |
408 } |
286 |
409 |
335 getParameter(req, String.class, "status").map(IssueStatus::valueOf).ifPresent(issue::setStatus); |
458 getParameter(req, String.class, "status").map(IssueStatus::valueOf).ifPresent(issue::setStatus); |
336 issue.setSubject(getParameter(req, String.class, "subject").orElseThrow()); |
459 issue.setSubject(getParameter(req, String.class, "subject").orElseThrow()); |
337 getParameter(req, Integer.class, "assignee").map( |
460 getParameter(req, Integer.class, "assignee").map( |
338 userid -> userid >= 0 ? new User(userid) : null |
461 userid -> userid >= 0 ? new User(userid) : null |
339 ).ifPresent(issue::setAssignee); |
462 ).ifPresent(issue::setAssignee); |
|
463 getParameter(req, Integer.class, "component").map( |
|
464 cid -> cid >= 0 ? new Component(cid) : null |
|
465 ).ifPresent(issue::setComponent); |
340 getParameter(req, String.class, "description").ifPresent(issue::setDescription); |
466 getParameter(req, String.class, "description").ifPresent(issue::setDescription); |
341 getParameter(req, Date.class, "eta").ifPresent(issue::setEta); |
467 getParameter(req, Date.class, "eta").ifPresent(issue::setEta); |
342 |
468 |
343 getParameter(req, Integer[].class, "affected") |
469 getParameter(req, Integer[].class, "affected") |
344 .map(Stream::of) |
470 .map(Stream::of) |
352 ).ifPresent(issue::setResolvedVersions); |
478 ).ifPresent(issue::setResolvedVersions); |
353 |
479 |
354 dao.getIssueDao().saveOrUpdate(issue, issue.getProject()); |
480 dao.getIssueDao().saveOrUpdate(issue, issue.getProject()); |
355 |
481 |
356 // TODO: fix issue #14 |
482 // TODO: fix issue #14 |
357 setRedirectLocation(req, "./projects/" + issue.getProject().getId() + "/versions/"); |
483 setRedirectLocation(req, "./projects/" + issue.getProject().getId() + "/all-components/all-versions/issues/"); |
358 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); |
484 setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL); |
359 |
485 |
360 return ResponseType.HTML; |
486 return ResponseType.HTML; |
361 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { |
487 } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) { |
362 resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED); |
488 resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED); |