THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

test
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

299 lines
15 KiB

@**
* Yona, 21st Century Project Hosting SW
*
* Copyright Yona & Yobi Authors & NAVER Corp.
* https://yona.io
**@
@(post:Posting, commentForm: play.data.Form[PostingComment], project:Project)
@import org.apache.commons.lang.StringUtils
@import utils.JodaDateUtil
@import utils.TemplateHelper._
@import utils.AccessControl._
@import models.enumeration._
@import play.libs.Json.toJson
@import utils.Markdown
@import controllers.api.IssueApi
@implicitField = @{ helper.FieldConstructor(simpleForm) }
@urlToPostings = @{
requestHeader.headers.get("Referer") match {
case Some(url) => { urlToList(url, routes.BoardApp.posts(project.owner, project.name).toString) }
case _ => routes.BoardApp.posts(project.owner, project.name).toString
}
}
@titleForOGTag = @{post.title + " |:| " + post.body.substring(0, Math.min(post.body.length, 200))}
@conatinsCurrentUserInWatchers = @{Watch.isWatching(UserApp.currentUser(), post.asResource())}
@isAllowedUpdate = @{
isAllowed(UserApp.currentUser(), post.asResource(), Operation.UPDATE)
}
@projectLayout(titleForOGTag, project, utils.MenuType.BOARD){
@projectMenu(project, utils.MenuType.BOARD, "main-menu-only")
<div class="page-wrap-outer">
<div class="project-page-wrap board-view">
@** Post Info **@
<div class="board-header issue">
<div class="pull-right mr10 mt10 hide-in-mobile">
<div class="date" title="@JodaDateUtil.getDateString(post.createdDate)">
@agoOrDateString(post.createdDate)
</div>
</div>
<div class="title">
<strong class="board-id">#@post.getNumber</strong> @post.title
<div class="pull-right hide show-in-mobile" style="font-size: 0.7em">
<span class="date" title="@JodaDateUtil.getDateString(post.createdDate)">
@agoOrDateString(post.createdDate)
</span>
</div>
</div>
</div>
@** Content body **@
<div class="board-body row-fluid">
<div class="span9 span-left-pane">
<div class="author-info">
<a href="@userInfo(post.authorLoginId)" class="usf-group">
<span class="avatar-wrap smaller">
<img src="@User.findByLoginId(post.authorLoginId).avatarUrl(32)" width="20" height="20">
</span>
@if(post.authorLoginId != null){
<strong class="name">@post.getAuthor.name</strong>
<span class="loginid"> <strong>@{"@"}</strong>@post.authorLoginId</span>
} else {
<strong class="name">@Messages("common.noAuthor")</strong>
}
</a>
@if(StringUtils.isNotEmpty(post.history)){
@if(UserApp.currentUser().isAnonymous){
<div class="posting-history">
<a href="@routes.UserApp.loginForm()?redirectUrl=@routes.BoardApp.post(project.owner, project.name, post.getNumber)" data-toggle="modal">@Messages("change.history")</a>
</div>
} else {
<div class="posting-history">
<a href="#-yona-posting-history" data-toggle="modal">@Messages("change.history")</a>
@common.partial_history(post)
</div>
}
}
</div>
@if(StringUtils.isEmpty(post.body)){
<div class="content empty-content"></div>
} else {
<div id="post-@post.getNumber" class="hide">
<form action="@api.routes.BoardApi.updatePostingContent(project.owner, project.name, post.getNumber)">
<textarea>@post.body</textarea>
</form>
</div>
<div id="post-body-@post.getNumber">
@common.tasklistBar()
<div class="content markdown-wrap" data-allowed-update="@isAllowedUpdate">@Html(Markdown.render(post.body, post.project))</div>
</div>
}
<div class="attachments" id="attachments" data-attachments="@toJson(AttachmentApp.getFileList(ResourceType.BOARD_POST.toString(), post.id.toString()))"></div>
<div class="board-actrow right-txt">
<div class="pull-left">
<div>
@if(isAllowed(UserApp.currentUser(), post.asResource(), Operation.WATCH)) {
<button id="watch-button" type="button" class="ybtn @if(conatinsCurrentUserInWatchers) {ybtn-watching}"
data-toggle="tooltip" data-placement="top" title="@Messages("issue.watch.description")" data-watching="@conatinsCurrentUserInWatchers">
@if(conatinsCurrentUserInWatchers) {
@Messages("post.unwatch")
} else {
@Messages("post.watch")
}
</button>
}
</div>
</div>
@if(StringUtils.isNotBlank(IssueApi.TRANSLATION_API)) {
<button type="button" id="translate" class="icon btn-transparent-with-fontsize-lineheight ml10" data-toggle="tooltip" title="@Messages("button.translation")"><i class="yobicon-lang"></i></button>
}
<span class="">
@if(isAllowed(UserApp.currentUser(), post.asResource(), Operation.UPDATE)) {
<button type="button" class="icon btn-transparent-with-fontsize-lineheight ml10 pt5px" data-toggle="tooltip" title="@Messages("button.edit")" onclick="window.location = '@routes.BoardApp.editPostForm(project.owner, project.name, post.getNumber)'"><i class="yobicon-edit-2"></i></button>
} else {
<a href="@routes.BoardApp.editPostForm(project.owner, project.name, post.getNumber)"><button type="button" class="icon btn-transparent-with-fontsize-lineheight ml10 pt5px" data-toggle="tooltip" title="@Messages("button.show.original")"><i class="yobicon-edit-2"></i></button></a>
}
@if(isAllowed(UserApp.currentUser(), post.asResource(), Operation.DELETE)) {
<a href="#deleteConfirm" data-toggle="modal">
<button type="button" class="icon btn-transparent-with-fontsize-lineheight ml6" data-toggle='tooltip' title="@Messages("button.delete")"><i class="yobicon-trash"></i></button></a>
}
</span>
</div>
<div class="watcher-list"></div>
@** Comment **@
<div id="comments" class="board-comment-wrap">
<div id="timeline">
<div class="timeline-list">
@partial_comments(project, post)
</div>
</div>
@common.commentForm(post.asResource(), ResourceType.NONISSUE_COMMENT, routes.BoardApp.newComment(project.owner, project.name, post.getNumber).toString())
</div>
@** // Comment **@
</div>
<div class="span3 span-right-pane mb20">
<div class="issue-info board-labels">
<dl>
@if(project.menuSetting.board) {
<dd class="project-btn-item">
<a href="@routes.BoardApp.newPostForm(project.owner, project.name)" class="ybtn ybtn-success">@Messages("post.write")</a>
</dd>
}
</dl>
@**<!-- labels -->**@
@if(!IssueLabel.findByProject(project).isEmpty){
@if(isAllowedUpdate){
@issue.partial_select_label(IssueLabel.findByProject(project), post.getLabelIds, "", "", project)
} else {
@issue.partial_show_selected_label(post.labels.toList, "")
}
}
@**<!-- // -->**@
<div class="right-menu-icons">
@if(isAllowed(UserApp.currentUser(), post.asResource(), Operation.UPDATE)) {
<button type="button" class="icon btn-transparent-with-fontsize-lineheight ml10 pt5px" data-toggle="tooltip" title="@Messages("button.edit")" onclick="window.location='@routes.BoardApp.editPostForm(project.owner, project.name, post.getNumber)'"><i class="yobicon-edit-2"></i></button>
} else {
<a href="@routes.BoardApp.editPostForm(project.owner, project.name, post.getNumber)"><button type="button" class="icon btn-transparent-with-fontsize-lineheight ml10 pt5px" data-toggle="tooltip" title="@Messages("button.show.original")"><i class="yobicon-edit-2"></i></button></a>
}
@if(isAllowed(UserApp.currentUser(), post.asResource(), Operation.DELETE)) {
<a href="#deleteConfirm" data-toggle="modal">
<button type="button" class="icon btn-transparent-with-fontsize-lineheight ml6" data-toggle='tooltip' title="@Messages("button.delete")"><i class="yobicon-trash"></i></button></a>
}
</div>
</div>
</div>
</div>
<div class="board-footer">
@help.keymap("boardDetail", project)
</div>
</div>
<script type="text/x-jquery-tmpl" id="tplAttachedFile"><!--
--><li class="attached-file" data-name="${fileName}" data-href="${fileHref}" data-mime="${mimeType}" data-size="${fileSize}">
<strong>${fileName}(${fileSizeReadable})${notice}</strong><!--
--><a class="attached-delete"><i class="ico btn-delete"></i></a></li>
</script>
@** Confirm to delete post **@
<div id="deleteConfirm" class="modal hide fade">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h3>@Messages("issue.delete")</h3>
</div>
<div class="modal-body">
<p>@Messages("post.delete.confirm")</p>
</div>
<div class="modal-footer">
<button type="button" class="ybtn ybtn-danger" data-request-method="delete" data-request-uri="@routes.BoardApp.deletePost(project.owner, project.name, post.getNumber)">@Messages("button.yes")</button>
<button type="button" class="ybtn" data-dismiss="modal">@Messages("button.no")</button>
</div>
</div>
</div>
@common.markdown(project)
@common.commentDeleteModal()
<link rel="stylesheet" type="text/css" media="screen" href="@routes.IssueLabelApp.labelStyles(project.owner, project.name)">
<link rel="stylesheet" type="text/css" media="screen" href="@routes.Assets.at("javascripts/lib/atjs/jquery.atwho.css")">
<link rel="stylesheet" type="text/css" media="screen" href="@routes.Assets.at("javascripts/lib/elevator/jquery.elevator.css")">
<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/atjs/jquery.caret.min.js")"></script>
<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/atjs/jquery.atwho.js")"></script>
<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/elevator/jquery.elevator.js")"></script>
<script type="text/javascript" src="@routes.Assets.at("javascripts/common/yona.Sha1.js")"></script>
<script type="text/javascript" src="@routes.Assets.at("javascripts/common/yona.Tasklist.js")"></script>
<script type="text/javascript" src="@routes.Assets.at("javascripts/common/yona.SubComment.js")"></script>
<script type="text/javascript">
$(document).ready(function(){
$yobi.loadModule("board.View", {
"sWatchUrl" : "@routes.WatchApp.watch(post.asResource.asParameter)",
"sUnwatchUrl": "@routes.WatchApp.unwatch(post.asResource.asParameter)"
});
// yobi.ShortcutKey
yobi.ShortcutKey.setKeymapLink({
"L": "@urlToPostings"
@if(project.menuSetting.board) {
,"N": "@routes.BoardApp.newPostForm(project.owner, project.name)"
}
@if(isAllowedUpdate){
,"E": "@routes.BoardApp.editPostForm(project.owner, project.name, post.getNumber)"
}
});
// yobi.Mention
yobi.Mention({
"target": "textarea[id^=editor-]",
"url" : "@Html(routes.ProjectApp.mentionList(project.owner, project.name, post.getNumber, post.asResource().getType.resource()).toString())"
});
$('.board-labels select').on('change', function(e){
var url = "@Html(controllers.api.routes.BoardApi.updatePostLabel(project.owner, project.name, post.getNumber).toString())";
$.ajax({
url: url,
method: "POST",
data: JSON.stringify(e.val),
contentType: "application/json; charset=UTF-8"
}).done(function(response) {
}).error(function(response){
});
});
// detect comment which contains mention at me
$(".comment-body:contains('@UserApp.currentUser().getPureNameOnly')").closest(".comment").addClass("mentioned");
$('#translate').one('click', function (e) {
var data = {
owner: "@project.owner",
projectName: "@project.name",
type: "posting",
number: "@post.getNumber"
};
$.ajax({
url: "/-_-api/v1/translation",
data: JSON.stringify(data),
type: "POST",
dataType: "json",
contentType: "application/json"
}).done(function (data) {
$(".markdown-wrap").first().html(data.translated);
$(this).attr("disabled", true);
});
});
$('.comment-translate').one('click', function (e) {
var payload = {
owner: "@project.owner",
projectName: "@project.name",
type: "post-comment",
number: $(this).data("commentId")
};
$.ajax({
url: "/-_-api/v1/translation",
data: JSON.stringify(payload),
type: "POST",
dataType: "json",
contentType: "application/json"
}).done(function (data) {
$("#comment-body-" + payload.number).find(".markdown-wrap").html(data.translated)
$(this).attr("disabled", true);
});
});
$.elevator({
shape: 'rounded',
glass: true
});
});
</script>
@common.select2()
}