Merge branch 'master' of git.zcorp.cc:easycorp/zentaopms
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM hub.qucheng.com/ci/zentao-ztf:latest
|
||||
FROM hub.qucheng.com/ci/zentao-ztf:php8-2023042805
|
||||
|
||||
# Install zentao
|
||||
ARG VERSION
|
||||
|
||||
Vendored
+2
-5
@@ -1,7 +1,7 @@
|
||||
pipeline {
|
||||
agent {
|
||||
kubernetes {
|
||||
inheritFrom "build-docker code-scan xuanim mysql-server"
|
||||
inheritFrom "build-docker code-scan xuanim"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,7 @@ pipeline {
|
||||
returnStdout: true,
|
||||
script: 'cat VERSION'
|
||||
).trim()}"""
|
||||
MYSQL_SERVER_HOST = """${sh(
|
||||
returnStdout: true,
|
||||
script: 'hostname -I'
|
||||
).trim()}"""
|
||||
MYSQL_SERVER_HOST = 'ci-mysql-0'
|
||||
MYSQL_ROOT_PASSWORD = 'pass4ci'
|
||||
|
||||
MIDDLE_IMAGE_REPO = "hub.qc.oop.cc/zentao-ztf"
|
||||
|
||||
+1
-1
@@ -6,4 +6,4 @@ ALTER TABLE `zt_todo` CHANGE `idvalue` `objectID` mediumint(8) unsigned default
|
||||
|
||||
UPDATE `zt_block` SET `dashboard` = `module`;
|
||||
UPDATE `zt_block` SET `module` = IF(`source` != '', `source`, `code`);
|
||||
|
||||
DROP INDEX account_vision_module_type_order ON `zt_block`;
|
||||
|
||||
@@ -779,7 +779,7 @@ class baseRouter
|
||||
if(empty($this->config->debug) || $this->config->debug < 4 || !extension_loaded('xhprof')) return false;
|
||||
|
||||
$log = xhprof_disable();
|
||||
$xhprofPath = $this->getTmpRoot() . 'xhprof';
|
||||
$xhprofPath = $this->getWwwRoot() . 'xhprof';
|
||||
$libUtilsPath = $xhprofPath . DS . 'xhprof_lib' . DS . 'utils' . DS;
|
||||
$outputDir = ini_get('xhprof.output_dir');
|
||||
|
||||
@@ -795,9 +795,16 @@ class baseRouter
|
||||
}
|
||||
|
||||
$xhprofRuns = new \XHProfRuns_Default($outputDir);
|
||||
$runID = $xhprofRuns->save_run($log, "{$this->moduleName}_{$this->methodName}");
|
||||
$type = "{$this->moduleName}_{$this->methodName}";
|
||||
$runID = $xhprofRuns->save_run($log, $type);
|
||||
header("Xhprof-RunID: {$runID}");
|
||||
|
||||
if(class_exists(\zin\zin::class) && isset(\zin\zin::$data['zinDebug']))
|
||||
{
|
||||
$xhprofURL = getWebRoot(true) . "xhprof/xhprof_html/index.php?run={$runID}&source={$type}";
|
||||
\zin\zin::$data['zinDebug']['xhprof'] = $xhprofURL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The form class file of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.easycorp.cn)
|
||||
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Lu Fei <lufei@easycorp.ltd>
|
||||
* @package form
|
||||
* @link https://www.zentao.net
|
||||
|
||||
+53
-26
@@ -1,4 +1,14 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The trace class file of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Lu Fei <lufei@easycorp.ltd>
|
||||
* @package trace
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
class trace
|
||||
{
|
||||
@@ -6,9 +16,11 @@ class trace
|
||||
'Request' => '请求',
|
||||
'Files' => '文件',
|
||||
'SQL Query' => 'SQL 查询',
|
||||
'SQL Explain' => 'SQL Explain',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $trace = array();
|
||||
|
||||
protected $app;
|
||||
@@ -38,37 +50,53 @@ class trace
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求加载的文件。
|
||||
* Get request files.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getRequestFiles()
|
||||
{
|
||||
$this->trace['files'] = get_included_files();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求的 SQL 语句。
|
||||
* Get request SQLs.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getRequestSqls()
|
||||
{
|
||||
$explain = array();
|
||||
/**
|
||||
foreach(dao::$querys as $query)
|
||||
{
|
||||
$explain[] = $this->dao->explain($query, false);
|
||||
}
|
||||
*/
|
||||
$this->trace['sqlQuery'] = dao::$querys;
|
||||
$this->trace['sqlExplain'] = $explain;
|
||||
}
|
||||
|
||||
public function getSQLProfile()
|
||||
/**
|
||||
* 获取请求的 SQL profiles。
|
||||
* Get request SQL profiles.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSQLProfiles()
|
||||
{
|
||||
$profiling = $this->dao->dbh->query('SHOW PROFILES')->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
|
||||
$this->trace['profiles'] = $profiling;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成请求 Trace。
|
||||
* Generate request trace.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTrace()
|
||||
{
|
||||
$this->getRequestInfo();
|
||||
$this->getRequestFiles();
|
||||
$this->getRequestSqls();
|
||||
$this->getSQLProfile();
|
||||
$this->getSQLProfiles();
|
||||
return $this->trace;
|
||||
}
|
||||
|
||||
@@ -78,7 +106,6 @@ class trace
|
||||
$lines = '';
|
||||
foreach($this->trace as $type => $content)
|
||||
{
|
||||
if($type == 'SQL Explain') continue;
|
||||
$lines .= $this->console($type, empty($content) ? array() : $content);
|
||||
}
|
||||
|
||||
@@ -93,6 +120,14 @@ JS;
|
||||
return $js;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接需要输出到 console 的内容。
|
||||
* Concat the content to output to console.
|
||||
*
|
||||
* @param string $type
|
||||
* @param array $content
|
||||
* @return string
|
||||
*/
|
||||
protected function console(string $type, $content)
|
||||
{
|
||||
$traceTabs = array_keys($this->types);
|
||||
@@ -106,19 +141,6 @@ JS;
|
||||
$msg = str_replace("\n", '\n', addslashes($item));
|
||||
$style = "color:#009bb4;";
|
||||
$line[] = "console.log(\"%c{$msg}\", \"{$style}\");";
|
||||
|
||||
$explain = array();
|
||||
if(!empty($this->trace['SQL Explain']))
|
||||
{
|
||||
foreach($this->trace['SQL Explain'][$key] as $explainKey => $explainItem)
|
||||
{
|
||||
$explain[] = $explainKey . ': ' . $explainItem;
|
||||
}
|
||||
}
|
||||
|
||||
$msg = implode(', ', $explain);
|
||||
$style = "color:red;";
|
||||
$line[] = "console.log(\"%c{$msg}\", \"{$style}\");";
|
||||
break;
|
||||
default:
|
||||
$item = is_string($key) ? $key . ' ' . $item : $key + 1 . ' ' . $item;
|
||||
@@ -131,6 +153,11 @@ JS;
|
||||
return implode(PHP_EOL, $line);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接 SQL Profile。
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function printSQLProfile()
|
||||
{
|
||||
$lines = array();
|
||||
|
||||
+26
-26
@@ -100,13 +100,13 @@ $config->block->params['project']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['project']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['project']->orderBy['control'] = 'select';
|
||||
|
||||
$config->block->params['projectTeam'] = clone $config->block->params['default'];
|
||||
$config->block->params['projectTeam']->type['name'] = $lang->block->type;
|
||||
$config->block->params['projectTeam']->type['options'] = $lang->block->typeList->projectAll;
|
||||
$config->block->params['projectTeam']->type['control'] = 'select';
|
||||
$config->block->params['projectTeam']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['projectTeam']->orderBy['options'] = $lang->block->orderByList->project;
|
||||
$config->block->params['projectTeam']->orderBy['control'] = 'select';
|
||||
$config->block->params['projectteam'] = clone $config->block->params['default'];
|
||||
$config->block->params['projectteam']->type['name'] = $lang->block->type;
|
||||
$config->block->params['projectteam']->type['options'] = $lang->block->typeList->projectAll;
|
||||
$config->block->params['projectteam']->type['control'] = 'select';
|
||||
$config->block->params['projectteam']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['projectteam']->orderBy['options'] = $lang->block->orderByList->project;
|
||||
$config->block->params['projectteam']->orderBy['control'] = 'select';
|
||||
|
||||
$config->block->params['build'] = clone $config->block->params['default'];
|
||||
|
||||
@@ -115,33 +115,33 @@ $config->block->params['product']->type['name'] = $lang->block->type;
|
||||
$config->block->params['product']->type['options'] = $lang->block->typeList->product;
|
||||
$config->block->params['product']->type['control'] = 'select';
|
||||
|
||||
$config->block->params['productStatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['productStatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['productStatistic']->type['options'] = $lang->block->typeList->product;
|
||||
$config->block->params['productStatistic']->type['control'] = 'select';
|
||||
$config->block->params['productstatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['productstatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['productstatistic']->type['options'] = $lang->block->typeList->product;
|
||||
$config->block->params['productstatistic']->type['control'] = 'select';
|
||||
|
||||
$config->block->params['projectStatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['projectStatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['projectStatistic']->type['options'] = $lang->block->typeList->project;
|
||||
$config->block->params['projectStatistic']->type['control'] = 'select';
|
||||
$config->block->params['projectstatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['projectstatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['projectstatistic']->type['options'] = $lang->block->typeList->project;
|
||||
$config->block->params['projectstatistic']->type['control'] = 'select';
|
||||
|
||||
$config->block->params['executionStatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['executionStatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['executionStatistic']->type['options'] = $lang->block->typeList->execution;
|
||||
$config->block->params['executionStatistic']->type['control'] = 'select';
|
||||
$config->block->params['executionstatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['executionstatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['executionstatistic']->type['options'] = $lang->block->typeList->execution;
|
||||
$config->block->params['executionstatistic']->type['control'] = 'select';
|
||||
|
||||
$config->block->params['qaStatistic'] = clone $config->block->params['default'];
|
||||
$config->block->params['qaStatistic']->type['name'] = $lang->block->type;
|
||||
$config->block->params['qaStatistic']->type['options'] = $lang->block->typeList->product;
|
||||
$config->block->params['qaStatistic']->type['control'] = 'select';
|
||||
|
||||
$config->block->params['waterfallIssue'] = clone $config->block->params['default'];
|
||||
$config->block->params['waterfallIssue']->type['name'] = $lang->block->type;
|
||||
$config->block->params['waterfallIssue']->type['options'] = $lang->block->typeList->issue;
|
||||
$config->block->params['waterfallIssue']->type['control'] = 'select';
|
||||
$config->block->params['waterfallIssue']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['waterfallIssue']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['waterfallIssue']->orderBy['control'] = 'select';
|
||||
$config->block->params['waterfallissue'] = clone $config->block->params['default'];
|
||||
$config->block->params['waterfallissue']->type['name'] = $lang->block->type;
|
||||
$config->block->params['waterfallissue']->type['options'] = $lang->block->typeList->issue;
|
||||
$config->block->params['waterfallissue']->type['control'] = 'select';
|
||||
$config->block->params['waterfallissue']->orderBy['name'] = $lang->block->orderBy;
|
||||
$config->block->params['waterfallissue']->orderBy['options'] = $lang->block->orderByList->product;
|
||||
$config->block->params['waterfallissue']->orderBy['control'] = 'select';
|
||||
|
||||
$config->block->params['waterfallRisk'] = clone $config->block->params['default'];
|
||||
$config->block->params['waterfallRisk']->type['name'] = $lang->block->type;
|
||||
|
||||
+10
-18
@@ -206,42 +206,34 @@ class block extends control
|
||||
* 展示应用的仪表盘
|
||||
* Display dashboard for app.
|
||||
*
|
||||
* @param string $module
|
||||
* @param int $projectID
|
||||
* @param string $dashboard
|
||||
* @param string $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function dashboard(string $module, int $projectID = 0)
|
||||
public function dashboard(string $dashboard, string $projectID = '0')
|
||||
{
|
||||
if($this->loadModel('user')->isLogon()) $this->session->set('blockModule', $module);
|
||||
$blocks = $this->block->getMyDashboard($module);
|
||||
$vision = $this->config->vision;
|
||||
$blocks = $this->block->getMyDashboard($dashboard);
|
||||
$projectID = (int)$projectID;
|
||||
|
||||
$section = 'common';
|
||||
if($module == 'project' and $projectID)
|
||||
{
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
$section = $project->model . 'common';
|
||||
}
|
||||
|
||||
$isInitiated = $this->block->fetchBlockInitStatus($module, $vision, $section);
|
||||
$isInitiated = $this->block->fetchBlockInitStatus($dashboard);
|
||||
|
||||
/* Init block when vist index first. */
|
||||
if(empty($blocks) and !$isInitiated and !defined('TUTORIAL') and $this->block->initBlock($module))
|
||||
if(empty($blocks) and !$isInitiated and !defined('TUTORIAL') and $this->block->initBlock($dashboard))
|
||||
{
|
||||
return print(js::reload());
|
||||
}
|
||||
|
||||
$blocks = $this->blockZen->processBlockForRender($blocks, isset($project) ? $project : null);
|
||||
$blocks = $this->blockZen->processBlockForRender($blocks, $projectID);
|
||||
|
||||
if($this->app->getViewType() == 'json') return print(json_encode($blocks));
|
||||
|
||||
list($shortBlocks, $longBlocks) = $this->blockZen->splitBlocksByLen($blocks);
|
||||
|
||||
$this->view->title = zget($this->lang->block->dashboard, $module, $this->lang->block->dashboard['default']);
|
||||
$this->view->title = zget($this->lang->block->dashboard, $dashboard, $this->lang->block->dashboard['default']);
|
||||
$this->view->longBlocks = $longBlocks;
|
||||
$this->view->shortBlocks = $shortBlocks;
|
||||
$this->view->dashboard = $module;
|
||||
$this->view->dashboard = $dashboard;
|
||||
$this->render();
|
||||
}
|
||||
|
||||
|
||||
+147
-123
@@ -133,183 +133,200 @@ $lang->block->titleList['bug'] = '指派给我的Bug';
|
||||
$lang->block->titleList['case'] = '指派给我的用例';
|
||||
$lang->block->titleList['testtask'] = '待测版本列表';
|
||||
|
||||
$lang->block->default['waterfall']['project']['3']['title'] = "{$lang->projectCommon}计划";
|
||||
$lang->block->default['waterfall']['project']['3']['code'] = 'waterfallgantt';
|
||||
$lang->block->default['waterfall']['project']['3']['source'] = 'project';
|
||||
$lang->block->default['waterfall']['project']['3']['grid'] = 8;
|
||||
$lang->block->default['waterfallproject']['3']['title'] = "{$lang->projectCommon}计划";
|
||||
$lang->block->default['waterfallproject']['3']['module'] = 'waterfallproject';
|
||||
$lang->block->default['waterfallproject']['3']['code'] = 'waterfallgantt';
|
||||
$lang->block->default['waterfallproject']['3']['grid'] = 8;
|
||||
|
||||
$lang->block->default['waterfall']['project']['6']['title'] = '最新动态';
|
||||
$lang->block->default['waterfall']['project']['6']['code'] = 'projectdynamic';
|
||||
$lang->block->default['waterfall']['project']['6']['grid'] = 4;
|
||||
$lang->block->default['waterfall']['project']['6']['source'] = 'project';
|
||||
$lang->block->default['waterfallproject']['6']['title'] = '最新动态';
|
||||
$lang->block->default['waterfallproject']['6']['module'] = 'waterfallproject';
|
||||
$lang->block->default['waterfallproject']['6']['code'] = 'projectdynamic';
|
||||
$lang->block->default['waterfallproject']['6']['grid'] = 4;
|
||||
|
||||
$lang->block->default['waterfallplus'] = $lang->block->default['waterfall'];
|
||||
$lang->block->default['waterfallplusproject'] = $lang->block->default['waterfallproject'];
|
||||
|
||||
$lang->block->default['scrum']['project']['1']['title'] = $lang->projectCommon . '概况';
|
||||
$lang->block->default['scrum']['project']['1']['code'] = 'scrumoverview';
|
||||
$lang->block->default['scrum']['project']['1']['grid'] = 8;
|
||||
$lang->block->default['scrumproject']['1']['title'] = $lang->projectCommon . '概况';
|
||||
$lang->block->default['scrumproject']['1']['module'] = 'scrumproject';
|
||||
$lang->block->default['scrumproject']['1']['code'] = 'scrumoverview';
|
||||
$lang->block->default['scrumproject']['1']['grid'] = 8;
|
||||
|
||||
$lang->block->default['scrum']['project']['2']['title'] = $lang->executionCommon . '列表';
|
||||
$lang->block->default['scrum']['project']['2']['code'] = 'scrumlist';
|
||||
$lang->block->default['scrum']['project']['2']['grid'] = 8;
|
||||
$lang->block->default['scrumproject']['2']['title'] = $lang->executionCommon . '列表';
|
||||
$lang->block->default['scrumproject']['2']['module'] = 'scrumproject';
|
||||
$lang->block->default['scrumproject']['2']['code'] = 'scrumlist';
|
||||
$lang->block->default['scrumproject']['2']['grid'] = 8;
|
||||
|
||||
$lang->block->default['scrum']['project']['2']['params']['type'] = 'undone';
|
||||
$lang->block->default['scrum']['project']['2']['params']['count'] = '20';
|
||||
$lang->block->default['scrum']['project']['2']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['scrumproject']['2']['params']['type'] = 'undone';
|
||||
$lang->block->default['scrumproject']['2']['params']['count'] = '20';
|
||||
$lang->block->default['scrumproject']['2']['params']['orderBy'] = 'id_desc';
|
||||
|
||||
$lang->block->default['scrum']['project']['3']['title'] = '待测版本';
|
||||
$lang->block->default['scrum']['project']['3']['code'] = 'scrumtest';
|
||||
$lang->block->default['scrum']['project']['3']['grid'] = 8;
|
||||
$lang->block->default['scrumproject']['3']['title'] = '待测版本';
|
||||
$lang->block->default['scrumproject']['3']['module'] = 'scrumproject';
|
||||
$lang->block->default['scrumproject']['3']['code'] = 'scrumtest';
|
||||
$lang->block->default['scrumproject']['3']['grid'] = 8;
|
||||
|
||||
$lang->block->default['scrum']['project']['3']['params']['type'] = 'wait';
|
||||
$lang->block->default['scrum']['project']['3']['params']['count'] = '15';
|
||||
$lang->block->default['scrum']['project']['3']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['scrumproject']['3']['params']['type'] = 'wait';
|
||||
$lang->block->default['scrumproject']['3']['params']['count'] = '15';
|
||||
$lang->block->default['scrumproject']['3']['params']['orderBy'] = 'id_desc';
|
||||
|
||||
$lang->block->default['scrum']['project']['4']['title'] = $lang->executionCommon . '总览';
|
||||
$lang->block->default['scrum']['project']['4']['code'] = 'sprint';
|
||||
$lang->block->default['scrum']['project']['4']['grid'] = 4;
|
||||
$lang->block->default['scrumproject']['4']['title'] = $lang->executionCommon . '总览';
|
||||
$lang->block->default['scrumproject']['4']['module'] = 'scrumproject';
|
||||
$lang->block->default['scrumproject']['4']['code'] = 'sprint';
|
||||
$lang->block->default['scrumproject']['4']['grid'] = 4;
|
||||
|
||||
$lang->block->default['scrum']['project']['5']['title'] = '最新动态';
|
||||
$lang->block->default['scrum']['project']['5']['code'] = 'projectdynamic';
|
||||
$lang->block->default['scrum']['project']['5']['grid'] = 4;
|
||||
$lang->block->default['kanban'] = $lang->block->default['scrum'];
|
||||
$lang->block->default['agileplus'] = $lang->block->default['scrum'];
|
||||
$lang->block->default['scrumproject']['5']['title'] = '最新动态';
|
||||
$lang->block->default['scrumproject']['5']['module'] = 'scrumproject';
|
||||
$lang->block->default['scrumproject']['5']['code'] = 'projectdynamic';
|
||||
$lang->block->default['scrumproject']['5']['grid'] = 4;
|
||||
|
||||
$lang->block->default['product']['1']['title'] = $lang->productCommon . '统计';
|
||||
$lang->block->default['product']['1']['code'] = 'statistic';
|
||||
$lang->block->default['product']['1']['grid'] = 8;
|
||||
$lang->block->default['kanbanproject'] = $lang->block->default['scrumproject'];
|
||||
$lang->block->default['agileplusproject'] = $lang->block->default['scrumproject'];
|
||||
|
||||
$lang->block->default['product']['1']['title'] = $lang->productCommon . '统计';
|
||||
$lang->block->default['product']['1']['module'] = 'product';
|
||||
$lang->block->default['product']['1']['code'] = 'statistic';
|
||||
$lang->block->default['product']['1']['grid'] = 8;
|
||||
|
||||
$lang->block->default['product']['1']['params']['type'] = 'all';
|
||||
$lang->block->default['product']['1']['params']['count'] = '20';
|
||||
|
||||
$lang->block->default['product']['2']['title'] = $lang->productCommon . '总览';
|
||||
$lang->block->default['product']['2']['code'] = 'overview';
|
||||
$lang->block->default['product']['2']['grid'] = 4;
|
||||
$lang->block->default['product']['2']['title'] = $lang->productCommon . '总览';
|
||||
$lang->block->default['product']['2']['module'] = 'product';
|
||||
$lang->block->default['product']['2']['code'] = 'overview';
|
||||
$lang->block->default['product']['2']['grid'] = 4;
|
||||
|
||||
$lang->block->default['product']['3']['title'] = '未关闭的' . $lang->productCommon;
|
||||
$lang->block->default['product']['3']['code'] = 'list';
|
||||
$lang->block->default['product']['3']['grid'] = 8;
|
||||
$lang->block->default['product']['3']['title'] = '未关闭的' . $lang->productCommon;
|
||||
$lang->block->default['product']['3']['module'] = 'product';
|
||||
$lang->block->default['product']['3']['code'] = 'list';
|
||||
$lang->block->default['product']['3']['grid'] = 8;
|
||||
|
||||
$lang->block->default['product']['3']['params']['count'] = 15;
|
||||
$lang->block->default['product']['3']['params']['type'] = 'noclosed';
|
||||
|
||||
$lang->block->default['product']['4']['title'] = "指派给我的{$lang->SRCommon}";
|
||||
$lang->block->default['product']['4']['code'] = 'story';
|
||||
$lang->block->default['product']['4']['grid'] = 4;
|
||||
$lang->block->default['product']['4']['title'] = "指派给我的{$lang->SRCommon}";
|
||||
$lang->block->default['product']['4']['module'] = 'product';
|
||||
$lang->block->default['product']['4']['code'] = 'story';
|
||||
$lang->block->default['product']['4']['grid'] = 4;
|
||||
|
||||
$lang->block->default['product']['4']['params']['count'] = 15;
|
||||
$lang->block->default['product']['4']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['product']['4']['params']['type'] = 'assignedTo';
|
||||
|
||||
$lang->block->default['execution']['1']['title'] = '执行统计';
|
||||
$lang->block->default['execution']['1']['code'] = 'statistic';
|
||||
$lang->block->default['execution']['1']['grid'] = 8;
|
||||
$lang->block->default['execution']['1']['title'] = '执行统计';
|
||||
$lang->block->default['execution']['1']['module'] = 'execution';
|
||||
$lang->block->default['execution']['1']['code'] = 'statistic';
|
||||
$lang->block->default['execution']['1']['grid'] = 8;
|
||||
|
||||
$lang->block->default['execution']['1']['params']['type'] = 'all';
|
||||
$lang->block->default['execution']['1']['params']['count'] = '20';
|
||||
|
||||
$lang->block->default['execution']['2']['title'] = '执行总览';
|
||||
$lang->block->default['execution']['2']['code'] = 'overview';
|
||||
$lang->block->default['execution']['2']['grid'] = 4;
|
||||
$lang->block->default['execution']['2']['title'] = '执行总览';
|
||||
$lang->block->default['execution']['2']['module'] = 'execution';
|
||||
$lang->block->default['execution']['2']['code'] = 'overview';
|
||||
$lang->block->default['execution']['2']['grid'] = 4;
|
||||
|
||||
$lang->block->default['execution']['3']['title'] = '未关闭的执行';
|
||||
$lang->block->default['execution']['3']['code'] = 'list';
|
||||
$lang->block->default['execution']['3']['grid'] = 8;
|
||||
$lang->block->default['execution']['3']['title'] = '未关闭的执行';
|
||||
$lang->block->default['execution']['3']['module'] = 'execution';
|
||||
$lang->block->default['execution']['3']['code'] = 'list';
|
||||
$lang->block->default['execution']['3']['grid'] = 8;
|
||||
|
||||
$lang->block->default['execution']['3']['params']['count'] = 15;
|
||||
$lang->block->default['execution']['3']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['execution']['3']['params']['type'] = 'undone';
|
||||
|
||||
$lang->block->default['execution']['4']['title'] = '指派给我的任务';
|
||||
$lang->block->default['execution']['4']['code'] = 'task';
|
||||
$lang->block->default['execution']['4']['grid'] = 4;
|
||||
$lang->block->default['execution']['4']['title'] = '指派给我的任务';
|
||||
$lang->block->default['execution']['4']['module'] = 'execution';
|
||||
$lang->block->default['execution']['4']['code'] = 'task';
|
||||
$lang->block->default['execution']['4']['grid'] = 4;
|
||||
|
||||
$lang->block->default['execution']['4']['params']['count'] = 15;
|
||||
$lang->block->default['execution']['4']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['execution']['4']['params']['type'] = 'assignedTo';
|
||||
|
||||
$lang->block->default['execution']['5']['title'] = '版本列表';
|
||||
$lang->block->default['execution']['5']['code'] = 'build';
|
||||
$lang->block->default['execution']['5']['grid'] = 8;
|
||||
$lang->block->default['execution']['5']['title'] = '版本列表';
|
||||
$lang->block->default['execution']['5']['module'] = 'execution';
|
||||
$lang->block->default['execution']['5']['code'] = 'build';
|
||||
$lang->block->default['execution']['5']['grid'] = 8;
|
||||
|
||||
$lang->block->default['execution']['5']['params']['count'] = 15;
|
||||
$lang->block->default['execution']['5']['params']['orderBy'] = 'id_desc';
|
||||
|
||||
$lang->block->default['qa']['1']['title'] = '测试统计';
|
||||
$lang->block->default['qa']['1']['code'] = 'statistic';
|
||||
$lang->block->default['qa']['1']['grid'] = 8;
|
||||
$lang->block->default['qa']['1']['title'] = '测试统计';
|
||||
$lang->block->default['qa']['1']['module'] = 'qa';
|
||||
$lang->block->default['qa']['1']['code'] = 'statistic';
|
||||
$lang->block->default['qa']['1']['grid'] = 8;
|
||||
|
||||
$lang->block->default['qa']['1']['params']['type'] = 'noclosed';
|
||||
$lang->block->default['qa']['1']['params']['count'] = '20';
|
||||
|
||||
//$lang->block->default['qa']['2']['title'] = '测试用例总览';
|
||||
//$lang->block->default['qa']['2']['block'] = 'overview';
|
||||
//$lang->block->default['qa']['2']['grid'] = 4;
|
||||
|
||||
$lang->block->default['qa']['2']['title'] = '指派给我的Bug';
|
||||
$lang->block->default['qa']['2']['code'] = 'bug';
|
||||
$lang->block->default['qa']['2']['grid'] = 4;
|
||||
$lang->block->default['qa']['2']['title'] = '指派给我的Bug';
|
||||
$lang->block->default['qa']['2']['module'] = 'qa';
|
||||
$lang->block->default['qa']['2']['code'] = 'bug';
|
||||
$lang->block->default['qa']['2']['grid'] = 4;
|
||||
|
||||
$lang->block->default['qa']['2']['params']['count'] = 15;
|
||||
$lang->block->default['qa']['2']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['qa']['2']['params']['type'] = 'assignedTo';
|
||||
|
||||
$lang->block->default['qa']['3']['title'] = '指派给我的用例';
|
||||
$lang->block->default['qa']['3']['code'] = 'case';
|
||||
$lang->block->default['qa']['3']['grid'] = 4;
|
||||
$lang->block->default['qa']['3']['title'] = '指派给我的用例';
|
||||
$lang->block->default['qa']['3']['module'] = 'qa';
|
||||
$lang->block->default['qa']['3']['code'] = 'case';
|
||||
$lang->block->default['qa']['3']['grid'] = 4;
|
||||
|
||||
$lang->block->default['qa']['3']['params']['count'] = 15;
|
||||
$lang->block->default['qa']['3']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['qa']['3']['params']['type'] = 'assigntome';
|
||||
|
||||
$lang->block->default['qa']['4']['title'] = '待测版本列表';
|
||||
$lang->block->default['qa']['4']['code'] = 'testtask';
|
||||
$lang->block->default['qa']['4']['grid'] = 8;
|
||||
$lang->block->default['qa']['4']['title'] = '待测版本列表';
|
||||
$lang->block->default['qa']['4']['module'] = 'qa';
|
||||
$lang->block->default['qa']['4']['code'] = 'testtask';
|
||||
$lang->block->default['qa']['4']['grid'] = 8;
|
||||
|
||||
$lang->block->default['qa']['4']['params']['count'] = 15;
|
||||
$lang->block->default['qa']['4']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['qa']['4']['params']['type'] = 'wait';
|
||||
|
||||
$lang->block->default['full']['my']['1']['title'] = '欢迎';
|
||||
$lang->block->default['full']['my']['1']['module'] = 'welcome';
|
||||
$lang->block->default['full']['my']['1']['code'] = 'welcome';
|
||||
$lang->block->default['full']['my']['1']['grid'] = 8;
|
||||
$lang->block->default['full']['my']['1']['source'] = '';
|
||||
|
||||
$lang->block->default['full']['my']['2']['title'] = '最新动态';
|
||||
$lang->block->default['full']['my']['2']['module'] = 'dynamic';
|
||||
$lang->block->default['full']['my']['2']['code'] = 'dynamic';
|
||||
$lang->block->default['full']['my']['2']['grid'] = 4;
|
||||
$lang->block->default['full']['my']['2']['source'] = '';
|
||||
|
||||
$lang->block->default['full']['my']['3']['title'] = '使用帮助';
|
||||
$lang->block->default['full']['my']['3']['module'] = 'guide';
|
||||
$lang->block->default['full']['my']['3']['code'] = 'guide';
|
||||
$lang->block->default['full']['my']['3']['source'] = '';
|
||||
$lang->block->default['full']['my']['3']['grid'] = 8;
|
||||
|
||||
$lang->block->default['full']['my']['4']['title'] = '我的待办';
|
||||
$lang->block->default['full']['my']['4']['code'] = 'list';
|
||||
$lang->block->default['full']['my']['4']['grid'] = 4;
|
||||
$lang->block->default['full']['my']['4']['source'] = 'todo';
|
||||
$lang->block->default['full']['my']['4']['title'] = '我的待办';
|
||||
$lang->block->default['full']['my']['4']['module'] = 'todo';
|
||||
$lang->block->default['full']['my']['4']['code'] = 'list';
|
||||
$lang->block->default['full']['my']['4']['grid'] = 4;
|
||||
|
||||
$lang->block->default['full']['my']['4']['params']['count'] = '20';
|
||||
|
||||
$lang->block->default['full']['my']['5']['title'] = "{$lang->projectCommon}统计";
|
||||
$lang->block->default['full']['my']['5']['code'] = 'statistic';
|
||||
$lang->block->default['full']['my']['5']['source'] = 'project';
|
||||
$lang->block->default['full']['my']['5']['grid'] = 8;
|
||||
$lang->block->default['full']['my']['5']['title'] = "{$lang->projectCommon}统计";
|
||||
$lang->block->default['full']['my']['5']['module'] = 'project';
|
||||
$lang->block->default['full']['my']['5']['code'] = 'statistic';
|
||||
$lang->block->default['full']['my']['5']['grid'] = 8;
|
||||
|
||||
$lang->block->default['full']['my']['5']['params']['count'] = '20';
|
||||
|
||||
$lang->block->default['full']['my']['6']['title'] = '我的贡献';
|
||||
$lang->block->default['full']['my']['6']['code'] = 'contribute';
|
||||
$lang->block->default['full']['my']['6']['source'] = '';
|
||||
$lang->block->default['full']['my']['6']['module'] = 'contribute';
|
||||
$lang->block->default['full']['my']['6']['code'] = 'contribute';
|
||||
$lang->block->default['full']['my']['6']['grid'] = 4;
|
||||
|
||||
$lang->block->default['full']['my']['7']['title'] = "我近期参与的{$lang->projectCommon}";
|
||||
$lang->block->default['full']['my']['7']['module'] = 'project';
|
||||
$lang->block->default['full']['my']['7']['code'] = 'recentproject';
|
||||
$lang->block->default['full']['my']['7']['source'] = 'project';
|
||||
$lang->block->default['full']['my']['7']['grid'] = 8;
|
||||
|
||||
$lang->block->default['full']['my']['8']['title'] = '我的待处理';
|
||||
$lang->block->default['full']['my']['8']['module'] = 'assigntome';
|
||||
$lang->block->default['full']['my']['8']['code'] = 'assigntome';
|
||||
$lang->block->default['full']['my']['8']['source'] = '';
|
||||
$lang->block->default['full']['my']['8']['grid'] = 8;
|
||||
|
||||
$lang->block->default['full']['my']['8']['params']['todoCount'] = '20';
|
||||
@@ -323,55 +340,63 @@ $lang->block->default['full']['my']['8']['params']['meetingCount'] = '20';
|
||||
$lang->block->default['full']['my']['8']['params']['feedbackCount'] = '20';
|
||||
|
||||
$lang->block->default['full']['my']['9']['title'] = "{$lang->projectCommon}人力投入";
|
||||
$lang->block->default['full']['my']['9']['module'] = 'project';
|
||||
$lang->block->default['full']['my']['9']['code'] = 'projectteam';
|
||||
$lang->block->default['full']['my']['9']['source'] = 'project';
|
||||
$lang->block->default['full']['my']['9']['grid'] = 8;
|
||||
|
||||
$lang->block->default['full']['my']['10']['title'] = "{$lang->projectCommon}列表";
|
||||
$lang->block->default['full']['my']['10']['module'] = 'project';
|
||||
$lang->block->default['full']['my']['10']['code'] = 'project';
|
||||
$lang->block->default['full']['my']['10']['source'] = 'project';
|
||||
$lang->block->default['full']['my']['10']['grid'] = 8;
|
||||
|
||||
$lang->block->default['full']['my']['10']['params']['orderBy'] = 'id_desc';
|
||||
$lang->block->default['full']['my']['10']['params']['count'] = '15';
|
||||
|
||||
/* Doc module block. */
|
||||
$lang->block->default['doc']['1']['title'] = '文档统计';
|
||||
$lang->block->default['doc']['1']['code'] = 'docstatistic';
|
||||
$lang->block->default['doc']['1']['grid'] = 8;
|
||||
$lang->block->default['doc']['1']['title'] = '文档统计';
|
||||
$lang->block->default['doc']['1']['module'] = 'doc';
|
||||
$lang->block->default['doc']['1']['code'] = 'docstatistic';
|
||||
$lang->block->default['doc']['1']['grid'] = 8;
|
||||
|
||||
$lang->block->default['doc']['2']['title'] = '文档动态';
|
||||
$lang->block->default['doc']['2']['code'] = 'docdynamic';
|
||||
$lang->block->default['doc']['2']['grid'] = 4;
|
||||
$lang->block->default['doc']['2']['title'] = '文档动态';
|
||||
$lang->block->default['doc']['2']['module'] = 'doc';
|
||||
$lang->block->default['doc']['2']['code'] = 'docdynamic';
|
||||
$lang->block->default['doc']['2']['grid'] = 4;
|
||||
|
||||
$lang->block->default['doc']['3']['title'] = '我收藏的文档';
|
||||
$lang->block->default['doc']['3']['code'] = 'docmycollection';
|
||||
$lang->block->default['doc']['3']['grid'] = 8;
|
||||
$lang->block->default['doc']['3']['title'] = '我收藏的文档';
|
||||
$lang->block->default['doc']['3']['module'] = 'doc';
|
||||
$lang->block->default['doc']['3']['code'] = 'docmycollection';
|
||||
$lang->block->default['doc']['3']['grid'] = 8;
|
||||
|
||||
$lang->block->default['doc']['4']['title'] = '最近更新的文档';
|
||||
$lang->block->default['doc']['4']['code'] = 'docrecentupdate';
|
||||
$lang->block->default['doc']['4']['grid'] = 8;
|
||||
$lang->block->default['doc']['4']['title'] = '最近更新的文档';
|
||||
$lang->block->default['doc']['4']['module'] = 'doc';
|
||||
$lang->block->default['doc']['4']['code'] = 'docrecentupdate';
|
||||
$lang->block->default['doc']['4']['grid'] = 8;
|
||||
|
||||
$lang->block->default['doc']['5']['title'] = '浏览排行榜';
|
||||
$lang->block->default['doc']['5']['code'] = 'docviewlist';
|
||||
$lang->block->default['doc']['5']['grid'] = 4;
|
||||
$lang->block->default['doc']['5']['title'] = '浏览排行榜';
|
||||
$lang->block->default['doc']['5']['module'] = 'doc';
|
||||
$lang->block->default['doc']['5']['code'] = 'docviewlist';
|
||||
$lang->block->default['doc']['5']['grid'] = 4;
|
||||
|
||||
if($config->vision == 'rnd')
|
||||
{
|
||||
$lang->block->default['doc']['6']['title'] = $lang->productCommon . '文档';
|
||||
$lang->block->default['doc']['6']['code'] = 'productdoc';
|
||||
$lang->block->default['doc']['6']['grid'] = 8;
|
||||
$lang->block->default['doc']['6']['title'] = $lang->productCommon . '文档';
|
||||
$lang->block->default['doc']['6']['module'] = 'doc';
|
||||
$lang->block->default['doc']['6']['code'] = 'productdoc';
|
||||
$lang->block->default['doc']['6']['grid'] = 8;
|
||||
|
||||
$lang->block->default['doc']['6']['params']['count'] = '20';
|
||||
}
|
||||
|
||||
$lang->block->default['doc']['7']['title'] = '收藏排行榜';
|
||||
$lang->block->default['doc']['7']['code'] = 'doccollectlist';
|
||||
$lang->block->default['doc']['7']['grid'] = 4;
|
||||
$lang->block->default['doc']['7']['title'] = '收藏排行榜';
|
||||
$lang->block->default['doc']['7']['module'] = 'doc';
|
||||
$lang->block->default['doc']['7']['code'] = 'doccollectlist';
|
||||
$lang->block->default['doc']['7']['grid'] = 4;
|
||||
|
||||
$lang->block->default['doc']['8']['title'] = $lang->projectCommon . '文档';
|
||||
$lang->block->default['doc']['8']['code'] = 'projectdoc';
|
||||
$lang->block->default['doc']['8']['grid'] = 8;
|
||||
$lang->block->default['doc']['8']['title'] = $lang->projectCommon . '文档';
|
||||
$lang->block->default['doc']['8']['module'] = 'doc';
|
||||
$lang->block->default['doc']['8']['code'] = 'projectdoc';
|
||||
$lang->block->default['doc']['8']['grid'] = 8;
|
||||
|
||||
$lang->block->default['doc']['8']['params']['count'] = '20';
|
||||
|
||||
@@ -556,13 +581,12 @@ $lang->block->typeList->project['doing'] = '进行中';
|
||||
$lang->block->typeList->project['all'] = '全部';
|
||||
$lang->block->typeList->project['involved'] = '我参与的';
|
||||
|
||||
$lang->block->typeList->projectAll['all'] = '全部';
|
||||
$lang->block->typeList->projectAll['undone'] = '未完成';
|
||||
$lang->block->typeList->projectAll['wait'] = '未开始';
|
||||
$lang->block->typeList->projectAll['doing'] = '进行中';
|
||||
$lang->block->typeList->projectAll['exceeded'] = '已逾期';
|
||||
$lang->block->typeList->projectAll['risky'] = '有风险';
|
||||
$lang->block->typeList->projectAll['more'] = '更多';
|
||||
$lang->block->typeList->projectAll['all'] = '全部';
|
||||
$lang->block->typeList->projectAll['undone'] = '未完成';
|
||||
$lang->block->typeList->projectAll['wait'] = '未开始';
|
||||
$lang->block->typeList->projectAll['doing'] = '进行中';
|
||||
$lang->block->typeList->projectAll['suspended'] = '已挂起';
|
||||
$lang->block->typeList->projectAll['closed'] = '已关闭';
|
||||
|
||||
$lang->block->typeList->execution['undone'] = '未完成';
|
||||
$lang->block->typeList->execution['doing'] = '进行中';
|
||||
|
||||
+25
-38
@@ -195,7 +195,7 @@ class blockModel extends model
|
||||
}
|
||||
elseif($code == 'statistic')
|
||||
{
|
||||
$code = $module . 'Statistic';
|
||||
$code = $module . $code;
|
||||
}
|
||||
|
||||
$params = zget($this->config->block->params, $code, '');
|
||||
@@ -401,48 +401,37 @@ class blockModel extends model
|
||||
* Init block when account use first.
|
||||
* 用户首次加载时初始化区块数据.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $type
|
||||
* @param string $dashboard
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function initBlock(string $module, string $type = ''): bool
|
||||
public function initBlock(string $dashboard): bool
|
||||
{
|
||||
if(!$module) return false;
|
||||
if(!$dashboard) return false;
|
||||
|
||||
$flow = isset($this->config->global->flow) ? $this->config->global->flow : 'full';
|
||||
$account = $this->app->user->account;
|
||||
$vision = $this->config->vision;
|
||||
|
||||
if($module == 'project')
|
||||
{
|
||||
$blocks = $this->lang->block->default[$type]['project'];
|
||||
$blocks = $dashboard == 'my' ? $this->lang->block->default[$flow][$dashboard] : $this->lang->block->default[$dashboard];
|
||||
|
||||
/* Mark project block has init. */
|
||||
$this->loadModel('setting')->setItem("$account.$module.{$type}common.blockInited@$vision", '1');
|
||||
}
|
||||
else
|
||||
{
|
||||
$blocks = $module == 'my' ? $this->lang->block->default[$flow][$module] : $this->lang->block->default[$module];
|
||||
|
||||
/* Mark this app has init. */
|
||||
$this->loadModel('setting')->setItem("$account.$module.common.blockInited@$vision", '1');
|
||||
}
|
||||
|
||||
$this->loadModel('setting')->setItem("$account.$module.block.initVersion", $this->config->block->version);
|
||||
foreach($blocks as $index => $block)
|
||||
{
|
||||
$block['order'] = $index;
|
||||
$block['module'] = $module;
|
||||
$block['type'] = $type;
|
||||
$block['account'] = $account;
|
||||
$block['params'] = isset($block['params']) ? helper::jsonEncode($block['params']) : '';
|
||||
$block['vision'] = $this->config->vision;
|
||||
if(!isset($block['source'])) $block['source'] = $module;
|
||||
$block['account'] = $account;
|
||||
$block['dashboard'] = $dashboard;
|
||||
$block['order'] = $index;
|
||||
$block['params'] = isset($block['params']) ? helper::jsonEncode($block['params']) : '';
|
||||
$block['vision'] = $this->config->vision;
|
||||
|
||||
$this->blockTao->insert($block);
|
||||
}
|
||||
return !dao::isError();
|
||||
if(dao::isError()) return false;
|
||||
|
||||
/* Mark this app has init. */
|
||||
$this->loadModel('setting')->setItem("$account.$dashboard.common.blockInited@$vision", '1');
|
||||
$this->loadModel('setting')->setItem("$account.$dashboard.block.initVersion", $this->config->block->version);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -483,19 +472,17 @@ class blockModel extends model
|
||||
* 获取区块是否已经初始化.
|
||||
* Fetch block is initiated or not.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $vision
|
||||
* @param string $section
|
||||
* @param string $dashboard
|
||||
* @return string
|
||||
*/
|
||||
public function fetchBlockInitStatus(string $module, string $vision, string $section): string
|
||||
public function fetchBlockInitStatus(string $dashboard): string
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_CONFIG)
|
||||
->where('module')->eq($module)
|
||||
->andWhere('owner')->eq($this->app->user->account)
|
||||
->andWhere('`section`')->eq($section)->fi()
|
||||
->andWhere('`key`')->eq('blockInited')
|
||||
->andWhere('vision')->eq($vision)
|
||||
->fetch('value');
|
||||
->where('module')->eq($dashboard)
|
||||
->andWhere('owner')->eq($this->app->user->account)
|
||||
->andWhere('`section`')->eq('common')
|
||||
->andWhere('`key`')->eq('blockInited')
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->fetch('value');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,9 +205,9 @@ class blockTest
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getAvailableBlocksTest($module = '', $dashboard = '', $model = '')
|
||||
public function getAvailableBlocksTest($dashboard = '', $module = '')
|
||||
{
|
||||
$objects = json_decode($this->objectModel->getAvailableBlocks($module, $dashboard, $model));
|
||||
$objects = $this->objectModel->getAvailableBlocks($dashboard,$module);
|
||||
|
||||
if(dao::isError()) return dao::getError();
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
include dirname(__FILE__, 2) . '/block.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,8 +15,8 @@ pid=1
|
||||
*/
|
||||
|
||||
$block = new blockTest();
|
||||
$data[0] = $block->getAvailableBlocksTest('project', 'project', 'waterfall');
|
||||
$data[0] = $block->getAvailableBlocksTest('waterfallProject');
|
||||
$data[1] = $block->getAvailableBlocksTest('qa');
|
||||
|
||||
r($data[0]) && p('waterfallgantt,projectdynamic') && e('项目计划,最新动态'); // 通过获取项目的可用区块
|
||||
r($data[1]) && p('statistic,bug,case,testtask') && e('测试统计,Bug列表,用例列表,版本列表'); // 通过获取测试的可用区块
|
||||
r($data[1]) && p('statistic,bug,case,testtask') && e('测试统计,Bug列表,用例列表,版本列表'); // 通过获取测试的可用区块
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
include dirname(__FILE__, 2) . '/block.class.php';
|
||||
|
||||
su('admin');
|
||||
#su('admin');
|
||||
|
||||
$userModel = new userModel();
|
||||
$user = $userModel->identify('admin', 'Asd123456');
|
||||
$userModel->login($user);
|
||||
|
||||
function initData()
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ set::title($title);
|
||||
jsVar('dashboard', $dashboard);
|
||||
|
||||
$paramsRows = array();
|
||||
$isMyDashboard = $dashboard == 'my';
|
||||
|
||||
foreach($params as $key => $row)
|
||||
{
|
||||
@@ -38,6 +39,8 @@ form
|
||||
on::change('#code', 'getForm'),
|
||||
formGroup
|
||||
(
|
||||
set::class($isMyDashboard ? '' : 'hidden'),
|
||||
set::value($isMyDashboard ? '' : $dashboard),
|
||||
set::label($lang->block->lblModule),
|
||||
set::name('module'),
|
||||
set::control(array
|
||||
|
||||
@@ -15,6 +15,7 @@ set::title($title);
|
||||
jsVar('blockID', $block->id);
|
||||
|
||||
$paramsRows = array();
|
||||
$isMyDashboard = $dashboard == 'my';
|
||||
|
||||
foreach($params as $key => $row)
|
||||
{
|
||||
@@ -40,7 +41,8 @@ form
|
||||
(
|
||||
set::label($lang->block->lblModule),
|
||||
set::name('module'),
|
||||
set::value($block->module),
|
||||
set::class($isMyDashboard ? '' : 'hidden'),
|
||||
set::value($isMyDashboard ? $block->module : $dashboard),
|
||||
set::control(array
|
||||
(
|
||||
'type' => 'select',
|
||||
|
||||
+12
-22
@@ -107,28 +107,19 @@ class blockZen extends block
|
||||
* 处理每个区块以渲染 UI。
|
||||
* Process each block for render UI.
|
||||
*
|
||||
* @param object[] $blocks
|
||||
* @param object|null $project
|
||||
* @param object[] $blocks
|
||||
* @param int $projectID
|
||||
* @return object[]
|
||||
*/
|
||||
protected function processBlockForRender(array $blocks, object $project = null): array
|
||||
protected function processBlockForRender(array $blocks, int $projectID): array
|
||||
{
|
||||
$acls = $this->app->user->rights['acls'];
|
||||
foreach($blocks as $key => $block)
|
||||
{
|
||||
if(in_array($block->code, array('waterfallrisk', 'waterfallissue')))
|
||||
{
|
||||
$model = isset($project->model) ? $project->model : 'waterfall';
|
||||
if($block->code == 'waterfallrisk' and !helper::hasFeature("{$model}_risk")) continue;
|
||||
if($block->code == 'waterfallissue' and !helper::hasFeature("{$model}_issue")) continue;
|
||||
}
|
||||
|
||||
if(in_array($block->code, array('scrumrisk', 'scrumissue')))
|
||||
{
|
||||
$model = isset($project->model) ? $project->model : 'scrum';
|
||||
if($block->code == 'scrumrisk' and !helper::hasFeature("{$model}_risk")) continue;
|
||||
if($block->code == 'scrumissue' and !helper::hasFeature("{$model}_issue")) continue;
|
||||
}
|
||||
if($block->code == 'waterfallrisk' and !helper::hasFeature("waterfall_risk")) continue;
|
||||
if($block->code == 'waterfallissue' and !helper::hasFeature("waterfall_issue")) continue;
|
||||
if($block->code == 'scrumrisk' and !helper::hasFeature("scrum_risk")) continue;
|
||||
if($block->code == 'scrumissue' and !helper::hasFeature("scrum_issue")) continue;
|
||||
|
||||
if(!empty($block->source) and $block->source != 'todo' and !empty($acls['views']) and !isset($acls['views'][$block->source]))
|
||||
{
|
||||
@@ -139,7 +130,7 @@ class blockZen extends block
|
||||
$block->params = json_decode($block->params);
|
||||
if(isset($block->params->num) and !isset($block->params->count)) $block->params->count = $block->params->num;
|
||||
|
||||
$this->getBlockMoreLink($block, $project);
|
||||
$this->getBlockMoreLink($block, $projectID);
|
||||
}
|
||||
|
||||
return $blocks;
|
||||
@@ -150,14 +141,13 @@ class blockZen extends block
|
||||
* Get the more link of the block.
|
||||
*
|
||||
* @param object $block
|
||||
* @param object $project
|
||||
* @param int $projectID
|
||||
* @return void
|
||||
*/
|
||||
private function getBlockMoreLink(object $block, object $project): void
|
||||
private function getBlockMoreLink(object $block, int $project): void
|
||||
{
|
||||
$code = $block->code;
|
||||
$source = empty($block->source) ? 'common' : $block->source;
|
||||
$projectID = isset($project->id) ? $project->id : 0;
|
||||
$code = $block->code;
|
||||
$source = empty($block->source) ? 'common' : $block->source;
|
||||
|
||||
$block->blockLink = $this->createLink('block', 'printBlock', "id=$block->id&module=$block->module");
|
||||
$block->moreLink = '';
|
||||
|
||||
+21
-29
@@ -290,51 +290,43 @@ class executionModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the execution id user last visited to session.
|
||||
* 检查用户是否可以访问当前执行。
|
||||
* Check whether access to the current execution is allowed or not.
|
||||
*
|
||||
* @param int $executionID
|
||||
* @param array $executions
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function saveState($executionID, $executions)
|
||||
public function checkAccess(int $executionID, array $executions): int
|
||||
{
|
||||
if(defined('TUTORIAL')) return $executionID;
|
||||
|
||||
/* When the cookie and session do not exist, get it from the database. */
|
||||
if(empty($executionID) and isset($this->config->execution->lastExecution) and isset($executions[$this->config->execution->lastExecution]))
|
||||
/* When the cookie and session do not exist, get it from the config. */
|
||||
if(!$executionID)
|
||||
{
|
||||
$this->session->set('execution', $this->config->execution->lastExecution, $this->app->tab);
|
||||
$this->setProjectSession($this->session->execution);
|
||||
return $this->session->execution;
|
||||
if(isset($this->cookie->lastExecution)) $executionID = (int)$this->cookie->lastExecution;
|
||||
if(isset($this->session->execution)) $executionID = (int)$this->session->execution;
|
||||
if(isset($this->config->execution->lastExecution)) $executionID = (int)$this->config->execution->lastExecution;
|
||||
}
|
||||
|
||||
if($executionID == 0 and $this->cookie->lastExecution)
|
||||
/* If the execution doesn't exist in the list, use the first execution in the list. */
|
||||
if(!isset($executions[$executionID])) $executionID = key($executions);
|
||||
|
||||
/* Check execution again. */
|
||||
if($executionID)
|
||||
{
|
||||
/* Execution link is execution-task. */
|
||||
$executionID = (int)$this->cookie->lastExecution;
|
||||
$executionID = in_array($executionID, array_keys($executions)) ? $executionID : key($executions);
|
||||
$execution = $this->dao->findByID($executionID)->from(TABLE_EXECUTION)->fetch();
|
||||
if(empty($execution)) return js::error($this->lang->notFound);
|
||||
if(strpos(",{$this->app->user->view->sprints},", ",{$executionID},") === false) $this->accessDenied();
|
||||
}
|
||||
|
||||
if($executionID == 0 and $this->session->execution) $executionID = $this->session->execution;
|
||||
if($executionID == 0) $executionID = key($executions);
|
||||
/* Save session. */
|
||||
$this->session->set('execution', $executionID, $this->app->tab);
|
||||
$this->setProjectSession($executionID);
|
||||
|
||||
$this->session->set('execution', (int)$executionID, $this->app->tab);
|
||||
|
||||
if(!isset($executions[$executionID]))
|
||||
{
|
||||
$this->session->set('execution', key($executions), $this->app->tab);
|
||||
|
||||
if($executionID)
|
||||
{
|
||||
$execution = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->andWhere('type')->in('sprint,stage,kanban')->fetch();
|
||||
if(empty($execution)) return js::error($this->lang->notFound);
|
||||
if(strpos(",{$this->app->user->view->sprints},", ",{$executionID},") === false) $this->accessDenied();
|
||||
}
|
||||
}
|
||||
|
||||
$this->setProjectSession($this->session->execution);
|
||||
return $this->session->execution;
|
||||
/* Return execution id. */
|
||||
return $executionID;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -121,9 +121,6 @@ class product extends control
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||||
$this->view->branchID = $branch;
|
||||
$this->view->branchStatus = $this->loadModel('branch')->getByID($branch, 0, 'status');
|
||||
$this->view->recTotal = $recTotal;
|
||||
$this->view->recPerPage = $recPerPage;
|
||||
$this->view->pageID = $pageID;
|
||||
$this->view->pager = $pager;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
+32
-62
@@ -22,6 +22,9 @@ class productModel extends model
|
||||
const OB_PROGRAM = 'program_asc';
|
||||
const OB_ORDER = 'order_asc';
|
||||
|
||||
const STORY_TYPE_STORY = 'story';
|
||||
const STORY_TYPE_REQ = 'requirement';
|
||||
|
||||
/**
|
||||
* Get product module menu.
|
||||
*
|
||||
@@ -323,7 +326,7 @@ class productModel extends model
|
||||
* @param int $programID
|
||||
* @param string|array $append
|
||||
* @param string|int $shadow all | 0 | 1
|
||||
* @return array
|
||||
* @return int[]
|
||||
*/
|
||||
public function getPairs(string $mode = '', int $programID = 0, string|array $append = '', string|int $shadow = 0): array
|
||||
{
|
||||
@@ -333,16 +336,7 @@ class productModel extends model
|
||||
$append = $this->productTao->formatAppendParam($append);
|
||||
$views = $this->app->user->view->products . (empty($append) ? '' : ",{$append}");
|
||||
|
||||
return $this->dao->select("t1.*, IF(INSTR(' closed', t1.status) < 2, 0, 1) AS isClosed")->from(TABLE_PRODUCT)->alias('t1')
|
||||
->leftJoin(TABLE_PROGRAM)->alias('t2')->on('t1.program = t2.id')
|
||||
->where('t1.vision')->eq($this->config->vision)
|
||||
->beginIF(strpos($mode, 'all') === false)->andWhere('t1.deleted')->eq(0)->fi()
|
||||
->beginIF($programID)->andWhere('t1.program')->eq($programID)->fi()
|
||||
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('t1.status')->ne('closed')->fi()
|
||||
->beginIF(!$this->app->user->admin and $this->config->vision == 'rnd')->andWhere('t1.id')->in($views)->fi()
|
||||
->beginIF($shadow !== 'all')->andWhere('t1.shadow')->eq((int)$shadow)->fi()
|
||||
->orderBy("isClosed,t1.program_asc,t2.order_asc,t1.line_desc,t1.order_asc")
|
||||
->fetchPairs('id', 'name');
|
||||
return $this->productTao->fetchPairs($programID, $mode, $views, $shadow);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1753,6 +1747,7 @@ class productModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取产品统计信息。
|
||||
* Get product stats.
|
||||
*
|
||||
* @param string $orderBy order_asc|program_asc
|
||||
@@ -1771,64 +1766,39 @@ class productModel extends model
|
||||
$products = strtolower($status) == static::ST_BYSEARCH ? $this->getListBySearch($param) : $this->productTao->getList($programID, $status, 0, $line);
|
||||
if(empty($products)) return array();
|
||||
|
||||
$productKeys = array_keys($products);
|
||||
$products = $this->productTao->getStatsProducts($productKeys,$programID, $orderBy, $pager);
|
||||
$stories = $this->productTao->getStoriesTODO($productKeys);
|
||||
$requirements = $this->productTao->getRequirementsTODO($productKeys);
|
||||
/* Get stats data. */
|
||||
$productKeys = array_keys($products);
|
||||
$products = $this->productTao->getStatsProducts($productKeys,$programID, $orderBy, $pager);
|
||||
$finishClosedStory = $this->productTao->getFinishClosedStoryTODO();
|
||||
$unclosedStory = $this->productTao->getUnClosedStoryTODO();
|
||||
$plans = $this->productTao->getPlansTODO($productKeys);
|
||||
$releases = $this->productTao->getReleasesTODO($productKeys);
|
||||
$bugs = $this->productTao->getBugsTODO($productKeys);
|
||||
$unResolved = $this->productTao->getUnResolvedTODO($productKeys);
|
||||
$fixedBugs = $this->productTao->getFixedBugsTODO($productKeys);
|
||||
$closedBugs = $this->productTao->getClosedBugsTODO($productKeys);
|
||||
$thisWeekBugs = $this->productTao->getThisWeekBugsTODO($productKeys);
|
||||
$assignToNull = $this->productTao->getAssignToNullTODO($productKeys);
|
||||
list($stories, $reqs) = $this->productTao->getStatsStoriesAndRequirements($productKeys, $storyType);
|
||||
|
||||
/* Padding the stories to sure all products have records. */
|
||||
$emptyStory = array_keys($this->lang->story->statusList);
|
||||
foreach($productKeys as $productID)
|
||||
{
|
||||
if(!isset($stories[$productID])) $stories[$productID] = $emptyStory;
|
||||
if(!isset($requirements[$productID])) $requirements[$productID] = $emptyStory;
|
||||
}
|
||||
|
||||
/* Padding the stories to sure all status have records. */
|
||||
foreach($stories as $key => $story)
|
||||
{
|
||||
foreach(array_keys($this->lang->story->statusList) as $status) $story[$status] = isset($story[$status]) ? $story[$status]->count : 0;
|
||||
$stories[$key] = $story;
|
||||
}
|
||||
foreach($requirements as $key => $requirement)
|
||||
{
|
||||
foreach(array_keys($this->lang->story->statusList) as $status) $requirement[$status] = isset($requirement[$status]) ? $requirement[$status]->count : 0;
|
||||
$requirements[$key] = $requirement;
|
||||
}
|
||||
|
||||
if($storyType == 'requirement') $stories = $requirements;
|
||||
|
||||
$finishClosedStory = $this->productTao->getFinishClosedStoryTODO();
|
||||
$unclosedStory = $this->productTao->getUnClosedStoryTODO();
|
||||
$plans = $this->productTao->getPlansTODO($productKeys);
|
||||
$releases = $this->productTao->getReleasesTODO($productKeys);
|
||||
$bugs = $this->productTao->getBugsTODO($productKeys);
|
||||
$unResolved = $this->productTao->getUnResolvedTODO($productKeys);
|
||||
$fixedBugs = $this->productTao->getFixedBugsTODO($productKeys);
|
||||
$closedBugs = $this->productTao->getClosedBugsTODO($productKeys);
|
||||
$thisWeekBugs = $this->productTao->getThisWeekBugsTODO($productKeys);
|
||||
$assignToNull = $this->productTao->getAssignToNullTODO($productKeys);
|
||||
|
||||
|
||||
/* Generate statistic array. */
|
||||
/* Render statistic result to each product. */
|
||||
$stats = array();
|
||||
foreach($products as $key => $product)
|
||||
{
|
||||
$product->stories = $stories[$product->id];
|
||||
$product->stories['finishClosed'] = isset($finishClosedStory[$product->id]) ? $finishClosedStory[$product->id] : 0;
|
||||
$product->stories['unclosed'] = isset($unclosedStory[$product->id]) ? $unclosedStory[$product->id] : 0;
|
||||
|
||||
$product->requirements = $requirements[$product->id];
|
||||
$product->plans = isset($plans[$product->id]) ? $plans[$product->id] : 0;
|
||||
$product->releases = isset($releases[$product->id]) ? $releases[$product->id] : 0;
|
||||
|
||||
$product->bugs = isset($bugs[$product->id]) ? $bugs[$product->id] : 0;
|
||||
$product->unResolved = isset($unResolved[$product->id]) ? $unResolved[$product->id] : 0;
|
||||
$product->closedBugs = isset($closedBugs[$product->id]) ? $closedBugs[$product->id] : 0;
|
||||
$product->fixedBugs = isset($fixedBugs[$product->id]) ? $fixedBugs[$product->id] : 0;
|
||||
$product->thisWeekBugs = isset($thisWeekBugs[$product->id]) ? $thisWeekBugs[$product->id] : 0;
|
||||
$product->assignToNull = isset($assignToNull[$product->id]) ? $assignToNull[$product->id] : 0;
|
||||
$product->stories['unclosed'] = isset($unclosedStory[$product->id]) ? $unclosedStory[$product->id] : 0;
|
||||
$product->requirements = $reqs[$product->id];
|
||||
$product->plans = isset($plans[$product->id]) ? $plans[$product->id] : 0;
|
||||
$product->releases = isset($releases[$product->id]) ? $releases[$product->id] : 0;
|
||||
$product->bugs = isset($bugs[$product->id]) ? $bugs[$product->id] : 0;
|
||||
$product->unResolved = isset($unResolved[$product->id]) ? $unResolved[$product->id] : 0;
|
||||
$product->closedBugs = isset($closedBugs[$product->id]) ? $closedBugs[$product->id] : 0;
|
||||
$product->fixedBugs = isset($fixedBugs[$product->id]) ? $fixedBugs[$product->id] : 0;
|
||||
$product->thisWeekBugs = isset($thisWeekBugs[$product->id]) ? $thisWeekBugs[$product->id] : 0;
|
||||
$product->assignToNull = isset($assignToNull[$product->id]) ? $assignToNull[$product->id] : 0;
|
||||
|
||||
/* Calculate product progress. */
|
||||
$closedTotal = $product->stories['closed'] + $product->requirements['closed'];
|
||||
$allTotal = array_sum($product->stories) + array_sum($product->requirements);
|
||||
$product->progress = empty($closedTotal) ? 0 : round($closedTotal / $allTotal * 100, 1);
|
||||
|
||||
@@ -12,6 +12,31 @@ declare(strict_types=1);
|
||||
|
||||
class productTao extends productModel
|
||||
{
|
||||
/**
|
||||
* 从数据表获取符合条件的id=>name的键值对。
|
||||
* Fetch pairs like id=>name.
|
||||
*
|
||||
* @param int $programID
|
||||
* @param string $mode all|noclosed
|
||||
* @param string $views
|
||||
* @param string|int $shadow all|0|1
|
||||
* @access protected
|
||||
* @return int[]
|
||||
*/
|
||||
protected function fetchPairs(int $programID, string $mode, string $views, string|int $shadow): array
|
||||
{
|
||||
return $this->dao->select("t1.*, IF(INSTR(' closed', t1.status) < 2, 0, 1) AS isClosed")->from(TABLE_PRODUCT)->alias('t1')
|
||||
->leftJoin(TABLE_PROGRAM)->alias('t2')->on('t1.program = t2.id')
|
||||
->where('t1.vision')->eq($this->config->vision)
|
||||
->beginIF(strpos($mode, 'all') === false)->andWhere('t1.deleted')->eq(0)->fi()
|
||||
->beginIF($programID)->andWhere('t1.program')->eq($programID)->fi()
|
||||
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('t1.status')->ne('closed')->fi()
|
||||
->beginIF(!$this->app->user->admin and $this->config->vision == 'rnd')->andWhere('t1.id')->in($views)->fi()
|
||||
->beginIF($shadow !== 'all')->andWhere('t1.shadow')->eq((int)$shadow)->fi()
|
||||
->orderBy("isClosed,t2.order_asc,t1.line_desc,t1.order_asc")
|
||||
->fetchPairs('id', 'name');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取产品ID数组中带有项目集信息的产品分页列表。
|
||||
* Get products with program data that in the ID list.
|
||||
@@ -333,4 +358,46 @@ class productTao extends productModel
|
||||
|
||||
return implode(',', $append);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用于数据统计的研发需求和用户需求列表。
|
||||
* Get dev stories and user requirements for statistics.
|
||||
*
|
||||
* @param array $productIDs
|
||||
* @param string $storyType
|
||||
* @access protected
|
||||
* @return [array, array]
|
||||
*/
|
||||
protected function getStatsStoriesAndRequirements(array $productIDs, string $storyType): array
|
||||
{
|
||||
$stories = $this->getStoriesTODO($productIDs);
|
||||
$requirements = $this->getRequirementsTODO($productIDs);
|
||||
|
||||
/* Padding the stories to sure all products have records. */
|
||||
$emptyStory = array_keys($this->lang->story->statusList);
|
||||
foreach($productIDs as $productID)
|
||||
{
|
||||
if(!isset($stories[$productID])) $stories[$productID] = $emptyStory;
|
||||
if(!isset($requirements[$productID])) $requirements[$productID] = $emptyStory;
|
||||
}
|
||||
|
||||
/* Collect count for each status of stories. */
|
||||
foreach($stories as $key => $story)
|
||||
{
|
||||
foreach(array_keys($this->lang->story->statusList) as $status) $story[$status] = isset($story[$status]) ? $story[$status]->count : 0;
|
||||
$stories[$key] = $story;
|
||||
}
|
||||
|
||||
/* Collect count for each status of requirements. */
|
||||
foreach($requirements as $key => $requirement)
|
||||
{
|
||||
foreach(array_keys($this->lang->story->statusList) as $status) $requirement[$status] = isset($requirement[$status]) ? $requirement[$status]->count : 0;
|
||||
$requirements[$key] = $requirement;
|
||||
}
|
||||
|
||||
/* Story type is 'requirement'. */
|
||||
if($storyType == static::STORY_TYPE_REQ) $stories = $requirements;
|
||||
|
||||
return [$stories, $requirements];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,11 +15,12 @@ pid=1
|
||||
|
||||
$product = new productTest('admin');
|
||||
|
||||
r($product->getProductPairs($t_peoduct10['programID'])) && p('11') && e('正常产品11'); // 测试项目集10下的11号产品
|
||||
r($product->getProductPairs($t_peoduct10['programID'])) && p('55') && e('多分支产品55'); // 测试项目集10下的55号产品
|
||||
r($product->getProductPairs($t_peoduct10['programID'])) && p('99') && e('多平台产品99'); // 测试项目集10下的99号产品
|
||||
r($product->getProductPairs($t_noproduct['programID'])) && p() && e('没有数据'); // 测试不存在的项目集
|
||||
r($product->getProductPairsCount($t_alproduct['programID'])) && p() && e('120'); // 返回所有产品的数量
|
||||
r($product->getProductPairsCount($t_peoduct10['programID'])) && p() && e('10'); // 返回项目集10下的所有产品
|
||||
r($product->getNoclosedPairs($t_notclose5['programID'])) && p('6') && e('正常产品6'); // 测试项目集10下的未关闭产品5
|
||||
r($product->getNoclosedPairsCount($t_peoduct10['programID'])) && p() && e('6'); // 返回项目集10下的未关闭产品的数量
|
||||
r($product->getProductPairs()) && p('11') && e('正常产品11'); // 测试项目集10下的11号产品
|
||||
r($product->getProductPairs('all')) && p('55') && e('多分支产品55'); // 测试项目集10下的55号产品
|
||||
r($product->getProductPairs('noclosed')) && p('99') && e('多平台产品99'); // 测试项目集10下的99号产品
|
||||
r($product->getProductPairs('all', 1)) && p() && e('没有数据'); // 测试不存在的项目集
|
||||
r($product->getProductPairs('all', -1)) && p() && e('没有数据'); // 测试不存在的项目集
|
||||
r($product->getProductPairs('all', 10001, '1')) && p() && e('没有数据'); // 测试不存在的项目集
|
||||
r($product->getProductPairs('noclosed', 1, '22,23')) && p() && e('没有数据'); // 测试不存在的项目集
|
||||
r($product->getProductPairs('noclosed', 1, '22,23', 'all')) && p() && e('没有数据'); // 测试不存在的项目集
|
||||
r($product->getProductPairs('noclosed', 1, '22,23', '1')) && p() && e('没有数据'); // 测试不存在的项目集
|
||||
|
||||
@@ -237,20 +237,6 @@ class productTest
|
||||
return $pairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get product pairs count.
|
||||
*
|
||||
* @param int $programID
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getProductPairsCount($programID)
|
||||
{
|
||||
$pairsCount = count($this->getProductPairs($programID));
|
||||
if($pairsCount == '没有数据') return '0';
|
||||
return $pairsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get all product pairs.
|
||||
*
|
||||
|
||||
Regular → Executable
@@ -1,9 +1,10 @@
|
||||
<?php
|
||||
$config->project->form = new stdclass();
|
||||
$config->project->form->create = array();
|
||||
$config->project->form->start = array();
|
||||
$config->project->form->close = array();
|
||||
$config->project->form->suspend = array();
|
||||
$config->project->form->create = array();
|
||||
$config->project->form->start = array();
|
||||
$config->project->form->close = array();
|
||||
$config->project->form->suspend = array();
|
||||
$config->project->form->activate = array();
|
||||
|
||||
$config->project->form->create['parent'] = array('type' => 'int', 'required' => false, 'default' => '');
|
||||
$config->project->form->create['name'] = array('type' => 'string', 'required' => true, 'filter' => 'trim');
|
||||
|
||||
+12
-24
@@ -1803,46 +1803,34 @@ class project extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活项目并更新其状态
|
||||
* Activate a project.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $projectID
|
||||
* @access public
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function activate($projectID)
|
||||
public function activate(string $projectID)
|
||||
{
|
||||
$this->loadModel('action');
|
||||
$this->app->loadLang('execution');
|
||||
$projectID = (int)$projectID;
|
||||
$project = $this->project->getByID($projectID);
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$changes = $this->project->activate($projectID);
|
||||
$postData = form::data($this->config->project->form->activate);
|
||||
|
||||
$postData = $this->projectZen->prepareActivateExtras($projectID, $postData);
|
||||
|
||||
$changes = $this->project->activate($projectID, $postData);
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
|
||||
if($this->post->comment != '' or !empty($changes))
|
||||
{
|
||||
$actionID = $this->action->create('project', $projectID, 'Activated', $this->post->comment);
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
$this->executeHooks($projectID);
|
||||
$comment = strip_tags($this->post->comment, $this->config->allowedTags);
|
||||
$this->projectZen->responseAfterActivate($projectID, $changes, $comment);
|
||||
return print(js::reload('parent.parent'));
|
||||
}
|
||||
|
||||
$newBegin = date('Y-m-d');
|
||||
$dateDiff = helper::diffDate($newBegin, $project->begin);
|
||||
$newEnd = date('Y-m-d', strtotime($project->end) + $dateDiff * 24 * 3600);
|
||||
|
||||
$this->view->title = $this->lang->project->activate;
|
||||
$this->view->position[] = $this->lang->project->activate;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||||
$this->view->actions = $this->action->getList('project', $projectID);
|
||||
$this->view->newBegin = $newBegin;
|
||||
$this->view->newEnd = $newEnd;
|
||||
$this->view->project = $project;
|
||||
|
||||
$this->display();
|
||||
$this->projectZen->buildActivateForm($project);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -198,8 +198,8 @@ class projectModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a project by id.
|
||||
* 根据项目ID获取项目信息。
|
||||
* Get a project by id.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
@@ -217,17 +217,18 @@ class projectModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过影子产品ID获取一条项目记录。
|
||||
* Get a project by its shadow product.
|
||||
*
|
||||
* @param int $product
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return object
|
||||
* @return object|false
|
||||
*/
|
||||
public function getByShadowProduct($product)
|
||||
public function getByShadowProduct(int $productID): object|false
|
||||
{
|
||||
return $this->dao->select('t2.*')->from(TABLE_PROJECTPRODUCT)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
|
||||
->where('t1.product')->eq($product)
|
||||
->where('t1.product')->eq($productID)
|
||||
->andWhere('t2.type')->eq('project')
|
||||
->limit(1)
|
||||
->fetch();
|
||||
@@ -1820,16 +1821,16 @@ class projectModel extends model
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function unlinkMember($projectID, $account, $removeExecution = 'no')
|
||||
public function unlinkMember(int $projectID, string $account, string $removeExecution = 'no'): void
|
||||
{
|
||||
$this->dao->delete()->from(TABLE_TEAM)->where('root')->eq((int)$projectID)->andWhere('type')->eq('project')->andWhere('account')->eq($account)->exec();
|
||||
$this->projectTao->unlinkTeamMember($projectID, 'project', $account);
|
||||
|
||||
$this->loadModel('user')->updateUserView($projectID, 'project', array($account));
|
||||
|
||||
if($removeExecution == 'yes')
|
||||
{
|
||||
$executions = $this->loadModel('execution')->getByProject($projectID, 'undone', 0, true);
|
||||
$this->dao->delete()->from(TABLE_TEAM)->where('root')->in(array_keys($executions))->andWhere('type')->eq('execution')->andWhere('account')->eq($account)->exec();
|
||||
$this->projectTao->unlinkTeamMember(array_keys($executions), 'execution', $account);
|
||||
$this->user->updateUserView(array_keys($executions), 'sprint', array($account));
|
||||
}
|
||||
|
||||
|
||||
+23
-16
@@ -220,7 +220,7 @@ class projectTao extends projectModel
|
||||
* @param object $postData
|
||||
* @param object $program
|
||||
* @access protected
|
||||
* @return bool
|
||||
* @return bool
|
||||
*/
|
||||
protected function createDocLib(int $projectID, object $project, object $postData, object $program): bool
|
||||
{
|
||||
@@ -269,7 +269,7 @@ class projectTao extends projectModel
|
||||
* @param object $postData
|
||||
* @param object $program
|
||||
* @access protected
|
||||
* @return bool
|
||||
* @return bool
|
||||
*/
|
||||
protected function createProduct(int $projectID, object $project, object $postData, object $program): bool
|
||||
{
|
||||
@@ -333,7 +333,7 @@ class projectTao extends projectModel
|
||||
* @param object $rawdata
|
||||
* @param object $program
|
||||
* @access protected
|
||||
* @return bool
|
||||
* @return bool
|
||||
*/
|
||||
protected function getLinkedProductsCount(object $project, object $rawdata): int
|
||||
{
|
||||
@@ -355,7 +355,7 @@ class projectTao extends projectModel
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access protected
|
||||
* @return bool
|
||||
* @return bool
|
||||
*/
|
||||
protected function addProjectAdmin(int $projectID): bool
|
||||
{
|
||||
@@ -441,16 +441,23 @@ class projectTao extends projectModel
|
||||
return helper::createLink('project', 'testcase', "projectID=%s");
|
||||
}
|
||||
|
||||
protected function buildLinkForTask if($module == 'testtask')
|
||||
{
|
||||
if($method == 'browseunits')
|
||||
{
|
||||
$link = helper::createLink('project', 'testcase', "projectID=%s");
|
||||
}
|
||||
else
|
||||
{
|
||||
$link = helper::createLink('project', 'testtask', "projectID=%s");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除项目团队成员。
|
||||
* Delete project team member.
|
||||
*
|
||||
* @param array|int $projectIdList
|
||||
* @param string $type
|
||||
* @param string $account
|
||||
* @access protected
|
||||
* @return bool
|
||||
*/
|
||||
protected function unlinkTeamMember(int|array $projectIdList, string $type, string $account): bool
|
||||
{
|
||||
$this->dao->delete()->from(TABLE_TEAM)
|
||||
->where('root')->in($projectIdList)
|
||||
->andWhere('type')->eq($type)
|
||||
->andWhere('account')->eq($account)
|
||||
->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
include dirname(__FILE__, 2) . '/project.class.php';
|
||||
su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$project = zdTable('project');
|
||||
$project->id->range('2-5');
|
||||
$project->project->range('2-5');
|
||||
$project->name->prefix("项目")->range('2-5');
|
||||
$project->code->prefix("project")->range('2-5');
|
||||
$project->type->range("project");
|
||||
$project->gen(4);
|
||||
|
||||
$projectproduct = zdTable('projectproduct');
|
||||
$projectproduct->product->range('1-3');
|
||||
$projectproduct->project->range('2-4');
|
||||
$projectproduct->branch->range("0");
|
||||
$projectproduct->gen(3);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel::getByShadowProduct;
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 执行projectTester模块的testGetByShadowPro方法,参数是2属性code @project3
|
||||
|
||||
- 执行projectTester模块的testGetByShadowPro方法,参数是5属性code @0
|
||||
|
||||
- 执行projectTester模块的testGetByShadowPro方法,参数是aaa属性code @($productID) must be of type int
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
initData();
|
||||
|
||||
$projectTester = new Project();
|
||||
r($projectTester->testGetByShadowProduct(2)) && p('code') && e('project3'); //获取ID为1的产品关联的项目
|
||||
r($projectTester->testGetByShadowProduct(5)) && p('code') && e('0'); //获取ID为4的产品关联的项目
|
||||
r($projectTester->testGetByShadowProduct('aaa')) && p('code') && e('($productID) must be of type int'); //获取ID为字符串的产品的项目
|
||||
@@ -1,29 +1,65 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
su('admin');
|
||||
su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$team = zdTable('team');
|
||||
$team->id->range('2-9');
|
||||
$team->root->range('2,7-9{3}');
|
||||
$team->type->range('project,execution{7}');
|
||||
$team->account->range('admin,user1,user2,admin');
|
||||
$team->limited->range('no');
|
||||
$team->join->range('2023-04-02');
|
||||
$team->days->range('7');
|
||||
$team->hours->range('7');
|
||||
$team->gen(8);
|
||||
|
||||
$execution = zdTable('project');
|
||||
$execution->id->range('2,6,8,9');
|
||||
$execution->project->range('2,3');
|
||||
$execution->name->prefix('项目')->range('8,9');
|
||||
$execution->code->prefix('project')->range('8,9');
|
||||
$execution->type->range('project{2},sprint,kanban');
|
||||
$execution->status->range('doing,suspended,closed');
|
||||
$execution->gen(4);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel->unlinkMember();
|
||||
title=测试 projectModel::getByID;
|
||||
timeout=0
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
查看移除团队成员之前的ID为11的项目团队成员数量 >> 3
|
||||
查看移除团队成员之后的ID为11的项目团队成员数量 >> 2
|
||||
查看项目ID为11的团队成员的真实姓名 >> 产品经理92
|
||||
查看项目ID为11的团队成员的真实姓名 >> 产品经理92
|
||||
- 执行$diffMembers @1 >> 1
|
||||
>> admin
|
||||
- 执行$beforeMembers['admin'] @admin >> 0
|
||||
>> 1
|
||||
- 执行$afterMembers['admin'] @0 >> admin
|
||||
>> 0
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
$tester->loadModel('project');
|
||||
|
||||
$beforeMembers = $tester->project->getTeamMemberPairs(11);
|
||||
$tester->project->unlinkMember(11, 'admin', false);
|
||||
$afterMembers = $tester->project->getTeamMemberPairs(11);
|
||||
initData();
|
||||
|
||||
r(count($beforeMembers)) && p('') && e('3'); // 查看移除团队成员之前的ID为11的项目团队成员数量
|
||||
r(count($afterMembers)) && p('') && e('2'); // 查看移除团队成员之后的ID为11的项目团队成员数量
|
||||
r($beforeMembers) && p('pm92') && e('产品经理92'); // 查看项目ID为11的团队成员的真实姓名
|
||||
r($afterMembers) && p('pm92') && e('产品经理92'); // 查看项目ID为11的团队成员的真实姓名
|
||||
$beforeMembers = $tester->project->getTeamMemberPairs(2);
|
||||
$beforeExecutionMembers = $tester->project->getTeamMemberPairs(8);
|
||||
|
||||
$tester->project->unlinkMember(2, 'admin', 'yes');
|
||||
|
||||
$afterMembers = $tester->project->getTeamMemberPairs(2);
|
||||
$afterExecutionMembers = $tester->project->getTeamMemberPairs(6);
|
||||
$diffMembers = count($beforeMembers) - count($afterMembers);
|
||||
$diffExecutionMembers = count($beforeExecutionMembers) - count($afterExecutionMembers);
|
||||
|
||||
r($diffMembers) && p() && e('1');
|
||||
r($beforeMembers['admin']) && p() && e('admin');
|
||||
r($afterMembers['admin']) && p() && e('0');
|
||||
r($diffExecutionMembers) && p() && e('1');
|
||||
r($beforeExecutionMembers['admin']) && p() && e('admin');
|
||||
r($afterExecutionMembers['admin']) && p() && e('0');
|
||||
|
||||
@@ -61,6 +61,18 @@ class Project
|
||||
return $this->triggerMethod('fetchProjectInfo', array('projectID' => $projectID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getByShadowProduct function.
|
||||
*
|
||||
* @param int $productID
|
||||
* @access public
|
||||
* @return string|bool|object
|
||||
*/
|
||||
public function testGetByShadowProduct($productID)
|
||||
{
|
||||
return $this->triggerMethod('getByShadowProduct', array('productID' => $productID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test start a project.
|
||||
*
|
||||
|
||||
@@ -50,6 +50,14 @@ class projectZen extends project
|
||||
return $project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check product and branch not empty.
|
||||
*
|
||||
* @param object $project
|
||||
* @param object $rawdata
|
||||
* @access protected
|
||||
* @return bool
|
||||
*/
|
||||
private function checkProductAndBranch(object $project, object $rawdata): bool
|
||||
{
|
||||
$linkedProductsCount = $this->project->getLinkedProductsCount($project, $rawdata);
|
||||
@@ -84,6 +92,14 @@ class projectZen extends project
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check days and budget by rules.
|
||||
*
|
||||
* @param object $project
|
||||
* @param object $rawdata
|
||||
* @access protected
|
||||
* @return bool
|
||||
*/
|
||||
private function checkDaysAndBudget(object $project, object $rawdata): bool
|
||||
{
|
||||
/* Judge workdays is legitimate. */
|
||||
@@ -115,6 +131,14 @@ class projectZen extends project
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check product name unique and not empty.
|
||||
*
|
||||
* @param object $project
|
||||
* @param object $rawdata
|
||||
* @access protected
|
||||
* @return bool
|
||||
*/
|
||||
private function checkProductNameUnqiue(object $project, object $rawdata): bool
|
||||
{
|
||||
/* When select create new product, product name cannot be empty and duplicate. */
|
||||
@@ -486,4 +510,75 @@ class projectZen extends project
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send variables to activate page.
|
||||
*
|
||||
* @param object $project
|
||||
* @access protected
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function buildActivateForm(object $project): void
|
||||
{
|
||||
$newBegin = date('Y-m-d');
|
||||
$dateDiff = helper::diffDate($newBegin, $project->begin);
|
||||
$newEnd = date('Y-m-d', strtotime($project->end) + $dateDiff * 24 * 3600);
|
||||
|
||||
$this->view->title = $this->lang->project->activate;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||||
$this->view->actions = $this->loadModel('action')->getList('project', $project->id);
|
||||
$this->view->newBegin = $newBegin;
|
||||
$this->view->newEnd = $newEnd;
|
||||
$this->view->project = $project;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* After activateing the project, do other operations.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param array $changes
|
||||
* @param string $comment
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function responseAfterActivate(int $projectID, array $changes, string $comment): void
|
||||
{
|
||||
if($this->post->comment != '' or !empty($changes))
|
||||
{
|
||||
$actionID = $this->action->create('project', $projectID, 'Activated', $this->post->comment);
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
$this->executeHooks($projectID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append extras data to post data.
|
||||
*
|
||||
* @param int $iprojectID
|
||||
* @param object $postData
|
||||
*
|
||||
* @access protected
|
||||
* @return object
|
||||
*/
|
||||
protected function prepareActivateExtras(int $projectID, object $postData): object
|
||||
{
|
||||
$oldProject = $this->project->getByID($projectID);
|
||||
|
||||
$editorIdList=$this->config->project->editor->activate['id'];
|
||||
if($this->app->rawModule=='program')$editorIdList=$this->config->program->editor->activate['id'];
|
||||
|
||||
return $postData->add('id',$projectID)
|
||||
->setDefault('realEnd','')
|
||||
->setDefault('status','doing')
|
||||
->setDefault('lastEditedBy',$this->app->user->account)
|
||||
->setDefault('lastEditedDate',helper::now())
|
||||
->setIF(!helper::isZeroDate($oldProject->realBegan),'realBegan',helper::today())
|
||||
->stripTags($editorIdList,$this->config->allowedTags)
|
||||
->remove('comment,readjustTime,readjustTask')
|
||||
->get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,6 @@ class qa extends control
|
||||
$this->view->title = $this->lang->qa->index;
|
||||
$this->view->position[] = $this->lang->qa->index;
|
||||
$this->view->products = $products;
|
||||
$this->display();
|
||||
echo $this->fetch('block', 'dashboard', 'dashboard=qa');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,3 +35,8 @@ $config->todo->assignTo->form['assignedTo'] = array('required' => true, 'type
|
||||
$config->todo->batchClose = new stdclass;
|
||||
$config->todo->batchClose->form = array();
|
||||
$config->todo->batchClose->form['todoIDList'] = array('required' => true, 'type' => 'array');
|
||||
|
||||
$config->todo->batchEdit = new stdClass;
|
||||
$config->todo->batchEdit->form = array();
|
||||
$config->todo->batchEdit->form['todoIDList'] = array('required' => true, 'type' => 'array');
|
||||
$config->todo->batchEdit->form['names'] = array('required' => true, 'type' => 'array');
|
||||
+75
-168
@@ -2,7 +2,7 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* The control file of example module of ZenTaoPMS.
|
||||
* The control file of todo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
@@ -29,15 +29,15 @@ class todo extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建待办
|
||||
* 创建待办。
|
||||
* Create a todo.
|
||||
*
|
||||
* @param string $date
|
||||
* @param string $from todo|feedback|block
|
||||
* @access public
|
||||
* @return int|void
|
||||
* @return int
|
||||
*/
|
||||
public function create(string $date = 'today', string $from = 'todo')
|
||||
public function create(string $date = 'today', string $from = 'todo'): int
|
||||
{
|
||||
if($date == 'today') $date = date::today();
|
||||
|
||||
@@ -56,7 +56,7 @@ class todo extends control
|
||||
|
||||
if($from == 'block')
|
||||
{
|
||||
$todo = $this->todo->getById($todoID);
|
||||
$todo = $this->todo->getByID($todoID);
|
||||
$todo->begin = date::formatTime($todo->begin);
|
||||
return $this->send(array('result' => 'success', 'id' => $todoID, 'name' => $todo->name, 'pri' => $todo->pri, 'priName' => $this->lang->todo->priList[$todo->pri], 'time' => date(DT_DATE4, strtotime($todo->date)) . ' ' . $todo->begin));
|
||||
}
|
||||
@@ -69,12 +69,7 @@ class todo extends control
|
||||
|
||||
unset($this->lang->todo->typeList['cycle']);
|
||||
|
||||
$this->view->title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->create;
|
||||
$this->view->date = date('Y-m-d', strtotime($date));
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->time = date::now();
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
|
||||
$this->display();
|
||||
$this->buildCreateForm($date);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,17 +123,16 @@ class todo extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑待办数据
|
||||
* 编辑待办数据。
|
||||
* Edit a todo.
|
||||
*
|
||||
* @param string $todoID
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function edit(string $todoID)
|
||||
public function edit(string $todoID): int
|
||||
{
|
||||
$todoID = (int)$todoID;
|
||||
|
||||
$todoID = (int)$todoID;
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$formData = form::data($this->config->todo->edit->form);
|
||||
@@ -164,18 +158,12 @@ class todo extends control
|
||||
}
|
||||
|
||||
/* Judge a private todo or not, If private, die. */
|
||||
$todo = $this->todo->getById($todoID);
|
||||
$todo = $this->todo->getByID($todoID);
|
||||
if($todo->private and $this->app->user->account != $todo->account) return print('private');
|
||||
|
||||
unset($this->lang->todo->typeList['cycle']);
|
||||
|
||||
$todo->date = date("Y-m-d", strtotime($todo->date));
|
||||
$this->view->title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->edit;
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->todo = $todo;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
|
||||
|
||||
$this->display();
|
||||
$this->renderEditData($todoID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,113 +176,26 @@ class todo extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function batchEdit($from = '', $type = 'today', $userID = '', $status = 'all')
|
||||
public function batchEdit(string $from = '', string $type = 'today', string $userID = '', string $status = 'all')
|
||||
{
|
||||
/* Get form data for my-todo. */
|
||||
if($from == 'myTodo')
|
||||
if($from == 'myTodo') $this->todoZen->batchEditFromMyTodo($type, $userID, $status);
|
||||
if($from == 'todoBatchEdit')
|
||||
{
|
||||
/* Initialize vars. */
|
||||
$editedTodos = array();
|
||||
$todoIDList = array();
|
||||
$columns = 7;
|
||||
|
||||
if($userID == '') $userID = $this->app->user->id;
|
||||
$user = $this->loadModel('user')->getById($userID, 'id');
|
||||
$account = $user->account;
|
||||
|
||||
$reviews = array();
|
||||
if($this->config->edition == 'max') $reviews = $this->loadModel('review')->getUserReviewPairs($account);
|
||||
$allTodos = $this->todo->getList($type, $account, $status);
|
||||
if($this->post->todoIDList) $todoIDList = $this->post->todoIDList;
|
||||
|
||||
/* Initialize todos whose need to edited. */
|
||||
foreach($allTodos as $todo)
|
||||
{
|
||||
if(in_array($todo->id, $todoIDList))
|
||||
{
|
||||
$editedTodos[$todo->id] = $todo;
|
||||
if($todo->type != 'custom')
|
||||
{
|
||||
if(!isset($objectIDList[$todo->type])) $objectIDList[$todo->type] = array();
|
||||
$objectIDList[$todo->type][$todo->objectID] = $todo->objectID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$bugs = $this->bug->getUserBugPairs($account, true, 0, '', '', isset($objectIDList['bug']) ? $objectIDList['bug'] : '');
|
||||
$tasks = $this->task->getUserTaskPairs($account, 'wait,doing', '', isset($objectIDList['task']) ? $objectIDList['task'] : '');
|
||||
$storys = $this->loadModel('story')->getUserStoryPairs($account, 10, 'story', '', isset($objectIDList['story']) ? $objectIDList['story'] : '');
|
||||
if($this->config->edition != 'open') $this->view->feedbacks = $this->loadModel('feedback')->getUserFeedbackPairs($account, '', isset($objectIDList['feedback']) ? $objectIDList['feedback'] : '');
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$issues = $this->loadModel('issue')->getUserIssuePairs($account);
|
||||
$risks = $this->loadmodel('risk')->getUserRiskPairs($account);
|
||||
$opportunities = $this->loadmodel('opportunity')->getUserOpportunityPairs($account);
|
||||
}
|
||||
$testtasks = $this->loadModel('testtask')->getUserTestTaskPairs($account);
|
||||
|
||||
/* Judge whether the edited todos is too large. */
|
||||
$countInputVars = count($editedTodos) * $columns;
|
||||
$showSuhosinInfo = common::judgeSuhosinSetting($countInputVars);
|
||||
|
||||
unset($this->lang->todo->typeList['cycle']);
|
||||
/* Set Custom*/
|
||||
foreach(explode(',', $this->config->todo->list->customBatchEditFields) as $field) $customFields[$field] = $this->lang->todo->$field;
|
||||
$this->view->customFields = $customFields;
|
||||
$this->view->showFields = $this->config->todo->custom->batchEditFields;
|
||||
|
||||
/* Assign. */
|
||||
$title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->batchEdit;
|
||||
$position[] = html::a($this->createLink('my', 'todo'), $this->lang->my->todo);
|
||||
$position[] = $this->lang->todo->common;
|
||||
$position[] = $this->lang->todo->batchEdit;
|
||||
|
||||
if($showSuhosinInfo) $this->view->suhosinInfo = extension_loaded('suhosin') ? sprintf($this->lang->suhosinInfo, $countInputVars) : sprintf($this->lang->maxVarsInfo, $countInputVars);
|
||||
$this->view->bugs = $bugs;
|
||||
$this->view->tasks = $tasks;
|
||||
$this->view->storys = $storys;
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$this->view->issues = $issues;
|
||||
$this->view->risks = $risks;
|
||||
$this->view->opportunities = $opportunities;
|
||||
}
|
||||
$this->view->reviews = $reviews;
|
||||
$this->view->testtasks = $testtasks;
|
||||
$this->view->editedTodos = $editedTodos;
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->time = date::now();
|
||||
$this->view->title = $title;
|
||||
$this->view->position = $position;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
|
||||
|
||||
$this->display();
|
||||
}
|
||||
/* Get form data from todo-batchEdit. */
|
||||
elseif($from == 'todoBatchEdit')
|
||||
{
|
||||
$allChanges = $this->todo->batchUpdate();
|
||||
foreach($allChanges as $todoID => $changes)
|
||||
{
|
||||
if(empty($changes)) continue;
|
||||
|
||||
$actionID = $this->loadModel('action')->create('todo', $todoID, 'edited');
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
return print(js::locate($this->session->todoList, 'parent'));
|
||||
$formData = form::data($this->config->todo->batchEdit->form);
|
||||
$this->todoZen->batchEditFromTodoBatchEdit($formData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启待办事项
|
||||
* 开启待办事项。
|
||||
* Start a todo.
|
||||
*
|
||||
* @param string $todoID
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function start(string $todoID)
|
||||
public function start(string $todoID): int
|
||||
{
|
||||
$todoID = (int)$todoID;
|
||||
$todo = $this->todo->getByID($todoID);
|
||||
@@ -303,79 +204,86 @@ class todo extends control
|
||||
if(in_array($todo->type, array('bug', 'task', 'story'))) return $this->todoZen->printConfirm($todo);
|
||||
if(isonlybody()) return print(js::reload('parent.parent'));
|
||||
|
||||
echo js::reload('parent');
|
||||
return print(js::reload('parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活待办事项
|
||||
* 激活待办事项。
|
||||
* Activated a todo.
|
||||
*
|
||||
* @param string $todoID
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function activate(string $todoID)
|
||||
public function activate(string $todoID): int
|
||||
{
|
||||
$todoID = (int)$todoID;
|
||||
$todo = $this->todo->getByID($todoID);
|
||||
|
||||
if($todo->status == 'done' or $todo->status == 'closed') $this->todo->activate($todoID);
|
||||
if($todo->status == 'done' || $todo->status == 'closed')
|
||||
{
|
||||
$isActivate = $this->todo->activate($todoID);
|
||||
if($isActivate === false) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
}
|
||||
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success'));
|
||||
if(isonlybody()) return print(js::reload('parent.parent'));
|
||||
|
||||
echo js::reload('parent');
|
||||
return print(js::reload('parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭待办。
|
||||
* Closed todo.
|
||||
*
|
||||
* @param $todoID
|
||||
*
|
||||
* @param string $todoID
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function close($todoID)
|
||||
public function close(string $todoID): int
|
||||
{
|
||||
$todo = $this->todo->getById($todoID);
|
||||
$todoID = (int)$todoID;
|
||||
$todo = $this->todo->getByID($todoID);
|
||||
if($todo->status == 'done') $this->todo->close($todoID);
|
||||
if(isonlybody()) return print(js::reload('parent.parent'));
|
||||
echo js::reload('parent');
|
||||
|
||||
return print(js::reload('parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 指派待办.
|
||||
* 指派待办。
|
||||
* Assign todo.
|
||||
*
|
||||
* @param string $todoID
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function assignTo(string $todoID)
|
||||
public function assignTo(string $todoID): int
|
||||
{
|
||||
$todoID = (int)$todoID;
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$formData = form::data($this->config->todo->assignTo->form);
|
||||
$todo = $this->todoZen->beforeAssignTo($formData);
|
||||
|
||||
$todo->id = (int)$todoID;
|
||||
$res = $this->todoZen->doAssignTo($todo);
|
||||
if(!$res) return print(js::error(dao::getError()));
|
||||
$todo->id = $todoID;
|
||||
$isAssigned = $this->todoZen->doAssignTo($todo);
|
||||
if(!$isAssigned) return print(js::error(dao::getError()));
|
||||
|
||||
return print(js::reload('parent.parent'));
|
||||
}
|
||||
|
||||
$this->view->todo = $this->todo->getById((int)$todoID);
|
||||
$this->view->todo = $this->todo->getByID($todoID);
|
||||
$this->view->members = $this->loadModel('user')->getPairs('noclosed|noempty|nodeleted');
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->actions = $this->loadModel('action')->getList('todo', (int)$todoID);
|
||||
$this->view->actions = $this->loadModel('action')->getList('todo', $todoID);
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
$this->view->time = date::now();
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取待办的信息.
|
||||
* Get info of todo .
|
||||
* 获取待办的信息。
|
||||
* Get info of todo.
|
||||
*
|
||||
* @param string $todoID
|
||||
* @param string $from my|company
|
||||
@@ -383,9 +291,9 @@ class todo extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function view(string $todoID,string $from = 'company')
|
||||
public function view(string $todoID, string $from = 'company')
|
||||
{
|
||||
$todo = $this->todo->getById((int)$todoID, true);
|
||||
$todo = $this->todo->getByID((int)$todoID, true);
|
||||
|
||||
if(!$todo)
|
||||
{
|
||||
@@ -416,7 +324,6 @@ class todo extends control
|
||||
if(!isset($this->session->project)) $this->session->set('project', (int)key($projects));
|
||||
|
||||
$this->view->title = $account == $todo->account ? "{$this->lang->todo->common} #$todo->id $todo->name" : $this->lang->todo->common;
|
||||
$this->view->position[] = $this->lang->todo->view;
|
||||
$this->view->todo = $todo;
|
||||
$this->view->times = date::buildTimeList((int)$this->config->todo->times->begin, (int)$this->config->todo->times->end, 5);
|
||||
$this->view->from = $from;
|
||||
@@ -427,7 +334,7 @@ class todo extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除待办.
|
||||
* 删除待办。
|
||||
* Delete a todo.
|
||||
*
|
||||
* @param string $todoID
|
||||
@@ -437,28 +344,23 @@ class todo extends control
|
||||
*/
|
||||
public function delete(string $todoID, string $confirm = 'no')
|
||||
{
|
||||
$todoID = (int)$todoID;
|
||||
if($confirm == 'no')
|
||||
{
|
||||
return print(js::confirm($this->lang->todo->confirmDelete, $this->createLink('todo', 'delete', "todoID=(int)$todoID&confirm=yes")));
|
||||
return print(js::confirm($this->lang->todo->confirmDelete, $this->createLink('todo', 'delete', "todoID={$todoID}&confirm=yes")));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->todo->delete(TABLE_TODO, (int)$todoID);
|
||||
$this->todo->delete(TABLE_TODO, $todoID);
|
||||
|
||||
/* if ajax request, send result. */
|
||||
if($this->server->ajax)
|
||||
if(helper::isAjaxRequest())
|
||||
{
|
||||
$response = array();
|
||||
$response = array('result' => 'success', 'message' => '');
|
||||
if(dao::isError())
|
||||
{
|
||||
$response['result'] = 'fail';
|
||||
$response['message'] = dao::getError();
|
||||
}
|
||||
else
|
||||
{
|
||||
$response['result'] = 'success';
|
||||
$response['message'] = '';
|
||||
}
|
||||
return $this->send($response);
|
||||
}
|
||||
|
||||
@@ -480,7 +382,7 @@ class todo extends control
|
||||
*/
|
||||
public function finish(string $todoID)
|
||||
{
|
||||
$todo = $this->todo->getById((int)$todoID);
|
||||
$todo = $this->todo->getByID((int)$todoID);
|
||||
if($todo->status != 'done' && $todo->status != 'closed') $this->todo->finish((int)$todoID);
|
||||
|
||||
if(in_array($todo->type, array('bug', 'task', 'story')))
|
||||
@@ -488,15 +390,20 @@ class todo extends control
|
||||
$confirmNote = 'confirm' . ucfirst($todo->type);
|
||||
$okTarget = isonlybody() ? 'parent' : 'window.parent.$.apps.open';
|
||||
$confirmURL = $this->createLink($todo->type, 'view', "id=$todo->objectID");
|
||||
|
||||
if($todo->type == 'bug') $app = 'qa';
|
||||
if($todo->type == 'task') $app = 'execution';
|
||||
if($todo->type == 'story') $app = 'product';
|
||||
$cancelURL = $this->server->HTTP_REFERER;
|
||||
$cancelURL = $this->server->http_referer;
|
||||
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success', 'message' => sprintf($this->lang->todo->$confirmNote, $todo->objectID), 'locate' => $confirmURL));
|
||||
return print(strpos($cancelURL, 'calendar') ? json_encode(array(sprintf($this->lang->todo->$confirmNote, $todo->objectID), $confirmURL)) : js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->objectID), $confirmURL, $cancelURL, $okTarget, 'parent', $app));
|
||||
}
|
||||
|
||||
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success'));
|
||||
if(defined('RUN_MODE') && RUN_MODE == 'api')
|
||||
{
|
||||
$this->send(array('status' => 'success'));
|
||||
return;
|
||||
}
|
||||
if(isonlybody()) return print(js::reload('parent.parent'));
|
||||
echo js::reload('parent');
|
||||
}
|
||||
@@ -518,8 +425,8 @@ class todo extends control
|
||||
if($todo->status == 'done' || $todo->status == 'closed') unset($todoList[$todoID]);
|
||||
}
|
||||
|
||||
$res = $this->todo->batchFinish((array)array_keys($todoList));
|
||||
if(!$res) return false;
|
||||
$isBatchFinished = $this->todo->batchFinish(array_keys($todoList));
|
||||
if(!$isBatchFinished) return false;
|
||||
|
||||
return print(js::reload('parent'));
|
||||
}
|
||||
@@ -529,27 +436,27 @@ class todo extends control
|
||||
* Batch close todos. The status of todo which need to close should be done.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function batchClose(): void
|
||||
public function batchClose(): int
|
||||
{
|
||||
$waitIdList = array();
|
||||
$todoIdlist = form::data($this->config->todo->batchClose->form)->get('todoIDList');
|
||||
foreach($todoIdlist as $todoID)
|
||||
{
|
||||
$todoID = (int) $todoID;
|
||||
$todo = $this->todo->getById($todoID);
|
||||
$todo = $this->todo->getByID($todoID);
|
||||
if($todo->status == 'done') $this->todo->close($todoID);
|
||||
if($todo->status != 'done' and $todo->status != 'closed') $waitIdList[] = $todoID;
|
||||
}
|
||||
if(!empty($waitIdList)) echo js::alert(sprintf($this->lang->todo->unfinishedTodo, implode(',', $waitIdList)));
|
||||
|
||||
echo js::reload('parent');
|
||||
return print(js::reload('parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改选中待办的日期。
|
||||
* Import selected todoes to today.
|
||||
* Import selected todos to today.
|
||||
*
|
||||
* @param string $todoID
|
||||
* @access public
|
||||
@@ -559,10 +466,10 @@ class todo extends control
|
||||
{
|
||||
$todoIDList = $_POST ? $this->post->todoIDList : array($todoID);
|
||||
$date = !empty($_POST['date']) ? $_POST['date'] : date::today();
|
||||
if(!$date || !$todoIDList) $this->locate((string)$this->session->todoList);
|
||||
if(!$date || !$todoIDList) return $this->locate((string)$this->session->todoList);
|
||||
|
||||
$this->todo->editDate((array)$todoIDList, (string)$date);
|
||||
$this->locate((string)$this->session->todoList);
|
||||
return this->locate((string)$this->session->todoList);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -577,7 +484,7 @@ class todo extends control
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$user = $this->loadModel('user')->getById($userID, 'id');
|
||||
$user = $this->loadModel('user')->getByID($userID, 'id');
|
||||
$account = $user->account;
|
||||
|
||||
$todoLang = $this->lang->todo;
|
||||
|
||||
+44
-47
@@ -2,7 +2,7 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* The model file of example module of ZenTaoPMS.
|
||||
* The model file of todo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
@@ -128,7 +128,7 @@ class todoModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新待办数据
|
||||
* 更新待办数据。
|
||||
* update a todo.
|
||||
*
|
||||
* @param int $todoID
|
||||
@@ -138,7 +138,7 @@ class todoModel extends model
|
||||
*/
|
||||
public function update(int $todoID, object $todo): array|false
|
||||
{
|
||||
$oldTodo = $this->dao->findById($todoID)->from(TABLE_TODO)->fetch();
|
||||
$oldTodo = $this->dao->findByID($todoID)->from(TABLE_TODO)->fetch();
|
||||
|
||||
if(!$this->todoTao->updateRow($todoID, $todo)) return false;
|
||||
|
||||
@@ -271,8 +271,8 @@ class todoModel extends model
|
||||
{
|
||||
foreach($todoIDList as $todoID)
|
||||
{
|
||||
$res = $this->dealFinishData($todoID);
|
||||
if(!$res) return $res;
|
||||
$finishResult = $this->dealFinishData($todoID);
|
||||
if(!$finishResult) return $finishResult;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -288,20 +288,20 @@ class todoModel extends model
|
||||
*/
|
||||
public function getByID(int $todoID, $setImgSize = false): object|false
|
||||
{
|
||||
$todo = $this->dao->findById($todoID)->from(TABLE_TODO)->fetch();
|
||||
$todo = $this->dao->findByID($todoID)->from(TABLE_TODO)->fetch();
|
||||
if(!$todo) return false;
|
||||
|
||||
$todo = $this->loadModel('file')->replaceImgURL((object)$todo, 'desc');
|
||||
if($setImgSize) $todo->desc = $this->file->setImgSize($todo->desc);
|
||||
if($todo->type == 'story') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_STORY)->fetch('title');
|
||||
if($todo->type == 'task') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_TASK)->fetch('name');
|
||||
if($todo->type == 'bug') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_BUG)->fetch('title');
|
||||
if($todo->type == 'issue' and $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_ISSUE)->fetch('title');
|
||||
if($todo->type == 'risk' and $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_RISK)->fetch('name');
|
||||
if($todo->type == 'opportunity' and $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_OPPORTUNITY)->fetch('name');
|
||||
if($todo->type == 'review' and $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_REVIEW)->fetch('title');
|
||||
if($todo->type == 'testtask') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_TESTTASK)->fetch('name');
|
||||
if($todo->type == 'feedback') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_FEEDBACK)->fetch('title');
|
||||
if($todo->type == 'story') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_STORY)->fetch('title');
|
||||
if($todo->type == 'task') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_TASK)->fetch('name');
|
||||
if($todo->type == 'bug') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_BUG)->fetch('title');
|
||||
if($todo->type == 'issue' and $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_ISSUE)->fetch('title');
|
||||
if($todo->type == 'risk' and $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_RISK)->fetch('name');
|
||||
if($todo->type == 'opportunity' and $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_OPPORTUNITY)->fetch('name');
|
||||
if($todo->type == 'review' and $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_REVIEW)->fetch('title');
|
||||
if($todo->type == 'testtask') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_TESTTASK)->fetch('name');
|
||||
if($todo->type == 'feedback') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_FEEDBACK)->fetch('title');
|
||||
$todo->date = str_replace('-', '', $todo->date);
|
||||
|
||||
return $todo;
|
||||
@@ -412,15 +412,15 @@ class todoModel extends model
|
||||
|
||||
while($todo = $stmt->fetch())
|
||||
{
|
||||
if($todo->type == 'story') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_STORY)->fetch('title');
|
||||
if($todo->type == 'task') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_TASK)->fetch('name');
|
||||
if($todo->type == 'bug') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_BUG)->fetch('title');
|
||||
if($todo->type == 'testtask') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_TESTTASK)->fetch('name');
|
||||
if($todo->type == 'issue' && $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_ISSUE)->fetch('title');
|
||||
if($todo->type == 'risk' && $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_RISK)->fetch('name');
|
||||
if($todo->type == 'opportunity' && $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_OPPORTUNITY)->fetch('name');
|
||||
if($todo->type == 'review' && $this->config->edition == 'max') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_REVIEW)->fetch('title');
|
||||
if($todo->type == 'feedback' and $this->config->edition != 'open') $todo->name = $this->dao->findById($todo->objectID)->from(TABLE_FEEDBACK)->fetch('title');
|
||||
if($todo->type == 'story') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_STORY)->fetch('title');
|
||||
if($todo->type == 'task') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_TASK)->fetch('name');
|
||||
if($todo->type == 'bug') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_BUG)->fetch('title');
|
||||
if($todo->type == 'testtask') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_TESTTASK)->fetch('name');
|
||||
if($todo->type == 'issue' && $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_ISSUE)->fetch('title');
|
||||
if($todo->type == 'risk' && $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_RISK)->fetch('name');
|
||||
if($todo->type == 'opportunity' && $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_OPPORTUNITY)->fetch('name');
|
||||
if($todo->type == 'review' && $this->config->edition == 'max') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_REVIEW)->fetch('title');
|
||||
if($todo->type == 'feedback' and $this->config->edition != 'open') $todo->name = $this->dao->findByID($todo->objectID)->from(TABLE_FEEDBACK)->fetch('title');
|
||||
$todo->begin = date::formatTime($todo->begin);
|
||||
$todo->end = date::formatTime($todo->end);
|
||||
|
||||
@@ -556,18 +556,16 @@ class todoModel extends model
|
||||
{
|
||||
$isClosed = $this->todoTao->closeTodo($todoID);
|
||||
|
||||
if($isClosed)
|
||||
{
|
||||
$this->loadModel('action')->create('todo', $todoID, 'closed', '', 'closed');
|
||||
if(!$isClosed) return false;
|
||||
|
||||
if($this->config->edition == 'biz' || $this->config->edition == 'max')
|
||||
{
|
||||
$feedbackID = $this->dao->select('objectID')->from(TABLE_TODO)->where('id')->eq($todoID)->andWhere('type')->eq('feedback')->fetch('objectID');
|
||||
if($feedbackID) $this->loadModel('feedback')->updateStatus('todo', $feedbackID, 'closed');
|
||||
}
|
||||
return true;
|
||||
$this->loadModel('action')->create('todo', $todoID, 'closed', '', 'closed');
|
||||
|
||||
if($this->config->edition == 'biz' || $this->config->edition == 'max')
|
||||
{
|
||||
$feedbackID = $this->dao->select('objectID')->from(TABLE_TODO)->where('id')->eq($todoID)->andWhere('type')->eq('feedback')->fetch('objectID');
|
||||
if($feedbackID) $this->loadModel('feedback')->updateStatus('todo', $feedbackID, 'closed');
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -656,25 +654,24 @@ class todoModel extends model
|
||||
$todo->finishedBy = $this->app->user->account;
|
||||
$this->todoTao->updateRow($todoID, $todo);
|
||||
|
||||
if(!dao::isError())
|
||||
{
|
||||
$this->loadModel('action')->create('todo', $todoID, 'finished', '', 'done');
|
||||
if(dao::isError()) return false;
|
||||
|
||||
if(($this->config->edition == 'biz' || $this->config->edition == 'max'))
|
||||
{
|
||||
$todo = $this->todoTao->fetch($todoID);
|
||||
$feedbackID = $todo->idvalue ?? '' ;
|
||||
if($feedbackID) $this->loadModel('feedback')->updateStatus('todo', $feedbackID, 'done');
|
||||
}
|
||||
return true;
|
||||
$this->loadModel('action')->create('todo', $todoID, 'finished', '', 'done');
|
||||
|
||||
if(($this->config->edition == 'biz' || $this->config->edition == 'max'))
|
||||
{
|
||||
$todo = $this->todoTao->fetch($todoID);
|
||||
$feedbackID = $todo->idvalue ?? '' ;
|
||||
if($feedbackID) $this->loadModel('feedback')->updateStatus('todo', $feedbackID, 'done');
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** 修改待办事项的时间。
|
||||
/**
|
||||
* 修改待办事项的时间。
|
||||
* Edit the date of todo.
|
||||
*
|
||||
* @param array $idList
|
||||
* @param array $todoIDList
|
||||
* @param string $date
|
||||
* @access public
|
||||
* @return int
|
||||
|
||||
+16
-17
@@ -75,11 +75,10 @@ class todoTao extends todoModel
|
||||
->where('id')->eq($todoID)
|
||||
->exec();
|
||||
return !dao::isError();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 处理要创建的todo的数据
|
||||
/**
|
||||
* 处理要创建的todo的数据。
|
||||
* Process the data for the todo to be created.
|
||||
*
|
||||
* @param object $todoData
|
||||
@@ -118,13 +117,13 @@ class todoTao extends todoModel
|
||||
}
|
||||
if(empty($todoData->cycle)) unset($todoData->config);
|
||||
|
||||
$todoData = $this->loadModel('file')->processImgURL($todoData, $this->config->todo->editor->create['id'], $this->post->uid);
|
||||
return $todoData;
|
||||
return $this->loadModel('file')->processImgURL($todoData, $this->config->todo->editor->create['id'], $this->post->uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取周期待办列表
|
||||
* Get cycle list.
|
||||
* 获取周期待办列表。
|
||||
* Get cycle list.
|
||||
*
|
||||
* @param array $todoList
|
||||
* @param string $orderBy
|
||||
* @access protected
|
||||
@@ -132,18 +131,18 @@ class todoTao extends todoModel
|
||||
*/
|
||||
protected function getCycleList(array $todoList, string $orderBy = 'date_asc'): array
|
||||
{
|
||||
return $this->dao->select('*')
|
||||
->from(TABLE_TODO)->where('type')->eq('cycle')
|
||||
return $this->dao->select('*')->from(TABLE_TODO)
|
||||
->where('type')->eq('cycle')
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('objectID')->in(array_keys($todoList))
|
||||
->orderBy($orderBy)
|
||||
->fetchAll('objectID');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过待办构建周期待办数据
|
||||
* Build cycle todo.
|
||||
*
|
||||
* @param object $todo
|
||||
* @access protected
|
||||
* @return stdclass
|
||||
@@ -168,9 +167,9 @@ class todoTao extends todoModel
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过周期待办,获取要生成待办的日期
|
||||
*
|
||||
* 通过周期待办,获取要生成待办的日期。
|
||||
* Gets the date by the cycle todo.
|
||||
*
|
||||
* @param object $todo
|
||||
* @param object|string $lastCycle
|
||||
* @param string $today
|
||||
@@ -207,8 +206,7 @@ class todoTao extends todoModel
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过周期待办,获取要生成每日待办的日期
|
||||
*
|
||||
* 通过周期待办,获取要生成每日待办的日期。
|
||||
* Gets the daily todo date by the cycle todo.
|
||||
*
|
||||
* @param object $todo
|
||||
@@ -305,6 +303,7 @@ class todoTao extends todoModel
|
||||
return false;
|
||||
}
|
||||
$todoData->config['beforeDays'] = (int)$todoData->config['beforeDays'];
|
||||
|
||||
$todoData->config = json_encode($todoData->config);
|
||||
$todoData->type = 'cycle';
|
||||
|
||||
@@ -317,11 +316,11 @@ class todoTao extends todoModel
|
||||
*
|
||||
* @param array $idList
|
||||
* @param string $date
|
||||
* @return int
|
||||
* @return bool
|
||||
*/
|
||||
protected function updateDate(array $todoIdList, string $date): int
|
||||
protected function updateDate(array $todoIdList, string $date): bool
|
||||
{
|
||||
$this->dao->update(TABLE_TODO)->set('date')->eq($date)->where('id')->in($todoIdList)->exec();
|
||||
return dao::isError() ? 0 : 1;
|
||||
return !dao::isError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
include dirname(__FILE__, 2) . '/todo.class.php';
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
declare(strict_types=1);
|
||||
namespace zin;
|
||||
/**
|
||||
* The batch create view of todo module of ZenTaoPMS.
|
||||
* AssignTo view of todo module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
|
||||
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Yue Liu <liuyue@easycorp.ltd>
|
||||
* @package todo
|
||||
* @version $Id: create.html.php 2741 2012-04-07 07:24:21 $
|
||||
* @link http://www.zentao.net
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
set::title($lang->todo->assignedTo);
|
||||
|
||||
+136
-14
@@ -3,11 +3,39 @@ declare(strict_types=1);
|
||||
|
||||
class todoZen extends todo
|
||||
{
|
||||
/**
|
||||
* 生成创建待办视图数据。
|
||||
* Build create form data.
|
||||
*
|
||||
* @param string $date
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected function buildCreateForm(string $date): void
|
||||
{
|
||||
$this->view->title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->create;
|
||||
$this->view->date = date('Y-m-d', strtotime($date));
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->time = date::now();
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
|
||||
$this->display();
|
||||
}
|
||||
|
||||
protected function renderEditData(int $todoID)
|
||||
{
|
||||
$todo->date = date("Y-m-d", strtotime($todo->date));
|
||||
$this->view->title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->edit;
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->todo = $todo;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理请求数据
|
||||
* Processing request data.
|
||||
*
|
||||
* @process protected
|
||||
* @param object $formData
|
||||
* @access protected
|
||||
* @return object
|
||||
@@ -36,12 +64,13 @@ class todoZen extends todo
|
||||
->stripTags($this->config->todo->editor->create['id'], $this->config->allowedTags)
|
||||
->remove(implode(',', $this->config->todo->moduleList) . ',uid')
|
||||
->get();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a todo after data processing
|
||||
* 创建完成待办后数据处理
|
||||
* 创建完成待办后数据处理。
|
||||
* Create a todo after data processing.
|
||||
*
|
||||
* @param object $todo
|
||||
* @access protected
|
||||
@@ -65,7 +94,7 @@ class todoZen extends todo
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理编辑待办的请求数据
|
||||
* 处理编辑待办的请求数据。
|
||||
* Processing edit request data.
|
||||
*
|
||||
* @param int $todoID
|
||||
@@ -75,7 +104,7 @@ class todoZen extends todo
|
||||
*/
|
||||
protected function beforeEdit(int $todoID, object $formData): object|false
|
||||
{
|
||||
$oldTodo = $this->dao->findById($todoID)->from(TABLE_TODO)->fetch();
|
||||
$oldTodo = $this->dao->findByID($todoID)->from(TABLE_TODO)->fetch();
|
||||
|
||||
$objectID = 0;
|
||||
$rowData = $formData->rawdata;
|
||||
@@ -96,7 +125,7 @@ class todoZen extends todo
|
||||
->remove(implode(',', $this->config->todo->moduleList) . ',uid')
|
||||
->get();
|
||||
|
||||
$todo = (object) array_merge((array) $rowData, (array) $todo);
|
||||
$todo = (object)array_merge((array)$rowData, (array)$todo);
|
||||
|
||||
if(in_array($todo->type, $this->config->todo->moduleList))
|
||||
{
|
||||
@@ -114,9 +143,7 @@ class todoZen extends todo
|
||||
|
||||
if(!empty($oldTodo->cycle)) $this->handleCycleConfig($todo);
|
||||
|
||||
$todo = $this->loadModel('file')->processImgURL($todo, $this->config->todo->editor->edit['id'], $rowData->uid);
|
||||
|
||||
return $todo;
|
||||
return $this->loadModel('file')->processImgURL($todo, $this->config->todo->editor->edit['id'], $rowData->uid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,15 +162,109 @@ class todoZen extends todo
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
protected function batchEditFromMyTodo($type, $userID, $status)
|
||||
{
|
||||
/* Initialize vars. */
|
||||
$editedTodos = array();
|
||||
$todoIDList = array();
|
||||
$reviews = array();
|
||||
$columns = 7;
|
||||
|
||||
if($userID == '') $userID = $this->app->user->id;
|
||||
$user = $this->loadModel('user')->getById($userID, 'id');
|
||||
$account = $user->account;
|
||||
|
||||
if($this->config->edition == 'max') $reviews = $this->loadModel('review')->getUserReviewPairs($account);
|
||||
$allTodos = $this->todo->getList($type, $account, $status);
|
||||
if($this->post->todoIDList) $todoIDList = $this->post->todoIDList;
|
||||
|
||||
/* Initialize todos whose need to edited. */
|
||||
foreach($allTodos as $todo)
|
||||
{
|
||||
if(in_array($todo->id, $todoIDList))
|
||||
{
|
||||
$editedTodos[$todo->id] = $todo;
|
||||
if($todo->type != 'custom')
|
||||
{
|
||||
if(!isset($objectIDList[$todo->type])) $objectIDList[$todo->type] = array();
|
||||
$objectIDList[$todo->type][$todo->objectID] = $todo->objectID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$bugs = $this->bug->getUserBugPairs($account, true, 0, '', '', isset($objectIDList['bug']) ? $objectIDList['bug'] : '');
|
||||
$tasks = $this->task->getUserTaskPairs($account, 'wait,doing', '', isset($objectIDList['task']) ? $objectIDList['task'] : '');
|
||||
$storys = $this->loadModel('story')->getUserStoryPairs($account, 10, 'story', '', isset($objectIDList['story']) ? $objectIDList['story'] : '');
|
||||
if($this->config->edition != 'open') $this->view->feedbacks = $this->loadModel('feedback')->getUserFeedbackPairs($account, '', isset($objectIDList['feedback']) ? $objectIDList['feedback'] : '');
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$issues = $this->loadModel('issue')->getUserIssuePairs($account);
|
||||
$risks = $this->loadmodel('risk')->getUserRiskPairs($account);
|
||||
$opportunities = $this->loadmodel('opportunity')->getUserOpportunityPairs($account);
|
||||
}
|
||||
$testtasks = $this->loadModel('testtask')->getUserTestTaskPairs($account);
|
||||
|
||||
/* Judge whether the edited todos is too large. */
|
||||
$countInputVars = count($editedTodos) * $columns;
|
||||
$showSuhosinInfo = common::judgeSuhosinSetting($countInputVars);
|
||||
|
||||
unset($this->lang->todo->typeList['cycle']);
|
||||
/* Set Custom*/
|
||||
foreach(explode(',', $this->config->todo->list->customBatchEditFields) as $field) $customFields[$field] = $this->lang->todo->$field;
|
||||
$this->view->customFields = $customFields;
|
||||
$this->view->showFields = $this->config->todo->custom->batchEditFields;
|
||||
|
||||
/* Assign. */
|
||||
$title = $this->lang->todo->common . $this->lang->colon . $this->lang->todo->batchEdit;
|
||||
$position[] = html::a($this->createLink('my', 'todo'), $this->lang->my->todo);
|
||||
$position[] = $this->lang->todo->common;
|
||||
$position[] = $this->lang->todo->batchEdit;
|
||||
|
||||
if($showSuhosinInfo) $this->view->suhosinInfo = extension_loaded('suhosin') ? sprintf($this->lang->suhosinInfo, $countInputVars) : sprintf($this->lang->maxVarsInfo, $countInputVars);
|
||||
$this->view->bugs = $bugs;
|
||||
$this->view->tasks = $tasks;
|
||||
$this->view->storys = $storys;
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$this->view->issues = $issues;
|
||||
$this->view->risks = $risks;
|
||||
$this->view->opportunities = $opportunities;
|
||||
}
|
||||
$this->view->reviews = $reviews;
|
||||
$this->view->testtasks = $testtasks;
|
||||
$this->view->editedTodos = $editedTodos;
|
||||
$this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta);
|
||||
$this->view->time = date::now();
|
||||
$this->view->title = $title;
|
||||
$this->view->position = $position;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted|noempty');
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
protected function batchEditFromTodoBatchEdit($formData)
|
||||
{
|
||||
$allChanges = $this->todo->batchUpdate();
|
||||
foreach($allChanges as $todoID => $changes)
|
||||
{
|
||||
if(empty($changes)) continue;
|
||||
|
||||
$actionID = $this->loadModel('action')->create('todo', $todoID, 'edited');
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
return print(js::locate($this->session->todoList, 'parent'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理循环待办的配置文件
|
||||
* 处理周期待办的配置值。
|
||||
* Handle cycle config.
|
||||
*
|
||||
* @param object $todo
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function handleCycleConfig(object &$todo): void
|
||||
private function handleCycleConfig(object $todo): void
|
||||
{
|
||||
$todo->date = date('Y-m-d');
|
||||
$todo->config['begin'] = $todo->date;
|
||||
@@ -215,7 +336,7 @@ class todoZen extends todo
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出确认弹框
|
||||
* 输出确认弹框。
|
||||
* Output confirm alert.
|
||||
*
|
||||
* @param object $todo
|
||||
@@ -230,7 +351,8 @@ class todoZen extends todo
|
||||
if($todo->type == 'bug') $app = 'qa';
|
||||
if($todo->type == 'task') $app = 'execution';
|
||||
if($todo->type == 'story') $app = 'product';
|
||||
$cancelURL = $this->server->HTTP_REFERER;
|
||||
$cancelURL = $this->server->http_referer;
|
||||
|
||||
return print(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->objectID), $confirmURL, $cancelURL, $okTarget, 'parent', $app));
|
||||
}
|
||||
|
||||
@@ -244,7 +366,7 @@ class todoZen extends todo
|
||||
protected function getProjectPairsByModel(string $model): array
|
||||
{
|
||||
$model = $model == 'opportunity' ? 'waterfall' : 'all';
|
||||
return $this->loadModel('project')->getPairsByModel((string)$model);
|
||||
return $this->loadModel('project')->getPairsByModel($model);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,4 +3,4 @@ sonar.sourceEncoding=UTF-8
|
||||
sonar.qualitygate.wait=true
|
||||
sonar.coverage.exclusions=**/*.*
|
||||
sonar.inclusions=**/**.php
|
||||
sonar.exclusions=**/*.bak,**/*.sql,**/*.js,**/*.css,**/*.yaml,**/*.zip,**/*.out,**/lang/*,**/test/*
|
||||
sonar.exclusions=**/*.bak,**/*.sql,**/*.js,**/*.css,**/*.yaml,**/*.zip,**/*.out,**/lang/*,**/test/**
|
||||
|
||||
@@ -12,7 +12,7 @@ fields:
|
||||
note: "产品名称"
|
||||
fields:
|
||||
- field: name1
|
||||
range: []{20},已关闭的{20},[]{20},已关闭的{20},[]{20},已关闭的{20},[]{10},已关闭的{10},[]{10},已关闭的{10},[]{10},已关闭的{10},[]{20}
|
||||
range: "[]{20},已关闭的{20},[]{20},已关闭的{20},[]{20},已关闭的{20},[]{10},已关闭的{10},[]{10},已关闭的{10},[]{10},已关闭的{10},[]{20}"
|
||||
- field: name2
|
||||
range: 正常产品{40},多分支产品{40},多平台产品{40},独立测试项目{7},独立产品{53},[@#$%%&&*测试名称长度能有多长并且包含特殊字符的一个长长的字符串()!@#¥%……&*]{10},已删除产品{10}
|
||||
- field: name3
|
||||
@@ -40,7 +40,7 @@ fields:
|
||||
note: "产品描述"
|
||||
fields:
|
||||
- field: desc1
|
||||
range: []{30},产品描述{20}
|
||||
range: "[]{30},产品描述{20}"
|
||||
- field: desc2
|
||||
range: <div>
|
||||
<p><h1>一、禅道项目管理软件是做什么的?</h1>
|
||||
@@ -76,7 +76,7 @@ fields:
|
||||
range: open{10},private{10},open{10},private{10},open{10},private{10},open{10},private{10},open{10},private{10},open{10},private{10},open{5},private{5},open{5},private{5},open{5},private{5},open{5},private{5},open{5},private{5},open{5},private{5},open{20}
|
||||
- field: whitelist
|
||||
note: "分组白名单"
|
||||
range: []{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{20}
|
||||
range: "[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{15},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{5},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{7},`,test1,dev1,pm1,td1,pd2,qd2,top1,others1`{3},[]{20}"
|
||||
- field: createdBy
|
||||
note: "创建者"
|
||||
fields:
|
||||
|
||||
@@ -260,7 +260,10 @@ class yaml
|
||||
$pos = strripos($runFileName, DS);
|
||||
if($pos !== false) $runFileName = mb_substr($runFileName, $pos+1);
|
||||
|
||||
$this->configFiles[] = $_SERVER['PWD'] . "/yaml/$runFileName/{$fileName}.yaml";
|
||||
$backtrace = debug_backtrace();
|
||||
$runPath = $backtrace[count($backtrace)-1]['file'];
|
||||
|
||||
$this->configFiles[] = dirname($runPath) . "/yaml/$runFileName/{$fileName}.yaml";
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@
|
||||
{
|
||||
if(!DEBUG) return;
|
||||
|
||||
updateZinbar({id: options.id, trace: data.trace}, data.errors);
|
||||
updateZinbar({id: options.id, trace: data.trace, xhprof: data.xhprof}, data.errors);
|
||||
}
|
||||
|
||||
function updatePageWithHtml(data)
|
||||
|
||||
Reference in New Issue
Block a user