Finish task#43858. review code in diff view of MR module.

This commit is contained in:
dingguodong
2021-11-10 15:07:03 +08:00
parent 99b100e7f4
commit 51960d25b4
6 changed files with 1241 additions and 6 deletions
+67 -1
View File
@@ -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);
}
}
+187
View File
@@ -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;}
+496
View File
@@ -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
View File
@@ -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();
}
}
+2
View File
@@ -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'>
+272
View File
@@ -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> &nbsp; <i class='icon-user text-muted'></i> <strong class='realname'></strong> &nbsp;<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'>&nbsp;<i class='icon-time'></i> <span class='date'></span></span> &nbsp;<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> &nbsp; <i class='icon-bug'></i> <strong class='bug-count'>0</strong> &nbsp; <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>