Wed, 18 Aug 2021 15:34:36 +0200
fixes default issue sorter field order
184 | 1 | /* |
2 | * Copyright 2021 Mike Becker. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions are met: | |
6 | * | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * | |
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
20 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
21 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
22 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | package de.uapcore.lightpit.servlet | |
27 | ||
28 | import de.uapcore.lightpit.AbstractServlet | |
29 | import de.uapcore.lightpit.HttpRequest | |
227
f0ede8046b59
#162 adds active flag to component
Mike Becker <universe@uap-core.de>
parents:
225
diff
changeset
|
30 | import de.uapcore.lightpit.boolValidator |
184 | 31 | import de.uapcore.lightpit.dao.DataAccessObject |
225
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
32 | import de.uapcore.lightpit.dateOptValidator |
184 | 33 | import de.uapcore.lightpit.entities.* |
34 | import de.uapcore.lightpit.types.IssueCategory | |
35 | import de.uapcore.lightpit.types.IssueStatus | |
36 | import de.uapcore.lightpit.types.VersionStatus | |
37 | import de.uapcore.lightpit.types.WebColor | |
38 | import de.uapcore.lightpit.util.AllFilter | |
39 | import de.uapcore.lightpit.util.IssueFilter | |
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
40 | import de.uapcore.lightpit.util.IssueSorter.Companion.DEFAULT_ISSUE_SORTER |
184 | 41 | import de.uapcore.lightpit.util.SpecificFilter |
42 | import de.uapcore.lightpit.viewmodel.* | |
43 | import java.sql.Date | |
44 | import javax.servlet.annotation.WebServlet | |
45 | ||
46 | @WebServlet(urlPatterns = ["/projects/*"]) | |
47 | class ProjectServlet : AbstractServlet() { | |
48 | ||
49 | init { | |
50 | get("/", this::projects) | |
51 | get("/%project", this::project) | |
52 | get("/%project/issues/%version/%component/", this::project) | |
53 | get("/%project/edit", this::projectForm) | |
54 | get("/-/create", this::projectForm) | |
55 | post("/-/commit", this::projectCommit) | |
56 | ||
57 | get("/%project/versions/", this::versions) | |
58 | get("/%project/versions/%version/edit", this::versionForm) | |
59 | get("/%project/versions/-/create", this::versionForm) | |
60 | post("/%project/versions/-/commit", this::versionCommit) | |
61 | ||
62 | get("/%project/components/", this::components) | |
63 | get("/%project/components/%component/edit", this::componentForm) | |
64 | get("/%project/components/-/create", this::componentForm) | |
65 | post("/%project/components/-/commit", this::componentCommit) | |
66 | ||
67 | get("/%project/issues/%version/%component/%issue", this::issue) | |
68 | get("/%project/issues/%version/%component/%issue/edit", this::issueForm) | |
186
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
69 | post("/%project/issues/%version/%component/%issue/comment", this::issueComment) |
184 | 70 | get("/%project/issues/%version/%component/-/create", this::issueForm) |
186
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
71 | post("/%project/issues/%version/%component/-/commit", this::issueCommit) |
184 | 72 | } |
73 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
74 | private fun projects(http: HttpRequest, dao: DataAccessObject) { |
184 | 75 | val projects = dao.listProjects() |
76 | val projectInfos = projects.map { | |
77 | ProjectInfo( | |
78 | project = it, | |
79 | versions = dao.listVersions(it), | |
80 | components = emptyList(), // not required in this view | |
81 | issueSummary = dao.collectIssueSummary(it) | |
82 | ) | |
83 | } | |
84 | ||
85 | with(http) { | |
86 | view = ProjectsView(projectInfos) | |
87 | navigationMenu = projectNavMenu(projects) | |
88 | styleSheets = listOf("projects") | |
89 | render("projects") | |
90 | } | |
91 | } | |
92 | ||
93 | private fun activeProjectNavMenu( | |
94 | projects: List<Project>, | |
95 | projectInfo: ProjectInfo, | |
96 | selectedVersion: Version? = null, | |
97 | selectedComponent: Component? = null | |
98 | ) = | |
99 | projectNavMenu( | |
100 | projects, | |
101 | projectInfo.versions, | |
102 | projectInfo.components, | |
103 | projectInfo.project, | |
104 | selectedVersion, | |
105 | selectedComponent | |
106 | ) | |
107 | ||
210 | 108 | private sealed interface LookupResult<T> |
109 | private class NotFound<T> : LookupResult<T> | |
110 | private data class Found<T>(val elem: T?) : LookupResult<T> | |
184 | 111 | |
112 | private fun <T : HasNode> HttpRequest.lookupPathParam(paramName: String, list: List<T>): LookupResult<T> { | |
113 | val node = pathParams[paramName] | |
114 | return if (node == null || node == "-") { | |
210 | 115 | Found(null) |
184 | 116 | } else { |
117 | val result = list.find { it.node == node } | |
118 | if (result == null) { | |
210 | 119 | NotFound() |
184 | 120 | } else { |
210 | 121 | Found(result) |
184 | 122 | } |
123 | } | |
124 | } | |
125 | ||
126 | private fun obtainProjectInfo(http: HttpRequest, dao: DataAccessObject): ProjectInfo? { | |
127 | val project = dao.findProjectByNode(http.pathParams["project"] ?: "") ?: return null | |
128 | ||
129 | val versions: List<Version> = dao.listVersions(project) | |
130 | val components: List<Component> = dao.listComponents(project) | |
131 | ||
132 | return ProjectInfo( | |
133 | project, | |
134 | versions, | |
135 | components, | |
136 | dao.collectIssueSummary(project) | |
137 | ) | |
138 | } | |
139 | ||
140 | private fun sanitizeNode(name: String): String { | |
141 | val san = name.replace(Regex("[/\\\\]"), "-") | |
142 | return if (san.startsWith(".")) { | |
143 | "v$san" | |
144 | } else { | |
145 | san | |
146 | } | |
147 | } | |
148 | ||
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
149 | private fun feedPath(project: Project) = "feed/${project.node}/issues.rss" |
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
150 | |
210 | 151 | private data class PathInfos( |
184 | 152 | val projectInfo: ProjectInfo, |
153 | val version: Version?, | |
154 | val component: Component? | |
155 | ) { | |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
156 | val project = projectInfo.project |
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
157 | val issuesHref by lazyOf("projects/${project.node}/issues/${version?.node ?: "-"}/${component?.node ?: "-"}/") |
184 | 158 | } |
159 | ||
160 | private fun withPathInfo(http: HttpRequest, dao: DataAccessObject): PathInfos? { | |
161 | val projectInfo = obtainProjectInfo(http, dao) | |
162 | if (projectInfo == null) { | |
163 | http.response.sendError(404) | |
164 | return null | |
165 | } | |
166 | ||
167 | val version = when (val result = http.lookupPathParam("version", projectInfo.versions)) { | |
210 | 168 | is NotFound -> { |
184 | 169 | http.response.sendError(404) |
170 | return null | |
171 | } | |
210 | 172 | is Found -> { |
184 | 173 | result.elem |
174 | } | |
175 | } | |
176 | val component = when (val result = http.lookupPathParam("component", projectInfo.components)) { | |
210 | 177 | is NotFound -> { |
184 | 178 | http.response.sendError(404) |
179 | return null | |
180 | } | |
210 | 181 | is Found -> { |
184 | 182 | result.elem |
183 | } | |
184 | } | |
185 | ||
186 | return PathInfos(projectInfo, version, component) | |
187 | } | |
188 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
189 | private fun project(http: HttpRequest, dao: DataAccessObject) { |
184 | 190 | withPathInfo(http, dao)?.run { |
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
191 | |
184 | 192 | val issues = dao.listIssues(IssueFilter( |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
193 | project = SpecificFilter(project), |
184 | 194 | version = version?.let { SpecificFilter(it) } ?: AllFilter(), |
195 | component = component?.let { SpecificFilter(it) } ?: AllFilter() | |
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
196 | )).sortedWith(DEFAULT_ISSUE_SORTER) |
184 | 197 | |
198 | with(http) { | |
205
7725a79416f3
#115 adds custom page titles
Mike Becker <universe@uap-core.de>
parents:
200
diff
changeset
|
199 | pageTitle = project.name |
184 | 200 | view = ProjectDetails(projectInfo, issues, version, component) |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
201 | feedPath = feedPath(project) |
184 | 202 | navigationMenu = activeProjectNavMenu( |
203 | dao.listProjects(), | |
204 | projectInfo, | |
205 | version, | |
206 | component | |
207 | ) | |
208 | styleSheets = listOf("projects") | |
209 | render("project-details") | |
210 | } | |
211 | } | |
212 | } | |
213 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
214 | private fun projectForm(http: HttpRequest, dao: DataAccessObject) { |
200
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
215 | if (!http.pathParams.containsKey("project")) { |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
216 | http.view = ProjectEditView(Project(-1), dao.listUsers()) |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
217 | http.navigationMenu = projectNavMenu(dao.listProjects()) |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
218 | } else { |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
219 | val projectInfo = obtainProjectInfo(http, dao) |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
220 | if (projectInfo == null) { |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
221 | http.response.sendError(404) |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
222 | return |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
223 | } |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
224 | http.view = ProjectEditView(projectInfo.project, dao.listUsers()) |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
225 | http.navigationMenu = activeProjectNavMenu( |
184 | 226 | dao.listProjects(), |
227 | projectInfo | |
228 | ) | |
229 | } | |
200
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
230 | http.styleSheets = listOf("projects") |
a5ddfaf6b469
fixes project creation not working
Mike Becker <universe@uap-core.de>
parents:
198
diff
changeset
|
231 | http.render("project-form") |
184 | 232 | } |
233 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
234 | private fun projectCommit(http: HttpRequest, dao: DataAccessObject) { |
184 | 235 | val project = Project(http.param("id")?.toIntOrNull() ?: -1).apply { |
236 | name = http.param("name") ?: "" | |
237 | node = http.param("node") ?: "" | |
238 | description = http.param("description") ?: "" | |
239 | ordinal = http.param("ordinal")?.toIntOrNull() ?: 0 | |
240 | repoUrl = http.param("repoUrl") ?: "" | |
241 | owner = (http.param("owner")?.toIntOrNull() ?: -1).let { | |
242 | if (it < 0) null else dao.findUser(it) | |
243 | } | |
244 | // intentional defaults | |
245 | if (node.isBlank()) node = name | |
246 | // sanitizing | |
247 | node = sanitizeNode(node) | |
248 | } | |
249 | ||
250 | if (project.id < 0) { | |
251 | dao.insertProject(project) | |
252 | } else { | |
253 | dao.updateProject(project) | |
254 | } | |
255 | ||
256 | http.renderCommit("projects/${project.node}") | |
257 | } | |
258 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
259 | private fun versions(http: HttpRequest, dao: DataAccessObject) { |
184 | 260 | val projectInfo = obtainProjectInfo(http, dao) |
261 | if (projectInfo == null) { | |
262 | http.response.sendError(404) | |
263 | return | |
264 | } | |
265 | ||
266 | with(http) { | |
205
7725a79416f3
#115 adds custom page titles
Mike Becker <universe@uap-core.de>
parents:
200
diff
changeset
|
267 | pageTitle = "${projectInfo.project.name} - ${i18n("navmenu.versions")}" |
184 | 268 | view = VersionsView( |
269 | projectInfo, | |
270 | dao.listVersionSummaries(projectInfo.project) | |
271 | ) | |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
272 | feedPath = feedPath(projectInfo.project) |
184 | 273 | navigationMenu = activeProjectNavMenu( |
274 | dao.listProjects(), | |
275 | projectInfo | |
276 | ) | |
277 | styleSheets = listOf("projects") | |
278 | render("versions") | |
279 | } | |
280 | } | |
281 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
282 | private fun versionForm(http: HttpRequest, dao: DataAccessObject) { |
184 | 283 | val projectInfo = obtainProjectInfo(http, dao) |
284 | if (projectInfo == null) { | |
285 | http.response.sendError(404) | |
286 | return | |
287 | } | |
288 | ||
289 | val version: Version | |
290 | when (val result = http.lookupPathParam("version", projectInfo.versions)) { | |
210 | 291 | is NotFound -> { |
184 | 292 | http.response.sendError(404) |
293 | return | |
294 | } | |
210 | 295 | is Found -> { |
184 | 296 | version = result.elem ?: Version(-1, projectInfo.project.id) |
297 | } | |
298 | } | |
299 | ||
300 | with(http) { | |
301 | view = VersionEditView(projectInfo, version) | |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
302 | feedPath = feedPath(projectInfo.project) |
184 | 303 | navigationMenu = activeProjectNavMenu( |
304 | dao.listProjects(), | |
305 | projectInfo, | |
306 | selectedVersion = version | |
307 | ) | |
308 | styleSheets = listOf("projects") | |
309 | render("version-form") | |
310 | } | |
311 | } | |
312 | ||
210 | 313 | private fun obtainIdAndProject(http: HttpRequest, dao:DataAccessObject): Pair<Int, Project>? { |
184 | 314 | val id = http.param("id")?.toIntOrNull() |
315 | val projectid = http.param("projectid")?.toIntOrNull() ?: -1 | |
316 | val project = dao.findProject(projectid) | |
210 | 317 | return if (id == null || project == null) { |
184 | 318 | http.response.sendError(400) |
210 | 319 | null |
320 | } else { | |
321 | Pair(id, project) | |
184 | 322 | } |
210 | 323 | } |
184 | 324 | |
210 | 325 | private fun versionCommit(http: HttpRequest, dao: DataAccessObject) { |
326 | val idParams = obtainIdAndProject(http, dao) ?: return | |
327 | val (id, project) = idParams | |
328 | ||
329 | val version = Version(id, project.id).apply { | |
184 | 330 | name = http.param("name") ?: "" |
331 | node = http.param("node") ?: "" | |
332 | ordinal = http.param("ordinal")?.toIntOrNull() ?: 0 | |
333 | status = http.param("status")?.let(VersionStatus::valueOf) ?: VersionStatus.Future | |
225
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
334 | // TODO: process error messages |
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
335 | eol = http.param("eol", ::dateOptValidator, null, mutableListOf()) |
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
336 | release = http.param("release", ::dateOptValidator, null, mutableListOf()) |
184 | 337 | // intentional defaults |
338 | if (node.isBlank()) node = name | |
339 | // sanitizing | |
340 | node = sanitizeNode(node) | |
341 | } | |
342 | ||
225
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
343 | // sanitize eol and release date |
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
344 | if (version.status.isEndOfLife) { |
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
345 | if (version.eol == null) version.eol = Date(System.currentTimeMillis()) |
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
346 | } else if (version.status.isReleased) { |
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
347 | if (version.release == null) version.release = Date(System.currentTimeMillis()) |
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
348 | } |
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
349 | |
184 | 350 | if (id < 0) { |
351 | dao.insertVersion(version) | |
352 | } else { | |
353 | dao.updateVersion(version) | |
354 | } | |
355 | ||
356 | http.renderCommit("projects/${project.node}/versions/") | |
357 | } | |
358 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
359 | private fun components(http: HttpRequest, dao: DataAccessObject) { |
184 | 360 | val projectInfo = obtainProjectInfo(http, dao) |
361 | if (projectInfo == null) { | |
362 | http.response.sendError(404) | |
363 | return | |
364 | } | |
365 | ||
366 | with(http) { | |
205
7725a79416f3
#115 adds custom page titles
Mike Becker <universe@uap-core.de>
parents:
200
diff
changeset
|
367 | pageTitle = "${projectInfo.project.name} - ${i18n("navmenu.components")}" |
184 | 368 | view = ComponentsView( |
369 | projectInfo, | |
370 | dao.listComponentSummaries(projectInfo.project) | |
371 | ) | |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
372 | feedPath = feedPath(projectInfo.project) |
184 | 373 | navigationMenu = activeProjectNavMenu( |
374 | dao.listProjects(), | |
375 | projectInfo | |
376 | ) | |
377 | styleSheets = listOf("projects") | |
378 | render("components") | |
379 | } | |
380 | } | |
381 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
382 | private fun componentForm(http: HttpRequest, dao: DataAccessObject) { |
184 | 383 | val projectInfo = obtainProjectInfo(http, dao) |
384 | if (projectInfo == null) { | |
385 | http.response.sendError(404) | |
386 | return | |
387 | } | |
388 | ||
389 | val component: Component | |
390 | when (val result = http.lookupPathParam("component", projectInfo.components)) { | |
210 | 391 | is NotFound -> { |
184 | 392 | http.response.sendError(404) |
393 | return | |
394 | } | |
210 | 395 | is Found -> { |
184 | 396 | component = result.elem ?: Component(-1, projectInfo.project.id) |
397 | } | |
398 | } | |
399 | ||
400 | with(http) { | |
401 | view = ComponentEditView(projectInfo, component, dao.listUsers()) | |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
402 | feedPath = feedPath(projectInfo.project) |
184 | 403 | navigationMenu = activeProjectNavMenu( |
404 | dao.listProjects(), | |
405 | projectInfo, | |
406 | selectedComponent = component | |
407 | ) | |
408 | styleSheets = listOf("projects") | |
409 | render("component-form") | |
410 | } | |
411 | } | |
412 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
413 | private fun componentCommit(http: HttpRequest, dao: DataAccessObject) { |
210 | 414 | val idParams = obtainIdAndProject(http, dao) ?: return |
415 | val (id, project) = idParams | |
184 | 416 | |
210 | 417 | val component = Component(id, project.id).apply { |
184 | 418 | name = http.param("name") ?: "" |
419 | node = http.param("node") ?: "" | |
420 | ordinal = http.param("ordinal")?.toIntOrNull() ?: 0 | |
421 | color = WebColor(http.param("color") ?: "#000000") | |
422 | description = http.param("description") | |
227
f0ede8046b59
#162 adds active flag to component
Mike Becker <universe@uap-core.de>
parents:
225
diff
changeset
|
423 | // TODO: process error message |
f0ede8046b59
#162 adds active flag to component
Mike Becker <universe@uap-core.de>
parents:
225
diff
changeset
|
424 | active = http.param("active", ::boolValidator, true, mutableListOf()) |
184 | 425 | lead = (http.param("lead")?.toIntOrNull() ?: -1).let { |
426 | if (it < 0) null else dao.findUser(it) | |
427 | } | |
428 | // intentional defaults | |
429 | if (node.isBlank()) node = name | |
430 | // sanitizing | |
431 | node = sanitizeNode(node) | |
432 | } | |
433 | ||
434 | if (id < 0) { | |
435 | dao.insertComponent(component) | |
436 | } else { | |
437 | dao.updateComponent(component) | |
438 | } | |
439 | ||
440 | http.renderCommit("projects/${project.node}/components/") | |
441 | } | |
442 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
443 | private fun issue(http: HttpRequest, dao: DataAccessObject) { |
184 | 444 | withPathInfo(http, dao)?.run { |
445 | val issue = dao.findIssue(http.pathParams["issue"]?.toIntOrNull() ?: -1) | |
446 | if (issue == null) { | |
447 | http.response.sendError(404) | |
448 | return | |
449 | } | |
450 | ||
451 | val comments = dao.listComments(issue) | |
452 | ||
453 | with(http) { | |
205
7725a79416f3
#115 adds custom page titles
Mike Becker <universe@uap-core.de>
parents:
200
diff
changeset
|
454 | pageTitle = "${projectInfo.project.name}: #${issue.id} ${issue.subject}" |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
455 | view = IssueDetailView(issue, comments, project, version, component) |
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
456 | feedPath = feedPath(projectInfo.project) |
184 | 457 | navigationMenu = activeProjectNavMenu( |
458 | dao.listProjects(), | |
459 | projectInfo, | |
460 | version, | |
461 | component | |
462 | ) | |
463 | styleSheets = listOf("projects") | |
207
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
464 | javascript = "issue-editor" |
184 | 465 | render("issue-view") |
466 | } | |
467 | } | |
468 | } | |
469 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
470 | private fun issueForm(http: HttpRequest, dao: DataAccessObject) { |
184 | 471 | withPathInfo(http, dao)?.run { |
472 | val issue = dao.findIssue(http.pathParams["issue"]?.toIntOrNull() ?: -1) ?: Issue( | |
473 | -1, | |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
474 | project, |
184 | 475 | ) |
476 | ||
215
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
477 | // for new issues set some defaults |
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
478 | if (issue.id < 0) { |
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
479 | // pre-select component, if available in the path info |
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
480 | issue.component = component |
184 | 481 | |
215
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
482 | // pre-select version, if available in the path info |
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
483 | if (version != null) { |
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
484 | if (version.status.isReleased) { |
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
485 | issue.affectedVersions = listOf(version) |
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
486 | } else { |
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
487 | issue.resolvedVersions = listOf(version) |
028792eda9b7
#156 fixes auto-selection overriding issue data
Mike Becker <universe@uap-core.de>
parents:
214
diff
changeset
|
488 | } |
191
193ee4828767
fixes #134 - automatic version selection
Mike Becker <universe@uap-core.de>
parents:
186
diff
changeset
|
489 | } |
193ee4828767
fixes #134 - automatic version selection
Mike Becker <universe@uap-core.de>
parents:
186
diff
changeset
|
490 | } |
193ee4828767
fixes #134 - automatic version selection
Mike Becker <universe@uap-core.de>
parents:
186
diff
changeset
|
491 | |
184 | 492 | with(http) { |
493 | view = IssueEditView( | |
494 | issue, | |
495 | projectInfo.versions, | |
496 | projectInfo.components, | |
497 | dao.listUsers(), | |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
498 | project, |
184 | 499 | version, |
500 | component | |
501 | ) | |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
502 | feedPath = feedPath(projectInfo.project) |
184 | 503 | navigationMenu = activeProjectNavMenu( |
504 | dao.listProjects(), | |
505 | projectInfo, | |
506 | version, | |
507 | component | |
508 | ) | |
509 | styleSheets = listOf("projects") | |
207
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
510 | javascript = "issue-editor" |
184 | 511 | render("issue-form") |
512 | } | |
513 | } | |
514 | } | |
515 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
516 | private fun issueComment(http: HttpRequest, dao: DataAccessObject) { |
184 | 517 | withPathInfo(http, dao)?.run { |
518 | val issue = dao.findIssue(http.pathParams["issue"]?.toIntOrNull() ?: -1) | |
519 | if (issue == null) { | |
520 | http.response.sendError(404) | |
521 | return | |
522 | } | |
523 | ||
207
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
524 | val commentId = http.param("commentid")?.toIntOrNull() ?: -1 |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
525 | if (commentId > 0) { |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
526 | val comment = dao.findComment(commentId) |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
527 | val originalAuthor = comment?.author?.username |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
528 | if (originalAuthor != null && originalAuthor == http.remoteUser) { |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
529 | comment.comment = http.param("comment") ?: "" |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
530 | dao.updateComment(comment) |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
531 | } else { |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
532 | http.response.sendError(403) |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
533 | return |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
534 | } |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
535 | } else { |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
536 | val comment = IssueComment(-1, issue.id).apply { |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
537 | author = http.remoteUser?.let { dao.findUserByName(it) } |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
538 | comment = http.param("comment") ?: "" |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
539 | } |
479dd7993ef9
#22 adds possibility to edit own comments
Mike Becker <universe@uap-core.de>
parents:
205
diff
changeset
|
540 | dao.insertComment(comment) |
184 | 541 | } |
542 | ||
543 | http.renderCommit("${issuesHref}${issue.id}") | |
544 | } | |
545 | } | |
546 | ||
193
1e4044d29b1c
fixes missing issue sorting
Mike Becker <universe@uap-core.de>
parents:
191
diff
changeset
|
547 | private fun issueCommit(http: HttpRequest, dao: DataAccessObject) { |
184 | 548 | withPathInfo(http, dao)?.run { |
549 | val issue = Issue( | |
550 | http.param("id")?.toIntOrNull() ?: -1, | |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
551 | project |
184 | 552 | ).apply { |
553 | component = dao.findComponent(http.param("component")?.toIntOrNull() ?: -1) | |
554 | category = IssueCategory.valueOf(http.param("category") ?: "") | |
555 | status = IssueStatus.valueOf(http.param("status") ?: "") | |
556 | subject = http.param("subject") ?: "" | |
557 | description = http.param("description") ?: "" | |
558 | assignee = http.param("assignee")?.toIntOrNull()?.let { | |
559 | when (it) { | |
560 | -1 -> null | |
561 | -2 -> component?.lead | |
562 | else -> dao.findUser(it) | |
563 | } | |
564 | } | |
225
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
565 | // TODO: process error messages |
87328572e36f
#159 adds release and eol dates
Mike Becker <universe@uap-core.de>
parents:
215
diff
changeset
|
566 | eta = http.param("eta", ::dateOptValidator, null, mutableListOf()) |
184 | 567 | |
568 | affectedVersions = http.paramArray("affected") | |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
569 | .mapNotNull { param -> param.toIntOrNull()?.let { Version(it, project.id) } } |
184 | 570 | resolvedVersions = http.paramArray("resolved") |
198
94f174d591ab
fixes wrong handling of feeds - only one channel per feed is allowed
Mike Becker <universe@uap-core.de>
parents:
193
diff
changeset
|
571 | .mapNotNull { param -> param.toIntOrNull()?.let { Version(it, project.id) } } |
184 | 572 | } |
573 | ||
186
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
574 | val openId = if (issue.id < 0) { |
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
575 | dao.insertIssue(issue) |
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
576 | } else { |
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
577 | dao.updateIssue(issue) |
214
69647ddb57f2
#153 adds comment box to issues form
Mike Becker <universe@uap-core.de>
parents:
210
diff
changeset
|
578 | val newComment = http.param("comment") |
69647ddb57f2
#153 adds comment box to issues form
Mike Becker <universe@uap-core.de>
parents:
210
diff
changeset
|
579 | if (!newComment.isNullOrBlank()) { |
69647ddb57f2
#153 adds comment box to issues form
Mike Becker <universe@uap-core.de>
parents:
210
diff
changeset
|
580 | dao.insertComment(IssueComment(-1, issue.id).apply { |
69647ddb57f2
#153 adds comment box to issues form
Mike Becker <universe@uap-core.de>
parents:
210
diff
changeset
|
581 | author = http.remoteUser?.let { dao.findUserByName(it) } |
69647ddb57f2
#153 adds comment box to issues form
Mike Becker <universe@uap-core.de>
parents:
210
diff
changeset
|
582 | comment = newComment |
69647ddb57f2
#153 adds comment box to issues form
Mike Becker <universe@uap-core.de>
parents:
210
diff
changeset
|
583 | }) |
69647ddb57f2
#153 adds comment box to issues form
Mike Becker <universe@uap-core.de>
parents:
210
diff
changeset
|
584 | } |
186
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
585 | issue.id |
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
586 | } |
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
587 | |
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
588 | if (http.param("more") != null) { |
185
5ec9fcfbdf9c
re-enables the "create another" feature
Mike Becker <universe@uap-core.de>
parents:
184
diff
changeset
|
589 | http.renderCommit("${issuesHref}-/create") |
5ec9fcfbdf9c
re-enables the "create another" feature
Mike Becker <universe@uap-core.de>
parents:
184
diff
changeset
|
590 | } else { |
186
05eec764facd
fixes some minor migration regressions
Mike Becker <universe@uap-core.de>
parents:
185
diff
changeset
|
591 | http.renderCommit("${issuesHref}${openId}") |
185
5ec9fcfbdf9c
re-enables the "create another" feature
Mike Becker <universe@uap-core.de>
parents:
184
diff
changeset
|
592 | } |
184 | 593 | } |
594 | } | |
595 | } |