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/VERSION b/VERSION index dafb659a69..dddffdec10 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -15.2 +15.3 diff --git a/api/v1/entries/bugs.php b/api/v1/entries/bugs.php index 70a31c67b2..93729e30ee 100644 --- a/api/v1/entries/bugs.php +++ b/api/v1/entries/bugs.php @@ -11,7 +11,7 @@ class bugsEntry extends entry public function get($productID) { $control = $this->loadController('bug', 'browse'); - $control->browse($productID); + $control->browse($productID, $this->param('branch', ''), $this->param('status', ''), 0, $this->param('order', ''), 0, $this->param('limit', 20), $this->param('page', 1)); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') diff --git a/api/v1/entries/executions.php b/api/v1/entries/executions.php index 03660142bb..c994ac729d 100644 --- a/api/v1/entries/executions.php +++ b/api/v1/entries/executions.php @@ -11,7 +11,7 @@ class executionsEntry extends entry public function get($projectID = 0) { $control = $this->loadController('execution', 'all'); - $control->all($this->param('status', 'all'), $this->param('project', $projectID)); + $control->all($this->param('status', 'all'), $this->param('project', $projectID), $this->param('order', 'id_desc'), 0, $this->param('total', 0), $this->param('limit', 20), $this->param('page', 1)); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') diff --git a/api/v1/entries/my.php b/api/v1/entries/my.php new file mode 100644 index 0000000000..a07722c884 --- /dev/null +++ b/api/v1/entries/my.php @@ -0,0 +1,18 @@ +loadModel('my')->getInfo(); + + if(!$info) return $this->sendError(400, $info->message); + $this->send(200, $info); + } +} diff --git a/api/v1/entries/programs.php b/api/v1/entries/programs.php index abd75ad87e..80b3bc422a 100644 --- a/api/v1/entries/programs.php +++ b/api/v1/entries/programs.php @@ -11,7 +11,7 @@ class ProgramsEntry extends Entry public function get() { $program = $this->loadController('program', 'browse'); - $program->browse(); + $program->browse($this->param('status', 'all'), $this->param('order', 'order_asc')); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') diff --git a/api/v1/entries/projectissue.php b/api/v1/entries/projectissue.php new file mode 100644 index 0000000000..2e88f2bae9 --- /dev/null +++ b/api/v1/entries/projectissue.php @@ -0,0 +1,97 @@ +loadModel('entry'); + $this->setParam('timeFormat', 'utc'); + + $idParams = explode('-', $issueID); + if(count($idParams) < 2) $this->sendError(400, 'The id of issue is wrong.'); + + $type = $idParams[0]; + $id = intval($idParams[1]); + + $issue = new stdclass(); + switch($type) + { + case 'story': + $this->app->loadLang('story'); + $storyStatus = array('' => '', 'draft' => 'opened', 'active' => 'opened', 'changed' => 'opened', 'closed' => 'closed'); + + $story = $this->dao->select('*')->from(TABLE_STORY)->where('id')->eq($id)->fetch(); + if(!$story) $this->send404(); + + $issue->id = $issueID; + $issue->title = $story->title; + $issue->labels = array($this->app->lang->story->common, zget($this->app->lang->story->categoryList, $story->category)); + $issue->pri = $story->pri; + $issue->assignedTo = $this->entry->getAssignees('story', $story); + $issue->openedDate = $story->openedDate; + $issue->openedBy = $this->entry->getUser($story->openedBy); + $issue->lastEditedDate = $story->lastEditedDate < '1970-01-01 01:01:01' ? $story->openedDate : $story->lastEditedDate; + $issue->lastEditedBy = $story->lastEditedDate < '1970-01-01 01:01:01' ? $story->openedBy : $story->lastEditedBy; + $issue->status = $storyStatus[$story->status]; + $issue->url = helper::createLink('story', 'view', "storyID=$id"); + + $storySpec = $this->dao->select('*')->from(TABLE_STORYSPEC)->where('story')->eq($id)->andWhere('version')->eq($story->version)->fetch(); + $issue->desc = $storySpec->spec; + break; + case 'bug': + $this->app->loadLang('bug'); + $bugStatus = array('' => '', 'active' => 'opened', 'resolved' => 'opened', 'closed' => 'closed'); + + $bug = $this->dao->select('*')->from(TABLE_BUG)->where('id')->eq($id)->fetch(); + if(!$bug) $this->send404(); + + $issue->id = $issueID; + $issue->title = $bug->title; + $issue->labels = array($this->app->lang->bug->common, zget($this->app->lang->bug->typeList, $bug->type)); + $issue->pri = $bug->pri; + $issue->assignedTo = $this->entry->getAssignees('bug', $bug); + $issue->openedDate = $bug->openedDate; + $issue->openedBy = $this->entry->getUser($bug->openedBy); + $issue->lastEditedDate = $bug->lastEditedDate < '1970-01-01 01:01:01' ? $bug->openedDate : $bug->lastEditedDate; + $issue->lastEditedBy = $bug->lastEditedDate < '1970-01-01 01:01:01' ? $bug->openedBy : $bug->lastEditedBy; + $issue->status = $bugStatus[$bug->status]; + $issue->url = helper::createLink('bug', 'view', "bugID=$id"); + $issue->desc = $bug->steps; + break; + case 'task': + $this->app->loadLang('task'); + $taskStatus = array('' => '', 'wait' => 'opened', 'doing' => 'opened', 'done' => 'opened', 'pause' => 'opened', 'cancel' => 'opened', 'closed' => 'closed'); + + $task = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($id)->fetch(); + if(!$task) $this->send404(); + + $issue->id = $issueID; + $issue->title = $task->name; + $issue->labels = array($this->app->lang->task->common, zget($this->app->lang->task->typeList, $task->type)); + $issue->pri = $task->pri; + $issue->assignedTo = $this->entry->getAssignees('task', $task); + $issue->openedDate = $task->openedDate; + $issue->openedBy = $this->entry->getUser($task->openedBy); + $issue->lastEditedDate = $task->lastEditedDate < '1970-01-01 01:01:01' ? $task->openedDate : $task->lastEditedDate; + $issue->lastEditedBy = $task->lastEditedDate < '1970-01-01 01:01:01' ? $task->openedBy : $task->lastEditedBy; + $issue->status = $taskStatus[$task->status]; + $issue->url = helper::createLink('task', 'view', "taskID=$id"); + $issue->desc = $task->desc; + + break; + default: + $this->send404(); + } + + $actions = $this->loadModel('action')->getList($type, $issueID); + + $this->send(200, array('issue' => $this->format($issue, 'openedDate:time,lastEditedDate:time'))); + } +} diff --git a/api/v1/entries/projectissues.php b/api/v1/entries/projectissues.php new file mode 100644 index 0000000000..8665b880ff --- /dev/null +++ b/api/v1/entries/projectissues.php @@ -0,0 +1,217 @@ +sendError(400, 'The project_id is not supported'); + + $this->setParam('timeFormat', 'utc'); + + $taskFields = 'id,status'; + $taskStatus = array('' => ''); + $taskStatus['opened'] = 'wait,doing,done,pause'; + $taskStatus['closed'] = 'closed'; + + $storyFields = 'id,status'; + $storyStatus = array('' => ''); + $storyStatus['opened'] = 'draft,active,changed'; + $storyStatus['closed'] = 'closed'; + + $bugFields = 'id,status'; + $bugStatus = array('' => ''); + $bugStatus['opened'] = 'active,resolved'; + $bugStatus['closed'] = 'closed'; + + $productID = (int)$productID; + $status = $this->param('status', ''); + $label = $this->param('label', ''); + $search = $this->param('search', ''); + $page = intval($this->param('page', 1)); + $limit = intval($this->param('limit', 20)); + $order = $this->param('order', 'openedDate_desc'); + + $orderParams = explode('_', $order); + $order = $orderParams[0]; + $sort = (isset($orderParams[1]) and strtolower($orderParams[1]) == 'asc') ? 'asc' : 'desc'; + + if($status == 'all') $status = ''; + if(!in_array($status, array('opened', 'closed', ''))) $this->sendError(400, 'The status is not supported'); + + switch($order) + { + case 'openedDate': + $taskFields .= ',openedDate'; + $storyFields .= ',openedDate'; + $bugFields .= ',openedDate'; + break; + case 'title': + $taskFields .= ',name as title'; + $storyFields .= ',title'; + $bugFields .= ',title'; + break; + case 'lastEditedDate': + $taskFields .= ",if(lastEditedDate < '1970-01-01 01-01-01', openedDate, lastEditedDate) as lastEditedDate"; + $storyFields .= ",if(lastEditedDate < '1970-01-01 01-01-01', openedDate, lastEditedDate) as lastEditedDate"; + $bugFields .= ",if(lastEditedDate < '1970-01-01 01-01-01', openedDate, lastEditedDate) as lastEditedDate"; + break; + default: + $this->sendError(400, 'The order is not supported'); + } + + $issues = array(); + + $executions = $this->dao->select('project')->from(TABLE_PROJECTPRODUCT)->where('product')->eq($productID)->fetchPairs(); + $tasks = $this->dao->select($taskFields)->from(TABLE_TASK)->where('execution')->in(array_values($executions)) + ->beginIF($search)->andWhere('name')->like("%$search%")->fi() + ->beginIF($label)->andWhere('type')->eq($label)->fi() + ->beginIF($status)->andWhere('status')->in($taskStatus[$status])->fi() + ->andWhere('deleted')->eq(0) + ->fetchAll(); + foreach($tasks as $task) $issues[] = array('id' => $task->id, 'type' => 'task', 'order' => $task->$order, 'status' => $this->getKey($task->status, $taskStatus)); + + $stories = $this->dao->select($storyFields)->from(TABLE_STORY)->where('product')->eq($productID) + ->beginIF($search)->andWhere('title')->like("%$search%")->fi() + ->beginIF($label)->andWhere('type')->eq($label)->fi() + ->beginIF($status)->andWhere('status')->in($storyStatus[$status])->fi() + ->andWhere('deleted')->eq(0) + ->fetchAll(); + foreach($stories as $story) + { + $issues[] = array('id' => $story->id, 'type' => 'story', 'order' => $story->$order, 'status' => $this->getKey($story->status, $storyStatus)); + } + + $bugs = $this->dao->select($bugFields)->from(TABLE_BUG)->where('product')->eq($productID) + ->beginIF($search)->andWhere('title')->like("%$search%")->fi() + ->beginIF($label)->andWhere('type')->eq($label)->fi() + ->beginIF($status)->andWhere('status')->in($bugStatus[$status])->fi() + ->andWhere('deleted')->eq(0) + ->fetchAll(); + foreach($bugs as $bug) + { + $issues[] = array('id' => $bug->id, 'type' => 'bug', 'order' => $bug->$order, 'status' => $this->getKey($bug->status, $bugStatus)); + } + + array_multisort(array_column($issues, 'order'), $sort == 'asc' ? SORT_ASC : SORT_DESC, $issues); + $total = count($issues); + $issues = $page < 1 ? array() : array_slice($issues, ($page-1) * $limit, $limit); + + $result = $this->processIssues($issues); + $this->send(200, array('page' => $page, 'total' => $total, 'limit' => $limit, 'issues' => $result)); + } + + /** + * Process issues, format fields. + * + * @param array $issues + * @param int $page + * @param int $limit + * @access public + * @return array + */ + public function processIssues($issues) + { + $this->app->loadLang('task'); + $this->app->loadLang('story'); + $this->app->loadLang('bug'); + + $this->loadModel('entry'); + + $tasks = array(); + $stories = array(); + $bugs = array(); + foreach($issues as $issue) + { + if($issue['type'] == 'story') $stories[] = $issue['id']; + if($issue['type'] == 'task') $tasks[] = $issue['id']; + if($issue['type'] == 'bug') $bugs[] = $issue['id']; + } + + if(!empty($tasks)) $tasks = $this->dao->select('*')->from(TABLE_TASK)->where('id')->in($tasks)->fetchAll('id'); + if(!empty($stories)) $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($stories)->fetchAll('id'); + if(!empty($bugs)) $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($bugs)->fetchAll('id'); + + $result = array(); + foreach($issues as $issue) + { + $r = new stdclass(); + if($issue['type'] == 'task') + { + $task = $tasks[$issue['id']]; + + $r->id = 'task-' . $task->id; + $r->title = $task->name; + $r->labels = array($this->app->lang->task->common, zget($this->app->lang->task->typeList, $task->type)); + $r->pri = $task->pri; + $r->assignedTo = $this->entry->getAssignees('task', $task); + $r->openedDate = $task->openedDate; + $r->openedBy = $this->entry->getUser($task->openedBy); + $r->lastEditedDate = $task->lastEditedDate < '1970-01-01 01:01:01' ? $task->openedDate : $task->lastEditedDate; + $r->lastEditedBy = $task->lastEditedDate < '1970-01-01 01:01:01' ? $task->openedBy : $task->lastEditedBy; + $r->status = $issue['status']; + $r->url = helper::createLink('task', 'view', "taskID=$task->id"); + } + else if($issue['type'] == 'story') + { + $story = $stories[$issue['id']]; + + $r->id = 'story-' . $story->id; + $r->title = $story->title; + $r->labels = array($this->app->lang->story->common, zget($this->app->lang->story->categoryList, $story->category)); + $r->pri = $story->pri; + $r->assignedTo = $this->entry->getAssignees('story', $story); + $r->openedDate = $story->openedDate; + $r->openedBy = $this->entry->getUser($story->openedBy); + $r->lastEditedDate = $story->lastEditedDate < '1970-01-01 01:01:01' ? $story->openedDate : $story->lastEditedDate; + $r->lastEditedBy = $story->lastEditedDate < '1970-01-01 01:01:01' ? $story->openedBy : $story->lastEditedBy; + $r->status = $issue['status']; + $r->url = helper::createLink('story', 'view', "storyID=$story->id"); + } + else if($issue['type'] == 'bug') + { + $bug = $bugs[$issue['id']]; + + $r->id = 'bug-' . $bug->id; + $r->title = $bug->title; + $r->labels = array($this->app->lang->bug->common, zget($this->app->lang->bug->typeList, $bug->type)); + $r->pri = $bug->pri; + $r->assignedTo = $this->entry->getAssignees('bug', $bug); + $r->openedDate = $bug->openedDate; + $r->openedBy = $this->entry->getUser($bug->openedBy); + $r->lastEditedDate = $bug->lastEditedDate < '1970-01-01 01:01:01' ? $bug->openedDate : $bug->lastEditedDate; + $r->lastEditedBy = $bug->lastEditedDate < '1970-01-01 01:01:01' ? $bug->openedBy : $bug->lastEditedBy; + $r->status = $issue['status']; + $r->url = helper::createLink('bug', 'view', "bugID=$bug->id"); + } + + $result[] = $this->format($r, 'openedDate:time,lastEditedDate:time'); + } + + return $result; + } + + /** + * Get key in array by value. + * + * @param string $value + * @param array $array + * @access private + * @return string + */ + private function getKey($value, $array) + { + foreach($array as $key => $values) + { + if($values and strpos($values, $value) !== FALSE) return $key; + } + + return ''; + } +} diff --git a/api/v1/entries/projects.php b/api/v1/entries/projects.php index f8d69bbaf5..d0d886679d 100644 --- a/api/v1/entries/projects.php +++ b/api/v1/entries/projects.php @@ -11,18 +11,18 @@ class projectsEntry extends entry public function get() { $control = $this->loadController('project', 'browse'); - $control->browse(); + $control->browse(0, $this->param('status', 'all'), 0, $this->param('order', 'order_asc'), 0, $this->param('limit', 20), $this->param('page', 1)); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') { - $pager = $data->data->pager; + $pager = $data->data->pager; $result = array(); foreach($data->data->projectStats as $project) { $result[] = $this->format($project, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time'); } - return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'projects' => $result)); + return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => (int)$pager->recPerPage, 'projects' => $result)); } if(isset($data->status) and $data->status == 'fail') diff --git a/api/v1/entries/stories.php b/api/v1/entries/stories.php index fecf7c28a9..ffebfbcb3c 100644 --- a/api/v1/entries/stories.php +++ b/api/v1/entries/stories.php @@ -11,7 +11,7 @@ class storiesEntry extends entry public function get($productID) { $control = $this->loadController('product', 'browse'); - $control->browse($productID); + $control->browse($productID, $this->param('branch', 0), $this->param('type', ''), 0, 'story', $this->param('order', ''), $this->param('total', 0), $this->param('limit', 20), $this->param('page', 1)); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') diff --git a/api/v1/entries/tasks.php b/api/v1/entries/tasks.php index 62b9121996..aa72e42120 100644 --- a/api/v1/entries/tasks.php +++ b/api/v1/entries/tasks.php @@ -11,7 +11,7 @@ class tasksEntry extends entry public function get($executionID) { $control = $this->loadController('execution', 'task'); - $control->task($executionID, 'all'); + $control->task($executionID, $this->param('status', 'all'), 0, $this->param('order', ''), $this->param('total', 0), $this->param('limit', 100), $this->param('page', 1)); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') diff --git a/config/config.php b/config/config.php index 0f2bc19fd6..a22a58ecc6 100644 --- a/config/config.php +++ b/config/config.php @@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}} if(!function_exists('getWebRoot')){function getWebRoot(){}} /* 基本设置。Basic settings. */ -$config->version = '15.2'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. +$config->version = '15.3'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. $config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP. $config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time. $config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php. @@ -109,7 +109,7 @@ $config->framework->purifier = true; // 是否对数据做purifier处理 $config->framework->logDays = 14; // 日志文件保存的天数。 The days to save log files. $config->framework->autoRepairTable = true; $config->framework->autoLang = false; -$config->framework->filterCSRF = false; +$config->framework->filterCSRF = true; $config->framework->setCookieSecure = true; $config->framework->sendXCTO = true; // Send X-Content-Type-Options header. $config->framework->sendXXP = true; // Send X-XSS-Protection header. diff --git a/config/filter.php b/config/filter.php index 42bd625242..2b07fbc15f 100644 --- a/config/filter.php +++ b/config/filter.php @@ -36,6 +36,7 @@ $filter->branch = new stdclass(); $filter->qa = new stdclass(); $filter->story = new stdclass(); $filter->task = new stdclass(); +$filter->execution = new stdclass(); $filter->testcase = new stdclass(); $filter->program = new stdclass(); $filter->project = new stdclass(); @@ -57,6 +58,7 @@ $filter->git = new stdclass(); $filter->svn = new stdclass(); $filter->search = new stdclass(); $filter->gitlab = new stdclass(); +$filter->ci = new stdclass(); $filter->block->default = new stdclass(); $filter->block->main = new stdclass(); @@ -112,6 +114,7 @@ $filter->svn->cat = new stdclass(); $filter->svn->diff = new stdclass(); $filter->task->create = new stdclass(); $filter->task->export = new stdclass(); +$filter->execution->story = new stdclass(); $filter->testcase->default = new stdclass(); $filter->testcase->create = new stdclass(); $filter->testcase->browse = new stdclass(); @@ -133,6 +136,7 @@ $filter->repo->ajaxsynccommit = new stdclass(); $filter->search->index = new stdclass(); $filter->gitlab->webhook = new stdclass(); $filter->gitlab->importissue = new stdclass(); +$filter->ci->checkCompileStatus = new stdclass(); $filter->bug->batchcreate->cookie['preBranch'] = 'int'; $filter->bug->browse->cookie['bugModule'] = 'int'; @@ -187,6 +191,7 @@ $filter->project->default->cookie['lastProject'] = 'int'; $filter->project->default->cookie['lastPRJ'] = 'int'; $filter->project->default->cookie['projectMode'] = 'code'; $filter->project->browse->cookie['involved'] = 'code'; +$filter->project->browse->cookie['projectType'] = 'code'; $filter->project->story->cookie['storyModuleParam'] = 'int'; $filter->project->story->cookie['storyPreProjectID'] = 'int'; $filter->project->story->cookie['storyProductParam'] = 'int'; @@ -212,6 +217,12 @@ $filter->story->export->cookie['checkedItem'] = 'reg::checked'; $filter->task->create->cookie['lastTaskModule'] = 'int'; $filter->task->export->cookie['checkedItem'] = 'reg::checked'; +$filter->execution->story->cookie['storyPreExecutionID'] = 'int'; +$filter->execution->story->cookie['storyModuleParam'] = 'int'; +$filter->execution->story->cookie['storyProductParam'] = 'int'; +$filter->execution->story->cookie['storyBranchParam'] = 'int'; +$filter->execution->story->cookie['executionStoryOrder'] = 'code'; + $filter->testcase->browse->cookie['caseModule'] = 'int'; $filter->testcase->browse->cookie['caseSuite'] = 'int'; $filter->testcase->browse->cookie['preBranch'] = 'int'; @@ -323,3 +334,4 @@ $filter->gitlab->importissue->get['product'] = 'string'; $filter->gitlab->importissue->get['project'] = 'int'; $filter->gitlab->importissue->get['repo'] = 'int'; +$filter->ci->checkCompileStatus->get['gitlabOnly'] = 'string'; diff --git a/config/routes.php b/config/routes.php index 5440427857..0dab867b89 100644 --- a/config/routes.php +++ b/config/routes.php @@ -33,9 +33,12 @@ $routes['/tasks/:id/finish'] = 'taskFinish'; $routes['/users'] = 'users'; $routes['/users/:id'] = 'user'; -$routes['/user'] = 'user'; +$routes['/my'] = 'my'; $routes['/programs'] = 'programs'; $routes['/programs/:id'] = 'program'; +$routes['/issues/:issueID'] = 'projectIssue'; +$routes['/projects/:projectID/issues'] = 'projectIssues'; + $config->routes = $routes; diff --git a/config/zentaopms.php b/config/zentaopms.php index 807ec5189c..0fbc294f6b 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -98,8 +98,8 @@ $config->hourPointCommonList['vi'][0] = 'giờ'; $config->hourPointCommonList['vi'][1] = 'điểm'; $config->hourPointCommonList['vi'][2] = 'function point'; -$config->manualUrl['home'] = 'https://www.zentao.net/book/zentaopmshelp.html?fullScreen=zentao'; -$config->manualUrl['int'] = 'https://www.zentao.pm/book/zentaomanual/zentao-installation-11.html?fullScreen=zentao'; +$config->manualUrl['home'] = 'https://www.zentao.net/book/zentaopmshelp.html?fullScreen=zentao&theme=' . $_COOKIE['theme']; +$config->manualUrl['int'] = 'https://www.zentao.pm/book/zentaomanual/zentao-installation-11.html?fullScreen=zentao&theme=' . $_COOKIE['theme']; /* Supported charsets. */ $config->charsets['zh-cn']['utf-8'] = 'UTF-8'; @@ -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`'); @@ -226,6 +228,7 @@ if(!defined('TABLE_SEARCHDICT')) define('TABLE_SEARCHDICT', $config->db->prefi $config->objectTables['product'] = TABLE_PRODUCT; $config->objectTables['productplan'] = TABLE_PRODUCTPLAN; $config->objectTables['story'] = TABLE_STORY; +$config->objectTables['requirement'] = TABLE_STORY; $config->objectTables['release'] = TABLE_RELEASE; $config->objectTables['program'] = TABLE_PROJECT; $config->objectTables['project'] = TABLE_PROJECT; diff --git a/db/standard/zentao15.3.sql b/db/standard/zentao15.3.sql new file mode 100644 index 0000000000..be16109976 --- /dev/null +++ b/db/standard/zentao15.3.sql @@ -0,0 +1,1243 @@ +CREATE TABLE `zt_acl` ( + `id` mediumint(9) NOT NULL AUTO_INCREMENT, + `account` char(30) NOT NULL, + `objectType` char(30) NOT NULL, + `objectID` mediumint(9) NOT NULL DEFAULT 0, + `type` char(40) NOT NULL DEFAULT 'whitelist', + `source` char(30) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_action` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `objectType` varchar(30) NOT NULL DEFAULT '', + `objectID` mediumint(8) unsigned NOT NULL DEFAULT 0, + `product` varchar(255) NOT NULL, + `project` mediumint(8) unsigned NOT NULL, + `execution` mediumint(8) unsigned NOT NULL, + `actor` varchar(100) NOT NULL DEFAULT '', + `action` varchar(30) NOT NULL DEFAULT '', + `date` datetime NOT NULL, + `comment` text NOT NULL, + `extra` text NOT NULL, + `read` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `date` (`date`), + KEY `actor` (`actor`), + KEY `project` (`project`), + KEY `action` (`action`), + KEY `objectID` (`objectID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_block` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `account` char(30) NOT NULL, + `module` varchar(20) NOT NULL, + `type` char(30) NOT NULL, + `title` varchar(100) NOT NULL, + `source` varchar(20) NOT NULL, + `block` varchar(20) NOT NULL, + `params` text NOT NULL, + `order` tinyint(3) unsigned NOT NULL DEFAULT 0, + `grid` tinyint(3) unsigned NOT NULL DEFAULT 0, + `height` smallint(5) unsigned NOT NULL DEFAULT 0, + `hidden` tinyint(1) unsigned NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `account_module_type_order` (`account`,`module`,`type`,`order`), + KEY `account` (`account`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_branch` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `product` mediumint(8) unsigned NOT NULL, + `name` varchar(255) NOT NULL, + `order` smallint(5) unsigned NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `product` (`product`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_bug` ( + `id` mediumint(8) NOT NULL AUTO_INCREMENT, + `project` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL DEFAULT 0, + `branch` mediumint(8) unsigned NOT NULL DEFAULT 0, + `module` mediumint(8) unsigned NOT NULL DEFAULT 0, + `execution` mediumint(8) unsigned NOT NULL DEFAULT 0, + `plan` mediumint(8) unsigned NOT NULL DEFAULT 0, + `story` mediumint(8) unsigned NOT NULL DEFAULT 0, + `storyVersion` smallint(6) NOT NULL DEFAULT 1, + `task` mediumint(8) unsigned NOT NULL DEFAULT 0, + `toTask` mediumint(8) unsigned NOT NULL DEFAULT 0, + `toStory` mediumint(8) NOT NULL DEFAULT 0, + `title` varchar(255) NOT NULL, + `keywords` varchar(255) NOT NULL, + `severity` tinyint(4) NOT NULL DEFAULT 0, + `pri` tinyint(3) unsigned NOT NULL, + `type` varchar(30) NOT NULL DEFAULT '', + `os` varchar(30) NOT NULL DEFAULT '', + `browser` varchar(30) NOT NULL DEFAULT '', + `hardware` varchar(30) NOT NULL, + `found` varchar(30) NOT NULL DEFAULT '', + `steps` text NOT NULL, + `status` enum('active','resolved','closed') NOT NULL DEFAULT 'active', + `subStatus` varchar(30) NOT NULL DEFAULT '', + `color` char(7) NOT NULL, + `confirmed` tinyint(1) NOT NULL DEFAULT 0, + `activatedCount` smallint(6) NOT NULL, + `activatedDate` datetime NOT NULL, + `mailto` text DEFAULT NULL, + `openedBy` varchar(30) NOT NULL DEFAULT '', + `openedDate` datetime NOT NULL, + `openedBuild` varchar(255) NOT NULL, + `assignedTo` varchar(30) NOT NULL DEFAULT '', + `assignedDate` datetime NOT NULL, + `deadline` date NOT NULL, + `resolvedBy` varchar(30) NOT NULL DEFAULT '', + `resolution` varchar(30) NOT NULL DEFAULT '', + `resolvedBuild` varchar(30) NOT NULL DEFAULT '', + `resolvedDate` datetime NOT NULL, + `closedBy` varchar(30) NOT NULL DEFAULT '', + `closedDate` datetime NOT NULL, + `duplicateBug` mediumint(8) unsigned NOT NULL, + `linkBug` varchar(255) NOT NULL, + `case` mediumint(8) unsigned NOT NULL, + `caseVersion` smallint(6) NOT NULL DEFAULT 1, + `result` mediumint(8) unsigned NOT NULL, + `repo` mediumint(8) unsigned NOT NULL, + `entry` varchar(255) NOT NULL, + `lines` varchar(10) NOT NULL, + `v1` varchar(40) NOT NULL, + `v2` varchar(40) NOT NULL, + `repoType` varchar(30) NOT NULL DEFAULT '', + `testtask` mediumint(8) unsigned NOT NULL, + `lastEditedBy` varchar(30) NOT NULL DEFAULT '', + `lastEditedDate` datetime NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `product` (`product`), + KEY `execution` (`execution`), + KEY `status` (`status`), + KEY `plan` (`plan`), + KEY `story` (`story`), + KEY `case` (`case`), + KEY `toStory` (`toStory`), + KEY `result` (`result`), + KEY `assignedTo` (`assignedTo`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_build` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `project` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL DEFAULT 0, + `branch` mediumint(8) unsigned NOT NULL DEFAULT 0, + `execution` mediumint(8) unsigned NOT NULL DEFAULT 0, + `name` char(150) NOT NULL, + `scmPath` char(255) NOT NULL, + `filePath` char(255) NOT NULL, + `date` date NOT NULL, + `stories` text NOT NULL, + `bugs` text NOT NULL, + `builder` char(30) NOT NULL DEFAULT '', + `desc` text NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `product` (`product`), + KEY `execution` (`execution`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_burn` ( + `execution` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL, + `task` mediumint(8) unsigned NOT NULL DEFAULT 0, + `date` date NOT NULL, + `estimate` float NOT NULL, + `left` float NOT NULL, + `consumed` float NOT NULL, + `storyPoint` float NOT NULL, + PRIMARY KEY (`execution`,`date`,`task`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_case` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `project` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL DEFAULT 0, + `execution` mediumint(8) unsigned NOT NULL, + `branch` mediumint(8) unsigned NOT NULL DEFAULT 0, + `lib` mediumint(8) unsigned NOT NULL DEFAULT 0, + `module` mediumint(8) unsigned NOT NULL DEFAULT 0, + `path` mediumint(8) unsigned NOT NULL DEFAULT 0, + `story` mediumint(30) unsigned NOT NULL DEFAULT 0, + `storyVersion` smallint(6) NOT NULL DEFAULT 1, + `title` varchar(255) NOT NULL, + `precondition` text NOT NULL, + `keywords` varchar(255) NOT NULL, + `pri` tinyint(3) unsigned NOT NULL DEFAULT 3, + `type` char(30) NOT NULL DEFAULT '1', + `auto` varchar(10) NOT NULL DEFAULT 'no', + `frame` varchar(10) NOT NULL, + `stage` varchar(255) NOT NULL, + `howRun` varchar(30) NOT NULL, + `scriptedBy` varchar(30) NOT NULL, + `scriptedDate` date NOT NULL, + `scriptStatus` varchar(30) NOT NULL, + `scriptLocation` varchar(255) NOT NULL, + `status` char(30) NOT NULL DEFAULT '1', + `subStatus` varchar(30) NOT NULL DEFAULT '', + `color` char(7) NOT NULL, + `frequency` enum('1','2','3') NOT NULL DEFAULT '1', + `order` tinyint(30) unsigned NOT NULL DEFAULT 0, + `openedBy` char(30) NOT NULL DEFAULT '', + `openedDate` datetime NOT NULL, + `reviewedBy` varchar(255) NOT NULL, + `reviewedDate` date NOT NULL, + `lastEditedBy` char(30) NOT NULL DEFAULT '', + `lastEditedDate` datetime NOT NULL, + `version` tinyint(3) unsigned NOT NULL DEFAULT 0, + `linkCase` varchar(255) NOT NULL, + `fromBug` mediumint(8) unsigned NOT NULL, + `fromCaseID` mediumint(8) unsigned NOT NULL, + `fromCaseVersion` mediumint(8) unsigned NOT NULL DEFAULT 1, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + `lastRunner` varchar(30) NOT NULL, + `lastRunDate` datetime NOT NULL, + `lastRunResult` char(30) NOT NULL, + PRIMARY KEY (`id`), + KEY `product` (`product`), + KEY `story` (`story`), + KEY `fromBug` (`fromBug`), + KEY `module` (`module`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_casestep` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `parent` mediumint(8) unsigned NOT NULL DEFAULT 0, + `case` mediumint(8) unsigned NOT NULL DEFAULT 0, + `version` smallint(3) unsigned NOT NULL DEFAULT 0, + `type` varchar(10) NOT NULL DEFAULT 'step', + `desc` text NOT NULL, + `expect` text NOT NULL, + PRIMARY KEY (`id`), + KEY `case` (`case`), + KEY `version` (`version`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_company` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `name` char(120) DEFAULT NULL, + `phone` char(20) DEFAULT NULL, + `fax` char(20) DEFAULT NULL, + `address` char(120) DEFAULT NULL, + `zipcode` char(10) DEFAULT NULL, + `website` char(120) DEFAULT NULL, + `backyard` char(120) DEFAULT NULL, + `guest` enum('1','0') NOT NULL DEFAULT '0', + `admins` char(255) DEFAULT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_compile` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `job` mediumint(8) unsigned NOT NULL, + `queue` mediumint(8) NOT NULL, + `status` varchar(255) NOT NULL, + `logs` text DEFAULT NULL, + `atTime` varchar(10) NOT NULL, + `testtask` mediumint(8) unsigned NOT NULL, + `tag` varchar(255) NOT NULL, + `times` tinyint(3) unsigned NOT NULL DEFAULT 0, + `createdBy` varchar(30) NOT NULL, + `createdDate` datetime NOT NULL, + `updateDate` datetime NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_config` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `owner` char(30) NOT NULL DEFAULT '', + `module` varchar(30) NOT NULL, + `section` char(30) NOT NULL DEFAULT '', + `key` char(30) NOT NULL DEFAULT '', + `value` longtext NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `unique` (`owner`,`module`,`section`,`key`) +) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; +CREATE TABLE `zt_cron` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `m` varchar(20) NOT NULL, + `h` varchar(20) NOT NULL, + `dom` varchar(20) NOT NULL, + `mon` varchar(20) NOT NULL, + `dow` varchar(20) NOT NULL, + `command` text NOT NULL, + `remark` varchar(255) NOT NULL, + `type` varchar(20) NOT NULL, + `buildin` tinyint(1) NOT NULL DEFAULT 0, + `status` varchar(20) NOT NULL, + `lastTime` datetime NOT NULL, + PRIMARY KEY (`id`), + KEY `lastTime` (`lastTime`) +) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=utf8; +CREATE TABLE `zt_dept` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `name` char(60) NOT NULL, + `parent` mediumint(8) unsigned NOT NULL DEFAULT 0, + `path` char(255) NOT NULL DEFAULT '', + `grade` tinyint(3) unsigned NOT NULL DEFAULT 0, + `order` smallint(4) unsigned NOT NULL DEFAULT 0, + `position` char(30) NOT NULL DEFAULT '', + `function` char(255) NOT NULL DEFAULT '', + `manager` char(30) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY `parent` (`parent`), + KEY `path` (`path`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_doc` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `project` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL, + `execution` mediumint(8) unsigned NOT NULL, + `lib` varchar(30) NOT NULL, + `module` varchar(30) NOT NULL, + `title` varchar(255) NOT NULL, + `keywords` varchar(255) NOT NULL, + `type` varchar(30) NOT NULL, + `views` smallint(5) unsigned NOT NULL, + `collector` text NOT NULL, + `addedBy` varchar(30) NOT NULL, + `addedDate` datetime NOT NULL, + `editedBy` varchar(30) NOT NULL, + `editedDate` datetime NOT NULL, + `mailto` text DEFAULT NULL, + `acl` varchar(10) NOT NULL DEFAULT 'open', + `groups` varchar(255) NOT NULL, + `users` text NOT NULL, + `version` smallint(5) unsigned NOT NULL DEFAULT 1, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `product` (`product`), + KEY `execution` (`execution`), + KEY `lib` (`lib`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_doccontent` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `doc` mediumint(8) unsigned NOT NULL, + `title` varchar(255) NOT NULL, + `digest` varchar(255) NOT NULL, + `content` longtext NOT NULL, + `files` text NOT NULL, + `type` varchar(10) NOT NULL, + `version` smallint(5) unsigned NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `doc_version` (`doc`,`version`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_doclib` ( + `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, + `type` varchar(30) NOT NULL, + `product` mediumint(8) unsigned NOT NULL, + `project` mediumint(8) unsigned NOT NULL, + `execution` mediumint(8) unsigned NOT NULL, + `name` varchar(60) NOT NULL, + `acl` varchar(10) NOT NULL DEFAULT 'open', + `groups` varchar(255) NOT NULL, + `users` text NOT NULL, + `main` enum('0','1') NOT NULL DEFAULT '0', + `collector` text NOT NULL, + `order` tinyint(5) unsigned NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `product` (`product`), + KEY `execution` (`execution`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_effort` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `user` char(30) NOT NULL DEFAULT '', + `todo` enum('1','0') NOT NULL DEFAULT '1', + `date` date NOT NULL, + `begin` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `end` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `type` enum('1','2','3') NOT NULL DEFAULT '1', + `idvalue` mediumint(8) unsigned NOT NULL DEFAULT 0, + `name` char(30) NOT NULL DEFAULT '', + `desc` char(255) NOT NULL DEFAULT '', + `status` enum('1','2','3') NOT NULL DEFAULT '1', + PRIMARY KEY (`id`), + KEY `user` (`user`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_entry` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `account` varchar(30) NOT NULL DEFAULT '', + `code` varchar(20) NOT NULL, + `key` varchar(32) NOT NULL, + `freePasswd` enum('0','1') NOT NULL DEFAULT '0', + `ip` varchar(100) NOT NULL, + `desc` text NOT NULL, + `createdBy` varchar(30) NOT NULL, + `createdDate` datetime NOT NULL, + `calledTime` int(10) unsigned NOT NULL DEFAULT 0, + `editedBy` varchar(30) NOT NULL, + `editedDate` datetime NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_expect` ( + `id` mediumint(8) NOT NULL AUTO_INCREMENT, + `userID` mediumint(8) NOT NULL, + `project` mediumint(8) NOT NULL DEFAULT 0, + `expect` text NOT NULL, + `progress` text NOT NULL, + `createdBy` char(30) NOT NULL, + `createdDate` date NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_extension` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(150) NOT NULL, + `code` varchar(30) NOT NULL, + `version` varchar(50) NOT NULL, + `author` varchar(100) NOT NULL, + `desc` text NOT NULL, + `license` text NOT NULL, + `type` varchar(20) NOT NULL DEFAULT 'extension', + `site` varchar(150) NOT NULL, + `zentaoCompatible` varchar(100) NOT NULL, + `installedTime` datetime NOT NULL, + `depends` varchar(100) NOT NULL, + `dirs` mediumtext NOT NULL, + `files` mediumtext NOT NULL, + `status` varchar(20) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `code` (`code`), + KEY `name` (`name`), + KEY `installedTime` (`installedTime`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_file` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `pathname` char(50) NOT NULL, + `title` char(255) NOT NULL, + `extension` char(30) NOT NULL, + `size` int(10) unsigned NOT NULL DEFAULT 0, + `objectType` char(30) NOT NULL, + `objectID` mediumint(9) NOT NULL, + `addedBy` char(30) NOT NULL DEFAULT '', + `addedDate` datetime NOT NULL, + `downloads` mediumint(8) unsigned NOT NULL DEFAULT 0, + `extra` varchar(255) NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `objectType` (`objectType`), + KEY `objectID` (`objectID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_group` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `project` mediumint(8) unsigned NOT NULL DEFAULT 0, + `name` char(30) NOT NULL, + `role` char(30) NOT NULL DEFAULT '', + `desc` char(255) NOT NULL DEFAULT '', + `acl` text DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM AUTO_INCREMENT=14 DEFAULT CHARSET=utf8; +CREATE TABLE `zt_grouppriv` ( + `group` mediumint(8) unsigned NOT NULL DEFAULT 0, + `module` char(30) NOT NULL DEFAULT '', + `method` char(30) NOT NULL DEFAULT '', + UNIQUE KEY `group` (`group`,`module`,`method`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_history` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `action` mediumint(8) unsigned NOT NULL DEFAULT 0, + `field` varchar(30) NOT NULL DEFAULT '', + `old` text NOT NULL, + `new` text NOT NULL, + `diff` mediumtext NOT NULL, + PRIMARY KEY (`id`), + KEY `action` (`action`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_job` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `repo` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL, + `frame` varchar(20) NOT NULL, + `engine` varchar(20) NOT NULL, + `server` mediumint(8) unsigned NOT NULL, + `pipeline` varchar(500) NOT NULL, + `triggerType` varchar(255) NOT NULL, + `svnDir` varchar(255) NOT NULL, + `atDay` varchar(255) DEFAULT NULL, + `atTime` varchar(10) DEFAULT NULL, + `customParam` text NOT NULL, + `comment` varchar(255) DEFAULT NULL, + `createdBy` varchar(30) NOT NULL, + `createdDate` datetime NOT NULL, + `editedBy` varchar(30) NOT NULL, + `editedDate` datetime NOT NULL, + `lastExec` datetime DEFAULT NULL, + `lastStatus` varchar(255) DEFAULT NULL, + `lastTag` varchar(255) DEFAULT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_lang` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `lang` varchar(30) NOT NULL, + `module` varchar(30) NOT NULL, + `section` varchar(30) NOT NULL, + `key` varchar(60) NOT NULL, + `value` text NOT NULL, + `system` enum('0','1') NOT NULL DEFAULT '1', + PRIMARY KEY (`id`), + UNIQUE KEY `lang` (`lang`,`module`,`section`,`key`) +) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; +CREATE TABLE `zt_log` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `objectType` varchar(30) NOT NULL, + `objectID` mediumint(8) unsigned NOT NULL, + `action` mediumint(8) unsigned NOT NULL, + `date` datetime NOT NULL, + `url` varchar(255) NOT NULL, + `contentType` varchar(30) NOT NULL, + `data` text NOT NULL, + `result` text NOT NULL, + PRIMARY KEY (`id`), + KEY `objectType` (`objectType`), + KEY `obejctID` (`objectID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_module` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `root` mediumint(8) unsigned NOT NULL DEFAULT 0, + `branch` mediumint(8) unsigned NOT NULL DEFAULT 0, + `name` char(60) NOT NULL DEFAULT '', + `parent` mediumint(8) unsigned NOT NULL DEFAULT 0, + `path` char(255) NOT NULL DEFAULT '', + `grade` tinyint(3) unsigned NOT NULL DEFAULT 0, + `order` smallint(5) unsigned NOT NULL DEFAULT 0, + `type` char(30) NOT NULL, + `owner` varchar(30) NOT NULL, + `collector` text NOT NULL, + `short` varchar(30) NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `root` (`root`), + KEY `type` (`type`), + KEY `path` (`path`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_notify` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `objectType` varchar(50) NOT NULL, + `objectID` mediumint(8) unsigned NOT NULL, + `action` mediumint(9) NOT NULL, + `toList` varchar(255) NOT NULL, + `ccList` text NOT NULL, + `subject` varchar(255) NOT NULL, + `data` text NOT NULL, + `createdBy` char(30) NOT NULL, + `createdDate` datetime NOT NULL, + `sendTime` datetime NOT NULL, + `status` varchar(10) NOT NULL DEFAULT 'wait', + `failReason` text NOT NULL, + PRIMARY KEY (`id`), + KEY `objectType_toList_status` (`objectType`,`toList`,`status`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_oauth` ( + `account` varchar(30) NOT NULL, + `openID` varchar(255) NOT NULL, + `providerType` varchar(30) NOT NULL, + `providerID` mediumint(8) unsigned NOT NULL, + KEY `account` (`account`), + KEY `providerType` (`providerType`), + KEY `providerID` (`providerID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_pipeline` ( + `id` smallint(8) unsigned NOT NULL AUTO_INCREMENT, + `type` char(30) NOT NULL, + `name` varchar(50) NOT NULL, + `url` varchar(255) DEFAULT NULL, + `account` varchar(30) DEFAULT NULL, + `password` varchar(255) NOT NULL, + `token` varchar(255) DEFAULT NULL, + `private` char(32) DEFAULT NULL, + `createdBy` varchar(30) NOT NULL, + `createdDate` datetime NOT NULL, + `editedBy` varchar(30) NOT NULL, + `editedDate` datetime NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_planstory` ( + `plan` mediumint(8) unsigned NOT NULL, + `story` mediumint(8) unsigned NOT NULL, + `order` mediumint(9) NOT NULL, + UNIQUE KEY `plan_story` (`plan`,`story`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_product` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `program` mediumint(8) unsigned NOT NULL, + `name` varchar(90) NOT NULL, + `code` varchar(45) NOT NULL, + `bind` enum('0','1') NOT NULL DEFAULT '0', + `line` mediumint(8) NOT NULL, + `type` varchar(30) NOT NULL DEFAULT 'normal', + `status` varchar(30) NOT NULL DEFAULT '', + `subStatus` varchar(30) NOT NULL DEFAULT '', + `desc` text NOT NULL, + `PO` varchar(30) NOT NULL, + `QD` varchar(30) NOT NULL, + `RD` varchar(30) NOT NULL, + `storyConcept` smallint(5) NOT NULL, + `acl` enum('open','private','custom') NOT NULL DEFAULT 'open', + `whitelist` text NOT NULL, + `createdBy` varchar(30) NOT NULL, + `createdDate` datetime NOT NULL, + `createdVersion` varchar(20) NOT NULL, + `order` mediumint(8) unsigned NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `acl` (`acl`), + KEY `order` (`order`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_productplan` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `product` mediumint(8) unsigned NOT NULL, + `branch` mediumint(8) unsigned NOT NULL, + `parent` mediumint(9) NOT NULL DEFAULT 0, + `title` varchar(90) NOT NULL, + `desc` text NOT NULL, + `begin` date NOT NULL, + `end` date NOT NULL, + `order` text NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `product` (`product`), + KEY `end` (`end`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_project` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `project` mediumint(8) NOT NULL DEFAULT 0, + `model` char(30) NOT NULL, + `type` char(30) NOT NULL DEFAULT 'sprint', + `product` char(30) NOT NULL DEFAULT 'single', + `lifetime` char(30) NOT NULL DEFAULT '', + `budget` varchar(30) NOT NULL DEFAULT '0', + `budgetUnit` char(30) NOT NULL DEFAULT 'CNY', + `attribute` varchar(30) NOT NULL DEFAULT '', + `percent` float unsigned NOT NULL DEFAULT 0, + `milestone` enum('0','1') NOT NULL DEFAULT '0', + `output` text NOT NULL, + `auth` char(30) NOT NULL, + `parent` mediumint(8) unsigned NOT NULL DEFAULT 0, + `path` varchar(255) NOT NULL, + `grade` tinyint(3) unsigned NOT NULL, + `name` varchar(90) NOT NULL, + `code` varchar(45) NOT NULL, + `begin` date NOT NULL, + `end` date NOT NULL, + `realBegan` date NOT NULL, + `realEnd` date NOT NULL, + `days` smallint(5) unsigned NOT NULL, + `storyConcept` smallint(5) unsigned NOT NULL, + `status` varchar(10) NOT NULL, + `subStatus` varchar(30) NOT NULL DEFAULT '', + `statge` enum('1','2','3','4','5') NOT NULL DEFAULT '1', + `pri` enum('1','2','3','4') NOT NULL DEFAULT '1', + `desc` text NOT NULL, + `version` smallint(6) NOT NULL, + `parentVersion` smallint(6) NOT NULL, + `planDuration` int(11) NOT NULL, + `realDuration` int(11) NOT NULL, + `openedBy` varchar(30) NOT NULL DEFAULT '', + `openedDate` datetime NOT NULL, + `openedVersion` varchar(20) NOT NULL, + `lastEditedBy` varchar(30) NOT NULL DEFAULT '', + `lastEditedDate` datetime NOT NULL, + `closedBy` varchar(30) NOT NULL DEFAULT '', + `closedDate` datetime NOT NULL, + `canceledBy` varchar(30) NOT NULL DEFAULT '', + `canceledDate` datetime NOT NULL, + `PO` varchar(30) NOT NULL DEFAULT '', + `PM` varchar(30) NOT NULL DEFAULT '', + `QD` varchar(30) NOT NULL DEFAULT '', + `RD` varchar(30) NOT NULL DEFAULT '', + `team` varchar(90) NOT NULL, + `acl` char(30) NOT NULL DEFAULT 'open', + `whitelist` text NOT NULL, + `order` mediumint(8) unsigned NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `parent` (`parent`), + KEY `begin` (`begin`), + KEY `end` (`end`), + KEY `status` (`status`), + KEY `acl` (`acl`), + KEY `order` (`order`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_projectcase` ( + `project` mediumint(8) unsigned NOT NULL DEFAULT 0, + `product` mediumint(8) unsigned NOT NULL DEFAULT 0, + `case` mediumint(8) unsigned NOT NULL DEFAULT 0, + `count` mediumint(8) unsigned NOT NULL DEFAULT 1, + `version` smallint(6) NOT NULL DEFAULT 1, + `order` smallint(6) unsigned NOT NULL, + UNIQUE KEY `project` (`project`,`case`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_projectproduct` ( + `project` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL, + `branch` mediumint(8) unsigned NOT NULL, + `plan` mediumint(8) unsigned NOT NULL, + PRIMARY KEY (`project`,`product`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_projectspec` ( + `project` mediumint(8) NOT NULL, + `version` smallint(6) NOT NULL, + `name` varchar(255) NOT NULL, + `milestone` enum('0','1') NOT NULL DEFAULT '0', + `begin` date NOT NULL, + `end` date NOT NULL, + UNIQUE KEY `project` (`project`,`version`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_projectstory` ( + `project` mediumint(8) unsigned NOT NULL DEFAULT 0, + `product` mediumint(8) unsigned NOT NULL, + `story` mediumint(8) unsigned NOT NULL DEFAULT 0, + `version` smallint(6) NOT NULL DEFAULT 1, + `order` smallint(6) unsigned NOT NULL, + UNIQUE KEY `project` (`project`,`story`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_relation` ( + `id` int(8) NOT NULL AUTO_INCREMENT, + `project` mediumint(8) NOT NULL, + `product` mediumint(8) NOT NULL, + `execution` mediumint(8) NOT NULL, + `AType` char(30) NOT NULL, + `AID` mediumint(8) NOT NULL, + `AVersion` char(30) NOT NULL, + `relation` char(30) NOT NULL, + `BType` char(30) NOT NULL, + `BID` mediumint(8) NOT NULL, + `BVersion` char(30) NOT NULL, + `extra` char(30) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `relation` (`product`,`relation`,`AType`,`BType`,`AID`,`BID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_release` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `project` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL DEFAULT 0, + `branch` mediumint(8) unsigned NOT NULL DEFAULT 0, + `build` mediumint(8) unsigned NOT NULL, + `name` varchar(255) NOT NULL DEFAULT '', + `marker` enum('0','1') NOT NULL DEFAULT '0', + `date` date NOT NULL, + `stories` text NOT NULL, + `bugs` text NOT NULL, + `leftBugs` text NOT NULL, + `desc` text NOT NULL, + `status` varchar(20) NOT NULL DEFAULT 'normal', + `subStatus` varchar(30) NOT NULL DEFAULT '', + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `product` (`product`), + KEY `build` (`build`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_repo` ( + `id` mediumint(9) NOT NULL AUTO_INCREMENT, + `product` varchar(255) NOT NULL, + `name` varchar(255) NOT NULL, + `path` varchar(255) NOT NULL, + `prefix` varchar(100) NOT NULL, + `encoding` varchar(20) NOT NULL, + `SCM` varchar(10) NOT NULL, + `client` varchar(100) NOT NULL, + `commits` mediumint(8) unsigned NOT NULL, + `account` varchar(30) NOT NULL, + `password` varchar(30) NOT NULL, + `encrypt` varchar(30) NOT NULL DEFAULT 'plain', + `acl` text NOT NULL, + `synced` tinyint(1) NOT NULL DEFAULT 0, + `lastSync` datetime NOT NULL, + `desc` text NOT NULL, + `extra` char(30) NOT NULL, + `deleted` tinyint(1) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_repobranch` ( + `repo` mediumint(8) unsigned NOT NULL, + `revision` mediumint(8) unsigned NOT NULL, + `branch` varchar(255) NOT NULL, + UNIQUE KEY `repo_revision_branch` (`repo`,`revision`,`branch`), + KEY `branch` (`branch`), + KEY `revision` (`revision`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_repofiles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `repo` mediumint(8) unsigned NOT NULL, + `revision` mediumint(8) unsigned NOT NULL, + `path` varchar(255) NOT NULL, + `parent` varchar(255) NOT NULL, + `type` varchar(20) NOT NULL, + `action` char(1) NOT NULL, + PRIMARY KEY (`id`), + KEY `path` (`path`), + KEY `parent` (`parent`), + KEY `repo` (`repo`), + KEY `revision` (`revision`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_repohistory` ( + `id` mediumint(9) NOT NULL AUTO_INCREMENT, + `repo` mediumint(9) NOT NULL, + `revision` varchar(40) NOT NULL, + `commit` mediumint(8) unsigned NOT NULL, + `comment` text NOT NULL, + `committer` varchar(100) NOT NULL, + `time` datetime NOT NULL, + PRIMARY KEY (`id`), + KEY `repo` (`repo`), + KEY `revision` (`revision`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_score` ( + `id` bigint(12) unsigned NOT NULL AUTO_INCREMENT, + `account` varchar(30) NOT NULL, + `module` varchar(30) NOT NULL DEFAULT '', + `method` varchar(30) NOT NULL, + `desc` varchar(250) NOT NULL DEFAULT '', + `before` int(11) NOT NULL DEFAULT 0, + `score` int(11) NOT NULL DEFAULT 0, + `after` int(11) NOT NULL DEFAULT 0, + `time` datetime NOT NULL, + PRIMARY KEY (`id`), + KEY `account` (`account`), + KEY `model` (`module`), + KEY `method` (`method`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_searchdict` ( + `key` smallint(5) unsigned NOT NULL, + `value` char(3) NOT NULL, + PRIMARY KEY (`key`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_searchindex` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `objectType` char(20) NOT NULL, + `objectID` mediumint(9) NOT NULL, + `title` text NOT NULL, + `content` text NOT NULL, + `addedDate` datetime NOT NULL, + `editedDate` datetime NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `object` (`objectType`,`objectID`), + KEY `addedDate` (`addedDate`), + FULLTEXT KEY `content` (`content`), + FULLTEXT KEY `title` (`title`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_stakeholder` ( + `id` mediumint(8) NOT NULL AUTO_INCREMENT, + `objectID` mediumint(8) NOT NULL, + `objectType` char(30) NOT NULL, + `user` char(30) NOT NULL, + `type` char(30) NOT NULL, + `key` enum('0','1') NOT NULL, + `from` char(30) NOT NULL, + `createdBy` char(30) NOT NULL, + `createdDate` date NOT NULL, + `editedBy` char(30) NOT NULL, + `editedDate` date NOT NULL, + `deleted` enum('0','1') NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_story` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `parent` mediumint(9) NOT NULL DEFAULT 0, + `product` mediumint(8) unsigned NOT NULL DEFAULT 0, + `branch` mediumint(8) unsigned NOT NULL DEFAULT 0, + `module` mediumint(8) unsigned NOT NULL DEFAULT 0, + `plan` text DEFAULT NULL, + `source` varchar(20) NOT NULL, + `sourceNote` varchar(255) NOT NULL, + `fromBug` mediumint(8) unsigned NOT NULL DEFAULT 0, + `title` varchar(255) NOT NULL, + `keywords` varchar(255) NOT NULL, + `type` varchar(30) NOT NULL DEFAULT 'story', + `category` varchar(30) NOT NULL DEFAULT 'feature', + `pri` tinyint(3) unsigned NOT NULL DEFAULT 3, + `estimate` float unsigned NOT NULL, + `status` enum('','changed','active','draft','closed') NOT NULL DEFAULT '', + `subStatus` varchar(30) NOT NULL DEFAULT '', + `color` char(7) NOT NULL, + `stage` enum('','wait','planned','projected','developing','developed','testing','tested','verified','released','closed') NOT NULL DEFAULT 'wait', + `stagedBy` char(30) NOT NULL, + `mailto` text DEFAULT NULL, + `openedBy` varchar(30) NOT NULL DEFAULT '', + `openedDate` datetime NOT NULL, + `assignedTo` varchar(30) NOT NULL DEFAULT '', + `assignedDate` datetime NOT NULL, + `lastEditedBy` varchar(30) NOT NULL DEFAULT '', + `lastEditedDate` datetime NOT NULL, + `reviewedBy` varchar(255) NOT NULL, + `reviewedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `closedBy` varchar(30) NOT NULL DEFAULT '', + `closedDate` datetime NOT NULL, + `closedReason` varchar(30) NOT NULL, + `toBug` mediumint(8) unsigned NOT NULL, + `childStories` varchar(255) NOT NULL, + `linkStories` varchar(255) NOT NULL, + `duplicateStory` mediumint(8) unsigned NOT NULL, + `version` smallint(6) NOT NULL DEFAULT 1, + `URChanged` enum('0','1') NOT NULL DEFAULT '0', + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `product` (`product`), + KEY `status` (`status`), + KEY `assignedTo` (`assignedTo`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_storyestimate` ( + `story` mediumint(9) NOT NULL, + `round` smallint(6) NOT NULL, + `estimate` text NOT NULL, + `average` float NOT NULL, + `openedBy` varchar(30) NOT NULL, + `openedDate` datetime NOT NULL, + UNIQUE KEY `story` (`story`,`round`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_storyreview` ( + `story` mediumint(9) NOT NULL, + `version` smallint(6) NOT NULL, + `reviewer` varchar(30) NOT NULL, + `result` varchar(30) NOT NULL, + `reviewDate` datetime NOT NULL, + UNIQUE KEY `story` (`story`,`version`,`reviewer`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_storyspec` ( + `story` mediumint(9) NOT NULL, + `version` smallint(6) NOT NULL, + `title` varchar(255) NOT NULL, + `spec` text NOT NULL, + `verify` text NOT NULL, + UNIQUE KEY `story` (`story`,`version`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_storystage` ( + `story` mediumint(8) unsigned NOT NULL, + `branch` mediumint(8) unsigned NOT NULL, + `stage` varchar(50) NOT NULL, + `stagedBy` char(30) NOT NULL, + UNIQUE KEY `story_branch` (`story`,`branch`), + KEY `story` (`story`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_suitecase` ( + `suite` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL, + `case` mediumint(8) unsigned NOT NULL, + `version` smallint(5) unsigned NOT NULL, + UNIQUE KEY `suitecase` (`suite`,`case`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_task` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `project` mediumint(8) unsigned NOT NULL, + `parent` mediumint(8) NOT NULL DEFAULT 0, + `execution` mediumint(8) unsigned NOT NULL DEFAULT 0, + `module` mediumint(8) unsigned NOT NULL DEFAULT 0, + `design` mediumint(8) unsigned NOT NULL, + `story` mediumint(8) unsigned NOT NULL DEFAULT 0, + `storyVersion` smallint(6) NOT NULL DEFAULT 1, + `designVersion` smallint(6) unsigned NOT NULL, + `fromBug` mediumint(8) unsigned NOT NULL DEFAULT 0, + `name` varchar(255) NOT NULL, + `type` varchar(20) NOT NULL, + `pri` tinyint(3) unsigned NOT NULL DEFAULT 0, + `estimate` float unsigned NOT NULL, + `consumed` float unsigned NOT NULL, + `left` float unsigned NOT NULL, + `deadline` date NOT NULL, + `status` enum('wait','doing','done','pause','cancel','closed') NOT NULL DEFAULT 'wait', + `subStatus` varchar(30) NOT NULL DEFAULT '', + `color` char(7) NOT NULL, + `mailto` text DEFAULT NULL, + `desc` text NOT NULL, + `version` smallint(6) NOT NULL, + `openedBy` varchar(30) NOT NULL, + `openedDate` datetime NOT NULL, + `assignedTo` varchar(30) NOT NULL, + `assignedDate` datetime NOT NULL, + `estStarted` date NOT NULL, + `realStarted` datetime NOT NULL, + `finishedBy` varchar(30) NOT NULL, + `finishedDate` datetime NOT NULL, + `finishedList` text NOT NULL, + `canceledBy` varchar(30) NOT NULL, + `canceledDate` datetime NOT NULL, + `closedBy` varchar(30) NOT NULL, + `closedDate` datetime NOT NULL, + `planDuration` int(11) NOT NULL, + `realDuration` int(11) NOT NULL, + `closedReason` varchar(30) NOT NULL, + `lastEditedBy` varchar(30) NOT NULL, + `lastEditedDate` datetime NOT NULL, + `activatedDate` date NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `execution` (`execution`), + KEY `story` (`story`), + KEY `parent` (`parent`), + KEY `assignedTo` (`assignedTo`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_taskestimate` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `task` mediumint(8) unsigned NOT NULL DEFAULT 0, + `date` date NOT NULL, + `left` float unsigned NOT NULL DEFAULT 0, + `consumed` float unsigned NOT NULL, + `account` char(30) NOT NULL DEFAULT '', + `work` text DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `task` (`task`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_taskspec` ( + `task` mediumint(8) NOT NULL, + `version` smallint(6) NOT NULL, + `name` varchar(255) NOT NULL, + `estStarted` date NOT NULL, + `deadline` date NOT NULL, + UNIQUE KEY `task` (`task`,`version`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_team` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `root` mediumint(8) unsigned NOT NULL DEFAULT 0, + `type` enum('project','task','execution') NOT NULL DEFAULT 'project', + `account` char(30) NOT NULL DEFAULT '', + `role` char(30) NOT NULL DEFAULT '', + `limited` char(8) NOT NULL DEFAULT 'no', + `join` date NOT NULL DEFAULT '0000-00-00', + `days` smallint(5) unsigned NOT NULL, + `hours` float(3,1) unsigned NOT NULL DEFAULT 0.0, + `estimate` decimal(12,2) unsigned NOT NULL DEFAULT 0.00, + `consumed` decimal(12,2) unsigned NOT NULL DEFAULT 0.00, + `left` decimal(12,2) unsigned NOT NULL DEFAULT 0.00, + `order` tinyint(3) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `team` (`root`,`type`,`account`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_testreport` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `project` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL, + `execution` mediumint(8) unsigned NOT NULL, + `tasks` varchar(255) NOT NULL, + `builds` varchar(255) NOT NULL, + `title` varchar(255) NOT NULL, + `begin` date NOT NULL, + `end` date NOT NULL, + `owner` char(30) NOT NULL, + `members` text NOT NULL, + `stories` text NOT NULL, + `bugs` text NOT NULL, + `cases` text NOT NULL, + `report` text NOT NULL, + `objectType` varchar(20) NOT NULL, + `objectID` mediumint(8) unsigned NOT NULL, + `createdBy` char(30) NOT NULL, + `createdDate` datetime NOT NULL, + `deleted` enum('0','1') NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_testresult` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `run` mediumint(8) unsigned NOT NULL, + `case` mediumint(8) unsigned NOT NULL, + `version` smallint(5) unsigned NOT NULL, + `job` mediumint(8) unsigned NOT NULL, + `compile` mediumint(8) unsigned NOT NULL, + `caseResult` char(30) NOT NULL, + `stepResults` text NOT NULL, + `lastRunner` varchar(30) NOT NULL, + `date` datetime NOT NULL, + `duration` float NOT NULL, + `xml` text NOT NULL, + PRIMARY KEY (`id`), + KEY `case` (`case`), + KEY `version` (`version`), + KEY `run` (`run`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_testrun` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `task` mediumint(8) unsigned NOT NULL DEFAULT 0, + `case` mediumint(8) unsigned NOT NULL DEFAULT 0, + `version` tinyint(3) unsigned NOT NULL DEFAULT 0, + `assignedTo` char(30) NOT NULL DEFAULT '', + `lastRunner` varchar(30) NOT NULL, + `lastRunDate` datetime NOT NULL, + `lastRunResult` char(30) NOT NULL, + `status` char(30) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `task` (`task`,`case`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_testsuite` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `project` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL, + `name` varchar(255) NOT NULL, + `desc` text NOT NULL, + `type` varchar(20) NOT NULL, + `addedBy` char(30) NOT NULL, + `addedDate` datetime NOT NULL, + `lastEditedBy` char(30) NOT NULL, + `lastEditedDate` datetime NOT NULL, + `deleted` enum('0','1') NOT NULL, + PRIMARY KEY (`id`), + KEY `product` (`product`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_testtask` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `project` mediumint(8) unsigned NOT NULL, + `product` mediumint(8) unsigned NOT NULL, + `name` char(90) NOT NULL, + `execution` mediumint(8) unsigned NOT NULL DEFAULT 0, + `build` char(30) NOT NULL, + `type` varchar(255) NOT NULL DEFAULT '', + `owner` varchar(30) NOT NULL, + `pri` tinyint(3) unsigned NOT NULL DEFAULT 0, + `begin` date NOT NULL, + `end` date NOT NULL, + `mailto` text DEFAULT NULL, + `desc` text NOT NULL, + `report` text NOT NULL, + `status` enum('blocked','doing','wait','done') NOT NULL DEFAULT 'wait', + `testreport` mediumint(8) unsigned NOT NULL, + `auto` varchar(10) NOT NULL DEFAULT 'no', + `subStatus` varchar(30) NOT NULL DEFAULT '', + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `product` (`product`), + KEY `build` (`build`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_todo` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `account` char(30) NOT NULL, + `date` date NOT NULL, + `begin` smallint(4) unsigned zerofill NOT NULL, + `end` smallint(4) unsigned zerofill NOT NULL, + `type` char(10) NOT NULL, + `cycle` tinyint(3) unsigned NOT NULL DEFAULT 0, + `idvalue` mediumint(8) unsigned NOT NULL DEFAULT 0, + `pri` tinyint(3) unsigned NOT NULL, + `name` char(150) NOT NULL, + `desc` text NOT NULL, + `status` enum('wait','doing','done','closed') NOT NULL DEFAULT 'wait', + `private` tinyint(1) NOT NULL, + `config` varchar(255) NOT NULL, + `assignedTo` varchar(30) NOT NULL DEFAULT '', + `assignedBy` varchar(30) NOT NULL DEFAULT '', + `assignedDate` datetime NOT NULL, + `finishedBy` varchar(30) NOT NULL DEFAULT '', + `finishedDate` datetime NOT NULL, + `closedBy` varchar(30) NOT NULL DEFAULT '', + `closedDate` datetime NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `account` (`account`), + KEY `assignedTo` (`assignedTo`), + KEY `finishedBy` (`finishedBy`), + KEY `date` (`date`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_user` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `company` mediumint(8) unsigned NOT NULL, + `type` char(30) NOT NULL DEFAULT 'inside', + `dept` mediumint(8) unsigned NOT NULL DEFAULT 0, + `account` char(30) NOT NULL DEFAULT '', + `password` char(32) NOT NULL DEFAULT '', + `role` char(10) NOT NULL DEFAULT '', + `realname` varchar(100) NOT NULL DEFAULT '', + `nickname` char(60) NOT NULL DEFAULT '', + `commiter` varchar(100) NOT NULL, + `avatar` text NOT NULL, + `birthday` date NOT NULL DEFAULT '0000-00-00', + `gender` enum('f','m') NOT NULL DEFAULT 'f', + `email` char(90) NOT NULL DEFAULT '', + `skype` char(90) NOT NULL DEFAULT '', + `qq` char(20) NOT NULL DEFAULT '', + `mobile` char(11) NOT NULL DEFAULT '', + `phone` char(20) NOT NULL DEFAULT '', + `weixin` varchar(90) NOT NULL DEFAULT '', + `dingding` varchar(90) NOT NULL DEFAULT '', + `slack` varchar(90) NOT NULL DEFAULT '', + `whatsapp` varchar(90) NOT NULL DEFAULT '', + `address` char(120) NOT NULL DEFAULT '', + `zipcode` char(10) NOT NULL DEFAULT '', + `nature` text NOT NULL, + `analysis` text NOT NULL, + `strategy` text NOT NULL, + `join` date NOT NULL DEFAULT '0000-00-00', + `visits` mediumint(8) unsigned NOT NULL DEFAULT 0, + `ip` char(15) NOT NULL DEFAULT '', + `last` int(10) unsigned NOT NULL DEFAULT 0, + `fails` tinyint(5) NOT NULL DEFAULT 0, + `locked` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `ranzhi` char(30) NOT NULL DEFAULT '', + `score` int(11) NOT NULL DEFAULT 0, + `scoreLevel` int(11) NOT NULL DEFAULT 0, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE KEY `account` (`account`), + KEY `dept` (`dept`), + KEY `email` (`email`), + KEY `commiter` (`commiter`), + KEY `deleted` (`deleted`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_usercontact` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `account` char(30) NOT NULL, + `listName` varchar(60) NOT NULL, + `userList` text NOT NULL, + PRIMARY KEY (`id`), + KEY `account` (`account`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_usergroup` ( + `account` char(30) NOT NULL DEFAULT '', + `group` mediumint(8) unsigned NOT NULL DEFAULT 0, + `project` text NOT NULL, + UNIQUE KEY `account` (`account`,`group`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_userquery` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `account` char(30) NOT NULL, + `module` varchar(30) NOT NULL, + `title` varchar(90) NOT NULL, + `form` text NOT NULL, + `sql` text NOT NULL, + `shortcut` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `account` (`account`), + KEY `module` (`module`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_usertpl` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `account` char(30) NOT NULL, + `type` char(30) NOT NULL, + `title` varchar(150) NOT NULL, + `content` text NOT NULL, + `public` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + KEY `account` (`account`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_userview` ( + `account` char(30) NOT NULL, + `programs` mediumtext NOT NULL, + `products` mediumtext NOT NULL, + `projects` mediumtext NOT NULL, + `sprints` mediumtext NOT NULL, + UNIQUE KEY `account` (`account`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE `zt_webhook` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `type` varchar(15) NOT NULL DEFAULT 'default', + `name` varchar(50) NOT NULL, + `url` varchar(255) NOT NULL, + `domain` varchar(255) NOT NULL, + `secret` varchar(255) NOT NULL, + `contentType` varchar(30) NOT NULL DEFAULT 'application/json', + `sendType` enum('sync','async') NOT NULL DEFAULT 'sync', + `products` text NOT NULL, + `executions` text NOT NULL, + `params` varchar(100) NOT NULL, + `actions` text NOT NULL, + `desc` text NOT NULL, + `createdBy` varchar(30) NOT NULL, + `createdDate` datetime NOT NULL, + `editedBy` varchar(30) NOT NULL, + `editedDate` datetime NOT NULL, + `deleted` enum('0','1') NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/db/update15.2.sql b/db/update15.2.sql index 59b2d09522..e3e0886078 100644 --- a/db/update15.2.sql +++ b/db/update15.2.sql @@ -3,3 +3,6 @@ ADD `engine` varchar(20) NOT NULL AFTER `frame`, CHANGE `jkHost` `server` mediumint(0) UNSIGNED NOT NULL AFTER `frame`, CHANGE `jkJob` `pipeline` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `server`; +UPDATE `zt_job` SET `engine` = 'jenkins' WHERE `engine` = ''; +UPDATE `zt_cron` SET `remark` = '执行DevOps构建任务' WHERE `remark` = '执行Jenkins任务'; +UPDATE `zt_cron` SET `remark` = '同步DevOps构建任务状态' WHERE `remark` = '同步Jenkins任务状态'; diff --git a/db/update15.3.sql b/db/update15.3.sql new file mode 100644 index 0000000000..743ccea4e4 --- /dev/null +++ b/db/update15.3.sql @@ -0,0 +1 @@ +ALTER TABLE `zt_testtask` ADD `realFinishedDate` datetime NOT NULL AFTER `end`; diff --git a/db/zentao.sql b/db/zentao.sql index 9457583bc7..ab4f9f3beb 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, @@ -1153,6 +1153,7 @@ CREATE TABLE IF NOT EXISTS `zt_testtask` ( `pri` tinyint(3) unsigned NOT NULL default '0', `begin` date NOT NULL, `end` date NOT NULL, + `realFinishedDate` datetime NOT NULL, `mailto` text, `desc` text NOT NULL, `report` text NOT NULL, @@ -1325,8 +1326,8 @@ INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type ('*/5', '*', '*', '*', '*', 'moduleName=admin&methodName=deleteLog', '删除过期日志', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), ('1', '1', '*', '*', '*', 'moduleName=todo&methodName=createCycle', '生成周期性待办', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), ('1', '0', '*', '*', '*', 'moduleName=ci&methodName=initQueue', '创建周期性任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), -('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=checkCompileStatus', '同步Jenkins任务状态', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), -('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=exec', '执行Jenkins任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'); +('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=checkCompileStatus', '同步DevOps构建任务状态', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), +('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=exec', '执行DevOps构建任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'); INSERT INTO `zt_group` (`id`, `name`, `role`, `desc`) VALUES (1, 'ADMIN', 'admin', 'for administrator'), @@ -1445,6 +1446,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (1,'doc','edit'), (1,'doc','editLib'), (1,'doc','index'), +(1,'doc','tableContents'), (1,'doc','objectLibs'), (1,'doc','showFiles'), (1,'doc','sort'), @@ -1860,6 +1862,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (2,'doc','create'), (2,'doc','edit'), (2,'doc','index'), +(2,'doc','tableContents'), (2,'doc','objectLibs'), (2,'doc','showFiles'), (2,'doc','view'), @@ -2055,6 +2058,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (3,'doc','create'), (3,'doc','edit'), (3,'doc','index'), +(3,'doc','tableContents'), (3,'doc','objectLibs'), (3,'doc','showFiles'), (3,'doc','view'), @@ -2305,6 +2309,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (4,'doc','edit'), (4,'doc','editLib'), (4,'doc','index'), +(4,'doc','tableContents'), (4,'doc','objectLibs'), (4,'doc','showFiles'), (4,'doc','view'), @@ -2599,6 +2604,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (5,'doc','edit'), (5,'doc','editLib'), (5,'doc','index'), +(5,'doc','tableContents'), (5,'doc','objectLibs'), (5,'doc','showFiles'), (5,'doc','view'), @@ -2921,6 +2927,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (6,'doc','edit'), (6,'doc','editLib'), (6,'doc','index'), +(6,'doc','tableContents'), (6,'doc','objectLibs'), (6,'doc','showFiles'), (6,'doc','view'), @@ -3197,6 +3204,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (7,'doc','edit'), (7,'doc','editLib'), (7,'doc','index'), +(7,'doc','tableContents'), (7,'doc','objectLibs'), (7,'doc','showFiles'), (7,'doc','view'), @@ -3485,6 +3493,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (8,'doc','edit'), (8,'doc','editLib'), (8,'doc','index'), +(8,'doc','tableContents'), (8,'doc','objectLibs'), (8,'doc','showFiles'), (8,'doc','view'), @@ -3768,6 +3777,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (9,'doc','edit'), (9,'doc','editLib'), (9,'doc','index'), +(9,'doc','tableContents'), (9,'doc','objectLibs'), (9,'doc','showFiles'), (9,'doc','view'), @@ -3980,6 +3990,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (10,'doc','allLibs'), (10,'doc','browse'), (10,'doc','index'), +(10,'doc','tableContents'), (10,'doc','objectLibs'), (10,'doc','showFiles'), (10,'doc','view'), @@ -4101,6 +4112,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES (11,'doc','allLibs'), (11,'doc','browse'), (11,'doc','index'), +(11,'doc','tableContents'), (11,'doc','objectLibs'), (11,'doc','showFiles'), (11,'doc','view'), diff --git a/doc/CHANGELOG b/doc/CHANGELOG index 2bd53acec8..9dc2f066b8 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -1,3 +1,108 @@ +2021-08-04 15.3 +完成的需求 +27092 文档下拉菜单中增加附件库的选择 +26857 禅道右下角显示禅道版本号方便商务支持同事排查问题节省交互时间 +26773 在文档全屏的时候显示上一篇、下一篇的操作 +26772 文档增加全屏查看功能 +26771 文档大纲支持展开/收起功能 +26770 文档详情页面增加文档大纲功能 +15718 项目集列表中,负责人名称前显示头像 +26766 目录的操作按钮放置到目录页面的右侧 +26765 对创建下拉菜单中的内容进行分组 +26764 在具体的文档库页面增加我的收藏快速入口 +26763 文档库增加目录页面 +26469 文档名称的font-size使用20px +26467 编辑文档页面,去掉三级导航 +26465 创建文档页面,去掉三级导航 +26463 手册模块中增加目录的高度 +26461 文档模块中增加目录信息 +26400 创建文档名称调整为创建 +26768 将关键词作为标签放到文档名称下面 +27489 实现附件库的卡片展示方式 +27488 实现附件库的列表展示方式 +27477 执行二级导航中执行名称前显示项目名称 +27476 禅道升级新版本后,引导用户使用青春蓝的主题 +27474 禅道更新全新icon +27433 禅道新增配色样式 +27432 实现项目卡片展示方式 +27098 项目库下拉菜单中可以搜索和查看已结束的项目文档 +27430 项目列表增加卡片视图的切换方式 +27429 调整产品列表中字段的显示顺序 +27428 产品列表中增加项目集、产品线列表的数据统计 +27427 产品列表中将编辑产品线调整到添加产品按钮前面 +27426 项目集列表中项目名称前的项目icon调整为模型icon +27425 项目集列表增加进度显示 +27424 调整项目集列表中字段的显示顺序 +27421 项目集列表调整项目和项目集添加方式的位置 +27389 任务bug列表把截止日期展示出来 +27270 升级程序中的sql需要兼容引擎只支持innodb的环境 +27260 文档目录中在具体的文档前面增加icon +27431 项目卡片视图中增加项目集筛选菜单 +修复的Bug +11198 升级到旗舰版后系统用户默认权限没有添加导致用户登录后无法正常访问 +12197 项目下新建文档保存后页面未正确展示 +12318 max2.0rc1 关于工作流:1.字段-公示类型的,无法生效 2.详情 动作界面,编辑--区块,无法添加 +12573 客户端消息右键创建任务页面所属执行没有列出阶段 +12846 word类型文档编辑页面文档类型没有默认值 +13141 新版本动作界面附件字段不显示 +13386 biz4.1按老版本习惯升级后,待办转任务未关联处项目数据 +13460 工作流项目流程字段和动作展示问题 +13536 请假详情页点击拒绝后跳转到了编辑页 +13039 任务看板导出和页面显示内容不一致 +13092 所有产品、项目不支持导出 +13377 pro7.1按老版本习惯升级后,新建产品保存时有错误提示信息 +12807 数据量多的时候创建索引时间很久 +12476 客户端中进入禅道相关页面加载错误 +12930 年底统计报表中需求创建数量不对 +13420 集成gitlab后查看代码页面报错 +13638 gitlab类型的版本库页面有代码报错 +13639 关联issue页面有代码报错 +13722 执行动态页面报错 +13647 创建需求、任务、Bug同步到gitlab,有js报错 +11269 beta3中有测试代码导致报错 +12412 主表设计下载的模板全是报错 +12422 主表字段导入确认页面显示问题 +12673 干系人相关动态文案需修改 +12928 权限分组列表显示的数据不全 +13059 创建的scrum项目无法保存 +13096 项目矩阵显示了与该项目无关的需求 +13097 任务不能记录日志 +13238 问题确认弹窗显示异常,无法操作 +13239 问题解决方式为转任务后,保存提示开始时间不能为空 +13278 旗舰版新增工作流发布在执行二级导航时,页面跳转有问题 +13332 瀑布模式单独创建阶段还需要维护阶段代号 +13346 通过阶段设置插入阶段会修改之前阶段的ID +13512 评审页面查看用例所属的产品时闪现代码 +13523 集成测试用例评审页面查看用例时有代码报错 +13530 自定义配置的模板类型发起评审时也列出来了 +13532 评审用户需求说明书页面有代码报错 +13538 评审软件需求说明书页面有代码报错 +13717 给瀑布项目会显示“所属迭代” +13486 创建FAQ页面有代码报错 +13559 项目内置流程新增字段在列表不显示 +13608 工作流新增字段默认值设置不生效 +12201 统计里报表涉及到项目的都显示为执行了 +13213 专业版App发布详情页有报错 +13243 变更需求导出 word 最后编辑日期为 0000-00-00 +13244 需求导出 word 展示模块取值错误 +13258 需求导出 word 图片大小适配问题 +13265 产品项目列表的迭代改为项目 +13564 自定义报表中项目计划完成日期统计有问题 +13724 移动端需求排序报错 +12106 批量编辑需求阶段显示报错 +13716 权限名称和对应页面菜单名字不一致 +6900 搜索用户名时,不显示用户名信息 +13045 新建产品是否需要强制关联产品规则统一 +13216 php5.3环境代码兼容问题 +13516 早上在执行下面操作完成第一个任务后会提示你无权限访问该迭代 +13616 再次编辑飞书配置时丢失秘钥 +13632 测试单中查看报表报错 +13659 测试单生成报表报错 +13701 批量编辑任务页面起止日期字段显示不全 +13703 甘特图百分比统计错误 +13721 按老版本习惯升级后,jenkins服务器数据丢失 +13725 测试-用例-导出模板-CSV文件名字拼错 + 2021-07-20 15.2 完成的需求 27297 调整产品下拉菜单信息展现方式 @@ -2122,7 +2227,7 @@ 1601 版本列表区块,版本ID显示为1、2,统一为001、002 1600 Bug详情页,解决操作没有图标,严重程度图标数字太靠上 1599 右上角,用户名--切换语言。显示的是英文 language ,简体和繁体下应显示为中文 -1597 永久关闭区块的提示文案,第二句开头少一个‘关’字,最后少个句号 [BUG#1597] +1597 永久关闭区块的提示文案,第二句开头少一个‘关’字,最后少个句号 1595 我的地盘里,编辑页面的 保存和取消 按钮的间距宽度比较宽,是否整个系统里统一一下保存和取消(返回)的间距宽度 1592 我的待办区块,添加待办成功后,跳转到区块底部 1591 我的待办区块,点击待办名称,然后编辑,待办名称必填项与边框有重叠 diff --git a/framework/api/entry.class.php b/framework/api/entry.class.php index 70a4ea7a3f..f48391751a 100644 --- a/framework/api/entry.class.php +++ b/framework/api/entry.class.php @@ -10,6 +10,8 @@ class entry extends baseEntry parent::__construct(); if(!isset($this->app->user)) $this->sendError(401, 'Unauthorized'); + + $this->dao = $this->loadModel('common')->dao; } } @@ -47,8 +49,9 @@ class baseEntry */ public function __construct() { - global $app; - $this->app = $app; + global $app, $config; + $this->app = $app; + $this->config = $config; $this->parseRequestBody(); } @@ -83,6 +86,20 @@ class baseEntry return $defaultValue; } + /** + * 设置请求参数 + * Set request param. + * + * @param string $key + * @param mixed $value + * @access public + * @return mixed + */ + public function setParam($key, $value) + { + $_GET[$key] = $value; + } + /** * 解析请求数据 * Parse body of request data. @@ -202,6 +219,17 @@ class baseEntry $this->send($code, $response); } + /** + * Send 404 response. + * + * @access public + * @return void + */ + public function send404() + { + $this->sendError(404, '404 Not found'); + } + /** * 加载禅道的控制器类 * Load controller of zentaopms @@ -305,9 +333,8 @@ class baseEntry */ public function getData() { - $output = ob_get_clean(); + $output = helper::removeUTF8Bom(ob_get_clean()); $output = json_decode($output); - if(isset($output->data)) $output->data = json_decode($output->data); return $output; @@ -476,9 +503,8 @@ class baseEntry return gmdate("Y-m-d\TH:i:s\Z", strtotime($value)); } return $value; - case 'int': case 'bool': - return $value; + return boolval($value) ? true : false; default: return $value; } diff --git a/framework/api/helper.class.php b/framework/api/helper.class.php new file mode 100644 index 0000000000..393952e38d --- /dev/null +++ b/framework/api/helper.class.php @@ -0,0 +1,219 @@ +requestType != 'GET') + { + $pathInfo = $app->getPathInfo(); + if(!empty($pathInfo)) + { + $dotPos = strrpos($pathInfo, '.'); + if($dotPos) + { + $viewType = substr($pathInfo, $dotPos + 1); + } + else + { + $config->default->view = $config->default->view == 'mhtml' ? 'html' : $config->default->view; + } + } + } + elseif($config->requestType == 'GET') + { + if(isset($_GET[$config->viewVar])) + { + $viewType = $_GET[$config->viewVar]; + } + else + { + /* Set default view when url has not module name. such as only domain. */ + $config->default->view = ($config->default->view == 'mhtml' and isset($_GET[$config->moduleVar])) ? 'html' : $config->default->view; + } + } + if($source and isset($viewType)) return $viewType; + + if(isset($viewType) and strpos($config->views, ',' . $viewType . ',') === false) $viewType = $config->default->view; + return isset($viewType) ? $viewType : $config->default->view; + } + + /** + * Encode json for $.parseJSON + * + * @param array $data + * @param int $options + * @static + * @access public + * @return string + */ + public static function jsonEncode4Parse($data, $options = 0) + { + $json = json_encode($data); + if($options) $json = str_replace(array("'", '"'), array('\u0027', '\u0022'), $json); + + $escapers = array("\\", "/", "\"", "'", "\n", "\r", "\t", "\x08", "\x0c", "\\\\u"); + $replacements = array("\\\\", "\\/", "\\\"", "\'", "\\n", "\\r", "\\t", "\\f", "\\b", "\\u"); + return str_replace($escapers, $replacements, $json); + } + + /** + * Convert encoding. + * + * @param string $string + * @param string $fromEncoding + * @param string $toEncoding + * @static + * @access public + * @return string + */ + public static function convertEncoding($string, $fromEncoding, $toEncoding = 'utf-8') + { + $toEncoding = str_replace('utf8', 'utf-8', $toEncoding); + if(function_exists('mb_convert_encoding')) + { + /* Remove like utf-8//TRANSLIT. */ + $position = strpos($toEncoding, '//'); + if($position !== false) $toEncoding = substr($toEncoding, 0, $position); + + /* Check string encoding. */ + $encodings = array_merge(array('GB2312','GBK','BIG5'), mb_list_encodings()); + $encoding = strtolower(mb_detect_encoding($string, $encodings)); + if($encoding == $toEncoding) return $string; + return mb_convert_encoding($string, $toEncoding, $encoding); + } + elseif(function_exists('iconv')) + { + if($fromEncoding == $toEncoding) return $string; + $convertString = @iconv($fromEncoding, $toEncoding, $string); + /* iconv error then return original. */ + if(!$convertString) return $string; + return $convertString; + } + + return $string; + } + + /** + * Calculate two working days. + * + * @param string $begin + * @param string $end + * + * @return bool|float + */ + public static function workDays($begin, $end) + { + $begin = strtotime($begin); + $end = strtotime($end); + if($end < $begin) return false; + + $double = floor(($end - $begin) / (7 * 24 * 3600)); + $begin = date('w', $begin); + $end = date('w', $end); + $end = $begin > $end ? $end + 5 : $end; + return $double * 5 + $end - $begin; + } + + /** + * Unify string to standard chars. + * + * @param string $string + * @param string $to + * @static + * @access public + * @return string + */ + public static function unify($string, $to = ',') + { + $labels = array('_', '、', ' ', '-', '?', '@', '&', '%', '~', '`', '+', '*', '/', '\\', ',', '。'); + $string = str_replace($labels, $to, $string); + return preg_replace("/[{$to}]+/", $to, trim($string, $to)); + } + + /** + * Create url of issue. + * + * @param string $module + * @param string $method + * @param string $vars + * @static + * @access public + * @return string + */ + static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlyBody = false) + { + global $config; + $link = parent::createLink($moduleName, $methodName, $vars, 'html'); + $pos = strpos($link, '.php'); + + /* The requestTypes are: GET, PATH_INFO2, PATH_INFO */ + if($config->requestType == 'GET') + { + $link = '/index' . substr($link, $pos); + } + elseif($config->requestType == 'PATH_INFO2') + { + $link = substr($link, $pos + 4); + } + return common::getSysURL() . $link; + } +} + +/** + * 检查是否是onlybody模式。 + * Check exist onlybody param. + * + * @access public + * @return void + */ +function isonlybody() +{ + return helper::inOnlyBodyMode(); +} + +/** + * Format time. + * + * @param int $time + * @param string $format + * @access public + * @return void + */ +function formatTime($time, $format = '') +{ + $time = str_replace('0000-00-00', '', $time); + $time = str_replace('00:00:00', '', $time); + if(trim($time) == '') return ; + if($format) return date($format, strtotime($time)); + return trim($time); +} + +/** + * Fix for session error. + * + * @param int $class + * @access protected + * @return void + */ +function autoloader($class) +{ + if(!class_exists($class)) + { + if($class == 'post_max_size' or $class == 'max_input_vars') eval('class ' . $class . ' {};'); + } +} + +spl_autoload_register('autoloader'); diff --git a/framework/base/helper.class.php b/framework/base/helper.class.php index 01abfd7f3e..4e7958ecf2 100644 --- a/framework/base/helper.class.php +++ b/framework/base/helper.class.php @@ -843,7 +843,7 @@ function getWebRoot($full = false) /** * 当数组/对象变量$var存在$key项时,返回存在的对应值或设定值,否则返回$key或不存在的设定值。 - * When the $var has the $key, return it, esle result one default value. + * When there is a $key in the array/object $var, it returns it or $valueWhenExists, otherwise returns $key or $valueWhenNone. * * @param array|object $var * @param string|int $key diff --git a/framework/base/model.class.php b/framework/base/model.class.php index 5feac4a9cb..0ce7ba892f 100644 --- a/framework/base/model.class.php +++ b/framework/base/model.class.php @@ -7,7 +7,7 @@ * * The author disclaims copyright to this source code. In place of * a legal notice, here is a blessing: - * + * * May you do good and not evil. * May you find forgiveness for yourself and forgive others. * May you share freely, never taking more than you give. @@ -17,7 +17,7 @@ class baseModel /** * 全局对象$app。 * The global $app object. - * + * * @var object * @access public */ @@ -26,7 +26,7 @@ class baseModel /** * 应用名称$appName。 * The global appName. - * + * * @var string * @access public */ @@ -35,7 +35,7 @@ class baseModel /** * 全局对象$config。 * The global $config object. - * + * * @var object * @access public */ @@ -44,7 +44,7 @@ class baseModel /** * 全局对象$lang。 * The global $lang object. - * + * * @var object * @access public */ @@ -53,7 +53,7 @@ class baseModel /** * 全局对象$dbh,数据库连接句柄。 * The global $dbh object, the database connection handler. - * + * * @var object * @access public */ @@ -62,7 +62,7 @@ class baseModel /** * $dao对象,用于访问或者更新数据库。 * The $dao object, used to access or update database. - * + * * @var object * @access public */ @@ -71,7 +71,7 @@ class baseModel /** * $post对象,用于访问$_POST变量。 * The $post object, used to access the $_POST var. - * + * * @var object * @access public */ @@ -80,7 +80,7 @@ class baseModel /** * $get对象,用于访问$_GET变量。 * The $get object, used to access the $_GET var. - * + * * @var object * @access public */ @@ -89,7 +89,7 @@ class baseModel /** * $session对象,用于访问$_SESSION变量。 * The $session object, used to access the $_SESSION var. - * + * * @var object * @access public */ @@ -98,7 +98,7 @@ class baseModel /** * $server对象,用于访问$_SERVER变量。 * The $server object, used to access the $_SERVER var. - * + * * @var object * @access public */ @@ -107,7 +107,7 @@ class baseModel /** * $cookie对象,用于访问$_COOKIE变量。 * The $cookie object, used to access the $_COOKIE var. - * + * * @var object * @access public */ @@ -116,7 +116,7 @@ class baseModel /** * $global对象,用于访问$_GLOBAL变量。 * The $global object, used to access the $_GLOBAL var. - * + * * @var object * @access public */ @@ -126,12 +126,12 @@ class baseModel * 构造方法。 * 1. 将全局变量设为model类的成员变量,方便model的派生类调用; * 2. 设置$config, $lang, $dbh, $dao。 - * + * * The construct function. * 1. global the global vars, refer them by the class member such as $this->app. * 2. set the pathes, config, lang of current module * - * @param string $appName + * @param string $appName * @access public * @return void */ @@ -158,7 +158,7 @@ class baseModel * 这个方法通过去掉该model类名的'ext'和'model'字符串,来获取当前模块名。 * 不要使用$app->getModuleName(),因为其返回的是用户请求的模块名。 * 另一个model可以通过loadModel()加载进来,与请求的模块名不一致。 - * + * * Get the module name of this model. Not the module user visiting. * * This method replace the 'ext' and 'model' string from the model class name, thus get the module name. @@ -180,7 +180,7 @@ class baseModel /** * 设置全局超级变量。 * Set the super vars. - * + * * @access public * @return void */ @@ -198,7 +198,7 @@ class baseModel * 比如:loadModel('user')引入user模块的model实例对象,可以通过$this->user来访问它。 * * Load the model of one module. After loaded, can use $this->$moduleName to visit the model object. - * + * * @param string $moduleName * @access public * @return object|bool the model object or false if model file not exists. @@ -207,6 +207,7 @@ class baseModel { if(empty($moduleName)) return false; if(empty($appName)) $appName = $this->appName; + $moduleName = strtolower($moduleName); global $loadedModels; if(isset($loadedModels[$appName][$moduleName])) @@ -242,9 +243,9 @@ class baseModel * And call them by the ext/model/$extension.php like this: $this->loadExtension('myextension')->method(). * You can encrypt the code in ext/model/class/*.class.php. * Because the framework will merge the extension files in ext/model/*.php to the module/model.php. - * - * @param string $extensionName - * @param string $moduleName + * + * @param string $extensionName + * @param string $moduleName * @access public * @return void */ @@ -253,8 +254,9 @@ class baseModel if(empty($extensionName)) return false; /* 设置扩展的名字和相应的文件。Set extenson name and extension file. */ - $extensionName = strtolower($extensionName); $moduleName = $moduleName ? $moduleName : $this->getModuleName(); + $moduleName = strtolower($moduleName); + $extensionName = strtolower($extensionName); $moduleExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'model'); if(!empty($moduleExtPath['site'])) $extensionFile = $moduleExtPath['site'] . 'class/' . $extensionName . '.class.php'; if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['common'] . 'class/' . $extensionName . '.class.php'; @@ -278,7 +280,7 @@ class baseModel /** * 加载DAO。 * Load DAO. - * + * * @access public * @return void */ @@ -290,7 +292,7 @@ class baseModel /** * 删除记录。 * Delete one record. - * + * * @param string $table the table name * @param string $id the id value of the record to be deleted * @access public diff --git a/framework/base/router.class.php b/framework/base/router.class.php index ded80fbd7d..e49536f612 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -609,8 +609,12 @@ class baseRouter if($this->config->framework->filterCSRF) { $httpType = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http'; + if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') $httpType = 'https'; + if(isset($_SERVER['REQUEST_SCHEME']) and strtolower($_SERVER['REQUEST_SCHEME']) == 'https') $httpType = 'https'; + $httpHost = $_SERVER['HTTP_HOST']; - if((!defined('RUN_MODE') or RUN_MODE != 'api') and strpos($this->server->http_referer, "$httpType://$httpHost") !== 0) $_FILES = $_POST = array(); + $isAPI = (defined('RUN_MODE') && RUN_MODE == 'api') || isset($_GET[$this->config->sessionVar]); + if(!$isAPI && strpos($this->server->http_referer, "$httpType://$httpHost") !== 0) $_FILES = $_POST = array(); } $_FILES = validater::filterFiles(); @@ -849,23 +853,22 @@ class baseRouter */ public function startSession() { - if(!defined('SESSION_STARTED')) - { - /* If request header has token, use it as session for authentication. */ - if(isset($_SERVER['HTTP_TOKEN'])) session_id($_SERVER['HTTP_TOKEN']); + if(defined('SESSION_STARTED')) return; - $sessionName = $this->config->sessionVar; - session_name($sessionName); - session_set_cookie_params(0, $this->config->webRoot, '', $this->config->cookieSecure, true); - if($this->config->customSession) session_save_path($this->getTmpRoot() . 'session'); - session_start(); + /* If request header has token, use it as session for authentication. */ + if(isset($_SERVER['HTTP_TOKEN'])) session_id($_SERVER['HTTP_TOKEN']); - $this->sessionID = session_id(); + $sessionName = $this->config->sessionVar; + session_name($sessionName); + session_set_cookie_params(0, $this->config->webRoot, '', $this->config->cookieSecure, true); + if($this->config->customSession) session_save_path($this->getTmpRoot() . 'session'); + session_start(); - if(isset($_GET[$this->config->sessionVar])) helper::restartSession($_GET[$this->config->sessionVar]); + $this->sessionID = session_id(); - define('SESSION_STARTED', true); - } + if(isset($_GET[$this->config->sessionVar])) helper::restartSession($_GET[$this->config->sessionVar]); + + define('SESSION_STARTED', true); } /** 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/base/pager/pager.class.php b/lib/base/pager/pager.class.php index f6ddc7f2c7..262b00539c 100644 --- a/lib/base/pager/pager.class.php +++ b/lib/base/pager/pager.class.php @@ -131,10 +131,10 @@ class basePager $this->setModuleName(); $this->setMethodName(); - $this->setRecTotal($recTotal); - $this->setRecPerPage($recPerPage); + $this->setRecTotal((int)$recTotal); + $this->setRecPerPage((int)$recPerPage); $this->setPageTotal(); - $this->setPageID($pageID); + $this->setPageID((int)$pageID); } /** diff --git a/lib/pager/pager.class.php b/lib/pager/pager.class.php index c65a1122db..1dd0dac22a 100644 --- a/lib/pager/pager.class.php +++ b/lib/pager/pager.class.php @@ -5,7 +5,7 @@ * * The author disclaims copyright to this source code. In place of * a legal notice, here is a blessing: - * + * * May you do good and not evil. * May you find forgiveness for yourself and forgive others. * May you share freely, never taking more than you give. @@ -15,7 +15,7 @@ helper::import(dirname(dirname(__FILE__)) . '/base/pager/pager.class.php'); /** * pager类. * Pager class. - * + * * @package framework */ class pager extends basePager @@ -23,7 +23,7 @@ class pager extends basePager /** * 设置模块名。 * Set the $moduleName property. - * + * * @access public * @return void */ @@ -44,7 +44,7 @@ class pager extends basePager /** * 设置方法名。 * Set the $methodName property. - * + * * @access public * @return void */ @@ -65,7 +65,7 @@ class pager extends basePager /** * 如果设置了请求的原始模块名和方法名,则去掉module参数,以便分页功能生成原始请求的URL而不是转换后的工作流URL。 * If the original module name and method name of the request are set, the module parameter is removed so that - * the paging function generates the URL of the original request instead of the converted workflow URL. + * the paging function generates the URL of the original request instead of the converted workflow URL. * * @access public * @return void @@ -87,9 +87,9 @@ class pager extends basePager /** * Show pager. - * - * @param string $align - * @param string $type + * + * @param string $align + * @param string $type * @access public * @return void */ diff --git a/lib/scm/gitlab.class.php b/lib/scm/gitlab.class.php index 82bf44ea1a..a5c472ed06 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)); @@ -168,10 +169,15 @@ class gitlab $list = $this->fetch($api, $params); if(empty($list)) break; - foreach($list as $branch) $branches[$branch->name] = $branch->name; + foreach($list as $branch) + { + if(!isset($branch->name)) continue; + $branches[$branch->name] = $branch->name; + } if(count($list) < $params['per_page']) break; } + if(empty($branches)) $branches['master'] = 'master'; asort($branches); return $branches; } @@ -517,7 +523,8 @@ class gitlab if(!scm::checkRevision($version)) return array(); $api = "commits"; - if(empty($count)) $count = 100; + /* TODO Put getCommits into cron job. And check best size of $count. */ + if(empty($count)) $count = 10; $params = array(); $params['ref_name'] = $branch; @@ -617,7 +624,6 @@ class gitlab $params->per_page = 100; $allResults = array(); - $files = array(); while(true) { $results = $this->fetch($api, $params); diff --git a/lib/scm/gitrepo.class.php b/lib/scm/gitrepo.class.php index 297adc4337..0d7cca6f6f 100644 --- a/lib/scm/gitrepo.class.php +++ b/lib/scm/gitrepo.class.php @@ -125,7 +125,6 @@ class GitRepo $list = execCmd($cmd . ' 2>&1', 'array', $result); if($result) return array(); - $branches = array(); foreach($list as $localBranch) { diff --git a/module/action/config.php b/module/action/config.php index 8319fefa2a..568e426ba1 100755 --- a/module/action/config.php +++ b/module/action/config.php @@ -46,3 +46,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,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,'; +$config->action->noLinkModules = ',doclib,module,webhook,gitlab,pipeline,jenkins,'; diff --git a/module/action/lang/de.php b/module/action/lang/de.php index 5a67dedaa2..3433bcbcf7 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -441,6 +441,7 @@ $lang->action->dynamicAction->doc['hidden'] = 'Hide Document'; $lang->action->dynamicAction->user['created'] = 'Create User'; $lang->action->dynamicAction->user['edited'] = 'Edit User'; +$lang->action->dynamicAction->user['deleted'] = 'Delete User'; $lang->action->dynamicAction->user['login'] = 'Login'; $lang->action->dynamicAction->user['logout'] = 'Logout'; $lang->action->dynamicAction->user['undeleted'] = 'Restore User'; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index e3b3b3aee2..a39bcf993c 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -103,7 +103,9 @@ $lang->action->objectTypes['entry'] = 'Entry'; $lang->action->objectTypes['webhook'] = 'Webhook'; $lang->action->objectTypes['team'] = 'Team'; $lang->action->objectTypes['whitelist'] = 'Whitelist'; -$lang->action->objectTypes['pipeline'] = 'GitLib'; +$lang->action->objectTypes['pipeline'] = 'GitLab'; +$lang->action->objectTypes['gitlab'] = 'GitLab'; +$lang->action->objectTypes['jenkins'] = 'Jenkins'; /* Used to describe operation history. */ $lang->action->desc = new stdclass(); @@ -445,6 +447,7 @@ $lang->action->dynamicAction->doc['hidden'] = 'Hide Document'; $lang->action->dynamicAction->user['created'] = 'Create User'; $lang->action->dynamicAction->user['edited'] = 'Edit User'; +$lang->action->dynamicAction->user['deleted'] = 'Delete User'; $lang->action->dynamicAction->user['login'] = 'Login'; $lang->action->dynamicAction->user['logout'] = 'Logout'; $lang->action->dynamicAction->user['undeleted'] = 'Restore User'; @@ -477,7 +480,7 @@ $lang->action->label->testtask = 'Request|testtask|view|caseID=%s'; $lang->action->label->testsuite = 'Test Suite|testsuite|view|suiteID=%s'; $lang->action->label->caselib = 'Case Library|caselib|view|libID=%s'; $lang->action->label->todo = 'Todo|todo|view|todoID=%s'; -$lang->action->label->doclib = 'Doc Library|doc|browse|libID=%s'; +$lang->action->label->doclib = 'Doc Library|doc|objectLibs|type=%s&objectID=%s&libID=%s&docID=&version=&appendLib=%s'; $lang->action->label->doc = 'Doc|doc|view|docID=%s'; $lang->action->label->user = 'User|user|view|account=%s'; $lang->action->label->testreport = 'Report|testreport|view|report=%s'; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index 7555229f72..4477988521 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -454,6 +454,7 @@ $lang->action->dynamicAction->doc['hidden'] = 'Masquer Document'; $lang->action->dynamicAction->user['created'] = 'Créer User'; $lang->action->dynamicAction->user['edited'] = 'Editer User'; +$lang->action->dynamicAction->user['deleted'] = 'Delete User'; $lang->action->dynamicAction->user['login'] = 'Connexion'; $lang->action->dynamicAction->user['logout'] = 'Déconnexion'; $lang->action->dynamicAction->user['undeleted'] = 'Restaure User'; diff --git a/module/action/lang/vi.php b/module/action/lang/vi.php index fe86495b31..a3545c5e43 100644 --- a/module/action/lang/vi.php +++ b/module/action/lang/vi.php @@ -441,6 +441,7 @@ $lang->action->dynamicAction->doc['hidden'] = 'Ẩn tài liệu'; $lang->action->dynamicAction->user['created'] = 'Tạo người dùng'; $lang->action->dynamicAction->user['edited'] = 'Sửa người dùng'; +$lang->action->dynamicAction->user['deleted'] = 'Delete User'; $lang->action->dynamicAction->user['login'] = 'Đăng nhập'; $lang->action->dynamicAction->user['logout'] = 'Thoát'; $lang->action->dynamicAction->user['undeleted'] = 'Khôi phục người dùng'; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index a328ca7951..334ccb1cad 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -103,7 +103,9 @@ $lang->action->objectTypes['entry'] = '应用'; $lang->action->objectTypes['webhook'] = 'Webhook'; $lang->action->objectTypes['team'] = '团队'; $lang->action->objectTypes['whitelist'] = '白名单'; -$lang->action->objectTypes['pipeline'] = 'GitLib'; +$lang->action->objectTypes['pipeline'] = 'GitLab'; +$lang->action->objectTypes['gitlab'] = 'GitLab'; +$lang->action->objectTypes['jenkins'] = 'Jenkins'; /* 用来描述操作历史记录。*/ $lang->action->desc = new stdclass(); @@ -445,6 +447,7 @@ $lang->action->dynamicAction->doc['hidden'] = '隐藏文档'; $lang->action->dynamicAction->user['created'] = '创建用户'; $lang->action->dynamicAction->user['edited'] = '编辑用户'; +$lang->action->dynamicAction->user['deleted'] = '删除用户'; $lang->action->dynamicAction->user['login'] = '用户登录'; $lang->action->dynamicAction->user['logout'] = '用户退出'; $lang->action->dynamicAction->user['undeleted'] = '还原用户'; @@ -477,7 +480,7 @@ $lang->action->label->testtask = '测试单|testtask|view|caseID=%s'; $lang->action->label->testsuite = '测试套件|testsuite|view|suiteID=%s'; $lang->action->label->caselib = '用例库|caselib|view|libID=%s'; $lang->action->label->todo = '待办|todo|view|todoID=%s'; -$lang->action->label->doclib = '文档库|doc|objectLibs|type=&objectID=&libID=%s'; +$lang->action->label->doclib = '文档库|doc|objectLibs|type=%s&objectID=%s&libID=%s&docID=&version=&appendLib=%s'; $lang->action->label->doc = '文档|doc|view|docID=%s'; $lang->action->label->user = '用户|user|view|account=%s'; $lang->action->label->testreport = '报告|testreport|view|report=%s'; diff --git a/module/action/lang/zh-tw.php b/module/action/lang/zh-tw.php index 971716aafe..f8a0d6950d 100755 --- a/module/action/lang/zh-tw.php +++ b/module/action/lang/zh-tw.php @@ -103,7 +103,9 @@ $lang->action->objectTypes['entry'] = '應用'; $lang->action->objectTypes['webhook'] = 'Webhook'; $lang->action->objectTypes['team'] = '團隊'; $lang->action->objectTypes['whitelist'] = '白名單'; -$lang->action->objectTypes['pipeline'] = 'GitLib'; +$lang->action->objectTypes['pipeline'] = 'GitLab'; +$lang->action->objectTypes['gitlab'] = 'GitLab'; +$lang->action->objectTypes['jenkins'] = 'Jenkins'; /* 用來描述操作歷史記錄。*/ $lang->action->desc = new stdclass(); @@ -445,6 +447,7 @@ $lang->action->dynamicAction->doc['hidden'] = '隱藏文檔'; $lang->action->dynamicAction->user['created'] = '創建用戶'; $lang->action->dynamicAction->user['edited'] = '編輯用戶'; +$lang->action->dynamicAction->user['deleted'] = '刪除用戶'; $lang->action->dynamicAction->user['login'] = '用戶登錄'; $lang->action->dynamicAction->user['logout'] = '用戶退出'; $lang->action->dynamicAction->user['undeleted'] = '還原用戶'; @@ -477,7 +480,7 @@ $lang->action->label->testtask = '測試單|testtask|view|caseID=%s'; $lang->action->label->testsuite = '測試套件|testsuite|view|suiteID=%s'; $lang->action->label->caselib = '用例庫|caselib|view|libID=%s'; $lang->action->label->todo = '待辦|todo|view|todoID=%s'; -$lang->action->label->doclib = '文檔庫|doc|objectLibs|type=&objectID=&libID=%s'; +$lang->action->label->doclib = '文檔庫|doc|objectLibs|type=%s&objectID=%s&libID=%s&docID=&version=&appendLib=%s'; $lang->action->label->doc = '文檔|doc|view|docID=%s'; $lang->action->label->user = '用戶|user|view|account=%s'; $lang->action->label->testreport = '報告|testreport|view|report=%s'; diff --git a/module/action/model.php b/module/action/model.php index 670ba4be6e..0738ab9bbf 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -36,7 +36,7 @@ class actionModel extends model $actor = $actor ? $actor : $this->app->user->account; $actionType = strtolower($actionType); - $actor = $actionType == 'openedbysystem' ? '' : $actor; + $actor = ($actionType == 'openedbysystem' or $actionType == 'closedbysystem') ? '' : $actor; if($actor == 'guest' and $actionType == 'logout') return false; $objectType = str_replace('`', '', $objectType); @@ -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); @@ -570,12 +569,29 @@ class actionModel extends model $objectIds = array_unique($objectIds); $table = $this->config->objectTables[$objectType]; $field = $this->config->action->objectNameFields[$objectType]; - - $objectNames[$objectType] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs(); + if($objectType == 'pipeline') + { + $objectNames['jenkins'] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->andWhere('type')->eq('jenkins')->fetchPairs(); + $objectNames['gitlab'] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->andWhere('type')->eq('gitlab')->fetchPairs(); + } + else + { + $objectNames[$objectType] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs(); + } } /* Add name field to the trashes. */ - foreach($trashes as $trash) $trash->objectName = isset($objectNames[$trash->objectType][$trash->objectID]) ? $objectNames[$trash->objectType][$trash->objectID] : ''; + foreach($trashes as $trash) + { + $objectType = $trash->objectType; + if($objectType == 'pipeline') + { + if(isset($objectNames['gitlab'][$trash->objectID])) $objectType = 'gitlab'; + if(isset($objectNames['jenkins'][$trash->objectID])) $objectType = 'jenkins'; + $trash->objectType = $objectType; + } + $trash->objectName = isset($objectNames[$objectType][$trash->objectID]) ? $objectNames[$objectType][$trash->objectID] : ''; + } return $trashes; } @@ -928,6 +944,7 @@ class actionModel extends model public function transformActions($actions) { $this->app->loadLang('todo'); + $this->app->loadLang('stakeholder'); $requirements = array(); /* Get commiters. */ @@ -948,7 +965,7 @@ class actionModel extends model $objectName = array(); $objectProject = array(); - if(strpos($this->config->action->needGetProjectType, $objectType) !== false) + if(strpos(",{$this->config->action->needGetProjectType},", ",{$objectType},") !== false) { $objectInfo = $this->dao->select("id, project, $field AS name")->from($table)->where('id')->in($objectIds)->fetchAll(); foreach($objectInfo as $object) @@ -989,6 +1006,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 +1053,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)) { @@ -1086,7 +1110,18 @@ class actionModel extends model } else { - $action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID), '', '', $projectID); + if($action->objectType == 'doclib') + { + $docLib = $this->dao->select('type,product,project,execution,deleted')->from(TABLE_DOCLIB)->where('id')->eq($action->objectID)->fetch(); + $docLib->type = $docLib->type == 'execution' ? 'project' : $docLib->type; + $docLib->objectID = strpos('product,project', $docLib->type) !== false ? $docLib->{$docLib->type} : 0; + $appendLib = $docLib->deleted == '1' ? $action->objectID : 0; + $action->objectLink = helper::createLink('doc', 'objectLibs', sprintf($vars, $docLib->type, $docLib->objectID, $action->objectID, $appendLib)); + } + else + { + $action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID), '', '', $projectID); + } } $action->objectLabel = $objectLabel; } diff --git a/module/action/view/trash.html.php b/module/action/view/trash.html.php index 1e0f21625f..bb1a8d656d 100755 --- a/module/action/view/trash.html.php +++ b/module/action/view/trash.html.php @@ -62,7 +62,7 @@ $flow = $config->action->customFlows[$action->objectType]; $module = $flow->module; } - if(strpos(',doclib,module,webhook,', ",{$module},") !== false) + if(strpos($this->config->action->noLinkModules, ",{$module},") !== false) { echo $action->objectName; } diff --git a/module/backup/view/index.html.php b/module/backup/view/index.html.php index 6d7bef3fd7..5572e7c853 100644 --- a/module/backup/view/index.html.php +++ b/module/backup/view/index.html.php @@ -36,7 +36,7 @@ backup->history?>
- " . $lang->backup->setting, '', "data-width='500' class='iframe btn btn-primary'");?> + " . $lang->backup->setting, '', "data-width='500' class='iframe btn btn-primary'");?> " . $lang->backup->backup, 'hiddenwin', "class='btn btn-primary backup'");?>
diff --git a/module/block/control.php b/module/block/control.php index 9378ba0f6d..272a454181 100644 --- a/module/block/control.php +++ b/module/block/control.php @@ -1750,7 +1750,7 @@ class block extends control $today = helper::today(); $now = date('H:i:s', strtotime(helper::now())); - $meetings = $this->dao->select('*')->from(TABLE_MEETING) + $stmt = $this->dao->select('*')->from(TABLE_MEETING) ->Where('deleted')->eq('0') ->andWhere('(date')->gt($today) ->orWhere('(begin')->gt($now) @@ -1759,9 +1759,10 @@ class block extends control ->andwhere('(host')->eq($this->app->user->account) ->orWhere('participant')->in($this->app->user->account) ->markRight(1) - ->orderBy('id_desc') - ->beginIF(isset($params->meetingNum))->limit($params->meetingNum) - ->fetchAll(); + ->orderBy('id_desc'); + + if(isset($params->meetingNum)) $stmt->limit($params->meetingNum); + $meetings = $stmt->fetchAll(); $count['meeting'] = count($meetings); $this->view->meetings = $meetings; @@ -1832,6 +1833,8 @@ class block extends control /* Get projects. */ $this->app->loadLang('task'); + $this->app->loadLang('program'); + $this->app->loadLang('execution'); $this->view->projects = $this->loadModel('project')->getOverviewList('byStatus', $status, $orderBy, $count); } diff --git a/module/block/view/dashboard.html.php b/module/block/view/dashboard.html.php index 484f5d26dc..2603308dcb 100644 --- a/module/block/view/dashboard.html.php +++ b/module/block/view/dashboard.html.php @@ -121,7 +121,6 @@ $(function() custom: response.data.content, width: 600 }); - myModalTrigger.show(); $('#showAnnual').click(function(){myModalTrigger.close()}); }); } diff --git a/module/block/view/executionblock.html.php b/module/block/view/executionblock.html.php index 90872be781..b02dc4080e 100644 --- a/module/block/view/executionblock.html.php +++ b/module/block/view/executionblock.html.php @@ -57,8 +57,8 @@ hours->totalLeft . $lang->execution->workHourUnit;?> -
-
hours->progress;?>
+
+
hours->progress);?>
diff --git a/module/block/view/productstatisticblock.html.php b/module/block/view/productstatisticblock.html.php index 40f7d58547..0445263b63 100644 --- a/module/block/view/productstatisticblock.html.php +++ b/module/block/view/productstatisticblock.html.php @@ -157,7 +157,7 @@ $(function()
- id}", "" . $lang->productplan->create, '', "class='btn btn-info'");?> + id}", " " . $lang->productplan->create, '', "class='btn btn-info'");?>
@@ -190,7 +190,7 @@ $(function()
- id}", "" . $lang->release->create, '', "class='btn btn-info'");?> + id}", " " . $lang->release->create, '', "class='btn btn-info'");?>
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/block/view/scrumlistblock.html.php b/module/block/view/scrumlistblock.html.php index aaa9cd6499..0a0e911379 100644 --- a/module/block/view/scrumlistblock.html.php +++ b/module/block/view/scrumlistblock.html.php @@ -57,8 +57,8 @@ hours->totalLeft . $lang->execution->workHourUnit;?> -
-
hours->progress;?>
+
+
hours->progress);?>
diff --git a/module/bug/control.php b/module/bug/control.php index 0d64822484..7decc3783f 100644 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -38,7 +38,6 @@ class bug extends control public function __construct($moduleName = '', $methodName = '') { parent::__construct($moduleName, $methodName); - $products = array(); $this->loadModel('product'); $this->loadModel('tree'); $this->loadModel('user'); @@ -48,25 +47,32 @@ class bug extends control $this->loadModel('qa'); /* Get product data. */ + $products = array(); $objectID = 0; - if($this->app->openApp == 'project') + $openApp = ($this->app->openApp == 'project' or $this->app->openApp == 'execution') ? $this->app->openApp : 'qa'; + if(!isonlybody()) { - $objectID = $this->session->project; - $products = $this->loadModel('project')->getProducts($objectID, false); - } - elseif($this->app->openApp == 'execution') - { - $objectID = $this->session->execution; - $products = $this->loadModel('execution')->getProducts($objectID, false); + if($this->app->openApp == 'project') + { + $objectID = $this->session->project; + $products = $this->loadModel('project')->getProducts($objectID, false); + } + elseif($this->app->openApp == 'execution') + { + $objectID = $this->session->execution; + $products = $this->loadModel('execution')->getProducts($objectID, false); + } + else + { + $products = $this->product->getPairs('', 0, 'program_asc'); + } + if(empty($products) and !helper::isAjaxRequest()) die($this->locate($this->createLink('product', 'showErrorNone', "moduleName=$openApp&activeMenu=bug&objectID=$objectID"))); } else { $products = $this->product->getPairs('', 0, 'program_asc'); } - $this->view->products = $this->products = $products; - $openApp = ($this->app->openApp == 'project' or $this->app->openApp == 'execution') ? $this->app->openApp : 'qa'; - if(empty($this->products) and !helper::isAjaxRequest()) die($this->locate($this->createLink('product', 'showErrorNone', "moduleName=$openApp&activeMenu=bug&objectID=$objectID"))); } /** @@ -98,15 +104,13 @@ class bug extends control { $this->loadModel('datatable'); - $products = $this->loadModel('product')->getPairs('noclosed'); - $productID = $this->product->saveState($productID, $products); - $this->qa->setMenu($products, $productID, $branch); + $productID = $this->product->saveState($productID, $this->products); + $this->qa->setMenu($this->products, $productID, $branch); /* Set browse type. */ $browseType = strtolower($browseType); /* Set productID, moduleID, queryID and branch. */ - if(!$this->projectID) $productID = $this->product->saveState($productID, $this->products); $branch = ($branch == '') ? (int)$this->cookie->preBranch : (int)$branch; setcookie('preProductID', $productID, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true); setcookie('preBranch', (int)$branch, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true); @@ -521,7 +525,7 @@ class bug extends control $projects = array(0 => ''); if($executionID) { - $products = array(); + $products = array(); $linkedProducts = $this->loadModel('execution')->getProducts($executionID); foreach($linkedProducts as $product) $products[$product->id] = $product->name; @@ -569,17 +573,6 @@ class bug extends control $this->view->customFields = $customFields; $this->view->showFields = $this->config->bug->custom->createFields; - /* Set gitlabProjects. */ - $this->loadModel('gitlab'); - $allGitlabs = $this->gitlab->getPairs(); - $gitlabProjects = $this->gitlab->getProjectsByExecution($executionID); - foreach($allGitlabs as $id => $name) - { - if($id and !isset($gitlabProjects[$id])) unset($allGitlabs[$id]); - } - $this->view->gitlabList = $allGitlabs; - $this->view->gitlabProjects = $gitlabProjects; - $this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->create; $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); $this->view->position[] = $this->lang->bug->create; @@ -749,6 +742,11 @@ class bug extends control $this->repo->setMenu($repos); $this->lang->navGroup->bug = 'devops'; } + if($this->app->openApp == 'product') + { + $this->loadModel('product')->setMenu($bug->product); + $this->lang->product->menu->plan['subModule'] .= ',bug'; + } } /* Get product info. */ @@ -1298,9 +1296,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; @@ -1478,16 +1473,8 @@ class bug extends control $_POST = array(); $bugs = $this->bug->getByList($bugIDList); - $this->loadModel('gitlab'); foreach($bugs as $bugID => $bug) { - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - if(!empty($relation)) - { - $currentIssue = $this->gitlab->apiGetSingleIssue($relation->gitlabID, $relation->projectID, $relation->issueID); - if($currentIssue->state != 'closed') $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug); - } - if($bug->status != 'resolved') { if($bug->status != 'closed') $skipBugs[$bugID] = $bugID; @@ -1571,11 +1558,6 @@ class bug extends control } else { - /* Delete related issue in gitlab. */ - $this->loadModel('gitlab'); - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - if(!empty($relation)) $this->gitlab->deleteIssue('bug', $bugID, $relation->issueID); - $this->bug->delete(TABLE_BUG, $bugID); if($bug->toTask != 0) { @@ -1592,7 +1574,9 @@ class bug extends control $this->executeHooks($bugID); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess)); - die(js::locate($this->session->bugList, 'parent')); + + $locateLink = $this->session->bugList ? $this->session->bugList : inlink('browse', "productID={$bug->product}"); + die(js::locate($locateLink, 'parent')); } } diff --git a/module/bug/css/edit.css b/module/bug/css/edit.css index 36613d69d7..7f63e63266 100644 --- a/module/bug/css/edit.css +++ b/module/bug/css/edit.css @@ -5,3 +5,4 @@ .chosen-choices li.search-choice {word-break: break-all;} #linkBugBox > li {margin-left: -56px;} #branch {width: 95px;} +#storyIdBox .chosen-auto-max-width {width: 215px !important;} diff --git a/module/bug/js/common.js b/module/bug/js/common.js index 21b9e0fdd8..af1bf9a0bf 100644 --- a/module/bug/js/common.js +++ b/module/bug/js/common.js @@ -525,7 +525,11 @@ function loadAssignedTo(executionID, selectedUser) $('#assignedTo').next('.picker').remove(); $('#assignedTo').replaceWith(data); var defaultAssignedTo = $('#assignedTo').val(); - if(defaultAssignedTo !== oldAssignedTo && selectedUser == '') $('#assignedTo').append(defaultOption); + if(defaultAssignedTo !== oldAssignedTo && selectedUser == '') + { + if($('#assignedTo option[value="' + oldAssignedTo + '"]').length > 0) $('#assignedTo option[value="' + oldAssignedTo + '"]').remove(); + $('#assignedTo').append(defaultOption); + } $('#assignedTo').chosen(); }); } diff --git a/module/bug/js/create.js b/module/bug/js/create.js index 65c4663659..c9cdc7d5ec 100644 --- a/module/bug/js/create.js +++ b/module/bug/js/create.js @@ -168,21 +168,3 @@ $(function() $(window).unload(function(){ if(blockID) window.parent.refreshBlock($('#block' + blockID)); }); - -$(document).ready(function() -{ - $('#gitlab').change(function() - { - host = $('#gitlab').val(); - if(host == '') return false; - projects = ''; - $.each(gitlabProjects[host], function(id, obj){projects = projects + ',' + obj.gitlabProject}); - url = createLink('repo', 'ajaxgetgitlabprojects', "host=" + host + "&projects=" + projects); - - $.get(url, function(response) - { - $('#gitlabProject').html('').append(response); - $('#gitlabProject').chosen().trigger("chosen:updated"); - }); - }); -}); diff --git a/module/bug/lang/de.php b/module/bug/lang/de.php index 045b983582..d93bd7ddf6 100644 --- a/module/bug/lang/de.php +++ b/module/bug/lang/de.php @@ -79,7 +79,7 @@ $lang->bug->lastEditedDate = 'Bearbeitet am'; $lang->bug->fromCase = 'Von Fall'; $lang->bug->toCase = 'Zu Fall'; $lang->bug->colorTag = 'Farb Tag'; -$lang->bug->repairRate = 'Repair Rate'; +$lang->bug->fixedRate = 'Fixed Rate'; /* 方法列表。*/ $lang->bug->index = 'Home'; diff --git a/module/bug/lang/en.php b/module/bug/lang/en.php index 05d1def113..060cfb07c5 100644 --- a/module/bug/lang/en.php +++ b/module/bug/lang/en.php @@ -24,7 +24,6 @@ $lang->bug->storyVersion = 'Story Version'; $lang->bug->color = 'Color'; $lang->bug->task = 'Task'; $lang->bug->title = 'Title'; -$lang->bug->sync2gitlab = 'Sync gitlab'; $lang->bug->severity = 'Severity'; $lang->bug->severityAB = 'S'; $lang->bug->pri = 'Priority'; @@ -80,7 +79,7 @@ $lang->bug->lastEditedDate = 'EditedDate'; $lang->bug->fromCase = 'From Case'; $lang->bug->toCase = 'To Case'; $lang->bug->colorTag = 'Color'; -$lang->bug->repairRate = 'Repair Rate'; +$lang->bug->fixedRate = 'Fixed Rate'; /* Method list. */ $lang->bug->index = 'Bug Home'; diff --git a/module/bug/lang/fr.php b/module/bug/lang/fr.php index 413efae0a8..2eed200247 100644 --- a/module/bug/lang/fr.php +++ b/module/bug/lang/fr.php @@ -79,7 +79,7 @@ $lang->bug->lastEditedDate = 'Date Modif'; $lang->bug->fromCase = 'du CasTest'; $lang->bug->toCase = 'vers CasTest'; $lang->bug->colorTag = 'Couleur'; -$lang->bug->repairRate = 'Repair Rate'; +$lang->bug->fixedRate = 'Repair Rate'; /* 方法列表。*/ $lang->bug->index = 'Accueil Bug'; diff --git a/module/bug/lang/vi.php b/module/bug/lang/vi.php index 0ac08693a6..9572429a46 100644 --- a/module/bug/lang/vi.php +++ b/module/bug/lang/vi.php @@ -79,7 +79,7 @@ $lang->bug->lastEditedDate = 'Ngày sửa'; $lang->bug->fromCase = 'Từ tình huống'; $lang->bug->toCase = 'Tới tình huống'; $lang->bug->colorTag = 'Màu'; -$lang->bug->repairRate = 'Repair Rate'; +$lang->bug->fixedRate = 'Repair Rate'; /* Method list. */ $lang->bug->index = 'Trang Bug'; diff --git a/module/bug/lang/zh-cn.php b/module/bug/lang/zh-cn.php index 6ac50fa6e2..9fc57d6499 100644 --- a/module/bug/lang/zh-cn.php +++ b/module/bug/lang/zh-cn.php @@ -24,7 +24,6 @@ $lang->bug->storyVersion = "{$lang->SRCommon}版本"; $lang->bug->color = '标题颜色'; $lang->bug->task = '相关任务'; $lang->bug->title = 'Bug标题'; -$lang->bug->sync2gitlab = '同步gitlab'; $lang->bug->severity = '严重程度'; $lang->bug->severityAB = '级别'; $lang->bug->pri = '优先级'; @@ -80,7 +79,7 @@ $lang->bug->lastEditedDate = '修改日期'; $lang->bug->fromCase = '来源用例'; $lang->bug->toCase = '生成用例'; $lang->bug->colorTag = '颜色标签'; -$lang->bug->repairRate = '修复率'; +$lang->bug->fixedRate = '修复率'; /* 方法列表。*/ $lang->bug->index = '首页'; diff --git a/module/bug/lang/zh-tw.php b/module/bug/lang/zh-tw.php index 813293bb93..f9c69fb0d3 100644 --- a/module/bug/lang/zh-tw.php +++ b/module/bug/lang/zh-tw.php @@ -24,7 +24,6 @@ $lang->bug->storyVersion = "{$lang->SRCommon}版本"; $lang->bug->color = '標題顏色'; $lang->bug->task = '相關任務'; $lang->bug->title = 'Bug標題'; -$lang->bug->sync2gitlab = '同步gitlab'; $lang->bug->severity = '嚴重程度'; $lang->bug->severityAB = '級別'; $lang->bug->pri = '優先順序'; @@ -60,6 +59,7 @@ $lang->bug->resolvedBuild = '解決版本'; $lang->bug->resolvedDate = '解決日期'; $lang->bug->resolvedDateAB = '解決日期'; $lang->bug->deadline = '截止日期'; +$lang->bug->deadlineAB = '截止'; $lang->bug->plan = '所屬' . '計劃'; $lang->bug->closedBy = '由誰關閉'; $lang->bug->closedDate = '關閉日期'; @@ -79,6 +79,7 @@ $lang->bug->lastEditedDate = '修改日期'; $lang->bug->fromCase = '來源用例'; $lang->bug->toCase = '生成用例'; $lang->bug->colorTag = '顏色標籤'; +$lang->bug->fixedRate = '修復率'; /* 方法列表。*/ $lang->bug->index = '首頁'; diff --git a/module/bug/model.php b/module/bug/model.php index f4d28e43b9..e4ccfe217e 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -84,13 +84,11 @@ class bugModel extends model /* Use classic mode to replace required project. */ if($this->config->systemMode == 'classic' and strpos($this->config->bug->create->requiredFields, 'project') !== false) $this->config->bug->create->requiredFields = str_replace('project', 'execution', $this->config->bug->create->requiredFields); - $this->dao->insert(TABLE_BUG)->data($bug, $skip = 'gitlab,gitlabProject')->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec(); + $this->dao->insert(TABLE_BUG)->data($bug)->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec(); if(!dao::isError()) { $bugID = $this->dao->lastInsertID(); - $this->loadModel('gitlab')->apiCreateIssue($this->post->gitlab, $this->post->gitlabProject, 'bug', $bugID, $bug); - $this->file->updateObjectID($this->post->uid, $bugID, 'bug'); $this->file->saveUpload('bug', $bugID); empty($bug->case) ? $this->loadModel('score')->create('bug', 'create', $bugID) : $this->loadModel('score')->create('bug', 'createFormCase', $bug->case); @@ -342,7 +340,7 @@ class bugModel extends model elseif($browseType == 'bysearch') $bugs = $this->getBySearch($productIDList, $branch, $queryID, $sort, '', $pager, $projectID); elseif($browseType == 'overduebugs') $bugs = $this->getOverdueBugs($productIDList, $branch, $modules, $executions, $sort, $pager, $projectID); - return $this->checkDelayBugs($bugs); + return $this->checkDelayedBugs($bugs); } /** @@ -352,7 +350,7 @@ class bugModel extends model * @access public * @return array */ - public function checkDelayBugs($bugs) + public function checkDelayedBugs($bugs) { foreach ($bugs as $bug) $bug = $this->checkDelayBug($bug); @@ -675,12 +673,6 @@ class bugModel extends model if(!empty($bug->resolvedBy)) $this->loadModel('score')->create('bug', 'resolve', $bugID); $this->file->updateObjectID($this->post->uid, $bugID, 'bug'); - if(!empty($bug)) - { - $this->loadModel('gitlab'); - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID); - } return common::createChanges($oldBug, $bug); } } @@ -802,11 +794,6 @@ class bugModel extends model $this->executeHooks($bugID); $allChanges[$bugID] = common::createChanges($oldBug, $bug); - - /* update bug to gitlab issue. */ - $this->loadModel('gitlab'); - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID); } else { @@ -859,15 +846,8 @@ class bugModel extends model } /* Update bugs. */ - $this->loadModel('gitlab'); foreach($activateBugs as $bugID => $bug) { - if(!empty($bug)) - { - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', (Object)$bug, $bugID); - } - $oldBug = $bugs[$bugID]; $this->dao->update(TABLE_BUG)->data($bug, $skipFields = 'comment')->autoCheck()->where('id')->eq((int)$bugID)->exec(); if(dao::isError()) die(js::error('bug#' . $bugID . dao::getError(true))); @@ -902,16 +882,6 @@ class bugModel extends model ->autoCheck() ->where('id')->eq($bugID)->exec(); - $this->loadModel('gitlab'); - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - $bug = $this->getById($bugID); // Get full bug object to update issue. - $bug->assignee_id = $this->gitlab->getGitlabUserID($relation->gitlabID, $bug->assignedTo); - if($bug->assignee_id != '') - { - /* TODO(dingguodong) we should alert to operator when can not find the user, and the operator should reconfigure user binding. */ - $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID); - } - if(!dao::isError()) return common::createChanges($oldBug, $bug); } @@ -956,7 +926,6 @@ class bugModel extends model { $now = helper::now(); $bugs = $this->getByList($bugIDList); - $this->loadModel('gitlab'); foreach($bugIDList as $bugID) { if($bugs[$bugID]->confirmed) continue; @@ -967,12 +936,6 @@ class bugModel extends model $bug->lastEditedDate = $now; $bug->confirmed = 1; - if(!empty($bug)) - { - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID); - } - $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec(); $this->executeHooks($bugID); } @@ -1064,10 +1027,6 @@ class bugModel extends model /* Link bug to build and release. */ $this->linkBugToBuild($bugID, $bug->resolvedBuild); - $this->loadModel('gitlab'); - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID); - return common::createChanges($oldBug, $bug); } @@ -1197,11 +1156,6 @@ class bugModel extends model $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec(); $this->executeHooks($bugID); - /* batch resolve issure bugs.*/ - $this->loadModel('gitlab'); - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID); - $changes[$bugID] = common::createChanges($oldBug, $bug); } @@ -1259,13 +1213,6 @@ class bugModel extends model } } - if(!empty($bug)) - { - $this->loadModel('gitlab'); - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID); - } - $bug->activatedCount += 1; return common::createChanges($oldBug, $bug); } @@ -1295,13 +1242,6 @@ class bugModel extends model $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec(); - $this->loadModel('gitlab'); - $relation = $this->gitlab->getRelationByObject('bug', $bugID); - if(!empty($relation)) - { - $currentIssue = $this->gitlab->apiGetSingleIssue($relation->gitlabID, $relation->projectID, $relation->issueID); - if($currentIssue->state != 'closed') $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID); - } return common::createChanges($oldBug, $bug); } diff --git a/module/bug/view/browse.html.php b/module/bug/view/browse.html.php index 2eb9bc2557..2356adcc4c 100644 --- a/module/bug/view/browse.html.php +++ b/module/bug/view/browse.html.php @@ -181,7 +181,7 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow
  • > createLink('bug', 'batchCreate', "productID=$productID&branch=$branch&executionID=0&moduleID=$moduleID"); - echo "
  • " . html::a($batchLink, "" . $lang->bug->batchCreate) . "
  • "; + echo "
  • " . html::a($batchLink, " " . $lang->bug->batchCreate) . "
  • "; ?> diff --git a/module/bug/view/report.html.php b/module/bug/view/report.html.php index 10db781752..118c64ed1a 100644 --- a/module/bug/view/report.html.php +++ b/module/bug/view/report.html.php @@ -13,7 +13,7 @@