diff --git a/api/v1/entries/bug.php b/api/v1/entries/bug.php index 7146d2d879..7e311f51ca 100644 --- a/api/v1/entries/bug.php +++ b/api/v1/entries/bug.php @@ -32,8 +32,9 @@ class bugEntry extends entry $bug = $data->data->bug; - /* Set product name */ - $bug->productName = $data->data->product->name; + /* Set product name and status */ + $bug->productName = $data->data->product->name; + $bug->productStatus = $data->data->product->status; /* Set module title */ $moduleTitle = ''; diff --git a/api/v1/entries/bugs.php b/api/v1/entries/bugs.php index 738de8a39d..4694e85145 100644 --- a/api/v1/entries/bugs.php +++ b/api/v1/entries/bugs.php @@ -33,6 +33,7 @@ class bugsEntry extends entry $bugs = $data->data->bugs; $pager = $data->data->pager; $result = array(); + $this->loadModel('product'); foreach($bugs as $bug) { $status = array('code' => $bug->status, 'name' => $this->lang->bug->statusList[$bug->status]); @@ -42,6 +43,9 @@ class bugsEntry extends entry $bug->status = $status['code']; $bug->statusName = $status['name']; + $product = $this->product->getById($bug->product); + $bug->productStatus = $product->status; + $result[$bug->id] = $this->format($bug, 'activatedDate:time,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,mailto:userList,resolvedBy:user,resolvedDate:time,closedBy:user,closedDate:time,lastEditedBy:user,lastEditedDate:time,deadline:date,deleted:bool'); } diff --git a/api/v1/entries/configs.php b/api/v1/entries/configs.php index 8ac46b7942..f9df6375fe 100644 --- a/api/v1/entries/configs.php +++ b/api/v1/entries/configs.php @@ -21,13 +21,14 @@ class configsEntry extends baseEntry { $configs = array(); - $configs[] = array('key' => 'language', 'value' => $this->config->default->lang); - $configs[] = array('key' => 'version', 'value' => $this->config->version); - $configs[] = array('key' => 'charset', 'value' => $this->config->charset); - $configs[] = array('key' => 'timezone', 'value' => $this->config->timezone); - $configs[] = array('key' => 'systemMode', 'value' => $this->config->systemMode); - $configs[] = array('key' => 'hourUnit', 'value' => $this->config->hourUnit); - $configs[] = array('key' => 'CRProduct', 'value' => $this->config->CRProduct); + $configs[] = array('key' => 'language', 'value' => $this->config->default->lang); + $configs[] = array('key' => 'version', 'value' => $this->config->version); + $configs[] = array('key' => 'charset', 'value' => $this->config->charset); + $configs[] = array('key' => 'timezone', 'value' => $this->config->timezone); + $configs[] = array('key' => 'systemMode', 'value' => $this->config->systemMode); + $configs[] = array('key' => 'hourUnit', 'value' => $this->config->hourUnit); + $configs[] = array('key' => 'CRProduct', 'value' => $this->config->CRProduct); + $configs[] = array('key' => 'CRExecution', 'value' => $this->config->CRExecution); $this->send(200, $configs); } diff --git a/api/v1/entries/executionstories.php b/api/v1/entries/executionstories.php index 4f32cb527c..2c16ac7dd2 100644 --- a/api/v1/entries/executionstories.php +++ b/api/v1/entries/executionstories.php @@ -32,8 +32,12 @@ class executionStoriesEntry extends entry $stories = $data->data->stories; $pager = $data->data->pager; $result = array(); + $this->loadModel('product'); foreach($stories as $story) { + $product = $this->product->getById($story->product); + $story->productStatus = $product->status; + $result[] = $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList'); } return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'stories' => $result)); diff --git a/api/v1/entries/product.php b/api/v1/entries/product.php index 280d59537c..34089f3221 100644 --- a/api/v1/entries/product.php +++ b/api/v1/entries/product.php @@ -54,6 +54,9 @@ class productEntry extends Entry case 'execution': $product->execution = $this->loadModel('product')->getExecutionPairsByProduct($productID); break; + case 'bugstatistic': + $product->bugStatistic = $this->loadModel('bug')->getStatistic($productID); + break; case 'moduleoptionmenu': $product->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($productID, 'story', 0, '0'); break; diff --git a/api/v1/entries/project.php b/api/v1/entries/project.php index 970823db25..61b8cf819a 100644 --- a/api/v1/entries/project.php +++ b/api/v1/entries/project.php @@ -63,9 +63,8 @@ class projectEntry extends entry $project->teams = $teams; break; case "products": - $status = $this->param('status', 'all'); $project->products = array(); - $productList = $this->loadModel('product')->getOrderedProducts($status, 40, $projectID); + $productList = $this->loadModel('product')->getProducts($projectID, $this->param('status', 'all')); foreach($productList as $product) $project->products[] = $product; break; case "stat": diff --git a/api/v1/entries/projectbugs.php b/api/v1/entries/projectbugs.php index 7468563e61..8ee1827387 100644 --- a/api/v1/entries/projectbugs.php +++ b/api/v1/entries/projectbugs.php @@ -33,6 +33,7 @@ class projectBugsEntry extends entry $bugs = $data->data->bugs; $pager = $data->data->pager; $result = array(); + $this->loadModel('product'); foreach($bugs as $bug) { $status = array('code' => $bug->status, 'name' => $this->lang->bug->statusList[$bug->status]); @@ -42,6 +43,9 @@ class projectBugsEntry extends entry $bug->status = $status['code']; $bug->statusName = $status['name']; + $product = $this->product->getById($bug->product); + $bug->productStatus = $product->status; + $result[$bug->id] = $this->format($bug, 'activatedDate:time,openedDate:time,assignedDate:time,resolvedDate:time,closedDate:time,lastEditedDate:time,deadline:date,deleted:bool'); } diff --git a/api/v1/entries/projectstories.php b/api/v1/entries/projectstories.php index e7729858e1..be44915f19 100644 --- a/api/v1/entries/projectstories.php +++ b/api/v1/entries/projectstories.php @@ -32,8 +32,12 @@ class projectStoriesEntry extends entry $stories = $data->data->stories; $pager = $data->data->pager; $result = array(); + $this->loadModel('product'); foreach($stories as $story) { + $product = $this->product->getById($story->product); + $story->productStatus = $product->status; + $result[] = $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList'); } return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'stories' => $result)); diff --git a/api/v1/entries/stories.php b/api/v1/entries/stories.php index fa64edb6c2..8ba8d8f53a 100644 --- a/api/v1/entries/stories.php +++ b/api/v1/entries/stories.php @@ -24,7 +24,7 @@ class storiesEntry extends entry if(!$productID) return $this->sendError(400, 'Need product id.'); $control = $this->loadController('product', 'browse'); - $control->browse($productID, $this->param('branch', ''), $this->param('status', 'unclosed'), 0, $this->param('type', 'story'), $this->param('order', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1)); + $control->browse($productID, $this->param('branch', ''), $this->param('status', 'unclosed'), 0, $this->param('type', 'story'), $this->param('order', 'id_desc'), 0, $this->param('limit', 500), $this->param('page', 1)); $data = $this->getData(); if(!$data or !isset($data->status)) return $this->sendError(400, 'error'); @@ -33,9 +33,21 @@ class storiesEntry extends entry $stories = $data->data->stories; $pager = $data->data->pager; $result = array(); + $this->loadModel('product'); foreach($stories as $story) { - if(isset($story->children)) $story->children = array_values((array)$story->children); + $product = $this->product->getById($story->product); + $story->productStatus = $product->status; + if(isset($story->children)) + { + $story->children = array_values((array)$story->children); + foreach($story->children as $id => $children) + { + $childrenProduct = $this->product->getById($children->product); + $story->children[$id]->productStatus = $childrenProduct->status; + } + } + $result[] = $this->format($story, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList'); } return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'stories' => $result)); diff --git a/api/v1/entries/story.php b/api/v1/entries/story.php index 4273caf022..08f6e1bcf9 100644 --- a/api/v1/entries/story.php +++ b/api/v1/entries/story.php @@ -36,8 +36,9 @@ class storyEntry extends Entry if(isset($story->planTitle)) $story->planTitle = array_values((array)$story->planTitle); if($story->parent > 0) $story->parentPri = $this->dao->select('pri')->from(TABLE_STORY)->where('id')->eq($story->parent)->fetch('pri'); - /* Set product name */ - $story->productName = $data->data->product->name; + /* Set product name and status*/ + $story->productName = $data->data->product->name; + $story->productStatus = $data->data->product->status; /* Set module title */ $moduleTitle = ''; diff --git a/api/v1/entries/task.php b/api/v1/entries/task.php index 926a337e98..a4b2f8c43e 100644 --- a/api/v1/entries/task.php +++ b/api/v1/entries/task.php @@ -87,6 +87,9 @@ class taskEntry extends Entry $task->preAndNext['pre'] = $preAndNext->pre ? $preAndNext->pre->id : ''; $task->preAndNext['next'] = $preAndNext->next ? $preAndNext->next->id : ''; + $execution = $this->loadModel('project')->getByID($task->execution, 'execution'); + $task->executionStatus = $execution->status; + $this->send(200, $this->format($task, 'deadline:date,openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,realStarted:time,finishedBy:user,finishedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,lastEditedBy:user,lastEditedDate:time,deleted:bool,mailto:userList')); } diff --git a/config/routes.php b/config/routes.php index bad7129397..4ef5ff66ef 100644 --- a/config/routes.php +++ b/config/routes.php @@ -57,8 +57,6 @@ $routes['/stories/:id/child'] = 'storyChild'; $routes['/stories/:id/recall'] = 'storyRecall'; $routes['/stories/:id/review'] = 'storyReview'; -$routes['/module/:id/stories'] = 'moduleStories'; - $routes['/products/:id/bugs'] = 'bugs'; $routes['/projects/:id/bugs'] = 'projectBugs'; $routes['/executions/:id/bugs'] = 'executionBugs'; diff --git a/db/update16.5.sql b/db/update16.5.sql index afb1d27fd1..bb437efddd 100644 --- a/db/update16.5.sql +++ b/db/update16.5.sql @@ -87,3 +87,5 @@ REPLACE INTO `zt_zoutput` (`id`, `activity`, `name`, `content`, `optional`, `sta (99,64,'禅道缺陷记录项','','yes','','admin','2020-01-09 14:26:52','','0000-00-00 00:00:00',495,'0'); DELETE FROM `zt_config` WHERE `section` = 'customMenu'; + +UPDATE `zt_story` SET `plan` = '' WHERE `plan` = 0; diff --git a/extension/lite/common/ext/lang/en/lite.php b/extension/lite/common/ext/lang/en/lite.php index 8abc4f8577..d25edaa44c 100644 --- a/extension/lite/common/ext/lang/en/lite.php +++ b/extension/lite/common/ext/lang/en/lite.php @@ -139,11 +139,11 @@ $lang->doc->menuOrder[30] = 'custom'; $lang->doc->menu->project['subMenu'] = new stdclass(); $lang->doc->menu->custom['subMenu'] = new stdclass(); -$xuanxuanMenu = $lang->admin->menu->xuanxuan; +if(isset($lang->admin->menu->xuanxuan)) $xuanxuanMenu = $lang->admin->menu->xuanxuan; /* Admin menu. */ $lang->admin->menu = new stdclass(); $lang->admin->menu->index = array('link' => "$lang->indexPage|admin|index", 'alias' => 'register,certifytemail,certifyztmobile,ztcompany'); -$lang->admin->menu->xuanxuan = $xuanxuanMenu; +if(isset($xuanxuanMenu)) $lang->admin->menu->xuanxuan = $xuanxuanMenu; $lang->admin->menu->company = array('link' => "{$lang->personnel->common}|company|browse|", 'subModule' => ',user,dept,group,'); $lang->admin->menu->custom = array('link' => "{$lang->custom->common}|custom|index", 'exclude' => 'custom-browsestoryconcept,custom-timezone,custom-estimate'); $lang->admin->menu->extension = array('link' => "{$lang->extension->common}|extension|browse", 'subModule' => 'extension'); diff --git a/extension/lite/common/ext/lang/zh-cn/lite.php b/extension/lite/common/ext/lang/zh-cn/lite.php index a76704d33f..95d53abccc 100644 --- a/extension/lite/common/ext/lang/zh-cn/lite.php +++ b/extension/lite/common/ext/lang/zh-cn/lite.php @@ -139,11 +139,11 @@ $lang->doc->menuOrder[30] = 'custom'; $lang->doc->menu->project['subMenu'] = new stdclass(); $lang->doc->menu->custom['subMenu'] = new stdclass(); -$xuanxuanMenu = $lang->admin->menu->xuanxuan; +if(isset($lang->admin->menu->xuanxuan)) $xuanxuanMenu = $lang->admin->menu->xuanxuan; /* Admin menu. */ $lang->admin->menu = new stdclass(); $lang->admin->menu->index = array('link' => "$lang->indexPage|admin|index", 'alias' => 'register,certifytemail,certifyztmobile,ztcompany'); -$lang->admin->menu->xuanxuan = $xuanxuanMenu; +if(isset($xuanxuanMenu)) $lang->admin->menu->xuanxuan = $xuanxuanMenu; $lang->admin->menu->company = array('link' => "{$lang->personnel->common}|company|browse|", 'subModule' => ',user,dept,group,'); $lang->admin->menu->custom = array('link' => "{$lang->custom->common}|custom|index", 'exclude' => 'custom-browsestoryconcept,custom-timezone,custom-estimate'); $lang->admin->menu->extension = array('link' => "{$lang->extension->common}|extension|browse", 'subModule' => 'extension'); diff --git a/framework/base/control.class.php b/framework/base/control.class.php index eab88f4956..dffd81c16f 100644 --- a/framework/base/control.class.php +++ b/framework/base/control.class.php @@ -483,15 +483,6 @@ class baseControl { if(empty($cssPath)) continue; - $extModulePath = dirname(dirname($cssPath)); - if(realpath($extModulePath) != $realModulePath) - { - $extMethodCssFile = $extModulePath . DS . 'css' . DS . $devicePrefix . $methodName . '.css'; - if(is_file($extMethodCssFile)) $css .= file_get_contents($extMethodCssFile); - $extMethodCssLangFile = $extModulePath . DS . 'css' . DS . $devicePrefix . "{$methodName}.{$clientLang}.css"; - if(is_file($extMethodCssLangFile)) $css .= file_get_contents($extMethodCssLangFile); - } - $cssMethodExt = $cssPath . $methodName . DS; $cssCommonExt = $cssPath . 'common' . DS; @@ -587,13 +578,6 @@ class baseControl { if(empty($jsPath)) continue; - $extModulePath = dirname(dirname($jsPath)); - if(realpath($extModulePath) != $realModulePath) - { - $extMethodJsFile = $extModulePath . DS . 'js' . DS . $this->devicePrefix . $methodName . '.js'; - if(is_file($extMethodJsFile)) $js .= file_get_contents($extMethodJsFile); - } - $jsMethodExt = $jsPath . $methodName . DS; $jsCommonExt = $jsPath . 'common' . DS; diff --git a/framework/router.class.php b/framework/router.class.php index 72c95beca9..04d7e0cd3e 100755 --- a/framework/router.class.php +++ b/framework/router.class.php @@ -219,7 +219,13 @@ class router extends baseRouter /* Get user preference. */ $account = isset($this->session->user->account) ? $this->session->user->account : ''; $userSetting = array(); - if($this->dbh and !empty($this->config->db->name)) $userSetting = $this->dbh->query('SELECT `key`, value FROM' . TABLE_CONFIG . "WHERE `owner`='{$account}' AND `module`='common' and `key` in ('programLink', 'productLink', 'projectLink', 'executionLink', 'URSR')")->fetchAll(); + if($this->dbh and !empty($this->config->db->name) and $account) + { + $sql = new sql(); + $account = $sql->quote($account); + $userSetting = $this->dbh->query('SELECT `key`, value FROM' . TABLE_CONFIG . "WHERE `owner`= $account AND `module`='common' and `key` in ('programLink', 'productLink', 'projectLink', 'executionLink', 'URSR')")->fetchAll(); + } + foreach($userSetting as $setting) { if($setting->key == 'URSR') $config->URSR = $setting->value; diff --git a/lib/base/filter/filter.class.php b/lib/base/filter/filter.class.php index 020f440076..8db2523369 100644 --- a/lib/base/filter/filter.class.php +++ b/lib/base/filter/filter.class.php @@ -1370,23 +1370,4 @@ class baseFixer foreach($fields as $key => $fieldName) if(!isset($this->data->$fieldName)) unset($fields[$key]); return $fields; } - - /** - * 过滤Emoji表情。 - * Filter Emoji. - * - * @param string $fieldName - * @access public - * @return object - */ - public function filterEmoji($fieldName){ - $fields = $this->processFields($fieldName); - foreach($fields as $fieldName) - { - $this->data->$fieldName = preg_replace_callback('/./u', function (array $match){ - return strlen($match[0]) >= 4 ? '' : $match[0]; - }, $this->data->$fieldName); - } - return $this; - } } diff --git a/lib/filter/filter.class.php b/lib/filter/filter.class.php index 623386462c..f4e9980630 100644 --- a/lib/filter/filter.class.php +++ b/lib/filter/filter.class.php @@ -75,6 +75,7 @@ class fixer extends baseFixer } if(isset($flowFields[$field]) and ($flowFields[$field]->control == 'textarea' or $flowFields[$field]->control == 'richtext')) $this->skipSpecial($field); $this->specialChars($field); + $this->data->$field = $this->filterEmoji($value); } if(empty($fields)) return $this->data; @@ -90,4 +91,21 @@ class fixer extends baseFixer return $this->data; } + + /** + * 过滤Emoji表情。 + * Filter Emoji. + * + * @param string $value + * @access public + * @return object + */ + public function filterEmoji($value){ + $value = preg_replace_callback('/./u', function (array $match) + { + return strlen($match[0]) >= 4 ? '' : $match[0]; + }, $value); + + return $value; + } } diff --git a/module/action/config.php b/module/action/config.php index bd3143a1bc..caa2de9145 100755 --- a/module/action/config.php +++ b/module/action/config.php @@ -59,4 +59,4 @@ $config->action->majorList['execution'] = array('opened', 'edited'); $config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,'; $config->action->needGetRelateField = ',story,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,'; -$config->action->noLinkModules = ',doclib,module,webhook,gitlab,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,'; +$config->action->noLinkModules = ',doclib,module,webhook,gitlab,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,'; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 915f2e3b8d..4a908589da 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -192,6 +192,7 @@ $lang->action->desc->run = '$date, by $actor e $lang->action->desc->syncprogram = '$date, started by $actor(starting the project sets the program status as Ongoing).' . "\n"; $lang->action->desc->syncproject = '$date, starting the execution sets the project status as Ongoing.' . "\n"; $lang->action->desc->syncexecution = '$date, starting the task sets the execution status as Ongoing.' . "\n"; +$lang->action->desc->syncexecutionbychild = '$date, starting the sub stage sets the execution status as Ongoing.' . "\n"; $lang->action->desc->importfromgitlab = '$date, Issue associate created from gitlab by $actor.' . "\n"; $lang->action->desc->archived = '$date, archived by $actor.' . "\n"; $lang->action->desc->restore = '$date, restore by $actor.' . "\n"; @@ -322,6 +323,7 @@ $lang->action->label->setdefaultbranch = 'Set default branch'; $lang->action->label->syncprogram = 'start'; $lang->action->label->syncproject = 'start'; $lang->action->label->syncexecution = 'start'; +$lang->action->label->syncexecutionbychild = 'start'; $lang->action->label->startProgram = '(The start of the project sets the status of the program as Ongoing)'; $lang->action->label->createmr = 'Merge Request Linked'; $lang->action->label->deletemr = 'Merge Request Unlinked'; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index 211820ac1b..1874ef290a 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -192,6 +192,7 @@ $lang->action->desc->run = '$date, 由 $actor $lang->action->desc->syncprogram = '$date, 由 $actor 启动(因项目开始而启动项目集)。' . "\n"; $lang->action->desc->syncproject = '$date, 系统判断由于' . $lang->executionCommon .'开始,将项目状态置为进行中。' . "\n"; $lang->action->desc->syncexecution = '$date, 系统判断由于任务开始,将' . $lang->executionCommon . '状态置为进行中。' . "\n"; +$lang->action->desc->syncexecutionbychild = '$date, 系统判断由于子阶段开始,将' . $lang->executionCommon . '状态置为进行中。' . "\n"; $lang->action->desc->importfromgitlab = '$date, 由 $actor 从Gitlab的Issue关联创建。' . "\n"; $lang->action->desc->archived = '$date, 由 $actor 归档。' . "\n"; $lang->action->desc->restore = '$date, 由 $actor 还原。' . "\n"; @@ -322,6 +323,7 @@ $lang->action->label->setdefaultbranch = '设置了默认分支'; $lang->action->label->syncprogram = '开始了'; $lang->action->label->syncproject = '开始了'; $lang->action->label->syncexecution = '开始了'; +$lang->action->label->syncexecutionbychild = '开始了'; $lang->action->label->startProgram = '(因项目开始而启动项目集)'; $lang->action->label->createmr = '合并请求关联了'; $lang->action->label->deletemr = '合并请求取消了'; diff --git a/module/api/control.php b/module/api/control.php index a97c4c81cf..6c10a1a171 100755 --- a/module/api/control.php +++ b/module/api/control.php @@ -78,7 +78,7 @@ class api extends control $this->view->libID = $libID; $this->view->apiID = $apiID; $this->view->libs = $libs; - $this->view->moduleTree = $libID ? $this->doc->getApiModuleTree($libID, $apiID) : ''; + $this->view->moduleTree = $libID ? $this->doc->getApiModuleTree($libID, $apiID, $release, $moduleID) : ''; $this->view->users = $this->user->getPairs('noclosed,noletter'); $this->display(); @@ -170,6 +170,8 @@ class api extends control /** * Api doc global struct page. * + * @param int $libID + * @param int $releaseID * @param string $orderBy * @param int $recTotal * @param int $recPerPage @@ -177,25 +179,34 @@ class api extends control * @access public * @return void */ - public function struct($libID = 0, $orderBy = 'id', $recTotal = 0, $recPerPage = 15, $pageID = 1) + public function struct($libID = 0, $releaseID = 0, $orderBy = 'id', $recTotal = 0, $recPerPage = 15, $pageID = 1) { $libs = $this->doc->getApiLibs(); $this->app->loadClass('pager', $static = true); - $this->lang->modulePageNav = $this->generateLibsDropMenu($libs, $libID); + $this->lang->modulePageNav = $this->generateLibsDropMenu($libs, $libID, $releaseID); $pager = new pager($recTotal, $recPerPage, $pageID); /* Append id for secend sort. */ $sort = common::appendOrder($orderBy); - $structs = $this->api->getStructByQuery($libID, $pager, $sort); + if($releaseID) + { + $release = $this->api->getRelease($libID, 'byId', $releaseID); + $structs = $this->api->getStructListByRelease($release, '1 = 1 ', $sort); + } + else + { + $structs = $this->api->getStructByQuery($libID, $pager, $sort); + } common::setMenuVars('doc', $libID); - $this->view->libID = $libID; - $this->view->structs = $structs; - $this->view->orderBy = $orderBy; - $this->view->title = $this->lang->api->struct; - $this->view->pager = $pager; + $this->view->libID = $libID; + $this->view->releaseID = $releaseID; + $this->view->structs = $structs; + $this->view->orderBy = $orderBy; + $this->view->title = $this->lang->api->struct; + $this->view->pager = $pager; $this->display(); } @@ -319,6 +330,7 @@ class api extends control /* Record action for create api library. */ $this->action->create('docLib', $libID, 'Created'); + if(!helper::isAjaxRequest()) return print(js::locate($this->createLink('api', 'index', "libID=$libID"), 'parent.parent')); return $this->sendSuccess(array('locate' => $this->createLink('api', 'index', "libID=$libID"))); } @@ -640,6 +652,8 @@ class api extends control if(empty($libs)) return ''; if(!isset($libs[$libID])) return ''; + $methodName = $this->app->rawMethod; + $libName = $libs[$libID]->name; $output = << @@ -658,7 +672,7 @@ EOT; foreach($libs as $key => $lib) { $selected = $key == $libID ? 'selected' : ''; - $output .= html::a(inlink('index', "libID=$key"), $lib->name, '', "class='$selected' data-app='{$this->app->tab}'"); + $output .= html::a(inlink($methodName, "libID=$key"), $lib->name, '', "class='$selected' data-app='{$this->app->tab}'"); } $output .= ""; @@ -681,12 +695,13 @@ EOT;
EOT; + $params = $methodName == 'index' ? "libID=$libID&moduleID=0&apiID=0&version=0" : "libID=$libID"; $selected = $version > 0 ? '' : 'selected'; - $output .= html::a(inlink('index', "libID=$libID&moduleID=0&apiID=0&version=0&release=0"), $this->lang->api->defaultVersion, '', "class='$selected'"); + $output .= html::a(inlink($methodName, $params . "&release=0"), $this->lang->api->defaultVersion, '', "class='$selected'"); foreach($versions as $key => $item) { $selected = $key == $version ? 'selected' : ''; - $output .= html::a(inlink('index', "libID=$libID&moduleID=0&apiID=0&version=0&release=$key"), $item->version, '', "class='$selected' data-app='{$this->app->tab}'"); + $output .= html::a(inlink($methodName, $params . "&release=$key"), $item->version, '', "class='$selected' data-app='{$this->app->tab}'"); } $output .= "
"; } diff --git a/module/api/css/index.css b/module/api/css/index.css index c1d1bbac1c..0c9baf1a18 100644 --- a/module/api/css/index.css +++ b/module/api/css/index.css @@ -11,10 +11,11 @@ .main-col .doc-title {display: flex; font-size: 16px; margin-bottom: 15px;} .main-col .doc-title .title {margin: 0; line-height: 30px; font-size: 25px;} .main-col .doc-title .http-method {line-height: 27px; height: 27px; font-size: 13px; margin-right: 10px; padding: 0 10px;} -.main-col .doc-title .path {line-height: 30px; font-size: 20px; margin-right: 15px; word-wrap: break-word;} +.main-col .doc-title .path {line-height: 30px; font-size: 20px; margin-right: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;} .main-col .doc-title .info {flex: 1 1 0;} .main-col .doc-title .version a {font-size: 13px; color: #8c8c8c;} .main-col .doc-title .version .dropdown-menu a:hover {color: #ffffff;} +.main-col .doc-title .actions {min-width: 120px; display: inline-block;} .main-col .doc-title .actions a + a {margin-left: 8px;} .main-col .doc-title .actions i {font-size: 15px; color: #8c8c8c;} #content h2.title {margin: 0; font-size: 17px;} @@ -94,10 +95,22 @@ color: #a41e22; } +.detail .list-group-item a { + display: flex; + align-items: center; +} + +.detail .list-group-item .path, .detail .list-group-item .desc { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + .detail .list-group-item .path { padding-left: 10px; font-size: 14px; - color: black + color: black; + flex: 1; } .detail .list-group-item .desc { width: auto; @@ -105,6 +118,7 @@ line-height: 38px; float: right; padding-right: 10px; + max-width: 200px; } .detail .list-group-item {list-style: none; font-size: 14px; margin-bottom: 10px; line-height: 30px} .detail .list-group-item span {line-height: 30px; width: 65px;} diff --git a/module/api/css/releases.css b/module/api/css/releases.css index cf65b9cbab..24e4509c99 100644 --- a/module/api/css/releases.css +++ b/module/api/css/releases.css @@ -2,3 +2,5 @@ .c-actions {width: 60px;} tbody tr td {white-space:nowrap; overflow:hidden; text-overflow:ellipsis;} + +.m-api-releases {padding-bottom: 0px !important;} diff --git a/module/api/lang/en.php b/module/api/lang/en.php index 269484c932..20aefb7498 100644 --- a/module/api/lang/en.php +++ b/module/api/lang/en.php @@ -199,9 +199,6 @@ $lang->api->structParamsOptons = array_merge($lang->api->paramsTypeOptions, ar $lang->api->allParamsTypeOptions = array_merge($lang->api->paramsTypeOptions, $lang->api->paramsTypeCustomOptions); $lang->api->requiredOptions = array(0 => 'No', 1 => 'Yes'); -$lang->doclib = new stdclass(); -$lang->doclib->name = 'API Library Name'; - $lang->apistruct = new stdClass(); $lang->apistruct->name = 'Name'; diff --git a/module/api/lang/zh-cn.php b/module/api/lang/zh-cn.php index ce73a1bf19..e49b961316 100755 --- a/module/api/lang/zh-cn.php +++ b/module/api/lang/zh-cn.php @@ -199,9 +199,6 @@ $lang->api->structParamsOptons = array_merge($lang->api->paramsTypeOptions, ar $lang->api->allParamsTypeOptions = array_merge($lang->api->paramsTypeOptions, $lang->api->paramsTypeCustomOptions); $lang->api->requiredOptions = array(0 => '否', 1 => '是'); -$lang->doclib = new stdclass(); -$lang->doclib->name = '接口库名称'; - $lang->apistruct = new stdClass(); $lang->apistruct->name = '结构名'; diff --git a/module/api/lang/zh-tw.php b/module/api/lang/zh-tw.php index 6e33b20062..e56d998aee 100644 --- a/module/api/lang/zh-tw.php +++ b/module/api/lang/zh-tw.php @@ -199,9 +199,6 @@ $lang->api->structParamsOptons = array_merge($lang->api->paramsTypeOptions, ar $lang->api->allParamsTypeOptions = array_merge($lang->api->paramsTypeOptions, $lang->api->paramsTypeCustomOptions); $lang->api->requiredOptions = array(0 => '否', 1 => '是'); -$lang->doclib = new stdclass(); -$lang->doclib->name = '介面庫名稱'; - $lang->apistruct = new stdClass(); $lang->apistruct->name = '結構名'; diff --git a/module/api/model.php b/module/api/model.php index c9711dc67a..4296aa73d6 100644 --- a/module/api/model.php +++ b/module/api/model.php @@ -28,7 +28,9 @@ class apiModel extends model const PARAMS_TYPE_CUSTOM = 'custom'; /** - * @param object $data + * Create release. + * + * @param object $data * @access public * @return int */ @@ -339,7 +341,7 @@ class apiModel extends model } if($version) { - $fields = 'spec.*,api.id,api.product,api.lib,api.version,api.paramsExample,api.responseExample,doc.name as libName,module.name as moduleName,api.editedBy,api.editedDate'; + $fields = 'spec.*,api.id,api.product,api.lib,api.version,doc.name as libName,module.name as moduleName,api.editedBy,api.editedDate'; } else { @@ -370,7 +372,7 @@ class apiModel extends model * @access public * @return array */ - public function getApiListByRelease($release, $where = '') + public function getApiListByRelease($release, $where = '1 = 1 ') { $strJoin = array(); foreach($release->snap['apis'] as $api) @@ -483,6 +485,33 @@ class apiModel extends model ->fetchAll(); } + /** + * Get struct list by release. + * + * @param object $release + * @param string $where + * @param string $orderBy + * @access public + * @return array + */ + public function getStructListByRelease($release, $where = '1 = 1 ', $orderBy = 'id') + { + $strJoin = array(); + foreach($release->snap['structs'] as $struct) + { + $strJoin[] = "(object.id = {$struct['id']} and spec.version = {$struct['version']} )"; + } + + if($strJoin) $where .= 'and (' . implode(' or ', $strJoin) . ')'; + $list = $this->dao->select('object.lib,spec.name,spec.type,spec.desc,spec.attribute,spec.version,spec.addedBy,spec.addedDate,object.id,user.realname as addedName')->from(TABLE_APISTRUCT)->alias('object') + ->leftJoin(TABLE_APISTRUCT_SPEC)->alias('spec')->on('object.name = spec.name') + ->leftJoin(TABLE_USER)->alias('user')->on('user.account = spec.addedBy') + ->where($where) + ->orderBy($orderBy) + ->fetchAll(); + return $list; + } + /** * @param int $libID * @param string $pager @@ -677,22 +706,24 @@ class apiModel extends model private function getApiSpecByData($data) { return array( - 'doc' => $data->id, - 'module' => $data->module, - 'title' => $data->title, - 'path' => $data->path, - 'protocol' => $data->protocol, - 'method' => $data->method, - 'requestType' => $data->requestType, - 'responseType' => isset($data->responseType) ? $data->responseType : '', - 'status' => $data->status, - 'owner' => $data->owner, - 'desc' => $data->desc, - 'version' => $data->version, - 'params' => $data->params, - 'response' => $data->response, - 'addedBy' => $this->app->user->account, - 'addedDate' => helper::now(), + 'doc' => $data->id, + 'module' => $data->module, + 'title' => $data->title, + 'path' => $data->path, + 'protocol' => $data->protocol, + 'method' => $data->method, + 'requestType' => $data->requestType, + 'responseType' => isset($data->responseType) ? $data->responseType : '', + 'status' => $data->status, + 'owner' => $data->owner, + 'desc' => $data->desc, + 'version' => $data->version, + 'params' => $data->params, + 'paramsExample' => $data->paramsExample, + 'responseExample' => $data->responseExample, + 'response' => $data->response, + 'addedBy' => $this->app->user->account, + 'addedDate' => helper::now(), ); } diff --git a/module/api/view/content.html.php b/module/api/view/content.html.php index 8775d459de..0f6fe16205 100644 --- a/module/api/view/content.html.php +++ b/module/api/view/content.html.php @@ -5,7 +5,7 @@
method;?>
-
path;?>
+
path;?>
@@ -91,16 +91,17 @@ '; $field = ''; for($i = 0; $i < $level; $i++) $field .= '  '. ($i == $level-1 ? '∟' : ' ') . '  '; - $field .= $data['field']; - $str .= '' . $field . ''; - $str .= '' . zget($typeList, $data['paramsType'], '') . ''; - $require = $data['required'] ? '是' : '否'; - $str .= '' . $require . ''; - $str .= '' . $data['desc'] . ''; - $str .= ''; + $field .= $data['field']; + $str .= '' . $field . ''; + $str .= '' . zget($typeList, $data['paramsType'], '') . ''; + $str .= '' . zget($lang->api->boolList, $data['required'], '') . ''; + $str .= '' . $data['desc'] . ''; + $str .= ''; if(isset($data['children']) && count($data['children']) > 0) { $level++; @@ -115,9 +116,9 @@ api->req->name;?> - api->req->type;?> - api->req->required;?> - api->req->desc;?> + api->req->type;?> + api->req->required;?> + api->req->desc;?> params['params'] as $item) echo parseTree($item, $typeList);?> @@ -133,9 +134,9 @@ api->req->name;?> - api->req->type;?> - api->req->required;?> - api->req->desc;?> + api->req->type;?> + api->req->required;?> + api->req->desc;?> diff --git a/module/api/view/createlib.html.php b/module/api/view/createlib.html.php index 9ae2834d75..8e215817d9 100644 --- a/module/api/view/createlib.html.php +++ b/module/api/view/createlib.html.php @@ -65,17 +65,5 @@
- api->noticeAcl);?> diff --git a/module/api/view/index.html.php b/module/api/view/index.html.php index ab1e501ca2..7ac4c80c56 100644 --- a/module/api/view/index.html.php +++ b/module/api/view/index.html.php @@ -84,8 +84,8 @@ diff --git a/module/api/view/struct.html.php b/module/api/view/struct.html.php index f1983a737b..15d5f30b6c 100644 --- a/module/api/view/struct.html.php +++ b/module/api/view/struct.html.php @@ -30,7 +30,7 @@ - recTotal}&recPerPage={$pager->recPerPage}";?> + recTotal}&recPerPage={$pager->recPerPage}";?> diff --git a/module/block/view/todoblock.html.php b/module/block/view/todoblock.html.php index 070cea49f2..05772fa2fa 100644 --- a/module/block/view/todoblock.html.php +++ b/module/block/view/todoblock.html.php @@ -39,7 +39,7 @@ if(!$selfCall) die(include('./todolist.html.php'));
-
'> + '>

todo->create;?>

diff --git a/module/bug/model.php b/module/bug/model.php index c6e0d6193b..ed068e2f61 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -1408,6 +1408,49 @@ class bugModel extends model } } + /** + * Get statistic. + * + * @param int $productID + * @param string $endDate + * @param int $days + * @access public + * @return void + */ + public function getStatistic($productID = 0, $endDate = '', $days = 30) + { + $startDate = ''; + if(empty($endDate)) $endDate = date('Y-m-d'); + + $dateArr = array(); + for($day = $days - 1; $day >= 0; $day--) + { + $time = strtotime(-$day . ' day', strtotime($endDate)); + $date = date('m/d', $time); + $dateArr[$date] = new stdClass(); + $dateArr[$date]->num = 0; + $dateArr[$date]->date = $date; + + if($day == $days -1) $startDate = date('Y-m-d', $time) . ' 00:00:00'; + } + + $dateFields = ['openedDate', 'resolvedDate', 'closedDate']; + $staticData = array(); + foreach($dateFields as $field) + { + $bugCount = $this->dao->select("count(id) as num, date_format($field, '%m/%d') as date")->from(TABLE_BUG) + ->where('product')->eq($productID) + ->andWhere($field)->ne('0000-00-00 00:00:00') + ->andWhere($field)->ne('') + ->andWhere('deleted')->eq(0) + ->andWhere($field)->between($startDate, $endDate . ' 23:50:59') + ->groupBy('date') + ->fetchAll('date'); + $staticData[$field] = array_merge($dateArr, $bugCount); + } + return $staticData; + } + /** * Build search form. * diff --git a/module/common/model.php b/module/common/model.php index b3a2a78654..e9cb226a17 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -65,7 +65,8 @@ class commonModel extends model if($thisModule == 'execution') { $executionID = $objectID; - $execution = $this->dao->select('id, project')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch(); + $execution = $this->dao->select('id, project, grade, parent')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch(); + $this->syncExecutionByChild($execution); $project = $this->syncProjectStatus($execution); $this->syncProgramStatus($project); } @@ -102,7 +103,6 @@ class commonModel extends model ->andWhere('status')->eq('wait') ->orderBy('id_desc') ->fetchPairs(); - $now = helper::now(); $this->dao->update(TABLE_PROGRAM)->set('status')->eq('doing')->set('realBegan')->eq($now)->where('id')->in($waitList)->exec(); foreach($waitList as $programID) @@ -137,6 +137,34 @@ class commonModel extends model return $project; } + /** + * Set the status of the execution to which the sub execution is linked as Ongoing. + * + * @param object $execution + * @access public + * @return object $parentExecution + */ + public function syncExecutionByChild($execution) + { + if($execution->grade == 1) return false; + + $parentExecutionID = $execution->parent; + $today = helper::today(); + $parentExecution = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->eq($parentExecutionID)->fetch(); + + if($parentExecution->status == 'wait') + { + $this->dao->update(TABLE_EXECUTION) + ->set('status')->eq('doing') + ->beginIf(helper::isZeroDate($parentExecution->realBegan))->set('realBegan')->eq($today)->fi() + ->where('id')->eq($parentExecutionID) + ->exec(); + $this->loadModel('action')->create('execution', $parentExecutionID, 'syncexecutionbychild'); + } + + return $parentExecution; + } + /** * Set the status of the execution to which the task is linked as Ongoing. * diff --git a/module/custom/lang/de.php b/module/custom/lang/de.php index 2a0dbef906..c8c95b290d 100644 --- a/module/custom/lang/de.php +++ b/module/custom/lang/de.php @@ -46,7 +46,7 @@ $lang->custom->SRConcept = "SR Concept"; $lang->custom->reviewRule = 'Review Rules'; $lang->custom->switch = "Switch"; $lang->custom->oneUnit = "One {$lang->hourCommon}"; -$lang->custom->convertRelationTitle = "Please set the conversion factor of {$lang->hourCommon} to %s first"; +$lang->custom->convertRelationTitle = "Please firstly set the conversion factor from {$lang->hourCommon} to %s"; if($config->systemMode == 'new') $lang->custom->execution = 'Execution'; if($config->systemMode == 'classic' || !$config->systemMode) $lang->custom->execution = $lang->executionCommon; @@ -71,7 +71,7 @@ $lang->custom->regionMustNumber = 'The interval must be a number!'; $lang->custom->tipNotEmpty = 'The prompt can not be empty!'; $lang->custom->currencyNotEmpty = 'You have to select one currency at least.'; $lang->custom->defaultNotEmpty = 'The default currency can not be empty'; -$lang->custom->convertRelationTips = "After {$lang->hourCommon} is converted to %s, historical data will be uniformly converted to %s"; +$lang->custom->convertRelationTips = "After converting {$lang->hourCommon} to %s, the historical data will be converted uniformly to %s."; $lang->custom->saveTips = 'After clicking save, the current %s will be used as the default estimation unit'; $lang->custom->numberError = 'The interval must be greater than zero!'; diff --git a/module/custom/lang/en.php b/module/custom/lang/en.php index a9396a720d..84ffb3fb62 100644 --- a/module/custom/lang/en.php +++ b/module/custom/lang/en.php @@ -47,7 +47,7 @@ $lang->custom->SRConcept = "SR Concept"; $lang->custom->reviewRule = 'Review Rules'; $lang->custom->switch = "Switch"; $lang->custom->oneUnit = "One {$lang->hourCommon}"; -$lang->custom->convertRelationTitle = "Please set the conversion factor of {$lang->hourCommon} to %s first"; +$lang->custom->convertRelationTitle = "Please firstly set the conversion factor from {$lang->hourCommon} to %s"; $lang->custom->superReviewers = "Super Reviewer"; if($config->systemMode == 'new') $lang->custom->execution = 'Execution'; @@ -73,7 +73,7 @@ $lang->custom->regionMustNumber = 'The interval must be a number!'; $lang->custom->tipNotEmpty = 'The prompt can not be empty!'; $lang->custom->currencyNotEmpty = 'You have to select one currency at least.'; $lang->custom->defaultNotEmpty = 'The default currency can not be empty'; -$lang->custom->convertRelationTips = "After {$lang->hourCommon} is converted to %s, historical data will be uniformly converted to %s"; +$lang->custom->convertRelationTips = "After converting {$lang->hourCommon} to %s, the historical data will be converted uniformly to %s."; $lang->custom->saveTips = 'After clicking save, the current %s will be used as the default estimation unit'; $lang->custom->numberError = 'The interval must be greater than zero!'; diff --git a/module/custom/lang/fr.php b/module/custom/lang/fr.php index bf14392a75..82808282f7 100644 --- a/module/custom/lang/fr.php +++ b/module/custom/lang/fr.php @@ -46,7 +46,7 @@ $lang->custom->SRConcept = "SR Concept"; $lang->custom->reviewRule = 'Review Rules'; $lang->custom->switch = "Switch"; $lang->custom->oneUnit = "One {$lang->hourCommon}"; -$lang->custom->convertRelationTitle = "Please set the conversion factor of {$lang->hourCommon} to %s first"; +$lang->custom->convertRelationTitle = "Please firstly set the conversion factor from {$lang->hourCommon} to %s"; if($config->systemMode == 'new') $lang->custom->execution = 'Execution'; if($config->systemMode == 'classic' || !$config->systemMode) $lang->custom->execution = $lang->executionCommon; @@ -71,7 +71,7 @@ $lang->custom->regionMustNumber = 'The interval must be a number!'; $lang->custom->tipNotEmpty = 'The prompt can not be empty!'; $lang->custom->currencyNotEmpty = 'You have to select one currency at least.'; $lang->custom->defaultNotEmpty = 'The default currency can not be empty'; -$lang->custom->convertRelationTips = "After {$lang->hourCommon} is converted to %s, historical data will be uniformly converted to %s"; +$lang->custom->convertRelationTips = "After converting {$lang->hourCommon} to %s, the historical data will be converted uniformly to %s."; $lang->custom->saveTips = 'After clicking save, the current %s will be used as the default estimation unit'; $lang->custom->numberError = 'The interval must be greater than zero!'; diff --git a/module/custom/lang/vi.php b/module/custom/lang/vi.php index 3db2bbe941..2d23c34019 100644 --- a/module/custom/lang/vi.php +++ b/module/custom/lang/vi.php @@ -46,7 +46,7 @@ $lang->custom->SRConcept = "SR Concept"; $lang->custom->reviewRule = 'Review Rules'; $lang->custom->switch = "Switch"; $lang->custom->oneUnit = "One {$lang->hourCommon}"; -$lang->custom->convertRelationTitle = "Please set the conversion factor of {$lang->hourCommon} to %s first"; +$lang->custom->convertRelationTitle = "Please firstly set the conversion factor from {$lang->hourCommon} to %s"; if($config->systemMode == 'new') $lang->custom->execution = 'Execution'; if($config->systemMode == 'classic' || !$config->systemMode) $lang->custom->execution = $lang->executionCommon; @@ -71,7 +71,7 @@ $lang->custom->regionMustNumber = 'The interval must be a number!'; $lang->custom->tipNotEmpty = 'The prompt can not be empty!'; $lang->custom->currencyNotEmpty = 'You have to select one currency at least.'; $lang->custom->defaultNotEmpty = 'The default currency can not bu empty'; -$lang->custom->convertRelationTips = "After {$lang->hourCommon} is converted to %s, historical data will be uniformly converted to %s"; +$lang->custom->convertRelationTips = "After converting {$lang->hourCommon} to %s, the historical data will be converted uniformly to %s."; $lang->custom->saveTips = 'After clicking save, the current %s will be used as the default estimation unit'; $lang->custom->numberError = 'The interval must be greater than zero!'; diff --git a/module/doc/control.php b/module/doc/control.php index e4dd5e20ba..362d8e7ef4 100644 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -171,6 +171,8 @@ class doc extends control if(empty($projects)) unset($libTypeList['project']); if(empty($executions)) unset($libTypeList['execution']); + $this->app->loadLang('api'); + $this->view->groups = $this->loadModel('group')->getPairs(); $this->view->users = $this->user->getPairs('nocode|noclosed'); $this->view->products = $products; diff --git a/module/doc/js/common.js b/module/doc/js/common.js index 13d5973f69..48edfdbc1d 100644 --- a/module/doc/js/common.js +++ b/module/doc/js/common.js @@ -42,7 +42,7 @@ function toggleAcl(acl, type) var notice = typeof(noticeAcl[libType][acl]) != 'undefined' ? noticeAcl[libType][acl] : ''; $('#noticeAcl').html(notice); - if(libType == 'custom' && acl == 'private') $('#whiteListBox').addClass('hidden'); + if((libType == 'custom' || libType == 'api') && acl == 'private') $('#whiteListBox').addClass('hidden'); if(libType == 'project' && typeof(doclibID) != 'undefined') { diff --git a/module/doc/js/createlib.js b/module/doc/js/createlib.js index 9867c1de4e..109cb8c86a 100644 --- a/module/doc/js/createlib.js +++ b/module/doc/js/createlib.js @@ -29,6 +29,14 @@ function changeByLibType(libType) $('table tr.execution').addClass('hidden'); $('#execution').attr('disabled', true); + $('.normalLib').removeClass('hidden'); + $('.normalLib input').attr('disabled', false); + + $('table tr.apilib').addClass('hidden'); + $('.apilib input, #desc, #baseUrl').attr('disabled', true); + + $('form').removeAttr('action'); + changeDoclibAcl(libType); } else if(libType == 'project') @@ -42,6 +50,14 @@ function changeByLibType(libType) $('table tr.execution').addClass('hidden'); $('#execution').attr('disabled', true); + $('.normalLib').removeClass('hidden'); + $('.normalLib input').attr('disabled', false); + + $('table tr.apilib').addClass('hidden'); + $('.apilib input, #desc, #baseUrl').attr('disabled', true); + + $('form').removeAttr('action'); + changeDoclibAcl(libType); } else if(libType == 'execution') @@ -55,6 +71,35 @@ function changeByLibType(libType) $('table tr.project').addClass('hidden'); $('#project').attr('disabled', true); + $('.normalLib').removeClass('hidden'); + $('.normalLib input').attr('disabled', false); + + $('table tr.apilib').addClass('hidden'); + $('.apilib input, #desc, #baseUrl').attr('disabled', true); + + $('form').removeAttr('action'); + + changeDoclibAcl(libType); + } + else if(libType == 'api') + { + $('table tr.product').addClass('hidden'); + $('#product').attr('disabled', true); + + $('table tr.project').addClass('hidden'); + $('#project').attr('disabled', true); + + $('table tr.execution').addClass('hidden'); + $('#execution').attr('disabled', true); + + $('.normalLib').addClass('hidden'); + $('.normalLib input').attr('disabled', true); + + $('table tr.apilib').removeClass('hidden'); + $('.apilib input, #desc, #baseUrl').attr('disabled', false); + + $('form').attr('action', createLink('api', 'createLib')); + changeDoclibAcl(libType); } else @@ -68,6 +113,14 @@ function changeByLibType(libType) $('table tr.execution').addClass('hidden'); $('#execution').attr('disabled', true); + $('.normalLib').removeClass('hidden'); + $('.normalLib input').attr('disabled', false); + + $('table tr.apilib').addClass('hidden'); + $('.apilib input, #desc, #baseUrl').attr('disabled', true); + + $('form').removeAttr('action'); + changeDoclibAcl(libType); } diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 7fa62b2cd8..8dd3708511 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -158,6 +158,7 @@ $lang->doc->allExecutions = 'All' . $lang->executionCommon . 's'; $lang->doc->libTypeList['product'] = $lang->productCommon . ' Library'; if($config->systemMode == 'new') $lang->doc->libTypeList['project'] = 'Project Library'; $lang->doc->libTypeList['execution'] = $lang->execution->common . ' Library'; +$lang->doc->libTypeList['api'] = 'API Library'; $lang->doc->libTypeList['custom'] = 'Custom Library'; $lang->doc->libGlobalList['api'] = 'Api Libray'; @@ -248,6 +249,9 @@ $lang->doc->noticeAcl['lib']['project']['private'] = 'Users who can access the $lang->doc->noticeAcl['lib']['project']['custom'] = 'Users in the whiltelist can access it.'; $lang->doc->noticeAcl['lib']['execution']['default'] = "Users who can access the selected {$lang->executionCommon} can access it."; $lang->doc->noticeAcl['lib']['execution']['custom'] = "Users who can access the selected {$lang->executionCommon} or users in the whiltelist can access it."; +$lang->doc->noticeAcl['lib']['api']['open'] = 'All users can access it.'; +$lang->doc->noticeAcl['lib']['api']['custom'] = 'Users in the whitelist can access it.'; +$lang->doc->noticeAcl['lib']['api']['private'] = 'Only the one who created it can access it.'; $lang->doc->noticeAcl['lib']['custom']['open'] = 'All users can access it.'; $lang->doc->noticeAcl['lib']['custom']['custom'] = 'Users in the whitelist can access it.'; $lang->doc->noticeAcl['lib']['custom']['private'] = 'Only the one who created it can access it.'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index c850ff1b94..ff69f8c514 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -21,6 +21,7 @@ $lang->doclib->execution = $lang->executionCommon . '库'; $lang->doclib->product = $lang->productCommon . '库'; $lang->doclib->apiLibName = '接口库名称'; +$lang->doclib->aclListA = array(); $lang->doclib->aclListA['default'] = '默认'; $lang->doclib->aclListA['custom'] = '自定义'; @@ -158,6 +159,7 @@ $lang->doc->allExecutions = '所有' . $lang->executionCommon; $lang->doc->libTypeList['product'] = $lang->productCommon . '文档库'; if($config->systemMode == 'new') $lang->doc->libTypeList['project'] = '项目文档库'; $lang->doc->libTypeList['execution'] = $lang->execution->common . '文档库'; +$lang->doc->libTypeList['api'] = '接口库'; $lang->doc->libTypeList['custom'] = '自定义文档库'; $lang->doc->libGlobalList['api'] = '接口文档库'; @@ -248,6 +250,9 @@ $lang->doc->noticeAcl['lib']['project']['private'] = "有所选项目访问权 $lang->doc->noticeAcl['lib']['project']['custom'] = "白名单的用户可以访问。"; $lang->doc->noticeAcl['lib']['execution']['default'] = "有所选{$lang->executionCommon}访问权限的用户可以访问。"; $lang->doc->noticeAcl['lib']['execution']['custom'] = "有所选{$lang->executionCommon}访问权限或白名单里的用户可以访问。"; +$lang->doc->noticeAcl['lib']['api']['open'] = '所有人都可以访问。'; +$lang->doc->noticeAcl['lib']['api']['custom'] = '白名单的用户可以访问。'; +$lang->doc->noticeAcl['lib']['api']['private'] = '只有创建者自己可以访问。'; $lang->doc->noticeAcl['lib']['custom']['open'] = '所有人都可以访问。'; $lang->doc->noticeAcl['lib']['custom']['custom'] = '白名单的用户可以访问。'; $lang->doc->noticeAcl['lib']['custom']['private'] = '只有创建者自己可以访问。'; diff --git a/module/doc/model.php b/module/doc/model.php index fb7135f2fd..76a9a7362f 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -89,6 +89,18 @@ class docModel extends model $products = $this->loadModel('product')->getPairs(); $projects = $this->loadModel('project')->getPairsByProgram(); $executions = $this->loadModel('execution')->getPairs(); + $waterfalls = array(); + if(empty($objectID) and ($type == 'all' or $type == 'execution')) + { + $waterfalls = $this->dao->select('t1.id,t2.name')->from(TABLE_EXECUTION)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id') + ->where('t1.type')->eq('stage') + ->andWhere('t2.type')->eq('project') + ->andWhere('t2.model')->eq('waterfall') + ->andWhere('t1.deleted')->eq('0') + ->andWhere('t2.deleted')->eq('0') + ->fetchPairs('id', 'name'); + } $libPairs = array(); while($lib = $stmt->fetch()) @@ -102,8 +114,12 @@ class docModel extends model if(strpos($extra, 'withObject') !== false) { if($lib->product != 0) $lib->name = zget($products, $lib->product, '') . ' / ' . $lib->name; - if($lib->execution != 0) $lib->name = zget($executions, $lib->execution, '') . ' / ' . $lib->name; if($lib->project != 0) $lib->name = zget($projects, $lib->project, '') . ' / ' . $lib->name; + if($lib->execution != 0) + { + $lib->name = zget($executions, $lib->execution, '') . ' / ' . $lib->name; + if(!empty($waterfalls[$lib->execution])) $lib->name = $waterfalls[$lib->execution] . ' / ' . $lib->name; + } } $libPairs[$lib->id] = $lib->name; @@ -2251,9 +2267,14 @@ EOT; /** * Get api doc module tree * - * @author thanatos thanatos915@163.com + * @param int $rootID + * @param pointer $docID + * @param int $release + * @param int $moduleID + * @access public + * @return string */ - public function getApiModuleTree($rootID, &$docID = 0, $release = 0) + public function getApiModuleTree($rootID, &$docID = 0, $release = 0, $moduleID = 0) { $startModulePath = ''; $currentMethod = $this->app->getMethodName(); @@ -2262,7 +2283,7 @@ EOT; if($release) { - $rel = $this->api->getReleaseById($release); + $rel = $this->api->getRelease($rootID, 'byId', $release); $docs = $this->api->getApiListByRelease($rel); } else @@ -2283,9 +2304,9 @@ EOT; $treeMenu = array(); if($release) { - foreach($release->snap['modules'] as $module) + foreach($rel->snap['modules'] as $module) { - $this->buildTree($treeMenu, 'api', 0, $rootID, $module, $moduleDocs, $docID); + $this->buildTree($treeMenu, 'api', 0, $rootID, $module, $moduleDocs, $docID, $moduleID); } } else @@ -2300,7 +2321,7 @@ EOT; $stmt = $this->dbh->query($query); while ($module = $stmt->fetch()) { - $this->buildTree($treeMenu, 'api', 0, $rootID, $module, $moduleDocs, $docID); + $this->buildTree($treeMenu, 'api', 0, $rootID, $module, $moduleDocs, $docID, $moduleID); } } @@ -2429,10 +2450,11 @@ EOT; * @param object $module * @param array $moduleDocs * @param pointer $docID + * @param int $moduleID * @access private * @return string */ - private function buildTree(&$treeMenu, $type, $objectID, $libID, $module, $moduleDocs, &$docID) + private function buildTree(&$treeMenu, $type, $objectID, $libID, $module, $moduleDocs, &$docID, $moduleID = 0) { if(!isset($treeMenu[$module->id])) $treeMenu[$module->id] = ''; @@ -2467,7 +2489,7 @@ EOT; if(common::hasPriv('doc', 'edit')) { $treeMenu[$module->id] .= "
"; - $treeMenu[$module->id] .= html::a(helper::createLink('doc', 'edit', "docID=$docID&comment=false&objectType=$type&objectID=$objectID&libID=$libID"), "", '', "title={$this->lang->doc->edit} data-app={$this->app->tab}"); + $treeMenu[$module->id] .= html::a(helper::createLink('doc', 'edit', "docID={$doc->id}&comment=false&objectType=$type&objectID=$objectID&libID=$libID"), "", '', "title={$this->lang->doc->edit} data-app={$this->app->tab}"); $treeMenu[$module->id] .= '
'; } $treeMenu[$module->id] .= '
'; @@ -2520,9 +2542,7 @@ EOT; if($type == static::DOC_TYPE_API) { - $params = $_GET; - $moduleID = isset($params['moduleID']) ? $params['moduleID'] : 0; - if($moduleID && $moduleID == $module->id) + if($moduleID and $moduleID == $module->id) { array_push($class, 'active'); } diff --git a/module/doc/view/createlib.html.php b/module/doc/view/createlib.html.php index f9c701c3af..b0a84345ee 100644 --- a/module/doc/view/createlib.html.php +++ b/module/doc/view/createlib.html.php @@ -19,7 +19,7 @@

doc->createLib;?>

- +
idAB);?> api->structType);?> api->structName;?>
@@ -45,10 +45,18 @@ - + + + + + + + + + + + + + diff --git a/module/execution/control.php b/module/execution/control.php index ed7f16616a..25f8e63cb8 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -3587,7 +3587,7 @@ class execution extends control if($execution->type == 'project') { $moduleName = 'projectstory'; - $param = "projectID=$executionID"; + $param = "projectID=$executionID&productID=$productID"; } if($execution->type == 'kanban') @@ -3596,7 +3596,7 @@ class execution extends control $lang->executionCommon = $lang->execution->kanban; include $this->app->getModulePath('', 'execution') . 'lang/' . $this->app->getClientLang() . '.php'; } - if($count != 0) echo js::alert(sprintf($this->lang->execution->haveDraft, $count)) . js::locate($this->createLink($moduleName, $execution->type == 'sprint' ? 'story' : 'kanban', $param)); + if($count != 0) echo js::alert(sprintf($this->lang->execution->haveDraft, $count)) . js::locate($this->createLink($moduleName, in_array($execution->type, array('sprint','project')) ? 'story' : 'kanban', $param)); return print(js::locate(helper::createLink($moduleName, $fromMethod, $param))); } diff --git a/module/extension/css/obtain.css b/module/extension/css/obtain.css index 00a2b3495f..5ee32db932 100644 --- a/module/extension/css/obtain.css +++ b/module/extension/css/obtain.css @@ -1,3 +1,5 @@ .pager {margin-top: 0;} .tree li>a:hover {color: #fff; background-color: #0c64eb;} .tree li>a.active {color: #fff; background-color: #0c64eb;} +.side-col {width: 210px;} +#sidebar .cell {width: 190px;} diff --git a/module/install/control.php b/module/install/control.php index 6cff26c16d..a6484ec6f3 100644 --- a/module/install/control.php +++ b/module/install/control.php @@ -206,13 +206,13 @@ class install extends control if(!empty($_POST)) { $this->install->grantPriv(); - if(dao::isError()) return print(js::error(dao::getError())); + if(dao::isError()) return print(js::error(dao::getError()) . js::locate('back')); $this->install->updateLang(); - if(dao::isError()) return print(js::error(dao::getError())); + if(dao::isError()) return print(js::error(dao::getError()) . js::locate('back')); if($this->post->importDemoData) $this->install->importDemoData(); - if(dao::isError()) echo js::alert($this->lang->install->errorImportDemoData); + if(dao::isError()) return print(js::alert($this->lang->install->errorImportDemoData) . js::locate('back')); $this->loadModel('setting'); $this->setting->updateVersion($this->config->version); diff --git a/module/install/js/step5.js b/module/install/js/step5.js new file mode 100644 index 0000000000..66eaff6a09 --- /dev/null +++ b/module/install/js/step5.js @@ -0,0 +1,21 @@ +$(function() +{ + $('#submit').click(function() + { + if($('#company').val().length == 0) + { + alert(errorEmpty.company); + return false; + } + else if($('#account').val().length == 0) + { + alert(errorEmpty.account); + return false; + } + else if($('#password').val().length == 0) + { + alert(errorEmpty.password); + return false; + } + }) +}) diff --git a/module/install/view/step5.html.php b/module/install/view/step5.html.php index 580de09650..686b740b81 100644 --- a/module/install/view/step5.html.php +++ b/module/install/view/step5.html.php @@ -10,6 +10,7 @@ */ ?> +install->errorEmpty);?>
doc->libType?>doc->execution?>
doclib->name?>
doclib->control;?> @@ -69,6 +77,12 @@
diff --git a/module/job/model.php b/module/job/model.php index 00d56de7d3..f88120da2a 100644 --- a/module/job/model.php +++ b/module/job/model.php @@ -248,7 +248,8 @@ class jobModel extends model $this->dao->insert(TABLE_JOB)->data($job) ->batchCheck($this->config->job->create->requiredFields, 'notempty') - ->batchCheckIF($job->triggerType === 'schedule', "atDay,atTime", 'notempty') + ->batchCheckIF($job->triggerType === 'schedule' and $job->atDay !== '0', "atDay", 'notempty') + ->batchCheckIF($job->triggerType === 'schedule', "atTime", 'notempty') ->batchCheckIF($job->triggerType === 'commit', "comment", 'notempty') ->batchCheckIF(($this->post->repoType == 'Subversion' and $job->triggerType == 'tag'), "svnDir", 'notempty') ->batchCheckIF($job->frame === 'sonarqube', "sonarqubeServer,projectKey", 'notempty') @@ -366,7 +367,8 @@ class jobModel extends model $this->dao->update(TABLE_JOB)->data($job) ->batchCheck($this->config->job->edit->requiredFields, 'notempty') - ->batchCheckIF($job->triggerType === 'schedule', "atDay,atTime", 'notempty') + ->batchCheckIF($job->triggerType === 'schedule' and $job->atDay !== '0', "atDay", 'notempty') + ->batchCheckIF($job->triggerType === 'schedule', "atTime", 'notempty') ->batchCheckIF($job->triggerType === 'commit', "comment", 'notempty') ->batchCheckIF(($this->post->repoType == 'Subversion' and $job->triggerType == 'tag'), "svnDir", 'notempty') ->batchCheckIF($job->frame === 'sonarqube', "sonarqubeServer,projectKey", 'notempty') diff --git a/module/mr/view/browse.html.php b/module/mr/view/browse.html.php index 304fc22f80..056075e64d 100644 --- a/module/mr/view/browse.html.php +++ b/module/mr/view/browse.html.php @@ -51,16 +51,16 @@
install->company;?>
- + recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?> - - - - - - - - + + + + + + + + diff --git a/module/my/control.php b/module/my/control.php index ec90460d6b..4738673f24 100644 --- a/module/my/control.php +++ b/module/my/control.php @@ -174,7 +174,7 @@ class my extends control $reviewCount = $pager->recTotal; /* Get the number of nc assigned to me. */ - $ncList = $this->my->getNcList('assignedToMe', 'id_desc', $pager); + $ncList = $this->my->getNcList('assignedToMe', 'id_desc', $pager, 'active'); $ncCount = $pager->recTotal; /* Get the number of meetings assigned to me. */ diff --git a/module/program/css/project.css b/module/program/css/project.css index 499e53ecc1..22392a5722 100644 --- a/module/program/css/project.css +++ b/module/program/css/project.css @@ -1,3 +1,4 @@ .project-type-label.label-outline {width: 50px; min-width: 50px;} .project-type-label.label {overflow: unset !important; text-overflow: unset !important; white-space: unset !important;} [lang^='en'] .project-name > .label-warning {width: 55px !important;} +#projectTableList > tr > td.c-name.text-left > div > a {color: #0c60e1;} diff --git a/module/programplan/model.php b/module/programplan/model.php index 3f522166b4..8d5e94cab6 100644 --- a/module/programplan/model.php +++ b/module/programplan/model.php @@ -775,11 +775,15 @@ class programplanModel extends model if($planChanged) $plan->version = $oldPlan->version + 1; if(empty($plan->parent)) $plan->parent = $projectID; + /* Fix bug #22030. Reset field name for show dao error. */ + $this->lang->project->name = $this->lang->programplan->name; + $this->dao->update(TABLE_PROJECT)->data($plan) ->autoCheck() ->batchCheck($this->config->programplan->edit->requiredFields, 'notempty') ->checkIF($plan->end != '0000-00-00', 'end', 'ge', $plan->begin) ->checkIF($plan->percent != false, 'percent', 'float') + ->checkIF((!empty($plan->name) and $this->config->systemMode == 'new'), 'name', 'unique', "id != {$planID} and type in ('sprint','stage') and `project` = {$oldPlan->project}") ->where('id')->eq($planID) ->exec(); @@ -920,6 +924,8 @@ class programplanModel extends model */ public function isCreateTask($planID) { + if(empty($planID)) return true; + $task = $this->dao->select('*')->from(TABLE_TASK)->where('execution')->eq($planID)->andWhere('deleted')->eq('0')->limit(1)->fetch(); return empty($task) ? true : false; } diff --git a/module/project/model.php b/module/project/model.php index adacde8868..cbcc0a2ce5 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -415,7 +415,7 @@ class projectModel extends model $workhour = new stdclass(); $workhour->totalHours = $this->dao->select('sum(t1.days * t1.hours) AS totalHours')->from(TABLE_TEAM)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.root=t2.id') - ->where('t2.project')->in($projectID) + ->where('t2.id')->in($projectID) ->andWhere('t2.deleted')->eq(0) ->andWhere('t1.type')->eq('project') ->fetch('totalHours'); diff --git a/module/project/view/browsebycard.html.php b/module/project/view/browsebycard.html.php index 5de6a42787..10e46fb71a 100644 --- a/module/project/view/browsebycard.html.php +++ b/module/project/view/browsebycard.html.php @@ -143,14 +143,15 @@
teamMembers)):?> diff --git a/module/repo/css/common.css b/module/repo/css/common.css index be0378342c..7d19921566 100644 --- a/module/repo/css/common.css +++ b/module/repo/css/common.css @@ -189,3 +189,5 @@ h3 {font-size: 16px;} #submitLabel {text-align: left;} .header-btn .btn > .text {text-overflow: unset !important;} + +#repoPageSize {right: 90px;} diff --git a/module/repo/model.php b/module/repo/model.php index 9575a12c48..dad33fcd20 100644 --- a/module/repo/model.php +++ b/module/repo/model.php @@ -57,7 +57,7 @@ class repoModel extends model } common::setMenuVars('devops', $repoID); - if(!session_id()) session_start(); + session_start(); $this->session->set('repoID', $repoID); session_write_close(); } diff --git a/module/repo/view/ajaxsidecommits.html.php b/module/repo/view/ajaxsidecommits.html.php index 203609b6b6..a02814a37d 100644 --- a/module/repo/view/ajaxsidecommits.html.php +++ b/module/repo/view/ajaxsidecommits.html.php @@ -14,6 +14,7 @@ $pathInfo = '&root=' . $this->repo->encodePath(empty($path) ? '/' : $path); if(isset($entry)) $pathInfo .= '&type=file'; ?> +repo->encodePath($path) . "&objectID=$objectID&type=$logType");?>
mr->id);?>mr->title);?>mr->sourceBranch);?>mr->targetBranch);?>mr->mergeStatus);?>mr->approvalStatus);?>mr->author);?>actions;?>mr->id);?>mr->title);?>mr->sourceBranch);?>mr->targetBranch);?>mr->mergeStatus);?>mr->approvalStatus);?>mr->author);?>actions;?>
@@ -52,6 +53,7 @@ if(isset($entry)) $pathInfo .= '&type=file'; repo->diff, '', count($revisions) < 2 ? 'disabled btn btn-primary' : 'btn btn-primary')?> repo->createLink('log', "repoID=$repoID&objectID=$objectID&entry=" . $this->repo->encodePath($path) . "&revision=HEAD&type=$logType"), $lang->repo->allLog, '', "class='allLogs' data-app='{$this->app->tab}'");?>
+
    pageID == 1 ? 1 : $pager->pageID - 1; @@ -84,4 +86,15 @@ $("input:checkbox[name='revision[]']").click(function(){ $("input:checkbox[name='revision[]']").each(function(){$(this).attr("disabled", false)}); } }); + +$(function() +{ + var myPager = $('#repoPageSize').data('zui.pager'); + if(!myPager) $('#repoPageSize').pager(); + + $('#repoPageSize').on('onPageChange', function(e, state, oldState) { + var link = createLink('repo', 'ajaxSideCommits', paramsBase + '&recTotal=' + state.recTotal + '&recPerPage=' + state.recPerPage + '&pageID=' + state.page); + $('#sidebar .side-body').load(link); + }); +}); diff --git a/module/report/control.php b/module/report/control.php index 18b4576200..d39d43779b 100644 --- a/module/report/control.php +++ b/module/report/control.php @@ -57,8 +57,8 @@ class report extends control { $this->session->set('executionList', $this->app->getURI(true), 'execution'); - $begin = $begin ? date('Y-m-d', strtotime($begin)) : ''; - $end = $end ? date('Y-m-d', strtotime($end)) : ''; + $begin = date('Y-m-d', ($begin ? strtotime($begin) : time() - (date('j') - 1) * 24 * 3600)); + $end = date('Y-m-d', ($end ? strtotime($end) : time() + (date('t') - date('j')) * 24 * 3600)); $this->view->title = $this->lang->report->projectDeviation; $this->view->position[] = $this->lang->report->projectDeviation; diff --git a/module/story/model.php b/module/story/model.php index 6a2c663f90..e11a7464b3 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -1732,7 +1732,16 @@ class storyModel extends model if($oldStory->branch) $story->plan = $planID; /* Append the plan id to plan field if product is multi and story is all branch. */ - if($this->session->currentProductType != 'normal' and empty($story->branch) and $planID != 0) $story->plan = $oldStory->plan ? $oldStory->plan . ",$planID" : ",$planID"; + if($this->session->currentProductType != 'normal' and empty($story->branch) and $planID != 0) + { + $branchPlanPairs = $this->dao->select('branch, id as plan')->from(TABLE_PRODUCTPLAN) + ->where('product')->eq($oldStory->product) + ->andWhere('id')->in($oldStory->plan) + ->fetchPairs(); + if(isset($branchPlanPairs[$plan->branch])) $branchPlanPairs[$plan->branch] = $planID; + + $story->plan = $oldStory->plan ? ',' . implode(',', $branchPlanPairs) : ",$planID"; + } /* Change stage. */ if($planID) @@ -2807,6 +2816,7 @@ class storyModel extends model ->where($storyQuery) ->andWhere('t1.project')->eq((int)$executionID) ->andWhere('t2.deleted')->eq(0) + ->andWhere('t4.deleted')->eq(0) ->andWhere('t2.type')->eq($storyType) ->beginIF($excludeStories)->andWhere('t2.id')->notIN($excludeStories)->fi() ->orderBy($orderBy) @@ -2862,6 +2872,7 @@ class storyModel extends model ->beginIF($this->session->storyBrowseType and strpos('changed|', $this->session->storyBrowseType) !== false)->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi() ->beginIF($modules)->andWhere('t2.module')->in($modules)->fi() ->andWhere('t2.deleted')->eq(0) + ->andWhere('t4.deleted')->eq(0) ->orderBy($orderBy) ->page($pager, 't2.id') ->fetchAll('id'); diff --git a/module/story/view/track.html.php b/module/story/view/track.html.php index e5b53e557d..54c5a4aea8 100644 --- a/module/story/view/track.html.php +++ b/module/story/view/track.html.php @@ -41,18 +41,6 @@
    - app->rawModule == 'projectstory'): ?> - - edition == 'max'):?> diff --git a/module/task/config.php b/module/task/config.php index e79127ec59..ac1b91dcd0 100644 --- a/module/task/config.php +++ b/module/task/config.php @@ -78,7 +78,7 @@ $config->task->datatable->fieldList['status']['width'] = '60'; $config->task->datatable->fieldList['status']['required'] = 'no'; $config->task->datatable->fieldList['estimate']['title'] = 'estimateAB'; -$config->task->datatable->fieldList['estimate']['fixed'] = 'right'; +$config->task->datatable->fieldList['estimate']['fixed'] = 'no'; $config->task->datatable->fieldList['estimate']['width'] = '60'; $config->task->datatable->fieldList['estimate']['required'] = 'no'; diff --git a/module/task/control.php b/module/task/control.php index 0f888f65c2..cc7f11ce6c 100644 --- a/module/task/control.php +++ b/module/task/control.php @@ -44,7 +44,7 @@ class task extends control $extra = str_replace(array(',', ' '), array('&', ''), $extra); parse_str($extra, $output); - $executions = $this->execution->getPairs(0, 'all', !common::checkNotCN() ? 'noclosed' : ''); + $executions = $this->execution->getPairs(0, 'all', 'noclosed'); $executionID = $this->execution->saveState($executionID, $executions); $this->execution->setMenu($executionID); diff --git a/module/testcase/css/create.css b/module/testcase/css/create.css index 7e1773ae69..9371649ca7 100644 --- a/module/testcase/css/create.css +++ b/module/testcase/css/create.css @@ -41,4 +41,3 @@ .pri-selector > .btn {padding: 5px 8px !important; width: 100%;} .pri-selector > .dropdown-menu {padding: 10px;} -.title-group .has-icon-right {min-width: 600px;} diff --git a/module/testcase/model.php b/module/testcase/model.php index 4bd0abe109..440db17d21 100644 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -72,7 +72,7 @@ class testcaseModel extends model $parentStepID = 0; $this->loadModel('score')->create('testcase', 'create', $caseID); - $data = fixer::input('post')->filterEmoji('steps,expects')->get(); + $data = fixer::input('post')->get(); foreach($data->steps as $stepID => $stepDesc) { if(empty($stepDesc)) continue; @@ -759,7 +759,7 @@ class testcaseModel extends model /* Ignore steps when post has no steps. */ if($this->post->steps) { - $data = fixer::input('post')->filterEmoji('steps,expects')->get(); + $data = fixer::input('post')->get(); foreach($data->steps as $stepID => $stepDesc) { diff --git a/module/todo/control.php b/module/todo/control.php index 1643aa1001..4705e05c8b 100644 --- a/module/todo/control.php +++ b/module/todo/control.php @@ -490,7 +490,7 @@ class todo extends control if($todo->type == 'story') $app = 'product'; $cancelURL = $this->server->HTTP_REFERER; if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success', 'message' => sprintf($this->lang->todo->$confirmNote, $todo->idvalue), 'locate' => $confirmURL)); - return print(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, $okTarget, 'parent', $app)); + return print(strpos($cancelURL, 'calendar') ? json_encode(array(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL)) : js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, $okTarget, 'parent', $app)); } if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success')); if(isonlybody()) return print(js::reload('parent.parent')); diff --git a/module/user/model.php b/module/user/model.php index 48391ea0bd..58374690d1 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -2700,7 +2700,7 @@ class userModel extends model $personalData['createdStories'] = $this->dao->select($count)->from(TABLE_STORY)->where('openedBy')->eq($account)->andWhere('deleted')->eq('0')->andWhere('type')->eq('story')->fetch('count'); $personalData['createdBugs'] = $this->dao->select($count)->from(TABLE_BUG)->where('openedBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count'); $personalData['resolvedBugs'] = $this->dao->select($count)->from(TABLE_BUG)->where('resolvedBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count'); - $personalData['createdCases'] = $this->dao->select($count)->from(TABLE_CASE)->where('openedBy')->eq($account)->andWhere('deleted')->eq('0')->andWhere('product')->ne(0)->fetch('count'); + $personalData['createdCases'] = $this->dao->select($count)->from(TABLE_CASE)->where('openedBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count'); if($this->config->edition == 'max') { $personalData['createdRisks'] = $this->dao->select($count)->from(TABLE_RISK)->where('createdBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count'); diff --git a/module/user/view/deny.html.php b/module/user/view/deny.html.php index ec98a85722..4f5dee48da 100644 --- a/module/user/view/deny.html.php +++ b/module/user/view/deny.html.php @@ -38,7 +38,7 @@ include '../../common/view/header.lite.html.php'; if($denyType == 'noview') { - $menuName = $menu; + $menuName = isset($lang->$menu->common) ? $lang->$module->common : $menu; if(isset($lang->menu->$menu))list($menuName) = explode('|', $lang->menu->$menu); printf($lang->user->errorView, $menuName); } diff --git a/module/weekly/model.php b/module/weekly/model.php old mode 100644 new mode 100755 index cc36f392aa..14c4cc7287 --- a/module/weekly/model.php +++ b/module/weekly/model.php @@ -427,6 +427,7 @@ class weeklyModel extends model ->from(TABLE_TASK) ->where('execution')->in($executionIdList) ->andWhere('consumed')->gt(0) + ->andWhere("(estStarted < '$nextMonday' or estStarted='0000-00-00')") ->andWhere('status')->ne('cancel') ->fetchAll('id'); @@ -466,13 +467,12 @@ class weeklyModel extends model $executions = $this->loadModel('execution')->getList($project, 'all', 'all', 0, 0, 0); $executionIdList = array_keys($executions); - if($this->config->edition == 'max') + if($this->config->edition != 'open') { $AC = $this->dao->select('sum(consumed) as consumed') ->from(TABLE_EFFORT) ->where('objectType')->eq('task') ->andWhere('execution')->in($executionIdList) - ->andWhere('date')->ge($monday) ->andWhere('date')->lt($nextMonday) ->fetch('consumed'); } @@ -482,7 +482,6 @@ class weeklyModel extends model $AC = $this->dao->select('sum(consumed) as consumed') ->from(TABLE_TASKESTIMATE) ->where('task')->in($taskIdList) - ->andWhere('date')->ge($monday) ->andWhere('date')->lt($nextMonday) ->fetch('consumed'); } diff --git a/xuanxuan/extension/xuan/client/ext/view/browse.html.php b/xuanxuan/extension/xuan/client/ext/view/browse.html.php index 8810feb46e..18567b875d 100644 --- a/xuanxuan/extension/xuan/client/ext/view/browse.html.php +++ b/xuanxuan/extension/xuan/client/ext/view/browse.html.php @@ -51,14 +51,16 @@ $position[] = $this->lang->client->browse;
    story->story;?>> - - story->tasks;?> story->design;?>
    +config->edition == 'open'):?> + getModuleRoot() . 'common/view/footer.html.php';?>