resolve conflict
This commit is contained in:
@@ -0,0 +1 @@
|
||||
ALTER TABLE `zt_effort` ADD `extra` text COLLATE 'utf8_general_ci' NOT NULL AFTER `end`;
|
||||
@@ -6554,6 +6554,7 @@ ALTER TABLE `zt_effort` CHANGE `begin` `begin` smallint(4) unsigned zerofill NOT
|
||||
ALTER TABLE `zt_effort` CHANGE `end` `end` smallint(4) unsigned zerofill NOT NULL AFTER `begin`;
|
||||
ALTER TABLE `zt_effort` ADD `deleted` enum('0','1') NOT NULL DEFAULT '0' AFTER `end`;
|
||||
ALTER TABLE `zt_effort` ADD `order` tinyint unsigned NOT NULL DEFAULT '0' AFTER `end`;
|
||||
ALTER TABLE `zt_effort` ADD `extra` text COLLATE 'utf8_general_ci' NULL AFTER `end`;
|
||||
ALTER TABLE `zt_effort` ADD INDEX `execution` (`execution`);
|
||||
ALTER TABLE `zt_effort` ADD INDEX `objectID` (`objectID`);
|
||||
ALTER TABLE `zt_effort` ADD INDEX `date` (`date`);
|
||||
@@ -7178,6 +7179,7 @@ CREATE TABLE IF NOT EXISTS `zt_ticket` (
|
||||
key `product` (`product`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_ticketsource`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_ticketsource` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ticketId` mediumint(8) unsigned NOT NULL,
|
||||
@@ -7189,6 +7191,7 @@ CREATE TABLE IF NOT EXISTS `zt_ticketsource` (
|
||||
key `ticketId` (`ticketId`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_ticketrelation`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_ticketrelation` (
|
||||
`id` mediumint unsigned NOT NULL AUTO_INCREMENT,
|
||||
`ticketId` mediumint unsigned NOT NULL,
|
||||
|
||||
@@ -600,7 +600,6 @@ class baseControl
|
||||
|
||||
if(!empty($jsExtPath))
|
||||
{
|
||||
$realModulePath = realPath($modulePath);
|
||||
foreach($jsExtPath as $jsPath)
|
||||
{
|
||||
if(empty($jsPath)) continue;
|
||||
@@ -730,7 +729,7 @@ class baseControl
|
||||
chdir(dirname($viewFile));
|
||||
|
||||
/**
|
||||
* 使用extract安定ob方法渲染$viewFile里面的代码。
|
||||
* 使用extract和ob方法渲染$viewFile里面的代码。
|
||||
* Use extract and ob functions to eval the codes in $viewFile.
|
||||
*/
|
||||
extract((array)$this->view);
|
||||
|
||||
@@ -87,7 +87,7 @@ class baseHelper
|
||||
/* 生成url链接的开始部分。Set the begin parts of the link. */
|
||||
if($config->requestType == 'PATH_INFO') $link = $config->webRoot . $appName;
|
||||
if($config->requestType != 'PATH_INFO') $link = $config->webRoot . $appName . basename($_SERVER['SCRIPT_NAME']);
|
||||
if($config->requestType == 'PATH_INFO2') $link .= '/';
|
||||
if($config->requestType == 'PATH_INFO2') $link = '/';
|
||||
|
||||
/**
|
||||
* #1: RequestType为GET。When the requestType is GET.
|
||||
@@ -178,7 +178,7 @@ class baseHelper
|
||||
* Check in only body mode or not.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public static function inOnlyBodyMode()
|
||||
{
|
||||
@@ -464,7 +464,7 @@ class baseHelper
|
||||
|
||||
$agent = $_SERVER["HTTP_USER_AGENT"];
|
||||
|
||||
/* Chrome should checked before safari.*/
|
||||
/* Chrome should check before safari.*/
|
||||
if(strpos($agent, 'Firefox') !== false) $browser['name'] = "firefox";
|
||||
if(strpos($agent, 'Opera') !== false) $browser['name'] = 'opera';
|
||||
if(strpos($agent, 'Safari') !== false) $browser['name'] = 'safari';
|
||||
@@ -853,7 +853,7 @@ function a($var)
|
||||
* Judge the server ip is local or not.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
function isLocalIP()
|
||||
{
|
||||
@@ -954,33 +954,42 @@ function htmlSpecialString($string, $flags = '', $encoding = 'UTF-8')
|
||||
return htmlspecialchars($string, $flags, $encoding);
|
||||
}
|
||||
|
||||
if (!function_exists('array_column'))
|
||||
if(!function_exists('array_column'))
|
||||
{
|
||||
function array_column(array $input, $columnKey, $indexKey = null)
|
||||
{
|
||||
$output = array();
|
||||
|
||||
foreach ($input as $row) {
|
||||
$key = $value = null;
|
||||
foreach($input as $row)
|
||||
{
|
||||
$key = $value = null;
|
||||
$keySet = $valueSet = false;
|
||||
|
||||
if (null !== $indexKey && array_key_exists($indexKey, $row)) {
|
||||
if(null !== $indexKey && array_key_exists($indexKey, $row))
|
||||
{
|
||||
$keySet = true;
|
||||
$key = (string) $row[$indexKey];
|
||||
$key = (string) $row[$indexKey];
|
||||
}
|
||||
|
||||
if (null === $columnKey) {
|
||||
if(null === $columnKey)
|
||||
{
|
||||
$valueSet = true;
|
||||
$value = $row;
|
||||
} elseif (\is_array($row) && \array_key_exists($columnKey, $row)) {
|
||||
$value = $row;
|
||||
}
|
||||
elseif(\is_array($row) && \array_key_exists($columnKey, $row))
|
||||
{
|
||||
$valueSet = true;
|
||||
$value = $row[$columnKey];
|
||||
$value = $row[$columnKey];
|
||||
}
|
||||
|
||||
if ($valueSet) {
|
||||
if ($keySet) {
|
||||
if($valueSet)
|
||||
{
|
||||
if($keySet)
|
||||
{
|
||||
$output[$key] = $value;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$output[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1719,7 +1719,7 @@ class baseRouter
|
||||
}
|
||||
|
||||
/* 1. 如果extensionLevel == 2,且扩展文件存在,返回该站点扩展文件。 If extensionLevel == 2 and site extensionFile exists, return it. */
|
||||
if($this->config->framework->extensionLevel == 2 and !empty( $moduleExtPaths['site']))
|
||||
if($this->config->framework->extensionLevel == 2 and !empty($moduleExtPaths['site']))
|
||||
{
|
||||
$this->extActionFile = $moduleExtPaths['site'] . $this->methodName . '.php';
|
||||
if(file_exists($this->extActionFile)) return true;
|
||||
@@ -1757,7 +1757,7 @@ class baseRouter
|
||||
if(empty($moduleExtPaths)) return false;
|
||||
|
||||
/* 如果extensionLevel == 2,且扩展文件存在,返回该站点扩展文件。If extensionLevel == 2 and site extensionFile exists, return it. */
|
||||
if($this->config->framework->extensionLevel == 2 and !empty( $moduleExtPaths['site']))
|
||||
if($this->config->framework->extensionLevel == 2 and !empty($moduleExtPaths['site']))
|
||||
{
|
||||
$locateFile = $moduleExtPaths['site'] . $this->methodName . '.302';
|
||||
if(file_exists($locateFile)) $this->sendAPI($locateFile);
|
||||
@@ -2497,9 +2497,8 @@ class baseRouter
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $appName app name
|
||||
* @param bool $exitIfNone exit or not
|
||||
* @access public
|
||||
* @return object|bool the config object or false.
|
||||
* @return void
|
||||
*/
|
||||
public function loadModuleConfig($moduleName, $appName = '')
|
||||
{
|
||||
@@ -2525,7 +2524,7 @@ class baseRouter
|
||||
if(!empty($extConfigPath['saas'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['saas'], '.php'));
|
||||
if(!empty($extConfigPath['custom'])) $commonExtConfigFiles = array_merge($commonExtConfigFiles, helper::ls($extConfigPath['custom'], '.php'));
|
||||
}
|
||||
if($config->framework->extensionLevel == 2 and !empty($extConfigPath['site'])) $siteExtConfigFiles = helper::ls($extConfigPath['site'], '.php');
|
||||
if($config->framework->extensionLevel == 2 and !empty($extConfigPath['site'])) $siteExtConfigFiles = helper::ls($extConfigPath['site'], '.php');
|
||||
$extConfigFiles = array_merge($commonExtConfigFiles, $siteExtConfigFiles);
|
||||
|
||||
/* 将主配置文件和扩展配置文件合并在一起。Put the main config file and extension config files together. */
|
||||
@@ -2690,12 +2689,12 @@ class baseRouter
|
||||
if($this->config->framework->extensionLevel >= 1)
|
||||
{
|
||||
if(!empty($extLangPath['common'])) $commonExtLangFiles = helper::ls($extLangPath['common'] . $this->clientLang, '.php');
|
||||
if(!empty($extLangPath['xuan'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['xuan'] . $this->clientLang, '.php'));
|
||||
if(!empty($extLangPath['xuan'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['xuan'] . $this->clientLang, '.php'));
|
||||
if(!empty($extLangPath['vision'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['vision'] . $this->clientLang, '.php'));
|
||||
if(!empty($extLangPath['custom'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['custom'] . $this->clientLang, '.php'));
|
||||
if(!empty($extLangPath['saas'])) $commonExtLangFiles = array_merge($commonExtLangFiles, helper::ls($extLangPath['saas'] . $this->clientLang, '.php'));
|
||||
}
|
||||
if($this->config->framework->extensionLevel == 2 and !empty($extLangPath['site'])) $siteExtLangFiles = helper::ls($extLangPath['site'] . $this->clientLang, '.php');
|
||||
if($this->config->framework->extensionLevel == 2 and !empty($extLangPath['site'])) $siteExtLangFiles = helper::ls($extLangPath['site'] . $this->clientLang, '.php');
|
||||
$extLangFiles = array_merge($commonExtLangFiles, $siteExtLangFiles);
|
||||
}
|
||||
|
||||
|
||||
@@ -315,9 +315,8 @@ class router extends baseRouter
|
||||
*
|
||||
* @param string $moduleName module name
|
||||
* @param string $appName app name
|
||||
* @param bool $exitIfNone exit or not
|
||||
* @access public
|
||||
* @return object|bool the config object or false.
|
||||
* @return void
|
||||
*/
|
||||
public function loadModuleConfig($moduleName, $appName = '')
|
||||
{
|
||||
|
||||
@@ -62,7 +62,7 @@ $config->action->majorList['project'] = array('opened', 'edited');
|
||||
$config->action->majorList['execution'] = array('opened', 'edited');
|
||||
|
||||
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
|
||||
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,module,';
|
||||
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,module,review,';
|
||||
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,gitea,gogs,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,';
|
||||
$config->action->ignoreObjectType4Dynamic = 'kanbanregion,kanbanlane,kanbancolumn';
|
||||
|
||||
|
||||
@@ -287,6 +287,15 @@ class actionModel extends model
|
||||
if(strpos(',deleted,', ",$actionType,") !== false) $module = $this->dao->select('*')->from(TABLE_MODULE)->where('id')->eq($objectID)->fetch();
|
||||
if(!empty($module) and $module->type == 'story') $record['product'] = $module->root;
|
||||
break;
|
||||
case 'review':
|
||||
$result = $this->dao->select('*')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch();
|
||||
if($result)
|
||||
{
|
||||
$products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($result->project)->fetchPairs('product');
|
||||
$record['product'] = join(',', array_keys($products));
|
||||
$record['project'] = zget($result, 'project', 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$result = $this->dao->select('*')->from($this->config->objectTables[$objectType])->where('id')->eq($objectID)->fetch();
|
||||
$record['product'] = zget($result, 'product', '0');
|
||||
|
||||
@@ -488,7 +488,7 @@ class bug extends control
|
||||
$steps = $this->lang->bug->tplStep . $this->lang->bug->tplResult . $this->lang->bug->tplExpect;
|
||||
$os = '';
|
||||
$browser = '';
|
||||
$assignedTo = '';
|
||||
$assignedTo = isset($currentProduct->QD) ? $currentProduct->QD : '';
|
||||
$deadline = '';
|
||||
$mailto = '';
|
||||
$keywords = '';
|
||||
@@ -2504,9 +2504,9 @@ class bug extends control
|
||||
|
||||
/**
|
||||
* Ajax get released builds.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int|string $branch
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int|string $branch
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
|
||||
@@ -335,6 +335,7 @@ class build extends control
|
||||
$this->view->type = $type;
|
||||
$this->view->bugPager = $bugPager;
|
||||
$this->view->branchName = $branchName;
|
||||
$this->view->childBuilds = empty($build->builds) ? array() : $this->dao->select('id,name,bugs,stories')->from(TABLE_BUILD)->where('id')->in($build->builds)->fetchAll();
|
||||
|
||||
if($this->app->getViewType() == 'json')
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.linkBox #queryBox .search-form .form-actions {padding-bottom: 5px;}
|
||||
.linkBox .table-header {padding: 8px 15px; border-bottom: 1px solid #cbd0db;}
|
||||
#unlinkStoryList, #unlinkBugList {border-top: 1px solid #cbd0db;}
|
||||
.page-title .dropdown-menu {top: 20px; left: 170px;}
|
||||
.page-title .dropdown-menu {top: 20px; left: 170px; max-height:300px; overflow:auto;}
|
||||
.page-title .text>a {font-weight: 700;}
|
||||
|
||||
.body-modal #mainContent {min-height: 200px;}
|
||||
|
||||
@@ -661,8 +661,8 @@ class buildModel extends model
|
||||
{
|
||||
$build->allBugs = $build->bugs;
|
||||
$build->allStories = $build->stories;
|
||||
$childBuilds = $this->dao->select('bugs, stories')->from(TABLE_BUILD)->where('id')->in($build->builds)->fetchAll();
|
||||
|
||||
$childBuilds = $this->dao->select('id,name,bugs,stories')->from(TABLE_BUILD)->where('id')->in($build->builds)->fetchAll();
|
||||
foreach($childBuilds as $childBuild)
|
||||
{
|
||||
if($childBuild->bugs) $build->allBugs .= ",{$childBuild->bugs}";
|
||||
@@ -720,7 +720,7 @@ class buildModel extends model
|
||||
{
|
||||
$executionID = $tab == 'execution' ? $extraParams['executionID'] : $build->execution;
|
||||
$execution = $this->loadModel('execution')->getByID($executionID);
|
||||
$build->executionDeleted = $execution ? $execution->deleted : 0;
|
||||
$build->executionDeleted = $execution ? $execution->deleted : 0;
|
||||
|
||||
$testtaskApp = (!empty($execution->type) and $execution->type == 'kanban') ? 'data-app="qa"' : "data-app='{$tab}'";
|
||||
|
||||
|
||||
@@ -88,8 +88,11 @@ tbody tr td:first-child input {display: none;}
|
||||
<?php endif;?>
|
||||
<?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?>
|
||||
</th>
|
||||
<th class='c-id' title=<?php echo $lang->pri;?>><?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
|
||||
<th class='c-pri' title=<?php echo $lang->pri;?>><?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
|
||||
<th class='text-left'><?php common::printOrderLink('title', $orderBy, $vars, $lang->story->title);?></th>
|
||||
<?php if($childBuilds):?>
|
||||
<th class='c-build w-200px text-left'><?php echo $lang->build->common;?></th>
|
||||
<?php endif;?>
|
||||
<th class='c-user'><?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='c-id text-right'><?php common::printOrderLink('estimate', $orderBy, $vars, $lang->story->estimateAB);?></th>
|
||||
<th class='c-status'><?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
|
||||
@@ -99,7 +102,21 @@ tbody tr td:first-child input {display: none;}
|
||||
</thead>
|
||||
<tbody class='text-center'>
|
||||
<?php foreach($stories as $storyID => $story):?>
|
||||
<?php $unlinkClass = strpos(",$build->stories,", ",$story->id,") !== false ? '' : "disabled";?>
|
||||
<?php
|
||||
$unlinkClass = strpos(",$build->stories,", ",$story->id,") !== false ? '' : "disabled";
|
||||
$buildName = $build->name;
|
||||
if($unlinkClass == 'disabled')
|
||||
{
|
||||
foreach($childBuilds as $childBuild)
|
||||
{
|
||||
if(strpos(",$childBuild->stories,", ",$story->id,") !== false)
|
||||
{
|
||||
$buildName = $childBuild->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td class='c-id text-left'>
|
||||
<?php if($canBatchUnlink):?>
|
||||
@@ -130,6 +147,9 @@ tbody tr td:first-child input {display: none;}
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<?php if($childBuilds):?>
|
||||
<td class='text-left' title='<?php echo $buildName?>'><?php echo $buildName;?></td>
|
||||
<?php endif;?>
|
||||
<td><?php echo zget($users, $story->openedBy);?></td>
|
||||
<td class='text-right' title="<?php echo $story->estimate . ' ' . $lang->hourCommon;?>"><?php echo $story->estimate . $config->hourUnit;?></td>
|
||||
<td>
|
||||
@@ -190,6 +210,9 @@ tbody tr td:first-child input {display: none;}
|
||||
</th>
|
||||
<th class='text-left'> <?php common::printOrderLink('title', $orderBy, $vars, $lang->bug->title);?></th>
|
||||
<th class='c-status'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->bug->status);?></th>
|
||||
<?php if($childBuilds):?>
|
||||
<th class='c-build w-200px text-left'><?php echo $lang->build->common?></th>
|
||||
<?php endif;?>
|
||||
<th class='c-user'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='c-date'> <?php common::printOrderLink('openedDate', $orderBy, $vars, $lang->bug->openedDateAB);?></th>
|
||||
<th class='c-user'> <?php common::printOrderLink('resolvedBy', $orderBy, $vars, $lang->bug->resolvedByAB);?></th>
|
||||
@@ -199,8 +222,22 @@ tbody tr td:first-child input {display: none;}
|
||||
</thead>
|
||||
<tbody class='text-center'>
|
||||
<?php foreach($bugs as $bug):?>
|
||||
<?php $bugLink = $this->createLink('bug', 'view', "bugID=$bug->id", '', true);?>
|
||||
<?php $unlinkClass = strpos(",$build->bugs,", ",$bug->id,") !== false ? '' : "disabled";?>
|
||||
<?php $bugLink = $this->createLink('bug', 'view', "bugID=$bug->id", '', true);?>
|
||||
<?php
|
||||
$unlinkClass = strpos(",$build->bugs,", ",$bug->id,") !== false ? '' : "disabled";
|
||||
$buildName = $build->name;
|
||||
if($unlinkClass == 'disabled')
|
||||
{
|
||||
foreach($childBuilds as $childBuild)
|
||||
{
|
||||
if(strpos(",$childBuild->bugs,", ",$bug->id,") !== false)
|
||||
{
|
||||
$buildName = $childBuild->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td class='c-id text-left'>
|
||||
<?php if($canBatchUnlink):?>
|
||||
@@ -216,6 +253,9 @@ tbody tr td:first-child input {display: none;}
|
||||
<?php echo $this->processStatus('bug', $bug);?>
|
||||
</span>
|
||||
</td>
|
||||
<?php if($childBuilds):?>
|
||||
<td class='text-left' title='<?php echo $buildName?>'><?php echo $buildName;?></td>
|
||||
<?php endif;?>
|
||||
<td><?php echo zget($users, $bug->openedBy);?></td>
|
||||
<td><?php echo helper::isZeroDate($bug->openedDate) ? '' : substr($bug->openedDate, 5, 11);?></td>
|
||||
<td><?php echo zget($users, $bug->resolvedBy);?></td>
|
||||
@@ -261,6 +301,7 @@ tbody tr td:first-child input {display: none;}
|
||||
<th class='c-status' title=<?php echo $lang->bug->severity;?>><?php common::printOrderLink('severity', $orderBy, $vars, $lang->bug->severityAB);?></th>
|
||||
<th class='text-left'><?php common::printOrderLink('title', $orderBy, $vars, $lang->bug->title);?></th>
|
||||
<th class='c-status'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->bug->status);?></th>
|
||||
<th class='c-build w-200px text-left'><?php echo $lang->bug->openedBuild;?></th>
|
||||
<th class='c-user'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='c-date'> <?php common::printOrderLink('openedDate', $orderBy, $vars, $lang->bug->openedDateAB);?></th>
|
||||
<th class='c-user'> <?php common::printOrderLink('resolvedBy', $orderBy, $vars, $lang->bug->resolvedByAB);?></th>
|
||||
@@ -298,6 +339,11 @@ tbody tr td:first-child input {display: none;}
|
||||
<?php echo $this->processStatus('bug', $bug);?>
|
||||
</span>
|
||||
</td>
|
||||
<?php
|
||||
$openedBuilds = '';
|
||||
foreach(explode(',', $bug->openedBuild) as $buildID) $openedBuilds .= ($buildID == 'trunk' ? 'Trunk' : zget($buildPairs, $buildID, '')) . ' ';
|
||||
?>
|
||||
<td class='text-left' title='<?php echo $openedBuilds;?>'><?php echo $openedBuilds;?></td>
|
||||
<td><?php echo zget($users, $bug->openedBy);?></td>
|
||||
<td><?php echo helper::isZeroDate($bug->openedDate) ? '' : substr($bug->openedDate, 5, 11);?></td>
|
||||
<td><?php echo zget($users, $bug->resolvedBy);?></td>
|
||||
|
||||
@@ -1582,14 +1582,17 @@ class executionModel extends model
|
||||
->andWhere('type')->eq('execution')
|
||||
->fetchPairs();
|
||||
}
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
|
||||
$executions = $this->dao->select('t1.*,t2.name projectName, t2.model as projectModel')->from(TABLE_EXECUTION)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
|
||||
->beginIF($productID)->leftJoin(TABLE_PROJECTPRODUCT)->alias('t3')->on('t1.id=t3.project')->fi()
|
||||
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t3')->on('t1.id=t3.project')
|
||||
->beginIF($project->division)->leftJoin(TABLE_PRODUCT)->alias('t4')->on('t4.id=t3.product')->fi()
|
||||
->where('t1.type')->in('sprint,stage,kanban')
|
||||
->andWhere('t1.deleted')->eq('0')
|
||||
->andWhere('t1.vision')->eq($this->config->vision)
|
||||
->andWhere('t1.multiple')->eq('1')
|
||||
->beginIF($project->division)->andWhere('t4.deleted')->eq('0')->fi()
|
||||
->beginIF(!$this->app->user->admin)->andWhere('t1.id')->in($this->app->user->view->sprints)->fi()
|
||||
->beginIF(!empty($executionQuery))->andWhere($executionQuery)->fi()
|
||||
->beginIF($productID)->andWhere('t3.product')->eq($productID)->fi()
|
||||
|
||||
@@ -30,7 +30,7 @@ $config->productplan->search['fields']['end'] = $lang->productplan->end;
|
||||
|
||||
$config->productplan->search['params']['id'] = array('operator' => '=', 'control' => 'input', 'values' => '');
|
||||
$config->productplan->search['params']['title'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
|
||||
$config->productplan->search['params']['branch'] = array('operator' => '=', 'control' => 'select', 'values' => '');
|
||||
$config->productplan->search['params']['branch'] = array('operator' => 'include', 'control' => 'select', 'values' => '');
|
||||
$config->productplan->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => array('' => '') + $lang->productplan->statusList);
|
||||
$config->productplan->search['params']['begin'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
|
||||
$config->productplan->search['params']['end'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
|
||||
|
||||
@@ -117,7 +117,7 @@ class productplan extends control
|
||||
$this->view->branches = $branchPairs;
|
||||
$this->view->defaultBranch = $defaultBranch;
|
||||
$this->view->parent = $parent;
|
||||
$this->view->parentPlanPairs = $this->productplan->getTopPlanPairs($productID, '', 'done,closed');
|
||||
$this->view->parentPlanPairs = $this->productplan->getTopPlanPairs($productID, 'done,closed');
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -151,11 +151,19 @@ class productplan extends control
|
||||
$oldBranch = array($planID => $plan->branch);
|
||||
|
||||
/* Get the parent plan pair exclusion itself. */
|
||||
$parentPlanPairs = $this->productplan->getTopPlanPairs($plan->product, $plan->branch);
|
||||
$parentPlanPairs = $this->productplan->getTopPlanPairs($plan->product);
|
||||
unset($parentPlanPairs[$planID]);
|
||||
$this->view->parentPlanPairs = $parentPlanPairs;
|
||||
|
||||
$this->commonAction($plan->product, $plan->branch);
|
||||
|
||||
if($plan->parent)
|
||||
{
|
||||
$parentPlan = $this->productplan->getByID($plan->parent);
|
||||
$branchPairs = array();
|
||||
foreach(explode(',', $parentPlan->branch) as $parentBranchID) $branchPairs[$parentBranchID] = $this->view->branchTagOption[$parentBranchID];
|
||||
$this->view->branchTagOption = $branchPairs;
|
||||
}
|
||||
$this->view->title = $this->view->product->name . $this->lang->colon . $this->lang->productplan->edit;
|
||||
$this->view->position[] = $this->lang->productplan->edit;
|
||||
$this->view->productID = $plan->product;
|
||||
@@ -948,12 +956,17 @@ class productplan extends control
|
||||
*/
|
||||
public function ajaxGetConflict($planID, $newBranch)
|
||||
{
|
||||
if($newBranch == '') return;
|
||||
|
||||
$plan = $this->productplan->getByID($planID);
|
||||
$oldBranch = $plan->branch;
|
||||
$planStories = $this->loadModel('story')->getPlanStories($planID, 'all');
|
||||
$planBugs = $this->loadModel('bug')->getPlanBugs($planID, 'all');
|
||||
$branchPairs = $this->loadModel('branch')->getPairs($plan->product);
|
||||
|
||||
$removeBranches = '';
|
||||
foreach(explode(',', $oldBranch) as $oldBranchID)
|
||||
{
|
||||
if($oldBranchID and strpos(",$newBranch,", ",$oldBranchID,") === false) $removeBranches .= "{$branchPairs[$oldBranchID]},";
|
||||
}
|
||||
|
||||
$conflictStoryCounts = 0;
|
||||
$conflictBugCounts = 0;
|
||||
@@ -972,15 +985,15 @@ class productplan extends control
|
||||
|
||||
if($conflictStoryCounts and $conflictBugCounts)
|
||||
{
|
||||
printf($this->lang->productplan->confirmChangePlan, $conflictStoryCounts, $conflictBugCounts);
|
||||
printf($this->lang->productplan->confirmChangePlan, trim($removeBranches, ','), $conflictStoryCounts, $conflictBugCounts);
|
||||
}
|
||||
elseif($conflictStoryCounts)
|
||||
{
|
||||
printf($this->lang->productplan->confirmRemoveStory, $conflictStoryCounts);
|
||||
printf($this->lang->productplan->confirmRemoveStory, trim($removeBranches, ','), $conflictStoryCounts);
|
||||
}
|
||||
elseif($conflictBugCounts)
|
||||
{
|
||||
printf($this->lang->productplan->confirmRemoveBug, $conflictBugCounts);
|
||||
printf($this->lang->productplan->confirmRemoveBug, trim($removeBranches, ','), $conflictBugCounts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1000,19 +1013,28 @@ class productplan extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: Get top plan.
|
||||
* AJAX: Get parent branches.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param int $planID
|
||||
* @param int $parentID
|
||||
* @param string $currentBranches
|
||||
* @access public
|
||||
* @return object
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetTopPlan($productID, $branch = 0, $planID = 0)
|
||||
public function ajaxGetParentBranches($productID = 0, $parentID = 0, $currentBranches = '')
|
||||
{
|
||||
$parentPlanPairs = $this->productplan->getTopPlanPairs($productID, $branch);
|
||||
if(isset($parentPlanPairs[$planID])) unset($parentPlanPairs[$planID]);
|
||||
return print(html::select('parent', array(0 => '') + $parentPlanPairs, 0, 'class="form-control"'));
|
||||
$branchPairs = $this->loadModel('branch')->getPairs($productID, 'active');
|
||||
if(!empty($parentID))
|
||||
{
|
||||
$parentBranches = array();
|
||||
$parentPlan = $this->productplan->getByID($parentID);
|
||||
foreach(explode(',', $parentPlan->branch) as $parentBranchID)
|
||||
{
|
||||
$parentBranches[$parentBranchID] = $branchPairs[$parentBranchID];
|
||||
if(!empty($currentBranches) and strpos(",$currentBranches,", ",$parentBranchID,") === false) $currentBranches = str_replace(",$parentBranchID,", ',', $currentBranches);
|
||||
}
|
||||
}
|
||||
return print(html::select('branch[]', empty($parentID) ? $branchPairs : $parentBranches, trim($currentBranches, ','), "class='form-control chosen' multiple required"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,7 +63,20 @@ $('#future').on('change', function()
|
||||
}
|
||||
});
|
||||
|
||||
$('#branch').change(function()
|
||||
$('#parent').change(function()
|
||||
{
|
||||
var parentID = $(this).val();
|
||||
var currentBranches = $('#branch').val() ? $('#branch').val().toString() : '';
|
||||
$.post(createLink('productplan', 'ajaxGetParentBranches', "productID=" + productID + "&parentID=" + parentID + "¤tBranches=" + currentBranches), function(data)
|
||||
{
|
||||
$('#branch').replaceWith(data);
|
||||
$('#branch_chosen').remove();
|
||||
$('#branch').chosen();
|
||||
$('#branch').change();
|
||||
})
|
||||
})
|
||||
|
||||
$('#dataform').on('change', '#branch', function()
|
||||
{
|
||||
if(parentPlanID) return;
|
||||
|
||||
@@ -72,21 +85,12 @@ $('#branch').change(function()
|
||||
|
||||
var branchIdList = branchIdList.toString();
|
||||
var lastPlanLink = createLink('productplan', 'ajaxGetLast', "productID=" + productID + "&branch=" + branchIdList);
|
||||
var topPlanLink = createLink('productplan', 'ajaxGetTopPlan', "productID=" + productID + "&branch=" + branchIdList);
|
||||
|
||||
$.post(lastPlanLink, function(data)
|
||||
{
|
||||
data = JSON.parse(data);
|
||||
var planTitle = data ? '(' + lastLang + ': ' + data.title + ')' : '';
|
||||
$('#title').parent().next('td').html(planTitle);
|
||||
})
|
||||
|
||||
$.post(topPlanLink, function(data)
|
||||
{
|
||||
$('#parent').replaceWith(data);
|
||||
$('#parent_chosen').remove();
|
||||
$('#parent').chosen();
|
||||
})
|
||||
});
|
||||
|
||||
$('#submit').click(function()
|
||||
|
||||
@@ -13,14 +13,7 @@ function convertStringToDate(dateString)
|
||||
return Date.parse(dateString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get conflict stories.
|
||||
*
|
||||
* @param int $planID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function getConflictStories(planID)
|
||||
$('#dataform').on('change', '#branch', function()
|
||||
{
|
||||
var newBranch = $('#branch').val() ? $('#branch').val().toString() : '';
|
||||
$.get(createLink('productplan', 'ajaxGetConflict', 'planID=' + planID + '&newBranch=' + newBranch), function(conflictStories)
|
||||
@@ -30,21 +23,12 @@ function getConflictStories(planID)
|
||||
var result = confirm(conflictStories) ? true : false;
|
||||
if(!result)
|
||||
{
|
||||
newBranch = oldBranch[planID];
|
||||
$('#branch').val(oldBranch[planID].split(','));
|
||||
$('#branch').trigger("chosen:updated");
|
||||
}
|
||||
}
|
||||
|
||||
var link = createLink('productplan', 'ajaxGetTopPlan', "productID=" + productID + "&branch=" + newBranch + "&planID=" + planID);
|
||||
$.post(link, function(data)
|
||||
{
|
||||
$('#parent').replaceWith(data);
|
||||
$('#parent_chosen').remove();
|
||||
$('#parent').chosen();
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Compute the end date for productplan.
|
||||
@@ -72,6 +56,18 @@ function computeEndDate(delta)
|
||||
$('#end').val(endDate).datetimepicker('update');
|
||||
}
|
||||
|
||||
$('#parent').change(function()
|
||||
{
|
||||
var parentID = $(this).val();
|
||||
var currentBranches = $('#branch').val() ? $('#branch').val().toString() : '';
|
||||
$.post(createLink('productplan', 'ajaxGetParentBranches', "productID=" + productID + "&parentID=" + parentID + "¤tBranches=" + currentBranches), function(data)
|
||||
{
|
||||
$('#branch').replaceWith(data);
|
||||
$('#branch_chosen').remove();
|
||||
$('#branch').chosen();
|
||||
})
|
||||
})
|
||||
|
||||
$('#future').on('change', function()
|
||||
{
|
||||
if($(this).prop('checked'))
|
||||
|
||||
@@ -75,9 +75,9 @@ $lang->productplan->projectNotEmpty = 'Project cannot be empty.';
|
||||
$lang->productplan->nextStep = "Next step";
|
||||
$lang->productplan->summary = "Total: <strong>%s</strong>, Parents: <strong>%s</strong>, Children: <strong>%s</strong>,Independent: <strong>%s</strong>.";
|
||||
$lang->productplan->checkedSummary = "Seleted: <strong>%total%</strong>, Parents: <strong>%parent%</strong>, Children: <strong>%child%</strong>, Independent: <strong>%independent%</strong>.";
|
||||
$lang->productplan->confirmChangePlan = "After the branch is unlinked, %s {$lang->SRCommon} and %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveStory = "After the branch is unlinked, %s {$lang->SRCommon} under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveBug = "After the branch is unlinked, %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmChangePlan = "After the branch of『%s』is unlinked, %s {$lang->SRCommon} and %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveStory = "After the branch of『%s』is unlinked, %s {$lang->SRCommon} under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveBug = "After the branch of『%s』is unlinked, %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
|
||||
$lang->productplan->id = 'ID';
|
||||
$lang->productplan->product = $lang->productCommon;
|
||||
@@ -139,7 +139,7 @@ $lang->productplan->beginGreaterChildTip = "The start date of the parent plan[%s
|
||||
$lang->productplan->endLetterChildTip = "The completion date of the parent plan[%s]: %s, cannot be less than the completion date of the child plan: %s.";
|
||||
$lang->productplan->beginLetterParentTip = "The start date of the child plan[%s]: %s, cannot be less than the start date of the parent plan: %s.";
|
||||
$lang->productplan->endGreaterParentTip = "The completion date of the child plan[%s]: %s, cannot be greater than the completion date of the parent plan: %s.";
|
||||
$lang->productplan->diffBranchesTip = "The @branch@ %s of parent plan is not linked with the child plan. @branch@'s stories and bugs whill be removed from the plan. Do you want to save?";
|
||||
$lang->productplan->diffBranchesTip = "The @branch@『%s』 of parent plan is not linked with the child plan. @branch@'s stories and bugs whill be removed from the plan. Do you want to save?";
|
||||
|
||||
$lang->productplan->featureBar['browse']['all'] = 'Alle';
|
||||
$lang->productplan->featureBar['browse']['undone'] = 'Undone';
|
||||
|
||||
@@ -75,9 +75,9 @@ $lang->productplan->projectNotEmpty = 'Project cannot be empty.';
|
||||
$lang->productplan->nextStep = "Next step";
|
||||
$lang->productplan->summary = "Total: <strong>%s</strong>, Parents: <strong>%s</strong>, Children: <strong>%s</strong>,Independent: <strong>%s</strong>.";
|
||||
$lang->productplan->checkedSummary = "Seleted: <strong>%total%</strong>, Parents: <strong>%parent%</strong>, Children: <strong>%child%</strong>, Independent: <strong>%independent%</strong>.";
|
||||
$lang->productplan->confirmChangePlan = "After the branch is unlinked, %s {$lang->SRCommon} and %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveStory = "After the branch is unlinked, %s {$lang->SRCommon} under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveBug = "After the branch is unlinked, %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmChangePlan = "After the branch of『%s』is unlinked, %s {$lang->SRCommon} and %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveStory = "After the branch of『%s』is unlinked, %s {$lang->SRCommon} under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveBug = "After the branch of『%s』is unlinked, %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
|
||||
$lang->productplan->id = 'ID';
|
||||
$lang->productplan->product = $lang->productCommon;
|
||||
@@ -139,7 +139,7 @@ $lang->productplan->beginGreaterChildTip = "The start date of the parent plan[%s
|
||||
$lang->productplan->endLetterChildTip = "The completion date of the parent plan[%s]: %s, cannot be less than the completion date of the child plan: %s.";
|
||||
$lang->productplan->beginLetterParentTip = "The start date of the child plan[%s]: %s, cannot be less than the start date of the parent plan: %s.";
|
||||
$lang->productplan->endGreaterParentTip = "The completion date of the child plan[%s]: %s, cannot be greater than the completion date of the parent plan: %s.";
|
||||
$lang->productplan->diffBranchesTip = "The @branch@ %s of parent plan is not linked with the child plan. @branch@'s stories and bugs whill be removed from the plan. Do you want to save?";
|
||||
$lang->productplan->diffBranchesTip = "The @branch@『%s』of parent plan is not linked with the child plan. @branch@'s stories and bugs whill be removed from the plan. Do you want to save?";
|
||||
|
||||
$lang->productplan->featureBar['browse']['all'] = 'All';
|
||||
$lang->productplan->featureBar['browse']['undone'] = 'Undone';
|
||||
|
||||
@@ -75,9 +75,9 @@ $lang->productplan->projectNotEmpty = 'Project cannot be empty.';
|
||||
$lang->productplan->nextStep = "Next step";
|
||||
$lang->productplan->summary = "Total: <strong>%s</strong>, Parents: <strong>%s</strong>, Children: <strong>%s</strong>,Independent: <strong>%s</strong>.";
|
||||
$lang->productplan->checkedSummary = "Seleted: <strong>%total%</strong>, Parents: <strong>%parent%</strong>, Children: <strong>%child%</strong>, Independent: <strong>%independent%</strong>.";
|
||||
$lang->productplan->confirmChangePlan = "After the branch is unlinked, %s {$lang->SRCommon} and %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveStory = "After the branch is unlinked, %s {$lang->SRCommon} under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveBug = "After the branch is unlinked, %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmChangePlan = "After the branch of『%s』is unlinked, %s {$lang->SRCommon} and %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveStory = "After the branch of『%s』is unlinked, %s {$lang->SRCommon} under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
$lang->productplan->confirmRemoveBug = "After the branch of『%s』is unlinked, %s bugs under the branch will be removed from the plan at the same time, so still want to unassociate?";
|
||||
|
||||
$lang->productplan->id = 'ID';
|
||||
$lang->productplan->product = $lang->productCommon;
|
||||
@@ -139,7 +139,7 @@ $lang->productplan->beginGreaterChildTip = "The start date of the parent plan[%s
|
||||
$lang->productplan->endLetterChildTip = "The completion date of the parent plan[%s]: %s, cannot be less than the completion date of the child plan: %s.";
|
||||
$lang->productplan->beginLetterParentTip = "The start date of the child plan[%s]: %s, cannot be less than the start date of the parent plan: %s.";
|
||||
$lang->productplan->endGreaterParentTip = "The completion date of the child plan[%s]: %s, cannot be greater than the completion date of the parent plan: %s.";
|
||||
$lang->productplan->diffBranchesTip = "The @branch@ %s of parent plan is not linked with the child plan. @branch@'s stories and bugs whill be removed from the plan. Do you want to save?";
|
||||
$lang->productplan->diffBranchesTip = "The @branch@『%s』of parent plan is not linked with the child plan. @branch@'s stories and bugs whill be removed from the plan. Do you want to save?";
|
||||
|
||||
$lang->productplan->featureBar['browse']['all'] = 'Tous';
|
||||
$lang->productplan->featureBar['browse']['undone'] = 'Undone';
|
||||
|
||||
@@ -75,9 +75,9 @@ $lang->productplan->projectNotEmpty = '所属项目不能为空。';
|
||||
$lang->productplan->nextStep = "下一步";
|
||||
$lang->productplan->summary = "本页共 <strong>%s</strong> 个计划,父计划 <strong>%s</strong>,子计划 <strong>%s</strong>,独立计划 <strong>%s</strong>。";
|
||||
$lang->productplan->checkedSummary = "共选中 <strong>%total%</strong> 个计划,父计划 <strong>%parent%</strong>,子计划 <strong>%child%</strong>,独立计划 <strong>%independent%</strong>。";
|
||||
$lang->productplan->confirmChangePlan = "分支解除关联后,分支下的%s个{$lang->SRCommon}和%s个Bug将同步从计划中移除,是否解除?";
|
||||
$lang->productplan->confirmRemoveStory = "分支解除关联后,分支下的%s个{$lang->SRCommon}将同步从计划中移除,是否解除?";
|
||||
$lang->productplan->confirmRemoveBug = "分支解除关联后,分支下的%s个Bug将同步从计划中移除,是否解除?";
|
||||
$lang->productplan->confirmChangePlan = "分支『%s』解除关联后,分支下的%s个{$lang->SRCommon}和%s个Bug将同步从计划中移除,是否解除?";
|
||||
$lang->productplan->confirmRemoveStory = "分支『%s』解除关联后,分支下的%s个{$lang->SRCommon}将同步从计划中移除,是否解除?";
|
||||
$lang->productplan->confirmRemoveBug = "分支『%s』解除关联后,分支下的%s个Bug将同步从计划中移除,是否解除?";
|
||||
|
||||
$lang->productplan->id = '编号';
|
||||
$lang->productplan->product = $lang->productCommon;
|
||||
@@ -139,7 +139,7 @@ $lang->productplan->beginGreaterChildTip = "父计划[%s]的开始日期:%s,
|
||||
$lang->productplan->endLetterChildTip = "父计划[%s]的完成日期:%s,不能小于子计划的完成日期: %s";
|
||||
$lang->productplan->beginLetterParentTip = "子计划[%s]的开始日期:%s,不能小于父计划的开始日期: %s";
|
||||
$lang->productplan->endGreaterParentTip = "子计划[%s]的完成日期:%s,不能大于父计划的完成日期: %s";
|
||||
$lang->productplan->diffBranchesTip = "父计划的@branch@ %s 未被子计划关联,对应@branch@的需求和bug将自动从计划中移除,是否保存?";
|
||||
$lang->productplan->diffBranchesTip = "父计划的@branch@『%s』未被子计划关联,对应@branch@的需求和bug将自动从计划中移除,是否保存?";
|
||||
|
||||
$lang->productplan->featureBar['browse']['all'] = '全部';
|
||||
$lang->productplan->featureBar['browse']['undone'] = '未完成';
|
||||
|
||||
@@ -222,29 +222,14 @@ class productplanModel extends model
|
||||
* Get top plan pairs.
|
||||
*
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param int $exclude
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTopPlanPairs($productID, $branch = '', $exclude = '')
|
||||
public function getTopPlanPairs($productID, $exclude = '')
|
||||
{
|
||||
$branchQuery = '';
|
||||
if($branch !== '')
|
||||
{
|
||||
$branchQuery .= '(';
|
||||
$branchCount = count(explode(',', $branch));
|
||||
foreach(explode(',', $branch) as $index => $branchID)
|
||||
{
|
||||
$branchQuery .= "CONCAT(',', branch, ',') LIKE '%,$branchID,%'";
|
||||
if($index < $branchCount - 1) $branchQuery .= ' AND ';
|
||||
}
|
||||
$branchQuery .= ')';
|
||||
}
|
||||
|
||||
$planPairs = $this->dao->select("id,title")->from(TABLE_PRODUCTPLAN)
|
||||
->where('product')->eq($productID)
|
||||
->beginIF($branch !== '' and !empty($branchQuery))->andWhere($branchQuery)->fi()
|
||||
->andWhere('parent')->le(0)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->beginIF($exclude)->andWhere('status')->notin($exclude)
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
<td class='muted'><?php echo $product->name;?></td><td></td><td></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php if(!$parent):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->productplan->parent;?></th>
|
||||
<td><?php echo html::select('parent', array(0 => '') + $parentPlanPairs, 0, "class='form-control chosen'");?>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php if($product->type != 'normal'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->product->branch;?></th>
|
||||
@@ -57,12 +63,6 @@
|
||||
<td><?php echo html::input('title', '', "class='form-control' required");?></td>
|
||||
<td colspan='2' class='muted'><?php if($lastPlan) echo '(' . $lang->productplan->last . ': ' . $lastPlan->title . ')';?></td>
|
||||
</tr>
|
||||
<?php if(!$parent):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->productplan->parent;?></th>
|
||||
<td><?php echo html::select('parent', array(0 => '') + $parentPlanPairs, 0, "class='form-control chosen'");?>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->productplan->begin;?></th>
|
||||
<td><?php echo html::input('begin', formatTime($begin), "class='form-control form-date'");?></td>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<?php js::set('today', helper::today());?>
|
||||
<?php js::set('productID', $productID);?>
|
||||
<?php js::set('oldBranch', $oldBranch);?>
|
||||
<?php js::set('planID', $plan->id);?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
@@ -30,17 +31,7 @@
|
||||
<th><?php echo $lang->productplan->product;?></th>
|
||||
<td class='muted'><?php echo $product->name;?></td><td></td><td></td>
|
||||
</tr>
|
||||
<?php if($product->type != 'normal' and $plan->parent != '-1'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->product->branch;?></th>
|
||||
<td><?php echo html::select('branch[]', $branchTagOption, $plan->branch, "onchange='getConflictStories($plan->id);' class='form-control chosen' multiple");?></td><td></td><td></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->productplan->title;?></th>
|
||||
<td><?php echo html::input('title', $plan->title, "class='form-control' required");?></td><td></td><td></td>
|
||||
</tr>
|
||||
<?php if($plan->parent == '-1'):?>
|
||||
<?php echo html::hidden('parent', $plan->parent);?>
|
||||
<?php else:?>
|
||||
@@ -49,6 +40,16 @@
|
||||
<td><?php echo html::select('parent', array(0 => '') + $parentPlanPairs, $plan->parent, "class='form-control chosen'");?>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php if(!$product->shadow and $product->type != 'normal' and $plan->parent != '-1'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->product->branch;?></th>
|
||||
<td><?php echo html::select('branch[]', $branchTagOption, $plan->branch, "class='form-control chosen' multiple");?></td><td></td><td></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->productplan->title;?></th>
|
||||
<td><?php echo html::input('title', $plan->title, "class='form-control' required");?></td><td></td><td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->productplan->status;?></th>
|
||||
<?php $disabled = $plan->parent == -1 ? "disabled='disabled'" : '' ;?>
|
||||
|
||||
@@ -1278,6 +1278,7 @@ class project extends control
|
||||
$this->view->branchOption = $branchOption;
|
||||
$this->view->branchTagOption = $branchTagOption;
|
||||
$this->view->executions = $executions;
|
||||
$this->view->plans = $this->loadModel('productplan')->getPairs($productID ? $productID : array_keys($products));
|
||||
$this->view->stories = $storyList;
|
||||
$this->view->tasks = $taskList;
|
||||
$this->view->projectPairs = $this->project->getPairsByProgram();
|
||||
|
||||
@@ -162,17 +162,16 @@ function setParentProgram(parentProgram)
|
||||
var productSelectHtml = data.allProducts;
|
||||
var planSelectHtml = data.plans;
|
||||
|
||||
$('.productsBox .row .col-sm-4 .input-group').each(function(index)
|
||||
$('.productsBox .row .col-sm-6 .input-group').each(function(index)
|
||||
{
|
||||
var selectedProduct = $(this).find('[name^=products]').val();
|
||||
var selectedBranch = $(this).find('[name^=branch]').val();
|
||||
var selectedPlan = $('#plan' + index ).find('[name^=plans]').val();
|
||||
|
||||
$(this).html(productSelectHtml);
|
||||
$(this).find('[name^=products]').html(productSelectHtml);
|
||||
$(this).find('[name^=products]').attr('name', 'products[' + index + ']').attr('id', 'products' + index).attr('data-branch', selectedBranch).attr('data-plan', selectedPlan);
|
||||
$(this).find('[name^=products]').val(selectedProduct).chosen().change();
|
||||
});
|
||||
$('.productsBox .row .col-sm-4:last').find('.input-group').append($('.productsBox .addProduct .input-group:first .input-group-addon').prop('outerHTML'));
|
||||
}
|
||||
|
||||
if(parentProgram != 0)
|
||||
@@ -245,7 +244,7 @@ function addNewProduct(obj)
|
||||
$('.newLine').removeClass('hidden');
|
||||
$('.productsBox .row').removeClass('hidden');
|
||||
$('.productsBox .row .input-group').find('select').removeAttr('disabled').trigger("chosen:updated");
|
||||
if($('#plansBox .col-sm-4').find('select').length > 1) $('.division').removeClass('hide');
|
||||
if($('.productsBox').find("select[name^=products]").length > 1) $('.division').removeClass('hide');
|
||||
|
||||
/* Hide the input box for creating a product. */
|
||||
$(obj).closest('td').attr('colspan', 3);
|
||||
|
||||
@@ -18,13 +18,13 @@ $(function()
|
||||
var productSelectHtml = data.allProducts;
|
||||
var planSelectHtml = data.plans;
|
||||
|
||||
$('#productsBox .row .col-sm-4 .input-group').each(function(index)
|
||||
$('.productsBox .row .col-sm-6 .input-group').each(function(index)
|
||||
{
|
||||
var selectedProduct = $(this).find('[name^=products]').val();
|
||||
var selectedBranch = $(this).find('[name^=branch]').val();
|
||||
var selectedPlan = $('#plan' + index ).find('[name^=plans]').val();
|
||||
|
||||
$(this).html(productSelectHtml);
|
||||
$(this).find('[name^=products]').html(productSelectHtml);
|
||||
$(this).find('[name^=products]').attr('name', 'products[' + index + ']').attr('id', 'products' + index).attr('data-branch', selectedBranch).attr('data-plan', selectedPlan);
|
||||
$(this).find('[name^=products]').val(selectedProduct).chosen().change();
|
||||
});
|
||||
|
||||
@@ -1583,7 +1583,7 @@ class projectModel extends model
|
||||
->exec();
|
||||
if(dao::isError()) return false;
|
||||
|
||||
if(!$oldProject->hasProduct && $oldProject->name != $project->name) $this->updateProductName($project->name, $projectID);
|
||||
if(!$oldProject->hasProduct and ($oldProject->name != $project->name or $oldProject->parent != $project->parent)) $this->updateShadowProduct($project);
|
||||
|
||||
/* Get team and language item. */
|
||||
$this->loadModel('user');
|
||||
@@ -1744,7 +1744,7 @@ class projectModel extends model
|
||||
|
||||
if(!dao::isError())
|
||||
{
|
||||
if(!$oldProject->hasProduct && $oldProject->name != $project->name) $this->updateProductName($project->name, $projectID);
|
||||
if(!$oldProject->hasProduct and ($oldProject->name != $project->name or $oldProject->parent != $project->parent)) $this->updateShadowProduct($project);
|
||||
|
||||
if(isset($project->parent))
|
||||
{
|
||||
@@ -2038,17 +2038,18 @@ class projectModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a product's name as its project.
|
||||
* Update shadow product for its project.
|
||||
*
|
||||
* @param string $projectName
|
||||
* @param int $projectID
|
||||
* @param object $project
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function updateProductName($projectName, $projectID)
|
||||
public function updateShadowProduct($project)
|
||||
{
|
||||
$product = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->fetch('product');
|
||||
$this->dao->update(TABLE_PRODUCT)->set('name')->eq($projectName)->where('id')->eq($product)->exec();
|
||||
$product = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($project->id)->fetch('product');
|
||||
$topProgram = !empty($project->parent) ? $this->loadModel('program')->getTopByID($project->parent) : 0;
|
||||
$this->dao->update(TABLE_PRODUCT)->set('name')->eq($project->name)->set('program')->eq($topProgram)->where('id')->eq($product)->exec();
|
||||
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="c-id-sm"><?php echo $lang->build->id;?></th>
|
||||
<th class="c-name w-250px text-left"><?php echo $lang->build->name;?></th>
|
||||
<th class="c-name text-left"><?php echo $lang->build->name;?></th>
|
||||
<?php if($project->hasProduct):?>
|
||||
<th class="c-name w-150px text-left"><?php echo $lang->build->product;?></th>
|
||||
<?php endif;?>
|
||||
@@ -56,8 +56,8 @@
|
||||
<th class="c-name w-150px text-left"><?php echo $lang->executionCommon;?></th>
|
||||
<?php endif;?>
|
||||
<th class="c-url w-300px text-left"><?php echo $lang->build->url;?></th>
|
||||
<th class="c-date"><?php echo $lang->build->date;?></th>
|
||||
<th class="c-user"><?php echo $lang->build->builder;?></th>
|
||||
<th class="c-date w-90px"><?php echo $lang->build->date;?></th>
|
||||
<th class="c-user w-70px"><?php echo $lang->build->builder;?></th>
|
||||
<th class="c-actions-5"><?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -804,13 +804,12 @@ class projectrelease extends control
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxLoadBuilds($projectID, $productID, $branch = 0)
|
||||
public function ajaxLoadBuilds($projectID, $productID)
|
||||
{
|
||||
$builds = $this->loadModel('build')->getBuildPairs($productID, $branch, 'notrunk,withbranch,hasproject', $projectID, 'project', '', false);
|
||||
$builds = $this->loadModel('build')->getBuildPairs($productID, 'all', 'notrunk,withbranch,hasproject', $projectID, 'project', '', false);
|
||||
$releasedBuilds = $this->projectrelease->getReleasedBuilds($projectID);
|
||||
foreach($releasedBuilds as $build) unset($builds[$build]);
|
||||
|
||||
|
||||
@@ -7,36 +7,8 @@
|
||||
function loadBuilds()
|
||||
{
|
||||
var productID = $('#product').val();
|
||||
var branch = $('#branch').length == 0 ? 0 : $('#branch').val();
|
||||
$('#buildBox').load(createLink('projectrelease', 'ajaxLoadBuilds', "projectID=" + projectID + "&productID=" + productID + "&branch=" + branch), function()
|
||||
$('#buildBox').load(createLink('projectrelease', 'ajaxLoadBuilds', "projectID=" + projectID + "&productID=" + productID), function()
|
||||
{
|
||||
$('#build').attr('data-placeholder', multipleSelect).chosen();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the branch when switching products.
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function loadBranches(productID)
|
||||
{
|
||||
$('#branch').remove();
|
||||
$('#branch_chosen').remove();
|
||||
$.get(createLink('branch', 'ajaxGetBranches', "productID=" + productID + '&oldBranch=0¶ms=active&projectID=' + projectID), function(data)
|
||||
{
|
||||
var $product = $('#product');
|
||||
var $inputGroup = $product.closest('.input-group');
|
||||
$inputGroup.find('.input-group-addon').toggleClass('hidden', !data);
|
||||
if(data)
|
||||
{
|
||||
$inputGroup.append(data);
|
||||
$inputGroup.find('#branch').attr('onchange', 'loadBuilds()');
|
||||
$('#branch').css('width', '120px').chosen();
|
||||
}
|
||||
loadBuilds();
|
||||
$inputGroup.fixInputGroup();
|
||||
})
|
||||
}
|
||||
|
||||
@@ -39,12 +39,7 @@
|
||||
<?php else:?>
|
||||
<tr>
|
||||
<th><?php echo $lang->release->product;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php echo html::select('product', $products, $product->id, "onchange='loadBranches(this.value)' class='form-control chosen'");?>
|
||||
<?php if($product->type != 'normal') echo html::select('branch', $branches, $branch, "onchange='loadBuilds()' class='form-control chosen control-branch'");?>
|
||||
</div>
|
||||
</td>
|
||||
<td><?php echo html::select('product', $products, $product->id, "onchange='loadBuilds()' class='form-control chosen'");?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -18,6 +18,7 @@ $config->transfer->listFields = '';
|
||||
$config->transfer->sysLangFields = ',pri,status,type,mode,severity,os,browser,resolution,confirmed,source,reviewResult,stage,change,category';
|
||||
$config->transfer->sysDataFields = 'execution,product,user';
|
||||
$config->transfer->userFields = 'assignedTo,openedBy,finishedBy,canceledBy,closedBy,lastEditedBy,lastRunner,resolvedBy,reviewedBy,mailto';
|
||||
$config->transfer->textareaFields = 'spec,desc';
|
||||
|
||||
$config->transfer->defaultZeroField = 'severity,pri';
|
||||
$config->transfer->defaultEmptyField = '';
|
||||
|
||||
@@ -163,13 +163,17 @@ class transfer extends control
|
||||
if($product->type == 'normal') unset($fields['branch']);
|
||||
if($this->session->storyType == 'requirement') unset($fields['plan']);
|
||||
}
|
||||
|
||||
if($model == 'bug')
|
||||
{
|
||||
$product = $this->loadModel('product')->getByID($this->session->bugTransferParams['productID']);
|
||||
if($product->type == 'normal') unset($fields['branch']);
|
||||
if($product->shadow and ($this->app->tab == 'execution' or $this->app->tab == 'project')) unset($fields['product']);
|
||||
}
|
||||
if($model == 'testcase')
|
||||
{
|
||||
$product = $this->loadModel('product')->getByID($this->session->testcaseTransferParams['productID']);
|
||||
if($product->type == 'normal') unset($fields['branch']);
|
||||
}
|
||||
if($model == 'task') $datas = $this->task->processDatas4Task($datas);
|
||||
$html = $this->transfer->buildNextList($datas->datas, $lastID, $fields, $pagerID, $model);
|
||||
die($html);
|
||||
|
||||
@@ -1473,6 +1473,7 @@ class transferModel extends model
|
||||
}
|
||||
$html .= '</td>';
|
||||
}
|
||||
elseif(strpos($this->transferConfig->textareaFields, $field) !== false) $html .= '<td>' . html::textarea("$name", $selected, "class='form-control' style='overflow:hidden;'") . '</td>';
|
||||
|
||||
else $html .= '<td>' . html::input("$name", $selected, "class='form-control autocomplete='off'") . '</td>';
|
||||
}
|
||||
|
||||
+1
-1
@@ -1203,7 +1203,7 @@ function showCheckedFields(fields)
|
||||
else if(!$fieldBox.hasClass('hidden'))
|
||||
{
|
||||
$fieldBox.addClass('hidden');
|
||||
$field.attr('disabled', true);
|
||||
if($(this).val() != 'branch') $field.attr('disabled', true);
|
||||
}
|
||||
|
||||
if(config.currentModule == 'story' && $(this).val() == 'source')
|
||||
|
||||
Reference in New Issue
Block a user