subtask: Change subtask feature
- Change new issue button to new subtask button in issue view page - Hide subtasks in all list - Make parent issue status bar more distinguishable
@44f616080f9a9ea08a8f290333d651fbacae773a
--- app/assets/stylesheets/less/_common.less
+++ app/assets/stylesheets/less/_common.less
... | ... | @@ -110,6 +110,12 @@ |
110 | 110 |
background:#f0f0f0; |
111 | 111 |
filter:none; |
112 | 112 |
|
113 |
+ &.done-outline { |
|
114 |
+ border: 1px solid @light-green; |
|
115 |
+ } |
|
116 |
+ &.red-outline { |
|
117 |
+ border: 1px solid @yona-red; |
|
118 |
+ } |
|
113 | 119 |
.box-shadow(inset 0px 1px 1px rgba(0,0,0,0.25)); |
114 | 120 |
.bar { |
115 | 121 |
height:100%; |
... | ... | @@ -117,6 +123,7 @@ |
117 | 123 |
&.orange { background:@orange; .box-shadow(none); } // #f28149 |
118 | 124 |
&.blue { background:@blue; .box-shadow(none); } |
119 | 125 |
&.grey { background:@gray-9e; .box-shadow(none); } |
126 |
+ &.red { background:@yona-red; .box-shadow(none); } |
|
120 | 127 |
&.done { background:@light-green; .box-shadow(none); } |
121 | 128 |
&.open { background:@state-open; .box-shadow(none); } |
122 | 129 |
&.closed { background:@state-closed; .box-shadow(none); } |
--- app/assets/stylesheets/less/_page.less
+++ app/assets/stylesheets/less/_page.less
... | ... | @@ -7020,3 +7020,17 @@ |
7020 | 7020 |
} |
7021 | 7021 |
} |
7022 | 7022 |
} |
7023 |
+ |
|
7024 |
+.subtask-mark { |
|
7025 |
+ border: 1px solid #e95e01; |
|
7026 |
+ border-radius: 3px; |
|
7027 |
+ padding: 2px 5px; |
|
7028 |
+ font-size: 14px; |
|
7029 |
+ color: #e95e01; |
|
7030 |
+ margin-right: 5px; |
|
7031 |
+} |
|
7032 |
+.subtask-number { |
|
7033 |
+ color: darkgrey; |
|
7034 |
+ font-size: 12px; |
|
7035 |
+ margin-right: 5px; |
|
7036 |
+} |
--- app/assets/stylesheets/less/_variables.less
+++ app/assets/stylesheets/less/_variables.less
... | ... | @@ -63,6 +63,7 @@ |
63 | 63 |
@yobi-orange : #FF7332; |
64 | 64 |
@yobi-orange-dark : #E95E01; |
65 | 65 |
@yobi-red : #C93426; |
66 |
+@yona-red : #f44336; |
|
66 | 67 |
@yobi-red-dark : #B13427; |
67 | 68 |
@yobi-white :#FFF; |
68 | 69 |
@yobi-white-dark :#F2F2F2; |
--- app/models/Issue.java
+++ app/models/Issue.java
... | ... | @@ -196,9 +196,9 @@ |
196 | 196 |
|
197 | 197 |
public static int countIssues(Long projectId, State state) { |
198 | 198 |
if (state == State.ALL) { |
199 |
- return finder.where().eq("project.id", projectId).findRowCount(); |
|
199 |
+ return finder.where().eq("project.id", projectId).isNull("parent.id").findRowCount(); |
|
200 | 200 |
} else { |
201 |
- return finder.where().eq("project.id", projectId).eq("state", state).findRowCount(); |
|
201 |
+ return finder.where().eq("project.id", projectId).isNull("parent.id").eq("state", state).findRowCount(); |
|
202 | 202 |
} |
203 | 203 |
} |
204 | 204 |
|
--- app/models/support/SearchCondition.java
+++ app/models/support/SearchCondition.java
... | ... | @@ -443,6 +443,10 @@ |
443 | 443 |
el.lt("dueDate", DateUtils.addDays(dueDate, 1)); |
444 | 444 |
} |
445 | 445 |
|
446 |
+ if (authorId == null && StringUtils.isBlank(filter) && assigneeId == null && mentionId == null) { |
|
447 |
+ el.isNull("parent.id"); |
|
448 |
+ } |
|
449 |
+ |
|
446 | 450 |
return el; |
447 | 451 |
} |
448 | 452 |
|
--- app/views/issue/partial_list_subtask.scala.html
+++ app/views/issue/partial_list_subtask.scala.html
... | ... | @@ -14,8 +14,8 @@ |
14 | 14 |
@defining(Issue.countByParentIssueIdAndState(issue.id, State.OPEN)) { openIssueCount => |
15 | 15 |
@defining(Issue.countByParentIssueIdAndState(issue.id, State.CLOSED)) { closedIssueCount => |
16 | 16 |
@defining(getPercent(closedIssueCount.toDouble, openIssueCount + closedIssueCount)) { percentage => |
17 |
- <div class="upload-progress"> |
|
18 |
- <div class="bar @if(percentage == 100) {done} else {grey}" style="width: @percentage%;" title="Subtask"></div> |
|
17 |
+ <div class="upload-progress @if(percentage == 100){done-outline} else {red-outline}"> |
|
18 |
+ <div class="bar @if(percentage == 100) {done} else {red}" style="width: @percentage%;" title="Subtask"></div> |
|
19 | 19 |
</div> |
20 | 20 |
<span class="completion-ratio @if(percentage == 100){txt-green}">@if(percentage != 100){@closedIssueCount/}@(closedIssueCount + openIssueCount)</span> |
21 | 21 |
} |
--- app/views/issue/partial_select_subtask.scala.html
+++ app/views/issue/partial_select_subtask.scala.html
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 |
**@ |
7 | 7 |
@(project:Project, parentIssueId:Long, currentIssueId:Long) |
8 | 8 |
|
9 |
-@showOption = @{Option(parentIssueId).isDefined && Option(currentIssueId).isDefined} |
|
9 |
+@showOption = @{Option(parentIssueId).isDefined || Option(currentIssueId).isDefined} |
|
10 | 10 |
@hasChildIssue = @{Option(currentIssueId).isDefined && Issue.finder.byId(currentIssueId).hasChildIssue} |
11 | 11 |
@import utils.TemplateHelper._ |
12 | 12 |
|
--- app/views/issue/view.scala.html
+++ app/views/issue/view.scala.html
... | ... | @@ -66,10 +66,10 @@ |
66 | 66 |
@if(!openChildIssues.isEmpty || !closedChildIssues.isEmpty) { |
67 | 67 |
<div class="child-issues"> |
68 | 68 |
@defining(Issue.finder.byId(parentIssueId)) { parentIssue => |
69 |
- <div class="issue-item parent-issue"><a href="@routes.IssueApp.issue(parentIssue.project.owner, parentIssue.project.name, parentIssue.getNumber)" class="@if(parentIssue.id == issue.id){bold}">#@parentIssue.getNumber @parentIssue.title @if(parentIssue.assignee != null) {- @parentIssue.assignee.user.name}</a> |
|
69 |
+ <div class="issue-item parent-issue"><a href="@routes.IssueApp.issue(parentIssue.project.owner, parentIssue.project.name, parentIssue.getNumber)" class="@if(parentIssue.id == issue.id){bold}">#@parentIssue.getNumber @parentIssue.title @if(parentIssue.assignee != null) {- @parentIssue.assignee.user.getPureNameOnly}</a> |
|
70 | 70 |
@defining(getPercent(closedChildIssues.size.toDouble, (openChildIssues.size + closedChildIssues.size).toDouble)) { percentage => |
71 |
- <div class="upload-progress"> |
|
72 |
- <div class="bar @if(percentage == 100){done} else {grey}" style="width: @percentage%;" title="Subtask"></div> |
|
71 |
+ <div class="upload-progress @if(percentage == 100){done-outline} else {red-outline}"> |
|
72 |
+ <div class="bar @if(percentage == 100){done} else {red}" style="width: @percentage%;" title="Subtask"></div> |
|
73 | 73 |
</div> |
74 | 74 |
<span class="@if(percentage == 100){txt-green}">@if(percentage != 100){@closedChildIssues.size/}@(openChildIssues.size + closedChildIssues.size)</span> |
75 | 75 |
<span class="parent-issue-state @parentIssue.state.state">@Messages("issue.state." + parentIssue.state.state)</span> |
... | ... | @@ -81,7 +81,7 @@ |
81 | 81 |
<div class="issue-item @if(childIssue.id == issue.id){bold}"> |
82 | 82 |
<span class="state-label open"></span> |
83 | 83 |
<a href="@routes.IssueApp.issue(childIssue.project.owner, childIssue.project.name, childIssue.getNumber)"> |
84 |
- <span class="item-name">@childIssue.title @if(childIssue.assignee != null) {- @childIssue.assignee.user.name}</span> |
|
84 |
+ <span class="item-name"><span class="subtask-number">#@childIssue.getNumber</span> @childIssue.title @if(childIssue.assignee != null) {- @childIssue.assignee.user.getPureNameOnly}</span> |
|
85 | 85 |
</a> |
86 | 86 |
</div> |
87 | 87 |
} |
... | ... | @@ -89,7 +89,7 @@ |
89 | 89 |
<div class="issue-item @if(childIssue.id == issue.id){bold}"> |
90 | 90 |
<span class="state-label closed"><i class=" yobicon-checkmark"></i></span> |
91 | 91 |
<a href="@routes.IssueApp.issue(childIssue.project.owner, childIssue.project.name, childIssue.getNumber)"> |
92 |
- <span class="item-name">@childIssue.title @if(childIssue.assignee != null) {- @childIssue.assignee.user.name}</span> |
|
92 |
+ <span class="item-name"><span class="subtask-number">#@childIssue.getNumber</span> @childIssue.title @if(childIssue.assignee != null) {- @childIssue.assignee.user.getPureNameOnly}</span> |
|
93 | 93 |
</a> |
94 | 94 |
</div> |
95 | 95 |
} |
... | ... | @@ -114,6 +114,9 @@ |
114 | 114 |
<span class="badge badge-issue-@issue.state.state.toLowerCase">@Messages("issue.state." + issue.state.state)</span> |
115 | 115 |
</div> |
116 | 116 |
<div class="title"> |
117 |
+ @if(issue.parent != null) { |
|
118 |
+ <span class="subtask-mark">subtask</span> |
|
119 |
+ } |
|
117 | 120 |
<strong class="board-id">#@issue.getNumber</strong> @issue.title |
118 | 121 |
<div class="pull-right hide show-in-mobile" style="font-size: 0.7em"> |
119 | 122 |
<span class="date" title="@JodaDateUtil.getDateString(issue.createdDate)"> |
... | ... | @@ -246,7 +249,7 @@ |
246 | 249 |
<dl> |
247 | 250 |
@if(project.menuSetting.issue) { |
248 | 251 |
<dd class="project-btn-item"> |
249 |
- <a href="@routes.IssueApp.newIssueForm(project.owner, project.name)?parentIssueId=@parentIssueId" class="ybtn ybtn-success">@Messages("button.newIssue")</a> |
|
252 |
+ <a href="@routes.IssueApp.newIssueForm(project.owner, project.name)?parentIssueId=@parentIssueId" class="ybtn ybtn-success">@Messages("button.newSubtask")</a> |
|
250 | 253 |
</dd> |
251 | 254 |
} |
252 | 255 |
<dt>@Messages("issue.assignee")</dt> |
--- conf/messages
+++ conf/messages
... | ... | @@ -61,6 +61,7 @@ |
61 | 61 |
button.new.enrollment = Send sign-up request |
62 | 62 |
button.newIssue = New issue |
63 | 63 |
button.newProject = Create new project |
64 |
+button.newSubtask = New subtask |
|
64 | 65 |
button.nextPage = Next page |
65 | 66 |
button.nextState.closed = Close issue |
66 | 67 |
button.nextState.open = Reopen issue |
--- conf/messages.ko-KR
+++ conf/messages.ko-KR
... | ... | @@ -61,6 +61,7 @@ |
61 | 61 |
button.new.enrollment = 멤버 등록 요청하기 |
62 | 62 |
button.newIssue = 새 이슈 등록 |
63 | 63 |
button.newProject = 새 프로젝트 만들기 |
64 |
+button.newSubtask = 새 서브 태스크 |
|
64 | 65 |
button.nextPage = 다음 페이지 |
65 | 66 |
button.nextState.closed = 이슈 닫기 |
66 | 67 |
button.nextState.open = 이슈 다시 열기 |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?