[Notice] Announcing the End of Demo Server [Read me]
issue: Issue sharing feature - view and message
@49812f7abaee35b151f57e8affd3ea5bf11aeb6c
--- app/assets/stylesheets/less/_common.less
+++ app/assets/stylesheets/less/_common.less
... | ... | @@ -219,6 +219,7 @@ |
219 | 219 |
.mt4 { margin-top:4px; } |
220 | 220 |
.mr3 { margin-right:3px; } |
221 | 221 |
.pb4 { padding-bottom: 4px} |
222 |
+.pl0 { padding-left: 0} |
|
222 | 223 |
|
223 | 224 |
.margin-top-20 { margin-top:20px; } |
224 | 225 |
.margin-left-20 { margin-left: 20px; } |
... | ... | @@ -281,3 +282,21 @@ |
281 | 282 |
.va-text-top { |
282 | 283 |
vertical-align: text-top !important; |
283 | 284 |
} |
285 |
+ |
|
286 |
+.width100p { |
|
287 |
+ width: 100% |
|
288 |
+} |
|
289 |
+ |
|
290 |
+.text-ellipsis { |
|
291 |
+ white-space: nowrap; |
|
292 |
+ overflow: hidden; |
|
293 |
+ text-overflow: ellipsis; |
|
294 |
+} |
|
295 |
+ |
|
296 |
+.z-index-1 { |
|
297 |
+ z-index: 1 !important; |
|
298 |
+} |
|
299 |
+ |
|
300 |
+.hideFromDisplayOnly { |
|
301 |
+ display: none; |
|
302 |
+} |
--- app/assets/stylesheets/less/_override.less
+++ app/assets/stylesheets/less/_override.less
... | ... | @@ -182,6 +182,23 @@ |
182 | 182 |
.box-shadow(none); |
183 | 183 |
} |
184 | 184 |
|
185 |
+.sharer-list { |
|
186 |
+ .select2-container{ |
|
187 |
+ border: none; |
|
188 |
+ box-shadow: none; |
|
189 |
+ border-radius: 0 !important; |
|
190 |
+ border-bottom: 1px solid rgba(0, 0, 0, 0.15); |
|
191 |
+ } |
|
192 |
+ .select2-container-multi { |
|
193 |
+ .select2-choices { |
|
194 |
+ .select2-search-choice { |
|
195 |
+ background-color: #ececec; |
|
196 |
+ border: 1px solid #dfdfdf; |
|
197 |
+ } |
|
198 |
+ } |
|
199 |
+ } |
|
200 |
+} |
|
201 |
+ |
|
185 | 202 |
.select2-dropdown-open { |
186 | 203 |
.select2-choice { |
187 | 204 |
border-bottom-color: transparent; |
--- app/assets/stylesheets/less/_page.less
+++ app/assets/stylesheets/less/_page.less
... | ... | @@ -3745,8 +3745,15 @@ |
3745 | 3745 |
.comments-count-color { |
3746 | 3746 |
color: @darkmagenta; |
3747 | 3747 |
} |
3748 |
+ .sharer-color { |
|
3749 |
+ color: @green; |
|
3750 |
+ } |
|
3748 | 3751 |
|
3749 | 3752 |
a:nth-child(2) { |
3753 |
+ margin-left: -5px; |
|
3754 |
+ } |
|
3755 |
+ |
|
3756 |
+ a:nth-child(3) { |
|
3750 | 3757 |
margin-left: -5px; |
3751 | 3758 |
} |
3752 | 3759 |
|
... | ... | @@ -7070,3 +7077,19 @@ |
7070 | 7077 |
border-radius: 4px; |
7071 | 7078 |
} |
7072 | 7079 |
} |
7080 |
+ |
|
7081 |
+.sharer-list { |
|
7082 |
+ margin-top: 40px; |
|
7083 |
+ padding: 10px; |
|
7084 |
+ |
|
7085 |
+ .issue-share-title { |
|
7086 |
+ font-size: 16px; |
|
7087 |
+ } |
|
7088 |
+ .sharer-item{ |
|
7089 |
+ display: inline-block; |
|
7090 |
+ background-color: #ececec; |
|
7091 |
+ border: 1px solid #dfdfdf; |
|
7092 |
+ border-radius: 3px; |
|
7093 |
+ padding: 1px 8px; |
|
7094 |
+ } |
|
7095 |
+} |
--- app/views/issue/partial_list.scala.html
+++ app/views/issue/partial_list.scala.html
... | ... | @@ -62,7 +62,7 @@ |
62 | 62 |
</span> |
63 | 63 |
} |
64 | 64 |
|
65 |
- @if(issue.comments.size>0 || issue.voters.size>0) { |
|
65 |
+ @if(issue.comments.size > 0 || issue.voters.size > 0 || issue.sharers.size > 0) { |
|
66 | 66 |
<span class="infos-item item-count-groups"> |
67 | 67 |
@if(issue.comments.size>0){ |
68 | 68 |
@views.html.common.commentCount(routes.IssueApp.issue(project.owner, project.name, issue.getNumber).toString + "#comments", issue.comments.size, true) |
... | ... | @@ -70,6 +70,9 @@ |
70 | 70 |
@if(issue.voters.size>0){ |
71 | 71 |
@views.html.common.voteCount(routes.IssueApp.issue(project.owner, project.name, issue.getNumber).toString + "#vote", issue.voters.size, true) |
72 | 72 |
} |
73 |
+ @if(issue.sharers.size > 0){ |
|
74 |
+ @views.html.common.sharerCount(issue.sharers.size, true) |
|
75 |
+ } |
|
73 | 76 |
</span> |
74 | 77 |
} |
75 | 78 |
|
--- app/views/issue/view.scala.html
+++ app/views/issue/view.scala.html
... | ... | @@ -5,6 +5,7 @@ |
5 | 5 |
* https://yona.io |
6 | 6 |
**@ |
7 | 7 |
@(title:String, issue:Issue, issueForm: play.data.Form[Issue], commentForm: play.data.Form[Comment],project:Project) |
8 |
+@import scala.collection.mutable.ArrayBuffer |
|
8 | 9 |
@import org.apache.commons.lang.StringUtils |
9 | 10 |
@import models.enumeration.ResourceType |
10 | 11 |
@import models.enumeration.Operation |
... | ... | @@ -56,6 +57,22 @@ |
56 | 57 |
} else { |
57 | 58 |
issue.id |
58 | 59 |
} |
60 |
+} |
|
61 |
+ |
|
62 |
+@hasAssignee = @{ |
|
63 |
+ issue.assigneeName != null |
|
64 |
+} |
|
65 |
+ |
|
66 |
+@hasSharer = @{ |
|
67 |
+ issue.sharers.size > 0 |
|
68 |
+} |
|
69 |
+ |
|
70 |
+@sharers = @{ |
|
71 |
+ var sharerIds = ArrayBuffer[String]() |
|
72 |
+ for( sharedUser <- issue.sharers ) { |
|
73 |
+ sharerIds += sharedUser.loginId |
|
74 |
+ } |
|
75 |
+ sharerIds.mkString(",") |
|
59 | 76 |
} |
60 | 77 |
|
61 | 78 |
@VOTER_AVATAR_SHOW_LIMIT = @{ 5 } |
... | ... | @@ -175,6 +192,9 @@ |
175 | 192 |
} |
176 | 193 |
</button> |
177 | 194 |
} |
195 |
+ @if(isAllowed(UserApp.currentUser(), issue.asResource(), Operation.UPDATE) && !hasSharer) { |
|
196 |
+ <button id="issue-share-button" type="button" class="ybtn">@Messages("button.share.issue")</button> |
|
197 |
+ } |
|
178 | 198 |
|
179 | 199 |
</div> |
180 | 200 |
</div> |
... | ... | @@ -219,6 +239,24 @@ |
219 | 239 |
} |
220 | 240 |
</span> |
221 | 241 |
</div> |
242 |
+ <dl class="sharer-list @if(!hasSharer){hideFromDisplayOnly}"> |
|
243 |
+ <dt class="issue-share-title mb10"> |
|
244 |
+ @Messages("issue.sharer") <span class="num issue-sharer-count">@if(issue.sharers.size > 0) { @issue.sharers.size }</span> |
|
245 |
+ </dt> |
|
246 |
+ <dd id="sharer-list" class="@if(!hasSharer){hideFromDisplayOnly}"> |
|
247 |
+ @if(isAllowed(UserApp.currentUser(), issue.asResource(), Operation.UPDATE)) { |
|
248 |
+ <input type="hidden" class="bigdrop width100p" id="issueSharer" name="issueSharer" placeholder="@Messages("issue.sharer.select")" value="@sharers" title=""> |
|
249 |
+ } else { |
|
250 |
+ @for(sharer <- issue.getSortedSharer){ |
|
251 |
+ <div class="text-ellipsis sharer-item"> |
|
252 |
+ <a href="@userInfo(sharer.loginId)" class="usf-group"> |
|
253 |
+ <strong class="name">@sharer.user.getDisplayName</strong> |
|
254 |
+ </a> |
|
255 |
+ </div> |
|
256 |
+ } |
|
257 |
+ } |
|
258 |
+ </dd> |
|
259 |
+ </dl> |
|
222 | 260 |
<div class="watcher-list"></div> |
223 | 261 |
<div class="subtasks"> |
224 | 262 |
@if(issue.parent == null) { |
... | ... | @@ -254,23 +292,21 @@ |
254 | 292 |
<dt>@Messages("issue.assignee")</dt> |
255 | 293 |
|
256 | 294 |
<dd> |
257 |
- @defining(issue.assigneeName != null) { isAssigned => |
|
258 |
- @if(isAllowed(UserApp.currentUser(), issue.asResource(), Operation.UPDATE)) { |
|
259 |
- @partial_assignee(project, issue) |
|
295 |
+ @if(isAllowed(UserApp.currentUser(), issue.asResource(), Operation.UPDATE)) { |
|
296 |
+ @partial_assignee(project, issue) |
|
297 |
+ } else { |
|
298 |
+ @if(hasAssignee){ |
|
299 |
+ <a href="@userInfo(issue.assignee.user.loginId)" class="usf-group"> |
|
300 |
+ <span class="avatar-wrap smaller"> |
|
301 |
+ <img src="@User.findByLoginId(issue.assignee.user.loginId).avatarUrl" width="20" height="20"> |
|
302 |
+ </span> |
|
303 |
+ <strong class="name">@issue.assignee.user.getDisplayName</strong> |
|
304 |
+ <span class="loginid"> <strong>@{"@"}</strong>@issue.assignee.user.loginId</span> |
|
305 |
+ </a> |
|
260 | 306 |
} else { |
261 |
- @if(isAssigned){ |
|
262 |
- <a href="@userInfo(issue.assignee.user.loginId)" class="usf-group"> |
|
263 |
- <span class="avatar-wrap smaller"> |
|
264 |
- <img src="@User.findByLoginId(issue.assignee.user.loginId).avatarUrl" width="20" height="20"> |
|
265 |
- </span> |
|
266 |
- <strong class="name">@issue.assignee.user.getDisplayName</strong> |
|
267 |
- <span class="loginid"> <strong>@{"@"}</strong>@issue.assignee.user.loginId</span> |
|
268 |
- </a> |
|
269 |
- } else { |
|
270 |
- <div> |
|
271 |
- @Messages("issue.noAssignee") |
|
272 |
- </div> |
|
273 |
- } |
|
307 |
+ <div> |
|
308 |
+ @Messages("issue.noAssignee") |
|
309 |
+ </div> |
|
274 | 310 |
} |
275 | 311 |
} |
276 | 312 |
</dd> |
... | ... | @@ -427,6 +463,7 @@ |
427 | 463 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/atjs/jquery.caret.min.js")"></script> |
428 | 464 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/atjs/jquery.atwho.js")"></script> |
429 | 465 |
<script type="text/javascript" src="@routes.Assets.at("javascripts/service/yona.issue.Assginee.js")"></script> |
466 |
+<script type="text/javascript" src="@routes.Assets.at("javascripts/service/yona.issue.Sharer.js")"></script> |
|
430 | 467 |
<script type="text/javascript"> |
431 | 468 |
$(function(){ |
432 | 469 |
// yobi.issue.View |
... | ... | @@ -471,6 +508,18 @@ |
471 | 508 |
"@Messages("issue.assignee")" |
472 | 509 |
); |
473 | 510 |
|
511 |
+ yonaIssueSharerModule( |
|
512 |
+ "@api.routes.IssueApi.findSharerByloginIds(project.owner, project.name, issue.getNumber)", |
|
513 |
+ "@api.routes.IssueApi.findSharableUsers(project.owner, project.name, issue.getNumber)", |
|
514 |
+ "@api.routes.IssueApi.updateSharer(project.owner, project.name, issue.getNumber)", |
|
515 |
+ "@Messages("issue.sharer")" |
|
516 |
+ ); |
|
517 |
+ |
|
518 |
+ $('#issue-share-button').on('click', function () { |
|
519 |
+ $('#sharer-list').show(); |
|
520 |
+ $('.sharer-list').show(); |
|
521 |
+ }); |
|
522 |
+ |
|
474 | 523 |
$('#translate').one('click', function (e) { |
475 | 524 |
var data = { |
476 | 525 |
owner: "@project.owner", |
--- conf/messages
+++ conf/messages
... | ... | @@ -75,6 +75,8 @@ |
75 | 75 |
button.selectFile = Select file |
76 | 76 |
button.setDefaultLoginPage = Set to default page |
77 | 77 |
button.setDefaultLoginPage.desc = Make current page to index page when logged in |
78 |
+button.share.issue = Issue Sharing |
|
79 |
+button.share.issue.desc = Allow others can see this issue and receive notifications |
|
78 | 80 |
button.show.original = See text |
79 | 81 |
button.signup = Sign up for {0} |
80 | 82 |
button.submitForm = Submit form |
... | ... | @@ -302,6 +304,8 @@ |
302 | 304 |
issue.noMilestone = No milestone |
303 | 305 |
issue.option = Option |
304 | 306 |
issue.search = Search Issues |
307 |
+issue.sharer = Issue Sharer |
|
308 |
+issue.sharer.select = Select Issue Sharer |
|
305 | 309 |
issue.state = Status |
306 | 310 |
issue.state.all = All |
307 | 311 |
issue.state.assigned = Assigned |
--- conf/messages.ko-KR
+++ conf/messages.ko-KR
... | ... | @@ -75,6 +75,8 @@ |
75 | 75 |
button.selectFile = 파일 선택 |
76 | 76 |
button.setDefaultLoginPage = 기본 페이지로 지정 |
77 | 77 |
button.setDefaultLoginPage.desc = 현재 페이지를 로그인 후 표시되는 기본 인덱스 페이지로 지정합니다 |
78 |
+button.share.issue = 이슈 공유 |
|
79 |
+button.share.issue.desc = 이 이슈에 대한 접근과 알림을 허용할 사용자를 지정합니다 |
|
78 | 80 |
button.show.original = 원문 보기 |
79 | 81 |
button.signup = {0} 시작 하기 |
80 | 82 |
button.submitForm = 폼 전송 |
... | ... | @@ -302,6 +304,8 @@ |
302 | 304 |
issue.noMilestone = 마일스톤 없음 |
303 | 305 |
issue.option = 이슈 옵션 |
304 | 306 |
issue.search = 이슈 검색 |
307 |
+issue.sharer = 이슈 공유 |
|
308 |
+issue.sharer.select = 이슈 공유 대상 선택 |
|
305 | 309 |
issue.state = 상태 |
306 | 310 |
issue.state.all = 전체 |
307 | 311 |
issue.state.assigned = 할당됨 |
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?