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

changeset 75
33b6843fdf8a
parent 74
91d1fc2a3a14
child 76
82f71fb1758a
     1.1 --- a/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java	Fri May 22 17:26:27 2020 +0200
     1.2 +++ b/src/main/java/de/uapcore/lightpit/modules/ProjectsModule.java	Fri May 22 21:23:57 2020 +0200
     1.3 @@ -38,12 +38,14 @@
     1.4  import javax.servlet.annotation.WebServlet;
     1.5  import javax.servlet.http.HttpServletRequest;
     1.6  import javax.servlet.http.HttpServletResponse;
     1.7 +import javax.servlet.http.HttpSession;
     1.8  import java.io.IOException;
     1.9 +import java.sql.Date;
    1.10  import java.sql.SQLException;
    1.11  import java.util.ArrayList;
    1.12  import java.util.List;
    1.13  import java.util.NoSuchElementException;
    1.14 -import java.util.Optional;
    1.15 +import java.util.Objects;
    1.16  
    1.17  import static de.uapcore.lightpit.Functions.fqn;
    1.18  
    1.19 @@ -61,32 +63,85 @@
    1.20      private static final Logger LOG = LoggerFactory.getLogger(ProjectsModule.class);
    1.21  
    1.22      public static final String SESSION_ATTR_SELECTED_PROJECT = fqn(ProjectsModule.class, "selected-project");
    1.23 +    public static final String SESSION_ATTR_SELECTED_ISSUE = fqn(ProjectsModule.class, "selected-issue");
    1.24 +    public static final String SESSION_ATTR_SELECTED_VERSION = fqn(ProjectsModule.class, "selected-version");
    1.25  
    1.26 -    private Project getSelectedProject(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
    1.27 -        final var projectDao = dao.getProjectDao();
    1.28 -        final var session = req.getSession();
    1.29 -        final var projectSelection = getParameter(req, Integer.class, "pid");
    1.30 -        final Project selectedProject;
    1.31 -        if (projectSelection.isPresent()) {
    1.32 -            selectedProject = projectDao.find(projectSelection.get());
    1.33 -        } else {
    1.34 -            final var sessionProject = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT);
    1.35 -            selectedProject = sessionProject == null ? null : projectDao.find(sessionProject.getId());
    1.36 +    private class SessionSelection {
    1.37 +        final HttpSession session;
    1.38 +        Project project;
    1.39 +        Version version;
    1.40 +        Issue issue;
    1.41 +
    1.42 +        SessionSelection(HttpServletRequest req, Project project) {
    1.43 +            this.session = req.getSession();
    1.44 +            this.project = project;
    1.45 +            version = null;
    1.46 +            issue = null;
    1.47 +            updateAttributes();
    1.48          }
    1.49 -        session.setAttribute(SESSION_ATTR_SELECTED_PROJECT, selectedProject);
    1.50 -        return selectedProject;
    1.51 +
    1.52 +        SessionSelection(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
    1.53 +            this.session = req.getSession();
    1.54 +            final var issueDao = dao.getIssueDao();
    1.55 +            final var projectDao = dao.getProjectDao();
    1.56 +            final var issueSelection = getParameter(req, Integer.class, "issue");
    1.57 +            if (issueSelection.isPresent()) {
    1.58 +                issue = issueDao.find(issueSelection.get());
    1.59 +            } else {
    1.60 +                final var issue = (Issue) session.getAttribute(SESSION_ATTR_SELECTED_ISSUE);
    1.61 +                this.issue = issue == null ? null : issueDao.find(issue.getId());
    1.62 +            }
    1.63 +            if (issue != null) {
    1.64 +                version = null; // show the issue globally
    1.65 +                project = projectDao.find(issue.getProject().getId());
    1.66 +            }
    1.67 +
    1.68 +            final var projectSelection = getParameter(req, Integer.class, "pid");
    1.69 +            if (projectSelection.isPresent()) {
    1.70 +                final var selectedProject = projectDao.find(projectSelection.get());
    1.71 +                if (!Objects.equals(selectedProject, project)) {
    1.72 +                    // reset version and issue if project changed
    1.73 +                    version = null;
    1.74 +                    issue = null;
    1.75 +                }
    1.76 +                project = selectedProject;
    1.77 +            } else {
    1.78 +                final var sessionProject = (Project) session.getAttribute(SESSION_ATTR_SELECTED_PROJECT);
    1.79 +                project = sessionProject == null ? null : projectDao.find(sessionProject.getId());
    1.80 +            }
    1.81 +            updateAttributes();
    1.82 +        }
    1.83 +
    1.84 +        void selectVersion(Version version) {
    1.85 +            if (!version.getProject().equals(project)) throw new AssertionError("Nice, you implemented a bug!");
    1.86 +            this.version = version;
    1.87 +            this.issue = null;
    1.88 +            updateAttributes();
    1.89 +        }
    1.90 +
    1.91 +        void selectIssue(Issue issue) {
    1.92 +            if (!issue.getProject().equals(project)) throw new AssertionError("Nice, you implemented a bug!");
    1.93 +            this.issue = issue;
    1.94 +            this.version = null;
    1.95 +            updateAttributes();
    1.96 +        }
    1.97 +
    1.98 +        void updateAttributes() {
    1.99 +            session.setAttribute(SESSION_ATTR_SELECTED_PROJECT, project);
   1.100 +            session.setAttribute(SESSION_ATTR_SELECTED_VERSION, version);
   1.101 +            session.setAttribute(SESSION_ATTR_SELECTED_ISSUE, issue);
   1.102 +        }
   1.103      }
   1.104  
   1.105  
   1.106      /**
   1.107       * Creates the breadcrumb menu.
   1.108       *
   1.109 -     * @param level           the current active level
   1.110 -     * @param selectedProject the selected project, if any, or null
   1.111 +     * @param level           the current active level (0: root, 1: project, 2: version, 3: issue)
   1.112 +     * @param sessionSelection the currently selected objects
   1.113       * @return a dynamic breadcrumb menu trying to display as many levels as possible
   1.114       */
   1.115 -    private List<MenuEntry> getBreadcrumbs(int level,
   1.116 -                                           Project selectedProject) {
   1.117 +    private List<MenuEntry> getBreadcrumbs(int level, SessionSelection sessionSelection) {
   1.118          MenuEntry entry;
   1.119  
   1.120          final var breadcrumbs = new ArrayList<MenuEntry>();
   1.121 @@ -95,52 +150,77 @@
   1.122          breadcrumbs.add(entry);
   1.123          if (level == 0) entry.setActive(true);
   1.124  
   1.125 -        if (selectedProject == null)
   1.126 -            return breadcrumbs;
   1.127 +        if (sessionSelection.project != null) {
   1.128 +            if (sessionSelection.project.getId() < 0) {
   1.129 +                entry = new MenuEntry(new ResourceKey("localization.projects", "button.create"),
   1.130 +                        "projects/edit", 1);
   1.131 +            } else {
   1.132 +                entry = new MenuEntry(sessionSelection.project.getName(),
   1.133 +                        "projects/view?pid=" + sessionSelection.project.getId(), 1);
   1.134 +            }
   1.135 +            if (level == 1) entry.setActive(true);
   1.136 +            breadcrumbs.add(entry);
   1.137 +        }
   1.138  
   1.139 -        entry = new MenuEntry(selectedProject.getName(),
   1.140 -                "projects/view?pid=" + selectedProject.getId(), 1);
   1.141 -        if (level == 1) entry.setActive(true);
   1.142 +        if (sessionSelection.version != null) {
   1.143 +            if (sessionSelection.version.getId() < 0) {
   1.144 +                entry = new MenuEntry(new ResourceKey("localization.projects", "button.version.create"),
   1.145 +                        "projects/versions/edit", 2);
   1.146 +            } else {
   1.147 +                entry = new MenuEntry(sessionSelection.version.getName(),
   1.148 +                        // TODO: change link to issue overview for that version
   1.149 +                        "projects/versions/edit?id=" + sessionSelection.version.getId(), 2);
   1.150 +            }
   1.151 +            if (level == 2) entry.setActive(true);
   1.152 +            breadcrumbs.add(entry);
   1.153 +        }
   1.154  
   1.155 -        breadcrumbs.add(entry);
   1.156 +        if (sessionSelection.issue != null) {
   1.157 +            entry = new MenuEntry(new ResourceKey("localization.projects", "menu.issues"),
   1.158 +                    // TODO: change link to a separate issue view (maybe depending on the selected version)
   1.159 +                    "projects/view?pid=" + sessionSelection.issue.getProject().getId(), 3);
   1.160 +            breadcrumbs.add(entry);
   1.161 +            if (sessionSelection.issue.getId() < 0) {
   1.162 +                entry = new MenuEntry(new ResourceKey("localization.projects", "button.issue.create"),
   1.163 +                        "projects/issues/edit", 2);
   1.164 +            } else {
   1.165 +                entry = new MenuEntry("#" + sessionSelection.issue.getId(),
   1.166 +                        // TODO: maybe change link to a view rather than directly opening the editor
   1.167 +                        "projects/issues/edit?id=" + sessionSelection.issue.getId(), 4);
   1.168 +            }
   1.169 +            if (level == 3) entry.setActive(true);
   1.170 +            breadcrumbs.add(entry);
   1.171 +        }
   1.172 +
   1.173          return breadcrumbs;
   1.174      }
   1.175  
   1.176      @RequestMapping(method = HttpMethod.GET)
   1.177      public ResponseType index(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
   1.178 -
   1.179 +        final var sessionSelection = new SessionSelection(req, dao);
   1.180          final var projectList = dao.getProjectDao().list();
   1.181          req.setAttribute("projects", projectList);
   1.182          setContentPage(req, "projects");
   1.183          setStylesheet(req, "projects");
   1.184  
   1.185 -        final var selectedProject = getSelectedProject(req, dao);
   1.186 -        setBreadcrumbs(req, getBreadcrumbs(0, selectedProject));
   1.187 +        setBreadcrumbs(req, getBreadcrumbs(0, sessionSelection));
   1.188  
   1.189          return ResponseType.HTML;
   1.190      }
   1.191  
   1.192 -    private void configureEditForm(HttpServletRequest req, DataAccessObjects dao, Optional<Project> project) throws SQLException {
   1.193 -        if (project.isPresent()) {
   1.194 -            req.setAttribute("project", project.get());
   1.195 -            setBreadcrumbs(req, getBreadcrumbs(1, project.get()));
   1.196 -        } else {
   1.197 -            req.setAttribute("project", new Project(-1));
   1.198 -            setBreadcrumbs(req, getBreadcrumbs(0, null));
   1.199 -        }
   1.200 -
   1.201 +    private void configureEditForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException {
   1.202 +        req.setAttribute("project", selection.project);
   1.203          req.setAttribute("users", dao.getUserDao().list());
   1.204          setContentPage(req, "project-form");
   1.205 +        setBreadcrumbs(req, getBreadcrumbs(1, selection));
   1.206      }
   1.207  
   1.208      @RequestMapping(requestPath = "edit", method = HttpMethod.GET)
   1.209      public ResponseType edit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
   1.210 +        final var selection = new SessionSelection(req, findByParameter(req, Integer.class, "id",
   1.211 +                dao.getProjectDao()::find).orElse(new Project(-1)));
   1.212  
   1.213 -        Optional<Project> project = findByParameter(req, Integer.class, "id", dao.getProjectDao()::find);
   1.214 -        configureEditForm(req, dao, project);
   1.215 -        if (project.isPresent()) {
   1.216 -            req.getSession().setAttribute(SESSION_ATTR_SELECTED_PROJECT, project.get());
   1.217 -        }
   1.218 +        configureEditForm(req, dao, selection);
   1.219  
   1.220          return ResponseType.HTML;
   1.221      }
   1.222 @@ -148,7 +228,7 @@
   1.223      @RequestMapping(requestPath = "commit", method = HttpMethod.POST)
   1.224      public ResponseType commit(HttpServletRequest req, DataAccessObjects dao) throws SQLException {
   1.225  
   1.226 -        Project project = null;
   1.227 +        Project project = new Project(-1);
   1.228          try {
   1.229              project = new Project(getParameter(req, Integer.class, "id").orElseThrow());
   1.230              project.setName(getParameter(req, String.class, "name").orElseThrow());
   1.231 @@ -163,11 +243,11 @@
   1.232              setRedirectLocation(req, "./projects/");
   1.233              setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   1.234              LOG.debug("Successfully updated project {}", project.getName());
   1.235 -        } catch (NoSuchElementException | NumberFormatException | SQLException ex) {
   1.236 +        } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
   1.237              // TODO: set request attribute with error text
   1.238              LOG.warn("Form validation failure: {}", ex.getMessage());
   1.239              LOG.debug("Details:", ex);
   1.240 -            configureEditForm(req, dao, Optional.ofNullable(project));
   1.241 +            configureEditForm(req, dao, new SessionSelection(req, project));
   1.242          }
   1.243  
   1.244          return ResponseType.HTML;
   1.245 @@ -175,123 +255,133 @@
   1.246  
   1.247      @RequestMapping(requestPath = "view", method = HttpMethod.GET)
   1.248      public ResponseType view(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException {
   1.249 -        final var selectedProject = getSelectedProject(req, dao);
   1.250 -        if (selectedProject == null) {
   1.251 -            resp.sendError(HttpServletResponse.SC_FORBIDDEN);
   1.252 -            return ResponseType.NONE;
   1.253 -        }
   1.254 +        final var sessionSelection = new SessionSelection(req, dao);
   1.255  
   1.256 -        req.setAttribute("versions", dao.getVersionDao().list(selectedProject));
   1.257 -        req.setAttribute("issues", dao.getIssueDao().list(selectedProject));
   1.258 +        req.setAttribute("versions", dao.getVersionDao().list(sessionSelection.project));
   1.259 +        req.setAttribute("issues", dao.getIssueDao().list(sessionSelection.project));
   1.260  
   1.261 -        // TODO: add more levels depending on last visited location
   1.262 -        setBreadcrumbs(req, getBreadcrumbs(1, selectedProject));
   1.263 -
   1.264 +        setBreadcrumbs(req, getBreadcrumbs(1, sessionSelection));
   1.265          setContentPage(req, "project-details");
   1.266  
   1.267          return ResponseType.HTML;
   1.268      }
   1.269  
   1.270 -    private void configureEditVersionForm(HttpServletRequest req, Optional<Version> version, Project selectedProject) {
   1.271 -        req.setAttribute("version", version.orElse(new Version(-1, selectedProject)));
   1.272 +    private void configureEditVersionForm(HttpServletRequest req, SessionSelection selection) {
   1.273 +        req.setAttribute("version", selection.version);
   1.274          req.setAttribute("versionStatusEnum", VersionStatus.values());
   1.275  
   1.276          setContentPage(req, "version-form");
   1.277 +        setBreadcrumbs(req, getBreadcrumbs(2, selection));
   1.278      }
   1.279  
   1.280      @RequestMapping(requestPath = "versions/edit", method = HttpMethod.GET)
   1.281      public ResponseType editVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException {
   1.282 -        final var selectedProject = getSelectedProject(req, dao);
   1.283 -        if (selectedProject == null) {
   1.284 +        final var sessionSelection = new SessionSelection(req, dao);
   1.285 +        if (sessionSelection.project == null) {
   1.286 +            // TODO: remove this bullshit and only retrieve the object from session if we are creating a fresh version
   1.287              resp.sendError(HttpServletResponse.SC_FORBIDDEN);
   1.288              return ResponseType.NONE;
   1.289          }
   1.290  
   1.291 -        configureEditVersionForm(req,
   1.292 -                findByParameter(req, Integer.class, "id", dao.getVersionDao()::find),
   1.293 -                selectedProject);
   1.294 +        sessionSelection.selectVersion(findByParameter(req, Integer.class, "id", dao.getVersionDao()::find)
   1.295 +                .orElse(new Version(-1, sessionSelection.project)));
   1.296 +        configureEditVersionForm(req, sessionSelection);
   1.297  
   1.298          return ResponseType.HTML;
   1.299      }
   1.300  
   1.301      @RequestMapping(requestPath = "versions/commit", method = HttpMethod.POST)
   1.302      public ResponseType commitVersion(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException {
   1.303 -        final var selectedProject = getSelectedProject(req, dao);
   1.304 -        if (selectedProject == null) {
   1.305 +        final var sessionSelection = new SessionSelection(req, dao);
   1.306 +        if (sessionSelection.project == null) {
   1.307 +            // TODO: remove this bullshit and retrieve project id from hidden field
   1.308              resp.sendError(HttpServletResponse.SC_FORBIDDEN);
   1.309              return ResponseType.NONE;
   1.310          }
   1.311  
   1.312 -        Version version = null;
   1.313 +        var version = new Version(-1, sessionSelection.project);
   1.314          try {
   1.315 -            version = new Version(getParameter(req, Integer.class, "id").orElseThrow(), selectedProject);
   1.316 +            version = new Version(getParameter(req, Integer.class, "id").orElseThrow(), sessionSelection.project);
   1.317              version.setName(getParameter(req, String.class, "name").orElseThrow());
   1.318              getParameter(req, Integer.class, "ordinal").ifPresent(version::setOrdinal);
   1.319              version.setStatus(VersionStatus.valueOf(getParameter(req, String.class, "status").orElseThrow()));
   1.320              dao.getVersionDao().saveOrUpdate(version);
   1.321  
   1.322 -            setRedirectLocation(req, "./projects/versions/");
   1.323 +            // specifying the pid parameter will purposely reset the session selected version!
   1.324 +            setRedirectLocation(req, "./projects/view?pid="+sessionSelection.project.getId());
   1.325              setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   1.326 -            LOG.debug("Successfully updated version {} for project {}", version.getName(), selectedProject.getName());
   1.327 -        } catch (NoSuchElementException | NumberFormatException | SQLException ex) {
   1.328 +            LOG.debug("Successfully updated version {} for project {}", version.getName(), sessionSelection.project.getName());
   1.329 +        } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
   1.330              // TODO: set request attribute with error text
   1.331              LOG.warn("Form validation failure: {}", ex.getMessage());
   1.332              LOG.debug("Details:", ex);
   1.333 -            configureEditVersionForm(req, Optional.ofNullable(version), selectedProject);
   1.334 +            sessionSelection.selectVersion(version);
   1.335 +            configureEditVersionForm(req, sessionSelection);
   1.336          }
   1.337  
   1.338          return ResponseType.HTML;
   1.339      }
   1.340  
   1.341 -    private void configureEditIssueForm(HttpServletRequest req, DataAccessObjects dao, Optional<Issue> issue, Project selectedProject) throws SQLException {
   1.342 -
   1.343 -        req.setAttribute("issue", issue.orElse(new Issue(-1, selectedProject)));
   1.344 +    private void configureEditIssueForm(HttpServletRequest req, DataAccessObjects dao, SessionSelection selection) throws SQLException {
   1.345 +        req.setAttribute("issue", selection.issue);
   1.346          req.setAttribute("issueStatusEnum", IssueStatus.values());
   1.347          req.setAttribute("issueCategoryEnum", IssueCategory.values());
   1.348 -        req.setAttribute("versions", dao.getVersionDao().list(selectedProject));
   1.349 +        req.setAttribute("versions", dao.getVersionDao().list(selection.project));
   1.350 +        req.setAttribute("users", dao.getUserDao().list());
   1.351  
   1.352          setContentPage(req, "issue-form");
   1.353 +        setBreadcrumbs(req, getBreadcrumbs(3, selection));
   1.354      }
   1.355  
   1.356      @RequestMapping(requestPath = "issues/edit", method = HttpMethod.GET)
   1.357      public ResponseType editIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException {
   1.358 -        final var selectedProject = getSelectedProject(req, dao);
   1.359 -        if (selectedProject == null) {
   1.360 +        final var sessionSelection = new SessionSelection(req, dao);
   1.361 +        if (sessionSelection.project == null) {
   1.362 +            // TODO: remove this bullshit and only retrieve the object from session if we are creating a fresh issue
   1.363              resp.sendError(HttpServletResponse.SC_FORBIDDEN);
   1.364              return ResponseType.NONE;
   1.365          }
   1.366  
   1.367 -        configureEditIssueForm(req, dao,
   1.368 -                findByParameter(req, Integer.class, "id", dao.getIssueDao()::find),
   1.369 -                selectedProject);
   1.370 +        sessionSelection.selectIssue(findByParameter(req, Integer.class, "id",
   1.371 +                dao.getIssueDao()::find).orElse(new Issue(-1, sessionSelection.project)));
   1.372 +        configureEditIssueForm(req, dao, sessionSelection);
   1.373  
   1.374          return ResponseType.HTML;
   1.375      }
   1.376  
   1.377      @RequestMapping(requestPath = "issues/commit", method = HttpMethod.POST)
   1.378      public ResponseType commitIssue(HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException, SQLException {
   1.379 -        final var selectedProject = getSelectedProject(req, dao);
   1.380 -        if (selectedProject == null) {
   1.381 +        // TODO: remove this bullshit and store the project ID as hidden field
   1.382 +        final var sessionSelection = new SessionSelection(req, dao);
   1.383 +        if (sessionSelection.project == null) {
   1.384              resp.sendError(HttpServletResponse.SC_FORBIDDEN);
   1.385              return ResponseType.NONE;
   1.386          }
   1.387  
   1.388 -        Issue issue = null;
   1.389 +        Issue issue = new Issue(-1, sessionSelection.project);
   1.390          try {
   1.391 -            issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow(), selectedProject);
   1.392 -
   1.393 -            // TODO: implement
   1.394 -
   1.395 +            issue = new Issue(getParameter(req, Integer.class, "id").orElseThrow(), sessionSelection.project);
   1.396 +            getParameter(req, String.class, "category").map(IssueCategory::valueOf).ifPresent(issue::setCategory);
   1.397 +            getParameter(req, String.class, "status").map(IssueStatus::valueOf).ifPresent(issue::setStatus);
   1.398 +            issue.setSubject(getParameter(req, String.class, "subject").orElseThrow());
   1.399 +            getParameter(req, Integer.class, "assignee").map(
   1.400 +                    userid -> userid >= 0 ? new User(userid) : null
   1.401 +            ).ifPresent(issue::setAssignee);
   1.402 +            getParameter(req, String.class, "description").ifPresent(issue::setDescription);
   1.403 +            getParameter(req, Date.class, "eta").ifPresent(issue::setEta);
   1.404              dao.getIssueDao().saveOrUpdate(issue);
   1.405  
   1.406 -            setRedirectLocation(req, "./projects/issues/");
   1.407 +            // TODO: redirect to issue overview
   1.408 +            // specifying the issue parameter keeps the edited issue as breadcrumb
   1.409 +            setRedirectLocation(req, "./projects/view?issue="+issue.getId());
   1.410              setContentPage(req, Constants.JSP_COMMIT_SUCCESSFUL);
   1.411 -            LOG.debug("Successfully updated issue {} for project {}", issue.getId(), selectedProject.getName());
   1.412 -        } catch (NoSuchElementException | NumberFormatException | SQLException ex) {
   1.413 +            LOG.debug("Successfully updated issue {} for project {}", issue.getId(), sessionSelection.project.getName());
   1.414 +        } catch (NoSuchElementException | IllegalArgumentException | SQLException ex) {
   1.415              // TODO: set request attribute with error text
   1.416              LOG.warn("Form validation failure: {}", ex.getMessage());
   1.417              LOG.debug("Details:", ex);
   1.418 -            configureEditIssueForm(req, dao, Optional.ofNullable(issue), selectedProject);
   1.419 +            sessionSelection.selectIssue(issue);
   1.420 +            configureEditIssueForm(req, dao, sessionSelection);
   1.421          }
   1.422  
   1.423          return ResponseType.HTML;

mercurial