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

changeset 80
27a25f32048e
parent 79
f64255a88d66
child 81
1a2e7b5d48f7
equal deleted inserted replaced
79:f64255a88d66 80:27a25f32048e
55 ) 55 )
56 public final class ProjectsModule extends AbstractLightPITServlet { 56 public final class ProjectsModule extends AbstractLightPITServlet {
57 57
58 private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class); 58 private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class);
59 59
60 public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected-project"); 60 public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project");
61 public static final String SESSION_ATTR_SELECTED_ISSUE = fqn(ProjectsModule.class, "selected-issue"); 61 public static final String SESSION_ATTR_SELECTED_ISSUE = fqn(ProjectsModule.class, "selected_issue");
62 public static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected-version"); 62 public static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected_version");
63 public static final String SESSION_ATTR_HIDE_ZEROS = fqn(ProjectsModule.class, "stats_hide_zeros");
63 64
64 private class SessionSelection { 65 private class SessionSelection {
65 final HttpSession session; 66 final HttpSession session;
66 Project project; 67 Project project;
67 Version version; 68 Version version;
126 session.setAttribute(SESSION_ATTR_SELECTED_VERSION, version); 127 session.setAttribute(SESSION_ATTR_SELECTED_VERSION, version);
127 session.setAttribute(SESSION_ATTR_SELECTED_ISSUE, issue); 128 session.setAttribute(SESSION_ATTR_SELECTED_ISSUE, issue);
128 } 129 }
129 } 130 }
130 131
132 private void setAttributeHideZeros(HttpServletRequest req) {
133 final Boolean value;
134 final var param = getParameter(req, Boolean.class, "reduced");
135 if (param.isPresent()) {
136 value = param.get();
137 req.getSession().setAttribute(SESSION_ATTR_HIDE_ZEROS, value);
138 } else {
139 final var sessionValue = req.getSession().getAttribute(SESSION_ATTR_HIDE_ZEROS);
140 if (sessionValue != null) {
141 value = (Boolean) sessionValue;
142 } else {
143 value = false;
144 req.getSession().setAttribute(SESSION_ATTR_HIDE_ZEROS, value);
145 }
146 }
147 req.setAttribute("statsHideZeros", value);
148 }
149
131 @Override 150 @Override
132 protected String getResourceBundleName() { 151 protected String getResourceBundleName() {
133 return "localization.projects"; 152 return "localization.projects";
134 } 153 }
135 154
155
156 private static final int BREADCRUMB_LEVEL_ROOT = 0;
157 private static final int BREADCRUMB_LEVEL_PROJECT = 1;
158 private static final int BREADCRUMB_LEVEL_VERSION = 2;
159 private static final int BREADCRUMB_LEVEL_ISSUE_LIST = 3;
160 private static final int BREADCRUMB_LEVEL_ISSUE = 4;
161
136 /** 162 /**
137 * Creates the breadcrumb menu. 163 * Creates the breadcrumb menu.
138 * 164 *
139 * @param level the current active level (0: root, 1: project, 2: version, 3: issue) 165 * @param level the current active level (0: root, 1: project, 2: version, 3: issue list, 4: issue)
140 * @param sessionSelection the currently selected objects 166 * @param sessionSelection the currently selected objects
141 * @return a dynamic breadcrumb menu trying to display as many levels as possible 167 * @return a dynamic breadcrumb menu trying to display as many levels as possible
142 */ 168 */
143 private List<MenuEntry> getBreadcrumbs(int level, SessionSelection sessionSelection) { 169 private List<MenuEntry> getBreadcrumbs(int level, SessionSelection sessionSelection) {
144 MenuEntry entry; 170 MenuEntry entry;
145 171
146 final var breadcrumbs = new ArrayList<MenuEntry>(); 172 final var breadcrumbs = new ArrayList<MenuEntry>();
147 entry = new MenuEntry(new ResourceKey("localization.lightpit", "menu.projects"), 173 entry = new MenuEntry(new ResourceKey("localization.lightpit", "menu.projects"),
148 "projects/"); 174 "projects/");
149 breadcrumbs.add(entry); 175 breadcrumbs.add(entry);
150 if (level == 0) entry.setActive(true); 176 if (level == BREADCRUMB_LEVEL_ROOT) entry.setActive(true);
151 177
152 if (sessionSelection.project != null) { 178 if (sessionSelection.project != null) {
153 if (sessionSelection.project.getId() < 0) { 179 if (sessionSelection.project.getId() < 0) {
154 entry = new MenuEntry(new ResourceKey("localization.projects", "button.create"), 180 entry = new MenuEntry(new ResourceKey("localization.projects", "button.create"),
155 "projects/edit"); 181 "projects/edit");
156 } else { 182 } else {
157 entry = new MenuEntry(sessionSelection.project.getName(), 183 entry = new MenuEntry(sessionSelection.project.getName(),
158 "projects/view?pid=" + sessionSelection.project.getId()); 184 "projects/view?pid=" + sessionSelection.project.getId());
159 } 185 }
160 if (level == 1) entry.setActive(true); 186 if (level == BREADCRUMB_LEVEL_PROJECT) entry.setActive(true);
161 breadcrumbs.add(entry); 187 breadcrumbs.add(entry);
162 } 188 }
163 189
164 if (sessionSelection.version != null) { 190 if (sessionSelection.version != null) {
165 if (sessionSelection.version.getId() < 0) { 191 if (sessionSelection.version.getId() < 0) {
168 } else { 194 } else {
169 entry = new MenuEntry(sessionSelection.version.getName(), 195 entry = new MenuEntry(sessionSelection.version.getName(),
170 // TODO: change link to issue overview for that version 196 // TODO: change link to issue overview for that version
171 "projects/versions/edit?id=" + sessionSelection.version.getId()); 197 "projects/versions/edit?id=" + sessionSelection.version.getId());
172 } 198 }
173 if (level == 2) entry.setActive(true); 199 if (level == BREADCRUMB_LEVEL_VERSION) entry.setActive(true);
174 breadcrumbs.add(entry); 200 breadcrumbs.add(entry);
175 } 201 }
176 202
203 if (sessionSelection.project != null) {
204 entry = new MenuEntry(new ResourceKey("localization.projects", "menu.issues"),
205 // TODO: maybe also add selected version
206 "projects/issues/?pid=" + sessionSelection.project.getId());
207 if (level == BREADCRUMB_LEVEL_ISSUE_LIST) entry.setActive(true);
208 breadcrumbs.add(entry);
209 }
210
177 if (sessionSelection.issue != null) { 211 if (sessionSelection.issue != null) {
178 entry = new MenuEntry(new ResourceKey("localization.projects", "menu.issues"),
179 // TODO: change link to a separate issue view (maybe depending on the selected version)
180 "projects/view?pid=" + sessionSelection.issue.getProject().getId());
181 breadcrumbs.add(entry);
182 if (sessionSelection.issue.getId() < 0) { 212 if (sessionSelection.issue.getId() < 0) {
183 entry = new MenuEntry(new ResourceKey("localization.projects", "button.issue.create"), 213 entry = new MenuEntry(new ResourceKey("localization.projects", "button.issue.create"),
184 "projects/issues/edit"); 214 "projects/issues/edit");
185 } else { 215 } else {
186 entry = new MenuEntry("#" + sessionSelection.issue.getId(), 216 entry = new MenuEntry("#" + sessionSelection.issue.getId(),
187 // TODO: maybe change link to a view rather than directly opening the editor 217 // TODO: maybe change link to a view rather than directly opening the editor
188 "projects/issues/edit?id=" + sessionSelection.issue.getId()); 218 "projects/issues/edit?id=" + sessionSelection.issue.getId());
189 } 219 }
190 if (level == 3) entry.setActive(true); 220 if (level == BREADCRUMB_LEVEL_ISSUE) entry.setActive(true);
191 breadcrumbs.add(entry); 221 breadcrumbs.add(entry);
192 } 222 }
193 223
194 return breadcrumbs; 224 return breadcrumbs;
195 } 225 }
200 final var projectList = dao.getProjectDao().list(); 230 final var projectList = dao.getProjectDao().list();
201 req.setAttribute("projects", projectList); 231 req.setAttribute("projects", projectList);
202 setContentPage(req, "projects"); 232 setContentPage(req, "projects");
203 setStylesheet(req, "projects"); 233 setStylesheet(req, "projects");
204 234
205 setBreadcrumbs(req, getBreadcrumbs(0, sessionSelection)); 235 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ROOT, sessionSelection));
206 236
207 return ResponseType.HTML; 237 return ResponseType.HTML;
208 } 238 }
209 239
210 private void configureEditForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { 240 private void configureEditForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException {
211 req.setAttribute("project", selection.project); 241 req.setAttribute("project", selection.project);
212 req.setAttribute("users", dao.getUserDao().list()); 242 req.setAttribute("users", dao.getUserDao().list());
213 setContentPage(req, "project-form"); 243 setContentPage(req, "project-form");
214 setBreadcrumbs(req, getBreadcrumbs(1, selection)); 244 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_PROJECT, selection));
215 } 245 }
216 246
217 @RequestMapping(requestPath = "edit", method = HttpMethod.GET) 247 @RequestMapping(requestPath = "edit", method = HttpMethod.GET)
218 public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException { 248 public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
219 final var selection = new SessionSelection(req, findByParameter(req, Integer.class, "id", 249 final var selection = new SessionSelection(req, findByParameter(req, Integer.class, "id",
251 281
252 return ResponseType.HTML; 282 return ResponseType.HTML;
253 } 283 }
254 284
255 @RequestMapping(requestPath = "view", method = HttpMethod.GET) 285 @RequestMapping(requestPath = "view", method = HttpMethod.GET)
256 public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { 286 public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
257 final var sessionSelection = new SessionSelection(req, dao); 287 final var sessionSelection = new SessionSelection(req, dao);
258 288 if (sessionSelection.project == null) {
259 req.setAttribute("versions", dao.getVersionDao().list(sessionSelection.project)); 289 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
260 req.setAttribute("issues", dao.getIssueDao().list(sessionSelection.project)); 290 return ResponseType.NONE;
261 291 }
262 setBreadcrumbs(req, getBreadcrumbs(1, sessionSelection)); 292
293 final var versionDao = dao.getVersionDao();
294 final var versions = versionDao.list(sessionSelection.project);
295 final var statsAffected = new ArrayList<VersionStatistics>();
296 final var statsScheduled = new ArrayList<VersionStatistics>();
297 final var statsResolved = new ArrayList<VersionStatistics>();
298 for (Version version : versions) {
299 statsAffected.add(versionDao.statsOpenedIssues(version));
300 statsScheduled.add(versionDao.statsScheduledIssues(version));
301 statsResolved.add(versionDao.statsResolvedIssues(version));
302 }
303
304 setAttributeHideZeros(req);
305
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));
263 setContentPage(req, "project-details"); 315 setContentPage(req, "project-details");
316 setStylesheet(req, "projects");
264 317
265 return ResponseType.HTML; 318 return ResponseType.HTML;
266 } 319 }
267 320
268 private void configureEditVersionForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { 321 private void configureEditVersionForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException {
322 final var versionDao = dao.getVersionDao();
269 req.setAttribute("projects", dao.getProjectDao().list()); 323 req.setAttribute("projects", dao.getProjectDao().list());
270 req.setAttribute("version", selection.version); 324 req.setAttribute("version", selection.version);
271 req.setAttribute("versionStatusEnum", VersionStatus.values()); 325 req.setAttribute("versionStatusEnum", VersionStatus.values());
272 326
327 req.setAttribute("issueStatusEnum", IssueStatus.values());
328 req.setAttribute("issueCategoryEnum", IssueCategory.values());
329 req.setAttribute("statsAffected", versionDao.statsOpenedIssues(selection.version));
330 req.setAttribute("statsScheduled", versionDao.statsScheduledIssues(selection.version));
331 req.setAttribute("statsResolved", versionDao.statsResolvedIssues(selection.version));
332 setAttributeHideZeros(req);
333
273 setContentPage(req, "version-form"); 334 setContentPage(req, "version-form");
274 setBreadcrumbs(req, getBreadcrumbs(2, selection)); 335 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_VERSION, selection));
275 } 336 }
276 337
277 @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET) 338 @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET)
278 public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { 339 public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
279 final var sessionSelection = new SessionSelection(req, dao); 340 final var sessionSelection = new SessionSelection(req, dao);
280 341
281 sessionSelection.selectVersion(findByParameter(req, Integer.class, "id", dao.getVersionDao()::find) 342 sessionSelection.selectVersion(findByParameter(req, Integer.class, "id", dao.getVersionDao()::find)
282 .orElse(new Version(-1, sessionSelection.project))); 343 .orElse(new Version(-1, sessionSelection.project)));
283 configureEditVersionForm(req, dao, sessionSelection); 344 configureEditVersionForm(req, dao, sessionSelection);
284 345
285 return ResponseType.HTML; 346 return ResponseType.HTML;
286 } 347 }
287 348
288 @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST) 349 @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST)
289 public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { 350 public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
290 final var sessionSelection = new SessionSelection(req, dao); 351 final var sessionSelection = new SessionSelection(req, dao);
291 352
292 var version = new Version(-1, sessionSelection.project); 353 var version = new Version(-1, sessionSelection.project);
293 try { 354 try {
294 version = new Version(getParameter(req, Integer.class, "id").orElseThrow(), sessionSelection.project); 355 version = new Version(getParameter(req, Integer.class, "id").orElseThrow(), sessionSelection.project);
318 req.setAttribute("issueStatusEnum", IssueStatus.values()); 379 req.setAttribute("issueStatusEnum", IssueStatus.values());
319 req.setAttribute("issueCategoryEnum", IssueCategory.values()); 380 req.setAttribute("issueCategoryEnum", IssueCategory.values());
320 req.setAttribute("users", dao.getUserDao().list()); 381 req.setAttribute("users", dao.getUserDao().list());
321 382
322 setContentPage(req, "issue-form"); 383 setContentPage(req, "issue-form");
323 setBreadcrumbs(req, getBreadcrumbs(3, selection)); 384 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ISSUE, selection));
385 }
386
387 @RequestMapping(requestPath = "issues/", method = HttpMethod.GET)
388 public ResponseType issues(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException {
389 final var sessionSelection = new SessionSelection(req, dao);
390 if (sessionSelection.project == null) {
391 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected.");
392 return ResponseType.NONE;
393 }
394
395 req.setAttribute("issues", dao.getIssueDao().list(sessionSelection.project));
396
397 setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ISSUE_LIST, sessionSelection));
398 setContentPage(req, "issues");
399 setStylesheet(req, "projects");
400
401 return ResponseType.HTML;
324 } 402 }
325 403
326 @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET) 404 @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET)
327 public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { 405 public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
328 final var sessionSelection = new SessionSelection(req, dao); 406 final var sessionSelection = new SessionSelection(req, dao);
329 407
330 sessionSelection.selectIssue(findByParameter(req, Integer.class, "id", 408 sessionSelection.selectIssue(findByParameter(req, Integer.class, "id",
331 dao.getIssueDao()::find).orElse(new Issue(-1, sessionSelection.project))); 409 dao.getIssueDao()::find).orElse(new Issue(-1, sessionSelection.project)));
332 configureEditIssueForm(req, dao, sessionSelection); 410 configureEditIssueForm(req, dao, sessionSelection);
333 411
334 return ResponseType.HTML; 412 return ResponseType.HTML;
335 } 413 }
336 414
337 @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST) 415 @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST)
338 public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { 416 public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException {
339 final var sessionSelection = new SessionSelection(req, dao); 417 final var sessionSelection = new SessionSelection(req, dao);
340 418
341 Issue issue = new Issue(-1, sessionSelection.project); 419 Issue issue = new Issue(-1, sessionSelection.project);
342 try { 420 try {
343 issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow(), sessionSelection.project); 421 issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow(), sessionSelection.project);

mercurial