Merge branch 'master' of https://gitlab.zcorp.cc/easycorp/zentaopms into importExport

This commit is contained in:
tanghucheng
2022-08-03 14:11:48 +08:00
42 changed files with 876 additions and 427 deletions
+2
View File
@@ -1,3 +1,5 @@
ALTER TABLE `zt_story` ADD COLUMN `linkRequirements` varchar(255) NOT NULL AFTER `linkStories`;
ALTER TABLE `zt_acl` ENGINE='InnoDB';
ALTER TABLE `zt_action` ENGINE='InnoDB';
ALTER TABLE `zt_api_lib_release` ENGINE='InnoDB';
+1
View File
@@ -1421,6 +1421,7 @@ CREATE TABLE IF NOT EXISTS `zt_story` (
`toBug` mediumint(8) unsigned NOT NULL,
`childStories` varchar(255) NOT NULL,
`linkStories` varchar(255) NOT NULL,
`linkRequirements` varchar(255) NOT NULL,
`duplicateStory` mediumint(8) unsigned NOT NULL,
`version` smallint(6) NOT NULL default '1',
`feedbackBy` varchar(100) NOT NULL,
-10
View File
@@ -280,16 +280,6 @@ class basePager
if(strtolower($key) == 'recperpage') $this->params[$key] = $this->recPerPage;
if(strtolower($key) == 'pageid') $this->params[$key] = $this->pageID;
}
parse_str(strip_tags(urldecode($_SERVER['QUERY_STRING'])), $query);
if(!empty($query['m']) && !empty($query['f']) && $query['m'] == $this->moduleName && $query['f'] == $this->methodName)
{
unset($query['m']);
unset($query['f']);
unset($query['t']);
$this->params = array_merge($this->params, $query);
}
}
/**
+4 -4
View File
@@ -240,10 +240,10 @@ $lang->action->desc->linkrelatedcase = '$date, <strong>$actor</strong> hat ein
$lang->action->desc->unlinkrelatedcase = '$date, <strong>$actor</strong> hate eine Fallverknüpfung aufgelöst <strong>$extra</strong>.' . "\n";
/* Used to describe the history of operations link story and bug to productplan. */
$lang->action->desc->linkstory = '$date, 由 <strong>$actor</strong> 关联需求 <strong>$extra</strong> 到计划。' . "\n";
$lang->action->desc->linkbug = '$date, 由 <strong>$actor</strong> 关联BUG <strong>$extra</strong> 到计划。' . "\n";
$lang->action->desc->unlinkstory = '$date, 由 <strong>$actor</strong> 从计划移除需求 <strong>$extra</strong>。' . "\n";
$lang->action->desc->unlinkbug = '$date, 由 <strong>$actor</strong> 从计划移除BUG <strong>$extra</strong>。' . "\n";
$lang->action->desc->linkstory = '$date, <strong>$actor</strong> link stories <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->linkbug = '$date, <strong>$actor</strong> link bugs <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->unlinkstory = '$date, <strong>$actor</strong> remove stories <strong>$extra</strong> from plan.' . "\n";
$lang->action->desc->unlinkbug = '$date, <strong>$actor</strong> remove bugs <strong>$extra</strong> from plan.' . "\n";
/* Used to display dynamic information. */
$lang->action->label = new stdclass();
+4 -4
View File
@@ -240,10 +240,10 @@ $lang->action->desc->linkrelatedcase = '$date, <strong>$actor</strong> linked
$lang->action->desc->unlinkrelatedcase = '$date, <strong>$actor</strong> unlinked a case <strong>$extra</strong>.' . "\n";
/* Used to describe the history of operations link story and bug to productplan. */
$lang->action->desc->linkstory = '$date, 由 <strong>$actor</strong> 关联需求 <strong>$extra</strong> 到计划。' . "\n";
$lang->action->desc->linkbug = '$date, 由 <strong>$actor</strong> 关联BUG <strong>$extra</strong> 到计划。' . "\n";
$lang->action->desc->unlinkstory = '$date, 由 <strong>$actor</strong> 从计划移除需求 <strong>$extra</strong>。' . "\n";
$lang->action->desc->unlinkbug = '$date, 由 <strong>$actor</strong> 从计划移除BUG <strong>$extra</strong>。' . "\n";
$lang->action->desc->linkstory = '$date, <strong>$actor</strong> link stories <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->linkbug = '$date, <strong>$actor</strong> link bugs <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->unlinkstory = '$date, <strong>$actor</strong> remove stories <strong>$extra</strong> from plan.' . "\n";
$lang->action->desc->unlinkbug = '$date, <strong>$actor</strong> remove bugs <strong>$extra</strong> from plan.' . "\n";
/* Used to display dynamic information. */
$lang->action->label = new stdclass();
+4 -4
View File
@@ -240,10 +240,10 @@ $lang->action->desc->linkrelatedcase = '$date, <strong>$actor</strong> a fait
$lang->action->desc->unlinkrelatedcase = '$date, <strong>$actor</strong> a délié le CasTest <strong>$extra</strong>.' . "\n";
/* Used to describe the history of operations link story and bug to productplan. */
$lang->action->desc->linkstory = '$date, 由 <strong>$actor</strong> 关联需求 <strong>$extra</strong> 到计划。' . "\n";
$lang->action->desc->linkbug = '$date, 由 <strong>$actor</strong> 关联BUG <strong>$extra</strong> 到计划。' . "\n";
$lang->action->desc->unlinkstory = '$date, 由 <strong>$actor</strong> 从计划移除需求 <strong>$extra</strong>。' . "\n";
$lang->action->desc->unlinkbug = '$date, 由 <strong>$actor</strong> 从计划移除BUG <strong>$extra</strong>。' . "\n";
$lang->action->desc->linkstory = '$date, <strong>$actor</strong> link stories <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->linkbug = '$date, <strong>$actor</strong> link bugs <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->unlinkstory = '$date, <strong>$actor</strong> remove stories <strong>$extra</strong> from plan.' . "\n";
$lang->action->desc->unlinkbug = '$date, <strong>$actor</strong> remove bugs <strong>$extra</strong> from plan.' . "\n";
/* Used to display dynamic information. */
$lang->action->label = new stdclass();
+10 -5
View File
@@ -1649,7 +1649,7 @@ class docModel extends model
if(!$this->checkPrivDoc($doc)) unset($docs[$id]);
}
$bugIdList = $testReportIdList = $caseIdList = $storyIdList = $planIdList = $releaseIdList = $executionIdList = $taskIdList = $buildIdList = $issueIdList = $meetingIdList = $designIdList = 0;
$bugIdList = $testReportIdList = $caseIdList = $storyIdList = $planIdList = $releaseIdList = $executionIdList = $taskIdList = $buildIdList = $issueIdList = $meetingIdList = $designIdList = $reviewIdList = 0;
$userView = $this->app->user->view->products;
if($type == 'project') $userView = $this->app->user->view->projects;
@@ -1685,9 +1685,10 @@ class docModel extends model
{
$issueIdList = $this->dao->select('id')->from(TABLE_ISSUE)->where('project')->eq($objectID)->andWhere('deleted')->eq('0')->andWhere('project')->in($this->app->user->view->projects)->get();
$meetingIdList = $this->dao->select('id')->from(TABLE_MEETING)->where('project')->eq($objectID)->andWhere('deleted')->eq('0')->andWhere('project')->in($this->app->user->view->projects)->get();
$reviewIdList = $this->dao->select('id')->from(TABLE_REVIEW)->where('project')->eq($objectID)->andWhere('deleted')->eq('0')->andWhere('project')->in($this->app->user->view->projects)->get();
}
$designIdList = $this->dao->select('id')->from(TABLE_DESIGN)->where('project')->eq($objectID)->andWhere('deleted')->eq('0')->andWhere('project')->in($this->app->user->view->projects)->get();
$designIdList = $this->dao->select('id')->from(TABLE_DESIGN)->where('project')->eq($objectID)->andWhere('deleted')->eq('0')->andWhere('project')->in($this->app->user->view->projects)->get();
$executionIdList = $this->loadModel('execution')->getIdList($objectID);
$taskPairs = $this->dao->select('id')->from(TABLE_TASK)->where('execution')->in($executionIdList)->andWhere('deleted')->eq('0')->andWhere('execution')->in($this->app->user->view->sprints)->fetchPairs('id');
if(!empty($taskPairs)) $taskIdList = implode(',', $taskPairs);
@@ -1720,6 +1721,7 @@ class docModel extends model
->beginIF($type == 'project')
->orWhere("(objectType = 'execution' and objectID in ('$executionIdList'))")
->orWhere("(objectType = 'issue' and objectID in ($issueIdList))")
->orWhere("(objectType = 'review' and objectID in ($reviewIdList))")
->orWhere("(objectType = 'meeting' and objectID in ($meetingIdList))")
->orWhere("(objectType = 'design' and objectID in ($designIdList))")
->fi()
@@ -1761,11 +1763,14 @@ class docModel extends model
$sourceList[$file->objectType][$file->objectID] = $file->objectID;
}
$this->app->loadConfig('action');
foreach($sourceList as $type => $idList)
{
$table = $this->config->objectTables[$type];
$title = in_array($type, array('story', 'bug', 'issue', 'case', 'testcase', 'testreport', 'doc', 'requirement')) ? 'title' : 'name';
$name = $this->dao->select('id,' . $title)->from($table)->where('id')->in($idList)->fetchPairs('id');
$table = zget($this->config->objectTables, $type, '');
$field = zget($this->config->action->objectNameFields, $type, '');
if(empty($table) or empty($field)) continue;
$name = $this->dao->select('id,' . $field)->from($table)->where('id')->in($idList)->fetchPairs('id', $field);
$sourcePairs[$type] = $name;
}
+28 -6
View File
@@ -45,9 +45,20 @@
<?php echo str_replace('.' . $file->extension, '', $file->title);?>
</td>
<td class='c-name'>
<?php echo ($file->objectType == 'requirement' ? $lang->URCommon : $lang->{$file->objectType}->common) . ' : ';?>
<a title='<?php echo $sourcePairs[$file->objectType][$file->objectID];?>' href='<?php echo $this->createLink(($file->objectType == 'requirement' ? 'story' : $file->objectType), 'view', "objectID=$file->objectID", '', true);?>' class='iframe' data-width='90%'>
<?php echo $sourcePairs[$file->objectType][$file->objectID];?>
<?php
if($file->objectType == 'requirement')
{
$commonTitle = $lang->URCommon . ' : ';
}
else
{
if(!isset($lang->{$file->objectType}->common)) $app->loadLang($file->objectType);
$commonTitle = $lang->{$file->objectType}->common . ' : ';
}
echo $commonTitle;
?>
<a title='<?php if(isset($sourcePairs[$file->objectType][$file->objectID])) echo $sourcePairs[$file->objectType][$file->objectID];?>' href='<?php echo $this->createLink(($file->objectType == 'requirement' ? 'story' : $file->objectType), 'view', "objectID=$file->objectID", '', true);?>' class='iframe' data-width='90%'>
<?php if(isset($sourcePairs[$file->objectType][$file->objectID])) echo $sourcePairs[$file->objectType][$file->objectID];?>
</a>
</td>
<td><?php echo $file->extension;?></td>
@@ -101,9 +112,20 @@
</a>
<div class='file-name' title='<?php echo $file->title;?>'><?php echo $file->title;?></a></div>
<div class='file-name text-muted'>
<?php echo ($file->objectType == 'requirement' ? $lang->URCommon : $lang->{$file->objectType}->common) . ' : ';?>
<a href='<?php echo $this->createLink(($file->objectType == 'requirement' ? 'story' : $file->objectType), 'view', "objectID=$file->objectID", '', true);?>' title='<?php echo $sourcePairs[$file->objectType][$file->objectID];?>' class='iframe' data-width='90%'>
<?php echo $sourcePairs[$file->objectType][$file->objectID];?>
<?php
if($file->objectType == 'requirement')
{
$commonTitle = $lang->URCommon . ' : ';
}
else
{
if(!isset($lang->{$file->objectType}->common)) $app->loadLang($file->objectType);
$commonTitle = $lang->{$file->objectType}->common . ' : ';
}
echo $commonTitle;
?>
<a href='<?php echo $this->createLink(($file->objectType == 'requirement' ? 'story' : $file->objectType), 'view', "objectID=$file->objectID", '', true);?>' title='<?php if(isset($sourcePairs[$file->objectType][$file->objectID])) echo $sourcePairs[$file->objectType][$file->objectID];?>' class='iframe' data-width='90%'>
<?php if(isset($sourcePairs[$file->objectType][$file->objectID])) echo $sourcePairs[$file->objectType][$file->objectID];?>
</a>
</div>
</div>
+1
View File
@@ -412,6 +412,7 @@ $lang->execution->storyDragError = "The {$lang->SRCommon} is still
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
$lang->execution->week = 'week';
$lang->execution->checkedExecutions = 'Seleted %s items';
/* Statistics. */
$lang->execution->charts = new stdclass();
+1
View File
@@ -412,6 +412,7 @@ $lang->execution->storyDragError = "The {$lang->SRCommon} is still
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
$lang->execution->week = 'week';
$lang->execution->checkedExecutions = 'Seleted %s items';
/* Statistics. */
$lang->execution->charts = new stdclass();
+1
View File
@@ -412,6 +412,7 @@ $lang->execution->storyDragError = "The {$lang->SRCommon} is still
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
$lang->execution->week = 'week';
$lang->execution->checkedExecutions = "Pour s électionner l'élément%s";
/* Statistics. */
$lang->execution->charts = new stdclass();
+1
View File
@@ -412,6 +412,7 @@ $lang->execution->storyDragError = "该{$lang->SRCommon}还是草
$lang->execution->countTip = '(%s人)';
$lang->execution->pleaseInput = "请输入";
$lang->execution->week = '周';
$lang->execution->checkedExecutions = '已选择%s项';
/* 统计。*/
$lang->execution->charts = new stdclass();
+4 -3
View File
@@ -100,7 +100,7 @@ class executionModel extends model
include $this->app->getModulePath('', 'execution') . 'lang/' . $this->app->getClientLang() . '.php';
}
if($execution->acl != 'private') unset($this->lang->execution->menu->settings['subMenu']->whitelist);
if(isset($execution->cal) and $execution->acl != 'private') unset($this->lang->execution->menu->settings['subMenu']->whitelist);
if($execution and $execution->lifetime == 'ops')
{
@@ -670,6 +670,7 @@ class executionModel extends model
}
}
$this->lang->error->unique = $this->lang->error->repeat;
$extendFields = $this->getFlowExtendFields();
foreach($data->executionIDList as $executionID)
{
@@ -788,8 +789,8 @@ class executionModel extends model
->checkIF($execution->begin != '', 'begin', 'date')
->checkIF($execution->end != '', 'end', 'date')
->checkIF($execution->end != '', 'end', 'ge', $execution->begin)
->checkIF((!empty($execution->name) and $this->config->systemMode == 'new'), 'name', 'unique', "id != $executionID and type in ('sprint','stage') and `project` = $projectID")
->checkIF(!empty($execution->code), 'code', 'unique', "id != $executionID and type in ('sprint','stage')")
->checkIF((!empty($execution->name) and $this->config->systemMode == 'new'), 'name', 'unique', "id != $executionID and type in ('sprint','stage','kanban') and `project` = $projectID and `deleted` = '0'")
->checkIF(!empty($execution->code), 'code', 'unique', "id != $executionID and type in ('sprint','stage','kanban') and `deleted` = '0'")
->checkFlow()
->where('id')->eq($executionID)
->limit(1)
+6
View File
@@ -513,6 +513,9 @@ $lang->resource->story->batchChangeModule = 'batchChangeModule';
$lang->resource->story->batchToTask = 'batchToTask';
$lang->resource->story->track = 'trackAB';
$lang->resource->story->processStoryChange = 'processStoryChange';
$lang->resource->story->linkStories = 'linkStoriesAB';
if($config->URAndSR) $lang->resource->story->linkRequirements = 'linkRequirementsAB';
$lang->story->methodOrder[5] = 'create';
$lang->story->methodOrder[10] = 'batchCreate';
@@ -542,6 +545,9 @@ $lang->story->methodOrder[125] = 'batchChangeModule';
$lang->story->methodOrder[130] = 'batchToTask';
$lang->story->methodOrder[135] = 'track';
$lang->story->methodOrder[140] = 'processStoryChange';
$lang->story->methodOrder[145] = 'linkStories';
if($config->URAndSR) $lang->story->methodOrder[150] = 'linkRequirements';
/* Product plan. */
$lang->resource->productplan = new stdclass();
+7 -7
View File
@@ -216,13 +216,13 @@ $lang->kanban->error->childLimitNote = 'The sum of products in the child colu
$lang->kanban->error->importObjNotEmpty = 'Please select at least one import object.';
$lang->kanban->error->childLimitEmpty = 'Please set the WIP quantity of the sub column before operation.';
$lang->kanban->orderList['id_asc'] = 'Story ID Ascending';
$lang->kanban->orderList['id_desc'] = 'Story ID Descending';
$lang->kanban->orderList['pri_asc'] = 'Story Priority Ascending';
$lang->kanban->orderList['pri_desc'] = 'Story Priority Descending';
$lang->kanban->orderList['stage_asc'] = 'Story Stage Ascending';
$lang->kanban->orderList['stage_desc'] = 'Story Stage Descending';
$lang->kanban->orderList['assignedTo'] = 'Assigned To';
$lang->kanban->orderList['id_asc'] = 'Story ID Ascending';
$lang->kanban->orderList['id_desc'] = 'Story ID Descending';
$lang->kanban->orderList['pri_asc'] = 'Story Priority Ascending';
$lang->kanban->orderList['pri_desc'] = 'Story Priority Descending';
$lang->kanban->orderList['stage_asc'] = 'Story Stage Ascending';
$lang->kanban->orderList['stage_desc'] = 'Story Stage Descending';
$lang->kanban->orderList['assignedTo_desc'] = 'Assigned To';
$lang->kanban->importList = array();
$lang->kanban->importList['off'] = 'Import is not enabled';
+7 -7
View File
@@ -216,13 +216,13 @@ $lang->kanban->error->childLimitNote = 'The sum of products in the child colu
$lang->kanban->error->importObjNotEmpty = 'Please select at least one import object.';
$lang->kanban->error->childLimitEmpty = 'Please set the WIP quantity of the sub column before operation.';
$lang->kanban->orderList['id_asc'] = 'Story ID Ascending';
$lang->kanban->orderList['id_desc'] = 'Story ID Descending';
$lang->kanban->orderList['pri_asc'] = 'Story Priority Ascending';
$lang->kanban->orderList['pri_desc'] = 'Story Priority Descending';
$lang->kanban->orderList['stage_asc'] = 'Story Stage Ascending';
$lang->kanban->orderList['stage_desc'] = 'Story Stage Descending';
$lang->kanban->orderList['assignedTo'] = 'Assigned To';
$lang->kanban->orderList['id_asc'] = 'Story ID Ascending';
$lang->kanban->orderList['id_desc'] = 'Story ID Descending';
$lang->kanban->orderList['pri_asc'] = 'Story Priority Ascending';
$lang->kanban->orderList['pri_desc'] = 'Story Priority Descending';
$lang->kanban->orderList['stage_asc'] = 'Story Stage Ascending';
$lang->kanban->orderList['stage_desc'] = 'Story Stage Descending';
$lang->kanban->orderList['assignedTo_desc'] = 'Assigned To';
$lang->kanban->importList = array();
$lang->kanban->importList['off'] = 'Import is not enabled';
+7 -7
View File
@@ -216,13 +216,13 @@ $lang->kanban->error->childLimitNote = 'The sum of products in the child colu
$lang->kanban->error->importObjNotEmpty = 'Please select at least one import object.';
$lang->kanban->error->childLimitEmpty = 'Please set the WIP quantity of the sub column before operation.';
$lang->kanban->orderList['id_asc'] = 'Story ID Ascendante';
$lang->kanban->orderList['id_desc'] = 'Story ID Descendante';
$lang->kanban->orderList['pri_asc'] = 'Story Priorité Ascendante';
$lang->kanban->orderList['pri_desc'] = 'Story Priorité Descendante';
$lang->kanban->orderList['stage_asc'] = 'Story Phase Ascendante';
$lang->kanban->orderList['stage_desc'] = 'Story Phase Descendante';
$lang->kanban->orderList['assignedTo'] = 'Assigné à';
$lang->kanban->orderList['id_asc'] = 'Story ID Ascendante';
$lang->kanban->orderList['id_desc'] = 'Story ID Descendante';
$lang->kanban->orderList['pri_asc'] = 'Story Priorité Ascendante';
$lang->kanban->orderList['pri_desc'] = 'Story Priorité Descendante';
$lang->kanban->orderList['stage_asc'] = 'Story Phase Ascendante';
$lang->kanban->orderList['stage_desc'] = 'Story Phase Descendante';
$lang->kanban->orderList['assignedTo_desc'] = 'Assigné à';
$lang->kanban->importList = array();
$lang->kanban->importList['off'] = 'Import is not enabled';
+7 -7
View File
@@ -216,13 +216,13 @@ $lang->kanban->error->childLimitNote = '子列在制品数量之和不能大
$lang->kanban->error->importObjNotEmpty = '请至少选择一个导入对象';
$lang->kanban->error->childLimitEmpty = '请先设置子列的在制品数量后再操作';
$lang->kanban->orderList['id_asc'] = '需求ID正序';
$lang->kanban->orderList['id_desc'] = '需求ID倒序';
$lang->kanban->orderList['pri_asc'] = '需求优先级正序';
$lang->kanban->orderList['pri_desc'] = '需求优先级倒序';
$lang->kanban->orderList['stage_asc'] = '需求阶段正序';
$lang->kanban->orderList['stage_desc'] = '需求阶段倒序';
$lang->kanban->orderList['assignedTo'] = '指派给';
$lang->kanban->orderList['id_asc'] = '需求ID正序';
$lang->kanban->orderList['id_desc'] = '需求ID倒序';
$lang->kanban->orderList['pri_asc'] = '需求优先级正序';
$lang->kanban->orderList['pri_desc'] = '需求优先级倒序';
$lang->kanban->orderList['stage_asc'] = '需求阶段正序';
$lang->kanban->orderList['stage_desc'] = '需求阶段倒序';
$lang->kanban->orderList['assignedTo_desc'] = '指派给';
$lang->kanban->importList = array();
$lang->kanban->importList['off'] = '不启用导入功能';
+2 -2
View File
@@ -1263,7 +1263,7 @@ class product extends control
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Process product structure. */
if($this->config->systemMode == 'classic' and $orderBy == 'program_asc') $orderBy = 'order_asc';
if($this->config->systemMode == 'classic' and $orderBy == 'program_asc') $orderBy = 'line_desc,order_asc';
$productStats = $this->product->getStats($orderBy, $pager, $browseType, '', 'story', '', $queryID);
$productStructure = $this->product->statisticProgram($productStats);
$productLines = $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('deleted')->eq(0)->orderBy('`order` asc')->fetchAll();
@@ -1281,7 +1281,7 @@ class product extends control
$this->view->title = $this->lang->product->common;
$this->view->position[] = $this->lang->product->common;
$this->view->recTotal = count($productStats);
$this->view->recTotal = $pager->recTotal;
$this->view->productStats = $productStats;
$this->view->productStructure = $productStructure;
$this->view->productLines = $productLines;
+2 -1
View File
@@ -833,6 +833,7 @@ class productModel extends model
$unlinkProducts = array();
$linkProducts = array();
$this->lang->error->unique = $this->lang->error->repeat;
foreach($products as $productID => $product)
{
$oldProduct = $oldProducts[$productID];
@@ -842,7 +843,7 @@ class productModel extends model
->data($product)
->autoCheck()
->batchCheck($this->config->product->edit->requiredFields , 'notempty')
->checkIF((!empty($product->name) and $this->config->systemMode == 'new'), 'name', 'unique', "id != $productID and `program` = $programID")
->checkIF((!empty($product->name) and $this->config->systemMode == 'new'), 'name', 'unique', "id != $productID and `program` = $programID and `deleted` = '0'")
->checkFlow()
->where('id')->eq($productID)
->exec();
+1
View File
@@ -964,6 +964,7 @@ class project extends control
$this->loadModel('execution');
$this->loadModel('task');
$this->loadModel('programplan');
$this->session->set('executionList', $this->app->getURI(true), 'project');
if($this->cookie->showTask) $this->session->set('taskList', $this->app->getURI(true), 'project');
+1
View File
@@ -1,4 +1,5 @@
#executionList > thead > tr > th .table-nest-toggle-global {top: 6px}
#executionList > thead > tr > th .table-nest-toggle-global:before {color: #a6aab8;}
#executionsSummary {padding-left: 10px;}
#mainMenu .pull-left .checkbox-primary {margin-top: 5px;}
.main-table tbody>tr>td:first-child, .main-table thead>tr>th:first-child { padding-left: 8px; }
+126
View File
@@ -4,8 +4,90 @@ $(function()
{
var show = $(this).is(':checked') ? 1 : 0;
$.cookie('showTask', show, {expires:config.cookieLife, path:config.webRoot});
$('input#editExecution1').prop('disabled', show);
window.location.reload();
});
if($.cookie('showTask') == 1) $('input#editExecution1').prop('disabled', true);
$('input#editExecution1').click(function()
{
var editExecution = $(this).is(':checked') ? 1 : 0;
$.cookie('editExecution', editExecution, {expires:config.cookieLife, path:config.webRoot});
$('input[name^="showTask"]').prop('disabled', editExecution);
showEditCheckbox(editExecution);
});
if($.cookie('editExecution') == 1)
{
$('input#editExecution1').prop('checked', 'true');
showEditCheckbox(true);
$('input[name^="showTask"]').prop('disabled', true);
}
$(document).on('click', ":checkbox[name^='executionIDList']", function()
{
var notCheckedLength = $(":checkbox[name^='executionIDList']:not(:checked)").length;
var checkedLength = $(":checkbox[name^='executionIDList']:checked").length;
if(checkedLength > 0) $('#executionForm').addClass('has-row-checked');
if(notCheckedLength == 0) $('.table-footer #checkAll').prop('checked', true);
if(checkedLength == 0)
{
$('.table-footer #checkAll').prop('checked', false);
$('#executionForm').removeClass('has-row-checked');
}
var summary = checkedExecutions.replace('%s', checkedLength);
if(cilentLang == "en" && checkedLength < 2) summary = summary.replace('items', 'item');
var statistic = "<div id='executionsSummary' class='table-statistic'>" + summary + "</div>";
if(checkedLength > 0)
{
$('#executionSummary').addClass('hidden');
$('#executionsSummary').remove();
$('.editCheckbox').after(statistic);
}
else
{
$('#executionSummary').removeClass('hidden');
$('#executionsSummary').addClass('hidden');
}
});
$(document).on('click', ".table-footer #checkAll", function()
{
if($(this).prop('checked'))
{
$(":checkbox[name^='executionIDList']").prop('checked', true);
$('#executionForm').addClass('has-row-checked');
var checkedLength = $(":checkbox[name^='executionIDList']:checked").length;
var summary = checkedExecutions.replace('%s', checkedLength);
if(cilentLang == "en" && checkedLength < 2) summary = summary.replace('items', 'item');
var statistic = "<div id='executionsSummary' class='table-statistic'>" + summary + "</div>";
$('#executionSummary').addClass('hidden');
$('#executionsSummary').remove();
$('.editCheckbox').after(statistic);
$(this).next('label').addClass('hover');
}
else
{
$(":checkbox[name^='executionIDList']").prop('checked', false);
$('#executionForm').removeClass('has-row-checked');
$('#executionSummary').removeClass('hidden');
$('#executionsSummary').addClass('hidden');
$(this).next('label').removeClass('hover');
}
});
/* Solve the problem that clicking the browser back button causes the checkbox to be selected by default. */
setTimeout(function()
{
$(":checkbox[name^='executionIDList']").each(function()
{
$(this).prop('checked', false);
});
$('.table-footer #checkAll').prop('checked', false);
}, 10);
})
window.addEventListener('scroll', this.handleScroll)
@@ -81,3 +163,47 @@ function getWindowHeight()
{
return document.compatMode == "CSS1Compat" ? windowHeight = document.documentElement.clientHeight : windowHeight = document.body.clientHeight
}
/**
* Show edit executions checkbox.
*
* @param int $show
* @access public
* @return void
*/
function showEditCheckbox(show)
{
$('.project-type-label').each(function()
{
$this = $(this);
$tr = $(this).closest('tr');
executionID = $tr.attr('data-id');
if(show)
{
var marginLeft = $tr.find('td:first').find('span.table-nest-icon').css('margin-left');
$tr.find('td:first').prepend("<div class='checkbox-primary'><input type='checkbox' name='executionIDList[]' value='" + executionID + "' id='executionIDList" + executionID + "'/><label for='executionIDList" + executionID + "'></lable></div>");
$tr.find('td:first').find('.checkbox-primary').css('margin-left', marginLeft).css('width', '14');
$tr.find('td:first').find('span.table-nest-icon').css('margin-left', '0');
}
else
{
var marginLeft = $tr.find('td:first').find('.checkbox-primary').css('margin-left');
$tr.find('td:first').find('span.table-nest-icon').css('margin-left', marginLeft);
$tr.find('td:first').find('[name^="executionIDList"]').parent().remove();
}
});
if(show)
{
var tableFooter = "<div class='editCheckbox'><div class='checkbox-primary check-all'><input type='checkbox' id='checkAll' /><label>" + selectAll + "</label></div><div class='table-actions btn-toolbar'><button type='submit' class='btn'>" + edit + "</button></div></div>";
$('#executionForm').attr('action', createLink('execution', 'batchEdit'));
$('.table-footer').prepend(tableFooter).show();
$('body').scroll();
}
else
{
$('#executionForm').find('.editCheckbox').remove();
if($('#executionForm .pager').length == 0) $('.table-footer').hide();
$('#executionForm').removeAttr('action');
}
}
+3 -2
View File
@@ -1583,6 +1583,7 @@ class projectModel extends model
}
if(dao::isError()) return false;
$this->lang->error->unique = $this->lang->error->repeat;
foreach($projects as $projectID => $project)
{
$oldProject = $oldProjects[$projectID];
@@ -1594,8 +1595,8 @@ class projectModel extends model
->checkIF($project->begin != '', 'begin', 'date')
->checkIF($project->end != '', 'end', 'date')
->checkIF($project->end != '', 'end', 'gt', $project->begin)
->checkIF(!empty($project->name), 'name', 'unique', "id != $projectID and `type`='project' and `parent` = $parentID and `model` = '{$project->model}'")
->checkIF(!empty($project->code), 'code', 'unique', "id != $projectID and `type`='project' and `model` = '{$project->model}'")
->checkIF(!empty($project->name), 'name', 'unique', "id != $projectID and `type`='project' and `parent` = $parentID and `model` = '{$project->model}' and `deleted` = '0'")
->checkIF(!empty($project->code), 'code', 'unique', "id != $projectID and `type`='project' and `model` = '{$project->model}' and `deleted` = '0'")
->checkFlow()
->where('id')->eq($projectID)
->exec();
+6 -1
View File
@@ -1,5 +1,9 @@
<?php include '../../common/view/header.html.php';?>
<?php js::set('projectID', $projectID);?>
<?php js::set('edit', $lang->edit);?>
<?php js::set('selectAll', $lang->selectAll);?>
<?php js::set('checkedExecutions', $lang->execution->checkedExecutions);?>
<?php js::set('cilentLang', $this->app->getClientLang());?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<div class='btn-group'>
@@ -23,7 +27,8 @@
<?php if($status == $key) $label .= " <span class='label label-light label-badge'>{$pager->recTotal}</span>";?>
<?php echo html::a($this->createLink('project', 'execution', "status=$key&projectID=$projectID&orderBy=$orderBy&productID=$productID"), $label, '', "class='btn btn-link' id='{$key}Tab'");?>
<?php endforeach;?>
<?php echo html::checkbox('showTask', array('1' => $lang->programplan->stageCustom->task), '', $this->cookie->showTask ? 'checked=checked' : '');?>
<?php if(common::hasPriv('execution', 'batchEdit') and !empty($executionStats)) echo html::checkbox('editExecution', array('1' => $lang->edit . $lang->executionCommon), '', $this->cookie->editExecution ? 'checked=checked' : '');?>
<?php if(common::hasPriv('execution', 'task')) echo html::checkbox('showTask', array('1' => $lang->programplan->stageCustom->task), '', $this->cookie->showTask ? 'checked=checked' : '');?>
</div>
<div class='btn-toolbar pull-right'>
<?php common::printLink('execution', 'export', "status=$status&productID=$productID&orderBy=$orderBy&from=project", "<i class='icon-export muted'> </i> " . $lang->export, '', "class='btn btn-link export'")?>
+73 -9
View File
@@ -1223,15 +1223,17 @@ class story extends control
$this->story->replaceURLang($story->type);
$story->files = $this->loadModel('file')->getByObject($story->type, $storyID);
$product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id, type, status')->fetch();
$plan = $this->dao->findById($story->plan)->from(TABLE_PRODUCTPLAN)->fetch('title');
$bugs = $this->dao->select('id,title,status,pri,severity')->from(TABLE_BUG)->where('story')->eq($storyID)->andWhere('deleted')->eq(0)->fetchAll();
$fromBug = $this->dao->select('id,title')->from(TABLE_BUG)->where('toStory')->eq($storyID)->fetch();
$cases = $this->dao->select('id,title,status,pri')->from(TABLE_CASE)->where('story')->eq($storyID)->andWhere('deleted')->eq(0)->fetchAll();
$linkedMRs = $this->loadModel('mr')->getLinkedMRPairs($storyID, 'story');
$modulePath = $this->tree->getParents($story->module);
$storyModule = empty($story->module) ? '' : $this->tree->getById($story->module);
$story->files = $this->loadModel('file')->getByObject($story->type, $storyID);
$product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id, type, status')->fetch();
$plan = $this->dao->findById($story->plan)->from(TABLE_PRODUCTPLAN)->fetch('title');
$bugs = $this->dao->select('id,title,status,pri,severity')->from(TABLE_BUG)->where('story')->eq($storyID)->andWhere('deleted')->eq(0)->fetchAll();
$fromBug = $this->dao->select('id,title')->from(TABLE_BUG)->where('toStory')->eq($storyID)->fetch();
$cases = $this->dao->select('id,title,status,pri')->from(TABLE_CASE)->where('story')->eq($storyID)->andWhere('deleted')->eq(0)->fetchAll();
$linkedMRs = $this->loadModel('mr')->getLinkedMRPairs($storyID, 'story');
$modulePath = $this->tree->getParents($story->module);
$storyModule = empty($story->module) ? '' : $this->tree->getById($story->module);
$linkedStories = isset($story->linkStoryTitles) ? array_keys($story->linkStoryTitles) : array();
$storyProducts = $this->dao->select('id,product')->from(TABLE_STORY)->where('id')->in($linkedStories)->fetchPairs();
/* Set the menu. */
$from = $this->app->tab;
@@ -1284,6 +1286,7 @@ class story extends control
$this->view->actions = $this->action->getList('story', $storyID);
$this->view->storyModule = $storyModule;
$this->view->modulePath = $modulePath;
$this->view->storyProducts = $storyProducts;
$this->view->version = $version == 0 ? $story->version : $version;
$this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('story', $storyID);
$this->view->from = $from;
@@ -2173,6 +2176,67 @@ class story extends control
$this->display();
}
/**
* Link related stories.
*
* @param int $storyID
* @param string $browseType
* @param string $excludeStories
* @param int $param
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function linkStories($storyID, $browseType = '', $excludeStories = '', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Get story, product, products, and queryID. */
$story = $this->story->getById($storyID);
$products = $this->product->getPairs();
$queryID = ($browseType == 'bySearch') ? (int)$param : 0;
$type = $story->type == 'story' ? 'linkRelateSR' : 'linkRelateUR';
/* Build search form. */
$actionURL = $this->createLink('story', 'linkStories', "storyID=$storyID&browseType=bySearch&excludeStories=$excludeStories&queryID=myQueryID", '', true);
$this->product->buildSearchForm($story->product, $products, $queryID, $actionURL);
$this->view->story = $story;
$this->view->stories2Link = $this->story->getStories2Link($storyID, $type, $browseType, $queryID, $story->type, $pager, $excludeStories);
$this->view->products = $products;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->pager = $pager;
$this->display();
}
/**
* Link related requirements.
*
* @param int $storyID
* @param string $browseType
* @param string $excludeStories
* @param int $param
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function linkRequirements($storyID, $browseType = '', $excludeStories = '', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->lang->story->title = str_replace($this->lang->SRCommon, $this->lang->URCommon, $this->lang->story->title);
$this->config->product->search['fields']['title'] = $this->lang->story->title;
unset($this->config->product->search['fields']['plan']);
unset($this->config->product->search['fields']['stage']);
echo $this->fetch('story', 'linkStories', "storyID=$storyID&browseType=$browseType&excludeStories=$excludeStories&param=$param&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID");
}
/**
* Process story change.
*
+1
View File
@@ -1 +1,2 @@
#product_chosen .chosen-single{border-right-width:1px}
.linkStoryTitle {white-space: nowrap; text-overflow: ellipsis;}
+1 -1
View File
@@ -1,2 +1,2 @@
.thWidth {width: 80px !important;}
.thWidth {width: 95px !important;}
.linkThWidth {width: 70px !important;}
+6
View File
@@ -0,0 +1,6 @@
.main-table {height: 80% !important}
#mainContent {min-height: 400px;}
.c-id, .c-status, .c-user {width: 80px;}
.c-pri {width: 60px;}
.c-product {width: 150px;}
.c-title {width: auto;}
+22
View File
@@ -32,4 +32,26 @@ $(function()
$('.feedbackBox').addClass('hidden');
}
});
$('#linkStoriesLink').click(function()
{
var storyIdList = '';
$('#linkStoriesBox input').each(function()
{
storyIdList += $(this).val() + ',';
});
var link = '';
if(storyType == 'story')
{
link = createLink('story', 'linkStories', 'storyID=' + storyID + '&browseType=&excludeStories=' + storyIdList, '', true);
}
else
{
link = createLink('story', 'linkRequirements', 'storyID=' + storyID + '&browseType=&excludeStories=' + storyIdList, '', true);
}
var modalTrigger = new $.zui.ModalTrigger({type: 'iframe', width: '95%', url: link});
modalTrigger.show();
});
})
+84 -78
View File
@@ -52,6 +52,8 @@ $lang->story->bugCountAB = 'B';
$lang->story->caseCountAB = 'C';
$lang->story->linkStory = 'Verküpfen';
$lang->story->unlinkStory = 'Verknüpfung aufheben';
$lang->story->linkStoriesAB = "Link {$lang->SRCommon}";
$lang->story->linkRequirementsAB = "Link {$lang->URCommon}";
$lang->story->export = "Daten exportieren";
$lang->story->zeroCase = "Storys ohne Fälle";
$lang->story->zeroTask = "Storys ohne Aufgaben anzeigen";
@@ -86,84 +88,88 @@ $lang->story->batchToTaskTips = "This action will create a task with the same na
$lang->story->successToTask = "Converted to task.";
$lang->story->storyRound = '%s time estimation';
$lang->story->id = 'ID';
$lang->story->parent = 'Parent';
$lang->story->product = $lang->productCommon;
$lang->story->project = 'Project';
$lang->story->branch = "Branch/Platform";
$lang->story->module = 'Module';
$lang->story->moduleAB = 'Module';
$lang->story->source = 'Von';
$lang->story->sourceNote = 'Hinweis';
$lang->story->fromBug = 'Von Bug';
$lang->story->title = 'Titel';
$lang->story->type = "Story/Requirement";
$lang->story->category = 'Category';
$lang->story->color = 'Color';
$lang->story->toBug = 'ToBug';
$lang->story->spec = 'Beschreibung';
$lang->story->assign = 'Assign';
$lang->story->verify = 'Akzeptanz';
$lang->story->pri = 'Priorität';
$lang->story->estimate = 'Schätzung(h)';
$lang->story->estimateAB = 'Schätzung(h)';
$lang->story->hour = 'Stunde';
$lang->story->status = 'Status';
$lang->story->subStatus = 'Sub Status';
$lang->story->stage = 'Phase';
$lang->story->stageAB = 'Phase';
$lang->story->stagedBy = 'SetBy';
$lang->story->mailto = 'Mail an';
$lang->story->openedBy = 'Ersteller';
$lang->story->openedDate = 'Erstellt am';
$lang->story->assignedTo = 'Zuständiger';
$lang->story->assignedDate = 'Zugewisen am';
$lang->story->lastEditedBy = 'Letzte Bearbeitung';
$lang->story->lastEditedDate = 'Bearbeitet am';
$lang->story->closedBy = 'Geschlossen von';
$lang->story->closedDate = 'Geschlossen am';
$lang->story->closedReason = 'Geschlossen weil';
$lang->story->rejectedReason = 'Abgelehnt weil';
$lang->story->reviewedBy = 'Prüfer';
$lang->story->reviewer = $lang->story->reviewedBy;
$lang->story->reviewers = 'Reviewers';
$lang->story->reviewedDate = 'Geprüft am';
$lang->story->activatedDate = 'Activated Date';
$lang->story->version = 'Version';
$lang->story->feedbackBy = 'From Name';
$lang->story->notifyEmail = 'From Email';
$lang->story->plan = 'Plan';
$lang->story->planAB = 'Plan';
$lang->story->comment = 'Kommentar';
$lang->story->children = "Child {$lang->SRCommon}";
$lang->story->childrenAB = "C";
$lang->story->linkStories = 'Story verknüpfen';
$lang->story->childStories = 'Story aufteilen';
$lang->story->duplicateStory = 'Story ID kopieren';
$lang->story->reviewResult = 'Ergbnis prüfen';
$lang->story->preVersion = 'Frühere Version';
$lang->story->keywords = 'Tags';
$lang->story->newStory = 'Weitere Story';
$lang->story->colorTag = 'Farb-Tag';
$lang->story->files = 'Dateien';
$lang->story->copy = "Story kopieren";
$lang->story->total = "Total Storys";
$lang->story->draft = 'Entwurf';
$lang->story->unclosed = 'Nicht geschlossen';
$lang->story->deleted = 'Gelöscht';
$lang->story->released = 'Released Linked Stories';
$lang->story->URChanged = 'Requirement Changed';
$lang->story->design = 'Designs';
$lang->story->case = 'Cases';
$lang->story->bug = 'Bugs';
$lang->story->repoCommit = 'Commits';
$lang->story->noRequirement = 'No Requirements';
$lang->story->one = 'One';
$lang->story->field = 'Synchronized fields';
$lang->story->completeRate = 'Completion Rate';
$lang->story->reviewed = 'Reviewed';
$lang->story->toBeReviewed = 'To Be Reviewed';
$lang->story->linkMR = 'Related MRs';
$lang->story->id = 'ID';
$lang->story->parent = 'Parent';
$lang->story->product = $lang->productCommon;
$lang->story->project = 'Project';
$lang->story->branch = "Branch/Platform";
$lang->story->module = 'Module';
$lang->story->moduleAB = 'Module';
$lang->story->source = 'Von';
$lang->story->sourceNote = 'Hinweis';
$lang->story->fromBug = 'Von Bug';
$lang->story->title = 'Titel';
$lang->story->type = "Story/Requirement";
$lang->story->category = 'Category';
$lang->story->color = 'Color';
$lang->story->toBug = 'ToBug';
$lang->story->spec = 'Beschreibung';
$lang->story->assign = 'Assign';
$lang->story->verify = 'Akzeptanz';
$lang->story->pri = 'Priorität';
$lang->story->estimate = 'Schätzung(h)';
$lang->story->estimateAB = 'Schätzung(h)';
$lang->story->hour = 'Stunde';
$lang->story->status = 'Status';
$lang->story->statusAB = 'Status';
$lang->story->subStatus = 'Sub Status';
$lang->story->stage = 'Phase';
$lang->story->stageAB = 'Phase';
$lang->story->stagedBy = 'SetBy';
$lang->story->mailto = 'Mail an';
$lang->story->openedBy = 'Ersteller';
$lang->story->openedByAB = 'Created';
$lang->story->openedDate = 'Erstellt am';
$lang->story->assignedTo = 'Zuständiger';
$lang->story->assignedToAB = 'Assign';
$lang->story->assignedDate = 'Zugewisen am';
$lang->story->lastEditedBy = 'Letzte Bearbeitung';
$lang->story->lastEditedDate = 'Bearbeitet am';
$lang->story->closedBy = 'Geschlossen von';
$lang->story->closedDate = 'Geschlossen am';
$lang->story->closedReason = 'Geschlossen weil';
$lang->story->rejectedReason = 'Abgelehnt weil';
$lang->story->reviewedBy = 'Prüfer';
$lang->story->reviewer = $lang->story->reviewedBy;
$lang->story->reviewers = 'Reviewers';
$lang->story->reviewedDate = 'Geprüft am';
$lang->story->activatedDate = 'Activated Date';
$lang->story->version = 'Version';
$lang->story->feedbackBy = 'From Name';
$lang->story->notifyEmail = 'From Email';
$lang->story->plan = 'Plan';
$lang->story->planAB = 'Plan';
$lang->story->comment = 'Kommentar';
$lang->story->children = "Child {$lang->SRCommon}";
$lang->story->childrenAB = "C";
$lang->story->linkStories = 'Story verknüpfen';
$lang->story->linkRequirements = "Linked {$lang->URCommon}";
$lang->story->childStories = 'Story aufteilen';
$lang->story->duplicateStory = 'Story ID kopieren';
$lang->story->reviewResult = 'Ergbnis prüfen';
$lang->story->preVersion = 'Frühere Version';
$lang->story->keywords = 'Tags';
$lang->story->newStory = 'Weitere Story';
$lang->story->colorTag = 'Farb-Tag';
$lang->story->files = 'Dateien';
$lang->story->copy = "Story kopieren";
$lang->story->total = "Total Storys";
$lang->story->draft = 'Entwurf';
$lang->story->unclosed = 'Nicht geschlossen';
$lang->story->deleted = 'Gelöscht';
$lang->story->released = 'Released Linked Stories';
$lang->story->URChanged = 'Requirement Changed';
$lang->story->design = 'Designs';
$lang->story->case = 'Cases';
$lang->story->bug = 'Bugs';
$lang->story->repoCommit = 'Commits';
$lang->story->noRequirement = 'No Requirements';
$lang->story->one = 'One';
$lang->story->field = 'Synchronized fields';
$lang->story->completeRate = 'Completion Rate';
$lang->story->reviewed = 'Reviewed';
$lang->story->toBeReviewed = 'To Be Reviewed';
$lang->story->linkMR = 'Related MRs';
$lang->story->ditto = 'Dito';
$lang->story->dittoNotice = 'Die Story gehört nicht zum Projekt wie die vorherige!';
+84 -78
View File
@@ -52,6 +52,8 @@ $lang->story->bugCountAB = 'B';
$lang->story->caseCountAB = 'C';
$lang->story->linkStory = 'Link Story';
$lang->story->unlinkStory = 'UnLinked';
$lang->story->linkStoriesAB = "Link {$lang->SRCommon}";
$lang->story->linkRequirementsAB = "Link {$lang->URCommon}";
$lang->story->export = "Export Data";
$lang->story->zeroCase = "Stories without cases";
$lang->story->zeroTask = "Only list stories without tasks";
@@ -86,84 +88,88 @@ $lang->story->batchToTaskTips = "This action will create a task with the same na
$lang->story->successToTask = "Converted to task.";
$lang->story->storyRound = '%s time estimation';
$lang->story->id = 'ID';
$lang->story->parent = 'Parent';
$lang->story->product = $lang->productCommon;
$lang->story->project = 'Project';
$lang->story->branch = "Branch/Platform";
$lang->story->module = 'Module';
$lang->story->moduleAB = 'Module';
$lang->story->source = 'From';
$lang->story->sourceNote = 'Note';
$lang->story->fromBug = 'From Bug';
$lang->story->title = 'Title';
$lang->story->type = "Story/Requirement";
$lang->story->category = 'Category';
$lang->story->color = 'Color';
$lang->story->toBug = 'ToBug';
$lang->story->spec = 'Description';
$lang->story->assign = 'Assign';
$lang->story->verify = 'Acceptance';
$lang->story->pri = 'Priority';
$lang->story->estimate = "Estimates";
$lang->story->estimateAB = 'Est.';
$lang->story->hour = $lang->hourCommon;
$lang->story->status = 'Status';
$lang->story->subStatus = 'Sub Status';
$lang->story->stage = 'Phase';
$lang->story->stageAB = 'Phase';
$lang->story->stagedBy = 'SetBy';
$lang->story->mailto = 'Mailto';
$lang->story->openedBy = 'Created By';
$lang->story->openedDate = 'Created Date';
$lang->story->assignedTo = 'AssignTo';
$lang->story->assignedDate = 'AssignedDate';
$lang->story->lastEditedBy = 'EditedBy';
$lang->story->lastEditedDate = 'EditedDate';
$lang->story->closedBy = 'ClosedBy';
$lang->story->closedDate = 'ClosedDate';
$lang->story->closedReason = 'Reason';
$lang->story->rejectedReason = 'Reject Reason';
$lang->story->reviewedBy = 'ReviewedBy';
$lang->story->reviewer = $lang->story->reviewedBy;
$lang->story->reviewers = 'Reviewers';
$lang->story->reviewedDate = 'ReviewedDate';
$lang->story->activatedDate = 'Activated Date';
$lang->story->version = 'Version';
$lang->story->feedbackBy = 'From Name';
$lang->story->notifyEmail = 'From Email';
$lang->story->plan = 'Linked Plan';
$lang->story->planAB = 'Plan';
$lang->story->comment = 'Comment';
$lang->story->children = "Child {$lang->SRCommon}";
$lang->story->childrenAB = "C";
$lang->story->linkStories = 'Linked Story';
$lang->story->childStories = 'Decomposed Story';
$lang->story->duplicateStory = 'Duplicated Story ID';
$lang->story->reviewResult = 'Review Result';
$lang->story->preVersion = 'Last Version';
$lang->story->keywords = 'Tags';
$lang->story->newStory = 'Continue adding';
$lang->story->colorTag = 'Color';
$lang->story->files = 'Files';
$lang->story->copy = "Copy Story";
$lang->story->total = "Total Stories";
$lang->story->draft = 'Draft';
$lang->story->unclosed = 'Unclosed';
$lang->story->deleted = 'Deleted';
$lang->story->released = 'Released Stories';
$lang->story->URChanged = 'Requirement Changed';
$lang->story->design = 'Design';
$lang->story->case = 'Cases';
$lang->story->bug = 'Bugs';
$lang->story->repoCommit = 'Commits';
$lang->story->noRequirement = 'No Requirements';
$lang->story->one = 'One';
$lang->story->field = 'Sync Field';
$lang->story->completeRate = 'Completion Rate';
$lang->story->reviewed = 'Reviewed';
$lang->story->toBeReviewed = 'To Be Reviewed';
$lang->story->linkMR = 'Related MRs';
$lang->story->id = 'ID';
$lang->story->parent = 'Parent';
$lang->story->product = $lang->productCommon;
$lang->story->project = 'Project';
$lang->story->branch = "Branch/Platform";
$lang->story->module = 'Module';
$lang->story->moduleAB = 'Module';
$lang->story->source = 'From';
$lang->story->sourceNote = 'Note';
$lang->story->fromBug = 'From Bug';
$lang->story->title = 'Title';
$lang->story->type = "Story/Requirement";
$lang->story->category = 'Category';
$lang->story->color = 'Color';
$lang->story->toBug = 'ToBug';
$lang->story->spec = 'Description';
$lang->story->assign = 'Assign';
$lang->story->verify = 'Acceptance';
$lang->story->pri = 'Priority';
$lang->story->estimate = "Estimates";
$lang->story->estimateAB = 'Est.';
$lang->story->hour = $lang->hourCommon;
$lang->story->status = 'Status';
$lang->story->statusAB = 'Status';
$lang->story->subStatus = 'Sub Status';
$lang->story->stage = 'Phase';
$lang->story->stageAB = 'Phase';
$lang->story->stagedBy = 'SetBy';
$lang->story->mailto = 'Mailto';
$lang->story->openedBy = 'Created By';
$lang->story->openedByAB = 'Created';
$lang->story->openedDate = 'Created Date';
$lang->story->assignedTo = 'AssignTo';
$lang->story->assignedToAB = 'Assign';
$lang->story->assignedDate = 'AssignedDate';
$lang->story->lastEditedBy = 'EditedBy';
$lang->story->lastEditedDate = 'EditedDate';
$lang->story->closedBy = 'ClosedBy';
$lang->story->closedDate = 'ClosedDate';
$lang->story->closedReason = 'Reason';
$lang->story->rejectedReason = 'Reject Reason';
$lang->story->reviewedBy = 'ReviewedBy';
$lang->story->reviewer = $lang->story->reviewedBy;
$lang->story->reviewers = 'Reviewers';
$lang->story->reviewedDate = 'ReviewedDate';
$lang->story->activatedDate = 'Activated Date';
$lang->story->version = 'Version';
$lang->story->feedbackBy = 'From Name';
$lang->story->notifyEmail = 'From Email';
$lang->story->plan = 'Linked Plan';
$lang->story->planAB = 'Plan';
$lang->story->comment = 'Comment';
$lang->story->children = "Child {$lang->SRCommon}";
$lang->story->childrenAB = "C";
$lang->story->linkStories = 'Linked Story';
$lang->story->linkRequirements = "Linked {$lang->URCommon}";
$lang->story->childStories = 'Decomposed Story';
$lang->story->duplicateStory = 'Duplicated Story ID';
$lang->story->reviewResult = 'Review Result';
$lang->story->preVersion = 'Last Version';
$lang->story->keywords = 'Tags';
$lang->story->newStory = 'Continue adding';
$lang->story->colorTag = 'Color';
$lang->story->files = 'Files';
$lang->story->copy = "Copy Story";
$lang->story->total = "Total Stories";
$lang->story->draft = 'Draft';
$lang->story->unclosed = 'Unclosed';
$lang->story->deleted = 'Deleted';
$lang->story->released = 'Released Stories';
$lang->story->URChanged = 'Requirement Changed';
$lang->story->design = 'Design';
$lang->story->case = 'Cases';
$lang->story->bug = 'Bugs';
$lang->story->repoCommit = 'Commits';
$lang->story->noRequirement = 'No Requirements';
$lang->story->one = 'One';
$lang->story->field = 'Sync Field';
$lang->story->completeRate = 'Completion Rate';
$lang->story->reviewed = 'Reviewed';
$lang->story->toBeReviewed = 'To Be Reviewed';
$lang->story->linkMR = 'Related MRs';
$lang->story->ditto = 'Ditto';
$lang->story->dittoNotice = 'This story is not linked to the same product as the last one is!';
+84 -78
View File
@@ -52,6 +52,8 @@ $lang->story->bugCountAB = 'B';
$lang->story->caseCountAB = 'C';
$lang->story->linkStory = 'Lier Story';
$lang->story->unlinkStory = 'Dissocier';
$lang->story->linkStoriesAB = "Lier {$lang->SRCommon}";
$lang->story->linkRequirementsAB = "Lier {$lang->URCommon}";
$lang->story->export = "Exporter Données";
$lang->story->zeroCase = "Stories sans CasTests";
$lang->story->zeroTask = "Seulement liste des stories sans tâches";
@@ -86,84 +88,88 @@ $lang->story->batchToTaskTips = "This action will create a task with the same na
$lang->story->successToTask = "Converted to task.";
$lang->story->storyRound = '%s time estimation';
$lang->story->id = 'ID';
$lang->story->parent = 'Parent';
$lang->story->product = $lang->productCommon;
$lang->story->project = 'Project';
$lang->story->branch = "Branche/Plateforme";
$lang->story->module = 'Module';
$lang->story->moduleAB = 'Module';
$lang->story->source = 'De';
$lang->story->sourceNote = 'Note';
$lang->story->fromBug = 'Depuis Bug';
$lang->story->title = 'Titre';
$lang->story->type = "Story/Requirement";
$lang->story->category = 'Category';
$lang->story->color = 'Couleur';
$lang->story->toBug = 'Vers Bug';
$lang->story->spec = 'Description';
$lang->story->assign = 'Affecter';
$lang->story->verify = 'Acceptance';
$lang->story->pri = 'Priorité';
$lang->story->estimate = 'Estimation';
$lang->story->estimateAB = 'Esti.(h)';
$lang->story->hour = 'Heures';
$lang->story->status = 'Statut';
$lang->story->subStatus = 'Sous-statut';
$lang->story->stage = 'Phase';
$lang->story->stageAB = 'Phase';
$lang->story->stagedBy = 'Fixé par';
$lang->story->mailto = 'Mailto';
$lang->story->openedBy = 'Créée par';
$lang->story->openedDate = 'Date Création';
$lang->story->assignedTo = 'Assignée à';
$lang->story->assignedDate = 'Date Assignation';
$lang->story->lastEditedBy = 'Editée par';
$lang->story->lastEditedDate = 'Date Edition';
$lang->story->closedBy = 'Fermée par';
$lang->story->closedDate = 'Date Fermeture';
$lang->story->closedReason = 'Raison';
$lang->story->rejectedReason = 'Raison du Rejet';
$lang->story->reviewedBy = 'Validée par';
$lang->story->reviewer = $lang->story->reviewedBy;
$lang->story->reviewers = 'Reviewers';
$lang->story->reviewedDate = 'Date Validation';
$lang->story->activatedDate = 'Activated Date';
$lang->story->version = 'Version';
$lang->story->feedbackBy = 'From Name';
$lang->story->notifyEmail = 'From Email';
$lang->story->plan = 'Intégrée Plans';
$lang->story->planAB = 'Plan';
$lang->story->comment = 'Commentaire';
$lang->story->children = "Enfant {$lang->SRCommon}";
$lang->story->childrenAB = "C";
$lang->story->linkStories = 'Stories Liées';
$lang->story->childStories = 'Stories Décomposées';
$lang->story->duplicateStory = 'Story ID Dupliquées';
$lang->story->reviewResult = 'Résultat Validation';
$lang->story->preVersion = 'Dernière Version';
$lang->story->keywords = 'Tags';
$lang->story->newStory = "Continuer d'ajouter";
$lang->story->colorTag = 'Couleur';
$lang->story->files = 'Fichiers';
$lang->story->copy = "Copier Story";
$lang->story->total = "Stories Total";
$lang->story->draft = 'Brouillon';
$lang->story->unclosed = 'Non Fermées';
$lang->story->deleted = 'Supprimée';
$lang->story->released = 'Stories Versionnées';
$lang->story->URChanged = 'Requirement Changed';
$lang->story->design = 'Designs';
$lang->story->case = 'Cases';
$lang->story->bug = 'Bugs';
$lang->story->repoCommit = 'Commits';
$lang->story->noRequirement = 'No Requirements';
$lang->story->one = 'One';
$lang->story->field = 'Synchronized fields';
$lang->story->completeRate = 'Completion Rate';
$lang->story->reviewed = 'Reviewed';
$lang->story->toBeReviewed = 'To Be Reviewed';
$lang->story->linkMR = 'Related MRs';
$lang->story->id = 'ID';
$lang->story->parent = 'Parent';
$lang->story->product = $lang->productCommon;
$lang->story->project = 'Project';
$lang->story->branch = "Branche/Plateforme";
$lang->story->module = 'Module';
$lang->story->moduleAB = 'Module';
$lang->story->source = 'De';
$lang->story->sourceNote = 'Note';
$lang->story->fromBug = 'Depuis Bug';
$lang->story->title = 'Titre';
$lang->story->type = "Story/Requirement";
$lang->story->category = 'Category';
$lang->story->color = 'Couleur';
$lang->story->toBug = 'Vers Bug';
$lang->story->spec = 'Description';
$lang->story->assign = 'Affecter';
$lang->story->verify = 'Acceptance';
$lang->story->pri = 'Priorité';
$lang->story->estimate = 'Estimation';
$lang->story->estimateAB = 'Esti.(h)';
$lang->story->hour = 'Heures';
$lang->story->status = 'Statut';
$lang->story->statusAB = 'Statut';
$lang->story->subStatus = 'Sous-statut';
$lang->story->stage = 'Phase';
$lang->story->stageAB = 'Phase';
$lang->story->stagedBy = 'Fixé par';
$lang->story->mailto = 'Mailto';
$lang->story->openedBy = 'Créée par';
$lang->story->openedByAB = 'Créer';
$lang->story->openedDate = 'Date Création';
$lang->story->assignedTo = 'Assignée à';
$lang->story->assignedToAB = 'Attribuer';
$lang->story->assignedDate = 'Date Assignation';
$lang->story->lastEditedBy = 'Editée par';
$lang->story->lastEditedDate = 'Date Edition';
$lang->story->closedBy = 'Fermée par';
$lang->story->closedDate = 'Date Fermeture';
$lang->story->closedReason = 'Raison';
$lang->story->rejectedReason = 'Raison du Rejet';
$lang->story->reviewedBy = 'Validée par';
$lang->story->reviewer = $lang->story->reviewedBy;
$lang->story->reviewers = 'Reviewers';
$lang->story->reviewedDate = 'Date Validation';
$lang->story->activatedDate = 'Activated Date';
$lang->story->version = 'Version';
$lang->story->feedbackBy = 'From Name';
$lang->story->notifyEmail = 'From Email';
$lang->story->plan = 'Intégrée Plans';
$lang->story->planAB = 'Plan';
$lang->story->comment = 'Commentaire';
$lang->story->children = "Enfant {$lang->SRCommon}";
$lang->story->childrenAB = "C";
$lang->story->linkStories = 'Stories Liées';
$lang->story->linkRequirements = "{$lang->URCommon} Lié es";
$lang->story->childStories = 'Stories Décomposées';
$lang->story->duplicateStory = 'Story ID Dupliquées';
$lang->story->reviewResult = 'Résultat Validation';
$lang->story->preVersion = 'Dernière Version';
$lang->story->keywords = 'Tags';
$lang->story->newStory = "Continuer d'ajouter";
$lang->story->colorTag = 'Couleur';
$lang->story->files = 'Fichiers';
$lang->story->copy = "Copier Story";
$lang->story->total = "Stories Total";
$lang->story->draft = 'Brouillon';
$lang->story->unclosed = 'Non Fermées';
$lang->story->deleted = 'Supprimée';
$lang->story->released = 'Stories Versionnées';
$lang->story->URChanged = 'Requirement Changed';
$lang->story->design = 'Designs';
$lang->story->case = 'Cases';
$lang->story->bug = 'Bugs';
$lang->story->repoCommit = 'Commits';
$lang->story->noRequirement = 'No Requirements';
$lang->story->one = 'One';
$lang->story->field = 'Synchronized fields';
$lang->story->completeRate = 'Completion Rate';
$lang->story->reviewed = 'Reviewed';
$lang->story->toBeReviewed = 'To Be Reviewed';
$lang->story->linkMR = 'Related MRs';
$lang->story->ditto = 'Idem';
$lang->story->dittoNotice = "La story n'est pas associée au même product que la précédente !";
+84 -78
View File
@@ -52,6 +52,8 @@ $lang->story->bugCountAB = 'B';
$lang->story->caseCountAB = 'C';
$lang->story->linkStory = "关联{$lang->SRCommon}";
$lang->story->unlinkStory = "移除相关{$lang->SRCommon}";
$lang->story->linkStoriesAB = "关联相关{$lang->SRCommon}";
$lang->story->linkRequirementsAB = "关联相关{$lang->URCommon}";
$lang->story->export = "导出数据";
$lang->story->zeroCase = "零用例{$lang->SRCommon}";
$lang->story->zeroTask = "只列零任务{$lang->SRCommon}";
@@ -86,84 +88,88 @@ $lang->story->batchToTaskTips = "此操作会创建与所选{$lang->SRCommon}同
$lang->story->successToTask = '批量转任务成功';
$lang->story->storyRound = '第 %s 轮估算';
$lang->story->id = '编号';
$lang->story->parent = '父需求';
$lang->story->product = "所属{$lang->productCommon}";
$lang->story->project = "所属项目";
$lang->story->branch = "分支/平台";
$lang->story->module = '所属模块';
$lang->story->moduleAB = '模块';
$lang->story->source = "来源";
$lang->story->sourceNote = '来源备注';
$lang->story->fromBug = '来源Bug';
$lang->story->title = "{$lang->SRCommon}名称";
$lang->story->type = "需求类型";
$lang->story->category = "类别";
$lang->story->color = '标题颜色';
$lang->story->toBug = '转Bug';
$lang->story->spec = "描述";
$lang->story->assign = '指派给';
$lang->story->verify = '验收标准';
$lang->story->pri = '优先级';
$lang->story->estimate = "预计{$lang->hourCommon}";
$lang->story->estimateAB = '预计';
$lang->story->hour = $lang->hourCommon;
$lang->story->status = '当前状态';
$lang->story->subStatus = '子状态';
$lang->story->stage = '所处阶段';
$lang->story->stageAB = '阶段';
$lang->story->stagedBy = '设置阶段者';
$lang->story->mailto = '抄送给';
$lang->story->openedBy = '由谁创建';
$lang->story->openedDate = '创建日期';
$lang->story->assignedTo = '指派给';
$lang->story->assignedDate = '指派日期';
$lang->story->lastEditedBy = '最后修改';
$lang->story->lastEditedDate = '最后修改日期';
$lang->story->closedBy = '由谁关闭';
$lang->story->closedDate = '关闭日期';
$lang->story->closedReason = '关闭原因';
$lang->story->rejectedReason = '拒绝原因';
$lang->story->reviewedBy = '由谁评审';
$lang->story->reviewer = $lang->story->reviewedBy;
$lang->story->reviewers = '评审人员';
$lang->story->reviewedDate = '评审时间';
$lang->story->activatedDate = '激活日期';
$lang->story->version = '版本号';
$lang->story->feedbackBy = '反馈者';
$lang->story->notifyEmail = '通知邮箱';
$lang->story->plan = "所属计划";
$lang->story->planAB = '计划';
$lang->story->comment = '备注';
$lang->story->children = "子需求";
$lang->story->childrenAB = "子";
$lang->story->linkStories = "相关{$lang->SRCommon}";
$lang->story->childStories = "细分需求";
$lang->story->duplicateStory = "重复需求ID";
$lang->story->reviewResult = '评审意见';
$lang->story->preVersion = '之前版本';
$lang->story->keywords = '关键词';
$lang->story->newStory = "继续添加{$lang->SRCommon}";
$lang->story->colorTag = '颜色标签';
$lang->story->files = '附件';
$lang->story->copy = "复制{$lang->SRCommon}";
$lang->story->total = "总{$lang->SRCommon}";
$lang->story->draft = '草稿';
$lang->story->unclosed = '未关闭';
$lang->story->deleted = '已删除';
$lang->story->released = "已发布{$lang->SRCommon}数";
$lang->story->URChanged = '用需变更';
$lang->story->design = '相关设计';
$lang->story->case = '相关用例';
$lang->story->bug = '相关Bug';
$lang->story->repoCommit = '相关提交';
$lang->story->noRequirement = '无需求';
$lang->story->one = '一个';
$lang->story->field = '同步的字段';
$lang->story->completeRate = '完成率';
$lang->story->reviewed = '已评审';
$lang->story->toBeReviewed = '待评审';
$lang->story->linkMR = '相关合并请求';
$lang->story->id = '编号';
$lang->story->parent = '父需求';
$lang->story->product = "所属{$lang->productCommon}";
$lang->story->project = "所属项目";
$lang->story->branch = "分支/平台";
$lang->story->module = '所属模块';
$lang->story->moduleAB = '模块';
$lang->story->source = "来源";
$lang->story->sourceNote = '来源备注';
$lang->story->fromBug = '来源Bug';
$lang->story->title = "{$lang->SRCommon}名称";
$lang->story->type = "需求类型";
$lang->story->category = "类别";
$lang->story->color = '标题颜色';
$lang->story->toBug = '转Bug';
$lang->story->spec = "描述";
$lang->story->assign = '指派给';
$lang->story->verify = '验收标准';
$lang->story->pri = '优先级';
$lang->story->estimate = "预计{$lang->hourCommon}";
$lang->story->estimateAB = '预计';
$lang->story->hour = $lang->hourCommon;
$lang->story->status = '当前状态';
$lang->story->statusAB = '状态';
$lang->story->subStatus = '子状态';
$lang->story->stage = '所处阶段';
$lang->story->stageAB = '阶段';
$lang->story->stagedBy = '设置阶段者';
$lang->story->mailto = '抄送给';
$lang->story->openedBy = '由谁创建';
$lang->story->openedByAB = '创建';
$lang->story->openedDate = '创建日期';
$lang->story->assignedTo = '指派给';
$lang->story->assignedToAB = '指派';
$lang->story->assignedDate = '指派日期';
$lang->story->lastEditedBy = '最后修改';
$lang->story->lastEditedDate = '最后修改日期';
$lang->story->closedBy = '由谁关闭';
$lang->story->closedDate = '关闭日期';
$lang->story->closedReason = '关闭原因';
$lang->story->rejectedReason = '拒绝原因';
$lang->story->reviewedBy = '由谁评审';
$lang->story->reviewer = $lang->story->reviewedBy;
$lang->story->reviewers = '评审人员';
$lang->story->reviewedDate = '评审时间';
$lang->story->activatedDate = '激活日期';
$lang->story->version = '版本号';
$lang->story->feedbackBy = '反馈者';
$lang->story->notifyEmail = '通知邮箱';
$lang->story->plan = "所属计划";
$lang->story->planAB = '计划';
$lang->story->comment = '备注';
$lang->story->children = "子需求";
$lang->story->childrenAB = "子";
$lang->story->linkStories = "相关{$lang->SRCommon}";
$lang->story->linkRequirements = "相关{$lang->URCommon}";
$lang->story->childStories = "细分需求";
$lang->story->duplicateStory = "重复需求ID";
$lang->story->reviewResult = '评审意见';
$lang->story->preVersion = '之前版本';
$lang->story->keywords = '关键词';
$lang->story->newStory = "继续添加{$lang->SRCommon}";
$lang->story->colorTag = '颜色标签';
$lang->story->files = '附件';
$lang->story->copy = "复制{$lang->SRCommon}";
$lang->story->total = "总{$lang->SRCommon}";
$lang->story->draft = '草稿';
$lang->story->unclosed = '未关闭';
$lang->story->deleted = '已删除';
$lang->story->released = "已发布{$lang->SRCommon}数";
$lang->story->URChanged = '用需变更';
$lang->story->design = '相关设计';
$lang->story->case = '相关用例';
$lang->story->bug = '相关Bug';
$lang->story->repoCommit = '相关提交';
$lang->story->noRequirement = '无需求';
$lang->story->one = '一个';
$lang->story->field = '同步的字段';
$lang->story->completeRate = '完成率';
$lang->story->reviewed = '已评审';
$lang->story->toBeReviewed = '待评审';
$lang->story->linkMR = '相关合并请求';
$lang->story->ditto = '同上';
$lang->story->dittoNotice = "该{$lang->SRCommon}与上一{$lang->SRCommon}不属于同一产品!";
+59 -19
View File
@@ -72,6 +72,9 @@ class storyModel extends model
$extraStories = array_unique($extraStories);
if(!empty($extraStories)) $story->extraStories = $this->dao->select('id,title')->from(TABLE_STORY)->where('id')->in($extraStories)->fetchPairs();
$linkStoryField = $story->type == 'story' ? 'linkStories' : 'linkRequirements';
if($story->{$linkStoryField}) $story->linkStoryTitles = $this->dao->select('id,title')->from(TABLE_STORY)->where('id')->in($story->{$linkStoryField})->fetchPairs();
$story->children = array();
if($story->parent == '-1') $story->children = $this->dao->select('*')->from(TABLE_STORY)->where('parent')->eq($storyID)->andWhere('deleted')->eq(0)->fetchAll('id');
@@ -812,10 +815,14 @@ class storyModel extends model
->join('reviewedBy', ',')
->join('mailto', ',')
->join('linkStories', ',')
->join('linkRequirements', ',')
->join('childStories', ',')
->remove('files,labels,comment,contactListMenu,stages,reviewer')
->get();
if($oldStory->type == 'story' and !isset($story->linkStories)) $story->linkStories = '';
if($oldStory->type == 'requirement' and !isset($story->linkRequirements)) $story->linkRequirements = '';
if(isset($story->plan) and is_array($story->plan)) $story->plan = trim(join(',', $story->plan), ',');
if(isset($_POST['branch']) and $_POST['branch'] == 0) $story->branch = 0;
if(!empty($_POST['stages']))
@@ -965,7 +972,7 @@ class storyModel extends model
if(empty($oldStory->plan) or empty($story->plan)) $this->setStage($storyID); // Set new stage for this story.
}
if($oldStory->stage != $story->stage)
if(isset($story->stage) and $oldStory->stage != $story->stage)
{
$executionIdList = $this->dao->select('t1.project')->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
@@ -981,6 +988,29 @@ class storyModel extends model
unset($oldStory->parent);
unset($story->parent);
if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $oldStory->feedback) $this->loadModel('feedback')->updateStatus('story', $oldStory->feedback, $story->status, $oldStory->status);
$linkStoryField = $oldStory->type == 'story' ? 'linkStories' : 'linkRequirements';
$linkStories = explode(',', $story->{$linkStoryField});
$oldLinkStories = explode(',', $oldStory->{$linkStoryField});
$addStories = array_diff($linkStories, $oldLinkStories);
$removeStories = array_diff($oldLinkStories, $linkStories);
$changeStories = array_merge($addStories, $removeStories);
$changeStories = $this->dao->select("id,$linkStoryField")->from(TABLE_STORY)->where('id')->in(array_filter($changeStories))->fetchPairs();
foreach($changeStories as $changeStoryID => $changeStory)
{
if(in_array($changeStoryID, $addStories))
{
$stories = empty($changeStory) ? $storyID : $changeStory . ',' . $storyID;
$this->dao->update(TABLE_STORY)->set($linkStoryField)->eq($stories)->where('id')->eq((int)$changeStoryID)->exec();
}
if(in_array($changeStoryID, $removeStories))
{
$linkStories = str_replace(",$storyID,", ',', ",$changeStory,");
$linkStories = trim($linkStories, ',');
$this->dao->update(TABLE_STORY)->set($linkStoryField)->eq(implode(',', $linkStories))->where('id')->eq((int)$changeStoryID)->exec();
}
}
return common::createChanges($oldStory, $story);
}
}
@@ -2379,39 +2409,49 @@ class storyModel extends model
* Get stories to link.
*
* @param int $storyID
* @param string $type
* @param string $type linkStories|linkRelateSR|linkRelateUR
* @param string $browseType
* @param int $queryID
* @param varchar $storyType
* @param string $storyType
* @param object $pager
* @param string $excludeStories
* @access public
* @return array
*/
public function getStories2Link($storyID, $type = 'linkStories', $browseType = 'bySearch', $queryID = 0, $storyType = 'story')
public function getStories2Link($storyID, $type = 'linkStories', $browseType = 'bySearch', $queryID = 0, $storyType = 'story', $pager = null, $excludeStories = '')
{
$story = $this->getById($storyID);
$linkedStories = $this->getRelation($storyID, $story->type);
$linkedStories = empty($linkedStories) ? array() : $linkedStories;
$tmpStoryType = $storyType == 'story' ? 'requirement' : 'story';
if($browseType == 'bySearch')
$stories2Link = array();
if($type == 'linkRelateSR' or $type == 'linkRelateUR')
{
$stories2Link = $this->getBySearch($story->product, $story->branch, $queryID, 'id', '', $tmpStoryType);
foreach($stories2Link as $key => $story2Link)
{
if($story2Link->id == $storyID) unset($stories2Link[$key]);
if(in_array($story2Link->id, explode(',', $story->$type))) unset($stories2Link[$key]);
}
$tmpStoryType = $story->type;
$linkStoryField = $story->type == 'story' ? 'linkStories' : 'linkRequirements';
$storyIDList = $story->id . ',' . $excludeStories . ',' . $story->{$linkStoryField};
}
else
{
$status = $storyType == 'story' ? 'active' : 'all';
$stories2Link = $this->getProductStories($story->product, $story->branch, 0, $status, $tmpStoryType, $orderBy = 'id_desc');
$linkedStories = $this->getRelation($storyID, $story->type);
$linkedStories = empty($linkedStories) ? array() : $linkedStories;
$storyIDList = array_keys($linkedStories);
}
foreach($stories2Link as $id => $story)
if($browseType == 'bySearch')
{
if(in_array($story->id, array_keys($linkedStories))) unset($stories2Link[$id]);
if($storyType == 'story' && $story->status == 'draft') unset($stories2Link[$id]);
$stories2Link = $this->getBySearch($story->product, $story->branch, $queryID, 'id_desc', '', $tmpStoryType, $storyIDList, $pager);
}
elseif($type != 'linkRelateSR' and $type != 'linkRelateUR')
{
$status = $storyType == 'story' ? 'active' : 'all';
$stories2Link = $this->getProductStories($story->product, $story->branch, 0, $status, $tmpStoryType, $orderBy = 'id_desc', true, $storyIDList, $pager);
}
if($type != 'linkRelateSR' and $type != 'linkRelateUR')
{
foreach($stories2Link as $id => $story)
{
if($storyType == 'story' and $story->status == 'draft') unset($stories2Link[$id]);
}
}
return $stories2Link;
+12 -15
View File
@@ -13,6 +13,7 @@
<?php include './header.html.php';?>
<?php js::set('page', 'edit')?>
<?php js::set('oldProductID', $story->product);?>
<?php js::set('storyID', $story->id);?>
<?php js::set('parentStory', !empty($story->children));?>
<?php js::set('moveChildrenTips', $lang->story->moveChildrenTips);?>
<?php js::set('rawModule', $this->app->rawModule);?>
@@ -249,11 +250,11 @@
<td><?php echo html::input('duplicateStory', $story->duplicateStory == 0 ? '' : $story->duplicateStory, "class='form-control'");?></td>
</tr>
<?php endif;?>
<?php if($story->status == 'closed'):?>
<tr class='text-top'>
<th><?php echo $lang->story->childStories;?></th>
<th class='thWidth'><?php echo $lang->story->linkStory;?></th>
<td>
<?php echo html::a($this->createLink('story', 'linkStory', "storyID=$story->id&type=childStories", '', true), $lang->story->linkStory, '', "data-toggle='modal' data-type='iframe' data-width='95%'");?>
<?php if(common::hasPriv('story', 'linkStories') and $story->type == 'story') echo html::a("#", $lang->story->linkStoriesAB, '', "class='text-primary' id='linkStoriesLink'");?>
<?php if(common::hasPriv('story', 'linkRequirements') and $story->type == 'requirement') echo html::a("#", $lang->story->linkRequirementsAB, '', "class='text-primary' id='linkStoriesLink'");?>
</td>
</tr>
<tr>
@@ -261,26 +262,22 @@
<td>
<ul class='list-unstyled'>
<?php
if($story->childStories)
$linkStoryField = $story->type == 'story' ? 'linkStories' : 'linkRequirements';
if(isset($story->linkStoryTitles))
{
$childStories = explode(',', $story->childStories);
foreach($childStories as $childStoryID)
foreach($story->linkStoryTitles as $linkStoryID => $linkStoryTitle)
{
if(isset($story->extraStories[$childStoryID]))
{
echo "<li><div class='checkbox-primary'>";
echo "<input type='checkbox' checked='checked' name='childStories[]' value=$childStoryID />";
echo "<label>#{$childStoryID} {$story->extraStories[$childStoryID]}</label>";
echo '</div></li>';
}
echo "<li><div class='checkbox-primary' title='$linkStoryTitle'>";
echo "<input type='checkbox' checked='checked' name='" . $linkStoryField . "[]' value=$linkStoryID />";
echo "<label class='linkStoryTitle'>#{$linkStoryID} {$linkStoryTitle}</label>";
echo '</div></li>';
}
}
?>
<span id='childStoriesBox'></span>
<span id='linkStoriesBox'></span>
</ul>
</td>
</tr>
<?php endif;?>
</table>
</div>
</div>
+102
View File
@@ -0,0 +1,102 @@
<?php
/**
* The link story view of story module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Shujie Tian <tianshujie@cnezsoft.com>
* @package story
* @version $Id: linkstories.html.php 4129 2022-08-01 14:57:12Z $
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/tablesorter.html.php';?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2>
<span class='label label-id'><?php echo $story->id;?></span>
<?php echo html::a($this->createLink('story', 'view', "storyID=$story->id"), $story->title, '_blank', "title='$story->title'");?>
<?php $title = $story->type == 'story' ? $lang->story->linkStoriesAB : $lang->story->linkRequirementsAB?>
<small class='text-muted'> <?php echo $lang->arrow . $lang->story->linkStoriesAB;?></small>
</h2>
</div>
<div id='queryBox' data-module='story' class='show divider'></div>
<?php if($stories2Link):?>
<form class='main-table' method='post' data-ride='table' target='hiddenwin' id='linkStoriesForm'>
<table class='table tablesorter' id='storyList'>
<thead>
<tr>
<th class="c-id">
<div class="checkbox-primary check-all" title="<?php echo $lang->selectAll?>">
<label></label>
</div>
<?php echo $lang->idAB;?>
</th>
<th class='c-pri' title=<?php echo $lang->pri;?>><?php echo $lang->priAB;?></th>
<th class='c-product'><?php echo $lang->story->product;?></th>
<th class='c-title'><?php echo $lang->story->title;?></th>
<th class='c-status'><?php echo $lang->story->statusAB;?></th>
<th class='c-user'><?php echo $lang->story->openedByAB;?></th>
<th class='c-user'><?php echo $lang->story->assignedToAB;?></th>
</tr>
</thead>
<tbody>
<?php $storyCount = 0;?>
<?php foreach($stories2Link as $story2Link):?>
<?php $storyLink = $this->createLink('story', 'view', "storyID=$story2Link->id");?>
<tr>
<td class='c-id'>
<div class="checkbox-primary">
<input type='checkbox' name='stories[]' value='<?php echo $story2Link->id;?>'/>
<label></label>
</div>
<?php printf('%03d', $story2Link->id);?>
</td>
<td><span class='label-pri <?php echo 'label-pri-' . $story2Link->pri?>' title='<?php echo zget($lang->story->priList, $story2Link->pri, $story2Link->pri);?>'><?php echo zget($lang->story->priList, $story2Link->pri, $story2Link->pri);?></span></td>
<td class='nobr' title="<?php echo $products[$story2Link->product]?>"><?php echo html::a($this->createLink('product', 'browse', "productID=$story2Link->product&branch=$story2Link->branch"), $products[$story2Link->product], '_blank');?></td>
<td class='text-left nobr' title="<?php echo $story2Link->title?>"><?php echo html::a($storyLink, $story2Link->title);?></td>
<td><?php echo $this->processStatus('story', $story2Link);?></td>
<td><?php echo zget($users, $story2Link->openedBy);?></td>
<td><?php echo zget($users, $story2Link->assignedTo);?></td>
</tr>
<?php $storyCount ++;?>
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer'>
<div class="checkbox-primary check-all"><label><?php echo $lang->selectAll?></label></div>
<div class="table-actions btn-toolbar"><?php if($storyCount) echo html::submitButton('', '', 'btn btn-default');?></div>
<?php $pager->show('right', 'pagerjs');?>
</div>
</form>
<?php endif;?>
</div>
<?php js::set('storyType', $story->type);?>
<script>
$(function()
{
<?php if($stories2Link):?>
$('#linkStoriesForm').table();
setTimeout(function(){$('#linkStoriesForm .table-footer').removeClass('fixed-footer');}, 100);
<?php endif;?>
$('#submit').click(function()
{
var output = '';
$('#linkStoriesForm').find('tr.checked').each(function(){
var storyID = $(this).find('td.c-id').find('div.checkbox-primary input').attr('value');
var storyTitle = "#" + storyID + ' ' + $(this).find('td').eq(3).attr('title');
var linkStoryField = storyType == 'story' ? 'linkStories' : 'linkRequirements';
var checkbox = "<li><div class='checkbox-primary' title='" + $(this).find('td').eq(3).attr('title') + "'><input type='checkbox' checked='checked' name='" + linkStoryField + "[]' " + "value=" + storyID + " /><label class='linkStoryTitle'>" + storyTitle + "</label></div></li>";
output += checkbox;
});
$.closeModal();
parent.$('#linkStoriesBox').append(output);
return false;
});
});
</script>
<?php include '../../common/view/footer.html.php';?>
+21
View File
@@ -516,6 +516,27 @@
</ul>
</td>
</tr>
<tr class='text-top'>
<th class='w-90px'><?php echo $lang->story->linkStories;?></th>
<td>
<?php
if(isset($story->linkStoryTitles))
{
foreach($story->linkStoryTitles as $linkStoryID => $linkStoryTitle)
{
if($app->user->admin or strpos(",{$app->user->view->products},", ",{$storyProducts[$linkStoryID]},") !== false)
{
echo '[S] ' . html::a($this->createLink('story', 'view', "storyID=$linkStoryID", '', true), "#$linkStoryID $linkStoryTitle", '', "class='iframe' data-width='80%' title='$linkStoryTitle'") . '<br />';
}
else
{
echo "<div title='$linkStoryTitle'>[S] #$linkStoryID $linkStoryTitle</div>";
}
}
}
?>
</td>
</tr>
<tr>
<th><?php echo $lang->story->linkMR;?></th>
<td class='pd-0'>
+2
View File
@@ -18,3 +18,5 @@
.c-consumedAB {width: 60px;}
.c-leftAB {width: 60px;}
.c-actions {width: 175px;}
#mainContent .main-actions .btn-toolbar .btn {padding-left: 7px; padding-right: 6px;}
+1 -1
View File
@@ -2518,7 +2518,7 @@ class taskModel extends model
->beginIF($type == 'assignedTo' and ($this->app->rawModule == 'my' or $this->app->rawModule == 'block'))->andWhere('t2.status', true)->ne('suspended')->orWhere('t4.status')->ne('suspended')->markRight(1)->fi()
->beginIF($type != 'all' and $type != 'finishedBy' and $type != 'assignedTo')->andWhere("t1.`$type`")->eq($account)->fi()
->beginIF($type == 'assignedTo')->andWhere("(t1.assignedTo = '{$account}' or (t1.mode = 'multi' and t5.`account` = '{$account}') )")->fi()
->beginIF($type == 'assignedTo' and $this->app->rawModule == 'my' and $this->app->rawMethod == 'work')->andWhere('t1.status')->ne('closed')->fi()
->beginIF($type == 'assignedTo' and $this->app->rawModule == 'my' and $this->app->rawMethod == 'work')->andWhere('t1.status')->notin('closed,cancel,pause')->fi()
->orderBy($orderBy)
->beginIF($limit > 0)->limit($limit)->fi()
->page($pager)
+2
View File
@@ -1,3 +1,5 @@
#mailtoGroup .chosen-container-single a {border-left-width: 0px;}
#ownerAndPriBox .picker .picker-selections .picker-selection {width: 158px;}
.table tbody>tr>td {width: 400px;}
[lang^='en'] .table tbody>tr>td, [lang^='de'].table tbody>tr>td {width: 460px;}
[lang^='fr'] .table tbody>tr>td {width: 480px;}
+2
View File
@@ -1,3 +1,5 @@
#mailtoGroup .chosen-container-single a {border-left-width: 0px;}
#ownerAndPriBox .picker .picker-selections .picker-selection {width: 158px;}
.table tbody>tr>td {width: 400px;}
[lang^='en'] .table tbody>tr>td, [lang^='de'].table tbody>tr>td {width: 460px;}
[lang^='fr'] .table tbody>tr>td {width: 480px;}