Merge branch 'master' into 'sprint/183_zhouxin_47982'

# Conflicts:
#   module/group/lang/resource.php
#   module/kanban/js/view.js
#   module/kanban/lang/en.php
#   module/kanban/lang/zh-cn.php
This commit is contained in:
孙广明
2022-01-21 05:47:16 +00:00
114 changed files with 2809 additions and 495 deletions
+4
View File
@@ -65,6 +65,7 @@ $filter->mr = new stdclass();
$filter->ci = new stdclass();
$filter->tree = new stdclass();
$filter->productplan = new stdclass();
$filter->kanban = new stdclass();
$filter->block->default = new stdclass();
$filter->block->main = new stdclass();
@@ -158,6 +159,7 @@ $filter->ci->checkCompileStatus = new stdclass();
$filter->execution->export = new stdclass();
$filter->tree->browse = new stdclass();
$filter->productplan->browse = new stdclass();
$filter->kanban->space = new stdclass();
$filter->my->work->cookie['pagerMyTask'] = 'int';
$filter->my->work->cookie['pagerMyRequirement'] = 'int';
@@ -404,3 +406,5 @@ $filter->ci->checkCompileStatus->get['gitlabOnly'] = 'string';
$filter->tree->browse->cookie['preProductID'] = 'int';
$filter->tree->browse->cookie['preBranch'] = 'reg::word';
$filter->kanban->space->cookie['showClosed'] = 'code';
+3
View File
@@ -292,6 +292,9 @@ $config->objectTables['kanbanlane'] = TABLE_KANBANLANE;
$config->objectTables['kanbanorder'] = TABLE_KANBANORDER;
$config->objectTables['kanbangroup'] = TABLE_KANBANGROUP;
$config->objectTables['kanbancard'] = TABLE_KANBANCARD;
$config->objectTables['sonarqube'] = TABLE_PIPELINE;
$config->objectTables['gitlab'] = TABLE_PIPELINE;
$config->objectTables['jebkins'] = TABLE_PIPELINE;
$config->newFeatures = array('introduction', 'tutorial', 'youngBlueTheme');
+6
View File
@@ -1,2 +1,8 @@
ALTER TABLE `zt_kanbanspace` ADD `type` varchar(50) NOT NULL AFTER `name`;
UPDATE `zt_kanbanspace` SET `type` = 'cooperation';
ALTER TABLE `zt_kanban` ADD `importObject` varchar(255) NOT NULL AFTER `displayCards`;
ALTER TABLE `zt_kanban` ADD `performable` enum ('0', '1') NOT NULL DEFAULT '0' AFTER `archived`;
ALTER TABLE `zt_job` ADD `sonarqubeServer` mediumint(8) unsigned NOT NULL AFTER `triggerType`;
ALTER TABLE `zt_job` ADD `projectKey` varchar(255) NOT NULL AFTER `sonarqubeServer`;
+1
View File
@@ -679,6 +679,7 @@ CREATE TABLE `zt_kanban` (
`status` enum('active','closed') NOT NULL default 'active',
`order` mediumint(8) NOT NULL DEFAULT '0',
`displayCards` smallint(6) NOT NULL default '0',
`importObject` varchar(255) NOT NULL,
`createdBy` char(30) NOT NULL,
`createdDate` datetime NOT NULL,
`lastEditedBy` char(30) NOT NULL,
+2 -1
View File
@@ -40,6 +40,7 @@ $config->action->objectNameFields['kanbanspace'] = 'name';
$config->action->objectNameFields['kanbanregion'] = 'name';
$config->action->objectNameFields['kanban'] = 'name';
$config->action->objectNameFields['kanbancard'] = 'name';
$config->action->objectNameFields['sonarqube'] = 'name';
$config->action->commonImgSize = 870;
@@ -55,4 +56,4 @@ $config->action->majorList['execution'] = array('opened', 'edited');
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,';
+20 -1
View File
@@ -134,6 +134,8 @@ $lang->action->objectTypes['kanbanregion'] = 'Kanban Region';
$lang->action->objectTypes['kanbanlane'] = 'Kanban Lane';
$lang->action->objectTypes['kanbancolumn'] = 'Kanban Column';
$lang->action->objectTypes['kanbancard'] = 'Kanban Card';
$lang->action->objectTypes['sonarqube'] = 'SonarQube Server';
$lang->action->objectTypes['sonarqubeproject'] = 'SonarQube Project';
/* Used to describe operation history. */
$lang->action->desc = new stdclass();
@@ -329,6 +331,7 @@ $lang->action->label->finishedbychild = 'finished';
$lang->action->label->closedbychild = 'closed';
$lang->action->label->activatedbychild = 'activated';
$lang->action->label->createchild = 'activated';
$lang->action->label->executed = 'executed';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
@@ -568,6 +571,22 @@ $lang->action->dynamicAction->user['loginxuanxuan'] = 'Login Desktop';
$lang->action->dynamicAction->entry['created'] = 'Add Application';
$lang->action->dynamicAction->entry['edited'] = 'Edit Application';
$lang->action->dynamicAction->job['created'] = 'Create Job';
$lang->action->dynamicAction->job['edited'] = 'Edit Job';
$lang->action->dynamicAction->job['executed'] = 'Execute Job';
$lang->action->dynamicAction->job['deleted'] = 'Delete Job';
$lang->action->dynamicAction->job['undeleted'] = 'Undelete Job';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = 'Delete SonarQube Project';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
/* Generate the corresponding object link. */
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
$lang->action->label->productplan = 'Plan|productplan|view|productID=%s';
@@ -603,7 +622,7 @@ $lang->action->label->issue = 'Issue|issue|view|issueID=%s';
$lang->action->label->design = 'Design|design|view|designID=%s';
$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->kanbanspace = 'Kanban Space|kanban|space|browseType=all';
$lang->action->label->kanbanspace = 'Kanban Space|kanban|space|browseType=%s';
$lang->action->label->kanbanregion = 'Kanban Region|kanban|view|kanbanID=%s';
$lang->action->label->kanban = 'Kanban|kanban|view|kanbanID=%s';
$lang->action->label->kanbancolumn = 'Kanban Column|execution|kanban|execution=%s';
+20 -1
View File
@@ -134,6 +134,8 @@ $lang->action->objectTypes['kanbanregion'] = '看板区域';
$lang->action->objectTypes['kanbanlane'] = '看板泳道';
$lang->action->objectTypes['kanbancolumn'] = '看板列';
$lang->action->objectTypes['kanbancard'] = '看板卡片';
$lang->action->objectTypes['sonarqube'] = 'SonarQube服务器';
$lang->action->objectTypes['sonarqubeproject'] = 'SonarQube项目';
/* 用来描述操作历史记录。*/
$lang->action->desc = new stdclass();
@@ -329,6 +331,7 @@ $lang->action->label->finishedbychild = '完成了';
$lang->action->label->closedbychild = '关闭了';
$lang->action->label->activatedbychild = '激活了';
$lang->action->label->createchild = '激活了';
$lang->action->label->executed = '执行了';
/* 动态信息按照对象分组 */
$lang->action->dynamicAction = new stdclass();
@@ -568,6 +571,22 @@ $lang->action->dynamicAction->user['loginxuanxuan'] = '登录客户端';
$lang->action->dynamicAction->entry['created'] = '添加应用';
$lang->action->dynamicAction->entry['edited'] = '编辑应用';
$lang->action->dynamicAction->job['created'] = '创建构建任务';
$lang->action->dynamicAction->job['edited'] = '编辑构建任务';
$lang->action->dynamicAction->job['executed'] = '执行构建任务';
$lang->action->dynamicAction->job['deleted'] = '删除构建任务';
$lang->action->dynamicAction->job['undeleted'] = '还原构建任务';
$lang->action->dynamicAction->sonarqube['created'] = '创建SonarQube服务器';
$lang->action->dynamicAction->sonarqube['edited'] = '设置SonarQube服务器';
$lang->action->dynamicAction->sonarqube['deleted'] = '删除SonarQube服务器';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = '删除SonarQube项目';
$lang->action->dynamicAction->gitlab['created'] = '创建GitLab服务器';
$lang->action->dynamicAction->gitlab['edited'] = '设置GitLab服务器';
$lang->action->dynamicAction->gitlab['deleted'] = '删除GitLab服务器';
/* 用来生成相应对象的链接。*/
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
$lang->action->label->productplan = "计划|productplan|view|productID=%s";
@@ -603,7 +622,7 @@ $lang->action->label->issue = '问题|issue|view|issueID=%s';
$lang->action->label->design = '设计|design|view|designID=%s';
$lang->action->label->stakeholder = '干系人|stakeholder|view|userID=%s';
$lang->action->label->api = '接口|api|index|libID=%s&moduleID=%s&apiID=%s';
$lang->action->label->kanbanspace = '看板空间|kanban|space|browseType=all';
$lang->action->label->kanbanspace = '看板空间|kanban|space|browseType=%s';
$lang->action->label->kanbanregion = '看板区域|kanban|view|kanbanID=%s';
$lang->action->label->kanban = '看板|kanban|view|kanbanID=%s';
$lang->action->label->kanbancolumn = '看板列|execution|kanban|execution=%s';
+5
View File
@@ -1289,6 +1289,11 @@ class actionModel extends model
{
$params = sprintf($vars, trim($action->product, ','));
}
elseif($action->objectType == 'kanbanspace')
{
$kanbanSpace = $this->dao->select('type')->from(TABLE_KANBANSPACE)->where('id')->eq($action->objectID)->fetch();
$params = sprintf($vars, $kanbanSpace->type);
}
elseif($action->objectType == 'kanbancolumn' or $action->objectType == 'kanbanlane')
{
$params = sprintf($vars, $action->extra);
+10 -1
View File
@@ -3,7 +3,16 @@
.ztf-logo {width: 30%;}
.zendata-logo { width: 30%;}
.block-zendata {height:230px;}
.block-zendata {height:230px; padding: 30px 14px;}
.block-details {padding: 30px 60px;}
.block-details li {width: 50%;}
.block-details-line li {width: 100%;}
.zendata-download {width: 68%;}
.ztf-download {width: 58%;}
.ztf-download-trait {margin: 35px 0 6px 0;}
.ztf-download-trait div {width: 47%;}
.qr-code {padding: 20px 0 20px 32px;}
@media screen and (max-height: 768px)
{
+1
View File
@@ -13,6 +13,7 @@
{
$user = zget($users, $action->actor);
if($action->action == 'login' or $action->action == 'logout') $action->objectName = $action->objectLabel = '';
if($action->objectType == 'sonarqubeproject') $action->objectName = $action->extra;
$class = $action->major ? "class='active'" : '';
echo "<li $class><div>";
if($action->objectLink) printf($lang->block->dynamicInfo, $action->date, $user, $action->actionLabel, $action->objectLabel, $action->objectLink, $action->objectName, $action->objectName);
+130 -14
View File
@@ -402,8 +402,22 @@ class bug extends control
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $bugID));
/* If link from no head then reload. */
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
if(isset($output['executionID']) and isonlybody())
{
$executionID = $this->post->execution ? $this->post->execution : $output['executionID'];
if($executionID == $output['executionID'])
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, 0)"));
}
else
{
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true));
}
}
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success', 'data' => $bugID));
if($this->app->tab == 'execution')
@@ -683,7 +697,25 @@ class bug extends control
setcookie('bugModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
/* If link from no head then reload. */
if(isonlybody() and $executionID)
{
$execution = $this->loadModel('execution')->getByID($executionID);
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::reload('parent.parent'));
}
}
if(isonlybody()) return print(js::reload('parent.parent'));
return print(js::locate($this->createLink('bug', 'browse', "productID={$productID}&branch=$branch&browseType=unclosed&param=0&orderBy=id_desc"), 'parent'));
}
@@ -1180,7 +1212,22 @@ class bug extends control
$this->executeHooks($bugID);
if(isonlybody()) return print(js::closeModal('parent.parent'));
if(isonlybody())
{
$bug = $this->bug->getById($bugID);
$execution = $this->loadModel('execution')->getByID($bug->execution);
if(isset($execution->type) and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent'));
}
}
return print(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
@@ -1354,6 +1401,7 @@ class bug extends control
*/
public function confirmBug($bugID, $extra = '')
{
$bug = $this->bug->getById($bugID);
if(!empty($_POST))
{
$changes = $this->bug->confirm($bugID, $extra);
@@ -1363,11 +1411,27 @@ class bug extends control
$this->executeHooks($bugID);
if(isonlybody()) return print(js::closeModal('parent.parent'));
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(isonlybody())
{
$execution = $this->loadModel('execution')->getByID($bug->execution);
if(isset($execution->type) and $execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent'));
}
}
return print(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
$bug = $this->bug->getById($bugID);
$productID = $bug->product;
$this->bug->checkBugExecutionPriv($bug);
$this->qa->setMenu($this->products, $productID, $bug->branch);
@@ -1410,6 +1474,7 @@ class bug extends control
*/
public function resolve($bugID, $extra = '')
{
$bug = $this->bug->getById($bugID);
if(!empty($_POST))
{
$changes = $this->bug->resolve($bugID, $extra);
@@ -1436,19 +1501,36 @@ class bug extends control
die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent.parent'));
}
}
if(isonlybody()) die(js::reload('parent.parent'));
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(isonlybody())
{
$execution = $this->loadModel('execution')->getByID($bug->execution);
if(isset($execution->type) and $execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent'));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
die(array('status' => 'success', 'data' => $bugID));
return print(array('status' => 'success', 'data' => $bugID));
}
else
{
die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
return print(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
}
$projectID = $this->lang->navGroup->bug == 'project' ? $this->session->project : 0;
$bug = $this->bug->getById($bugID);
$productID = $bug->product;
$users = $this->user->getPairs('noclosed');
$assignedTo = $bug->openedBy;
@@ -1504,6 +1586,7 @@ class bug extends control
*/
public function activate($bugID, $extra = '')
{
$bug = $this->bug->getById($bugID);
if(!empty($_POST))
{
$changes = $this->bug->activate($bugID, $extra);
@@ -1516,11 +1599,27 @@ class bug extends control
$this->executeHooks($bugID);
if(isonlybody()) die(js::closeModal('parent.parent'));
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(isonlybody())
{
$execution = $this->loadModel('execution')->getByID($bug->execution);
if(isset($execution->type) and $execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent'));
}
}
die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
$bug = $this->bug->getById($bugID);
$productID = $bug->product;
$this->bug->checkBugExecutionPriv($bug);
$this->qa->setMenu($this->products, $productID, $bug->branch);
@@ -1547,6 +1646,7 @@ class bug extends control
*/
public function close($bugID, $extra = '')
{
$bug = $this->bug->getById($bugID);
if(!empty($_POST))
{
$changes = $this->bug->close($bugID, $extra);
@@ -1557,18 +1657,34 @@ class bug extends control
$this->executeHooks($bugID);
if(isonlybody()) die(js::closeModal('parent.parent'));
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(isonlybody())
{
$execution = $this->loadModel('execution')->getByID($bug->execution);
if(isset($execution->type) and $execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent'));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
die(array('status' => 'success', 'data' => $bugID));
return print(array('status' => 'success', 'data' => $bugID));
}
else
{
die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
return print(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
}
$bug = $this->bug->getById($bugID);
$productID = $bug->product;
$this->bug->checkBugExecutionPriv($bug);
$this->qa->setMenu($this->products, $productID, $bug->branch);
+3 -4
View File
@@ -48,8 +48,8 @@ $lang->bug->confirmed = 'Confirmed';
$lang->bug->confirmedAB = 'C';
$lang->bug->toTask = 'Convert to Task';
$lang->bug->toStory = 'Convert to Story';
$lang->bug->feedbackBy = 'From Name';
$lang->bug->notifyEmail = 'From Email';
$lang->bug->feedbackBy = 'Discovered by';
$lang->bug->notifyEmail = 'Discoverer Email';
$lang->bug->mailto = 'Mailto';
$lang->bug->openedBy = 'ReportedBy';
$lang->bug->openedByAB = 'Reporter';
@@ -272,7 +272,7 @@ $lang->bug->typeList['config'] = 'Configuration';
$lang->bug->typeList['install'] = 'Installation';
$lang->bug->typeList['security'] = 'Security';
$lang->bug->typeList['performance'] = 'Performance';
$lang->bug->typeList['standard'] = 'CodingConventions';
$lang->bug->typeList['standard'] = 'Standard Specification';
$lang->bug->typeList['automation'] = 'TestScript';
$lang->bug->typeList['designdefect'] = 'DesignDefect';
$lang->bug->typeList['others'] = 'Others';
@@ -419,7 +419,6 @@ $lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
$lang->bug->moreSelects['toclosed'] = $lang->bug->toClosed;
$lang->bug->moreSelects['unconfirmed'] = $lang->bug->unconfirmed;
$lang->bug->moreSelects['assigntonull'] = $lang->bug->assignToNull;
$lang->bug->moreSelects['longlifebugs'] = $lang->bug->longLifeBugs;
-1
View File
@@ -419,7 +419,6 @@ $lang->bug->featureBar['browse']['toclosed'] = $lang->bug->toClosed;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
$lang->bug->moreSelects['unconfirmed'] = $lang->bug->unconfirmed;
$lang->bug->moreSelects['assigntonull'] = $lang->bug->assignToNull;
$lang->bug->moreSelects['longlifebugs'] = $lang->bug->longLifeBugs;
+26 -22
View File
@@ -386,22 +386,24 @@ $lang->qa->menuOrder[45] = 'automation';
$lang->qa->dividerMenu = ',bug,testtask,caselib,';
/* DevOps menu. */
$lang->devops->menu = new stdclass();
$lang->devops->menu->code = array('link' => "{$lang->repo->common}|repo|browse|repoID=%s", 'alias' => 'diff,view,revision,log,blame,showsynccommit');
$lang->devops->menu->compile = array('link' => "{$lang->devops->compile}|job|browse", 'subModule' => 'compile,job');
$lang->devops->menu->mr = array('link' => "{$lang->devops->mr}|mr|browse");
$lang->devops->menu->gitlab = array('link' => "GitLab|gitlab|browse", 'alias' => 'create,edit');
$lang->devops->menu->jenkins = array('link' => "Jenkins|jenkins|browse", 'alias' => 'create,edit');
$lang->devops->menu->maintain = array('link' => "{$lang->devops->repo}|repo|maintain", 'alias' => 'create,edit');
$lang->devops->menu->rules = array('link' => "{$lang->devops->rules}|repo|setrules");
$lang->devops->menu = new stdclass();
$lang->devops->menu->code = array('link' => "{$lang->repo->common}|repo|browse|repoID=%s", 'alias' => 'diff,view,revision,log,blame,showsynccommit');
$lang->devops->menu->compile = array('link' => "{$lang->devops->compile}|job|browse", 'subModule' => 'compile,job');
$lang->devops->menu->mr = array('link' => "{$lang->devops->mr}|mr|browse");
$lang->devops->menu->gitlab = array('link' => "GitLab|gitlab|browse", 'alias' => 'create,edit');
$lang->devops->menu->sonarqube = array('link' => "SonarQube|sonarqube|browse");
$lang->devops->menu->jenkins = array('link' => "Jenkins|jenkins|browse", 'alias' => 'create,edit');
$lang->devops->menu->maintain = array('link' => "{$lang->devops->repo}|repo|maintain", 'alias' => 'create,edit');
$lang->devops->menu->rules = array('link' => "{$lang->devops->rules}|repo|setrules");
$lang->devops->menuOrder[5] = 'code';
$lang->devops->menuOrder[10] = 'compile';
$lang->devops->menuOrder[15] = 'mr';
$lang->devops->menuOrder[20] = 'gitlab';
$lang->devops->menuOrder[25] = 'jenkins';
$lang->devops->menuOrder[30] = 'maintain';
$lang->devops->menuOrder[35] = 'rules';
$lang->devops->menuOrder[25] = 'sonarqube';
$lang->devops->menuOrder[30] = 'jenkins';
$lang->devops->menuOrder[35] = 'maintain';
$lang->devops->menuOrder[40] = 'rules';
/* Kanban menu. */
$lang->kanban->menu = new stdclass();
@@ -489,7 +491,7 @@ $lang->admin->menu->allModel['subMenu']->storyConcept = array('link' => "{$lang-
$lang->admin->menu->allModel['menuOrder'][5] = 'storyConcept';
$lang->admin->menu->waterfall['subMenu'] = new stdclass();
$lang->admin->menu->waterfall['subMenu']->stage = array('link' => '阶段|stage|setType|', 'subModule' => 'stage');
$lang->admin->menu->waterfall['subMenu']->stage = array('link' => "{$lang->stage->common}|stage|setType|", 'subModule' => 'stage');
/* Admin menu order. */
$lang->admin->menuOrder[5] = 'index';
@@ -618,16 +620,18 @@ $lang->navGroup->testtask = 'qa';
$lang->navGroup->testsuite = 'qa';
$lang->navGroup->caselib = 'qa';
$lang->navGroup->devops = 'devops';
$lang->navGroup->repo = 'devops';
$lang->navGroup->job = 'devops';
$lang->navGroup->jenkins = 'devops';
$lang->navGroup->mr = 'devops';
$lang->navGroup->gitlab = 'devops';
$lang->navGroup->compile = 'devops';
$lang->navGroup->ci = 'devops';
$lang->navGroup->svn = 'devops';
$lang->navGroup->git = 'devops';
$lang->navGroup->devops = 'devops';
$lang->navGroup->repo = 'devops';
$lang->navGroup->job = 'devops';
$lang->navGroup->jenkins = 'devops';
$lang->navGroup->mr = 'devops';
$lang->navGroup->gitlab = 'devops';
$lang->navGroup->sonarqube = 'devops';
$lang->navGroup->sonarqubeproject = 'devops';
$lang->navGroup->compile = 'devops';
$lang->navGroup->ci = 'devops';
$lang->navGroup->svn = 'devops';
$lang->navGroup->git = 'devops';
$lang->navGroup->company = 'system';
+7 -1
View File
@@ -66,10 +66,14 @@
<?php $tab = '';?>
<?php if($action->objectType == 'meeting') $tab = $action->project ? "data-app='project'" : "data-app='my'";?>
<?php
if(empty($action->objectName))
if(empty($action->objectName) and $action->objectID)
{
echo '#' . $action->objectID;
}
elseif(empty($action->objectID) and $action->extra)
{
echo $action->extra;
}
elseif(empty($action->objectLink))
{
echo $action->objectName;
@@ -79,8 +83,10 @@
echo html::a($action->objectLink, $action->objectName, '', $tab);
}
?>
<?php if($action->objectID):?>
<span class="label label-id"><?php echo $action->objectID;?></span>
<?php endif;?>
<?php endif;?>
</span>
</div>
</li>
+1 -1
View File
@@ -55,7 +55,7 @@ if($config->systemMode == 'classic' || !$config->systemMode) $lang->custom->exec
$lang->custom->unitList['efficiency'] = 'Working Hours/';
$lang->custom->unitList['manhour'] = 'Man-hour/';
$lang->custom->unitList['cost'] = 'Yuan/Hour';
$lang->custom->unitList['cost'] = 'USD/Hour';
$lang->custom->unitList['hours'] = 'Hours';
$lang->custom->unitList['days'] = 'Days';
$lang->custom->unitList['loc'] = 'KLOC';
+28 -6
View File
@@ -1969,6 +1969,7 @@ class execution extends control
$this->app->loadLang('bug');
$this->app->loadLang('story');
if(empty($groupBy)) $groupBy = 'default';
$this->session->set('execLaneType', $browseType);
$this->lang->execution->menu = new stdclass();
$execution = $this->commonAction($executionID);
@@ -1992,8 +1993,14 @@ class execution extends control
/* Get execution's product. */
$productID = 0;
$products = $this->loadModel('product')->getProducts($execution->project);
if($products) $productID = key($products);
$branchID = 0;
$products = $this->loadModel('product')->getProducts($executionID);
if($products)
{
$productID = key($products);
$branches = $this->loadModel('branch')->getPairs($productID, '', $executionID);
if($branches) $branchID = key($branches);
}
$plans = $this->execution->getPlans($products);
$allPlans = array('' => '');
@@ -2011,6 +2018,7 @@ class execution extends control
$this->view->orderBy = $orderBy;
$this->view->groupBy = $groupBy;
$this->view->productID = $productID;
$this->view->branchID = $branchID;
$this->view->allPlans = $allPlans;
$this->view->kanbanData = $kanbanData;
$this->view->executionActions = $executionActions;
@@ -2651,7 +2659,7 @@ class execution extends control
if(empty($products))
{
echo js::alert($this->lang->execution->errorNoLinkedProducts);
die(js::locate($this->createLink('execution', 'manageproducts', "executionID=$objectID")));
return print(js::locate($this->createLink('execution', 'manageproducts', "executionID=$objectID")));
}
if(!empty($_POST))
@@ -2659,8 +2667,22 @@ class execution extends control
$this->execution->linkStory($objectID, array(), array(), $extra);
if($object->type != 'project' and $object->project != 0) $this->execution->linkStory($object->project);
if(isonlybody()) die(js::reload('parent'));
die(js::locate($browseLink));
if(isonlybody())
{
if($this->app->tab == 'execution' and $object->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($objectID, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent', '', "parent.updateKanban($kanbanData)"));
}
else
{
return print(js::reload('parent'));
}
}
return print(js::locate($browseLink));
}
if($object->type == 'project')
@@ -3434,7 +3456,7 @@ class execution extends control
include $this->app->getModulePath('', 'execution') . 'lang/' . $this->app->getClientLang() . '.php';
}
if($count != 0) echo js::alert(sprintf($this->lang->execution->haveDraft, $count)) . js::locate($this->createLink($moduleName, $execution->type == 'sprint' ? 'story' : 'kanban', $param));
die(js::locate(helper::createLink($moduleName, $fromMethod, $param)));
return print(js::locate(helper::createLink($moduleName, $fromMethod, $param)));
}
/**
+41 -12
View File
@@ -189,8 +189,8 @@ function createColumnMenu(options)
if(!privs.length) return [];
var items = [];
if(privs.includes('setColumn')) items.push({label: kanbanLang.editColumn, icon: 'edit', url: createLink('kanban', 'setColumn', 'columnID=' + column.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
if(privs.includes('setWIP')) items.push({label: kanbanLang.setWIP, icon: 'alert', url: createLink('kanban', 'setWIP', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width' : '500px'}});
if(privs.includes('setColumn')) items.push({label: kanbanLang.editColumn, icon: 'edit', url: createLink('kanban', 'setColumn', 'columnID=' + column.id + '&executionID=' + executionID + '&from=RDKanban', '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
if(privs.includes('setWIP')) items.push({label: kanbanLang.setWIP, icon: 'alert', url: createLink('kanban', 'setWIP', 'columnID=' + column.id + '&executionID=' + executionID + '&from=RDKanban', '' ,'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width' : '500px'}});
var bounds = options.$trigger[0].getBoundingClientRect();
items.$options = {x: bounds.right, y: bounds.top};
@@ -780,7 +780,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if((fromColType == 'developing' || fromColType == 'wait') && priv.canFinishTask)
{
var link = createLink('task', 'finish', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'finish', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -788,7 +788,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if(fromColType == 'developing' && priv.canPauseTask)
{
var link = createLink('task', 'pause', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'pause', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -796,12 +796,12 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if((fromColType == 'pause' || fromColType == 'canceled' || fromColType == 'closed' || fromColType == 'developed') && priv.canActivateTask)
{
var link = createLink('task', 'activate', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'activate', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
if(fromColType == 'wait' && priv.canStartTask)
{
var link = createLink('task', 'start', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'start', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -809,7 +809,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if((fromColType == 'developing' || fromColType == 'wait' || fromColType == 'pause') && priv.canCancelTask)
{
var link = createLink('task', 'cancel', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'cancel', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -817,7 +817,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if((fromColType == 'developed' || fromColType == 'canceled') && priv.canCloseTask)
{
var link = createLink('task', 'close', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'close', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -832,7 +832,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if(fromColType == 'unconfirmed' && priv.canConfirmBug)
{
var link = createLink('bug', 'confirmBug', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('bug', 'confirmBug', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -841,7 +841,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
if(fromColType == 'confirmed' || fromColType == 'unconfirmed') moveCard = true;
if((fromColType == 'closed' || fromColType == 'fixed' || fromColType == 'testing' || fromColType == 'tested') && priv.canActivateBug)
{
var link = createLink('bug', 'activate', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('bug', 'activate', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -849,7 +849,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if(fromColType == 'fixing' || fromColType == 'confirmed' || fromColType == 'unconfirmed')
{
var link = createLink('bug', 'resolve', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('bug', 'resolve', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -865,7 +865,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if(fromColType == 'testing' || fromColType == 'tested')
{
var link = createLink('bug', 'close', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('bug', 'close', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -903,6 +903,33 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
}
}
/**
* Close modal and update kanban data.
*
* @param string kanbanData
* @param int regionID
* @access public
* @return void
*/
function updateKanban(kanbanData, regionID = 0)
{
setTimeout(function()
{
if(regionID)
{
updateRegion(regionID, kanbanData[regionID]);
}
else
{
$('#kanban').children('.region').children("div[id^='kanban']").each(function()
{
var regionID = $(this).attr('data-id');
updateRegion(regionID, kanbanData[regionID]);
});
}
}, 200);
}
/**
* Shift card.
*
@@ -1019,6 +1046,8 @@ function initKanban($kanban)
*/
$(function()
{
if($.cookie('isFullScreen') == 1) $.cookie('isFullScreen', 0);
window.kanbanScaleSize = +$.zui.store.get('executionKanbanScaleSize', 1);
$('#kanbanScaleSize').text(window.kanbanScaleSize);
$('#kanbanScaleControl .btn[data-type="+"]').attr('disabled', window.kanbanScaleSize >= 4 ? 'disabled' : null);
+1 -1
View File
@@ -32,7 +32,7 @@
<?php echo html::a($this->createLink($this->app->rawModule, $this->app->rawMethod, "status=$key&projectID=$projectID&orderBy=$orderBy&productID=$productID"), "<span class='text'>{$label}</span>", '', "class='btn btn-link' id='{$key}Tab' data-app='$from'");?>
<?php endforeach;?>
<?php if($from == 'execution' and $this->config->systemMode == 'new'):?>
<div class='input-control w-150px'>
<div class='input-control w-180px'>
<?php echo html::select('project', $projects, $projectID, "class='form-control chosen' data-placeholder='{$lang->execution->selectProject}'");?>
</div>
<?php endif;?>
+2 -3
View File
@@ -146,12 +146,12 @@ js::set('hasTaskButton', $hasTaskButton);
<button class='btn btn-primary' type='button' data-toggle='dropdown'><i class='icon icon-plus'></i> <?php echo $this->lang->create;?> <span class='caret'></span></button>
<ul class='dropdown-menu pull-right'>
<?php if($canCreateStory) echo '<li>' . html::a(helper::createLink('story', 'create', "productID=$productID&branch=0&moduleID=0&story=0&execution=$execution->id", '', true), $lang->execution->createStory, '', "class='iframe'") . '</li>';?>
<?php if($canBatchCreateStory) echo '<li>' . html::a(helper::createLink('story', 'batchCreate', "productID=$productID&branch=0&moduleID=0&story=0&execution=$execution->id", '', true), $lang->execution->batchCreateStroy, '', "class='iframe' data-width='90%'") . '</li>';?>
<?php if($canBatchCreateStory) echo '<li>' . html::a(helper::createLink('story', 'batchCreate', "productID=$productID&branch=$branchID&moduleID=0&story=0&execution=$execution->id", '', true), $lang->execution->batchCreateStroy, '', "class='iframe' data-width='90%'") . '</li>';?>
<?php if($canLinkStory) echo '<li>' . html::a(helper::createLink('execution', 'linkStory', "execution=$execution->id", '', true), $lang->execution->linkStory, '', "class='iframe' data-width='90%'") . '</li>';?>
<?php if($canLinkStoryByPlane) echo '<li>' . html::a('#linkStoryByPlan', $lang->execution->linkStoryByPlan, '', 'data-toggle="modal"') . '</li>';?>
<?php if($hasStoryButton and $hasBugButton) echo '<li class="divider"></li>';?>
<?php if($canCreateBug) echo '<li>' . html::a(helper::createLink('bug', 'create', "productID=$productID&branch=0&extra=executionID=$execution->id", '', true), $lang->bug->create, '', "class='iframe'") . '</li>';?>
<?php if($canBatchCreateBug) echo '<li>' . html::a(helper::createLink('bug', 'batchCreate', "productID=$productID&branch=0&executionID=$execution->id", '', true), $lang->bug->batchCreate, '', "class='iframe'") . '</li>';?>
<?php if($canBatchCreateBug) echo '<li>' . html::a(helper::createLink('bug', 'batchCreate', "productID=$productID&branch=$branchID&executionID=$execution->id", '', true), $lang->bug->batchCreate, '', "class='iframe'") . '</li>';?>
<?php if(($hasStoryButton or $hasBugButton) and $hasTaskButton) echo '<li class="divider"></li>';?>
<?php if($canCreateTask) echo '<li>' . html::a(helper::createLink('task', 'create', "execution=$execution->id", '', true), $lang->task->create, '', "class='iframe'") . '</li>';?>
<?php if($canBatchCreateTask) echo '<li>' . html::a(helper::createLink('task', 'batchCreate', "execution=$execution->id", '', true), $lang->execution->batchCreateTask, '', "class='iframe'") . '</li>';?>
@@ -168,7 +168,6 @@ js::set('hasTaskButton', $hasTaskButton);
<div class="region<?php if($canSortRegion) echo ' sort';?>" data-id="<?php echo $region->id;?>">
<div class="region-header dropdown">
<span class="strong"><?php echo $region->name;?></span>
<label class="label label-region"><?php echo $this->lang->kanbanlane->common . ' ' . $region->laneCount;?></label>
<span><i class="icon icon-chevron-double-up" data-id="<?php echo $region->id;?>"></i></span>
<span class='regionActions'>
<?php if($canEditRegion || $canCreateLane || $canDeleteRegion):?>
+1 -1
View File
@@ -32,7 +32,7 @@
<thead>
<tr>
<?php $vars = "orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?>
<th class='c-id'><?php common::printOrderLink('id', $orderBy, $vars, $lang->gitlab->id);?></th>
<th class='c-id text-center'><?php common::printOrderLink('id', $orderBy, $vars, $lang->gitlab->id);?></th>
<th class='c-name text-left'><?php common::printOrderLink('name', $orderBy, $vars, $lang->gitlab->name);?></th>
<th class='text-left'><?php common::printOrderLink('url', $orderBy, $vars, $lang->gitlab->url);?></th>
<th class='c-actions-6'><?php echo $lang->actions;?></th>
+25 -7
View File
@@ -670,7 +670,6 @@ $lang->resource->kanban->deleteCard = 'deleteCard';
$lang->resource->kanban->moveCard = 'moveCard';
$lang->resource->kanban->setCardColor = 'setCardColor';
$lang->resource->kanban->laneMove = 'laneMove';
$lang->resource->kanban->cardsSort = 'cardsSort';
$lang->resource->kanban->viewArchivedColumn = 'viewArchivedColumn';
$lang->resource->kanban->viewArchivedCard = 'viewArchivedCard';
$lang->resource->kanban->restoreCard = 'restoreCard';
@@ -722,6 +721,7 @@ $lang->kanban->methodorder[205] = 'archiveColumn';
$lang->kanban->methodorder[210] = 'restoreCard';
$lang->kanban->methodorder[215] = 'setLaneHeight';
$lang->kanban->methodOrder[220] = 'batchCreateCard';
$lang->kanban->methodorder[220] = 'import';
/* Execution. */
$lang->resource->execution = new stdclass();
@@ -1388,6 +1388,24 @@ $lang->gitlab->methodOrder[135] = 'browseTag';
$lang->gitlab->methodOrder[140] = 'browseTagPriv';
$lang->gitlab->methodOrder[145] = 'deleteTagPriv';
/* SonarQube. */
$lang->resource->sonarqube = new stdclass();
$lang->resource->sonarqube->browse = 'browse';
$lang->resource->sonarqube->create = 'create';
$lang->resource->sonarqube->edit = 'edit';
$lang->resource->sonarqube->delete = 'delete';
$lang->resource->sonarqube->browseProject = 'browseProject';
$lang->resource->sonarqube->deleteProject = 'deleteProject';
$lang->resource->sonarqube->execJob = 'execJob';
$lang->sonarqube->methodOrder[5] = 'browse';
$lang->sonarqube->methodOrder[10] = 'create';
$lang->sonarqube->methodOrder[15] = 'edit';
$lang->sonarqube->methodOrder[20] = 'delete';
$lang->sonarqube->methodOrder[25] = 'browseProject';
$lang->sonarqube->methodOrder[35] = 'deleteProject';
$lang->sonarqube->methodOrder[40] = 'execJob';
/* merge request. */
$lang->resource->mr = new stdclass();
$lang->resource->mr->create = 'create';
@@ -1732,12 +1750,12 @@ $lang->backup->methodOrder[25] = 'setting';
$lang->backup->methodOrder[30] = 'rmPHPHeader';
$lang->resource->cron = new stdclass();
$lang->resource->cron->index = 'index';
$lang->resource->cron->turnon = 'turnon';
$lang->resource->cron->create = 'createAction';
$lang->resource->cron->edit = 'edit';
$lang->resource->cron->toggle = 'toggle';
$lang->resource->cron->delete = 'delete';
$lang->resource->cron->index = 'index';
$lang->resource->cron->turnon = 'turnon';
$lang->resource->cron->create = 'createAction';
$lang->resource->cron->edit = 'edit';
$lang->resource->cron->toggle = 'toggle';
$lang->resource->cron->delete = 'delete';
$lang->resource->cron->openProcess = 'restart';
$lang->cron->methodOrder[5] = 'index';
+1
View File
@@ -0,0 +1 @@
#menu { width: 106px;}
+3
View File
@@ -200,6 +200,9 @@ class install extends control
$this->install->grantPriv();
if(dao::isError()) die(js::error(dao::getError()));
$this->install->updateLang();
if(dao::isError()) die(js::error(dao::getError()));
if($this->post->importDemoData) $this->install->importDemoData();
if(dao::isError()) echo js::alert($this->lang->install->errorImportDemoData);
+59
View File
@@ -159,6 +159,65 @@ $lang->install->account = 'Admin Account';
$lang->install->password = 'Admin Password';
$lang->install->errorEmptyPassword = 'Password should not be blank.';
$lang->install->processList['11'] = 'Project management';
$lang->install->processList['12'] = 'Project planning';
$lang->install->processList['13'] = 'Project monitoring';
$lang->install->processList['14'] = 'Risk management';
$lang->install->processList['15'] = 'Closing management';
$lang->install->processList['16'] = 'Quantitative Project management';
$lang->install->processList['17'] = 'Requirements development';
$lang->install->processList['18'] = 'Design and development';
$lang->install->processList['19'] = 'Implementation and testing';
$lang->install->processList['20'] = 'System test';
$lang->install->processList['21'] = 'Customer acceptance';
$lang->install->processList['22'] = 'Quality assurance';
$lang->install->processList['23'] = 'Configuration management';
$lang->install->processList['24'] = 'Metric analysis';
$lang->install->processList['25'] = 'Cause analysis and resolution';
$lang->install->processList['26'] = 'Decision analysis';
$lang->install->basicmeasList['2'] = array('name' => 'Initial size of project user requirements', 'unit' => 'Story points or function points', 'definition' => 'Sum of the size of the baseline version of the first CUSTOMER requirements specification for each product of the project');
$lang->install->basicmeasList['3'] = array('name' => 'Initial scale of project software requirements', 'unit' => 'Story points or function points', 'definition' => 'Sum of the size of the first software requirements specification baseline release for each product of the project');
$lang->install->basicmeasList['4'] = array('name' => 'Real-time scale of project user requirements', 'unit' => 'Story points or function points', 'definition' => 'The actual size of the project user requirements');
$lang->install->basicmeasList['5'] = array('name' => 'Real-time scale of project software requirements', 'unit' => 'Story points or function points', 'definition' => 'The actual scale of the project software requirements');
$lang->install->basicmeasList['6'] = array('name' => 'Estimated project size', 'unit' => 'Story points or function points', 'definition' => 'The estimated size of the project when it was originally estimated');
$lang->install->basicmeasList['8'] = array('name' => 'Project requirements phase planning days', 'unit' => 'Day', 'definition' => 'The sum of planned days for all requirements phases under the project');
$lang->install->basicmeasList['9'] = array('name' => 'Number of days planned during project design phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all design phases under the project');
$lang->install->basicmeasList['10'] = array('name' => 'Planned number of days during project development phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all development phases under the project');
$lang->install->basicmeasList['11'] = array('name' => 'Number of days planned for project test phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all test phases under the project');
$lang->install->basicmeasList['12'] = array('name' => 'Actual days of project requirements phase', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all requirements phases under the project');
$lang->install->basicmeasList['13'] = array('name' => 'Actual days of project design phase', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all design phases under the project');
$lang->install->basicmeasList['14'] = array('name' => 'Actual number of days during the project development phase', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all r&d phases under the project');
$lang->install->basicmeasList['15'] = array('name' => 'Actual number of days during the project test phase', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all test phases under the project');
$lang->install->basicmeasList['26'] = array('name' => 'Plan days by product demand phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all requirements phases under the product');
$lang->install->basicmeasList['27'] = array('name' => 'Plan days by product design stage', 'unit' => 'Day', 'definition' => 'The sum of planned days for all design phases under the product');
$lang->install->basicmeasList['28'] = array('name' => 'Planned days by product development phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all development phases under the product');
$lang->install->basicmeasList['29'] = array('name' => 'Plan days by product test phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all test phases under the product');
$lang->install->basicmeasList['30'] = array('name' => 'Actual days of product demand stage', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all requirement phases under the product');
$lang->install->basicmeasList['31'] = array('name' => 'Actual days of product design stage', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all design phases under the product');
$lang->install->basicmeasList['32'] = array('name' => 'By actual days of product development stage', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all development phases under the product');
$lang->install->basicmeasList['33'] = array('name' => 'By actual days of product test phase', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all testing phases under the product');
$lang->install->basicmeasList['34'] = array('name' => 'Real-time estimated working hours of project tasks', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all tasks under the project');
$lang->install->basicmeasList['35'] = array('name' => 'Total estimated real-time working hours of project requirements', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all requirements related tasks of the project');
$lang->install->basicmeasList['36'] = array('name' => 'Total estimated time of project design work in real time', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all design-related tasks of the project');
$lang->install->basicmeasList['37'] = array('name' => 'Total estimated time of project development in real time', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all development related tasks of the project');
$lang->install->basicmeasList['38'] = array('name' => 'Total estimated time of project test work in real time', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all test related tasks of the project');
$lang->install->basicmeasList['39'] = array('name' => 'Actual man-hours consumed by project tasks', 'unit' => 'Hour','definition' => 'The sum of the actual man-hours consumed for all tasks under the project');
$lang->install->basicmeasList['40'] = array('name' => 'The actual number of man-hours consumed by project demand work', 'unit' => 'Hour','definition' => 'The sum of the actual man-hours consumed by all demand-related tasks of the project');
$lang->install->basicmeasList['41'] = array('name' => 'The actual number of man-hours consumed by project design work', 'unit' => 'Hour','definition' => 'The sum of the actual man-hours consumed by all design-related tasks of the project');
$lang->install->basicmeasList['42'] = array('name' => 'The actual number of man-hours consumed by project development work', 'unit' => 'Hour','definition' => 'The sum of the actual man-hours consumed by all development related tasks of the project');
$lang->install->basicmeasList['43'] = array('name' => 'The actual number of man-hours consumed by the project testing work', 'unit' => 'Hour','definition' => 'The sum of the actual man-hours consumed by all test related tasks of the project');
$lang->install->basicmeasList['44'] = array('name' => 'Total estimated initial hours of project development work', 'unit' => 'Hour','definition' => 'The sum of the initial estimated work hours of all development related work in the first baseline release of the project plan');
$lang->install->basicmeasList['45'] = array('name' => 'Total estimated initial hours of project design work', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours of all design-related work in the first baseline version of the project plan');
$lang->install->basicmeasList['46'] = array('name' => 'Total estimated initial work hours for project testing', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours of all test-related work in the first baseline release of the project plan');
$lang->install->basicmeasList['47'] = array('name' => 'Total estimated initial hours of work required for the project', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours of all requirements related work in the first baseline version of the project plan');
$lang->install->basicmeasList['48'] = array('name' => 'Total estimated initial work hours for project tasks', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all tasks in the first baseline version of the project plan');
$lang->install->basicmeasList['49'] = array('name' => 'The final estimated number of project development hours', 'unit' => 'Hour','definition' => 'The sum of the initial estimated work hours of all development-related tasks in the last baseline release of the project plan');
$lang->install->basicmeasList['50'] = array('name' => 'Total estimated final work hours of project requirements', 'unit' => 'Hour','definition' => 'The sum of the initial estimated work hours of all requirements related tasks in the last baseline release of the project plan');
$lang->install->basicmeasList['51'] = array('name' => 'The final estimated number of project testing hours', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours of all test related tasks in the last baseline release of the project plan');
$lang->install->basicmeasList['52'] = array('name' => 'The final estimated total working hours of project design work', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours of all design-related tasks in the last baseline release of the project plan');
$lang->install->basicmeasList['53'] = array('name' => 'Total estimated final work hours of project tasks', 'unit' => 'Hour', 'definition' => 'The sum of the initial estimated man-hours for all tasks in the last baseline release of the project plan');
$lang->install->selectedMode = 'Selection mode';
$lang->install->selectedModeTips = 'You can go to the Admin - Custom - Mode to set it later.';
+59
View File
@@ -159,6 +159,65 @@ $lang->install->account = '管理员帐号';
$lang->install->password = '管理员密码';
$lang->install->errorEmptyPassword = '密码不能为空';
$lang->install->processList['11'] = '立项管理';
$lang->install->processList['12'] = '项目规划';
$lang->install->processList['13'] = '项目监控';
$lang->install->processList['14'] = '风险管理';
$lang->install->processList['15'] = '结项管理';
$lang->install->processList['16'] = '量化项目管理';
$lang->install->processList['17'] = '需求开发';
$lang->install->processList['18'] = '设计开发';
$lang->install->processList['19'] = '实现与测试';
$lang->install->processList['20'] = '系统测试';
$lang->install->processList['21'] = '客户验收';
$lang->install->processList['22'] = '质量保证';
$lang->install->processList['23'] = '配置管理';
$lang->install->processList['24'] = '度量分析';
$lang->install->processList['25'] = '原因分析与解决';
$lang->install->processList['26'] = '决策分析';
$lang->install->basicmeasList['2'] = array('name' => '项目用户需求初始规模', 'unit' => '故事点或功能点', 'definition' => '项目每个产品的第一个用户需求规格说明书基线版本的规模之和');
$lang->install->basicmeasList['3'] = array('name' => '项目软件需求初始规模', 'unit' => '故事点或功能点', 'definition' => '项目每个产品的第一个软件需求规格说明书基线版本的规模之和');
$lang->install->basicmeasList['4'] = array('name' => '项目用户需求实时规模', 'unit' => '故事点或功能点', 'definition' => '项目用户需求实际的规模');
$lang->install->basicmeasList['5'] = array('name' => '项目软件需求实时规模', 'unit' => '故事点或功能点', 'definition' => '项目软件需求实际的规模');
$lang->install->basicmeasList['6'] = array('name' => '项目估算规模', 'unit' => '故事点或功能点', 'definition' => '项目最初估算时估计的规模');
$lang->install->basicmeasList['8'] = array('name' => '项目需求阶段计划天数', 'unit' => '天', 'definition' => '项目下面所有需求阶段计划天数的和');
$lang->install->basicmeasList['9'] = array('name' => '项目设计阶段计划天数', 'unit' => '天', 'definition' => '项目下面所有设计阶段计划天数的和');
$lang->install->basicmeasList['10'] = array('name' => '项目开发阶段计划天数', 'unit' => '天', 'definition' => '项目下面所有研发阶段计划天数的和');
$lang->install->basicmeasList['11'] = array('name' => '项目测试阶段计划天数', 'unit' => '天', 'definition' => '项目下面所有测试阶段计划天数的和');
$lang->install->basicmeasList['12'] = array('name' => '项目需求阶段实际天数', 'unit' => '天', 'definition' => '项目下面所有需求阶段实际天数的和');
$lang->install->basicmeasList['13'] = array('name' => '项目设计阶段实际天数', 'unit' => '天', 'definition' => '项目下面所有设计阶段实际天数的和');
$lang->install->basicmeasList['14'] = array('name' => '项目开发阶段实际天数', 'unit' => '天', 'definition' => '项目下面所有研发阶段实际天数的和');
$lang->install->basicmeasList['15'] = array('name' => '项目测试阶段实际天数', 'unit' => '天', 'definition' => '项目下面所有测试阶段实际天数的和');
$lang->install->basicmeasList['26'] = array('name' => '分产品需求阶段计划天数', 'unit' => '天', 'definition' => '产品下面所有需求阶段计划天数的和');
$lang->install->basicmeasList['27'] = array('name' => '分产品设计阶段计划天数', 'unit' => '天', 'definition' => '产品下面所有设计阶段计划天数的和');
$lang->install->basicmeasList['28'] = array('name' => '分产品开发阶段计划天数', 'unit' => '天', 'definition' => '产品下面所有研发阶段计划天数的和');
$lang->install->basicmeasList['29'] = array('name' => '分产品测试阶段计划天数', 'unit' => '天', 'definition' => '产品下面所有测试阶段计划天数的和');
$lang->install->basicmeasList['30'] = array('name' => '分产品需求阶段实际天数', 'unit' => '天', 'definition' => '产品下面所有需求阶段实际天数的和');
$lang->install->basicmeasList['31'] = array('name' => '分产品设计阶段实际天数', 'unit' => '天', 'definition' => '产品下面所有设计阶段实际天数的和');
$lang->install->basicmeasList['32'] = array('name' => '分产品开发阶段实际天数', 'unit' => '天', 'definition' => '产品下面所有研发阶段实际天数的和');
$lang->install->basicmeasList['33'] = array('name' => '分产品测试阶段实际天数', 'unit' => '天', 'definition' => '产品下面所有测试阶段实际天数的和');
$lang->install->basicmeasList['34'] = array('name' => '项目任务实时预计工时数', 'unit' => '小时', 'definition' => '项目下面所有任务的最初预计工时和');
$lang->install->basicmeasList['35'] = array('name' => '项目需求工作实时总预计工时数', 'unit' => '小时', 'definition' => '项目所有需求相关任务的最初预计工时和');
$lang->install->basicmeasList['36'] = array('name' => '项目设计工作实时总预计工时数', 'unit' => '小时', 'definition' => '项目所有设计相关任务的最初预计工时和');
$lang->install->basicmeasList['37'] = array('name' => '项目开发工作实时总预计工时数', 'unit' => '小时', 'definition' => '项目所有开发相关任务的最初预计工时和');
$lang->install->basicmeasList['38'] = array('name' => '项目测试工作实时总预计工时数', 'unit' => '小时', 'definition' => '项目所有测试相关任务的最初预计工时和');
$lang->install->basicmeasList['39'] = array('name' => '项目任务实际消耗工时数', 'unit' => '小时', 'definition' => '项目下面所有任务的实际消耗工时和');
$lang->install->basicmeasList['40'] = array('name' => '项目需求工作实际消耗工时数', 'unit' => '小时', 'definition' => '项目所有需求相关任务的实际消耗工时和');
$lang->install->basicmeasList['41'] = array('name' => '项目设计工作实际消耗工时数', 'unit' => '小时', 'definition' => '项目所有设计相关任务的实际消耗工时和');
$lang->install->basicmeasList['42'] = array('name' => '项目开发工作实际消耗工时数', 'unit' => '小时', 'definition' => '项目所有开发相关任务的实际消耗工时和');
$lang->install->basicmeasList['43'] = array('name' => '项目测试工作实际消耗工时数', 'unit' => '小时', 'definition' => '项目所有测试相关任务的实际消耗工时和');
$lang->install->basicmeasList['44'] = array('name' => '项目开发工作最初总预计工时数', 'unit' => '小时', 'definition' => '项目计划第一个基线版本中所有开发相关工作最初预计工时和');
$lang->install->basicmeasList['45'] = array('name' => '项目设计工作最初总预计工时数', 'unit' => '小时', 'definition' => '项目计划第一个基线版本中所有设计相关工作最初预计工时和');
$lang->install->basicmeasList['46'] = array('name' => '项目测试工作最初总预计工时数', 'unit' => '小时', 'definition' => '项目计划第一个基线版本中所有测试相关工作最初预计工时和');
$lang->install->basicmeasList['47'] = array('name' => '项目需求工作最初总预计工时数', 'unit' => '小时', 'definition' => '项目计划第一个基线版本中所有需求相关工作最初预计工时和');
$lang->install->basicmeasList['48'] = array('name' => '项目任务最初总预计工时数', 'unit' => '小时', 'definition' => '项目计划第一个基线版本中所有任务最初预计工时和');
$lang->install->basicmeasList['49'] = array('name' => '项目开发工作最终总预计工时数', 'unit' => '小时', 'definition' => '项目计划最后一个基线版本中所有开发相关任务最初预计工时和');
$lang->install->basicmeasList['50'] = array('name' => '项目需求工作最终总预计工时数', 'unit' => '小时', 'definition' => '项目计划最后一个基线版本中所有需求相关任务最初预计工时和');
$lang->install->basicmeasList['51'] = array('name' => '项目测试工作最终总预计工时数', 'unit' => '小时', 'definition' => '项目计划最后一个基线版本中所有测试相关任务最初预计工时和');
$lang->install->basicmeasList['52'] = array('name' => '项目设计工作最终总预计工时数', 'unit' => '小时', 'definition' => '项目计划最后一个基线版本中所有设计相关任务最初预计工时和');
$lang->install->basicmeasList['53'] = array('name' => '项目任务最终总预计工时数', 'unit' => '小时', 'definition' => '项目计划最后一个基线版本中所有任务最初预计工时和');
$lang->install->selectedMode = '选择模式';
$lang->install->selectedModeTips = '后续您还可以去后台-自定义-模式中进行调整';
+41 -9
View File
@@ -509,7 +509,6 @@ class installModel extends model
$company->name = $this->post->company;
$company->admins = ",{$this->post->account},";
$this->dao->insert(TABLE_COMPANY)->data($company)->autoCheck()->batchCheck('name', 'notempty')->exec();
if(!dao::isError())
{
/* Set admin. */
@@ -519,21 +518,54 @@ class installModel extends model
$admin->password = md5($this->post->password);
$admin->gender = 'f';
$this->dao->replace(TABLE_USER)->data($admin)->check('account', 'notempty')->exec();
}
}
/* Update group name and desc on dafault lang. */
$groups = $this->dao->select('*')->from(TABLE_GROUP)->orderBy('id')->fetchAll();
foreach($groups as $group)
/**
* Update language for group and cron.
*
* @access public
* @return void
*/
public function updateLang()
{
/* Update group name and desc on dafault lang. */
$groups = $this->dao->select('*')->from(TABLE_GROUP)->orderBy('id')->fetchAll();
foreach($groups as $group)
{
$data = zget($this->lang->install->groupList, $group->name, '');
if($data) $this->dao->update(TABLE_GROUP)->data($data)->where('id')->eq($group->id)->exec();
}
/* Update cron remark by lang. */
foreach($this->lang->install->cronList as $command => $remark)
{
$this->dao->update(TABLE_CRON)->set('remark')->eq($remark)->where('command')->eq($command)->exec();
}
if(!empty($this->config->maxVersion))
{
/* Update process by lang. */
foreach($this->lang->install->processList as $id => $name)
{
$data = zget($this->lang->install->groupList, $group->name, '');
if($data) $this->dao->update(TABLE_GROUP)->data($data)->where('id')->eq($group->id)->exec();
$this->dao->update(TABLE_PROCESS)->set('name')->eq($name)->where('id')->eq($id)->exec();
}
/* Update cron remark by lang. */
foreach($this->lang->install->cronList as $command => $remark)
/* Update basicmeas by lang. */
foreach($this->lang->install->basicmeasList as $id => $basic)
{
$this->dao->update(TABLE_CRON)->set('remark')->eq($remark)->where('command')->eq($command)->exec();
$this->dao->update(TABLE_BASICMEAS)->set('name')->eq($basic['name'])->set('unit')->eq($basic['unit'])->set('definition')->eq($basic['definition'])->where('id')->eq($id)->exec();
}
/* Update lang,stage by lang. */
$this->app->loadLang('stage');
foreach($this->lang->stage->typeList as $key => $value)
{
$this->dao->update(TABLE_LANG)->set('value')->eq($value)->where('`key`')->eq($key)->exec();
$this->dao->update(TABLE_STAGE)->set('name')->eq($value)->where('`type`')->eq($key)->exec();
}
}
}
/**
+36 -12
View File
@@ -88,6 +88,8 @@ class job extends control
}
return $this->send(array('result' => 'fail', 'message' => $errors));
}
$this->loadModel('action')->create('job', $jobID, 'created');
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $jobID));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
@@ -120,7 +122,8 @@ class job extends control
$this->view->repoTypes = $repoTypes;
$this->view->products = array(0 => '') + $this->loadModel('product')->getProductPairsByProject($this->projectID);
$this->view->jenkinsServerList = array('' => '') + $this->loadModel('jenkins')->getPairs();
$this->view->jenkinsServerList = array('' => '') + $this->loadModel('jenkins')->getPairs();
$this->view->sonarqubeServerList = array('') + $this->loadModel('pipeline')->getPairs('sonarqube');
$this->display();
}
@@ -162,6 +165,8 @@ class job extends control
}
return $this->send(array('result' => 'fail', 'message' => $errors));
}
$this->loadModel('action')->create('job', $id, 'edited');
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
@@ -189,17 +194,18 @@ class job extends control
if($jobProduct and $jobProduct->deleted == 0) $products += array($job->product => $jobProduct->name);
}
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->job->edit;
$this->view->position[] = html::a(inlink('browse'), $this->lang->ci->job);
$this->view->position[] = $this->lang->job->edit;
$this->view->repoPairs = $repoPairs;
$this->view->gitlabRepos = $gitlabRepos;
$this->view->repoTypes = $repoTypes;
$this->view->repoType = zget($repoTypes, $job->repo, 'Git');
$this->view->job = $job;
$this->view->products = array(0 => '') + $products;
$this->view->jenkinsServerList = $this->loadModel('jenkins')->getPairs();
$this->view->pipelines = $this->jenkins->getTasks($job->server);
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->job->edit;
$this->view->position[] = html::a(inlink('browse'), $this->lang->ci->job);
$this->view->position[] = $this->lang->job->edit;
$this->view->repoPairs = $repoPairs;
$this->view->gitlabRepos = $gitlabRepos;
$this->view->repoTypes = $repoTypes;
$this->view->repoType = zget($repoTypes, $job->repo, 'Git');
$this->view->job = $job;
$this->view->products = array('') + $products;
$this->view->jenkinsServerList = $this->loadModel('jenkins')->getPairs();
$this->view->sonarqubeServerList = array('') + $this->loadModel('pipeline')->getPairs('sonarqube');
$this->view->pipelines = $this->jenkins->getTasks($job->server);
$this->display();
}
@@ -323,6 +329,7 @@ class job extends control
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->app->loadLang('compile');
$this->loadModel('action')->create('job', $id, 'executed');
return $this->send(array('result' => 'success', 'message' => sprintf($this->lang->job->sendExec, zget($this->lang->compile->statusList, $compile->status))));
}
@@ -414,4 +421,21 @@ class job extends control
$this->send(array('result' => 'success', 'type' => strtolower($repo->SCM)));
}
/**
* Ajax check SonarQube linked by repoID.
*
* @param int $repoID
* @access public
* @return void
*/
public function ajaxCheckSonarqubeLink($repoID, $jobID = 0)
{
$repo = $this->loadModel('job')->getSonarqubeByRepo(array($repoID), $jobID, true);
if(!empty($repo))
{
$message = $repo[$repoID]->deleted ? $this->lang->job->jobIsDeleted : sprintf($this->lang->job->repoExists, $repo[$repoID]->id . '-' . $repo[$repoID]->name);
$this->send(array('result' => 'fail', 'message' => $message));
}
$this->send(array('result' => 'success', 'message' => ''));
}
}
+87 -1
View File
@@ -1,5 +1,51 @@
$(document).ready(function()
{
/*
* Get frame select.
* param string engine eg. jenkins|gitlab
*/
function getFrameSelect(engine)
{
$('#frameBox .input-group').empty();
$('#frameBox .input-group').append("<div class='load-indicator loading'></div>");
var html = "<select id='frame' name='frame' class='form-control chosen'>";
for(frame in frameList)
{
if(engine == 'jenkins' || frame != 'sonarqube') html += "<option value='" + frame + "'>" + frameList[frame] + "</option>";
}
html += '</select>';
$('#frameBox .loading').remove();
$('#frameBox .input-group').append(html);
$('#frameBox #frame').chosen();
$('#frame').change();
}
getFrameSelect('');
/*
* Check sonarqube linked.
*/
function checkSonarquebLink()
{
var repoID = $('#repo').val();
var frame = $('#frame').val();
if(frame != 'sonarqube' || repoID == 0) return false;
$.getJSON(createLink('job', 'ajaxCheckSonarqubeLink', 'repoID=' + repoID), function(result)
{
if(result.result != 'success')
{
alert(result.message);
$('#repo').val(0).trigger('chosen:updated');
$('#reference').val('').trigger('chosen:updated');
$('.reference').hide();
return false;
}
})
}
$(document).on('change', '#repo', function()
{
var repoID = $(this).val();
@@ -63,6 +109,9 @@ $(document).ready(function()
$('#triggerggerType option[value=tag]').html(data.type == 'gitlab' ? buildTag : dirChange).trigger('chosen:updated');
}
});
/* Check exists sonarqube data. */
checkSonarquebLink();
});
$(document).on('change', '[name^=svnDir]', function()
@@ -139,6 +188,42 @@ $(document).ready(function()
$('#jenkinsServerTR #jkTask').chosen({drop_direction: 'auto'});
})
/* There has been a problem with handling the prompt label. */
$('#jkTaskLabel').remove();
})
$(document).on('change', '#frame', function()
{
var frame = $(this).val();
if(frame == 'sonarqube')
{
$('tr.sonarqube').removeClass('hide');
/* Check exists sonarqube data. */
checkSonarquebLink();
}
else
{
$('tr.sonarqube').addClass('hide');
}
})
$(document).on('change', '#sonarqubeServer', function()
{
var sonarqubeID = $(this).val();
$('#sonarProject #projectKey').remove();
$('#sonarProject #projectKey_chosen').remove();
$('#sonarProject .input-group').append("<div class='load-indicator loading'></div>");
$.get(createLink('sonarqube', 'ajaxGetProjectList', 'sonarqubeID=' + sonarqubeID), function(html)
{
$('#sonarProject .loading').remove();
$('#sonarProject .input-group').append(html);
$('#sonarProject #projectKey').chosen({drop_direction: 'auto'});
})
/* There has been a problem with handling the prompt label. */
$('#projectKeyLabel').remove();
})
var scheduleOption = "<option value='schedule'>" + $('#triggerType').find('[value=schedule]').text() + "</option>";
@@ -161,9 +246,10 @@ $(document).ready(function()
$('tr.gitlabRepo').hide();
$('tr.commonRepo').show();
}
getFrameSelect(engine);
});
$('#engine').change();
$('#triggerType').change();
});
+89 -1
View File
@@ -1,5 +1,52 @@
$(document).ready(function()
{
/*
* Get frame select.
* param string engine eg. jenkins|gitlab
*/
function getFrameSelect()
{
$('#frameBox .input-group').empty();
$('#frameBox .input-group').append("<div class='load-indicator loading'></div>");
var html = "<select id='frame' name='frame' class='form-control chosen'>";
for(frame in frameList)
{
if(job.engine == 'jenkins' || frame != 'sonarqube')
{
html += "<option value='" + frame + "'";
if(frame == job.frame) html += " selected";
html += ">" + frameList[frame] + "</option>";
}
}
html += '</select>';
$('#frameBox .loading').remove();
$('#frameBox .input-group').append(html);
$('#frameBox #frame').chosen();
}
getFrameSelect();
/* Check sonarqube linked. */
function checkSonarquebLink()
{
var repoID = $('#repo').val();
var frame = $('#frame').val();
if(frame != 'sonarqube' || repoID == 0) return false;
$.getJSON(createLink('job', 'ajaxCheckSonarqubeLink', 'repoID=' + repoID + '&jobID=' + job.id), function(result)
{
if(result.result != 'success')
{
alert(result.message);
$('#repo').val(0).trigger('chosen:updated');
$('#reference').val('').trigger('chosen:updated');
$('.reference').hide();
return false;
}
})
}
$('#gitlabRepo').change(function()
{
$('#repo').val($(this).val()).change();
@@ -45,6 +92,9 @@ $(document).ready(function()
$('#svnDirBox #svnDir').chosen();
})
}
/* Check exists sonarqube data. */
checkSonarquebLink();
})
$(document).on('change', '[name^=svnDir]', function()
@@ -124,6 +174,43 @@ $(document).ready(function()
$('#jenkinsServerTR #jkTask').val(jkTask).chosen();
})
/* There has been a problem with handling the prompt label. */
$('#jkTaskLabel').remove();
})
$(document).on('change', '#frame', function()
{
var frame = $(this).val();
if(frame == 'sonarqube')
{
$('tr.sonarqube').removeClass('hide');
/* Check exists sonarqube data. */
checkSonarquebLink();
}
else
{
$('tr.sonarqube').addClass('hide');
}
})
$(document).on('change', '#sonarqubeServer', function()
{
var sonarqubeID = $(this).val();
var projectKey = sonarqubeID == job.sonarqubeServer ? job.projectKey.replace(/-/g, '*') : '';
$('#sonarProject #projectKey').remove();
$('#sonarProject #projectKey_chosen').remove();
$('#sonarProject .input-group').append("<div class='load-indicator loading'></div>");
$.get(createLink('sonarqube', 'ajaxGetProjectList', 'sonarqubeID=' + sonarqubeID + '&projectKey=' + projectKey), function(html)
{
$('#sonarProject .loading').remove();
$('#sonarProject .input-group').append(html);
$('#sonarProject #projectKey').chosen({drop_direction: 'auto'});
})
/* There has been a problem with handling the prompt label. */
$('#projectKeyLabel').remove();
})
var scheduleOption = "<option value='schedule'>" + $('#triggerType').find('[value=schedule]').text() + "</option>";
@@ -169,6 +256,7 @@ $(document).ready(function()
$('#engine').change();
$('#jkServer').change();
$('#frame').change();
$('#sonarqubeServer').change();
$('#triggerType').change();
});
+53 -46
View File
@@ -14,46 +14,52 @@ $lang->job->execSuccess = 'Build success';
$lang->job->browseAction = 'Job List';
$lang->job->id = 'ID';
$lang->job->name = 'Name';
$lang->job->repo = 'Repo';
$lang->job->product = $lang->productCommon;
$lang->job->svnDir = 'SVN Tag Watch Path';
$lang->job->jenkins = 'Jenkins';
$lang->job->jkHost = 'Jenkins Server';
$lang->job->jkJob = 'Jenkins Task';
$lang->job->buildSpec = 'Build Target'; // 'pipeline@server'
$lang->job->engine = 'Engine';
$lang->job->server = 'Server';
$lang->job->pipeline = 'Pipeline';
$lang->job->buildType = 'Build Type';
$lang->job->frame = 'Frame';
$lang->job->triggerType = 'Trigger';
$lang->job->atDay = 'Custom Days';
$lang->job->atTime = 'At Time';
$lang->job->lastStatus = 'Last Status';
$lang->job->lastExec = 'Last Executed';
$lang->job->comment = 'Match Keywords';
$lang->job->customParam = 'Custom build parameters';
$lang->job->paramName = 'Name';
$lang->job->paramValue = 'Value';
$lang->job->custom = 'Custom';
$lang->job->createdBy = 'Created By';
$lang->job->createdDate = 'Created Date';
$lang->job->editedBy = 'Edited By';
$lang->job->editedDate = 'Edited Date';
$lang->job->lastTag = 'Last Tag';
$lang->job->deleted = 'Deleted';
$lang->job->repoServer = 'Repo Server';
$lang->job->id = 'ID';
$lang->job->name = 'Name';
$lang->job->repo = 'Repo';
$lang->job->product = $lang->productCommon;
$lang->job->svnDir = 'SVN Tag Watch Path';
$lang->job->jenkins = 'Jenkins';
$lang->job->jkHost = 'Jenkins Server';
$lang->job->jkJob = 'Jenkins Task';
$lang->job->buildSpec = 'Build Target'; // 'pipeline@server'
$lang->job->engine = 'Engine';
$lang->job->server = 'Server';
$lang->job->pipeline = 'Pipeline';
$lang->job->buildType = 'Build Type';
$lang->job->frame = 'Frame';
$lang->job->triggerType = 'Trigger';
$lang->job->atDay = 'Custom Days';
$lang->job->atTime = 'At Time';
$lang->job->lastStatus = 'Last Status';
$lang->job->lastExec = 'Last Executed';
$lang->job->comment = 'Match Keywords';
$lang->job->customParam = 'Custom build parameters';
$lang->job->paramName = 'Name';
$lang->job->paramValue = 'Value';
$lang->job->custom = 'Custom';
$lang->job->createdBy = 'Created By';
$lang->job->createdDate = 'Created Date';
$lang->job->editedBy = 'Edited By';
$lang->job->editedDate = 'Edited Date';
$lang->job->lastTag = 'Last Tag';
$lang->job->deleted = 'Deleted';
$lang->job->repoServer = 'Repo Server';
$lang->job->sonarqubeServer = 'SonarQube Server';
$lang->job->projectKey = 'SonarQube Project';
$lang->job->lblBasic = 'Basic Info';
$lang->job->example = 'e.g.';
$lang->job->commitEx = "Used to match the keywords used to create a compile. Multiple keywords are separated by ','";
$lang->job->cronSample = 'e.g. 0 0 2 * * 2-6/1 means 2:00 a.m. every weekday.';
$lang->job->sendExec = 'Send execute request success.';
$lang->job->inputName = 'Please enter parameter name.';
$lang->job->invalidName = 'The parameter name should be letters, numbers or underlines.';
$lang->job->example = 'e.g.';
$lang->job->commitEx = "Used to match the keywords used to create a compile. Multiple keywords are separated by ','";
$lang->job->cronSample = 'e.g. 0 0 2 * * 2-6/1 means 2:00 a.m. every weekday.';
$lang->job->sendExec = 'Send execute request success.';
$lang->job->inputName = 'Please enter parameter name.';
$lang->job->invalidName = 'The parameter name should be letters, numbers or underlines.';
$lang->job->repoExists = 'This repository has a build task associated with it『%s』';
$lang->job->projectExists = 'This SonarQube Project has a build task associated with it『%s』';
$lang->job->mustUseJenkins = 'SonarQube frame is only used if the build engine is JenKins.';
$lang->job->jobIsDeleted = 'This repository is associated with a build task, please view the data from the recycle bin';
$lang->job->buildTypeList['build'] = 'Only Build';
$lang->job->buildTypeList['buildAndDeploy'] = 'Build And Deploy';
@@ -63,15 +69,16 @@ $lang->job->triggerTypeList['tag'] = 'Tag';
$lang->job->triggerTypeList['commit'] = 'Code Commit';
$lang->job->triggerTypeList['schedule'] = 'Schedule';
$lang->job->frameList[''] = '';
$lang->job->frameList['junit'] = 'JUnit';
$lang->job->frameList['testng'] = 'TestNG';
$lang->job->frameList['phpunit'] = 'PHPUnit';
$lang->job->frameList['pytest'] = 'Pytest';
$lang->job->frameList['jtest'] = 'JTest';
$lang->job->frameList['cppunit'] = 'CppUnit';
$lang->job->frameList['gtest'] = 'GTest';
$lang->job->frameList['qtest'] = 'QTest';
$lang->job->frameList[''] = '';
$lang->job->frameList['junit'] = 'JUnit';
$lang->job->frameList['testng'] = 'TestNG';
$lang->job->frameList['phpunit'] = 'PHPUnit';
$lang->job->frameList['pytest'] = 'Pytest';
$lang->job->frameList['jtest'] = 'JTest';
$lang->job->frameList['cppunit'] = 'CppUnit';
$lang->job->frameList['gtest'] = 'GTest';
$lang->job->frameList['qtest'] = 'QTest';
$lang->job->frameList['sonarqube'] = 'SonarQube';
$lang->job->paramValueList[''] = '';
$lang->job->paramValueList['$zentao_version'] = 'Current version';
+53 -46
View File
@@ -14,46 +14,52 @@ $lang->job->execSuccess = '执行成功';
$lang->job->browseAction = '构建任务列表';
$lang->job->id = 'ID';
$lang->job->name = '名称';
$lang->job->repo = '代码库';
$lang->job->product = '关联' . $lang->productCommon;
$lang->job->svnDir = 'SVN监控路径';
$lang->job->jenkins = 'Jenkins';
$lang->job->jkHost = 'Jenkins服务器';
$lang->job->jkJob = 'Jenkins任务';
$lang->job->buildSpec = '构建对象'; // 'pipeline@server'
$lang->job->engine = '构建引擎';
$lang->job->server = '服务器';
$lang->job->pipeline = '流水线';
$lang->job->buildType = '构建类型';
$lang->job->frame = '工具/框架';
$lang->job->triggerType = '触发方式';
$lang->job->atDay = '自定义日期';
$lang->job->atTime = '执行时间';
$lang->job->lastStatus = '最后执行状态';
$lang->job->lastExec = '最后执行时间';
$lang->job->comment = '匹配关键字';
$lang->job->customParam = '自定义构建参数';
$lang->job->paramName = '名称';
$lang->job->paramValue = '值';
$lang->job->custom = '自定义';
$lang->job->createdBy = '由谁创建';
$lang->job->createdDate = '创建日期';
$lang->job->editedBy = '由谁编辑';
$lang->job->editedDate = '编辑日期';
$lang->job->lastTag = '最后标签';
$lang->job->deleted = '已删除';
$lang->job->repoServer = '版本库服务器';
$lang->job->id = 'ID';
$lang->job->name = '名称';
$lang->job->repo = '代码库';
$lang->job->product = '关联' . $lang->productCommon;
$lang->job->svnDir = 'SVN监控路径';
$lang->job->jenkins = 'Jenkins';
$lang->job->jkHost = 'Jenkins服务器';
$lang->job->jkJob = 'Jenkins任务';
$lang->job->buildSpec = '构建对象'; // 'pipeline@server'
$lang->job->engine = '构建引擎';
$lang->job->server = '服务器';
$lang->job->pipeline = '流水线';
$lang->job->buildType = '构建类型';
$lang->job->frame = '工具/框架';
$lang->job->triggerType = '触发方式';
$lang->job->atDay = '自定义日期';
$lang->job->atTime = '执行时间';
$lang->job->lastStatus = '最后执行状态';
$lang->job->lastExec = '最后执行时间';
$lang->job->comment = '匹配关键字';
$lang->job->customParam = '自定义构建参数';
$lang->job->paramName = '名称';
$lang->job->paramValue = '值';
$lang->job->custom = '自定义';
$lang->job->createdBy = '由谁创建';
$lang->job->createdDate = '创建日期';
$lang->job->editedBy = '由谁编辑';
$lang->job->editedDate = '编辑日期';
$lang->job->lastTag = '最后标签';
$lang->job->deleted = '已删除';
$lang->job->repoServer = '版本库服务器';
$lang->job->sonarqubeServer = 'SonarQube服务器';
$lang->job->projectKey = 'SonarQube项目';
$lang->job->lblBasic = '基本信息';
$lang->job->example = '举例';
$lang->job->commitEx = "用于匹配创建构建任务的关键字,多个关键字用','分割";
$lang->job->cronSample = '如 0 0 2 * * 2-6/1 表示每个工作日凌晨2点';
$lang->job->sendExec = '发送执行请求成功!执行结果:%s';
$lang->job->inputName = '请输入参数名称。';
$lang->job->invalidName = '参数名称应该是英文字母、数字或下划线的组合。';
$lang->job->example = '举例';
$lang->job->commitEx = "用于匹配创建构建任务的关键字,多个关键字用','分割";
$lang->job->cronSample = '如 0 0 2 * * 2-6/1 表示每个工作日凌晨2点';
$lang->job->sendExec = '发送执行请求成功!执行结果:%s';
$lang->job->inputName = '请输入参数名称。';
$lang->job->invalidName = '参数名称应该是英文字母、数字或下划线的组合。';
$lang->job->repoExists = '此版本库已关联构建任务『%s』';
$lang->job->projectExists = '此SonarQube项目已关联构建任务『%s』';
$lang->job->mustUseJenkins = 'SonarQube工具/框架仅在构建引擎为JenKins的情况下使用';
$lang->job->jobIsDeleted = '此版本库已关联构建任务,请从回收站查看数据';
$lang->job->buildTypeList['build'] = '仅构建';
$lang->job->buildTypeList['buildAndDeploy'] = '构建部署';
@@ -63,15 +69,16 @@ $lang->job->triggerTypeList['tag'] = '打标签';
$lang->job->triggerTypeList['commit'] = '提交注释包含关键字';
$lang->job->triggerTypeList['schedule'] = '定时计划';
$lang->job->frameList[''] = '';
$lang->job->frameList['junit'] = 'JUnit';
$lang->job->frameList['testng'] = 'TestNG';
$lang->job->frameList['phpunit'] = 'PHPUnit';
$lang->job->frameList['pytest'] = 'Pytest';
$lang->job->frameList['jtest'] = 'JTest';
$lang->job->frameList['cppunit'] = 'CppUnit';
$lang->job->frameList['gtest'] = 'GTest';
$lang->job->frameList['qtest'] = 'QTest';
$lang->job->frameList[''] = '';
$lang->job->frameList['junit'] = 'JUnit';
$lang->job->frameList['testng'] = 'TestNG';
$lang->job->frameList['phpunit'] = 'PHPUnit';
$lang->job->frameList['pytest'] = 'Pytest';
$lang->job->frameList['jtest'] = 'JTest';
$lang->job->frameList['cppunit'] = 'CppUnit';
$lang->job->frameList['gtest'] = 'GTest';
$lang->job->frameList['qtest'] = 'QTest';
$lang->job->frameList['sonarqube'] = 'SonarQube';
$lang->job->paramValueList[''] = '';
$lang->job->paramValueList['$zentao_version'] = '当前版本号';
+101 -3
View File
@@ -156,7 +156,8 @@ class jobModel extends model
public function create()
{
$job = fixer::input('post')
->setDefault('atDay', '')
->setDefault('atDay,projectKey', '')
->setDefault('sonarqubeServer', 0)
->add('createdBy', $this->app->user->account)
->add('createdDate', helper::now())
->remove('repoType,reference')
@@ -181,6 +182,35 @@ class jobModel extends model
unset($job->jkTask);
unset($job->gitlabRepo);
/* SonarQube tool is only used if the engine is JenKins. */
if($job->engine != 'jenkins' and $job->frame == 'sonarqube')
{
dao::$errors[]['frame'] = $this->lang->job->mustUseJenkins;
return false;
}
if($job->repo > 0 and $job->frame == 'sonarqube')
{
$sonarqubeJob = $this->getSonarqubeByRepo(array($job->repo));
if(!empty($sonarqubeJob))
{
$message = sprintf($this->lang->job->repoExists, $sonarqubeJob[$job->repo]->id . '-' . $sonarqubeJob[$job->repo]->name);
dao::$errors[]['repo'] = $message;
return false;
}
}
if(!empty($job->projectKey) and $job->frame == 'sonarqube')
{
$projectList = $this->getJobBySonarqubeProject($job->sonarqubeServer, array($job->projectKey));
if(!empty($projectList))
{
$message = sprintf($this->lang->job->projectExists, $projectList[$job->projectKey]->id);
dao::$errors[]['projectKey'] = $message;
return false;
}
}
if($job->triggerType == 'schedule') $job->atDay = empty($_POST['atDay']) ? '' : join(',', $this->post->atDay);
$job->svnDir = '';
@@ -219,6 +249,7 @@ class jobModel extends model
->batchCheckIF($job->triggerType === 'schedule', "atDay,atTime", 'notempty')
->batchCheckIF($job->triggerType === 'commit', "comment", 'notempty')
->batchCheckIF(($this->post->repoType == 'Subversion' and $job->triggerType == 'tag'), "svnDir", 'notempty')
->batchCheckIF($job->frame === 'sonarqube', "sonarqubeServer,projectKey", 'notempty')
->autoCheck()
->exec();
if(dao::isError()) return false;
@@ -268,6 +299,35 @@ class jobModel extends model
unset($job->jkTask);
unset($job->gitlabRepo);
/* SonarQube tool is only used if the engine is JenKins. */
if($job->engine != 'jenkins' and $job->frame == 'sonarqube')
{
dao::$errors[] = $this->lang->job->mustUseJenkins;
return false;
}
if($job->repo > 0 and $job->frame == 'sonarqube')
{
$sonarqubeJob = $this->getSonarqubeByRepo(array($job->repo), $id);
if(!empty($sonarqubeJob))
{
$message = sprintf($this->lang->job->repoExists, $sonarqubeJob[$job->repo]->id . '-' . $sonarqubeJob[$job->repo]->name);
dao::$errors[]['repo'] = $message;
return false;
}
}
if(!empty($job->projectKey) and $job->frame == 'sonarqube')
{
$projectList = $this->getJobBySonarqubeProject($job->sonarqubeServer, array($job->projectKey));
if(!empty($projectList) && $projectList[$job->projectKey]->id != $id)
{
$message = sprintf($this->lang->job->projectExists, $projectList[$job->projectKey]->id);
dao::$errors[]['projectKey'] = $message;
return false;
}
}
if($job->triggerType == 'schedule') $job->atDay = empty($_POST['atDay']) ? '' : join(',', $this->post->atDay);
$job->svnDir = '';
@@ -304,11 +364,10 @@ class jobModel extends model
$this->dao->update(TABLE_JOB)->data($job)
->batchCheck($this->config->job->edit->requiredFields, 'notempty')
->batchCheckIF($job->triggerType === 'schedule', "atDay,atTime", 'notempty')
->batchCheckIF($job->triggerType === 'commit', "comment", 'notempty')
->batchCheckIF(($this->post->repoType == 'Subversion' and $job->triggerType == 'tag'), "svnDir", 'notempty')
->batchCheckIF($job->frame === 'sonarqube', "sonarqubeServer,projectKey", 'notempty')
->autoCheck()
->where('id')->eq($id)
->exec();
@@ -539,4 +598,43 @@ class jobModel extends model
return '';
}
/**
* Get sonarqube by RepoID.
*
* @param array $repoIDList
* @param int $jobID
* @param bool $showDeleted
* @access public
* @return array
*/
public function getSonarqubeByRepo($repoIDList, $jobID = 0, $showDeleted = false)
{
return $this->dao->select('id,name,repo,deleted')->from(TABLE_JOB)
->where('frame')->eq('sonarqube')
->andWhere('repo')->in($repoIDList)
->beginIF(!$showDeleted)->andWhere('deleted')->eq('0')->fi()
->beginIF($jobID > 0)->andWhere('id')->ne($jobID)->fi()
->fetchAll('repo');
}
/**
* Get job pairs by sonarqube projectkeys.
*
* @param int $sonarqubeID
* @param array $projectKeys
* @param bool $emptyShowAll
* @param bool $showDeleted
* @access public
* @return array
*/
public function getJobBySonarqubeProject($sonarqubeID, $projectKeys = array(), $emptyShowAll = false, $showDeleted = false)
{
return $this->dao->select('projectKey,id')->from(TABLE_JOB)
->where('frame')->eq('sonarqube')
->andWhere('sonarqubeServer')->eq($sonarqubeID)
->beginIF(!$showDeleted)->andWhere('deleted')->eq('0')->fi()
->beginIF(!empty($projectKeys) or !$emptyShowAll)->andWhere('projectKey')->in($projectKeys)->fi()
->fetchPairs();
}
}
+22 -3
View File
@@ -16,6 +16,7 @@
<?php js::set('triggerType', 'tag');?>
<?php js::set('dirChange', $lang->job->dirChange);?>
<?php js::set('buildTag', $lang->job->buildTag);?>
<?php js::set('frameList', $lang->job->frameList);?>
<div id='mainContent' class='main-row'>
<div class='main-content'>
@@ -26,7 +27,7 @@
<form id='jobForm' method='post' class='form-ajax'>
<table class='table table-form'>
<tr>
<th class='w-120px'><?php echo $lang->job->name; ?></th>
<th class='w-140px'><?php echo $lang->job->name; ?></th>
<td class='required'><?php echo html::input('name', '', "class='form-control'"); ?></td>
<td colspan="2" ></td>
</tr>
@@ -51,9 +52,13 @@
<th><?php echo $lang->job->product; ?></th>
<td><?php echo html::select('product', '', '', "class='form-control chosen'"); ?></td>
</tr>
<tr>
<tr id="frameBox">
<th><?php echo $lang->job->frame; ?></th>
<td><?php echo html::select('frame', $lang->job->frameList, '', "class='form-control chosen'"); ?></td>
<td>
<div class='input-group'>
<?php echo html::select('frame', array('' => ''), '', "class='form-control chosen'"); ?>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->job->triggerType; ?></th>
@@ -68,6 +73,20 @@
</div>
</td>
</tr>
<tr class='sonarqube hide'>
<th><?php echo $lang->job->sonarqubeServer;?></th>
<td><?php echo html::select('sonarqubeServer', $sonarqubeServerList, '', "class='form-control chosen' required");?></td>
<td colspan="2"></td>
</tr>
<tr id='sonarProject' class='sonarqube hide'>
<th><?php echo $lang->job->projectKey;?></th>
<td class='required'>
<div class='input-group'>
<?php echo html::select('projectKey', array('' => ''), '', "class='form-control chosen'");?>
</div>
</td>
<td colspan="2"></td>
</tr>
<tr class="comment-fields">
<th><?php echo $lang->job->comment;?></th>
<td class='required'><?php echo html::input('comment', '', "class='form-control'");?></td>
+23 -3
View File
@@ -18,6 +18,8 @@
<?php js::set('dirChange', $lang->job->dirChange);?>
<?php js::set('buildTag', $lang->job->buildTag);?>
<?php js::set('jkTask', $job->pipeline);?>
<?php js::set('job', $job);?>
<?php js::set('frameList', $lang->job->frameList);?>
<div id='mainContent' class='main-row'>
<div class='main-content'>
@@ -28,7 +30,7 @@
<form id='jobForm' method='post' class='form-ajax'>
<table class='table table-form'>
<tr>
<th class='w-120px'><?php echo $lang->job->name;?></th>
<th class='w-140px'><?php echo $lang->job->name;?></th>
<td class='required'><?php echo html::input('name', $job->name, "class='form-control'");?></td>
<td colspan="2" ></td>
</tr>
@@ -50,9 +52,13 @@
<th><?php echo $lang->job->product;?></th>
<td><?php echo html::select('product', $products, $job->product, "class='form-control chosen'");?></td>
</tr>
<tr>
<tr id="frameBox">
<th><?php echo $lang->job->frame;?></th>
<td><?php echo html::select('frame', $lang->job->frameList, $job->frame, "class='form-control chosen'");?></td>
<td>
<div class='input-group'>
<?php echo html::select('frame', array('' => ''), '', "class='form-control chosen'"); ?>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->job->triggerType;?></th>
@@ -88,6 +94,20 @@
</div>
</td>
</tr>
<tr class='sonarqube hide'>
<th><?php echo $lang->job->sonarqubeServer;?></th>
<td><?php echo html::select('sonarqubeServer', $sonarqubeServerList, $job->sonarqubeServer, "class='form-control chosen' required");?></td>
<td colspan="2"></td>
</tr>
<tr id='sonarProject' class='sonarqube hide'>
<th><?php echo $lang->job->projectKey;?></th>
<td class="required">
<div class='input-group'>
<?php echo html::select('projectKey', array('' => ''), '', "class='form-control chosen'");?>
</div>
</td>
<td colspan="2"></td>
</tr>
<tr class="comment-fields">
<th><?php echo $lang->job->comment;?></th>
<td class='required'><?php echo html::input('comment', $job->comment, "class='form-control'");?></td>
+122 -15
View File
@@ -21,15 +21,14 @@ class kanban extends control
* @access public
* @return void
*/
public function space($browseType = 'my', $recTotal = 0, $recPerPage = 15, $pageID = 1)
public function space($browseType = 'private', $recTotal = 0, $recPerPage = 15, $pageID = 1)
{
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$this->view->title = $this->lang->kanbanspace->common;
$this->view->spaceList = $this->kanban->getSpaceList($browseType, $pager);
$this->view->spaceList = $this->kanban->getSpaceList($browseType, $pager, $this->cookie->showClosed);
$this->view->unclosedSpace = $this->kanban->getCanViewObjects('kanbanspace', 'noclosed');
$this->view->browseType = $browseType;
$this->view->pager = $pager;
@@ -42,14 +41,15 @@ class kanban extends control
/**
* Create a space.
*
* @param string $type
* @access public
* @return void
*/
public function createSpace()
public function createSpace($type = 'private')
{
if(!empty($_POST))
{
$spaceID = $this->kanban->createSpace();
$spaceID = $this->kanban->createSpace($type);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
@@ -57,7 +57,11 @@ class kanban extends control
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted');
unset($this->lang->kanbanspace->featureBar['involved']);
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted');
$this->view->type = $type;
$this->view->typeList = $this->lang->kanbanspace->featureBar;
$this->display();
}
@@ -145,10 +149,11 @@ class kanban extends control
* Create a kanban.
*
* @param int $spaceID
* @param string $type
* @access public
* @return void
*/
public function create($spaceID = 0)
public function create($spaceID = 0, $type = 'private')
{
if(!empty($_POST))
{
@@ -160,9 +165,17 @@ class kanban extends control
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted');
unset($this->lang->kanbanspace->featureBar['involved']);
$space = $this->kanban->getSpaceById($spaceID);
$spaceUsers = $spaceID == 0 ? ',' : trim($space->owner) . ',' . trim($space->team) . ',' . trim($space->whitelist);
$users = $this->loadModel('user')->getPairs('noclosed|nodeleted', '', 0, $spaceUsers);
$this->view->users = $users;
$this->view->spaceID = $spaceID;
$this->view->spacePairs = array(0 => '') + $this->kanban->getSpacePairs('noclosed');
$this->view->spacePairs = array(0 => '') + $this->kanban->getSpacePairs($type);
$this->view->type = $type;
$this->view->typeList = $this->lang->kanbanspace->featureBar;
$this->display();
}
@@ -189,9 +202,15 @@ class kanban extends control
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->users = $this->loadModel('user')->getPairs('noclosed');
$this->view->spacePairs = array(0 => '') + $this->kanban->getSpacePairs('noclosed');
$this->view->kanban = $this->kanban->getByID($kanbanID);
$kanban = $this->kanban->getByID($kanbanID);
$space = $this->kanban->getSpaceById($kanban->space);
$spaceUsers = trim($space->owner) . ',' . trim($space->team) . ',' . trim($space->whitelist);
$users = $this->loadModel('user')->getPairs('noclosed|nodeleted', '', 0, $spaceUsers);
$this->view->users = $users;
$this->view->spacePairs = array(0 => '') + $this->kanban->getSpacePairs($space->type);
$this->view->kanban = $kanban;
$this->view->type = $space->type;
$this->display();
}
@@ -669,12 +688,11 @@ class kanban extends control
* @param int $kanbanID
* @param int $regionID
* @param int $groupID
* @param int $laneID
* @param int $columnID
* @access public
* @return void
*/
public function createCard($kanbanID = 0, $regionID = 0, $groupID = 0, $laneID = 0, $columnID = 0)
public function createCard($kanbanID = 0, $regionID = 0, $groupID = 0, $columnID = 0)
{
if($_POST)
{
@@ -810,6 +828,26 @@ class kanban extends control
die(json_encode($kanbanGroup));
}
/**
* Sort cards.
*
* @param int $kanbanID
* @param int $laneID
* @param int $columnID
* @param string $cards
* @access public
* @return void
*/
public function sortCard($kanbanID, $laneID, $columnID, $cards = '')
{
if(empty($cards)) return;
$this->dao->update(TABLE_KANBANCELL)->set('cards')->eq(",$cards,")->where('kanban')->eq($kanbanID)->andWhere('lane')->eq($laneID)->andWhere('`column`')->eq($columnID)->exec();
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess));
}
/**
* Archive a card.
*
@@ -919,18 +957,29 @@ class kanban extends control
*/
public function setWIP($columnID, $executionID = 0, $from = 'kanban')
{
$column = $this->kanban->getColumnById($columnID);
if($_POST)
{
$this->kanban->setWIP($columnID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action')->create('kanbancolumn', $columnID, 'Edited', '', $executionID);
if($from == 'RDKanban')
{
if(dao::isError()) return $this->sendError(dao::getError());
$regionID = $column->region;
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, $regionID)"));
}
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->app->loadLang('story');
$column = $this->kanban->getColumnById($columnID);
if(!$column) die(js::error($this->lang->notFound) . js::locate($this->createLink('execution', 'kanban', "executionID=$executionID")));
$title = isset($column->parentName) ? $column->parentName . '/' . $column->name : $column->name;
@@ -997,6 +1046,16 @@ class kanban extends control
$this->action->logHistory($actionID, $changes);
}
if($from == 'RDKanban')
{
if(dao::isError()) return $this->sendError(dao::getError());
$regionID = $column->region;
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, $regionID)"));
}
return $this->sendSuccess(array('locate' => 'parent'));
}
@@ -1005,6 +1064,28 @@ class kanban extends control
$this->display();
}
/**
* Set done function.
*
* @param int $kanbanID
* @access public
* @return void
*/
public function setDoneFunction($kanbanID)
{
if(!empty($_POST))
{
$this->dao->update(TABLE_KANBAN)->set('performable')->eq($_POST['performable'])->exec();
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->kanban = $this->kanban->getByID($kanbanID);
$this->display();
}
/**
* AJAX: Update the cards sorting of the lane column.
*
@@ -1184,4 +1265,30 @@ class kanban extends control
if(empty($lanes)) return;
return print(html::select('otherLane', $lanes, '', "class='form-control'"));
}
/**
* Import.
*
* @param int $kanbanID
* @access public
* @return void
*/
public function import($kanbanID)
{
if(!empty($_POST))
{
$this->kanban->import($kanbanID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$kanban = $this->kanban->getByID($kanbanID);
$this->view->enableImport = empty($kanban->importObject) ? 'off' : 'on';
$this->view->importObjects = empty($kanban->importObject) ? array() : explode(',', $kanban->importObject);
$this->display();
}
}
+2
View File
@@ -0,0 +1,2 @@
#importForm .checkbox-primary:not(:first-child) {margin-left: 10px;}
#importForm .checkbox-primary {display: inline-block}
+3 -2
View File
@@ -52,10 +52,11 @@
.region .kanban-lane > .kanban-lane-name:hover > .actions {opacity: 1;}
.region .kanban-lane.sort > .kanban-lane-name {cursor: move;}
.region .kanban-lane-col {max-height: unset !important; overflow: auto!important; position: relative;}
.region .kanban-lane-col {max-height: unset !important; overflow: auto; position: relative;}
.region .kanban-lane-col.has-scrollbar > .kanban-lane-actions {position: absolute; background-color: inherit; bottom: 0; left: 0; right: 0;}
.region .kanban-lane-items {overflow: auto; padding-bottom: 10px;}
.region .kanban-lane-items {overflow: hidden; padding-bottom: 10px;}
.region .kanban-lane-items:hover {overflow: overlay !important;}
.region .kanban-item {position: relative}
.region .kanban-item > .kanban-card > .title {line-height: 18px;}
+3 -20
View File
@@ -1,20 +1,3 @@
$(function()
{
if(typeof acl != 'undefined' && acl != null) setWhite(acl);
});
/**
* Set white list.
*
* @param string $acl
* @access public
* @return void
*/
function setWhite(acl)
{
acl != 'private' ? $('#whitelistBox').addClass('hidden') : $('#whitelistBox').removeClass('hidden');
}
/**
* Set mailto.
*
@@ -35,8 +18,8 @@ function setMailto(field, value)
}
/**
* Initialize custom color selector.
*
* Initialize custom color selector.
*
* @access public
* @return void
*/
@@ -59,6 +42,6 @@ function initColorPicker()
$('input[name=color]').val(color);
$(this).addClass('checked');
$(this).siblings().removeClass('checked');
})
})
}
+14
View File
@@ -0,0 +1,14 @@
/**
* When space type or space value change.
*
* @oaram int spaceID
* @param string type
* @access public
* @return void
*/
function changeValue(spaceID, type = '')
{
if(type == '') type = spaceType;
location.href = createLink('kanban', 'create', 'spaceID=' + spaceID + '&type=' + type);
}
+12
View File
@@ -0,0 +1,12 @@
/**
* When type change.
*
* @param string type
* @access public
* @return void
*/
function changeType(type)
{
location.href = createLink('kanban', 'createSpace', 'type=' + type);
}
+33
View File
@@ -0,0 +1,33 @@
$(function()
{
if(enableImport == 'off') $("input[name^='importObjectList']").attr('disabled', 'disabled');
$("input[name='import']").change(function()
{
if($(this).val() == 'off')
{
$("input[name^='importObjectList']").attr('disabled', 'disabled');
}
else
{
$("input[name^='importObjectList']").removeAttr('disabled');
}
})
$("input[name^='importObjectList']").change(function()
{
if($("input:checked[name^=importObjectList]").length != 0 && !$('#emptyTip').is('.hidden')) $('#emptyTip').addClass('hidden');
})
$('#submit').click(function()
{
var enableImport = $("input:checked[name='import']").val();
var objectListLength = $("input:checked[name^=importObjectList]").length;
if(enableImport == 'on' && objectListLength == 0)
{
$('#emptyTip').removeClass('hidden');
return false;
}
})
})
+10
View File
@@ -20,3 +20,13 @@ $('.panel').mouseleave(function(e)
$('.kanban-actions').css('visibility','hidden');
$('.dropdown').removeClass('open');
});
$(function()
{
$('input[name^="showClosed"]').click(function()
{
var showClosed = $(this).is(':checked') ? 1 : 0;
$.cookie('showClosed', showClosed, {expires:config.cookieLife, path:config.webRoot});
window.location.reload();
});
});
+14 -10
View File
@@ -257,6 +257,8 @@ function renderKanbanItem(item, $item)
var $title = $item.children('.title');
var privs = item.actions;
var printMoreBtn = (privs.includes('editCard') || privs.includes('archiveCard') || privs.includes('copyCard') || privs.includes('deleteCard') || privs.includes('moveCard') || privs.includes('setCardColor'));
if(privs.includes('sortCard')) $item.parent().addClass('sort');
if(!$title.length)
{
if(privs.includes('viewCard')) $title = $('<a class="title iframe" data-toggle="modal" data-width="80%"></a>').appendTo($item).attr('href', createLink('kanban', 'viewCard', 'cardID=' + item.id, '', true));
@@ -488,7 +490,7 @@ function openAddTaskForm($element)
var laneID = $element.closest('.kanban-lane').data('id');
var columnID = $element.closest('.kanban-col').data('id');
var status = $element.closest('.kanban-col').data('type');
var modalUrl = createLink('kanban', 'createCard', 'kanbanID=' + kanbanID + '&regionID=' + regionID + '&groupID=' + groupID + '&laneID=' + laneID + '&columnID=' + columnID);
var modalUrl = createLink('kanban', 'createCard', 'kanbanID=' + kanbanID + '&regionID=' + regionID + '&groupID=' + groupID + '&columnID=' + columnID);
$.zui.modalTrigger.show(
{
url: modalUrl,
@@ -952,29 +954,29 @@ $(function()
var $cards = null;
$('#kanban').sortable(
{
selector: '.region, .kanban-board, .kanban-lane',
trigger: '.region.sort > .region-header, .kanban-board.sort > .kanban-header > .kanban-group-header, .kanban-lane.sort > .kanban-lane-name',
selector: '.region, .kanban-board, .kanban-lane, .kanban-item.sort',
trigger: '.region.sort > .region-header, .kanban-board.sort > .kanban-header > .kanban-group-header, .kanban-lane.sort > .kanban-lane-name, .kanban-item.sort',
container: function($ele)
{
return $ele.parent();
},
targetSelector: function($ele)
{
/* Sort regions */
/* Sort regions. */
if($ele.hasClass('region'))
{
sortType = 'region';
return $ele.parent().children('.region');
}
/* Sort boards */
/* Sort boards. */
if($ele.hasClass('kanban-board'))
{
sortType = 'board';
return $ele.parent().children('.kanban-board');
}
/* Sort lanes */
/* Sort lanes. */
if($ele.hasClass('kanban-lane'))
{
sortType = 'lane';
@@ -983,10 +985,10 @@ $(function()
return $ele.parent().children('.kanban-lane');
}
/* Sort lanes */
/* Sort cards. */
if($ele.hasClass('kanban-item'))
{
sortType = 'item';
sortType = 'card';
return $ele.parent().children('.kanban-item');
}
},
@@ -1037,9 +1039,11 @@ $(function()
var region = e.element.parent().parent().data('id');
url = createLink('kanban', 'sortLane', 'region=' + region + '&lanes=' + orders.join(','));
}
if(sortType == 'item')
if(sortType == 'card')
{
url = createLink('task', 'sort', 'kanbanID=' + kanbanID + '&tasks=' + orders.join(','));
var laneID = e.element.closest('.kanban-lane').data('id');
var columnID = e.element.closest('.kanban-col').data('id');
url = createLink('kanban', 'sortCard', 'kanbanID=' + kanbanID + '&laneID=' + laneID + '&columnID=' + columnID + '&cards=' + orders.join(','));
}
if(!url) return true;
+25 -5
View File
@@ -37,6 +37,8 @@ $lang->kanban->setCardColor = 'Set Card Color';
$lang->kanban->deleteCard = 'Delete Card';
$lang->kanban->assigntoCard = 'Assign';
$lang->kanban->setting = 'Setting';
$lang->kanban->setDoneFunction = 'Set done function';
$lang->kanban->doneFunction = 'Done function';
$lang->kanban->splitColumn = 'Split Column';
$lang->kanban->createColumnOnLeft = 'Create Column On Left';
$lang->kanban->createColumnOnRight = 'Create Column On Right';
@@ -56,6 +58,8 @@ $lang->kanban->restoreCard = 'Restore Card';
$lang->kanban->restore = 'Restore';
$lang->kanban->child = 'Child';
$lang->kanban->batchCreateCard = 'Batchcreate Card';
$lang->kanban->import = 'Import';
$lang->kanban->showClosed = 'Closed';
/* Fields. */
$lang->kanban->space = 'Space';
@@ -95,6 +99,9 @@ $lang->kanban->aclList['private'] = 'Private (For the kanban team, whitelist mem
$lang->kanban->enableArchived['0'] = 'No Enable';
$lang->kanban->enableArchived['1'] = 'Enable';
$lang->kanban->enableFinished['0'] = 'No Enable';
$lang->kanban->enableFinished['1'] = 'Enable';
$lang->kanban->type = array();
$lang->kanban->type['all'] = "All KanBan";
$lang->kanban->type['story'] = "Story KanBan";
@@ -159,6 +166,18 @@ $lang->kanban->error = new stdclass();
$lang->kanban->error->mustBeInt = 'The WIPs must be positive integer.';
$lang->kanban->error->parentLimitNote = 'The WIPs in the parent column cannot be < the sum of the WIPs in the child column.';
$lang->kanban->error->childLimitNote = 'The sum of products in the child column cannot be > the number of products in the parent column.';
$lang->kanban->error->importObjNotEmpty = 'Please select at least one import object.';
$lang->kanban->importList = array();
$lang->kanban->importList['off'] = 'Import is not enabled';
$lang->kanban->importList['on'] = 'Enable the import function, you can only import content that you have permission to view.';
$lang->kanban->importObjectList = array();
$lang->kanban->importObjectList['plan'] = 'Product Plan';
$lang->kanban->importObjectList['release'] = 'Release';
$lang->kanban->importObjectList['build'] = 'Build';
$lang->kanban->importObjectList['execution'] = 'Execution';
$lang->kanban->importObjectList['cards'] = 'Other Kanban Cards';
$lang->kanban->defaultColumn = array();
$lang->kanban->defaultColumn['wait'] = 'wait';
@@ -219,16 +238,17 @@ $lang->kanbanspace->lastEditedBy = 'Edited By';
$lang->kanbanspace->lastEditedDate = 'Edited Date';
$lang->kanbanspace->closedBy = 'Closed By';
$lang->kanbanspace->closedDate = 'Closed Date';
$lang->kanbanspace->type = 'Type';
$lang->kanbanspace->empty = 'No Space';
$lang->kanbanspace->aclList['open'] = 'Open (Accessible with kanban view permissions)';
$lang->kanbanspace->aclList['private'] = 'Private (For the space owner, team and whitelist members only)';
$lang->kanbanspace->featureBar['all'] = 'All';
$lang->kanbanspace->featureBar['my'] = 'My';
$lang->kanbanspace->featureBar['other'] = 'Other';
$lang->kanbanspace->featureBar['closed'] = 'Closed';
$lang->kanbanspace->featureBar['private'] = 'Private Space';
$lang->kanbanspace->featureBar['cooperation'] = 'Cooperation Space';
$lang->kanbanspace->featureBar['public'] = 'Public Space';
$lang->kanbanspace->featureBar['involved'] = 'Involved';
$lang->kanbancolumn = new stdclass();
$lang->kanbancolumn->name = $lang->kanban->columnName;
@@ -309,7 +329,7 @@ $lang->kanbancard->empty = 'No Card';
$lang->kanbancard->confirmArchive = 'Are you sure to archive this card? After archiving the card, it will be hidden from the column and you can view it in the Region - Archived.';
$lang->kanbancard->confirmDelete = 'Are you sure to delete this card? After deleting the card, it will be deleted from the Kanban. You can only view it in the system recycle bin.';
$lang->kanbancard->confirmRestore = 'Are you sure you want to restore this card? After the card is restored, the card will be restored to the "%s" Kanban column.';
$lang->kanbancard->confirmRestore = "Are you sure you want to restore this card? After the card is restored, the card will be restored to the '%s' Kanban column.";
$lang->kanbancard->confirmRestoreTip = "The card's column has been archived or deleted, please restore '%s' column first.";
$lang->kanbancard->priList[1] = 1;
+27 -7
View File
@@ -37,6 +37,8 @@ $lang->kanban->setCardColor = '设置卡片颜色';
$lang->kanban->deleteCard = '删除卡片';
$lang->kanban->assigntoCard = '指派';
$lang->kanban->setting = '设置';
$lang->kanban->setDoneFunction = '设置完成功能';
$lang->kanban->doneFunction = '完成功能';
$lang->kanban->splitColumn = '新增子看板列';
$lang->kanban->createColumnOnLeft = '左侧新增看板列';
$lang->kanban->createColumnOnRight = '右侧新增看板列';
@@ -56,6 +58,8 @@ $lang->kanban->restoreCard = '还原卡片';
$lang->kanban->restore = '还原';
$lang->kanban->child = '子';
$lang->kanban->batchCreateCard = '批量创建卡片';
$lang->kanban->import = '导入功能';
$lang->kanban->showClosed = '显示已关闭';
/* Fields. */
$lang->kanban->space = '所属空间';
@@ -95,6 +99,9 @@ $lang->kanban->aclList['private'] = '私有(看板团队成员、白名单、
$lang->kanban->enableArchived['0'] = '不启用';
$lang->kanban->enableArchived['1'] = '启用';
$lang->kanban->enableFinished['0'] = '不启用';
$lang->kanban->enableFinished['1'] = '启用';
$lang->kanban->type = array();
$lang->kanban->type['all'] = "综合看板";
$lang->kanban->type['story'] = "{$lang->SRCommon}看板";
@@ -156,9 +163,21 @@ $lang->kanban->my = '我的看板';
$lang->kanban->other = '其他';
$lang->kanban->error = new stdclass();
$lang->kanban->error->mustBeInt = '在制品数量必须是正整数。';
$lang->kanban->error->parentLimitNote = '父列的在制品数量不能小于子列在制品数量之和';
$lang->kanban->error->childLimitNote = '子列在制品数量之和不能大于父列的在制品数量';
$lang->kanban->error->mustBeInt = '在制品数量必须是正整数。';
$lang->kanban->error->parentLimitNote = '父列的在制品数量不能小于子列在制品数量之和';
$lang->kanban->error->childLimitNote = '子列在制品数量之和不能大于父列的在制品数量';
$lang->kanban->error->importObjNotEmpty = '请至少选择一个导入对象';
$lang->kanban->importList = array();
$lang->kanban->importList['off'] = '不启用导入功能';
$lang->kanban->importList['on'] = '启用导入功能,只能导入自己有权限查看的内容';
$lang->kanban->importObjectList = array();
$lang->kanban->importObjectList['plan'] = '产品计划';
$lang->kanban->importObjectList['release'] = '产品发布';
$lang->kanban->importObjectList['build'] = '项目版本';
$lang->kanban->importObjectList['execution'] = '项目执行';
$lang->kanban->importObjectList['cards'] = '其他看板卡片';
$lang->kanban->defaultColumn = array();
$lang->kanban->defaultColumn['wait'] = '未开始';
@@ -219,16 +238,17 @@ $lang->kanbanspace->lastEditedBy = '最后修改';
$lang->kanbanspace->lastEditedDate = '最后修改日期';
$lang->kanbanspace->closedBy = '由谁关闭';
$lang->kanbanspace->closedDate = '关闭日期';
$lang->kanbanspace->type = '空间类型';
$lang->kanbanspace->empty = '暂时没有空间';
$lang->kanbanspace->aclList['open'] = '公开(有看板空间视图权限即可访问)';
$lang->kanbanspace->aclList['private'] = '私有(只有看板空间负责人、团队成员、白名单可访问)';
$lang->kanbanspace->featureBar['all'] = '所有';
$lang->kanbanspace->featureBar['my'] = '我的空间';
$lang->kanbanspace->featureBar['other'] = '其他空间';
$lang->kanbanspace->featureBar['closed'] = '已关闭';
$lang->kanbanspace->featureBar['private'] = '私人空间';
$lang->kanbanspace->featureBar['cooperation'] = '协作空间';
$lang->kanbanspace->featureBar['public'] = '公共空间';
$lang->kanbanspace->featureBar['involved'] = '我参与的';
$lang->kanbancolumn = new stdclass();
$lang->kanbancolumn->name = $lang->kanban->columnName;
+90 -68
View File
@@ -460,7 +460,7 @@ class kanbanModel extends model
$cardID = $this->dao->lastInsertID();
$this->file->saveUpload('kanbancard', $cardID);
$this->file->updateObjectID($this->post->uid, $cardID, 'kanbancard');
$this->addKanbanCell($kanbanID, $this->post->lane, $columnID, 'common', $cardID);
$this->addKanbanCell($kanbanID, (int)$this->post->lane, $columnID, 'common', $cardID);
return $cardID;
}
@@ -721,7 +721,7 @@ class kanbanModel extends model
$kanbanData = array();
$actions = array('sortGroup');
$regions = $this->getRegionPairs($executionID);
$regions = $this->getRegionPairs($executionID, $regionID);
$regionIDList = $regionID == 0 ? array_keys($regions) : array(0 => $regionID);
$groupGroup = $this->getGroupGroupByRegions($regionIDList);
$laneGroup = $this->getLaneGroupByRegions($regionIDList, $browseType);
@@ -783,14 +783,16 @@ class kanbanModel extends model
* Get ordered region pairs.
*
* @param int $kanbanID
* @param int $regionID
* @access public
* @return array
*/
public function getRegionPairs($kanbanID)
public function getRegionPairs($kanbanID, $regionID = 0)
{
return $this->dao->select('id,name')->from(TABLE_KANBANREGION)
->where('kanban')->eq($kanbanID)
->andWhere('deleted')->eq('0')
->beginIF($regionID)->andWhere('id')->eq($regionID)->fi()
->orderBy('order_asc')
->fetchPairs();
}
@@ -930,27 +932,41 @@ class kanbanModel extends model
*/
public function getCardGroupByKanban($kanbanID)
{
$cards = $this->dao->select('t1.*,t2.kanban,t2.lane,t2.column')->from(TABLE_KANBANCARD)->alias('t1')
->leftJoin(TABLE_KANBANCELL)->alias('t2')->on('t1.kanban=t2.kanban')
/* Get card data.*/
$cards = $this->dao->select('*')->from(TABLE_KANBANCARD)->alias('t1')
->where('deleted')->eq(0)
->andWhere("INSTR(t2.cards, CONCAT(',',t1.id,','))")->gt(0)
->andWhere('kanban')->eq($kanbanID)
->andWhere('archived')->eq(0)
->andWhere('t2.kanban')->eq($kanbanID)
->andWhere('t2.type')->eq('common')
//->orderBy('`order` asc')
->fetchAll('id');
$actions = array('editCard', 'archiveCard', 'deleteCard', 'moveCard', 'setCardColor', 'viewCard');
$cardGroup = array();
foreach($cards as $card)
{
$card->actions = array();
foreach($actions as $action)
{
if(common::hasPriv('kanban', $action)) $card->actions[] = $action;
}
$cellList = $this->dao->select('*')->from(TABLE_KANBANCELL)
->where('kanban')->eq($kanbanID)
->andWhere('type')->eq('common')
->fetchAll();
$cardGroup[$card->lane]['column' . $card->column][] = $card;
$actions = array('editCard', 'archiveCard', 'deleteCard', 'moveCard', 'setCardColor', 'viewCard', 'sortCard');
$cardGroup = array();
foreach($cellList as $cell)
{
$cardIdList = array_filter(explode(',', $cell->cards));
if(empty($cardIdList)) continue;
foreach($cardIdList as $cardID)
{
if(!isset($cards[$cardID])) continue;
$card = zget($cards, $cardID);
$card->column = $cell->column;
$card->lane = $cell->lane;
$card->actions = array();
foreach($actions as $action)
{
if(common::hasPriv('kanban', $action)) $card->actions[] = $action;
}
$cardGroup[$cell->lane]['column' . $cell->column][] = $card;
}
}
return $cardGroup;
@@ -1395,7 +1411,7 @@ class kanbanModel extends model
/**
* Get space list.
*
* @param string $browseType all|my|other|closed
* @param string $browseType private|cooperation|public|involved
* @param object $pager
* @access public
* @return array
@@ -1403,18 +1419,19 @@ class kanbanModel extends model
public function getSpaceList($browseType, $pager = null)
{
$account = $this->app->user->account;
$spaceIdList = $this->getCanViewObjects('kanbanspace');
$spaceIdList = $this->getCanViewObjects('kanbanspace', $browseType);
$spaceList = $this->dao->select('*')->from(TABLE_KANBANSPACE)
->where('deleted')->eq(0)
->beginIF($browseType == 'my')->andWhere('owner')->eq($account)->fi()
->beginIF($browseType == 'other')->andWhere('owner')->ne($account)->fi()
->beginIF($browseType == 'closed')->andWhere('status')->eq('closed')->fi()
->beginIF(in_array($browseType, array('private', 'cooperation', 'public')))->andWhere('type')->eq($browseType)->fi()
->beginIF($browseType == 'private')->andWhere('owner')->eq($account)->fi()
->beginIF($browseType == 'involved')->andWhere('owner')->ne($account)->fi()
->beginIF($this->cookie->showClosed == 0)->andWhere('status')->ne('closed')->fi()
->beginIF(!$this->app->user->admin)->andWhere('id')->in($spaceIdList)->fi()
->orderBy('id_desc')
->page($pager)
->fetchAll('id');
$kanbanIdList = $this->getCanViewObjects();
$kanbanIdList = $this->getCanViewObjects('kanban', $browseType);
$kanbanGroup = $this->getGroupBySpaceList(array_keys($spaceList), $kanbanIdList);
foreach($spaceList as $spaceID => $space)
{
@@ -1427,21 +1444,20 @@ class kanbanModel extends model
/**
* Get space pairs.
*
* @param string $browseType all|my|other|closed
* @param string $browseType private|cooperation|public|involved
* @access public
* @return array
*/
public function getSpacePairs($browseType = 'all')
public function getSpacePairs($browseType = 'private')
{
$account = $this->app->user->account;
$spaceIdList = $this->getCanViewObjects('kanbanspace');
return $this->dao->select('id,name')->from(TABLE_KANBANSPACE)
->where('deleted')->eq(0)
->beginIF($browseType == 'my')->andWhere('owner')->eq($account)->fi()
->beginIF($browseType == 'other')->andWhere('owner')->ne($account)->fi()
->beginIF($browseType == 'closed')->andWhere('status')->eq('closed')->fi()
->beginIF($browseType == 'noclosed')->andWhere('status')->ne('closed')->fi()
->beginIF(in_array($browseType, array('private', 'cooperation', 'public')))->andWhere('type')->eq($browseType)->fi()
->beginIF($browseType == 'involved')->andWhere('owner')->ne($account)->fi()
->beginIF($this->cookie->showClosed == 0)->andWhere('status')->ne('closed')->fi()
->beginIF(!$this->app->user->admin)->andWhere('id')->in($spaceIdList)->fi()
->orderBy('id_desc')
->fetchPairs('id');
@@ -1451,7 +1467,7 @@ class kanbanModel extends model
* Get can view objects.
*
* @param string $objectType kanbanspace|kanban
* @param string $param noclosed
* @param string $param noclosed|private|cooperation|public|involved
* @access public
* @return array
*/
@@ -1463,31 +1479,29 @@ class kanbanModel extends model
->beginIF(strpos($param, 'noclosed') !== false)->andWhere('status')->ne('closed')->fi()
->fetchAll('id');
$spaceList = $objectType == 'kanban' ? $this->dao->select('id,owner,team,whitelist')->from(TABLE_KANBANSPACE)->fetchAll('id') : array();
$spaceList = $objectType == 'kanban' ? $this->dao->select('id,owner,type')->from(TABLE_KANBANSPACE)->fetchAll('id') : array();
if($this->app->user->admin) return array_keys($objects);
$account = $this->app->user->account;
foreach($objects as $objectID => $object)
{
if($object->acl == 'private' or $object->acl == 'extend')
{
$remove = true;
if($object->owner == $account) $remove = false;
if(strpos(",{$object->team},", ",$account,") !== false) $remove = false;
if(strpos(",{$object->whitelist},", ",$account,") !== false) $remove = false;
if($objectType == 'kanban')
{
$spaceOwner = isset($spaceList[$object->space]->owner) ? $spaceList[$object->space]->owner : '';
$spaceTeam = isset($spaceList[$object->space]->team) ? trim($spaceList[$object->space]->team, ',') : '';
$spaceWhiteList = isset($spaceList[$object->space]->whitelist) ? trim($spaceList[$object->space]->whitelist, ',') : '';
if(strpos(",$spaceOwner,", ",$account,") !== false) $remove = false;
if(strpos(",$spaceTeam,", ",$account,") !== false and $object->acl == 'extend') $remove = false;
if(strpos(",$spaceWhiteList,", ",$account,") !== false and $object->acl == 'extend') $remove = false;
}
$remove = true;
if($param == 'public') continue;
if($remove) unset($objects[$objectID]);
if($object->owner == $account) $remove = false;
if(strpos(",{$object->team},", ",$account,") !== false) $remove = false;
if(strpos(",{$object->whitelist},", ",$account,") !== false) $remove = false;
if($objectType == 'kanban')
{
$spaceOwner = isset($spaceList[$object->space]->owner) ? $spaceList[$object->space]->owner : '';
$spaceType = isset($spaceList[$object->space]->type) ? $spaceList[$object->space]->type : '';
if(strpos(",$spaceOwner,", ",$account,") !== false) $remove = false;
if($spaceType == 'public') $remove = false;
}
if($remove) unset($objects[$objectID]);
}
return array_keys($objects);
@@ -1505,12 +1519,16 @@ class kanbanModel extends model
$space = fixer::input('post')
->setDefault('createdBy', $account)
->setDefault('createdDate', helper::now())
->setdefault('team', '')
->setdefault('whitelist', '')
->join('whitelist', ',')
->join('team', ',')
->trim('name')
->remove('uid,contactListMenu')
->get();
if($space->type == 'private') $space->owner = $account;
if(strpos(",{$space->team},", ",$account,") === false and $space->owner != $account) $space->team .= ",$account";
$space = $this->loadModel('file')->processImgURL($space, $this->config->kanban->editor->createspace['id'], $this->post->uid);
@@ -1551,8 +1569,6 @@ class kanbanModel extends model
->remove('uid,contactListMenu')
->get();
$space->whitelist = $space->acl == 'open' ? '' : $space->whitelist;
$space = $this->loadModel('file')->processImgURL($space, $this->config->kanban->editor->editspace['id'], $this->post->uid);
$this->dao->update(TABLE_KANBANSPACE)->data($space)
@@ -1695,10 +1711,13 @@ class kanbanModel extends model
$kanban = fixer::input('post')
->setDefault('createdBy', $account)
->setDefault('createdDate', helper::now())
->setdefault('owner', '')
->setdefault('team', '')
->setdefault('whitelist', '')
->join('whitelist', ',')
->join('team', ',')
->trim('name')
->remove('uid,contactListMenu')
->remove('uid,contactListMenu,type')
->get();
if(strpos(",{$kanban->team},", ",$account,") === false and $kanban->owner != $account) $kanban->team .= ",$account";
@@ -1711,12 +1730,6 @@ class kanbanModel extends model
->where('space')->eq($kanban->space)
->fetch('maxOrder');
$kanban->order = $maxOrder ? $maxOrder+ 1 : 1;
if($kanban->acl == 'extend')
{
$spaceAcl = $this->dao->select('acl')->from(TABLE_KANBANSPACE)->where('id')->eq($kanban->space)->fetch('acl');
$kanban->acl = $spaceAcl == 'open' ? 'open' : 'extend';
}
}
@@ -1759,14 +1772,6 @@ class kanbanModel extends model
->remove('uid,contactListMenu')
->get();
if($kanban->acl == 'extend')
{
$spaceAcl = $this->dao->select('acl')->from(TABLE_KANBANSPACE)->where('id')->eq($kanban->space)->fetch('acl');
$kanban->acl = $spaceAcl == 'open' ? 'open' : 'extend';
$kanban->whitelist = $kanban->acl == 'open' ? '' : $kanban->whitelist;
}
$kanban = $this->loadModel('file')->processImgURL($kanban, $this->config->kanban->editor->edit['id'], $this->post->uid);
$this->dao->update(TABLE_KANBAN)->data($kanban)
@@ -2606,19 +2611,21 @@ class kanbanModel extends model
$actions .= "<div class='btn-group'>";
$actions .= "<a href='javascript:fullScreen();' id='fullScreenBtn' class='btn btn-link'><i class='icon icon-fullscreen'></i> {$this->lang->kanban->fullScreen}</a>";
$printSettingBtn = (common::hasPriv('kanban', 'createRegion') or $printSetHeight or common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete'));
$printSettingBtn = (common::hasPriv('kanban', 'createRegion') or $printSetHeight or common::hasPriv('kanban', 'setDoneFunction') or common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete'));
if($printSettingBtn)
{
$actions .= "<a data-toggle='dropdown' class='btn btn-link dropdown-toggle setting' type='button'>" . '<i class="icon icon-cog-outline"></i> ' . $this->lang->kanban->setting . '</a>';
$actions .= "<ul id='kanbanActionMenu' class='dropdown-menu text-left'>";
if(common::hasPriv('kanban', 'createRegion')) $actions .= '<li>' . html::a(helper::createLink('kanban', 'createRegion', "kanbanID=$kanban->id", '', true), '<i class="icon icon-plus"></i>' . $this->lang->kanban->createRegion, '', "class='iframe btn btn-link'") . '</li>';
if(common::hasPriv('kanban', 'import')) $actions .= '<li>' . html::a(helper::createLink('kanban', 'import', "kanbanID=$kanban->id", '', true), '<i class="icon icon-import"></i>' . $this->lang->kanban->import, '', "class='iframe btn btn-link'") . '</li>';
if($printSetHeight)
{
$width = $this->app->getClientLang() == 'en' ? '70%' : '60%';
$actions .= '<li>' . html::a(helper::createLink('kanban', 'setLaneHeight', "kanbanID=$kanban->id", '', true), '<i class="icon icon-size-height"></i>' . $this->lang->kanban->laneHeight, '', "class='iframe btn btn-link' data-width='$width'") . '</li>';
}
if(common::hasPriv('kanban', 'setDoneFunction')) $actions .= '<li>' . html::a(helper::createLink('kanban', 'setDoneFunction', "kanbanID=$kanban->id", '', true), '<i class="icon icon-checked"></i>' . $this->lang->kanban->doneFunction, '', "class='iframe btn btn-link'") . '</li>';
$kanbanActions = '';
$attr = $kanban->status == 'closed' ? "disabled='disabled'" : '';
@@ -2627,7 +2634,7 @@ class kanbanModel extends model
if(common::hasPriv('kanban', 'delete')) $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'delete', "kanbanID=$kanban->id"), '<i class="icon icon-trash"></i>' . $this->lang->kanban->delete, 'hiddenwin', "class='btn btn-link'") . '</li>';
if($kanbanActions)
{
$actions .= ((common::hasPriv('kanban', 'createRegion') or $printSetHeight) and (common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete'))) ? "<div class='divider'></div>" . $kanbanActions : $kanbanActions;
$actions .= ((common::hasPriv('kanban', 'createRegion') or $printSetHeight or common::hasPriv('kanban', 'setDoneFunction')) and (common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete'))) ? "<div class='divider'></div>" . $kanbanActions : $kanbanActions;
}
$actions .= "</ul>";
}
@@ -3164,4 +3171,19 @@ class kanbanModel extends model
return true;
}
/**
* Import.
*
* @param int $kanbanID
* @access public
* @return void
*/
public function import($kanbanID)
{
$importObjects = $_POST['import'] == 'off' ? array() : $_POST['importObjectList'];
$importObjectList = implode(',', $importObjects);
$this->dao->update(TABLE_KANBAN)->set('importObject')->eq($importObjectList)->where('id')->eq($kanbanID)->exec();
}
}
+11 -5
View File
@@ -12,15 +12,21 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('spaceType', $type);?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->kanban->create;?></h2>
</div>
<form class='form-indicator main-form form-ajax' method='post' enctype='multipart/form-data' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->kanbanspace->type;?></th>
<td><?php echo html::select('type', $typeList, $type, "onchange='changeValue({$spaceID}, this.value)' class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->kanban->space;?></th>
<td><?php echo html::select('space', $spacePairs, $spaceID, "class='form-control chosen'");?></td>
<td><?php echo html::select('space', $spacePairs, $spaceID, "onchange='changeValue(this.value)' class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
@@ -31,6 +37,7 @@
<th><?php echo $lang->kanban->archived;?></th>
<td><?php echo html::radio('archived', $lang->kanban->enableArchived, '0');?></td>
</tr>
<?php if($type != 'private'):?>
<tr>
<th><?php echo $lang->kanban->owner;?></th>
<td><?php echo html::select('owner', $users, '', "class='form-control chosen' data-drop_direction='down'");?></td>
@@ -44,6 +51,7 @@
</div>
</td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->kanban->desc;?></th>
<td colspan='2'>
@@ -51,14 +59,12 @@
<?php echo html::textarea('desc', '', "rows='10' class='form-control'");?>
</td>
</tr>
<tr>
<th><?php echo $lang->kanban->acl;?></th>
<td colspan='2'><?php echo nl2br(html::radio('acl', $lang->kanban->aclList, 'private', "onclick='setWhite(this.value);'", 'block'));?></td>
</tr>
<?php if($type == 'private'):?>
<tr id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, '', 'class="form-control chosen" multiple');?></td>
</tr>
<?php endif;?>
<tr>
<td colspan='3' class='text-center form-actions'>
<?php echo html::submitButton();?>
+10 -6
View File
@@ -19,10 +19,15 @@
<form class='form-indicator main-form form-ajax' method='post' enctype='multipart/form-data' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->kanbanspace->name;?></th>
<td><?php echo html::input('name', '', "class='form-control'");?></td>
<th><?php echo $lang->kanbanspace->type;?></th>
<td><?php echo html::select('type', $typeList, $type, "onchange='changeType(this.value)' class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->kanbanspace->name;?></th>
<td><?php echo html::input('name', '', "class='form-control'");?></td>
</tr>
<?php if($type != 'private'):?>
<tr>
<th><?php echo $lang->kanbanspace->owner;?></th>
<td><?php echo html::select('owner', $users, '', "class='form-control chosen'");?></td>
@@ -36,6 +41,7 @@
</div>
</td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->kanbanspace->desc;?></th>
<td colspan='2'>
@@ -43,14 +49,12 @@
<?php echo html::textarea('desc', '', "rows='10' class='form-control'");?>
</td>
</tr>
<tr>
<th><?php echo $lang->kanbanspace->acl;?></th>
<td colspan='2'><?php echo nl2br(html::radio('acl', $lang->kanbanspace->aclList, 'private', "onclick='setWhite(this.value);'", 'block'));?></td>
</tr>
<?php if($type == 'private'):?>
<tr id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, '', 'class="form-control chosen" multiple');?></td>
</tr>
<?php endif;?>
<tr>
<td colspan='3' class='text-center form-actions'>
<?php echo html::submitButton();?>
+4 -5
View File
@@ -12,7 +12,6 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('acl', $kanban->acl);?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->kanban->edit;?></h2>
@@ -31,6 +30,7 @@
<th><?php echo $lang->kanban->archived;?></th>
<td><?php echo html::radio('archived', $lang->kanban->enableArchived, $kanban->archived);?></td>
</tr>
<?php if($type != 'private'):?>
<tr>
<th><?php echo $lang->kanban->owner;?></th>
<td><?php echo html::select('owner', $users, $kanban->owner, "class='form-control chosen' data-drop_direction='down'");?></td>
@@ -44,6 +44,7 @@
</div>
</td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->kanban->desc;?></th>
<td colspan='2'>
@@ -51,14 +52,12 @@
<?php echo html::textarea('desc', $kanban->desc, "rows='10' class='form-control'");?>
</td>
</tr>
<tr>
<th><?php echo $lang->kanban->acl;?></th>
<td colspan='2'><?php echo nl2br(html::radio('acl', $lang->kanban->aclList, $kanban->acl == 'open' ? 'extend' : $kanban->acl, "onclick='setWhite(this.value);'", 'block'));?></td>
</tr>
<?php if($type == 'private'):?>
<tr id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, $kanban->whitelist, 'class="form-control chosen" multiple');?></td>
</tr>
<?php endif;?>
<tr>
<td colspan='3' class='text-center form-actions'>
<?php echo html::submitButton();?>
+4 -5
View File
@@ -12,7 +12,6 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('acl', $space->acl);?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->kanban->editSpace;?></h2>
@@ -24,6 +23,7 @@
<td><?php echo html::input('name', $space->name, "class='form-control'");?></td>
<td></td>
</tr>
<?php if($space->type != 'private'):?>
<tr>
<th><?php echo $lang->kanbanspace->owner;?></th>
<td><?php echo html::select('owner', $users, $space->owner, "class='form-control chosen'");?></td>
@@ -37,6 +37,7 @@
</div>
</td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->kanbanspace->desc;?></th>
<td colspan='2'>
@@ -44,14 +45,12 @@
<?php echo html::textarea('desc', $space->desc, "rows='10' class='form-control'");?>
</td>
</tr>
<tr>
<th><?php echo $lang->kanbanspace->acl;?></th>
<td colspan='2'><?php echo nl2br(html::radio('acl', $lang->kanbanspace->aclList, $space->acl, "onclick='setWhite(this.value);'", 'block'));?></td>
</tr>
<?php if($space->type == 'private'):?>
<tr id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, $space->whitelist, 'class="form-control chosen" multiple');?></td>
</tr>
<?php endif;?>
<tr>
<td colspan='3' class='text-center form-actions'>
<?php echo html::submitButton();?>
+52
View File
@@ -0,0 +1,52 @@
<?php
/**
* The import file of kanban module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Fangzhou Hu <hufangzhou@easycorp.ltd>
* @package kanban
* @version $Id: import.html.php 935 2022-01-19 14:15:24Z hufangzhou@easycorp.ltd $
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.lite.html.php';?>
<?php js::set('enableImport', $enableImport);?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<?php echo "<span>" . $lang->kanban->import . '</span>';?>
</h2>
</div>
<form method='post' class="load-indicator main-form form-ajax" target='hiddenwin' id='importForm'>
<table align='center' class='table table-form'>
<tr>
<td colspan='2'>
<label class="radio-inline">
<input type='radio' name='import' value='off' <?php echo $enableImport == 'off' ? "checked='checked'" : ''; ?> id='importoff'/>
<?php echo $lang->kanban->importList['off'];?>
</label>
</td>
</tr>
<tr>
<td colspan='2'>
<label class="radio-inline">
<input type='radio' name='import' value='on' <?php echo $enableImport == 'on' ? "checked='checked'" : ''; ?> id='importon'/>
<?php echo $lang->kanban->importList['on'];?>
</label>
</td>
</tr>
<tr>
<td colspan='2'><?php echo html::checkbox('importObjectList', $lang->kanban->importObjectList, $importObjects);?></td>
</tr>
<tr id='emptyTip' class='hidden'><td colspan='3' style='color: red;'><?php echo $lang->kanban->error->importObjNotEmpty;?></td></tr>
<tr>
<td class='form-actions'><?php echo html::submitButton();?></td>
</tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
@@ -0,0 +1,34 @@
<?php
/**
* The setdonefunction file of kanban module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yue Ma <mayue@easycorp.ltd>
* @package kanban
* @version $Id: setdonefunction.html.php 935 2022-01-1 14:20:24Z $
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->kanban->setDoneFunction;?></h2>
</div>
<form class='main-form form-ajax' method='post' enctype='multipart/form-data' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->kanban->doneFunction;?></th>
<td><?php echo nl2br(html::radio('performable', $lang->kanban->enableFinished, $kanban->performable));?></td>
</tr>
<tr>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton();?>
</td>
</tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+4 -11
View File
@@ -19,10 +19,11 @@
<?php if($browseType == $key) $label .= " <span class='label label-light label-badge'>{$pager->recTotal}</span>";?>
<?php echo html::a(inlink('space', "browseType=$key"), $label, '', "class='btn btn-link $active'");?>
<?php endforeach;?>
<?php echo html::checkbox('showClosed', array('1' => $lang->kanban->showClosed), '', $this->cookie->showClosed ? 'checked=checked' : '');?>
</div>
<div class="btn-toolbar pull-right">
<?php if(!empty($unclosedSpace)) common::printLink('kanban', 'create', '', '<i class="icon icon-plus"></i> ' . $lang->kanban->create, '', 'class="btn btn-secondary iframe" data-width="75%"', '', true);?>
<?php common::printLink('kanban', 'createSpace', '', '<i class="icon icon-plus"></i> ' . $lang->kanban->createSpace, '', 'class="btn btn-primary iframe" data-width="75%"', '', true);?>
<?php if(!empty($unclosedSpace) and $browseType != 'involved') common::printLink('kanban', 'create', "spaceID=0&type={$browseType}", '<i class="icon icon-plus"></i> ' . $lang->kanban->create, '', 'class="btn btn-secondary iframe" data-width="75%"', '', true);?>
<?php if($browseType != 'involved')common::printLink('kanban', 'createSpace', "type={$browseType}", '<i class="icon icon-plus"></i> ' . $lang->kanban->createSpace, '', 'class="btn btn-primary iframe" data-width="75%"', '', true);?>
</div>
</div>
<div id='mainContent'>
@@ -44,13 +45,12 @@
<span class="label label-closed"><?php echo $lang->kanban->closed;?></span>
<?php endif;?>
<?php echo $space->name;?>
<?php echo isset($space->kanbans) ? count($space->kanbans) : '';?>
</h4>
</div>
</div>
<div class='spaceActions pull-right'>
<?php $class = $space->status == 'closed' ? 'disabled' : '';?>
<?php if($space->status != 'closed') common::printLink('kanban', 'create', "spaceID={$space->id}", '<i class="icon icon-plus"></i> ' . $lang->kanban->create, '', "class='iframe' data-width='75%'", '', true);?>
<?php if($space->status != 'closed' and $browseType != 'involved') common::printLink('kanban', 'create', "spaceID={$space->id}&type={$space->type}", '<i class="icon icon-plus"></i> ' . $lang->kanban->create, '', "class='iframe' data-width='75%'", '', true);?>
<?php common::printLink('kanban', 'editSpace', "spaceID={$space->id}", '<i class="icon icon-cog-outline"></i> ' . $lang->kanban->setting, '', "class='iframe' data-width='75%'", '', true);?>
<?php common::printLink('kanban', 'closeSpace', "spaceID={$space->id}", '<i class="icon icon-off"></i> ' . $lang->close, '', "class='iframe {$class}'", '', true);?>
<?php common::printLink('kanban', 'deleteSpace', "spaceID={$space->id}", '<i class="icon icon-trash"></i> ' . $lang->delete, 'hiddenwin', '', '', true);?>
@@ -140,13 +140,6 @@
<?php endif;?>
<div class='kanban-members-total pull-left'><?php echo sprintf($lang->kanban->teamSumCount, $teamCount);?></div>
</div>
<div class='kanbanAcl'>
<?php $icon = 'unlock';?>
<?php if($kanban->acl == 'private') $icon = 'lock';?>
<?php if($kanban->acl == 'extend') $icon = 'inherit-space';?>
<i class="<?php echo 'icon-' . $icon;?>"></i>
<?php echo zget($lang->kanban->aclGroup, $kanban->acl, '');?>
</div>
</div>
</div>
</div>
-1
View File
@@ -50,7 +50,6 @@ $canCreateLane = commonModel::hasPriv('kanban', 'createLane');
<div class="region<?php if($canSortRegion) echo ' sort';?>" data-id="<?php echo $region->id;?>">
<div class="region-header dropdown">
<span class="strong"><?php echo $region->name;?></span>
<label class="label label-region"><?php echo $this->lang->kanbanlane->common . ' ' . $region->laneCount;?></label>
<span><i class="icon icon-chevron-double-up" data-id="<?php echo $region->id;?>"></i></span>
<span class='regionActions'>
<?php if($canEditRegion || $canCreateLane || $canDeleteRegion):?>
+1
View File
@@ -258,6 +258,7 @@ class mrModel extends model
{
$MR = fixer::input('post')
->setDefault('jobID', 0)
->setDefault('compileID', 0)
->setDefault('repoID', 0)
->setDefault('removeSourceBranch','0')
->setDefault('needCI', 0)
+2 -1
View File
@@ -133,7 +133,8 @@
<table class="table table-data">
<tbody>
<tr>
<th class="w-90px"><?php echo $lang->job->common;?></th>
<?php $class = in_array($this->app->getClientLang(), array('zh-cn','zh-tw')) ? 'w-90px' : 'w-100px'; ?>
<th class="<?php echo $class; ?>"><?php echo $lang->job->common;?></th>
<td><?php echo $compile->name;?></td>
</tr>
<tr>
+14 -15
View File
@@ -86,7 +86,7 @@ class my extends control
*/
public function work($mode = 'task', $type = 'assignedTo', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->showWorkCount($orderBy, $recTotal, $recPerPage, $pageID);
$this->showWorkCount($recTotal, $recPerPage, $pageID);
echo $this->fetch('my', $mode, "type=$type&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID");
}
@@ -94,14 +94,13 @@ class my extends control
/**
* Show to-do work count.
*
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function showWorkCount($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
public function showWorkCount($recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->loadModel('task');
$this->loadModel('story');
@@ -119,9 +118,9 @@ class my extends control
$taskCount = $pager->recTotal;
/* Get the number of stories assigned to me. */
$assignedToStories = $this->story->getUserStories($this->app->user->account, 'assignedTo', $orderBy, $pager, 'story', false);
$assignedToStories = $this->story->getUserStories($this->app->user->account, 'assignedTo', 'id_desc', $pager, 'story', false);
$assignedToStoryCount = $pager->recTotal;
$reviewByStories = $this->story->getUserStories($this->app->user->account, 'reviewBy', $orderBy, $pager, 'story', false);
$reviewByStories = $this->story->getUserStories($this->app->user->account, 'reviewBy', 'id_desc', $pager, 'story', false);
$reviewByStoryCount = $pager->recTotal;
$storyCount = $assignedToStoryCount + $reviewByStoryCount;
@@ -130,23 +129,23 @@ class my extends control
if($isOpenedURAndSR)
{
/* Get the number of requirements assigned to me. */
$assignedRequirements = $this->story->getUserStories($this->app->user->account, 'assignedTo', $orderBy, $pager, 'requirement');
$assignedRequirements = $this->story->getUserStories($this->app->user->account, 'assignedTo', 'id_desc', $pager, 'requirement');
$assignedRequirementCount = $pager->recTotal;
$reviewByRequirements = $this->story->getUserStories($this->app->user->account, 'reviewBy', $orderBy, $pager, 'requirement');
$reviewByRequirements = $this->story->getUserStories($this->app->user->account, 'reviewBy', 'id_desc', $pager, 'requirement');
$reviewByRequirementCount = $pager->recTotal;
$requirementCount = $assignedRequirementCount + $reviewByRequirementCount;
}
/* Get the number of bugs assigned to me. */
$bugs = $this->bug->getUserBugs($this->app->user->account, 'assignedTo', $orderBy, 0, $pager);
$bugs = $this->bug->getUserBugs($this->app->user->account, 'assignedTo', 'id_desc', 0, $pager);
$bugCount = $pager->recTotal;
/* Get the number of testcases assigned to me. */
$cases = $this->testcase->getByAssignedTo($this->app->user->account, $orderBy, $pager, 'skip');
$cases = $this->testcase->getByAssignedTo($this->app->user->account, 'id_desc', $pager, 'skip');
$caseCount = $pager->recTotal;
/* Get the number of testtasks assigned to me. */
$testTasks = $this->testtask->getByUser($this->app->user->account, $pager, $orderBy, 'wait');
$testTasks = $this->testtask->getByUser($this->app->user->account, $pager, 'id_desc', 'wait');
$testTaskCount = $pager->recTotal;
$issueCount = 0;
@@ -163,23 +162,23 @@ class my extends control
$this->loadModel('meeting');
/* Get the number of issues assigned to me. */
$issues = $this->issue->getUserIssues('assignedTo', $this->app->user->account, $orderBy, $pager);
$issues = $this->issue->getUserIssues('assignedTo', $this->app->user->account, 'id_desc', $pager);
$issueCount = $pager->recTotal;
/* Get the number of risks assigned to me. */
$risks = $this->risk->getUserRisks('assignedTo', $this->app->user->account, $orderBy, $pager);
$risks = $this->risk->getUserRisks('assignedTo', $this->app->user->account, 'id_desc', $pager);
$riskCount = $pager->recTotal;
/* Get the number of reviews assigned to me. */
$reviewList = $this->review->getUserReviews('wait', $orderBy, $pager);
$reviewList = $this->review->getUserReviews('wait', 'id_desc', $pager);
$reviewCount = $pager->recTotal;
/* Get the number of nc assigned to me. */
$ncList = $this->my->getNcList('assignedToMe', $orderBy, $pager);
$ncList = $this->my->getNcList('assignedToMe', 'id_desc', $pager);
$ncCount = $pager->recTotal;
/* Get the number of meetings assigned to me. */
$meetings = $this->meeting->getListByUser('futureMeeting', $orderBy, 0, $pager);
$meetings = $this->meeting->getListByUser('futureMeeting', 'id_desc', 0, $pager);
$meetingCount = $pager->recTotal;
}
+6
View File
@@ -64,6 +64,10 @@
{
echo '#' . $action->objectID;
}
elseif(empty($action->objectID) and $action->extra)
{
echo $action->extra;
}
elseif(empty($action->objectLink))
{
echo $action->objectName;
@@ -73,8 +77,10 @@
echo html::a($action->objectLink, $action->objectName, '', $tab);
}
?>
<?php if($action->objectID):?>
<span class="label label-id"><?php echo $action->objectID;?></span>
<?php endif;?>
<?php endif;?>
</span>
</div>
</li>
+1 -1
View File
@@ -58,7 +58,7 @@
<th class='c-user'> <?php common::printOrderLink('lastRunner', $orderBy, $vars, $lang->testtask->lastRunAccount);?></th>
<th class='c-full-date'><?php common::printOrderLink('lastRunDate', $orderBy, $vars, $lang->testtask->lastRunTime);?></th>
<th class='c-result'> <?php common::printOrderLink('lastRunResult', $orderBy, $vars, $lang->testtask->lastRunResult);?></th>
<th class='c-status'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
<th class='c-status'> <?php echo $lang->statusAB;?></th>
<th class='c-actions-5 text-center'> <?php echo $lang->actions;?></th>
</tr>
</thead>
+19 -2
View File
@@ -76,7 +76,7 @@ class pipelineModel extends model
->add('private',md5(rand(10,113450)))
->add('createdBy', $this->app->user->account)
->add('createdDate', helper::now())
->trim('token')
->trim('url,token,account,password')
->skipSpecial('url,token,account,password')
->get();
if($type == 'gitlab') $pipeline->url = rtrim($pipeline->url, '/');
@@ -105,7 +105,7 @@ class pipelineModel extends model
$pipeline = fixer::input('post')
->add('editedBy', $this->app->user->account)
->add('editedDate', helper::now())
->trim('token')
->trim('url,token,account,password')
->skipSpecial('url,token,account,password')
->get();
@@ -122,4 +122,21 @@ class pipelineModel extends model
return !dao::isError();
}
/**
* Delete one record.
*
* @param string $id the id to be deleted
* @param string $object the action object
* @access public
* @return int
*/
public function delete($id, $object = 'gitlab')
{
$this->dao->update(TABLE_PIPELINE)->set('deleted')->eq(1)->where('id')->eq($id)->exec();
$this->loadModel('action')->create($object, $id, 'deleted', '', ACTIONMODEL::CAN_UNDELETED);
$actionID = $this->dao->lastInsertID();
return $actionID;
}
}
+17 -17
View File
@@ -184,23 +184,23 @@ $lang->project->unlinkExecutionMembers = "The team members you are removing are
$lang->project->tenThousand = '';
$lang->project->unitList['CNY'] = 'Chinese Yuan';
$lang->project->unitList['USD'] = 'United States Dollar';
$lang->project->unitList['HKD'] = 'Hong Kong Dollar';
$lang->project->unitList['NTD'] = 'New Taiwan Dollar';
$lang->project->unitList['EUR'] = 'European Currency Unit';
$lang->project->unitList['DEM'] = 'German Mark';
$lang->project->unitList['CHF'] = 'Swiss Franc';
$lang->project->unitList['FRF'] = 'French Franc';
$lang->project->unitList['GBP'] = 'Great Britain Pound';
$lang->project->unitList['NLG'] = 'NetherLandish Guilder';
$lang->project->unitList['CAD'] = 'Canadian Dollar';
$lang->project->unitList['RUR'] = 'Russian Rouble';
$lang->project->unitList['INR'] = 'Indian Rupee';
$lang->project->unitList['AUD'] = 'Australian Dollar';
$lang->project->unitList['NZD'] = 'New Zealand Dollar';
$lang->project->unitList['THB'] = 'Thailand Baht';
$lang->project->unitList['SGD'] = 'Singapore Dollar';
$lang->project->unitList['CNY'] = 'RMB';
$lang->project->unitList['USD'] = 'USD';
$lang->project->unitList['HKD'] = 'HKD';
$lang->project->unitList['NTD'] = 'NTD';
$lang->project->unitList['EUR'] = 'EUR';
$lang->project->unitList['DEM'] = 'DEM';
$lang->project->unitList['CHF'] = 'CHF';
$lang->project->unitList['FRF'] = 'FRF';
$lang->project->unitList['GBP'] = 'GPR';
$lang->project->unitList['NLG'] = 'NLG';
$lang->project->unitList['CAD'] = 'CAD';
$lang->project->unitList['RUR'] = 'RUB';
$lang->project->unitList['INR'] = 'IDR';
$lang->project->unitList['AUD'] = 'AUD';
$lang->project->unitList['NZD'] = 'NZD';
$lang->project->unitList['THB'] = 'THB';
$lang->project->unitList['SGD'] = 'SGD';
$lang->project->currencySymbol['CNY'] = '¥';
$lang->project->currencySymbol['USD'] = '$';
+8 -8
View File
@@ -83,7 +83,8 @@ class repo extends control
$repoID = $this->repo->saveState(0, $objectID);
if($this->viewType !== 'json') $this->commonAction($repoID, $objectID);
$repoList = $this->repo->getList(0, '', $orderBy);
$repoList = $this->repo->getList(0, '', $orderBy);
$sonarRepoList = $this->loadModel('job')->getSonarqubeByRepo(array_keys($repoList));
/* Pager. */
$this->app->loadClass('pager', $static = true);
@@ -95,11 +96,12 @@ class repo extends control
$this->view->position[] = $this->lang->repo->common;
$this->view->position[] = $this->lang->repo->browse;
$this->view->orderBy = $orderBy;
$this->view->objectID = $objectID;
$this->view->pager = $pager;
$this->view->repoList = empty($repoList) ? $repoList: $repoList[$pageID - 1];;
$this->view->products = $this->loadModel('product')->getPairs();
$this->view->orderBy = $orderBy;
$this->view->objectID = $objectID;
$this->view->pager = $pager;
$this->view->repoList = empty($repoList) ? $repoList: $repoList[$pageID - 1];;
$this->view->products = $this->loadModel('product')->getPairs();
$this->view->sonarRepoList = $sonarRepoList;
$this->display();
}
@@ -403,8 +405,6 @@ class repo extends control
/* Cache infos. */
if($refresh or !$cacheFile or !file_exists($cacheFile) or (time() - filemtime($cacheFile)) / 60 > $this->config->repo->cacheTime)
{
$this->repo->syncCommit($repoID, $branchID);
/* Get cache infos. */
$infos = $this->scm->ls($path, $revision);
+3 -2
View File
@@ -424,7 +424,7 @@ class repoModel extends model
/* Convert to id by url. */
$this->loadModel('gitlab');
$url = strtolower($url);
$url = str_replace('https://', 'http://', strtolower($url));
$matches = array();
foreach($gitlabs as $gitlabID => $gitlab)
{
@@ -435,7 +435,8 @@ class repoModel extends model
$projects = $this->gitlab->apiGetProjects($gitlabID);
foreach($projects as $project)
{
if((!$isSSH and strtolower($project->http_url_to_repo) == $url) or ($isSSH and strtolower($project->ssh_url_to_repo) == $url))
$urlToRepo = str_replace('https://', 'http://', strtolower($project->http_url_to_repo));
if((!$isSSH and $urlToRepo == $url) or ($isSSH and strtolower($project->ssh_url_to_repo) == $url))
{
$matched->gitlab = $gitlabID;
$matched->project = $project->id;
+6 -1
View File
@@ -27,7 +27,7 @@
<th class='c-name text-left'><?php common::printOrderLink('name', $orderBy, $vars, $lang->repo->name); ?></th>
<th class='c-product text-left'><?php common::printOrderLink('product', $orderBy, $vars, $lang->repo->product); ?></th>
<th class='text-left'><?php echo $lang->repo->path; ?></th>
<th class='c-actions-3 w-150px'><?php echo $lang->actions; ?></th>
<th class='c-actions-6'><?php echo $lang->actions; ?></th>
</tr>
</thead>
<tbody>
@@ -59,6 +59,11 @@
common::printIcon('gitlab', 'createWebhook', "repoID=$repo->id", '', 'list', 'change', 'hiddenwin');
common::printIcon('gitlab', 'importIssue', "repo={$repo->id}", '', 'list', 'link');
}
if(isset($sonarRepoList[$repo->id]))
{
$jobID = $sonarRepoList[$repo->id]->id;
common::printIcon('sonarqube', 'execJob', "jobID=$jobID", '', 'list', 'sonarqube', 'hiddenwin');
}
common::printIcon('repo', 'delete', "repoID=$repo->id&objectID=$objectID", '', 'list', 'trash', 'hiddenwin');
?>
</td>
+1
View File
@@ -18,6 +18,7 @@ $lang->report->undefined = 'Undefined';
$lang->report->query = 'Query';
$lang->report->annual = 'Annual Summary';
$lang->report->project = 'Project';
$lang->report->PO = 'PO';
$lang->report->colors[] = 'AFD8F8';
$lang->report->colors[] = 'F6BD0F';
+1
View File
@@ -18,6 +18,7 @@ $lang->report->undefined = '未设定';
$lang->report->query = '查询';
$lang->report->annual = '年度总结';
$lang->report->project = '项目';
$lang->report->PO = 'PO';
$lang->report->colors[] = 'AFD8F8';
$lang->report->colors[] = 'F6BD0F';
+1 -1
View File
@@ -44,7 +44,7 @@
<thead>
<tr>
<th class='c-name'><?php echo $lang->product->name;?></th>
<th class='c-user'><?php echo $lang->product->PO;?></th>
<th class='c-user'><?php echo $lang->report->PO;?></th>
<th><?php echo $lang->productplan->common;?></th>
<th class="c-date"><?php echo $lang->productplan->begin;?></th>
<th class="c-date"><?php echo $lang->productplan->end;?></th>
+8
View File
@@ -0,0 +1,8 @@
<?php
$config->sonarqube = new stdclass();
$config->sonarqube->create = new stdclass();
$config->sonarqube->create->requiredFields = 'name,url,account,password';
$config->sonarqube->edit = new stdclass();
$config->sonarqube->edit->requiredFields = 'name,url,account,password';
+265
View File
@@ -0,0 +1,265 @@
<?php
/**
* The control file of sonarqube module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yanyi Cao <caoyanyi@easycorp.ltd>
* @package sonarqube
* @version $Id: ${FILE_NAME} 5144 2022/1/11 8:55 上午 caoyanyi@easycorp.ltd $
* @link http://www.zentao.net
*/
class sonarqube extends control
{
/**
* The mr constructor.
* @param string $moduleName
* @param string $methodName
*/
public function __construct($moduleName = '', $methodName = '')
{
parent::__construct($moduleName, $methodName);
/* This is essential when changing tab(menu) from gitlab to repo. */
/* Optional: common::setMenuVars('devops', $this->session->repoID); */
$this->loadModel('ci')->setMenu();
}
/**
* Browse sonarqube.
*
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$sonarqubeList = $this->loadModel('pipeline')->getList('sonarqube', $orderBy, $pager);
$this->view->title = $this->lang->sonarqube->common . $this->lang->colon . $this->lang->sonarqube->browse;
$this->view->sonarqubeList = $sonarqubeList;
$this->view->orderBy = $orderBy;
$this->view->pager = $pager;
$this->display();
}
/**
* Ajax get project select.
*
* @param int $sonarqubeID
* @param string $projectKey
* @access public
* @return void
*/
public function ajaxGetProjectList($sonarqubeID, $projectKey = '')
{
$jobPairs = $this->loadModel('job')->getJobBySonarqubeProject($sonarqubeID, array(), true, true);
$existsProject = array_diff(array_keys($jobPairs), array($projectKey));
$projectList = $this->sonarqube->apiGetProjects($sonarqubeID);
$projectPairs = array('' => '');
foreach($projectList as $project)
{
if(!empty($project) and !in_array($project->key, $existsProject)) $projectPairs[$project->key] = $project->name;
}
echo html::select('projectKey', $projectPairs, str_replace('*', '-', $projectKey), "class='form-control chosen'");
}
/**
* create a sonarqube.
*
* @access public
* @return void
*/
public function create()
{
if($_POST)
{
$this->checkToken();
$sonarqubeID = $this->loadModel('pipeline')->create('sonarqube');
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$actionID = $this->loadModel('action')->create('sonarqube', $sonarqubeID, 'created');
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
$this->view->title = $this->lang->sonarqube->common . $this->lang->colon . $this->lang->sonarqube->createServer;
$this->display();
}
/**
* Check post info.
*
* @param int $sonarqubeID
* @access protected
* @return void
*/
protected function checkToken($sonarqubeID = 0)
{
$sonarqube = fixer::input('post')->trim('url,token,account,password')->get();
$this->dao->update('sonarqube')->data($sonarqube)
->batchCheck(empty($sonarqubeID) ? $this->config->sonarqube->create->requiredFields : $this->config->sonarqube->edit->requiredFields, 'notempty')
->batchCheck("url", 'URL');
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
if(strpos($sonarqube->url, 'http') !== 0) return $this->send(array('result' => 'fail', 'message' => array('url' => array($this->lang->sonarqube->hostError))));
/* Check name and url unique. */
$existSonarQube = $this->dao->select('*')->from(TABLE_PIPELINE)
->where("type='sonarqube' and (name='{$sonarqube->name}' or url='{$sonarqube->url}')")
->andWhere('deleted')->eq('0')
->beginIF(!empty($sonarqubeID))->andWhere('id')->ne($sonarqubeID)->fi()
->fetch();
if(isset($existSonarQube->name) and $existSonarQube->name == $sonarqube->name) return $this->send(array('result' => 'fail', 'message' => $this->lang->sonarqube->nameRepeatError));
if(isset($existSonarQube->url) and $existSonarQube->url == $sonarqube->url) return $this->send(array('result' => 'fail', 'message' => $this->lang->sonarqube->urlRepeatError));
$token = base64_encode("{$sonarqube->account}:{$sonarqube->password}");
$result = $this->sonarqube->apiValidate($sonarqube->url, $token);
if(!isset($result->valid) or !$result->valid) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->sonarqube->validError))));
$this->post->set('token', $token);
}
/**
* Edit a sonarqube.
*
* @param int $sonarqubeID
* @access public
* @return void
*/
public function edit($sonarqubeID)
{
$oldSonarQube = $this->loadModel('pipeline')->getByID($sonarqubeID);
if($_POST)
{
$this->checkToken($sonarqubeID);
$this->pipeline->update($sonarqubeID);
$sonarqube = $this->pipeline->getByID($sonarqubeID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action');
$actionID = $this->action->create('sonarqube', $sonarqubeID, 'edited');
$changes = common::createChanges($oldSonarQube, $sonarqube);
$this->action->logHistory($actionID, $changes);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
$this->view->title = $this->lang->sonarqube->common . $this->lang->colon . $this->lang->sonarqube->editServer;
$this->view->sonarqube = $oldSonarQube;
$this->display();
}
/**
* Delete a sonarqube.
*
* @param int $sonarqubeID
* @access public
* @return void
*/
public function delete($sonarqubeID, $confirm = 'no')
{
if($confirm != 'yes') die(js::confirm($this->lang->sonarqube->confirmDelete, inlink('delete', "sonarqubeID=$sonarqubeID&confirm=yes")));
$oldSonarQube = $this->loadModel('pipeline')->getByID($sonarqubeID);
$this->loadModel('action');
$actionID = $this->pipeline->delete($sonarqubeID, 'sonarqube');
$sonarQube = $this->pipeline->getByID($sonarqubeID);
$changes = common::createChanges($oldSonarQube, $sonarQube);
$this->action->logHistory($actionID, $changes);
echo js::reload('parent');
}
/**
* Exec job.
*
* @param int $jobID
* @access public
* @return void
*/
public function execJob($jobID)
{
echo $this->fetch('job', 'exec', "jobID=$jobID");
}
/**
* Browse sonarqube project.
*
* @param int $sonarqubeID
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function browseProject($sonarqubeID, $orderBy = 'name_desc', $recTotal = 0, $recPerPage = 15, $pageID = 1)
{
$this->app->loadClass('pager', $static = true);
$keyword = fixer::input('post')->setDefault('keyword', '')->get('keyword');
$sonarqubeProjectList = $this->sonarqube->apiGetProjects($sonarqubeID, $keyword);
$projectKeyList = array();
foreach($sonarqubeProjectList as $key => $sonarqubeProject)
{
if(!isset($sonarqubeProject->lastAnalysisDate)) $sonarqubeProject->lastAnalysisDate = '';
$projectKeyList[] = $sonarqubeProject->key;
}
/* Data sort. */
list($order, $sort) = explode('_', $orderBy);
$orderList = array();
foreach($sonarqubeProjectList as $sonarqubeProject) $orderList[] = $sonarqubeProject->$order;
array_multisort($orderList, $sort == 'desc' ? SORT_DESC : SORT_ASC, $sonarqubeProjectList);
/* Pager. */
$this->app->loadClass('pager', $static = true);
$recTotal = count($sonarqubeProjectList);
$pager = new pager($recTotal, $recPerPage, $pageID);
$sonarqubeProjectList = array_chunk($sonarqubeProjectList, $pager->recPerPage);
$this->view->sonarqube = $this->loadModel('pipeline')->getByID($sonarqubeID);
$this->view->keyword = urldecode(urldecode($keyword));
$this->view->pager = $pager;
$this->view->title = $this->lang->sonarqube->common . $this->lang->colon . $this->lang->sonarqube->browseProject;
$this->view->sonarqubeID = $sonarqubeID;
$this->view->sonarqubeProjectList = (empty($sonarqubeProjectList) or empty($sonarqubeProjectList[$pageID - 1])) ? array() : $sonarqubeProjectList[$pageID - 1];
$this->view->projectJobPairs = $this->loadModel('job')->getJobBySonarqubeProject($sonarqubeID, $projectKeyList);
$this->view->orderBy = $orderBy;
$this->display();
}
/**
* Delete project.
*
* @param int $sonarqubeID
* @param string $projectKey
* @param string $confirm
* @access public
* @return void
*/
public function deleteProject($sonarqubeID, $projectKey, $confirm = 'no')
{
if($confirm != 'yes') die(js::confirm($this->lang->sonarqube->confirmDeleteProject, inlink('deleteProject', "sonarqubeID=$sonarqubeID&projectKey=$projectKey&confirm=yes")));
/* Fix error when request type is PATH_INFO and the tag name contains '-'.*/
$projectKey = str_replace('*', '-', $projectKey);
$reponse = $this->sonarqube->apiDeleteProject($sonarqubeID, $projectKey);
if(isset($reponse->errors)) return print(js::alert($reponse->errors[0]->msg));
$this->loadModel('action')->create('sonarqubeproject', 0, 'deleted', '', $projectKey);
return print(js::reload('parent'));
}
}
+2
View File
@@ -0,0 +1,2 @@
.text-c-counts > span {margin-left: 5px;}
#mainMenu .pull-left {margin-right: 15px;}
+2
View File
@@ -0,0 +1,2 @@
.table-form .c-name {width: 130px;}
.table-form .c-input {width: 650px;}
+2
View File
@@ -0,0 +1,2 @@
.table-form .c-name {width: 130px;}
.table-form .c-input {width: 650px;}
+22
View File
@@ -0,0 +1,22 @@
$(document).ready(function()
{
$('#projectSearch').click(function()
{
triggerSearch();
});
$('#keyword').keypress(function(event)
{
if(event.which == 13) triggerSearch();
})
});
/**
* Trigger filtering function.
*
* @access public
* @return void
*/
function triggerSearch()
{
$("#sonarqubeProjectForm").submit();
}
+43
View File
@@ -0,0 +1,43 @@
<?php
$lang->sonarqube = new stdclass;
$lang->sonarqube->common = 'SonarQube';
$lang->sonarqube->browse = 'SonarQube Browse';
$lang->sonarqube->search = 'Search';
$lang->sonarqube->create = 'Create SonarQube';
$lang->sonarqube->edit = 'Edit SonarQube';
$lang->sonarqube->delete = 'Delete SonarQube';
$lang->sonarqube->serverFail = 'Connect to SonarQube server failed, please check the SonarQube server.';
$lang->sonarqube->browseProject = "SonarQube Project List";
$lang->sonarqube->createProject = "Create SonarQube Project";
$lang->sonarqube->deleteProject = "Delete SonarQube Project";
$lang->sonarqube->placeholderSearch = 'Project name';
$lang->sonarqube->execJob = "Exec SonarQube Job";
$lang->sonarqube->desc = 'Description';
$lang->sonarqube->id = 'ID';
$lang->sonarqube->name = "Server Name";
$lang->sonarqube->url = 'Server Address';
$lang->sonarqube->account = 'Username';
$lang->sonarqube->password = 'Password';
$lang->sonarqube->token = 'Token';
$lang->sonarqube->defaultProject = 'Default Project';
$lang->sonarqube->private = 'MD5 Verify';
$lang->sonarqube->createServer = 'Create SonarQube Server';
$lang->sonarqube->editServer = 'Edit SonarQube Server';
$lang->sonarqube->createSuccess = 'Create success';
$lang->sonarqube->placeholder = new stdclass;
$lang->sonarqube->placeholder->name = '';
$lang->sonarqube->placeholder->url = "Please fill in the access address of the SonarQube Server homepage, as: https://sonarqube.zentao.net.";
$lang->sonarqube->nameRepeatError = "Server name already exists!";
$lang->sonarqube->urlRepeatError = 'Server address already exists!';
$lang->sonarqube->validError = 'SonarQube user authority authentication failed!';
$lang->sonarqube->hostError = "Invalid SonarQube service address.";
$lang->sonarqube->confirmDelete = 'Do you want to delete this SonarQube server?';
$lang->sonarqube->confirmDeleteProject = 'Do you want to delete this SonarQube project?';
$lang->sonarqube->projectKey = 'Project Key';
$lang->sonarqube->projectName = 'Project Name';
$lang->sonarqube->projectlastAnalysis = 'Last analysis time';
+43
View File
@@ -0,0 +1,43 @@
<?php
$lang->sonarqube = new stdclass;
$lang->sonarqube->common = 'SonarQube';
$lang->sonarqube->browse = '浏览SonarQube';
$lang->sonarqube->search = '搜索';
$lang->sonarqube->create = '添加SonarQube';
$lang->sonarqube->edit = '编辑SonarQube';
$lang->sonarqube->delete = '删除SonarQube';
$lang->sonarqube->serverFail = '连接SonarQube服务器异常,请检查SonarQube服务器。';
$lang->sonarqube->browseProject = "SonarQube项目列表";
$lang->sonarqube->createProject = "创建SonarQube项目";
$lang->sonarqube->deleteProject = "删除SonarQube项目";
$lang->sonarqube->placeholderSearch = '请输入项目名称';
$lang->sonarqube->execJob = "执行SonarQube任务";
$lang->sonarqube->id = 'ID';
$lang->sonarqube->name = "服务器名称";
$lang->sonarqube->url = '服务器地址';
$lang->sonarqube->account = '用户名';
$lang->sonarqube->password = '密码';
$lang->sonarqube->token = 'Token';
$lang->sonarqube->defaultProject = '默认项目';
$lang->sonarqube->private = 'MD5验证';
$lang->sonarqube->createServer = '添加SonarQube服务器';
$lang->sonarqube->editServer = '修改SonarQube服务器';
$lang->sonarqube->desc = '描述';
$lang->sonarqube->createSuccess = "创建成功";
$lang->sonarqube->placeholder = new stdclass;
$lang->sonarqube->placeholder->name = '';
$lang->sonarqube->placeholder->url = "请填写SonarQube Server首页的访问地址,如:https://sonarqube.zentao.net。";
$lang->sonarqube->nameRepeatError = "服务器名称已存在!";
$lang->sonarqube->urlRepeatError = "服务器地址已存在!";
$lang->sonarqube->validError = "SonarQube 用户权限认证失败!";
$lang->sonarqube->hostError = "无效的SonarQube服务地址。";
$lang->sonarqube->confirmDelete = '确认删除该SonarQube吗?';
$lang->sonarqube->confirmDeleteProject = '确认删除该SonarQube项目吗?';
$lang->sonarqube->projectKey = '项目标识';
$lang->sonarqube->projectName = '项目名称';
$lang->sonarqube->projectlastAnalysis = '最后执行时间';
+92
View File
@@ -0,0 +1,92 @@
<?php
/**
* The model file of sonarqube module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yanyi Cao <caoyanyi@easycorp.ltd>
* @package sonarqube
* @version $Id: $
* @link http://www.zentao.net
*/
class sonarqubeModel extends model
{
/**
* Get sonarqube api base url and header by id.
*
* @param int $sonarqubeID
* @access public
* @return array
*/
public function getApiBase($sonarqubeID)
{
$sonarqube = $this->loadModel('pipeline')->getByID($sonarqubeID);
if(!$sonarqube) return array('', array());
$url = rtrim($sonarqube->url, '/') . '/api/%s';
$header[] = 'Authorization: Basic ' . $sonarqube->token;
return array($url, $header);
}
/**
* check sonarqube valid
*
* @param string $host
* @param string $token
* @access public
* @return array
*/
public function apiValidate($host, $token)
{
$url = rtrim($host, '/') . "/api/authentication/validate";
$header = 'Authorization: Basic ' . $token;
return json_decode(commonModel::http($url, null, array(), $header));
}
/**
* Get projects of one sonarqube.
*
* @param int $sonarqubeID
* @param string $keyword
* @access public
* @return array
*/
public function apiGetProjects($sonarqubeID, $keyword = '')
{
list($apiRoot, $header) = $this->getApiBase($sonarqubeID);
if(!$apiRoot) return array();
$url = sprintf($apiRoot, "projects/search");
$allResults = array();
for($page = 1; true; $page++)
{
$result = json_decode(commonModel::http($url. "?p={$page}&ps=500" . ($keyword ? "&q={$keyword}" : ''), null, array(), $header));
if(!isset($result->components)) break;
if(!empty($result->components)) $allResults = array_merge($allResults, $result->components);
if(count($result->components) < 500) break;
}
return $allResults;
}
/**
* Delete sonarqube project by api.
*
* @param int $sonarqubeID
* @param int $projectKey
* @access public
* @return bool|object
*/
public function apiDeleteProject($sonarqubeID, $projectKey)
{
list($apiRoot, $header) = $this->getApiBase($sonarqubeID);
if(!$apiRoot) return false;
$url = sprintf($apiRoot, "projects/delete?project=$projectKey");
$result = json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'POST'), $header));
return $result;
}
}
+64
View File
@@ -0,0 +1,64 @@
<?php
/**
* The browse view file of sonarqube module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yanyi Cao <caoyanyi@easycorp.ltd>
* @package sonarqube
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-right">
<?php if(common::hasPriv('sonarqube', 'create')) common::printLink('sonarqube', 'create', "", "<i class='icon icon-plus'></i> " . $lang->sonarqube->create, '', "class='btn btn-primary'");?>
</div>
</div>
<?php if(empty($sonarqubeList)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->noData;?></span>
<?php if(common::hasPriv('sonarqube', 'create')):?>
<?php echo html::a($this->createLink('sonarqube', 'create'), "<i class='icon icon-plus'></i> " . $lang->sonarqube->create, '', "class='btn btn-info'");?>
<?php endif;?>
</p>
</div>
<?php else:?>
<div id='mainContent' class='main-row'>
<form class='main-table' id='ajaxForm' method='post'>
<table id='sonarqubeList' class='table has-sort-head table-fixed'>
<thead>
<tr>
<?php $vars = "orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?>
<th class='c-id text-center'><?php common::printOrderLink('id', $orderBy, $vars, $lang->sonarqube->id);?></th>
<th class='c-name text-left'><?php common::printOrderLink('name', $orderBy, $vars, $lang->sonarqube->name);?></th>
<th class='text-left'><?php common::printOrderLink('url', $orderBy, $vars, $lang->sonarqube->url);?></th>
<th class='c-actions-3'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach ($sonarqubeList as $id => $sonarqube): ?>
<tr class='text'>
<td class='text-center'><?php echo $id;?></td>
<td class='text-c-name' title='<?php echo $sonarqube->name;?>'><?php echo $sonarqube->name;?></td>
<td class='text' title='<?php echo $sonarqube->url;?>'><?php echo $sonarqube->url;?></td>
<td class='c-actions text-left'>
<?php
common::printLink('sonarqube', 'browseProject', "sonarqubeID=$id", "<i class='icon icon-list-box'></i> ", '',"title='{$lang->sonarqube->browseProject}' class='btn btn-primary'");
common::printLink('sonarqube', 'edit', "sonarqubeID=$id", "<i class='icon icon-edit'></i> ", '',"title='{$lang->sonarqube->edit}' class='btn btn-primary'");
if(common::hasPriv('sonarqube', 'delete')) echo html::a($this->createLink('sonarqube', 'delete', "sonarqubeID=$id"), '<i class="icon-trash"></i>', 'hiddenwin', "title='{$lang->sonarqube->delete}' class='btn'");
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php if($sonarqubeList):?>
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
<?php endif;?>
</form>
</div>
<?php endif;?>
<?php include '../../common/view/footer.html.php';?>
@@ -0,0 +1,83 @@
<?php
/**
* The browse view file of sonarqube module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Gang Zeng <liugang@cnezsoft.com>
* @package sonarqube
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id="mainMenu" class="clearfix">
<div class='pull-left'>
<?php echo html::a($this->createLink('sonarqube', 'browse'), "<i class='icon icon-back icon-sm'></i> " . $lang->goback, '', "class='btn btn-secondary'");?>
</div>
<div id="sidebarHeader">
<div class="title"><?php echo $this->lang->sonarqube->common . ':' . $sonarqube->name; ?></div>
</div>
<div class="btn-toolbar pull-left">
<div>
<form id='sonarqubeProjectForm' method='post'>
<?php echo html::input('keyword', $keyword, "class='form-control' placeholder='{$lang->sonarqube->placeholderSearch}' style='display: inline-block;width:auto;margin:0 10px'");?>
<a id="projectSearch" class="btn btn-primary"><?php echo $lang->sonarqube->search?></a>
</form>
</div>
</div>
<div class="btn-toolbar pull-right hide">
<?php if(common::hasPriv('sonarqube', 'createProject')) common::printLink('sonarqube', 'createProject', "sonarqubeID=$sonarqubeID", "<i class='icon icon-plus'></i> " . $lang->sonarqube->createProject, '', "class='btn btn-primary'");?>
</div>
</div>
<?php if(empty($sonarqubeProjectList)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->noData;?></span>
<?php if(empty($keyword) and common::hasPriv('sonarqube', 'createProject')):?>
<?php //echo html::a($this->createLink('sonarqube', 'createProject', "sonarqubeID=$sonarqubeID"), "<i class='icon icon-plus'></i> " . $lang->sonarqube->createProject, '', "class='btn btn-info'");?>
<?php endif;?>
</p>
</div>
<?php else:?>
<div id='mainContent' class='main-row'>
<form class='main-table' id='ajaxForm' method='post'>
<table id='sonarqubeProjectList' class='table has-sort-head table-fixed'>
<?php $vars = "sonarqubeID={$sonarqubeID}&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?>
<thead>
<tr>
<th class='c-key text-left'><?php common::printOrderLink('key', $orderBy, $vars, $lang->sonarqube->projectKey);?></th>
<th class='c-name text-left'><?php common::printOrderLink('name', $orderBy, $vars, $lang->sonarqube->projectName);?></th>
<th class='text-left'><?php common::printOrderLink('lastAnalysisDate', $orderBy, $vars, $lang->sonarqube->projectlastAnalysis);?></th>
<th class='c-actions-2'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach ($sonarqubeProjectList as $id => $sonarqubeProject): ?>
<tr class='text'>
<td class='text' title='<?php echo $sonarqubeProject->key;?>'><?php echo $sonarqubeProject->key;?></td>
<td class='text-c-name' title='<?php echo $sonarqubeProject->name;?>'><?php echo $sonarqubeProject->name;?></td>
<td class='text' title='<?php echo substr($sonarqubeProject->lastAnalysisDate, 0, 10);?>'><?php echo substr($sonarqubeProject->lastAnalysisDate, 0, 10);?></td>
<td class='c-actions text-left'>
<?php
/* Fix error when request type is PATH_INFO and the project key contains '-'.*/
$projectKey = str_replace('-', '*', $sonarqubeProject->key);
common::printLink('sonarqube', 'deleteProject', "sonarqubeID=$sonarqubeID&project=$projectKey", "<i class='icon icon-trash'></i> ", 'hiddenwin', "title='{$lang->sonarqube->deleteProject}' class='btn btn-primary'");
if(isset($projectJobPairs[$sonarqubeProject->key]))
{
$jobID = $projectJobPairs[$sonarqubeProject->key];
common::printIcon('sonarqube', 'execJob', "jobID=$jobID", '', 'list', 'sonarqube', 'hiddenwin');
}
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php if($sonarqubeProjectList):?>
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
<?php endif;?>
</form>
</div>
<?php endif;?>
<?php include '../../common/view/footer.html.php';?>
+51
View File
@@ -0,0 +1,51 @@
<?php
/**
* The create view file of sonarqube module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Gang Zeng <zenggang@cnezsoft.com>
* @package sonarqube
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-row'>
<div class='main-col main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->sonarqube->createServer;?></h2>
</div>
<form id='sonarqubeForm' method='post' class='form-ajax'>
<table class='table table-form'>
<tr>
<th class='c-name'><?php echo $lang->sonarqube->name;?></th>
<td class='c-input'><?php echo html::input('name', '', "class='form-control' placeholder='{$lang->sonarqube->placeholder->name}'");?></td>
<td class="tips-git"></td>
</tr>
<tr>
<th><?php echo $lang->sonarqube->url;?></th>
<td><?php echo html::input('url', '', "class='form-control' placeholder='{$lang->sonarqube->placeholder->url}'");?></td>
</tr>
<tr>
<th><?php echo $lang->sonarqube->account;?></th>
<td><?php echo html::input('account', '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->sonarqube->password;?></th>
<td><?php echo html::password('password', '', "class='form-control'");?></td>
</tr>
<tr>
<th></th>
<td class='text-center form-actions'>
<?php echo html::submitButton();?>
<?php if(!isonlybody()) echo html::a(inlink('browse', ""), $lang->goback, '', 'class="btn btn-wide"');?>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+51
View File
@@ -0,0 +1,51 @@
<?php
/**
* The edit view file of sonarqube module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Gang Zeng<zenggang@cnezsoft.com>
* @package sonarqube
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-row'>
<div class='main-col main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->sonarqube->editServer;?></h2>
</div>
<form id='sonarqubeForm' method='post' class='form-ajax'>
<table class='table table-form'>
<tr>
<th class="c-name"><?php echo $lang->sonarqube->name;?></th>
<td class="c-input"><?php echo html::input('name', isset($sonarqube->name) ? $sonarqube->name : '', "class='form-control' placeholder='{$lang->sonarqube->placeholder->name}'");?></td>
<td class="tips-git"></td>
</tr>
<tr>
<th><?php echo $lang->sonarqube->url;?></th>
<td><?php echo html::input('url', isset($sonarqube->url) ? $sonarqube->url : '', "class='form-control' placeholder='{$lang->sonarqube->placeholder->url}'");?></td>
</tr>
<tr>
<th><?php echo $lang->sonarqube->account;?></th>
<td><?php echo html::input('account', isset($sonarqube->account) ? $sonarqube->account : '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->sonarqube->password;?></th>
<td><?php echo html::password('password', isset($sonarqube->password) ? $sonarqube->password : '', "class='form-control'");?></td>
</tr>
<tr>
<th></th>
<td class='text-center form-actions'>
<?php echo html::submitButton();?>
<?php if(!isonlybody()) echo html::a(inlink('browse', ""), $lang->goback, '', 'class="btn btn-wide"');?>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+103 -17
View File
@@ -157,7 +157,21 @@ class story extends control
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $storyID));
/* If link from no head then reload. */
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, 0)"));
}
else
{
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
}
if($this->post->newStory)
{
@@ -398,13 +412,13 @@ class story extends control
if($storyID)
{
$story = $this->story->getById($storyID);
if($story->status != 'active' or $story->stage != 'wait' or $story->parent > 0) die(js::alert($this->lang->story->errorNotSubdivide) . js::locate('back'));
if($story->status != 'active' or $story->stage != 'wait' or $story->parent > 0) return print(js::alert($this->lang->story->errorNotSubdivide) . js::locate('back'));
}
if(!empty($_POST))
{
$mails = $this->story->batchCreate($productID, $branch, $type);
if(dao::isError()) die(js::error(dao::getError()));
if(dao::isError()) return print(js::error(dao::getError()));
$stories = array();
foreach($mails as $mail) $stories[] = $mail->storyID;
@@ -426,11 +440,25 @@ class story extends control
}
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $stories));
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
if($storyID)
{
die(js::locate(inlink('view', "storyID=$storyID"), 'parent'));
return print(js::locate(inlink('view', "storyID=$storyID"), 'parent'));
}
elseif($executionID)
{
@@ -438,13 +466,13 @@ class story extends control
$moduleName = $execution->type == 'project' ? 'projectstory' : 'execution';
$param = $execution->type == 'project' ? "projectID=$executionID&productID=$productID" : "executionID=$executionID&orderBy=id_desc&browseType=unclosed";
$link = $this->createLink($moduleName, 'story', $param);
die(js::locate($link, 'parent'));
return print(js::locate($link, 'parent'));
}
else
{
setcookie('storyModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
$locateLink = $this->session->storyList ? $this->session->storyList : $this->createLink('product', 'browse', "productID=$productID&branch=$branch&browseType=unclosed&queryID=0&type=$type");
die(js::locate($locateLink, 'parent'));
return print(js::locate($locateLink, 'parent'));
}
}
@@ -921,9 +949,24 @@ class story extends control
$module = $this->app->tab == 'project' ? 'projectstory' : 'story';
if(isonlybody()) die(js::reload('parent.parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::reload('parent.parent'));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success'));
die(js::locate($this->createLink($module, 'view', "storyID=$storyID"), 'parent'));
return print(js::locate($this->createLink($module, 'view', "storyID=$storyID"), 'parent'));
}
$this->commonAction($storyID);
@@ -974,8 +1017,22 @@ class story extends control
$this->executeHooks($storyID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent'));
}
$this->commonAction($storyID);
@@ -1243,7 +1300,7 @@ class story extends control
if(!empty($_POST))
{
$changes = $this->story->close($storyID);
if(dao::isError()) die(js::error(dao::getError()));
if(dao::isError()) return print(js::error(dao::getError()));
if($changes)
{
@@ -1253,14 +1310,29 @@ class story extends control
$this->executeHooks($storyID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
die(array('status' => 'success', 'data' => $storyID));
return print(array('status' => 'success', 'data' => $storyID));
}
else
{
die(js::locate(inlink('view', "storyID=$storyID"), 'parent'));
return print(js::locate(inlink('view', "storyID=$storyID"), 'parent'));
}
}
@@ -1586,8 +1658,22 @@ class story extends control
$this->executeHooks($storyID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this', 'function(){parent.parent.$(\'[data-ride="searchList"]\').searchList();}'));
die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this', 'function(){parent.parent.$(\'[data-ride="searchList"]\').searchList();}'));
}
}
return print(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent'));
}
/* Get story and product. */
+6 -1
View File
@@ -2142,6 +2142,12 @@ class storyModel extends model
$releases = $this->dao->select('*')->from(TABLE_RELEASE)->where("CONCAT(',', stories, ',')")->like("%,$storyID,%")->andWhere('deleted')->eq(0)->fetchPairs('branch', 'branch');
foreach($releases as $branch) $stages[$branch] = 'released';
$currentStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch();
foreach($executions as $executionID => $branch)
{
$this->kanban->updateLane($executionID, 'story', $storyID);
}
if(empty($stages)) return;
if($hasBranch)
{
@@ -2173,7 +2179,6 @@ class storyModel extends model
$this->dao->update(TABLE_STORY)->set('stage')->eq(current($stages))->where('id')->eq($storyID)->exec();
}
$currentStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch();
if($story->stage != $currentStory->stage)
{
foreach($executions as $executionID => $branch)
+220 -17
View File
@@ -146,7 +146,20 @@ class task extends control
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $taskID));
/* If link from no head then reload. */
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
if(isonlybody())
{
if($execution->type == 'kanban')
{
$kanbanData = $this->kanban->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, 0)"));
}
else
{
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
}
/* Locate the browser. */
if($this->app->getViewType() == 'xhtml')
@@ -309,7 +322,20 @@ class task extends control
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $taskIDList));
/* If link from no head then reload. */
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
if(isonlybody())
{
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, 0)"));
}
else
{
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
}
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $taskLink));
}
@@ -424,7 +450,22 @@ class task extends control
}
}
if(isonlybody()) die(js::reload('parent.parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::reload('parent.parent'));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
return $this->send(array('status' => 'success', 'data' => $taskID));
@@ -622,8 +663,23 @@ class task extends control
$this->executeHooks($taskID);
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success'));
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
$members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted');
@@ -809,6 +865,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
$task = $this->task->getById($taskID);
if(!empty($_POST))
@@ -848,7 +907,23 @@ class task extends control
}
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success'));
if(isonlybody()) die(js::closeModal('parent.parent', 'this', "function(){parent.parent.location.reload();}"));
if(isonlybody())
{
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this', "function(){parent.parent.location.reload();}"));
}
}
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
@@ -895,8 +970,22 @@ class task extends control
}
}
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
$this->session->set('estimateList', $this->app->getURI(true), 'execution');
@@ -976,6 +1065,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(!empty($_POST))
{
$this->loadModel('action');
@@ -1010,7 +1102,25 @@ class task extends control
}
}
}
if(isonlybody()) die(js::closeModal('parent.parent', 'this', "function(){parent.parent.location.reload();}"));
if(isonlybody())
{
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, 'all', 'id_desc', $regionID);
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this', "function(){parent.parent.location.reload();}"));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
return $this->send(array('result' => 'success', 'data' => $taskID));
@@ -1063,6 +1173,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(!empty($_POST))
{
$this->loadModel('action');
@@ -1077,8 +1190,25 @@ class task extends control
$this->executeHooks($taskID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
$this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->task->pause;
@@ -1116,8 +1246,23 @@ class task extends control
$this->executeHooks($taskID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
$this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->task->restart;
@@ -1141,6 +1286,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(!empty($_POST))
{
$this->loadModel('action');
@@ -1156,7 +1304,24 @@ class task extends control
$this->executeHooks($taskID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this', "function(){parent.parent.location.reload();}"));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this', "function(){parent.parent.location.reload();}"));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
return $this->send(array('status' => 'success', 'data' => $taskID));
@@ -1273,6 +1438,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(!empty($_POST))
{
$this->loadModel('action');
@@ -1287,7 +1455,23 @@ class task extends control
$this->executeHooks($taskID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
@@ -1310,6 +1494,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(!empty($_POST))
{
$this->loadModel('action');
@@ -1324,8 +1511,24 @@ class task extends control
$this->executeHooks($taskID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
if(!empty($this->view->task->team))
+1 -1
View File
@@ -37,7 +37,7 @@
<?php endif;?>
</h2>
</div>
<form method='post' target='hiddenwin' onsubmit='return checkLeft();'>
<form method='post' target='hiddenwin' <?php if($app->rawMethod == 'start') echo "onsubmit='return checkLeft();'"?>>
<table class='table table-form'>
<tr>
<th class='w-90px'><?php echo $lang->task->assignedTo;?></th>
+13 -2
View File
@@ -517,8 +517,19 @@ class testcase extends control
if(!empty($_POST))
{
$caseIDList = $this->testcase->batchCreate($productID, $branch, $storyID);
if(dao::isError()) die(js::error(dao::getError()));
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
if(dao::isError()) return print(js::error(dao::getError()));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
return print(js::closeModal('parent.parent', ''));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $caseIDList));
+1 -1
View File
@@ -58,7 +58,7 @@ $lang->testreport->bugOpenedByGroups = 'Nach Ersteller';
$lang->testreport->bugResolvedByGroups = 'Nach Löser';
$lang->testreport->bugResolutionGroups = 'Nach Lösung';
$lang->testreport->bugModuleGroups = 'Nach Modul';
$lang->testreport->bugStageGroups = 'Bug importance stage distribution';
$lang->testreport->bugStageGroups = 'Bug Priority Distribution';
$lang->testreport->bugHandleGroups = 'Distribution of daily bug processing';
$lang->testreport->legacyBugs = 'Legacy Bugs';
$lang->testreport->bugConfirmedRate = 'Bestätigte Bugs Rate (Lösung ist gelöst oder verschoben / Status ist gelöst oder Geschlossen)';
+1 -1
View File
@@ -59,7 +59,7 @@ $lang->testreport->bugOpenedByGroups = 'Bug ReportedBy Distribution';
$lang->testreport->bugResolvedByGroups = 'Bug ResolvedBy Distribution';
$lang->testreport->bugResolutionGroups = 'Bug Resolution Distribution';
$lang->testreport->bugModuleGroups = 'Bug Module Distribution';
$lang->testreport->bugStageGroups = 'Bug importance stage distribution';
$lang->testreport->bugStageGroups = 'Bug Priority Distribution';
$lang->testreport->bugHandleGroups = 'Distribution of daily bug processing';
$lang->testreport->legacyBugs = 'Left Bugs';
$lang->testreport->bugConfirmedRate = 'Confirmed-Bug Rate (Resolution is fixed or postponed / status is resolved or closed)';
+1 -1
View File
@@ -58,7 +58,7 @@ $lang->testreport->bugOpenedByGroups = 'Distribution Bug Signalé par';
$lang->testreport->bugResolvedByGroups = 'Distribution Bug Résolu par';
$lang->testreport->bugResolutionGroups = 'Distribution Bug Résolution';
$lang->testreport->bugModuleGroups = 'Distribution Bug Module';
$lang->testreport->bugStageGroups = 'Bug importance stage distribution';
$lang->testreport->bugStageGroups = 'Bug Priority Distribution';
$lang->testreport->bugHandleGroups = 'Distribution of daily bug processing';
$lang->testreport->legacyBugs = 'Bugs Restants';
$lang->testreport->bugConfirmedRate = 'Taux de Bugs confirmés (Résolution est corrigée ou reportée / statut est résolu ou fermé)';
+1 -1
View File
@@ -58,7 +58,7 @@ $lang->testreport->bugOpenedByGroups = 'Phân chia người báo cáo Bug';
$lang->testreport->bugResolvedByGroups = 'Phân chia người giải quyết Bug';
$lang->testreport->bugResolutionGroups = 'Phân chia giải pháp Bug';
$lang->testreport->bugModuleGroups = 'Phân chia Module Bug';
$lang->testreport->bugStageGroups = 'Bug importance stage distribution';
$lang->testreport->bugStageGroups = 'Bug Priority Distribution';
$lang->testreport->bugHandleGroups = 'Distribution of daily bug processing';
$lang->testreport->legacyBugs = 'Bug còn lại';
$lang->testreport->bugConfirmedRate = 'Đánh giá Bug đã xác nhận (Nghị quyết đã ban hành hoặc tạm hoãn / tình trạng được giải quyết hoặc đóng)';
+1 -1
View File
@@ -179,7 +179,7 @@ $lang->testtask->report->charts['bugOpenedByGroups'] = 'Bugersteller Bericht'
$lang->testtask->report->charts['bugResolvedByGroups'] = 'Gelöst von Bericht';
$lang->testtask->report->charts['bugResolutionGroups'] = 'Lösungsbersicht';
$lang->testtask->report->charts['bugModuleGroups'] = 'Bug Modul Bericht';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug importance stage distribution';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug Priority Distribution';
$lang->testtask->report->charts['bugHandleGroups'] = 'Distribution of daily bug processing';
$lang->testtask->report->options = new stdclass();
+1 -1
View File
@@ -189,7 +189,7 @@ $lang->testtask->report->charts['bugOpenedByGroups'] = 'Bug ReportedBy Distri
$lang->testtask->report->charts['bugResolvedByGroups'] = 'Bug ResolvedBy Distribution';
$lang->testtask->report->charts['bugResolutionGroups'] = 'Bug Resolution Distribution';
$lang->testtask->report->charts['bugModuleGroups'] = 'Bug Module Distribution';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug importance stage distribution';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug Priority Distribution';
$lang->testtask->report->charts['bugHandleGroups'] = 'Distribution of daily bug processing';
$lang->testtask->report->options = new stdclass();
+1 -1
View File
@@ -179,7 +179,7 @@ $lang->testtask->report->charts['bugOpenedByGroups'] = 'Distribution signalem
$lang->testtask->report->charts['bugResolvedByGroups'] = 'Distribution Résolus par';
$lang->testtask->report->charts['bugResolutionGroups'] = 'Distribution Résolution';
$lang->testtask->report->charts['bugModuleGroups'] = 'Distribution Bug Module';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug importance stage distribution';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug Priority Distribution';
$lang->testtask->report->charts['bugHandleGroups'] = 'Distribution of daily bug processing';
$lang->testtask->report->options = new stdclass();
+1 -1
View File
@@ -179,7 +179,7 @@ $lang->testtask->report->charts['bugOpenedByGroups'] = 'Phân chia người b
$lang->testtask->report->charts['bugResolvedByGroups'] = 'Phân chia người giải quyết Bug';
$lang->testtask->report->charts['bugResolutionGroups'] = 'Phân chia giải pháp Bug';
$lang->testtask->report->charts['bugModuleGroups'] = 'Phân chia Module Bug';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug importance stage distribution';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug Priority Distribution';
$lang->testtask->report->charts['bugHandleGroups'] = 'Distribution of daily bug processing';
$lang->testtask->report->options = new stdclass();
+9 -9
View File
@@ -3,24 +3,24 @@ author: Zeng gang
version: "1.0"
fields:
- field: id
range: 1
range: 1-2
- field: type
range: gitlab
range: gitlab,sonarqube
- field: name
range: gitlab服务器
range: gitlab服务器,sonarqube服务器
- field: url
range: [http://192.168.1.161:51080]
range: [http://192.168.1.161:51080],[http://192.168.1.161:59001]
- field: account
range: []
range: [],[admin]
- field: password
range: []
range: [],[UDJzc3cwcmQ=]
- field: token
range: x88fZokrp5hShia2jyBN
range: x88fZokrp5hShia2jyBN,YWRtaW46UDJzc3cwcmQ=
- field: private
range: 08bcc98f75d7d40053dc80722bdc117b
range: 08bcc98f75d7d40053dc80722bdc117b,228b25587479f2fc7570428e8bcbabdc
- field: createdBy
range: admin
- field: createdDate
range: [2021-12-09 11:23:35]
range: [2021-12-09 11:23:35],[2022-01-12 08:47:37]
- field: deleted
range: 0
+1 -1
View File
@@ -20,6 +20,6 @@ $builder->team = array('rows' => 400, 'extends' => array('team'));
$builder->build = array('rows' => 8, 'extends' => array('build'));
$builder->release = array('rows' => 8, 'extends' => array('release'));
$builder->pipeline = array('rows' => 1, 'extends' => array('pipeline'));
$builder->pipeline = array('rows' => 2, 'extends' => array('pipeline'));
$builder->repo = array('rows' => 1, 'extends' => array('repo'));
$builder->mr = array('rows' => 1, 'extends' => array('mr'));
+5 -2
View File
@@ -11,7 +11,7 @@ pid=1
使用空的gitlabID、projectID、分支对象创建GitLab分支 >> return false
使用空的gitlabID、projectID,正确的分支对象创建GitLab分支 >> return null
使用正确的gitlabID、分支信息,错误的projectID创建分支 >> 404 Project Not Found
使用正确的gitlabID,projectID,分支对象创建GitLab分支 >> test_branch17
使用正确的gitlabID,projectID,分支对象创建GitLab分支 >> 1
使用重复的分支信息创建分支 >> Branch already exists
*/
@@ -36,5 +36,8 @@ $gitlabID = 1;
r($gitlab->apiCreateBranch($gitlabID, $projectID, $branch)) && p('message') && e('404 Project Not Found'); //使用正确的gitlabID、分支信息,错误的projectID创建分支
$projectID = 1555;
r($gitlab->apiCreateBranch($gitlabID, $projectID, $branch)) && p('name') && e($branch->branch); //通过gitlabID,projectID,分支对象正确创建GitLab分支
$result = $gitlab->apiCreateBranch($gitlabID, $projectID, $branch);
if(!empty($result->name) and $result->name == $branch->branch) $result = true;
if(!empty($result->message) and $result->message == 'Branch already exists') $result = true;
r($result) && p() && e(1); //通过gitlabID,projectID,分支对象正确创建GitLab分支
r($gitlab->apiCreateBranch($gitlabID, $projectID, $branch)) && p('message') && e('Branch already exists'); //使用重复的分支信息创建分支
@@ -40,6 +40,7 @@ if($result === false) $result = 'return false';
r($result) && p() && e('return false'); //使用正确的gitlabID、保护分支信息,错误的projectID创建保护分支
$projectID = 966;
$gitlab->apiDeleteBranchPriv($gitlabID, $projectID, $branch->name);
r($gitlab->apiCreateBranchPriv($gitlabID, $projectID, $branch)) && p('name') && e($branch->name); //通过gitlabID,projectID,保护分支对象正确创建GitLab保护分支
r($gitlab->apiCreateBranchPriv($gitlabID, $projectID, $branch)) && p('message') && e("Protected branch 'master' already exists"); //使用重复的保护分支信息创建保护分支
+3 -2
View File
@@ -35,7 +35,8 @@ $tag = 'masters';
$result = $gitlab->apiDeleteTagPriv($gitlabID, $projectID, $tag);
r($result) && p('message') && e('404 Not found'); //使用错误的保护标签信息删除保护标签
$tag = '2021/12/30';
$result = $gitlab->apiDeleteTagPriv($gitlabID, $projectID, $tag);
$projectID = 1555;
$tag = 'test_tag1';
$result = $gitlab->apiDeleteTagPriv($gitlabID, $projectID, $tag);
if(!$result or substr($result->message, 0, 2) == '20') $result = 'return true';
r($result) && p() && e('return true'); //通过gitlabID,projectID,标签名称正确删除保护标签
+7 -7
View File
@@ -8,11 +8,11 @@ title=测试 gitlabModel::apiGetBranches();
cid=1
pid=1
通过gitlabID,projectID,获取GitLab分支列表 >> branch1
通过gitlabID,projectID,获取GitLab分支数量 >> 3
当前项目没有分支时,获取GitLab分支列表 >> 0
通过gitlabID,projectID,获取GitLab分支列表 >> 1
通过gitlabID,projectID,获取GitLab分支数量 >> 1
当前项目没有分支时,获取GitLab分支列表 >> 0
当gitlabID存在,projectID不存在时,获取GitLab分支列表 >> 404 Project Not Found
当gitlabID,projectID都为0时,获取GitLab分支列表 >> return empty
当gitlabID,projectID都为0时,获取GitLab分支列表 >> return empty
*/
@@ -21,11 +21,11 @@ $gitlab = $tester->loadModel('gitlab');
$gitlabID = 1;
$projectID = 1552;
$result = $gitlab->apiGetBranches($gitlabID, $projectID);
r($result) && p('0:name') && e('branch1'); //通过gitlabID,projectID,获取GitLab分支列表
r(count($result)) && p() && e(3); //通过gitlabID,projectID,获取GitLab分支数量
r(isset(array_shift($result)->name)) && p() && e(1); //通过gitlabID,projectID,获取GitLab分支列表
r(count($result) > 0) && p() && e(1); //通过gitlabID,projectID,获取GitLab分支数量
$gitlabID = 1;
$projectID = 1570;
$projectID = 959;
r(count($gitlab->apiGetBranches($gitlabID, $projectID))) && p() && e(0); //当前项目没有分支时,获取GitLab分支列表
$gitlabID = 1;

Some files were not shown because too many files have changed in this diff Show More