Merge branch 'master' into zenops_46
This commit is contained in:
+4
-4
@@ -383,10 +383,10 @@ INSERT INTO `zt_product` (`id`, `program`, `name`, `code`, `bind`, `line`, `type
|
||||
INSERT INTO `zt_productplan` (`id`, `product`, `branch`, `parent`, `title`, `desc`, `begin`, `end`, `order`, `deleted`) VALUES
|
||||
(1, 1, 0, 0, '1.0版本', '开发出企业网站1.0版本。<br />', '2020-06-05', '2021-06-04', '', '0');
|
||||
INSERT INTO `zt_project` (`id`, `project`, `model`, `type`, `lifetime`, `budget`, `budgetUnit`, `attribute`, `percent`, `milestone`, `output`, `auth`, `parent`, `path`, `grade`, `name`, `code`, `begin`, `end`, `realBegan`, `realEnd`, `days`, `status`, `subStatus`, `pri`, `desc`, `version`, `parentVersion`, `planDuration`, `realDuration`, `openedBy`, `openedDate`, `openedVersion`, `lastEditedBy`, `lastEditedDate`, `closedBy`, `closedDate`, `canceledBy`, `canceledDate`, `PO`, `PM`, `QD`, `RD`, `team`, `acl`, `whitelist`, `order`, `deleted`) VALUES
|
||||
(1, 7, '', 'sprint', 'sprint', '0', 'CNY', '', 0, '0', '', '', 7, ',7,1,', 1, '企业网站第一期', 'coWeb1', '2020-06-05', '2021-12-04', '0000-00-00', '0000-00-00', 391, 'doing', '', '1', '开发企业网站的基本雏形。<br />', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 'productManager', 'projectManager', 'testManager', 'productManager', '公司开发团队', 'open', '', 5, '0'),
|
||||
(2, 7, '', 'sprint', 'sprint', '0', 'CNY', '', 0, '0', '', '', 7, ',7,2,', 1, '企业网站第二期', 'coWebsite2', '2021-06-05', '2022-06-04', '0000-00-00', '0000-00-00', 260, 'wait', '', '1', '', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 'productManager', 'projectManager', 'testManager', 'productManager', '公司开发团队', 'open', '', 10, '0'),
|
||||
(7, 0, 'scrum', 'project', 'sprint', '0', 'CNY', '', 0, '0', '', 'extend', 6, ',6,7,', 2, '企业管理系统', '', '2021-06-05', '2022-06-04', '0000-00-00', '0000-00-00', 0, 'doing', '', '1', '', 0, 0, 0, 0, 'admin', '2021-04-28 11:22:04', '15.0.rc3', 'admin', '2021-04-28 11:22:04', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'projectManager', '', '', '', 'open', ',tester3,admin', 35, '0'),
|
||||
(6, 0, '', 'program', 'sprint', '0', 'CNY', '', 0, '0', '', '', 0, ',6,', 1, '企业管理', '', '2021-06-05', '2022-06-04', '0000-00-00', '0000-00-00', 0, 'doing', '', '1', '', 0, 0, 0, 0, 'admin', '2021-04-28 11:22:04', '15.0.rc3', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '', '', '', '', 'open', '', 30, '0');
|
||||
(1, 7, '', 'sprint', 'long', '0', 'CNY', '', 0, '0', '', '', 7, ',7,1,', 1, '企业网站第一期', 'coWeb1', '2020-06-05', '2021-12-04', '0000-00-00', '0000-00-00', 391, 'doing', '', '1', '开发企业网站的基本雏形。<br />', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 'productManager', 'projectManager', 'testManager', 'productManager', '公司开发团队', 'open', '', 5, '0'),
|
||||
(2, 7, '', 'sprint', 'long', '0', 'CNY', '', 0, '0', '', '', 7, ',7,2,', 1, '企业网站第二期', 'coWebsite2', '2021-06-05', '2022-06-04', '0000-00-00', '0000-00-00', 260, 'wait', '', '1', '', 0, 0, 0, 0, '', '0000-00-00 00:00:00', '', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', 'productManager', 'projectManager', 'testManager', 'productManager', '公司开发团队', 'open', '', 10, '0'),
|
||||
(7, 0, 'scrum', 'project', '', '0', 'CNY', '', 0, '0', '', 'extend', 6, ',6,7,', 2, '企业管理系统', '', '2021-06-05', '2022-06-04', '0000-00-00', '0000-00-00', 0, 'doing', '', '1', '', 0, 0, 0, 0, 'admin', '2021-04-28 11:22:04', '15.0.rc3', 'admin', '2021-04-28 11:22:04', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 'projectManager', '', '', '', 'open', ',tester3,admin', 35, '0'),
|
||||
(6, 0, '', 'program', '', '0', 'CNY', '', 0, '0', '', '', 0, ',6,', 1, '企业管理', '', '2021-06-05', '2022-06-04', '0000-00-00', '0000-00-00', 0, 'doing', '', '1', '', 0, 0, 0, 0, 'admin', '2021-04-28 11:22:04', '15.0.rc3', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '', '', '', '', 'open', '', 30, '0');
|
||||
INSERT INTO `zt_projectcase` (`project`, `product`, `case`, `count`, `version`, `order`) VALUES
|
||||
(1, 1, 2, 1, 1, 4),
|
||||
(7, 1, 1, 1, 1, 5),
|
||||
|
||||
@@ -39,3 +39,6 @@ REPLACE INTO `zt_report` (`code`, `name`, `module`, `sql`, `vars`, `langs`, `par
|
||||
ALTER TABLE `zt_project` ADD `division` enum('0','1') COLLATE 'utf8_general_ci' NOT NULL DEFAULT '1' AFTER `vision`;
|
||||
|
||||
ALTER TABLE `zt_build` ADD `builds` varchar(255) NOT NULL AFTER `execution`;
|
||||
|
||||
UPDATE `zt_block` SET block = 'scrumrisk' WHERE module = 'project' AND type = 'scrum' AND block = 'waterfallrisk';
|
||||
UPDATE `zt_block` SET block = 'scrumissue' WHERE module = 'project' AND type = 'scrum' AND block = 'waterfallissue';
|
||||
|
||||
@@ -90,7 +90,7 @@ class product extends control
|
||||
$product = $this->product->getById($productID);
|
||||
|
||||
/* Get stories. */
|
||||
if($browseType == 'reviewing') $browseType = 'reviewingstory';
|
||||
if(in_array($browseType, array('reviewing', 'draft', 'changing'))) $browseType .= 'story';
|
||||
$stories = $this->product->getStories($productID, $branchID, $browseType, $queryID, $moduleID, $storyType, $sort, $pager);
|
||||
|
||||
/* Display status of branch. */
|
||||
|
||||
@@ -1661,6 +1661,7 @@ class actionModel extends model
|
||||
|
||||
/* Set app for no multiple project. */
|
||||
if(!empty($action->objectLink) and !empty($project) and empty($project->multiple)) $action->objectLink .= '#app=project';
|
||||
if($this->config->vision == 'lite' and $action->objectType == 'module') $action->objectLink .= '#app=project';
|
||||
|
||||
return $action;
|
||||
}
|
||||
|
||||
@@ -1434,6 +1434,35 @@ class block extends control
|
||||
$this->view->releases = $releases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print scrum issue block.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function printScrumIssueBlock()
|
||||
{
|
||||
$uri = $this->app->tab == 'my' ? $this->createLink('my', 'index') : $this->server->http_referer;
|
||||
$this->session->set('issueList', $uri, 'project');
|
||||
if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||||
$this->view->issues = $this->loadModel('issue')->getBlockIssues($this->session->project, $this->params->type, $this->viewType == 'json' ? 0 : (int)$this->params->count, $this->params->orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print scrum risk block.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function printScrumRiskBlock()
|
||||
{
|
||||
$uri = $this->app->tab == 'my' ? $this->createLink('my', 'index') : $this->server->http_referer;
|
||||
$this->session->set('riskList', $uri, 'project');
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||||
$this->view->risks = $this->loadModel('risk')->getBlockRisks($this->session->project, $this->params->type, $this->viewType == 'json' ? 0 : (int)$this->params->count, $this->params->orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print sprint block.
|
||||
*
|
||||
|
||||
@@ -750,6 +750,51 @@ class blockModel extends model
|
||||
return json_encode($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scrum issue params.
|
||||
*
|
||||
* @param string $module
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getScrumIssueParams($module = '')
|
||||
{
|
||||
$this->app->loadLang('issue');
|
||||
|
||||
$params = $this->appendCountParams();
|
||||
$params->type['name'] = $this->lang->block->type;
|
||||
$params->type['options'] = $this->lang->issue->labelList;
|
||||
$params->type['control'] = 'select';
|
||||
|
||||
$params->orderBy['name'] = $this->lang->block->orderBy;
|
||||
$params->orderBy['options'] = $this->lang->block->orderByList->product;
|
||||
$params->orderBy['control'] = 'select';
|
||||
|
||||
return json_encode($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scrum risk params.
|
||||
*
|
||||
* @param string $module▫
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getScrumRiskParams($module = '')
|
||||
{
|
||||
$this->app->loadLang('risk');
|
||||
$params = $this->appendCountParams();
|
||||
$params->type['name'] = $this->lang->block->type;
|
||||
$params->type['options'] = $this->lang->risk->featureBar['browse'];
|
||||
$params->type['control'] = 'select';
|
||||
|
||||
$params->orderBy['name'] = $this->lang->block->orderBy;
|
||||
$params->orderBy['options'] = $this->lang->block->orderByList->product;
|
||||
$params->orderBy['control'] = 'select';
|
||||
|
||||
return json_encode($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get execution params.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php if(empty($issues)): ?>
|
||||
<div class='empty-tip'><?php echo $lang->block->emptyTip;?></div>
|
||||
<?php else:?>
|
||||
<style>
|
||||
.block-issues .c-id {width: 55px;}
|
||||
.block-issues .c-status {width: 80px;}
|
||||
.block-issues.block-sm .c-status {text-align: center;}
|
||||
.c-assignedTo {width: 100px; padding:0px !important;text-align:center;}
|
||||
.c-severity, .c-pri {text-align:center;}
|
||||
</style>
|
||||
<div class='panel-body has-table scrollbar-hover'>
|
||||
<table class='table table-borderless table-hover table-fixed table-fixed-head tablesorter block-issues <?php if(!$longBlock) echo 'block-sm';?>'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='c-id'><?php echo $lang->idAB;?></th>
|
||||
<th class='c-status'><?php echo $lang->issue->type;?></th>
|
||||
<th class='c-name'> <?php echo $lang->issue->title;?></th>
|
||||
<?php if($longBlock):?>
|
||||
<th class='c-status'><?php echo $lang->issue->severity;?></th>
|
||||
<th class='c-number'><?php echo $lang->issue->pri;?></th>
|
||||
<th class='c-user'><?php echo $lang->issue->owner;?></th>
|
||||
<th class='c-assignedTo'><?php echo $lang->issue->assignedTo;?></th>
|
||||
<?php endif;?>
|
||||
<th class='c-status'><?php echo $lang->issue->status;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($issues as $issue):?>
|
||||
<?php
|
||||
$viewLink = $this->createLink('issue', 'view', "issueID={$issue->id}");
|
||||
?>
|
||||
<tr>
|
||||
<td class='c-id-xs'><?php echo sprintf('%03d', $issue->id);?></td>
|
||||
<td class='c-type'><?php echo zget($lang->issue->typeList, $issue->type);?></td>
|
||||
<td class='c-name' title='<?php echo $issue->title?>'><?php echo html::a($viewLink, $issue->title);?></td>
|
||||
<?php if($longBlock):?>
|
||||
<td class='c-severity'><?php echo zget($lang->issue->severityList, $issue->severity, $issue->severity)?></td>
|
||||
<td class='c-pri'><?php echo zget($lang->issue->priList, $issue->pri, $issue->pri)?></td>
|
||||
<td><?php echo zget($users, $issue->owner, $issue->owner)?></td>
|
||||
<td class='c-assignedTo'><?php echo zget($users, $issue->assignedTo, $issue->assignedTo)?></td>
|
||||
<?php endif;?>
|
||||
<td class='c-status'>
|
||||
<span class="status-issue status-<?php echo $issue->status?>"><?php echo zget($lang->issue->statusList, $issue->status);?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php if(empty($risks)): ?>
|
||||
<div class='empty-tip'><?php echo $lang->block->emptyTip;?></div>
|
||||
<?php else:?>
|
||||
<style>
|
||||
.block-risks .c-id {width: 40px;}
|
||||
.block-risks .c-pri {width: 85px; text-align: center;}
|
||||
.block-risks .c-strategy, .block-risks .c-status {width: 80px;}
|
||||
.block-risks .c-user, .block-risks .c-rate, .block-risks .c-category {width: 110px;}
|
||||
.c-rate, .c-category {text-align:center;}
|
||||
.c-assignedTo {width: 100px; padding:0px !important;text-align:center;}
|
||||
.pri-low {color: #000000;}
|
||||
.pri-middle {color: #FF9900;}
|
||||
.pri-high {color: #E53333;}
|
||||
</style>
|
||||
<div class='panel-body has-table scrollbar-hover'>
|
||||
<table class='table table-borderless table-hover table-fixed table-fixed-head tablesorter block-risks <?php if(!$longBlock) echo 'block-sm';?>'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='c-id'><?php echo $lang->idAB;?></th>
|
||||
<th class='c-name'><?php echo $lang->risk->name;?></th>
|
||||
<?php if($longBlock):?>
|
||||
<th class='c-strategy'> <?php echo $lang->risk->strategy;?></th>
|
||||
<?php endif;?>
|
||||
<th class='c-status'><?php echo $lang->risk->status;?></th>
|
||||
<?php if($longBlock):?>
|
||||
<th class='c-rate'><?php echo $lang->risk->rate;?></th>
|
||||
<th class='c-pri'><?php echo $lang->risk->pri;?></th>
|
||||
<th class='c-assignedTo text-center'><?php echo $lang->risk->assignedTo;?></th>
|
||||
<th class='c-category'><?php echo $lang->risk->category;?></th>
|
||||
<?php endif;?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($risks as $risk):?>
|
||||
<?php
|
||||
$viewLink = $this->createLink('risk', 'view', "riskID={$risk->id}");
|
||||
?>
|
||||
<tr>
|
||||
<td class='c-id-xs'><?php echo sprintf('%03d', $risk->id);?></td>
|
||||
<td class='c-name' title='<?php echo $risk->name?>'><?php echo html::a($viewLink, $risk->name);?></td>
|
||||
<?php if($longBlock):?>
|
||||
<td class='c-strategy'><?php echo zget($lang->risk->strategyList, $risk->strategy, $risk->strategy)?></td>
|
||||
<?php endif;?>
|
||||
<td class='c-status'>
|
||||
<span class="status-risk status-<?php echo $risk->status?>"><?php echo zget($lang->risk->statusList, $risk->status);?></span>
|
||||
</td>
|
||||
<?php if($longBlock):?>
|
||||
<td class='c-rate'><?php echo $risk->rate?></td>
|
||||
<td class='c-pri'><?php echo "<span class='pri-{$risk->pri}'>" . zget($lang->risk->priList, $risk->pri) . "</span>";?></td>
|
||||
<td class='c-assignedTo'><?php echo zget($users, $risk->assignedTo, $risk->assignedTo)?></td>
|
||||
<td class='c-category'><?php echo zget($lang->risk->categoryList, $risk->category, $risk->category)?></td>
|
||||
<?php endif;?>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
@@ -211,7 +211,7 @@ class branch extends control
|
||||
public function ajaxGetDropMenu($productID, $branch, $module, $method, $extra = '')
|
||||
{
|
||||
parse_str($extra, $output);
|
||||
$isQaModule = (strpos(',project,execution,', ",{$this->app->tab},") !== false and strpos(',bug,testcase,', ",$method,") !== false and !empty($productID)) ? true : false;
|
||||
$isQaModule = (strpos(',project,execution,', ",{$this->app->tab},") !== false and strpos(',bug,testcase,groupCase,zeroCase,', ",$method,") !== false and !empty($productID)) ? true : false;
|
||||
$param = $isQaModule ? $extra : 0;
|
||||
$param = isset($output['projectID']) ? $output['projectID'] : $param;
|
||||
$branches = $this->branch->getPairs($productID, 'all', $param);
|
||||
|
||||
@@ -16,6 +16,8 @@ $(function()
|
||||
saveCustomFields('batchCreateFields', 10, $titleCol, 150);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#dropMenu').css('z-index', 9999);
|
||||
})
|
||||
|
||||
/**
|
||||
|
||||
+10
-2
@@ -23,7 +23,15 @@ function loadProductExecutions(productID, projectID)
|
||||
|
||||
$('#executionBox').load(link, function()
|
||||
{
|
||||
$(this).find('select').chosen();
|
||||
$select = $(this).find('select');
|
||||
$tr = $(this).closest('tr');
|
||||
$tr.removeClass('hidden');
|
||||
if($select.data('multiple') == 0)
|
||||
{
|
||||
$tr.addClass('hidden');
|
||||
$select.find('option:last').prop('selected', true);
|
||||
}
|
||||
$select.chosen();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -37,7 +45,7 @@ $('#toTaskButton').on('click', function()
|
||||
{
|
||||
$('#cancelButton').click();
|
||||
link = createLink('task', 'create', 'executionID=' + executionID + '&storyID=0&moduleID=0&taskID=0&todoID=0&extra=projectID=' + projectID + '&bugID=' + bugID);
|
||||
window.parent.$.apps.open(link, 'execution');
|
||||
window.parent.$.apps.open(link, $('#execution').data('multiple') == 0 ? 'project' : 'execution');
|
||||
}
|
||||
else if(projectID == 0)
|
||||
{
|
||||
|
||||
@@ -74,8 +74,8 @@ class build extends control
|
||||
$this->project->setMenu($projectID);
|
||||
$executions = $this->execution->getPairs($projectID, 'all', 'stagefilter');
|
||||
$executionID = empty($executionID) ? key($executions) : $executionID;
|
||||
$productGroups = $this->product->getProducts($executionID);
|
||||
$branchGroups = $this->project->getBranchesByProject($executionID);
|
||||
$productGroups = $executionID ? $this->product->getProducts($executionID) : array();
|
||||
$branchGroups = $executionID ? $this->project->getBranchesByProject($executionID) : array();
|
||||
$this->session->set('project', $projectID);
|
||||
}
|
||||
elseif($this->app->tab == 'execution')
|
||||
@@ -531,6 +531,27 @@ class build extends control
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get last build.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $executionID
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function ajaxGetLastBuild($projectID, $executionID)
|
||||
{
|
||||
$lastBuild = $this->build->getLast($executionID, $projectID);
|
||||
if($lastBuild)
|
||||
{
|
||||
echo "<div class='help-block'> " . $this->lang->build->last . ": <a class='code label label-badge label-light' id='lastBuildBtn'>" . $lastBuild->name . "</a></div>";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Link stories.
|
||||
*
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
$().ready(function()
|
||||
{
|
||||
$('#lastBuildBtn').click(function()
|
||||
$(document).on('click', '#lastBuildBtn', function()
|
||||
{
|
||||
$('#name').val($(this).text()).focus();
|
||||
});
|
||||
|
||||
$(document).on('change', '#product, #branch', function()
|
||||
{
|
||||
var projectID = $('#project').val();
|
||||
var productID = $('#product').val();
|
||||
var branch = $('#branch').length > 0 ? $('#branch').val() : '';
|
||||
$.get(createLink('build', 'ajaxGetProjectBuilds', 'projectID=' + projectID + '&productID=' + productID + '&varName=builds&build=&branch=' + branch + '&index=&needCreate=&type=noempty,notrunk,separate,singled&extra=multiple'), function(data)
|
||||
@@ -18,17 +19,19 @@ $().ready(function()
|
||||
|
||||
$('input[name=isIntegrated]').change(function()
|
||||
{
|
||||
var projectID = $('#project').val();
|
||||
var executionID = $('#execution').val();
|
||||
if($(this).val() == 'no')
|
||||
{
|
||||
$('#execution').closest('tr').show();
|
||||
$('#buildBox').closest('tr').hide();
|
||||
loadProducts($('#execution').val());
|
||||
loadProducts(executionID);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#execution').closest('tr').hide();
|
||||
$('#buildBox').closest('tr').show();
|
||||
loadProducts($('#project').val());
|
||||
loadProducts(projectID);
|
||||
}
|
||||
});
|
||||
$('#product').change();
|
||||
@@ -48,6 +51,7 @@ function loadProducts(executionID)
|
||||
$('#branch').remove();
|
||||
$('#branch_chosen').remove();
|
||||
$('#noProduct').remove();
|
||||
executionID = executionID ? executionID : 0;
|
||||
$.get(createLink('product', 'ajaxGetProducts', 'executionID=' + executionID), function(data)
|
||||
{
|
||||
if(data)
|
||||
@@ -66,4 +70,23 @@ function loadProducts(executionID)
|
||||
loadBranches($("#product").val());
|
||||
}
|
||||
});
|
||||
loadLastBuild();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load last build
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function loadLastBuild()
|
||||
{
|
||||
var isIntegrated = $('input[name=isIntegrated]:checked').val();
|
||||
var projectID = $('#project').val();
|
||||
var executionID = $('#execution').val();
|
||||
if(isIntegrated == 'yes') executionID = 0;
|
||||
$.get(createLink('build', 'ajaxGetLastBuild', 'projectID=' + projectID + '&executionID=' + executionID), function(data)
|
||||
{
|
||||
$('#lastBuildBox').html(data);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ $lang->build->branchName = '%s';
|
||||
$lang->build->execution = $lang->executionCommon;
|
||||
$lang->build->integrated = 'Integrated';
|
||||
$lang->build->singled = 'Singled';
|
||||
$lang->build->builds = 'Builds';
|
||||
$lang->build->builds = 'Included Builds';
|
||||
$lang->build->name = 'Name';
|
||||
$lang->build->date = 'Datum';
|
||||
$lang->build->builder = 'Builder';
|
||||
|
||||
@@ -35,7 +35,7 @@ $lang->build->branchName = '%s';
|
||||
$lang->build->execution = $lang->executionCommon;
|
||||
$lang->build->integrated = 'Integrated';
|
||||
$lang->build->singled = 'Singled';
|
||||
$lang->build->builds = 'Builds';
|
||||
$lang->build->builds = 'Included Builds';
|
||||
$lang->build->name = 'Name';
|
||||
$lang->build->date = 'Date';
|
||||
$lang->build->builder = 'Builder';
|
||||
|
||||
@@ -35,7 +35,7 @@ $lang->build->branchName = '%s';
|
||||
$lang->build->execution = $lang->executionCommon;
|
||||
$lang->build->integrated = 'Integrated';
|
||||
$lang->build->singled = 'Singled';
|
||||
$lang->build->builds = 'Builds';
|
||||
$lang->build->builds = 'Included Builds';
|
||||
$lang->build->name = 'Nom';
|
||||
$lang->build->date = 'Date';
|
||||
$lang->build->builder = 'Builder';
|
||||
|
||||
+19
-1
@@ -321,7 +321,7 @@ class buildModel extends model
|
||||
{
|
||||
return $this->dao->select('id, name')->from(TABLE_BUILD)
|
||||
->where('deleted')->eq(0)
|
||||
->beginIF($executionID)->andWhere('execution')->eq((int)$executionID)->fi()
|
||||
->andWhere('execution')->eq((int)$executionID)
|
||||
->beginIF($projectID)->andWhere('project')->eq((int)$projectID)->fi()
|
||||
->orderBy('date DESC,id DESC')
|
||||
->limit(1)
|
||||
@@ -608,6 +608,24 @@ class buildModel extends model
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the action is clickable.
|
||||
*
|
||||
* @param string $bug
|
||||
* @param string $action
|
||||
* @param string $module
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function isClickable($object, $action, $module = 'bug')
|
||||
{
|
||||
$action = strtolower($action);
|
||||
|
||||
if($module == 'testtask' && $action == 'create') return !!$object->execution;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build action menu.
|
||||
*
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
</tr>
|
||||
<tr class="<?php echo $hidden;?>">
|
||||
<th class='w-120px'><?php echo $lang->build->product;?></th>
|
||||
<?php if(!empty($products)):?>
|
||||
<?php if(!empty($products) || !$executionID):?>
|
||||
<td>
|
||||
<div class='input-group' id='productBox'>
|
||||
<?php echo html::select('product', $products, empty($product) ? '' : $product->id, "onchange='loadBranches(this.value);' class='form-control chosen' required");?>
|
||||
@@ -58,7 +58,7 @@
|
||||
<tr>
|
||||
<th class='w-120px'><?php echo $lang->build->name;?></th>
|
||||
<td><?php echo html::input('name', '', "class='form-control' required");?></td>
|
||||
<td class='text-muted'>
|
||||
<td class='text-muted' id='lastBuildBox'>
|
||||
<?php if($lastBuild):?>
|
||||
<div class='help-block'> <?php echo $lang->build->last . ': <a class="code label label-badge label-light" id="lastBuildBtn">' . $lastBuild->name . '</a>';?></div>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -1680,7 +1680,7 @@ EOD;
|
||||
{
|
||||
if($app->getModuleName() != $module) $app->control->loadModel($module);
|
||||
$modelClass = class_exists("ext{$module}Model") ? "ext{$module}Model" : $module . "Model";
|
||||
if(class_exists($modelClass) and is_callable(array($modelClass, 'isClickable')))
|
||||
if(class_exists($modelClass) and method_exists($modelClass, 'isClickable'))
|
||||
{
|
||||
//$clickable = call_user_func_array(array($modelClass, 'isClickable'), array('object' => $object, 'method' => $method));
|
||||
// fix bug on php 8.0 link: https://www.php.net/manual/zh/function.call-user-func-array.php#125953
|
||||
|
||||
@@ -652,6 +652,7 @@ class custom extends control
|
||||
$this->view->disabledFeatures = $disabledFeatures;
|
||||
$this->view->enabledScrumFeatures = $enabledScrumFeatures;
|
||||
$this->view->disabledScrumFeatures = $disabledScrumFeatures;
|
||||
$this->view->currentModeTips = sprintf($this->lang->custom->currentModeTips, $this->lang->custom->modeList[$mode], $this->lang->custom->modeList[$mode == 'light' ? 'ALM' : 'light']);
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
+10
-10
@@ -261,22 +261,22 @@ $lang->custom->modeIntroductionList['light'] = 'Provides the core function of pr
|
||||
$lang->custom->modeIntroductionList['ALM'] = 'The concept is more complete and rigorous, and the function is more abundant. It is suitable for medium and large R&D teams';
|
||||
|
||||
$lang->custom->features['program'] = 'Program';
|
||||
$lang->custom->features['productRR'] = 'Product - R&D requirements';
|
||||
$lang->custom->features['productUR'] = 'Product - User requirements';
|
||||
$lang->custom->features['productRR'] = 'Product - R&D Requirements';
|
||||
$lang->custom->features['productUR'] = 'Product - User Requirements';
|
||||
$lang->custom->features['productLine'] = 'Product - Product Line';
|
||||
$lang->custom->features['projectScrum'] = 'Project - Scrum model';
|
||||
$lang->custom->features['projectWaterfall'] = 'Project - Waterfall model';
|
||||
$lang->custom->features['projectKanban'] = 'Project - Kanban model';
|
||||
$lang->custom->features['projectScrum'] = 'Project - Scrum Model';
|
||||
$lang->custom->features['projectWaterfall'] = 'Project - Waterfall Model';
|
||||
$lang->custom->features['projectKanban'] = 'Project - Kanban Model';
|
||||
$lang->custom->features['execution'] = 'Execution';
|
||||
$lang->custom->features['qa'] = 'QA';
|
||||
$lang->custom->features['devops'] = 'DevOps';
|
||||
$lang->custom->features['kanban'] = 'Kanban';
|
||||
$lang->custom->features['doc'] = 'Document';
|
||||
$lang->custom->features['doc'] = 'Doc';
|
||||
$lang->custom->features['report'] = 'Statistics';
|
||||
$lang->custom->features['system'] = 'Organize';
|
||||
$lang->custom->features['assetlib'] = 'Assetlib';
|
||||
$lang->custom->features['oa'] = 'OA';
|
||||
$lang->custom->features['ops'] = 'Operation';
|
||||
$lang->custom->features['system'] = 'System';
|
||||
$lang->custom->features['assetlib'] = 'Asset Lib';
|
||||
$lang->custom->features['oa'] = 'Attend';
|
||||
$lang->custom->features['ops'] = 'Deploy';
|
||||
$lang->custom->features['feedback'] = 'Feedback';
|
||||
$lang->custom->features['traincourse'] = 'Academy';
|
||||
$lang->custom->features['workflow'] = 'Workflow';
|
||||
|
||||
+10
-10
@@ -261,22 +261,22 @@ $lang->custom->modeIntroductionList['light'] = 'Provides the core function of pr
|
||||
$lang->custom->modeIntroductionList['ALM'] = 'The concept is more complete and rigorous, and the function is more abundant. It is suitable for medium and large R&D teams';
|
||||
|
||||
$lang->custom->features['program'] = 'Program';
|
||||
$lang->custom->features['productRR'] = 'Product - R&D requirements';
|
||||
$lang->custom->features['productUR'] = 'Product - User requirements';
|
||||
$lang->custom->features['productRR'] = 'Product - R&D Requirements';
|
||||
$lang->custom->features['productUR'] = 'Product - User Requirements';
|
||||
$lang->custom->features['productLine'] = 'Product - Product Line';
|
||||
$lang->custom->features['projectScrum'] = 'Project - Scrum model';
|
||||
$lang->custom->features['projectWaterfall'] = 'Project - Waterfall model';
|
||||
$lang->custom->features['projectKanban'] = 'Project - Kanban model';
|
||||
$lang->custom->features['projectScrum'] = 'Project - Scrum Model';
|
||||
$lang->custom->features['projectWaterfall'] = 'Project - Waterfall Model';
|
||||
$lang->custom->features['projectKanban'] = 'Project - Kanban Model';
|
||||
$lang->custom->features['execution'] = 'Execution';
|
||||
$lang->custom->features['qa'] = 'QA';
|
||||
$lang->custom->features['devops'] = 'DevOps';
|
||||
$lang->custom->features['kanban'] = 'Kanban';
|
||||
$lang->custom->features['doc'] = 'Document';
|
||||
$lang->custom->features['doc'] = 'Doc';
|
||||
$lang->custom->features['report'] = 'Statistics';
|
||||
$lang->custom->features['system'] = 'Organize';
|
||||
$lang->custom->features['assetlib'] = 'Assetlib';
|
||||
$lang->custom->features['oa'] = 'OA';
|
||||
$lang->custom->features['ops'] = 'Operation';
|
||||
$lang->custom->features['system'] = 'System';
|
||||
$lang->custom->features['assetlib'] = 'Asset Lib';
|
||||
$lang->custom->features['oa'] = 'Attend';
|
||||
$lang->custom->features['ops'] = 'Deploy';
|
||||
$lang->custom->features['feedback'] = 'Feedback';
|
||||
$lang->custom->features['traincourse'] = 'Academy';
|
||||
$lang->custom->features['workflow'] = 'Workflow';
|
||||
|
||||
+10
-10
@@ -261,22 +261,22 @@ $lang->custom->modeIntroductionList['light'] = 'Provides the core function of pr
|
||||
$lang->custom->modeIntroductionList['ALM'] = 'The concept is more complete and rigorous, and the function is more abundant. It is suitable for medium and large R&D teams';
|
||||
|
||||
$lang->custom->features['program'] = 'Program';
|
||||
$lang->custom->features['productRR'] = 'Product - R&D requirements';
|
||||
$lang->custom->features['productUR'] = 'Product - User requirements';
|
||||
$lang->custom->features['productRR'] = 'Product - R&D Requirements';
|
||||
$lang->custom->features['productUR'] = 'Product - User Requirements';
|
||||
$lang->custom->features['productLine'] = 'Product - Product Line';
|
||||
$lang->custom->features['projectScrum'] = 'Project - Scrum model';
|
||||
$lang->custom->features['projectWaterfall'] = 'Project - Waterfall model';
|
||||
$lang->custom->features['projectKanban'] = 'Project - Kanban model';
|
||||
$lang->custom->features['projectScrum'] = 'Project - Scrum Model';
|
||||
$lang->custom->features['projectWaterfall'] = 'Project - Waterfall Model';
|
||||
$lang->custom->features['projectKanban'] = 'Project - Kanban Model';
|
||||
$lang->custom->features['execution'] = 'Execution';
|
||||
$lang->custom->features['qa'] = 'QA';
|
||||
$lang->custom->features['devops'] = 'DevOps';
|
||||
$lang->custom->features['kanban'] = 'Kanban';
|
||||
$lang->custom->features['doc'] = 'Document';
|
||||
$lang->custom->features['doc'] = 'Doc';
|
||||
$lang->custom->features['report'] = 'Statistics';
|
||||
$lang->custom->features['system'] = 'Organize';
|
||||
$lang->custom->features['assetlib'] = 'Assetlib';
|
||||
$lang->custom->features['oa'] = 'OA';
|
||||
$lang->custom->features['ops'] = 'Operation';
|
||||
$lang->custom->features['system'] = 'System';
|
||||
$lang->custom->features['assetlib'] = 'Asset Lib';
|
||||
$lang->custom->features['oa'] = 'Attend';
|
||||
$lang->custom->features['ops'] = 'Deploy';
|
||||
$lang->custom->features['feedback'] = 'Feedback';
|
||||
$lang->custom->features['traincourse'] = 'Academy';
|
||||
$lang->custom->features['workflow'] = 'Workflow';
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<h2><?php echo $lang->custom->modeManagement;?></h2>
|
||||
</div>
|
||||
<div class='main-table'>
|
||||
<p class='strong'><?php echo sprintf($lang->custom->currentModeTips, $lang->custom->modeList[$mode], $lang->custom->modeList[$mode == 'light' ? 'ALM' : 'light']);?> </p>
|
||||
<p class='strong'><?php echo $currentModeTips;?></p>
|
||||
<table class='table table-bordered'>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -55,15 +55,15 @@
|
||||
<?php endforeach;?>
|
||||
<tr class='text-center select-mode'>
|
||||
<td class='text-left strong'><?php echo $this->lang->custom->selectUsage;?></td>
|
||||
<td>
|
||||
<?php $primaryClass = $mode == 'light' ? '' : 'btn-primary';?>
|
||||
<?php $disabled = $mode == 'light' ? 'disabled' : '';?>
|
||||
<?php echo html::commonButton($lang->custom->useLight, "id='useLight' data-mode='light' $disabled", "btn btn-wide $primaryClass");?>
|
||||
<?php $title = $mode == 'light' ? "title='{$currentModeTips}'" : '';?>
|
||||
<td <?php echo $title;?>>
|
||||
<?php $disabled = $mode == 'light' ? 'disabled' : '';?>
|
||||
<?php echo html::commonButton($lang->custom->useLight, "id='useLight' data-mode='light' $disabled", "btn btn-wide btn-primary");?>
|
||||
</td>
|
||||
<td>
|
||||
<?php $primaryClass = $mode == 'ALM' ? '' : 'btn-primary';?>
|
||||
<?php $disabled = $mode == 'ALM' ? 'disabled' : '';?>
|
||||
<?php echo html::commonButton($lang->custom->useALM, "id='useALM' data-mode='ALM' $disabled", "btn btn-wide $primaryClass");?>
|
||||
<?php $title = $mode == 'ALM' ? "title='{$currentModeTips}'" : '';?>
|
||||
<td <?php echo $title;?>>
|
||||
<?php $disabled = $mode == 'ALM' ? 'disabled' : '';?>
|
||||
<?php echo html::commonButton($lang->custom->useALM, "id='useALM' data-mode='ALM' $disabled", "btn btn-wide btn-primary");?>
|
||||
<?php echo html::hidden('mode', $mode);?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -623,6 +623,7 @@ class doc extends control
|
||||
*/
|
||||
public function delete($docID, $confirm = 'no', $from = 'list')
|
||||
{
|
||||
$this->loadModel('file');
|
||||
if($confirm == 'no')
|
||||
{
|
||||
$type = $this->dao->select('type')->from(TABLE_DOC)->where('id')->eq($docID)->fetch('type');
|
||||
@@ -644,7 +645,7 @@ class doc extends control
|
||||
$this->loadModel('action')->create($file->objectType, $file->objectID, 'deletedFile', '', $extra=$file->title);
|
||||
|
||||
$fileRecord = $this->dao->select('id')->from(TABLE_FILE)->where('pathname')->eq($file->pathname)->fetch();
|
||||
if(empty($fileRecord)) @unlink($file->realPath);
|
||||
if(empty($fileRecord)) $this->file->unlinkFile($file);
|
||||
}
|
||||
|
||||
/* if ajax request, send result. */
|
||||
|
||||
@@ -93,7 +93,7 @@ class docModel extends model
|
||||
$projects = $this->loadModel('project')->getPairsByProgram();
|
||||
$executions = $this->loadModel('execution')->getPairs(0, 'all', 'multiple');
|
||||
$waterfalls = array();
|
||||
if(empty($objectID) and ($type == 'all' or $type == 'execution'))
|
||||
if(empty($objectID) and $type != 'product' and $type != 'project' and $type != 'custom')
|
||||
{
|
||||
$waterfalls = $this->dao->select('t1.id,t2.name')->from(TABLE_EXECUTION)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
|
||||
@@ -643,9 +643,7 @@ class docModel extends model
|
||||
{
|
||||
foreach($files as $file)
|
||||
{
|
||||
$pathName = $this->file->getRealPathName($file->pathname);
|
||||
$file->webPath = $this->file->webPath . $pathName;
|
||||
$file->realPath = $this->file->savePath . $pathName;
|
||||
$this->loadModel('file')->setFileWebAndRealPaths($file);
|
||||
if(strpos(",{$docContent->files},", ",{$file->id},") !== false) $docFiles[$file->id] = $file;
|
||||
}
|
||||
}
|
||||
@@ -1740,9 +1738,7 @@ class docModel extends model
|
||||
|
||||
foreach($files as $fileID => $file)
|
||||
{
|
||||
$pathName = $this->file->getRealPathName($file->pathname);
|
||||
$file->realPath = $this->file->savePath . $pathName;
|
||||
$file->webPath = $this->file->webPath . $pathName;
|
||||
$this->file->setFileWebAndRealPaths($file);
|
||||
}
|
||||
|
||||
return $files;
|
||||
|
||||
@@ -84,12 +84,8 @@
|
||||
<div class='col'>
|
||||
<div class='lib-file'>
|
||||
<?php
|
||||
$imageWidth = 0;
|
||||
if(stripos('jpg|jpeg|gif|png|bmp', $file->extension) !== false and file_exists($file->realPath))
|
||||
{
|
||||
$imageSize = getimagesize($file->realPath);
|
||||
$imageWidth = $imageSize ? $imageSize[0] : 0;
|
||||
}
|
||||
$imageSize = $this->loadModel('file')->getImageSize($file);
|
||||
$imageWidth = $imageSize[0];
|
||||
|
||||
$fileID = $file->id;
|
||||
$url = helper::createLink('file', 'download', 'fileID=' . $fileID);
|
||||
|
||||
@@ -3867,22 +3867,12 @@ class execution extends control
|
||||
|
||||
$executionStats = $this->execution->getStatData(0, $status, $productID, 0, false, $queryID, $orderBy, $pager);
|
||||
|
||||
$parentIdList = array();
|
||||
foreach($executionStats as $execution)
|
||||
{
|
||||
if($execution->type != 'stage') continue;
|
||||
if($execution->grade == 2 and $execution->project != $execution->parent) $parentIdList[$execution->parent] = $execution->parent;
|
||||
}
|
||||
$parents = array();
|
||||
if($parentIdList) $parents = $this->execution->getByIdList($parentIdList);
|
||||
|
||||
$allExecutionsNum = $this->execution->getStatData(0, 'all');
|
||||
$this->view->allExecutionsNum = count($allExecutionsNum);
|
||||
|
||||
$this->view->executionStats = $executionStats;
|
||||
$this->view->productList = $this->loadModel('product')->getProductPairsByProject(0);
|
||||
$this->view->productID = $productID;
|
||||
$this->view->parents = $parents;
|
||||
$this->view->pager = $pager;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||||
@@ -4165,7 +4155,9 @@ class execution extends control
|
||||
include $this->app->getModulePath('', 'execution') . 'lang/' . $this->app->getClientLang() . '.php';
|
||||
}
|
||||
|
||||
if($count != 0) echo js::alert(sprintf($this->lang->execution->haveDraft, $count)) . js::locate($this->createLink($moduleName, $fromMethod, $param));
|
||||
$haveDraft = sprintf($this->lang->execution->haveDraft, $count);
|
||||
if(!$execution->multiple) $haveDraft = str_replace($this->lang->executionCommon, $this->lang->projectCommon, $haveDraft);
|
||||
if($count != 0) echo js::alert($haveDraft) . js::locate($this->createLink($moduleName, $fromMethod, $param));
|
||||
return print(js::locate(helper::createLink($moduleName, $fromMethod, $param)));
|
||||
}
|
||||
|
||||
|
||||
@@ -349,7 +349,7 @@ $lang->execution->howToUpdateBurn = "<a href='https://api.zentao.net/goto.p
|
||||
$lang->execution->whyNoStories = "看起来没有{$lang->SRCommon}可以关联。请检查下{$lang->executionCommon}关联的{$lang->productCommon}中有没有{$lang->SRCommon},而且要确保它们已经审核通过。";
|
||||
$lang->execution->projectNoStories = "看起来没有{$lang->SRCommon}可以关联。请检查下项目中有没有{$lang->SRCommon},而且要确保它们已经审核通过。";
|
||||
$lang->execution->productStories = "{$lang->executionCommon}关联的{$lang->SRCommon}是{$lang->productCommon}{$lang->SRCommon}的子集,并且只有评审通过的{$lang->SRCommon}才能关联。请<a href='%s'>关联{$lang->SRCommon}</a>。";
|
||||
$lang->execution->haveDraft = "有%s条草稿状态的{$lang->SRCommon}无法关联到该执行";
|
||||
$lang->execution->haveDraft = "有%s条草稿状态的{$lang->SRCommon}无法关联到该{$lang->executionCommon}";
|
||||
$lang->execution->doneExecutions = '已结束';
|
||||
$lang->execution->selectDept = '选择部门';
|
||||
$lang->execution->selectDeptTitle = '选择一个部门的成员';
|
||||
|
||||
+18
-11
@@ -114,14 +114,12 @@ class executionModel extends model
|
||||
}
|
||||
|
||||
$stageFilter = array('request', 'design', 'review');
|
||||
if(isset($execution->attribute))
|
||||
if(isset($execution->attribute) and in_array($execution->attribute, $stageFilter))
|
||||
{
|
||||
if($this->config->edition == 'open' and in_array($execution->attribute, $stageFilter))
|
||||
{
|
||||
unset($this->lang->execution->menu->story);
|
||||
unset($this->lang->execution->menu->qa);
|
||||
unset($this->lang->execution->menu->build);
|
||||
}
|
||||
unset($this->lang->execution->menu->story);
|
||||
unset($this->lang->execution->menu->devops);
|
||||
unset($this->lang->execution->menu->qa);
|
||||
unset($this->lang->execution->menu->build);
|
||||
}
|
||||
|
||||
if($executions and (!isset($executions[$executionID]) or !$this->checkPriv($executionID))) $this->accessDenied();
|
||||
@@ -1578,6 +1576,8 @@ class executionModel extends model
|
||||
->page($pager)
|
||||
->fetchAll('id');
|
||||
|
||||
if(empty($productID) and !empty($executions)) $projectProductIdList = $this->dao->select('project, product')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($executions))->fetchPairs();
|
||||
|
||||
$hours = $this->loadModel('project')->computerProgress($executions);
|
||||
$burns = $this->getBurnData($executions);
|
||||
|
||||
@@ -1625,7 +1625,7 @@ class executionModel extends model
|
||||
}
|
||||
|
||||
/* In the case of the waterfall model, calculate the sub-stage. */
|
||||
if($param == 'skipParent')
|
||||
if($param === 'skipParent')
|
||||
{
|
||||
if($execution->parent < 0 and $execution->type == 'stage') unset($executions[$key]);
|
||||
if($execution->projectName) $execution->name = $execution->projectName . ' / ' . $execution->name;
|
||||
@@ -1638,6 +1638,12 @@ class executionModel extends model
|
||||
unset($executions[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bind execution product */
|
||||
if(!empty($projectProductIdList) and !empty($projectProductIdList[$execution->id]))
|
||||
{
|
||||
$execution->product = $projectProductIdList[$execution->id];
|
||||
}
|
||||
}
|
||||
return array_values($executions);
|
||||
}
|
||||
@@ -3170,12 +3176,12 @@ class executionModel extends model
|
||||
{
|
||||
dao::$errors['message'][] = sprintf($this->lang->execution->daysGreaterProject, $execution->days);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if((float)$hours[$key] > 24)
|
||||
{
|
||||
dao::$errors['message'][] = $this->lang->execution->errorHours;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->dao->delete()->from(TABLE_TEAM)->where('root')->eq($executionID)->andWhere('type')->eq($executionType)->exec();
|
||||
@@ -5183,7 +5189,6 @@ class executionModel extends model
|
||||
$_POST = array();
|
||||
$_POST['project'] = $projectID;
|
||||
$_POST['name'] = $project->name;
|
||||
$_POST['code'] = $project->code;
|
||||
$_POST['begin'] = $project->begin;
|
||||
$_POST['end'] = $project->end;
|
||||
$_POST['realBegan'] = $project->realBegan;
|
||||
@@ -5197,6 +5202,8 @@ class executionModel extends model
|
||||
$_POST['status'] = $project->status;
|
||||
$_POST['acl'] = 'open';
|
||||
|
||||
if(!empty($_POST['code'])) $_POST['code'] = $project->code;
|
||||
|
||||
$projectProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->fetchAll();
|
||||
foreach($projectProducts as $projectProduct)
|
||||
{
|
||||
|
||||
@@ -187,7 +187,7 @@ $closedExecutionsHtml .= '</ul>';
|
||||
<script>
|
||||
$(function()
|
||||
{
|
||||
<?php if($currentExecution->status == 'done' or $currentExecution->status == 'closed'):?>
|
||||
<?php if($currentExecution and ($currentExecution->status == 'done' or $currentExecution->status == 'closed')):?>
|
||||
$('.col-footer .toggle-right-col').click(function(){ scrollToSelected(); })
|
||||
<?php else:?>
|
||||
scrollToSelected();
|
||||
|
||||
@@ -256,7 +256,7 @@
|
||||
{
|
||||
if(!$execution->hasProduct and $value->id == 'branch') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $value->id == 'plan') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $value->id == 'stage') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $storyType == 'requirement' and $value->id == 'stage') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $storyType == 'requirement' and $value->id == 'taskCount') continue;
|
||||
if($value->show)
|
||||
{
|
||||
@@ -277,7 +277,7 @@
|
||||
{
|
||||
if(!$execution->hasProduct and $value->id == 'branch') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $value->id == 'plan') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $value->id == 'stage') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $storyType == 'requirement' and $value->id == 'stage') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $storyType == 'requirement' and $value->id == 'taskCount') continue;
|
||||
$this->story->printCell($value, $story, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table', $storyType, $execution, $showBranch);
|
||||
}
|
||||
@@ -294,7 +294,7 @@
|
||||
{
|
||||
if(!$execution->hasProduct and $value->id == 'branch') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $value->id == 'plan') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $value->id == 'stage') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $storyType == 'requirement' and $value->id == 'stage') continue;
|
||||
if(!$execution->hasProduct and !$execution->multiple and $storyType == 'requirement' and $value->id == 'taskCount') continue;
|
||||
$this->story->printCell($value, $child, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table', $storyType, $execution);
|
||||
}?>
|
||||
@@ -402,7 +402,8 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="icon icon-close"></i></button>
|
||||
<h4 class="modal-title"><?php echo $lang->execution->linkStoryByPlan;?></h4><?php echo '(' . $lang->execution->linkStoryByPlanTips . ')';?>
|
||||
<?php $linkStoryByPlanTips = $execution->multiple ? $lang->execution->linkStoryByPlanTips : str_replace($lang->executionCommon, $lang->projectCommon, $lang->execution->linkStoryByPlanTips);?>
|
||||
<h4 class="modal-title"><?php echo $lang->execution->linkStoryByPlan;?></h4><?php echo '(' . $linkStoryByPlanTips . ')';?>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class='input-group'>
|
||||
|
||||
@@ -146,7 +146,7 @@ class file extends control
|
||||
$file->extension = $extension;
|
||||
}
|
||||
|
||||
if(file_exists($file->realPath))
|
||||
if($this->file->fileExists($file))
|
||||
{
|
||||
/* If the mode is open, locate directly. */
|
||||
if($mode == 'open')
|
||||
@@ -290,7 +290,7 @@ class file extends control
|
||||
|
||||
/* Fix Bug #1518. */
|
||||
$fileRecord = $this->dao->select('id')->from(TABLE_FILE)->where('pathname')->eq($file->pathname)->fetch();
|
||||
if(empty($fileRecord)) @unlink($file->realPath);
|
||||
if(empty($fileRecord)) $this->file->unlinkFile($file);
|
||||
|
||||
/* Update test case version for test case synchronization. */
|
||||
if($file->objectType == 'testcase') $this->file->updateTestcaseVersion($file);
|
||||
@@ -500,7 +500,7 @@ class file extends control
|
||||
public function read($fileID)
|
||||
{
|
||||
$file = $this->file->getById($fileID);
|
||||
if(empty($file) or !file_exists($file->realPath)) return false;
|
||||
if(empty($file) or !$this->file->fileExists($file)) return false;
|
||||
|
||||
$obLevel = ob_get_level();
|
||||
for($i = 0; $i < $obLevel; $i++) ob_end_clean();
|
||||
|
||||
+81
-12
@@ -60,9 +60,7 @@ class fileModel extends model
|
||||
continue;
|
||||
}
|
||||
|
||||
$realPathName = $this->getRealPathName($file->pathname);
|
||||
$file->realPath = $this->savePath . $realPathName;
|
||||
$file->webPath = $this->webPath . $realPathName;
|
||||
$this->setFileWebAndRealPaths($file);
|
||||
}
|
||||
|
||||
return $files;
|
||||
@@ -88,9 +86,7 @@ class fileModel extends model
|
||||
return $file;
|
||||
}
|
||||
|
||||
$realPathName = $this->getRealPathName($file->pathname);
|
||||
$file->realPath = $this->savePath . $realPathName;
|
||||
$file->webPath = $this->webPath . $realPathName;
|
||||
$this->setFileWebAndRealPaths($file);
|
||||
|
||||
return $file;
|
||||
}
|
||||
@@ -117,9 +113,7 @@ class fileModel extends model
|
||||
continue;
|
||||
}
|
||||
|
||||
$realPathName = $this->getRealPathName($file->pathname);
|
||||
$file->realPath = $this->savePath . $realPathName;
|
||||
$file->webPath = $this->webPath . $realPathName;
|
||||
$this->setFileWebAndRealPaths($file);
|
||||
}
|
||||
|
||||
return $files;
|
||||
@@ -487,6 +481,20 @@ class fileModel extends model
|
||||
$this->webPath = $this->app->getWebRoot() . "data/upload/{$this->app->company->id}/";
|
||||
}
|
||||
|
||||
/**
|
||||
* Set paths: realPath and webPath.
|
||||
*
|
||||
* @param object $file
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function setFileWebAndRealPaths(&$file)
|
||||
{
|
||||
$pathName = $this->getRealPathName($file->pathname);
|
||||
$file->realPath = $this->savePath . $pathName;
|
||||
$file->webPath = $this->webPath . $pathName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the set image size code.
|
||||
*
|
||||
@@ -512,6 +520,30 @@ class fileModel extends model
|
||||
return str_replace(' src="data/upload', ' onload="setImageSize(this,' . $maxSize . ')" src="data/upload', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check file exists or not.
|
||||
*
|
||||
* @param object $file
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function fileExists($file)
|
||||
{
|
||||
return file_exists($file->realPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink file.
|
||||
*
|
||||
* @param object $file
|
||||
* @access public
|
||||
* @return bool|null
|
||||
*/
|
||||
public function unlinkFile($file)
|
||||
{
|
||||
return @unlink($file->realPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a file.
|
||||
*
|
||||
@@ -1021,7 +1053,7 @@ class fileModel extends model
|
||||
{
|
||||
$file = $this->getById($imageID);
|
||||
$this->dao->delete()->from(TABLE_FILE)->where('id')->eq($imageID)->exec();
|
||||
@unlink($file->realPath);
|
||||
$this->unlinkFile($file);
|
||||
}
|
||||
}
|
||||
unset($_SESSION['album'][$uid]);
|
||||
@@ -1089,7 +1121,7 @@ class fileModel extends model
|
||||
{
|
||||
if($this->config->file->storageType == 'fs')
|
||||
{
|
||||
return file_exists($file->realPath) ? getimagesize($file->realPath) : 0;
|
||||
return file_exists($file->realPath) ? getimagesize($file->realPath) : array(0, 0, $file->extension);
|
||||
}
|
||||
else if($this->config->file->storageType == 's3')
|
||||
{
|
||||
@@ -1155,7 +1187,7 @@ class fileModel extends model
|
||||
$this->dao->delete()->from(TABLE_FILE)->where('id')->in($deleteFiles)->exec();
|
||||
foreach($deleteFiles as $fileID)
|
||||
{
|
||||
@unlink($oldObject->files[$fileID]->realPath);
|
||||
$this->unlinkFile($oldObject->files[$fileID]);
|
||||
$oldFiles = empty($oldFiles) ? '' : trim(str_replace(",$fileID,", ',', ",$oldFiles,"), ',');
|
||||
}
|
||||
}
|
||||
@@ -1167,4 +1199,41 @@ class fileModel extends model
|
||||
$newObject->files = trim($oldFiles . $addedFiles, ',');
|
||||
$oldObject->files = join(',', array_keys($oldObject->files));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last modified timestamp of file.
|
||||
*
|
||||
* @param object $file
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function fileMTime($file)
|
||||
{
|
||||
return filemtime($file->realPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file size.
|
||||
*
|
||||
* @param object $file
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function fileSize($file)
|
||||
{
|
||||
return filesize($file->realPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save file to local storage temporarily.
|
||||
*
|
||||
* @param object $file
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function saveAsTempFile($file)
|
||||
{
|
||||
/* If the storage type is local, do nothing. */
|
||||
if($this->config->file->storageType == 'fs') return $file->realPath;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,12 +54,9 @@
|
||||
$uploadDate = $lang->file->uploadDate . substr($file->addedDate, 0, 10);
|
||||
$fileTitle = "<i class='icon icon-file-text'></i> " . $file->title;
|
||||
if(strpos($file->title, ".{$file->extension}") === false && $file->extension != 'txt') $fileTitle .= ".{$file->extension}";
|
||||
$imageWidth = 0;
|
||||
if(stripos('jpg|jpeg|gif|png|bmp', $file->extension) !== false)
|
||||
{
|
||||
$imageSize = $this->file->getImageSize($file);
|
||||
$imageWidth = $imageSize ? $imageSize[0] : 0;
|
||||
}
|
||||
|
||||
$imageSize = $this->file->getImageSize($file);
|
||||
$imageWidth = $imageSize[0];
|
||||
|
||||
$fileSize = 0;
|
||||
/* Show size info. */
|
||||
|
||||
@@ -157,7 +157,7 @@ function setFileName(fileID)
|
||||
if(stripos('jpg|jpeg|gif|png|bmp', $file->extension) !== false)
|
||||
{
|
||||
$imageSize = $this->file->getImageSize($file);
|
||||
$imageWidth = $imageSize ? $imageSize[0] : 0;
|
||||
$imageWidth = $imageSize[0];
|
||||
}
|
||||
|
||||
$fileSize = 0;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#mainContent tr td {background-color: rgb(255, 255, 255); border-bottom: 1px solid rgb(238, 238, 238); border-right: 1px solid rgb(238, 238, 238);}
|
||||
|
||||
.btn-wide {padding: 6px 85px;}
|
||||
#useLight:hover, #useALM:hover{color: #fff; background-color: #2e7fff; border-color: transparent;}
|
||||
|
||||
#mainContent .datatable {cursor: default;}
|
||||
.container {padding-top: 20px;}
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
<td title="<?php echo zget($lang->bug->typeList, $bug->type, '');?>"><?php echo zget($lang->bug->typeList, $bug->type, '');?></td>
|
||||
<td class='text-left nobr'>
|
||||
<?php
|
||||
if(isset($bug->shadow))
|
||||
if(isset($bug->shadow) and !empty($bug->shadow))
|
||||
{
|
||||
echo html::a($this->createLink('project', 'browse'), $bug->productName, null, "title={$bug->productName}");
|
||||
}
|
||||
|
||||
@@ -894,6 +894,7 @@ class product extends control
|
||||
public function ajaxGetProducts($executionID)
|
||||
{
|
||||
$this->loadModel('build');
|
||||
if(!$executionID) return print(html::select('product', array(), '', "class='form-control chosen' required"));
|
||||
$products = $this->product->getProductPairsByProject($executionID);
|
||||
if(empty($products))
|
||||
{
|
||||
@@ -961,6 +962,7 @@ class product extends control
|
||||
if($execution->type == 'kanban') $projectID = $execution->project;
|
||||
}
|
||||
|
||||
if($projectID) $project = $this->loadModel('project')->getById($projectID);
|
||||
$mode .= ($from == 'bugToTask' or empty($this->config->CRExecution)) ? 'noclosed' : '';
|
||||
$mode .= !$projectID ? ',multiple' : '';
|
||||
$executions = $from == 'showImport' ? $this->product->getAllExecutionPairsByProduct($productID, $branch, $projectID) : $this->product->getExecutionPairsByProduct($productID, $branch, 'id_desc', $projectID, $mode);
|
||||
@@ -969,7 +971,8 @@ class product extends control
|
||||
if($number === '')
|
||||
{
|
||||
$event = $from == 'bugToTask' ? '' : " onchange='loadExecutionRelated(this.value)'";
|
||||
return print(html::select('execution', array('' => '') + $executions, $executionID, "class='form-control' $event"));
|
||||
$datamultiple = !empty($project) ? "data-multiple={$project->multiple}" : '';
|
||||
return print(html::select('execution', array('' => '') + $executions, $executionID, "class='form-control' $datamultiple $event"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -27,11 +27,6 @@ $(function()
|
||||
}
|
||||
})
|
||||
|
||||
$('#reviewItem ~ ul > li').on('click', function()
|
||||
{
|
||||
if(storyString !== '') alert(reviewStory);
|
||||
});
|
||||
|
||||
$(document).on('click', '.story-toggle', function(e)
|
||||
{
|
||||
var $toggle = $(this);
|
||||
@@ -79,6 +74,38 @@ $(function()
|
||||
});
|
||||
});
|
||||
|
||||
$('#reviewItem ~ ul > li').on('click', function()
|
||||
{
|
||||
var storyIDList = new Array();
|
||||
var storyString = '';
|
||||
var reviewStoryTips = '';
|
||||
$("input[name^='storyIdList']:checked").each(function()
|
||||
{
|
||||
storyIDList.push($(this).val());
|
||||
});
|
||||
|
||||
$.each(storyIDList, function(storyKey, storyValue)
|
||||
{
|
||||
var getStoryReview = createLink('product', 'ajaxGetReviewers', "productID=" + productID + "&storyID=" + storyValue);
|
||||
|
||||
$.ajaxSettings.async = false;
|
||||
$.get(getStoryReview, function(data)
|
||||
{
|
||||
var reviewer = new Array();
|
||||
$(data).find('option:selected').each(function()
|
||||
{
|
||||
reviewer.push($(this).val());
|
||||
});
|
||||
|
||||
if($.inArray(account, reviewer) == -1) storyString += ' #' + storyValue;
|
||||
});
|
||||
$.ajaxSettings.async = true;
|
||||
});
|
||||
|
||||
reviewStoryTips = reviewStory.replace("%s", storyString);
|
||||
if(storyString !== '') alert(reviewStoryTips);
|
||||
});
|
||||
|
||||
$('#batchUnlinkStory').click(function()
|
||||
{
|
||||
var storyIdList = '';
|
||||
|
||||
@@ -101,7 +101,7 @@ $lang->product->changeLineError = "Products already exist under the product
|
||||
$lang->product->programEmpty = 'Program should not be empty!';
|
||||
$lang->product->nameIsDuplicate = "『%s』 product line already exists, please reset!";
|
||||
$lang->product->nameIsDuplicated = "Product Line『%s』 exists. Go to Admin->System->Data->Recycle Bin to restore it, if you are sure it is deleted.";
|
||||
$lang->product->reviewStory = 'You are not a reviewer for needs " %s %s", and cannot review. This operation has been filtered';
|
||||
$lang->product->reviewStory = 'You are not a reviewer for needs "%s" , and cannot review. This operation has been filtered';
|
||||
|
||||
$lang->product->id = 'ID';
|
||||
$lang->product->program = "Program";
|
||||
|
||||
@@ -101,7 +101,7 @@ $lang->product->changeLineError = "Products already exist under the product
|
||||
$lang->product->programEmpty = 'Program should not be empty!';
|
||||
$lang->product->nameIsDuplicate = "『%s』 product line already exists, please reset!";
|
||||
$lang->product->nameIsDuplicated = "Product Line『%s』 exists. Go to Admin->System->Data->Recycle Bin to restore it, if you are sure it is deleted.";
|
||||
$lang->product->reviewStory = 'You are not a reviewer for needs " %s %s", and cannot review. This operation has been filtered';
|
||||
$lang->product->reviewStory = 'You are not a reviewer for needs "%s" , and cannot review. This operation has been filtered';
|
||||
|
||||
$lang->product->id = 'ID';
|
||||
$lang->product->program = "Program";
|
||||
|
||||
@@ -101,7 +101,7 @@ $lang->product->changeLineError = "产品线下已有产品,不可修改
|
||||
$lang->product->programEmpty = '项目集不能为空';
|
||||
$lang->product->nameIsDuplicate = "『%s』产品线已经存在,请重新设置!";
|
||||
$lang->product->nameIsDuplicated = "产品线已经有『%s』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。";
|
||||
$lang->product->reviewStory = '您不是研发需求"%s %s"的评审人,无法评审,本次操作已被过滤。';
|
||||
$lang->product->reviewStory = '您不是研发需求 "%s" 的评审人,无法评审,本次操作已被过滤。';
|
||||
|
||||
$lang->product->id = '编号';
|
||||
$lang->product->program = "所属项目集";
|
||||
|
||||
@@ -101,7 +101,7 @@ class productModel extends model
|
||||
|
||||
if($isQaModule and $this->app->tab == 'project')
|
||||
{
|
||||
if($this->app->tab == 'project') $extra = $currentMethod == 'testcase' ? $extra : $this->session->project;
|
||||
if($this->app->tab == 'project') $extra = strpos(',testcase,groupCase,zeroCase,', ",$currentMethod,") !== false ? $extra : $this->session->project;
|
||||
if($this->app->tab == 'execution') $extra = $this->session->execution;
|
||||
}
|
||||
|
||||
@@ -2346,9 +2346,13 @@ class productModel extends model
|
||||
}
|
||||
elseif($module == 'testcase' and in_array($method, array('groupCase', 'zeroCase')) and $this->app->tab == 'project')
|
||||
{
|
||||
parse_str($extra, $output);
|
||||
$projectID = isset($output['projectID']) ? $output['projectID'] : 0;
|
||||
$link = helper::createLink($module, $method, "productID=%s&branch=" . ($branch ? "%s" : 'all') . "&groupBy=&projectID=$projectID") . "#app=project";
|
||||
$projectID = $extra;
|
||||
if(strpos($extra, 'projecID') !== false)
|
||||
{
|
||||
parse_str($extra, $output);
|
||||
$projectID = isset($output['projectID']) ? $output['projectID'] : 0;
|
||||
}
|
||||
$link = helper::createLink($module, $method, "productID=%s&branch=" . ($branch ? "%s" : 'all') . "&groupBy=&projectID=$projectID") . "#app=project";
|
||||
}
|
||||
elseif($module == 'testcase' and $method == 'browse')
|
||||
{
|
||||
|
||||
@@ -56,9 +56,9 @@ foreach($products as $programID => $programProducts)
|
||||
}
|
||||
$productsPinYin = common::convert2Pinyin($productNames);
|
||||
|
||||
$myProductsHtml = $config->systemMode == 'ALM' ? '<ul class="tree tree-angles" data-ride="tree">' : '<ul class="noProgram">';
|
||||
$normalProductsHtml = $config->systemMode == 'ALM' ? '<ul class="tree tree-angles" data-ride="tree">' : '<ul class="noProgram">';
|
||||
$closedProductsHtml = $config->systemMode == 'ALM' ? '<ul class="tree tree-angles" data-ride="tree">' : '<ul class="noProgram">';
|
||||
$myProductsHtml = $config->systemMode == 'ALM' ? '<ul class="tree tree-angles" data-ride="tree">' : '';
|
||||
$normalProductsHtml = $config->systemMode == 'ALM' ? '<ul class="tree tree-angles" data-ride="tree">' : '';
|
||||
$closedProductsHtml = $config->systemMode == 'ALM' ? '<ul class="tree tree-angles" data-ride="tree">' : '';
|
||||
|
||||
foreach($products as $programID => $programProducts)
|
||||
{
|
||||
|
||||
@@ -20,8 +20,6 @@ body {margin-bottom: 25px;}
|
||||
.assignedTo{border-radius: 4px !important;}
|
||||
</style>
|
||||
<?php
|
||||
$storyString = '';
|
||||
$reviewStoryTips = '';
|
||||
$lang->story->createCommon = $storyType == 'story' ? $lang->story->createStory : $lang->story->createRequirement;
|
||||
$unfoldStories = isset($config->product->browse->unfoldStories) ? json_decode($config->product->browse->unfoldStories, true) : array();
|
||||
$unfoldStories = zget($unfoldStories, $productID, array());
|
||||
@@ -29,6 +27,8 @@ $isProjectStory = $this->app->rawModule == 'projectstory';
|
||||
$projectHasProduct = $isProjectStory && !empty($project->hasProduct);
|
||||
$projectIDParam = $isProjectStory ? "projectID=$projectID&" : '';
|
||||
js::set('browseType', $browseType);
|
||||
js::set('account', $this->app->user->account);
|
||||
js::set('reviewStory', $lang->product->reviewStory);
|
||||
js::set('productID', $productID);
|
||||
js::set('projectID', $projectID);
|
||||
js::set('branch', $branch);
|
||||
@@ -76,13 +76,14 @@ js::set('vision', $this->config->vision);
|
||||
<?php if($isProjectStory): ?>
|
||||
<?php if(!empty($project->hasProduct)):?>
|
||||
<div class='btn-group'>
|
||||
<a href='javascript:;' class='btn btn-link btn-limit text-ellipsis' data-toggle='dropdown' style="max-width: 120px;"><span class='text' title='<?php echo $productName;?>'><?php echo $productName;?></span> <span class='caret'></span></a>
|
||||
<a href='javascript:;' class='btn btn-link btn-limit text-ellipsis' data-toggle='dropdown' style="max-width: 120px;"><div class='text' style="overflow: hidden;" title='<?php echo $productName;?>'><?php echo $productName;?></div> <span class='caret'></span></a>
|
||||
<ul class='dropdown-menu' style='max-height:240px; max-width: 300px; overflow-y:auto'>
|
||||
<?php
|
||||
echo "<li>" . html::a($this->createLink('projectstory', 'story', "projectID=$projectID"), $lang->product->all) . "</li>";
|
||||
echo '<li ' . (empty($productID) ? "class='active'" : '') . '>' . html::a($this->createLink('projectstory', 'story', "projectID=$projectID"), $lang->product->all) . "</li>";
|
||||
foreach($projectProducts as $projectProduct)
|
||||
{
|
||||
echo "<li>" . html::a($this->createLink('projectstory', 'story', "projectID=$projectID&productID=$projectProduct->id&branch=all"), $projectProduct->name, '', "title='{$projectProduct->name}' class='text-ellipsis'") . "</li>";
|
||||
$active = $projectProduct->id == $productID ? "class='active'" : '';
|
||||
echo "<li $active>" . html::a($this->createLink('projectstory', 'story', "projectID=$projectID&productID=$projectProduct->id&branch=all"), $projectProduct->name, '', "title='{$projectProduct->name}' class='text-ellipsis'") . "</li>";
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
@@ -403,12 +404,7 @@ js::set('vision', $this->config->vision);
|
||||
<div class="table-actions btn-toolbar">
|
||||
<div class='btn-group dropup'>
|
||||
<?php
|
||||
foreach($stories as $story)
|
||||
{
|
||||
$storyProductIds[$story->product] = $story->product;
|
||||
if(!in_array($this->app->user->account, $story->reviewer)) $storyString .= $story->title . ',';
|
||||
}
|
||||
$reviewStoryTips = sprintf($lang->product->reviewStory, '', $storyString);
|
||||
foreach($stories as $story) $storyProductIds[$story->product] = $story->product;
|
||||
$storyProductID = count($storyProductIds) > 1 ? 0 : $productID;
|
||||
$disabled = $canBatchEdit ? '' : "disabled='disabled'";
|
||||
$actionLink = $this->createLink('story', 'batchEdit', "productID=$storyProductID&projectID=$projectID&branch=$branch&storyType=$storyType");
|
||||
@@ -701,10 +697,6 @@ js::set('vision', $this->config->vision);
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
js::set('storyString', $storyString);
|
||||
js::set('reviewStory', $reviewStoryTips);
|
||||
?>
|
||||
<script>
|
||||
var moduleID = <?php echo $moduleID?>;
|
||||
var branchID = $.cookie('storyBranch');
|
||||
|
||||
@@ -1609,7 +1609,7 @@ class programModel extends model
|
||||
$menu .= "<div class='btn-group'>";
|
||||
$menu .= "<button type='button' class='btn dropdown-toggle' data-toggle='context-dropdown' title='{$this->lang->more}'><i class='icon-ellipsis-v'></i></button>";
|
||||
$menu .= "<ul class='dropdown-menu pull-right text-center' role='menu'>";
|
||||
$menu .= $this->buildMenu('project', 'manageProducts', "$params&from=program", $program, $type, 'link', '', 'btn-action', '', "data-app='project'");
|
||||
$menu .= $this->buildMenu('project', 'manageProducts', "$params&from=program", $program, $type, 'link', '', 'btn-action', '', "data-app='project'" . ($program->hasProduct ? '' : " disabled='disabled'"));
|
||||
|
||||
$disabledWhitelist = $program->acl == 'open' ? " disabled='disabled' style='pointer-events: none;'" : '';
|
||||
$menu .= $this->buildMenu('project', 'whitelist', "$params&module=project&from=browse", $program, $type, 'shield-check', '', 'btn-action', '', "data-app='project'" . $disabledWhitelist);
|
||||
|
||||
@@ -68,6 +68,7 @@ class project extends control
|
||||
$fields[$fieldName] = zget($projectLang, $fieldName);
|
||||
unset($fields[$key]);
|
||||
}
|
||||
if(isset($this->config->setCode) and empty($this->config->setCode)) unset($fields['code']);
|
||||
|
||||
if(isset($fields['hasProduct'])) $fields['hasProduct'] = $projectLang->type;
|
||||
|
||||
@@ -2240,8 +2241,7 @@ class project extends control
|
||||
$branchGroups = $this->loadModel('branch')->getByProducts(array_keys($allProducts), 'ignoreNormal|noclosed');
|
||||
if($this->config->systemMode == 'ALM')
|
||||
{
|
||||
$paths = explode(',', trim($project->path, ','));
|
||||
$topProgramID = count($paths) > 1 ? $this->program->getTopByPath($project->path) : 0;
|
||||
$topProgramID = $project->parent ? $this->program->getTopByPath($project->path) : 0;
|
||||
$productsGroupByProgram = $this->product->getProductsGroupByProgram();
|
||||
|
||||
$currentProducts = array();
|
||||
|
||||
@@ -1,21 +1,3 @@
|
||||
$(function()
|
||||
{
|
||||
$('#createBuild').click(function()
|
||||
{
|
||||
if(executions.length == 0)
|
||||
{
|
||||
var message = noDevStage;
|
||||
if(allExecutions.length == 0) message = createExecution;
|
||||
alert(message);
|
||||
|
||||
var link = createLink('execution', 'create', 'projectID=' + projectID);
|
||||
|
||||
window.parent.$.apps.open(link, 'execution');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Change product.
|
||||
*
|
||||
|
||||
@@ -150,11 +150,12 @@ function loadBranches(product)
|
||||
/* When selecting a product, delete a plan that is empty by default. */
|
||||
$("#planDefault").remove();
|
||||
|
||||
var chosenProducts = 0;
|
||||
var chosenProducts = [];
|
||||
$("#productsBox select[name^='products']").each(function()
|
||||
{
|
||||
var $product = $(product);
|
||||
if($(this).val() > 0) chosenProducts ++;
|
||||
var productID = $(this).val();
|
||||
if(productID > 0 && chosenProducts.indexOf(productID) == -1) chosenProducts.push(productID);
|
||||
if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id') && !multiBranchProducts[$product.val()])
|
||||
{
|
||||
bootbox.alert(errorSameProducts);
|
||||
@@ -164,7 +165,7 @@ function loadBranches(product)
|
||||
}
|
||||
});
|
||||
|
||||
chosenProducts > 1 ? $('.division').removeClass('hide') : $('.division').addClass('hide');
|
||||
chosenProducts.length > 1 ? $('.division').removeClass('hide') : $('.division').addClass('hide');
|
||||
|
||||
if($('#productsBox .input-group:last select:first').val() != 0)
|
||||
{
|
||||
|
||||
@@ -294,11 +294,12 @@ function loadBranches(product)
|
||||
/* When selecting a product, delete a plan that is empty by default. */
|
||||
$("#planDefault").remove();
|
||||
|
||||
var chosenProducts = 0;
|
||||
var chosenProducts = [];
|
||||
$("#productsBox select[name^='products']").each(function()
|
||||
{
|
||||
var $product = $(product);
|
||||
if($(this).val() > 0) chosenProducts ++;
|
||||
var $product = $(product);
|
||||
var productID = $(this).val();
|
||||
if(productID > 0 && chosenProducts.indexOf(productID) == -1) chosenProducts.push(productID);
|
||||
if($product.val() != 0 && $product.val() == $(this).val() && $product.attr('id') != $(this).attr('id') && !multiBranchProducts[$product.val()])
|
||||
{
|
||||
bootbox.alert(errorSameProducts);
|
||||
@@ -308,7 +309,7 @@ function loadBranches(product)
|
||||
}
|
||||
});
|
||||
|
||||
(chosenProducts > 1 && model == 'waterfall') ? $('.division').removeClass('hide') : $('.division').addClass('hide');
|
||||
(chosenProducts.length > 1 && model == 'waterfall') ? $('.division').removeClass('hide') : $('.division').addClass('hide');
|
||||
|
||||
if($('#productsBox .row .input-group:last select:first').val() != 0)
|
||||
{
|
||||
|
||||
@@ -69,6 +69,68 @@ $(function()
|
||||
}
|
||||
});
|
||||
|
||||
$('form#productsBox').submit();
|
||||
var checkedProducts = [];
|
||||
var otherProducts = $('#otherProducts').val();
|
||||
for(key in otherProducts)
|
||||
{
|
||||
var productBranch = otherProducts[key].split('_');
|
||||
var selectProduct = productBranch[0];
|
||||
if(checkedProducts.indexOf(selectProduct) == -1) checkedProducts.push(selectProduct);
|
||||
}
|
||||
|
||||
$('input[name^="products"]:checked').each(function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if(checkedProducts.indexOf(value) == -1) checkedProducts.push(value);
|
||||
})
|
||||
|
||||
if(noticeSwitch && checkedProducts.length > 1)
|
||||
{
|
||||
notice();
|
||||
}
|
||||
else
|
||||
{
|
||||
$('form#productsBox').submit();
|
||||
}
|
||||
});
|
||||
|
||||
$('#submit').click(function()
|
||||
{
|
||||
var checkedProducts = [];
|
||||
$('input[name^="products"]:checked').each(function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if(checkedProducts.indexOf(value) == -1) checkedProducts.push(value);
|
||||
})
|
||||
|
||||
if(noticeSwitch && checkedProducts.length > 1)
|
||||
{
|
||||
notice();
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
function notice()
|
||||
{
|
||||
bootbox.confirm(
|
||||
{
|
||||
'message' : noticeDivsion,
|
||||
'buttons':{
|
||||
confirm:{
|
||||
label: divisionSwitchList['1'],
|
||||
className: 'btn'
|
||||
},
|
||||
cancel:{
|
||||
label: divisionSwitchList['0'],
|
||||
className: 'btn-primary'
|
||||
},
|
||||
},
|
||||
callback: function(result)
|
||||
{
|
||||
if(result) $('#submit').after("<input type='hidden' value='1' name='division'>");
|
||||
$('form#productsBox').submit();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2369,6 +2369,11 @@ class projectModel extends model
|
||||
}
|
||||
|
||||
$this->user->updateUserView($products, 'product', $members);
|
||||
if((int)$projectID > 0 and !empty($_POST['division']))
|
||||
{
|
||||
$this->dao->update(TABLE_PROJECT)->set('division')->eq('1')->where('id')->eq((int)$projectID)->exec();
|
||||
$this->dao->update(TABLE_EXECUTION)->set('division')->eq('1')->where('project')->eq((int)$projectID)->exec();
|
||||
}
|
||||
|
||||
return !dao::isError();
|
||||
}
|
||||
@@ -3019,7 +3024,7 @@ class projectModel extends model
|
||||
$menu .= "<div class='btn-group'>";
|
||||
$menu .= "<button type='button' class='btn dropdown-toggle' data-toggle='context-dropdown' title='{$this->lang->more}'><i class='icon-ellipsis-v'></i></button>";
|
||||
$menu .= "<ul class='dropdown-menu pull-right text-center' role='menu'>";
|
||||
if($project->hasProduct) $menu .= $this->buildMenu($moduleName, 'manageProducts', $params . "&from={$this->app->tab}", $project, 'browse', 'link', '', 'btn-action', '', '', $this->lang->project->manageProducts);
|
||||
$menu .= $this->buildMenu($moduleName, 'manageProducts', $params . "&from={$this->app->tab}", $project, 'browse', 'link', '', 'btn-action', '', $project->hasProduct ? '' : "disabled='disabled'", $this->lang->project->manageProducts);
|
||||
$menu .= $this->buildMenu('project', 'whitelist', "$params&module=project&from=$from", $project, 'browse', 'shield-check', '', 'btn-action', '', $dataApp);
|
||||
$menu .= $this->buildMenu($moduleName, "delete", $params, $project, 'browse', 'trash', 'hiddenwin', 'btn-action');
|
||||
$menu .= "</ul>";
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<?php if($project->hasProduct):?>
|
||||
<?php if($project->hasProduct and $this->config->vision != 'lite'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->manageProducts;?></th>
|
||||
<td class='text-left' id='productsBox' colspan="3">
|
||||
|
||||
@@ -104,7 +104,8 @@
|
||||
<tbody id="executionTableList">
|
||||
<?php foreach($executionStats as $execution):?>
|
||||
<?php $execution->division = $project->division;?>
|
||||
<?php $this->execution->printNestedList($execution, false, $users, $productID);?>
|
||||
<?php $executionProductID = (empty($productID) and !empty($execution->product)) ? $execution->product : $productID;?>
|
||||
<?php $this->execution->printNestedList($execution, false, $users, $executionProductID);?>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
<?php $i = 0;?>
|
||||
<?php foreach($linkedProducts as $productID => $linkedProduct):?>
|
||||
<?php foreach($linkedBranches[$productID] as $branchID):?>
|
||||
<?php $disabled = in_array($productID, $unmodifiableProducts) ? "disabled='disabled'" : '';?>
|
||||
<?php $cannotUnlink = (in_array($productID, $unmodifiableProducts) and ($project->model == 'waterfall'));?>
|
||||
<?php $disabled = $cannotUnlink ? "disabled='disabled'" : '';?>
|
||||
<div class='col-sm-4'>
|
||||
<div class='product checked <?php echo isset($allBranches[$productID]) ? ' has-branch' : ''?>'>
|
||||
<div class="checkbox-primary" title='<?php echo $linkedProduct->name;?>'>
|
||||
@@ -48,6 +49,7 @@
|
||||
<?php if(isset($allBranches[$productID][$branchID])) echo html::select("branch[$i]", $allBranches[$productID], $branchID, "class='form-control chosen' data-drop_direction='down' disabled='disabled'");?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if($cannotUnlink) echo html::hidden("products[$i]", $productID);?>
|
||||
<?php echo html::hidden("branch[$i]", $branchID);?>
|
||||
|
||||
<?php
|
||||
@@ -135,35 +137,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if(!$project->division and count($linkedProducts) == 1 and empty($executions)):?>
|
||||
<?php $noticeSwitch = (!$project->division and count($linkedProducts) == 1 and empty($executions));?>
|
||||
<?php js::set('linkedProducts', array_keys($linkedProducts));?>
|
||||
<?php js::set('noticeSwitch', $noticeSwitch);?>
|
||||
<?php js::set('noticeDivsion', $lang->project->noticeDivsion);?>
|
||||
<?php js::set('divisionSwitchList', $lang->project->divisionSwitchList);?>
|
||||
<script>
|
||||
$('#submit').click(function()
|
||||
{
|
||||
bootbox.confirm(
|
||||
{
|
||||
'message' : noticeDivsion,
|
||||
'buttons':{
|
||||
confirm:{
|
||||
label: divisionSwitchList['1'],
|
||||
className: 'btn'
|
||||
},
|
||||
cancel:{
|
||||
label: divisionSwitchList['0'],
|
||||
className: 'btn-primary'
|
||||
},
|
||||
},
|
||||
callback: function(result)
|
||||
{
|
||||
if(result) $('div.form-actions').append("<input type='hidden' value='1' name='division'>");
|
||||
$('form').submit();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
})
|
||||
</script>
|
||||
<?php endif;?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
<?php if($project->deleted):?>
|
||||
<span class='label label-danger label-outline'><?php echo $lang->project->deleted;?></span>
|
||||
<?php endif; ?>
|
||||
<span class="label label-primary label-outline"><?php echo zget($lang->execution->lifeTimeList, $project->lifetime);?></span>
|
||||
<span class="label label-primary label-outline"><?php echo zget($lang->execution->lifeTimeList, $project->lifetime, '');?></span>
|
||||
<?php if(isset($project->delay)):?>
|
||||
<span class="label label-danger label-outline"><?php echo $lang->project->delayed;?></span>
|
||||
<?php else:?>
|
||||
|
||||
@@ -91,6 +91,19 @@ class release extends control
|
||||
$buildList = $this->build->getByList(array_keys($builds));
|
||||
foreach($buildList as $build)
|
||||
{
|
||||
if(!$build->execution && !empty($build->builds))
|
||||
{
|
||||
$childBuilds = $this->build->getByList($build->builds);
|
||||
foreach($childBuilds as $childBuild)
|
||||
{
|
||||
$childBuild->stories = trim($childBuild->stories, ',');
|
||||
$childBuild->bugs = trim($childBuild->bugs, ',');
|
||||
|
||||
if($childBuild->stories) $build->stories .= ',' . $childBuild->stories;
|
||||
if($childBuild->bugs) $build->bugs .= ',' . $childBuild->bugs;
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($build->stories) or !empty($build->bugs)) $notEmptyBuilds[$build->id] = $build->id;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ $lang->release->errorDate = '发布日期不能大于今天。';
|
||||
$lang->release->basicInfo = '基本信息';
|
||||
|
||||
$lang->release->id = 'ID';
|
||||
$lang->release->product = $lang->productCommon;
|
||||
$lang->release->product = '所属产品';
|
||||
$lang->release->branch = '平台/分支';
|
||||
$lang->release->project = '所属项目';
|
||||
$lang->release->build = '版本';
|
||||
|
||||
@@ -374,7 +374,7 @@ class releaseModel extends model
|
||||
}
|
||||
elseif($notify == 'SC' and !empty($release->build))
|
||||
{
|
||||
$stories = $this->dao->select('stories')->from(TABLE_BUILD)->where('id')->eq($release->build)->fetch('stories');
|
||||
$stories = join(',', $this->dao->select('stories')->from(TABLE_BUILD)->where('id')->in($release->build)->fetchAll());
|
||||
$stories .= $this->dao->select('stories')->from(TABLE_RELEASE)->where('id')->eq($release->id)->fetch('stories');
|
||||
$stories = trim($stories, ',');
|
||||
|
||||
@@ -390,7 +390,7 @@ class releaseModel extends model
|
||||
$objectID = $notify == 'ET' ? $release->build : $release->id;
|
||||
$members = $this->dao->select('t2.account')->from($table)->alias('t1')
|
||||
->leftJoin(TABLE_TEAM)->alias('t2')->on("t1.$type=t2.root")
|
||||
->where('t1.id')->eq($objectID)
|
||||
->where('t1.id')->in($objectID)
|
||||
->andWhere('t2.type')->eq($type)
|
||||
->fetchPairs();
|
||||
|
||||
|
||||
@@ -145,8 +145,8 @@ $config->story->datatable->fieldList['branch']['title'] = 'branch';
|
||||
$config->story->datatable->fieldList['branch']['fixed'] = 'no';
|
||||
$config->story->datatable->fieldList['branch']['width'] = '100';
|
||||
$config->story->datatable->fieldList['branch']['required'] = 'no';
|
||||
$config->story->datatable->fieldList['branch']['control'] = 'multiple';
|
||||
$config->story->datatable->fieldList['branch']['dataSource'] = array('module' => 'story', 'method' => 'getRelatedObjects', 'params' => 'branch&id,name');
|
||||
$config->story->datatable->fieldList['branch']['control'] = 'select';
|
||||
$config->story->datatable->fieldList['branch']['dataSource'] = array('module' => 'branch', 'method' => 'getPairs', 'params' => '$productID&active');
|
||||
|
||||
$config->story->datatable->fieldList['module']['title'] = 'module';
|
||||
$config->story->datatable->fieldList['module']['control'] = 'select';
|
||||
|
||||
@@ -47,13 +47,13 @@ class storyModel extends model
|
||||
if($setImgSize) $story->spec = $this->file->setImgSize($story->spec);
|
||||
if($setImgSize) $story->verify = $this->file->setImgSize($story->verify);
|
||||
|
||||
$story->executions = $this->dao->select('t1.project, t2.name, t2.status, t2.type')->from(TABLE_PROJECTSTORY)->alias('t1')
|
||||
$story->executions = $this->dao->select('t1.project, t2.name, t2.status, t2.type, t2.multiple')->from(TABLE_PROJECTSTORY)->alias('t1')
|
||||
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.project = t2.id')
|
||||
->where('t1.story')->eq($storyID)
|
||||
->andWhere('t2.type')->in('sprint,stage,kanban')
|
||||
->orderBy('t1.`order` DESC')
|
||||
->fetchAll('project');
|
||||
$story->tasks = $this->dao->select('id, name, assignedTo, execution, status, consumed, `left`,type')->from(TABLE_TASK)->where('story')->eq($storyID)->andWhere('deleted')->eq(0)->orderBy('id DESC')->fetchGroup('execution');
|
||||
$story->tasks = $this->dao->select('id, name, assignedTo, execution, project, status, consumed, `left`,type')->from(TABLE_TASK)->where('story')->eq($storyID)->andWhere('deleted')->eq(0)->orderBy('id DESC')->fetchGroup('execution');
|
||||
$story->stages = $this->dao->select('*')->from(TABLE_STORYSTAGE)->where('story')->eq($storyID)->fetchPairs('branch', 'stage');
|
||||
//$story->bugCount = $this->dao->select('COUNT(*)')->alias('count')->from(TABLE_BUG)->where('story')->eq($storyID)->fetch('count');
|
||||
//$story->caseCount = $this->dao->select('COUNT(*)')->alias('count')->from(TABLE_CASE)->where('story')->eq($storyID)->fetch('count');
|
||||
|
||||
@@ -458,11 +458,12 @@
|
||||
foreach($executionTasks as $task)
|
||||
{
|
||||
if(!isset($executions[$task->execution])) continue;
|
||||
$execution = isset($story->executions[$task->execution]) ? $story->executions[$task->execution] : '';
|
||||
$executionLink = !empty($execution->multiple) ? $this->createLink('execution', 'view', "executionID=$task->execution") : $this->createLink('project', 'view', "executionID=$task->project");
|
||||
$executionName = $executions[$task->execution];
|
||||
$taskInfo = $task->id . ' <span class="label label-success label-outline">' . $this->lang->task->statusList[$task->status] . '</span> ' . $task->name;
|
||||
$class = isonlybody() ? 'showinonlybody' : 'iframe';
|
||||
$execution = isset($story->executions[$task->execution]) ? $story->executions[$task->execution] : '';
|
||||
$execName = (isset($execution->type) and $execution->type == 'kanban' and isonlybody()) ? $executionName : html::a($this->createLink('execution', 'view', "executionID=$task->execution"), $executionName, '', "class='text-muted'");
|
||||
$execName = (isset($execution->type) and $execution->type == 'kanban' and isonlybody()) ? $executionName : html::a($executionLink, $executionName, '', "class='text-muted'");
|
||||
echo "<li title='$task->name'>" . $execName . html::a($this->createLink('task', 'view', "taskID=$task->id", '', true), $taskInfo, '', "class=$class data-width='80%'") . '</li>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,11 @@ $(function()
|
||||
{
|
||||
$('.record-estimate-toggle').modalTrigger({width:900, type:'iframe', afterHide: function(){parent.location.href=parent.location.href;}});
|
||||
if(!newRowCount) $('#taskTeamEditor tr.member').last().addClass('member-last');
|
||||
|
||||
if($('#consumedSpan').parent().find('button').hasClass('disabled'))
|
||||
{
|
||||
$('#consumedSpan').parent().find('button').attr('disabled','disabled')
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
|
||||
@@ -254,7 +254,7 @@ class testcase extends control
|
||||
if($this->app->tab == 'project')
|
||||
{
|
||||
$products = array('0' => $this->lang->product->all) + $this->product->getProducts($this->session->project, 'all', '', false);
|
||||
if(!$product->shadow) $this->lang->modulePageNav = $this->product->select($products, $productID, 'testcase', 'groupCase', "projectID=$projectID", $branch);
|
||||
if(!$product->shadow) $this->lang->modulePageNav = $this->product->select($products, $productID, 'testcase', 'groupCase', $projectID, $branch);
|
||||
}
|
||||
|
||||
$this->session->set('caseList', $this->app->getURI(true), $this->app->tab);
|
||||
@@ -325,7 +325,7 @@ class testcase extends control
|
||||
$products = $this->product->getProducts($this->session->project, 'all', '', false);
|
||||
$productID = $this->product->saveState($productID, $products);
|
||||
$product = $this->product->getByID($productID);
|
||||
if(!$product->shadow) $this->lang->modulePageNav = $this->product->select($products, $productID, 'testcase', 'zeroCase', "projectID=$projectID", $branchID);
|
||||
if(!$product->shadow) $this->lang->modulePageNav = $this->product->select($products, $productID, 'testcase', 'zeroCase', $projectID, $branchID);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -346,7 +346,7 @@ class testcaseModel extends model
|
||||
->where('t1.project')->eq((int)$executionID)
|
||||
->beginIF(!empty($productID))->andWhere('t1.product')->eq($productID)->fi()
|
||||
->beginIF(!empty($moduleID))->andWhere('t4.path')->like("%,$moduleID,%")->fi()
|
||||
->beginIF(!empty($productID))->andWhere('t2.branch')->eq($branchID)->fi()
|
||||
->beginIF(!empty($productID) and $branchID !== 'all')->andWhere('t2.branch')->eq($branchID)->fi()
|
||||
->andWhere('t2.deleted')->eq('0')
|
||||
->andWhere('t3.version > t2.storyVersion')
|
||||
->andWhere("t3.status")->eq('active')
|
||||
@@ -362,7 +362,7 @@ class testcaseModel extends model
|
||||
->beginIF($browseType != 'all' and $browseType != 'byModule')->andWhere('t2.status')->eq($browseType)->fi()
|
||||
->beginIF(!empty($productID))->andWhere('t1.product')->eq($productID)->fi()
|
||||
->beginIF(!empty($moduleID))->andWhere('t3.path')->like("%,$moduleID,%")->fi()
|
||||
->beginIF(!empty($productID))->andWhere('t2.branch')->eq($branchID)->fi()
|
||||
->beginIF(!empty($productID) and $branchID !== 'all')->andWhere('t2.branch')->eq($branchID)->fi()
|
||||
->andWhere('t2.deleted')->eq('0')
|
||||
->orderBy($orderBy)
|
||||
->page($pager)
|
||||
|
||||
@@ -1398,9 +1398,7 @@ class testtaskModel extends model
|
||||
$stepFiles = array();
|
||||
foreach($files as $file)
|
||||
{
|
||||
$pathName = $this->file->getRealPathName($file->pathname);
|
||||
$file->webPath = $this->file->webPath . $pathName;
|
||||
$file->realPath = $this->file->savePath . $pathName;
|
||||
$this->file->setFileWebAndRealPaths($file);
|
||||
if($file->objectType == 'caseResult')
|
||||
{
|
||||
$resultFiles[$file->objectID][$file->id] = $file;
|
||||
|
||||
@@ -507,7 +507,6 @@ class transferModel extends model
|
||||
$modelData = $this->getDatasByFile($tmpFile);
|
||||
}
|
||||
if(isset($fields['id'])) unset($fields['id']);
|
||||
$this->session->set($model . 'TemplateFields', array_keys($fields));
|
||||
return $modelData;
|
||||
}
|
||||
|
||||
@@ -812,7 +811,7 @@ class transferModel extends model
|
||||
if($modelDatas) $modelDatas = $this->updateChildDatas($modelDatas);
|
||||
|
||||
/* Deal linkStories datas. */
|
||||
if($modelDatas) $modelDatas = $this->updateLinkStories($modelDatas);
|
||||
if($modelDatas and isset($fieldList['linkStories'])) $modelDatas = $this->updateLinkStories($modelDatas);
|
||||
|
||||
return $modelDatas;
|
||||
}
|
||||
|
||||
@@ -169,6 +169,7 @@ class upgrade extends control
|
||||
/* Set default program for product and project with no program. */
|
||||
$this->upgrade->relateDefaultProgram($programID);
|
||||
|
||||
$_POST['projectType'] = 'execution';
|
||||
$this->upgrade->upgradeInProjectMode($programID, $systemMode);
|
||||
|
||||
$this->upgrade->computeObjectMembers();
|
||||
@@ -186,12 +187,12 @@ class upgrade extends control
|
||||
|
||||
$selectMode = false;
|
||||
}
|
||||
if(version_compare($openVersion, '15_0', '>=') and $systemMode == 'new')
|
||||
if(version_compare($openVersion, '15_0_rc1', '>=') and $systemMode == 'new')
|
||||
{
|
||||
$this->loadModel('setting')->setItem('system.common.global.mode', 'ALM');
|
||||
$selectMode = false;
|
||||
}
|
||||
if(version_compare($openVersion, '18_0', '>=')) $selectMode = false;
|
||||
if(version_compare($openVersion, '18_0_beta1', '>=')) $selectMode = false;
|
||||
|
||||
if($selectMode) $this->locate(inlink('to18Guide', "fromVersion=$fromVersion"));
|
||||
|
||||
@@ -240,16 +241,9 @@ class upgrade extends control
|
||||
/* Set default program for product and project with no program. */
|
||||
$this->upgrade->relateDefaultProgram($programID);
|
||||
|
||||
if(version_compare($openVersion, '15_0', '<')) $this->locate(inlink('selectMergeMode', "fromVersion=$fromVersion&mode=light"));
|
||||
|
||||
$this->locate(inlink('afterExec', "fromVersion=$fromVersion"));
|
||||
}
|
||||
if($mode == 'ALM')
|
||||
{
|
||||
if(version_compare($openVersion, '15_0', '<')) $this->locate(inlink('selectMergeMode', "fromVersion=$fromVersion&mode=ALM"));
|
||||
|
||||
$this->locate(inlink('afterExec', "fromVersion=$fromVersion"));
|
||||
}
|
||||
$this->locate(inlink('selectMergeMode', "fromVersion=$fromVersion&mode=$mode"));
|
||||
}
|
||||
|
||||
list($disabledFeatures, $enabledScrumFeatures, $disabledScrumFeatures) = $this->loadModel('custom')->computeFeatures();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#mainContent tr td {background-color: rgb(255, 255, 255); border-bottom: 1px solid rgb(238, 238, 238); border-right: 1px solid rgb(238, 238, 238);}
|
||||
|
||||
.btn-wide {padding: 6px 85px;}
|
||||
#useLight:hover, #useALM:hover{color: #fff; background-color: #2e7fff; border-color: transparent;}
|
||||
|
||||
#mainContent .datatable {cursor: default;}
|
||||
.container {padding-top: 20px;}
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ else
|
||||
<div class='panel-body'>
|
||||
<?php
|
||||
$checkFileName = $_SESSION['checkFileName'];
|
||||
$checkFileName = str_replace(dirname(dirname(dirname(__FILE__))) . DS, '', $checkFileName);
|
||||
$checkFileName = str_replace(dirname(dirname(__FILE__)) . DS, '', $checkFileName);
|
||||
printf($lang->misc->noticeRepair, $checkFileName);
|
||||
?>
|
||||
<p><a href='<?php echo $config->webRoot . 'checktable.php';?>' class='btn btn-sm'><i class='icon-refresh'></i> <?php echo $lang->refresh;?></a></p>
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ if(!isset($config->installed) or !$config->installed) die(header('location: inst
|
||||
|
||||
/* Check for need upgrade. */
|
||||
$config->installedVersion = $app->getInstalledVersion();
|
||||
if($config->version != $config->installedVersion) die(header('location: upgrade.php'));
|
||||
if($config->version != $config->installedVersion && file_exists('upgrade.php')) die(header('location: upgrade.php'));
|
||||
|
||||
/* Run the app. */
|
||||
$common = $app->loadCommon();
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 35 KiB |
Reference in New Issue
Block a user