Merge branch '12.x' of https://github.com/easysoft/zentaopms into 12.x
This commit is contained in:
+4
-4
@@ -2,13 +2,13 @@ Z PUBLIC LICENSE 1.2
|
||||
|
||||
许可
|
||||
|
||||
Z PUBLIC LICENSE 由青岛易软天创网络科技有限公司(www.cnezsoft.com)起草,简称ZPL协议。
|
||||
Z PUBLIC LICENSE 由青岛易软天创网络科技有限公司(www.easycorp.cn)起草,简称ZPL协议。
|
||||
任何人均可使用该协议来发布开源软件,并可对下面协议正文中以下划线标注的空白部分做相应修改,
|
||||
除此之外的任何内容不得做任何修改。青岛易软天创网络科技有限公司拥有对该协议条款的最终解释权。
|
||||
|
||||
前言:
|
||||
|
||||
禅道项目管理软件(以下简称该软件)由 青岛易软天创网络科技有限公司(www.cnezsoft.com)开发(以下简称我)。我依法拥有该软件的所有版权。
|
||||
禅道项目管理软件(以下简称该软件)由 青岛易软天创网络科技有限公司(www.easycorp.cn)开发(以下简称我)。我依法拥有该软件的所有版权。
|
||||
本着共享开放的角度,我以开放源代码的形式发布该软件。您可以在遵守该协议的前提下使用该软件。
|
||||
自您安装该软件开始,您和我之间的合同关系自动成立。除非您停止使用该软件或与我有签署额外合同,
|
||||
您须认真遵循该授权协议约定的每一条款。
|
||||
@@ -16,9 +16,9 @@ Z PUBLIC LICENSE 由青岛易软天创网络科技有限公司(www.cnezsoft.co
|
||||
我的联系方式:
|
||||
联系人:徐先生
|
||||
电话: 4006-8899-23
|
||||
Email: co@cnezsoft.com
|
||||
Email: co@zentao.net
|
||||
QQ: 1492153927
|
||||
地址: 青岛开发区武夷山路167号千禧龙花园 9-1-101室
|
||||
地址: 青岛开发区长江路232号国贸中心C座2单元2902室
|
||||
|
||||
约定:
|
||||
|
||||
|
||||
+3
-3
@@ -2,20 +2,20 @@ Z PUBLIC LICENSE 1.2
|
||||
|
||||
Authorization
|
||||
|
||||
Z PUBLIC LICENSE, also known as ZPL Agreement, is drafted by EasyCorp(en.easycorp.ltd).
|
||||
Z PUBLIC LICENSE, also known as ZPL Agreement, is drafted by EasyCorp(www.easycorp.ltd).
|
||||
Anyone can use the agreement to publish open source software, and modify the blank in the following text of the agreement accordingly.
|
||||
No other text of the agreement shall be changed. EasyCorp has the final interpretation of the terms in the agreement.
|
||||
|
||||
Preface
|
||||
|
||||
ZenTao ALM (Hereinafter referred to as "the software") developed by EasyCorp (en.easycorp.ltd) (hereinafter referred to I). I'm entitled to all copyright of the software.
|
||||
ZenTao ALM (Hereinafter referred to as "the software") developed by EasyCorp (www.easycorp.ltd) (hereinafter referred to I). I'm entitled to all copyright of the software.
|
||||
The software is released as open source software. You are authorized to use the software as long as you are in compliance with this agreement.
|
||||
By installation of the software, you agree that a contractual relationship between you and me is automatically established.
|
||||
You are obliged to fully comply with all the terms of this agreement unless you choose to stop using the software or you have signed additional agreement with me.
|
||||
|
||||
My Contact:
|
||||
Email: renee@easysoft.ltd
|
||||
Site: http://www.zentao.pm
|
||||
Site: https://www.zentao.pm
|
||||
|
||||
We agree:
|
||||
|
||||
|
||||
+12
-11
@@ -712,8 +712,9 @@ class baseDAO
|
||||
/**
|
||||
* 将记录进行分页,自动设置limit语句。
|
||||
* Page the records, set the limit part auto.
|
||||
*
|
||||
* @param object $pager
|
||||
*
|
||||
* @param object $pager
|
||||
* @param string $distinctField
|
||||
* @access public
|
||||
* @return object the dao object self.
|
||||
*/
|
||||
@@ -722,15 +723,15 @@ class baseDAO
|
||||
if(!is_object($pager)) return $this;
|
||||
|
||||
/*
|
||||
* 如果$pager的总记录为0,需要计算总结果数。
|
||||
* If the record total is 0, compute it.
|
||||
**/
|
||||
if($pager->recTotal == 0)
|
||||
{
|
||||
$recTotal = $this->count($distinctField);
|
||||
$pager->setRecTotal($recTotal);
|
||||
$pager->setPageTotal();
|
||||
}
|
||||
* 重新计算分页数据,并判断是否需要返回上一页。
|
||||
* Calculate pagination to determine whether to return to the previous page.
|
||||
*/
|
||||
$originalPageID = $pager->pageID;
|
||||
$recTotal = $this->count($distinctField);
|
||||
$pager->setRecTotal($recTotal);
|
||||
$pager->setPageTotal();
|
||||
if($originalPageID > $pager->pageTotal) $pager->setPageID($pager->pageTotal);
|
||||
|
||||
$this->sqlobj->limit($pager->limit());
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -360,8 +360,8 @@ class basePager
|
||||
/**
|
||||
* 设置分页信息的样式。
|
||||
* Get the pager html string.
|
||||
*
|
||||
* @param string $align
|
||||
*
|
||||
* @param string $align
|
||||
* @param string $type the pager type, full|short|shortest
|
||||
* @access public
|
||||
* @return string
|
||||
@@ -392,7 +392,7 @@ class basePager
|
||||
$position = $this->pageTotal == 1 ? '' : $this->pageID . '/' . $this->pageTotal;
|
||||
$pager = $pager . ' ' . $position;
|
||||
}
|
||||
else if($type != 'full')
|
||||
else if($type != 'full')
|
||||
{
|
||||
$pager = $this->pageID . '/' . $this->pageTotal . ' ' . $pager;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class dingapi
|
||||
|
||||
$url = $this->apiUrl . 'topapi/message/corpconversation/asyncsend_v2?access_token=' . $this->token;
|
||||
$response = common::http($url, $postData);
|
||||
$errors = commonModel::$errors;
|
||||
$errors = commonModel::$requestErrors;
|
||||
|
||||
$response = json_decode($response);
|
||||
if(isset($response->errcode) and $response->errcode == 0) return array('result' => 'success');
|
||||
@@ -150,7 +150,7 @@ class dingapi
|
||||
public function queryAPI($url)
|
||||
{
|
||||
$response = common::http($url);
|
||||
$errors = commonModel::$errors;
|
||||
$errors = commonModel::$requestErrors;
|
||||
|
||||
$response = json_decode($response);
|
||||
if(isset($response->errcode) and $response->errcode == 0) return $response;
|
||||
|
||||
@@ -114,7 +114,7 @@ class wechatapi
|
||||
|
||||
$url = $this->apiUrl . 'message/send?access_token=' . $this->token;
|
||||
$response = common::http($url, json_encode($message), array(), array('Content-Type: text/plain'));
|
||||
$errors = commonModel::$errors;
|
||||
$errors = commonModel::$requestErrors;
|
||||
|
||||
$response = json_decode($response);
|
||||
if(isset($response->errcode) and $response->errcode == 0) return array('result' => 'success');
|
||||
@@ -134,7 +134,7 @@ class wechatapi
|
||||
public function queryAPI($url)
|
||||
{
|
||||
$response = common::http($curl);
|
||||
$errors = commonModel::$errors;
|
||||
$errors = commonModel::$requestErrors;
|
||||
|
||||
$response = json_decode($response);
|
||||
if(isset($response->errcode) and $response->errcode == 0) return $response;
|
||||
|
||||
@@ -43,7 +43,7 @@ $lang->block->myBug = '我的BUG';
|
||||
$lang->block->myProject = '未关闭的' . $lang->projectCommon;
|
||||
$lang->block->myProduct = '未关闭的' . $lang->productCommon;
|
||||
$lang->block->delayed = '已延期';
|
||||
$lang->block->noData = '当前统计类型下暂无数据';
|
||||
$lang->block->noData = '当前统计类型下暂无数据。';
|
||||
$lang->block->emptyTip = '暂无信息';
|
||||
|
||||
$lang->block->params = new stdclass();
|
||||
|
||||
@@ -43,7 +43,7 @@ $lang->block->myBug = '我的BUG';
|
||||
$lang->block->myProject = '未關閉的' . $lang->projectCommon;
|
||||
$lang->block->myProduct = '未關閉的' . $lang->productCommon;
|
||||
$lang->block->delayed = '已延期';
|
||||
$lang->block->noData = '當前統計類型下暫無數據';
|
||||
$lang->block->noData = '當前統計類型下暫無數據。';
|
||||
$lang->block->emptyTip = '暫無信息';
|
||||
|
||||
$lang->block->params = new stdclass();
|
||||
|
||||
@@ -21,7 +21,7 @@ $useGuest = $this->app->user->account == 'guest';
|
||||
<?php if(empty($longBlocks) and empty($shortBlocks)):?>
|
||||
<div class="table-empty-tip">
|
||||
<p>
|
||||
<span class="text-muted"><?php echo $lang->block->noData. ',';?></span>
|
||||
<span class="text-muted"><?php echo $lang->block->noData;?></span>
|
||||
<?php echo html::a($this->createLink("block", "admin", "id=0&module=$module"), "<i class='icon icon-plus'></i> {$lang->block->createBlock}", '', "data-toggle='modal' data-type='ajax' data-width='700' data-title='{$lang->block->createBlock}' class='btn btn-info'")?>
|
||||
<?php echo html::a($this->createLink("block", "ajaxReset", "module=$module"), "<i class='icon icon-refresh'></i> {$lang->block->reset}", 'hiddenwin', 'class="btn btn-info"')?>
|
||||
</p>
|
||||
|
||||
@@ -127,18 +127,13 @@ class bug extends control
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
if($this->app->getViewType() == 'mhtml') $recPerPage = 10;
|
||||
$pager = pager::init(0, $recPerPage, $pageID);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
/* Get projects. */
|
||||
$projects = $this->loadModel('project')->getPairs('empty|withdelete');
|
||||
|
||||
/* Get bugs. */
|
||||
$bugs = $this->bug->getBugs($productID, $projects, $branch, $browseType, $moduleID, $queryID, $sort, $pager);
|
||||
if(empty($bugs) and $pageID > 1)
|
||||
{
|
||||
$pager = pager::init(0, $recPerPage, 1);
|
||||
$bugs = $this->bug->getBugs($productID, $projects, $branch, $browseType, $moduleID, $queryID, $sort, $pager);
|
||||
}
|
||||
|
||||
/* Process the sql, get the conditon partion, save it to session. */
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug', $browseType == 'needconfirm' ? false : true);
|
||||
@@ -371,7 +366,7 @@ class bug extends control
|
||||
$pri = 3;
|
||||
$color = '';
|
||||
|
||||
/* Parse the extras. extract fix php7.2*/
|
||||
/* Parse the extras. extract fix php7.2. */
|
||||
$extras = str_replace(array(',', ' '), array('&', ''), $extras);
|
||||
parse_str($extras, $output);
|
||||
extract($output);
|
||||
@@ -487,6 +482,7 @@ class bug extends control
|
||||
$this->view->branch = $branch;
|
||||
$this->view->branches = $branches;
|
||||
$this->view->color = $color;
|
||||
$this->view->stepsRequired = strpos($this->config->bug->create->requiredFields, 'steps');
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -112,16 +112,17 @@ function loadAllBuilds(object)
|
||||
{
|
||||
productID = $('#product').val();
|
||||
projectID = $('#project').val();
|
||||
if(page == 'edit') buildBox = $(object).closest('.input-group').attr('id');
|
||||
|
||||
var buildBox = '';
|
||||
if(page == 'edit') buildBox = $(object).closest('.input-group').attr('id');
|
||||
|
||||
if(projectID)
|
||||
{
|
||||
loadAllProjectBuilds(projectID, productID);
|
||||
loadAllProjectBuilds(projectID, productID, buildBox);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadAllProductBuilds(productID);
|
||||
loadAllProductBuilds(productID, buildBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,10 +132,11 @@ function loadAllBuilds(object)
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @param string $buildBox
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function loadAllProjectBuilds(projectID, productID)
|
||||
function loadAllProjectBuilds(projectID, productID, buildBox)
|
||||
{
|
||||
branch = $('#branch').val();
|
||||
if(typeof(branch) == 'undefined') branch = 0;
|
||||
@@ -171,10 +173,11 @@ function loadAllProjectBuilds(projectID, productID)
|
||||
* Load all builds of the product.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $buildBox
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function loadAllProductBuilds(productID)
|
||||
function loadAllProductBuilds(productID, buildBox)
|
||||
{
|
||||
branch = $('#branch').val();
|
||||
if(typeof(branch) == 'undefined') branch = 0;
|
||||
|
||||
+25
-4
@@ -22,7 +22,7 @@ function loadAllUsers()
|
||||
/**
|
||||
* Load team members of the latest project of a product as assignedTo list.
|
||||
*
|
||||
* @param $productID
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -33,7 +33,7 @@ function loadProjectTeamMembers(productID)
|
||||
}
|
||||
|
||||
/**
|
||||
* load assignedTo and stories of module.
|
||||
* Load assignedTo and stories of module.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -50,6 +50,8 @@ function loadModuleRelated()
|
||||
/**
|
||||
* Set the assignedTo field.
|
||||
*
|
||||
* @param int $moduleID
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -83,13 +85,14 @@ function setAssignedTo(moduleID, productID)
|
||||
});
|
||||
}
|
||||
|
||||
var stepsTemplate;
|
||||
$(function()
|
||||
{
|
||||
if($('#project').val()) loadProjectRelated($('#project').val());
|
||||
|
||||
$('[data-toggle=tooltip]').tooltip();
|
||||
|
||||
// adjust size of bug type input group
|
||||
/* Adjust size of bug type input group. */
|
||||
var adjustBugTypeGroup = function()
|
||||
{
|
||||
var $group = $('#bugTypeInputGroup');
|
||||
@@ -107,7 +110,7 @@ $(function()
|
||||
adjustBugTypeGroup();
|
||||
$(window).on('resize', adjustBugTypeGroup);
|
||||
|
||||
// init pri and severity selector
|
||||
/* Init pri and severity selector. */
|
||||
$('#severity, #pri').on('change', function()
|
||||
{
|
||||
var $select = $(this);
|
||||
@@ -115,4 +118,22 @@ $(function()
|
||||
var value = $select.val();
|
||||
$selector.find('.pri-text').html($selector.data('type') === 'severity' ? '<span class="label-severity" data-severity="' + value + '" title="' + value + '"></span>' : '<span class="label-pri label-pri-' + value + '" title="' + value + '">' + value + '</span>');
|
||||
});
|
||||
|
||||
/* Get steps template. */
|
||||
stepsTemplate = editor['steps'].html();
|
||||
$("a[id^='tplTitleBox']").on('click', function()
|
||||
{
|
||||
setTimeout("stepsTemplate = editor['steps'].html()", 100);
|
||||
});
|
||||
|
||||
/* Judgment of required items for steps. */
|
||||
$('#submit').on('click', function()
|
||||
{
|
||||
var steps = editor['steps'].html();
|
||||
if(stepsRequired !== false && stepsTemplate == steps)
|
||||
{
|
||||
bootbox.alert(stepsNotEmpty);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -172,12 +172,13 @@ $lang->bug->legendRelated = 'Sonstige Infos';
|
||||
$lang->bug->buttonConfirm = 'Confirm';
|
||||
|
||||
/* 交互提示。*/
|
||||
$lang->bug->summary = "Bugs on this page : <strong>%s</strong> Total, <strong>%s</strong> Unresolved.";
|
||||
$lang->bug->confirmChangeProduct = "Change {$lang->productCommon} will cause linked {$lang->projectCommon},Story and Task change. Do you want to do this?";
|
||||
$lang->bug->confirmDelete = 'Do you want to delete this bug?';
|
||||
$lang->bug->remindTask = 'This Bug has been converted to Task. Do you want to update Status of Task(ID %s)?';
|
||||
$lang->bug->skipClose = 'Bug %s is not resolved. You cannot close it.';
|
||||
$lang->bug->projectAccessDenied = "You access to the {$lang->projectCommon} to which this bug belongs is denied!";
|
||||
$lang->bug->summary = "Bugs on this page : <strong>%s</strong> Total, <strong>%s</strong> Unresolved.";
|
||||
$lang->bug->confirmChangeProduct = "Change {$lang->productCommon} will cause linked {$lang->projectCommon},Story and Task change. Do you want to do this?";
|
||||
$lang->bug->confirmDelete = 'Do you want to delete this bug?';
|
||||
$lang->bug->remindTask = 'This Bug has been converted to Task. Do you want to update Status of Task(ID %s)?';
|
||||
$lang->bug->skipClose = 'Bug %s is not resolved. You cannot close it.';
|
||||
$lang->bug->projectAccessDenied = "You access to the {$lang->projectCommon} to which this bug belongs is denied!";
|
||||
$lang->bug->stepsNotEmpty = "The reproduction step cannot be empty.";
|
||||
|
||||
/* 模板。*/
|
||||
$lang->bug->tplStep = "<p>[Steps]</p><br/>";
|
||||
|
||||
@@ -172,12 +172,13 @@ $lang->bug->legendRelated = 'Related Info';
|
||||
$lang->bug->buttonConfirm = 'Confirm';
|
||||
|
||||
/* Interactive prompt. */
|
||||
$lang->bug->summary = "Total <strong>%s</strong> bugs on this page, and <strong>%s</strong> Active.";
|
||||
$lang->bug->confirmChangeProduct = "Any change to {$lang->productCommon} will cause linked {$lang->projectCommon}s, stories and tasks change. Do you want to do this?";
|
||||
$lang->bug->confirmDelete = 'Do you want to delete this bug?';
|
||||
$lang->bug->remindTask = 'This bug has been converted to a task. Do you want to update the status of Task(ID %s)?';
|
||||
$lang->bug->skipClose = 'Bug %s is active. You cannot close it.';
|
||||
$lang->bug->projectAccessDenied = "You access to the {$lang->projectCommon} to which this bug belongs is denied!";
|
||||
$lang->bug->summary = "Total <strong>%s</strong> bugs on this page, and <strong>%s</strong> Active.";
|
||||
$lang->bug->confirmChangeProduct = "Any change to {$lang->productCommon} will cause linked {$lang->projectCommon}s, stories and tasks change. Do you want to do this?";
|
||||
$lang->bug->confirmDelete = 'Do you want to delete this bug?';
|
||||
$lang->bug->remindTask = 'This bug has been converted to a task. Do you want to update the status of Task(ID %s)?';
|
||||
$lang->bug->skipClose = 'Bug %s is active. You cannot close it.';
|
||||
$lang->bug->projectAccessDenied = "You access to the {$lang->projectCommon} to which this bug belongs is denied!";
|
||||
$lang->bug->stepsNotEmpty = "The reproduction step cannot be empty.";
|
||||
|
||||
/* Template. */
|
||||
$lang->bug->tplStep = "<p>[Steps]</p><br/>";
|
||||
|
||||
@@ -172,12 +172,13 @@ $lang->bug->legendRelated = 'Infos connexes';
|
||||
$lang->bug->buttonConfirm = 'Confirmer';
|
||||
|
||||
/* 交互提示。*/
|
||||
$lang->bug->summary = "Total de <strong>%s</strong> bugs sur cette page, et <strong>%s</strong> sont Actifs.";
|
||||
$lang->bug->confirmChangeProduct = "Tout changement aux {$lang->productCommon} fera que les {$lang->projectCommon}s, stories et tâches associées vont changer. Voulez-vous faire cela ?";
|
||||
$lang->bug->confirmDelete = 'Voulez-vous supprimer ce bug ?';
|
||||
$lang->bug->remindTask = 'Ce bug a été converti en tâche. Voulez-vous mettre à jour le statut de la Tâche(ID %s) ?';
|
||||
$lang->bug->skipClose = 'Bug %s est actif. Vous ne pouvez pas le fermer.';
|
||||
$lang->bug->projectAccessDenied = "Votre accès à {$lang->projectCommon} auquel ce bug appartient est refusé !";
|
||||
$lang->bug->summary = "Total de <strong>%s</strong> bugs sur cette page, et <strong>%s</strong> sont Actifs.";
|
||||
$lang->bug->confirmChangeProduct = "Tout changement aux {$lang->productCommon} fera que les {$lang->projectCommon}s, stories et tâches associées vont changer. Voulez-vous faire cela ?";
|
||||
$lang->bug->confirmDelete = 'Voulez-vous supprimer ce bug ?';
|
||||
$lang->bug->remindTask = 'Ce bug a été converti en tâche. Voulez-vous mettre à jour le statut de la Tâche(ID %s) ?';
|
||||
$lang->bug->skipClose = 'Bug %s est actif. Vous ne pouvez pas le fermer.';
|
||||
$lang->bug->projectAccessDenied = "Votre accès à {$lang->projectCommon} auquel ce bug appartient est refusé !";
|
||||
$lang->bug->stepsNotEmpty = "The reproduction step cannot be empty.";
|
||||
|
||||
/* 模板。*/
|
||||
$lang->bug->tplStep = "<p>[Etape]</p><br/>";
|
||||
|
||||
@@ -172,12 +172,13 @@ $lang->bug->legendRelated = 'Thông tin liên quan';
|
||||
$lang->bug->buttonConfirm = 'Xác nhận';
|
||||
|
||||
/* Interactive prompt. */
|
||||
$lang->bug->summary = "Tổng <strong>%s</strong> bugs, và <strong>%s</strong> kích hoạt.";
|
||||
$lang->bug->confirmChangeProduct = "Mọi sự thay đổi tới {$lang->productCommon} sẽ là nguyên nhân liên kết {$lang->projectCommon}, câu chuyện và nhiệm vụ thay đổi. Bạn có muốn làm điều này?";
|
||||
$lang->bug->confirmDelete = 'Bạn có muốn xóa bug này?';
|
||||
$lang->bug->remindTask = 'Bug này đã chuyển thành một nhiệm vụ. Bạn có muốn cập nhật tình trạng của nhiệm vụ(ID %s)?';
|
||||
$lang->bug->skipClose = 'Bug %s được kích hoạt. Bạn không thể đóng nó.';
|
||||
$lang->bug->projectAccessDenied = "Truy cập của bạn tới {$lang->projectCommon} mà Bug này sở hữu bị từ chối!";
|
||||
$lang->bug->summary = "Tổng <strong>%s</strong> bugs, và <strong>%s</strong> kích hoạt.";
|
||||
$lang->bug->confirmChangeProduct = "Mọi sự thay đổi tới {$lang->productCommon} sẽ là nguyên nhân liên kết {$lang->projectCommon}, câu chuyện và nhiệm vụ thay đổi. Bạn có muốn làm điều này?";
|
||||
$lang->bug->confirmDelete = 'Bạn có muốn xóa bug này?';
|
||||
$lang->bug->remindTask = 'Bug này đã chuyển thành một nhiệm vụ. Bạn có muốn cập nhật tình trạng của nhiệm vụ(ID %s)?';
|
||||
$lang->bug->skipClose = 'Bug %s được kích hoạt. Bạn không thể đóng nó.';
|
||||
$lang->bug->projectAccessDenied = "Truy cập của bạn tới {$lang->projectCommon} mà Bug này sở hữu bị từ chối!";
|
||||
$lang->bug->stepsNotEmpty = "The reproduction step cannot be empty.";
|
||||
|
||||
/* Template. */
|
||||
$lang->bug->tplStep = "<p>[Các bước]</p><br/>";
|
||||
|
||||
@@ -172,12 +172,13 @@ $lang->bug->legendRelated = '其他信息';
|
||||
$lang->bug->buttonConfirm = '确认';
|
||||
|
||||
/* 交互提示。*/
|
||||
$lang->bug->summary = "本页共 <strong>%s</strong> 个Bug,未解决 <strong>%s</strong>。";
|
||||
$lang->bug->confirmChangeProduct = "修改{$lang->productCommon}会导致相应的{$lang->projectCommon}、{$lang->storyCommon}和任务发生变化,确定吗?";
|
||||
$lang->bug->confirmDelete = '您确认要删除该Bug吗?';
|
||||
$lang->bug->remindTask = '该Bug已经转化为任务,是否更新任务(编号:%s)状态 ?';
|
||||
$lang->bug->skipClose = 'Bug %s 不是已解决状态,不能关闭。';
|
||||
$lang->bug->projectAccessDenied = "您无权访问该Bug所属的{$lang->projectCommon}!";
|
||||
$lang->bug->summary = "本页共 <strong>%s</strong> 个Bug,未解决 <strong>%s</strong>。";
|
||||
$lang->bug->confirmChangeProduct = "修改{$lang->productCommon}会导致相应的{$lang->projectCommon}、{$lang->storyCommon}和任务发生变化,确定吗?";
|
||||
$lang->bug->confirmDelete = '您确认要删除该Bug吗?';
|
||||
$lang->bug->remindTask = '该Bug已经转化为任务,是否更新任务(编号:%s)状态 ?';
|
||||
$lang->bug->skipClose = 'Bug %s 不是已解决状态,不能关闭。';
|
||||
$lang->bug->projectAccessDenied = "您无权访问该Bug所属的{$lang->projectCommon}!";
|
||||
$lang->bug->stepsNotEmpty = "重现步骤不能为空。";
|
||||
|
||||
/* 模板。*/
|
||||
$lang->bug->tplStep = "<p>[步骤]</p><br/>";
|
||||
|
||||
+15
-21
@@ -129,23 +129,10 @@ class bugModel extends model
|
||||
*
|
||||
* @param string $from object that is transfered to bug.
|
||||
* @access public
|
||||
* @return int|bool
|
||||
* @return array|bool
|
||||
*/
|
||||
public function create($from = '')
|
||||
{
|
||||
/* Delete HTML tags, line breaks, and spaces in templates and steps. */
|
||||
if($this->post->templateID)
|
||||
{
|
||||
$stepsTemplate = strip_tags($this->dao->select('content')->from(TABLE_USERTPL)->where('id')->eq($this->post->templateID)->fetch('content'));
|
||||
$stepsTemplate = preg_replace("/\s/", "", $stepsTemplate);
|
||||
}
|
||||
else
|
||||
{
|
||||
$stepsTemplate = strip_tags($this->lang->bug->tplStep . $this->lang->bug->tplResult . $this->lang->bug->tplExpect);
|
||||
}
|
||||
$steps = strip_tags(preg_replace("/\s/", "", $this->post->steps));
|
||||
$steps = str_replace(" ", "", $steps);
|
||||
|
||||
$now = helper::now();
|
||||
$bug = fixer::input('post')
|
||||
->setDefault('openedBy', $this->app->user->account)
|
||||
@@ -157,12 +144,11 @@ class bugModel extends model
|
||||
->setIF($this->post->assignedTo != '', 'assignedDate', $now)
|
||||
->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
|
||||
->setIF(strpos($this->config->bug->create->requiredFields, 'project') !== false, 'project', $this->post->project)
|
||||
->setIF($steps == $stepsTemplate, 'steps', '')
|
||||
->stripTags($this->config->bug->editor->create['id'], $this->config->allowedTags)
|
||||
->cleanInt('product,project,module,severity')
|
||||
->join('openedBuild', ',')
|
||||
->join('mailto', ',')
|
||||
->remove('files, labels,uid,oldTaskID,contactListMenu,templateID')
|
||||
->remove('files, labels,uid,oldTaskID,contactListMenu')
|
||||
->get();
|
||||
|
||||
/* Check repeat bug. */
|
||||
@@ -191,17 +177,19 @@ class bugModel extends model
|
||||
* Batch create
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function batchCreate($productID, $branch = 0)
|
||||
{
|
||||
/* Load module and init vars. */
|
||||
$this->loadModel('action');
|
||||
$branch = (int)$branch;
|
||||
$productID = (int)$productID;
|
||||
$now = helper::now();
|
||||
$actions = array();
|
||||
$data = fixer::input('post')->get();
|
||||
$branch = (int)$branch;
|
||||
$productID = (int)$productID;
|
||||
$now = helper::now();
|
||||
$actions = array();
|
||||
$data = fixer::input('post')->get();
|
||||
|
||||
$result = $this->loadModel('common')->removeDuplicate('bug', $data, "product={$productID}");
|
||||
$data = $result['data'];
|
||||
@@ -234,8 +222,10 @@ class bugModel extends model
|
||||
$data->browsers[$i] = $browser;
|
||||
}
|
||||
|
||||
/* If there are images to upload, load the file module. */
|
||||
if(isset($data->uploadImage)) $this->loadModel('file');
|
||||
$extendFields = $this->getFlowExtendFields();
|
||||
|
||||
$bugs = array();
|
||||
foreach($data->title as $i => $title)
|
||||
{
|
||||
@@ -260,6 +250,7 @@ class bugModel extends model
|
||||
$bug->browser = $data->browsers[$i];
|
||||
$bug->keywords = $data->keywords[$i];
|
||||
|
||||
/* Assign the bug to the person in charge of the module. */
|
||||
if(!empty($moduleOwners[$bug->module]))
|
||||
{
|
||||
$bug->assignedTo = $moduleOwners[$bug->module];
|
||||
@@ -273,6 +264,7 @@ class bugModel extends model
|
||||
if($message) die(js::alert($message));
|
||||
}
|
||||
|
||||
/* Required field check. */
|
||||
foreach(explode(',', $this->config->bug->create->requiredFields) as $field)
|
||||
{
|
||||
$field = trim($field);
|
||||
@@ -282,6 +274,7 @@ class bugModel extends model
|
||||
$bugs[$i] = $bug;
|
||||
}
|
||||
|
||||
/* When the bug is created by uploading an image, add the image to the step of the bug. */
|
||||
foreach($bugs as $i => $bug)
|
||||
{
|
||||
if(!empty($data->uploadImage[$i]))
|
||||
@@ -319,6 +312,7 @@ class bugModel extends model
|
||||
|
||||
$this->executeHooks($bugID);
|
||||
|
||||
/* When the bug is created by uploading the image, add the image to the file of the bug. */
|
||||
$this->loadModel('score')->create('bug', 'create', $bugID);
|
||||
if(!empty($data->uploadImage[$i]) and !empty($file))
|
||||
{
|
||||
|
||||
@@ -20,6 +20,8 @@ js::set('createRelease', $lang->release->create);
|
||||
js::set('createBuild', $lang->build->create);
|
||||
js::set('refresh', $lang->refresh);
|
||||
js::set('flow', $config->global->flow);
|
||||
js::set('stepsRequired', $stepsRequired);
|
||||
js::set('stepsNotEmpty', $lang->bug->stepsNotEmpty);
|
||||
?>
|
||||
<div id="mainContent" class="main-content fade">
|
||||
<div class="center-block">
|
||||
@@ -219,10 +221,9 @@ js::set('flow', $config->global->flow);
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->bug->steps;?></th>
|
||||
<td colspan='2' class='steps'>
|
||||
<td colspan='2'>
|
||||
<?php echo $this->fetch('user', 'ajaxPrintTemplates', 'type=bug&link=steps');?>
|
||||
<?php echo html::textarea('steps', $steps, "rows='10' class='form-control'");?>
|
||||
<?php echo html::hidden('templateID', '');?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
|
||||
@@ -200,11 +200,6 @@ class caselib extends control
|
||||
|
||||
/* save session .*/
|
||||
$cases = $this->caselib->getLibCases($libID, $browseType, $queryID, $moduleID, $sort, $pager);
|
||||
if(empty($cases) and $pageID > 1)
|
||||
{
|
||||
$pager = pager::init(0, $recPerPage, 1);
|
||||
$cases = $this->caselib->getLibCases($libID, $browseType, $queryID, $moduleID, $sort, $pager);
|
||||
}
|
||||
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', true);
|
||||
|
||||
|
||||
+6
-6
@@ -66,13 +66,13 @@ class ciModel extends model
|
||||
$userPWD = "$jenkinsUser:$jenkinsPassword";
|
||||
$queueUrl = sprintf('%s/queue/item/%s/api/json', $jenkinsServer, $compile->queue);
|
||||
|
||||
$response = common::http($queueUrl, '', array('CURLOPT_USERPWD' => $userPWD));
|
||||
$response = common::http($queueUrl, '', array(CURLOPT_USERPWD => $userPWD));
|
||||
|
||||
$this->dao->update(TABLE_COMPILE)->set('times = times + 1')->where('id')->eq($compile->id)->exec();
|
||||
if(strripos($response, "404") > -1)
|
||||
{
|
||||
$infoUrl = sprintf("%s/job/%s/api/xml?tree=builds[id,number,result,queueId]&xpath=//build[queueId=%s]", $jenkinsServer, $compile->jkJob, $compile->queue);
|
||||
$response = common::http($infoUrl, '', array('CURLOPT_USERPWD' => $userPWD));
|
||||
$response = common::http($infoUrl, '', array(CURLOPT_USERPWD => $userPWD));
|
||||
if($response)
|
||||
{
|
||||
$buildInfo = simplexml_load_string($response);
|
||||
@@ -83,7 +83,7 @@ class ciModel extends model
|
||||
$this->updateBuildStatus($compile, $result);
|
||||
|
||||
$logUrl = sprintf('%s/job/%s/%s/consoleText', $jenkinsServer, $compile->jkJob, $buildNumber);
|
||||
$response = common::http($logUrl, '', array('CURLOPT_USERPWD' => $userPWD));
|
||||
$response = common::http($logUrl, '', array(CURLOPT_USERPWD => $userPWD));
|
||||
$this->dao->update(TABLE_COMPILE)->set('logs')->eq($response)->where('id')->eq($compile->id)->exec();
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,7 @@ class ciModel extends model
|
||||
if(!empty($queueInfo->executable))
|
||||
{
|
||||
$buildUrl = $queueInfo->executable->url . 'api/json?pretty=true';
|
||||
$response = common::http($buildUrl, '', array('CURLOPT_USERPWD' => $userPWD));
|
||||
$response = common::http($buildUrl, '', array(CURLOPT_USERPWD => $userPWD));
|
||||
$buildInfo = json_decode($response);
|
||||
|
||||
if($buildInfo->building)
|
||||
@@ -106,7 +106,7 @@ class ciModel extends model
|
||||
$this->updateBuildStatus($compile, $result);
|
||||
|
||||
$logUrl = $buildInfo->url . 'logText/progressiveText/api/json';
|
||||
$response = common::http($logUrl, '', array('CURLOPT_USERPWD' => $userPWD));
|
||||
$response = common::http($logUrl, '', array(CURLOPT_USERPWD => $userPWD));
|
||||
$this->dao->update(TABLE_COMPILE)->set('logs')->eq($response)->where('id')->eq($compile->id)->exec();
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ class ciModel extends model
|
||||
public function sendRequest($url, $data, $userPWD = '')
|
||||
{
|
||||
if(!empty($data->PARAM_TAG)) $data->PARAM_REVISION = '';
|
||||
$response = common::http($url, $data, array('CURLOPT_HEADER' => true, 'CURLOPT_USERPWD' => $userPWD));
|
||||
$response = common::http($url, $data, array(CURLOPT_HEADER => true, CURLOPT_USERPWD => $userPWD));
|
||||
if(preg_match("!Location: .*item/(.*)/!", $response, $matches)) return $matches[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
+10
-8
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
class commonModel extends model
|
||||
{
|
||||
static public $errors = array();
|
||||
static public $requestErrors = array();
|
||||
|
||||
/**
|
||||
* The construc method, to do some auto things.
|
||||
@@ -1859,8 +1859,8 @@ EOD;
|
||||
*
|
||||
* @param string $url
|
||||
* @param string|array $data
|
||||
* @param bool $optHeader
|
||||
* @param string $userPWD
|
||||
* @param array $options This is option and value pair, like CURLOPT_HEADER => true. Use curl_setopt function to set options.
|
||||
* @param array $headers Set request headers.
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
@@ -1870,7 +1870,10 @@ EOD;
|
||||
global $lang, $app;
|
||||
if(!extension_loaded('curl')) return json_encode(array('result' => 'fail', 'message' => $lang->error->noCurlExt));
|
||||
|
||||
commonModel::$errors = array();
|
||||
commonModel::$requestErrors = array();
|
||||
|
||||
if(!is_array($headers)) $headers = (array)$headers;
|
||||
$headers[] = "API-RemoteIP: " . zget($_SERVER, 'REMOTE_ADDR', '');
|
||||
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
|
||||
@@ -1884,17 +1887,16 @@ EOD;
|
||||
curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
curl_setopt($curl, CURLOPT_HEADER, FALSE);
|
||||
curl_setopt($curl, CURLINFO_HEADER_OUT, TRUE);
|
||||
|
||||
$headers[] = "API-RemoteIP: " . $_SERVER['REMOTE_ADDR'];
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
|
||||
if(!empty($data))
|
||||
{
|
||||
curl_setopt($curl, CURLOPT_POST, true);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
|
||||
foreach($options as $option => $value) curl_setopt($curl, $option, $value);
|
||||
if($options) curl_setopt_array($curl, $options);
|
||||
|
||||
$response = curl_exec($curl);
|
||||
$errors = curl_error($curl);
|
||||
@@ -1914,7 +1916,7 @@ EOD;
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
if($errors) commonModel::$errors[] = $errors;
|
||||
if($errors) commonModel::$requestErrors[] = $errors;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
@@ -513,15 +513,15 @@ class docModel extends model
|
||||
*
|
||||
* @param int $libID
|
||||
* @param int $module
|
||||
* @param string $mode undeleted|all
|
||||
* @param string $mode normal|all
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getPrivDocs($libID = 0, $module = 0, $mode = 'undeleted')
|
||||
public function getPrivDocs($libID = 0, $module = 0, $mode = 'normal')
|
||||
{
|
||||
$stmt = $this->dao->select('*')->from(TABLE_DOC)
|
||||
->where('1=1')
|
||||
->beginIF($mode == 'undeleted')->andWhere('deleted')->eq(0)->fi()
|
||||
->beginIF($mode == 'normal')->andWhere('deleted')->eq(0)->fi()
|
||||
->beginIF($this->config->doc->notArticleType)->andWhere('type')->notIN($this->config->doc->notArticleType)->fi()
|
||||
->beginIF($libID)->andWhere('lib')->in($libID)->fi()
|
||||
->beginIF(strpos($this->config->doc->custom->showLibs, 'children') === false)->andWhere('module')->in($module)->fi()
|
||||
|
||||
@@ -195,7 +195,7 @@ $lang->install->chanzhi->desc = <<<EOD
|
||||
EOD;
|
||||
|
||||
$lang->install->zdoo = new stdclass();
|
||||
$lang->install->zdoo->name = 'ZDOO';
|
||||
$lang->install->zdoo->name = 'ZDOO协同';
|
||||
$lang->install->zdoo->logo = 'images/main/zdoo.ico';
|
||||
$lang->install->zdoo->url = 'https://www.zdoo.com';
|
||||
$lang->install->zdoo->desc = <<<EOD
|
||||
|
||||
@@ -72,7 +72,7 @@ class jenkinsModel extends model
|
||||
$jenkinsPassword = $jenkins->token ? $jenkins->token : $jenkins->password;
|
||||
|
||||
$userPWD = "$jenkinsUser:$jenkinsPassword";
|
||||
$response = common::http($jenkinsServer . '/api/json/items/list', '', array('CURLOPT_USERPWD' => $userPWD));
|
||||
$response = common::http($jenkinsServer . '/api/json/items/list', '', array(CURLOPT_USERPWD => $userPWD));
|
||||
$response = json_decode($response);
|
||||
|
||||
$tasks = array();
|
||||
|
||||
@@ -100,13 +100,11 @@ $('#jkHost').change(function()
|
||||
$('#jkJobBox .loading').remove();
|
||||
$('#jkJobBox .input-group').append(html);
|
||||
|
||||
var dropDirection = $('#jkJobBox #jkJob option').length > 2 ? 'up' : 'auto';
|
||||
$('#jkJobBox #jkJob').chosen({drop_direction: dropDirection});
|
||||
$('#jkJobBox #jkJob').chosen({drop_direction: 'auto'});
|
||||
})
|
||||
})
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('#jkHost').chosen({drop_direction: $('#jkHost option').length > 3 ? 'up' : 'auto'});
|
||||
$('#triggerType').change();
|
||||
});
|
||||
|
||||
@@ -104,14 +104,12 @@ $('#jkHost').change(function()
|
||||
$('#jkJobBox .loading').remove();
|
||||
$('#jkJobBox .input-group').append(html);
|
||||
|
||||
var dropDirection = $('#jkJobBox #jkJob option').length > 2 ? 'up' : 'auto';
|
||||
$('#jkJobBox #jkJob').val(jkJob).chosen({drop_direction: dropDirection});
|
||||
$('#jkJobBox #jkJob').val(jkJob).chosen({drop_direction: 'auto'});
|
||||
})
|
||||
})
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('#jkHost').chosen({drop_direction: $('#jkHost option').length > 3 ? 'up' : 'auto'});
|
||||
$('#jkHost').change();
|
||||
$('#triggerType').change();
|
||||
});
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
<th><?php echo $lang->job->jkHost; ?></th>
|
||||
<td colspan='2'>
|
||||
<div class='table-row'>
|
||||
<div class='table-col'><?php echo html::select('jkHost', $jkHostList, '', "class='form-control'"); ?></div>
|
||||
<div class='table-col'><?php echo html::select('jkHost', $jkHostList, '', "class='form-control chosen'"); ?></div>
|
||||
<div id='jkJobBox' class='table-col'>
|
||||
<div class='input-group'>
|
||||
<span class='input-group-addon'><?php echo $lang->job->jkJob; ?></span>
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
<th><?php echo $lang->job->jkHost; ?></th>
|
||||
<td colspan='2'>
|
||||
<div class='table-row'>
|
||||
<div class='table-col'><?php echo html::select('jkHost', $jkHostList, $job->jkHost, "class='form-control'");?></div>
|
||||
<div class='table-col'><?php echo html::select('jkHost', $jkHostList, $job->jkHost, "class='form-control chosen'");?></div>
|
||||
<div id='jkJobBox' class='table-col'>
|
||||
<div class='input-group'>
|
||||
<span class='input-group-addon'><?php echo $lang->job->jkJob; ?></span>
|
||||
|
||||
@@ -54,7 +54,7 @@ $lang->misc->zentao->service['servicemore']= '更多服务...';
|
||||
|
||||
global $config;
|
||||
$lang->misc->zentao->others['chanzhi'] = "<img src='{$config->webRoot}theme/default/images/main/chanzhi.ico' /> 蝉知门户";
|
||||
$lang->misc->zentao->others['zdoo'] = "<img src='{$config->webRoot}theme/default/images/main/zdoo.ico' /> ZDOO";
|
||||
$lang->misc->zentao->others['zdoo'] = "<img src='{$config->webRoot}theme/default/images/main/zdoo.ico' /> ZDOO协同";
|
||||
$lang->misc->zentao->others['xuanxuan'] = "<img src='{$config->webRoot}theme/default/images/main/xuanxuan.ico' /> 喧喧聊天";
|
||||
$lang->misc->zentao->others['ydisk'] = "<img src='{$config->webRoot}theme/default/images/main/ydisk.ico' /> 悦库网盘";
|
||||
$lang->misc->zentao->others['meshiot' ] = "<img src='{$config->webRoot}theme/default/images/main/meshiot.ico' /> 易天物联";
|
||||
|
||||
@@ -165,16 +165,10 @@ class product extends control
|
||||
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
if($this->app->getViewType() == 'mhtml') $recPerPage = 10;
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
/* Get stories. */
|
||||
$stories = $this->product->getStories($productID, $branch, $browseType, $queryID, $moduleID, $storyType, $sort, $pager);
|
||||
if(empty($stories) and $pageID > 1)
|
||||
{
|
||||
$pager = pager::init(0, $recPerPage, 1);
|
||||
$stories = $this->product->getStories($productID, $branch, $browseType, $queryID, $moduleID, $storyType, $sort, $pager);
|
||||
}
|
||||
|
||||
/* Process the sql, get the conditon partion, save it to session. */
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story', $browseType != 'bysearch');
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<p>
|
||||
<span class="text-muted"><?php echo $lang->project->noProject;?></span>
|
||||
<?php if(common::hasPriv('project', 'create')):?>
|
||||
<?php echo html::a($this->createLink('project', 'create', "projectID=©ProjectID=&planID=&confirm=&productID=$productID"), "<i class='icon icon-plus'></i> " . $lang->project->create, '', "class='btn btn-info'");?>
|
||||
<?php echo html::a($this->createLink('project', 'create', "productID=$productID"), "<i class='icon icon-plus'></i> " . $lang->project->create, '', "class='btn btn-info'");?>
|
||||
<?php endif;?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
<?php foreach($extendFields as $extendField) echo "<td>" . $this->loadModel('flow')->getFieldValue($extendField, $plan) . "</td>";?>
|
||||
<td class='c-actions'>
|
||||
<?php
|
||||
if(common::hasPriv('project', 'create')) echo html::a(helper::createLink('project', 'create', "projectID=©ProjectID=&planID=$plan->id"), '<i class="icon-plus"></i>', '', "class='btn' title='{$lang->project->create}'");
|
||||
if(common::hasPriv('project', 'create')) echo html::a(helper::createLink('project', 'create', "productID=&projectID=©ProjectID=&planID=$plan->id"), '<i class="icon-plus"></i>', '', "class='btn' title='{$lang->project->create}'");
|
||||
if(common::hasPriv('productplan', 'linkStory')) echo html::a(inlink('view', "planID=$plan->id&type=story&orderBy=id_desc&link=true"), '<i class="icon-link"></i>', '', "class='btn' title='{$lang->productplan->linkStory}'");
|
||||
if(common::hasPriv('productplan', 'linkBug') and $config->global->flow != 'onlyStory') echo html::a(inlink('view', "planID=$plan->id&type=bug&orderBy=id_desc&link=true"), '<i class="icon-bug"></i>', '', "class='btn' title='{$lang->productplan->linkBug}'");
|
||||
common::printIcon('productplan', 'edit', "planID=$plan->id", $plan, 'list');
|
||||
|
||||
@@ -181,11 +181,6 @@ class project extends control
|
||||
|
||||
/* Get tasks. */
|
||||
$tasks = $this->project->getTasks($productID, $projectID, $this->projects, $browseType, $queryID, $moduleID, $sort, $pager);
|
||||
if(empty($tasks) and $pageID > 1)
|
||||
{
|
||||
$pager = pager::init(0, $recPerPage, 1);
|
||||
$tasks = $this->project->getTasks($productID, $projectID, $this->projects, $browseType, $queryID, $moduleID, $sort, $pager);
|
||||
}
|
||||
|
||||
/* Build the search form. */
|
||||
$actionURL = $this->createLink('project', 'task', "projectID=$projectID&status=bySearch¶m=myQueryID");
|
||||
@@ -706,11 +701,6 @@ class project extends control
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$stories = $this->story->getProjectStories($projectID, $sort, $type, $param, 'story', '', $pager);
|
||||
if(empty($stories) and $pageID > 1)
|
||||
{
|
||||
$pager = pager::init(0, $recPerPage, 1);
|
||||
$stories = $this->story->getProjectStories($projectID, $sort, $type, $param, 'story', '', $pager);
|
||||
}
|
||||
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story', false);
|
||||
$users = $this->user->getPairs('noletter');
|
||||
@@ -1044,14 +1034,16 @@ class project extends control
|
||||
/**
|
||||
* Create a project.
|
||||
*
|
||||
* @param string $productID
|
||||
* @param string $projectID
|
||||
* @param string $copyProjectID
|
||||
* @param int $planID
|
||||
* @param string $confirm
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create($projectID = '', $copyProjectID = '', $planID = 0, $confirm = 'no', $productID = '')
|
||||
public function create($productID = '', $projectID = '', $copyProjectID = '', $planID = 0, $confirm = 'no')
|
||||
{
|
||||
if($projectID)
|
||||
{
|
||||
@@ -1063,7 +1055,7 @@ class project extends control
|
||||
}
|
||||
else
|
||||
{
|
||||
die(js::confirm($this->lang->project->importPlanStory, inlink('create', "projectID=$projectID©ProjectID=&planID=$planID&confirm=yes"), inlink('create', "projectID=$projectID"), 'parent', 'parent'));
|
||||
die(js::confirm($this->lang->project->importPlanStory, inlink('create', "productID=&projectID=$projectID©ProjectID=&planID=$planID&confirm=yes"), inlink('create', "productID=&projectID=$projectID"), 'parent', 'parent'));
|
||||
}
|
||||
}
|
||||
$this->view->title = $this->lang->project->tips;
|
||||
@@ -1129,11 +1121,11 @@ class project extends control
|
||||
}
|
||||
if(!empty($planID))
|
||||
{
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('create', "projectID=$projectID©ProjectID=&planID=$planID&confirm=no")));
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('create', "productID=&projectID=$projectID©ProjectID=&planID=$planID&confirm=no")));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('create', "projectID=$projectID")));
|
||||
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('create', "productID=&projectID=$projectID")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -239,6 +239,26 @@ $(function()
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
/*Assign value to the manage products by the different request type.*/
|
||||
var url = window.location.href;
|
||||
if(window.config.requestType == 'GET')
|
||||
{
|
||||
var paramStr = url.split('?')[1];
|
||||
var paramArr = paramString.split('&');
|
||||
var productID = paramArr[2].split('=')[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
var urlArr = url.split('/');
|
||||
var paramStr = urlArr[urlArr.length-1];
|
||||
var paramArr = paramStr.split('-');
|
||||
var productID = paramArr[2].split('.')[0];
|
||||
}
|
||||
var product = $('#productsBox .input-group:last select:first');
|
||||
$(product).val(productID);
|
||||
$(product).trigger("chosen:updated");
|
||||
loadBranches($(product));
|
||||
|
||||
adjustProductBoxMargin();
|
||||
adjustPlanBoxMargin();
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function setCopyProject(projectID)
|
||||
{
|
||||
location.href = createLink('project', 'create', 'projectID=0©ProjectID=' + projectID);
|
||||
location.href = createLink('project', 'create', 'productID=&projectID=0©ProjectID=' + projectID);
|
||||
}
|
||||
|
||||
$(function()
|
||||
|
||||
@@ -1704,7 +1704,7 @@ class projectModel extends model
|
||||
}
|
||||
}
|
||||
$this->linkStory($projectID, $planStories, $planProducts);
|
||||
if($count != 0) echo js::alert(sprintf($this->lang->project->haveDraft, $count)) . js::locate(helper::createLink('project', 'create', "projectID=$projectID"));
|
||||
if($count != 0) echo js::alert(sprintf($this->lang->project->haveDraft, $count)) . js::locate(helper::createLink('project', 'create', "productID=&projectID=$projectID"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
<?php endforeach;?>
|
||||
<div class='col-sm-4'>
|
||||
<div class='input-group'>
|
||||
<?php echo html::select("products[$i]", $allProducts, $productID, "class='form-control chosen' onchange='loadBranches(this)'");?>
|
||||
<?php echo html::select("products[$i]", $allProducts, '', "class='form-control chosen' onchange='loadBranches(this)'");?>
|
||||
<span class='input-group-addon fix-border'></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1463,7 +1463,6 @@ class story extends control
|
||||
$storyInfo['estimate'] = $story->estimate;
|
||||
$storyInfo['pri'] = $story->pri;
|
||||
$storyInfo['spec'] = html_entity_decode($story->spec);
|
||||
|
||||
|
||||
echo json_encode($storyInfo);
|
||||
}
|
||||
|
||||
@@ -562,7 +562,6 @@ class storyModel extends model
|
||||
->remove('files,labels,comment,contactListMenu,stages')
|
||||
->get();
|
||||
if(isset($story->plan) and is_array($story->plan)) $story->plan = trim(join(',', $story->plan), ',');
|
||||
if(empty($_POST['product'])) $story->branch = $oldStory->branch;
|
||||
if(isset($_POST['branch']) and $_POST['branch'] == 0) $story->branch = 0;
|
||||
if(!empty($_POST['stages']))
|
||||
{
|
||||
@@ -1758,6 +1757,7 @@ class storyModel extends model
|
||||
$branch = join(',', $branch);
|
||||
if($branch) $branch = "0,$branch";
|
||||
}
|
||||
|
||||
$stories = $this->dao->select('*')->from(TABLE_STORY)
|
||||
->where('product')->in($productID)
|
||||
->beginIF(!$hasParent)->andWhere("parent")->ge(0)->fi()
|
||||
@@ -1767,7 +1767,10 @@ class storyModel extends model
|
||||
->beginIF($status and $status != 'all')->andWhere('status')->in($status)->fi()
|
||||
->andWhere('deleted')->eq(0)
|
||||
->andWhere('type')->eq($type)
|
||||
->orderBy($orderBy)->page($pager)->fetchAll('id');
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
|
||||
return $this->mergePlanTitle($productID, $stories, $branch, $type);
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,13 @@
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php else:?>
|
||||
<tr>
|
||||
<th class='thWidth'><?php echo $lang->product->branch;?></th>
|
||||
<td>
|
||||
<div class='input-group'><?php if($product->type != 'normal') echo html::select('branch', $branches, $story->branch, "onchange='loadBranch();' class='form-control chosen control-branch'");?></div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th class='thWidth'><?php echo $lang->story->module;?></th>
|
||||
|
||||
@@ -1631,7 +1631,7 @@ class taskModel extends model
|
||||
$this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('id')->eq((int)$taskID)->exec();
|
||||
if($oldTask->fromBug) $this->dao->update(TABLE_BUG)->set('toTask')->eq(0)->where('id')->eq($oldTask->fromBug)->exec();
|
||||
if($oldTask->parent > 0) $this->updateParentStatus($taskID);
|
||||
if($oldTask->parent == '-1')
|
||||
if($oldTask->parent == '-1')
|
||||
{
|
||||
unset($task->assignedTo);
|
||||
$this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('parent')->eq((int)$taskID)->exec();
|
||||
@@ -1695,7 +1695,7 @@ class taskModel extends model
|
||||
->exec();
|
||||
|
||||
if($oldTask->parent > 0) $this->updateParentStatus($taskID);
|
||||
if($oldTask->parent == '-1')
|
||||
if($oldTask->parent == '-1')
|
||||
{
|
||||
unset($task->left);
|
||||
$this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('parent')->eq((int)$taskID)->exec();
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
<?php endif;?>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<form method='post' target='hiddenwin'>
|
||||
<table class='table table-form'>
|
||||
<tr class='hide'>
|
||||
|
||||
@@ -92,16 +92,11 @@ class testcase extends control
|
||||
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = pager::init($recTotal, $recPerPage, $pageID);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
$sort = $this->loadModel('common')->appendOrder($orderBy);
|
||||
|
||||
/* Get test cases. */
|
||||
$cases = $this->testcase->getTestCases($productID, $branch, $browseType, $browseType == 'bysearch' ? $queryID : $suiteID, $moduleID, $sort, $pager);
|
||||
if(empty($cases) and $pageID > 1)
|
||||
{
|
||||
$pager = pager::init(0, $recPerPage, 1);
|
||||
$cases = $this->testcase->getTestCases($productID, $branch, $browseType, $browseType == 'bysearch' ? $queryID : $suiteID, $moduleID, $sort, $pager);
|
||||
}
|
||||
|
||||
/* save session .*/
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', $browseType != 'bysearch' ? false : true);
|
||||
@@ -1504,7 +1499,7 @@ class testcase extends control
|
||||
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = pager::init(0, $recPerPage, $pageID);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$this->view->title = $this->lang->testcase->common . $this->lang->colon . $this->lang->testcase->importFromLib;
|
||||
$this->view->position[] = $this->lang->testcase->importFromLib;
|
||||
|
||||
@@ -63,11 +63,6 @@ class testreport extends control
|
||||
$pager = pager::init($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$reports = $this->testreport->getList($objectID, $objectType, $extra, $orderBy, $pager);
|
||||
if(empty($reports) and $pageID > 1)
|
||||
{
|
||||
$pager = pager::init(0, $recPerPage, 1);
|
||||
$reports = $this->testreport->getList($objectID, $objectType, $extra, $orderBy, $pager);
|
||||
}
|
||||
|
||||
if($objectType == 'project' and isset($_POST['taskIdList']))
|
||||
{
|
||||
@@ -450,7 +445,7 @@ class testreport extends control
|
||||
$tasks = $report->tasks ? $this->testtask->getByList($report->tasks) : array();;
|
||||
$builds = $report->builds ? $this->build->getByList($report->builds) : array();
|
||||
$cases = $this->testreport->getTaskCases($tasks, $report->begin, $report->end, $report->cases, $pager);
|
||||
$totalCases = $this->testreport->getTaskCases($tasks, $report->begin, $report->end, $report->cases);
|
||||
$caseIdList = $this->testreport->getCaseIdList($reportID);
|
||||
$bugInfo = $this->testreport->getBugInfo($tasks, $report->product, $report->begin, $report->end, $builds);
|
||||
|
||||
if($report->objectType == 'testtask')
|
||||
@@ -478,10 +473,10 @@ class testreport extends control
|
||||
$this->view->actions = $this->loadModel('action')->getList('testreport', $reportID);
|
||||
|
||||
$this->view->storySummary = $this->product->summary($stories);
|
||||
$this->view->caseSummary = $this->testreport->getResultSummary($tasks, $totalCases, $report->begin, $report->end);
|
||||
$this->view->caseSummary = $this->testreport->getResultSummary($tasks, $caseIdList, $report->begin, $report->end);
|
||||
|
||||
$perCaseResult = $this->testreport->getPerCaseResult4Report($tasks, $totalCases, $report->begin, $report->end);
|
||||
$perCaseRunner = $this->testreport->getPerCaseRunner4Report($tasks, $totalCases, $report->begin, $report->end);
|
||||
$perCaseResult = $this->testreport->getPerCaseResult4Report($tasks, $caseIdList, $report->begin, $report->end);
|
||||
$perCaseRunner = $this->testreport->getPerCaseRunner4Report($tasks, $caseIdList, $report->begin, $report->end);
|
||||
$this->view->datas['testTaskPerRunResult'] = $this->loadModel('report')->computePercent($perCaseResult);
|
||||
$this->view->datas['testTaskPerRunner'] = $this->report->computePercent($perCaseRunner);
|
||||
|
||||
|
||||
@@ -362,6 +362,24 @@ class testreportModel extends model
|
||||
return $cases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get caseID list.
|
||||
*
|
||||
* @param int $reportID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getCaseIdList($reportID)
|
||||
{
|
||||
$caseIdList = $this->dao->select('`case`')->from(TABLE_TESTREPORT)->alias('t1')
|
||||
->leftJoin(TABLE_TESTRUN)->alias('t2')->on('t1.tasks=t2.task')
|
||||
->where('t1.id')->eq($reportID)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->fetchPairs('case');
|
||||
|
||||
return $caseIdList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get result summary.
|
||||
*
|
||||
@@ -409,6 +427,7 @@ class testreportModel extends model
|
||||
->leftJoin(TABLE_TESTRUN)->alias('t2')
|
||||
->on('t1.run= t2.id')
|
||||
->where('t2.task')->in(array_keys($tasks))
|
||||
->andwhere('t1.date = t2.lastRunDate')
|
||||
->andWhere('t1.`case`')->in(array_keys($cases))
|
||||
->andWhere('t1.date')->ge($begin)
|
||||
->andWhere('t1.date')->le($end . " 23:59:59")
|
||||
@@ -440,6 +459,7 @@ class testreportModel extends model
|
||||
->leftJoin(TABLE_TESTRUN)->alias('t2')
|
||||
->on('t1.run= t2.id')
|
||||
->where('t2.task')->in(array_keys($tasks))
|
||||
->andwhere('t1.date = t2.lastRunDate')
|
||||
->andWhere('t1.`case`')->in(array_keys($cases))
|
||||
->andWhere('t1.date')->ge($begin)
|
||||
->andWhere('t1.date')->le($end . " 23:59:59")
|
||||
|
||||
@@ -54,11 +54,6 @@ class testsuite extends control
|
||||
$productName = isset($this->products[$productID]) ? $this->products[$productID] : '';
|
||||
|
||||
$suites = $this->testsuite->getSuites($productID, $sort, $pager);
|
||||
if(empty($suites) and $pageID > 1)
|
||||
{
|
||||
$pager = pager::init(0, $recPerPage, 1);
|
||||
$suites = $this->testsuite->getSuites($productID, $sort, $pager);
|
||||
}
|
||||
|
||||
$this->view->title = $productName . $this->lang->testsuite->common;
|
||||
$this->view->position[] = html::a($this->createLink('testsuite', 'browse', "productID=$productID"), $productName);
|
||||
|
||||
@@ -77,11 +77,6 @@ class testtask extends control
|
||||
|
||||
/* Get tasks. */
|
||||
$tasks = $this->testtask->getProductTasks($productID, $branch, $sort, $pager, $scopeAndStatus, $beginTime, $endTime);
|
||||
if(empty($tasks) and $pageID > 1)
|
||||
{
|
||||
$pager = pager::init(0, $recPerPage, 1);
|
||||
$tasks = $this->testtask->getProductTasks($productID, $branch, $sort, $pager, $scopeAndStatus, $beginTime, $endTime);
|
||||
}
|
||||
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->common;
|
||||
$this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
|
||||
@@ -123,7 +123,7 @@ $lang->testtask->showFail = '失败<span class="text-danger">%s</span>次';
|
||||
$lang->testtask->confirmDelete = '您确认要删除该测试单吗?';
|
||||
$lang->testtask->confirmUnlinkCase = '您确认要移除该用例吗?';
|
||||
$lang->testtask->noticeNoOther = '该产品还没有其他测试单';
|
||||
$lang->testtask->noTesttask = '暂时没有测试单';
|
||||
$lang->testtask->noTesttask = '暂时没有测试单。';
|
||||
$lang->testtask->checkLinked = '请检查测试单的产品是否与项目相关联';
|
||||
$lang->testtask->noImportData = '导入的XML没有解析出数据。';
|
||||
$lang->testtask->unitXMLFormat = '请选择Junit XML 格式的文件。';
|
||||
|
||||
@@ -77,7 +77,6 @@ function setTemplate(templateID)
|
||||
var cmd = editor['<?php echo $link;?>'].edit.cmd;
|
||||
editor['<?php echo $link;?>'].html('');
|
||||
cmd.inserthtml(content);
|
||||
$("#mainContent #dataform .table.table-form .steps #templateID").val(templateID);
|
||||
}
|
||||
|
||||
function deleteTemplate(templateID)
|
||||
|
||||
Vendored
+2
-4
@@ -1,4 +1,2 @@
|
||||
alert('日语是收费功能,需要购买插件安装');
|
||||
$.cookie('lang', 'zh-cn', {expires:config.cookieLife, path:config.webRoot});
|
||||
location.href = location.href;
|
||||
|
||||
var locateLink = config.webRoot + 'tip4japanese.html';
|
||||
if(location.href.indexOf(locateLink) < 0) location.href = locateLink;
|
||||
|
||||
@@ -58,3 +58,5 @@ a.showMoreImage:hover{opacity: 1;}
|
||||
.color-darkblue:hover{background:rgb(0,0,139)}
|
||||
.color-darkblue:focus{background:rgb(0,0,139)}
|
||||
.margin-l-50px{margin-left:50px;}
|
||||
|
||||
.chosen-container .chosen-drop{z-index: 1100;}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='zh-cn'>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<title>グリッド・リサーチ株式会社に完全日本語使用権を取得ください</title>
|
||||
<style>
|
||||
body{margin:0px;}
|
||||
p{margin:0px; margin-bottom:3px;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style='width:500px;margin:100px auto; border:1px solid #000; padding:10px;'>
|
||||
<h5 style='margin-top:0px;'>グリッド・リサーチ株式会社に完全日本語使用権を取得ください</h5>
|
||||
<div style='font-size:12px;'>
|
||||
<p>〒104-0041 東京都中央区新富1-15-11 マキプラザ 3階</p>
|
||||
<p>電話:03-3537-9700(代表)</p>
|
||||
<p>MailTo:sales1@grids.co.jp</p>
|
||||
</div>
|
||||
<div style='margin-top:20px; font-size:13px;'>
|
||||
Language :
|
||||
<a style='padding-right:5px;' href="javascript:switchLang('zh-cn')">简体</a>
|
||||
<a style='padding-right:5px;' href="javascript:switchLang('zh-tw')">繁體</a>
|
||||
<a style='padding-right:5px;' href="javascript:switchLang('en')">English</a>
|
||||
<a style='padding-right:5px;' href="javascript:switchLang('de')">Deutsch</a>
|
||||
<a style='padding-right:5px;' href="javascript:switchLang('fr')">Français</a>
|
||||
<a style='padding-right:5px;' href="javascript:switchLang('vi')">Tiếng Việt</a>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function switchLang(lang)
|
||||
{
|
||||
document.cookie = "lang=" + lang;
|
||||
location.href = window.location.protocol+"//"+window.location.host;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user