diff --git a/api/v1/entries/product.php b/api/v1/entries/product.php
index d387d95f6d..36ef598f11 100644
--- a/api/v1/entries/product.php
+++ b/api/v1/entries/product.php
@@ -55,7 +55,7 @@ class productEntry extends Entry
$product->execution = $this->loadModel('product')->getExecutionPairsByProduct($productID);
break;
case 'moduleoptionmenu':
- $product->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($productID, 'bug', 0, 'all');
+ $product->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($productID, 'story', 0, 'all');
break;
case 'builds':
$product->builds = $this->loadModel('build')->getBuildPairs($productID, 'all', 'noempty,noterminate,nodone,withbranch', $this->param('object', 0), $this->param('objectType', 'execution'));
diff --git a/api/v1/entries/task.php b/api/v1/entries/task.php
index 15cd194d6e..926a337e98 100644
--- a/api/v1/entries/task.php
+++ b/api/v1/entries/task.php
@@ -102,7 +102,7 @@ class taskEntry extends Entry
$oldTask = $this->loadModel('task')->getByID($taskID);
/* Set $_POST variables. */
- $fields = 'name,type,desc,assignedTo,pri,estimate,left,consumed,story,parent,execution,module,closedReason,status,estStarted,deadline,team,teamEstimate,multiple,mailto,uid';
+ $fields = 'name,type,desc,assignedTo,pri,estimate,left,consumed,story,parent,execution,module,closedReason,status,estStarted,deadline,team,teamEstimate,teamConsumed,teamLeft,multiple,mailto,uid';
$this->batchSetPost($fields, $oldTask);
$control = $this->loadController('task', 'edit');
diff --git a/db/zentao.sql b/db/zentao.sql
index aefa069dda..892cb37ec5 100644
--- a/db/zentao.sql
+++ b/db/zentao.sql
@@ -8816,7 +8816,7 @@ ALTER TABLE `zt_story` ADD `fromStory` mediumint(8) unsigned NOT NULL default 0
ALTER TABLE `zt_story` ADD `fromVersion` smallint(6) NOT NULL default 1 after `fromStory`;
ALTER TABLE `zt_story` ADD `approvedDate` date NOT NULL after `assignedDate`;
-ALTER TABLE `zt_todo` CHANGE `type` `type` char(15) NOT NULL AFTER `feedback`;
+ALTER TABLE `zt_todo` CHANGE `type` char(15) NOT NULL AFTER `feedback`;
-- DROP TABLE IF EXISTS `zt_durationestimation`;
CREATE TABLE IF NOT EXISTS `zt_durationestimation` (
diff --git a/extension/lite/common/ext/lang/en/lite.php b/extension/lite/common/ext/lang/en/lite.php
index f8f60da3e7..c0b729fa71 100644
--- a/extension/lite/common/ext/lang/en/lite.php
+++ b/extension/lite/common/ext/lang/en/lite.php
@@ -202,6 +202,8 @@ $lang->admin->menu->system['subMenu']->safe = array('link' => "$lang->sec
$lang->admin->menu->system['subMenu']->cron = array('link' => "{$lang->admin->cron}|cron|index", 'subModule' => 'cron');
$lang->admin->menu->system['subMenu']->timezone = array('link' => "$lang->timezone|custom|timezone");
$lang->admin->menu->system['subMenu']->buildIndex = array('link' => "{$lang->admin->buildIndex}|search|buildindex|");
+
+if($config->visions == ',lite,' and $config->edition != 'open') $lang->admin->menu->system['subMenu']->license = array('link' => "License|admin|license'", 'alias' => 'license');
if($config->visions != ',lite,') unset($lang->admin->menu->system['subMenu']->buildIndex);
if($config->edition != 'open')
diff --git a/extension/lite/common/ext/lang/zh-cn/lite.php b/extension/lite/common/ext/lang/zh-cn/lite.php
index c49dd6958c..4771e9f0d1 100644
--- a/extension/lite/common/ext/lang/zh-cn/lite.php
+++ b/extension/lite/common/ext/lang/zh-cn/lite.php
@@ -202,6 +202,8 @@ $lang->admin->menu->system['subMenu']->safe = array('link' => "$lang->sec
$lang->admin->menu->system['subMenu']->cron = array('link' => "{$lang->admin->cron}|cron|index", 'subModule' => 'cron');
$lang->admin->menu->system['subMenu']->timezone = array('link' => "$lang->timezone|custom|timezone");
$lang->admin->menu->system['subMenu']->buildIndex = array('link' => "{$lang->admin->buildIndex}|search|buildindex|");
+
+if($config->visions == ',lite,' and $config->edition != 'open') $lang->admin->menu->system['subMenu']->license = array('link' => "授权信息|admin|license'", 'alias' => 'license');
if($config->visions != ',lite,') unset($lang->admin->menu->system['subMenu']->buildIndex);
if($config->edition != 'open')
diff --git a/lib/dingapi/dingapi.class.php b/lib/dingapi/dingapi.class.php
index dacf0a52b7..238e1a084c 100644
--- a/lib/dingapi/dingapi.class.php
+++ b/lib/dingapi/dingapi.class.php
@@ -188,6 +188,7 @@ class dingapi
if(isset($response->errcode) and $response->errcode == 0) return $response;
if(empty($response)) $this->errors = $errors;
+ if(isset($response->result) and $response->result == 'fail') $this->errors['curl'] = $response->message;
if(isset($response->errcode)) $this->errors[$response->errcode] = "Errcode:{$response->errcode}, Errmsg:{$response->errmsg}";
return false;
}
diff --git a/lib/feishuapi/feishuapi.class.php b/lib/feishuapi/feishuapi.class.php
index d25126517d..3749eb5a99 100644
--- a/lib/feishuapi/feishuapi.class.php
+++ b/lib/feishuapi/feishuapi.class.php
@@ -9,12 +9,12 @@ class feishuapi
private $errors = array();
/**
- * Construct
- *
- * @param string $appKey
- * @param string $appSecret
- * @param string $agentId
- * @param string $apiUrl
+ * Construct
+ *
+ * @param string $appKey
+ * @param string $appSecret
+ * @param string $agentId
+ * @param string $apiUrl
* @access public
* @return void
*/
@@ -29,7 +29,7 @@ class feishuapi
/**
* Get token.
- *
+ *
* @access public
* @return string
*/
@@ -47,7 +47,7 @@ class feishuapi
/**
* Get users.
- *
+ *
* @param string $selectedDepts
* @access public
* @return array
@@ -103,7 +103,7 @@ class feishuapi
/**
* Get depts.
- *
+ *
* @access public
* @return array
*/
@@ -146,7 +146,7 @@ class feishuapi
/**
* Get department tree structure.
- *
+ *
* @access public
* @return array
*/
@@ -186,10 +186,10 @@ class feishuapi
}
/**
- * Send message
- *
- * @param string $userList
- * @param string $message
+ * Send message
+ *
+ * @param string $userList
+ * @param string $message
* @access public
* @return array
*/
@@ -207,8 +207,8 @@ class feishuapi
/**
* Query API.
- *
- * @param string $url
+ *
+ * @param string $url
* @access public
* @return string
*/
@@ -225,6 +225,7 @@ class feishuapi
if(isset($response->code) and $response->code == 0) return $response;
if(empty($response)) $this->errors = $errors;
+ if(isset($response->result) and $response->result == 'fail') $this->errors['curl'] = $response->message;
if(isset($response->code)) $this->errors[$response->code] = "Errcode:{$response->code}, Errmsg:{$response->msg}";
if(!empty($this->errors))
{
@@ -236,7 +237,7 @@ class feishuapi
/**
* Check for errors.
- *
+ *
* @access public
* @return bool
*/
@@ -247,7 +248,7 @@ class feishuapi
/**
* Get errors.
- *
+ *
* @access public
* @return array
*/
diff --git a/lib/front/front.class.php b/lib/front/front.class.php
index e4da51367d..d9078b82f8 100644
--- a/lib/front/front.class.php
+++ b/lib/front/front.class.php
@@ -259,7 +259,7 @@ class html extends baseHTML
}
elseif(is_object($user))
{
- $userObj->avatar = $user->avatar;
+ $userObj->avatar = isset($user->avatar) ? $user->avatar : '';
$userObj->account = $user->account;
$userObj->name = isset($user->name) ? $user->name : (isset($user->realname) ? $user->realname : $user->account);
$user = $userObj;
diff --git a/lib/scm/scm.class.php b/lib/scm/scm.class.php
index c16cc4e942..30cb1f9965 100644
--- a/lib/scm/scm.class.php
+++ b/lib/scm/scm.class.php
@@ -230,7 +230,7 @@ class scm
*/
public static function checkRevision($revision)
{
- if(preg_match('/[^a-z0-9\-_\.\^]/i', $revision)) return false;
+ if(preg_match('/[^a-z0-9\-_\.\^\w][\x{4e00}-\x{9fa5}]/ui', $revision)) return false;
return true;
}
}
diff --git a/module/action/control.php b/module/action/control.php
index 488ea7763a..7a143d26ba 100755
--- a/module/action/control.php
+++ b/module/action/control.php
@@ -131,6 +131,19 @@ class action extends control
*/
public function comment($objectType, $objectID)
{
+ if(strtolower($objectType) == 'task')
+ {
+ $task = $this->loadModel('task')->getById($objectID);
+ $executions = explode(',', $this->app->user->view->sprints);
+ if(!in_array($task->execution, $executions)) return print(js::error($this->lang->error->accessDenied));
+ }
+ elseif(strtolower($objectType) == 'story')
+ {
+ $story = $this->loadModel('story')->getById($objectID);
+ $executions = explode(',', $this->app->user->view->sprints);
+ if(!array_intersect(array_keys($story->executions), $executions)) return print(js::error($this->lang->error->accessDenied));
+ }
+
$actionID = $this->action->create($objectType, $objectID, 'Commented', $this->post->comment);
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
diff --git a/module/action/model.php b/module/action/model.php
index 2b42174155..8a7690b2d9 100755
--- a/module/action/model.php
+++ b/module/action/model.php
@@ -490,7 +490,7 @@ class actionModel extends model
$name = $this->dao->select('name')->from(TABLE_TESTSUITE)->where('id')->eq($action->extra)->fetch('name');
if($name) $action->extra = common::hasPriv('caselib', 'browse') ? html::a(helper::createLink('caselib', 'browse', "libID=$action->extra"), $name) : $name;
}
- elseif(strpos('importfromstorylib,importfromrisklib,importfromissuelib,importfromopportunitylib', $actionName) !== false)
+ elseif(strpos(',importfromstorylib,importfromrisklib,importfromissuelib,importfromopportunitylib,', ",{$actionName},") !== false and $this->config->edition == 'max')
{
$name = $this->dao->select('name')->from(TABLE_ASSETLIB)->where('id')->eq($action->extra)->fetch('name');
if($name) $action->extra = common::hasPriv('assetlib', $action->objectType) ? html::a(helper::createLink('assetlib', $action->objectType, "libID=$action->extra"), $name) : $name;
diff --git a/module/block/control.php b/module/block/control.php
index 1b08f2b03c..e8237a4b99 100644
--- a/module/block/control.php
+++ b/module/block/control.php
@@ -1399,7 +1399,8 @@ class block extends control
->where('deleted')->eq(0)
->beginIF($this->config->vision == 'lite')->andWhere('type')->eq('kanban')->fi()
->beginIF($this->config->vision == 'rnd')->andWhere('type')->eq('sprint')->fi()
- ->andWhere('parent')->eq($this->session->project)
+ ->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->sprints)->fi()
+ ->andWhere('project')->eq($this->session->project)
->groupBy('status')
->fetchPairs();
diff --git a/module/common/lang/en.php b/module/common/lang/en.php
index 78c7628741..5b353efe1a 100644
--- a/module/common/lang/en.php
+++ b/module/common/lang/en.php
@@ -388,6 +388,7 @@ $lang->error->noData = 'No data.';
$lang->error->editedByOther = 'This record might have been changed. Please refresh and try to edit again!';
$lang->error->tutorialData = 'No data can be imported in tutorial mode. Please quit tutorial first!';
$lang->error->noCurlExt = 'No Curl module installed';
+$lang->error->loginTimeout = 'Login has timed out, please login again!';
/* Page info. */
$lang->pager = new stdclass();
diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index 9df9fbcc1e..91c85e100e 100644
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -389,6 +389,7 @@ $lang->error->noData = '没有数据';
$lang->error->editedByOther = '该记录可能已经被改动。请刷新页面重新编辑!';
$lang->error->tutorialData = '新手模式下不会插入数据,请退出新手模式操作';
$lang->error->noCurlExt = '服务器未安装Curl模块。';
+$lang->error->loginTimeout = '登录已超时,请重新登入!';
/* 分页信息。*/
$lang->pager = new stdclass();
diff --git a/module/common/model.php b/module/common/model.php
index 326a822199..5aaa48b24c 100644
--- a/module/common/model.php
+++ b/module/common/model.php
@@ -123,9 +123,15 @@ class commonModel extends model
$projectID = $execution->project;
$project = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($projectID)->fetch();
+ $today = helper::today();
if($project->status == 'wait')
{
- $this->dao->update(TABLE_PROJECT)->set('status')->eq('doing')->where('id')->eq($projectID)->exec();
+ $this->dao->update(TABLE_PROJECT)
+ ->set('status')->eq('doing')
+ ->beginIf(helper::isZeroDate($project->realBegan))->set('realBegan')->eq($today)->fi()
+ ->where('id')->eq($projectID)
+ ->exec();
+
$this->loadModel('action')->create('project', $projectID, 'syncproject');
}
return $project;
@@ -2245,7 +2251,17 @@ EOD;
}
else
{
- $referer = helper::safe64Encode($this->app->getURI(true));
+ $uri = $this->app->getURI(true);
+ if($module == 'message' and $method == 'ajaxgetmessage')
+ {
+ $uri = helper::createLink('my');
+ }
+ elseif(helper::isAjaxRequest())
+ {
+ die(json_encode(array('result' => false, 'message' => $this->lang->error->loginTimeout))); // Fix bug #14478.
+ }
+
+ $referer = helper::safe64Encode($uri);
print(js::locate(helper::createLink('user', 'login', "referer=$referer")));
helper::end();
}
diff --git a/module/common/view/gantt.html.php b/module/common/view/gantt.html.php
index 55d4430146..5a111ad848 100644
--- a/module/common/view/gantt.html.php
+++ b/module/common/view/gantt.html.php
@@ -18,3 +18,6 @@ js::import($jsRoot . 'dhtmlxgantt/ext/dhtmlxgantt_marker.js');
$currentLang = $app->getClientLang();
if($currentLang != 'en') js::import($jsRoot . 'dhtmlxgantt/lang/' . $currentLang . '.js');
?>
+
diff --git a/module/custom/control.php b/module/custom/control.php
index 8001a8cdc9..62ad339866 100644
--- a/module/custom/control.php
+++ b/module/custom/control.php
@@ -172,14 +172,14 @@ class custom extends control
}
if(!empty($key) and !isset($oldCustoms[$key]) and $key != 'n/a' and !validater::checkREG($key, '/^[a-z_A-Z_0-9]+$/')) return $this->send(array('result' => 'fail', 'message' => $this->lang->custom->notice->invalidStringKey));
- /* The length of roleList in user module and typeList in todo module is less than 10. check it when saved. */
- if($field == 'roleList' or $module == 'todo' and $field == 'typeList')
- {
- if(strlen($key) > 10) return $this->send(array('result' => 'fail', 'message' => $this->lang->custom->notice->invalidStrlen['ten']));
- }
+ /* The length of roleList in user module is less than 10. check it when saved. */
+ if($module == 'user' and $field == 'roleList' and strlen($key) > 10) return $this->send(array('result' => 'fail', 'message' => $this->lang->custom->notice->invalidStrlen['ten']));
+
+ /* The length of typeList in todo module is less than 15. check it when saved. */
+ if($module == 'todo' and $field == 'typeList' and strlen($key) > 15) return $this->send(array('result' => 'fail', 'message' => $this->lang->custom->notice->invalidStrlen['fifteen']));
/* The length of sourceList in story module and typeList in task module is less than 20, check it when saved. */
- if($field == 'sourceList' or $module == 'task' and $field == 'typeList')
+ if(($module == 'story' and $field == 'sourceList') or ($module == 'task' and $field == 'typeList'))
{
if(strlen($key) > 20) return $this->send(array('result' => 'fail', 'message' => $this->lang->custom->notice->invalidStrlen['twenty']));
}
@@ -188,7 +188,7 @@ class custom extends control
if($module == 'testcase' and $field == 'stageList' and strlen($key) > 255) return $this->send(array('result' => 'fail', 'message' => $this->lang->custom->notice->invalidStrlen['twoHundred']));
/* The length of field that in bug and testcase module and reasonList in story and task module is less than 30, check it when saved. */
- if($module == 'bug' or $field == 'reasonList' or $module == 'testcase')
+ if(in_array($module, array('bug', 'testcase')) or (in_array($module, array('story', 'task')) and $field == 'reasonList'))
{
if(strlen($key) > 30) return $this->send(array('result' => 'fail', 'message' => $this->lang->custom->notice->invalidStrlen['thirty']));
}
diff --git a/module/custom/lang/en.php b/module/custom/lang/en.php
index efcc7f963f..a9396a720d 100644
--- a/module/custom/lang/en.php
+++ b/module/custom/lang/en.php
@@ -183,6 +183,7 @@ $lang->custom->notice->indexPage['project'] = "ZenTao 8.2+ has Project Home. Do
$lang->custom->notice->indexPage['qa'] = "ZenTao 8.2+ has Test Homepage. Do you want to go to Test Homepage?";
$lang->custom->notice->invalidStrlen['ten'] = 'The key should be <= 10 characters.';
+$lang->custom->notice->invalidStrlen['fifteen'] = 'The key should be <= 15 characters.';
$lang->custom->notice->invalidStrlen['twenty'] = 'The key should be <= 20 characters.';
$lang->custom->notice->invalidStrlen['thirty'] = 'The key should be <= 30 characters.';
$lang->custom->notice->invalidStrlen['twoHundred'] = 'The key should be <= 225 characters.';
diff --git a/module/custom/lang/zh-cn.php b/module/custom/lang/zh-cn.php
index 5e77ee1f0e..991319a060 100644
--- a/module/custom/lang/zh-cn.php
+++ b/module/custom/lang/zh-cn.php
@@ -183,6 +183,7 @@ $lang->custom->notice->indexPage['project'] = "从8.2版本起增加了项目主
$lang->custom->notice->indexPage['qa'] = "从8.2版本起增加了测试主页视图,是否默认进入测试主页?";
$lang->custom->notice->invalidStrlen['ten'] = '键的长度必须小于10个字符!';
+$lang->custom->notice->invalidStrlen['fifteen'] = '键的长度必须小于15个字符!';
$lang->custom->notice->invalidStrlen['twenty'] = '键的长度必须小于20个字符!';
$lang->custom->notice->invalidStrlen['thirty'] = '键的长度必须小于30个字符!';
$lang->custom->notice->invalidStrlen['twoHundred'] = '键的长度必须小于225个字符!';
diff --git a/module/custom/model.php b/module/custom/model.php
index 273a093ff9..1b9eed74ad 100644
--- a/module/custom/model.php
+++ b/module/custom/model.php
@@ -434,7 +434,7 @@ class customModel extends model
global $lang, $app, $dbh;
if(!isset($lang->$module->featureBar[$method])) return;
$queryModule = $module == 'execution' ? 'task' : ($module == 'product' ? 'story' : $module);
- $shortcuts = $dbh->query('select id, title from ' . TABLE_USERQUERY . " where `account` = '{$app->user->account}' AND `module` = '{$queryModule}' AND `shortcut` = '1' order by id")->fetchAll();
+ $shortcuts = $dbh->query('select id, title from ' . TABLE_USERQUERY . " where (`account` = '{$app->user->account}' or `common` = '1') AND `module` = '{$queryModule}' AND `shortcut` = '1' order by id")->fetchAll();
if($shortcuts)
{
diff --git a/module/dev/view/header.html.php b/module/dev/view/header.html.php
index 090073ba79..9efce6496b 100644
--- a/module/dev/view/header.html.php
+++ b/module/dev/view/header.html.php
@@ -1,4 +1,4 @@
-
+getModuleRoot() . 'common/view/header.html.php';?>
diff --git a/module/doc/js/objectlibs.js b/module/doc/js/objectlibs.js
index 080e036379..a661bf9b5d 100644
--- a/module/doc/js/objectlibs.js
+++ b/module/doc/js/objectlibs.js
@@ -87,6 +87,8 @@ function fullScreen()
whenFailEnterFullscreen(error);
}
}
+
+ $('.main-col iframe').css('min-height', $(window).height() + 'px');
}
/**
@@ -102,6 +104,7 @@ function exitFullScreen()
$('#content .actions').removeClass('hidden');
$('#content .file-image .right-icon').removeClass('hidden');
$('#content .detail').eq(1).removeClass('hidden');
+ $('.main-col iframe').css('min-height', '380px');
$.cookie('isFullScreen', 0);
}
diff --git a/module/execution/control.php b/module/execution/control.php
index 904db8455a..ed7f16616a 100644
--- a/module/execution/control.php
+++ b/module/execution/control.php
@@ -3310,10 +3310,22 @@ class execution extends control
$this->view->title = $this->lang->execution->allExecutions;
$this->view->position[] = $this->lang->execution->allExecutions;
- $this->view->executionStats = $this->project->getStats($projectID, $status, $productID, 0, 30, $orderBy, $pager);
+ $executionStats = $this->project->getStats($projectID, $status, $productID, 0, 30, $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);
+
+ $this->view->executionStats = $executionStats;
$this->view->productList = $this->loadModel('product')->getProductPairsByProject($projectID);
$this->view->productID = $productID;
$this->view->projectID = $projectID;
+ $this->view->parents = $parents;
$this->view->projects = array('') + $this->project->getPairsByProgram();
$this->view->pager = $pager;
$this->view->orderBy = $orderBy;
diff --git a/module/execution/css/all.css b/module/execution/css/all.css
index c6d895178a..c1ac7084d4 100644
--- a/module/execution/css/all.css
+++ b/module/execution/css/all.css
@@ -24,3 +24,5 @@ td.flex span.project-type-label {margin-left: 5px; min-width: 36px;}
.c-action {text-align: center;}
.c-name > span {margin-right: 2px;}
td.flex span.project-type-label {min-width: 40px;}
+
+.label-children {min-width:22px !important;}
diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php
index 44dfab54d5..3040a6e2b1 100644
--- a/module/execution/view/all.html.php
+++ b/module/execution/view/all.html.php
@@ -124,12 +124,18 @@
id);?>
- flex' title='name?>'>
+ name;
+ $onlyChildStage = ($execution->grade == 2 and $execution->project != $execution->parent);
+ if($onlyChildStage and isset($parents[$execution->parent])) $executionName = $parents[$execution->parent]->name . '/' . $executionName;
+ ?>
+ | flex' title=''>
systemMode == 'new'):?>
'>execution->typeList[$execution->type]?>
projectModel == 'kanban' ? html::a($this->createLink('execution', 'kanban', 'executionID=' . $execution->id), $execution->name, '', "class='text-ellipsis'") : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $execution->name, '', "class='text-ellipsis'");
+ $executionLink = $execution->projectModel == 'kanban' ? html::a($this->createLink('execution', 'kanban', 'executionID=' . $execution->id), $executionName, '', "class='text-ellipsis'") : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $executionName, '', "class='text-ellipsis'");
+ if($onlyChildStage) echo "{$lang->programplan->childrenAB} ";
echo !empty($execution->children) ? $execution->name : $executionLink;
if(isset($execution->delay)) echo "{$lang->execution->delayed} ";
?>
@@ -214,9 +220,9 @@
|
delay)) echo "{$lang->execution->delayed} ";
echo "{$lang->programplan->childrenAB}";
echo html::a($this->createLink('execution', 'task', 'execution=' . $child->id), $child->name);
+ if(isset($child->delay)) echo "{$lang->execution->delayed} ";
?>
|
PM);?> |
diff --git a/module/extension/model.php b/module/extension/model.php
index 29de175bba..30dbc63ec7 100644
--- a/module/extension/model.php
+++ b/module/extension/model.php
@@ -456,7 +456,7 @@ class extensionModel extends model
if(!is_writable($parentDir) or !@mkdir($path, 0777, true))
{
$return->errors .= sprintf($this->lang->extension->errorTargetPathNotExists, $path) . '
';
- $return->mkdirCommands .= "mkdir -p $path
";
+ $return->mkdirCommands .= "sudo mkdir -p $path
";
$return->chmodCommands .= "sudo chmod -R 777 $path
";
}
$return->dirs2Created[] = $path;
diff --git a/module/job/model.php b/module/job/model.php
index c1387806d6..00d56de7d3 100644
--- a/module/job/model.php
+++ b/module/job/model.php
@@ -457,12 +457,12 @@ class jobModel extends model
if($job->triggerType == 'tag')
{
- $lastTag = $this->getLastTagByRepo($repo, $job);
- if($lastTag)
+ $job->lastTag = $this->getLastTagByRepo($repo, $job);
+
+ if($job->lastTag)
{
- $build->tag = $lastTag;
- $job->lastTag = $lastTag;
- $this->dao->update(TABLE_JOB)->set('lastTag')->eq($lastTag)->where('id')->eq($job->id)->exec();
+ $build->tag = $job->lastTag;
+ $this->dao->update(TABLE_JOB)->set('lastTag')->eq($job->lastTag)->where('id')->eq($job->id)->exec();
}
}
diff --git a/module/mr/control.php b/module/mr/control.php
index a24ac9d82e..497ba80482 100644
--- a/module/mr/control.php
+++ b/module/mr/control.php
@@ -422,11 +422,13 @@ class mr extends control
}
}
- $this->view->repo = $this->loadModel('repo')->getRepoByID($MR->repoID);
- $this->view->repoID = $MR->repoID;
- $this->view->diffs = $diffs;
- $this->view->encoding = $encoding;
- $this->view->arrange = $arrange;
+ $this->view->repo = $this->loadModel('repo')->getRepoByID($MR->repoID);
+ $this->view->repoID = $MR->repoID;
+ $this->view->diffs = $diffs;
+ $this->view->encoding = $encoding;
+ $this->view->arrange = $arrange;
+ $this->view->sourceBranch = $MR->sourceBranch;
+ $this->view->targetBranch = $MR->targetBranch;
$this->display();
}
diff --git a/module/mr/model.php b/module/mr/model.php
index 07d84f3532..712740bb74 100644
--- a/module/mr/model.php
+++ b/module/mr/model.php
@@ -1177,7 +1177,6 @@ class mrModel extends model
$bugInfo['content'] = $data->steps;
$bugInfo['title'] = $data->title;
$bugInfo['objectType'] = 'bug';
- $bugInfo['entry'] = $data->entry;
return $bugInfo;
}
diff --git a/module/mr/view/header.review.html.php b/module/mr/view/header.review.html.php
index 1b6201d186..d6e2032306 100644
--- a/module/mr/view/header.review.html.php
+++ b/module/mr/view/header.review.html.php
@@ -38,7 +38,8 @@ if($repoExecution)
}
$reviews = $this->mr->getReview($repoID, $MR->id);
-$v1 = isset($oldRevision) ? $oldRevision : 0;
+$v1 = str_replace('-', '*', $sourceBranch);
+$v2 = str_replace('-', '*', $targetBranch);
$this->loadModel('repo');
@@ -46,7 +47,7 @@ $taskModuleSelect = html::select('taskModule', $taskModules, $taskRepoModule,
$taskUserSelect = html::select('taskAssignedTo', $taskMembers, '', 'class="form-control chosen"');
$taskExecutionSelect = html::select('taskExecution', $taskExecutions, $repoExecution, 'class="form-control chosen" onchange="changeExecution(this)"');
-$reviewUrl = $this->createLink('mr', 'addReview', "repoID=$repoID&mr={$MR->id}&v1=$v1&v2=");
+$reviewUrl = $this->createLink('mr', 'addReview', "repoID=$repoID&mr={$MR->id}&v1=$v1&v2=$v2");
$productSelect = html::select('product', $products, $repoProduct, 'class="product form-control chosen" onchange="changeProduct(this)"');
$branches = $this->loadModel('branch')->getPairs($repoProduct);
$moduleSelect = html::select('module', $modules, $bugRepoModule, 'class="form-control chosen"');
@@ -153,7 +154,6 @@ js::set('revision', '');
repo->submit, '', 'btn btn-wide btn-primary reviewSubmit');?>
cancel, "onclick='hiddenForm()'", 'btn btn-wide');?>
-
|
diff --git a/module/my/control.php b/module/my/control.php
index 171cef2db3..96593fcdb5 100644
--- a/module/my/control.php
+++ b/module/my/control.php
@@ -418,8 +418,9 @@ EOF;
if($this->config->systemMode == 'new')
{
$projects = $this->dao->select('t1.id,t1.name,t2.id as execution')->from(TABLE_PROJECT)->alias('t1')
- ->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.id=t2.parent')
+ ->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.id=t2.project')
->where('t2.id')->in($executionIDList)
+ ->andWhere('t1.type')->eq('project')
->fetchAll('execution');
}
@@ -856,7 +857,7 @@ EOF;
$this->view->browseType = $browseType;
$this->view->ncs = $ncList;
$this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter');
- $this->view->projects = $this->loadModel('project')->getPairsByProgram(0);
+ $this->view->projects = $this->loadModel('project')->getPairsByProgram();
$this->view->pager = $pager;
$this->view->orderBy = $orderBy;
$this->view->mode = 'nc';
diff --git a/module/product/model.php b/module/product/model.php
index 010ea89847..1222111415 100644
--- a/module/product/model.php
+++ b/module/product/model.php
@@ -1285,6 +1285,7 @@ class productModel extends model
->beginIF($branch)->andWhere('t1.branch')->in($branch)->fi()
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
->andWhere('t2.deleted')->eq('0')
+ ->orderBy('id_desc')
->fetchAll('id');
$projectIdList = array();
diff --git a/module/programplan/model.php b/module/programplan/model.php
index 61d5044520..86aef7899e 100644
--- a/module/programplan/model.php
+++ b/module/programplan/model.php
@@ -200,8 +200,8 @@ class programplanModel extends model
if($data->start_date) $data->start_date = date('d-m-Y', strtotime($data->start_date));
if($data->start_date == '' or $data->endDate == '') $data->duration = 0;
- $datas['data'][] = $data;
- $stageIndex[] = array('planID' => $plan->id, 'progress' => array('totalConsumed' => 0, 'totalReal' => 0));
+ $datas['data'][] = $data;
+ $stageIndex[$plan->id] = array('planID' => $plan->id, 'parent' => $plan->parent, 'progress' => array('totalConsumed' => 0, 'totalReal' => 0));
}
$taskSign = "[ T ] ";
@@ -273,9 +273,15 @@ class programplanModel extends model
{
$stageIndex[$index]['progress']['totalConsumed'] += $task->consumed;
$stageIndex[$index]['progress']['totalReal'] += ($task->left + $task->consumed);
+
+ $stageIndex[$stage['parent']]['progress']['totalConsumed'] += $task->consumed;
+ $stageIndex[$stage['parent']]['progress']['totalReal'] += ($task->left + $task->consumed);
}
}
}
+
+ /* Ceturns all the values from the stageIndex and indexes the array numerically. */
+ $stageIndex = array_values($stageIndex);
/* Calculate the progress of the phase. */
foreach($stageIndex as $index => $stage)
diff --git a/module/programplan/view/gantt.html.php b/module/programplan/view/gantt.html.php
index 64d4306258..aa84cbe895 100644
--- a/module/programplan/view/gantt.html.php
+++ b/module/programplan/view/gantt.html.php
@@ -22,6 +22,11 @@
.gantt_task_content{display: none;}
.checkbox-primary {margin-top: 0px; margin-left: 10px;}
form {display: block; margin-top: 0em; margin-block-end: 1em;}
+
+.gantt_grid .gantt_grid_scale{width:100% !important;}
+.gantt_grid .gantt_grid_data{width:100% !important;}
+.gantt_grid .gantt_grid_data .gantt_row{width:100% !important;}
+
createLink('programplan', 'ajaxCustom'));?>
@@ -71,7 +76,15 @@ function drawGanttToCanvas(exportType, successCallback, errorCallback)
var $ganttDataArea = $ganttView.find('.gantt_data_area');
var $ganttDridData = $ganttView.find('.gantt_grid_data');
var ganttHeight = $ganttView.find('.gantt_task_bg').outerHeight() + $ganttView.find('.gantt_grid_scale').outerHeight() + 1;
- var ganttWidth = $ganttDataArea.outerWidth() + $ganttDridData.outerWidth();
+
+
+ var ganttWidth = $ganttDridData.width() - 100;
+ var ganttHeight = $ganttView.find('.gantt_grid_scale').outerHeight();
+ $ganttDridData.find('.gantt_row').each(function() {ganttHeight += $(this).outerHeight();});
+
+ var ganttWidth = $ganttDataArea.outerWidth() + $ganttDridData.outerWidth();
+ var ganttHeight = $ganttView.find('.gantt_task_bg').outerHeight() + $ganttView.find('.gantt_grid_scale').outerHeight() + 1;
+
$ganttContainer.css(
{
@@ -202,13 +215,13 @@ function zoomTasks(node)
break;
case "week":
gantt.config.min_column_width = 70;
- gantt.config.scales = [{unit: 'week', step: 1, format: "project->gantt->zooming['week'];?> #%W"}, {unit:"day", step:1, date:"%D"}]
+ gantt.config.scales = [{unit: 'week', step: 1, format: "execution->gantt->zooming['week'];?> #%W"}, {unit:"day", step:1, date:"%D"}]
gantt.config.scale_height = 60;
break;
case "month":
gantt.config.min_column_width = 70;
gantt.config.scale_height = 60;
- gantt.config.scales = [{unit: 'month', step: 1, format: '%M'}, {unit:"week", step:1, date:"project->gantt->zooming['week'];?> #%W"}];
+ gantt.config.scales = [{unit: 'month', step: 1, format: '%M'}, {unit:"week", step:1, date:"execution->gantt->zooming['week'];?> #%W"}];
break;
}
gantt.render();
diff --git a/module/repo/control.php b/module/repo/control.php
index c7c3ea7633..5a4779c469 100644
--- a/module/repo/control.php
+++ b/module/repo/control.php
@@ -272,9 +272,10 @@ class repo extends control
$this->commonAction($repoID, $objectID);
- $file = $entry;
- $repo = $this->repo->getRepoByID($repoID);
- $entry = $this->repo->decodePath($entry);
+ $file = $entry;
+ $repo = $this->repo->getRepoByID($repoID);
+ $entry = $this->repo->decodePath($entry);
+ $revision = str_replace('*', '-', $revision);
$this->scm->setEngine($repo);
$info = $this->scm->info($entry, $revision);
diff --git a/module/search/model.php b/module/search/model.php
index 770c90cc3f..5605abff9c 100644
--- a/module/search/model.php
+++ b/module/search/model.php
@@ -334,7 +334,7 @@ class searchModel extends model
*
* @param int $queryID
* @access public
- * @return string
+ * @return object
*/
public function getQuery($queryID)
{
@@ -357,6 +357,20 @@ class searchModel extends model
return $query;
}
+ /**
+ * Get a query.
+ *
+ * @param int $queryID
+ * @access public
+ * @return object
+ */
+ public function getByID($queryID)
+ {
+ $query = $this->dao->findByID($queryID)->from(TABLE_USERQUERY)->fetch();
+ if(!$query) return false;
+ return $query;
+ }
+
/**
* Save current query to db.
*
diff --git a/module/search/view/buildform.html.php b/module/search/view/buildform.html.php
index 7af76e8e24..52918a87dc 100644
--- a/module/search/view/buildform.html.php
+++ b/module/search/view/buildform.html.php
@@ -228,7 +228,7 @@ foreach($fieldParams as $fieldName => $param)
$queryName):?>
- search->getQuery($queryID);?>
+ search->getByID($queryID);?>
- app->user->account == $query->account) ? '' : ''), '', "class='label user-query' data-query-id='$queryID' title='{$queryName}'");?>
@@ -363,7 +363,6 @@ $(function()
var setDateField = function(query, fieldNO)
{
var $period = $('#selectPeriod');
- if($period.length) $period.remove();
";
diff --git a/module/story/control.php b/module/story/control.php
index dc976c96ee..cfa42bfa95 100644
--- a/module/story/control.php
+++ b/module/story/control.php
@@ -1132,8 +1132,6 @@ class story extends control
$reviewers = $this->story->getReviewerPairs($storyID, $story->version);
$reviewedBy = trim($story->reviewedBy, ',');
- $superReviewers = trim(zget($this->config->story, 'superReviewers', ''), ',');
- $checkSuperReviewed = empty($reviewedBy) ? false : strpos(",$superReviewers,", ",$reviewedBy,");
$this->executeHooks($storyID);
@@ -1165,7 +1163,6 @@ class story extends control
$this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('story', $storyID);
$this->view->from = $from;
$this->view->param = $param;
- $this->view->checkSuperReviewed = $checkSuperReviewed !== false ? true : false;
$this->display();
}
@@ -1341,6 +1338,7 @@ class story extends control
{
$changes = $this->story->close($storyID);
if(dao::isError()) return print(js::error(dao::getError()));
+ $this->story->closeParentRequirement($storyID);
if($changes)
{
diff --git a/module/story/model.php b/module/story/model.php
index 245ba7a3b5..4240c85c9e 100644
--- a/module/story/model.php
+++ b/module/story/model.php
@@ -2989,6 +2989,25 @@ class storyModel extends model
return array(0 => '') + $stories ;
}
+ /**
+ * Close requirement if all son story for segmentation has been closed.
+ *
+ * @param int $storyID
+ * @access public
+ * @return void
+ */
+ public function closeParentRequirement($storyID)
+ {
+ $parentID = $this->dao->select('BID')->from(TABLE_RELATION)->where('AID')->eq($storyID)->fetch();
+ $stories = $this->dao->select('t2.id, t2.status')->from(TABLE_RELATION)->alias('t1')
+ ->leftJoin(TABLE_STORY)->alias('t2')->on('t2.id=t1.AID')
+ ->where('t1.BType')->eq('requirement')
+ ->andWhere('t2.status')->ne('closed')
+ ->andWhere('t2.type')->eq('story')
+ ->fetchPairs();
+ if(empty($stories)) $this->close($parentID->BID);
+ }
+
/**
* Get stories of a user.
*
diff --git a/module/story/view/view.html.php b/module/story/view/view.html.php
index f0c8895767..b6967b86c7 100644
--- a/module/story/view/view.html.php
+++ b/module/story/view/view.html.php
@@ -395,7 +395,6 @@
story->assignedTo;?> |
assignedTo) echo zget($users, $story->assignedTo) . $lang->at . $story->assignedDate;?> |
-
| story->reviewers;?> |
@@ -410,7 +409,6 @@
?>
|
-
| story->reviewedDate;?> |
reviewedBy) echo $story->reviewedDate;?> |
diff --git a/module/todo/js/common.js b/module/todo/js/common.js
index d0dd53402a..e6f4a994ce 100644
--- a/module/todo/js/common.js
+++ b/module/todo/js/common.js
@@ -48,7 +48,7 @@ function loadList(type, id, defaultType, idvalue)
if(data.length != 0)
{
$(divClass).html(data).find('select').chosen();
- if(config.currentMethod == 'edit') $(divClass).html(data).find('select').val(idvalue).trigger('chosen:updated');
+ if(config.currentMethod == 'edit' || type == 'feedback') $(divClass).html(data).find('select').val(idvalue).trigger('chosen:updated');
}
else
{
diff --git a/module/todo/js/create.js b/module/todo/js/create.js
index 46315fd964..bd5ffd5a0e 100644
--- a/module/todo/js/create.js
+++ b/module/todo/js/create.js
@@ -31,7 +31,7 @@ $(function()
});
$('#pri').on('change', function()
- {
+ {
var $select = $(this);
var $selector = $select.closest('.pri-selector');
var value = $select.val();
diff --git a/module/todo/model.php b/module/todo/model.php
index 512756c9d5..d3a569fac3 100644
--- a/module/todo/model.php
+++ b/module/todo/model.php
@@ -553,7 +553,7 @@ class todoModel extends model
if($todo->type == 'risk' && $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_RISK)->fetch('name');
if($todo->type == 'opportunity' && $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_OPPORTUNITY)->fetch('name');
if($todo->type == 'review' && $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_REVIEW)->fetch('title');
- if($todo->type == 'feedback' && $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_FEEDBACK)->fetch('title');
+ if($todo->type == 'feedback' and $this->config->edition != 'open') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_FEEDBACK)->fetch('title');
$todo->begin = date::formatTime($todo->begin);
$todo->end = date::formatTime($todo->end);
diff --git a/module/todo/view/create.html.php b/module/todo/view/create.html.php
index 26e62d13aa..b565b6bdb1 100644
--- a/module/todo/view/create.html.php
+++ b/module/todo/view/create.html.php
@@ -171,7 +171,7 @@
|
- createLink('my', 'todo', 'type=all'), $lang->goback, '', "class='btn btn-back btn-wide'");?>
+ session->todoList, $lang->goback, '', "class='btn btn-back btn-wide'");?>
|
diff --git a/module/tree/lang/en.php b/module/tree/lang/en.php
index 04f5afe740..9fb6632a2e 100644
--- a/module/tree/lang/en.php
+++ b/module/tree/lang/en.php
@@ -18,7 +18,7 @@ $lang->tree->browseTask = 'Manage Task Module';
$lang->tree->manage = 'Manage Module';
$lang->tree->fix = 'Fix Module';
$lang->tree->manageProduct = "Manage {$lang->productCommon} Modules";
-$lang->tree->manageExecution = "Manage {$lang->executionCommon} Modules";
+$lang->tree->manageExecution = "Manage {$lang->execution->common} Modules";
$lang->tree->manageLine = "Manage {$lang->productCommon} Line";
$lang->tree->manageBug = 'Manage Bug';
$lang->tree->manageCase = 'Manage Case';
@@ -32,7 +32,7 @@ $lang->tree->manageLineChild = "Manage {$lang->productCommon} Line";
$lang->tree->manageBugChild = 'Manage Child Modules of Bugs';
$lang->tree->manageCaseChild = 'Manage Child Cases';
$lang->tree->manageCaselibChild = 'Manage Child Libraries';
-$lang->tree->manageTaskChild = "Manage Child {$lang->executionCommon} Modules";
+$lang->tree->manageTaskChild = "Manage Child {$lang->execution->common} Modules";
$lang->tree->syncFromProduct = "Copy from Other {$lang->productCommon}s";
$lang->tree->dragAndSort = "Drag to order";
$lang->tree->sort = "Order";
diff --git a/module/tree/lang/zh-cn.php b/module/tree/lang/zh-cn.php
index c2b90998d9..5d6c89c0f1 100644
--- a/module/tree/lang/zh-cn.php
+++ b/module/tree/lang/zh-cn.php
@@ -18,7 +18,7 @@ $lang->tree->browseTask = '任务模块维护';
$lang->tree->manage = '维护模块';
$lang->tree->fix = '修正数据';
$lang->tree->manageProduct = "维护{$lang->productCommon}视图模块";
-$lang->tree->manageExecution = "维护{$lang->executionCommon}视图模块";
+$lang->tree->manageExecution = "维护{$lang->execution->common}视图模块";
$lang->tree->manageLine = "维护{$lang->productCommon}线";
$lang->tree->manageBug = '维护测试视图模块';
$lang->tree->manageCase = '维护用例视图模块';
@@ -32,7 +32,7 @@ $lang->tree->manageLineChild = "维护{$lang->productCommon}线";
$lang->tree->manageBugChild = '维护Bug子模块';
$lang->tree->manageCaseChild = '维护用例子模块';
$lang->tree->manageCaselibChild = '维护用例库子模块';
-$lang->tree->manageTaskChild = "维护{$lang->executionCommon}子模块";
+$lang->tree->manageTaskChild = "维护{$lang->execution->common}子模块";
$lang->tree->syncFromProduct = '复制模块';
$lang->tree->dragAndSort = "拖放排序";
$lang->tree->sort = "排序";
diff --git a/module/upgrade/model.php b/module/upgrade/model.php
index bbfee0a1ef..68ffad56fe 100644
--- a/module/upgrade/model.php
+++ b/module/upgrade/model.php
@@ -495,7 +495,8 @@ class upgradeModel extends model
$this->updateGroup4Lite();
break;
- case '16.5':
+ case '16_5':
+ $this->updateProjectStatus();
$this->updateStoryReviewer();
break;
}
@@ -6181,4 +6182,35 @@ class upgradeModel extends model
$this->dao->insert(TABLE_STORYREVIEW)->data($data)->exec();
}
}
+
+ /**
+ * Update the project status.
+ *
+ * @access public
+ * @return void
+ */
+ public function updateProjectStatus()
+ {
+ $projects = $this->dao->select('*')->from(TABLE_PROJECT)
+ ->where('deleted')->eq('0')
+ ->andWhere('status')->eq('doing')
+ ->andWhere('type')->eq('project')
+ ->andWhere('realBegan')->eq('0000-00-00')
+ ->fetchAll('id');
+
+ if(empty($projects)) return;
+
+ $projectIDList = array_keys($projects);
+
+ $executions = $this->dao->select('id,project,min(realBegan) as minBegan')->from(TABLE_EXECUTION)
+ ->where('status')->eq('doing')
+ ->andWhere('deleted')->eq('0')
+ ->andWhere('project')->in($projectIDList)
+ ->groupBy('project')
+ ->fetchAll();
+
+ if(empty($executions)) return;
+
+ foreach ($executions as $execution) $this->dao->update(TABLE_PROJECT)->set('realBegan')->eq($execution->minBegan)->where('id')->eq($execution->project)->exec();
+ }
}
diff --git a/module/user/model.php b/module/user/model.php
index 1be9b079b9..4cd28e993e 100644
--- a/module/user/model.php
+++ b/module/user/model.php
@@ -228,7 +228,7 @@ class userModel extends model
{
$users = $this->dao->select('account, realname, avatar, dept, role')->from(TABLE_USER)
->where('deleted')->eq(0)
- ->beginIF($accounts)->andWhere('type')->eq($type)->fi()
+ ->beginIF($type)->andWhere('type')->eq($type)->fi()
->beginIF($accounts)->andWhere('account')->in($accounts)->fi()
->fetchAll('account');
diff --git a/module/user/view/deny.html.php b/module/user/view/deny.html.php
index dc42f44198..ec98a85722 100644
--- a/module/user/view/deny.html.php
+++ b/module/user/view/deny.html.php
@@ -50,7 +50,7 @@ include '../../common/view/header.lite.html.php';
my->common, ($isOnlybody ? '_parent' : ''), 'class="btn show-in-app" onclick="changeLeftNavigation()"');
+ echo html::a($this->createLink('my'), $lang->my->common, ($isOnlybody ? '_parent' : ''), "class='btn show-in-app' data-app='my'");
if($refererBeforeDeny) echo html::a(helper::safe64Decode($refererBeforeDeny), $lang->user->goback, ($isOnlybody ? '_parent' : ''), "class='btn'");
echo html::a($this->createLink('user', 'logout', "referer=" . helper::safe64Encode($denyPage)), $lang->user->relogin, ($isOnlybody ? '_parent' : ''), "class='btn btn-primary'");
?>
@@ -60,20 +60,4 @@ include '../../common/view/header.lite.html.php';