diff -r f64255a88d66 -r 27a25f32048e src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java --- a/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java Sat May 23 14:13:09 2020 +0200 +++ b/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java Sun May 24 15:30:43 2020 +0200 @@ -57,9 +57,10 @@ private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class); - public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected-project"); - public static final String SESSION_ATTR_SELECTED_ISSUE = fqn(ProjectsModule.class, "selected-issue"); - public static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected-version"); + public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected_project"); + public static final String SESSION_ATTR_SELECTED_ISSUE = fqn(ProjectsModule.class, "selected_issue"); + public static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected_version"); + public static final String SESSION_ATTR_HIDE_ZEROS = fqn(ProjectsModule.class, "stats_hide_zeros"); private class SessionSelection { final HttpSession session; @@ -128,15 +129,40 @@ } } + private void setAttributeHideZeros(HttpServletRequest req) { + final Boolean value; + final var param = getParameter(req, Boolean.class, "reduced"); + if (param.isPresent()) { + value = param.get(); + req.getSession().setAttribute(SESSION_ATTR_HIDE_ZEROS, value); + } else { + final var sessionValue = req.getSession().getAttribute(SESSION_ATTR_HIDE_ZEROS); + if (sessionValue != null) { + value = (Boolean) sessionValue; + } else { + value = false; + req.getSession().setAttribute(SESSION_ATTR_HIDE_ZEROS, value); + } + } + req.setAttribute("statsHideZeros", value); + } + @Override protected String getResourceBundleName() { return "localization.projects"; } + + private static final int BREADCRUMB_LEVEL_ROOT = 0; + private static final int BREADCRUMB_LEVEL_PROJECT = 1; + private static final int BREADCRUMB_LEVEL_VERSION = 2; + private static final int BREADCRUMB_LEVEL_ISSUE_LIST = 3; + private static final int BREADCRUMB_LEVEL_ISSUE = 4; + /** * Creates the breadcrumb menu. * - * @param level the current active level (0: root, 1: project, 2: version, 3: issue) + * @param level the current active level (0: root, 1: project, 2: version, 3: issue list, 4: issue) * @param sessionSelection the currently selected objects * @return a dynamic breadcrumb menu trying to display as many levels as possible */ @@ -147,7 +173,7 @@ entry = new MenuEntry(new ResourceKey("localization.lightpit", "menu.projects"), "projects/"); breadcrumbs.add(entry); - if (level == 0) entry.setActive(true); + if (level == BREADCRUMB_LEVEL_ROOT) entry.setActive(true); if (sessionSelection.project != null) { if (sessionSelection.project.getId() < 0) { @@ -157,7 +183,7 @@ entry = new MenuEntry(sessionSelection.project.getName(), "projects/view?pid=" + sessionSelection.project.getId()); } - if (level == 1) entry.setActive(true); + if (level == BREADCRUMB_LEVEL_PROJECT) entry.setActive(true); breadcrumbs.add(entry); } @@ -170,15 +196,19 @@ // TODO: change link to issue overview for that version "projects/versions/edit?id=" + sessionSelection.version.getId()); } - if (level == 2) entry.setActive(true); + if (level == BREADCRUMB_LEVEL_VERSION) entry.setActive(true); + breadcrumbs.add(entry); + } + + if (sessionSelection.project != null) { + entry = new MenuEntry(new ResourceKey("localization.projects", "menu.issues"), + // TODO: maybe also add selected version + "projects/issues/?pid=" + sessionSelection.project.getId()); + if (level == BREADCRUMB_LEVEL_ISSUE_LIST) entry.setActive(true); breadcrumbs.add(entry); } if (sessionSelection.issue != null) { - entry = new MenuEntry(new ResourceKey("localization.projects", "menu.issues"), - // TODO: change link to a separate issue view (maybe depending on the selected version) - "projects/view?pid=" + sessionSelection.issue.getProject().getId()); - breadcrumbs.add(entry); if (sessionSelection.issue.getId() < 0) { entry = new MenuEntry(new ResourceKey("localization.projects", "button.issue.create"), "projects/issues/edit"); @@ -187,7 +217,7 @@ // TODO: maybe change link to a view rather than directly opening the editor "projects/issues/edit?id=" + sessionSelection.issue.getId()); } - if (level == 3) entry.setActive(true); + if (level == BREADCRUMB_LEVEL_ISSUE) entry.setActive(true); breadcrumbs.add(entry); } @@ -202,7 +232,7 @@ setContentPage(req, "projects"); setStylesheet(req, "projects"); - setBreadcrumbs(req, getBreadcrumbs(0, sessionSelection)); + setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ROOT, sessionSelection)); return ResponseType.HTML; } @@ -211,7 +241,7 @@ req.setAttribute("project", selection.project); req.setAttribute("users", dao.getUserDao().list()); setContentPage(req, "project-form"); - setBreadcrumbs(req, getBreadcrumbs(1, selection)); + setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_PROJECT, selection)); } @RequestMapping(requestPath = "edit", method = HttpMethod.GET) @@ -253,29 +283,60 @@ } @RequestMapping(requestPath = "view", method = HttpMethod.GET) - public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { + public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { final var sessionSelection = new SessionSelection(req, dao); + if (sessionSelection.project == null) { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected."); + return ResponseType.NONE; + } - req.setAttribute("versions", dao.getVersionDao().list(sessionSelection.project)); - req.setAttribute("issues", dao.getIssueDao().list(sessionSelection.project)); + final var versionDao = dao.getVersionDao(); + final var versions = versionDao.list(sessionSelection.project); + final var statsAffected = new ArrayList(); + final var statsScheduled = new ArrayList(); + final var statsResolved = new ArrayList(); + for (Version version : versions) { + statsAffected.add(versionDao.statsOpenedIssues(version)); + statsScheduled.add(versionDao.statsScheduledIssues(version)); + statsResolved.add(versionDao.statsResolvedIssues(version)); + } - setBreadcrumbs(req, getBreadcrumbs(1, sessionSelection)); + setAttributeHideZeros(req); + + req.setAttribute("versions", versions); + req.setAttribute("statsAffected", statsAffected); + req.setAttribute("statsScheduled", statsScheduled); + req.setAttribute("statsResolved", statsResolved); + + req.setAttribute("issueStatusEnum", IssueStatus.values()); + req.setAttribute("issueCategoryEnum", IssueCategory.values()); + + setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_PROJECT, sessionSelection)); setContentPage(req, "project-details"); + setStylesheet(req, "projects"); return ResponseType.HTML; } private void configureEditVersionForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException { + final var versionDao = dao.getVersionDao(); req.setAttribute("projects", dao.getProjectDao().list()); req.setAttribute("version", selection.version); req.setAttribute("versionStatusEnum", VersionStatus.values()); + req.setAttribute("issueStatusEnum", IssueStatus.values()); + req.setAttribute("issueCategoryEnum", IssueCategory.values()); + req.setAttribute("statsAffected", versionDao.statsOpenedIssues(selection.version)); + req.setAttribute("statsScheduled", versionDao.statsScheduledIssues(selection.version)); + req.setAttribute("statsResolved", versionDao.statsResolvedIssues(selection.version)); + setAttributeHideZeros(req); + setContentPage(req, "version-form"); - setBreadcrumbs(req, getBreadcrumbs(2, selection)); + setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_VERSION, selection)); } @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET) - public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { + public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { final var sessionSelection = new SessionSelection(req, dao); sessionSelection.selectVersion(findByParameter(req, Integer.class, "id", dao.getVersionDao()::find) @@ -286,7 +347,7 @@ } @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST) - public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { + public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { final var sessionSelection = new SessionSelection(req, dao); var version = new Version(-1, sessionSelection.project); @@ -320,11 +381,28 @@ req.setAttribute("users", dao.getUserDao().list()); setContentPage(req, "issue-form"); - setBreadcrumbs(req, getBreadcrumbs(3, selection)); + setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ISSUE, selection)); + } + + @RequestMapping(requestPath = "issues/", method = HttpMethod.GET) + public ResponseType issues(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException, IOException { + final var sessionSelection = new SessionSelection(req, dao); + if (sessionSelection.project == null) { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, "No project selected."); + return ResponseType.NONE; + } + + req.setAttribute("issues", dao.getIssueDao().list(sessionSelection.project)); + + setBreadcrumbs(req, getBreadcrumbs(BREADCRUMB_LEVEL_ISSUE_LIST, sessionSelection)); + setContentPage(req, "issues"); + setStylesheet(req, "projects"); + + return ResponseType.HTML; } @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET) - public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { + public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { final var sessionSelection = new SessionSelection(req, dao); sessionSelection.selectIssue(findByParameter(req, Integer.class, "id", @@ -335,7 +413,7 @@ } @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST) - public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException { + public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws SQLException { final var sessionSelection = new SessionSelection(req, dao); Issue issue = new Issue(-1, sessionSelection.project);