Finish task#43858. review code in diff view of MR module.
This commit is contained in:
+67
-1
@@ -106,6 +106,27 @@ class mr extends control
|
||||
|
||||
$gitlabUsers = $this->gitlab->getUserAccountIdPairs($MR->gitlabID);
|
||||
|
||||
/* Import lang for required modules. */
|
||||
$this->loadModel('repo');
|
||||
$this->loadModel('job');
|
||||
$this->loadModel('compile');
|
||||
|
||||
$repoList = array();
|
||||
$rawRepoList = $this->repo->getGitLabRepoList($MR->gitlabID, $MR->sourceProject);
|
||||
foreach($rawRepoList as $rawRepo) $repoList[$rawRepo->id] = "[$rawRepo->id] $rawRepo->name";
|
||||
|
||||
$jobList = array();
|
||||
$rawJobList = $this->job->getListByRepoID($MR->repoID);
|
||||
foreach($rawJobList as $rawJob) $jobList[$rawJob->id] = "[$rawJob->id] $rawJob->name";
|
||||
|
||||
$compileList = array();
|
||||
$rawCompileList = $this->compile->getListByJobID($MR->jobID);
|
||||
foreach($rawCompileList as $rawCompile) $compileList[$rawCompile->id] = "[$rawCompile->id] [{$this->lang->compile->statusList[$rawCompile->status]}] $rawCompile->name";
|
||||
|
||||
$this->view->repoList = $repoList;
|
||||
$this->view->jobList = !empty($MR->repoID) ? $jobList : array();
|
||||
$this->view->compileList = !empty($MR->jobID) ? $compileList : array();
|
||||
|
||||
$this->view->title = $this->lang->mr->edit;
|
||||
$this->view->MR = $MR;
|
||||
$this->view->targetBranchList = $targetBranchList;
|
||||
@@ -286,6 +307,8 @@ class mr extends control
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->repo = $this->loadModel('repo')->getRepoByID($MR->repoID);
|
||||
$this->view->repoID = $MR->repoID;
|
||||
$this->view->title = $this->lang->mr->viewDiff;
|
||||
$this->view->diffs = $diffs;
|
||||
$this->view->encoding = $encoding;
|
||||
@@ -353,6 +376,49 @@ class mr extends control
|
||||
return $this->send($this->mr->reopen($MR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Bug for this review.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $file
|
||||
* @param int $v1
|
||||
* @param int $v2
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function addBug($repoID, $file, $v1, $v2)
|
||||
{
|
||||
$this->loadModel('repo');
|
||||
if($this->get->repoPath) $file = $this->get->repoPath;
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$result = $this->mr->saveBug($repoID, $file, $v1, $v2);
|
||||
if(dao::isError()) die(json_encode($result));
|
||||
|
||||
$bugID = $result['id'];
|
||||
$repo = $this->repo->getRepoById($repoID);
|
||||
$entry = $repo->name . '/' . $this->repo->decodePath($file);
|
||||
$location = sprintf($this->lang->repo->reviewLocation, $entry, $repo->SCM != 'Subversion' ? substr($v2, 0, 10) : $v2, $this->post->begin, $this->post->end);
|
||||
if(empty($v1))
|
||||
{
|
||||
$revision = $repo->SCM != 'Subversion' ? substr($v2, 0, 10) : $v2;
|
||||
$link = $this->repo->createLink('view', "repoID=$repoID&objectID=0&entry={$file}&revision=$v2&showBug=true") . '#L' . $this->post->begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
$revision = $repo->SCM != 'Subversion' ? substr($v1, 0, 10) : $v1;
|
||||
$revision .= ' : ';
|
||||
$revision .= $repo->SCM != 'Subversion' ? substr($v2, 0, 10) : $v2;
|
||||
$link = $this->repo->createLink('diff', "repoID=$repoID&objectID=0&entry={$file}&oldRevision=$v1&newRevision=$v2&showBug=true") . '#L' . $this->post->begin;
|
||||
}
|
||||
|
||||
$actionID = $this->loadModel('action')->create('bug', $bugID, 'repoCreated', '', html::a($link, $location));
|
||||
$this->loadModel('mail')->sendmail($bugID, $actionID);
|
||||
|
||||
echo json_encode($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: Get MR target projects.
|
||||
*
|
||||
@@ -441,7 +507,7 @@ class mr extends control
|
||||
|
||||
if(!$compileList) return $this->send(array('message' => array()));
|
||||
$options = "<option value=''></option>";
|
||||
foreach($compileList as $compile) $options .= "<option value='{$compile->id}' data-name='{$compile->name}'>[{$compile->id}] [{$compile->status}] {$compile->name}</option>";
|
||||
foreach($compileList as $compile) $options .= "<option value='{$compile->id}' data-name='{$compile->name}'>[{$compile->id}] [{$this->lang->compile->statusList[$compile->status]}] {$compile->name}</option>";
|
||||
$this->send($options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
a {color: #169;}
|
||||
a:hover, a:active {text-decoration:underline; color: #C61A1A;}
|
||||
#swapper a {text-decoration: none;}
|
||||
#swapper .col-footer a:hover {color: #0c64eb;}
|
||||
h2,h3 {font-size: 20px; margin: 0; clear: both;}
|
||||
h3 {font-size: 16px;}
|
||||
.revision {font-size: 12px; line-height: 20px; text-align: right; padding-right: 8px;}
|
||||
.directory {background-image:url('theme/default/images/repo/dir.png');}
|
||||
.file {background-image:url('theme/default/images/repo/txt.png');}
|
||||
//.icon {width: 17px; padding-left: 10px; padding-right: 2px;}
|
||||
.mini-icon {display: inline-block; height: 16px; width: 16px; background-color: transparent; background-position: 0 0; background-repeat: no-repeat; vertical-align: text-bottom;}
|
||||
.action {float: left;}
|
||||
.input-group select#encrypt {border-left: 0px;}
|
||||
.arrange {float: right;}
|
||||
.versions {position: relative;}
|
||||
#diffRepo {position: absolute; left: 20px; z-index: 1000;}
|
||||
#repoID {display: inline-block; width: auto;}
|
||||
.repoCode a:hover {text-decoration: none;}
|
||||
.commentButton
|
||||
{
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
left: -28px;
|
||||
width: 40px;
|
||||
z-index: 10;
|
||||
cursor:pointer;
|
||||
font-size: 18px;
|
||||
color: #4183C4;
|
||||
display: none;
|
||||
}
|
||||
.repoCode tr.over .commentButton {display: block;}
|
||||
.bug
|
||||
{
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
left: -7px;
|
||||
width: 20px;
|
||||
z-index: 0;
|
||||
cursor:pointer;
|
||||
font-size: 18px;
|
||||
color: #4183C4;
|
||||
line-height: 18px;
|
||||
}
|
||||
.repoCode .icon {opacity: 1;}
|
||||
.icon-comment-add:before {content: '\e74c'; transform: scale(-1, 1); display: inline-block; font-weight: normal;}
|
||||
.icon-comment-add:after {content: '+'; display: block; font-weight: normal; position: absolute; left: 16px; top: 1px; font-family: Arial; font-weight: bold; font-size: 12px;}
|
||||
.icon-comments:before {content: '\e750'; transform: scale(-1, 1); display: inline-block; font-weight: normal; font-size: 18px; line-height: 18px;}
|
||||
.commentButton:hover,.bug:hover {color: #d20b0b;}
|
||||
.commentBoard {border-top: 1px solid #E4E4E4; border-bottom: 1px solid #E4E4E4; padding: 0; white-space: normal; background-color: #eee; padding: 10px;}
|
||||
.commentBoard .table-form th {background: none;}
|
||||
.lines input {width: 40px;}
|
||||
.commentSubmit, .commentCancel {margin-right: 10px;}
|
||||
.commentFoot .optional {float: left;}
|
||||
.commentBoard.using .bugContainer {border: 1px solid #ddd; background: #fff;}
|
||||
.commentBoard.using .bugContainer > .commentHeader {background: #f1f1f1; padding: 0 10px; border-bottom: 1px solid #ddd;}
|
||||
.commentHeaderAuthor {max-width: 600px; line-height: 33px; font-weight: bold; color: #222; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;}
|
||||
.comment {width: 100%; word-break: keep-all; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;}
|
||||
.commentContent {margin: 10px;}
|
||||
.commentHeaderRight {float: right;}
|
||||
|
||||
/* Sider */
|
||||
#mainContent > #sidebar > .side-body.affix {top: 0px; z-index: 10000;}
|
||||
|
||||
/* Pre row */
|
||||
.repoCode table > tbody > tr.over td {background: #f8eec7;}
|
||||
.repoCode table > tbody > tr.over th {background: #cdcdcd; color: #333;}
|
||||
|
||||
/* Comment-btn */
|
||||
.comment-btn {position: relative; margin: 0; padding: 0; display: none;}
|
||||
.repoCode tr.over .comment-btn {display: block;}
|
||||
.comment-btn .icon-wrapper {display: block; position: absolute; background: #4183C4; border-radius: 2px; width: 24px; height: 20px; left: -6px; top: 0; line-height: 20px; text-align: center; color: #fff; cursor: pointer; transition: transform 0.2s;}
|
||||
.comment-btn .icon-wrapper:before {display: block; content: ' '; right: -4px; top: 6px; position: absolute; border-left: 4px solid #4183C4; border-right: 0 solid transparent; border-bottom: 4px solid transparent; border-top: 4px solid transparent; width: 0; height: 0;}
|
||||
.comment-btn .icon-wrapper:hover {background: #169; transform: scale(1.1);}
|
||||
.comment-btn .icon-wrapper:hover:before {border-left-color: #169;}
|
||||
|
||||
.repoCode tr.commented {cursor: pointer;}
|
||||
|
||||
.repoCode tr.commented .comment-btn {display: block;}
|
||||
.repoCode tr.commented .comment-btn .icon-wrapper {background: none; border: none; width: 24px; line-height: 18px; height: 18px; left: -6px; color: #4183c4;}
|
||||
.repoCode tr.commented .comment-btn .icon-wrapper:hover {border-color: #169; color: #169;}
|
||||
.repoCode tr.commented .comment-btn .icon-wrapper > i:before {font-size: 18px; transform: scale(-1, 1); display: inline-block;}
|
||||
.repoCode tr.commented .comment-btn .icon-wrapper:before {display: none;}
|
||||
|
||||
.repoCode tr.over.commented .comment-btn .icon-wrapper, .repoCode tr.selected.commented .comment-btn .icon-wrapper {line-height: 20px; height: 20px; background: #4183C4; color: #fff; left: -6px;}
|
||||
.repoCode tr.over.commented .comment-btn .icon-wrapper > i:before {font-size: 14px;}
|
||||
.repoCode tr.selected.commented .comment-btn .icon-wrapper > i:before {font-size: 14px;}
|
||||
.repoCode tr.over.commented .comment-btn .icon-wrapper:before, .repoCode tr.selected.commented .comment-btn .icon-wrapper:before {display: block;}
|
||||
|
||||
/* repo action form */
|
||||
.repoCode .comment-list, .repoCode .comment-actions {max-width: 900px;}
|
||||
.repoCode .bugFormContainer {border: 1px solid #bbb; margin: 0 0 0 15px; padding: 10px 20px 10px 10px; max-width: 880px; background: #fff;}
|
||||
.repoCode .bugFormContainer th {width: 70px;}
|
||||
|
||||
.repoCode .action-row {display: none;}
|
||||
.repoCode .with-action-row .action-row {display: table-row;}
|
||||
.repoCode .action-cell {background: #EEE; white-space: normal; padding: 10px 15px 10px 0;}
|
||||
.repoCode .with-action-row table tr.selected .comment-btn:last-child {display: block;}
|
||||
.repoCode .with-action-row table tr.selected td {background: #f8eec7;}
|
||||
.repoCode .with-action-row table tr.selected th {background: #cdcdcd;}
|
||||
.repoCode .with-action-row table tr.selected .comment-btn .icon-wrapper > i:before, .repoCode #diff.with-action-row tr.selected .comment-btn .icon-wrapper > i:before {content: '\d7';}
|
||||
|
||||
.repoCode .comment-row {display: none;}
|
||||
.repoCode .comment-row.show {display: table-row !important;}
|
||||
.repoCode .comment-cell {background: #eee; white-space: normal;}
|
||||
.repoCode .comment-cell .panel {margin: 10px; border-color: #bbb;}
|
||||
.repoCode .comment-cell .panel-body {padding: 6px 10px;}
|
||||
.repoCode .comment-cell .panel-actions.pull-right {margin-right: 0; margin-top: 0;}
|
||||
.repoCode .comment-cell .editing .panel-body, .repoCode .comment-cell .commentContainer.show-form .panel-body {display: none;}
|
||||
.repoCode .comment-cell .bug-edit-form, {padding: 10px; display: none;}
|
||||
.repoCode .comment-cell .editing .bug-edit-form, .repoCode .comment-cell .commentContainer.show-form .comment-edit-form {display: block;}
|
||||
|
||||
.repoCode .comment {border: 1px solid #e5e5e5; background: #fafafa; padding: 5px 10px; margin-bottom: 10px;}
|
||||
.repoCode .comment .comment-edit-form {margin-top: 10px;}
|
||||
.repoCode .panel-bug .steps {background: #f1f1f1; padding: 5px 10px;}
|
||||
.repoCode .panel-bug .bug-edit-form {margin-bottom: 10px;}
|
||||
.repoCode .panel-bug .panel-body {display: none;}
|
||||
.repoCode .panel-bug .panel-heading {cursor: pointer;}
|
||||
.repoCode .panel-bug.show .panel-body {display: block;}
|
||||
.repoCode .panel-bug.show .icon-chevron-sign-down:before {content: '\e711';}
|
||||
.repoCode .panel-bug.show-edit-form .bug-edit-form,
|
||||
.repoCode .panel-bug.show-form .commentForm,
|
||||
.repoCode .comment.show-form .comment-edit-form {display: block;}
|
||||
.repoCode .panel-bug .bug-edit-form,
|
||||
.repoCode .panel-bug.show-form .addComment,
|
||||
.repoCode .panel-bug .commentForm,
|
||||
.repoCode .comment .comment-edit-form,
|
||||
.repoCode .panel-bug.show-edit-form .panel-body .title,
|
||||
.repoCode .panel-bug.show-edit-form .bug-date,
|
||||
.repoCode .comment.show-form .comment-content, .repoCode .comment.show-form .comment-date {display: none;}
|
||||
|
||||
.repoCode .text-content {white-space: normal; white-space: pre-line;}
|
||||
.repoCode .text-muted {color: #aaa;}
|
||||
|
||||
.repoCode tr {transition: all 1s;}
|
||||
.repoCode tr.highlight {background: #fff4e5;}
|
||||
.repoCode tr.highlight td, .repoCode tr.highlight th {background: none; border-top: 1px solid #e48600; border-bottom: 1px solid #e48600;}
|
||||
.repoCode tr.highlight.commented th {color: #e48600;}
|
||||
.repoCode tr.highlight.commented td, .repoCode tr.highlight.commented th {border-bottom: none;}
|
||||
.repoCode tr.highlight + tr.highlight td, .repoCode tr.highlight + tr.highlight th {border-top: none;}
|
||||
|
||||
.repoCode .row-tip {display: none;}
|
||||
.repoCode tr.commented .row-tip {display: block; position: relative; right: -3px; bottom: -1px;}
|
||||
.repoCode tr.commented .tip, .repoCode tr.commented.open .tip.on-collapse {display: block; position: absolute; right: 0; bottom: 0; color: #4183c4; opacity: 0; padding: 0 5px; background: #edf3ff; height: 20px; line-height: 20px; transition: opacity 0.2s;}
|
||||
.repoCode tr.commented:hover .tip.on-expand {opacity: 1;}
|
||||
.repoCode tr.commented.open .tip.on-collapse {opacity: 1;}
|
||||
.repoCode tr.commented.open .tip.on-expand {display: none;}
|
||||
.repoCode tr.commented.open .tip.on-collapse span {display: none;}
|
||||
.repoCode tr.commented.open:hover .tip.on-collapse span {display: inline;}
|
||||
.repoCode tr.commented.open {background: #f8fafe;}
|
||||
.repoCode tr.commented .preview-icon {position: absolute; left: -6px; bottom: 0; width: 20px; height: 20px; line-height: 20px; text-align: center; color: #4183c4; background: #edf3ff; display: none;}
|
||||
.repoCode tr.commented:hover .preview-icon {display: block; transform: scale(-1, 1);}
|
||||
.repoCode tr.commented .preview-icon:before {font-size: 18px;}
|
||||
|
||||
.repoCode #diff tr.commented .row-tip {right: 0;}
|
||||
.repoCode #diff tr.commented .icon-chat-dot {left: 0;}
|
||||
|
||||
.repoCode .panel, .bugFormContainer {transition: border 0.4s;}
|
||||
.repoCode .panel.highlight, #bugForm.highlight .bugFormContainer {border-color: #e48600;}
|
||||
|
||||
#bugsPreview {white-space: normal;}
|
||||
#bugsPreview .dropdown-menu {top: -100%; left: 30%; padding-top: 0; min-width: 300px; max-width: 500px;}
|
||||
#bugsPreview .dropdown-menu > li.dropdown-header {background: #f1f1f1; padding-top: 8px;}
|
||||
#bugsPreview .dropdown-menu > li > a {border-top: 1px solid #e5e5e5; text-overflow : ellipsis; overflow: hidden;}
|
||||
#bugsPreview .dropdown-menu.show {display: block;}
|
||||
|
||||
.icon-comments {position: relative; left: -50px;}
|
||||
|
||||
/* bug form */
|
||||
#bugForm, #bugForm table {margin: 0; padding: 0;}
|
||||
|
||||
.panel .table + .panel-footer {border-top: 0; background: #fff;}
|
||||
|
||||
.transparent {border-color:transparent; background: none repeat scroll 0 0 transparent;}
|
||||
.transparent:hover {border-color:transparent; background: none repeat scroll 0 0 transparent;}
|
||||
|
||||
.side-col {width: 600px;}
|
||||
#sidebar > .side-body {width: 580px;}
|
||||
.hide-sidebar #sidebar > .side-body {display: none;}
|
||||
|
||||
#sidebar>.sidebar-toggle {left: 5px; right: auto;}
|
||||
#sidebar>.sidebar-toggle>.icon {right: -4px; left: auto;}
|
||||
|
||||
#logForm .fixed-footer a.allLogs {color: #fff !important;}
|
||||
|
||||
#submitLabel {text-align: left;}
|
||||
|
||||
.header-btn .btn > .text {text-overflow: unset !important;}
|
||||
@@ -10,3 +10,499 @@ function changeEncoding(encoding)
|
||||
$('#encoding').val(encoding);
|
||||
$('#encoding').parents('form').submit();
|
||||
}
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
var $diffCode = $('.diff');
|
||||
var hidePreview;
|
||||
var $bugsPreview = $('#bugsPreview');
|
||||
var $bugsPreviewMenu = $('#bugsPreview').children('.dropdown-menu');
|
||||
var $rows = $diffCode.find('tr');
|
||||
var rowTip = $('#rowTip').html();
|
||||
var lastLine;
|
||||
$rows.each(function()
|
||||
{
|
||||
var $row = $(this);
|
||||
if(!$row.hasClass('empty'))
|
||||
{
|
||||
$row.children('th').first().prepend("<div class='comment-btn diff'><span class='icon-wrapper'><i class='icon-plus'></i></span></div>");
|
||||
$row.children('td').first().append(rowTip);
|
||||
}
|
||||
|
||||
if(lastLine && !$row.data('line'))
|
||||
{
|
||||
$row.attr('data-line', lastLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastLine = $row.data('line');
|
||||
}
|
||||
}).hover(function()
|
||||
{
|
||||
var $this = $(this);
|
||||
if($this.hasClass('empty')) return;
|
||||
$this.addClass("over");
|
||||
},
|
||||
function()
|
||||
{
|
||||
$(this).removeClass("over");
|
||||
});
|
||||
|
||||
var isInline = $.cookie('arrange') == 'inline';
|
||||
var $bugFormRow = $('<tr class="action-row"><th></th>' + (isInline ? '<th></th><td class="action-cell"></td>' : '<td colspan="3" class="action-cell"></td>') + '</tr>');
|
||||
var $bugForm = $('#bugForm');
|
||||
var $commentCell = $('#commentCell');
|
||||
var $bugPanel = $('#bugPanel');
|
||||
// $bugForm.find('input[name="begin"], input[name="end"]').attr('max', lastLine);
|
||||
$bugFormRow.find('td').append($bugForm.removeClass('hide'));
|
||||
|
||||
var highlight = function($e)
|
||||
{
|
||||
$('.highlight').removeClass('highlight');
|
||||
$e.addClass('highlight');
|
||||
};
|
||||
|
||||
var createComment = function(comment, $comments)
|
||||
{
|
||||
console.log();
|
||||
var $comment = $commentCell.clone()
|
||||
.removeClass('hide')
|
||||
.attr('id', 'comment-' + comment.id)
|
||||
.attr('data-comment', comment.id);
|
||||
$comment.find('.realname').text(comment.realname);
|
||||
$comment.find('.comment-content').text(comment.comment);
|
||||
$comment.find('.date').text(comment.date);
|
||||
$comment.find('.edit').toggle(comment.edit);
|
||||
$comment.find('.comment-edit-form').attr('action', createLink('repo', 'editComment', 'commentID=' + comment.id));
|
||||
|
||||
if($comments)
|
||||
{
|
||||
if(typeof $comments !== 'object') $comments = $('#bug-' + $comments + ' .comments');
|
||||
($comments.hasClass('comments') ? $comments : $comments.find('.comments')).append($comment);
|
||||
}
|
||||
|
||||
return $comment;
|
||||
};
|
||||
|
||||
var createBug = function(bug, line, $commentRow, show)
|
||||
{
|
||||
var commentCount, j;
|
||||
var $bug = $bugPanel.clone().removeClass('hide').attr('id', 'bug-' + bug.id).attr('data-bug', bug.id);
|
||||
$bug.find('.bugid').text(bug.id);
|
||||
$bug.find('.realname').text(bug.realname);
|
||||
$bug.find('.openedDate').text(bug.openedDate);
|
||||
$bug.find('.title').text(bug.title);
|
||||
$bug.find('.steps').toggle(bug.steps != '').html(bug.steps);
|
||||
$bug.find('.edit').toggle(bug.edit);
|
||||
$bug.find('.code-lines').text(bug.lines);
|
||||
$bug.find('.delete').toggle(bug.delete);
|
||||
$bug.find('input[name="objectID"]').val(bug.id);
|
||||
$bug.find('.bug-edit-form').attr('action', createLink('repo', 'editBug', 'bugID=' + bug.id));
|
||||
$bug.find('a.view-bug').attr('href', createLink('bug', 'view', "bugID=" + bug.id));
|
||||
$bug.data('data', bug);
|
||||
$bug.toggleClass('show', show > 1);
|
||||
if(show > 2) highlight($bug);
|
||||
|
||||
if(bug.comments)
|
||||
{
|
||||
commentCount = bug.comments.length;
|
||||
$bugComments = $bug.find('.comments');
|
||||
for(j = 0; j < commentCount; j++)
|
||||
{
|
||||
createComment(bug.comments[j], $bugComments);
|
||||
}
|
||||
}
|
||||
|
||||
if(!line && bug.line) line = bug.line;
|
||||
if(line)
|
||||
{
|
||||
if(!$commentRow)
|
||||
{
|
||||
var $row = $rows.filter('[data-line="' + line + '"]').last();
|
||||
$commentRow = $row.next('tr');
|
||||
if(!$commentRow.hasClass('comment-row'))
|
||||
{
|
||||
$commentRow = $('<tr class="comment-row"><th></th>' + (isInline ? '<th></th><td class="comment-cell"><div class="comment-list"></div></td>' : '<td colspan="3" class="comment-cell"><div class="comment-list"></div></td>') + '</tr>');
|
||||
$row.addClass('commented').after($commentRow);
|
||||
}
|
||||
}
|
||||
($commentRow.hasClass('comment-list') ? $commentRow : $commentRow.find('.comment-list')).append($bug);
|
||||
|
||||
if(show && $commentRow.hasClass('comment-row')) $commentRow.addClass('show');
|
||||
}
|
||||
|
||||
return $bug;
|
||||
};
|
||||
|
||||
var toggleComment = function($row, show)
|
||||
{
|
||||
var $commentRow;
|
||||
if($row.hasClass('comment-row'))
|
||||
{
|
||||
$commentRow = $row;
|
||||
$row = $commentRow.prev('tr');
|
||||
if($row.hasClass('action-row'))
|
||||
{
|
||||
$row = $row.prev('tr');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$commentRow = $row.next('tr');
|
||||
if($commentRow.hasClass('action-row'))
|
||||
{
|
||||
$commentRow = $commentRow.next('tr');
|
||||
}
|
||||
}
|
||||
if(show === undefined)
|
||||
{
|
||||
show = !$row.hasClass('open');
|
||||
}
|
||||
if($row.hasClass('commented') && $commentRow.hasClass('comment-row'))
|
||||
{
|
||||
$commentRow.toggleClass('show', show);
|
||||
$row.toggleClass('open', show);
|
||||
}
|
||||
};
|
||||
|
||||
$diffCode.on('click', '.comment-btn', function(e)
|
||||
{
|
||||
$rows.removeClass('selected');
|
||||
var $row = $(this).closest('tr');
|
||||
if($diffCode.hasClass('with-action-row') && $row.hasClass('with-action-row'))
|
||||
{
|
||||
$diffCode.removeClass('with-action-row');
|
||||
}
|
||||
else
|
||||
{
|
||||
$diffCode.addClass('with-action-row');
|
||||
var line = $row.data('line');
|
||||
if(!$row.hasClass('with-action-row'))
|
||||
{
|
||||
$rows.removeClass('with-action-row')
|
||||
$row.addClass('with-action-row');
|
||||
|
||||
$bugForm.find('input[name="begin"]').val(line);
|
||||
$bugForm.find('input[name="end"]').attr('min', line).val(line);
|
||||
$bugForm.find('select#assignedTo').val(blamePairs[line]);
|
||||
$bugForm.find('select#assignedTo').trigger("chosen:updated");
|
||||
|
||||
$row.after($bugFormRow);
|
||||
|
||||
KindEditor.remove('#commentText');
|
||||
$('#commentText').kindeditor();
|
||||
|
||||
var getCommiterLink = createLink('repo', 'ajaxgetcommitter', 'repoID=' + repoID + "&entry=" + file + "&revision=" + revision + "&line=" + line);
|
||||
var connector = getCommiterLink.indexOf('&') >= 0 ? '&' : '?';
|
||||
getCommiterLink = getCommiterLink + connector + 'entry=' + file;
|
||||
$.ajax({url: getCommiterLink}).done(function(responseText)
|
||||
{
|
||||
$bugForm.find('#assignedTo').val(responseText).trigger("chosen:updated");
|
||||
});
|
||||
}
|
||||
highlight($bugForm);
|
||||
$bugForm.find('input[name="title"]').focus();
|
||||
$row.addClass('selected');
|
||||
}
|
||||
e.stopPropagation();
|
||||
}).on('click', '.bugCancel', function()
|
||||
{
|
||||
$rows.removeClass('selected');
|
||||
$diffCode.removeClass('with-action-row');
|
||||
}).on('click', '.bugEdit', function(e)
|
||||
{
|
||||
var $panelBug = $(this).closest('.panel-bug');
|
||||
|
||||
if($panelBug.hasClass('show-edit-form'))
|
||||
{
|
||||
$panelBug.removeClass('show-edit-form');
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
$panelBug.addClass('show show-edit-form').find('input[name="commentText"]').val($panelBug.find('.title').first().text()).focus();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}).on('submit', '.bug-edit-form', function()
|
||||
{
|
||||
var $form = $(this);
|
||||
$(this).ajaxSubmit(
|
||||
{
|
||||
success:function(text)
|
||||
{
|
||||
var $bug = $form.closest('.panel-bug');
|
||||
$bug.find('.title').text(text);
|
||||
$bug.removeClass('show-edit-form');
|
||||
},
|
||||
beforeSubmit:function(formData, jqForm)
|
||||
{
|
||||
var form = jqForm[0];
|
||||
if(!form.commentText.value)
|
||||
{
|
||||
alert(contentError);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}).on('click', '.bugEditCancel', function()
|
||||
{
|
||||
$(this).closest('.panel-bug').removeClass('show-edit-form');
|
||||
}).on('click', '.bugDelete', function(e)
|
||||
{
|
||||
var $bug = $(this).closest('.panel-bug');
|
||||
if(!$bug.length) return;
|
||||
|
||||
if(confirm(confirmDelete))
|
||||
{
|
||||
var link = createLink('repo', 'deleteBug', 'bugID=' + $bug.data('bug') + '&confirm=yes');
|
||||
$.get(link, function(data)
|
||||
{
|
||||
if(data == 'deleted')
|
||||
{
|
||||
var $commentRow = $bug.closest('.comment-row');
|
||||
if($commentRow.find('.panel-bug').length === 1)
|
||||
{
|
||||
$commentRow.removeClass('show').prev('tr').removeClass('commented');
|
||||
}
|
||||
$bug.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}).on('click', '.addComment', function()
|
||||
{
|
||||
$(this).closest('.panel-bug').addClass('show-form').find('.commentForm textarea').focus();
|
||||
}).on('click', '.commentCancel', function()
|
||||
{
|
||||
$(this).closest('.panel-bug').removeClass('show-form');
|
||||
}).on('submit', '.commentForm', function()
|
||||
{
|
||||
var $form = $(this);
|
||||
$form.ajaxSubmit(
|
||||
{
|
||||
success:function(json)
|
||||
{
|
||||
var $panelBug = $form.closest('.panel-bug');
|
||||
$form.find('textarea').val('');
|
||||
$panelBug.removeClass('show-form');
|
||||
createComment($.parseJSON(json), $panelBug.data('bug'));
|
||||
},
|
||||
beforeSubmit:function(formData, jqForm)
|
||||
{
|
||||
var form = jqForm[0];
|
||||
if(!form.comment.value)
|
||||
{
|
||||
alert(commentError);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}).on('click', '.commentEdit', function()
|
||||
{
|
||||
var $comment = $(this).closest('.comment');
|
||||
|
||||
if($comment.hasClass('show-form'))
|
||||
{
|
||||
$comment.removeClass('show-form');
|
||||
return;
|
||||
}
|
||||
$comment.addClass('show-form').find('textarea').val($comment.find('.comment-content').text()).focus();
|
||||
}).on('click', '.commentEditCancel', function()
|
||||
{
|
||||
$(this).closest('.comment').removeClass('show-form');
|
||||
}).on('submit', '.comment-edit-form', function()
|
||||
{
|
||||
var $form = $(this);
|
||||
$form.ajaxSubmit(
|
||||
{
|
||||
success:function(html)
|
||||
{
|
||||
var $comment = $form.closest('.comment');
|
||||
$comment.find('.comment-content').html(html);
|
||||
$comment.removeClass('show-form');
|
||||
},
|
||||
beforeSubmit:function(formData, jqForm)
|
||||
{
|
||||
var form = jqForm[0];
|
||||
if(!form.commentText.value)
|
||||
{
|
||||
alert(contentError);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}).on('click', '.commentDelete', function()
|
||||
{
|
||||
var $container = $(this).closest('.commentContainer');
|
||||
if(!$container.length) return;
|
||||
|
||||
if(confirm(confirmDeleteComment))
|
||||
{
|
||||
var commentID = $container.data('comment');
|
||||
var link = createLink('repo', 'deleteComment', 'commentID=' + commentID + '&confirm=yes');
|
||||
|
||||
$.get(link, function(data)
|
||||
{
|
||||
if(data == 'deleted')
|
||||
{
|
||||
var $commentRow = $container.closest('.comment-row');
|
||||
if($commentRow.find('.bugContainer, .commentContainer').length === 1)
|
||||
{
|
||||
$commentRow.removeClass('show').prev('tr').removeClass('commented');
|
||||
}
|
||||
$container.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}).on('click', 'tr.commented', function()
|
||||
{
|
||||
toggleComment($(this));
|
||||
}).on('click', '.panel-bug > .panel-heading', function()
|
||||
{
|
||||
$(this).closest('.panel-bug').toggleClass('show');
|
||||
}).on('mouseenter', 'tr.commented td .preview-icon', function(e)
|
||||
{
|
||||
var $cell = $(this).closest('td');
|
||||
var $row = $cell.closest('tr');
|
||||
var $commentRow = $row.next('tr');
|
||||
|
||||
var $bugs = $commentRow.find('.panel-bug'), line = '?';
|
||||
$bugsPreviewMenu.children('li:not(.dropdown-header)').remove();
|
||||
$bugsPreviewMenu.find('.bug-count').text($bugs.length);
|
||||
$bugsPreviewMenu.find('.comment-count').text($commentRow.find('.comment').length);
|
||||
$bugs.each(function()
|
||||
{
|
||||
var bug = $(this).data('data');
|
||||
line = bug.line;
|
||||
$bugsPreviewMenu.append('<li><a href="javascript:;" data-id="#bug-' + bug.id + '"><small class="text-muted">#' + bug.id + '</small> ' + bug.title + '</a></li>');
|
||||
});
|
||||
$bugsPreviewMenu.find('.code-line').text(line);
|
||||
|
||||
$bugsPreview.prependTo($cell);
|
||||
clearTimeout(hidePreview);
|
||||
$bugsPreviewMenu.css({top: 0-$bugsPreviewMenu.outerHeight(), left: Math.max(0, e.offsetX-$bugsPreviewMenu.outerWidth())}).addClass('show');
|
||||
setTimeout(function(){$bugsPreviewMenu.addClass('in');}, 50);
|
||||
}).on('mouseleave', 'tr.commented td', function()
|
||||
{
|
||||
$bugsPreviewMenu.removeClass('in');
|
||||
hidePreview = setTimeout(function(){$bugsPreviewMenu.removeClass('show');}, 200);
|
||||
});
|
||||
|
||||
$bugsPreviewMenu.on('click', 'li', function(e)
|
||||
{
|
||||
var $bug = $($(this).find('a').data('id'));
|
||||
if($bug.length)
|
||||
{
|
||||
$bug.addClass('show');
|
||||
toggleComment($bug.closest('tr.comment-row'), true);
|
||||
highlight($bug);
|
||||
|
||||
$bugsPreviewMenu.removeClass('in');
|
||||
hidePreview = setTimeout(function(){$bugsPreviewMenu.removeClass('show');}, 200);
|
||||
}
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
$bugForm.submit(function()
|
||||
{
|
||||
$(this).ajaxSubmit(
|
||||
{
|
||||
success:function(json)
|
||||
{
|
||||
json = $.parseJSON(json);
|
||||
if(json.result == 'fail')
|
||||
{
|
||||
alert(json.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
createBug(json, null, null, 3);
|
||||
$diffCode.removeClass('with-action-row');
|
||||
$diffCode.find('tr.with-action-row.selected').removeClass('selected');
|
||||
$bugForm.find('#title').val('');
|
||||
KindEditor.html('#commentText', '');
|
||||
},
|
||||
beforeSubmit:function(formData, jqForm)
|
||||
{
|
||||
var form = jqForm[0];
|
||||
if(!form.product.value)
|
||||
{
|
||||
alert(productError);
|
||||
return false;
|
||||
}
|
||||
if(!form.title.value)
|
||||
{
|
||||
alert(titleError);
|
||||
$bugForm.find('input[name="title"]').focus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}).on('change', 'input[name="begin"]', function()
|
||||
{
|
||||
var begin = $(this).val();
|
||||
var $end = $bugForm.find('input[name="end"]').attr('min', begin);
|
||||
if(parseInt($end.val()) < parseInt(begin))
|
||||
{
|
||||
$end.val(begin);
|
||||
}
|
||||
});
|
||||
|
||||
if(bugs)
|
||||
{
|
||||
var lineBugs, bugsCount, i;
|
||||
for(var line in bugs)
|
||||
{
|
||||
if(line)
|
||||
{
|
||||
lineBugs = bugs[line];
|
||||
bugsCount = lineBugs.length;
|
||||
|
||||
for(i = 0; i < bugsCount; i++)
|
||||
{
|
||||
createBug(lineBugs[i], line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(anchor, 200);
|
||||
|
||||
$(document).on('click', function()
|
||||
{
|
||||
$('.highlight').removeClass('highlight');
|
||||
});
|
||||
|
||||
function anchor()
|
||||
{
|
||||
var hash = window.location.hash;
|
||||
if(hash)
|
||||
{
|
||||
var line = hash.substr(1).replace('L', '');
|
||||
var $row = $('.diff tr[data-line="' + line +'"]').first();
|
||||
if($row.length)
|
||||
{
|
||||
var anchor = $row.offset().top;
|
||||
|
||||
$('body,html').animate({scrollTop:anchor - 50}, 500);
|
||||
|
||||
$row.addClass('highlight');
|
||||
if($row.hasClass('commented'))
|
||||
{
|
||||
toggleComment($row, true);
|
||||
var $commentRow = $row.next('tr');
|
||||
if($commentRow.hasClass('comment-row'))
|
||||
{
|
||||
$commentRow.addClass('highlight');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
+217
-5
@@ -173,10 +173,29 @@ class mrModel extends model
|
||||
*/
|
||||
public function update($MRID)
|
||||
{
|
||||
$MR = fixer::input('post')
|
||||
->setDefault('editedBy', $this->app->user->account)
|
||||
->setDefault('editedDate', helper::now())
|
||||
->get();
|
||||
if (!empty($_POST['compile']))
|
||||
{
|
||||
$repoID = $this->post->repo;
|
||||
$jobID = $this->post->job;
|
||||
$compileID = $this->post->compile;
|
||||
$compileStatus = $this->loadModel('compile')->getByID($this->post->compile)->status;
|
||||
|
||||
$MR = fixer::input('post')
|
||||
->setDefault('editedBy', $this->app->user->account)
|
||||
->setDefault('editedDate', helper::now())
|
||||
->add('repoID', $repoID)
|
||||
->add('jobID', $jobID)
|
||||
->add('compileID', $compileID)
|
||||
->add('compileStatus', $compileStatus)
|
||||
->get();
|
||||
}
|
||||
else
|
||||
{
|
||||
$MR = fixer::input('post')
|
||||
->setDefault('editedBy', $this->app->user->account)
|
||||
->setDefault('editedDate', helper::now())
|
||||
->get();
|
||||
}
|
||||
|
||||
/* Update MR in GitLab. */
|
||||
$newMR = new stdclass;
|
||||
@@ -195,7 +214,7 @@ class mrModel extends model
|
||||
$MR->assignee = zget($gitlabUsers, $MR->assignee, '');
|
||||
|
||||
/* Update MR in Zentao database. */
|
||||
$this->dao->update(TABLE_MR)->data($MR)
|
||||
$this->dao->update(TABLE_MR)->data($MR, $this->config->mr->edit->skippedFields)
|
||||
->where('id')->eq($MRID)
|
||||
->batchCheck($this->config->mr->edit->requiredFields, 'notempty')
|
||||
->autoCheck()
|
||||
@@ -736,4 +755,197 @@ class mrModel extends model
|
||||
if(isset($rawMR->state) and $rawMR->state == 'opened') return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => helper::createLink('mr', 'view', "mr={$MR->id}"));
|
||||
return array('result' => 'fail', 'message' => $this->lang->fail, 'locate' => helper::createLink('mr', 'view', "mr={$MR->id}"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get review.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $entry
|
||||
* @param string $revision
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getReview($repoID, $entry, $revision)
|
||||
{
|
||||
$reviews = array();
|
||||
$bugs = $this->dao->select('t1.*, t2.realname')->from(TABLE_BUG)->alias('t1')
|
||||
->leftJoin(TABLE_USER)->alias('t2')
|
||||
->on('t1.openedBy = t2.account')
|
||||
->where('t1.repo')->eq($repoID)
|
||||
->andWhere('t1.entry')->eq($entry)
|
||||
->andWhere('t1.v2')->eq($revision)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->fetchAll('id');
|
||||
$comments = $this->dao->select('t1.*, t2.realname')->from(TABLE_ACTION)->alias('t1')
|
||||
->leftJoin(TABLE_USER)->alias('t2')
|
||||
->on('t1.actor = t2.account')
|
||||
->where('t1.objectType')->eq('bug')
|
||||
->andWhere('t1.objectID')->in(array_keys($bugs))
|
||||
->andWhere('t1.action')->eq('commented')
|
||||
->fetchGroup('objectID', 'id');
|
||||
foreach($bugs as $bug)
|
||||
{
|
||||
if(common::hasPriv('bug', 'edit')) $bug->edit = true;
|
||||
if(common::hasPriv('bug', 'delete')) $bug->delete = true;
|
||||
$lines = explode(',', trim($bug->lines, ','));
|
||||
$line = $lines[0];
|
||||
$reviews[$line]['bugs'][$bug->id] = $bug;
|
||||
|
||||
if(isset($comments[$bug->id]))
|
||||
{
|
||||
foreach($comments[$bug->id] as $key => $comment)
|
||||
{
|
||||
if($comment->actor == $this->app->user->account) $comment->edit = true;
|
||||
}
|
||||
$reviews[$line]['comments'] = $comments;
|
||||
}
|
||||
}
|
||||
|
||||
return $reviews;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bugs by repo.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $browseType
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getBugsByRepo($repoID, $browseType, $orderBy, $pager)
|
||||
{
|
||||
/* Get execution that user can access. */
|
||||
$executions = $this->loadModel('execution')->getPairs($this->session->project, 'all', 'empty|withdelete');
|
||||
|
||||
$bugs = $this->dao->select('*')->from(TABLE_BUG)
|
||||
->where('repo')->eq($repoID)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->beginIF(!$this->app->user->admin)->andWhere('product')->in($this->app->user->view->products)->fi()
|
||||
->beginIF(!$this->app->user->admin)->andWhere('execution')->in(array_keys($executions))->fi()
|
||||
->beginIF($browseType == 'assigntome')->andWhere('assignedTo')->eq($this->app->user->account)->fi()
|
||||
->beginIF($browseType == 'openedbyme')->andWhere('openedBy')->eq($this->app->user->account)->fi()
|
||||
->beginIF($browseType == 'resolvedbyme')->andWhere('resolvedBy')->eq($this->app->user->account)->fi()
|
||||
->beginIF($browseType == 'assigntonull')->andWhere('assignedTo')->eq('')->fi()
|
||||
->beginIF($browseType == 'unresolved')->andWhere('resolvedBy')->eq('')->fi()
|
||||
->beginIF($browseType == 'unclosed')->andWhere('status')->ne('closed')->fi()
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll();
|
||||
return $bugs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get execution pairs.
|
||||
*
|
||||
* @param int $product
|
||||
* @param int $branch
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getExecutionPairs($product, $branch = 0)
|
||||
{
|
||||
$pairs = array();
|
||||
$executions = $this->loadModel('execution')->getList(0, 'all', 'undone', 0, $product, $branch);
|
||||
foreach($executions as $execution) $pairs[$execution->id] = $execution->name;
|
||||
return $pairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save bug.
|
||||
*
|
||||
* @param int $repoID
|
||||
* @param string $file
|
||||
* @param int $v1
|
||||
* @param int $v2
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function saveBug($repoID, $file, $v1, $v2)
|
||||
{
|
||||
$now = helper::now();
|
||||
$data = fixer::input('post')
|
||||
->add('severity', 3)
|
||||
->add('openedBy', $this->app->user->account)
|
||||
->add('openedDate', $now)
|
||||
->add('openedBuild', 'trunk')
|
||||
->add('assignedDate', $now)
|
||||
->add('type', 'codeimprovement')
|
||||
->add('repo', $repoID)
|
||||
->add('entry', $file)
|
||||
->add('lines', $this->post->begin . ',' . $this->post->end)
|
||||
->add('v1', $v1)
|
||||
->add('v2', $v2)
|
||||
->remove('commentText,begin,end,uid')
|
||||
->get();
|
||||
|
||||
$data->steps = $this->loadModel('file')->pasteImage($this->post->commentText, $this->post->uid);
|
||||
$this->dao->insert(TABLE_BUG)->data($data)->exec();
|
||||
|
||||
if(!dao::isError())
|
||||
{
|
||||
$bugID = $this->dao->lastInsertID();
|
||||
$this->file->updateObjectID($this->post->uid, $bugID, 'bug');
|
||||
setcookie("repoPairs[$repoID]", $data->product);
|
||||
|
||||
return array('result' => 'success', 'id' => $bugID, 'realname' => $this->app->user->realname, 'openedDate' => substr($now, 5, 11), 'edit' => true, 'delete' => true, 'lines' => $data->lines, 'line' => $this->post->begin, 'steps' => $data->steps, 'title' => $data->title);
|
||||
}
|
||||
|
||||
return array('result' => 'fail', 'message' => join("\n", dao::getError()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @param string $title
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function updateBug($bugID, $title)
|
||||
{
|
||||
$this->dao->update(TABLE_BUG)->set('title')->eq($title)->where('id')->eq($bugID)->exec();
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update comment.
|
||||
*
|
||||
* @param int $commentID
|
||||
* @param string $comment
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function updateComment($commentID, $comment)
|
||||
{
|
||||
$this->dao->update(TABLE_ACTION)->set('comment')->eq($comment)->where('id')->eq($commentID)->exec();
|
||||
return $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete comment.
|
||||
*
|
||||
* @param int $commentID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function deleteComment($commentID)
|
||||
{
|
||||
return $this->dao->delete()->from(TABLE_ACTION)->where('id')->eq($commentID)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last review info.
|
||||
*
|
||||
* @param string $entry
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getLastReviewInfo($entry)
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_BUG)->where('entry')->eq($entry)->orderby('id_desc')->fetch();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/form.html.php';?>
|
||||
<?php include '../../common/view/kindeditor.html.php';?>
|
||||
<?php include 'header.review.html.php';?>
|
||||
<?php if(!isonlybody()):?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
$file= '';
|
||||
$suffix = '';
|
||||
/* get last review info in this file. */
|
||||
$lastReview = $this->mr->getLastReviewInfo($file);
|
||||
$repoModule = isset($lastReview) && isset($lastReview->module) ? $lastReview->module : '';
|
||||
|
||||
/* Get product pairs. */
|
||||
if($repo->product)
|
||||
{
|
||||
$products = $this->dao->select('id,name')->from(TABLE_PRODUCT)->where('`id`')->in($repo->product)->fetchPairs();
|
||||
}
|
||||
else
|
||||
{
|
||||
$products = $this->loadModel('product')->getPairs();
|
||||
}
|
||||
|
||||
/* get product by cookie or last review in this file. */
|
||||
$repoProduct = isset($_COOKIE['repoPairs'][$repoID]) ? $_COOKIE['repoPairs'][$repoID] : '';
|
||||
$repoProduct = isset($lastReview) && isset($lastReview->product) ? $lastReview->product : $repoProduct;
|
||||
$repoProduct = isset($products[$repoProduct]) ? $repoProduct : key($products);
|
||||
$executions = $this->mr->getExecutionPairs($repoProduct);
|
||||
$modules = $this->loadModel('tree')->getOptionMenu($repoProduct, $viewType = 'bug', $startModuleID = 0);
|
||||
$users = $this->loadModel('user')->getPairs('devfirst|nodeleted|noclosed');
|
||||
$products = array('' => '') + $products;
|
||||
$executions = array('' => '') + $executions;
|
||||
|
||||
$cwd = getcwd();
|
||||
$commiters = $this->user->getCommiters();
|
||||
$blamePairs = array();
|
||||
if($suffix and $suffix != 'binary' and strpos($this->config->repo->images, "|$suffix|") === false)
|
||||
{
|
||||
$blames = $this->scm->blame($entry, $info->revision);
|
||||
foreach($blames as $line => $blame)
|
||||
{
|
||||
if(!isset($blame['committer']))
|
||||
{
|
||||
if(isset($blamePairs[$line - 1])) $blamePairs[$line] = $blamePairs[$line - 1];
|
||||
continue;
|
||||
}
|
||||
$blamePairs[$line] = zget($commiters, $blame['committer'], $blame['committer']);
|
||||
}
|
||||
}
|
||||
chdir($cwd);
|
||||
|
||||
//$reviews = $this->mr->getReview($repoID, $file, $info->revision);
|
||||
$reviews = $this->mr->getReview($repoID, $file, '');
|
||||
$v1 = isset($oldRevision) ? $oldRevision : 0;
|
||||
$this->loadModel('repo');
|
||||
// $bugUrl = $this->repo->createLink('addBug', "repoID=$repoID&file=$file&v1=$v1&v2={$info->revision}");
|
||||
$bugUrl = $this->createLink('mr', 'addBug', "repoID=$repoID&file=$file&v1=$v1&v2=");
|
||||
$commentUrl = $this->createLink('mr', 'addComment');
|
||||
$productSelect = html::select('product', $products, $repoProduct, 'class="product form-control chosen" onchange="changeProduct(this)"');
|
||||
$branches = $this->loadModel('branch')->getPairs($repoProduct);
|
||||
$moduleSelect = html::select('module', $modules, $repoModule, 'class="form-control chosen"');
|
||||
$executionSelect = html::select('execution', $executions, '', 'class="form-control chosen"');
|
||||
$typeSelect = html::select('repoType', $lang->repo->typeList, '', 'class="form-control chosen"');
|
||||
$userSelect = html::select('assignedTo', $users, '', 'class="form-control chosen assignedTo"');
|
||||
$bugs = array();
|
||||
foreach($reviews as $line => $lineReview)
|
||||
{
|
||||
$lineBugs = array();
|
||||
foreach ($lineReview['bugs'] as $bugID => $bug)
|
||||
{
|
||||
$lineBug = array();
|
||||
$lineBug['id'] = $bugID;
|
||||
$lineBug['line'] = $line;
|
||||
$lineBug['title'] = $bug->title;
|
||||
$lineBug['steps'] = $bug->steps;
|
||||
$lineBug['realname'] = $bug->realname;
|
||||
$lineBug['openedDate'] = substr($bug->openedDate, 5, 11);
|
||||
$lineBug['lines'] = $bug->lines;
|
||||
if($bug->edit) $lineBug['edit'] = true;
|
||||
if($bug->delete) $lineBug['delete'] = true;
|
||||
|
||||
if(isset($lineReview['comments']))
|
||||
{
|
||||
$comments = $lineReview['comments'][$bugID];
|
||||
if(isset($comments))
|
||||
{
|
||||
$bugComments = array();
|
||||
foreach ($comments as $commentID => $comment)
|
||||
{
|
||||
$bugComment = array(
|
||||
'id' => $comment->id,
|
||||
'edit' => $comment->edit,
|
||||
'realname' => $comment->realname,
|
||||
'date' => substr($comment->date, 5, 11),
|
||||
'comment' => $comment->comment,
|
||||
);
|
||||
$bugComments[] = $bugComment;
|
||||
}
|
||||
$lineBug['comments'] = $bugComments;
|
||||
}
|
||||
}
|
||||
$lineBugs[] = $lineBug;
|
||||
}
|
||||
|
||||
$bugs[$line] = $lineBugs;
|
||||
}
|
||||
|
||||
js::set('bugs', $bugs);
|
||||
js::set('productError', $lang->repo->error->product);
|
||||
js::set('contentError', $lang->repo->error->commentText);
|
||||
js::set('titleError', $lang->repo->error->title);
|
||||
js::set('commentError', $lang->repo->error->comment);
|
||||
js::set('submit', $lang->repo->submit);
|
||||
js::set('cancel', $lang->repo->cancel);
|
||||
js::set('confirmDelete', $lang->repo->notice->deleteBug);
|
||||
js::set('confirmDeleteComment', $lang->repo->notice->deleteComment);
|
||||
js::set('repoID', $repoID);
|
||||
// js::set('revision', $info->revision);
|
||||
js::set('revision', '');
|
||||
js::set('file', $file);
|
||||
js::set('blamePairs', $blamePairs);
|
||||
?>
|
||||
<?php if(common::hasPriv('mr', 'addBug')):?>
|
||||
<form id="bugForm" class="bugForm main-form hide" method="post" action="<?php echo $bugUrl?>">
|
||||
<div class="bugFormContainer">
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->product?></th>
|
||||
<td class='w-p45'>
|
||||
<div class='input-group'>
|
||||
<?php echo $productSelect?>
|
||||
<?php if($branches) echo html::select('branch', $branches, '', "class='form-control' style='width:95px'");?>
|
||||
</div>
|
||||
</td>
|
||||
<th><?php echo $lang->repo->module?></th>
|
||||
<td><?php echo $moduleSelect?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->execution?></th>
|
||||
<td><?php echo $executionSelect?></td>
|
||||
<th><?php echo $lang->repo->type?></th>
|
||||
<td><?php echo $typeSelect?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->assign?></th>
|
||||
<td><?php echo $userSelect?></td>
|
||||
<th><?php echo $lang->repo->lines?></th>
|
||||
<td class='lines'>
|
||||
<div class="input-group">
|
||||
<input class="line form-control" type="number" min="1" name="begin">
|
||||
<span class="input-group-addon fix-border">-</span>
|
||||
<input class="line form-control" type="number" min="1" name="end">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->title?></th>
|
||||
<td colspan='3'>
|
||||
<?php echo html::input('title', '', "class='form-control'");?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->repo->detile?></th>
|
||||
<td colspan='3'><textarea id="commentText" name="commentText" class="commentInput form-control" spellcheck="false"></textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td colspan="3" class='form-actions'>
|
||||
<?php echo html::submitButton($lang->repo->submit, '', 'btn btn-wide btn-primary bugSubmit');?>
|
||||
<?php echo html::commonButton($lang->cancel, "onclick='hiddenForm()'", 'btn btn-wide');?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="optional"></div>
|
||||
</div>
|
||||
</form>
|
||||
<?php else:?>
|
||||
<form id='bugForm' class='bugForm hide'>
|
||||
<?php printf($lang->user->errorDeny, $lang->repo->common, $lang->repo->addBug);?>
|
||||
</form>
|
||||
<?php endif;?>
|
||||
|
||||
<div class='panel panel-sm hide panel-bug' id='bugPanel'>
|
||||
<div class='panel-heading'>
|
||||
<div class='panel-actions pull-right'>
|
||||
<?php if(common::hasPriv('bug', 'view')):?>
|
||||
<a href='javascript:;' class='view-bug'>Bug#<span class='bugid'></span></a>
|
||||
<?php else:?>
|
||||
Bug#<span class='bugid'></span>
|
||||
<?php endif;?>
|
||||
<?php if(common::hasPriv('bug', 'edit')):?>
|
||||
<a href='javascript:;' class='edit bugEdit'><i class='icon-pencil'></i></a>
|
||||
<?php endif;?>
|
||||
<?php if(common::hasPriv('bug', 'delete')):?>
|
||||
<a href='javascript:;' class='delete bugDelete'><i class='icon-remove'></i></a>
|
||||
<?php endif;?>
|
||||
<a href="javascript:;"><i class='icon-chevron-down'></i></a>
|
||||
</div>
|
||||
<i class='icon-bug text-muted'></i> <strong class='title'></strong>
|
||||
</div>
|
||||
<div class='panel-body'>
|
||||
<p><?php echo $lang->repo->lines?> <strong class='code-lines'></strong> <i class='icon-user text-muted'></i> <strong class='realname'></strong> <span class='text-muted bug-date'><i class='icon-time'></i> <span class='openedDate'></span></span></p>
|
||||
<form method='post' class='bug-edit-form' action>
|
||||
<input type='text' name='commentText' class='commentInput form-control mgb-10'>
|
||||
<button type='submit' class='btn btn-sm btn-primary bugEditSubmit'><?php echo $lang->repo->submit?></button>
|
||||
<button type='button' class='btn btn-sm bugEditCancel'><?php echo $lang->repo->cancel?></button>
|
||||
</form>
|
||||
<p class='steps text-content'></p>
|
||||
<div class='comments'></div>
|
||||
<?php if(common::hasPriv('repo', 'addComment')):?>
|
||||
<button class='btn btn-sm addComment' type='button'><?php echo $lang->repo->addComment?></button>
|
||||
<form class='commentForm' method='post' action='<?php echo $commentUrl?>' id='commentForm'>
|
||||
<textarea name='comment' class='commentText form-control mgb-10' spellcheck='false' placeholder='<?php echo $lang->repo->notice->commentContent?>'></textarea>
|
||||
<input class='commentSubmit btn btn-sm btn-primary' type='submit' value='<?php echo $lang->repo->submit?>'>
|
||||
<input class='commentCancel btn btn-sm' type='button' value='<?php echo $lang->repo->cancel?>'>
|
||||
<input type='hidden' name='objectID' value=''>
|
||||
<div class='optional'></div>
|
||||
</form>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
<div class='comment hide' id='commentCell'>
|
||||
<i class='icon-user text-muted'></i> <strong class='realname'></strong>: <span class='comment-content text-content'></span> <span class='text-muted comment-date'> <i class='icon-time'></i> <span class='date'></span></span> <a href='javascript:;' class='edit commentEdit pull-right'><i class='icon-pencil'></i></a>
|
||||
<form method='post' class='comment-edit-form' action=''>
|
||||
<textarea name='commentText' class='commentInput form-control mgb-10'></textarea>
|
||||
<button type='submit' class='btn btn-sm btn-primary commentEditSubmit'><?php echo $lang->repo->submit?></button>
|
||||
<button type='button' class='btn btn-sm commentEditCancel'><?php echo $lang->repo->cancel?></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class='dropdown' id="bugsPreview">
|
||||
<ul class='dropdown-menu fade'>
|
||||
<li class='dropdown-header'><?php echo $lang->repo->line?><strong class='code-line'></strong> <i class='icon-bug'></i> <strong class='bug-count'>0</strong> <i class='icon-comments-alt'></i> <strong class='comment-count'>0</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id='rowTip' class='hide'><div class='row-tip'><i class='icon-chat-dot preview-icon'></i><div class='on-expand tip'><span><?php echo $lang->repo->expand?> </span><i class='icon-chevron-down'></i></div><div class='on-collapse tip'><span><?php echo $lang->repo->collapse?> </span><i class='icon-chevron-up'></i></div></div></div>
|
||||
<script>
|
||||
function changeProduct(select)
|
||||
{
|
||||
loadProductBranches(select);
|
||||
productID = $(select).children('option:selected').val();
|
||||
link = createLink('repo', 'ajaxGetExecutions', 'productID=' + productID);
|
||||
$(select).closest('.bugFormContainer').find('select[name=execution]').parent().load(link, '', function(){$('#execution').chosen();});
|
||||
moduleLink = createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=bug&branch=0&rootModuleID=0&returnType=html');
|
||||
$(select).closest('.bugFormContainer').find('select[name=module]').parent().load(moduleLink, '', function(){$('#module').chosen();});
|
||||
}
|
||||
|
||||
function loadProductBranches(select)
|
||||
{
|
||||
$(select).closest('.input-group').find('#branch').remove();
|
||||
productID = $(select).children('option:selected').val();
|
||||
$.get(createLink('branch', 'ajaxGetBranches', "productID=" + productID), function(data)
|
||||
{
|
||||
if(data)
|
||||
{
|
||||
$(select).closest('.input-group').append(data);
|
||||
$(select).closest('.input-group').find('#branch').css('width', '95px');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadBranch(select)
|
||||
{
|
||||
branch = $(select).val();
|
||||
productID = $(select).closest('.input-group').find('#product').val();
|
||||
link = createLink('repo', 'ajaxGetExecutions', 'productID=' + productID + '&branch=' + branch);
|
||||
$(select).closest('.bugFormContainer').find('select[name=execution]').parent().load(link, '', function(){$('#execution').chosen();});
|
||||
moduleLink = createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=bug&branch=' + branch + '&rootModuleID=0&returnType=html');
|
||||
$(select).closest('.bugFormContainer').find('select[name=module]').parent().load(moduleLink, '', function(){$('#module').chosen();});
|
||||
}
|
||||
|
||||
function hiddenForm()
|
||||
{
|
||||
$('.with-action-row').removeClass('with-action-row');
|
||||
}
|
||||
|
||||
/* remove a function */
|
||||
function loadModuleRelated(){}
|
||||
</script>
|
||||
Reference in New Issue
Block a user