Merge branch 'master' of https://github.com/easysoft/zentaopms
This commit is contained in:
+5
-1
@@ -39,7 +39,11 @@ echo %ztcli% > %baseDir%ztcli.bat
|
||||
echo ztcli.bat ok
|
||||
|
||||
:: create backup.bat
|
||||
SET backup= %phpcli% %baseDir%php\backup.php
|
||||
if %requestType% == 'PATH_INFO' (
|
||||
SET backup= %phpcli% %baseDir%ztcli "%pmsRoot%/backup-backup.html"
|
||||
)else (
|
||||
SET backup= %phpcli% %baseDir%ztcli "%pmsRoot%/index.php?m=backup&f=backup"
|
||||
)
|
||||
echo %backup% > %baseDir%backup.bat
|
||||
echo backup.bat ok
|
||||
|
||||
|
||||
+5
-1
@@ -42,7 +42,11 @@ echo $ztcli > $basePath/ztcli.sh
|
||||
echo "ztcli.sh ok"
|
||||
|
||||
# backup database
|
||||
backup="$phpcli $basePath/php/backup.php"
|
||||
if [ $requestType == 'PATH_INFO' ]; then
|
||||
backup="$phpcli $basePath/ztcli '$pmsRoot/backup-backup.html'";
|
||||
else
|
||||
backup="$phpcli $basePath/ztcli '$pmsRoot/index.php?m=backup&f=backup'";
|
||||
fi
|
||||
echo $backup > $basePath/backup.sh
|
||||
echo "backup.sh ok"
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
/* Backup the db. */
|
||||
error_reporting(E_ALL ^ E_NOTICE);
|
||||
|
||||
/* Include config.php and pclzip class. */
|
||||
$pmsRoot = dirname(dirname(dirname(__FILE__)));
|
||||
$myConfig = $pmsRoot . '/config/config.php';
|
||||
$zipClass = $pmsRoot . '/lib/pclzip/pclzip.class.php';
|
||||
$zdbClass = $pmsRoot . '/lib/zdb/zdb.class.php';
|
||||
|
||||
include $myConfig;
|
||||
include $zipClass;
|
||||
include $zdbClass;
|
||||
|
||||
/* Init the backupRoot and dest directory. */
|
||||
$backupRoot = $pmsRoot . "/backup";
|
||||
$destDir = $backupRoot . "/" . date('Ym');
|
||||
|
||||
if(!file_exists($backupRoot)) mkdir($backupRoot, 0777);
|
||||
if(!file_exists($destDir)) mkdir($destDir, 0777);
|
||||
|
||||
/* Backup database. */
|
||||
$dbRawFile = "db." . date('Ymd') . ".sql";
|
||||
$dsn = "mysql:host={$config->db->host}; port={$config->db->port}; dbname={$config->db->name}";
|
||||
$dbh = new PDO($dsn, $config->db->user, $config->db->password, array(PDO::ATTR_PERSISTENT => $config->db->persistant));
|
||||
$dbh->exec("SET NAMES {$config->db->encoding}");
|
||||
echo "Backuping database,";
|
||||
$zdb = new zdb();
|
||||
$return = $zdb->dump($dbRawFile);
|
||||
if($return->result)
|
||||
{
|
||||
$dbZipFile = $destDir . "/" . str_replace("sql", "zip", $dbRawFile);
|
||||
$archive = new pclzip($dbZipFile);
|
||||
|
||||
if($archive->create($dbRawFile))
|
||||
{
|
||||
unlink($dbRawFile);
|
||||
echo " successfully saved to $dbZipFile\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
die("Error : " . $archive->errorInfo(true));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Failed to backup database!\n";
|
||||
}
|
||||
|
||||
/* Backup the attachments. */
|
||||
chdir(dirname(dirname(dirname(__FILE__))) . "/www");
|
||||
if(!is_dir('data/upload')) die(" No files needed backup.\n");
|
||||
|
||||
echo "Backuping files,";
|
||||
$attachFile = $destDir . "/" . "file." . date('Ymd', time()) . ".zip";
|
||||
$archive = new pclzip($attachFile);
|
||||
if($archive->create("data/upload", PCLZIP_OPT_REMOVE_PATH, "data")) die(" successfully saved to $attachFile\n");
|
||||
die("Error : ".$archive->errorInfo(true));
|
||||
+1
-1
@@ -38,7 +38,7 @@ $config->langs['zh-tw'] = '繁體';
|
||||
$config->langs['en'] = 'English';
|
||||
|
||||
/* 设备类型视图文件前缀。The prefix for view file for different device. */
|
||||
$config->devicePrefix['mhtml'] = 'm.';
|
||||
$config->devicePrefix['mhtml'] = '';
|
||||
|
||||
/* 默认值设置。Default settings. */
|
||||
$config->default = new stdclass();
|
||||
|
||||
@@ -199,3 +199,8 @@ $filter->user->login->get['account'] = 'account';
|
||||
$filter->user->login->get['lang'] = 'reg::lang';
|
||||
$filter->user->login->get['password'] = 'reg::any';
|
||||
$filter->user->edit->get['from'] = 'reg::word';
|
||||
|
||||
$filter->git->cat->get['repoUrl'] = 'reg::base64';
|
||||
$filter->git->diff->get['repoUrl'] = 'reg::base64';
|
||||
$filter->svn->cat->get['repoUrl'] = 'reg::base64';
|
||||
$filter->svn->diff->get['repoUrl'] = 'reg::base64';
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `zt_productplan` ADD `order` TEXT NOT NULL AFTER `end`;
|
||||
+2
-1
@@ -438,6 +438,7 @@ CREATE TABLE IF NOT EXISTS `zt_productplan` (
|
||||
`desc` text NOT NULL,
|
||||
`begin` date NOT NULL,
|
||||
`end` date NOT NULL,
|
||||
`order` text NOT NULL,
|
||||
`deleted` enum('0','1') NOT NULL default '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `plan` (`product`,`end`)
|
||||
@@ -916,7 +917,7 @@ INSERT INTO `zt_group` (`id`, `name`, `role`, `desc`) VALUES
|
||||
(9, 'TOP', 'top', 'for top manager.'),
|
||||
(10, 'OTHERS', 'others', 'for others.'),
|
||||
(11, 'guest', 'guest', 'For guest'),
|
||||
(12, 'limited', 'limited', 'For limited user');
|
||||
(12, 'LIMITED', 'limited', 'For limited user');
|
||||
|
||||
INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(1, 'action', 'editComment'),
|
||||
|
||||
@@ -104,6 +104,23 @@ class action extends control
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comment.
|
||||
*
|
||||
* @param string $objectType
|
||||
* @param int $objectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function comment($objectType, $objectID)
|
||||
{
|
||||
$actionID = $this->action->create($objectType, $objectID, 'Commented', $this->post->comment);
|
||||
|
||||
$moduleName = $objectType == 'case' ? 'testcase' : $objectType;
|
||||
$this->loadModel($moduleName)->sendmail($objectID, $actionID);
|
||||
die(js::reload('parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit comment of a action.
|
||||
*
|
||||
|
||||
@@ -25,6 +25,7 @@ $lang->action->undelete = 'Restore';
|
||||
$lang->action->hideOne = 'Hide';
|
||||
$lang->action->hideAll = 'Hide All';
|
||||
$lang->action->editComment = 'Edit';
|
||||
$lang->action->comment = 'Comment';
|
||||
|
||||
$lang->action->trashTips = 'Note: Delete in ZenTao is logic.';
|
||||
$lang->action->textDiff = 'Text Format';
|
||||
|
||||
@@ -25,6 +25,7 @@ $lang->action->undelete = '还原';
|
||||
$lang->action->hideOne = '隐藏';
|
||||
$lang->action->hideAll = '全部隐藏';
|
||||
$lang->action->editComment = '修改备注';
|
||||
$lang->action->comment = '备注';
|
||||
|
||||
$lang->action->trashTips = '提示:为了保证系统的完整性,禅道系统的删除都是标记删除。';
|
||||
$lang->action->textDiff = '文本格式';
|
||||
|
||||
@@ -6,7 +6,7 @@ $config->bug->longlife = 7;
|
||||
$config->bug->create = new stdclass();
|
||||
$config->bug->edit = new stdclass();
|
||||
$config->bug->resolve = new stdclass();
|
||||
$config->bug->create->requiredFields = 'title,openedBuild';
|
||||
$config->bug->create->requiredFields = 'title,openedBuild,module';
|
||||
$config->bug->edit->requiredFields = $config->bug->create->requiredFields;
|
||||
$config->bug->resolve->requiredFields = 'resolution';
|
||||
|
||||
|
||||
+106
-75
@@ -15,7 +15,7 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Construct function, load some modules auto.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -43,7 +43,7 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* The index page, locate to browse.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -54,15 +54,15 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Browse bugs.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $branch
|
||||
* @param string $browseType
|
||||
* @param int $param
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @param string $browseType
|
||||
* @param int $param
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -171,11 +171,11 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* The report page.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $browseType
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $browseType
|
||||
* @param int $branchID
|
||||
* @param int $moduleID
|
||||
* @param int $moduleID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -211,8 +211,8 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Create a bug.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $extras others params, forexample, projectID=10,moduleID=10
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -328,6 +328,9 @@ class bug extends control
|
||||
$projectMembers = $this->view->users;
|
||||
}
|
||||
|
||||
$moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $branch);
|
||||
if(empty($moduleOptionMenu)) die(js::locate(helper::createLink('tree', 'browse', "productID=$productID&view=story")));
|
||||
|
||||
/* Set custom. */
|
||||
foreach(explode(',', $this->config->bug->list->customCreateFields) as $field) $customFields[$field] = $this->lang->bug->$field;
|
||||
$this->view->customFields = $customFields;
|
||||
@@ -339,7 +342,7 @@ class bug extends control
|
||||
|
||||
$this->view->productID = $productID;
|
||||
$this->view->productName = $this->products[$productID];
|
||||
$this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $branch);
|
||||
$this->view->moduleOptionMenu = $moduleOptionMenu;
|
||||
$this->view->stories = $stories;
|
||||
$this->view->projects = $this->product->getProjectPairs($productID, $branch ? "0,$branch" : 0, $params = 'nodeleted');
|
||||
$this->view->builds = $builds;
|
||||
@@ -372,11 +375,11 @@ class bug extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch create.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $projectID
|
||||
* @param int $moduleID
|
||||
* Batch create.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $projectID
|
||||
* @param int $moduleID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -453,8 +456,8 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* View a bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -481,7 +484,7 @@ class bug extends control
|
||||
/* Get product info. */
|
||||
$productID = $bug->product;
|
||||
$productName = $this->products[$productID];
|
||||
|
||||
|
||||
/* Header and positon. */
|
||||
$this->view->title = "BUG #$bug->id $bug->title - " . $this->products[$productID];
|
||||
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $productName);
|
||||
@@ -503,8 +506,8 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Edit a bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -625,11 +628,11 @@ class bug extends control
|
||||
$this->bug->sendmail($bugID, $actionID);
|
||||
|
||||
$bug = $this->bug->getById($bugID);
|
||||
if($bug->toTask != 0)
|
||||
if($bug->toTask != 0)
|
||||
{
|
||||
foreach($changes as $change)
|
||||
{
|
||||
if($change['field'] == 'status')
|
||||
if($change['field'] == 'status')
|
||||
{
|
||||
$confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask");
|
||||
$cancelURL = $this->server->HTTP_REFERER;
|
||||
@@ -727,7 +730,7 @@ class bug extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Update assign of bug.
|
||||
* Update assign of bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
@@ -763,6 +766,34 @@ class bug extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch change branch.
|
||||
*
|
||||
* @param int $branchID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function batchChangeBranch($branchID)
|
||||
{
|
||||
if($this->post->bugIDList)
|
||||
{
|
||||
$bugIDList = $this->post->bugIDList;
|
||||
$bugIDList = array_unique($bugIDList);
|
||||
unset($_POST['bugIDList']);
|
||||
$allChanges = $this->bug->batchChangeBranch($bugIDList, $branchID);
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
foreach($allChanges as $bugID => $changes)
|
||||
{
|
||||
$this->loadModel('action');
|
||||
$actionID = $this->action->create('bug', $bugID, 'Edited');
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
$this->bug->sendmail($bugID, $actionID);
|
||||
}
|
||||
}
|
||||
$this->loadModel('score')->create('ajax', 'batchOther');
|
||||
die(js::locate($this->session->bugList, 'parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch change the module of bug.
|
||||
*
|
||||
@@ -792,9 +823,9 @@ class bug extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch update assign of bug.
|
||||
*
|
||||
* @param int $projectID
|
||||
* Batch update assign of bug.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -823,8 +854,8 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* confirm a bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -856,8 +887,8 @@ class bug extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch confirm bugs.
|
||||
*
|
||||
* Batch confirm bugs.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -875,11 +906,11 @@ class bug extends control
|
||||
$this->loadModel('score')->create('ajax', 'batchOther');
|
||||
die(js::locate($this->session->bugList, 'parent'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve a bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -896,7 +927,7 @@ class bug extends control
|
||||
$this->bug->sendmail($bugID, $actionID);
|
||||
|
||||
$bug = $this->bug->getById($bugID);
|
||||
if($bug->toTask != 0)
|
||||
if($bug->toTask != 0)
|
||||
{
|
||||
/* If task is not finished, update it's status. */
|
||||
$task = $this->task->getById($bug->toTask);
|
||||
@@ -907,7 +938,7 @@ class bug extends control
|
||||
$cancelURL = $this->createLink('bug', 'view', "bugID=$bugID");
|
||||
die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent.parent'));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(isonlybody()) die(js::closeModal('parent.parent'));
|
||||
die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
|
||||
}
|
||||
@@ -936,9 +967,9 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Batch resolve bugs.
|
||||
*
|
||||
* @param string $resolution
|
||||
* @param string $resolvedBuild
|
||||
*
|
||||
* @param string $resolution
|
||||
* @param string $resolvedBuild
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -995,8 +1026,8 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Close a bug.
|
||||
*
|
||||
* @param int $bugID
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1113,8 +1144,8 @@ class bug extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch close bugs.
|
||||
*
|
||||
* Batch close bugs.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1225,7 +1256,7 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Save current template.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
@@ -1238,7 +1269,7 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Build the user templates selection code.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1250,8 +1281,8 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Delete a user template.
|
||||
*
|
||||
* @param int $templateID
|
||||
*
|
||||
* @param int $templateID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1263,8 +1294,8 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* AJAX: get bugs of a user in html select.
|
||||
*
|
||||
* @param string $account
|
||||
*
|
||||
* @param string $account
|
||||
* @param string $id the id of the select control.
|
||||
* @access public
|
||||
* @return string
|
||||
@@ -1280,9 +1311,9 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* AJAX: Get bug owner of a module.
|
||||
*
|
||||
* @param int $moduleID
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $moduleID
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
@@ -1294,32 +1325,32 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* AJAX: get team members of the project as assignedTo list.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $selectedUser
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $selectedUser
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function ajaxLoadAssignedTo($projectID, $selectedUser = '')
|
||||
{
|
||||
$projectMembers = $this->loadModel('project')->getTeamMemberPairs($projectID);
|
||||
|
||||
|
||||
die(html::select('assignedTo', $projectMembers, $selectedUser, 'class="form-control"'));
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: get team members of the latest project of a product as assignedTo list.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* x
|
||||
* @param string $selectedUser
|
||||
* @param string $selectedUser
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function ajaxLoadProjectTeamMembers($productID, $selectedUser = '')
|
||||
{
|
||||
$latestProject = $this->product->getLatestProject($productID);
|
||||
if(!empty($latestProject))
|
||||
if(!empty($latestProject))
|
||||
{
|
||||
$projectMembers = $this->loadModel('project')->getTeamMemberPairs($latestProject->id, 'nodeleted');
|
||||
}
|
||||
@@ -1346,9 +1377,9 @@ class bug extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: get actions of a bug. for web app.
|
||||
*
|
||||
* @param int $bugID
|
||||
* AJAX: get actions of a bug. for web app.
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1359,10 +1390,10 @@ class bug extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data to export
|
||||
*
|
||||
* @param string $productID
|
||||
* @param string $orderBy
|
||||
* Get data to export
|
||||
*
|
||||
* @param string $productID
|
||||
* @param string $orderBy
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1550,8 +1581,8 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Ajax get bug by ID.
|
||||
*
|
||||
* @param int $bugID
|
||||
*
|
||||
* @param int $bugID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
|
||||
@@ -78,7 +78,7 @@ function loadBranch()
|
||||
$('#taskIdBox').innerHTML = '<select id="task"></select>'; // Reset the task.
|
||||
$('#task').chosen(defaultChosenOptions);
|
||||
productID = $('#product').val();
|
||||
loadProductModules(productID);
|
||||
loadProductModules(productID);
|
||||
loadProductProjects(productID);
|
||||
loadProductBuilds(productID);
|
||||
loadProductplans(productID);
|
||||
|
||||
@@ -217,18 +217,18 @@ $lang->bug->browserList['other'] = 'Other';
|
||||
$lang->bug->typeList[''] = '';
|
||||
$lang->bug->typeList['codeerror'] = 'Code Error';
|
||||
$lang->bug->typeList['interface'] = 'Interface Optimization';
|
||||
$lang->bug->typeList['designchange'] = 'Design Change';
|
||||
$lang->bug->typeList['newfeature'] = 'New Feature';
|
||||
$lang->bug->typeList['designdefect'] = 'Design Defect';
|
||||
$lang->bug->typeList['config'] = 'Configuration';
|
||||
$lang->bug->typeList['install'] = 'Install/Deploy';
|
||||
$lang->bug->typeList['security'] = 'Security';
|
||||
$lang->bug->typeList['performance'] = 'Performance';
|
||||
$lang->bug->typeList['standard'] = 'Standard';
|
||||
$lang->bug->typeList['automation'] = 'Testing Script';
|
||||
$lang->bug->typeList['trackthings'] = 'Issue Tracking';
|
||||
$lang->bug->typeList['others'] = 'Other';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$lang->bug->statusList[''] = '';
|
||||
$lang->bug->statusList['active'] = 'Active';
|
||||
$lang->bug->statusList['resolved'] = 'Resolved';
|
||||
|
||||
@@ -115,6 +115,7 @@ $lang->bug->byQuery = '搜索';
|
||||
$lang->bug->needConfirm = '需求变动';
|
||||
$lang->bug->allProduct = '所有' . $lang->productCommon;
|
||||
|
||||
|
||||
$lang->bug->ditto = '同上';
|
||||
$lang->bug->dittoNotice = '该bug与上一bug不属于同一产品!';
|
||||
|
||||
@@ -216,17 +217,17 @@ $lang->bug->browserList['other'] = '其他';
|
||||
$lang->bug->typeList[''] = '';
|
||||
$lang->bug->typeList['codeerror'] = '代码错误';
|
||||
$lang->bug->typeList['interface'] = '界面优化';
|
||||
$lang->bug->typeList['designchange'] = '设计变更';
|
||||
$lang->bug->typeList['newfeature'] = '新增需求';
|
||||
$lang->bug->typeList['designdefect'] = '设计缺陷';
|
||||
$lang->bug->typeList['config'] = '配置相关';
|
||||
$lang->bug->typeList['install'] = '安装部署';
|
||||
$lang->bug->typeList['security'] = '安全相关';
|
||||
$lang->bug->typeList['performance'] = '性能问题';
|
||||
$lang->bug->typeList['standard'] = '标准规范';
|
||||
$lang->bug->typeList['automation'] = '测试脚本';
|
||||
$lang->bug->typeList['trackthings'] = '事务跟踪';
|
||||
$lang->bug->typeList['others'] = '其他';
|
||||
$lang->bug->typeList['designchange'] = '设计变更';
|
||||
$lang->bug->typeList['newfeature'] = '新增需求';
|
||||
$lang->bug->typeList['designdefect'] = '设计缺陷';
|
||||
$lang->bug->typeList['trackthings'] = '事务跟踪';
|
||||
|
||||
$lang->bug->statusList[''] = '';
|
||||
$lang->bug->statusList['active'] = '激活';
|
||||
|
||||
+34
-1
@@ -113,7 +113,11 @@ class bugModel extends model
|
||||
|
||||
for($i = 0; $i < $batchNum; $i++)
|
||||
{
|
||||
if(!empty($data->title[$i]) and empty($data->openedBuilds[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->bug->openedBuild)));
|
||||
if(!empty($data->title[$i]))
|
||||
{
|
||||
if(empty($data->modules[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->bug->module)));
|
||||
if(empty($data->openedBuilds[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->bug->openedBuild)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Get pairs(moduleID => moduleOwner) for bug. */
|
||||
@@ -865,6 +869,35 @@ class bugModel extends model
|
||||
$this->linkBugToBuild($bugID, $bug->resolvedBuild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch change branch.
|
||||
*
|
||||
* @param array $bugIDList
|
||||
* @param int $branchID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function batchChangeBranch($bugIDList, $branchID)
|
||||
{
|
||||
$now = helper::now();
|
||||
$allChanges = array();
|
||||
$oldBugs = $this->getByList($bugIDList);
|
||||
foreach($bugIDList as $bugID)
|
||||
{
|
||||
$oldBug = $oldBugs[$bugID];
|
||||
if($branchID == $oldBug->branch) continue;
|
||||
|
||||
$bug = new stdclass();
|
||||
$bug->lastEditedBy = $this->app->user->account;
|
||||
$bug->lastEditedDate = $now;
|
||||
$bug->branch = $branchID;
|
||||
|
||||
$this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec();
|
||||
if(!dao::isError()) $allChanges[$bugID] = common::createChanges($oldBug, $bug);
|
||||
}
|
||||
return $allChanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch change the module of bug.
|
||||
*
|
||||
|
||||
@@ -39,7 +39,7 @@ foreach(explode(',', $showFields) as $field)
|
||||
<tr>
|
||||
<th class='w-50px'> <?php echo $lang->idAB;?></th>
|
||||
<th class='w-120px<?php echo zget($visibleFields, $product->type, ' hidden')?>'> <?php echo $lang->product->branch;?></th>
|
||||
<th class='w-120px<?php echo zget($visibleFields, 'module', ' hidden')?>'> <?php echo $lang->bug->module;?></th>
|
||||
<th class='w-120px<?php echo zget($visibleFields, 'module', ' hidden')?>'> <?php echo $lang->bug->module;?> <span class='required'></span></th>
|
||||
<th class='w-130px<?php echo zget($visibleFields, 'project', ' hidden')?>'><?php echo $lang->bug->project;?></th>
|
||||
<th><?php echo $lang->bug->openedBuild;?> <span class='required'></span></th>
|
||||
<th><?php echo $lang->bug->title;?> <span class='required'></span></th>
|
||||
|
||||
@@ -237,6 +237,23 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow
|
||||
$misc = common::hasPriv('bug', 'batchActivate') ? "onclick=\"setFormAction('$actionLink')\"" : $class;
|
||||
if($misc) echo "<li>" . html::a('javascript:;', $lang->bug->activate, '', $misc) . "</li>";
|
||||
|
||||
if(common::hasPriv('bug', 'batchChangeBranch') and $this->session->currentProductType != 'normal')
|
||||
{
|
||||
$withSearch = count($branches) > 8;
|
||||
echo "<li class='dropdown-submenu'>";
|
||||
echo html::a('javascript:;', $lang->product->branchName[$this->session->currentProductType], '', "id='branchItem'");
|
||||
echo "<div class='dropdown-menu" . ($withSearch ? ' with-search':'') . "'>";
|
||||
echo "<ul class='dropdown-list'>";
|
||||
foreach($branches as $branchID => $branchName)
|
||||
{
|
||||
$actionLink = $this->createLink('bug', 'batchChangeBranch', "branchID=$branchID");
|
||||
echo "<li class='option' data-key='$branchID'>" . html::a('#', $branchName, '', "onclick=\"setFormAction('$actionLink', 'hiddenwin')\"") . "</li>";
|
||||
}
|
||||
echo '</ul>';
|
||||
if($withSearch) echo "<div class='menu-search'><div class='input-group input-group-sm'><input type='text' class='form-control' placeholder=''><span class='input-group-addon'><i class='icon-search'></i></span></div></div>";
|
||||
echo '</div></li>';
|
||||
}
|
||||
|
||||
if(common::hasPriv('bug', 'batchChangeModule'))
|
||||
{
|
||||
$withSearch = count($modules) > 8;
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
<div class='actions'><?php if(!$bug->deleted) echo $actionLinks;?></div>
|
||||
<fieldset id='commentBox' class='hide'>
|
||||
<legend><?php echo $lang->comment;?></legend>
|
||||
<form method='post' action='<?php echo inlink('edit', "bugID=$bug->id&comment=true")?>'>
|
||||
<form method='post' action='<?php echo $this->createLink('action', 'comment', "objectType=bug&objectID=$bug->id")?>' target='hiddenwin'>
|
||||
<div class="form-group"><?php echo html::textarea('comment', '',"rows='5' class='w-p100'");?></div>
|
||||
<?php echo html::submitButton() . html::backButton();?>
|
||||
</form>
|
||||
|
||||
@@ -174,7 +174,7 @@ class build extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function view($buildID, $type = 'story', $link = 'false', $param = '')
|
||||
public function view($buildID, $type = 'story', $link = 'false', $param = '', $orderBy = 'id_desc')
|
||||
{
|
||||
if($type == 'story')$this->session->set('storyList', $this->app->getURI(true));
|
||||
if($type == 'bug') $this->session->set('bugList', $this->app->getURI(true));
|
||||
@@ -189,7 +189,9 @@ class build extends control
|
||||
$product = $this->loadModel('product')->getById($build->product);
|
||||
if($product->type != 'normal') $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
|
||||
|
||||
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($build->bugs)->andWhere('deleted')->eq(0)->fetchAll();
|
||||
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($build->bugs)->andWhere('deleted')->eq(0)
|
||||
->beginIF($type == 'bug')->orderBy($orderBy)->fi()
|
||||
->fetchAll();
|
||||
|
||||
if($this->config->global->flow == 'onlyTest')
|
||||
{
|
||||
@@ -203,7 +205,9 @@ class build extends control
|
||||
}
|
||||
else
|
||||
{
|
||||
$stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($build->stories)->andWhere('deleted')->eq(0)->fetchAll('id');
|
||||
$stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($build->stories)->andWhere('deleted')->eq(0)
|
||||
->beginIF($type == 'story')->orderBy($orderBy)->fi()
|
||||
->fetchAll('id');
|
||||
$stages = $this->dao->select('*')->from(TABLE_STORYSTAGE)->where('story')->in($build->stories)->andWhere('branch')->eq($build->branch)->fetchPairs('story', 'stage');
|
||||
foreach($stages as $storyID => $stage)$stories[$storyID]->stage = $stage;
|
||||
|
||||
@@ -214,7 +218,7 @@ class build extends control
|
||||
$this->view->position[] = html::a($this->createLink('project', 'task', "projectID=$build->project"), $projects[$build->project]);
|
||||
$this->view->position[] = $this->lang->build->view;
|
||||
$this->view->stories = $stories;
|
||||
$this->view->generatedBugs = $this->bug->getProjectBugs($build->project, $build->id, '', 0, 'status_desc,id_desc', null);
|
||||
$this->view->generatedBugs = $this->bug->getProjectBugs($build->project, $build->id, '', 0, $type == 'newbug' ? $orderBy : 'status_desc,id_desc', null);
|
||||
$this->view->bugs = $bugs;
|
||||
$this->view->type = $type;
|
||||
}
|
||||
@@ -225,6 +229,7 @@ class build extends control
|
||||
$this->view->actions = $this->loadModel('action')->getList('build', $buildID);
|
||||
$this->view->link = $link;
|
||||
$this->view->param = $param;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->branchName = $build->productType == 'normal' ? '' : $this->loadModel('branch')->getById($build->branch);
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -10,5 +10,8 @@
|
||||
|
||||
.table-actions {padding-left: 5px;}
|
||||
|
||||
#buildInfo {border-top: 1px solid #ddd;}
|
||||
#buildInfo > div {padding-top: 15px;}
|
||||
|
||||
#querybox form {margin: 0px !important;}
|
||||
#moreOrLite {right: 0px !important;}
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php
|
||||
$jsRoot = $this->app->getWebRoot() . "js/";
|
||||
include '../../common/view/tablesorter.html.php';
|
||||
?>
|
||||
<div id='querybox' class='show'></div>
|
||||
<div id='unlinkBugList'>
|
||||
<form method='post' id='unlinkedBugsForm' target='hiddenwin' action='<?php echo $this->createLink('build', 'linkBug', "buildID={$build->id}&browseType=$browseType¶m=$param");?>'>
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php
|
||||
$jsRoot = $this->app->getWebRoot() . "js/";
|
||||
include '../../common/view/tablesorter.html.php';
|
||||
?>
|
||||
<div id='querybox' class='show'></div>
|
||||
<div id='unlinkStoryList'>
|
||||
<form method='post' id='unlinkedStoriesForm' target='hiddenwin' action='<?php echo $this->createLink('build', 'linkStory', "buildID={$build->id}&browseType=$browseType¶m=$param");?>'>
|
||||
|
||||
@@ -79,9 +79,10 @@ tfoot tr td .table-actions .btn{display:none;}
|
||||
<div class='tabs'>
|
||||
<?php $countStories = count($stories); $countBugs = count($bugs); $countNewBugs = count($generatedBugs);?>
|
||||
<ul class='nav nav-tabs'>
|
||||
<li <?php if($type == 'story') echo "class='active'"?>><a href='#stories' data-toggle='tab'><?php echo html::icon($lang->icons['story'], 'green') . ' ' . $lang->build->stories;?></a></li>
|
||||
<li <?php if($type == 'bug') echo "class='active'"?>><a href='#bugs' data-toggle='tab'><?php echo html::icon($lang->icons['bug'], 'green') . ' ' . $lang->build->bugs;?></a></li>
|
||||
<li <?php if($type == 'newbug') echo "class='active'"?>><a href='#newBugs' data-toggle='tab'><?php echo html::icon($lang->icons['bug'], 'red') . ' ' . $lang->build->generatedBugs;?></a></li>
|
||||
<li <?php if($type == 'story') echo "class='active'"?>><a href='#stories' data-toggle='tab'><?php echo html::icon($lang->icons['story'], 'green') . ' ' . $lang->build->stories;?></a></li>
|
||||
<li <?php if($type == 'bug') echo "class='active'"?>><a href='#bugs' data-toggle='tab'><?php echo html::icon($lang->icons['bug'], 'green') . ' ' . $lang->build->bugs;?></a></li>
|
||||
<li <?php if($type == 'newbug') echo "class='active'"?>><a href='#newBugs' data-toggle='tab'><?php echo html::icon($lang->icons['bug'], 'red') . ' ' . $lang->build->generatedBugs;?></a></li>
|
||||
<li <?php if($type == 'buildInfo') echo "class='active'"?>><a href='#buildInfo' data-toggle='tab'><?php echo html::icon($lang->icons['plan'], 'blue') . ' ' . $lang->build->view;?></a></li>
|
||||
</ul>
|
||||
<div class='tab-content'>
|
||||
<div class='tab-pane <?php if($type == 'story') echo 'active'?>' id='stories'>
|
||||
@@ -91,16 +92,17 @@ tfoot tr td .table-actions .btn{display:none;}
|
||||
<?php endif;?>
|
||||
<form method='post' target='hiddenwin' action='<?php echo inlink('batchUnlinkStory', "buildID={$build->id}")?>' id='linkedStoriesForm'>
|
||||
<table class='table table-hover table-condensed table-striped tablesorter table-fixed table-selectable' id='storyList'>
|
||||
<?php $vars = "buildID={$build->id}&type=story&link=$link¶m=$param&orderBy=%s";?>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='w-id'><?php echo $lang->idAB;?></th>
|
||||
<th class='w-pri'><?php echo $lang->priAB;?></th>
|
||||
<th><?php echo $lang->story->title;?></th>
|
||||
<th class='w-user'><?php echo $lang->openedByAB;?></th>
|
||||
<th class='w-hour'><?php echo $lang->story->estimateAB;?></th>
|
||||
<th class='w-hour'><?php echo $lang->statusAB;?></th>
|
||||
<th class='w-100px'><?php echo $lang->story->stageAB;?></th>
|
||||
<th class='w-50px'><?php echo $lang->actions;?></th>
|
||||
<th class='w-id {sorter:false}'> <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
|
||||
<th class='w-pri {sorter:false}'> <?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
|
||||
<th class='text-left {sorter:false}'><?php common::printOrderLink('title', $orderBy, $vars, $lang->story->title);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='w-hour {sorter:false}'> <?php common::printOrderLink('estimate', $orderBy, $vars, $lang->story->estimateAB);?></th>
|
||||
<th class='w-hour {sorter:false}'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
|
||||
<th class='w-100px {sorter:false}'> <?php common::printOrderLink('stage', $orderBy, $vars, $lang->story->stageAB);?></th>
|
||||
<th class='w-50px {sorter:false}'> <?php echo $lang->actions?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php $canBatchUnlink = common::hasPriv('build', 'batchUnlinkStory');?>
|
||||
@@ -150,16 +152,17 @@ tfoot tr td .table-actions .btn{display:none;}
|
||||
<?php endif;?>
|
||||
<form method='post' target='hiddenwin' action="<?php echo inLink('batchUnlinkBug', "build=$build->id");?>" id='linkedBugsForm'>
|
||||
<table class='table table-hover table-condensed table-striped tablesorter table-fixed table-selectable' id='bugList'>
|
||||
<?php $vars = "buildID={$build->id}&type=bug&link=$link¶m=$param&orderBy=%s";?>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='w-id'><?php echo $lang->idAB;?></th>
|
||||
<th><?php echo $lang->bug->title;?></th>
|
||||
<th class='w-100px'><?php echo $lang->bug->status;?></th>
|
||||
<th class='w-user'><?php echo $lang->openedByAB;?></th>
|
||||
<th class='w-date'><?php echo $lang->bug->openedDateAB;?></th>
|
||||
<th class='w-user'><?php echo $lang->bug->resolvedByAB;?></th>
|
||||
<th class='w-100px'><?php echo $lang->bug->resolvedDateAB;?></th>
|
||||
<th class='w-50px'><?php echo $lang->actions;?></th>
|
||||
<th class='w-id {sorter:false}'> <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
|
||||
<th class='text-left {sorter:false}'><?php common::printOrderLink('title', $orderBy, $vars, $lang->bug->title);?></th>
|
||||
<th class='w-100px {sorter:false}'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->bug->status);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='w-date {sorter:false}'> <?php common::printOrderLink('openedDate', $orderBy, $vars, $lang->bug->openedDateAB);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('resolvedBy', $orderBy, $vars, $lang->bug->resolvedByAB);?></th>
|
||||
<th class='w-100px {sorter:false}'> <?php common::printOrderLink('resolvedDate', $orderBy, $vars, $lang->bug->resolvedDateAB);?></th>
|
||||
<th class='w-50px {sorter:false}'> <?php echo $lang->actions?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php $canBatchUnlink = common::hasPriv('build', 'batchUnlinkBug');?>
|
||||
@@ -203,16 +206,18 @@ tfoot tr td .table-actions .btn{display:none;}
|
||||
</div>
|
||||
<div class='tab-pane <?php if($type == 'newbug') echo 'active'?>' id='newBugs'>
|
||||
<table class='table table-hover table-condensed table-striped tablesorter table-fixed'>
|
||||
<?php $vars = "buildID={$build->id}&type=newbug&link=$link¶m=$param&orderBy=%s";?>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='w-id'><?php echo $lang->idAB;?></th>
|
||||
<th class='w-severity'><?php echo $lang->bug->severityAB;?></th>
|
||||
<th><?php echo $lang->bug->title;?></th>
|
||||
<th class='w-100px'><?php echo $lang->bug->status;?></th>
|
||||
<th class='w-user'><?php echo $lang->openedByAB;?></th>
|
||||
<th class='w-date'><?php echo $lang->bug->openedDateAB;?></th>
|
||||
<th class='w-user'><?php echo $lang->bug->resolvedByAB;?></th>
|
||||
<th class='w-100px'><?php echo $lang->bug->resolvedDateAB;?></th>
|
||||
<th class='w-id {sorter:false}'> <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
|
||||
<th class='w-severity {sorter:false}'><?php common::printOrderLink('severity', $orderBy, $vars, $lang->bug->severityAB);?></th>
|
||||
<th class='text-left {sorter:false}'> <?php common::printOrderLink('title', $orderBy, $vars, $lang->bug->title);?></th>
|
||||
<th class='w-100px {sorter:false}'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->bug->status);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='w-date {sorter:false}'> <?php common::printOrderLink('openedDate', $orderBy, $vars, $lang->bug->openedDateAB);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('resolvedBy', $orderBy, $vars, $lang->bug->resolvedByAB);?></th>
|
||||
<th class='w-100px {sorter:false}'> <?php common::printOrderLink('resolvedDate', $orderBy, $vars, $lang->bug->resolvedDateAB);?></th>
|
||||
<th class='w-50px {sorter:false}'> <?php echo $lang->actions?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php foreach($generatedBugs as $bug):?>
|
||||
@@ -239,60 +244,62 @@ tfoot tr td .table-actions .btn{display:none;}
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<div class='tab-pane <?php if($type == 'buildInfo') echo 'active'?>' id='buildInfo'>
|
||||
<div class="row-table">
|
||||
<div class='col-main'>
|
||||
<fieldset>
|
||||
<legend><?php echo $lang->build->basicInfo?></legend>
|
||||
<table class='table table-data table-condensed table-borderless table-fixed'>
|
||||
<tr>
|
||||
<th class='w-80px'><?php echo $lang->build->product;?></th>
|
||||
<td><?php echo $build->productName;?></td>
|
||||
</tr>
|
||||
<?php if($build->productType != 'normal'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->product->branch;?></th>
|
||||
<td><?php echo $branchName;?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->name;?></th>
|
||||
<td><?php echo $build->name;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->builder;?></th>
|
||||
<td><?php echo $users[$build->builder];?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->date;?></th>
|
||||
<td><?php echo $build->date;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->scmPath;?></th>
|
||||
<td style='word-break:break-all;'><?php echo html::a($build->scmPath, $build->scmPath, '_blank')?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->filePath;?></th>
|
||||
<td style='word-break:break-all;'><?php echo html::a($build->filePath, $build->filePath, '_blank');?></td>
|
||||
</tr>
|
||||
<?php if($this->config->global->flow != 'onlyTest'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->desc;?></th>
|
||||
<td><div class='article-content'><?php echo $build->desc;?></div></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
</table>
|
||||
</fieldset>
|
||||
<?php if($this->config->global->flow != 'onlyTest'):?>
|
||||
<?php echo $this->fetch('file', 'printFiles', array('files' => $build->files, 'fieldset' => 'true'));?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<div class="col-side"><?php include '../../common/view/action.html.php';?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
<div class='col-side'>
|
||||
<div class='main-side main'>
|
||||
<?php if($this->config->global->flow != 'onlyTest'):?>
|
||||
<fieldset>
|
||||
<legend><?php echo $lang->build->desc;?></legend>
|
||||
<div class='article-content'><?php echo $build->desc;?></div>
|
||||
</fieldset>
|
||||
<?php endif;?>
|
||||
<fieldset>
|
||||
<legend><?php echo $lang->build->basicInfo?></legend>
|
||||
<table class='table table-data table-condensed table-borderless table-fixed'>
|
||||
<tr>
|
||||
<th class='w-80px'><?php echo $lang->build->product;?></th>
|
||||
<td><?php echo $build->productName;?></td>
|
||||
</tr>
|
||||
<?php if($build->productType != 'normal'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->product->branch;?></th>
|
||||
<td><?php echo $branchName;?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->name;?></th>
|
||||
<td><?php echo $build->name;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->builder;?></th>
|
||||
<td><?php echo $users[$build->builder];?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->date;?></th>
|
||||
<td><?php echo $build->date;?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->scmPath;?></th>
|
||||
<td style='word-break:break-all;'><?php echo html::a($build->scmPath, $build->scmPath, '_blank')?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->filePath;?></th>
|
||||
<td style='word-break:break-all;'><?php echo html::a($build->filePath, $build->filePath, '_blank');?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<?php if($this->config->global->flow != 'onlyTest'):?>
|
||||
<?php echo $this->fetch('file', 'printFiles', array('files' => $build->files, 'fieldset' => 'true'));?>
|
||||
<?php include '../../common/view/action.html.php';?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if($this->config->global->flow != 'onlyTest'):?>
|
||||
<?php js::set('param', helper::safe64Decode($param))?>
|
||||
|
||||
+100
-86
@@ -48,7 +48,7 @@ class commonModel extends model
|
||||
/**
|
||||
* Set the commpany.
|
||||
*
|
||||
* First, search company by the http host. If not found, search by the default domain. Last, use the first as the default.
|
||||
* First, search company by the http host. If not found, search by the default domain. Last, use the first as the default.
|
||||
* After get the company, save it to session.
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -72,7 +72,7 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Set the user info.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -99,7 +99,7 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Load configs from database and save it to config->system and config->personal.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -170,9 +170,9 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Deny access.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @return mixed
|
||||
*/
|
||||
public function deny($module, $method)
|
||||
{
|
||||
@@ -207,7 +207,7 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Print the run info.
|
||||
*
|
||||
*
|
||||
* @param mixed $startTime the start time.
|
||||
* @access public
|
||||
* @return array the run info array.
|
||||
@@ -223,7 +223,7 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Print top bar.
|
||||
*
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -293,8 +293,9 @@ class commonModel extends model
|
||||
/**
|
||||
* Create menu item link
|
||||
*
|
||||
* @param object $menuItemLink
|
||||
* @param boolean $isTutorialMode
|
||||
* @param object $menuItem
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
@@ -321,6 +322,8 @@ class commonModel extends model
|
||||
* Print the main menu.
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @param string $methodName
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -383,14 +386,14 @@ class commonModel extends model
|
||||
if($config->global->flow == 'onlyTask') $searchObject = 'task';
|
||||
}
|
||||
|
||||
echo "<div class='input-group input-group-sm' id='searchbox'>";
|
||||
echo "<div class='input-group input-group-sm' id='searchbox'>";
|
||||
echo "<div class='input-group-btn' id='typeSelector'>";
|
||||
echo "<button type='button' class='btn dropdown-toggle' data-toggle='dropdown'><span id='searchTypeName'>" . $lang->searchObjects[$searchObject] . "</span> <span class='caret'></span></button>";
|
||||
echo html::hidden('searchType', $searchObject);
|
||||
echo "<ul class='dropdown-menu'>";
|
||||
foreach ($lang->searchObjects as $key => $value)
|
||||
{
|
||||
echo "<li><a href='javascript:;' data-value='{$key}'>{$value}</a></li>";
|
||||
echo "<li><a href='javascript:;' data-value='{$key}'>{$value}</a></li>";
|
||||
}
|
||||
echo '</ul></div>';
|
||||
echo html::input('searchQuery', '', "onclick='this.value=\"\"' onkeydown='if(event.keyCode==13) shortcut()' class='form-control' placeholder='" . $lang->searchTips . "'");
|
||||
@@ -400,8 +403,8 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Print the module menu.
|
||||
*
|
||||
* @param string $moduleName
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -470,9 +473,9 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Print the bread menu.
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @param string $position
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @param string $position
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -504,7 +507,7 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Print the link for notify file.
|
||||
*
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -519,8 +522,10 @@ class commonModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Print QR code Link.
|
||||
*
|
||||
* Print QR code Link.
|
||||
*
|
||||
* @param string $color
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -537,16 +542,16 @@ class commonModel extends model
|
||||
/**
|
||||
* Print the link contains orderBy field.
|
||||
*
|
||||
* This method will auto set the orderby param according the params. Fox example, if the order by is desc,
|
||||
* This method will auto set the orderby param according the params. Fox example, if the order by is desc,
|
||||
* will be changed to asc.
|
||||
*
|
||||
*
|
||||
* @param string $fieldName the field name to sort by
|
||||
* @param string $orderBy the order by string
|
||||
* @param string $vars the vars to be passed
|
||||
* @param string $label the label of the link
|
||||
* @param string $module the module name
|
||||
* @param string $method the method name
|
||||
* @static
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -583,17 +588,21 @@ class commonModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Print link to an modules' methd.
|
||||
*
|
||||
* Before printing, check the privilege first. If no privilege, return fasle. Else, print the link, return true.
|
||||
*
|
||||
* @param string $module the module name
|
||||
* @param string $method the method
|
||||
* @param string $vars vars to be passed
|
||||
* @param string $label the label of the link
|
||||
* @param string $target the target of the link
|
||||
* @param string $misc others
|
||||
* @param bool $newline
|
||||
* @param string $module the module name
|
||||
* @param string $method the method
|
||||
* @param string $vars vars to be passed
|
||||
* @param string $label the label of the link
|
||||
* @param string $target the target of the link
|
||||
* @param string $misc others
|
||||
* @param bool $newline
|
||||
* @param bool $onlyBody
|
||||
* @param $object
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
@@ -607,7 +616,7 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Print icon of split line.
|
||||
*
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -619,11 +628,13 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Print icon of comment.
|
||||
*
|
||||
* @param string $module
|
||||
*
|
||||
* @param string $module
|
||||
* @param $object
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
* @return mixed
|
||||
*/
|
||||
public static function printCommentIcon($module, $object = null)
|
||||
{
|
||||
@@ -631,7 +642,7 @@ class commonModel extends model
|
||||
|
||||
global $lang;
|
||||
|
||||
if(!commonModel::hasPriv($module, 'edit', $object)) return false;
|
||||
if(!commonModel::hasPriv('action', 'comment', $object)) return false;
|
||||
echo html::a('#commentBox', '<i class="icon-comment-alt"></i>', '', "title='$lang->comment' onclick='setComment()' class='btn'");
|
||||
}
|
||||
|
||||
@@ -683,7 +694,7 @@ class commonModel extends model
|
||||
$title = $method;
|
||||
if($method == 'create' and $icon == 'copy') $method = 'copy';
|
||||
if(isset($lang->$method) and is_string($lang->$method)) $title = $lang->$method;
|
||||
if((isset($lang->$module->$method) or $app->loadLang($module)) and isset($lang->$module->$method))
|
||||
if((isset($lang->$module->$method) or $app->loadLang($module)) and isset($lang->$module->$method))
|
||||
{
|
||||
$title = $method == 'report' ? $lang->$module->$method->common : $lang->$module->$method;
|
||||
}
|
||||
@@ -759,8 +770,11 @@ class commonModel extends model
|
||||
/**
|
||||
* Print backLink and preLink and nextLink.
|
||||
*
|
||||
* @param string $backLink
|
||||
* @param object $preAndNext
|
||||
* @param string $backLink
|
||||
* @param object $preAndNext
|
||||
* @param string $linkTemplate
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -772,7 +786,7 @@ class commonModel extends model
|
||||
$title = $lang->goback . $lang->backShortcutKey;
|
||||
echo html::a($backLink, '<i class="icon-goback icon-level-up icon-large icon-rotate-270"></i>', '', "id='back' class='btn' title={$title}");
|
||||
|
||||
if(isset($preAndNext->pre) and $preAndNext->pre)
|
||||
if(isset($preAndNext->pre) and $preAndNext->pre)
|
||||
{
|
||||
$id = (isset($_SESSION['testcaseOnlyCondition']) and !$_SESSION['testcaseOnlyCondition'] and $app->getModuleName() == 'testcase' and isset($preAndNext->pre->case)) ? 'case' : 'id';
|
||||
$title = isset($preAndNext->pre->title) ? $preAndNext->pre->title : $preAndNext->pre->name;
|
||||
@@ -780,7 +794,7 @@ class commonModel extends model
|
||||
$link = $linkTemplate ? sprintf($linkTemplate, $preAndNext->pre->$id) : inLink('view', "ID={$preAndNext->pre->$id}");
|
||||
echo html::a($link, '<i class="icon-pre icon-chevron-left"></i>', '', "id='pre' class='btn' title='{$title}'");
|
||||
}
|
||||
if(isset($preAndNext->next) and $preAndNext->next)
|
||||
if(isset($preAndNext->next) and $preAndNext->next)
|
||||
{
|
||||
$id = (isset($_SESSION['testcaseOnlyCondition']) and !$_SESSION['testcaseOnlyCondition'] and $app->getModuleName() == 'testcase' and isset($preAndNext->next->case)) ? 'case' : 'id';
|
||||
$title = isset($preAndNext->next->title) ? $preAndNext->next->title : $preAndNext->next->name;
|
||||
@@ -792,7 +806,7 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Create changes of one object.
|
||||
*
|
||||
*
|
||||
* @param mixed $old the old object
|
||||
* @param mixed $new the new object
|
||||
* @static
|
||||
@@ -818,10 +832,10 @@ class commonModel extends model
|
||||
|
||||
if($magicQuote) $value = stripslashes($value);
|
||||
if(isset($old->$key) and $value != stripslashes($old->$key))
|
||||
{
|
||||
{
|
||||
$diff = '';
|
||||
if(substr_count($value, "\n") > 1 or
|
||||
substr_count($old->$key, "\n") > 1 or
|
||||
if(substr_count($value, "\n") > 1 or
|
||||
substr_count($old->$key, "\n") > 1 or
|
||||
strpos('name,title,desc,spec,steps,content,digest,verify,report', strtolower($key)) !== false)
|
||||
{
|
||||
$diff = commonModel::diff($old->$key, $value);
|
||||
@@ -834,9 +848,9 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Diff two string. (see phpt)
|
||||
*
|
||||
* @param string $text1
|
||||
* @param string $text2
|
||||
*
|
||||
* @param string $text1
|
||||
* @param string $text2
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
@@ -860,8 +874,8 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Judge Suhosin Setting whether the actual size of post data is large than the setting size.
|
||||
*
|
||||
* @param int $countInputVars
|
||||
*
|
||||
* @param int $countInputVars
|
||||
* @static
|
||||
* @access public
|
||||
* @return bool
|
||||
@@ -885,9 +899,9 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Get the previous and next object.
|
||||
*
|
||||
*
|
||||
* @param string $type story|task|bug|case
|
||||
* @param string $objectID
|
||||
* @param string $objectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -952,9 +966,9 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Save one executed query.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param string $objectType story|task|bug|testcase
|
||||
*
|
||||
* @param string $sql
|
||||
* @param string $objectType story|task|bug|testcase
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -996,10 +1010,10 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Remove duplicate for story, task, bug, case, doc.
|
||||
*
|
||||
*
|
||||
* @param string $type e.g. story task bug case doc.
|
||||
* @param array|object $data
|
||||
* @param string $condition
|
||||
* @param array|object $data
|
||||
* @param string $condition
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1033,9 +1047,9 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Append order by.
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param string $append
|
||||
*
|
||||
* @param string $orderBy
|
||||
* @param string $append
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
@@ -1048,9 +1062,9 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Check field exists
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $field
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $field
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
@@ -1071,7 +1085,7 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Check upgrade's status file is ok or not.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1092,7 +1106,7 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Check the user has permission to access this method, if not, locate to the login page or deny page.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1157,11 +1171,11 @@ class commonModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Check db priv.
|
||||
*
|
||||
* @param object $object
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* Check db priv.
|
||||
*
|
||||
* @param object $object
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -1259,7 +1273,7 @@ class commonModel extends model
|
||||
* we used %s as placeholder. These %s should be setted in one module.
|
||||
*
|
||||
* The items of one module's menu may be an string or array. For example, please see module/common/lang.
|
||||
*
|
||||
*
|
||||
* @param string $object the menus of one module
|
||||
* @param string $key the menu item to be replaced
|
||||
* @param string $params the params passed to the menu item
|
||||
@@ -1278,7 +1292,7 @@ class commonModel extends model
|
||||
$menu->$key->link = vsprintf($menu->$key->link, $params);
|
||||
$menu->$key = (array)$menu->$key;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
$menu->$key = vsprintf($menu->$key, $params);
|
||||
}
|
||||
@@ -1300,7 +1314,7 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Get the full url of the system.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
@@ -1323,8 +1337,8 @@ class commonModel extends model
|
||||
|
||||
/**
|
||||
* Convert items to Pinyin.
|
||||
*
|
||||
* @param array $items
|
||||
*
|
||||
* @param array $items
|
||||
* @static
|
||||
* @access public
|
||||
* @return array
|
||||
@@ -1365,8 +1379,8 @@ class commonModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Check an entry.
|
||||
*
|
||||
* Check an entry.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1394,9 +1408,9 @@ class commonModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Check token of an entry.
|
||||
*
|
||||
* @param string $key
|
||||
* Check token of an entry.
|
||||
*
|
||||
* @param string $key
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1409,9 +1423,9 @@ class commonModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Response.
|
||||
*
|
||||
* @param int $code
|
||||
* Response.
|
||||
*
|
||||
* @param int $code
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1425,10 +1439,10 @@ class commonModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Http.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string|array $data
|
||||
* Http.
|
||||
*
|
||||
* @param string $url
|
||||
* @param string|array $data
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
|
||||
@@ -13,7 +13,7 @@ if($extHookFiles) foreach($extHookFiles as $extHookFile) include $extHookFile;
|
||||
?>
|
||||
<?php if(empty($_GET['onlybody']) or $_GET['onlybody'] != 'yes'):?>
|
||||
<?php $this->app->loadConfig('sso');?>
|
||||
<?php
|
||||
<?php
|
||||
if(!empty($this->config->sso->redirect)) js::set('ssoRedirect', $this->config->sso->redirect);
|
||||
?>
|
||||
<header id='header'>
|
||||
|
||||
@@ -159,6 +159,7 @@ class cron extends control
|
||||
while(true)
|
||||
{
|
||||
dao::$cache = array();
|
||||
|
||||
/* When cron is null then die. */
|
||||
if(empty($crons)) break;
|
||||
if(empty($parsedCrons)) break;
|
||||
@@ -170,10 +171,12 @@ class cron extends control
|
||||
|
||||
/* Run crons. */
|
||||
$now = new datetime('now');
|
||||
unset($_SESSION['company']);
|
||||
unset($this->app->company);
|
||||
$this->common->setCompany();
|
||||
$this->common->loadConfigFromDB();
|
||||
foreach($parsedCrons as $id => $cron)
|
||||
{
|
||||
|
||||
$cronInfo = $this->cron->getById($id);
|
||||
/* Skip empty and stop cron.*/
|
||||
if(empty($cronInfo) or $cronInfo->status == 'stop') continue;
|
||||
|
||||
@@ -64,6 +64,7 @@ $lang->doc->manageType = 'Manage Category';
|
||||
$lang->doc->editType = 'Edit';
|
||||
$lang->doc->deleteType = 'Delete';
|
||||
$lang->doc->addType = 'Add';
|
||||
$lang->doc->childType = 'Child';
|
||||
|
||||
$lang->doc->libName = 'Name';
|
||||
$lang->doc->libType = 'Category';
|
||||
|
||||
@@ -64,6 +64,7 @@ $lang->doc->manageType = '维护分类';
|
||||
$lang->doc->editType = '编辑分类';
|
||||
$lang->doc->deleteType = '删除分类';
|
||||
$lang->doc->addType = '增加分类';
|
||||
$lang->doc->childType = '子分类';
|
||||
|
||||
$lang->doc->libName = '文档库名称';
|
||||
$lang->doc->libType = '文档库类型';
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
<i class='icon icon-download'></i>
|
||||
</a>
|
||||
<div class='card-heading'>
|
||||
<a href='<?php echo $this->createLink($file->objectType, 'view', "objectID=$file->objectID");?>'><?php echo $file->title . '.' . $file->extension . ' [' . strtoupper($file->objectType) . ' #' . $file->objectID . ']';?></a>
|
||||
<a href='<?php echo $this->createLink($file->objectType, 'view', "objectID=$file->objectID");?>' title='<?php echo substr($file->addedDate, 0, 10)?>'><?php echo $file->title . '.' . $file->extension . ' [' . strtoupper($file->objectType) . ' #' . $file->objectID . ']';?></a>
|
||||
<?php if(common::hasPriv('file', 'delete')): ?>
|
||||
<a href='<?php echo $this->createLink('file', 'delete', "fileID=$file->id"); ?>' target='hiddenwin' title='<?php echo $lang->delete?>' class='delete pull-right'><i class='icon icon-remove'></i></a>
|
||||
<?php endif?>
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
<?php include '../../common/view/action.html.php';?>
|
||||
<fieldset id='commentBox' class='hide'>
|
||||
<legend><?php echo $lang->comment;?></legend>
|
||||
<form method='post' action='<?php echo inlink('edit', "docID=$doc->id&comment=true")?>'>
|
||||
<form method='post' action='<?php echo $this->createLink('action', 'comment', "objectType=doc&objectID=$doc->id")?>' target='hiddenwin'>
|
||||
<div class="form-group"><?php echo html::textarea('comment', '',"style='width:100%;height:100px'");?></div>
|
||||
<?php echo html::submitButton() . html::backButton();?>
|
||||
</form>
|
||||
|
||||
@@ -46,6 +46,7 @@ $lang->extension->downloads = 'Downloads';
|
||||
$lang->extension->compatible = 'Compatibility';
|
||||
$lang->extension->grade = 'Score';
|
||||
$lang->extension->depends = 'Dependent';
|
||||
$lang->extension->expireDate = 'Expire';
|
||||
$lang->extension->zentaoCompatible = 'Compatible Version';
|
||||
$lang->extension->installedTime = 'Installed Time';
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ $lang->extension->downloads = '下载量';
|
||||
$lang->extension->compatible = '兼容性';
|
||||
$lang->extension->grade = '评分';
|
||||
$lang->extension->depends = '依赖';
|
||||
$lang->extension->expireDate = '到期日期';
|
||||
$lang->extension->zentaoCompatible = '适用版本';
|
||||
$lang->extension->installedTime = '安装时间';
|
||||
|
||||
|
||||
@@ -886,4 +886,35 @@ class extensionModel extends model
|
||||
if($type != 'between') return !$result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extension expire date.
|
||||
*
|
||||
* @param int $extension
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getExpireDate($extension)
|
||||
{
|
||||
$licencePath = $this->app->getConfigRoot() . 'license/';
|
||||
$today = date('Y-m-d');
|
||||
$expireDate = '';
|
||||
|
||||
$licenceOrderFile = $licencePath . 'order' . $extension->code . $extension->version . '.txt';
|
||||
if(file_exists($licenceOrderFile))
|
||||
{
|
||||
$order = file_get_contents($licenceOrderFile);
|
||||
$order = unserialize($order);
|
||||
if($order->type != 'life')
|
||||
{
|
||||
$days = isset($order->days) ? $order->days : 0;
|
||||
if($order->type == 'demo') $days = 31;
|
||||
if($order->type == 'year') $days = 365;
|
||||
$startDate = $order->paidDate != '0000-00-00 00:00:00' ? $order->paidDate : $order->createdDate;
|
||||
if($days) $expireDate = date('Y-m-d', strtotime($startDate) + $days * 24 * 3600);
|
||||
}
|
||||
}
|
||||
|
||||
return $expireDate;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
<?php
|
||||
echo "{$lang->extension->version}: <i>{$extension->version}</i> ";
|
||||
echo "{$lang->extension->author}: <i>{$extension->author}</i> ";
|
||||
$expireDate = $this->extension->getExpireDate($extension);
|
||||
if(!empty($expireDate)) echo "{$lang->extension->expireDate}: <i>{$expireDate}</i>";
|
||||
?>
|
||||
</div>
|
||||
</div></div>
|
||||
|
||||
@@ -32,7 +32,9 @@ class git extends control
|
||||
*/
|
||||
public function diff($path, $revision)
|
||||
{
|
||||
if(isset($_GET['repoUrl'])) $path = $this->get->repoUrl;
|
||||
$path = helper::safe64Decode($path);
|
||||
|
||||
$this->view->path = $path;
|
||||
$this->view->revision = $revision;
|
||||
$this->view->diff = $this->git->diff($path, $revision);
|
||||
@@ -50,7 +52,9 @@ class git extends control
|
||||
*/
|
||||
public function cat($path, $revision)
|
||||
{
|
||||
if(isset($_GET['repoUrl'])) $path = $this->get->repoUrl;
|
||||
$path = helper::safe64Decode($path);
|
||||
|
||||
$this->view->path = $path;
|
||||
$this->view->revision = $revision;
|
||||
$this->view->code = $this->git->cat($path, $revision);
|
||||
|
||||
+19
-3
@@ -643,9 +643,8 @@ class gitModel extends model
|
||||
{
|
||||
foreach($actionFiles as $file)
|
||||
{
|
||||
$param = array('url' => helper::safe64Encode($repoRoot . $file), 'revision' => $log->revision);
|
||||
$catLink = trim(html::a(helper::createLink('git', 'cat', $param, 'html'), 'view', '', "class='repolink'"));
|
||||
$diffLink = trim(html::a(helper::createLink('git', 'diff', $param, 'html'), 'diff', '', "class='repolink'"));
|
||||
$catLink = trim(html::a($this->buildURL('cat', $repoRoot . $file, $log->revision), 'view', '', "class='repolink'"));
|
||||
$diffLink = trim(html::a($this->buildURL('diff', $repoRoot . $file, $log->revision), 'diff', '', "class='repolink'"));
|
||||
$diff .= $action . " " . $file . " $catLink ";
|
||||
$diff .= $action == 'M' ? "$diffLink\n" : "\n" ;
|
||||
}
|
||||
@@ -747,4 +746,21 @@ class gitModel extends model
|
||||
{
|
||||
echo helper::now() . " $log\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Build URL.
|
||||
*
|
||||
* @param string $methodName
|
||||
* @param string $url
|
||||
* @param int $revision
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildURL($methodName, $url, $revision)
|
||||
{
|
||||
$buildedURL = helper::createLink('git', $methodName, "path=&revision=$revision", 'html');
|
||||
$buildedURL .= strpos($buildedURL, '?') === false ? '?' : '&';
|
||||
$buildedURL .= 'repoUrl=' . helper::safe64Encode($url);
|
||||
return $buildedURL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.lite.html.php';?>
|
||||
<?php $catLink = inlink('cat', 'url=' . helper::safe64Encode($path) . "&revision=$revision");?>
|
||||
<?php $catLink = $this->git->buildURL('cat', $path, $revision);?>
|
||||
<div class='box-title'><?php echo html::a($catLink, "$path@$revision");?></div>
|
||||
<div class='box-content'><xmp><?php echo $diff;?></xmp></div>
|
||||
<?php include '../../common/view/footer.lite.html.php';?>
|
||||
|
||||
@@ -1005,12 +1005,15 @@ $lang->resource->action->trash = 'trash';
|
||||
$lang->resource->action->undelete = 'undelete';
|
||||
$lang->resource->action->hideOne = 'hideOne';
|
||||
$lang->resource->action->hideAll = 'hideAll';
|
||||
$lang->resource->action->comment = 'comment';
|
||||
$lang->resource->action->editComment = 'editComment';
|
||||
|
||||
$lang->action->methodOrder[5] = 'trash';
|
||||
$lang->action->methodOrder[10] = 'undelete';
|
||||
$lang->action->methodOrder[15] = 'hideOne';
|
||||
$lang->action->methodOrder[20] = 'hideAll';
|
||||
$lang->action->methodOrder[25] = 'comment';
|
||||
$lang->action->methodOrder[30] = 'editComment';
|
||||
|
||||
$lang->resource->backup = new stdclass();
|
||||
$lang->resource->backup->index = 'index';
|
||||
|
||||
@@ -422,7 +422,6 @@ class groupModel extends model
|
||||
$action = strtolower($action);
|
||||
|
||||
if($action == 'manageview' and $group->role == 'limited') return false;
|
||||
if($action == 'edit' and $group->role == 'limited') return false;
|
||||
if($action == 'copy' and $group->role == 'limited') return false;
|
||||
|
||||
return true;
|
||||
|
||||
+22
-20
@@ -126,26 +126,28 @@ $lang->install->account = 'Admin Account';
|
||||
$lang->install->password = 'Admin Password';
|
||||
$lang->install->errorEmptyPassword = 'Password should not be blank.';
|
||||
|
||||
$lang->install->groupList['ADMIN']['name'] = 'Admin';
|
||||
$lang->install->groupList['ADMIN']['desc'] = 'System Administrator';
|
||||
$lang->install->groupList['DEV']['name'] = 'Dev';
|
||||
$lang->install->groupList['DEV']['desc'] = 'Dev Team';
|
||||
$lang->install->groupList['QA']['name'] = 'QA';
|
||||
$lang->install->groupList['QA']['desc'] = 'QA Team';
|
||||
$lang->install->groupList['PM']['name'] = 'PM';
|
||||
$lang->install->groupList['PM']['desc'] = 'for Project Manager';
|
||||
$lang->install->groupList['PO']['name'] = 'PO';
|
||||
$lang->install->groupList['PO']['desc'] = 'for Product Owner';
|
||||
$lang->install->groupList['TD']['name'] = 'Dev Manager';
|
||||
$lang->install->groupList['TD']['desc'] = 'for Dev Manager';
|
||||
$lang->install->groupList['PD']['name'] = 'PD';
|
||||
$lang->install->groupList['PD']['desc'] = 'for Product Director';
|
||||
$lang->install->groupList['QD']['name'] = 'QD';
|
||||
$lang->install->groupList['QD']['desc'] = 'for QA Director';
|
||||
$lang->install->groupList['TOP']['name'] = 'Senior';
|
||||
$lang->install->groupList['TOP']['desc'] = 'for Senior Manager';
|
||||
$lang->install->groupList['OTHERS']['name'] = 'Other';
|
||||
$lang->install->groupList['OTHERS']['desc'] = 'for Other';
|
||||
$lang->install->groupList['ADMIN']['name'] = 'Admin';
|
||||
$lang->install->groupList['ADMIN']['desc'] = 'System Administrator';
|
||||
$lang->install->groupList['DEV']['name'] = 'Dev';
|
||||
$lang->install->groupList['DEV']['desc'] = 'Dev Team';
|
||||
$lang->install->groupList['QA']['name'] = 'QA';
|
||||
$lang->install->groupList['QA']['desc'] = 'QA Team';
|
||||
$lang->install->groupList['PM']['name'] = 'PM';
|
||||
$lang->install->groupList['PM']['desc'] = 'for Project Manager';
|
||||
$lang->install->groupList['PO']['name'] = 'PO';
|
||||
$lang->install->groupList['PO']['desc'] = 'for Product Owner';
|
||||
$lang->install->groupList['TD']['name'] = 'Dev Manager';
|
||||
$lang->install->groupList['TD']['desc'] = 'for Dev Manager';
|
||||
$lang->install->groupList['PD']['name'] = 'PD';
|
||||
$lang->install->groupList['PD']['desc'] = 'for Product Director';
|
||||
$lang->install->groupList['QD']['name'] = 'QD';
|
||||
$lang->install->groupList['QD']['desc'] = 'for QA Director';
|
||||
$lang->install->groupList['TOP']['name'] = 'Senior';
|
||||
$lang->install->groupList['TOP']['desc'] = 'for Senior Manager';
|
||||
$lang->install->groupList['OTHERS']['name'] = 'Other';
|
||||
$lang->install->groupList['OTHERS']['desc'] = 'for Other';
|
||||
$lang->install->groupList['LIMITED']['name'] = 'Limited User';
|
||||
$lang->install->groupList['LIMITED']['desc'] = 'for Limited user (editing only content related to itself)';
|
||||
|
||||
$lang->install->cronList[''] = 'Monitor cron';
|
||||
$lang->install->cronList['moduleName=project&methodName=computeburn'] = 'Update Burndown Chart';
|
||||
|
||||
@@ -126,26 +126,28 @@ $lang->install->account = '管理员帐号';
|
||||
$lang->install->password = '管理员密码';
|
||||
$lang->install->errorEmptyPassword = '密码不能为空';
|
||||
|
||||
$lang->install->groupList['ADMIN']['name'] = '管理员';
|
||||
$lang->install->groupList['ADMIN']['desc'] = '系统管理员';
|
||||
$lang->install->groupList['DEV']['name'] = '研发';
|
||||
$lang->install->groupList['DEV']['desc'] = '研发人员';
|
||||
$lang->install->groupList['QA']['name'] = '测试';
|
||||
$lang->install->groupList['QA']['desc'] = '测试人员';
|
||||
$lang->install->groupList['PM']['name'] = '项目经理';
|
||||
$lang->install->groupList['PM']['desc'] = '项目经理';
|
||||
$lang->install->groupList['PO']['name'] = '产品经理';
|
||||
$lang->install->groupList['PO']['desc'] = '产品经理';
|
||||
$lang->install->groupList['TD']['name'] = '研发主管';
|
||||
$lang->install->groupList['TD']['desc'] = '研发主管';
|
||||
$lang->install->groupList['PD']['name'] = '产品主管';
|
||||
$lang->install->groupList['PD']['desc'] = '产品主管';
|
||||
$lang->install->groupList['QD']['name'] = '测试主管';
|
||||
$lang->install->groupList['QD']['desc'] = '测试主管';
|
||||
$lang->install->groupList['TOP']['name'] = '高层管理';
|
||||
$lang->install->groupList['TOP']['desc'] = '高层管理';
|
||||
$lang->install->groupList['OTHERS']['name'] = '其他';
|
||||
$lang->install->groupList['OTHERS']['desc'] = '其他';
|
||||
$lang->install->groupList['ADMIN']['name'] = '管理员';
|
||||
$lang->install->groupList['ADMIN']['desc'] = '系统管理员';
|
||||
$lang->install->groupList['DEV']['name'] = '研发';
|
||||
$lang->install->groupList['DEV']['desc'] = '研发人员';
|
||||
$lang->install->groupList['QA']['name'] = '测试';
|
||||
$lang->install->groupList['QA']['desc'] = '测试人员';
|
||||
$lang->install->groupList['PM']['name'] = '项目经理';
|
||||
$lang->install->groupList['PM']['desc'] = '项目经理';
|
||||
$lang->install->groupList['PO']['name'] = '产品经理';
|
||||
$lang->install->groupList['PO']['desc'] = '产品经理';
|
||||
$lang->install->groupList['TD']['name'] = '研发主管';
|
||||
$lang->install->groupList['TD']['desc'] = '研发主管';
|
||||
$lang->install->groupList['PD']['name'] = '产品主管';
|
||||
$lang->install->groupList['PD']['desc'] = '产品主管';
|
||||
$lang->install->groupList['QD']['name'] = '测试主管';
|
||||
$lang->install->groupList['QD']['desc'] = '测试主管';
|
||||
$lang->install->groupList['TOP']['name'] = '高层管理';
|
||||
$lang->install->groupList['TOP']['desc'] = '高层管理';
|
||||
$lang->install->groupList['OTHERS']['name'] = '其他';
|
||||
$lang->install->groupList['OTHERS']['desc'] = '其他';
|
||||
$lang->install->groupList['LIMITED']['name'] = '受限用户';
|
||||
$lang->install->groupList['LIMITED']['desc'] = '受限用户分组(只能编辑与自己相关的内容)';
|
||||
|
||||
$lang->install->cronList[''] = '监控定时任务';
|
||||
$lang->install->cronList['moduleName=project&methodName=computeburn'] = '更新燃尽图';
|
||||
|
||||
+11
-6
@@ -55,21 +55,26 @@ class mail extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function detect()
|
||||
public function detect($type = 'smtp')
|
||||
{
|
||||
if($_POST)
|
||||
if($_POST or $type == 'gmail')
|
||||
{
|
||||
set_time_limit(30);
|
||||
$error = '';
|
||||
if($this->post->fromAddress == false) $error = sprintf($this->lang->error->notempty, $this->lang->mail->fromAddress);
|
||||
if(!validater::checkEmail($this->post->fromAddress)) $error .= '\n' . sprintf($this->lang->error->email, $this->lang->mail->fromAddress);
|
||||
if($type != 'gmail')
|
||||
{
|
||||
$error = '';
|
||||
if($this->post->fromAddress == false) $error = sprintf($this->lang->error->notempty, $this->lang->mail->fromAddress);
|
||||
if(!validater::checkEmail($this->post->fromAddress)) $error .= '\n' . sprintf($this->lang->error->email, $this->lang->mail->fromAddress);
|
||||
|
||||
if($error) die(js::alert($error));
|
||||
if($error) die(js::alert($error));
|
||||
}
|
||||
if($type == 'gmail' and empty($_POST['fromAddress'])) $_POST['fromAddress'] = '@gmail.com';
|
||||
|
||||
echo "<script>setTimeout(function(){parent.location.href='" . inlink('edit') . "'}, 10000)</script>";
|
||||
$mailConfig = $this->mail->autoDetect($this->post->fromAddress);
|
||||
$mailConfig->fromAddress = $this->post->fromAddress;
|
||||
$mailConfig->domain = common::getSysURL();
|
||||
if($type == 'gmail') $mailConfig->fromAddress = '';
|
||||
$this->session->set('mailConfig', $mailConfig);
|
||||
|
||||
die(js::locate(inlink('edit'), 'parent'));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
$(document).ready()
|
||||
{
|
||||
$('#password').focus();
|
||||
$('#fromAddress').focus();
|
||||
if($('#fromAddress').val() != '')$('#password').focus();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ $lang->mail->resend = 'Resend';
|
||||
$lang->mail->browse = 'Email List';
|
||||
$lang->mail->delete = 'Delete Email';
|
||||
$lang->mail->ztCloud = 'ZenTao CloudMail';
|
||||
$lang->mail->gmail = 'GMAIL';
|
||||
$lang->mail->sendCloud = 'Notice SendCloud';
|
||||
$lang->mail->batchDelete = 'Batch Delete';
|
||||
$lang->mail->sendcloudUser = 'Sync Contact';
|
||||
|
||||
@@ -10,6 +10,7 @@ $lang->mail->resend = '重发';
|
||||
$lang->mail->browse = '邮件列表';
|
||||
$lang->mail->delete = '删除邮件';
|
||||
$lang->mail->ztCloud = '禅道云发信';
|
||||
$lang->mail->gmail = 'GMAIL发信';
|
||||
$lang->mail->sendCloud = 'Notice发信';
|
||||
$lang->mail->batchDelete = '批量删除';
|
||||
$lang->mail->sendcloudUser = '同步联系人';
|
||||
|
||||
@@ -24,6 +24,9 @@ include '../../common/view/header.html.php';
|
||||
<?php if($this->app->getClientLang() != 'en' and common::hasPriv('mail', 'ztCloud')):?>
|
||||
<?php echo html::a(inlink('ztCloud'), $lang->mail->ztCloud, '', "class='btn btn-sm w-120px'")?>
|
||||
<?php endif;?>
|
||||
<?php if($this->app->getClientLang() == 'en'):?>
|
||||
<?php echo html::a(inlink('detect', 'type=gmail'), $lang->mail->gmail, '', "class='btn btn-sm w-120px'")?>
|
||||
<?php endif;?>
|
||||
<?php if(common::hasPriv('mail', 'detect')):?>
|
||||
<?php echo html::a(inlink('detect'), $lang->mail->smtp, '', "class='btn btn-sm w-120px'")?>
|
||||
<?php endif;?>
|
||||
|
||||
+25
-6
@@ -406,18 +406,35 @@ class my extends control
|
||||
if($this->post->mode == 'new')
|
||||
{
|
||||
$listID = $this->user->createContactList($this->post->newList, $this->post->users);
|
||||
$this->user->setGlobalContacts($listID, isset($_POST['share']));
|
||||
if(isonlybody()) die(js::closeModal('parent.parent', '', 'function(){parent.parent.ajaxGetContacts(\'#mailtoGroup\')}'));
|
||||
die(js::locate(inlink('manageContacts', "listID=$listID"), 'parent'));
|
||||
}
|
||||
elseif($this->post->mode == 'edit')
|
||||
{
|
||||
$this->user->updateContactList($this->post->listID, $this->post->listName, $this->post->users);
|
||||
$this->user->setGlobalContacts($this->post->listID, isset($_POST['share']));
|
||||
die(js::locate(inlink('manageContacts', "listID={$this->post->listID}"), 'parent'));
|
||||
}
|
||||
}
|
||||
|
||||
$mode = empty($mode) ? 'edit' : $mode;
|
||||
$lists = $this->user->getContactLists($this->app->user->account);
|
||||
$mode = empty($mode) ? 'edit' : $mode;
|
||||
$lists = $this->user->getContactLists($this->app->user->account);
|
||||
|
||||
$globalContacts = isset($this->config->my->global->globalContacts) ? $this->config->my->global->globalContacts : '';
|
||||
$globalContacts = !empty($globalContacts) ? explode(',', $globalContacts) : array();
|
||||
|
||||
$myContacts = $this->user->getListByAccount($this->app->user->account);
|
||||
$disabled = $globalContacts;
|
||||
|
||||
if(!empty($myContacts) && !empty($globalContacts))
|
||||
{
|
||||
foreach($globalContacts as $id)
|
||||
{
|
||||
if(in_array($id, array_keys($myContacts))) unset($disabled[array_search($id, $disabled)]);
|
||||
}
|
||||
}
|
||||
|
||||
$listID = $listID ? $listID : key($lists);
|
||||
if(!$listID) $mode = 'new';
|
||||
|
||||
@@ -434,10 +451,12 @@ class my extends control
|
||||
$this->view->list = $this->user->getContactListByID($listID);
|
||||
}
|
||||
|
||||
$this->view->mode = $mode;
|
||||
$this->view->lists = $lists;
|
||||
$this->view->listID = $listID;
|
||||
$this->view->users = $this->user->getPairs('noletter|noempty|noclosed|noclosed');
|
||||
$this->view->mode = $mode;
|
||||
$this->view->lists = $lists;
|
||||
$this->view->listID = $listID;
|
||||
$this->view->users = $this->user->getPairs('noletter|noempty|noclosed|noclosed');
|
||||
$this->view->disabled = $disabled;
|
||||
$this->view->globalContacts = $globalContacts;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
body.body-modal {padding-bottom: 20px; min-height: 400px}
|
||||
|
||||
.list-group-item.active {color: #1A4F85}
|
||||
|
||||
@@ -17,6 +17,7 @@ $lang->my->changePassword = 'Edit Password';
|
||||
$lang->my->unbind = 'Unbind Ranger';
|
||||
$lang->my->manageContacts = 'Maintain Contact';
|
||||
$lang->my->deleteContacts = 'Delete Contact';
|
||||
$lang->my->shareContacts = 'Share List';
|
||||
$lang->my->limited = 'Restricted operation (editing only content related to itself)';
|
||||
$lang->my->score = 'My Score';
|
||||
$lang->my->scoreRule = 'Score Rule';
|
||||
|
||||
@@ -17,6 +17,7 @@ $lang->my->changePassword = '修改密码';
|
||||
$lang->my->unbind = '解除然之绑定';
|
||||
$lang->my->manageContacts = '维护联系人';
|
||||
$lang->my->deleteContacts = '删除联系人';
|
||||
$lang->my->shareContacts = '共享联系人列表';
|
||||
$lang->my->limited = '受限操作(只能编辑与自己相关的内容)';
|
||||
$lang->my->score = '我的积分';
|
||||
$lang->my->scoreRule = '积分规则';
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
foreach($lists as $id => $listName)
|
||||
{
|
||||
$listClass = ($id == $listID) ? 'list-group-item active' : 'list-group-item';
|
||||
echo html::a(inlink('managecontacts', "listID=$id&mode=edit"), $listName, '', "class='{$listClass}'");
|
||||
$shareIcon = in_array($id, $globalContacts) ? '<i class="icon icon-share-sign"></i> ' : '';
|
||||
echo html::a(inlink('managecontacts', "listID=$id&mode=edit"), $shareIcon . $listName, '', "class='{$listClass}'");
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
@@ -44,13 +45,14 @@
|
||||
<td class='w-300px'>
|
||||
<div class='required required-wrapper'></div>
|
||||
<?php
|
||||
if($mode == 'edit') $readonly = in_array($list->id, $disabled) ? ' readonly' : '';
|
||||
if($mode == 'new')
|
||||
{
|
||||
echo html::input('newList', '', "class='form-control'");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::input('listName', $list->listName, "class='form-control'");
|
||||
echo html::input('listName', $list->listName, "$readonly class='form-control'");
|
||||
echo html::hidden('listID', $list->id);
|
||||
}
|
||||
?>
|
||||
@@ -67,11 +69,22 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::select('users[]', $users, $list->userList, "multiple class='form-control chosen'");
|
||||
echo html::select('users[]', $users, $list->userList, "multiple $readonly class='form-control chosen'");
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php if(common::hasPriv('datatable', 'setGlobal')):?>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td colspan="2">
|
||||
<label class="checkbox-inline">
|
||||
<input type="checkbox" name="share" value="1" <?php if($mode != 'new' && in_array($list->id, $globalContacts)) echo 'checked';?>/> <?php echo $lang->my->shareContacts;?>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php if($mode == 'new' || !in_array($list->id, $disabled)):?>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
@@ -79,6 +92,7 @@
|
||||
<?php if($mode == 'edit') echo html::a(inlink('deleteContacts', "listID=$listID"), $lang->delete, 'hiddenwin', "class='btn btn-danger'");?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,8 +25,49 @@ $(function()
|
||||
setTimeout(function(){fixedTheadOfList('#storyList')}, 100);
|
||||
|
||||
if($('#storyList thead th.w-title').width() < 150) $('#storyList thead th.w-title').width(150);
|
||||
|
||||
$(document).on('click', "#storyList tbody tr", function(){showCheckedSummary();});
|
||||
$(document).on('change', "#storyList :checkbox", function(){showCheckedSummary();});
|
||||
$(document).on('click', "#datatable-storyList table tr", function(){showCheckedSummary();});
|
||||
})
|
||||
|
||||
function showCheckedSummary()
|
||||
{
|
||||
var $summary = $('tfoot .table-actions .text:last');
|
||||
if(!$summary.hasClass('readed'))
|
||||
{
|
||||
taskSummary = $summary.html();
|
||||
$summary.addClass('readed');
|
||||
}
|
||||
|
||||
var checkedTotal = 0;
|
||||
var checkedEstimate = 0;
|
||||
var checkedCase = 0;
|
||||
$('[name^="storyIDList"]').each(function()
|
||||
{
|
||||
if($(this).prop('checked'))
|
||||
{
|
||||
checkedTotal += 1;
|
||||
var taskID = $(this).val();
|
||||
$tr = $("#storyList tbody tr[data-id='" + taskID + "']");
|
||||
checkedEstimate += Number($tr.data('estimate'));
|
||||
if(Number($tr.data('cases')) > 0) checkedCase += 1;
|
||||
}
|
||||
});
|
||||
if(checkedTotal > 0)
|
||||
{
|
||||
rate = Math.round(checkedCase / checkedTotal * 10000) / 100 + '' + '%';
|
||||
summary = checkedSummary.replace('%total%', checkedTotal)
|
||||
.replace('%estimate%', checkedEstimate)
|
||||
.replace('%rate%', rate)
|
||||
$('tfoot .table-actions .text:last').html(summary);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('tfoot .table-actions .text:last').html(taskSummary);
|
||||
}
|
||||
}
|
||||
|
||||
function setQueryBar(queryID, title)
|
||||
{
|
||||
$('#bysearchTab').before("<li id='QUERY" + queryID + "Tab' class='active'><a href='" + createLink('product', 'browse', "productID=" + productID + "&branch=" + branch + "&browseType=bysearch¶m=" + queryID) + "'>" + title + "</a></li>");
|
||||
|
||||
@@ -109,8 +109,9 @@ $lang->product->aclList['open'] = "Default (User with {$lang->productCommon}
|
||||
$lang->product->aclList['private'] = "Private {$lang->productCommon} ({$lang->projectCommon} team members only)";
|
||||
$lang->product->aclList['custom'] = 'Custom (Team members and Whitelist members have access to it.)';
|
||||
|
||||
$lang->product->storySummary = " <strong>%s</strong> Story(ies), <strong>%s</strong> hour(s) estimated, case coverage is <strong>%s</strong> on this page.";
|
||||
$lang->product->noMatched = '"%s" cannot be found.' . $lang->productCommon;
|
||||
$lang->product->storySummary = " <strong>%s</strong> Story(ies), <strong>%s</strong> hour(s) estimated, case coverage is <strong>%s</strong> on this page.";
|
||||
$lang->product->checkedSummary = " <strong>%total%</strong> Checked, <strong>%estimate%</strong> hour(s) estimated, case coverage is <strong>%rate%</strong>.";
|
||||
$lang->product->noMatched = '"%s" cannot be found.' . $lang->productCommon;
|
||||
|
||||
$lang->product->mySelects['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->mySelects['openedbyme'] = $lang->product->openedByMe;
|
||||
|
||||
@@ -16,7 +16,7 @@ $lang->product->dynamic = "动态";
|
||||
$lang->product->view = "{$lang->productCommon}概况";
|
||||
$lang->product->edit = "编辑{$lang->productCommon}";
|
||||
$lang->product->batchEdit = "批量编辑";
|
||||
$lang->product->create = "新增{$lang->productCommon}";
|
||||
$lang->product->create = "添加{$lang->productCommon}";
|
||||
$lang->product->delete = "删除{$lang->productCommon}";
|
||||
$lang->product->deleted = "已删除";
|
||||
$lang->product->close = "关闭";
|
||||
@@ -108,8 +108,9 @@ $lang->product->aclList['open'] = "默认设置(有{$lang->productCommon}视
|
||||
$lang->product->aclList['private'] = "私有{$lang->productCommon}(只有{$lang->productCommon}相关负责人和{$lang->projectCommon}团队成员才能访问)";
|
||||
$lang->product->aclList['custom'] = '自定义白名单(团队成员和白名单的成员可以访问)';
|
||||
|
||||
$lang->product->storySummary = "本页共 <strong>%s</strong> 个需求,预计 <strong>%s</strong> 个工时,用例覆盖率<strong>%s</strong>。";
|
||||
$lang->product->noMatched = '找不到包含"%s"的' . $lang->productCommon;
|
||||
$lang->product->storySummary = "本页共 <strong>%s</strong> 个需求,预计 <strong>%s</strong> 个工时,用例覆盖率<strong>%s</strong>。";
|
||||
$lang->product->checkedSummary = "选中 <strong>%total%</strong> 个需求,预计 <strong>%estimate%</strong> 个工时,用例覆盖率<strong>%rate%</strong>。";
|
||||
$lang->product->noMatched = '找不到包含"%s"的' . $lang->productCommon;
|
||||
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['unplan'] = $lang->product->unplan;
|
||||
|
||||
+61
-55
@@ -14,11 +14,16 @@
|
||||
class productModel extends model
|
||||
{
|
||||
/**
|
||||
* Set menu.
|
||||
*
|
||||
* @param array $products
|
||||
* @param int $productID
|
||||
* @param string $extra
|
||||
*
|
||||
* Set menu.
|
||||
*
|
||||
* @param array $products
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param int $module
|
||||
* @param string $moduleType
|
||||
* @param string $extra
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -53,13 +58,14 @@ class productModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the select code of products.
|
||||
*
|
||||
* @param array $products
|
||||
* @param int $productID
|
||||
* @param string $currentModule
|
||||
* @param string $currentMethod
|
||||
* @param string $extra
|
||||
* Create the select code of products.
|
||||
*
|
||||
* @param array $products
|
||||
* @param int $productID
|
||||
* @param string $currentModule
|
||||
* @param string $currentMethod
|
||||
* @param string $extra
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
@@ -115,8 +121,8 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Save the product id user last visited to session.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @param array $products
|
||||
* @access public
|
||||
* @return int
|
||||
@@ -148,8 +154,8 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Check privilege.
|
||||
*
|
||||
* @param int $product
|
||||
*
|
||||
* @param int $product
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
@@ -157,7 +163,7 @@ class productModel extends model
|
||||
{
|
||||
/* Is admin? */
|
||||
$account = ',' . $this->app->user->account . ',';
|
||||
if($this->app->user->admin) return true;
|
||||
if($this->app->user->admin) return true;
|
||||
|
||||
$acls = $this->app->user->rights['acls'];
|
||||
if(!empty($acls['products']) and !in_array($product->id, $acls['products'])) return false;
|
||||
@@ -172,8 +178,8 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Get product by id.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
@@ -188,8 +194,8 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Get by idList.
|
||||
*
|
||||
* @param array $productIDList
|
||||
*
|
||||
* @param array $productIDList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -200,9 +206,9 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Get products.
|
||||
*
|
||||
* @param string $status
|
||||
* @param int $limit
|
||||
*
|
||||
* @param string $status
|
||||
* @param int $limit
|
||||
* @param int $line
|
||||
* @access public
|
||||
* @return array
|
||||
@@ -227,9 +233,9 @@ class productModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product pairs.
|
||||
*
|
||||
* @param string $mode
|
||||
* Get product pairs.
|
||||
*
|
||||
* @param string $mode
|
||||
* @return array
|
||||
*/
|
||||
public function getPairs($mode = '')
|
||||
@@ -273,7 +279,7 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Get grouped products.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -284,7 +290,7 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Create a product.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
@@ -325,8 +331,8 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Update a product.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -358,7 +364,7 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Batch update products.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -399,10 +405,10 @@ class productModel extends model
|
||||
$this->fixOrder();
|
||||
return $allChanges;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close product.
|
||||
*
|
||||
*
|
||||
* @param int $productID.
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -520,8 +526,8 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Get projects of a product in pairs.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $param all|nodeleted
|
||||
* @access public
|
||||
* @return array
|
||||
@@ -549,8 +555,8 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Get roadmap of a proejct
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -585,8 +591,8 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Get team members of a product from projects.
|
||||
*
|
||||
* @param object $product
|
||||
*
|
||||
* @param object $product
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -624,9 +630,9 @@ class productModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product stat by id
|
||||
*
|
||||
* @param int $productID
|
||||
* Get product stat by id
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return object|bool
|
||||
*/
|
||||
@@ -737,7 +743,7 @@ class productModel extends model
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('product')->in(array_keys($products))
|
||||
->groupBy('product')
|
||||
->fetchPairs();
|
||||
->fetchPairs();
|
||||
$unResolved = $this->dao->select('product,count(*) AS count')
|
||||
->from(TABLE_BUG)
|
||||
->where('status')->eq('active')
|
||||
@@ -803,8 +809,8 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Get the summary of product's stories.
|
||||
*
|
||||
* @param array $stories
|
||||
*
|
||||
* @param array $stories
|
||||
* @access public
|
||||
* @return string.
|
||||
*/
|
||||
@@ -834,9 +840,9 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Judge an action is clickable or not.
|
||||
*
|
||||
* @param object $product
|
||||
* @param string $action
|
||||
*
|
||||
* @param object $product
|
||||
* @param string $action
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -851,10 +857,10 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Create the link from module,method,extra
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @param mix $extra
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @param mix $extra
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -903,7 +909,7 @@ class productModel extends model
|
||||
|
||||
/**
|
||||
* Fix order.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -925,7 +931,7 @@ class productModel extends model
|
||||
* get the latest project of the product.
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getLatestProject($productID)
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($stories as $story):?>
|
||||
<tr class='text-center' data-id='<?php echo $story->id?>'>
|
||||
<tr class='text-center' data-id='<?php echo $story->id?>' data-estimate='<?php echo $story->estimate?>' data-cases='<?php echo zget($storyCases, $story->id, 0);?>'>
|
||||
<?php foreach($setting as $key => $value) $this->story->printCell($value, $story, $users, $branches, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table');?>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
@@ -323,6 +323,7 @@
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<?php js::set('checkedSummary', $lang->product->checkedSummary);?>
|
||||
<script language='javascript'>
|
||||
var moduleID = <?php echo $moduleID?>;
|
||||
$('#module<?php echo $moduleID;?>').addClass('active');
|
||||
|
||||
+101
-37
@@ -13,8 +13,10 @@ class productplan extends control
|
||||
{
|
||||
/**
|
||||
* Common actions
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -33,8 +35,10 @@ class productplan extends control
|
||||
|
||||
/**
|
||||
* Create a plan.
|
||||
*
|
||||
* @param int $product
|
||||
*
|
||||
* @param string $product
|
||||
* @param int $branch
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -70,8 +74,9 @@ class productplan extends control
|
||||
|
||||
/**
|
||||
* Edit a plan.
|
||||
*
|
||||
* @param int $planID
|
||||
*
|
||||
* @param int $planID
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -99,8 +104,10 @@ class productplan extends control
|
||||
|
||||
/**
|
||||
* Batch edit plan.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -130,11 +137,11 @@ class productplan extends control
|
||||
}
|
||||
die(js::locate('back'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete a plan.
|
||||
*
|
||||
* @param int $planID
|
||||
*
|
||||
* @param int $planID
|
||||
* @param string $confirm yes|no
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -171,11 +178,12 @@ class productplan extends control
|
||||
|
||||
/**
|
||||
* Browse plans.
|
||||
*
|
||||
* @param int $product
|
||||
* @param string $orderBy
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param string $orderBy
|
||||
* @param string $browseType
|
||||
* @param int $recTotal
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
@@ -209,6 +217,9 @@ class productplan extends control
|
||||
* @param int $planID
|
||||
* @param string $type
|
||||
* @param string $orderBy
|
||||
* @param string $link
|
||||
* @param string $param
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -217,13 +228,39 @@ class productplan extends control
|
||||
$this->session->set('storyList', $this->app->getURI(true) . '&type=' . 'story');
|
||||
$this->session->set('bugList', $this->app->getURI(true) . '&type=' . 'bug');
|
||||
|
||||
$reSort = false;
|
||||
if($type == 'story' && strpos($orderBy, 'order') !== false)
|
||||
{
|
||||
$orderBy = str_replace('order', 'id', $orderBy);
|
||||
$reSort = true;
|
||||
}
|
||||
|
||||
/* Append id for secend sort. */
|
||||
$sort = $this->loadModel('common')->appendOrder($orderBy);
|
||||
|
||||
$plan = $this->productplan->getByID($planID, true);
|
||||
if(!$plan) die(js::error($this->lang->notFound) . js::locate('back'));
|
||||
$this->commonAction($plan->product, $plan->branch);
|
||||
$products = $this->product->getPairs();
|
||||
$products = $this->product->getPairs();
|
||||
|
||||
$planStories = $this->loadModel('story')->getPlanStories($planID, 'all', $type == 'story' ? $sort : 'id_desc');
|
||||
if($reSort)
|
||||
{
|
||||
if(!empty($plan->order))
|
||||
{
|
||||
$stories = array();
|
||||
$order = explode(',', $plan->order);
|
||||
if(strpos($orderBy, 'asc') !== false) $order = array_reverse($order, true);
|
||||
foreach($order as $id)
|
||||
{
|
||||
if(empty($id)) continue;
|
||||
$stories[$id] = $planStories[$id];
|
||||
}
|
||||
$planStories = $stories;
|
||||
unset($stories);
|
||||
}
|
||||
$orderBy = str_replace('id', 'order', $orderBy);
|
||||
}
|
||||
|
||||
$this->loadModel('datatable');
|
||||
$showModule = !empty($this->config->datatable->productBrowse->showModule) ? $this->config->datatable->productBrowse->showModule : '';
|
||||
@@ -231,7 +268,7 @@ class productplan extends control
|
||||
|
||||
$this->view->title = "PLAN #$plan->id $plan->title/" . $products[$plan->product];
|
||||
$this->view->position[] = $this->lang->productplan->view;
|
||||
$this->view->planStories = $this->loadModel('story')->getPlanStories($planID, 'all', $type == 'story' ? $sort : 'id_desc');
|
||||
$this->view->planStories = $planStories;
|
||||
$this->view->planBugs = $this->loadModel('bug')->getPlanBugs($planID, 'all', $type == 'bug' ? $sort : 'id_desc');
|
||||
$this->view->products = $products;
|
||||
$this->view->summary = $this->product->summary($this->view->planStories);
|
||||
@@ -248,10 +285,12 @@ class productplan extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax: Get product plans.
|
||||
*
|
||||
* @param int $productID
|
||||
* Ajax: Get product plans.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param string $number
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -264,10 +303,28 @@ class productplan extends control
|
||||
die(html::select($planName, $plans, '', "class='form-control'"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort story for productplan.
|
||||
*
|
||||
* @param int $planID
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function ajaxStorySort($planID = 0)
|
||||
{
|
||||
if(empty($planID)) return true;
|
||||
$this->dao->update(TABLE_PRODUCTPLAN)->set('`order`')->eq($this->post->storys)->where('id')->eq((int)$planID)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Link stories.
|
||||
*
|
||||
* @param int $planID
|
||||
* @param int $planID
|
||||
* @param string $browseType
|
||||
* @param int $param
|
||||
* @param string $orderBy
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -340,9 +397,10 @@ class productplan extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink story
|
||||
*
|
||||
* @param int $storyID
|
||||
* Unlink story
|
||||
*
|
||||
* @param int $storyID
|
||||
* @param int $planID
|
||||
* @param string $confirm yes|no
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -377,9 +435,11 @@ class productplan extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch unlink story.
|
||||
*
|
||||
* @param string $confirm
|
||||
* Batch unlink story.
|
||||
*
|
||||
* @param int $planID
|
||||
* @param string $orderBy
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -391,10 +451,12 @@ class productplan extends control
|
||||
|
||||
/**
|
||||
* Link bugs.
|
||||
*
|
||||
* @param int $planID
|
||||
* @param string $browseType
|
||||
* @param int $param
|
||||
*
|
||||
* @param int $planID
|
||||
* @param string $browseType
|
||||
* @param int $param
|
||||
* @param string $orderBy
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -469,9 +531,9 @@ class productplan extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink story
|
||||
*
|
||||
* @param int $bugID
|
||||
* Unlink story
|
||||
*
|
||||
* @param int $bugID
|
||||
* @param string $confirm yes|no
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -506,9 +568,11 @@ class productplan extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch unlink story.
|
||||
*
|
||||
* @param string $confirm
|
||||
* Batch unlink story.
|
||||
*
|
||||
* @param $planID
|
||||
* @param string $orderBy
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
|
||||
@@ -40,4 +40,9 @@ $('#begin').on('change', function()
|
||||
{
|
||||
$("#end").val('');
|
||||
$("input:radio[name='delta']").attr("checked",false);
|
||||
});
|
||||
});
|
||||
|
||||
$('#end').on('change', function()
|
||||
{
|
||||
$("input:radio[name='delta']").attr("checked", false);
|
||||
});
|
||||
|
||||
@@ -41,4 +41,19 @@ $(function()
|
||||
$option.toggleClass('hide', $option.text().toString().toLowerCase().indexOf(val) < 0 && $option.data('key').toString().toLowerCase().indexOf(val) < 0);
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
$('#storyList').on('sort.sortable', function(e, data)
|
||||
{
|
||||
var list = '';
|
||||
for(i = 0; i < data.list.length; i++) list += $(data.list[i]).attr('data-id') + ',';
|
||||
console.log(list);
|
||||
$.post(createLink('productplan', 'ajaxStorySort', 'planID=' + planID), {'storys' : list, 'orderBy' : orderBy}, function()
|
||||
{
|
||||
var $target = $(data.element[0]);
|
||||
$target.hide();
|
||||
$target.fadeIn(1000);
|
||||
order = 'order_asc';
|
||||
history.pushState({}, 0, createLink('productplan', 'view', "planID=" + planID + '&type=story&orderBy=' + order));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,6 +26,7 @@ $lang->productplan->unlinkStory = "Unlink Story";
|
||||
$lang->productplan->batchUnlinkStory = "Batch Unlink";
|
||||
$lang->productplan->linkedStories = 'link Story';
|
||||
$lang->productplan->unlinkedStories = 'UnLinkEd';
|
||||
$lang->productplan->updateOrder = 'Ranking';
|
||||
|
||||
$lang->productplan->linkBug = "Link Bug";
|
||||
$lang->productplan->unlinkBug = "Unlink Bug";
|
||||
|
||||
@@ -26,6 +26,7 @@ $lang->productplan->unlinkStory = "移除需求";
|
||||
$lang->productplan->batchUnlinkStory = "批量移除需求";
|
||||
$lang->productplan->linkedStories = '需求';
|
||||
$lang->productplan->unlinkedStories = '未关联需求';
|
||||
$lang->productplan->updateOrder = '排序';
|
||||
|
||||
$lang->productplan->linkBug = "关联Bug";
|
||||
$lang->productplan->unlinkBug = "移除Bug";
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/sortable.html.php';?>
|
||||
<?php js::set('confirmUnlinkStory', $lang->productplan->confirmUnlinkStory)?>
|
||||
<?php js::set('confirmUnlinkBug', $lang->productplan->confirmUnlinkBug)?>
|
||||
<?php js::set('planID', $plan->id);?>
|
||||
<div id='titlebar'>
|
||||
<div class='heading'>
|
||||
<span class='prefix'><?php echo html::icon($lang->icons['plan']);?> <strong><?php echo $plan->id;?></strong></span>
|
||||
@@ -30,9 +32,23 @@
|
||||
{
|
||||
ob_start();
|
||||
echo "<div class='btn-group'>";
|
||||
echo "<div class='btn-group' id='createActionMenu'>";
|
||||
common::printIcon('story', 'create', "productID=$plan->product&branch=$plan->branch&moduleID=0&storyID=0&projectID=0&bugID=0&planID=$plan->id", $plan, 'button', 'plus');
|
||||
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> ' . $lang->productplan->linkStory, '', "class='btn'");
|
||||
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> ' . $lang->productplan->linkBug, '', "class='btn'");
|
||||
$batchMisc = common::hasPriv('story', 'batchCreate') ? '' : "disabled";
|
||||
$batchLink = common::hasPriv('story', 'batchCreate') ? $this->createLink('story', 'batchCreate', "productID=$plan->product&branch=$plan->branch&moduleID=0&story=0&project=0&plan={$plan->id}") : '#';
|
||||
echo "<button type='button' class='btn dropdown-toggle {$batchMisc}' data-toggle='dropdown'><span class='caret'></span></button>";
|
||||
echo "<ul class='dropdown-menu pull-right'>";
|
||||
echo "<li>" . html::a($batchLink, $lang->story->batchCreate, '', "class='$batchMisc'") . "</li>";
|
||||
echo '</ul>';
|
||||
echo '</div>';
|
||||
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> ' . $lang->productplan->linkStory, '', "class='btn'");
|
||||
}
|
||||
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> ' . $lang->productplan->linkBug, '', "class='btn'");
|
||||
}
|
||||
echo '</div>';
|
||||
echo "<div class='btn-group'>";
|
||||
common::printIcon('productplan', 'edit', "planID=$plan->id", $plan);
|
||||
@@ -60,6 +76,7 @@
|
||||
<div class='tab-content'>
|
||||
<div id='stories' class='tab-pane <?php if($type == 'story') echo 'active'?>'>
|
||||
<?php if(common::hasPriv('productplan', 'linkStory')):?>
|
||||
<?php $canOrder = common::hasPriv('project', 'storySort');?>
|
||||
<div class='action'>
|
||||
<?php echo html::a("javascript:showLink($plan->id, \"story\")", '<i class="icon-link"></i> ' . $lang->productplan->linkStory, '', "class='btn btn-sm btn-primary'");?>
|
||||
</div>
|
||||
@@ -70,21 +87,24 @@
|
||||
<?php $vars = "planID={$plan->id}&type=story&orderBy=%s&link=$link¶m=$param"; ?>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='w-id {sorter:false}' > <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
|
||||
<th class='w-pri {sorter:false}'> <?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
|
||||
<?php if($modulePairs):?>
|
||||
<th class='w-150px text-left {sorter:false}'> <?php common::printOrderLink('module', $orderBy, $vars, $lang->story->module);?></th>
|
||||
<th class='w-id {sorter:false}' > <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
|
||||
<?php if($canOrder):?>
|
||||
<th class='w-50px {sorter:false}'><?php common::printOrderLink('order', $orderBy, $vars, $lang->productplan->updateOrder);?></th>
|
||||
<?php endif;?>
|
||||
<th class='text-left {sorter:false}'> <?php common::printOrderLink('title', $orderBy, $vars, $lang->story->title);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('assignedTo', $orderBy, $vars, $lang->assignedToAB);?></th>
|
||||
<th class='w-60px {sorter:false}'> <?php common::printOrderLink('estimate', $orderBy, $vars, $lang->story->estimateAB);?></th>
|
||||
<th class='w-status {sorter:false}'><?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
|
||||
<th class='w-80px {sorter:false}'> <?php common::printOrderLink('stage', $orderBy, $vars, $lang->story->stageAB);?></th>
|
||||
<th class='w-50px {sorter:false}'> <?php echo $lang->actions?></th>
|
||||
<th class='w-pri {sorter:false}'> <?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
|
||||
<?php if($modulePairs):?>
|
||||
<th class='w-150px text-left {sorter:false}'><?php common::printOrderLink('module', $orderBy, $vars, $lang->story->module);?></th>
|
||||
<?php endif;?>
|
||||
<th class='text-left {sorter:false}'><?php common::printOrderLink('title', $orderBy, $vars, $lang->story->title);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('assignedTo', $orderBy, $vars, $lang->assignedToAB);?></th>
|
||||
<th class='w-60px {sorter:false}'> <?php common::printOrderLink('estimate', $orderBy, $vars, $lang->story->estimateAB);?></th>
|
||||
<th class='w-status {sorter:false}'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
|
||||
<th class='w-80px {sorter:false}'> <?php common::printOrderLink('stage', $orderBy, $vars, $lang->story->stageAB);?></th>
|
||||
<th class='w-50px {sorter:false}'> <?php echo $lang->actions?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tbody class='sortable'>
|
||||
<?php
|
||||
$totalEstimate = 0.0;
|
||||
$canBatchUnlink = common::hasPriv('productPlan', 'batchUnlinkStory');
|
||||
@@ -95,17 +115,16 @@
|
||||
$viewLink = $this->createLink('story', 'view', "storyID=$story->id");
|
||||
$totalEstimate += $story->estimate;
|
||||
?>
|
||||
<tr class='text-center'>
|
||||
<tr class='text-center' data-id='<?php echo $story->id;?>'>
|
||||
<td class='cell-id'>
|
||||
<?php if($canBatchUnlink or $canBatchChangePlan):?>
|
||||
<input type='checkbox' name='storyIDList[]' value='<?php echo $story->id;?>'/>
|
||||
<input type='checkbox' name='storyIDList[]' value='<?php echo $story->id;?>'/>
|
||||
<?php endif;?>
|
||||
<?php echo html::a($viewLink, sprintf("%03d", $story->id));?>
|
||||
</td>
|
||||
<?php if($canOrder):?><td class='sort-handler'><i class='icon-move'></i></td><?php endif;?>
|
||||
<td><span class='<?php echo 'pri' . zget($lang->story->priList, $story->pri, $story->pri)?>'><?php echo zget($lang->story->priList, $story->pri, $story->pri);?></span></td>
|
||||
<?php if($modulePairs):?>
|
||||
<td class='text-left nobr'><?php if(!empty($story->module)) echo $modulePairs[$story->module];?></td>
|
||||
<?php endif;?>
|
||||
<?php if($modulePairs):?><td class='text-left nobr'><?php if(!empty($story->module)) echo $modulePairs[$story->module];?></td><?php endif;?>
|
||||
<td class='text-left nobr' title='<?php echo $story->title?>'><?php echo html::a($viewLink , $story->title);?></td>
|
||||
<td><?php echo zget($users, $story->openedBy);?></td>
|
||||
<td><?php echo zget($users, $story->assignedTo);?></td>
|
||||
@@ -126,7 +145,7 @@
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan='9'>
|
||||
<td colspan='<?php echo $canOrder ? 11 : 10;?>'>
|
||||
<div class='table-actions clearfix'>
|
||||
<?php if(count($planStories)):?>
|
||||
<?php echo html::selectButton();?>
|
||||
@@ -332,7 +351,7 @@
|
||||
<tr class='text-center'>
|
||||
<td class='cell-id'>
|
||||
<?php if($canBatchUnlink):?>
|
||||
<input type='checkbox' name='unlinkBugs[]' value='<?php echo $bug->id;?>'/>
|
||||
<input type='checkbox' name='unlinkBugs[]' value='<?php echo $bug->id;?>'/>
|
||||
<?php endif;?>
|
||||
<?php echo html::a($this->createLink('bug', 'view', "bugID=$bug->id"), sprintf("%03d", $bug->id));?>
|
||||
</td>
|
||||
@@ -357,7 +376,7 @@
|
||||
<tr>
|
||||
<td colspan='7'>
|
||||
<div class='table-actions clearfix'>
|
||||
<?php
|
||||
<?php
|
||||
if(count($planBugs) and $canBatchUnlink)
|
||||
{
|
||||
echo html::selectButton();
|
||||
|
||||
@@ -857,6 +857,9 @@ class project extends control
|
||||
/**
|
||||
* Create a project.
|
||||
*
|
||||
* @param string $projectID
|
||||
* @param string $copyProjectID
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1305,8 +1308,8 @@ class project extends control
|
||||
public function tree($projectID, $type = '')
|
||||
{
|
||||
$this->project->setMenu($this->projects, $projectID);
|
||||
$project = $this->loadModel('project')->getById($projectID);
|
||||
$tree = $this->project->getProjectTree($projectID);
|
||||
$project = $this->loadModel('project')->getById($projectID);
|
||||
$tree = $this->project->getProjectTree($projectID);
|
||||
|
||||
/* Save to session. */
|
||||
$uri = $this->app->getURI(true);
|
||||
@@ -1946,6 +1949,7 @@ class project extends control
|
||||
*/
|
||||
public function tips($projectID)
|
||||
{
|
||||
$this->view->project = $this->project->getById($projectID);
|
||||
$this->view->projectID = $projectID;
|
||||
$this->display('project', 'tips');
|
||||
}
|
||||
|
||||
@@ -163,12 +163,15 @@ function loadBranch(){}
|
||||
/* Auto compute the work days. */
|
||||
$(function()
|
||||
{
|
||||
if(typeof(replaceID) != 'undefined') setModal4List('iframe', replaceID, function($list)
|
||||
if(typeof(replaceID) != 'undefined')
|
||||
{
|
||||
$list.find('.progress-pie:visible').progressPie();
|
||||
var datatable = $list.data('zui.datatable');
|
||||
if(datatable) datatable.$datatable.find('.progress-pie:visible').progressPie();
|
||||
});
|
||||
setModal4List('iframe', replaceID, function($list)
|
||||
{
|
||||
$list.find('.progress-pie:visible').progressPie();
|
||||
var datatable = $list.data('zui.datatable');
|
||||
if(datatable) datatable.$datatable.find('.progress-pie:visible').progressPie();
|
||||
});
|
||||
}
|
||||
$(".date").bind('dateSelected', function()
|
||||
{
|
||||
computeWorkDays(this.id);
|
||||
|
||||
@@ -19,6 +19,10 @@ $(function()
|
||||
$("#days").val('');
|
||||
$("input:radio[name='delta']").attr("checked",false);
|
||||
});
|
||||
$('#end').on('change', function()
|
||||
{
|
||||
$("input:radio[name='delta']").attr("checked", false);
|
||||
})
|
||||
});
|
||||
|
||||
function showTypeTips()
|
||||
|
||||
@@ -21,4 +21,43 @@ $(function()
|
||||
|
||||
$('#module' + moduleID).addClass('active');
|
||||
$('#product' + productID).addClass('active');
|
||||
$(document).on('click', "#storyList tbody tr", function(){showCheckedSummary();});
|
||||
$(document).on('change', "#storyList :checkbox", function(){showCheckedSummary();});
|
||||
});
|
||||
|
||||
function showCheckedSummary()
|
||||
{
|
||||
var $summary = $('tfoot .table-actions .text:last');
|
||||
if(!$summary.hasClass('readed'))
|
||||
{
|
||||
taskSummary = $summary.html();
|
||||
$summary.addClass('readed');
|
||||
}
|
||||
|
||||
var checkedTotal = 0;
|
||||
var checkedEstimate = 0;
|
||||
var checkedCase = 0;
|
||||
$('[name^="storyIDList"]').each(function()
|
||||
{
|
||||
if($(this).prop('checked'))
|
||||
{
|
||||
checkedTotal += 1;
|
||||
var taskID = $(this).val();
|
||||
$tr = $("#storyList tbody tr[data-id='" + taskID + "']");
|
||||
checkedEstimate += Number($tr.data('estimate'));
|
||||
if(Number($tr.data('cases')) > 0) checkedCase += 1;
|
||||
}
|
||||
});
|
||||
if(checkedTotal > 0)
|
||||
{
|
||||
rate = Math.round(checkedCase / checkedTotal * 10000) / 100 + '' + '%';
|
||||
summary = checkedSummary.replace('%total%', checkedTotal)
|
||||
.replace('%estimate%', checkedEstimate)
|
||||
.replace('%rate%', rate)
|
||||
$('tfoot .table-actions .text:last').html(summary);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('tfoot .table-actions .text:last').html(taskSummary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,10 @@ $(function()
|
||||
});
|
||||
|
||||
if($('#taskList thead th.w-name').width() < 150) $('#taskList thead th.w-name').width(150);
|
||||
|
||||
$(document).on('click', "#taskList tbody tr", function(){showCheckedSummary();});
|
||||
$(document).on('change', "#taskList :checkbox", function(){showCheckedSummary();});
|
||||
$(document).on('click', "#datatable-taskList table tr", function(){showCheckedSummary();});
|
||||
});
|
||||
|
||||
function setQueryBar(queryID, title)
|
||||
@@ -30,5 +34,49 @@ function setQueryBar(queryID, title)
|
||||
$tagTab.before("<li id='QUERY" + queryID + "Tab' class='active'><a href='" + createLink('project', 'task', "projectID=" + projectID + "&browseType=bysearch¶m=" + queryID) + "'>" + title + "</a></li>");
|
||||
}
|
||||
|
||||
function showCheckedSummary()
|
||||
{
|
||||
var $summary = $('tfoot .table-actions .text:last');
|
||||
if(!$summary.hasClass('readed'))
|
||||
{
|
||||
taskSummary = $summary.html();
|
||||
$summary.addClass('readed');
|
||||
}
|
||||
|
||||
var checkedTotal = 0;
|
||||
var checkedWait = 0;
|
||||
var checkedDoing = 0;
|
||||
var checkedEstimate = 0;
|
||||
var checkedConsumed = 0;
|
||||
var checkedLeft = 0;
|
||||
$('[name^="taskIDList"]').each(function()
|
||||
{
|
||||
if($(this).prop('checked'))
|
||||
{
|
||||
checkedTotal += 1;
|
||||
var taskID = $(this).val();
|
||||
$tr = $("#taskList tbody tr[data-id='" + taskID + "']");
|
||||
if($tr.data('status') == 'wait') checkedWait += 1;
|
||||
if($tr.data('status') == 'doing') checkedDoing += 1;
|
||||
checkedEstimate += Number($tr.data('estimate'));
|
||||
checkedConsumed += Number($tr.data('consumed'));
|
||||
checkedLeft += Number($tr.data('left'));
|
||||
}
|
||||
});
|
||||
if(checkedTotal > 0)
|
||||
{
|
||||
summary = checkedSummary.replace('%total%', checkedTotal).replace('%wait%', checkedWait)
|
||||
.replace('%doing%', checkedDoing)
|
||||
.replace('%estimate%', checkedEstimate)
|
||||
.replace('%consumed%', checkedConsumed)
|
||||
.replace('%left%', checkedLeft);
|
||||
$('tfoot .table-actions .text:last').html(summary);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('tfoot .table-actions .text:last').html(taskSummary);
|
||||
}
|
||||
}
|
||||
|
||||
$('#module' + moduleID).addClass('active');
|
||||
$('#product' + productID).addClass('active');
|
||||
|
||||
@@ -180,6 +180,7 @@ $lang->project->beginAndEnd = 'Time Frame';
|
||||
$lang->project->lblStats = 'Hour Report';
|
||||
$lang->project->stats = '<strong>%s</strong> Hour(s) available, <strong>%s</strong> Hour(s) Estimated, <strong>%s</strong> Hour(s) Consumed, <strong>%s</strong> Hour(s) Remained.';
|
||||
$lang->project->taskSummary = " <strong>%s</strong> Tasks on this page, <strong>%s</strong> Wait, <strong>%s</strong> Doing. <strong>%s</strong> Hour(s) Estimated, <strong>%s</strong> Hour(s) Consumed, <strong>%s</strong> Hour(s) Remained.";
|
||||
$lang->project->checkedSummary = " <strong>%total%</strong> Checked, <strong>%wait%</strong> Wait, <strong>%doing%</strong> Doing, <strong>%estimate%</strong> Hour(s) Estimated, <strong>%consumed%</strong> Hour(s) Consumed, <strong>%left%</strong> Hour(s) Remained.";
|
||||
$lang->project->memberHours = "%s has <strong>%s</strong> Hour(s) available ";
|
||||
$lang->project->groupSummary = "<strong>%s</strong> Tasks in this group, Wait <strong>%s</strong>, Doing <strong>%s</strong>. <strong>%s</strong> Hour(s) Estimated , <strong>%s</strong> Hour(s) Consumed, <strong>%s</strong> Hour(s) Remained.";
|
||||
$lang->project->groupSummaryAB = "Total Tasks <strong>%s</strong>, Wait <strong>%s</strong>, Doing <strong>%s</strong>.<br /> <strong>%s</strong> Hour(s) Estimated, <strong>%s</strong> Hour(s) Consumed,<strong>%s</strong> Hour(s) Remained.";
|
||||
|
||||
@@ -42,7 +42,7 @@ $lang->project->progress = '进度';
|
||||
$lang->project->hours = '预计 %s 消耗 %s 剩余 %s';
|
||||
$lang->project->viewBug = '查看bug';
|
||||
$lang->project->noProduct = "无{$lang->productCommon}{$lang->projectCommon}";
|
||||
$lang->project->createStory = "新增需求";
|
||||
$lang->project->createStory = "添加需求";
|
||||
$lang->project->all = '所有';
|
||||
$lang->project->undone = '未完成';
|
||||
$lang->project->unclosed = '未关闭';
|
||||
@@ -180,6 +180,7 @@ $lang->project->beginAndEnd = '起止时间';
|
||||
$lang->project->lblStats = '工时统计';
|
||||
$lang->project->stats = '可用工时<strong>%s</strong>工时,总共预计<strong>%s</strong>工时,已经消耗<strong>%s</strong>工时,预计剩余<strong>%s</strong>工时';
|
||||
$lang->project->taskSummary = "本页共 <strong>%s</strong> 个任务,未开始 <strong>%s</strong>,进行中 <strong>%s</strong>,总预计<strong>%s</strong>工时,已消耗<strong>%s</strong>工时,剩余<strong>%s</strong>工时。";
|
||||
$lang->project->checkedSummary = "选中 <strong>%total%</strong> 个任务,未开始 <strong>%wait%</strong>,进行中 <strong>%doing%</strong>,总预计<strong>%estimate%</strong>工时,已消耗<strong>%consumed%</strong>工时,剩余<strong>%left%</strong>工时。";
|
||||
$lang->project->memberHours = "%s共有 <strong>%s</strong> 个可用工时,";
|
||||
$lang->project->groupSummary = "本组共 <strong>%s</strong> 个任务,未开始 <strong>%s</strong>,进行中 <strong>%s</strong>,总预计<strong>%s</strong>工时,已消耗<strong>%s</strong>工时,剩余<strong>%s</strong>工时。";
|
||||
$lang->project->groupSummaryAB = "总任务<strong>%s</strong> ,未开始<strong>%s</strong>,进行中<strong>%s</strong>。<br />总预计<strong>%s</strong>,已消耗<strong>%s</strong>,剩余<strong>%s</strong>。";
|
||||
@@ -214,7 +215,7 @@ $lang->project->tips = '提示';
|
||||
$lang->project->afterInfo = "{$lang->projectCommon}添加成功,您现在可以进行以下操作:";
|
||||
$lang->project->setTeam = '设置团队';
|
||||
$lang->project->linkStory = '关联需求';
|
||||
$lang->project->createTask = '添加任务';
|
||||
$lang->project->createTask = '创建任务';
|
||||
$lang->project->goback = "返回任务列表";
|
||||
$lang->project->noweekend = '去除周末';
|
||||
$lang->project->withweekend = '显示周末';
|
||||
|
||||
@@ -1423,13 +1423,15 @@ class projectModel extends model
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function linkStory($projectID)
|
||||
public function linkStory($projectID, $stories = array())
|
||||
{
|
||||
if($this->post->stories == false) return false;
|
||||
if(empty($stories)) $stories = $this->post->stories;
|
||||
if(empty($stories)) return false;
|
||||
|
||||
$this->loadModel('action');
|
||||
$versions = $this->loadModel('story')->getVersions($this->post->stories);
|
||||
$versions = $this->loadModel('story')->getVersions($stories);
|
||||
$lastOrder = (int)$this->dao->select('*')->from(TABLE_PROJECTSTORY)->where('project')->eq($projectID)->orderBy('order_desc')->limit(1)->fetch('order');
|
||||
foreach($this->post->stories as $key => $storyID)
|
||||
foreach($stories as $key => $storyID)
|
||||
{
|
||||
$productID = (int)$this->post->products[$storyID];
|
||||
$data = new stdclass();
|
||||
@@ -2239,7 +2241,7 @@ class projectModel extends model
|
||||
*/
|
||||
public function getPrevKanban($projectID)
|
||||
{
|
||||
$prevKanbans = $this->loadModel('setting')->getItem("ower=null&module=project§ion=kanban&key=project$projectID");
|
||||
$prevKanbans = $this->loadModel('setting')->getItem("owner=null&module=project§ion=kanban&key=project$projectID");
|
||||
return json_decode($prevKanbans, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,21 @@
|
||||
common::printIcon('story', 'export', "productID=$productID&orderBy=id_desc", '', 'button', '', '', 'export');
|
||||
|
||||
$this->lang->story->create = $this->lang->project->createStory;
|
||||
if($productID and !$this->loadModel('story')->checkForceReview()) common::printIcon('story', 'create', "productID=$productID&branch=&moduleID=0&story=0&project=$project->id");
|
||||
if($productID and !$this->loadModel('story')->checkForceReview())
|
||||
{
|
||||
echo "<div class='btn-group' id='createActionMenu'>";
|
||||
common::printIcon('story', 'create', "productID=$productID&branch=0&moduleID=0&story=0&project=$project->id");
|
||||
|
||||
$misc = common::hasPriv('story', 'batchCreate') ? '' : "disabled";
|
||||
$link = common::hasPriv('story', 'batchCreate') ? $this->createLink('story', 'batchCreate', "productID=$productID&branch=0&moduleID=0&story=0&project=$project->id") : '#';
|
||||
echo "<button type='button' class='btn dropdown-toggle {$misc}' data-toggle='dropdown'>";
|
||||
echo "<span class='caret'></span>";
|
||||
echo '</button>';
|
||||
echo "<ul class='dropdown-menu pull-right'>";
|
||||
echo "<li>" . html::a($link, $lang->story->batchCreate, '', "class='$misc'") . "</li>";
|
||||
echo '</ul>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
if(commonModel::isTutorialMode())
|
||||
{
|
||||
@@ -58,7 +72,7 @@
|
||||
<div class='main'>
|
||||
<script>setTreeBox();</script>
|
||||
<form method='post' id='projectStoryForm'>
|
||||
<?php $canOrder = common::hasPriv('project', 'storySort');?>
|
||||
<?php $canOrder = common::hasPriv('project', 'storySort');?>
|
||||
<table class='table tablesorter table-condensed table-fixed table-selectable' id='storyList'>
|
||||
<thead>
|
||||
<tr class='colhead'>
|
||||
@@ -91,7 +105,7 @@
|
||||
$storyLink = $this->createLink('story', 'view', "storyID=$story->id&version=$story->version&from=project¶m=$project->id");
|
||||
$totalEstimate += $story->estimate;
|
||||
?>
|
||||
<tr class='text-center' id="story<?php echo $story->id;?>" data-id='<?php echo $story->id;?>' data-order='<?php echo $story->order ?>'>
|
||||
<tr class='text-center' id="story<?php echo $story->id;?>" data-id='<?php echo $story->id;?>' data-order='<?php echo $story->order ?>' data-estimate='<?php echo $story->estimate?>' data-cases='<?php echo zget($storyCases, $story->id, 0)?>'>
|
||||
<td class='cell-id'>
|
||||
<?php if($canBatchEdit or $canBatchClose):?>
|
||||
<input type='checkbox' name='storyIDList[<?php echo $story->id;?>]' value='<?php echo $story->id;?>' />
|
||||
@@ -218,6 +232,7 @@
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<?php js::set('checkedSummary', $lang->product->checkedSummary);?>
|
||||
<?php js::set('projectID', $project->id);?>
|
||||
<?php js::set('orderBy', $orderBy)?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -49,8 +49,15 @@ js::set('browseType', $browseType);
|
||||
|
||||
if($useDatatable) include '../../common/view/datatable.html.php';
|
||||
$customFields = $this->datatable->getSetting('project');
|
||||
$widths = $this->datatable->setFixedFieldWidth($customFields);
|
||||
$columns = 0;
|
||||
if($project->type == 'ops')
|
||||
{
|
||||
foreach($customFields as $id => $customField)
|
||||
{
|
||||
if($customField->id == 'story') unset($customFields[$id]);
|
||||
}
|
||||
}
|
||||
$widths = $this->datatable->setFixedFieldWidth($customFields);
|
||||
$columns = 0;
|
||||
?>
|
||||
<table class='table table-condensed table-hover table-striped tablesorter table-fixed <?php echo ($useDatatable ? 'datatable' : 'table-selectable');?> table-selectable' id='taskList' data-checkable='true' data-fixed-left-width='<?php echo $widths['leftWidth']?>' data-fixed-right-width='<?php echo $widths['rightWidth']?>' data-custom-menu='true' data-checkbox-name='taskIDList[]'>
|
||||
<thead>
|
||||
@@ -69,14 +76,14 @@ js::set('browseType', $browseType);
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($tasks as $task):?>
|
||||
<tr class='text-center' data-id='<?php echo $task->id;?>'>
|
||||
<tr class='text-center' data-id='<?php echo $task->id;?>' data-status='<?php echo $task->status?>' data-estimate='<?php echo $task->estimate?>' data-consumed='<?php echo $task->consumed?>' data-left='<?php echo $task->left?>'>
|
||||
<?php foreach($customFields as $field) $this->task->printCell($field, $task, $users, $browseType, $branchGroups, $modulePairs, $useDatatable ? 'datatable' : 'table');?>
|
||||
</tr>
|
||||
<?php if(!empty($task->children)):?>
|
||||
<?php foreach($task->children as $key => $child):?>
|
||||
<?php $class = $key == 0 ? ' table-child-top' : '';?>
|
||||
<?php $class .= ($key + 1 == count($task->children)) ? ' table-child-bottom' : '';?>
|
||||
<tr class='text-center table-children<?php echo $class;?> parent-<?php echo $task->id;?>' data-id='<?php echo $child->id?>'>
|
||||
<tr class='text-center table-children<?php echo $class;?> parent-<?php echo $task->id;?>' data-id='<?php echo $child->id?>' data-status='<?php echo $task->status?>' data-estimate='<?php echo $task->estimate?>' data-consumed='<?php echo $task->consumed?>' data-left='<?php echo $task->left?>'>
|
||||
<?php foreach($customFields as $field) $this->task->printCell($field, $child, $users, $browseType, $branchGroups, $modulePairs, $useDatatable ? 'datatable' : 'table', true);?>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
@@ -166,6 +173,7 @@ js::set('browseType', $browseType);
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<?php js::set('checkedSummary', $lang->project->checkedSummary);?>
|
||||
<?php js::set('replaceID', 'taskList')?>
|
||||
<script>
|
||||
$('#project<?php echo $projectID;?>').addClass('active')
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
foreach(customModel::getFeatureMenu('project', 'task') as $menuItem)
|
||||
{
|
||||
if($project->type == 'ops' && $menuItem->name == 'needconfirm') continue;
|
||||
if(isset($menuItem->hidden)) continue;
|
||||
$menuType = $menuItem->name;
|
||||
if(strpos($menuType, 'QUERY') === 0)
|
||||
@@ -73,6 +74,7 @@
|
||||
foreach ($lang->project->groups as $key => $value)
|
||||
{
|
||||
if($key == '') continue;
|
||||
if($project->type == 'ops' && $key == 'story') continue;
|
||||
echo '<li' . ($key == $groupBy ? " class='active'" : '') . '>';
|
||||
common::printLink('project', 'groupTask', "project=$projectID&groupBy=$key", $value);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<h6><?php echo $lang->project->afterInfo;?></h6>
|
||||
<div class='pdb-20'>
|
||||
<?php echo html::a($this->createLink('project', 'team', "projectID=$projectID"), $lang->project->setTeam, '', "class='btn'");?>
|
||||
<?php if($this->config->global->flow != 'onlyTask') echo html::a($this->createLink('project', 'linkstory', "projectID=$projectID"), $lang->project->linkStory, '', "class='btn'");?>
|
||||
<?php if($this->config->global->flow != 'onlyTask' && $project->type != 'ops') echo html::a($this->createLink('project', 'linkstory', "projectID=$projectID"), $lang->project->linkStory, '', "class='btn'");?>
|
||||
<?php echo html::a($this->createLink('task', 'create', "project=$projectID"), $lang->project->createTask, '', "class='btn'");?>
|
||||
<?php echo html::a($this->createLink('project', 'task', "projectID=$projectID"), $lang->project->goback, '', "class='btn'");?>
|
||||
</div>
|
||||
|
||||
@@ -126,7 +126,7 @@ class release extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function view($releaseID, $type = 'story', $link = 'false', $param = '')
|
||||
public function view($releaseID, $type = 'story', $link = 'false', $param = '', $orderBy = 'id_desc')
|
||||
{
|
||||
if($type == 'story') $this->session->set('storyList', $this->app->getURI(true));
|
||||
if($type == 'bug' or $type == 'leftBug') $this->session->set('bugList', $this->app->getURI(true));
|
||||
@@ -137,15 +137,21 @@ class release extends control
|
||||
$release = $this->release->getById((int)$releaseID, true);
|
||||
if(!$release) die(js::error($this->lang->notFound) . js::locate('back'));
|
||||
|
||||
$stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($release->stories)->andWhere('deleted')->eq(0)->fetchAll('id');
|
||||
$stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($release->stories)->andWhere('deleted')->eq(0)
|
||||
->beginIF($type == 'story')->orderBy($orderBy)->fi()
|
||||
->fetchAll('id');
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story');
|
||||
$stages = $this->dao->select('*')->from(TABLE_STORYSTAGE)->where('story')->in($release->stories)->andWhere('branch')->eq($release->branch)->fetchPairs('story', 'stage');
|
||||
foreach($stages as $storyID => $stage)$stories[$storyID]->stage = $stage;
|
||||
|
||||
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->bugs)->andWhere('deleted')->eq(0)->fetchAll();
|
||||
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->bugs)->andWhere('deleted')->eq(0)
|
||||
->beginIF($type == 'bug')->orderBy($orderBy)->fi()
|
||||
->fetchAll();
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'linkedBug');
|
||||
|
||||
$leftBugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->leftBugs)->andWhere('deleted')->eq(0)->fetchAll();
|
||||
$leftBugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->leftBugs)->andWhere('deleted')->eq(0)
|
||||
->beginIF($type == 'leftBug')->orderBy($orderBy)->fi()
|
||||
->fetchAll();
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'leftBugs');
|
||||
|
||||
$this->commonAction($release->product);
|
||||
@@ -162,6 +168,7 @@ class release extends control
|
||||
$this->view->type = $type;
|
||||
$this->view->link = $link;
|
||||
$this->view->param = $param;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->branchName = $release->productType == 'normal' ? '' : $this->loadModel('branch')->getById($release->branch);
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php
|
||||
$jsRoot = $this->app->getWebRoot() . "js/";
|
||||
include '../../common/view/tablesorter.html.php';
|
||||
?>
|
||||
<div id='querybox' class='show'></div>
|
||||
<?php
|
||||
$releaseBugs = $type == 'bug' ? $release->bugs : $release->leftBugs;
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php
|
||||
$jsRoot = $this->app->getWebRoot() . "js/";
|
||||
include '../../common/view/tablesorter.html.php';
|
||||
?>
|
||||
<div id='querybox' class='show'></div>
|
||||
<div id='unlinkStoryList'>
|
||||
<form method='post' target='hiddenwin' id='unlinkedStoriesForm' action='<?php echo $this->createLink('release', 'linkStory', "releaseID=$release->id&browseType=$browseType¶m=$param")?>'>
|
||||
|
||||
@@ -82,16 +82,17 @@
|
||||
<?php endif;?>
|
||||
<form method='post' target='hiddenwin' action="<?php echo inLink('batchUnlinkStory', "release=$release->id");?>" id='linkedStoriesForm'>
|
||||
<table class='table table-hover table-condensed table-striped tablesorter table-fixed table-selectable' id='storyList'>
|
||||
<?php $vars = "releaseID={$release->id}&type=story&link=$link¶m=$param&orderBy=%s";?>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='w-id'><?php echo $lang->idAB;?></th>
|
||||
<th class='w-pri'><?php echo $lang->priAB;?></th>
|
||||
<th class="text-left"><?php echo $lang->story->title;?></th>
|
||||
<th class='w-user'><?php echo $lang->openedByAB;?></th>
|
||||
<th class='w-hour'><?php echo $lang->story->estimateAB;?></th>
|
||||
<th class='w-hour'><?php echo $lang->statusAB;?></th>
|
||||
<th class='w-100px'><?php echo $lang->story->stageAB;?></th>
|
||||
<th class='w-50px'><?php echo $lang->actions;?></th>
|
||||
<th class='w-id {sorter:false}'> <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
|
||||
<th class='w-pri {sorter:false}'> <?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
|
||||
<th class="text-left {sorter:false}"><?php common::printOrderLink('title', $orderBy, $vars, $lang->story->title);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='w-hour {sorter:false}'> <?php common::printOrderLink('estimate', $orderBy, $vars, $lang->story->estimateAB);?></th>
|
||||
<th class='w-hour {sorter:false}'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
|
||||
<th class='w-100px {sorter:false}'> <?php common::printOrderLink('stage', $orderBy, $vars, $lang->story->stageAB);?></th>
|
||||
<th class='w-50px {sorter:false}'> <?php echo $lang->actions?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php $canBatchUnlink = common::hasPriv('release', 'batchUnlinkStory');?>
|
||||
@@ -141,16 +142,17 @@
|
||||
<?php endif;?>
|
||||
<form method='post' target='hiddenwin' action="<?php echo inLink('batchUnlinkBug', "releaseID=$release->id");?>" id='linkedBugsForm'>
|
||||
<table class='table table-hover table-condensed table-striped tablesorter table-fixed table-selectable' id='bugList'>
|
||||
<?php $vars = "releaseID={$release->id}&type=bug&link=$link¶m=$param&orderBy=%s";?>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='w-id'><?php echo $lang->idAB;?></th>
|
||||
<th><?php echo $lang->bug->title;?></th>
|
||||
<th class='w-100px'><?php echo $lang->bug->status;?></th>
|
||||
<th class='w-user'><?php echo $lang->openedByAB;?></th>
|
||||
<th class='w-date'><?php echo $lang->bug->openedDateAB;?></th>
|
||||
<th class='w-user'><?php echo $lang->bug->resolvedByAB;?></th>
|
||||
<th class='w-100px'><?php echo $lang->bug->resolvedDateAB;?></th>
|
||||
<th class='w-50px'><?php echo $lang->actions;?></th>
|
||||
<th class='w-id {sorter:false}'> <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
|
||||
<th class='text-left {sorter:false}'><?php common::printOrderLink('title', $orderBy, $vars, $lang->bug->title);?></th>
|
||||
<th class='w-100px {sorter:false}'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->bug->status);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='w-date {sorter:false}'> <?php common::printOrderLink('openedDate', $orderBy, $vars, $lang->bug->openedDateAB);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('resolvedBy', $orderBy, $vars, $lang->bug->resolvedByAB);?></th>
|
||||
<th class='w-100px {sorter:false}'> <?php common::printOrderLink('resolvedDate', $orderBy, $vars, $lang->bug->resolvedDateAB);?></th>
|
||||
<th class='w-50px {sorter:false}'> <?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php $canBatchUnlink = common::hasPriv('release', 'batchUnlinkBug');?>
|
||||
@@ -200,15 +202,16 @@
|
||||
<?php endif;?>
|
||||
<form method='post' target='hiddenwin' action="<?php echo inLink('batchUnlinkBug', "releaseID=$release->id&type=leftBug");?>" id='linkedBugsForm'>
|
||||
<table class='table table-hover table-condensed table-striped tablesorter table-fixed table-selectable' id='leftBugList'>
|
||||
<?php $vars = "releaseID={$release->id}&type=leftBug&link=$link¶m=$param&orderBy=%s";?>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='w-id'><?php echo $lang->idAB;?></th>
|
||||
<th class='w-severity'><?php echo $lang->bug->severityAB;?></th>
|
||||
<th><?php echo $lang->bug->title;?></th>
|
||||
<th class='w-100px'><?php echo $lang->bug->status;?></th>
|
||||
<th class='w-user'><?php echo $lang->openedByAB;?></th>
|
||||
<th class='w-150px'><?php echo $lang->bug->openedDateAB;?></th>
|
||||
<th class='w-50px'><?php echo $lang->actions;?></th>
|
||||
<th class='w-id {sorter:false}'> <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
|
||||
<th class='w-severity {sorter:false}'><?php common::printOrderLink('severity', $orderBy, $vars, $lang->bug->severityAB);?></th>
|
||||
<th class='text-left {sorter:false}'> <?php common::printOrderLink('title', $orderBy, $vars, $lang->bug->title);?></th>
|
||||
<th class='w-100px {sorter:false}'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->bug->status);?></th>
|
||||
<th class='w-user {sorter:false}'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='w-150px {sorter:false}'> <?php common::printOrderLink('openedDate', $orderBy, $vars, $lang->bug->openedDateAB);?></th>
|
||||
<th class='w-50px {sorter:false}'> <?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php $canBatchUnlink = common::hasPriv('release', 'batchUnlinkBug');?>
|
||||
|
||||
@@ -56,11 +56,11 @@ include '../../common/view/chosen.html.php';
|
||||
.outer > #querybox {margin: -20px -20px 20px; border-top: none; border-bottom: 1px solid #ddd}
|
||||
|
||||
#searchform input.date::-webkit-input-placeholder{color: #000000; opacity: 1;}
|
||||
#searchform input.date::-moz-placeholder{color: #000000; opacity: 1;}
|
||||
#searchform input.date::-moz-placeholder{color: #000000; opacity: 1;}
|
||||
#searchform input.date:-ms-input-placeholder{color: #000000; opacity: 1;}
|
||||
</style>
|
||||
<script language='Javascript'>
|
||||
var dtOptions =
|
||||
var dtOptions =
|
||||
{
|
||||
language: '<?php echo $this->app->getClientLang();?>',
|
||||
weekStart: 1,
|
||||
@@ -97,8 +97,8 @@ var actionURL = '<?php echo $actionURL;?>';
|
||||
|
||||
/**
|
||||
* Set date field
|
||||
*
|
||||
* @param string $query
|
||||
*
|
||||
* @param string $query
|
||||
* @return void
|
||||
*/
|
||||
function setDateField(query, fieldNO)
|
||||
@@ -160,9 +160,9 @@ function setDateField(query, fieldNO)
|
||||
|
||||
/**
|
||||
* When the value of the fields select changed, set the operator and value of the new field.
|
||||
*
|
||||
* @param string $obj
|
||||
* @param int $fieldNO
|
||||
*
|
||||
* @param string $obj
|
||||
* @param int $fieldNO
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -177,7 +177,7 @@ function setField(obj, fieldNO, moduleparams)
|
||||
if(typeof(params[fieldName]['class']) != undefined && params[fieldName]['class'] == 'date')
|
||||
{
|
||||
setDateField($(obj).closest('form').find("#value" + fieldNO), fieldNO);
|
||||
$(obj).closest('form').find("#value" + fieldNO).addClass('date'); // Shortcut the width of the datepicker to make sure align with others.
|
||||
$(obj).closest('form').find("#value" + fieldNO).addClass('date'); // Shortcut the width of the datepicker to make sure align with others.
|
||||
var groupItems = <?php echo $config->search->groupItems?>;
|
||||
var maxNO = 2 * groupItems;
|
||||
var nextNO = fieldNO > groupItems ? fieldNO - groupItems + 1 : fieldNO + groupItems;
|
||||
@@ -207,7 +207,7 @@ function setField(obj, fieldNO, moduleparams)
|
||||
|
||||
/**
|
||||
* Reset forms.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -216,12 +216,13 @@ function resetForm(obj)
|
||||
for(i = 1; i <= groupItems * 2; i ++)
|
||||
{
|
||||
$(obj).closest('form').find('#value' + i).val('').trigger('chosen:updated');
|
||||
$(obj).closest('form').find('#dateValue' + i).val('').attr('placeholder','');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show more fields.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -241,7 +242,7 @@ function showmore(obj)
|
||||
|
||||
/**
|
||||
* Show lite search form.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -261,8 +262,8 @@ function showlite(obj)
|
||||
|
||||
/**
|
||||
* loadQueries.
|
||||
*
|
||||
* @param queryID $queryID
|
||||
*
|
||||
* @param queryID $queryID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -273,8 +274,8 @@ function loadQueries(queryID)
|
||||
|
||||
/**
|
||||
* Execute a query.
|
||||
*
|
||||
* @param int $queryID
|
||||
*
|
||||
* @param int $queryID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -286,7 +287,7 @@ function executeQuery(queryID)
|
||||
|
||||
/**
|
||||
* Delete a query.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -383,7 +384,7 @@ foreach($fieldParams as $fieldName => $param)
|
||||
/* Print value. */
|
||||
echo "<td id='valueBox$fieldNO' style='overflow:visible'>";
|
||||
if($param['control'] == 'select') echo html::select("value$fieldNO", $param['values'], $formSession["value$fieldNO"], "class='form-control searchSelect chosen'");
|
||||
if($param['control'] == 'input')
|
||||
if($param['control'] == 'input')
|
||||
{
|
||||
$fieldName = $formSession["field$fieldNO"];
|
||||
$fieldValue = $formSession["value$fieldNO"];
|
||||
@@ -467,7 +468,7 @@ foreach($fieldParams as $fieldName => $param)
|
||||
?>
|
||||
</table>
|
||||
</td>
|
||||
<td class='<?php echo $style == 'simple' ? 'w-80px' : 'w-160px';?>'>
|
||||
<td class='<?php echo $style == 'simple' ? 'w-80px' : 'w-160px';?>'>
|
||||
<?php
|
||||
echo html::hidden('module', $module);
|
||||
echo html::hidden('actionURL', $actionURL);
|
||||
|
||||
@@ -13,7 +13,7 @@ $config->story->edit = new stdclass();
|
||||
$config->story->change = new stdclass();
|
||||
$config->story->close = new stdclass();
|
||||
$config->story->review = new stdclass();
|
||||
$config->story->create->requiredFields = 'title';
|
||||
$config->story->create->requiredFields = 'title,module';
|
||||
$config->story->change->requiredFields = 'title';
|
||||
$config->story->close->requiredFields = 'closedReason';
|
||||
$config->story->review->requiredFields = 'assignedTo,reviewedBy';
|
||||
|
||||
@@ -102,6 +102,7 @@ class story extends control
|
||||
|
||||
$users = $this->user->getPairs('pdfirst|noclosed|nodeleted');
|
||||
$moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'story', 0, $branch);
|
||||
if(empty($moduleOptionMenu)) die(js::locate(helper::createLink('tree', 'browse', "productID=$productID&view=story")));
|
||||
|
||||
/* Set menu. */
|
||||
$this->product->setMenu($products, $product->id, $branch);
|
||||
@@ -194,22 +195,28 @@ class story extends control
|
||||
* Create a batch stories.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param int $moduleID
|
||||
* @param int $storyID
|
||||
* @param int $project
|
||||
* @param int $plan
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function batchCreate($productID = 0, $branch = 0, $moduleID = 0, $storyID = 0)
|
||||
public function batchCreate($productID = 0, $branch = 0, $moduleID = 0, $storyID = 0, $project = 0, $plan = 0)
|
||||
{
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$mails = $this->story->batchCreate($productID, $branch);
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
|
||||
$stories = array();
|
||||
foreach($mails as $mail)
|
||||
{
|
||||
$stories[] = $mail->storyID;
|
||||
if($mail->actionID) $this->story->sendmail($mail->storyID, $mail->actionID);
|
||||
}
|
||||
if($project) $this->loadModel('project')->linkStory($project, $stories);
|
||||
|
||||
/* If storyID not equal zero, subdivide this story to child stories and close it. */
|
||||
if($storyID)
|
||||
@@ -236,7 +243,7 @@ class story extends control
|
||||
$this->product->setMenu($products, $product->id, $branch);
|
||||
|
||||
/* Init vars. */
|
||||
$planID = 0;
|
||||
$planID = $plan;
|
||||
$pri = 0;
|
||||
$estimate = '';
|
||||
$title = '';
|
||||
@@ -672,7 +679,7 @@ class story extends control
|
||||
$this->story->review($storyID);
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
$result = $this->post->result;
|
||||
if($this->post->closedReason != '' and strpos('done,postponed,subdivided', $this->post->closedReason) === false) $result = 'pass';
|
||||
if($this->post->closedReason != '' and strpos('done,postponed,subdivided,willnotdo', $this->post->closedReason) === false) $result = 'pass';
|
||||
$actionID = $this->action->create('story', $storyID, 'Reviewed', $this->post->comment, ucfirst($result));
|
||||
$this->story->sendmail($storyID, $actionID);
|
||||
if($this->post->result == 'reject')
|
||||
|
||||
@@ -73,7 +73,7 @@ $lang->story->lastEditedBy = 'Last Edited By';
|
||||
$lang->story->lastEditedDate = 'Last Edited On';
|
||||
$lang->story->closedBy = 'Closed By';
|
||||
$lang->story->closedDate = 'Closed On';
|
||||
$lang->story->closedReason = 'Close Reason';
|
||||
$lang->story->closedReason = 'Reason';
|
||||
$lang->story->rejectedReason = 'Reject Reason';
|
||||
$lang->story->reviewedBy = 'Reviewer';
|
||||
$lang->story->reviewedDate = 'Review on';
|
||||
|
||||
+190
-185
@@ -15,9 +15,9 @@ class storyModel extends model
|
||||
{
|
||||
/**
|
||||
* Get a story by id.
|
||||
*
|
||||
* @param int $storyID
|
||||
* @param int $version
|
||||
*
|
||||
* @param int $storyID
|
||||
* @param int $version
|
||||
* @param bool $setImgSize
|
||||
* @access public
|
||||
* @return object|bool
|
||||
@@ -67,8 +67,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories by idList.
|
||||
*
|
||||
* @param int|array|string $storyIDList
|
||||
*
|
||||
* @param int|array|string $storyIDList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -84,8 +84,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get story specs.
|
||||
*
|
||||
* @param array $storyIdList
|
||||
*
|
||||
* @param array $storyIdList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -98,9 +98,9 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get affected things.
|
||||
*
|
||||
* @param object $story
|
||||
* Get affected things.
|
||||
*
|
||||
* @param object $story
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
@@ -135,7 +135,7 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Create a story.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return int|bool the id of the created story or false when error.
|
||||
*/
|
||||
@@ -184,7 +184,7 @@ class storyModel extends model
|
||||
$data->verify = $story->verify;
|
||||
$this->dao->insert(TABLE_STORYSPEC)->data($data)->exec();
|
||||
|
||||
if($projectID != 0 and $story->status != 'draft')
|
||||
if($projectID != 0 and $story->status != 'draft')
|
||||
{
|
||||
$lastOrder = (int)$this->dao->select('*')->from(TABLE_PROJECTSTORY)->where('project')->eq($projectID)->orderBy('order_desc')->limit(1)->fetch('order');
|
||||
$this->dao->insert(TABLE_PROJECTSTORY)
|
||||
@@ -209,7 +209,7 @@ class storyModel extends model
|
||||
$bug->assignedTo = 'closed';
|
||||
$bug->assignedDate = $now;
|
||||
$this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec();
|
||||
|
||||
|
||||
$this->loadModel('action')->create('bug', $bugID, 'ToStory', '', $storyID);
|
||||
$this->action->create('bug', $bugID, 'Closed');
|
||||
|
||||
@@ -218,13 +218,13 @@ class storyModel extends model
|
||||
->where('objectType')->eq('bug')
|
||||
->andWhere('objectID')->eq($bugID)
|
||||
->fetchAll();
|
||||
if(!empty($files))
|
||||
{
|
||||
if(!empty($files))
|
||||
{
|
||||
foreach($files as $file)
|
||||
{
|
||||
$file->objectType = 'story';
|
||||
$file->objectID = $storyID;
|
||||
unset($file->id);
|
||||
$file->objectID = $storyID;
|
||||
unset($file->id);
|
||||
$this->dao->insert(TABLE_FILE)->data($file)->exec();
|
||||
}
|
||||
}
|
||||
@@ -238,7 +238,7 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Create a batch stories.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return int|bool the id of the created story or false when error.
|
||||
*/
|
||||
@@ -258,6 +258,7 @@ class storyModel extends model
|
||||
$plan = 0;
|
||||
$pri = 0;
|
||||
$source = '';
|
||||
|
||||
for($i = 0; $i < $batchNum; $i++)
|
||||
{
|
||||
$module = $stories->module[$i] == 'ditto' ? $module : $stories->module[$i];
|
||||
@@ -268,6 +269,8 @@ class storyModel extends model
|
||||
$stories->plan[$i] = $plan;
|
||||
$stories->pri[$i] = (int)$pri;
|
||||
$stories->source[$i] = $source;
|
||||
|
||||
if(!empty($stories->title[$i]) && empty($stories->module[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->story->module)));
|
||||
}
|
||||
|
||||
if(isset($stories->uploadImage)) $this->loadModel('file');
|
||||
@@ -296,7 +299,7 @@ class storyModel extends model
|
||||
$this->dao->insert(TABLE_STORY)->data($data)->autoCheck()
|
||||
->batchCheck($this->config->story->create->requiredFields, 'notempty')
|
||||
->exec();
|
||||
if(dao::isError())
|
||||
if(dao::isError())
|
||||
{
|
||||
echo js::error(dao::getError());
|
||||
die(js::reload('parent'));
|
||||
@@ -324,8 +327,8 @@ class storyModel extends model
|
||||
|
||||
if(rename($realPath, $this->file->savePath . $this->file->getSaveName($file['pathname'])))
|
||||
{
|
||||
$file['addedBy'] = $this->app->user->account;
|
||||
$file['addedDate'] = $now;
|
||||
$file['addedBy'] = $this->app->user->account;
|
||||
$file['addedDate'] = $now;
|
||||
$file['objectType'] = 'story';
|
||||
$file['objectID'] = $storyID;
|
||||
if(in_array($file['extension'], $this->config->file->imageExtensions))
|
||||
@@ -356,7 +359,7 @@ class storyModel extends model
|
||||
/* Remove upload image file and session. */
|
||||
if(!empty($stories->uploadImage) and $this->session->storyImagesFile)
|
||||
{
|
||||
$classFile = $this->app->loadClass('zfile');
|
||||
$classFile = $this->app->loadClass('zfile');
|
||||
$file = current($_SESSION['storyImagesFile']);
|
||||
$realPath = dirname($file['realpath']);
|
||||
if(is_dir($realPath)) $classFile->removeDir($realPath);
|
||||
@@ -368,8 +371,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Change a story.
|
||||
*
|
||||
* @param int $storyID
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return array the change of the story.
|
||||
*/
|
||||
@@ -444,8 +447,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Update a story.
|
||||
*
|
||||
* @param int $storyID
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return array the changes of the story.
|
||||
*/
|
||||
@@ -476,7 +479,7 @@ class storyModel extends model
|
||||
->join('mailto', ',')
|
||||
->remove('linkStories,childStories,files,labels,comment')
|
||||
->get();
|
||||
if(is_array($story->plan)) $story->plan = trim(join(',', $story->plan), ',');
|
||||
if(isset($story->plan) and is_array($story->plan)) $story->plan = trim(join(',', $story->plan), ',');
|
||||
if(empty($_POST['product'])) $story->branch = $oldStory->branch;
|
||||
|
||||
$this->dao->update(TABLE_STORY)
|
||||
@@ -510,7 +513,7 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Batch update stories.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return array.
|
||||
*/
|
||||
@@ -536,9 +539,9 @@ class storyModel extends model
|
||||
if($data->modules[$storyID] == 'ditto') $data->modules[$storyID] = isset($prev['module']) ? $prev['module'] : 0;
|
||||
if($data->plans[$storyID] == 'ditto') $data->plans[$storyID] = isset($prev['plan']) ? $prev['plan'] : 0;
|
||||
if($data->sources[$storyID] == 'ditto') $data->sources[$storyID] = isset($prev['source']) ? $prev['source'] : '';
|
||||
if(isset($data->stages[$storyID]) and ($data->stages[$storyID] == 'ditto')) $data->stages[$storyID] = isset($prev['stage']) ? $prev['stage'] : '';
|
||||
if(isset($data->closedBys[$storyID]) and ($data->closedBys[$storyID] == 'ditto')) $data->closedBys[$storyID] = isset($prev['closedBy']) ? $prev['closedBy'] : '';
|
||||
if(isset($data->closedReasons[$storyID]) and ($data->closedReasons[$storyID] == 'ditto')) $data->closedReasons[$storyID] = isset($prev['closedReason']) ? $prev['closedReason'] : '';
|
||||
if(isset($data->stages[$storyID]) and ($data->stages[$storyID] == 'ditto')) $data->stages[$storyID] = isset($prev['stage']) ? $prev['stage'] : '';
|
||||
if(isset($data->closedBys[$storyID]) and ($data->closedBys[$storyID] == 'ditto')) $data->closedBys[$storyID] = isset($prev['closedBy']) ? $prev['closedBy'] : '';
|
||||
if(isset($data->closedReasons[$storyID]) and ($data->closedReasons[$storyID] == 'ditto')) $data->closedReasons[$storyID] = isset($prev['closedReason']) ? $prev['closedReason'] : '';
|
||||
|
||||
$prev['pri'] = $data->pris[$storyID];
|
||||
$prev['branch'] = isset($data->branches[$storyID]) ? $data->branches[$storyID] : 0;
|
||||
@@ -608,7 +611,7 @@ class storyModel extends model
|
||||
$this->dao->insert(TABLE_STORYSPEC)->data($data)->exec();
|
||||
}
|
||||
|
||||
if(!dao::isError())
|
||||
if(!dao::isError())
|
||||
{
|
||||
if($story->closedReason == 'done') $this->loadModel('score')->create('story', 'close');
|
||||
$allChanges[$storyID] = common::createChanges($oldStory, $story);
|
||||
@@ -625,8 +628,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Review a story.
|
||||
*
|
||||
* @param int $storyID
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
@@ -686,8 +689,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Batch review stories.
|
||||
*
|
||||
* @param array $storyIDList
|
||||
*
|
||||
* @param array $storyIDList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -730,10 +733,10 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Subdivide story
|
||||
*
|
||||
* @param int $storyID
|
||||
* @param array $stories
|
||||
* Subdivide story
|
||||
*
|
||||
* @param int $storyID
|
||||
* @param array $stories
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
@@ -773,8 +776,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Close a story.
|
||||
*
|
||||
* @param int $storyID
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
@@ -795,7 +798,7 @@ class storyModel extends model
|
||||
->add('closedBy', $this->app->user->account)
|
||||
->add('assignedTo', 'closed')
|
||||
->add('assignedDate', $now)
|
||||
->add('status', 'closed')
|
||||
->add('status', 'closed')
|
||||
->removeIF($this->post->closedReason != 'duplicate', 'duplicateStory')
|
||||
->removeIF($this->post->closedReason != 'subdivided', 'childStories')
|
||||
->setIF($this->post->closedReason == 'done', 'stage', 'released')
|
||||
@@ -814,7 +817,7 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Batch close story.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -864,7 +867,7 @@ class storyModel extends model
|
||||
->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty')
|
||||
->where('id')->eq($storyID)->exec();
|
||||
|
||||
if(!dao::isError())
|
||||
if(!dao::isError())
|
||||
{
|
||||
$allChanges[$storyID] = common::createChanges($oldStory, $story);
|
||||
}
|
||||
@@ -909,11 +912,11 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Batch change the plan of story.
|
||||
*
|
||||
* @param array $storyIDList
|
||||
* @param int $planID
|
||||
*
|
||||
* @param array $storyIDList
|
||||
* @param int $planID
|
||||
* @access public
|
||||
* @return array
|
||||
* @return array
|
||||
*/
|
||||
public function batchChangePlan($storyIDList, $planID, $oldPlanID = 0)
|
||||
{
|
||||
@@ -949,9 +952,9 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Batch change branch.
|
||||
*
|
||||
* @param array $storyIDList
|
||||
* @param int $branchID
|
||||
*
|
||||
* @param array $storyIDList
|
||||
* @param int $branchID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -977,8 +980,10 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Batch change the stage of story.
|
||||
*
|
||||
* @param string $stage
|
||||
*
|
||||
* @param $storyIDList
|
||||
* @param $stage
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1008,7 +1013,7 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Batch assign to.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1038,8 +1043,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Activate a story.
|
||||
*
|
||||
* @param int $storyID
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
@@ -1066,8 +1071,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Set stage of a story.
|
||||
*
|
||||
* @param int $storyID
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
@@ -1159,11 +1164,11 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Judge stage according to the devel and test tasks' status.
|
||||
*
|
||||
* Judge stage according to the devel and test tasks' status.
|
||||
*
|
||||
* 1. one doing devel task, all test tasks waiting, set stage as developing.
|
||||
* 2. all devel tasks done, all test tasks waiting, set stage as developed.
|
||||
* 3. one test task doing, set stage as testing.
|
||||
* 3. one test task doing, set stage as testing.
|
||||
* 4. all test tasks done, still some devel tasks not done(wait, doing), set stage as testing.
|
||||
* 5. all test tasks done, all devel tasks done, set stage as tested.
|
||||
*/
|
||||
@@ -1172,7 +1177,7 @@ class storyModel extends model
|
||||
$stage = 'projected';
|
||||
$testTasks = isset($branchTestTasks[$branch]) ? $branchTestTasks[$branch] : 0;
|
||||
$develTasks = isset($branchDevelTasks[$branch]) ? $branchDevelTasks[$branch] : 0;
|
||||
if($statusList['devel']['doing'] > 0 and $statusList['test']['wait'] == $testTasks) $stage = 'developing';
|
||||
if($statusList['devel']['doing'] > 0 and $statusList['test']['wait'] == $testTasks) $stage = 'developing';
|
||||
if($statusList['devel']['done'] == $develTasks and $develTasks > 0 and $statusList['test']['wait'] == $testTasks) $stage = 'developed';
|
||||
if($statusList['test']['doing'] > 0) $stage = 'testing';
|
||||
if(($statusList['devel']['wait'] > 0 or $statusList['devel']['doing'] > 0) and $statusList['test']['done'] == $testTasks and $testTasks > 0) $stage = 'testing';
|
||||
@@ -1302,7 +1307,7 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories list of a product.
|
||||
*
|
||||
*
|
||||
* @param int $productID
|
||||
* @param array|string $moduleIdList
|
||||
* @param string $status
|
||||
@@ -1334,12 +1339,12 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories pairs of a product.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param array|string $moduleIdList
|
||||
* @param string $status
|
||||
* @param string $order
|
||||
* @param int $limit
|
||||
*
|
||||
* @param int $productID
|
||||
* @param array|string $moduleIdList
|
||||
* @param string $status
|
||||
* @param string $order
|
||||
* @param int $limit
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1362,11 +1367,11 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories by assignedTo.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $account
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $account
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1377,11 +1382,11 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories by openedBy.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $account
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $account
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1392,11 +1397,11 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories by reviewedBy.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $account
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $account
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1407,11 +1412,11 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories by closedBy.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $account
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $account
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @return array
|
||||
*/
|
||||
public function getByClosedBy($productID, $branch, $modules, $account, $orderBy, $pager)
|
||||
@@ -1421,11 +1426,11 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories by status.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @param string $status
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @param string $status
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1453,12 +1458,12 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories by a field.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $fieldName
|
||||
* @param mixed $fieldValue
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $fieldName
|
||||
* @param mixed $fieldValue
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @param string $operator equal|include
|
||||
* @access public
|
||||
* @return array
|
||||
@@ -1481,10 +1486,10 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get to be closed stories.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $orderBy
|
||||
* @param string $pager
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $orderBy
|
||||
* @param string $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1519,7 +1524,7 @@ class storyModel extends model
|
||||
{
|
||||
if($projectID != '')
|
||||
{
|
||||
$products = $this->loadModel('project')->getProducts($projectID);
|
||||
$products = $this->loadModel('project')->getProducts($projectID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1549,7 +1554,7 @@ class storyModel extends model
|
||||
foreach($products as $product) $branches[$product->branch] = $product->branch;
|
||||
unset($branches[0]);
|
||||
$branches = join(',', $branches);
|
||||
if($branches) $storyQuery .= " AND `branch`" . helper::dbIN("0,$branches");
|
||||
if($branches) $storyQuery .= " AND `branch`" . helper::dbIN("0,$branches");
|
||||
if($this->app->moduleName == 'release' or $this->app->moduleName == 'build')
|
||||
{
|
||||
$storyQuery .= " AND `status` NOT IN ('draft')";// Fix bug #990.
|
||||
@@ -1572,11 +1577,11 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories by a sql.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $sql
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $sql
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1611,12 +1616,12 @@ class storyModel extends model
|
||||
}
|
||||
return $stories;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get stories list of a project.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $orderBy
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $orderBy
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1693,9 +1698,9 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories pairs of a project.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @param array|string $moduleIdList
|
||||
* @param string $type
|
||||
* @access public
|
||||
@@ -1763,11 +1768,11 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get stories of a user.
|
||||
*
|
||||
* @param string $account
|
||||
* @param string $type the query type
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
*
|
||||
* @param string $account
|
||||
* @param string $type the query type
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1785,19 +1790,19 @@ class storyModel extends model
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
->fetchAll();
|
||||
|
||||
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story');
|
||||
$productIdList = array();
|
||||
foreach($stories as $story) $productIdList[$story->product] = $story->product;
|
||||
|
||||
|
||||
return $this->mergePlanTitle($productIdList, $stories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get story pairs of a user.
|
||||
*
|
||||
* @param string $account
|
||||
* @param string $limit
|
||||
*
|
||||
* @param string $account
|
||||
* @param string $limit
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1811,11 +1816,11 @@ class storyModel extends model
|
||||
->limit($limit)
|
||||
->fetchAll();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get doing projects' members of a story.
|
||||
*
|
||||
* @param int $storyID
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1832,8 +1837,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get version of a story.
|
||||
*
|
||||
* @param int $storyID
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
@@ -1844,7 +1849,7 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get versions of some stories.
|
||||
*
|
||||
*
|
||||
* @param array|string story id list
|
||||
* @access public
|
||||
* @return array
|
||||
@@ -1856,8 +1861,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Get zero case.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1876,8 +1881,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Batch get story stage.
|
||||
*
|
||||
* @param array $stories
|
||||
*
|
||||
* @param array $stories
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1890,8 +1895,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Check need confirm.
|
||||
*
|
||||
* @param array $dataList
|
||||
*
|
||||
* @param array $dataList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1919,9 +1924,9 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Format stories
|
||||
*
|
||||
* @param array $stories
|
||||
* Format stories
|
||||
*
|
||||
* @param array $stories
|
||||
* @param string $type
|
||||
* @param int $limit
|
||||
* @access public
|
||||
@@ -1960,8 +1965,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Extract accounts from some stories.
|
||||
*
|
||||
* @param array $stories
|
||||
*
|
||||
* @param array $stories
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1980,8 +1985,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Extract accounts from a story.
|
||||
*
|
||||
* @param object $story
|
||||
*
|
||||
* @param object $story
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -1997,8 +2002,8 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Merge the default chart settings and the settings of current chart.
|
||||
*
|
||||
* @param string $chartType
|
||||
*
|
||||
* @param string $chartType
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -2016,7 +2021,7 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per product
|
||||
* Get report data of storys per product
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
@@ -2070,7 +2075,7 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per source
|
||||
* Get report data of storys per source
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
@@ -2087,8 +2092,8 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per plan
|
||||
*
|
||||
* Get report data of storys per plan
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2104,8 +2109,8 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per status
|
||||
*
|
||||
* Get report data of storys per status
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2120,8 +2125,8 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per stage
|
||||
*
|
||||
* Get report data of storys per stage
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2136,8 +2141,8 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per pri
|
||||
*
|
||||
* Get report data of storys per pri
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2152,8 +2157,8 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per estimate
|
||||
*
|
||||
* Get report data of storys per estimate
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2165,8 +2170,8 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per openedBy
|
||||
*
|
||||
* Get report data of storys per openedBy
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2182,8 +2187,8 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per assignedTo
|
||||
*
|
||||
* Get report data of storys per assignedTo
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2199,8 +2204,8 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per closedReason
|
||||
*
|
||||
* Get report data of storys per closedReason
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2215,8 +2220,8 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get report data of storys per change
|
||||
*
|
||||
* Get report data of storys per change
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2228,9 +2233,9 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get kanban group data.
|
||||
*
|
||||
* @param array $stories
|
||||
* Get kanban group data.
|
||||
*
|
||||
* @param array $stories
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2244,9 +2249,9 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Adjust the action clickable.
|
||||
*
|
||||
* @param object $story
|
||||
* @param string $action
|
||||
*
|
||||
* @param object $story
|
||||
* @param string $action
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -2264,9 +2269,9 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Merge plan title.
|
||||
*
|
||||
* @param int|array $productID
|
||||
* @param array $stories
|
||||
*
|
||||
* @param int|array $productID
|
||||
* @param array $stories
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -2455,7 +2460,7 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Set report condition.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
@@ -2475,7 +2480,7 @@ class storyModel extends model
|
||||
|
||||
/**
|
||||
* Check force review for user.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
@@ -2488,10 +2493,10 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail
|
||||
*
|
||||
* @param int $storyID
|
||||
* @param int $actionID
|
||||
* Send mail
|
||||
*
|
||||
* @param int $storyID
|
||||
* @param int $actionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
|
||||
@@ -40,7 +40,7 @@ if($this->story->checkForceReview()) unset($visibleFields['review']);
|
||||
<tr class='text-center'>
|
||||
<th class='w-30px'><?php echo $lang->idAB;?></th>
|
||||
<th class='w-120px<?php echo zget($visibleFields, $product->type, ' hidden')?>'><?php echo $lang->product->branch;?></th>
|
||||
<th class='w-p15<?php echo zget($visibleFields, 'module', ' hidden')?>'><?php echo $lang->story->module;?></th>
|
||||
<th class='w-p15<?php echo zget($visibleFields, 'module', ' hidden')?>'><?php echo $lang->story->module;?> <span class='required'></span></th>
|
||||
<th class='w-p15<?php echo zget($visibleFields, 'plan', ' hidden')?>'><?php echo $lang->story->plan;?></th>
|
||||
<th <?php if(count($visibleFields) >= 9) echo "class='w-150px'"?>><?php echo $lang->story->title;?> <span class='required'></span></th>
|
||||
<th class='w-p15<?php echo zget($visibleFields, 'spec', ' hidden')?>'><?php echo $lang->story->spec;?></th>
|
||||
@@ -56,7 +56,7 @@ if($this->story->checkForceReview()) unset($visibleFields['review']);
|
||||
<?php if(!empty($titles)):?>
|
||||
<?php foreach($titles as $storyTitle => $fileName):?>
|
||||
<?php $moduleID = $i == 0 ? $moduleID : 'ditto';?>
|
||||
<?php $planID = $i == 0 ? '' : 'ditto';?>
|
||||
<?php $planID = $i == 0 ? $planID : 'ditto';?>
|
||||
<?php $pri = $i == 0 ? '' : 'ditto';?>
|
||||
<?php $source = $i == 0 ? '' : 'ditto';?>
|
||||
<tr class='text-center'>
|
||||
@@ -88,7 +88,7 @@ if($this->story->checkForceReview()) unset($visibleFields['review']);
|
||||
<?php $nextStart = $i;?>
|
||||
<?php for($i = $nextStart; $i < $config->story->batchCreate; $i++):?>
|
||||
<?php $moduleID = $i - $nextStart == 0 ? $moduleID : 'ditto';?>
|
||||
<?php $planID = $i - $nextStart == 0 ? '' : 'ditto';?>
|
||||
<?php $planID = $i - $nextStart == 0 ? $planID : 'ditto';?>
|
||||
<?php $pri = $i - $nextStart == 0 ? '' : 'ditto';?>
|
||||
<?php $source = $i - $nextStart == 0 ? '' : 'ditto';?>
|
||||
<tr class='text-center'>
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
</div>
|
||||
<fieldset id='commentBox' class='hide'>
|
||||
<legend><?php echo $lang->comment;?></legend>
|
||||
<form method='post' action='<?php echo inlink('edit', "storyID=$story->id")?>'>
|
||||
<form method='post' action='<?php echo $this->createLink('action', 'comment', "objectType=story&objectID=$story->id")?>' target='hiddenwin'>
|
||||
<div class="form-group"><?php echo html::textarea('comment', '',"rows='5' class='w-p100'");?></div>
|
||||
<?php echo html::submitButton() . html::backButton();?>
|
||||
</form>
|
||||
|
||||
@@ -32,7 +32,9 @@ class svn extends control
|
||||
*/
|
||||
public function diff($url, $revision)
|
||||
{
|
||||
if(isset($_GET['repoUrl'])) $url = $this->get->repoUrl;
|
||||
$url = helper::safe64Decode($url);
|
||||
|
||||
$this->view->url = $url;
|
||||
$this->view->revision = $revision;
|
||||
$this->view->diff = $this->svn->diff($url, $revision);
|
||||
@@ -50,7 +52,9 @@ class svn extends control
|
||||
*/
|
||||
public function cat($url, $revision)
|
||||
{
|
||||
if(isset($_GET['repoUrl'])) $url = $this->get->repoUrl;
|
||||
$url = helper::safe64Decode($url);
|
||||
|
||||
$this->view->url = $url;
|
||||
$this->view->revision = $revision;
|
||||
$this->view->code = $this->svn->cat($url, $revision);
|
||||
|
||||
+20
-3
@@ -611,9 +611,8 @@ class svnModel extends model
|
||||
{
|
||||
foreach($actionFiles as $file)
|
||||
{
|
||||
$param = array('url' => helper::safe64Encode($repoRoot . $file), 'revision' => $log->revision);
|
||||
$catLink = trim(html::a(helper::createLink('svn', 'cat', $param, 'html'), 'view', '', "class='repolink'"));
|
||||
$diffLink = trim(html::a(helper::createLink('svn', 'diff', $param, 'html'), 'diff', '', "class='repolink'"));
|
||||
$catLink = trim(html::a($this->buildURL('cat', $repoRoot . $file, $log->revision), 'view', '', "class='repolink'"));
|
||||
$diffLink = trim(html::a($this->buildURL('diff', $repoRoot . $file, $log->revision), 'diff', '', "class='repolink'"));
|
||||
$diff .= $action . " " . $file . " $catLink ";
|
||||
$diff .= $action == 'M' ? "$diffLink\n" : "\n" ;
|
||||
}
|
||||
@@ -715,4 +714,22 @@ class svnModel extends model
|
||||
{
|
||||
echo helper::now() . " $log\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Build URL.
|
||||
*
|
||||
* @param string $methodName
|
||||
* @param string $url
|
||||
* @param int $revision
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function buildURL($methodName, $url, $revision)
|
||||
{
|
||||
$buildedURL = helper::createLink('svn', $methodName, "url=&revision=$revision", 'html');
|
||||
$buildedURL .= strpos($buildedURL, '?') === false ? '?' : '&';
|
||||
$buildedURL .= 'repoUrl=' . helper::safe64Encode($url);
|
||||
|
||||
return $buildedURL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.lite.html.php';?>
|
||||
<?php $catLink = inlink('cat', 'url=' . helper::safe64Encode($url) . "&revision=$revision");?>
|
||||
<?php $catLink = $this->svn->buildURL('cat', $url, $revision);?>
|
||||
<div class='box-title'><?php echo html::a($catLink, "$url@$revision");?></div>
|
||||
<div class='box-content'><xmp><?php echo $diff;?></xmp></div>
|
||||
<?php include '../../common/view/footer.lite.html.php';?>
|
||||
|
||||
@@ -152,6 +152,8 @@ class task extends control
|
||||
|
||||
/* Set Custom*/
|
||||
foreach(explode(',', $this->config->task->customCreateFields) as $field) $customFields[$field] = $this->lang->task->$field;
|
||||
if($project->type == 'ops') unset($customFields['story']);
|
||||
|
||||
$this->view->customFields = $customFields;
|
||||
$this->view->showFields = $this->config->task->custom->createFields;
|
||||
|
||||
@@ -1172,14 +1174,17 @@ class task extends control
|
||||
*/
|
||||
public function export($projectID, $orderBy)
|
||||
{
|
||||
$project = $this->project->getById($projectID);
|
||||
$allExportFields = $this->config->task->exportFields;
|
||||
if($project->type == 'ops') $allExportFields = str_replace(' story,', '', $allExportFields);
|
||||
|
||||
if($_POST)
|
||||
{
|
||||
$this->loadModel('file');
|
||||
$taskLang = $this->lang->task;
|
||||
$taskConfig = $this->config->task;
|
||||
$taskLang = $this->lang->task;
|
||||
|
||||
/* Create field lists. */
|
||||
$fields = $this->post->exportFields ? $this->post->exportFields : explode(',', $taskConfig->exportFields);
|
||||
$fields = $this->post->exportFields ? $this->post->exportFields : explode(',', $allExportFields);
|
||||
foreach($fields as $key => $fieldName)
|
||||
{
|
||||
$fieldName = trim($fieldName);
|
||||
@@ -1286,7 +1291,7 @@ class task extends control
|
||||
$this->fetch('file', 'export2' . $this->post->fileType, $_POST);
|
||||
}
|
||||
|
||||
$this->view->allExportFields = $this->config->task->exportFields;
|
||||
$this->view->allExportFields = $allExportFields;
|
||||
$this->view->customExport = true;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<div class='heading'>
|
||||
<span class='prefix'><?php echo html::icon($lang->icons['task']);?></span>
|
||||
<strong><small class='text-muted'><?php echo html::icon($lang->icons['batchCreate']);?></small> <?php echo $lang->task->batchCreate;?></strong>
|
||||
<span><small><a href='javascript:toggleZeroTaskStory();' id='zeroTaskStory'><?php echo $lang->story->zeroTask;?><i class='icon icon-remove'></i></a></small></span>
|
||||
<?php if($project->type != 'ops'):?><span><small><a href='javascript:toggleZeroTaskStory();' id='zeroTaskStory'><?php echo $lang->story->zeroTask;?><i class='icon icon-remove'></i></a></small></span><?php endif;?>
|
||||
<div class='actions'>
|
||||
<?php echo html::commonButton($lang->pasteText, "data-toggle='myModal'", 'btn btn-primary')?>
|
||||
<button type="button" class="btn btn-default" data-toggle="customModal"><i class='icon icon-cog'></i> </button>
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
<div class='actions'> <?php if(!$task->deleted) echo $actionLinks;?></div>
|
||||
<fieldset id='commentBox' class='hide'>
|
||||
<legend><?php echo $lang->comment;?></legend>
|
||||
<form method='post' action='<?php echo inlink('edit', "taskID=$task->id&comment=true")?>'>
|
||||
<form method='post' action='<?php echo $this->createLink('action', 'comment', "objectType=task&objectID=$task->id")?>' target='hiddenwin'>
|
||||
<div class="form-group"><?php echo html::textarea('comment', '',"rows='5' class='w-p100'");?></div>
|
||||
<?php echo html::submitButton() . html::backButton();?>
|
||||
</form>
|
||||
|
||||
+137
-111
@@ -15,7 +15,7 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Construct function, load product, tree, user auto.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -31,7 +31,7 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Index page.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -61,8 +61,8 @@ class testcase extends control
|
||||
$browseType = strtolower($browseType);
|
||||
|
||||
/* Set browseType, productID, moduleID and queryID. */
|
||||
$productID = $this->product->saveState($productID, $this->products);
|
||||
$branch = ($branch === '') ? (int)$this->cookie->preBranch : (int)$branch;
|
||||
$productID = $this->product->saveState($productID, $this->products);
|
||||
$branch = ($branch === '') ? (int)$this->cookie->preBranch : (int)$branch;
|
||||
setcookie('preProductID', $productID, $this->config->cookieLife, $this->config->webRoot);
|
||||
setcookie('preBranch', (int)$branch, $this->config->cookieLife, $this->config->webRoot);
|
||||
|
||||
@@ -75,9 +75,9 @@ class testcase extends control
|
||||
if($browseType == 'bysuite') setcookie('caseSuite', (int)$param, $this->config->cookieLife, $this->config->webRoot);
|
||||
if($browseType != 'bymodule') $this->session->set('caseBrowseType', $browseType);
|
||||
|
||||
$moduleID = ($browseType == 'bymodule') ? (int)$param : ($browseType == 'bysearch' ? 0 : ($this->cookie->caseModule ? $this->cookie->caseModule : 0));
|
||||
$suiteID = ($browseType == 'bysuite') ? (int)$param : ($browseType == 'bymodule' ? ($this->cookie->caseSuite ? $this->cookie->caseSuite : 0) : 0);
|
||||
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
|
||||
$moduleID = ($browseType == 'bymodule') ? (int)$param : ($browseType == 'bysearch' ? 0 : ($this->cookie->caseModule ? $this->cookie->caseModule : 0));
|
||||
$suiteID = ($browseType == 'bysuite') ? (int)$param : ($browseType == 'bymodule' ? ($this->cookie->caseSuite ? $this->cookie->caseSuite : 0) : 0);
|
||||
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
|
||||
|
||||
/* Set menu, save session. */
|
||||
$this->testcase->setMenu($this->products, $productID, $branch, $moduleID, $suiteID);
|
||||
@@ -93,7 +93,7 @@ class testcase extends control
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = pager::init($recTotal, $recPerPage, $pageID);
|
||||
$sort = $this->loadModel('common')->appendOrder($orderBy);
|
||||
$sort = $this->loadModel('common')->appendOrder($orderBy);
|
||||
|
||||
/* Get test cases. */
|
||||
$cases = $this->testcase->getTestCases($productID, $branch, $browseType, $browseType == 'bysearch' ? $queryID : $suiteID, $moduleID, $sort, $pager);
|
||||
@@ -141,9 +141,9 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Group case.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $groupBy
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $groupBy
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -173,21 +173,21 @@ class testcase extends control
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->common;
|
||||
$this->view->position[] = html::a($this->createLink('testcase', 'groupTask', "productID=$productID&groupBy=$groupBy"), $this->products[$productID]);
|
||||
$this->view->position[] = $this->lang->testcase->common;
|
||||
$this->view->productID = $productID;
|
||||
$this->view->productName = $this->products[$productID];
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->browseType = 'group';
|
||||
$this->view->groupBy = $groupBy;
|
||||
$this->view->orderBy = $groupBy;
|
||||
$this->view->groupByList = $groupByList;
|
||||
$this->view->cases = $groupCases;
|
||||
$this->view->suiteList = $this->loadModel('testsuite')->getSuites($productID);
|
||||
$this->view->suiteID = 0;
|
||||
$this->view->moduleID = 0;
|
||||
$this->view->branch = $branch;
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->common;
|
||||
$this->view->position[] = html::a($this->createLink('testcase', 'groupTask', "productID=$productID&groupBy=$groupBy"), $this->products[$productID]);
|
||||
$this->view->position[] = $this->lang->testcase->common;
|
||||
$this->view->productID = $productID;
|
||||
$this->view->productName = $this->products[$productID];
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->browseType = 'group';
|
||||
$this->view->groupBy = $groupBy;
|
||||
$this->view->orderBy = $groupBy;
|
||||
$this->view->groupByList = $groupByList;
|
||||
$this->view->cases = $groupCases;
|
||||
$this->view->suiteList = $this->loadModel('testsuite')->getSuites($productID);
|
||||
$this->view->suiteID = 0;
|
||||
$this->view->moduleID = 0;
|
||||
$this->view->branch = $branch;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -286,13 +286,13 @@ class testcase extends control
|
||||
/* If bugID large than 0, use this bug as template. */
|
||||
if($bugID > 0)
|
||||
{
|
||||
$bug = $this->loadModel('bug')->getById($bugID);
|
||||
$type = $bug->type;
|
||||
$pri = $bug->pri ? $bug->pri : $bug->severity;
|
||||
$storyID = $bug->story;
|
||||
$caseTitle= $bug->title;
|
||||
$keywords = $bug->keywords;
|
||||
$steps = $this->testcase->createStepsFromBug($bug->steps);
|
||||
$bug = $this->loadModel('bug')->getById($bugID);
|
||||
$type = $bug->type;
|
||||
$pri = $bug->pri ? $bug->pri : $bug->severity;
|
||||
$storyID = $bug->story;
|
||||
$caseTitle = $bug->title;
|
||||
$keywords = $bug->keywords;
|
||||
$steps = $this->testcase->createStepsFromBug($bug->steps);
|
||||
}
|
||||
|
||||
/* Padding the steps to the default steps count. */
|
||||
@@ -428,9 +428,9 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Create bug.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $extras
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $extras
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -453,20 +453,20 @@ class testcase extends control
|
||||
|
||||
if(!$case) die(js::error($this->lang->notFound) . js::locate('back', 'parent'));
|
||||
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->createBug;
|
||||
$this->view->runID = $runID;
|
||||
$this->view->case = $case;
|
||||
$this->view->caseID = $caseID;
|
||||
$this->view->version = $version;
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->createBug;
|
||||
$this->view->runID = $runID;
|
||||
$this->view->case = $case;
|
||||
$this->view->caseID = $caseID;
|
||||
$this->view->version = $version;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* View a test case.
|
||||
*
|
||||
* @param int $caseID
|
||||
* @param int $version
|
||||
* @param string $from
|
||||
*
|
||||
* @param int $caseID
|
||||
* @param int $version
|
||||
* @param string $from
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -527,8 +527,8 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Edit a case.
|
||||
*
|
||||
* @param int $caseID
|
||||
*
|
||||
* @param int $caseID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -586,9 +586,9 @@ class testcase extends control
|
||||
}
|
||||
else
|
||||
{
|
||||
$productID = $case->product;
|
||||
$title = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->edit;
|
||||
$position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
$productID = $case->product;
|
||||
$title = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->edit;
|
||||
$position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
|
||||
/* Set menu. */
|
||||
$this->testcase->setMenu($this->products, $productID, $case->branch);
|
||||
@@ -615,21 +615,21 @@ class testcase extends control
|
||||
$position[] = $this->lang->testcase->common;
|
||||
$position[] = $this->lang->testcase->edit;
|
||||
|
||||
$this->view->title = $title;
|
||||
$this->view->position = $position;
|
||||
$this->view->currentModuleID = $case->module;
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->case = $case;
|
||||
$this->view->actions = $this->loadModel('action')->getList('case', $caseID);
|
||||
$this->view->isLibCase = $isLibCase;
|
||||
$this->view->title = $title;
|
||||
$this->view->position = $position;
|
||||
$this->view->currentModuleID = $case->module;
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->case = $case;
|
||||
$this->view->actions = $this->loadModel('action')->getList('case', $caseID);
|
||||
$this->view->isLibCase = $isLibCase;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch edit case.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -728,7 +728,8 @@ class testcase extends control
|
||||
if($showSuhosinInfo) $this->view->suhosinInfo = extension_loaded('suhosin') ? sprintf($this->lang->suhosinInfo, $countInputVars) : sprintf($this->lang->maxVarsInfo, $countInputVars);
|
||||
|
||||
$this->loadModel('story');
|
||||
$this->view->stories = $this->story->getProductStoryPairs($productID, $branch);
|
||||
$stories = $this->story->getProductStoryPairs($productID, $branch);
|
||||
$this->view->stories = array('' => '', 'ditto' => $this->lang->testcase->ditto) + $stories;
|
||||
|
||||
/* Set custom. */
|
||||
foreach(explode(',', $this->config->testcase->customBatchEditFields) as $field) $customFields[$field] = $this->lang->testcase->$field;
|
||||
@@ -750,8 +751,8 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Review case.
|
||||
*
|
||||
* @param int $caseID
|
||||
*
|
||||
* @param int $caseID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -761,7 +762,7 @@ class testcase extends control
|
||||
{
|
||||
$this->testcase->review($caseID);
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
$result = $this->post->result;
|
||||
$result = $this->post->result;
|
||||
$this->loadModel('action')->create('case', $caseID, 'Reviewed', $this->post->comment, ucfirst($result));
|
||||
die(js::reload('parent.parent'));
|
||||
}
|
||||
@@ -774,8 +775,8 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Batch review case.
|
||||
*
|
||||
* @param string $result
|
||||
*
|
||||
* @param string $result
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -791,8 +792,8 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Delete a test case
|
||||
*
|
||||
* @param int $caseID
|
||||
*
|
||||
* @param int $caseID
|
||||
* @param string $confirm yes|noe
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -828,8 +829,8 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Batch delete cases.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -842,6 +843,33 @@ class testcase extends control
|
||||
die(js::locate($this->session->caseList));
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch change branch.
|
||||
*
|
||||
* @param int $branchID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function batchChangeBranch($branchID)
|
||||
{
|
||||
if($this->post->caseIDList)
|
||||
{
|
||||
$caseIDList = $this->post->caseIDList;
|
||||
$caseIDList = array_unique($caseIDList);
|
||||
unset($_POST['caseIDList']);
|
||||
$allChanges = $this->testcase->batchChangeBranch($caseIDList, $branchID);
|
||||
if(dao::isError()) die(js::error(dao::getError()));
|
||||
foreach($allChanges as $caseID => $changes)
|
||||
{
|
||||
$this->loadModel('action');
|
||||
$actionID = $this->action->create('case', $caseID, 'Edited');
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
}
|
||||
|
||||
die(js::locate($this->session->caseList, 'parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch change the module of case.
|
||||
*
|
||||
@@ -871,8 +899,8 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Batch review case.
|
||||
*
|
||||
* @param string $result
|
||||
*
|
||||
* @param string $result
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -973,9 +1001,9 @@ class testcase extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm testcase changed.
|
||||
*
|
||||
* @param int $caseID
|
||||
* Confirm testcase changed.
|
||||
*
|
||||
* @param int $caseID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -988,8 +1016,8 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Confirm story changes.
|
||||
*
|
||||
* @param int $caseID
|
||||
*
|
||||
* @param int $caseID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1003,8 +1031,8 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Batch ctory change cases.
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1018,11 +1046,11 @@ class testcase extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* export
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $orderBy
|
||||
* @param int $taskID
|
||||
* export
|
||||
*
|
||||
* @param int $productID
|
||||
* @param string $orderBy
|
||||
* @param int $taskID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1090,8 +1118,6 @@ class testcase extends control
|
||||
|
||||
foreach($cases as $case)
|
||||
{
|
||||
$case->title = htmlspecialchars_decode($case->title);
|
||||
|
||||
$relatedModuleIdList[$case->module] = $case->module;
|
||||
$relatedStoryIdList[$case->story] = $case->story;
|
||||
$relatedCaseIdList[$case->linkCase] = $case->linkCase;
|
||||
@@ -1134,8 +1160,8 @@ class testcase extends control
|
||||
}
|
||||
if($step->version != $case->version) continue;
|
||||
$sign = (in_array($this->post->fileType, array('html', 'xml'))) ? '<br />' : "\n";
|
||||
$case->stepDesc .= $stepId . ". " . htmlspecialchars_decode($step->desc) . $sign;
|
||||
$case->stepExpect .= $stepId . ". " . htmlspecialchars_decode($step->expect) . $sign;
|
||||
$case->stepDesc .= $stepId . ". " . $step->desc . $sign;
|
||||
$case->stepExpect .= $stepId . ". " . $step->expect . $sign;
|
||||
$childId ++;
|
||||
}
|
||||
}
|
||||
@@ -1196,9 +1222,9 @@ class testcase extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Export templet
|
||||
*
|
||||
* @param int $productID
|
||||
* Export templet
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1220,8 +1246,8 @@ class testcase extends control
|
||||
$fields['stage'] = $this->lang->testcase->stage;
|
||||
|
||||
$fields[''] = '';
|
||||
$fields['typeValue'] = $this->lang->testcase->lblTypeValue;
|
||||
$fields['stageValue'] = $this->lang->testcase->lblStageValue;
|
||||
$fields['typeValue'] = $this->lang->testcase->lblTypeValue;
|
||||
$fields['stageValue'] = $this->lang->testcase->lblStageValue;
|
||||
if($product->type != 'normal') $fields['branchValue'] = $this->lang->product->branchName[$product->type];
|
||||
|
||||
$branches = $this->loadModel('branch')->getPairs($productID);
|
||||
@@ -1257,9 +1283,9 @@ class testcase extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Import csv
|
||||
*
|
||||
* @param int $productID
|
||||
* Import csv
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1324,14 +1350,14 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Import case from lib.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param int $libID
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param int $libID
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1395,8 +1421,8 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Show import data
|
||||
*
|
||||
* @param int $productID
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1419,7 +1445,7 @@ class testcase extends control
|
||||
$fields = array_flip($fields);
|
||||
|
||||
$rows = $this->loadModel('file')->parseCSV($file);
|
||||
$header = array();
|
||||
$header = array();
|
||||
foreach($rows[0] as $i => $rowValue)
|
||||
{
|
||||
if(empty($rowValue)) break;
|
||||
@@ -1451,7 +1477,7 @@ class testcase extends control
|
||||
{
|
||||
$id = trim(substr($cellValue, strrpos($cellValue,'(#') + 2), ')');
|
||||
$case->$field = $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif(in_array($field, $caseConfig->export->listFields))
|
||||
{
|
||||
@@ -1568,10 +1594,10 @@ class testcase extends control
|
||||
|
||||
/**
|
||||
* Case bugs.
|
||||
*
|
||||
* @param int $runID
|
||||
* @param int $caseID
|
||||
* @param int $version
|
||||
*
|
||||
* @param int $runID
|
||||
* @param int $caseID
|
||||
* @param int $version
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
|
||||
@@ -541,13 +541,15 @@ class testcaseModel extends model
|
||||
else
|
||||
{
|
||||
/* Compare every step. */
|
||||
$i = 0;
|
||||
foreach($oldCase->steps as $key => $oldStep)
|
||||
{
|
||||
if(trim($oldStep->desc) != trim($steps[$key]['desc']) or trim($oldStep->expect) != $steps[$key]['expect'])
|
||||
if(trim($oldStep->desc) != trim($steps[$i]['desc']) or trim($oldStep->expect) != $steps[$i]['expect'])
|
||||
{
|
||||
$stepChanged = true;
|
||||
break;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
$version = $stepChanged ? $oldCase->version + 1 : $oldCase->version;
|
||||
@@ -762,13 +764,15 @@ class testcaseModel extends model
|
||||
if($data->pris[$caseID] == 'ditto') $data->pris[$caseID] = isset($prev['pri']) ? $prev['pri'] : 3;
|
||||
if($data->branches[$caseID] == 'ditto') $data->branches[$caseID] = isset($prev['branch']) ? $prev['branch'] : 0;
|
||||
if($data->modules[$caseID] == 'ditto') $data->modules[$caseID] = isset($prev['module']) ? $prev['module'] : 0;
|
||||
if($data->stories[$caseID] == 'ditto') $data->stories[$caseID] = isset($prev['story']) ? $prev['story'] : 0;
|
||||
if($data->types[$caseID] == 'ditto') $data->types[$caseID] = isset($prev['type']) ? $prev['type'] : '';
|
||||
if($data->stories[$caseID] == '') $data->stories[$caseID] = 0;
|
||||
|
||||
$prev['pri'] = $data->pris[$caseID];
|
||||
$prev['type'] = $data->types[$caseID];
|
||||
$prev['story'] = $data->stories[$caseID];
|
||||
$prev['branch'] = $data->branches[$caseID];
|
||||
$prev['module'] = $data->modules[$caseID];
|
||||
$prev['type'] = $data->types[$caseID];
|
||||
}
|
||||
|
||||
/* Initialize cases from the post data.*/
|
||||
@@ -817,6 +821,36 @@ class testcaseModel extends model
|
||||
return $allChanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch change branch.
|
||||
*
|
||||
* @param array $caseIDList
|
||||
* @param int $branchID
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function batchChangeBranch($caseIDList, $branchID)
|
||||
{
|
||||
$now = helper::now();
|
||||
$allChanges = array();
|
||||
$oldCases = $this->getByList($caseIDList);
|
||||
foreach($caseIDList as $caseID)
|
||||
{
|
||||
$oldCase = $oldCases[$caseID];
|
||||
if($branchID == $oldCase->branch) continue;
|
||||
|
||||
$case = new stdclass();
|
||||
$case->lastEditedBy = $this->app->user->account;
|
||||
$case->lastEditedDate = $now;
|
||||
$case->branch = $branchID;
|
||||
|
||||
$this->dao->update(TABLE_CASE)->data($case)->autoCheck()->where('id')->eq((int)$caseID)->exec();
|
||||
if(!dao::isError()) $allChanges[$caseID] = common::createChanges($oldCase, $case);
|
||||
}
|
||||
|
||||
return $allChanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch change the module of case.
|
||||
*
|
||||
|
||||
@@ -128,6 +128,23 @@ js::set('branch', $branch);
|
||||
$misc = common::hasPriv('testtask', 'batchRun') ? "onclick=\"setFormAction('$actionLink')\"" : $class;
|
||||
echo "<li>" . html::a('#', $lang->testtask->runCase, '', $misc) . "</li>";
|
||||
|
||||
if(common::hasPriv('testcase', 'batchChangeBranch') and $this->session->currentProductType != 'normal')
|
||||
{
|
||||
$withSearch = count($branches) > 8;
|
||||
echo "<li class='dropdown-submenu'>";
|
||||
echo html::a('javascript:;', $lang->product->branchName[$this->session->currentProductType], '', "id='branchItem'");
|
||||
echo "<div class='dropdown-menu" . ($withSearch ? ' with-search':'') . "'>";
|
||||
echo "<ul class='dropdown-list'>";
|
||||
foreach($branches as $branchID => $branchName)
|
||||
{
|
||||
$actionLink = $this->createLink('testcase', 'batchChangeBranch', "branchID=$branchID");
|
||||
echo "<li class='option' data-key='$branchID'>" . html::a('#', $branchName, '', "onclick=\"setFormAction('$actionLink', 'hiddenwin')\"") . "</li>";
|
||||
}
|
||||
echo '</ul>';
|
||||
if($withSearch) echo "<div class='menu-search'><div class='input-group input-group-sm'><input type='text' class='form-control' placeholder=''><span class='input-group-addon'><i class='icon-search'></i></span></div></div>";
|
||||
echo '</div></li>';
|
||||
}
|
||||
|
||||
if(common::hasPriv('testcase', 'batchChangeModule'))
|
||||
{
|
||||
$withSearch = count($modules) > 8;
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
<div class='actions'><?php echo $actionLinks;?></div>
|
||||
<fieldset id='commentBox' class='hide'>
|
||||
<legend><?php echo $lang->comment;?></legend>
|
||||
<form method='post' action='<?php echo inlink('edit', "caseID=$case->id&comment=true")?>'>
|
||||
<form method='post' action='<?php echo $this->createLink('action', 'comment', "objectType=case&objectID=$case->id")?>' target='hiddenwin'>
|
||||
<div class="form-group"><?php echo html::textarea('comment', '',"rows='5' class='w-p100'");?></div>
|
||||
<?php echo html::submitButton() . html::backButton();?>
|
||||
</form>
|
||||
|
||||
@@ -112,7 +112,7 @@ class treeModel extends model
|
||||
ksort($treeMenu);
|
||||
$topMenu = @array_shift($treeMenu);
|
||||
$topMenu = explode("\n", trim($topMenu));
|
||||
$lastMenu[] = '/';
|
||||
$lastMenu[] = in_array($type, array('bug', 'story')) ? '' : '/';
|
||||
foreach($topMenu as $menu)
|
||||
{
|
||||
if(!strpos($menu, '|')) continue;
|
||||
|
||||
@@ -182,7 +182,7 @@ $(function()
|
||||
{
|
||||
linkTemplate: '<?php echo helper::createLink('tree', 'browse', "rootID=$rootID&viewType=$viewType&moduleID={0}&branch={1}"); ?>',
|
||||
title: '<?php echo $viewType == 'line' ? '': $lang->tree->child ?>',
|
||||
template: '<a href="javascript:;"><?php echo $viewType == 'line' ? '': $lang->tree->child?></a>'
|
||||
template: '<a href="javascript:;"><?php echo $viewType == 'line' ? '': (strpos($viewType, 'doc') !== false ? $lang->doc->childType : $lang->tree->child)?></a>'
|
||||
}
|
||||
},
|
||||
action: function(event)
|
||||
|
||||
@@ -39,7 +39,7 @@ $lang->tutorial->tasks['createAccount']['nav'] = array('module' => 'user', 'met
|
||||
$lang->tutorial->tasks['createAccount']['desc'] = "<p>在系统创建一个新的用户帐号:</p><ul><li data-target='nav'>打开 <span class='task-nav'>组织 <i class='icon icon-angle-right'></i> 用户 <i class='icon icon-angle-right'></i> 添加用户</span> 页面;</li><li data-target='form'>在添加用户表单中填写新用户信息;</li><li data-target='submit'>保存用户信息。</li></ul>";
|
||||
|
||||
$lang->tutorial->tasks['createProduct'] = array('title' => '创建产品');
|
||||
$lang->tutorial->tasks['createProduct']['nav'] = array('module' => 'product', 'method' => 'create', 'menu' => 'create', 'form' => '#dataform', 'submit' => '#submit', 'targetPageName' => '新增产品');
|
||||
$lang->tutorial->tasks['createProduct']['nav'] = array('module' => 'product', 'method' => 'create', 'menu' => 'create', 'form' => '#dataform', 'submit' => '#submit', 'targetPageName' => '添加产品');
|
||||
$lang->tutorial->tasks['createProduct']['desc'] = "<p>在系统创建一个新的产品:</p><ul><li data-target='nav'>打开 <span class='task-nav'>产品 <i class='icon icon-angle-right'></i> 添加产品</span> 页面;</li><li data-target='form'>在表单中填写要创建的产品信息;</li><li data-target='submit'>保存产品信息。</li></ul>";
|
||||
|
||||
$lang->tutorial->tasks['createStory'] = array('title' => '创建需求');
|
||||
|
||||
@@ -1901,4 +1901,41 @@ class upgradeModel extends model
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change limited name.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function changeLimitedName()
|
||||
{
|
||||
$this->app->loadLang('install');
|
||||
$this->dao->update(TABLE_GROUP)->set('name')->eq($this->lang->install->groupList['LIMITED']['name'])
|
||||
->set('desc')->eq($this->lang->install->groupList['LIMITED']['desc'])
|
||||
->where('role')->eq('limited')
|
||||
->exec();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust Priv for 9.7
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function adjustPriv9_7()
|
||||
{
|
||||
$groups = $this->dao->select('*')->from(TABLE_GROUPPRIV)->where('method')->eq('edit')->andWhere('module')->in('story,task,bug,testcase')->fetchPairs('group', 'group');
|
||||
foreach($groups as $groupID)
|
||||
{
|
||||
$groupPriv = new stdclass();
|
||||
$groupPriv->group = $groupID;
|
||||
$groupPriv->module = 'action';
|
||||
$groupPriv->method = 'comment';
|
||||
$this->dao->replace(TABLE_GROUPPRIV)->data($groupPriv)->exec();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user