Merge branch 'master' into 'sprint/174_xieqiyu_45015'

# Conflicts:
#   module/testcase/control.php
This commit is contained in:
李玉春
2021-12-03 05:07:19 +00:00
100 changed files with 609 additions and 574 deletions
+1 -1
View File
@@ -59,7 +59,7 @@ class buildsEntry extends entry
$control = $this->loadController('build', 'create');
$this->requireFields('execution,product,name,builder,date');
$control->create(0,0,$projectID);
$control->create(0, 0, $projectID);
$data = $this->getData();
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
+3
View File
@@ -36,6 +36,9 @@ class configEntry extends baseEntry
case 'timezone':
$config['value'] = $this->config->timezone;
break;
case 'systemMode':
$config['value'] = $this->config->systemMode;
break;
default:
$this->sendError(400, 'No configuration.');
return;
+5 -4
View File
@@ -21,10 +21,11 @@ class configsEntry extends baseEntry
{
$configs = array();
$configs[] = array('key' => 'language', 'value' => $this->config->default->lang);
$configs[] = array('key' => 'version', 'value' => $this->config->version);
$configs[] = array('key' => 'charset', 'value' => $this->config->charset);
$configs[] = array('key' => 'timezone', 'value' => $this->config->timezone);
$configs[] = array('key' => 'language', 'value' => $this->config->default->lang);
$configs[] = array('key' => 'version', 'value' => $this->config->version);
$configs[] = array('key' => 'charset', 'value' => $this->config->charset);
$configs[] = array('key' => 'timezone', 'value' => $this->config->timezone);
$configs[] = array('key' => 'systemMode', 'value' => $this->config->systemMode);
$this->send(200, $configs);
}
+1 -7
View File
@@ -29,17 +29,11 @@ class productEntry extends Entry
if(!$data or !isset($data->status)) return $this->send400('error');
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
$product = $this->format($data->data->product, 'createdDate:time');
$product = $this->format($data->data->product, 'createdDate:time,whitelist:userList,createdBy:user,PO:user,RD:user,QD:user,feedback:user');
$this->loadModel('testcase');
$product->caseReview = ($this->config->testcase->needReview or !empty($this->config->testcase->forceReview));
$users = $data->data->users;
$product->PO = $this->formatUser($product->PO, $users);
$product->QD = $this->formatUser($product->QD, $users);
$product->RD = $this->formatUser($product->RD, $users);
$product->createdBy = $this->formatUser($product->createdBy, $users);
if(isset($product->feedback)) $product->feedback = $this->formatUser($product->feedback, $users);
if(!$fields) return $this->send(200, $product);
/* Set other fields. */
+13 -2
View File
@@ -59,8 +59,19 @@ class productplanEntry extends Entry
$data = $this->getData();
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
$plan = $this->productplan->getByID($planID);
$this->sendSuccess(200, $this->format($plan, 'begin:date,end:date'));
/* Get plan info. */
$control = $this->loadController('productplan', 'view');
$control->view($planID);
$data = $this->getData();
if(!$data or !isset($data->status)) return $this->send400('error');
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
$plan = $data->data->plan;
$plan->stories = $data->data->planStories;
$plan->bugs = $data->data->planBugs;
$this->send(200, $this->format($plan, 'begin:date,end:date,deleted:bool,stories:array,bugs:array'));
}
/**
@@ -1,6 +1,6 @@
<?php
/**
* The productplanlinkbug entry point of ZenTaoPMS.
* The productplanlinkbugs entry point of ZenTaoPMS.
*
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
@@ -9,7 +9,7 @@
* @version 1
* @link http://www.zentao.net
*/
class productplanLinkBugEntry extends entry
class productplanLinkBugsEntry extends entry
{
/**
* POST method.
@@ -1,6 +1,6 @@
<?php
/**
* The productplanlinkstory entry point of ZenTaoPMS.
* The productplanlinkstories entry point of ZenTaoPMS.
*
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
@@ -9,7 +9,7 @@
* @version 1
* @link http://www.zentao.net
*/
class productplanLinkStoryEntry extends entry
class productplanLinkStoriesEntry extends entry
{
/**
* POST method.
+5 -2
View File
@@ -46,7 +46,7 @@ class productplansEntry extends entry
}
else
{
$result[$plan->id] = $plan;
$result[$plan->id] = $this->format($plan, 'begin:date,end:date,deleted:bool,project:int');
}
}
@@ -72,6 +72,9 @@ class productplansEntry extends entry
$fields = 'branch,begin,end,title,desc';
$this->batchSetPost($fields);
$this->setPost('product', $productID);
$this->setPost('parent', $this->request('parent', 0));
$this->setPost('branch', $this->request('branch', 0));
$control = $this->loadController('productplan', 'create');
$control->create($productID, $this->param('branch', 0), $this->param('parent', 0));
@@ -82,7 +85,7 @@ class productplansEntry extends entry
$plan = $this->loadModel('productplan')->getByID($data->id);
$plan->stories = array();
$plan->bugs = array();
return $this->send(200, $plan);
return $this->send(200, $this->format($plan, 'begin:date,end:date,deleted:bool,project:int'));
}
$this->sendError(400, array('message' => isset($data->message) ? $data->message : 'error'));
@@ -1,6 +1,6 @@
<?php
/**
* The productplanunlinkbug entry point of ZenTaoPMS.
* The productplanunlinkbugs entry point of ZenTaoPMS.
*
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
@@ -9,7 +9,7 @@
* @version 1
* @link http://www.zentao.net
*/
class productplanUnlinkBugEntry extends entry
class productplanUnlinkBugsEntry extends entry
{
/**
* POST method.
@@ -1,6 +1,6 @@
<?php
/**
* The productplanunlinkstory entry point of ZenTaoPMS.
* The productplanunlinkstories entry point of ZenTaoPMS.
*
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
@@ -9,7 +9,7 @@
* @version 1
* @link http://www.zentao.net
*/
class productplanUnlinkStoryEntry extends entry
class productplanUnlinkStoriesEntry extends entry
{
/**
* POST method.
+3 -3
View File
@@ -79,7 +79,7 @@ class productsEntry extends entry
}
}
$result[] = $this->format($product, 'createdDate:time');
$result[] = $this->format($product, 'createdDate:time,whitelist:userList,createdBy:user,PO:user,RD:user,QD:user');
}
$data = array();
@@ -113,11 +113,11 @@ class productsEntry extends entry
$control->create($this->request('program', 0));
$data = $this->getData();
if(isset($data->status) and $data->status == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
if(isset($data->result) and $data->result == 'fail') return $this->sendError(zget($data, 'code', 400), $data->message);
/* Response */
$product = $this->loadModel('product')->getByID($data->id);
$product = $this->format($product, 'createdDate:time,whitelist:[]string');
$product = $this->format($product, 'createdDate:time,whitelist:userList,createdBy:user,PO:user,RD:user,QD:user');
$this->send(200, $product);
}
+2 -2
View File
@@ -23,7 +23,7 @@ class programEntry extends Entry
$program = $this->loadModel('program')->getByID($programID);
if(!$program) return $this->send404();
$this->send(200, $this->format($program, 'openedDate:time,realBegan:date,realEnd:date,deleted:bool'));
$this->send(200, $this->format($program, 'begin:date,end:date,PO:user,PM:user,QD:user,RD:user,realBegan:date,realEnd:date,openedBy:user,openedDate:time,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,deleted:bool,whitelist:userList'));
}
/**
@@ -47,7 +47,7 @@ class programEntry extends Entry
$this->getData();
$program = $this->program->getByID($programID);
$this->send(200, $this->format($program, 'openedDate:time'));
$this->send(200, $this->format($program, 'begin:date,end:date,PO:user,PM:user,QD:user,RD:user,realBegan:date,realEnd:date,openedBy:user,openedDate:time,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,deleted:bool,whitelist:userList'));
}
/**
+5 -10
View File
@@ -22,6 +22,8 @@ class programsEntry extends Entry
$_COOKIE['showClosed'] = $this->param('showClosed', 0);
$mergeChildren = $this->param('mergeChildren', 0);
$this->config->systemMode = 'new';
$fields = $this->param('fields', '');
if(stripos(strtolower(",{$fields},"), ",dropmenu,") !== false) return $this->getDropMenu();
@@ -39,19 +41,12 @@ class programsEntry extends Entry
foreach($programs as $program)
{
if(isset($progressList->{$program->id})) $program->progress = $progressList->{$program->id};
$param = $this->format($program, 'begin:date,end:date,realBegan:date,realEnd:date,openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time,deleted:bool');
$program = $this->format($program, 'begin:date,end:date,PO:user,PM:user,QD:user,RD:user,realBegan:date,realEnd:date,openedBy:user,openedDate:time,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,deleted:bool,whitelist:userList');
if($mergeChildren)
{
unset($program->desc);
$program->openedBy = zget($users, $program->openedBy);
$program->closedBy = zget($users, $program->closedBy);
$program->canceledBy = zget($users, $program->canceledBy);
$program->PO = zget($users, $program->PO);
$program->PM = zget($users, $program->PM);
$program->QD = zget($users, $program->QD);
$program->RD = zget($users, $program->RD);
$program->end = $program->end == LONG_TIME ? $this->lang->program->longTime : $program->end;
$program->end = $program->end == LONG_TIME ? $this->lang->program->longTime : $program->end;
$programBudget = in_array($this->app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$program->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$program->budget, 2);
$program->labelBudget = $program->budget != 0 ? zget($this->lang->project->currencySymbol, $program->budgetUnit) . ' ' . $programBudget : $this->lang->project->future;
@@ -94,7 +89,7 @@ class programsEntry extends Entry
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
$program = $this->loadModel('program')->getByID($data->id);
$this->send(201, $this->format($program, 'openedDate:time,whitelist:stringList'));
$this->send(201, $this->format($program, 'begin:date,end:date,PO:user,PM:user,QD:user,RD:user,realBegan:date,realEnd:date,openedBy:user,openedDate:time,lastEditedDate:time,closedBy:user,closedDate:time,canceledBy:user,canceledDate:time,deleted:bool,whitelist:userList'));
}
/**
+2 -1
View File
@@ -28,11 +28,12 @@ class projectReleasesEntry extends entry
/* Response */
$data = $this->getData();
if(isset($data->status) and $data->status == 'success')
{
$result = array();
$releases = $data->data->releases;
foreach($releases as $release) $result[] = $this->format($release, 'deleted:bool,date:date');
foreach($releases as $release) $result[] = $this->format($release, 'deleted:bool,date:date,mailto:userList');
return $this->send(200, array('total' => count($result), 'releases' => $result));
}
+2
View File
@@ -26,6 +26,8 @@ class projectsEntry extends entry
$_COOKIE['involved'] = $this->param('involved', 0);
$this->config->systemMode = 'new';
if($programID)
{
$control = $this->loadController('program', 'project');
+1 -1
View File
@@ -32,7 +32,7 @@ class releasesEntry extends entry
{
$result = array();
$releases = $data->data->releases;
foreach($releases as $release) $result[] = $this->format($release, 'deleted:bool,date:date');
foreach($releases as $release) $result[] = $this->format($release, 'deleted:bool,date:date,mailto:userList');
return $this->send(200, array('total' => count($result), 'releases' => $result));
}
+25 -3
View File
@@ -14,7 +14,7 @@ class userEntry extends Entry
/**
* GET method.
*
* @param int $userID
* @param int|string $userID
* @access public
* @return void
*/
@@ -23,6 +23,13 @@ class userEntry extends Entry
/* Get my info defaultly. */
if(!$userID) return $this->getInfo($this->param('fields', ''));
if(!is_numeric($userID))
{
$user = $this->loadModel('user')->getById($userID, 'account');
if(!$user) return $this->send404();
$userID = $user->id;
}
/* Get user by id. */
$control = $this->loadController('user', 'profile');
$control->profile($userID);
@@ -349,17 +356,25 @@ class userEntry extends Entry
/**
* PUT method.
*
* @param int $userID
* @param int|string $userID
* @access public
* @return void
*/
public function put($userID)
{
if(!is_numeric($userID))
{
$user = $this->loadModel('user')->getById($userID, 'account');
if(!$user) return $this->send404();
$userID = $user->id;
}
$oldUser = $this->loadModel('user')->getByID($userID, 'id');
/* Set $_POST variables. */
$fields = 'dept,realname,email,commiter,gender';
$this->batchSetPost($fields, $oldUser);
$this->setPost('account', $oldUser->account);
if($this->request('gender') and !in_array($this->request('gender'), array('f', 'm'))) return $this->sendError(400, "The value of gendar must be 'f' or 'm'");
@@ -380,12 +395,19 @@ class userEntry extends Entry
/**
* DELETE method.
*
* @param int $userID
* @param int|string $userID
* @access public
* @return void
*/
public function delete($userID)
{
if(!is_numeric($userID))
{
$user = $this->loadModel('user')->getById($userID, 'account');
if(!$user) return $this->send404();
$userID = $user->id;
}
$this->setPost('verifyPassword', md5($this->app->user->password . $this->app->session->rand));
$control = $this->loadController('user', 'delete');
+7 -7
View File
@@ -24,13 +24,13 @@ $routes['/products/:id'] = 'product';
$routes['/productlines'] = 'productLines';
$routes['/productlines/:id'] = 'productLine';
$routes['/productplans'] = 'productPlans';
$routes['/products/:id/plans'] = 'productPlans';
$routes['/productplans/:id'] = 'productPlan';
$routes['/productplans/:id/linkstory'] = 'productPlanLinkStory';
$routes['/productplans/:id/unlinkstory'] = 'productPlanUnlinkStory';
$routes['/productplans/:id/linkbug'] = 'productPlanLinkBug';
$routes['/productplans/:id/unlinkbug'] = 'productPlanUnlinkBug';
$routes['/productplans'] = 'productPlans';
$routes['/products/:id/plans'] = 'productPlans';
$routes['/productplans/:id'] = 'productPlan';
$routes['/productplans/:id/linkstories'] = 'productPlanLinkStories';
$routes['/productplans/:id/unlinkstories'] = 'productPlanUnlinkStories';
$routes['/productplans/:id/linkbugs'] = 'productPlanLinkBugs';
$routes['/productplans/:id/unlinkbugs'] = 'productPlanUnlinkBugs';
$routes['/releases'] = 'releases';
$routes['/products/:id/releases'] = 'releases';
+11
View File
@@ -116,6 +116,17 @@ CREATE TABLE IF NOT EXISTS `zt_holiday` (
KEY `name` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_mrapproval`;
CREATE TABLE IF NOT EXISTS `zt_mrapproval` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`mrID` mediumint(8) unsigned NOT NULL,
`account` varchar(255) NOT NULL,
`date` datetime NOT NULL,
`action` char(30) NOT NULL,
`comment` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
REPLACE INTO `zt_stage` (`name`,`percent`,`type`,`createdBy`,`createdDate`,`editedBy`,`editedDate`,`deleted`) VALUES
('需求','10','request','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
('设计','10','design','admin','2020-02-08 21:08:30','admin','2020-02-12 13:50:27','0'),
+15
View File
@@ -615,6 +615,21 @@ class baseEntry
$array = array();
if(!empty($value)) foreach($value as $v) $array[] = $v;
return $array;
case 'user':
if(empty($value)) return null;
if(empty($this->users)) $this->users = $this->dao->select('id,account,avatar,realname')->from(TABLE_USER)->fetchAll('account');
return zget($this->users, $value, null);
case 'userList':
$values = explode(',', $value);
if(empty($values)) return array();
$userList = array();
foreach($values as $val)
{
$val = $this->cast($val, 'user');
if($val) $userList[] = $val;
}
return $userList;
default:
return $value;
}
+1
View File
@@ -2118,6 +2118,7 @@ class baseRouter
$view->methodVar = $this->config->methodVar;
$view->viewVar = $this->config->viewVar;
$view->sessionVar = $this->config->sessionVar;
$view->systemMode = $this->config->systemMode;
$this->session->set('random', mt_rand(0, 10000));
$view->sessionName = session_name();
+2 -2
View File
@@ -491,7 +491,7 @@ class baseHTML
$gobackLink = "<a href='javascript:history.go(-1)' class='btn btn-back $class' $misc>{$label}</a>";
$tab = $_COOKIE['tab'];
$referer = isset($_SERVER['HTTP_REFERER']) ? strtolower($_SERVER['HTTP_REFERER']) : '';
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
$refererParts = parse_url($referer);
if($config->requestType == 'PATH_INFO' and empty($refererParts)) return $gobackLink;
@@ -504,7 +504,7 @@ class baseHTML
$gobackLink = isset($gobackList[$tab]) ? $gobackList[$tab] : '';
/* If the link of the referer is not the link of the current page or the link of the index, the cookie and gobackLink will be updated. */
if(!preg_match("/(m=|\/)(index|search|$currentModule)(&f=|-)(index|buildquery|$currentMethod)(&|-|\.)?/", $refererLink))
if(!preg_match("/(m=|\/)(index|search|$currentModule)(&f=|-)(index|buildquery|$currentMethod)(&|-|\.)?/", strtolower($refererLink)))
{
$gobackList[$tab] = $referer;
$gobackLink = $referer;
+1
View File
@@ -559,6 +559,7 @@ class gitlab
$list = $this->fetch($api, $params);
$commits = array();
$files = array();
foreach($list as $commit)
{
if(!is_object($commit)) continue;
+4 -2
View File
@@ -291,8 +291,9 @@ $lang->action->label->syncprogram = 'start';
$lang->action->label->syncproject = 'start';
$lang->action->label->syncexecution = 'start';
$lang->action->label->startProgram = '(The start of the project sets the status of the program as Ongoing)';
$lang->action->label->createmr = 'MR Linked';
$lang->action->label->mergedmr = 'MR Merged';
$lang->action->label->createmr = 'Merge Request Linked';
$lang->action->label->deletemr = 'Merge Request Unlinked';
$lang->action->label->mergedmr = 'Merge Request Merged';
$lang->action->label->reopen = 'Reopen';
$lang->action->label->approve = 'Passed';
$lang->action->label->reject = 'Rejected';
@@ -535,6 +536,7 @@ $lang->action->label->stakeholder = 'Stakeholder|stakeholder|view|userID=%s';
$lang->action->label->api = 'Interface|api|index|libID=%s&moduleID=%s&apiID=%s';
$lang->action->label->kanbancolumn = 'Kanban column|execution|kanban|execution=%s';
$lang->action->label->kanbanlane = 'Kanban Lane|execution|kanban|execution=%s&type=all';
$lang->action->label->mr = 'Merge Request|mr|view|id=%s';
/* Object type. */
$lang->action->search = new stdclass();
+4 -2
View File
@@ -294,8 +294,9 @@ $lang->action->label->syncprogram = '开始了';
$lang->action->label->syncproject = '开始了';
$lang->action->label->syncexecution = '开始了';
$lang->action->label->startProgram = '(因项目开始而启动项目集)';
$lang->action->label->createmr = 'MR关联了';
$lang->action->label->mergedmr = 'MR合并了';
$lang->action->label->createmr = '合并请求关联了';
$lang->action->label->deletemr = '合并请求取消了';
$lang->action->label->mergedmr = '合并请求合并了';
$lang->action->label->compilepass = '构建成功';
$lang->action->label->compilefail = '构建失败';
$lang->action->label->reopen = '重新打开';
@@ -540,6 +541,7 @@ $lang->action->label->stakeholder = '干系人|stakeholder|view|userID=%s';
$lang->action->label->api = '接口|api|index|libID=%s&moduleID=%s&apiID=%s';
$lang->action->label->kanbancolumn = '看板列|execution|kanban|execution=%s';
$lang->action->label->kanbanlane = '看板泳道|execution|kanban|execution=%s&type=all';
$lang->action->label->mr = '合并请求|mr|view|id=%s';
/* Object type. */
$lang->action->search = new stdclass();
+9 -13
View File
@@ -53,10 +53,11 @@ class api extends control
$libID = $api->lib;
$api->desc = htmlspecialchars_decode($api->desc);
$this->view->api = $api;
$this->view->apiID = $apiID;
$this->view->version = $version;
$this->view->actions = $apiID ? $this->action->getList('api', $apiID) : array();
$this->view->api = $api;
$this->view->apiID = $apiID;
$this->view->version = $version;
$this->view->typeList = $this->api->getTypeList($api->lib);
$this->view->actions = $apiID ? $this->action->getList('api', $apiID) : array();
}
}
else
@@ -64,7 +65,8 @@ class api extends control
/* Get module api list. */
$apiList = $this->api->getListByModuleId($libID, $moduleID, $release);
$this->view->apiList = $apiList;
$this->view->apiList = $apiList;
$this->view->typeList = $this->api->getTypeList($api->lib);
}
$this->setMenu($libID);
@@ -435,12 +437,7 @@ class api extends control
$this->setMenu($api->lib);
$options = array();
foreach($this->lang->api->paramsTypeOptions as $key => $item)
{
$options[] = array('label' => $item, 'value' => $key);
}
$this->view->typeOptions = $options;
$this->getTypeOptions($api->lib);
$this->view->gobackLink = $this->createLink('api', 'index', "libID={$api->lib}&moduleID={$api->module}");
$this->view->user = $this->app->user->account;
$this->view->allUsers = $this->loadModel('user')->getPairs('devfirst|noclosed');;
@@ -835,7 +832,7 @@ EOT;
/**
* Get options of type.
*
* @param string $keyField
* @param int $libID
* @access public
* @return void
*/
@@ -855,5 +852,4 @@ EOT;
}
$this->view->typeOptions = $options;
}
}
+25
View File
@@ -705,4 +705,29 @@ class apiModel extends model
'addedDate' => helper::now(),
);
}
/**
* Get Type list.
*
* @param int $libID
* @access public
* @return void
*/
public function getTypeList($libID)
{
$typeList = array();
foreach($this->lang->api->paramsTypeOptions as $key => $item)
{
$typeList[$key] = $item;
}
/* Get all struct by libID. */
$structs = $this->getStructListByLibID($libID);
foreach($structs as $struct)
{
$typeList[$struct->id] = $struct->name;
}
return $typeList;
}
}
+17 -25
View File
@@ -89,30 +89,24 @@
</table>
<?php endif;?>
<?php
function parseTree($data, $level = 0)
function parseTree($data, $typeList, $level = 0)
{
$str = '<tr>';
$field = '';
for($i = 0; $i < $level; $i++)
{
$field .= '&nbsp;&nbsp;∟&nbsp;&nbsp;';
}
$field .= $data['field'];
$str .= '<td>' . $field . '</td>';
$str .= '<td>' . $data['paramsType'] . '</td>';
$require = $data['required'] ? '是' : '否';
$str .= '<td>' . $require . '</td>';
$str .= '<td>' . $data['desc'] . '</td>';
$str .= '</tr>';
if(isset($data['children']) && count($data['children']) > 0)
{
$level++;
foreach($data['children'] as $item)
$str = '<tr>';
$field = '';
for($i = 0; $i < $level; $i++) $field .= '&nbsp;&nbsp;'. ($i == $level-1 ? '∟' : '&nbsp;') . '&nbsp;&nbsp;';
$field .= $data['field'];
$str .= '<td>' . $field . '</td>';
$str .= '<td>' . zget($typeList, $data['paramsType'], '') . '</td>';
$require = $data['required'] ? '是' : '否';
$str .= '<td>' . $require . '</td>';
$str .= '<td>' . $data['desc'] . '</td>';
$str .= '</tr>';
if(isset($data['children']) && count($data['children']) > 0)
{
$str .= parseTree($item, $level);
$level++;
foreach($data['children'] as $item) $str .= parseTree($item, $typeList, $level);
}
}
return $str;
return $str;
}
?>
<?php if($api->params['params']):?>
@@ -126,9 +120,7 @@
<th><?php echo $lang->api->req->desc;?></th>
</tr>
</thead>
<tbody>
<?php foreach($api->params['params'] as $item) echo parseTree($item);?>
</tbody>
<tbody><?php foreach($api->params['params'] as $item) echo parseTree($item, $typeList);?></tbody>
</table>
<?php endif;?>
<?php if($api->paramsExample):?>
@@ -147,7 +139,7 @@
</tr>
</thead>
<tbody>
<?php foreach($api->response as $item) echo parseTree($item);?>
<?php foreach($api->response as $item) echo parseTree($item, $typeList);?>
</tbody>
</table>
<?php endif;?>
+2 -39
View File
@@ -103,48 +103,16 @@ $lang->block->spent = 'Has Been Spent';
$lang->block->budget = 'Budget';
$lang->block->left = 'Residuals';
$lang->block->default['waterfall']['project']['1']['title'] = 'Project Weekly';
$lang->block->default['waterfall']['project']['1']['block'] = 'waterfallreport';
$lang->block->default['waterfall']['project']['1']['source'] = 'project';
$lang->block->default['waterfall']['project']['1']['grid'] = 8;
$lang->block->default['waterfall']['project']['2']['title'] = 'Estimate';
$lang->block->default['waterfall']['project']['2']['block'] = 'waterfallestimate';
$lang->block->default['waterfall']['project']['2']['source'] = 'project';
$lang->block->default['waterfall']['project']['2']['grid'] = 4;
$lang->block->default['waterfall']['project']['3']['title'] = 'Plan Gantt Chart';
$lang->block->default['waterfall']['project']['3']['block'] = 'waterfallgantt';
$lang->block->default['waterfall']['project']['3']['source'] = 'project';
$lang->block->default['waterfall']['project']['3']['grid'] = 8;
$lang->block->default['waterfall']['project']['4']['title'] = 'Progress Chart';
$lang->block->default['waterfall']['project']['4']['block'] = 'waterfallprogress';
$lang->block->default['waterfall']['project']['4']['grid'] = 4;
$lang->block->default['waterfall']['project']['5']['title'] = 'Project Issue';
$lang->block->default['waterfall']['project']['5']['block'] = 'waterfallissue';
$lang->block->default['waterfall']['project']['5']['source'] = 'project';
$lang->block->default['waterfall']['project']['5']['grid'] = 8;
$lang->block->default['waterfall']['project']['5']['params']['type'] = 'all';
$lang->block->default['waterfall']['project']['5']['params']['count'] = '15';
$lang->block->default['waterfall']['project']['5']['params']['orderBy'] = 'id_desc';
$lang->block->default['waterfall']['project']['6']['title'] = 'Dynamic';
$lang->block->default['waterfall']['project']['6']['block'] = 'projectdynamic';
$lang->block->default['waterfall']['project']['6']['grid'] = 4;
$lang->block->default['waterfall']['project']['6']['source'] = 'project';
$lang->block->default['waterfall']['project']['7']['title'] = 'Project Risk';
$lang->block->default['waterfall']['project']['7']['block'] = 'waterfallrisk';
$lang->block->default['waterfall']['project']['7']['source'] = 'project';
$lang->block->default['waterfall']['project']['7']['grid'] = 8;
$lang->block->default['waterfall']['project']['7']['params']['type'] = 'all';
$lang->block->default['waterfall']['project']['7']['params']['count'] = '15';
$lang->block->default['waterfall']['project']['7']['params']['orderBy'] = 'id_desc';
$lang->block->default['scrum']['project']['1']['title'] = 'Project Overall';
$lang->block->default['scrum']['project']['1']['block'] = 'scrumoverview';
$lang->block->default['scrum']['project']['1']['grid'] = 8;
@@ -375,13 +343,8 @@ $lang->block->modules['scrum']['index']->availableBlocks->projectdynamic = 'Dyna
$lang->block->modules['waterfall']['index'] = new stdclass();
$lang->block->modules['waterfall']['index']->availableBlocks = new stdclass();
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallreport = 'Project Weekly';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallestimate = 'Estimate';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = 'Plan Gantt Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallprogress = 'Progress Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallissue = 'Project Issue';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallrisk = 'Project Risk';
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = 'Plan Gantt Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['product'] = new stdclass();
$lang->block->modules['product']->availableBlocks = new stdclass();
+2 -7
View File
@@ -355,13 +355,8 @@ $lang->block->modules['scrum']['index']->availableBlocks->projectdynamic = 'Dyna
$lang->block->modules['waterfall']['index'] = new stdclass();
$lang->block->modules['waterfall']['index']->availableBlocks = new stdclass();
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallreport = 'Project Weekly';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallestimate = 'Estimate';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = 'Plan Gantt Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallprogress = 'Progress Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallissue = 'Project Issue';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallrisk = 'Project Risk';
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = 'Plan Gantt Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['product'] = new stdclass();
$lang->block->modules['product']->availableBlocks = new stdclass();
+2 -39
View File
@@ -103,48 +103,16 @@ $lang->block->spent = 'Has Been Spent';
$lang->block->budget = 'Budget';
$lang->block->left = 'Residuals';
$lang->block->default['waterfall']['project']['1']['title'] = 'Project Weekly';
$lang->block->default['waterfall']['project']['1']['block'] = 'waterfallreport';
$lang->block->default['waterfall']['project']['1']['source'] = 'project';
$lang->block->default['waterfall']['project']['1']['grid'] = 8;
$lang->block->default['waterfall']['project']['2']['title'] = 'Estimate';
$lang->block->default['waterfall']['project']['2']['block'] = 'waterfallestimate';
$lang->block->default['waterfall']['project']['2']['source'] = 'project';
$lang->block->default['waterfall']['project']['2']['grid'] = 4;
$lang->block->default['waterfall']['project']['3']['title'] = 'Plan Gantt Chart';
$lang->block->default['waterfall']['project']['3']['block'] = 'waterfallgantt';
$lang->block->default['waterfall']['project']['3']['source'] = 'project';
$lang->block->default['waterfall']['project']['3']['grid'] = 8;
$lang->block->default['waterfall']['project']['4']['title'] = 'Progress Chart';
$lang->block->default['waterfall']['project']['4']['block'] = 'waterfallprogress';
$lang->block->default['waterfall']['project']['4']['grid'] = 4;
$lang->block->default['waterfall']['project']['5']['title'] = 'project Issue';
$lang->block->default['waterfall']['project']['5']['block'] = 'waterfallissue';
$lang->block->default['waterfall']['project']['5']['source'] = 'project';
$lang->block->default['waterfall']['project']['5']['grid'] = 8;
$lang->block->default['waterfall']['project']['5']['params']['type'] = 'all';
$lang->block->default['waterfall']['project']['5']['params']['count'] = '15';
$lang->block->default['waterfall']['project']['5']['params']['orderBy'] = 'id_desc';
$lang->block->default['waterfall']['project']['6']['title'] = 'Dynamic';
$lang->block->default['waterfall']['project']['6']['block'] = 'dynamic';
$lang->block->default['waterfall']['project']['6']['grid'] = 4;
$lang->block->default['waterfall']['project']['6']['source'] = '';
$lang->block->default['waterfall']['project']['7']['title'] = 'Project Risk';
$lang->block->default['waterfall']['project']['7']['block'] = 'waterfallrisk';
$lang->block->default['waterfall']['project']['7']['source'] = 'project';
$lang->block->default['waterfall']['project']['7']['grid'] = 8;
$lang->block->default['waterfall']['project']['7']['params']['type'] = 'all';
$lang->block->default['waterfall']['project']['7']['params']['count'] = '15';
$lang->block->default['waterfall']['project']['7']['params']['orderBy'] = 'id_desc';
$lang->block->default['scrum']['project']['1']['title'] = 'Project Overall';
$lang->block->default['scrum']['project']['1']['block'] = 'scrumoverview';
$lang->block->default['scrum']['project']['1']['grid'] = 8;
@@ -375,13 +343,8 @@ $lang->block->modules['scrum']['index']->availableBlocks->projectdynamic = 'Dyna
$lang->block->modules['waterfall']['index'] = new stdclass();
$lang->block->modules['waterfall']['index']->availableBlocks = new stdclass();
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallreport = 'Project Weekly';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallestimate = 'Estimate';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = 'Plan Gantt Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallprogress = 'Progress Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallissue = 'Project Issue';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallrisk = 'Project Risk';
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = 'Plan Gantt Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['product'] = new stdclass();
$lang->block->modules['product']->availableBlocks = new stdclass();
+2 -39
View File
@@ -103,48 +103,16 @@ $lang->block->spent = 'Has Been Spent';
$lang->block->budget = 'Budget';
$lang->block->left = 'Residuals';
$lang->block->default['waterfall']['project']['1']['title'] = 'Project Weekly';
$lang->block->default['waterfall']['project']['1']['block'] = 'waterfallreport';
$lang->block->default['waterfall']['project']['1']['source'] = 'project';
$lang->block->default['waterfall']['project']['1']['grid'] = 8;
$lang->block->default['waterfall']['project']['2']['title'] = 'Estimate';
$lang->block->default['waterfall']['project']['2']['block'] = 'waterfallestimate';
$lang->block->default['waterfall']['project']['2']['source'] = 'project';
$lang->block->default['waterfall']['project']['2']['grid'] = 4;
$lang->block->default['waterfall']['project']['3']['title'] = 'Plan Gantt Chart';
$lang->block->default['waterfall']['project']['3']['block'] = 'waterfallgantt';
$lang->block->default['waterfall']['project']['3']['source'] = 'project';
$lang->block->default['waterfall']['project']['3']['grid'] = 8;
$lang->block->default['waterfall']['project']['4']['title'] = 'Progress Chart';
$lang->block->default['waterfall']['project']['4']['block'] = 'waterfallprogress';
$lang->block->default['waterfall']['project']['4']['grid'] = 4;
$lang->block->default['waterfall']['project']['5']['title'] = 'Project Issue';
$lang->block->default['waterfall']['project']['5']['block'] = 'waterfallissue';
$lang->block->default['waterfall']['project']['5']['source'] = 'project';
$lang->block->default['waterfall']['project']['5']['grid'] = 8;
$lang->block->default['waterfall']['project']['5']['params']['type'] = 'all';
$lang->block->default['waterfall']['project']['5']['params']['count'] = '15';
$lang->block->default['waterfall']['project']['5']['params']['orderBy'] = 'id_desc';
$lang->block->default['waterfall']['project']['6']['title'] = 'Dynamic';
$lang->block->default['waterfall']['project']['6']['block'] = 'dynamic';
$lang->block->default['waterfall']['project']['6']['grid'] = 4;
$lang->block->default['waterfall']['project']['6']['source'] = 'project';
$lang->block->default['waterfall']['project']['7']['title'] = 'Project Risk';
$lang->block->default['waterfall']['project']['7']['block'] = 'waterfallrisk';
$lang->block->default['waterfall']['project']['7']['source'] = 'project';
$lang->block->default['waterfall']['project']['7']['grid'] = 8;
$lang->block->default['waterfall']['project']['7']['params']['type'] = 'all';
$lang->block->default['waterfall']['project']['7']['params']['count'] = '15';
$lang->block->default['waterfall']['project']['7']['params']['orderBy'] = 'id_desc';
$lang->block->default['scrum']['project']['1']['title'] = 'Project Overall';
$lang->block->default['scrum']['project']['1']['block'] = 'scrumoverview';
$lang->block->default['scrum']['project']['1']['grid'] = 8;
@@ -375,13 +343,8 @@ $lang->block->modules['scrum']['index']->availableBlocks->projectdynamic = 'Dyna
$lang->block->modules['waterfall']['index'] = new stdclass();
$lang->block->modules['waterfall']['index']->availableBlocks = new stdclass();
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallreport = $lang->executionCommon . ' Weekly';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallestimate = 'Estimate';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = 'Plan Gantt Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallprogress = 'Progress Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallissue = $lang->executionCommon . ' Issue';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallrisk = $lang->executionCommon . ' Risk';
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = 'Plan Gantt Chart';
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['product'] = new stdclass();
$lang->block->modules['product']->availableBlocks = new stdclass();
-5
View File
@@ -355,12 +355,7 @@ $lang->block->modules['scrum']['index']->availableBlocks->projectdynamic = '最
$lang->block->modules['waterfall']['index'] = new stdclass();
$lang->block->modules['waterfall']['index']->availableBlocks = new stdclass();
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallreport = '项目周报';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallestimate = '估算';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = "项目计划";
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallprogress = '到目前为止项目进展趋势图';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallissue = '项目问题';
$lang->block->modules['waterfall']['index']->availableBlocks->waterfallrisk = '项目风险';
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = '最新动态';
$lang->block->modules['product'] = new stdclass();
+162 -158
View File
@@ -1,8 +1,10 @@
<?php $waterfallGanttID = uniqid('wg'); ?>
<div class="panel-body">
<div id='waterfallGantt'>
<div id='<?php echo $waterfallGanttID; ?>'>
<?php if(count($products) >= 2): ?>
<?php echo html::select('waterfallGanttProductID', $products, $productID, "class='form-control chosen'");?>
<span id="ganttProductTips"><i>* </i><?php echo $lang->block->selectProduct;?></span>
<?php echo html::select($waterfallGanttID . 'ProductID', $products, $productID, "class='form-control chosen'");?>
<span class='gantt-product-tips'><i>* </i><?php echo $lang->block->selectProduct;?></span>
<?php endif;?>
<?php if(empty($plans['data'])): ?>
<div class='empty-tip'><?php echo $lang->programplan->noData;?></div>
@@ -18,12 +20,12 @@
<?php endif;?>
</div>
<style>
#ganttProductTips{position: absolute; top: -32px; left: 240px; opacity: 0.5;}
#ganttProductTips i{vertical-align: middle;}
.gantt-product-tips {position: absolute; top: -32px; left: 240px; opacity: 0.5;}
.gantt-product-tips i {vertical-align: middle;}
.block-waterfallgantt > .panel-body {overflow: visible!important}
#waterfallGantt {position: relative}
#waterfallGanttProductID_chosen {position: absolute; top: -39px; left: 120px; width: 150px!important}
[lang="zh-cn"] #waterfallGanttProductID_chosen {left: 85px}
#<?php echo $waterfallGanttID; ?> {position: relative}
#<?php echo $waterfallGanttID; ?>ProductID_chosen {position: absolute; top: -39px; left: 120px; width: 150px!important}
[lang="zh-cn"] #<?php echo $waterfallGanttID; ?>ProductID_chosen {left: 85px}
.gantt-plans {padding: 20px 0 22px; max-height: 380px; overflow: hidden;}
.gantt-plan {width: 70px; height: 50px; line-height: 50px}
.gantt-plan div {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
@@ -39,171 +41,173 @@
.gantt-today {position: absolute; top: -16px; left: 0; bottom: 0; border-left: #00da88 dotted 1px;}
.gantt-today > div {position: absolute; top: 0; left: 0; font-size: 12px; line-height: 14px; padding: 0 3px; background: #00da88; color: #fff; white-space: nowrap; z-index: 10;}
</style>
<script>
function initWaterfallGanttBlock()
{
/* Init product select control */
var $waterfallGanttProductID = $('#waterfallGanttProductID');
$waterfallGanttProductID.on('change', function()
{
$.get(createLink('product', 'ajaxSetState', 'productID=' + $waterfallGanttProductID.val()), function()
{
refreshBlock($waterfallGanttProductID.closest('.panel'));
});
});
<script>
(function() {
function initWaterfallGanttBlock()
{
/* Init product select control */
var $waterfallGanttProductID = $('#<?php echo $waterfallGanttID; ?>ProductID');
$waterfallGanttProductID.on('change', function()
{
$.get(createLink('product', 'ajaxSetState', 'productID=' + $waterfallGanttProductID.val()), function()
{
refreshBlock($waterfallGanttProductID.closest('.panel'));
});
});
<?php if(!empty($plans['data'])): ?>
var ganttData = <?php echo json_encode($plans['data']); ?>;
if(!ganttData) return;
<?php if(!empty($plans['data'])): ?>
var ganttData = <?php echo json_encode($plans['data']); ?>;
if(!ganttData) return;
var plans = [];
var tasks = [];
var plansMap = {};
var startDatetime = Number.MAX_SAFE_INTEGER;
var endDatetime = 0;
var minTimeGap = Number.MAX_SAFE_INTEGER;
var $gantt = $('#waterfallGantt');
var ONE_DAY = 24 * 3600 * 1000;
var TIME_GAP_STEP = 7;
var MIN_COL_WIDTH = 60;
var plans = [];
var tasks = [];
var plansMap = {};
var startDatetime = Number.MAX_SAFE_INTEGER;
var endDatetime = 0;
var minTimeGap = Number.MAX_SAFE_INTEGER;
var $gantt = $('#<?php echo $waterfallGanttID; ?>');
var ONE_DAY = 24 * 3600 * 1000;
var TIME_GAP_STEP = 7;
var MIN_COL_WIDTH = 60;
$.each(ganttData, function(index, item)
{
plansMap[item.id] = item;
if(item.type == 'plan' && item.parent == '0')
{
item.startDatetime = createDatetime(item.start_date);
item.endDatetime = createDatetime(item.deadline);
startDatetime = Math.min(startDatetime, item.startDatetime);
endDatetime = Math.max(endDatetime, item.endDatetime);
minTimeGap = Math.min(minTimeGap, endDatetime - startDatetime);
item.tasks = [];
item.completeTasks = [];
item.progress = 0;
plans.push(item);
}
else if(item.type === 'task')
{
item.progress = Number.parseInt(item.taskProgress.replace('%', ''), 10);
tasks.push(item);
}
});
$.each(ganttData, function(index, item)
{
plansMap[item.id] = item;
if(item.type == 'plan' && item.parent == '0')
{
item.startDatetime = createDatetime(item.start_date);
item.endDatetime = createDatetime(item.deadline);
startDatetime = Math.min(startDatetime, item.startDatetime);
endDatetime = Math.max(endDatetime, item.endDatetime);
minTimeGap = Math.min(minTimeGap, endDatetime - startDatetime);
item.tasks = [];
item.completeTasks = [];
item.progress = 0;
plans.push(item);
}
else if(item.type === 'task')
{
item.progress = Number.parseInt(item.taskProgress.replace('%', ''), 10);
tasks.push(item);
}
});
$.each(tasks, function(index, task)
{
var plan = plansMap[task.parent];
while(plan.parent > 0)
{
plan = plansMap[plan.parent];
if(typeof(plan) != 'object') return;
}
plan.progress += task.progress;
if(task.progress === 100) plan.completeTasks.push(task);
plan.tasks.push(task);
});
$.each(tasks, function(index, task)
{
var plan = plansMap[task.parent];
while(plan.parent > 0)
{
plan = plansMap[plan.parent];
if(typeof(plan) != 'object') return;
}
plan.progress += task.progress;
if(task.progress === 100) plan.completeTasks.push(task);
plan.tasks.push(task);
});
var $plans = $gantt.find('.gantt-plans');
var $ganttContainer = $gantt.find('.gantt-container');
var $ganttCanvas = $gantt.find('.gantt-canvas');
var themeColor = $.getThemeColor('primary');
var canvasHeight = plans.length * 50 + 10;
var $plans = $gantt.find('.gantt-plans');
var $ganttContainer = $gantt.find('.gantt-container');
var $ganttCanvas = $gantt.find('.gantt-canvas');
var themeColor = $.getThemeColor('primary');
var canvasHeight = plans.length * 50 + 10;
var days = Math.ceil((endDatetime - startDatetime) / ONE_DAY);
minTimeGap = Math.max(1, Math.ceil(minTimeGap / ONE_DAY));
var days = Math.ceil((endDatetime - startDatetime) / ONE_DAY);
minTimeGap = Math.max(1, Math.ceil(minTimeGap / ONE_DAY));
/* Update gantt plans and bars */
$.each(plans, function(index, plan)
{
plan.progress = !plan.tasks.length ? 0 : plan.progress / plan.tasks.length;
var $plan = $('<div class="gantt-plan"></div>');
$plan.append('<div class="strong" title="' + plan.text + '">' + plan.text + '</div>');
$plans.append($plan);
/* Update gantt plans and bars */
$.each(plans, function(index, plan)
{
plan.progress = !plan.tasks.length ? 0 : plan.progress / plan.tasks.length;
var $plan = $('<div class="gantt-plan"></div>');
$plan.append('<div class="strong" title="' + plan.text + '">' + plan.text + '</div>');
$plans.append($plan);
var $bar = $('<div class="gantt-bar"></div>');
$('<div class="gantt-bar-progress bg-primary"></div>').css(
{
width: plan.progress + '%',
background: themeColor,
}).appendTo($bar);
$bar.append('<div class="gantt-task-info text-muted small"><?php echo $lang->programplan->task;?> ' + plan.completeTasks.length + '/' + plan.tasks.length + '</div>').attr('title', $.zui.formatDate(plan.startDatetime, 'yyyy-MM-dd') + '~' + $.zui.formatDate(plan.endDatetime, 'yyyy-MM-dd'));
var $row = $('<div class="gantt-row" data-id="' + plan.id + '"></div>').append($bar);
$ganttCanvas.append($row);
});
var $bar = $('<div class="gantt-bar"></div>');
$('<div class="gantt-bar-progress bg-primary"></div>').css(
{
width: plan.progress + '%',
background: themeColor,
}).appendTo($bar);
$bar.append('<div class="gantt-task-info text-muted small"><?php echo $lang->programplan->task;?> ' + plan.completeTasks.length + '/' + plan.tasks.length + '</div>').attr('title', $.zui.formatDate(plan.startDatetime, 'yyyy-MM-dd') + '~' + $.zui.formatDate(plan.endDatetime, 'yyyy-MM-dd'));
var $row = $('<div class="gantt-row" data-id="' + plan.id + '"></div>').append($bar);
$ganttCanvas.append($row);
});
/* Layout gantt container */
$ganttContainer.css('left', $plans.width() + 15);
$ganttCanvas.css('height', canvasHeight);
/* Layout gantt container */
$ganttContainer.css('left', $plans.width() + 15);
$ganttCanvas.css('height', canvasHeight);
/* Layout gantt */
layoutGantt();
$(window).on('resize', layoutGantt);
setTimeout(layoutGantt, 100);
/* Layout gantt */
layoutGantt();
$(window).on('resize', layoutGantt);
setTimeout(layoutGantt, 100);
/* Bind events */
$ganttContainer.on('scroll', function()
{
$plans.scrollTop($ganttContainer.scrollTop());
});
/* Bind events */
$ganttContainer.on('scroll', function()
{
$plans.scrollTop($ganttContainer.scrollTop());
});
/**
* Layout gantt
*
* @return {void}
*/
function layoutGantt()
{
var minWidth = $ganttContainer.width();
var timeGap = minTimeGap < TIME_GAP_STEP ? minTimeGap : Math.floor(minTimeGap / TIME_GAP_STEP) * TIME_GAP_STEP;
var colsCount = Math.ceil(days / timeGap);
var canvasWidth = Math.max(minWidth, colsCount * MIN_COL_WIDTH);
var colWidth = Math.floor(canvasWidth / colsCount);
var pxPerMs = colWidth / (timeGap * ONE_DAY);
$ganttCanvas.css('width', canvasWidth).find('.gantt-col').remove();
for (var i = 0; i < colsCount; ++i)
{
var $col = $('<div class="gantt-col"></div>');
$col.css(
{
left: i * colWidth,
width: colWidth,
height: canvasHeight
});
var colTime = startDatetime + i * timeGap * ONE_DAY;
$col.append('<div class="gantt-col-time text-muted small">' + $.zui.formatDate(colTime, 'MM/dd') + '</div>');
$ganttCanvas.append($col);
}
/**
* Layout gantt
*
* @return {void}
*/
function layoutGantt()
{
var minWidth = $ganttContainer.width();
var timeGap = minTimeGap < TIME_GAP_STEP ? minTimeGap : Math.floor(minTimeGap / TIME_GAP_STEP) * TIME_GAP_STEP;
var colsCount = Math.ceil(days / timeGap);
var canvasWidth = Math.max(minWidth, colsCount * MIN_COL_WIDTH);
var colWidth = Math.floor(canvasWidth / colsCount);
var pxPerMs = colWidth / (timeGap * ONE_DAY);
$ganttCanvas.css('width', canvasWidth).find('.gantt-col').remove();
for (var i = 0; i < colsCount; ++i)
{
var $col = $('<div class="gantt-col"></div>');
$col.css(
{
left: i * colWidth,
width: colWidth,
height: canvasHeight
});
var colTime = startDatetime + i * timeGap * ONE_DAY;
$col.append('<div class="gantt-col-time text-muted small">' + $.zui.formatDate(colTime, 'MM/dd') + '</div>');
$ganttCanvas.append($col);
}
$.each(plans, function(index, plan)
{
var $planRow = $gantt.find('.gantt-row[data-id="' + plan.id + '"]');
$planRow.find('.gantt-bar').css(
{
left: Math.floor((plan.startDatetime - startDatetime) * pxPerMs),
width: Math.floor((plan.endDatetime - plan.startDatetime) * pxPerMs)
});
});
$.each(plans, function(index, plan)
{
var $planRow = $gantt.find('.gantt-row[data-id="' + plan.id + '"]');
$planRow.find('.gantt-bar').css(
{
left: Math.floor((plan.startDatetime - startDatetime) * pxPerMs),
width: Math.floor((plan.endDatetime - plan.startDatetime) * pxPerMs)
});
});
$gantt.find('.gantt-today').css('left', (Date.now() - startDatetime) * pxPerMs);
}
$gantt.find('.gantt-today').css('left', (Date.now() - startDatetime) * pxPerMs);
}
/**
* Create date from string
*
* @param {String} dateStr like '2020-08-02'
* @return {Number} Date timestramp
*/
function createDatetime(dateStr)
{
dateStr = dateStr.split('-');
var year = Number.parseInt(dateStr[0].length > 3 ? dateStr[0] : dateStr[2], 10);
var month = Number.parseInt(dateStr[1], 10);
var day = Number.parseInt(dateStr[2].length > 3 ? dateStr[0] : dateStr[2], 10);
return new Date(year, month - 1, day).getTime();
}
/**
* Create date from string
*
* @param {String} dateStr like '2020-08-02'
* @return {Number} Date timestramp
*/
function createDatetime(dateStr)
{
dateStr = dateStr.split('-');
var year = Number.parseInt(dateStr[0].length > 3 ? dateStr[0] : dateStr[2], 10);
var month = Number.parseInt(dateStr[1], 10);
var day = Number.parseInt(dateStr[2].length > 3 ? dateStr[0] : dateStr[2], 10);
return new Date(year, month - 1, day).getTime();
}
<?php endif;?>
}
<?php endif;?>
}
initWaterfallGanttBlock();
</script>
initWaterfallGanttBlock();
}());
</script>
</div>
+5
View File
@@ -883,6 +883,7 @@ class bug extends control
$bug = $this->bug->getById($bugID);
$productID = $bug->product;
$executionID = $bug->execution;
$projectID = $bug->project;
$currentModuleID = $bug->module;
$this->bug->checkBugExecutionPriv($bug);
@@ -928,6 +929,10 @@ class bug extends control
{
$openedBuilds = $this->build->getExecutionBuildPairs($executionID, $productID, $bug->branch, 'noempty,noterminate,nodone');
}
elseif($projectID)
{
$openedBuilds = $this->build->getProjectBuildPairs($projectID, $productID, $bug->branch, 'noempty,noterminate,nodone');
}
else
{
$openedBuilds = $this->build->getProductBuildPairs($productID, $bug->branch, 'noempty,noterminate,nodone');
+39
View File
@@ -278,6 +278,7 @@ function loadProductExecutions(productID, projectID = 0)
if(typeof(bugExecution) == 'string' && systemMode != 'classic') $('#executionIdBox').prepend("<span class='input-group-addon' style='border-left-width: 0px;'>" + bugExecution + "</span>");
if(required) $(this).addClass('required');
});
loadProjectBuilds(projectID);
}
/**
@@ -393,6 +394,44 @@ function loadExecutionStories(executionID)
$('#storyIdBox').load(link, function(){$('#story').chosen();});
}
/**
* Load builds of a project.
*
* @param int $projectID
* @access public
* @return void
*/
function loadProjectBuilds(projectID)
{
var branch = $('#branch').val();
if(typeof(branch) == 'undefined') branch = 0;
var productID = $('#product').val();
var oldOpenedBuild = $('#openedBuild').val() ? $('#openedBuild').val() : 0;
if(page == 'create')
{
var link = createLink('build', 'ajaxGetProjectBuilds', 'projectID=' + projectID + '&productID=' + productID + '&varName=openedBuild&build=' + oldOpenedBuild + "&branch=" + branch);
$.get(link, function(data)
{
if(!data) data = '<select id="openedBuild" name="openedBuild" class="form-control" multiple=multiple></select>';
$('#openedBuild').replaceWith(data);
$('#openedBuild').val(oldOpenedBuild);
$('#openedBuild_chosen').remove();
$('#openedBuild').next('.picker').remove();
$("#openedBuild").chosen();
})
}
else
{
var link = createLink('build', 'ajaxGetProjectBuilds', 'projectID=' + projectID + '&productID=' + productID + '&varName=openedBuild&build=' + oldOpenedBuild + '&branch=' + branch);
$('#openedBuildBox').load(link, function(){$(this).find('select').val(oldOpenedBuild).chosen()});
var oldResolvedBuild = $('#resolvedBuild').val() ? $('#resolvedBuild').val() : 0;
var link = createLink('build', 'ajaxGetProductBuilds', 'productID=' + productID + '&varName=resolvedBuild&build=' + oldResolvedBuild + '&branch=' + branch);
$('#resolvedBuildBox').load(link, function(){$(this).find('select').val(oldResolvedBuild).chosen()});
}
}
/**
* Load builds of a execution.
*
+1 -1
View File
@@ -153,7 +153,7 @@
foreach($modulePath as $key => $module)
{
$moduleTitle .= $module->name;
if(!common::printLink('bug', 'browse', "productID=$bug->product&branch=$module->branch&browseType=byModule&param=$module->id", $module->name)) echo $module->name;
if(!common::printLink('bug', 'browse', "productID=$bug->product&branch=$module->branch&browseType=byModule&param=$module->id", $module->name, '', "data-app='qa'")) echo $module->name;
if(isset($modulePath[$key + 1]))
{
$moduleTitle .= '/';
+36
View File
@@ -380,6 +380,42 @@ class build extends control
}
}
/**
* AJAX: get builds of a project in html select.
*
* @param int $projectID
* @param string $varName the name of the select object to create
* @param string $build build to selected
* @param string|int $branch
* @param int $index the index of batch create bug.
* @param bool $needCreate if need to append the link of create build
* @param string $type get all builds or some builds belong to normal releases and executions are not done.
* @access public
* @return string
*/
public function ajaxGetProjectBuilds($projectID, $productID, $varName, $build = '', $branch = 'all', $index = 0, $needCreate = false, $type = 'normal')
{
$isJsonView = $this->app->getViewType() == 'json';
if($varName == 'openedBuild')
{
if(empty($projectID)) $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $index, $type);
$params = ($type == 'all') ? 'noempty' : 'noempty, noterminate, nodone';
$builds = $this->build->getProjectBuildPairs($projectID, $productID, $branch, $params, $build);
if($isJsonView) die(json_encode($builds));
die(html::select($varName . '[]', $builds , '', 'size=4 class=form-control multiple'));
}
if($varName == 'resolvedBuild')
{
if(empty($projectID)) $this->ajaxGetProductBuilds($productID, $varName, $build, $branch, $index, $type);
$params = ($type == 'all') ? '' : 'noterminate, nodone';
$builds = $this->build->getProjectBuildPairs($projectID, $productID, $branch, $params, $build);
if($isJsonView) die(json_encode($builds));
die(html::select($varName, $builds, $build, "class='form-control'"));
}
}
/**
* AJAX: get builds of an execution in html select.
*
+4 -2
View File
@@ -848,7 +848,9 @@ class commonModel extends model
if(!isset($linkPart[2])) continue;
$method = $linkPart[2];
if($currentModule == 'report' and $method == 'annualData') continue; // Skip some pages that do not require permissions.
/* Skip some pages that do not require permissions.*/
if($currentModule == 'report' and $method == 'annualData') continue;
if($currentModule == 'my' and $currentMethod == 'team') continue;
if(common::hasPriv($currentModule, $method))
{
@@ -2161,7 +2163,7 @@ EOD;
$menu = isset($lang->navGroup->$module) ? $lang->navGroup->$module : $module;
$menu = strtolower($menu);
if($menu != 'qa' and !isset($lang->$menu->menu)) return true;
if($menu == 'my' or $menu == 'index' or $module == 'tree') return true;
if(($menu == 'my' && $method != 'team')or $menu == 'index' or $module == 'tree') return true;
if($module == 'company' and $method == 'dynamic') return true;
if($module == 'action' and $method == 'editcomment') return true;
if($module == 'action' and $method == 'comment') return true;
+2 -2
View File
@@ -22,7 +22,7 @@
#kanbanList .kanban-card {display: grid;}
#kanbanList .kanban-card > .title {white-space: nowrap; overflow: hidden; text-overflow: ellipsis;}
#kanbanList .kanban-card.has-progress {padding-right: 40px; position: relative;}
#kanbanList .kanban-card.has-progress > .progress-pie {position: absolute; right: 7px; top: 7px}
#kanbanList .kanban-card.has-progress > .progress-pie {position: absolute; right: 7px; top: 7px; width: 24px; height: 24px;}
#kanbanList .kanban-card.has-left-border {border-left: 2px solid #838a9d;}
#kanbanList .kanban-card.has-left-border.border-left-green {border-left-color: #0bd986;}
#kanbanList .kanban-card.has-left-border.border-left-red {border-left-color: #ff5d5d;}
@@ -40,7 +40,7 @@
#kanbanList .kanban-card.kanban-card-span:hover,
#kanbanList .kanban-col[data-type="unclosedProduct"] .kanban-card:hover {box-shadow: none;}
#kanbanList .kanban-card.kanban-card-span > .title,
#kanbanList .kanban-col[data-type="unclosedProduct"] .kanban-card > .title {white-space: normal; line-height: 1;}
#kanbanList .kanban-col[data-type="unclosedProduct"] .kanban-card > .title {white-space: nowrap; line-height: 1;}
#kanbanList .kanban-col[data-type="normalRelease"] .kanban-card > .title {display: flex; flex-direction: row; flex-wrap: nowrap; align-items: center;}
#kanbanList .kanban-col[data-type="normalRelease"] .kanban-card > .title > .text {display: block; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;}
-7
View File
@@ -1402,13 +1402,6 @@ class execution extends control
}
}
$isStage = false;
if(!empty($project->model) and $project->model == 'waterfall')
{
$isStage = true;
$this->lang->execution->type = str_replace($this->lang->executionCommon, $this->lang->project->stage, $this->lang->execution->type);
}
$this->loadModel('user');
$poUsers = $this->user->getPairs('noclosed|nodeleted|pofirst', '', $this->config->maxCount);
if(!empty($this->config->user->moreLink)) $this->config->moreLinks["PM"] = $this->config->user->moreLink;
+1
View File
@@ -5,3 +5,4 @@
#kanbanList .kanban-col[data-type="project"] .kanban-lane-items {height: 100%; display: flex; flex-direction: column; justify-content: center;}
#kanbanList .kanban-lane-name > .text {display: none;}
#kanbanList .kanban-item.link-block > a {cursor: move;}
#kanbanList .kanban-lane + .kanban-lane {margin-top: 2px!important;}
+1 -1
View File
@@ -32,7 +32,7 @@
#kanbanContainer {margin: 0;}
#kanbanContainer > .panel-body {overflow: auto;}
#kanbans .kanban {min-height: initial;}
#kanbans .kanban-lane {min-height: 150px;}
#kanbans .kanban-lane {min-height: 150px; margin-top: 2px;}
#kanbans .kanban-affixed > .kanban-header {top: 100px;}
#kanbans .kanban-card[data-scale-size="4"] {padding: 8px;}
#kanbans .kanban-card[data-scale-size="3"] {padding: 3px 4px;}
+2 -2
View File
@@ -159,13 +159,13 @@ $(function()
{
data: processKanbanData(),
laneNameWidth: 5,
virtualize: true,
droppable:
{
selector: '.kanban-item:not(.kanban-item-span)',
target: findDropColumns,
finish: handleFinishDrop,
mouseButton: 'left'
},
virtualize: true
}
});
});
+2 -2
View File
@@ -880,7 +880,7 @@ $(function()
var menuCreator = window.menuCreators[menuType];
if(!menuCreator) return;
var options = $.extend({event, $trigger: $trigger}, $trigger.data());
var options = $.extend({event: event, $trigger: $trigger}, $trigger.data());
var items = menuCreator(options);
if(!items || !items.length) return;
@@ -921,7 +921,7 @@ $(function()
{
$.get(createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=" + entertime + "&browseType=" + browseType + "&groupBy=" + groupBy), function(data)
{
if(data && lastUpdateData !== lastUpdateData)
if(data && lastUpdateData !== data)
{
lastUpdateData = data;
kanbanGroup = $.parseJSON(data);
+1 -1
View File
@@ -73,7 +73,7 @@ class executionModel extends model
/* Unset story, bug, build and testtask if type is ops. */
$execution = $this->getByID($executionID);
if($execution and $execution->type == 'stage')
if($execution and $execution->type == 'stage' and $this->config->systemMode == 'new')
{
global $lang;
$this->app->loadLang('project');
+1 -1
View File
@@ -36,7 +36,7 @@
<?php js::set('errorSameProducts', $lang->execution->errorSameProducts);?>
<?php js::set('errorSameBranches', $lang->execution->errorSameBranches);?>
<?php js::set('productID', empty($productID) ? 0 : $productID);?>
<?php js::set('isStage', false);?>
<?php js::set('isStage', $isStage);?>
<?php js::set('copyExecutionID', $copyExecutionID);?>
<?php js::set('systemMode', $config->systemMode);?>
<?php js::set('projectCommon', $lang->project->common);?>
+3
View File
@@ -103,6 +103,7 @@ body {margin-bottom: 25px;}
?>
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i> <?php echo $lang->product->searchStory;?></a>
</div>
<?php if(!isonlybody()): ?>
<div class="btn-toolbar pull-right">
<?php
if(!isset($browseType)) $browseType = '';
@@ -176,6 +177,7 @@ body {margin-bottom: 25px;}
<?php echo "</div>";?>
<?php endif;?>
</div>
<?php endif; ?>
</div>
<div id="mainContent" class="main-row fade">
<div class="side-col" id="sidebar">
@@ -364,6 +366,7 @@ body {margin-bottom: 25px;}
</div>
</div>
<?php js::set('replaceID', 'taskList')?>
<?php if(isonlybody()) js::set('modalWidthReset', 1200) ?>
<script>
$(function()
{
+2 -2
View File
@@ -7,7 +7,7 @@ $lang->gitlab->create = 'Create GitLab';
$lang->gitlab->edit = 'Edit GitLab';
$lang->gitlab->view = 'View GitLab';
$lang->gitlab->bindUser = 'Bind User';
$lang->gitlab->webhook = 'webhook';
$lang->gitlab->webhook = 'Webhook';
$lang->gitlab->bindProduct = 'Import Product';
$lang->gitlab->importIssue = 'Import Issue';
$lang->gitlab->delete = 'Delete GitLab';
@@ -84,7 +84,7 @@ $lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'
$lang->gitlab->errorLang[0] = 'You cannot set Internal as its Visibility Level, if it is private in GitLab.';
$lang->gitlab->errorLang[1] = 'You cannot set Public as its Visibility Level, if it is private in GitLab.';
$lang->gitlab->errorLang[2] = 'Is too short (minimum is 8 characters)';
$lang->gitlab->errorLang[2] = 'Password is too short (minimum is 8 characters)';
$lang->gitlab->errorLang[3] = 'It should contain only letters, digits, underscore, hyphen and period. It should not start with hypen, or end with .git or .atom.';
$lang->gitlab->project = new stdclass;
+5 -5
View File
@@ -7,7 +7,7 @@ $lang->gitlab->create = '添加GitLab';
$lang->gitlab->edit = '编辑GitLab';
$lang->gitlab->view = '查看GitLab';
$lang->gitlab->bindUser = '绑定用户';
$lang->gitlab->webhook = 'webhook';
$lang->gitlab->webhook = 'Webhook';
$lang->gitlab->bindProduct = '关联产品';
$lang->gitlab->importIssue = '关联issue';
$lang->gitlab->delete = '删除GitLab';
@@ -19,7 +19,7 @@ $lang->gitlab->binded = '已绑定';
$lang->gitlab->serverFail = '连接GitLab服务器异常,请检查GitLab服务器。';
$lang->gitlab->lastUpdate = '最后更新';
$lang->gitlab->confirmAddWebhook = '您确定创建Webhook吗?';
$lang->gitlab->addWebhookSuccess = 'webhook创建成功';
$lang->gitlab->addWebhookSuccess = 'Webhook创建成功';
$lang->gitlab->failCreateWebhook = 'Webhook创建失败,请查看日志';
$lang->gitlab->placeholderSearch = '请输入项目名称';
@@ -84,7 +84,7 @@ $lang->gitlab->apiError[3] = "can contain only letters, digits, '_', '-' and '.'
$lang->gitlab->errorLang[0] = '私有分组的项目,可见性级别不能设为内部。';
$lang->gitlab->errorLang[1] = '私有分组的项目,可见性级别不能设为公开。';
$lang->gitlab->errorLang[2] = '太短(最少8个字符)';
$lang->gitlab->errorLang[2] = '密码太短(最少8个字符)';
$lang->gitlab->errorLang[3] = "只能包含字母、数字、'.'-'和'.'。不能以'-'开头、以'.git'结尾或以'.atom'结尾。";
$lang->gitlab->project = new stdclass;
@@ -114,9 +114,9 @@ $lang->gitlab->user = new stdclass;
$lang->gitlab->user->id = "用户ID";
$lang->gitlab->user->name = "名称";
$lang->gitlab->user->username = "用户名";
$lang->gitlab->user->email = "电子邮件";
$lang->gitlab->user->email = "邮箱";
$lang->gitlab->user->password = "密码";
$lang->gitlab->user->passwordRepeat = "重复密码";
$lang->gitlab->user->passwordRepeat = "请重复密码";
$lang->gitlab->user->projectsLimit = "限制项目";
$lang->gitlab->user->canCreateGroup = "可创建组";
$lang->gitlab->user->external = "外部人员";
+1 -1
View File
@@ -13,7 +13,7 @@
<?php include '../../common/view/header.html.php';?>
<div id="mainMenu" class="clearfix">
<div class='pull-left'>
<?php echo html::backButton('<i class="icon icon-back icon-sm"></i> ' . $lang->goback, '', 'btn btn-secondary');?>
<?php echo html::linkButton('<i class="icon icon-back icon-sm"></i> ' . $lang->goback, $this->createLink('gitlab', 'browse'), 'self', '','btn btn-secondary');?>
</div>
<div class="btn-toolbar pull-right">
<?php if(common::hasPriv('gitlab', 'create')) common::printLink('gitlab', 'createGroup', "gitlabID=$gitlabID", "<i class='icon icon-plus'></i> " . $lang->gitlab->group->create, '', "class='btn btn-primary'");?>
+1 -1
View File
@@ -13,7 +13,7 @@
<?php include '../../common/view/header.html.php';?>
<div id="mainMenu" class="clearfix">
<div class='pull-left'>
<?php echo html::backButton('<i class="icon icon-back icon-sm"></i> ' . $lang->goback, '', 'btn btn-secondary');?>
<?php echo html::linkButton('<i class="icon icon-back icon-sm"></i> ' . $lang->goback, $this->createLink('gitlab', 'browse'), 'self', '','btn btn-secondary');?>
</div>
<div class="btn-toolbar pull-right">
<?php common::printLink('gitlab', 'createUser', "gitlabID=$gitlabID", "<i class='icon icon-plus'></i> " . $lang->gitlab->user->create, '', "class='btn btn-primary'");?>
+1 -1
View File
@@ -72,7 +72,7 @@
<th><?php echo $lang->gitlab->user->avatar;?></th>
<td>
<div id="avatarUpload" class="text-center">
<?php echo html::avatar(array('avatar'=>' ', 'account'=>''), 50); ?>
<?php echo html::avatar(array('avatar'=>$defaultTheme . 'images/repo/avatar.jpeg', 'account'=>''), 50); ?>
<input type="file" name="avatar" id="files" class="form-control hidden">
<?php echo html::a('javascript:void(0);', '<i class="icon icon-pencil icon-2x"></i>', '', "class='btn-avatar' id='avatarUploadBtn' data-toggle='tooltip' data-container='body' data-placement='bottom' title='{$lang->gitlab->user->avatar}'");?>
</div>
+1 -1
View File
@@ -73,7 +73,7 @@
<th><?php echo $lang->gitlab->user->avatar;?></th>
<td>
<div id="avatarUpload" class="text-center">
<?php echo html::avatar(array('avatar'=>$user->avatar_url, 'account'=>''), 50); ?>
<?php echo html::avatar(array('avatar'=>$user->avatar_url ? $user->avatar_url : $defaultTheme . 'images/repo/avatar.jpeg', 'account'=>''), 50); ?>
<input type="file" name="avatar" id="files" class="form-control hidden">
<?php echo html::a('javascript:void(0);', '<i class="icon icon-pencil icon-2x"></i>', '', "class='btn-avatar' id='avatarUploadBtn' data-toggle='tooltip' data-container='body' data-placement='bottom' title='{$lang->gitlab->user->avatar}'");?>
</div>
@@ -9,7 +9,7 @@
</div>
<div id='mainContent' class='main-content'>
<form class='main-form form-ajax' method='post' id='teamForm'>
<table class='table table-form'>
<table class='table-form'>
<thead>
<tr class='text-center'>
<th><?php echo $lang->gitlab->group->memberName;?></th>
@@ -51,7 +51,7 @@
</tbody>
<tfoot>
<tr>
<td colspan='6' class='text-center form-actions'>
<td colspan='4' class='text-center form-actions'>
<?php
echo html::submitButton('', '', 'hidden btn btn-wide btn-primary');
echo html::commonButton($lang->save, 'onclick="saveMembers()" id="saveBtn"', 'btn btn-wide btn-primary');
@@ -8,13 +8,15 @@
</div>
<div id='mainContent' class='main-content'>
<form class='main-form form-ajax' method='post' id='teamForm'>
<table class='table table-form'>
<table class='table-form'>
<thead>
<tr class='text-center'>
<th><?php echo $lang->gitlab->group->memberName;?></th>
<th><?php echo $lang->gitlab->group->memberAccessLevel;?></th>
<th class='c-date'><?php echo $lang->gitlab->group->memberExpiresAt;?></th>
<th class="c-actions"><?php echo $lang->actions;?></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
@@ -52,7 +54,7 @@
</tbody>
<tfoot>
<tr>
<td colspan='6' class='text-center form-actions'>
<td colspan='4' class='text-center form-actions'>
<?php
echo html::submitButton('', '', 'hidden btn btn-wide btn-primary');
echo html::commonButton($lang->save, 'onclick="saveMembers()" id="saveBtn"', 'btn btn-wide btn-primary');
+1 -1
View File
@@ -1281,7 +1281,7 @@ $lang->resource->mr->create = 'create';
$lang->resource->mr->browse = 'browse';
$lang->resource->mr->edit = 'edit';
$lang->resource->mr->delete = 'delete';
$lang->resource->mr->view = 'view';
$lang->resource->mr->view = 'overview';
$lang->resource->mr->accept = 'accept';
$lang->resource->mr->diff = 'viewDiff';
$lang->resource->mr->link = 'linkList';
+1
View File
@@ -292,6 +292,7 @@ class mailModel extends model
}
/* Remove deleted users. */
$this->app->loadConfig('message');
$users = $this->loadModel('user')->getPairs('nodeleted|all');
$blockUsers = isset($this->config->message->blockUser) ? explode(',', $this->config->message->blockUser) : array();
foreach($toList as $key => $to) if(!isset($users[trim($to)]) or in_array(trim($to), $blockUsers)) unset($toList[$key]);
+5 -2
View File
@@ -208,7 +208,7 @@ class mr extends control
$this->view->compile = $this->loadModel('compile')->getById($MR->compileID);
$this->view->compileJob = $MR->jobID ? $this->loadModel('job')->getById($MR->jobID) : false;
$this->view->title = $this->lang->mr->view;
$this->view->title = $this->lang->mr->overview;
$this->view->MR = $MR;
$this->view->rawMR = isset($rawMR) ? $rawMR : false;
$this->view->product = $product;
@@ -400,7 +400,10 @@ class mr extends control
public function close($MRID)
{
$MR = $this->mr->getByID($MRID);
return $this->send($this->mr->close($MR));
$result = $this->mr->close($MR);
if($result['result'] == 'fali') return $this->send($result);
die(js::locate($result['locate'], 'parent'));
}
/**
-2
View File
@@ -7,7 +7,6 @@ $lang->mr->browse = "Browse";
$lang->mr->list = "List";
$lang->mr->edit = "Edit";
$lang->mr->delete = "Delete";
$lang->mr->view = "View";
$lang->mr->accept = "Accept";
$lang->mr->source = 'source';
$lang->mr->target = 'target';
@@ -82,7 +81,6 @@ $lang->mr->sourceBranch = 'Source branch';
$lang->mr->targetProject = 'Target project';
$lang->mr->targetBranch = 'Target branch';
$lang->mr->usersTips = 'Tip: If you cannot choose the assignee, please go to the GitLab page to bind the user first.';
$lang->mr->notFound = "Merge Request does not exist!";
$lang->mr->toCreatedMessage = "The merge request you submitted:<a href='%s'>%s</a>, the build task succeeded.";
$lang->mr->toReviewerMessage = "You have one merge request <a href='%s'>%s</a> waiting.";
+2 -4
View File
@@ -7,7 +7,6 @@ $lang->mr->browse = "浏览{$lang->mr->common}";
$lang->mr->list = $lang->mr->browse;
$lang->mr->edit = "编辑{$lang->mr->common}";
$lang->mr->delete = "删除{$lang->mr->common}";
$lang->mr->view = "{$lang->mr->common}详情";
$lang->mr->accept = "合并请求";
$lang->mr->source = '源项目分支';
$lang->mr->target = '目标项目分支';
@@ -64,8 +63,8 @@ $lang->mr->approvalStatusList['approved'] = '已通过';
$lang->mr->approvalStatusList['rejected'] = '已拒绝';
$lang->mr->notApproved = '审核拒绝的';
$lang->mr->assignedToMe = '指派给我的';
$lang->mr->createdByMe = '我创建的';
$lang->mr->assignedToMe = '指派给我';
$lang->mr->createdByMe = '由我创建';
$lang->mr->statusList = array();
$lang->mr->statusList['all'] = '所有';
@@ -87,7 +86,6 @@ $lang->mr->targetBranch = '目标分支';
$lang->mr->noCompileJob = '没有构建任务';
$lang->mr->compileUnexecuted = '还未执行';
$lang->mr->usersTips = '提示:如果无法选择指派人,请先前往GitLab页面绑定用户。';
$lang->mr->notFound = "此{$lang->mr->common}不存在。";
$lang->mr->toCreatedMessage = "您提交的合并请求:<a href='%s'>%s</a> 构建任务执行通过。";
$lang->mr->toReviewerMessage = "有一个合并请求:<a href='%s'>%s</a> 待审核。";
+1 -3
View File
@@ -6,7 +6,6 @@ $lang->mr->browse = "瀏覽{$lang->mr->common}";
$lang->mr->list = $lang->mr->browse;
$lang->mr->edit = "編輯{$lang->mr->common}";
$lang->mr->delete = "刪除{$lang->mr->common}";
$lang->mr->view = "{$lang->mr->common}詳情";
$lang->mr->accept = "合併請求";
$lang->mr->source = '源項目分支';
$lang->mr->target = '目標項目分支';
@@ -69,8 +68,7 @@ $lang->mr->sourceBranch = '源分支';
$lang->mr->targetProject = '目標項目';
$lang->mr->targetBranch = '目標分支';
$lang->mr->usersTips = '提示:如果無法選擇指派人,請先前往GitLab頁面綁定用戶。';
$lang->mr->notFound = "此{$lang->mr->common}不存在。";
$lang->mr->notFound = "此{$lang->mr->common}不存在。";
$lang->mr->apiError = new stdclass;
$lang->mr->apiError->createMR = "通過API創建合併請求失敗,失敗原因:%s";
+4 -2
View File
@@ -705,7 +705,7 @@ class mrModel extends model
public function approve($MR, $action = 'approve', $comment = '')
{
$this->loadModel('action');
$actionID = $this->action->create('mrapproval', $MR->id, $action);
$actionID = $this->action->create('mr', $MR->id, $action);
$oldMR = $MR;
if(isset($MR->status) and $MR->status == 'opened')
@@ -1080,7 +1080,9 @@ class mrModel extends model
*/
public function unlink($MRID, $productID, $type, $linkID)
{
return $this->dao->delete()->from(TABLE_RELATION)->where('product')->eq($productID)->andWhere('AType')->eq('mr')->andWhere('AID')->eq($MRID)->andWhere('BType')->eq($type)->andWhere('BID')->eq($linkID)->exec();
$this->dao->delete()->from(TABLE_RELATION)->where('product')->eq($productID)->andWhere('AType')->eq('mr')->andWhere('AID')->eq($MRID)->andWhere('BType')->eq($type)->andWhere('BID')->eq($linkID)->exec();
$this->loadModel('action')->create($type, $linkID, 'deletemr');
}
/**
+1 -1
View File
@@ -82,7 +82,7 @@
<?php endif;?>
<td class='c-actions'>
<?php
common::printLink('mr', 'view', "mr={$MR->id}", '<i class="icon icon-eye"></i>', '', "title='{$lang->mr->view}' class='btn btn-info'");
common::printLink('mr', 'view', "mr={$MR->id}", '<i class="icon icon-eye"></i>', '', "title='{$lang->mr->overview}' class='btn btn-info'");
common::printLink('mr', 'edit', "mr={$MR->id}", '<i class="icon icon-edit"></i>', '', "title='{$lang->mr->edit}' class='btn btn-info'");
common::printLink('mr', 'diff', "mr={$MR->id}", '<i class="icon icon-review"></i>', '', "title='{$lang->mr->viewDiff}' class='btn btn-info'");
common::printLink('mr', 'link', "mr={$MR->id}", '<i class="icon icon-link"></i>', '', "title='{$lang->mr->link}' class='btn btn-info'" . ($MR->linkButton == false ? 'disabled' : ''));
-4
View File
@@ -72,10 +72,6 @@
<th><?php echo $lang->mr->assignee;?></th>
<td><?php echo html::select('assignee', $users, '', "class='form-control chosen'");?></td>
</tr>
<tr>
<th></th>
<td><?php echo $lang->mr->usersTips;?></td>
</tr>
<tr>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton();?>
-4
View File
@@ -87,10 +87,6 @@
<th><?php echo $lang->mr->assignee;?></th>
<td><?php echo html::select('assignee', $users, $assignee, "class='form-control chosen'");?></td>
</tr>
<tr>
<th></th>
<td><?php echo $lang->mr->usersTips;?></td>
</tr>
<tr>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton();?>
+2 -2
View File
@@ -103,7 +103,7 @@
<div class="btn-toolbar">
<?php common::printBack(inlink('browse', '')); ?>
<?php $acceptDisabled = ($MR->approvalStatus != 'approved' or ($MR->compileID !=0 and $MR->compileStatus != 'success')) ? ' disabled' : ''; ?>
<?php if($rawMR->state == 'opened' and !$rawMR->has_conflicts) echo html::a(inlink('accept', "mr=$MR->id", '', true), '<i class="icon icon-flow"></i> ' . $lang->mr->acceptMR, '', "id='mergeButton' class='btn' $acceptDisabled"); ?>
<?php if($rawMR->state == 'opened' and !$rawMR->has_conflicts) echo html::a(inlink('accept', "mr=$MR->id"), '<i class="icon icon-flow"></i> ' . $lang->mr->acceptMR, '', "id='mergeButton' class='btn' $acceptDisabled"); ?>
<?php if($rawMR->state == 'opened'): ?>
<?php if($rawMR->has_conflicts or ($MR->compileID !=0 and $MR->compileStatus != 'success') or $MR->approvalStatus == 'approved'):?>
<?php echo html::a(inlink('approval', "mr=$MR->id&action=approve", '', true), '<i class="icon icon-ok"></i> ' . $lang->mr->approve, '', "id='mergeButton' class='btn iframe showinonlybody' disabled"); ?>
@@ -111,7 +111,7 @@
<?php echo html::a(inlink('approval', "mr=$MR->id&action=approve", '', true), '<i class="icon icon-ok"></i> ' . $lang->mr->approve, '', "id='mergeButton' class='btn iframe showinonlybody'"); ?>
<?php endif;?>
<?php echo html::a(inlink('approval', "mr=$MR->id&action=reject", '', true), '<i class="icon icon-bug"></i> ' . $lang->mr->reject, '', "id='mergeButton' class='btn iframe showinonlybody'" . ($MR->approvalStatus == 'rejected' ? 'disabled' : '')); ?>
<?php echo html::a(inlink('close', "mr=$MR->id"), '<i class="icon icon-close"></i> ' . $lang->mr->close, '', "id='mergeButton' class='btn'"); ?>
<?php common::printIcon('mr', 'close', "mr=$MR->id", $MR, 'button', 'off', 'hiddenwin');?>
<?php echo html::a(inlink('edit', "mr=$MR->id"), '<i class="icon icon-edit"></i> ' . str_replace($lang->mr->common, '', $lang->mr->edit), '', "id='mergeButton' class='btn'"); ?>
<?php endif;?>
<?php if($rawMR->state == 'closed') echo html::a(inlink('reopen', "mr=$MR->id"), '<i class="icon icon-restart"></i> ' . $lang->mr->reopen, '', "id='mergeButton' class='btn'"); ?>
+1 -1
View File
@@ -364,7 +364,7 @@ class my extends control
$sort = $this->loadModel('common')->appendOrder($orderBy);
$bugs = $this->loadModel('bug')->getUserBugs($this->app->user->account, $type, $sort, 0, $pager);
$bugs = $this->bug->checkDelayedBugs($bugs);
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'myBug');
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug', false);
/* assign. */
$this->view->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->bug;
+21 -14
View File
@@ -161,6 +161,7 @@ class productModel extends model
if($this->cookie->preProductID != $this->session->product)
{
$this->cookie->set('preBranch', 0);
setcookie('preBranch', 0, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
}
return $this->session->product;
@@ -530,20 +531,26 @@ class productModel extends model
$output .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
$output .= "</div></div>";
$notNormalProduct = (isset($currentProduct->type) and $currentProduct->type != 'normal');
$isTrackMethod = ($currentModule == 'story' and $currentMethod == 'track');
$isTreeBrowseMethod = ($currentModule == 'tree' and $currentMethod == 'browse');
$isShowBranchMethod = (strpos($this->config->product->showBranchMethod, $currentMethod) !== false and $currentModule == 'product') || $isTrackMethod || $isTreeBrowseMethod;
if($notNormalProduct and strpos(',testsuite,testreport,', ',' . $currentModule . ',') === false and ($this->app->tab == 'qa' or $isShowBranchMethod))
$notNormalProduct = (isset($currentProduct->type) and $currentProduct->type != 'normal');
if($notNormalProduct)
{
$this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$currentProduct->type]);
$branches = $this->loadModel('branch')->getPairs($productID, 'all');
$branchName = isset($branches[$branch]) ? $branches[$branch] : $branches[0];
$dropMenuLink = helper::createLink('branch', 'ajaxGetDropMenu', "objectID=$productID&branch=$branch&module=$currentModule&method=$currentMethod&extra=$extra");
$isShowBranch = false;
if($currentModule == 'story' and $currentMethod == 'track') $isShowBranch = true;
if($currentModule == 'tree' and $currentMethod == 'browse') $isShowBranch = true;
if($currentModule == 'product' and strpos($this->config->product->showBranchMethod, $currentMethod) !== false) $isShowBranch = true;
if($this->app->tab == 'qa' and strpos(',testsuite,testreport,testtask,', ",$currentModule,") === false) $isShowBranch = true;
if($this->app->tab == 'qa' and $currentModule == 'testtask' and strpos(',create,edit,', ",$currentMethod,") === false) $isShowBranch = true;
if($isShowBranch)
{
$this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$currentProduct->type]);
$branches = $this->loadModel('branch')->getPairs($productID, 'all');
$branchName = isset($branches[$branch]) ? $branches[$branch] : $branches[0];
$dropMenuLink = helper::createLink('branch', 'ajaxGetDropMenu', "objectID=$productID&branch=$branch&module=$currentModule&method=$currentMethod&extra=$extra");
$output .= "<div class='btn-group header-btn'><button id='currentBranch' data-toggle='dropdown' type='button' class='btn'><span class='text'>{$branchName}</span> <span class='caret' style='margin-bottom: -1px'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
$output .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
$output .= "</div></div>";
$output .= "<div class='btn-group header-btn'><button id='currentBranch' data-toggle='dropdown' type='button' class='btn'><span class='text'>{$branchName}</span> <span class='caret' style='margin-bottom: -1px'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
$output .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
$output .= "</div></div>";
}
}
return $output;
@@ -1020,7 +1027,7 @@ class productModel extends model
->orWhere('t2.PM')->eq($this->app->user->account)
->markRight(1)
->fi()
->beginIF($branch)->andWhere('t1.branch')->in($branch)->fi()
->beginIF($branch !== '' and $branch !== 'all')->andWhere('t1.branch')->in($branch)->fi()
->andWhere('t2.deleted')->eq('0')
->orderBy($orderBy)
->fetchAll('id');
@@ -1234,7 +1241,7 @@ class productModel extends model
$executionPairs = $executionPairs + $execution->children;
continue;
}
if($this->config->systemMode == 'new') $executionPairs[$execution->id] = $projectPairs[$execution->project] . '/' . $execution->name;
if($this->config->systemMode == 'new' and isset($projectPairs[$execution->project])) $executionPairs[$execution->id] = $projectPairs[$execution->project] . '/' . $execution->name;
if($this->config->systemMode == 'classic') $executionPairs[$execution->id] = $execution->name;
}
+13 -1
View File
@@ -115,6 +115,13 @@ function processKanbanData(key, programsData)
return {id: kanbanId, columns: columns, lanes: lanes};
}
/** Calculate column height */
function calcColHeight(col, lane, colCards, colHeight)
{
if (col.type !== 'doingProject') return colHeight;
return colCards.length * 62;
}
$(function()
{
/* Init all kanbans */
@@ -122,6 +129,11 @@ $(function()
{
var $kanban = $('#kanban-' + key);
if(!$kanban.length) return;
$kanban.kanban({data: processKanbanData(key, programsData), virtualize: true});
$kanban.kanban(
{
data: processKanbanData(key, programsData),
virtualize: true,
calcColHeight: calcColHeight
});
});
});
+1
View File
@@ -920,6 +920,7 @@ class programplanModel extends model
->where('t1.product')->eq($productID)
->andWhere('t2.project')->eq($executionID)
->andWhere('t2.grade')->eq(1)
->andWhere('t2.deleted')->eq(0)
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
->orderBy('t2.id desc')
->fetchPairs();
+1
View File
@@ -18,6 +18,7 @@
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php
$productID = $productID == 0 ? key($this->product->getProductPairsByProject($project->id)) : $productID;
$buildName = $build ? " <span class='label label-danger'>Build:{$build->name}</span>" : '';
echo html::a($this->inlink('bug', "projectID={$project->id}&productID={$productID}&orderBy=status,id_desc&build=$buildID&type=all"), "<span class='text'>{$lang->bug->allBugs}</span>" . ($type == 'all' ? " <span class='label label-light label-badge'>{$pager->recTotal}</span>$buildName" : ''), '', "id='allTab' class='btn btn-link" . ('all' == $type ? ' btn-active-text' : '') . "'");
echo html::a($this->inlink('bug', "projectID={$project->id}&productID={$productID}&orderBy=status,id_desc&build=$buildID&type=unresolved"), "<span class='text'>{$lang->bug->unResolved}</span>" . ($type == 'unresolved' ? " <span class='label label-light label-badge'>{$pager->recTotal}</span>$buildName" : ''), '', "id='unresolvedTab' class='btn btn-link" . ('unresolved' == $type ? ' btn-active-text' : '') . "'");
+4 -4
View File
@@ -279,8 +279,8 @@ class projectrelease extends control
/**
* Notify for release.
*
* @param int $releaseID
*
* @param int $releaseID
* @access public
* @return void
*/
@@ -290,7 +290,7 @@ class projectrelease extends control
{
if(isset($_POST['notify']))
{
$notify = implode(',', $this->post->notify);
$notify = implode(',', $this->post->notify);
$this->dao->update(TABLE_RELEASE)->set('notify')->eq($notify)->where('id')->eq($releaseID)->exec();
$this->release->sendmail($releaseID);
@@ -298,7 +298,7 @@ class projectrelease extends control
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->release = $this->release->getById($releaseID);
$this->view->actions = $this->loadModel('action')->getList('release', $releaseID);
$this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed');
+1
View File
@@ -26,3 +26,4 @@ $lang->projectrelease->unlinkStory = "Unlink {$lang->SRCommon}";
$lang->projectrelease->unlinkBug = 'Unlink Bug';
$lang->projectrelease->export = 'Export as HTML';
$lang->projectrelease->browseAction = "Release List";
$lang->projectrelease->notify = 'notify';
+1
View File
@@ -26,3 +26,4 @@ $lang->projectrelease->unlinkStory = "Unlink {$lang->SRCommon}";
$lang->projectrelease->unlinkBug = 'Unlink Bug';
$lang->projectrelease->export = 'Export as HTML';
$lang->projectrelease->browseAction = "Release List";
$lang->projectrelease->notify = 'notify';
+1
View File
@@ -26,3 +26,4 @@ $lang->projectrelease->unlinkStory = "Unlink {$lang->SRCommon}";
$lang->projectrelease->unlinkBug = 'Unlink Bug';
$lang->projectrelease->export = 'Export HTML';
$lang->projectrelease->browseAction = "Release List";
$lang->projectrelease->notify = 'notify';
+1
View File
@@ -26,3 +26,4 @@ $lang->projectrelease->unlinkStory = "Unlink {$lang->SRCommon}";
$lang->projectrelease->unlinkBug = 'Unlink Bug';
$lang->projectrelease->export = 'Xuất ra HTML';
$lang->projectrelease->browseAction = "Release List";
$lang->projectrelease->notify = 'notify';
+1
View File
@@ -26,3 +26,4 @@ $lang->projectrelease->unlinkStory = "移除{$lang->SRCommon}";
$lang->projectrelease->unlinkBug = '移除Bug';
$lang->projectrelease->export = '导出HTML';
$lang->projectrelease->browseAction = "发布列表";
$lang->projectrelease->notify = "通知";
+4 -1
View File
@@ -32,7 +32,10 @@ class qaModel extends model
$branch = ($this->cookie->preBranch !== '' and $branch === '') ? $this->cookie->preBranch : $branch;
setcookie('preBranch', $branch, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
if(!in_array($this->app->rawModule, $this->config->qa->noDropMenuModule)) $this->lang->switcherMenu = $this->loadModel('product')->getSwitcher($productID, $extra, $branch);
$product = $this->loadModel('product')->getById($productID);
if($product->type != 'normal') $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
if(!in_array($this->app->rawModule, $this->config->qa->noDropMenuModule)) $this->lang->switcherMenu = $this->product->getSwitcher($productID, $extra, $branch);
if($this->app->rawModule == 'product' and $this->app->rawMethod == 'showerrornone') $this->lang->switcherMenu = '';
common::setMenuVars('qa', $productID);
}
+1
View File
@@ -1854,6 +1854,7 @@ class repoModel extends model
public function syncCommit($repoID, $branchID)
{
$repo = $this->getRepoByID($repoID);
$this->scm = $this->app->loadClass('scm');
$this->scm->setEngine($repo);
$latestInDB = $this->dao->select('DISTINCT t1.*')->from(TABLE_REPOHISTORY)->alias('t1')
+6 -3
View File
@@ -45,10 +45,13 @@ function loadProduct(productID)
*/
function loadBranch()
{
var branch = $('#branch').val();
var branch = $('#branch').val();
var productID = $('#product').val();
if(typeof(branch) == 'undefined') branch = 0;
loadProductModules($('#product').val(), branch);
loadProductPlans($('#product').val(), branch);
if(typeof(productID) == 'undefined' && config.currentMethod == 'edit') productID = oldProductID;
loadProductModules(productID, branch);
loadProductPlans(productID, branch);
}
/**
+3 -3
View File
@@ -409,7 +409,7 @@ class taskModel extends model
$mails[$i]->actionID = $actionID;
}
if(!dao::isError())
if(!dao::isError())
{
$this->loadModel('score')->create('ajax', 'batchCreate');
$this->loadModel('kanban')->updateLane($executionID, 'task');
@@ -1728,7 +1728,7 @@ class taskModel extends model
if($oldTask->parent > 0) $this->updateParentStatus($taskID);
if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story);
if($task->status == 'done' && !dao::isError())
if($task->status == 'done' && !dao::isError())
{
$this->loadModel('score')->create('task', 'finish', $taskID);
$this->loadModel('kanban')->updateLane($oldTask->execution, 'task');
@@ -2164,7 +2164,7 @@ class taskModel extends model
->page($pager)
->fetchAll('id');
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'task');
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'task', false);
$taskTeam = $this->dao->select('*')->from(TABLE_TEAM)->where('root')->in(array_keys($tasks))->andWhere('type')->eq('task')->fetchGroup('root');
if(!empty($taskTeam))
+4 -3
View File
@@ -1778,7 +1778,7 @@ class testcase extends control
$this->view->productID = $productID;
$this->view->branch = $branch;
$this->view->cases = $this->loadModel('testsuite')->getNotImportedCases($productID, $libID, $orderBy, $pager, $browseType, $queryID);
$this->view->modules = $this->loadModel('tree')->getOptionMenu($productID, 'case', 0, (int)$branch);
$this->view->modules = $this->loadModel('tree')->getOptionMenu($productID, 'case', 0, $branch === 'all' ? 0 : (int)$branch);
$this->view->libModules = $this->tree->getOptionMenu($libID, 'caselib');
$this->view->pager = $pager;
$this->view->orderBy = $orderBy;
@@ -1839,7 +1839,8 @@ class testcase extends control
$caseLang = $this->lang->testcase;
$caseConfig = $this->config->testcase;
$modules = $this->loadModel('tree')->getOptionMenu($productID, 'case', 0, $branch);
$branches = $this->loadModel('branch')->getPairs($productID);
$modules = $this->loadModel('tree')->getOptionMenu($productID, 'case', 0, empty(array_keys($branches)) ? 0 : array_keys($branches));
$stories = $this->loadModel('story')->getProductStoryPairs($productID, $branch);
$fields = $this->testcase->getImportFields($productID);
$fields = array_flip($fields);
@@ -2020,7 +2021,7 @@ class testcase extends control
$this->view->caseData = $caseData;
$this->view->stepData = $stepData;
$this->view->productID = $productID;
$this->view->branches = $this->loadModel('branch')->getPairs($productID);
$this->view->branches = $branches;
$this->view->isEndPage = $pagerID >= $allPager;
$this->view->allCount = $allCount;
$this->view->allPager = $allPager;
+2 -1
View File
@@ -81,7 +81,8 @@ $(function()
</td>
<td><?php echo html::input("title[$key]", htmlSpecialString($case->title, ENT_QUOTES), "class='form-control'")?></td>
<td style='overflow:visible'>
<?php echo html::select("module[$key]", $modules, isset($case->module) ? $case->module : ((!empty($case->id) and isset($cases[$case->id])) ? $cases[$case->id]->module : ''), "class='form-control chosen moduleChange'")?>
<?php $caseModules = (isset($case->branch) and $case->branch != 0) ? $modules[BRANCH_MAIN] + $modules[$case->branch] : $modules;?>
<?php echo html::select("module[$key]", $caseModules, isset($case->module) ? $case->module : ((!empty($case->id) and isset($cases[$case->id])) ? $cases[$case->id]->module : ''), "class='form-control chosen moduleChange'")?>
</td>
<td style='overflow:visible'>
<?php $storyID = isset($case->story) ? $case->story : ((!empty($case->id) and isset($cases[$case->id])) ? $cases[$case->id]->story : '');?>
+1 -1
View File
@@ -252,7 +252,7 @@ class testtask extends control
/* Create testtask from testtask of test.*/
$productID = $productID ? $productID : key($this->products);
$executions = empty($productID) ? array() : $this->loadModel('product')->getExecutionPairsByProduct($productID, 0, 'id_desc', $projectID);
$executions = empty($productID) ? array() : $this->loadModel('product')->getExecutionPairsByProduct($productID, '', 'id_desc', $projectID);
$builds = empty($productID) ? array() : $this->loadModel('build')->getProductBuildPairs($productID, 'all', 'notrunk', true);
$testreports = $this->testtask->getTestReportPairsByBuild($build);
+1 -1
View File
@@ -23,7 +23,7 @@ function loadProductRelated()
*/
function loadExecutions(productID)
{
link = createLink('product', 'ajaxGetExecutions', 'productID=' + productID + '&projectID=' + projectID);
link = createLink('product', 'ajaxGetExecutions', 'productID=' + productID + '&projectID=' + projectID + '&branch=');
$.get(link, function(data)
{
if(!data) data = '<select id="execution" name="execution" class="form-control"></select>';
+1 -1
View File
@@ -1433,7 +1433,7 @@ class testtaskModel extends model
echo "</span>";
break;
case 'title':
if(isset($run->branch)) echo "<span class='label label-info label-outline'>{$branches[$run->branch]}</span>";
if(!empty($branches)) echo "<span class='label label-badge label-outline'>{$branches[$run->branch]}</span>";
if($canView)
{
if($fromCaseID)
+1
View File
@@ -123,6 +123,7 @@ class treeModel extends model
*/
public function getOptionMenu($rootID, $type = 'story', $startModule = 0, $branch = 0)
{
if(empty($branch)) $branch = 0;
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getModulePairs();
/* If type of $branch is array, get modules of these branches. */
+38 -1
View File
@@ -341,7 +341,7 @@ class upgrade extends control
/* When upgrading historical data as a project, handle products that are not linked with the project. */
if(!empty($singleProducts)) $this->upgrade->computeProductAcl($singleProducts, $programID);
}
elseif($type == 'sprint' or $type == 'moreLink')
elseif($type == 'sprint')
{
$linkedSprints = $this->post->sprints;
@@ -363,6 +363,43 @@ class upgrade extends control
}
}
}
elseif($type == 'moreLink')
{
$linkedSprints = $this->post->sprints;
/* Create Program. */
list($programID, $projectList, $lineID) = $this->upgrade->createProgram(array(), $linkedSprints);
if(dao::isError()) die(js::error(dao::getError()));
if($_POST['projectType'] == 'execution')
{
/* Use historical projects as execution upgrades. */
$this->upgrade->processMergedData($programID, $projectList, $lineID, array(), $linkedSprints);
}
else
{
/* Use historical projects as project upgrades. */
foreach($linkedSprints as $sprint)
{
$this->upgrade->processMergedData($programID, $projectList[$sprint], $lineID, array(), array($sprint => $sprint));
}
/* If is more-link sprints, and as project upgrade, set old relation into new project. */
$projectProducts = $this->dao->select('product,project,branch,plan')->from(TABLE_PROJECTPRODUCT)
->where('project')->in($linkedSprints)
->fetchAll();
foreach($projectProducts as $projectProduct)
{
$data = new stdclass();
$data->project = $projectList[$projectProduct->project];
$data->product = $projectProduct->product;
$data->plan = $projectProduct->plan;
$data->branch = $projectProduct->branch;
$this->dao->replace(TABLE_PROJECTPRODUCT)->data($data)->exec();
}
}
}
die(js::locate($this->createLink('upgrade', 'mergeProgram', "type=$type&programID=$programID&projectType=$projectType"), 'parent'));
}
-4
View File
@@ -35,10 +35,6 @@ div.divider {vertical-align: middle;}
.programParams td > label:first-child {margin-right: 10px;}
.programParams td > label:last-child {margin-left: 0px;}
.lineGroup .sprintRename input {max-width: 120px;}
.projectList .scroll-handle .checkbox-primary {display: inline-block;}
.sprintRename {margin-top: 5px;}
.sprintRename input {display: inline-block; width: auto;}
.sprintRename .btn-group {display: inline-block;}
.sprintGroup .sprintItem .checkbox-primary {display: inline-block;}
-42
View File
@@ -1150,45 +1150,3 @@ function isSelectAll(lineID = 0, type = 'product')
if(objectNum > checkedObjectNum || objectNum == 0) checked = false;
return checked;
}
$(function()
{
$('.sprintItem').mouseover(function()
{
$(this).find('#sprintEdit').removeClass('hidden');
}).mouseout(function()
{
$(this).find('#sprintEdit').addClass('hidden');
})
$(document).on('click', '#sprintEdit i', function()
{
$(this).parents('.sprintItem').addClass('hidden');
$(this).parents('.sprintItem').next('.sprintRename').removeClass('hidden');
})
$('.sprintRename button.name-confirm').click(function()
{
var execution = $(this).parent().siblings('input').attr('name').split('_');
var newExecutionName = $(this).parent().siblings('input').val();
var link = createLink('execution', 'ajaxUpdateExecutionName', 'executionID=' + execution[1] + '&newExecutionName=' + newExecutionName);
var $this = $(this);
$.post(link, function(data)
{
if(data)
{
$this.closest('.sprintRename').addClass('hidden');
$this.closest('.sprintRename').prev('.sprintItem').removeClass('hidden').find('.checkbox-primary label').text(newExecutionName);
}
})
})
$('.sprintRename button.name-cancel').click(function()
{
var oldValue = $(this).closest('.sprintRename').prev('.sprintItem').find('.checkbox-primary label').text();
$(this).closest('.sprintRename').addClass('hidden');
$(this).closest('.sprintRename').prev('.sprintItem').removeClass('hidden');
$(this).parent().siblings('input').val(oldValue);
})
})
+4 -12
View File
@@ -50,22 +50,14 @@
</div>
<div class='projectList'>
<div class='scroll-handle'>
<?php if(isset($productGroups[$productID])):?>
<?php foreach($productGroups[$productID] as $sprint):?>
<?php if(isset($productGroups[$productID])):?>
<?php foreach($productGroups[$productID] as $sprint):?>
<div class="sprintItem">
<?php echo html::checkBox("sprints[$line->id][$productID]", array($sprint->id => $sprint->name), '', "title='{$sprint->name}' data-product='{$product->id}' data-line='{$line->id}' data-begin='{$sprint->begin}' data-end='{$sprint->end}' data-status='{$sprint->status}' data-pm='{$sprint->PM}' class='tile'");?>
<?php echo html::hidden("sprintIdList[$line->id][$productID][$sprint->id]", $sprint->id);?>
<a href='#' id='sprintEdit' class='hidden'><i class="icon-common-edit icon-edit muted"></i></a>
</div>
<div class="sprintRename hidden">
<?php echo html::input("sprintRename_$sprint->id", $sprint->name, "class='form-control'");?>
<div class="btn-group">
<button type="button" class="btn btn-success name-confirm"><i class='icon icon-check'></i></button>
<button type="button" class="btn btn-gray name-cancel"><i class='icon icon-close'></i></button>
</div>
</div>
<?php endforeach;?>
<?php endif;?>
<?php endforeach;?>
<?php endif;?>
</div>
</div>
</div>
+4 -12
View File
@@ -27,22 +27,14 @@
</div>
<div class='projectList'>
<div class='scroll-handle'>
<?php if(isset($productGroups[$productID])):?>
<?php foreach($productGroups[$productID] as $sprint):?>
<?php if(isset($productGroups[$productID])):?>
<?php foreach($productGroups[$productID] as $sprint):?>
<div class="sprintItem">
<?php echo html::checkBox("sprints[$productID]", array($sprint->id => $sprint->name), '', "data-product='{$productID}' data-begin='{$sprint->begin}' data-end='{$sprint->end}' data-status='{$sprint->status}' data-pm='{$sprint->PM}'");?>
<?php echo html::hidden("sprintIdList[$productID][$sprint->id]", $sprint->id);?>
<a href='#' id='sprintEdit' class='hidden'><i class="icon-common-edit icon-edit muted"></i></a>
</div>
<div class="sprintRename hidden">
<?php echo html::input("sprintRename_$sprint->id", $sprint->name, "class='form-control'");?>
<div class="btn-group">
<button type="button" class="btn btn-success name-confirm"><i class='icon icon-check'></i></button>
<button type="button" class="btn btn-gray name-cancel"><i class='icon icon-close'></i></button>
</div>
</div>
<?php endforeach;?>
<?php endif;?>
<?php endforeach;?>
<?php endif;?>
</div>
</div>
</div>
@@ -17,14 +17,6 @@
<?php foreach($noMergedSprints as $sprintID => $sprint):?>
<div class="sprintItem">
<?php echo html::checkBox("sprints", array($sprint->id => $sprint->name), '', "data-begin='{$sprint->begin}' data-end='{$sprint->end}' data-status='{$sprint->status}' data-pm='{$sprint->PM}'");?>
<a href='#' id='sprintEdit' class='hidden'><i class="icon-common-edit icon-edit muted"></i></a>
</div>
<div class="sprintRename hidden">
<?php echo html::input("sprintRename_$sprint->id", $sprint->name, "class='form-control'");?>
<div class="btn-group">
<button type="button" class="btn btn-success name-confirm"><i class='icon icon-check'></i></button>
<button type="button" class="btn btn-gray name-cancel"><i class='icon icon-close'></i></button>
</div>
</div>
<?php endforeach;?>
</div>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+7 -7
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

File diff suppressed because one or more lines are too long
@@ -1,7 +1,6 @@
<?php
$config->message->available['xuanxuan']['story'] = $config->message->objectTypes['story'];
$config->message->available['xuanxuan']['task'] = $config->message->objectTypes['task'];
$config->message->available['xuanxuan']['bug'] = $config->message->objectTypes['bug'];
$config->message->available['xuanxuan']['todo'] = $config->message->objectTypes['todo'];
$config->message->available['xuanxuan']['release'] = $config->message->objectTypes['release'];
$config->message->setting['xuanxuan']['setting'] = $config->message->available['xuanxuan'];
$config->message->available['xuanxuan']['story'] = $config->message->objectTypes['story'];
$config->message->available['xuanxuan']['task'] = $config->message->objectTypes['task'];
$config->message->available['xuanxuan']['bug'] = $config->message->objectTypes['bug'];
$config->message->available['xuanxuan']['todo'] = $config->message->objectTypes['todo'];
$config->message->setting['xuanxuan']['setting'] = $config->message->available['xuanxuan'];