diff --git a/Makefile b/Makefile index 86e59f379a..4e40ef2186 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ clean: rm -fr lampp common: mkdir zentaopms + cp -fr api zentaopms/ cp -fr bin zentaopms/ cp -fr config zentaopms/ && rm -fr zentaopms/config/my.php cp -fr db zentaopms/ diff --git a/config/zentaopms.php b/config/zentaopms.php index 42527f2f3e..fe193d98ca 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -137,6 +137,8 @@ $config->openMethods[] = 'sso.gettodolist'; $config->openMethods[] = 'file.read'; $config->openMethods[] = 'index.changelog'; $config->openMethods[] = 'my.preference'; +$config->openMethods[] = 'my.changepassword'; +$config->openMethods[] = 'my.profile'; /* Define the tables. */ define('TABLE_COMPANY', '`' . $config->db->prefix . 'company`'); diff --git a/db/zentao.sql b/db/zentao.sql index 34e46e9e8d..a0f5b70f0e 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -858,7 +858,7 @@ CREATE TABLE IF NOT EXISTS `zt_searchdict` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_searchindex`; CREATE TABLE IF NOT EXISTS `zt_searchindex` ( - `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `objectType` char(20) NOT NULL, `objectID` mediumint(9) NOT NULL, `title` text NOT NULL, diff --git a/framework/router.class.php b/framework/router.class.php index 55b7f0f1b9..b24a71f998 100755 --- a/framework/router.class.php +++ b/framework/router.class.php @@ -513,11 +513,9 @@ class router extends baseRouter if($methodName == 'batchOperate') array_unshift($params, $this->rawMethod); // $params = array('close', 1); if($methodName == 'browse') { - if(!(isset($params[0]) and $params[0] == 'bysearch')) - { - array_unshift($params, 'browse'); - } + if(!(isset($params[0]) and $params[0] == 'bysearch')) array_unshift($params, 'browse'); } + array_unshift($params, $this->rawModule); // $params = array($module, 'close', 1); array_unshift($params, $methodName); // $params = array('operate', $module, 'close', 1); array_unshift($params, $moduleName); // $params = array('flow', 'operate', $module, 'close', 1); @@ -541,22 +539,23 @@ class router extends baseRouter /* Prepend other params. */ if($methodName == 'browse') { - if(isset($params['label']) and $params['label'] == 'bysearch') - { - $params['label'] = ''; - $params['mode'] = 'bysearch'; - } - else - { - $params['mode'] = 'browse'; - } + if(!(isset($params['mode']) and $params['mode'] == 'bysearch')) $params['mode'] = 'browse'; } + $params['module'] = $this->rawModule; // $param = array('label' => 1, 'mode' => 'search', 'module' => $module); $params[$this->config->methodVar] = $methodName; // $param = array('label' => 1, 'mode' => 'search', 'module' => $module, 'f' => 'browse'); $params[$this->config->moduleVar] = $moduleName; // $param = array('label' => 1, 'mode' => 'search', 'module' => $module, 'f' => 'browse', 'm' => 'flow'); $params = array_reverse($params); // $params = array('m' => 'flow', 'f' => 'browse', 'module' => $module, 'mode' => 'search', 'label' => 1); + /* Reset $_GET for setParamsByGET. */ + $get = $params; + foreach($_GET as $key => $value) + { + if(!isset($get[$key])) $get[$key] = $value; + } + $_GET = $get; + $this->URI = $path . '?' . http_build_query($params); // $this->URI = '/index.php?m=flow&f=browse&module=$module&mode=search&label=1'; } } diff --git a/lib/scm/gitlab.class.php b/lib/scm/gitlab.class.php index 12193541c1..b4f29cc6d7 100644 --- a/lib/scm/gitlab.class.php +++ b/lib/scm/gitlab.class.php @@ -111,6 +111,7 @@ class gitlab if(!empty($commits)) { $commit = $commits[0]; + $file->revision = $commit->id; $file->committer = $commit->committer_name; $file->comment = $commit->message; $file->date = date('Y-m-d H:i:s', strtotime($commit->committed_date)); diff --git a/module/action/model.php b/module/action/model.php index 670ba4be6e..d20d43f87d 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -49,8 +49,7 @@ class actionModel extends model $action->date = helper::now(); $action->extra = $extra; - if($objectType == 'story' and $actionType !== 'reviewed' and strpos('reviewclosed,passreviewed,clarifyreviewed', $actionType) !== false) $action->actor = 'System'; - + if($objectType == 'story' and $actionType !== 'reviewed' and strpos(',reviewclosed,passreviewed,clarifyreviewed,', ",$actionType,") !== false) $action->actor = 'System'; /* Use purifier to process comment. Fix bug #2683. */ $action->comment = fixer::stripDataTags($comment); @@ -928,6 +927,7 @@ class actionModel extends model public function transformActions($actions) { $this->app->loadLang('todo'); + $this->app->loadLang('stakeholder'); $requirements = array(); /* Get commiters. */ @@ -989,6 +989,13 @@ class actionModel extends model if($object->type == 'project') $objectProject[$object->id] = $object->id; } } + elseif($objectType == 'stakeholder'){ + $objectName = $this->dao->select("t1.id, t2.realname")->from($table)->alias('t1') + ->leftJoin(TABLE_USER)->alias('t2')->on("t1.{$field} = t2.account") + ->where('t1.id')->in($objectIds) + ->fetchPairs(); + $objectProject = array(); + } else { $objectName = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs(); @@ -1029,7 +1036,7 @@ class actionModel extends model $objectType = strtolower($action->objectType); $action->originalDate = $action->date; $action->date = date(DT_MONTHTIME2, strtotime($action->date)); - $action->actionLabel = isset($this->lang->action->label->$actionType) ? $this->lang->action->label->$actionType : $action->action; + $action->actionLabel = isset($this->lang->action->label->$actionType) ? $this->lang->action->label->$actionType : (isset($this->lang->$objectType->$actionType) ? $this->lang->$objectType->$actionType : $action->action); $action->objectLabel = $objectType; if(isset($this->lang->action->label->$objectType)) { diff --git a/module/block/view/projectblock.html.php b/module/block/view/projectblock.html.php index 6f79a93be2..f02a58fa89 100644 --- a/module/block/view/projectblock.html.php +++ b/module/block/view/projectblock.html.php @@ -34,7 +34,7 @@ teamCount;?> consumed . $lang->execution->workHourUnit;?> - app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);?> + app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);?> budget != 0 ? zget($lang->project->currencySymbol, $project->budgetUnit) . ' ' . $programBudget : $lang->project->future;?> leftStories;?> leftTasks;?> diff --git a/module/block/view/projectstatisticblock.html.php b/module/block/view/projectstatisticblock.html.php index fdf17551bb..fc32d4098f 100644 --- a/module/block/view/projectstatisticblock.html.php +++ b/module/block/view/projectstatisticblock.html.php @@ -221,7 +221,7 @@ $(function() project->budget . ':';?> app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2); + $projectBudget = in_array($this->app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2); echo $project->budget != 0 ? $projectBudget : $this->lang->project->future; ?> @@ -229,7 +229,7 @@ $(function()
- app->getClientLang(), ['zh-cn','zh-tw']);?> + app->getClientLang(), array('zh-cn','zh-tw'));?>
project->pv . '(' . $lang->project->pvTitle . ')' : $lang->project->pv; ?>
project->ev . '(' . $lang->project->evTitle . ')' : $lang->project->ev;?>
project->ac . '(' . $lang->project->acTitle . ')' : $lang->project->ac;?>
diff --git a/module/bug/control.php b/module/bug/control.php index 8b731dd688..dac1bfd8a0 100644 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -1287,9 +1287,6 @@ class bug extends control $this->qa->setMenu($this->products, $productID, $bug->branch); $this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve; - $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->bug->resolve; - $this->view->bug = $bug; $this->view->users = $users; $this->view->assignedTo = $assignedTo; diff --git a/module/common/model.php b/module/common/model.php index ac75910585..09a8002689 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -1366,13 +1366,14 @@ EOD; /** * Create changes of one object. * - * @param mixed $old the old object - * @param mixed $new the new object + * @param mixed $old the old object + * @param mixed $new the new object + * @param string $moduleName * @static * @access public * @return array */ - public static function createChanges($old, $new) + public static function createChanges($old, $new, $moduleName = '') { global $app, $config; @@ -1389,7 +1390,7 @@ EOD; if($oldID && $oldStatus && $newStatus && !$newSubStatus && $oldStatus != $newStatus) { - $moduleName = $app->getModuleName(); + if(empty($moduleName)) $moduleName = $app->getModuleName(); $field = $app->dbh->query('SELECT options FROM ' . TABLE_WORKFLOWFIELD . " WHERE `module` = '$moduleName' AND `field` = 'subStatus'")->fetch(); if(!empty($field->options)) $field->options = json_decode($field->options, true); diff --git a/module/doc/view/edit.html.php b/module/doc/view/edit.html.php index 88ef2e06bd..1b346fb5ea 100644 --- a/module/doc/view/edit.html.php +++ b/module/doc/view/edit.html.php @@ -45,7 +45,13 @@ doc->type;?> - doc->types, $doc->type);?> + + doc->types; + if(!isset($lang->doc->types[$doc->type])) $typeList = $lang->doc->typeList; + echo html::radio('type', array($doc->type => zget($typeList, $doc->type)), $doc->type); + ?> + type == 'url') echo "class='hidden'"?>> doc->content;?> diff --git a/module/execution/control.php b/module/execution/control.php index eb9ab9f64d..2009467ea7 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1371,13 +1371,7 @@ class execution extends control if(!empty($_POST)) { - $oldPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($executionID)->andWhere('plan')->ne(0)->fetchPairs('plan'); - $oldPlanStories = $this->dao->select('t1.story')->from(TABLE_PROJECTSTORY)->alias('t1') - ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.project=t2.project') - ->where('t1.project')->eq($executionID) - ->andWhere('t2.plan')->in(array_keys($oldPlans)) - ->fetchAll('story'); - + $oldPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($executionID)->andWhere('plan')->ne(0)->fetchPairs('plan'); $oldProducts = $this->execution->getProducts($executionID); $changes = $this->execution->update($executionID); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); @@ -1411,7 +1405,7 @@ class execution extends control if(!empty($newPlans) and !empty($diffResult)) { $projectID = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch('project'); - $this->loadModel('productplan')->linkProject($executionID, $_POST['plans'], $oldPlanStories); + $this->loadModel('productplan')->linkProject($executionID, $_POST['plans']); $this->productplan->linkProject($projectID, $_POST['plans']); } diff --git a/module/execution/model.php b/module/execution/model.php index 0b6c536367..b2a440d805 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -442,7 +442,7 @@ class executionModel extends model $oldExecution = $this->dao->findById($executionID)->from(TABLE_EXECUTION)->fetch(); /* Judgment of required items. */ - if($this->post->code == '') + if($oldExecution->type != 'stage' and $this->post->code == '') { dao::$errors['code'] = sprintf($this->lang->error->notempty, $this->lang->execution->code); return false; @@ -502,7 +502,7 @@ class executionModel extends model ->checkIF($execution->begin != '', 'begin', 'date') ->checkIF($execution->end != '', 'end', 'date') ->checkIF($execution->end != '', 'end', 'gt', $execution->begin) - ->check('code', 'unique', "id!=$executionID and deleted='0'") + ->check('code', 'unique', "id!=$executionID and code!='' and deleted='0'") ->where('id')->eq($executionID) ->limit(1) ->exec(); @@ -609,11 +609,11 @@ class executionModel extends model $nameList[$executionName] = $executionName; /* Check unique code for edited executions. */ - if(empty($executionCode)) + if($projectModel == 'scrum' and empty($executionCode)) { dao::$errors['code'][] = 'execution#' . $executionID . sprintf($this->lang->error->notempty, $this->lang->project->code); } - else + elseif(!empty($executionCode)) { /* Check unique code for edited executions. */ if(isset($codeList[$executionCode])) dao::$errors['code'][] = 'execution#' . $executionID . sprintf($this->lang->error->unique, $this->lang->project->code, $executionCode); @@ -2190,7 +2190,7 @@ class executionModel extends model $data->story = $storyID; $data->version = $versions[$storyID]; $data->order = ++$lastOrder; - $this->dao->insert(TABLE_PROJECTSTORY)->data($data)->exec(); + $this->dao->replace(TABLE_PROJECTSTORY)->data($data)->exec(); $this->story->setStage($storyID); $this->linkCases($executionID, (int)$products[$storyID], $storyID); @@ -3643,6 +3643,7 @@ class executionModel extends model public function updateUserView($executionID, $objectType = 'sprint', $users = array()) { $this->loadModel('user')->updateUserView($executionID, $objectType, $users); + $products = $this->getProducts($executionID, $withBranch = false); if(!empty($products)) $this->user->updateUserView(array_keys($products), 'product', $users); } diff --git a/module/my/view/project.html.php b/module/my/view/project.html.php index 2c1b458d4a..e1803e03fe 100644 --- a/module/my/view/project.html.php +++ b/module/my/view/project.html.php @@ -64,7 +64,7 @@ begin;?> end == LONG_TIME ? $this->lang->project->longTime : $project->end;?> - app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);?> + app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);?> budget != 0 ? zget($lang->project->currencySymbol, $project->budgetUnit) . ' ' . $projectBudget : $lang->project->future;?> PM]) ? $PMList[$project->PM]->id : ''?> diff --git a/module/product/config.php b/module/product/config.php index 638ca8db21..acfdef1152 100644 --- a/module/product/config.php +++ b/module/product/config.php @@ -11,7 +11,7 @@ $config->product->custom->batchEditFields = 'line,PO,QD,RD'; if($config->systemMode == 'new') $config->product->custom->batchEditFields .= ',program'; $config->product->list = new stdclass(); -$config->product->list->exportFields = 'id,name,line,activeStories,changedStories,draftStories,closedStories,plans,releases,bugs,unResolvedBugs,assignToNullBugs'; +$config->product->list->exportFields = 'id,program,name,line,activeRequirements,changedRequirements,draftRequirements,closedRequirements,activeStories,changedStories,draftStories,closedStories,plans,releases,bugs,unResolvedBugs,assignToNullBugs'; global $lang, $app; $app->loadLang('story'); diff --git a/module/product/control.php b/module/product/control.php index d635f5f0d0..c31a3a3af2 100644 --- a/module/product/control.php +++ b/module/product/control.php @@ -1238,13 +1238,18 @@ class product extends control $productStats = $this->product->getStats($orderBy, null, $status); foreach($productStats as $i => $product) { - $product->line = zget($lines, $product->line, ''); - $product->activeStories = (int)$product->stories['active']; - $product->changedStories = (int)$product->stories['changed']; - $product->draftStories = (int)$product->stories['draft']; - $product->closedStories = (int)$product->stories['closed']; - $product->unResolvedBugs = (int)$product->unResolved; - $product->assignToNullBugs = (int)$product->assignToNull; + $product->line = zget($lines, $product->line, ''); + $product->activeRequirements = (int)$product->requirements['active']; + $product->changedRequirements = (int)$product->requirements['changed']; + $product->draftRequirements = (int)$product->requirements['draft']; + $product->closedRequirements = (int)$product->requirements['closed']; + $product->activeStories = (int)$product->stories['active']; + $product->changedStories = (int)$product->stories['changed']; + $product->draftStories = (int)$product->stories['draft']; + $product->closedStories = (int)$product->stories['closed']; + $product->unResolvedBugs = (int)$product->unResolved; + $product->assignToNullBugs = (int)$product->assignToNull; + $product->program = $product->programName; if($this->post->exportType == 'selected') { diff --git a/module/product/lang/de.php b/module/product/lang/de.php index c96d8e64a6..ddc607bb7b 100644 --- a/module/product/lang/de.php +++ b/module/product/lang/de.php @@ -26,7 +26,7 @@ $lang->product->other = 'Andere'; $lang->product->closed = 'Geschlossen'; $lang->product->updateOrder = 'Ranking'; $lang->product->orderAction = "Rank {$lang->productCommon}"; -$lang->product->all = "Alle {$lang->productCommon}"; +$lang->product->all = "{$lang->productCommon} List"; $lang->product->manageLine = "Manage {$lang->productCommon} Line"; $lang->product->newLine = "Create {$lang->productCommon} Line"; $lang->product->export = 'Exportiere Daten'; @@ -61,6 +61,10 @@ $lang->product->draftStories = 'Entwurf [S]'; $lang->product->draftStoriesTitle = 'Draft Stories'; $lang->product->closedStories = 'Geschlossene [S]'; $lang->product->closedStoriesTitle = 'Closed Stories'; +$lang->product->activeRequirements = "Active {$lang->URCommon}"; +$lang->product->changedRequirements = "Changed {$lang->URCommon}"; +$lang->product->draftRequirements = "Draft {$lang->URCommon}"; +$lang->product->closedRequirements = "Closed {$lang->URCommon}"; $lang->product->unResolvedBugs = 'Ungelöste [B]'; $lang->product->unResolvedBugsTitle = 'Active Bugs'; $lang->product->assignToNullBugs = 'Nicht zugewiesene [B]'; diff --git a/module/product/lang/en.php b/module/product/lang/en.php index 32afdb17ae..262bf7667e 100644 --- a/module/product/lang/en.php +++ b/module/product/lang/en.php @@ -24,7 +24,7 @@ $lang->product->mine = 'Mine'; $lang->product->other = 'Others'; $lang->product->closed = 'Closed'; $lang->product->updateOrder = 'Order'; -$lang->product->all = "All {$lang->productCommon}s"; +$lang->product->all = "{$lang->productCommon} List"; $lang->product->manageLine = "Manage {$lang->productCommon} Line"; $lang->product->newLine = "Create {$lang->productCommon} Line"; $lang->product->export = 'Export'; @@ -65,6 +65,10 @@ $lang->product->draftStories = 'Draft [S]'; $lang->product->draftStoriesTitle = 'Draft Stories'; $lang->product->closedStories = 'Closed [S]'; $lang->product->closedStoriesTitle = 'Closed Stories'; +$lang->product->activeRequirements = "Active {$lang->URCommon}"; +$lang->product->changedRequirements = "Changed {$lang->URCommon}"; +$lang->product->draftRequirements = "Draft {$lang->URCommon}"; +$lang->product->closedRequirements = "Closed {$lang->URCommon}"; $lang->product->unResolvedBugs = 'Active [B]'; $lang->product->unResolvedBugsTitle = 'Active Bugs'; $lang->product->assignToNullBugs = 'Unassigned [B]'; diff --git a/module/product/lang/fr.php b/module/product/lang/fr.php index d8733d015e..3aece42b02 100644 --- a/module/product/lang/fr.php +++ b/module/product/lang/fr.php @@ -26,7 +26,7 @@ $lang->product->other = 'Autres'; $lang->product->closed = 'Fermés'; $lang->product->updateOrder = 'Ordre'; $lang->product->orderAction = "Rang {$lang->productCommon}"; -$lang->product->all = "Tous les {$lang->productCommon}s"; +$lang->product->all = "{$lang->productCommon} List"; $lang->product->manageLine = "Manage {$lang->productCommon} Line"; $lang->product->newLine = "Create {$lang->productCommon} Line"; $lang->product->export = 'Export'; @@ -61,6 +61,10 @@ $lang->product->draftStories = 'Brouillon [S]'; $lang->product->draftStoriesTitle = 'Stories en Analyse'; $lang->product->closedStories = 'Fermées [S]'; $lang->product->closedStoriesTitle = 'Stories Fermées'; +$lang->product->activeRequirements = "Active {$lang->URCommon}"; +$lang->product->changedRequirements = "Changed {$lang->URCommon}"; +$lang->product->draftRequirements = "Draft {$lang->URCommon}"; +$lang->product->closedRequirements = "Closed {$lang->URCommon}"; $lang->product->unResolvedBugs = 'Ouverts [B]'; $lang->product->unResolvedBugsTitle = 'Bugs Ouverts'; $lang->product->assignToNullBugs = 'Orphelins [B]'; diff --git a/module/product/lang/vi.php b/module/product/lang/vi.php index 270cda8ec6..d7b61c160d 100644 --- a/module/product/lang/vi.php +++ b/module/product/lang/vi.php @@ -26,7 +26,7 @@ $lang->product->other = 'Khác'; $lang->product->closed = 'Đã đóng'; $lang->product->updateOrder = 'Sắp xếp'; $lang->product->orderAction = "Đánh giá {$lang->productCommon}"; -$lang->product->all = "Tất cả {$lang->productCommon}"; +$lang->product->all = "{$lang->productCommon} List"; $lang->product->manageLine = "Manage {$lang->productCommon} Line"; $lang->product->newLine = "Create {$lang->productCommon} Line"; $lang->product->export = 'Xuất'; @@ -61,6 +61,10 @@ $lang->product->draftStories = 'Nháp [S]'; $lang->product->draftStoriesTitle = 'Câu chuyện nháp'; $lang->product->closedStories = 'Đã đóng [S]'; $lang->product->closedStoriesTitle = 'Câu chuyện đã đóng'; +$lang->product->activeRequirements = "Active {$lang->URCommon}"; +$lang->product->changedRequirements = "Changed {$lang->URCommon}"; +$lang->product->draftRequirements = "Draft {$lang->URCommon}"; +$lang->product->closedRequirements = "Closed {$lang->URCommon}"; $lang->product->unResolvedBugs = 'Kích hoạt [B]'; $lang->product->unResolvedBugsTitle = 'Kích hoạt Bugs'; $lang->product->assignToNullBugs = 'Chưa giao [B]'; diff --git a/module/product/lang/zh-cn.php b/module/product/lang/zh-cn.php index 7d59a2f19a..c92e133a38 100644 --- a/module/product/lang/zh-cn.php +++ b/module/product/lang/zh-cn.php @@ -24,7 +24,7 @@ $lang->product->mine = '我负责'; $lang->product->other = '其他'; $lang->product->closed = '已关闭'; $lang->product->updateOrder = '排序'; -$lang->product->all = "所有{$lang->productCommon}"; +$lang->product->all = "{$lang->productCommon}列表"; $lang->product->manageLine = "维护{$lang->productCommon}线"; $lang->product->newLine = "新建{$lang->productCommon}线"; $lang->product->export = '导出数据'; @@ -65,6 +65,10 @@ $lang->product->draftStories = "草稿{$lang->SRCommon}"; $lang->product->draftStoriesTitle = "草稿{$lang->SRCommon}"; $lang->product->closedStories = "已关闭{$lang->SRCommon}"; $lang->product->closedStoriesTitle = "已关闭{$lang->SRCommon}"; +$lang->product->activeRequirements = "激活{$lang->URCommon}"; +$lang->product->changedRequirements = "已变更{$lang->URCommon}"; +$lang->product->draftRequirements = "草稿{$lang->URCommon}"; +$lang->product->closedRequirements = "已关闭{$lang->URCommon}"; $lang->product->unResolvedBugs = '未解决Bug'; $lang->product->unResolvedBugsTitle = '未解决Bug'; $lang->product->assignToNullBugs = '未指派Bug'; diff --git a/module/product/lang/zh-tw.php b/module/product/lang/zh-tw.php index 503420764c..83d723ab14 100644 --- a/module/product/lang/zh-tw.php +++ b/module/product/lang/zh-tw.php @@ -65,6 +65,10 @@ $lang->product->draftStories = "草稿{$lang->SRCommon}"; $lang->product->draftStoriesTitle = "草稿{$lang->SRCommon}"; $lang->product->closedStories = "已關閉{$lang->SRCommon}"; $lang->product->closedStoriesTitle = "已關閉{$lang->SRCommon}"; +$lang->product->activeRequirements = "激活{$lang->URCommon}"; +$lang->product->changedRequirements = "已變更{$lang->URCommon}"; +$lang->product->draftRequirements = "草稿{$lang->URCommon}"; +$lang->product->closedRequirements = "已關閉{$lang->URCommon}"; $lang->product->unResolvedBugs = '未解決Bug'; $lang->product->unResolvedBugsTitle = '未解決Bug'; $lang->product->assignToNullBugs = '未指派Bug'; diff --git a/module/product/view/all.html.php b/module/product/view/all.html.php index 19e5d44450..5358fc01ba 100644 --- a/module/product/view/all.html.php +++ b/module/product/view/all.html.php @@ -19,8 +19,9 @@
+ " . $lang->export, '', "class='btn btn-link export'")?>  " . $lang->product->line, '', 'class="btn btn-link iframe"', '', true);?> - ' . $lang->product->create, '', 'class="btn btn-primary"');?> + ' . $lang->product->create, '', 'class="btn btn-primary"');?>
diff --git a/module/product/view/project.html.php b/module/product/view/project.html.php index 48e82067cb..567ac03de2 100644 --- a/module/product/view/project.html.php +++ b/module/product/view/project.html.php @@ -76,7 +76,7 @@ - app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);?> + app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);?> budget != 0 ? zget($this->lang->project->currencySymbol, $project->budgetUnit) . ' ' . $projectBudget : $this->lang->project->future;?> budget != 0 ? 'text-right' : 'text-center';?> diff --git a/module/productplan/model.php b/module/productplan/model.php index 3d78e0598a..d5a3e884b8 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -582,14 +582,11 @@ class productplanModel extends model * * @param int $projectID * @param array $newPlans - * @param array $oldPlanStories * @access public * @return void */ - public function linkProject($projectID, $newPlans, $oldPlanStories = '') + public function linkProject($projectID, $newPlans) { - if(!empty($oldPlanStories)) $this->dao->delete()->from(TABLE_PROJECTSTORY)->where('project')->eq($projectID)->andWhere('story')->in(array_keys($oldPlanStories))->exec(); - $this->loadModel('execution'); foreach($newPlans as $planID) { diff --git a/module/program/lang/zh-cn.php b/module/program/lang/zh-cn.php index e7f18a5d18..60f7fa83b0 100644 --- a/module/program/lang/zh-cn.php +++ b/module/program/lang/zh-cn.php @@ -1,5 +1,6 @@ program->id = '编号'; $lang->program->name = '项目集名称'; $lang->program->template = '项目集模板'; $lang->program->category = '项目集类型'; @@ -8,14 +9,27 @@ $lang->program->copy = '复制项目集'; $lang->program->status = '状态'; $lang->program->PM = '负责人'; $lang->program->budget = '预算'; -$lang->program->progress = '项目进度'; -$lang->program->children = '子项目集'; +$lang->program->budgetUnit = '预算单位'; +$lang->program->begin = '计划开始'; +$lang->program->end = '计划完成'; +$lang->program->stage = '阶段'; +$lang->program->type = '类型'; +$lang->program->pri = '优先级'; $lang->program->parent = '父项目集'; -$lang->program->allInput = '项目集总投入'; -$lang->program->teamCount = '总人数'; -$lang->program->longTime = '长期'; $lang->program->view = '项目集详情'; $lang->program->exchangeRate = '汇率'; +$lang->program->openedBy = '由谁创建'; +$lang->program->openedDate = '创建日期'; +$lang->program->closedBy = '由谁关闭'; +$lang->program->closedDate = '关闭日期'; +$lang->program->canceledBy = '由谁取消'; +$lang->program->canceledDate = '取消日期'; +$lang->program->team = '团队'; +$lang->program->order = '排序'; +$lang->program->days = '可用工作日'; +$lang->program->acl = '访问控制'; +$lang->program->whitelist = '白名单'; +$lang->program->deleted = '已删除'; /* Actions. */ $lang->program->common = '项目集'; @@ -24,6 +38,8 @@ $lang->program->create = '添加项目集'; $lang->program->createGuide = '选择项目模板'; $lang->program->edit = '编辑项目集'; $lang->program->browse = '项目集列表'; +$lang->program->view = '项目集详情'; +$lang->program->copy = '复制项目集'; $lang->program->product = '产品列表'; $lang->program->project = '项目集项目列表'; $lang->program->all = '所有项目集'; @@ -39,16 +55,11 @@ $lang->program->createStakeholder = '添加干系人'; $lang->program->unlinkStakeholder = '移除干系人'; $lang->program->batchUnlinkStakeholders = '批量移除干系人'; $lang->program->unlink = '移除'; -$lang->program->moreProgram = '更多项目集'; -$lang->program->confirmBatchUnlink = "您确定要批量移除这些干系人吗?"; -$lang->program->stakeholderType = '干系人类型'; -$lang->program->isStakeholderKey = '关键干系人'; $lang->program->importStakeholder = '从父项目集导入'; $lang->program->unbindWhitelist = '移除白名单'; $lang->program->importStakeholder = '从父项目集导入'; $lang->program->manageMembers = '项目集团队'; $lang->program->beyondParentBudget = '已超出所属项目集的剩余预算'; -$lang->program->parentBudget = '所属项目集剩余预算:'; $lang->program->beginLetterParent = "父项目集的开始日期:%s,开始日期不能小于父项目集的开始日期"; $lang->program->endGreaterParent = "父项目集的完成日期:%s,完成日期不能大于父项目集的完成日期"; $lang->program->beginGreateChild = "子项目集的最小开始日期:%s,父项目集的开始日期不能大于子项目集的最小开始日期"; @@ -61,12 +72,33 @@ $lang->program->changePRJUnit = '更新项目预算单位'; $lang->program->readjustTime = '重新调整项目集起止时间'; $lang->program->accessDenied = '你无权访问该项目集'; +$lang->program->progress = '项目进度'; +$lang->program->children = '子项目集'; +$lang->program->allInput = '项目集总投入'; +$lang->program->teamCount = '总人数'; +$lang->program->longTime = '长期'; +$lang->program->moreProgram = '更多项目集'; +$lang->program->stakeholderType = '干系人类型'; +$lang->program->parentBudget = '所属项目集剩余预算:'; +$lang->program->isStakeholderKey = '关键干系人'; + $lang->program->stakeholderTypeList['inside'] = '内部'; $lang->program->stakeholderTypeList['outside'] = '外部'; -$lang->program->noProgram = '暂时没有项目集'; -$lang->program->showClosed = '显示已关闭'; -$lang->program->tips = '选择了父项目集,则可关联该父项目集下的产品。如果项目未选择任何项目集,则系统会默认创建一个和该项目同名的产品并关联该项目。'; +$lang->program->noProgram = '暂时没有项目集'; +$lang->program->showClosed = '显示已关闭'; +$lang->program->tips = '选择了父项目集,则可关联该父项目集下的产品。如果项目未选择任何项目集,则系统会默认创建一个和该项目同名的产品并关联该项目。'; +$lang->program->confirmBatchUnlink = "您确定要批量移除这些干系人吗?"; +$lang->program->beginLetterParent = "父项目集的开始日期:%s,开始日期不能小于父项目集的开始日期"; +$lang->program->endGreaterParent = "父项目集的完成日期:%s,完成日期不能大于父项目集的完成日期"; +$lang->program->beginGreateChild = "子项目集的最小开始日期:%s,父项目集的开始日期不能大于子项目集的最小开始日期"; +$lang->program->endLetterChild = "子项目的最大完成日期:%s,父项目的完成日期不能小于子项目的最大完成日期"; +$lang->program->closeErrorMessage = '存在子项目集或项目为未关闭状态'; +$lang->program->hasChildren = '该项目集有子项目集或项目存在,不能删除。'; +$lang->program->confirmDelete = "您确定要删除吗?"; +$lang->program->readjustTime = '重新调整项目集起止时间'; +$lang->program->accessDenied = '你无权访问该项目集'; +$lang->program->beyondParentBudget = '已超出所属项目集的剩余预算'; $lang->program->endList[31] = '一个月'; $lang->program->endList[93] = '三个月'; diff --git a/module/program/view/browsebylist.html.php b/module/program/view/browsebylist.html.php index d38038ed9e..d09aba1970 100644 --- a/module/program/view/browsebylist.html.php +++ b/module/program/view/browsebylist.html.php @@ -70,7 +70,7 @@ createLink('user', 'profile', "userID=$userID", '', true), $userName, '', "title='{$userName}' data-toggle='modal' data-type='iframe' data-width='600'");?> - app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$program->budget / 10000, 2) . $lang->project->tenThousand : round((float)$program->budget, 2);?> + app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$program->budget / 10000, 2) . $lang->project->tenThousand : round((float)$program->budget, 2);?> budget != 0 ? zget($lang->project->currencySymbol, $program->budgetUnit) . ' ' . $programBudget : $lang->project->future;?> begin;?> end == LONG_TIME ? $lang->program->longTime : $program->end;?> diff --git a/module/project/config.php b/module/project/config.php index cea74baa0d..e28c1dbbec 100644 --- a/module/project/config.php +++ b/module/project/config.php @@ -11,7 +11,7 @@ $config->project->editor->activate = array('id' => 'comment', 'tools' => 'simple $config->project->editor->view = array('id' => 'lastComment', 'tools' => 'simpleTools'); $config->project->list = new stdclass(); -$config->project->list->exportFields = 'id,name,code,template,product,status,begin,end,budget,PM,end,desc'; +$config->project->list->exportFields = 'id,parent,name,linkedProducts,status,begin,end,budget,PM,end,desc'; $config->project->create = new stdclass(); $config->project->edit = new stdclass(); @@ -92,14 +92,14 @@ $config->project->datatable->fieldList['estimate']['pri'] = '8'; $config->project->datatable->fieldList['consume']['title'] = 'consume'; $config->project->datatable->fieldList['consume']['fixed'] = 'no'; -$config->project->datatable->fieldList['consume']['width'] = '70'; +$config->project->datatable->fieldList['consume']['width'] = '80'; $config->project->datatable->fieldList['consume']['maxWidth'] = '80'; $config->project->datatable->fieldList['consume']['required'] = 'no'; $config->project->datatable->fieldList['consume']['sort'] = 'no'; $config->project->datatable->fieldList['consume']['pri'] = '7'; $config->project->datatable->fieldList['progress']['title'] = 'progress'; -$config->project->datatable->fieldList['progress']['fixed'] = 'right'; +$config->project->datatable->fieldList['progress']['fixed'] = 'no'; $config->project->datatable->fieldList['progress']['width'] = '60'; $config->project->datatable->fieldList['progress']['required'] = 'no'; $config->project->datatable->fieldList['progress']['sort'] = 'no'; diff --git a/module/project/control.php b/module/project/control.php index 54e2ca6c5b..8795e52885 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -68,7 +68,7 @@ class project extends control unset($fields[$key]); } - $projects = $this->project->getList($status, $orderBy, null); + $projects = $this->project->getInfoList($status, 30, $orderBy, null); $users = $this->loadModel('user')->getPairs('noletter'); foreach($projects as $i => $project) { @@ -77,6 +77,10 @@ class project extends control $project->model = zget($projectLang->modelList, $project->model); $project->product = zget($projectLang->productList, $project->product); $project->budget = $project->budget . zget($projectLang->unitList, $project->budgetUnit); + $project->parent = $project->parentName; + + $linkedProducts = $this->project->getProducts($project->id, false); + $project->linkedProducts = implode(',', $linkedProducts); if($this->post->exportType == 'selected') { @@ -419,12 +423,7 @@ class project extends control if($_POST) { - $oldPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->fetchPairs('plan'); - $oldPlanStories = $this->dao->select('t1.story')->from(TABLE_PROJECTSTORY)->alias('t1') - ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.project=t2.project') - ->where('t1.project')->eq($projectID) - ->andWhere('t2.plan')->in(array_keys($oldPlans)) - ->fetchAll('story'); + $oldPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->andWhere('plan')->ne(0)->fetchPairs('plan'); $changes = $this->project->update($projectID); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); @@ -439,7 +438,7 @@ class project extends control $diffResult = array_diff($oldPlans, $_POST['plans']); if(!empty($_POST['plans']) and !empty($diffResult)) { - $this->loadModel('productplan')->linkProject($projectID, $_POST['plans'], $oldPlanStories); + $this->loadModel('productplan')->linkProject($projectID, $_POST['plans']); } if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent')); @@ -1623,7 +1622,7 @@ class project extends control $response = array(); $response['result'] = true; $response['message'] = $this->lang->project->changeProgramTip; - + /* Get new program products. */ $newProducts = $this->program->getProductPairs($programID, 'assign', 'noclosed'); $response['newProducts'] = html::select("newProducts", array('0' => '') + $newProducts, '', "class='form-control chosen' onchange='loadBranches(this)'"); diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index a624285a6c..bdfac9cf45 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -47,7 +47,7 @@ $lang->project->errorNoProducts = '最少关联一个产品'; $lang->project->copyNoProject = '没有可用的项目来复制'; $lang->project->searchByName = '输入项目名称进行检索'; $lang->project->deleted = '已删除'; -$lang->project->linkedProducts = '已关联'; +$lang->project->linkedProducts = '已关联产品'; $lang->project->unlinkedProducts = '未关联'; $lang->project->testreport = '测试报告'; $lang->project->selectProgram = '项目集筛选'; @@ -55,7 +55,9 @@ $lang->project->teamMember = '团队成员'; /* Fields. */ $lang->project->common = '项目'; +$lang->project->id = '项目编号'; $lang->project->stage = '阶段'; +$lang->project->model = '项目管理方式'; $lang->project->PM = '负责人'; $lang->project->name = '项目名称'; $lang->project->category = '项目类型'; @@ -65,7 +67,19 @@ $lang->project->copy = '复制项目'; $lang->project->begin = '计划开始'; $lang->project->end = '计划完成'; $lang->project->status = '状态'; +$lang->project->subStatus = '子状态'; +$lang->project->type = '项目类型'; +$lang->project->pri = '优先级'; +$lang->project->openedBy = '由谁创建'; +$lang->project->openedDate = '创建日期'; +$lang->project->closedBy = '由谁关闭'; +$lang->project->closedDate = '关闭日期'; +$lang->project->canceledBy = '由谁取消'; +$lang->project->canceledDate = '取消日期'; +$lang->project->team = '团队'; +$lang->project->order = '排序'; $lang->project->budget = '预算'; +$lang->project->budgetUnit = '预算单位'; $lang->project->template = '项目模板'; $lang->project->estimate = '预计'; $lang->project->consume = '消耗'; diff --git a/module/project/model.php b/module/project/model.php index 733420ee2d..78a0bc4800 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -780,7 +780,6 @@ class projectModel extends model $whitelist = explode(',', $project->whitelist); $this->loadModel('personnel')->updateWhitelist($whitelist, 'project', $projectID); - if($project->acl != 'open') $this->loadModel('user')->updateUserView($projectID, 'project'); /* Create doc lib. */ $this->app->loadLang('doc'); @@ -962,7 +961,13 @@ class projectModel extends model $whitelist = explode(',', $project->whitelist); $this->loadModel('personnel')->updateWhitelist($whitelist, 'project', $projectID); - if($project->acl != 'open') $this->loadModel('user')->updateUserView($projectID, 'project'); + if($project->acl != 'open') + { + $this->loadModel('user')->updateUserView($projectID, 'project'); + + $executions = $this->dao->select('id')->from(TABLE_EXECUTION)->where('project')->eq($projectID)->fetchPairs('id', 'id'); + if($executions) $this->user->updateUserView($executions, 'sprint'); + } if($project->acl == 'private') { @@ -1356,7 +1361,7 @@ class projectModel extends model if($id == 'budget') { - $projectBudget = in_array($this->app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2); + $projectBudget = in_array($this->app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2); $budgetTitle = $project->budget != 0 ? zget($this->lang->project->currencySymbol, $project->budgetUnit) . ' ' . $projectBudget : $this->lang->project->future; $title = "title='$budgetTitle'"; @@ -1367,6 +1372,7 @@ class projectModel extends model if($id == 'surplus') $title = "title='{$project->hours->totalLeft} {$this->lang->execution->workHour}'"; echo ""; + if(isset($this->config->bizVersion)) $this->loadModel('flow')->printFlowCell('project', $project, $id); switch($id) { case 'id': @@ -1517,6 +1523,23 @@ class projectModel extends model if($needUpdate) $this->user->updateUserView($needUpdate, 'product', $members); } + /** + * Update userview for involved product and execution. + * + * @param int $projectID + * @param array $users + * @access public + * @return void + */ + public function updateInvolvedUserView($projectID, $users = array()) + { + $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->fetchPairs('product', 'product'); + $this->loadModel('user')->updateUserView($products, 'product', $stakeholder); + + $executions = $this->dao->select('id')->from(TABLE_EXECUTION)->where('project')->eq($projectID)->fetchPairs('id', 'id'); + if($executions) $this->user->updateUserView($executions, 'sprint', $stakeholder); + } + /** * Get team members. * diff --git a/module/project/view/browse.html.php b/module/project/view/browse.html.php index 2dd5b6751f..5d619ac9f6 100644 --- a/module/project/view/browse.html.php +++ b/module/project/view/browse.html.php @@ -11,6 +11,7 @@ */ ?> +  ", '', "class='btn btn-icon' title='{$lang->project->bylist}' id='switchButton' data-type='bylist'");?>  ", '', "class='btn btn-icon text-primary' title='{$lang->project->bycard}' id='switchButton' data-type='bycard'");?>
+ " . $lang->export, '', "class='btn btn-link export'")?> config->maxVersion)):?> ' . $lang->project->create, '', 'class="btn btn-primary" data-toggle="modal" data-target="#guideDialog"');?> config->systemMode == 'new'):?> diff --git a/module/project/view/browsebylist.html.php b/module/project/view/browsebylist.html.php index 2b9c8dd788..aff507d339 100644 --- a/module/project/view/browsebylist.html.php +++ b/module/project/view/browsebylist.html.php @@ -37,6 +37,7 @@  ", '', "class='btn btn-icon text-primary' title='{$lang->project->bylist}' id='switchButton' data-type='bylist'");?>  ", '', "class='btn btn-icon' title='{$lang->project->bycard}' id='switchButton' data-type='bycard'");?> + " . $lang->export, '', "class='btn btn-link export'")?> config->maxVersion)):?> ' . $lang->project->create, '', 'class="btn btn-primary" data-toggle="modal" data-target="#guideDialog"');?> config->systemMode == 'new'):?> @@ -78,10 +79,16 @@ recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}"; - $setting = $this->datatable->getSetting('project'); + $vars = "programID=$programID&browseType=$browseType¶m=$param&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}"; + $datatableId = $this->moduleName . ucfirst($this->methodName); + $useDatatable = (isset($config->datatable->$datatableId->mode) and $config->datatable->$datatableId->mode == 'datatable'); + $setting = $this->datatable->getSetting('project'); + $widths = $this->datatable->setFixedFieldWidth($setting); + + if($useDatatable) include '../../common/view/datatable.html.php'; ?> - + ';?> +
' data-fixed-left-width='' data-fixed-right-width=''> config->systemMode == 'new' ? common::hasPriv('project', 'batchEdit') : common::hasPriv('project', 'batchEdit');?> @@ -104,6 +111,7 @@
+ ';?> - printExtendFields('', 'table');?> project->desc;?> + printExtendFields('', 'table', 'columns=3');?> project->acl;?> project->aclList, $acl, "onclick='setWhite(this.value);'", 'block'));?> diff --git a/module/project/view/edit.html.php b/module/project/view/edit.html.php index 567dd9d69a..16516f4544 100644 --- a/module/project/view/edit.html.php +++ b/module/project/view/edit.html.php @@ -149,6 +149,7 @@ desc, "rows='6' class='form-control kindeditor' hidefocus='true'" . (strpos($requiredFields, 'desc') !== false ? ' required' : ''));?> + printExtendFields('', 'table', 'columns=3');?> project->acl;?> acl, "onclick='setWhite(this.value);'", 'block'));?> diff --git a/module/repo/control.php b/module/repo/control.php index 84b8379a9d..aeb1d3e529 100644 --- a/module/repo/control.php +++ b/module/repo/control.php @@ -170,7 +170,6 @@ class repo extends control if(strtolower($repo->SCM) == 'gitlab') { $projects = $this->loadModel('gitlab')->apiGetProjects($repo->gitlab); - $options = array(); foreach($projects as $project) $options[$project->id] = $project->name_with_namespace; diff --git a/module/report/lang/zh-cn.php b/module/report/lang/zh-cn.php index 46ff54dbaa..8ae2b06d61 100644 --- a/module/report/lang/zh-cn.php +++ b/module/report/lang/zh-cn.php @@ -63,7 +63,7 @@ $lang->reportList->test->lists[13] = 'Bug指派表|report|bugassign'; $lang->reportList->staff->lists[10] = '员工负载表|report|workload'; $lang->report->id = '编号'; -$lang->report->execution = $lang->executionCommon; +$lang->report->execution = '执行'; $lang->report->product = $lang->productCommon; $lang->report->user = '姓名'; $lang->report->bugTotal = 'Bug'; diff --git a/module/search/control.php b/module/search/control.php index f4d6e5e5ab..e0baa17683 100644 --- a/module/search/control.php +++ b/module/search/control.php @@ -166,7 +166,8 @@ class search extends control } else { - return $this->send(array('result' => 'unfinished', 'message' => sprintf($this->lang->search->buildResult, zget($this->lang->searchObjects, ($result['type'] == 'case' ? 'testcase' : $result['type']), $result['type']), $result['count']),'next' => inlink('buildIndex', "type={$result['type']}&lastID={$result['lastID']}") )); + $type = zget($this->lang->searchObjects, ($result['type'] == 'case' ? 'testcase' : $result['type']), $result['type']); + return $this->send(array('result' => 'unfinished', 'message' => sprintf($this->lang->search->buildResult, $type, $type, $result['count']), 'type' => $type, 'count' => $result['count'], 'next' => inlink('buildIndex', "type={$result['type']}&lastID={$result['lastID']}") )); } } diff --git a/module/search/js/buildindex.js b/module/search/js/buildindex.js index 74df862ea4..7f9fdc4f60 100644 --- a/module/search/js/buildindex.js +++ b/module/search/js/buildindex.js @@ -13,8 +13,19 @@ $(document).ready(function() } else { + className = response.type + 'count'; + $typeCount = $('#resultBox .' + className) + if($typeCount.length == 0) + { + $('#resultBox').append("
  • " + response.message + "
  • "); + } + else + { + count = parseInt($typeCount.html()) + parseInt(response.count); + $typeCount.html(count); + } + $('#execButton').attr('href', response.next); - $('#resultBox').append("
  • " + response.message + "
  • "); return $('#execButton').click(); } }); diff --git a/module/search/lang/de.php b/module/search/lang/de.php index d37d7d28bc..6097774685 100644 --- a/module/search/lang/de.php +++ b/module/search/lang/de.php @@ -68,7 +68,7 @@ $lang->search->preview = 'Preview'; $lang->search->result = 'Search Results'; $lang->search->buildSuccessfully = 'Search index initialized.'; $lang->search->executeInfo = '%s search results for you in %s seconds.'; -$lang->search->buildResult = 'Created index %s and added %s records.'; +$lang->search->buildResult = "Create index %s and created %s records."; $lang->search->modules['all'] = 'All'; $lang->search->modules['task'] = 'Task'; diff --git a/module/search/lang/en.php b/module/search/lang/en.php index b35e74c92b..0ee2b29838 100644 --- a/module/search/lang/en.php +++ b/module/search/lang/en.php @@ -68,7 +68,7 @@ $lang->search->preview = 'Preview'; $lang->search->result = 'Search Results'; $lang->search->buildSuccessfully = 'Search index initialized.'; $lang->search->executeInfo = '%s search results for you in %s seconds.'; -$lang->search->buildResult = 'Created index %s and added %s records.'; +$lang->search->buildResult = "Create index %s and created %s records."; $lang->search->modules['all'] = 'All'; $lang->search->modules['task'] = 'Task'; diff --git a/module/search/lang/fr.php b/module/search/lang/fr.php index c385e47934..47970e082f 100644 --- a/module/search/lang/fr.php +++ b/module/search/lang/fr.php @@ -68,7 +68,7 @@ $lang->search->preview = 'Preview'; $lang->search->result = 'Search Results'; $lang->search->buildSuccessfully = 'Search index initialized.'; $lang->search->executeInfo = '%s search results for you in %s seconds.'; -$lang->search->buildResult = 'Created index %s and added %s records.'; +$lang->search->buildResult = "Create index %s and created %s records."; $lang->search->modules['all'] = 'All'; $lang->search->modules['task'] = 'Task'; diff --git a/module/search/lang/vi.php b/module/search/lang/vi.php index 4d8a3132eb..a2cb4d565b 100644 --- a/module/search/lang/vi.php +++ b/module/search/lang/vi.php @@ -68,7 +68,7 @@ $lang->search->preview = 'Preview'; $lang->search->result = 'Kết quả tìm kiếm'; $lang->search->buildSuccessfully = 'Tìm kiếm khởi tạo chỉ mục.'; $lang->search->executeInfo = '%s kết quả tìm kiếm trong %s giây'; -$lang->search->buildResult = 'Chỉ mục được tao %s và được thêm %s mục'; +$lang->search->buildResult = "Create index %s and created %s records."; $lang->search->modules['all'] = 'Tất cả'; $lang->search->modules['task'] = 'Nhiệm vụ'; diff --git a/module/search/lang/zh-cn.php b/module/search/lang/zh-cn.php index 9ec02c18d1..180076618f 100644 --- a/module/search/lang/zh-cn.php +++ b/module/search/lang/zh-cn.php @@ -68,7 +68,7 @@ $lang->search->preview = '预览'; $lang->search->result = '搜索结果'; $lang->search->buildSuccessfully = '初始化搜索索引成功'; $lang->search->executeInfo = '为您找到相关结果%s个,耗时%s秒'; -$lang->search->buildResult = '创建 %s 索引, 新增 %s 条记录;'; +$lang->search->buildResult = "创建 %s 索引, 已创建 %s 条记录;"; $lang->search->modules['all'] = '全部'; $lang->search->modules['task'] = '任务'; diff --git a/module/search/model.php b/module/search/model.php index 3c4d0db64f..0ebe5792d5 100644 --- a/module/search/model.php +++ b/module/search/model.php @@ -31,6 +31,8 @@ class searchModel extends model if($module == 'projectBug') $flowModule = 'bug'; $fields = $this->loadModel('workflowfield')->getList($flowModule); + $maxCount = $this->config->maxCount; + $this->config->maxCount = 0; foreach($fields as $field) { @@ -60,6 +62,7 @@ class searchModel extends model $searchConfig['fields'][$field->field] = $field->name; $searchConfig['params'][$field->field] = array('operator' => $operator, 'control' => $control, 'values' => $options, 'class' => $class); } + $this->config->maxCount = $maxCount; } $searchParams['module'] = $searchConfig['module']; @@ -263,7 +266,7 @@ class searchModel extends model if($hasUser) { - $users = $this->loadModel('user')->getPairs('realname|noclosed', $appendUsers, $this->config->maxCount); + $users = $this->loadModel('user')->getPairs('realname|noclosed', $appendUsers); $users['$@me'] = $this->lang->search->me; } if($hasProduct) $products = array('' => '') + $this->loadModel('product')->getPairs('', $this->session->project); @@ -694,10 +697,15 @@ class searchModel extends model */ public function saveDict($dict) { + static $savedDict; + if(empty($savedDict)) $savedDict = $this->dao->select("`key`")->from(TABLE_SEARCHDICT)->fetchPairs('key', 'key'); foreach($dict as $key => $value) { if(!is_numeric($key) or empty($value) or strlen($key) != 5) continue; - $this->dao->replace(TABLE_SEARCHDICT)->data(array('key' => $key, 'value' => $value))->exec(); + if(isset($savedDict[$key])) continue; + + $this->dao->insert(TABLE_SEARCHDICT)->data(array('key' => $key, 'value' => $value))->exec(); + $savedDict[$key] = $key; } } diff --git a/module/stakeholder/control.php b/module/stakeholder/control.php index d52584aadd..15a88ae385 100644 --- a/module/stakeholder/control.php +++ b/module/stakeholder/control.php @@ -310,14 +310,11 @@ class stakeholder extends control $stakeholder = $this->stakeholder->getByID($userID); $this->stakeholder->delete(TABLE_STAKEHOLDER, $userID); $this->loadModel('user')->updateUserView($this->session->project, 'project'); + /* Update linked products view. */ if($stakeholder->objectType == 'project' and $stakeholder->objectID) { - $products = $this->loadModel('product')->getProductPairsByProject($stakeholder->objectID); - if(!empty($products)) - { - foreach($products as $productID => $productName) $this->user->updateUserView($productID, 'product',$stakeholder->user); - } + $this->loadModel('project')->updateInvolvedUserView($stakeholder->objectID, $stakeholder->user); /* Update the viewers of the project main doc library. */ $canViewUsers = $this->dao->select('users')->from(TABLE_DOCLIB)->where('type')->eq('project')->andWhere('project')->eq($stakeholder->objectID)->andWhere('main')->eq(1)->fetch(); diff --git a/module/stakeholder/model.php b/module/stakeholder/model.php index 7076fce50f..161c442caa 100644 --- a/module/stakeholder/model.php +++ b/module/stakeholder/model.php @@ -105,11 +105,7 @@ class stakeholderModel extends model /* Update linked products view. */ if($stakeholder->objectType == 'project' and $stakeholder->objectID) { - $products = $this->loadModel('product')->getProductPairsByProject($stakeholder->objectID); - if(!empty($products)) - { - foreach($products as $productID => $productName) $this->user->updateUserView($productID, 'product', $stakeholder->user); - } + $this->loadModel('project')->updateInvolvedUserView($stakeholder->objectID, $stakeholder->user); /* Update the viewers of the project main doc library. */ $canViewUsers = $this->dao->select('users')->from(TABLE_DOCLIB)->where('type')->eq('project')->andWhere('project')->eq($stakeholder->objectID)->andWhere('main')->eq(1)->fetch(); @@ -184,12 +180,7 @@ class stakeholderModel extends model $this->loadModel('user')->updateUserView($projectID, 'project', $changedAccounts); - /* Update linked products view. */ - $products = $this->loadModel('product')->getProductPairsByProject($projectID); - if(!empty($products)) - { - foreach($products as $productID => $productName) $this->user->updateUserView($productID, 'product', $changedAccounts); - } + $this->loadModel('project')->updateInvolvedUserView($projectID, $changedAccounts); /* Update the viewers of the project main doc library. */ $canViewUsers = $this->dao->select('users')->from(TABLE_DOCLIB)->where('type')->eq('project')->andWhere('project')->eq($stakeholder->objectID)->andWhere('main')->eq(1)->fetch(); diff --git a/module/story/control.php b/module/story/control.php index c9f87b0461..55e14ae0c1 100644 --- a/module/story/control.php +++ b/module/story/control.php @@ -1488,7 +1488,7 @@ class story extends control /* Load pager and get tracks. */ $this->app->loadClass('pager', $static = true); $pager = new pager($recTotal, $recPerPage, $pageID); - $tracks = $this->story->getTracks($productID, $branch, $pager); + $tracks = $this->story->getTracks($productID, $branch, $projectID, $pager); if($projectID) { diff --git a/module/story/model.php b/module/story/model.php index f7a5685fa9..4c250bf3e5 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -198,13 +198,11 @@ class storyModel extends model $story = fixer::input('post') ->cleanInt('product,module,pri,plan') ->callFunc('title', 'trim') - ->add('assignedDate', 0) ->add('version', 1) ->add('status', 'draft') ->setDefault('plan,verify', '') ->setDefault('openedBy', $this->app->user->account) ->setDefault('openedDate', $now) - ->setIF($this->post->assignedTo != '', 'assignedDate', $now) ->setIF($this->post->needNotReview or $executionID > 0, 'status', 'active') ->setIF($this->post->plan > 0, 'stage', 'planned') ->setIF($this->post->estimate, 'estimate', (float)$this->post->estimate) @@ -254,14 +252,20 @@ class storyModel extends model /* Save the story reviewer to storyreview table. */ if(isset($_POST['reviewer'])) { + $assignedTo = ''; foreach($this->post->reviewer as $reviewer) { + if(empty($reviewer)) continue; + $reviewData = new stdclass(); $reviewData->story = $storyID; $reviewData->version = 1; $reviewData->reviewer = $reviewer; $this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec(); + + if(empty($assignedTo)) $assignedTo = $reviewer; } + if($assignedTo) $this->dao->update(TABLE_STORY)->set('assignedTo')->eq($assignedTo)->set('assignedDate')->eq(helper::now())->where('id')->eq($storyID)->exec(); } /* Project or execution linked story. */ @@ -547,14 +551,20 @@ class storyModel extends model /* Save the story reviewer to storyreview table. */ if(isset($_POST['reviewer'][$i])) { + $assignedTo = ''; foreach($_POST['reviewer'][$i] as $reviewer) { + if(empty($reviewer)) continue; + $reviewData = new stdclass(); $reviewData->story = $storyID; $reviewData->version = 1; $reviewData->reviewer = $reviewer; $this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec(); + + if(empty($assignedTo)) $assignedTo = $reviewer; } + if($assignedTo) $this->dao->update(TABLE_STORY)->set('assignedTo')->eq($assignedTo)->set('assignedDate')->eq($now)->where('id')->eq($storyID)->exec(); } $this->executeHooks($storyID); @@ -682,6 +692,7 @@ class storyModel extends model /* Update the reviewer. */ $oldReviewerList = $this->getReviewerPairs($storyID, $oldStory->version); + $assignedTo = ''; foreach($_POST['reviewer'] as $reviewer) { if(!$specChanged and in_array($reviewer, array_keys($oldReviewerList))) continue; @@ -691,7 +702,10 @@ class storyModel extends model $reviewData->version = $specChanged ? $story->version : $oldStory->version; $reviewData->reviewer = $reviewer; $this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec(); + + if(empty($assignedTo)) $assignedTo = $reviewer; } + if($assignedTo and $assignedTo != $oldStory->assignedTo) $this->dao->update(TABLE_STORY)->set('assignedTo')->eq($assignedTo)->set('assignedDate')->eq(helper::now())->where('id')->eq($storyID)->exec(); $this->file->updateObjectID($this->post->uid, $storyID, 'story'); @@ -3289,6 +3303,14 @@ class storyModel extends model } } + if(strtolower($actionType) == 'changed' or strtolower($actionType) == 'opened') + { + $reviewerList = $this->getReviewerPairs($story->id, $story->version); + unset($reviewerList[$story->assignedTo]); + + $ccList .= ',' . join(',', array_keys($reviewerList)); + } + if(empty($toList)) { if(empty($ccList)) return false; @@ -3878,11 +3900,12 @@ class storyModel extends model * * @param int $productID * @param int $branch + * @param int $projectID * @param object $pager * @access public * @return bool|array */ - public function getTracks($productID = 0, $branch = 0, $pager = null) + public function getTracks($productID = 0, $branch = 0, $projectID = 0, $pager = null) { $tracks = array(); $sourcePageID = $pager->pageID; @@ -3890,7 +3913,24 @@ class storyModel extends model if($this->config->URAndSR) { - $requirements = $this->getProductStories($productID, $branch, 0, 'all', 'requirement', 'id_desc', true, '', $pager); + $projectStories = array(); + if($projectID) + { + $requirements = $this->dao->select('t3.*')->from(TABLE_PROJECTSTORY)->alias('t1') + ->leftJoin(TABLE_RELATION)->alias('t2')->on("t1.story=t2.AID && t2.AType='story'") + ->leftJoin(TABLE_STORY)->alias('t3')->on("t2.BID=t3.id && t2.BType='requirement'") + ->where('t1.project')->eq($projectID) + ->andWhere('t1.product')->eq($productID) + ->andWhere('t3.id')->ne('') + ->page($pager, 't3.id') + ->fetchAll('id'); + $projectStories = $this->getExecutionStories($projectID, $productID, $branch, '`order`_desc', 'all', 0, 'story'); + } + else + { + $requirements = $this->getProductStories($productID, $branch, 0, 'all', 'requirement', 'id_desc', true, '', $pager); + } + if($pager->pageID != $sourcePageID) { $requirements = array(); @@ -3903,6 +3943,12 @@ class storyModel extends model $stories = empty($stories) ? array() : $stories; foreach($stories as $id => $title) { + if($projectStories and !isset($projectStories[$id])) + { + unset($stories[$id]); + continue; + } + $stories[$id] = new stdclass(); $stories[$id]->title = $title; $stories[$id]->cases = $this->loadModel('testcase')->getStoryCases($id); @@ -3931,12 +3977,26 @@ class storyModel extends model ->andWhere('relation')->eq('subdivideinto') ->andWhere('product')->eq($productID) ->fetchPairs('BID', 'BID'); - $stories = $this->getProductStories($productID, 0, 0, 'all', 'story', 'id_desc', true, $excludeStories); - if($stories) $pager->recTotal += 1; + if($projectID) + { + $stories = $this->getExecutionStories($projectID, $productID, $branch, '`order`_desc', 'all', 0, 'story', $excludeStories); + } + else + { + $stories = $this->getProductStories($productID, 0, 0, 'all', 'story', 'id_desc', true, $excludeStories); + } + if($stories) $pager->recTotal += count($stories); } else { - $stories = $this->getProductStories($productID, 0, 0, 'all', 'story', 'id_desc', true, $excludeStories, $pager); + if($projectID) + { + $stories = $this->getExecutionStories($projectID, $productID, $branch, '`order`_desc', 'all', 0, 'story', $excludeStories, $pager); + } + else + { + $stories = $this->getProductStories($productID, 0, 0, 'all', 'story', 'id_desc', true, $excludeStories, $pager); + } } if(count($tracks) < $pager->recPerPage) diff --git a/module/story/view/track.html.php b/module/story/view/track.html.php index 6eeb36a2ba..90ca4f0f08 100644 --- a/module/story/view/track.html.php +++ b/module/story/view/track.html.php @@ -58,7 +58,7 @@ URAndSR):?> - story->statusList, $requirement->status);?> diff --git a/module/story/view/view.html.php b/module/story/view/view.html.php index 6822c29716..8579027fb5 100644 --- a/module/story/view/view.html.php +++ b/module/story/view/view.html.php @@ -375,9 +375,16 @@ reviewedBy, ',')); - foreach($reviewers as $reviewer) + if($reviewers) { - echo in_array($reviewer, $reviewedBy) ? ' ' . zget($users, $reviewer) . '' : ' ' . zget($users, $reviewer) . ''; + foreach($reviewers as $reviewer) + { + echo in_array($reviewer, $reviewedBy) ? ' ' . zget($users, $reviewer) . '' : ' ' . zget($users, $reviewer) . ''; + } + } + elseif($reviewedBy) + { + foreach($reviewedBy as $reviewer) echo ' ' . zget($users, $reviewer) . ''; } ?> diff --git a/module/task/model.php b/module/task/model.php index 975633e381..cb56455e0d 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -662,6 +662,9 @@ class taskModel extends model if($parentTask->story) $this->loadModel('story')->setStage($parentTask->story); $newParentTask = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($parentID)->fetch(); + + unset($oldParentTask->subStatus); + unset($newParentTask->subStatus); $changes = common::createChanges($oldParentTask, $newParentTask); $action = ''; if($status == 'done' and $parentTask->status != 'done') $action = 'Finished'; diff --git a/module/testcase/control.php b/module/testcase/control.php index 8deb6933b0..884299d67a 100644 --- a/module/testcase/control.php +++ b/module/testcase/control.php @@ -642,11 +642,10 @@ class testcase extends control if($this->app->openApp == 'qa') $this->testcase->setMenu($this->products, $productID, $case->branch); $this->view->title = "CASE #$case->id $case->title - " . $this->products[$productID]; - $this->view->position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); $this->view->product = $product; $this->view->branches = $branches; - $this->view->productName = $this->products[$productID]; + $this->view->productName = isset($this->products[$productID]) ? $this->products[$productID] : ''; $this->view->branchName = $product->type == 'normal' ? '' : zget($branches, $case->branch, ''); } @@ -1505,7 +1504,7 @@ class testcase extends control $this->post->set('kind', 'testcase'); $this->post->set('rows', $rows); $this->post->set('extraNum', $num); - $this->post->set('fileName', 'template'); + $this->post->set('fileName', 'Template'); $this->fetch('file', 'export2csv', $_POST); } diff --git a/module/testcase/view/view.html.php b/module/testcase/view/view.html.php index 1c8df7a903..88905d038a 100644 --- a/module/testcase/view/view.html.php +++ b/module/testcase/view/view.html.php @@ -151,7 +151,7 @@ testcase->product;?> - createLink('product', 'browse', "productID=$case->product"), $productName) : $productName;?> + createLink('product', 'browse', "productID=$case->product"), $productName) : $productName;?> type != 'normal'):?> diff --git a/module/testtask/view/results.html.php b/module/testtask/view/results.html.php index 963e272ffb..8ba8c46c69 100644 --- a/module/testtask/view/results.html.php +++ b/module/testtask/view/results.html.php @@ -51,7 +51,8 @@ app->openApp == 'execution' and isset($testtask)) ? "executionID=$testtask->execution" : "";?> - id,{$executionParam},buildID=$testtask->build" : ",$executionParam";?> + id,buildID=$testtask->build" : "";?> + app->openApp == 'project' ? "projectID={$this->session->project}," : ''?> diff --git a/module/todo/js/view.js b/module/todo/js/view.js index 4bd5d4aaa2..2bd2424d06 100644 --- a/module/todo/js/view.js +++ b/module/todo/js/view.js @@ -78,7 +78,24 @@ function createProject() var onlybody = config.onlybody; config.onlybody = 'no'; - var link = systemMode == 'new' ? createLink('project', 'create') : createLink('execution', 'create'); + var link = createLink('project', 'create'); + + config.onlybody = onlybody; + parent.location.href = link; +} + +/** + * Create execution. + * + * @access public + * @return void + */ +function createExecution() +{ + var onlybody = config.onlybody; + config.onlybody = 'no'; + + var link = createLink('execution', 'create'); config.onlybody = onlybody; parent.location.href = link; diff --git a/module/todo/view/view.html.php b/module/todo/view/view.html.php index 79a8b6ea65..16e1a6c768 100644 --- a/module/todo/view/view.html.php +++ b/module/todo/view/view.html.php @@ -202,11 +202,11 @@