Merge branch 'master' into zenops_46

This commit is contained in:
caoyanyi
2022-11-28 08:41:37 +08:00
73 changed files with 632 additions and 248 deletions
+4 -4
View File
@@ -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),
+3
View File
@@ -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. */
+1
View File
@@ -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;
}
+29
View File
@@ -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.
*
+45
View File
@@ -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;?>
+58
View File
@@ -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;?>
+1 -1
View File
@@ -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);
+2
View File
@@ -16,6 +16,8 @@ $(function()
saveCustomFields('batchCreateFields', 10, $titleCol, 150);
return false;
});
$('#dropMenu').css('z-index', 9999);
})
/**
+10 -2
View File
@@ -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)
{
+23 -2
View File
@@ -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'> &nbsp; " . $this->lang->build->last . ": <a class='code label label-badge label-light' id='lastBuildBtn'>" . $lastBuild->name . "</a></div>";
}
else
{
echo '';
}
}
/**
* Link stories.
*
+26 -3
View File
@@ -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);
});
}
+1 -1
View File
@@ -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';
+1 -1
View File
@@ -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';
+1 -1
View File
@@ -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
View File
@@ -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.
*
+2 -2
View File
@@ -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'> &nbsp; <?php echo $lang->build->last . ': <a class="code label label-badge label-light" id="lastBuildBtn">' . $lastBuild->name . '</a>';?></div>
<?php endif;?>
+1 -1
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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';
+9 -9
View File
@@ -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>
+2 -1
View File
@@ -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. */
+3 -7
View File
@@ -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;
+2 -6
View File
@@ -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);
+3 -11
View File
@@ -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)));
}
+1 -1
View File
@@ -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
View File
@@ -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();
+5 -4
View File
@@ -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'>
+3 -3
View File
@@ -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
View File
@@ -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;
}
}
+3 -6
View File
@@ -54,12 +54,9 @@
$uploadDate = $lang->file->uploadDate . substr($file->addedDate, 0, 10);
$fileTitle = "<i class='icon icon-file-text'></i> &nbsp;" . $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. */
+1 -1
View File
@@ -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;
+1
View File
@@ -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;}
+1 -1
View File
@@ -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}");
}
+4 -1
View File
@@ -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
{
+32 -5
View File
@@ -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 = '';
+1 -1
View File
@@ -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";
+1 -1
View File
@@ -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";
+1 -1
View File
@@ -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 = "所属项目集";
+8 -4
View File
@@ -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')
{
+3 -3
View File
@@ -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)
{
+7 -15
View File
@@ -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');
+1 -1
View File
@@ -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);
+2 -2
View File
@@ -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();
-18
View File
@@ -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.
*
+4 -3
View File
@@ -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)
{
+5 -4
View File
@@ -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)
{
+63 -1
View File
@@ -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();
}
}
);
}
+6 -1
View File
@@ -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>";
+1 -1
View File
@@ -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">
+2 -1
View File
@@ -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>
+6 -30
View File
@@ -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';?>
+1 -1
View File
@@ -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:?>
+13
View File
@@ -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;
}
+1 -1
View File
@@ -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 = '版本';
+2 -2
View File
@@ -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();
+2 -2
View File
@@ -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';
+2 -2
View File
@@ -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');
+3 -2
View File
@@ -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 . '&nbsp<span class="label label-success label-outline">' . $this->lang->task->statusList[$task->status] . '</span>&nbsp' . $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>';
}
}
+5
View File
@@ -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')
}
})
/**
+2 -2
View File
@@ -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
{
+2 -2
View File
@@ -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)
+1 -3
View File
@@ -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;
+1 -2
View 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;
}
+4 -10
View File
@@ -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();
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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