Merge branch 'master' into zenops_44

This commit is contained in:
caoyanyi
2022-08-26 13:38:13 +08:00
245 changed files with 2940 additions and 1521 deletions
+1 -1
View File
@@ -1 +1 @@
17.5
17.6
+4 -5
View File
@@ -20,9 +20,8 @@ class executionEntry extends Entry
*/
public function get($executionID)
{
$fields = $this->param('fields');
$productID = $this->param('productID');
$status = $this->param('status', 'all');
$fields = $this->param('fields');
$status = $this->param('status', 'all');
$control = $this->loadController('execution', 'view');
$control->view($executionID);
@@ -47,8 +46,8 @@ class executionEntry extends Entry
foreach($executionProduct->plans as $planID)
{
$plan = new stdclass();
$plan->id = $planID;
$plan->name = $data->data->planGroups->{$productID}->{$planID};
$plan->id = trim($planID, ',');
$plan->name = $data->data->planGroups->{$productID}->{$plan->id};
$product->plans[] = $plan;
}
$execution->products[] = $product;
+1 -1
View File
@@ -60,7 +60,7 @@ class programEntry extends Entry
public function delete($programID)
{
$control = $this->loadController('program', 'delete');
$control->delete(0, $programID, 'true');
$control->delete($programID, 'true');
$data = $this->getData();
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
+1 -1
View File
@@ -29,7 +29,7 @@ class tabsEntry extends baseEntry
foreach($tabs as $menuKey)
{
if(!isset($this->lang->my->$menuKey)) continue;
if(!common::hasPriv('my', $menuKey)) continue;
if(!common::hasPriv('my', 'work')) continue;
$label = $this->lang->my->$menuKey;
if($menuKey == 'calendar') $label = $this->lang->my->calendarAction;
+3 -3
View File
@@ -254,7 +254,7 @@ class userEntry extends Entry
if(!common::hasPriv('my', 'todo')) break;
$control = $this->loadController('my', 'todo');
$control->todo($this->param('date', 'all'), '', 'all', 'date_desc', 0, 0, $this->param('limit', 5), 1);
$control->todo($this->param('date', 'before'), '', 'all', 'date_desc', 0, $this->param('limit', 5), 1);
$data = $this->getData();
if($data->status == 'success')
@@ -313,7 +313,7 @@ class userEntry extends Entry
{
$this->config->openMethods[] = 'my.risk';
$control = $this->loadController('my', 'risk');
$control->risk('createdBy', 0, 'id_desc', 0, $this->param('limit', 5), 1);
$control->risk('assignedTo', 0, 'id_desc', 0, $this->param('limit', 5), 1);
$data = $this->getData();
if($data->status == 'success')
@@ -331,7 +331,7 @@ class userEntry extends Entry
{
$this->config->openMethods[] = 'my.myMeeting';
$control = $this->loadController('my', 'myMeeting');
$control->myMeeting('all', '', 'id_desc', 0, $this->param('limit', 5), 1);
$control->myMeeting('futureMeeting', '', 'id_desc', 0, $this->param('limit', 5), 1);
$data = $this->getData();
if($data->status == 'success')
+1 -1
View File
@@ -50,7 +50,7 @@ if($config->requestType == 'PATH_INFO')
{
$_SERVER['PATH_INFO'] = $path['basename'];
}
else
else
{
/* url like http://pms.zentao.net/zentao/my/, PATH_INFO is 'my'. */
if(is_dir('./module/' . $path['basename']))
+1 -1
View File
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
if(!function_exists('getWebRoot')){function getWebRoot(){}}
/* 基本设置。Basic settings. */
$config->version = '17.5'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->version = '17.6'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->liteVersion = '1.2'; // 迅捷版版本。 The version of Lite.
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
+3
View File
@@ -398,3 +398,6 @@ $config->programPriv->waterfall = array_merge($config->programPriv->scrum, array
$config->waterfallModules = array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'cm', 'milestone', 'design', 'opportunity', 'auditplan', 'trainplan', 'gapanalysis', 'pssp', 'researchplan', 'researchreport');
$config->showMainMenu = true;
$config->maxPriValue = '256';
$config->importWhiteList = array('user', 'task', 'story', 'bug', 'testcase', 'feedback');
+4 -4
View File
@@ -15,7 +15,7 @@ INSERT INTO `zt_action` (`id`, `objectType`, `objectID`, `product`, `project`, `
(11, 'story', 1, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:09:49', '', '', '0'),
(12, 'story', 2, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:16:37', '', '', '0'),
(13, 'story', 3, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:18:10', '', '', '0'),
(14, 'story', 3, ',1,', 0, 0, 'productManager', 'changed', '2012-06-05 10:19:06', '', '', '0'),
(14, 'story', 3, ',1,', 0, 0, 'productManager', 'changing', '2012-06-05 10:19:06', '', '', '0'),
(15, 'story', 4, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:20:16', '', '', '0'),
(16, 'story', 5, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:21:39', '', '', '0'),
(17, 'story', 6, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:23:11', '', '', '0'),
@@ -589,9 +589,9 @@ INSERT INTO `zt_story` (`id`, `parent`, `product`, `branch`, `module`, `plan`, `
(2, 0, 1, 0, 2, '1', 'po', '', 0, '新闻中心的设计和开发。', '', 'story', 1, 1, 'active', '', '', 'projected', '', '', 'productManager', '2012-06-05 10:16:37', 'productManager', '2012-06-05 10:16:37', 'productManager', '2012-06-05 10:25:33', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(3, 0, 1, 0, 3, '1', 'po', '', 0, '成果展示的设计和开发', '', 'story', 1, 0, 'active', '', '', 'developing', '', '', 'productManager', '2012-06-05 10:18:10', 'productManager', '2012-06-05 10:18:10', 'productManager', '2012-06-05 10:25:38', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 2, '0', '0'),
(4, 0, 1, 0, 4, '1', 'po', '', 0, '售后服务的设计和开发', '', 'story', 1, 1, 'active', '', '', 'developed', '', '', 'productManager', '2012-06-05 10:20:16', 'productManager', '2012-06-05 10:20:16', 'productManager', '2012-06-05 10:25:42', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(5, 0, 1, 0, 5, '1', 'po', '', 0, '诚聘英才的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:21:39', 'productManager', '2012-06-05 10:21:39', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(6, 0, 1, 0, 6, '1', 'po', '', 0, '合作洽谈的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:23:11', 'productManager', '2012-06-05 10:23:11', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(7, 0, 1, 0, 7, '1', 'po', '', 0, '关于我们的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:24:19', 'productManager', '2012-06-05 10:24:19', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0');
(5, 0, 1, 0, 5, '1', 'po', '', 0, '诚聘英才的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:21:39', 'productManager', '2012-06-05 10:21:39', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(6, 0, 1, 0, 6, '1', 'po', '', 0, '合作洽谈的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:23:11', 'productManager', '2012-06-05 10:23:11', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(7, 0, 1, 0, 7, '1', 'po', '', 0, '关于我们的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:24:19', 'productManager', '2012-06-05 10:24:19', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0');
INSERT INTO `zt_storyspec` (`story`, `version`, `title`, `spec`, `verify`) VALUES
(1, 1, '首页设计和开发', '作为一名本公司的用户,我希望可以在首页看到该公司网站的基本内容,例如最新动态、部分成果展示、联系信息、工商信息等。<br />', '开发并通过验收<br />'),
(2, 1, '新闻中心的设计和开发。', '作为一名本公司的用户,我希望可以在新闻中心看到该公司网站的企业新闻,这样可以通过新闻了解企业的最新动态。<br />', ''),
+4 -4
View File
@@ -15,7 +15,7 @@ INSERT INTO `zt_action` (`id`, `objectType`, `objectID`, `product`, `project`, `
(11, 'story', 1, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:09:49', '', '', '0'),
(12, 'story', 2, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:16:37', '', '', '0'),
(13, 'story', 3, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:18:10', '', '', '0'),
(14, 'story', 3, ',1,', 0, 0, 'productManager', 'changed', '2012-06-05 10:19:06', '', '', '0'),
(14, 'story', 3, ',1,', 0, 0, 'productManager', 'changing', '2012-06-05 10:19:06', '', '', '0'),
(15, 'story', 4, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:20:16', '', '', '0'),
(16, 'story', 5, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:21:39', '', '', '0'),
(17, 'story', 6, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:23:11', '', '', '0'),
@@ -589,9 +589,9 @@ INSERT INTO `zt_story` (`id`, `parent`, `product`, `branch`, `module`, `plan`, `
(2, 0, 1, 0, 2, '1', 'po', '', 0, '新闻中心的设计和开发。', '', 'story', 1, 1, 'active', '', '', 'projected', '', '', 'productManager', '2012-06-05 10:16:37', 'productManager', '2012-06-05 10:16:37', 'productManager', '2012-06-05 10:25:33', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(3, 0, 1, 0, 3, '1', 'po', '', 0, '成果展示的设计和开发', '', 'story', 1, 0, 'active', '', '', 'developing', '', '', 'productManager', '2012-06-05 10:18:10', 'productManager', '2012-06-05 10:18:10', 'productManager', '2012-06-05 10:25:38', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 2, '0', '0'),
(4, 0, 1, 0, 4, '1', 'po', '', 0, '售后服务的设计和开发', '', 'story', 1, 1, 'active', '', '', 'developed', '', '', 'productManager', '2012-06-05 10:20:16', 'productManager', '2012-06-05 10:20:16', 'productManager', '2012-06-05 10:25:42', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(5, 0, 1, 0, 5, '1', 'po', '', 0, '诚聘英才的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:21:39', 'productManager', '2012-06-05 10:21:39', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(6, 0, 1, 0, 6, '1', 'po', '', 0, '合作洽谈的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:23:11', 'productManager', '2012-06-05 10:23:11', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(7, 0, 1, 0, 7, '1', 'po', '', 0, '关于我们的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:24:19', 'productManager', '2012-06-05 10:24:19', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0');
(5, 0, 1, 0, 5, '1', 'po', '', 0, '诚聘英才的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:21:39', 'productManager', '2012-06-05 10:21:39', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(6, 0, 1, 0, 6, '1', 'po', '', 0, '合作洽谈的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:23:11', 'productManager', '2012-06-05 10:23:11', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'),
(7, 0, 1, 0, 7, '1', 'po', '', 0, '关于我们的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:24:19', 'productManager', '2012-06-05 10:24:19', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0');
INSERT INTO `zt_storyspec` (`story`, `version`, `title`, `spec`, `verify`) VALUES
(1, 1, '首页设计和开发', '作为一名本公司的用户,我希望可以在首页看到该公司网站的基本内容,例如最新动态、部分成果展示、联系信息、工商信息等。<br />', '开发并通过验收<br />'),
(2, 1, '新闻中心的设计和开发。', '作为一名本公司的用户,我希望可以在新闻中心看到该公司网站的企业新闻,这样可以通过新闻了解企业的最新动态。<br />', ''),
+4
View File
@@ -1,3 +1,7 @@
ALTER TABLE `zt_story` MODIFY `status` enum('','changed','active','draft','closed','reviewing') NOT NULL DEFAULT '' AFTER `estimate`;
UPDATE `zt_story` SET `status` = 'reviewing' WHERE `status` = 'changed';
ALTER TABLE `zt_story` MODIFY `status` enum('','changing','active','draft','closed','reviewing') NOT NULL DEFAULT '' AFTER `estimate`;
ALTER TABLE `zt_feedback` ADD `repeatFeedback` mediumint(8) NOT NULL DEFAULT 0 AFTER `feedbackBy`;
ALTER TABLE `zt_assetlib` ADD `order` SMALLINT UNSIGNED NOT NULL DEFAULT '0' AFTER `desc`;
+5 -2
View File
@@ -791,6 +791,7 @@ CREATE TABLE IF NOT EXISTS `zt_job` (
`lastExec` datetime DEFAULT NULL,
`lastStatus` varchar(255) DEFAULT NULL,
`lastTag` varchar(255) DEFAULT NULL,
`lastSyncDate` datetime DEFAULT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -1442,7 +1443,7 @@ CREATE TABLE IF NOT EXISTS `zt_story` (
`category` varchar(30) NOT NULL default 'feature',
`pri` tinyint(3) unsigned NOT NULL default '3',
`estimate` float unsigned NOT NULL,
`status` enum('','changed','active','draft','closed') NOT NULL default '',
`status` enum('','changing','active','draft', 'reviewing', 'closed') NOT NULL default '',
`subStatus` varchar(30) NOT NULL default '',
`color` char(7) NOT NULL,
`stage` enum('','wait','planned','projected','developing','developed','testing','tested','verified','released', 'closed') NOT NULL DEFAULT 'wait',
@@ -1908,7 +1909,8 @@ INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type
('1', '0', '*', '*', '*', 'moduleName=ci&methodName=initQueue', '创建周期性任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=checkCompileStatus', '同步DevOps构建任务状态', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=exec', '执行DevOps构建任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
('*/5', '*', '*', '*', '*', 'moduleName=mr&methodName=syncMR', '定时同步GitLab合并数据到禅道数据库', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
('*/5', '*', '*', '*', '*', 'moduleName=mr&methodName=syncMR', '定时同步GitLab合并数据到禅道数据库', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
('*/5', '*', '*', '*', '*', 'moduleName=compile&methodName=syncCompile', '定时同步构建记录', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
INSERT INTO `zt_group` (`id`, `vision`, `name`, `role`, `desc`) VALUES
(1, 'rnd', 'ADMIN', 'admin', 'for administrator'),
@@ -7089,6 +7091,7 @@ CREATE TABLE IF NOT EXISTS `zt_feedback` (
`assignedTo` varchar(255) NOT NULL,
`assignedDate` datetime NOT NULL,
`feedbackBy` varchar(100) NOT NULL,
`repeatFeedback` mediumint(8) NOT NULL DEFAULT 0,
`mailto` varchar(255) NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
+121
View File
@@ -1,3 +1,124 @@
2022-08-25 17.6
完成的需求
开源版:
30520 用户需求和研发需求权限区分
30718 我的地盘软件需求列表区块软件需求列表中将草稿状态调整为评审中,新增草稿状态的需求展示
30721 贡献列表中用户需求和软件需求列表中将草稿状态调整为评审中
30722 提软件需求和提用户需求页面中增加存为草稿按钮
30724 草稿状态的需求详情中增加提交评审操作
30725 软件需求和用户需求列表筛选标签中将草稿标签调整为评审中
30726 软件需求和用户需求列表筛选标签中增加草稿标签
30727 计划关联需求时搜索列表中将草稿调整为评审中
30729 需求报表中按状态进行统计表中将草稿调整为评审中,新增草稿状态的统计
30730 release关联需求时过滤掉草稿和评审中状态的需求
30731 项目关联需求时过滤掉草稿和评审中状态的需求
30732 项目需求列表中通过新增需求,可以展示草稿和评审中的需求
30733 执行关联需求时过滤掉草稿和评审中状态的需求
30734 执行需求列表中通过新增需求后可以展示草稿和评审中状态的需求
30735 Scrum看板的需求类泳道中通过新增需求可以展示草稿和评审中状态的需求
30736 专业研发看板的需求类泳道中通过新增需求可以展示草稿和评审中状态的需求
30737 build关联需求时过滤掉草稿和评审中状态的需求
30738 年度总结报表中需求状态分布中将草稿状态调整为评审中,新增草稿状态
30739 产品统计报表中产品汇总表中将草稿状态调整为评审中,新增草稿状态
30740 产品统计报表中产品需求状态分布表中将草稿状态调整为评审中,新增草稿状态
30741 项目统计报表中项目需求状态分布表中将草稿状态调整为评审中,新增草稿状态
30743 草稿状态对应需求阶段的规则
31134 新增的草稿状态需求不受强制评审流程控制
31251 实现草稿状态需求的提交评审功能
34650 产品列表中用户需求和研发需求增加评审中状态
34651 产品概况中其他信息模块软需维度优化
34896 软件需求状态“已变更”调整为“变更中”
34897 用户需求状态“已变更”调整为“变更中”
34898 已关闭的软件需求激活后状态可以选择“激活”或者关闭前的状态
34899 已关闭的用户需求激活后状态可以选择“激活”或者关闭前的状态
34900 软需从草稿提交评审,根据不同评审结果进行后续处理
34901 用需从草稿提交评审,根据不同评审结果进行后续处理
34902 软件需求草稿状态时按钮调整
34903 软件需求评审中状态时按钮调整
34904 软件需求变更中状态时按钮调整
34922 软件需求激活状态时按钮调整
34924 用户需求草稿状态时按钮调整
34925 用户需求评审中状态时按钮调整
34926 用户需求变更中状态时按钮调整
34927 用户需求激活状态时按钮调整
34931 Bug转需求时可以保存为草稿
34933 已关闭的需求激活后指派人不能选择closed
34934 需求变更评审时,系统根据需求不同评审结果进行后续处理
34935 草稿需求评审时,评审人可选择确认通过、有待明确、拒绝
35080 创建bug页面操作系统、浏览器支持多选
35278 执行中转入任务页面增加分页展示
35301 回收站的执行列表中增加所属项目字段
35320 需求草稿状态时可以修改草稿内容
35321 发起人对变更流程提交至”评审中“的需求选择撤销后需求根据状态回溯到不同内容
35356 父阶段状态跟随子阶段状态自动更改
35413 文档切换所属文档库时需要同步附件
35821 回收站的任务列表中增加所属执行字段
35887 关闭的bug指派人显示closed,不可编辑
35908 在搜索表单中通过日期字段检索时去掉00:00:00的格式
35935 修改零用例软需和矩阵的权限位置
35998 更新bug中操作系统码值
35999 更新bug中浏览器码值
36111 bug编辑页面可以关联用例
36184 测试单列表增加项目信息展示
36188 需求按照优先级排序时,空值放最后
36189 Bug按照优先级或严重程度排序时,空值放最后
36190 用例关联bug和用例页增加分页
36522 注册系统管理员的密码规则同系统中中级密码强度
企业版:
28045 反馈关闭原因为重复时,增加重复反馈输入的选项
30523 反馈转Bug时取消选择项目弹窗直接进入提Bug页面
30912 地盘日志列表新建日志时可以搜索该用户参与的所有执行
31984 反馈增加批量导入功能
33940 反馈增加导出模板功能
34296 提交反馈默认公开
34844 组织日志菜单下增加增加未填写日志成员的选项
34998 反馈导出时的时间支持精确到分秒
35024 用户需求和研发需求的导出数据增加类别字段
35083 执行甘特图支持在图上用连接的方式维护任务关系
35861 甘特图全屏样式优化
36185 执行甘特图查看任务关系维护按钮、设置按钮、甘特图按钮优化
36581 任务工时明细表的横向滚动条置顶显示
36618 有编辑他人反馈权限,可以批量编辑他人反馈
旗舰版:
30432 瀑布项目设计功能类型支持自定义功能
34682 资产库可以排序
修复的Bug
26232 执行软件需求列表简单表格下横向滚动条显示遮挡
26272 地盘待处理/贡献研发需求列表中,子需求的名称和所属产品未显示title
26380 复制项目时项目计划起止日期还是受项目集计划起止日期限制
26448 列表设置弹窗界面高度需要优化
26614 编辑项目页面计划起止日期/预算提示文案样式优化
26618 创建测试任务时可以选择到已创建测试任务的需求
26644 超出项目集计划起止日期提示换行
26645 鼠标悬浮在附上时页面抖动
25925 执行信息确认页面,日期选择后控件没有自动收起
25929 敏捷项目和迭代设置中的白名单列表没有被复制
25969 阶段信息确认页面没有显示已有的阶段负责人和阶段类型
25974 阶段信息确认页面修改负责人后,没有按照修改后的负责人进行显示
25989 英文下迭代信息确认页面表头显示优化
25996 复制项目时,执行信息确认页面执行的状态默认设置应该为未开始
25999 复制项目时,执行信息确认页面没有校验计划开始结束时间的先后
26032 项目中发起评审,弹窗字段未居中
26034 英文下项目中发起审批,文本换行
26054 英德法下甘特图页面报错
26057 英德法下甘特图页面没有显示分组选项
26303 复制迭代时间控件一直显示
26326 甘特图阶段工期计算错误
26327 阶段甘特图中任务工期计算错误
26365 项目计划评审页面自定义表单设置样式问题
26580 评审项目计划页面甘特图切换为按指派给分组跳转到了阶段甘特图页面
26638 甘特图拖动排序历史记录没有写中文语言项
26655 瀑布项目设计三级导航不高亮了
25961 迅捷页面用户授权异常
26200 自定义库目录修改所属文档库到wiki库不能查看
26221 导出数据的excel中,“抄送给”显示成了用户名
26265 导入大数据测试用例页面有报错
26278 导入文件超出PHP最大上传大小时没有提示
26364 编辑项目页面有代码报错
26371 导出的需求,用户名的显示不一致
26424 导入用例页面无影响,提示PHPExcel原因
26657 不能批量编辑他人反馈
2022-08-11 17.5
完成的需求
开源版:
@@ -261,6 +261,7 @@ $lang->resource->story->delete = 'deleteAction';
$lang->resource->story->view = 'view';
$lang->resource->story->change = 'changeAction';
$lang->resource->story->review = 'reviewAction';
$lang->resource->story->submitReview = 'submitReview';
$lang->resource->story->batchReview = 'batchReview';
$lang->resource->story->recall = 'recall';
$lang->resource->story->assignTo = 'assignAction';
@@ -289,6 +290,7 @@ $lang->story->methodOrder[25] = 'delete';
$lang->story->methodOrder[30] = 'view';
$lang->story->methodOrder[35] = 'change';
$lang->story->methodOrder[40] = 'review';
$lang->story->methodOrder[44] = 'submitReview';
$lang->story->methodOrder[45] = 'batchReview';
$lang->story->methodOrder[50] = 'recall';
$lang->story->methodOrder[55] = 'close';
+3 -2
View File
@@ -95,8 +95,9 @@
}
else
{
$class = ($task->executionType == 'kanban') ? 'iframe' : '';
echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', true, $task->project), $task->name, null, "class='$class' data-width='80%' style='color: $task->color'");
$onlybody = $task->executionType == 'kanban' ? true : '';
$class = $task->executionType == 'kanban' ? 'iframe' : '';
echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', $onlybody, $task->project), $task->name, null, "class='$class' data-width='80%' style='color: $task->color'");
}
?>
<?php if(!empty($task->children)) echo '<a class="task-toggle" data-id="' . $task->id . '"><i class="icon icon-angle-double-right"></i></a>';?>
@@ -85,7 +85,8 @@
<tfoot>
<tr>
<td colspan="7" class="text-center form-actions">
<?php echo html::submitButton($lang->save);?>
<?php echo html::commonButton($lang->save, "id='saveButton'", 'btn btn-primary btn-wide');?>
<?php echo html::commonButton($lang->story->saveDraft, "id='saveDraftButton'", 'btn btn-secondary btn-wide');?>
<?php echo html::backButton();?>
</td>
</tr>
+18 -20
View File
@@ -24,13 +24,21 @@
<div class="center-block">
<div class="main-header">
<h2><?php echo $lang->story->create;?></h2>
<?php if(!$this->story->checkForceReview()):?>
<div class="needNotReviewBox">
<div class='checkbox-primary'>
<input id='needNotReview' name='needNotReview' value='1' type='checkbox' class='no-margin' <?php echo $needReview;?>/>
<label for='needNotReview'><?php echo $lang->story->needNotReview;?></label>
</div>
</div>
<?php endif;?>
</div>
<form class="load-indicator main-form form-ajax" method='post' enctype='multipart/form-data' id='dataform'>
<table class="table table-form">
<tbody>
<tr>
<th><?php echo $lang->story->module;?></th>
<td>
<td colspan='2'>
<div class='input-group' id='moduleIdBox'>
<?php
echo html::select('module', $moduleOptionMenu, $moduleID, "class='form-control chosen'");
@@ -39,7 +47,7 @@
echo "<div class='input-group-addon'>";
echo html::a($this->createLink('tree', 'browse', "rootID=$productID&view=story&currentModuleID=0&branch=$branch", '', true), $lang->tree->manage, '', "class='text-primary' data-toggle='modal' data-type='iframe' data-width='90%'");
echo '&nbsp; ';
echo html::a("javascript:void(0)", $lang->refresh, '', "class='refresh' onclick='loadProductModules($productID)'");
echo html::a("javascript:void(0)", $lang->refreshIcon, '', "class='refresh' title='refresh' onclick='loadProductModules($productID)'");
echo '</div>';
}
?>
@@ -48,21 +56,13 @@
</tr>
<tr>
<th><?php echo $lang->story->reviewedBy;?></th>
<td colspan='<?php echo $type == 'story' ? 4 : 2;?>' id='reviewerBox'>
<td colspan='2' id='reviewerBox'>
<div class="table-row">
<?php $required = $this->story->checkForceReview() ? 'required' : '';?>
<?php echo $this->story->checkForceReview() ? '' : html::hidden('needNotReview', 1);?>
<div class="table-col">
<?php echo html::select('reviewer[]', $reviewers, empty($needReview) ? $product->PO : '', "class='form-control chosen' multiple");?>
<?php echo html::select('reviewer[]', $reviewers, empty($needReview) ? $product->PO : '', "class='form-control picker-select' multiple $required");?>
</div>
<?php if(!$this->story->checkForceReview()):?>
<div class="table-col w-130px">
<span class="input-group-addon" style="border: 1px solid #dcdcdc; border-left-width: 0px;">
<div class='checkbox-primary'>
<input id='needNotReview' name='needNotReview' value='1' type='checkbox' class='no-margin' <?php echo $needReview;?>/>
<label for='needNotReview'><?php echo $lang->story->needNotReview;?></label>
</div>
</span>
</div>
<?php endif;?>
</div>
</td>
</tr>
@@ -134,10 +134,6 @@
<?php echo html::textarea('spec', $spec, "rows='9' class='form-control kindeditor disabled-ie-placeholder' hidefocus='true' placeholder='" . htmlSpecialString($lang->noticePasteImg) . "'");?>
</td>
</tr>
<tr class='hide'>
<th><?php echo $lang->story->status;?></th>
<td><?php echo html::hidden('status', 'draft');?></td>
</tr>
<?php $this->printExtendFields('', 'table', 'columns=4');?>
<tr>
<th><?php echo $lang->story->legendAttatch;?></th>
@@ -147,7 +143,7 @@
<th><?php echo $lang->story->mailto;?></th>
<td colspan="4">
<div class="input-group">
<?php echo html::select('mailto[]', $users, str_replace(' ' , '', $mailto), "class='form-control chosen' data-placeholder='{$lang->chooseUsersToMail}' multiple");?>
<?php echo html::select('mailto[]', $users, str_replace(' ' , '', $mailto), "class='form-control picker-select' data-placeholder='{$lang->chooseUsersToMail}' multiple");?>
<?php echo $this->fetch('my', 'buildContactLists');?>
</div>
</td>
@@ -162,10 +158,12 @@
<tfoot>
<tr>
<td colspan="5" class="text-center form-actions">
<?php echo html::hidden('type', $type) . html::submitButton();?>
<?php echo html::hidden('type', $type);?>
<?php echo html::hidden('product', $productID);?>
<?php echo html::hidden('plan', $planID);?>
<?php echo html::hidden('vision', 'lite');?>
<?php echo html::commonButton($lang->save, "id='saveButton'", 'btn btn-primary btn-wide');?>
<?php echo html::commonButton($lang->story->saveDraft, "id='saveDraftButton'", 'btn btn-secondary btn-wide');?>
<?php echo html::backButton();?>
</td>
</tr>
+49 -10
View File
@@ -14,14 +14,16 @@
<?php include $this->app->getModuleRoot() . 'common/view/kindeditor.html.php';?>
<?php js::set('page', 'edit')?>
<?php js::set('oldProductID', $story->product);?>
<?php js::set('storyID', $story->id);?>
<?php js::set('parentStory', !empty($story->children));?>
<?php js::set('moveChildrenTips', $lang->story->moveChildrenTips);?>
<?php js::set('rawModule', $this->app->rawModule);?>
<?php js::set('reviewedReviewer', $reviewedReviewer);?>
<?php js::set('storyModule', $lang->story->module);?>
<?php js::set('reviewers', explode(',', $reviewers));?>
<?php js::set('reviewers', $reviewers);?>
<?php js::set('reviewerNotEmpty', $lang->story->notice->reviewerNotEmpty);?>
<?php js::set('feedbackSource', $config->story->feedbackSource); ?>
<?php js::set('storyStatus', $story->status);?>
<div class='main-content' id='mainContent'>
<form method='post' enctype='multipart/form-data' target='hiddenwin' id='dataform'>
<div class='main-header'>
@@ -34,7 +36,7 @@
<div class='main-row'>
<div class='main-col col-8'>
<div class='cell'>
<div class='form-group'>
<div class='form-group titleBox'>
<div class="input-control has-icon-right">
<div class="colorpicker">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown" title="<?php echo $lang->task->colorTag ?>"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
@@ -43,12 +45,40 @@
</ul>
<input type="hidden" class="colorpicker" id="color" name="color" value="<?php echo $story->color ?>" data-icon="color" data-wrapper="input-control-icon-right" data-update-color=".story-title" data-provide="colorpicker">
</div>
<?php echo html::input('title', $story->title, 'class="form-control disabled story-title" disabled="disabled"');?>
<?php echo html::input('title', $story->title, 'class="form-control disabled story-title"' . (strpos('draft,changing', $story->status) !== false ? '' : ' disabled="disabled"'));?>
</div>
</div>
<?php if(strpos('draft,changing', $story->status) !== false):?>
<div class='detail'>
<div class='detail-title'><?php echo $lang->story->reviewers;?></div>
<div class='detail-content'>
<div class="table-row">
<?php if(!$this->story->checkForceReview()):?>
<div class="table-col">
<?php echo html::select('reviewer[]', $productReviewers, $reviewers, 'class="form-control picker-select" multiple')?>
</div>
<div class="table-col needNotReviewBox">
<span class="input-group-addon" style="border: 1px solid #dcdcdc; border-left-width: 0px;">
<div class='checkbox-primary'>
<input id='needNotReview' name='needNotReview' value='1' type='checkbox' class='no-margin' <?php echo empty($reviewers) ? 'checked' : '';?>/>
<label for='needNotReview'><?php echo $lang->story->needNotReview;?></label>
</div>
</span>
</div>
<?php else:?>
<div class="table-col">
<?php echo html::select('reviewer[]', $productReviewers, $reviewers, 'class="form-control picker-select" multiple required')?>
</div>
<?php endif;?>
</div>
</div>
</div>
<?php endif;?>
<div class='detail'>
<div class='detail-title'><?php echo $lang->story->legendSpec;?></div>
<div class='detail-content article-content'><?php echo $story->spec;?></div>
<div class='detail-content article-content'>
<?php echo strpos('draft,changing', $story->status) !== false ? html::textarea('spec', htmlSpecialString($story->spec), "rows='5' class='form-control'") : $story->spec;?>
</div>
</div>
<?php $this->printExtendFields($story, 'div', 'position=left');?>
<div class='detail'>
@@ -61,7 +91,15 @@
<?php
echo html::hidden('lastEditedDate', $story->lastEditedDate);
echo html::hidden('product', $story->product);
echo html::submitButton($lang->save);
if(strpos('draft,changing', $story->status) !== false)
{
echo html::commonButton($lang->save, "id='saveButton'", 'btn btn-primary btn-wide');
echo html::commonButton($story->status == 'changing' ? $lang->story->doNotSubmit : $lang->story->saveDraft, "id='saveDraftButton'", 'btn btn-secondary btn-wide');
}
else
{
echo html::submitButton($lang->save);
}
if(!isonlybody()) echo html::backButton();
?>
</div>
@@ -85,7 +123,7 @@
echo "<span class='input-group-addon'>";
echo html::a($this->createLink('tree', 'browse', "rootID=$story->product&view=story&currentModuleID=0&branch=$story->branch", '', true), $lang->tree->manage, '', "class='text-primary' data-toggle='modal' data-type='iframe' data-width='95%'");
echo '&nbsp; ';
echo html::a("javascript:void(0)", $lang->refresh, '', "class='refresh' onclick='loadProductModules($story->product)'");
echo html::a("javascript:void(0)", $lang->refreshIcon, '', "class='refresh' title='$lang->refresh' onclick='loadProductModules($story->product)'");
echo '</span>';
}
?>
@@ -129,7 +167,7 @@
<th><?php echo $lang->story->mailto;?></th>
<td>
<div class='input-group'>
<?php echo html::select('mailto[]', $users, str_replace(' ' , '', $story->mailto), "class='form-control chosen' multiple");?>
<?php echo html::select('mailto[]', $users, str_replace(' ' , '', $story->mailto), "class='form-control picker-select' multiple");?>
<?php echo $this->fetch('my', 'buildContactLists');?>
</div>
</td>
@@ -145,12 +183,13 @@
</tr>
<tr>
<th><?php echo $lang->story->assignedTo;?></th>
<td><?php echo html::select('assignedTo', $users, $story->assignedTo, 'class="form-control chosen"');?></td>
<?php $assignedToList = $story->status == 'closed' ? $users + array('closed' => 'Closed') : $users;?>
<td><?php echo html::select('assignedTo', $assignedToList, $story->assignedTo, 'class="form-control chosen"');?></td>
</tr>
<?php if($isShowReviewer):?>
<?php if($story->status == 'reviewing'):?>
<tr>
<th><?php echo $lang->story->reviewers;?></th>
<td><?php echo html::select('reviewer[]', $productReviewers, $reviewers, 'class="form-control chosen" multiple')?></td>
<td><?php echo html::select('reviewer[]', $productReviewers, $reviewers, 'class="form-control picker-select" multiple')?></td>
</tr>
<?php endif;?>
<?php if($story->status == 'closed'):?>
+29 -4
View File
@@ -108,7 +108,14 @@
<td class='c-actions'>
<?php
common::printIcon('story', 'change', "storyID=$child->id", $child, 'list', 'alter');
common::printIcon('story', 'review', "storyID=$child->id", $child, 'list', 'search', '', 'iframe showinonlybody', true);
if(strpos('draft,changing', $child->status) !== false)
{
common::printIcon('story', 'submitReview', "storyID=$child->id", $child, 'list', 'sub-review', '', 'iframe showinonlybody', true);
}
else
{
common::printIcon('story', 'review', "storyID=$child->id", $child, 'list', 'search', '', 'iframe showinonlybody', true);
}
common::printIcon('story', 'assignTo', "storyID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true);
common::printIcon('story', 'close', "storyID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true);
common::printIcon('story', 'activate', "storyID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true);
@@ -134,7 +141,14 @@
<?php if(!$story->deleted):?>
<?php
common::printIcon('story', 'change', "storyID=$story->id", $story, 'button', 'alter', '', 'showinonlybody');
common::printIcon('story', 'review', "storyID=$story->id", $story, 'button', 'search', '', 'showinonlybody');
if(strpos('draft,changing', $story->status) !== false)
{
common::printIcon('story', 'submitReview', "storyID=$story->id", $story, 'button', 'sub-review', '', 'iframe showinonlybody', true);
}
else
{
common::printIcon('story', 'review', "storyID=$story->id", $story, 'button', 'search', '', 'iframe showinonlybody', true);
}
if($story->status == 'active' and $story->stage == 'wait' and $story->parent <= 0 and !isonlybody())
{
$divideLang = $lang->story->subdivide;
@@ -147,7 +161,7 @@
common::printIcon('story', 'close', "storyID=$story->id", $story, 'button', '', '', 'iframe showinonlybody', true);
common::printIcon('story', 'activate', "storyID=$story->id", $story, 'button', '', '', 'iframe showinonlybody', true);
if($from == 'execution' and strpos('draft,closed', $story->status) === false) common::printIcon('task', 'create', "execution=$param&storyID=$story->id&moduleID=$story->module", $story, 'button', 'plus', '', 'showinonlybody');
if($from == 'execution' and strpos('draft,reviewing,closed', $story->status) === false) common::printIcon('task', 'create', "execution=$param&storyID=$story->id&moduleID=$story->module", $story, 'button', 'plus', '', 'showinonlybody');
echo "<div class='divider'></div>";
common::printIcon('story', 'edit', "storyID=$story->id", $story);
@@ -221,7 +235,18 @@
</tr>
<tr>
<th><?php echo $lang->story->legendMailto;?></th>
<td><?php $mailto = explode(',', $story->mailto); foreach($mailto as $account) {if(empty($account)) continue; echo "<span>" . zget($users, trim($account)) . '</span> &nbsp;'; }?></td>
<td>
<?php
if(!empty($story->mailto))
{
foreach(explode(',', $story->mailto) as $account)
{
if(empty($account)) continue;
echo "<span>" . zget($users, trim($account)) . '</span> &nbsp;';
}
}
?>
</td>
</tr>
</tbody>
</table>
+22 -2
View File
@@ -1461,6 +1461,17 @@ class baseRouter
chdir(dirname($file2Included));
helper::import($file2Included);
/* Check file is encode by ioncube. */
$isEncrypted = false;
if($isExt)
{
$fp = fopen($file2Included, 'r');
$line1 = fgets($fp);
$line2 = fgets($fp);
fclose($fp);
if(strpos($line1, '<?php //') === 0 and strpos($line2, "if(!extension_loaded('ionCube Loader'))") === 0) $isEncrypted = true;
}
/*
* 设置control的类名。
* Set the class name of the control.
@@ -1500,7 +1511,7 @@ class baseRouter
{
$default = $paramDefaultValue[$className][$methodName][$name];
}
elseif($param->isDefaultValueAvailable())
elseif(!$isEncrypted and $param->isDefaultValueAvailable())
{
$default = $param->getDefaultValue();
}
@@ -1540,11 +1551,12 @@ class baseRouter
$_COOKIE = validater::filterParam($_COOKIE, 'cookie');
}
}
return true;
}
catch(EndResponseException $endResponseException)
{
echo $endResponseException->getContent();
return false;
}
}
@@ -2146,6 +2158,8 @@ class baseRouter
public function loadModule()
{
try {
if(is_null($this->params) and !$this->setParams()) return false;
/* 调用该方法 Call the method. */
$module = $this->control;
@@ -3190,6 +3204,7 @@ class ztSessionHandler implements SessionHandlerInterface
* @access public
* @return bool
*/
#[\ReturnTypeWillChange]
public function open($savePath, $sessionName)
{
$this->sessSavePath = $savePath;
@@ -3202,6 +3217,7 @@ class ztSessionHandler implements SessionHandlerInterface
* @access public
* @return bool
*/
#[\ReturnTypeWillChange]
public function close()
{
return true;
@@ -3214,6 +3230,7 @@ class ztSessionHandler implements SessionHandlerInterface
* @access public
* @return bool
*/
#[\ReturnTypeWillChange]
public function read($id)
{
$sessFile = $this->getSessionFile($id);
@@ -3233,6 +3250,7 @@ class ztSessionHandler implements SessionHandlerInterface
* @access public
* @return bool
*/
#[\ReturnTypeWillChange]
public function write($id, $sessData)
{
$sessFile = $this->getSessionFile($id);
@@ -3263,6 +3281,7 @@ class ztSessionHandler implements SessionHandlerInterface
* @access public
* @return bool
*/
#[\ReturnTypeWillChange]
public function destroy($id)
{
$sessFile = $this->getSessionFile($id);
@@ -3279,6 +3298,7 @@ class ztSessionHandler implements SessionHandlerInterface
* @access public
* @return bool
*/
#[\ReturnTypeWillChange]
public function gc($maxlifeTime)
{
$time = time();
+1
View File
@@ -57,6 +57,7 @@ class html extends baseHTML
{
$id = "id='$name'";
if(strpos($attrib, 'id=') !== false) $id = '';
if(is_null($value)) $value = '';
$value = str_replace("'", '&#039;', $value);
$autocomplete = $autocomplete ? 'autocomplete="on"' : 'autocomplete="off"';
return "<input type='text' name='$name' {$id} value='$value' $attrib $autocomplete />\n";
+27
View File
@@ -115,6 +115,33 @@ class action extends control
$preferredType = $preferredType + $toPreferredType;
}
/* Get the projects name of executions. */
if($browseType == 'execution')
{
$this->loadModel('project');
$projectIdList = array();
foreach($trashes as $trash) $projectIdList[] = $trash->project;
$this->view->projectList = $this->project->getByIdList($projectIdList, 'all');
}
/* Get the products name of story. */
if(strpos(',story,requirement,', ",$browseType,") !== false)
{
$this->loadModel('story');
$storyIdList = array();
foreach($trashes as $trash) $storyIdList[] = $trash->objectID;
$this->view->productList = $this->story->getByList($storyIdList, 'story', 'all');
}
/* Get the executions name of task. */
if($browseType == 'task')
{
$this->app->loadLang('task');
$this->loadModel('execution');
$executionIdList = array();
foreach($trashes as $trash) $executionIdList[] = $trash->execution;
$this->view->executionList = $this->execution->getByIdList($executionIdList, 'all');
}
/* Title and position. */
$this->view->title = $this->lang->action->trash;
$this->view->position[] = $this->lang->action->trash;
+6
View File
@@ -6,3 +6,9 @@
.dropdown-menu .btn-active-text:hover .text:after {border-bottom: 0px;}
#querybox #searchform{border-bottom: 1px solid #ddd; margin-bottom: 20px;}
td.flex {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center; margin-bottom: 0px;}
.flex span.label-danger {margin-left: 5px; min-width: 50px;}
[lang^=en] .flex span.label-danger {min-width: 52px;}
[lang^=de] .flex span.label-danger {min-width: 58px;}
[lang^=fr] .flex span.label-danger {min-width: 63px;}
.c-name > .text-ellipsis {text-overflow: clip;}
+4
View File
@@ -221,6 +221,8 @@ $lang->action->desc->updatetolib = '$date, updated to ' . $lang->testca
$lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n";
$lang->action->desc->reopen = '$date, reopened by <strong>$actor</strong> .' . "\n";
$lang->action->desc->merged = '$date, merged by <strong>$actor</strong> .' . "\n";
$lang->action->desc->submitreview = '$date, submitted for review by <strong>$actor</strong>.' . "\n";
$lang->action->desc->ganttmove = '$date, sort by <strong>$actor</strong> .' . "\n";
/* Used to describe the history of operations related to parent-child tasks. */
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> created a child task <strong>$extra</strong>。' . "\n";
@@ -274,6 +276,7 @@ $lang->action->label->blocked = 'blocked ';
$lang->action->label->resolved = 'resolved ';
$lang->action->label->reviewed = 'reviewed ';
$lang->action->label->recalled = 'recalled';
$lang->action->label->recalledchange = 'undo changes';
$lang->action->label->moved = 'moved ';
$lang->action->label->confirmed = 'Confirm Story';
$lang->action->label->bugconfirmed = 'Confirmed';
@@ -386,6 +389,7 @@ $lang->action->label->unlinkbug = 'unlink bugs from';
$lang->action->label->tolib = 'imported';
$lang->action->label->updatetolib = 'updated';
$lang->action->label->ganttmove = 'sorted';
$lang->action->label->submitreview = 'submitted';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
+4
View File
@@ -221,6 +221,8 @@ $lang->action->desc->updatetolib = '$date, updated to ' . $lang->testca
$lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n";
$lang->action->desc->reopen = '$date, reopened by <strong>$actor</strong> .' . "\n";
$lang->action->desc->merged = '$date, merged by <strong>$actor</strong> .' . "\n";
$lang->action->desc->submitreview = '$date, submitted for review by <strong>$actor</strong>.' . "\n";
$lang->action->desc->ganttmove = '$date, sort by <strong>$actor</strong> .' . "\n";
/* Used to describe the history of operations related to parent-child tasks. */
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> created a child task <strong>$extra</strong>。' . "\n";
@@ -274,6 +276,7 @@ $lang->action->label->blocked = 'blocked ';
$lang->action->label->resolved = 'resolved ';
$lang->action->label->reviewed = 'reviewed ';
$lang->action->label->recalled = 'recalled';
$lang->action->label->recalledchange = 'undo changes';
$lang->action->label->moved = 'moved ';
$lang->action->label->confirmed = 'confirmed Story ';
$lang->action->label->bugconfirmed = 'confirmed';
@@ -386,6 +389,7 @@ $lang->action->label->unlinkbug = 'unlink bugs from';
$lang->action->label->tolib = 'imported';
$lang->action->label->updatetolib = 'updated';
$lang->action->label->ganttmove = 'sorted';
$lang->action->label->submitreview = 'submitted';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
+4
View File
@@ -221,6 +221,8 @@ $lang->action->desc->updatetolib = '$date, MàJ de ' . $lang->testcase-
$lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n";
$lang->action->desc->reopen = '$date, reopened by <strong>$actor</strong> .' . "\n";
$lang->action->desc->merged = '$date, merged by <strong>$actor</strong> .' . "\n";
$lang->action->desc->submitreview = '$date, submitted for review by <strong>$actor</strong>.' . "\n";
$lang->action->desc->ganttmove = '$date, sort by <strong>$actor</strong> .' . "\n";
/* Used to describe the history of operations related to parent-child tasks. */
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> a créé un sous-tâche <strong>$extra</strong>。' . "\n";
@@ -274,6 +276,7 @@ $lang->action->label->blocked = 'a bloqué ';
$lang->action->label->resolved = 'a résolu ';
$lang->action->label->reviewed = 'a revu ';
$lang->action->label->recalled = 'recalled';
$lang->action->label->recalledchange = 'undo changes';
$lang->action->label->moved = 'a déplacé ';
$lang->action->label->confirmed = 'a confirmé Story ';
$lang->action->label->bugconfirmed = 'a confirmé le Bug ';
@@ -386,6 +389,7 @@ $lang->action->label->unlinkbug = 'unlink bugs from';
$lang->action->label->tolib = 'Importé';
$lang->action->label->updatetolib = 'MàJ';
$lang->action->label->ganttmove = 'sorted';
$lang->action->label->submitreview = 'submitted';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass();
+3
View File
@@ -183,6 +183,7 @@ $lang->action->desc->syncproject = '$date, starting the execution sets the p
$lang->action->desc->syncexecution = '$date, starting the task sets the execution status as Ongoing.' . "\n";
$lang->action->desc->reopen = '$date, reopened by <strong>$actor</strong> .' . "\n";
$lang->action->desc->merged = '$date, merged by <strong>$actor</strong> .' . "\n";
$lang->action->desc->submitreview = '$date, submitted for review by <strong>$actor</strong>.' . "\n";
/* Used to describe the history of operations related to parent-child tasks. */
$lang->action->desc->createchildren = '$date, <strong>$actor</strong> created a child task <strong>$extra</strong>。' . "\n";
@@ -228,6 +229,7 @@ $lang->action->label->blocked = 'blocked ';
$lang->action->label->resolved = 'resolved ';
$lang->action->label->reviewed = 'reviewed ';
$lang->action->label->recalled = 'recalled';
$lang->action->label->recalledchange = 'undo changes';
$lang->action->label->moved = 'moved ';
$lang->action->label->confirmed = 'confirmed Story ';
$lang->action->label->bugconfirmed = 'Đã xác nhận';
@@ -303,6 +305,7 @@ $lang->action->label->syncprogram = 'start';
$lang->action->label->syncproject = 'start';
$lang->action->label->syncexecution = 'start';
$lang->action->label->startProgram = '(The start of the project sets the status of the program as Ongoing)';
$lang->action->label->submitreview = 'submitted';
/* Dynamic information is grouped by object. */
$lang->action->dynamicAction = new stdclass;
+4
View File
@@ -221,6 +221,8 @@ $lang->action->desc->updatetolib = '$date, 由 <strong>$actor</strong>
$lang->action->desc->adjusttasktowait = '$date, 系统判断由于消耗工时调整为0,将任务状态置为未开始。' . "\n";
$lang->action->desc->reopen = '$date, 由 <strong>$actor</strong> 重新打开。' . "\n";
$lang->action->desc->merged = '$date, 由 <strong>$actor</strong> 合并。' . "\n";
$lang->action->desc->submitreview = '$date, 由 <strong>$actor</strong> 提交评审。' . "\n";
$lang->action->desc->ganttmove = '$date, 由 <strong>$actor</strong> 排序。' . "\n";
/* 用来描述和父子任务相关的操作历史记录。*/
$lang->action->desc->createchildren = '$date, 由 <strong>$actor</strong> 创建子任务 <strong>$extra</strong>。' . "\n";
@@ -274,6 +276,7 @@ $lang->action->label->blocked = '阻塞了';
$lang->action->label->resolved = '解决了';
$lang->action->label->reviewed = '评审了';
$lang->action->label->recalled = '撤销评审';
$lang->action->label->recalledchange = '撤销变更';
$lang->action->label->moved = '移动了';
$lang->action->label->confirmed = "确认了{$lang->SRCommon}";
$lang->action->label->bugconfirmed = '确认了';
@@ -386,6 +389,7 @@ $lang->action->label->unlinkbug = '移除BUG从';
$lang->action->label->tolib = '导入了';
$lang->action->label->updatetolib = '更新了';
$lang->action->label->ganttmove = '排序了';
$lang->action->label->submitreview = '提交了评审';
/* 动态信息按照对象分组 */
$lang->action->dynamicAction = new stdclass();
+11 -6
View File
@@ -510,7 +510,8 @@ class actionModel extends model
elseif(($actionName == 'closed' and $action->objectType == 'story') or ($actionName == 'resolved' and $action->objectType == 'bug'))
{
$action->appendLink = '';
if(strpos($action->extra, ':')!== false)
if(strpos($action->extra, '|') !== false) $action->extra = substr($action->extra, 0, strpos($action->extra, '|'));
if(strpos($action->extra, ':') !== false)
{
list($extra, $id) = explode(':', $action->extra);
$action->extra = $extra;
@@ -996,10 +997,10 @@ class actionModel extends model
{
$productCondition = '';
foreach(explode(',', $authedProducts) as $product) $productCondition = empty($productCondition) ? "(execution = '0' and project = '0' and (product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'";
$productCondition .= '))';
if(!empty($productCondition)) $productCondition .= '))';
$projectCondition = "(execution = '0' and project != '0' and project " . helper::dbIN($authedProjects) . ')';
$executionCondition = isset($authedExecutions) ? "(execution != 0 and execution " . helper::dbIN($authedExecutions) . ')' : '';
$executionCondition = isset($authedExecutions) ? "(execution != 0 and execution " . helper::dbIN($authedExecutions) . ')' : "(execution != 0 and execution = '$executionID')";
}
elseif($productID == 'all' and is_numeric($projectID))
{
@@ -1010,7 +1011,7 @@ class actionModel extends model
$productCondition = '';
foreach(array_keys($products) as $product) $productCondition = empty($productCondition) ? "(execution = '0' and project = '0' and (product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'";
$productCondition .= '))';
if(!empty($productCondition)) $productCondition .= '))';
$projectCondition = "(execution = '0' and project = '$projectID')";
$executionCondition = "(execution != '0' and execution " . helper::dbIN($authedExecutions) . ')';
@@ -1024,7 +1025,7 @@ class actionModel extends model
$authedProjects = array_intersect(array_keys($projects), explode(',', $authedProjects));
$authedExecutions = isset($authedExecutions) ? array_intersect(array_keys($executions), explode(',', $authedExecutions)) : array_keys($executions);
$productCondition = "product like '%,$productID,%'";
$productCondition = "(execution = '0' and project = '0' and product like '%,$productID,%')";
$projectCondition = "(execution = '0' and project != '0' and project " . helper::dbIN($authedProjects) . ')';
$executionCondition = "(execution != '0' and execution " . helper::dbIN($authedExecutions) . ')';
}
@@ -1539,7 +1540,11 @@ class actionModel extends model
if($action->objectType == 'story')
{
$story = $this->loadModel('story')->getByID($action->objectID);
if(!empty($story)) $moduleName = $story->type;
if(!empty($story))
{
$moduleName = $story->type;
$action->objectLink = helper::createLink('story', 'view', "id=$story->id&version=0&param=0&storyType=$story->type");
}
}
if($action->objectType == 'doclib')
+33
View File
@@ -82,6 +82,15 @@
<th class='c-object-type'><?php common::printOrderLink('objectType', $orderBy, $vars, $lang->action->objectType);?></th>
<th class='c-id'><?php common::printOrderLink('objectID', $orderBy, $vars, $lang->idAB);?></th>
<th><?php echo $lang->action->objectName;?></th>
<?php if($config->systemMode == 'new' and $currentObjectType == 'execution'):?>
<th class='w-250px'><?php echo $this->lang->project->project;?></th>
<?php endif;?>
<?php if(strpos(',story,requirement,', ",$currentObjectType,") !== false):?>
<th class='w-250px'><?php echo $this->lang->story->product;?></th>
<?php endif;?>
<?php if($currentObjectType == 'task'):?>
<th class='w-250px'><?php echo $this->lang->task->execution;?></th>
<?php endif;?>
<th class='c-user'><?php common::printOrderLink('actor', $orderBy, $vars, $lang->action->actor);?></th>
<th class='c-full-date'><?php common::printOrderLink('date', $orderBy, $vars, $lang->action->date);?></th>
<th class='c-actions'><?php echo $lang->actions;?></th>
@@ -137,6 +146,30 @@
}
?>
</td>
<?php if($config->systemMode == 'new' and $currentObjectType == 'execution'):?>
<td class="c-name flex" title="<?php echo $projectList[$action->project]->name;?>">
<span class="text-ellipsis"><?php echo $projectList[$action->project]->name;?></span>
<?php if($projectList[$action->project]->deleted):?>
<span class='label label-danger'><?php echo $this->lang->project->deleted;?></span>
<?php endif;?>
</td>
<?php endif;?>
<?php if(strpos(',story,requirement,', ",$currentObjectType,") !== false):?>
<td class="c-name flex" title="<?php echo $productList[$action->objectID]->productTitle;?>">
<span class="text-ellipsis"><?php echo $productList[$action->objectID]->productTitle;?></span>
<?php if($productList[$action->objectID]->productDeleted):?>
<span class='label label-danger'><?php echo $this->lang->story->deleted;?></span>
<?php endif;?>
</td>
<?php endif;?>
<?php if($currentObjectType == 'task'):?>
<td class="c-name flex" title="<?php echo $executionList[$action->execution]->name;?>">
<span class="text-ellipsis"><?php echo $executionList[$action->execution]->name;?></span>
<?php if($executionList[$action->execution]->deleted):?>
<span class='label label-danger'><?php echo $this->lang->execution->deleted;?></span>
<?php endif;?>
</td>
<?php endif;?>
<td><?php echo zget($users, $action->actor);?></td>
<td><?php echo $action->date;?></td>
<td>
+4 -3
View File
@@ -778,8 +778,9 @@ class block extends control
*/
public function printReleaseBlock()
{
$this->session->set('releaseList', $this->app->getURI(true), 'product');
$this->session->set('buildList', $this->app->getURI(true), 'execution');
$uri = $this->createLink('my', 'index');
$this->session->set('releaseList', $uri, 'product');
$this->session->set('buildList', $uri, 'execution');
$this->app->loadLang('release');
$this->view->releases = $this->dao->select('t1.*,t2.name as productName,t3.name as buildName')->from(TABLE_RELEASE)->alias('t1')
@@ -801,7 +802,7 @@ class block extends control
*/
public function printBuildBlock()
{
$this->session->set('buildList', $this->app->getURI(true), 'execution');
$this->session->set('buildList', $this->createLink('my', 'index'), 'execution');
$this->app->loadLang('build');
$builds = $this->dao->select('t1.*, t2.name as productName')->from(TABLE_BUILD)->alias('t1')
+5 -2
View File
@@ -44,8 +44,11 @@
<tr>
<td class='c-id-xs'><?php echo sprintf('%03d', $task->id);?></td>
<td class='c-pri <?php if($longBlock) echo "c-pri-long"?>'><span class='label-pri label-pri-<?php echo $task->pri;?>' title='<?php echo zget($lang->task->priList, $task->pri, $task->pri)?>'><?php echo zget($lang->task->priList, $task->pri, $task->pri)?></span></td>
<?php $class = ($task->executionType == 'kanban') ? 'iframe' : '';?>
<td class='c-name' style='color: <?php echo $task->color?>' title='<?php echo $task->name?>'><?php echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', true, $task->project), $task->name, null, "class='$class' data-width='80%' data-toggle='modal'")?></td>
<?php
$onlybody = $task->executionType == 'kanban' ? true : '';
$class = $task->executionType == 'kanban' ? "class='iframe' data-toggle='modal'" : '';
?>
<td class='c-name' style='color: <?php echo $task->color?>' title='<?php echo $task->name?>'><?php echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', $onlybody, $task->project), $task->name, null, "$class data-width='80%'")?></td>
<?php if($longBlock):?>
<td class='c-estimate text-center' title="<?php echo $task->estimate . ' ' . $lang->execution->workHour;?>"><?php echo $task->estimate . $lang->execution->workHourUnit;?></td>
<td class='c-deadline'><?php if(substr($task->deadline, 0, 4) > 0) echo $task->deadline;?></td>
+24 -9
View File
@@ -1152,16 +1152,20 @@ class bug extends control
}
if($bug->status == 'closed') $assignedToList['closed'] = 'Closed';
$branch = $product->type == 'branch' ? ($bug->branch > 0 ? $bug->branch . ',0' : '0') : '';
$productBugs = $this->bug->getProductBugPairs($productID, $branch);
$this->view->bug = $bug;
$this->view->productID = $productID;
$this->view->product = $product;
$this->view->productBugs = $productBugs;
$this->view->productName = $this->products[$productID];
$this->view->plans = $this->loadModel('productplan')->getPairs($productID, $bug->branch, '', true);
$this->view->projects = array(0 => '') + $this->product->getProjectPairsByProduct($productID, $bug->branch, $bug->project);
$this->view->moduleOptionMenu = $moduleOptionMenu;
$this->view->currentModuleID = $currentModuleID;
$this->view->executions = array(0 => '') + $this->product->getExecutionPairsByProduct($bug->product, $bug->branch, 'id_desc', $bug->project);
$this->view->stories = $bug->execution ? $this->story->getExecutionStoryPairs($bug->execution) : $this->story->getProductStoryPairs($bug->product, $bug->branch);
$this->view->stories = $bug->execution ? $this->story->getExecutionStoryPairs($bug->execution) : $this->story->getProductStoryPairs($bug->product, $bug->branch, 0, 'all', 'id_desc', 0, 'full', 'story', false);
$this->view->branchOption = $branchOption;
$this->view->branchTagOption = $branchTagOption;
$this->view->tasks = $this->task->getExecutionTaskPairs($bug->execution);
@@ -1301,6 +1305,7 @@ class bug extends control
$branchIdList = array();
$projectIdList = array();
$executionIdList = array();
$productBugList = array();
foreach($bugs as $bug)
{
$projectIdList[$bug->project] = $bug->project;
@@ -1309,6 +1314,10 @@ class bug extends control
$branchIdList[$bug->product][$bug->branch] = $bug->branch;
if(!isset($modules[$bug->product][$bug->branch]) and isset($modules[$bug->product])) $modules[$bug->product][$bug->branch] = $modules[$bug->product][0] + $this->tree->getModulesName($bug->module);
$bugProduct = isset($productList) ? $productList[$bug->product] : $product;
$branch = $bugProduct->type == 'branch' ? ($bug->branch > 0 ? $bug->branch . ',0' : '0') : '';
if(!isset($productBugList[$bug->product][$bug->branch])) $productBugList[$bug->product][$bug->branch] = $this->bug->getProductBugPairs($bug->product, $branch);
}
/* Get assigned to member. */
@@ -1388,6 +1397,7 @@ class bug extends control
$this->view->users = $users;
$this->view->modules = $modules;
$this->view->branchTagOption = $branchTagOption;
$this->view->productBugList = $productBugList;
$this->display();
}
@@ -1797,17 +1807,22 @@ class bug extends control
if(!isset($users[$assignedTo])) $assignedTo = $this->bug->getModuleOwner($bug->module, $productID);
unset($this->lang->bug->resolutionList['tostory']);
$product = $this->loadModel('product')->getById($productID);
$branch = $product->type == 'branch' ? ($bug->branch > 0 ? $bug->branch . ',0' : '0') : '';
$productBugs = $this->bug->getProductBugPairs($productID, $branch);
$this->bug->checkBugExecutionPriv($bug);
$this->qa->setMenu($this->products, $productID, $bug->branch);
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve;
$this->view->bug = $bug;
$this->view->users = $users;
$this->view->assignedTo = $assignedTo;
$this->view->executions = $this->loadModel('product')->getExecutionPairsByProduct($productID, $bug->branch ? "0,{$bug->branch}" : 0, 'id_desc', $projectID);
$this->view->builds = $this->loadModel('build')->getBuildPairs($productID, $bug->branch, 'withbranch');
$this->view->actions = $this->action->getList('bug', $bugID);
$this->view->execution = isset($execution) ? $execution : '';
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve;
$this->view->bug = $bug;
$this->view->users = $users;
$this->view->assignedTo = $assignedTo;
$this->view->productBugs = $productBugs;
$this->view->executions = $this->loadModel('product')->getExecutionPairsByProduct($productID, $bug->branch ? "0,{$bug->branch}" : 0, 'id_desc', $projectID);
$this->view->builds = $this->loadModel('build')->getBuildPairs($productID, $bug->branch, 'withbranch');
$this->view->actions = $this->action->getList('bug', $bugID);
$this->view->execution = isset($execution) ? $execution : '';
$this->display();
}
+1
View File
@@ -7,3 +7,4 @@
.select-project-modal .modal-body {right: 15px;}
.osContent, .browserContent {margin: 0 0 5px;}
.browserContent {margin-left: -4px;}
.resolution {white-space: nowrap; overflow: hidden;}
+6
View File
@@ -77,4 +77,10 @@ $(function()
{
hiddenRequireFields();
});
$('select[id^="duplicateBugs"]').picker(
{
disableEmptySearch : true,
dropWidth : 'auto'
});
});
+1 -1
View File
@@ -678,7 +678,7 @@ function setStories(moduleID, productID, storyID)
if(typeof(branch) == 'undefined') branch = 0;
var executionID = $('#execution').val();
if(typeof(executionID) == 'undefined') executionID = 0;
link = createLink('story', 'ajaxGetProductStories', 'productID=' + productID + '&branch=' + branch + '&moduleID=' + moduleID + '&storyID=' + storyID + '&onlyOption=false&status=&limit=0&type=full&hasParent=1&executionID=' + executionID);
link = createLink('story', 'ajaxGetProductStories', 'productID=' + productID + '&branch=' + branch + '&moduleID=' + moduleID + '&storyID=' + storyID + '&onlyOption=false&status=&limit=0&type=full&hasParent=0&executionID=' + executionID);
$.get(link, function(stories)
{
if(!stories) stories = '<select id="story" name="story" class="form-control"></select>';
+6
View File
@@ -19,6 +19,12 @@ $(function()
}
});
}
$('#duplicateBug').picker(
{
disableEmptySearch : true,
dropWidth : 'auto'
});
});
/**
+6
View File
@@ -45,4 +45,10 @@ $(function()
$('#newBuildExecutionBox').addClass('hidden');
}
})
$('#duplicateBug').picker(
{
disableEmptySearch : true,
dropWidth : 'auto'
});
})
+2
View File
@@ -176,6 +176,7 @@ $lang->bug->labelPostponed = 'Postponed';
$lang->bug->changed = 'Changed';
$lang->bug->storyChanged = 'Story Changed';
$lang->bug->linkMR = 'Related MRs';
$lang->bug->duplicateTip = 'Please enter keyword search';
/* Page tags. */
$lang->bug->lblAssignedTo = 'Bearbeiter';
@@ -416,6 +417,7 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed;
$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
$lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
+3 -1
View File
@@ -77,7 +77,7 @@ $lang->bug->deadlineAB = 'Deadline';
$lang->bug->plan = 'Plan';
$lang->bug->closedBy = 'ClosedBy';
$lang->bug->closedDate = 'ClosedDate';
$lang->bug->duplicateBug = 'Duplicated Bug ID';
$lang->bug->duplicateBug = 'Duplicated Bug';
$lang->bug->lastEditedBy = 'EditedBy';
$lang->bug->linkBug = 'Linked Bugs';
$lang->bug->linkBugs = 'Link Bug';
@@ -176,6 +176,7 @@ $lang->bug->labelPostponed = 'Postponed';
$lang->bug->changed = 'Changed';
$lang->bug->storyChanged = 'Story Changed';
$lang->bug->linkMR = 'Related MRs';
$lang->bug->duplicateTip = 'Please enter keyword search';
/* Page tags. */
$lang->bug->lblAssignedTo = 'AssignTo';
@@ -416,6 +417,7 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed;
$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
$lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
+3 -1
View File
@@ -77,7 +77,7 @@ $lang->bug->deadlineAB = 'Butoir';
$lang->bug->plan = 'Plan';
$lang->bug->closedBy = 'Fermé par';
$lang->bug->closedDate = 'Date Fermeture';
$lang->bug->duplicateBug = 'Bug ID en doublon';
$lang->bug->duplicateBug = 'Bug en doublon';
$lang->bug->lastEditedBy = 'Edité par';
$lang->bug->linkBug = 'Bugs Liés';
$lang->bug->linkBugs = 'Associer Bug';
@@ -176,6 +176,7 @@ $lang->bug->labelPostponed = 'Postponed';
$lang->bug->changed = 'Changed';
$lang->bug->storyChanged = 'Story Changed';
$lang->bug->linkMR = 'Related MRs';
$lang->bug->duplicateTip = 'Please enter keyword search';
/* Page tags. */
$lang->bug->lblAssignedTo = 'Affecté à';
@@ -416,6 +417,7 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed;
$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
$lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
+3 -1
View File
@@ -77,7 +77,7 @@ $lang->bug->deadlineAB = '截止';
$lang->bug->plan = '所属' . '计划';
$lang->bug->closedBy = '由谁关闭';
$lang->bug->closedDate = '关闭日期';
$lang->bug->duplicateBug = '重复ID';
$lang->bug->duplicateBug = '重复Bug';
$lang->bug->lastEditedBy = '最后修改者';
$lang->bug->linkBug = '相关Bug';
$lang->bug->linkBugs = '关联相关Bug';
@@ -176,6 +176,7 @@ $lang->bug->labelPostponed = '被延期';
$lang->bug->changed = '已变动';
$lang->bug->storyChanged = '需求变动';
$lang->bug->linkMR = '相关合并请求';
$lang->bug->duplicateTip = '请输入关键字';
/* 页面标签。*/
$lang->bug->lblAssignedTo = '当前指派';
@@ -420,6 +421,7 @@ $lang->bug->featureBar['browse']['assignedbyme'] = $lang->bug->assignedByMe;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
$lang->bug->moreSelects['unconfirmed'] = $lang->bug->unconfirmed;
$lang->bug->moreSelects['assigntonull'] = $lang->bug->assignToNull;
$lang->bug->moreSelects['longlifebugs'] = $lang->bug->longLifeBugs;
+49 -26
View File
@@ -384,6 +384,9 @@ class bugModel extends model
$browseType = ($browseType == 'bymodule' and $this->session->bugBrowseType and $this->session->bugBrowseType != 'bysearch') ? $this->session->bugBrowseType : $browseType;
$browseType = $browseType == 'bybranch' ? 'bymodule' : $browseType;
if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort);
if(strpos($sort, 'severity_') !== false) $sort = str_replace('severity_', 'severityOrder_', $sort);
/* Get bugs by browse type. */
$bugs = array();
if($browseType == 'all') $bugs = $this->getAllBugs($productIDList, $branch, $modules, $executions, $sort, $pager, $projectID);
@@ -483,7 +486,7 @@ class bugModel extends model
*/
public function getModuleBugs($productIDList, $branch = 0, $moduleIdList = 0, $executions = array(), $orderBy = 'id_desc', $pager = null, $projectID = 0)
{
return $this->dao->select('*')->from(TABLE_BUG)
return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('product')->in($productIDList)
->beginIF($branch !== 'all')->andWhere('branch')->eq($branch)->fi()
->beginIF(!empty($moduleIdList))->andWhere('module')->in($moduleIdList)->fi()
@@ -506,7 +509,8 @@ class bugModel extends model
*/
public function getPlanBugs($planID, $status = 'all', $orderBy = 'id_desc', $pager = null)
{
$bugs = $this->dao->select('*')->from(TABLE_BUG)
if(strpos($orderBy, 'pri_') !== false) $orderBy = str_replace('pri_', 'priOrder_', $orderBy);
$bugs = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_BUG)
->where('plan')->eq((int)$planID)
->beginIF(!$this->app->user->admin)->andWhere('execution')->in('0,' . $this->app->user->view->sprints)->fi()
->beginIF($status != 'all')->andWhere('status')->in($status)->fi()
@@ -1125,6 +1129,7 @@ class bugModel extends model
->setDefault('assignedDate', $now)
->setDefault('resolvedDate', $now)
->setDefault('assignedTo', $oldBug->openedBy)
->setDefault('duplicateBug', 0)
->removeIF($this->post->resolution != 'duplicate', 'duplicateBug')
->stripTags($this->config->bug->editor->resolve['id'], $this->config->allowedTags)
->remove('files,labels')
@@ -1565,7 +1570,6 @@ class bugModel extends model
$bugCount = $this->dao->select("count(id) as num, date_format($field, '%m/%d') as date")->from(TABLE_BUG)
->where('product')->eq($productID)
->andWhere($field)->ne('0000-00-00 00:00:00')
->andWhere($field)->ne('')
->andWhere('deleted')->eq(0)
->andWhere($field)->between($startDate, $endDate . ' 23:50:59')
->groupBy('date')
@@ -1713,8 +1717,7 @@ class bugModel extends model
$moduleName = $this->app->rawMethod == 'work' ? 'workBug' : 'contributeBug';
$queryName = $moduleName . 'Query';
$formName = $moduleName . 'Form';
$bugIDList = array();
$bugIDList = array();
if($moduleName == 'contributeBug')
{
$bugsAssignedByMe = $this->loadModel('my')->getAssignedByMe($account, 0, '', $orderBy, 'bug');
@@ -1742,7 +1745,7 @@ class bugModel extends model
$query = preg_replace('/`(\w+)`/', 't1.`$1`', $query);
if($type != 'bySearch' and !$this->loadModel('common')->checkField(TABLE_BUG, $type)) return array();
return $this->dao->select('t1.*,t2.name as productName')->from(TABLE_BUG)->alias('t1')
return $this->dao->select("t1.*,t2.name as productName, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq('0')
@@ -1823,6 +1826,9 @@ class bugModel extends model
public function getProjectBugs($projectID, $productID = 0, $branchID = 0, $build = 0, $type = '', $param = 0, $orderBy = 'id_desc', $excludeBugs = '', $pager = null)
{
$type = strtolower($type);
if(strpos($orderBy, 'pri_') !== false) $orderBy = str_replace('pri_', 'priOrder_', $orderBy);
if(strpos($orderBy, 'severity_') !== false) $orderBy = str_replace('severity_', 'severityOrder_', $orderBy);
if($type == 'bysearch')
{
$queryID = (int)$param;
@@ -1839,7 +1845,7 @@ class bugModel extends model
$bugQuery = $this->getBugQuery($this->session->projectBugQuery);
$bugs = $this->dao->select('*')->from(TABLE_BUG)
$bugs = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where($bugQuery)
->andWhere('project')->eq((int)$projectID)
->andWhere('deleted')->eq(0)
@@ -1852,7 +1858,7 @@ class bugModel extends model
}
else
{
$bugs = $this->dao->select('t1.*')->from(TABLE_BUG)->alias('t1')
$bugs = $this->dao->select("t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
->leftJoin(TABLE_MODULE)->alias('t2')->on('t1.module=t2.id')
->where('t1.deleted')->eq(0)
->beginIF(empty($build))->andWhere('t1.project')->eq($projectID)->fi()
@@ -1891,6 +1897,9 @@ class bugModel extends model
public function getExecutionBugs($executionID, $productID = 0, $branchID = 'all', $build = 0, $type = '', $param = 0, $orderBy = 'id_desc', $excludeBugs = '', $pager = null)
{
$type = strtolower($type);
if(strpos($orderBy, 'pri_') !== false) $orderBy = str_replace('pri_', 'priOrder_', $orderBy);
if(strpos($orderBy, 'severity_') !== false) $orderBy = str_replace('severity_', 'severityOrder_', $orderBy);
if($type == 'bysearch')
{
$queryID = (int)$param;
@@ -1907,7 +1916,7 @@ class bugModel extends model
$bugQuery = $this->getBugQuery($this->session->executionBugQuery);
$bugs = $this->dao->select('*')->from(TABLE_BUG)
$bugs = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where($bugQuery)
->andWhere('execution')->eq((int)$executionID)
->andWhere('deleted')->eq(0)
@@ -1920,7 +1929,7 @@ class bugModel extends model
}
else
{
$bugs = $this->dao->select('t1.*')->from(TABLE_BUG)->alias('t1')
$bugs = $this->dao->select("t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
->leftJoin(TABLE_MODULE)->alias('t2')->on('t1.module=t2.id')
->where('t1.deleted')->eq(0)
->beginIF(!empty($productID) and $branchID !== 'all')->andWhere('t1.branch')->eq($branchID)->fi()
@@ -1985,16 +1994,18 @@ class bugModel extends model
/**
* get Product Bug Pairs
*
* @param int $productID
* @param int $productID
* @param int|string $branch
* @access public
* @return void
*/
public function getProductBugPairs($productID)
public function getProductBugPairs($productID, $branch = '')
{
$bugs = array('' => '');
$data = $this->dao->select('id, title')->from(TABLE_BUG)
->where('product')->eq((int)$productID)
->beginIF(!$this->app->user->admin)->andWhere('execution')->in('0,' . $this->app->user->view->sprints)->fi()
->beginIF($branch !== '')->andWhere('branch')->in($branch)->fi()
->andWhere('deleted')->eq(0)
->orderBy('id desc')
->fetchAll();
@@ -2542,7 +2553,7 @@ class bugModel extends model
*/
public function getAllBugs($productIDList, $branch, $modules, $executions, $orderBy, $pager = null, $projectID = 0)
{
$bugs = $this->dao->select('t1.*, t2.title as planTitle')->from(TABLE_BUG)->alias('t1')
$bugs = $this->dao->select("t1.*, t2.title as planTitle, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id')
->where('t1.product')->in($productIDList)
->andWhere('t1.execution')->in(array_keys($executions))
@@ -2573,7 +2584,9 @@ class bugModel extends model
*/
public function getByAssigntome($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID)
{
return $this->dao->findByAssignedTo($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->in($productIDList)
return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('assignedTo')->eq($this->app->user->account)
->andWhere('product')->in($productIDList)
->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->beginIF($projectID)->andWhere('project')->eq($projectID)->fi()
@@ -2598,7 +2611,9 @@ class bugModel extends model
*/
public function getByOpenedbyme($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID)
{
return $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->in($productIDList)
return $this->dao->select("*,IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('openedBy')->eq($this->app->user->account)
->andWhere('product')->in($productIDList)
->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->beginIF($projectID)->andWhere('project')->eq($projectID)->fi()
@@ -2623,7 +2638,9 @@ class bugModel extends model
*/
public function getByResolvedbyme($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID)
{
return $this->dao->findByResolvedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->in($productIDList)
return $this->dao->select("*,IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('resolvedBy')->eq($this->app->user->account)
->andWhere('product')->in($productIDList)
->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->beginIF($projectID)->andWhere('project')->eq($projectID)->fi()
@@ -2649,7 +2666,9 @@ class bugModel extends model
public function getByAssigntonull($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID)
{
return $this->dao->findByAssignedTo('')->from(TABLE_BUG)->andWhere('product')->in($productIDList)
return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('assignedTo')->eq('')
->andWhere('product')->in($productIDList)
->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->beginIF($projectID)->andWhere('project')->eq($projectID)->fi()
@@ -2674,7 +2693,7 @@ class bugModel extends model
*/
public function getUnconfirmed($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID)
{
return $this->dao->select('*')->from(TABLE_BUG)
return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('product')->in($productIDList)
->andWhere('execution')->in(array_keys($executions))
->andWhere('deleted')->eq(0)
@@ -2702,7 +2721,7 @@ class bugModel extends model
*/
public function getOverdueBugs($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID)
{
return $this->dao->select('*')->from(TABLE_BUG)
return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('product')->in($productIDList)
->andWhere('execution')->in(array_keys($executions))
->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi()
@@ -2732,7 +2751,7 @@ class bugModel extends model
*/
public function getByStatus($productIDList, $branch, $modules, $executions, $status, $orderBy, $pager, $projectID)
{
return $this->dao->select('*')->from(TABLE_BUG)
return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('product')->in($productIDList)
->andWhere('execution')->in(array_keys($executions))
->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi()
@@ -2763,7 +2782,9 @@ class bugModel extends model
public function getByLonglifebugs($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID)
{
$lastEditedDate = date(DT_DATE1, time() - $this->config->bug->longlife * 24 * 3600);
return $this->dao->findByLastEditedDate("<", $lastEditedDate)->from(TABLE_BUG)->andWhere('product')->in($productIDList)
return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('lastEditedDate')->lt($lastEditedDate)
->andWhere('product')->in($productIDList)
->andWhere('execution')->in(array_keys($executions))
->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
@@ -2789,7 +2810,9 @@ class bugModel extends model
*/
public function getByPostponedbugs($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID)
{
return $this->dao->findByResolution('postponed')->from(TABLE_BUG)->andWhere('product')->in($productIDList)
return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('resolution')->eq('postponed')
->andWhere('product')->in($productIDList)
->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
->beginIF($projectID)->andWhere('project')->eq($projectID)->fi()
@@ -2814,7 +2837,7 @@ class bugModel extends model
*/
public function getByNeedconfirm($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID)
{
return $this->dao->select('t1.*, t2.title AS storyTitle')->from(TABLE_BUG)->alias('t1')
return $this->dao->select("t1.*, t2.title AS storyTitle, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
->where("t2.status = 'active'")
->andWhere('t1.product')->in($productIDList)
@@ -2846,7 +2869,7 @@ class bugModel extends model
public function getByAssignedbyme($productIDList, $branch, $modules, $executions, $sort, $pager, $projectID)
{
$actionIDList = $this->dao->select('objectID')->from(TABLE_ACTION)->where('objectType')->eq('bug')->andWhere('action')->eq('assigned')->andWhere('actor')->eq($this->app->user->account)->fetchPairs('objectID', 'objectID');
return $this->dao->select('*')->from(TABLE_BUG)
return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)
->where('product')->in($productIDList)
->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi()
->beginIF($modules)->andWhere('module')->in($modules)->fi()
@@ -2918,7 +2941,7 @@ class bugModel extends model
if($branch !== 'all' and strpos($bugQuery, '`branch` =') === false) $bugQuery .= " AND `branch` in('0','$branch')";
if(strpos($bugQuery, $allBranch) !== false) $bugQuery = str_replace($allBranch, '1', $bugQuery);
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery)
$bugs = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)->where($bugQuery)
->beginIF(!$this->app->user->admin)->andWhere('execution')->in('0,' . $this->app->user->view->sprints)->fi()
->beginIF($excludeBugs)->andWhere('id')->notIN($excludeBugs)->fi()
@@ -2950,7 +2973,7 @@ class bugModel extends model
*/
public function getReviewBugs($productIDList, $branch, $modules, $executions, $orderBy, $pager = null, $projectID = 0)
{
$bugs = $this->dao->select('t1.*, t2.title as planTitle')->from(TABLE_BUG)->alias('t1')
$bugs = $this->dao->select("t1.*, t2.title as planTitle, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)->alias('t1')
->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id')
->where('t1.product')->in($productIDList)
->andWhere('t1.execution')->in(array_keys($executions))
+2 -2
View File
@@ -139,11 +139,11 @@
<td <?php echo zget($visibleFields, 'keywords', "class='hidden'")?>><?php echo html::input("keywords[$bugID]", $bug->keywords, 'class=form-control');?></td>
<td class='<?php echo zget($visibleFields, 'resolvedBy', ' hidden')?>' style='overflow:visible'><?php echo html::select("resolvedBys[$bugID]", $users, $bug->resolvedBy, "class='form-control picker-select' data-drop-width='auto'");?></td>
<td <?php echo zget($visibleFields, 'resolution', "class='hidden'")?>>
<table class='table-borderless table no-margin'>
<table class='table-borderless table no-margin table-form'>
<tr>
<td class='pd-0'><?php echo html::select("resolutions[$bugID]", $resolutionList, $bug->resolution, "class='form-control' onchange=setDuplicate(this.value,$bugID)");?></td>
<td class='pd-0 w-p50' id='<?php echo 'duplicateBugBox' . $bugID;?>' <?php if($bug->resolution != 'duplicate') echo "style='display:none'";?>>
<?php echo html::input("duplicateBugs[$bugID]", '', "class='form-control duplicate-input' placeholder='{$lang->bug->duplicateBug}'");?>
<?php echo html::select("duplicateBugs[$bugID]", $productBugList[$bug->product][$bug->branch], $bug->duplicateBug, "class='form-control' placeholder='{$lang->bug->duplicateTip}'");?>
</td>
</tr>
</table>
+3 -3
View File
@@ -71,16 +71,16 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow
{
$moreLabel = $lang->more;
$moreLabelActive = '';
if(isset($lang->bug->moreSelects[$browseType]))
if(isset($lang->bug->moreSelects[$this->session->bugBrowseType]))
{
$moreLabel = "<span class='text'>{$lang->bug->moreSelects[$browseType]}</span> <span class='label label-light label-badge'>{$pager->recTotal}</span>";
$moreLabel = "<span class='text'>{$lang->bug->moreSelects[$this->session->bugBrowseType]}</span> <span class='label label-light label-badge'>{$pager->recTotal}</span>";
$moreLabelActive = 'btn-active-text';
}
echo "<div class='btn-group'><a href='javascript:;' data-toggle='dropdown' class='btn btn-link {$moreLabelActive}'>{$moreLabel} <span class='caret'></span></a>";
echo "<ul class='dropdown-menu'>";
foreach($lang->bug->moreSelects as $menuBrowseType => $label)
{
$active = $menuBrowseType == $browseType ? 'btn-active-text' : '';
$active = $menuBrowseType == $this->session->bugBrowseType ? 'btn-active-text' : '';
echo '<li>' . html::a($this->createLink('bug', 'browse', "productid=$productID&branch=$branch&browseType=$menuBrowseType"), "<span class='text'>{$label}</span>", '', "class='btn btn-link $active'") . '</li>';
}
echo '</ul></div>';
+1 -1
View File
@@ -265,7 +265,7 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project);
</tr>
<tr id='duplicateBugBox' <?php if($bug->resolution != 'duplicate') echo "style='display:none'";?>>
<th><?php echo $lang->bug->duplicateBug;?></th>
<td><?php echo html::input('duplicateBug', $bug->duplicateBug, 'class=form-control');?></td>
<td class='required'><?php echo html::select('duplicateBug', $productBugs, $bug->duplicateBug, "class='form-control' placeholder='{$lang->bug->duplicateTip}'");?></td>
</tr>
<tr>
<th><?php echo $lang->bug->closedBy;?></th>
+1 -1
View File
@@ -38,7 +38,7 @@ js::set('productID' , $bug->product);
</tr>
<tr id='duplicateBugBox' class='hide'>
<th><?php echo $lang->bug->duplicateBug;?></th>
<td class='required'><?php echo html::input('duplicateBug', '', "class='form-control'");?></td>
<td class='required'><?php echo html::select('duplicateBug', $productBugs, '', "class='form-control' placeholder='{$lang->bug->duplicateTip}'");?></td>
</tr>
<tr>
<th><?php echo $lang->bug->resolvedBuild;?></th>
+10 -3
View File
@@ -262,7 +262,14 @@
</tr>
<tr>
<th><?php echo $lang->bug->mailto;?></th>
<td><?php $mailto = explode(',', str_replace(' ', '', $bug->mailto)); foreach($mailto as $account) echo ' ' . zget($users, $account); ?></td>
<td>
<?php
if(empty($bug->mailto))
{
foreach(explode(',', str_replace(' ', '', $bug->mailto)) as $account) echo ' ' . zget($users, $account);
}
?>
</td>
</tr>
</tbody>
</table>
@@ -348,10 +355,10 @@
</tr>
<tr>
<th><?php echo $lang->bug->resolution;?></th>
<td>
<td class='resolution'>
<?php
echo isset($lang->bug->resolutionList[$bug->resolution]) ? $lang->bug->resolutionList[$bug->resolution] : $bug->resolution;
if(isset($bug->duplicateBugTitle)) echo " #$bug->duplicateBug:" . html::a($this->createLink('bug', 'view', "bugID=$bug->duplicateBug", '', true), $bug->duplicateBugTitle, '', "class='iframe' data-width='80%'");
if(isset($bug->duplicateBugTitle)) echo " #$bug->duplicateBug:" . html::a($this->createLink('bug', 'view', "bugID=$bug->duplicateBug", '', true), $bug->duplicateBugTitle, '', "title='{$bug->duplicateBugTitle}' class='iframe' data-width='80%'");
?>
</td>
</tr>
+10 -20
View File
@@ -233,22 +233,27 @@ class build extends control
$this->app->loadClass('pager', $static = true);
if($this->app->getViewType() == 'mhtml') $recPerPage = 10;
$sort = common::appendOrder($orderBy);
if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort);
/* Get product and bugs. */
$product = $this->loadModel('product')->getById($build->product);
if($product->type != 'normal') $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]);
$bugPager = new pager($type == 'bug' ? $recTotal : 0, $recPerPage, $type == 'bug' ? $pageID : 1);
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($build->bugs)->andWhere('deleted')->eq(0)
->beginIF($type == 'bug')->orderBy($orderBy)->fi()
$bugs = $this->dao->select('*')->from(TABLE_BUG)
->where('id')->in($build->bugs)
->andWhere('deleted')->eq(0)
->beginIF($type == 'bug')->orderBy($sort)->fi()
->page($bugPager)
->fetchAll();
/* Get stories and stages. */
$storyPager = new pager($type == 'story' ? $recTotal : 0, $recPerPage, $type == 'story' ? $pageID : 1);
$stories = $this->dao->select('*')->from(TABLE_STORY)
$stories = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_STORY)
->where('id')->in($build->stories)
->andWhere('deleted')->eq(0)
->beginIF($type == 'story')->orderBy($orderBy)->fi()
->beginIF($type == 'story')->orderBy($sort)->fi()
->page($storyPager)
->fetchAll('id');
@@ -273,7 +278,7 @@ class build extends control
$this->view->storyPager = $storyPager;
$generatedBugPager = new pager($type == 'generatedBug' ? $recTotal : 0, $recPerPage, $type == 'generatedBug' ? $pageID : 1);
$this->view->generatedBugs = $this->bug->getExecutionBugs($build->execution, $build->product, 'all', $build->id, $type, $param, $type == 'generatedBug' ? $orderBy : 'status_desc,id_desc', '', $generatedBugPager);
$this->view->generatedBugs = $this->bug->getExecutionBugs($build->execution, $build->product, 'all', $build->id, $type, $param, $type == 'generatedBug' ? $sort : 'status_desc,id_desc', '', $generatedBugPager);
$this->view->generatedBugPager = $generatedBugPager;
$this->executeHooks($buildID);
@@ -586,21 +591,6 @@ class build extends control
{
$this->build->unlinkStory($buildID, $storyID);
/* if ajax request, send result. */
if($this->server->ajax)
{
if(dao::isError())
{
$response['result'] = 'fail';
$response['message'] = dao::getError();
}
else
{
$response['result'] = 'success';
$response['message'] = '';
}
return $this->send($response);
}
return print(js::reload('parent'));
}
+1 -1
View File
@@ -131,7 +131,7 @@ tbody tr td:first-child input {display: none;}
if($canBeChanged and common::hasPriv('build', 'unlinkStory'))
{
$unlinkURL = inlink('unlinkStory', "buildID=$build->id&story=$story->id");
echo html::a("###", '<i class="icon-unlink"></i>', '', "onclick='ajaxDelete(\"$unlinkURL\", \"storyList\", confirmUnlinkStory)' class='btn' title='{$lang->build->unlinkStory}'");
echo html::a($unlinkURL, '<i class="icon-unlink"></i>', 'hiddenwin', "class='btn' title='{$lang->build->unlinkStory}'");
}
?>
</td>
+16 -9
View File
@@ -1335,28 +1335,31 @@ class commonModel extends model
$label = $menuItem->text;
$dropMenu = '';
/* Print sub menus. */
if(isset($menuItem->dropMenu))
{
foreach($menuItem->dropMenu as $dropMenuItem)
foreach($menuItem->dropMenu as $dropMenuKey => $dropMenuItem)
{
if($dropMenuItem->hidden) continue;
if(isset($dropMenuItem->hidden) and $dropMenuItem->hidden) continue;
$subActive = '';
$subModule = '';
$subMethod = '';
$subParams = '';
$subLabel = $dropMenuItem->text;
if(isset($dropMenuItem->link['module'])) $subModule = $dropMenuItem->link['module'];
if(isset($dropMenuItem->link['method'])) $subMethod = $dropMenuItem->link['method'];
if(isset($dropMenuItem->link['vars'])) $subParams = $dropMenuItem->link['vars'];
$subLabel = '';
list($dropMenuName, $dropMenuModule, $dropMenuMethod, $dropMenuParams) = explode('|', $dropMenuItem['link']);
if(isset($dropMenuModule)) $subModule = $dropMenuModule;
if(isset($dropMenuMethod)) $subMethod = $dropMenuMethod;
if(isset($dropMenuParams)) $subParams = $dropMenuParams;
if(isset($dropMenuName)) $subLabel = $dropMenuName;
$subLink = helper::createLink($subModule, $subMethod, $subParams);
if($currentModule == strtolower($subModule) and $currentMethod == strtolower($subMethod)) $subActive = 'active';
$misc = (isset($lang->navGroup->$subModule) and $tab != $lang->navGroup->$subModule) ? "data-app='$tab'" : '';
$dropMenu .= "<li class='$subActive' data-id='$dropMenuItem->name'>" . html::a($subLink, $subLabel, '', $misc) . '</li>';
$dropMenu .= "<li class='$subActive' data-id='$dropMenuKey'>" . html::a($subLink, $subLabel, '', $misc) . '</li>';
}
if(empty($dropMenu)) continue;
@@ -2111,9 +2114,12 @@ EOD;
$table = $this->config->objectTables[$type];
$orderBy = $type . 'OrderBy';
$orderBy = $this->session->$orderBy;
$select = '';
if($this->session->$typeOnlyCondition)
{
$sql = $this->dao->select('*')->from($table)
if(strpos($orderBy, 'priOrder') !== false) $select .= ", IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder";
if(strpos($orderBy, 'severityOrder') !== false) $select .= ", IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder";
$sql = $this->dao->select("*$select")->from($table)
->where($queryCondition)
->beginIF($orderBy != false)->orderBy($orderBy)->fi()
->get();
@@ -2495,6 +2501,7 @@ EOD;
if($module == 'story' and !empty($params['storyType']) and strpos(",story,requirement,", ",{$params['storyType']},") !== false) $module = $params['storyType'];
if($module == 'product' and $method == 'browse' and !empty($app->params['storyType']) and $app->params['storyType'] == 'requirement') $method = 'requirement';
if($module == 'product' and $method == 'browse' and !empty($params['storyType']) and $params['storyType'] == 'requirement') $method = 'requirement';
if($module == 'story' and $method == 'linkrequirements') $module = 'requirement';
/* If the user is doing a tutorial, have all tutorial privs. */
if(defined('TUTORIAL'))
@@ -2533,7 +2540,7 @@ EOD;
$acls = $app->user->rights['acls'];
/* White list of import method. */
if(in_array($module, array('user', 'task', 'story', 'bug', 'testcase')) and $method == 'showimport')
if(in_array($module, $app->config->importWhiteList) and $method == 'showimport')
{
if(isset($rights[$module]['import']) and commonModel::hasDBPriv($object, $module, 'import')) return true;
}
+1 -1
View File
@@ -99,7 +99,7 @@ $(function()
<table class='table table-form'>
<tr>
<td class='w-160px'><?php echo $lang->datatable->showModule;?></td>
<td><?php echo html::radio('showModule', $lang->datatable->showModuleList, isset($config->datatable->$datatableId->showModule) ? $config->datatable->$datatableId->showModule : '');?></td>
<td><?php echo html::radio('showModule', $lang->datatable->showModuleList, isset($config->datatable->$datatableId->showModule) ? $config->datatable->$datatableId->showModule : '0');?></td>
</tr>
<?php if($app->moduleName == 'execution' and $app->methodName == 'task' and $this->config->vision != 'lite'):?>
<tr>
+1 -1
View File
@@ -23,7 +23,7 @@ $lang->datatable->displaySetting = 'Set list';
$lang->datatable->showModule = 'Anzeigen/Verstecken des Modul Names';
$lang->datatable->showBranch = 'Show branches in the list';
$lang->datatable->showAllModule = 'Show product modules';
$lang->datatable->showModuleList[] = 'N/A';
$lang->datatable->showModuleList['0'] = 'N/A';
$lang->datatable->showModuleList['base'] = 'Basisknoten';
$lang->datatable->showModuleList['end'] = 'Endknoten';
$lang->datatable->showAllModuleList[0] = 'Hide';
+1 -1
View File
@@ -23,7 +23,7 @@ $lang->datatable->displaySetting = 'Set List';
$lang->datatable->showModule = 'Show modules in the list';
$lang->datatable->showBranch = 'Show branches in the list';
$lang->datatable->showAllModule = 'Show product modules';
$lang->datatable->showModuleList[] = 'N/A';
$lang->datatable->showModuleList['0'] = 'N/A';
$lang->datatable->showModuleList['base'] = 'Base Node';
$lang->datatable->showModuleList['end'] = 'End Node';
$lang->datatable->showAllModuleList[0] = 'Hide';
+1 -1
View File
@@ -23,7 +23,7 @@ $lang->datatable->displaySetting = 'Set list';
$lang->datatable->showModule = 'Montrer les noms des modules dans la page de listes';
$lang->datatable->showBranch = 'Show branches in the list';
$lang->datatable->showAllModule = 'Afficher les modules de produits';
$lang->datatable->showModuleList[] = 'N/A';
$lang->datatable->showModuleList['0'] = 'N/A';
$lang->datatable->showModuleList['base'] = 'Base Node';
$lang->datatable->showModuleList['end'] = 'End Node';
$lang->datatable->showAllModuleList[0] = 'Cacher';
+1 -1
View File
@@ -23,7 +23,7 @@ $lang->datatable->displaySetting = '显示设置';
$lang->datatable->showModule = '列表页是否显示模块名';
$lang->datatable->showBranch = '列表页是否显示%s名';
$lang->datatable->showAllModule = '是否显示完整产品模块';
$lang->datatable->showModuleList[] = '不显示';
$lang->datatable->showModuleList['0'] = '不显示';
$lang->datatable->showModuleList['base'] = '只显示一级模块';
$lang->datatable->showModuleList['end'] = '只显示最后一级模块';
$lang->datatable->showAllModuleList[0] = '不显示';
+15 -2
View File
@@ -1,15 +1,28 @@
$(function()
{
$('#subNavbar .nav li').removeClass('active');
$('#subNavbar .nav li').removeClass('active');
$('#subNavbar .nav li[data-id=' + type + ']').addClass('active');
$('#subNavbar .nav li > a').each(function()
{
var type = $(this).parent().attr('data-id');
if(type == 'bysearch') return;
if(type == 'more')
{
$(this).attr('href', '###');
return;
}
type = type == 'all' ? type : type.toUpperCase();
type = type == 'all' ? type : type.toLowerCase();
var href = createLink('design', 'browse', 'projectID=' + projectID + '&productID=' + productID + '&type=' + type);
$(this).attr('href', href);
});
if($('#subNavbar .dropdown-menu li[data-id=' + type +']').hasClass('active'))
{
var typeName = $('#subNavbar li[data-id=' + type +'] > a').html();
$('#subNavbar').find(".dropdown-hover > a").html(typeName + "<span class='caret'></span>");
$("#subNavbar li[data-id='more']").addClass('active');
}
})
+1
View File
@@ -37,6 +37,7 @@ $lang->design->createdDate = 'CreatedDate';
$lang->design->basicInfo = 'Basic Information';
$lang->design->noAssigned = 'Unassigned';
$lang->design->comment = 'Comment';
$lang->design->more = 'Mehr';
/* 动作列表. */
$lang->design->common = 'Design';
+1
View File
@@ -37,6 +37,7 @@ $lang->design->createdDate = 'CreatedDate';
$lang->design->basicInfo = 'Basic Information';
$lang->design->noAssigned = 'Unassigned';
$lang->design->comment = 'Comment';
$lang->design->more = 'More';
/* 动作列表. */
$lang->design->common = 'Design';
+1
View File
@@ -37,6 +37,7 @@ $lang->design->createdDate = 'CreatedDate';
$lang->design->basicInfo = 'Basic Information';
$lang->design->noAssigned = 'Unassigned';
$lang->design->comment = 'Comment';
$lang->design->more = 'Suite';
/* 动作列表. */
$lang->design->common = 'Design';
+1
View File
@@ -37,6 +37,7 @@ $lang->design->createdDate = '创建时间';
$lang->design->basicInfo = '基本信息';
$lang->design->noAssigned = '未指派';
$lang->design->comment = '注释';
$lang->design->more = '更多';
/* 动作列表. */
$lang->design->common = '设计';
+12 -1
View File
@@ -406,9 +406,20 @@ class designModel extends model
/* Show custom design types. */
$this->lang->waterfall->menu->design['subMenu'] = new stdclass();
$this->lang->waterfall->menu->design['subMenu']->all = array('link' => "{$this->lang->all}|design|browse|projectID=%s&productID=0&browseType=all");
$count = 1;
foreach(array_filter($this->lang->design->typeList) as $key => $value)
{
$this->lang->waterfall->menu->design['subMenu']->$key = array('link' => "{$value}|design|browse|projectID=%s&productID=0&browseType={$key}");
$key = strtolower($key);
if($count <= 4) $this->lang->waterfall->menu->design['subMenu']->$key = array('link' => "{$value}|design|browse|projectID=%s&productID=0&browseType={$key}");
if($count == 5)
{
$this->lang->waterfall->menu->design['subMenu']->more = array('link' => "{$this->lang->design->more}|design|browse|projectID=%s&productID=0&browseType={$key}", 'class' => 'dropdown dropdown-hover');
$this->lang->waterfall->menu->design['subMenu']->more['dropMenu'] = new stdclass();
}
if($count >= 5) $this->lang->waterfall->menu->design['subMenu']->more['dropMenu']->$key = array('link' => "{$value}|design|browse|projectID=%s&productID=0&browseType={$key}");
$count ++;
}
if($this->app->rawMethod == 'browse') $this->lang->waterfall->menu->design['subMenu']->bysearch = array('link' => '<a href="javascript:;" class="querybox-toggle"><i class="icon-search icon"></i> ' . $this->lang->searchAB . '</a>');
+1 -1
View File
@@ -16,7 +16,7 @@
<?php js::set('projectID', $design->project);?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php $browseLink = $app->session->designList != false ? $app->session->designList : $this->createLink('design', 'browse', "productID=$design->product");?>
<?php $browseLink = $app->session->designList != false ? $app->session->designList : $this->createLink('design', 'browse', "projectID=$design->project");?>
<?php if(!isonlybody()) echo html::a($browseLink, '<i class="icon icon-back icon-sm"></i> ' . $lang->goback, '', "class='btn btn-secondary'");?>
<div class="divider"></div>
<div class="page-title">
+1 -1
View File
@@ -1125,7 +1125,7 @@ class doc extends control
/* Set Custom. */
foreach(explode(',', $this->config->doc->customObjectLibs) as $libType) $customObjectLibs[$libType] = $this->lang->doc->customObjectLibs[$libType];
$actionURL = $this->createLink('doc', 'browse', "lib=0&browseType=bySearch&queryID=myQueryID");
$actionURL = $this->createLink('doc', 'tableContents', "type=$type&objectID=$objectID&libID=$libID&browseType=bySearch&param=myQueryID");
$this->doc->buildSearchForm(0, array(), 0, $actionURL, $type);
$moduleTree = $type == 'book' ? $this->doc->getBookStructure($libID) : $this->doc->getTreeMenu($type, $objectID, $libID, 0, $docID);
+12 -2
View File
@@ -60,18 +60,20 @@ class docModel extends model
* @param string $type
* @param string $extra
* @param string $appendLibs
* @param int $projectID
* @param int $objectID
* @param string $excludeType
*
* @access public
* @return array
*/
public function getLibs($type = '', $extra = '', $appendLibs = '', $objectID = 0)
public function getLibs($type = '', $extra = '', $appendLibs = '', $objectID = 0, $excludeType = '')
{
if($type == 'all' or $type == 'includeDeleted')
{
$stmt = $this->dao->select('*')->from(TABLE_DOCLIB)
->where('type')->ne('api')
->beginIF($type == 'all')->andWhere('deleted')->eq(0)->fi()
->beginIF($excludeType)->andWhere('type')->notin($excludeType)->fi()
->andWhere('vision')->eq($this->config->vision)
->orderBy('`order` asc, id_desc')
->query();
@@ -928,6 +930,13 @@ class docModel extends model
{
$this->loadModel('product');
/* Fixed search modal for doc view. */
if($this->app->getMethodName() == 'objectlibs')
{
$queryName = $type . 'Doc';
$type = 'objectLibs';
}
if($this->app->rawMethod == 'contribute')
{
$this->config->doc->search['module'] = 'contributeDoc';
@@ -951,6 +960,7 @@ class docModel extends model
}
else
{
$this->config->doc->search['module'] = $queryName;
$products = $this->product->getPairs('nocode', $this->session->project);
$this->config->doc->search['params']['execution']['values'] = array('' => '') + $this->loadModel('execution')->getPairs($this->session->project, 'all', 'noclosed') + array('all' => $this->lang->doc->allExecutions);
$this->config->doc->search['params']['lib']['values'] = array('' => '', $libID => ($libID ? $libs[$libID] : 0), 'all' => $this->lang->doclib->all);
+1 -2
View File
@@ -158,8 +158,7 @@
$(function()
{
var contentHeight = $(document).height() - 120;
setTimeout(function(){$('.ke-edit-iframe, .ke-edit').height(contentHeight);}, 100);
setTimeout(function(){$('.CodeMirror').height(contentHeight);}, 100);
setTimeout(function(){$('.ke-edit-iframe, .ke-edit, .ke-edit-textarea, .CodeMirror').height(contentHeight);}, 100);
$(document).on('click', '#modalBasicInfo tfoot .btn', function() {$('#modalBasicInfo').modal('hide');});
+1 -2
View File
@@ -155,8 +155,7 @@
$(function()
{
var contentHeight = $(document).height() - 100;
setTimeout(function(){$('.ke-edit-iframe, .ke-edit').height(contentHeight);}, 100);
setTimeout(function(){$('.CodeMirror').height(contentHeight);}, 100);
setTimeout(function(){$('.ke-edit-iframe, .ke-edit, .ke-edit-textarea, .CodeMirror').height(contentHeight);}, 100);
$(document).on('click', '#modalBasicInfo tfoot .btn', function() {$('#modalBasicInfo').modal('hide');});
+12 -5
View File
@@ -179,10 +179,14 @@ if(!isset($config->setCode) or $config->setCode == 1)
{
$config->execution->datatable->defaultField = array('id', 'name', 'code', 'project', 'PM', 'status', 'progress', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn');
}
else
elseif($config->systemMode == 'new')
{
$config->execution->datatable->defaultField = array('id', 'name', 'project', 'PM', 'status', 'progress', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn');
}
else
{
$config->execution->datatable->defaultField = array('id', 'name', 'PM', 'status', 'progress', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn');
}
$config->execution->datatable->fieldList['id']['title'] = 'idAB';
$config->execution->datatable->fieldList['id']['fixed'] = 'left';
@@ -202,10 +206,13 @@ if(!isset($config->setCode) or $config->setCode == 1)
$config->execution->datatable->fieldList['code']['required'] = 'no';
}
$config->execution->datatable->fieldList['project']['title'] = 'project';
$config->execution->datatable->fieldList['project']['fixed'] = 'no';
$config->execution->datatable->fieldList['project']['width'] = '100';
$config->execution->datatable->fieldList['project']['required'] = 'no';
if($config->systemMode == 'new')
{
$config->execution->datatable->fieldList['project']['title'] = 'project';
$config->execution->datatable->fieldList['project']['fixed'] = 'no';
$config->execution->datatable->fieldList['project']['width'] = '100';
$config->execution->datatable->fieldList['project']['required'] = 'no';
}
$config->execution->datatable->fieldList['PM']['title'] = 'owner';
$config->execution->datatable->fieldList['PM']['fixed'] = 'no';
+3 -1
View File
@@ -783,6 +783,7 @@ class execution extends control
/* Append id for secend sort. */
$sort = common::appendOrder($orderBy);
if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort);
$queryID = ($type == 'bysearch') ? $param : 0;
$execution = $this->commonAction($executionID);
@@ -3751,6 +3752,7 @@ class execution extends control
$this->view->pager = $pager;
$this->view->orderBy = $orderBy;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->projects = array('') + $this->project->getPairsByProgram();
$this->view->status = $status;
$this->view->from = $from;
$this->view->param = $param;
@@ -3996,7 +3998,7 @@ class execution extends control
{
foreach($planStory as $id => $story)
{
if($story->status == 'draft')
if($story->status == 'draft' or $story->status == 'reviewing')
{
$count++;
unset($planStory[$id]);
+1
View File
@@ -19,3 +19,4 @@ th.c-pri{width:50px;}
.panel-actions {position: relative; padding: 0;}
.switchBtn {background-color: #fff !important;}
.switchBtn > i {padding-left: 7px;}
#main>.container {padding: 0 20px 20px 23px;}
+2 -1
View File
@@ -141,9 +141,10 @@ function loadBranches(product)
if($inputgroup.find('.chosen-container').size() >= 2) $inputgroup.find('.chosen-container:last').remove();
var projectID = (typeof(systemMode) != 'undefined' && systemMode == 'new') ? $('#project').val() : 0;
if(typeof(projectID) == 'undefined') projectID = 0;
var index = $inputgroup.find('select:first').attr('id').replace('products' , '');
$.get(createLink('branch', 'ajaxGetBranches', "productID=" + $(product).val() + "&oldBranch=&param=active&projectID=" + projectID + "&withMainBranch="), function(data)
$.get(createLink('branch', 'ajaxGetBranches', "productID=" + $(product).val() + "&oldBranch=&param=active&projectID=" + projectID + "&withMainBranch=true"), function(data)
{
if(data)
{
+1 -1
View File
@@ -1130,7 +1130,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
if(data)
{
data = $.parseJSON(data);
if(data.status == 'draft' || data.status == 'changed')
if(data.status == 'draft' || data.status == 'changing' || data.status == 'reviewing')
{
bootbox.alert(executionLang.storyDragError);
}
+1 -1
View File
@@ -810,7 +810,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
if(data)
{
data = $.parseJSON(data);
if(data.status == 'draft' || data.status == 'changed')
if(data.status == 'draft' || data.status == 'changing' || data.status == 'reviewing')
{
bootbox.alert(executionLang.storyDragError);
}
+1 -1
View File
@@ -411,7 +411,7 @@ $lang->execution->unresolvedBug = "[%s] unresolved bugs. ";
$lang->execution->projectNotEmpty = 'Project cannot be empty.';
$lang->execution->confirmStoryToTask = $lang->SRCommon . '%s are converted to tasks in the current. Do you want to convert them anyways?';
$lang->execution->ge = "『%s』should be >= actual begin『%s』.";
$lang->execution->storyDragError = "The {$lang->SRCommon} is still a draft or has been changed, please drag it after the review";
$lang->execution->storyDragError = "The {$lang->SRCommon} is not active. Please activate and drag again.";
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
$lang->execution->week = 'week';
+1 -1
View File
@@ -411,7 +411,7 @@ $lang->execution->unresolvedBug = "[%s] unresolved bugs. ";
$lang->execution->projectNotEmpty = 'Project cannot be empty.';
$lang->execution->confirmStoryToTask = $lang->SRCommon . '%s are converted to tasks in the current. Do you want to convert them anyways?';
$lang->execution->ge = "『%s』should be >= actual begin『%s』.";
$lang->execution->storyDragError = "The {$lang->SRCommon} is still a draft or has been changed, please drag it after the review";
$lang->execution->storyDragError = "The {$lang->SRCommon} is not active. Please activate and drag again.";
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
$lang->execution->week = 'week';
+1 -1
View File
@@ -411,7 +411,7 @@ $lang->execution->unresolvedBug = "[%s] unresolved bugs. ";
$lang->execution->projectNotEmpty = 'Project cannot be empty.';
$lang->execution->confirmStoryToTask = $lang->SRCommon . '%s are converted to tasks in the current. Do you want to convert them anyways?';
$lang->execution->ge = "『%s』should be >= actual begin『%s』.";
$lang->execution->storyDragError = "The {$lang->SRCommon} is still a draft or has been changed, please drag it after the review";
$lang->execution->storyDragError = "The {$lang->SRCommon} is not active. Please activate and drag again.";
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
$lang->execution->week = 'week';
+1 -1
View File
@@ -411,7 +411,7 @@ $lang->execution->unresolvedBug = "[%s]个未解决的bug,";
$lang->execution->projectNotEmpty = '所属项目不能为空。';
$lang->execution->confirmStoryToTask = '%s' . $lang->SRCommon . '已经在当前' . $lang->execution->common . '中转了任务,请确认是否重复转任务。';
$lang->execution->ge = "『%s』应当不小于实际开始时间『%s』。";
$lang->execution->storyDragError = "该{$lang->SRCommon}还是草稿或已变更状态,请评审通过后再拖动";
$lang->execution->storyDragError = "该{$lang->SRCommon}不是激活状态,请激活后再拖动";
$lang->execution->countTip = '(%s人)';
$lang->execution->pleaseInput = "请输入";
$lang->execution->week = '周';
+25 -6
View File
@@ -785,6 +785,18 @@ class executionModel extends model
return false;
}
/* Replace required language. */
if($this->app->tab == 'project')
{
$this->lang->project->name = $this->lang->execution->name;
$this->lang->project->code = $this->lang->execution->code;
}
else
{
$this->lang->project->name = $this->lang->execution->execName;
$this->lang->project->code = $this->lang->execution->execCode;
}
$this->dao->update(TABLE_EXECUTION)->data($execution)
->autoCheck($skipFields = 'begin,end')
->batchcheck($this->config->execution->edit->requiredFields, 'notempty')
@@ -1303,12 +1315,16 @@ class executionModel extends model
* Get execution by idList.
*
* @param array $executionIdList
* @param string $mode all
* @access public
* @return array
*/
public function getByIdList($executionIdList = array())
public function getByIdList($executionIdList = array(), $mode = '')
{
return $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->in($executionIdList)->andWhere('deleted')->eq(0)->fetchAll('id');
return $this->dao->select('*')->from(TABLE_EXECUTION)
->where('id')->in($executionIdList)
->beginIF($mode != 'all')->andWhere('deleted')->eq(0)->fi()
->fetchAll('id');
}
/**
@@ -1561,10 +1577,11 @@ class executionModel extends model
* @param string $status
* @param int $limit
* @param string $pairs
* @param int $appenedID
* @access public
* @return array
*/
public function getByProject($projectID, $status = 'all', $limit = 0, $pairs = false, $devel = false)
public function getByProject($projectID, $status = 'all', $limit = 0, $pairs = false, $devel = false, $appendedID = 0)
{
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getExecutionPairs();
@@ -1581,6 +1598,7 @@ class executionModel extends model
->beginIF($status != 'all' and $status != 'undone' and $status != 'noclosed')->andWhere('status')->in($status)->fi()
->beginIF($status == 'noclosed')->andWhere('status')->ne('closed')->fi()
->beginIF($devel === true)->andWhere('attribute')->in('dev,qa,release')->fi()
->beginIF($appendedID)->orWhere('id')->eq($appendedID)->fi()
->orderBy($orderBy)
->beginIF($limit)->limit($limit)->fi()
->fetchAll('id');
@@ -2688,7 +2706,7 @@ class executionModel extends model
parse_str($extra, $output);
foreach($stories as $key => $storyID)
{
$notAllowedStatus = $this->app->rawMethod == 'batchcreate' ? 'closed' : 'draft,closed';
$notAllowedStatus = $this->app->rawMethod == 'batchcreate' ? 'closed' : 'draft,reviewing,closed';
if(strpos($notAllowedStatus, $storyList[$storyID]->status) !== false) continue;
if(isset($linkedStories[$storyID])) continue;
@@ -2783,7 +2801,7 @@ class executionModel extends model
{
foreach($planStory as $id => $story)
{
if($story->status == 'draft')
if($story->status == 'draft' or $story->status == 'reviewing')
{
unset($planStory[$id]);
continue;
@@ -3636,7 +3654,8 @@ class executionModel extends model
->page($pager)
->fetchAll('id');
$tasks = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.product, t2.branch, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName')
$orderBy = str_replace('pri_', 'priOrder_', $orderBy);
$tasks = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.product, t2.branch, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName, IF(t1.`pri` = 0, 999, t1.`pri`) as priOrder')
->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
->leftJoin(TABLE_USER)->alias('t3')->on('t1.assignedTo = t3.account')
+1 -1
View File
@@ -229,7 +229,7 @@
<tr id="story<?php echo $story->id;?>" data-id='<?php echo $story->id;?>' data-order='<?php echo $story->order ?>' data-estimate='<?php echo $story->estimate?>' data-cases='<?php echo zget($storyCases, $story->id, 0)?>'>
<?php foreach($setting as $key => $value)
{
$this->story->printCell($value, $story, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table', '', $execution, $showBranch);
$this->story->printCell($value, $story, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table', 'story', $execution, $showBranch);
}
?>
</tr>
+1
View File
@@ -314,6 +314,7 @@ class file extends control
$this->view->files = $files;
$this->view->fieldset = $fieldset;
$this->view->object = $object;
$this->view->method = $method;
if($method == 'view') return $this->display('file', 'viewfiles');
$this->display();
+6
View File
@@ -70,3 +70,9 @@ $lang->file->errorSuffix = 'Format ist falsch. Nur .zip Dateien!';
$lang->file->errorExtract = 'Entpacken fehlgeschlagen. Die Datei ist vermutlich defekt.';
$lang->file->fileNotFound = 'The file was not found. The physical file might have been deleted!';
$lang->file->fileContentEmpty = 'The file is empty. Check the file and upload it again.';
$lang->file->uploadError[1] = 'The uploaded filesize exceeds the limit. Please change the upload_max_filesize and post_max_size options in php.ini';
$lang->file->uploadError[2] = 'The size of the uploaded file exceeds the value specified by the MAX_FILE_SIZE option in the HTML form';
$lang->file->uploadError[3] = 'Only part of the file has been uploaded, please re-upload';
$lang->file->uploadError[4] = 'No files have been uploaded';
$lang->file->uploadError[5] = 'The size of the file is 0. Please upload the file again';
+6
View File
@@ -70,3 +70,9 @@ $lang->file->errorSuffix = 'Format is incorrect. .zip files ONLY!';
$lang->file->errorExtract = 'Extracting files failed. Files might be damaged or there might be invalid files in the zip package.';
$lang->file->fileNotFound = 'The file was not found. The physical file might have been deleted!';
$lang->file->fileContentEmpty = 'The file is empty. Check the file and upload it again.';
$lang->file->uploadError[1] = 'The uploaded filesize exceeds the limit. Please change the upload_max_filesize and post_max_size options in php.ini';
$lang->file->uploadError[2] = 'The size of the uploaded file exceeds the value specified by the MAX_FILE_SIZE option in the HTML form';
$lang->file->uploadError[3] = 'Only part of the file has been uploaded, please re-upload';
$lang->file->uploadError[4] = 'No files have been uploaded';
$lang->file->uploadError[5] = 'The size of the file is 0. Please upload the file again';
+6
View File
@@ -70,3 +70,9 @@ $lang->file->errorSuffix = 'Format incorrect. Fichiers .zip SEULEMENT !';
$lang->file->errorExtract = "Echec de l'extraction des fichiers. Les fichiers peuvent être endommagé ou il y a un fichier invalide dans le zip.";
$lang->file->fileNotFound = 'Fichier non trouvé. Le fichier physique a peut-être été supprimé par innadvertance !';
$lang->file->fileContentEmpty = 'The file is empty. Check the file and upload it again.';
$lang->file->uploadError[1] = 'The uploaded filesize exceeds the limit. Please change the upload_max_filesize and post_max_size options in php.ini';
$lang->file->uploadError[2] = 'The size of the uploaded file exceeds the value specified by the MAX_FILE_SIZE option in the HTML form';
$lang->file->uploadError[3] = 'Only part of the file has been uploaded, please re-upload';
$lang->file->uploadError[4] = 'No files have been uploaded';
$lang->file->uploadError[5] = 'The size of the file is 0. Please upload the file again';
+6
View File
@@ -65,3 +65,9 @@ $lang->file->errorSuffix = 'Format is incorrect. .zip files ONLY!';
$lang->file->errorExtract = 'Extracting files failed. Files might be damaged or there might be invalid files in the zip package.';
$lang->file->fileNotFound = 'Tập tin was not found. The physical file might have been deleted!';
$lang->file->fileContentEmpty = 'The file is empty. Check the file and upload it again.';
$lang->file->uploadError[1] = 'The uploaded filesize exceeds the limit. Please change the upload_max_filesize and post_max_size options in php.ini';
$lang->file->uploadError[2] = 'The size of the uploaded file exceeds the value specified by the MAX_FILE_SIZE option in the HTML form';
$lang->file->uploadError[3] = 'Only part of the file has been uploaded, please re-upload';
$lang->file->uploadError[4] = 'No files have been uploaded';
$lang->file->uploadError[5] = 'The size of the file is 0. Please upload the file again';
+6
View File
@@ -70,3 +70,9 @@ $lang->file->errorSuffix = '压缩包格式错误,只能上传zip压缩
$lang->file->errorExtract = '解压缩失败!可能文件已经损坏,或压缩包里含有非法上传文件。';
$lang->file->fileNotFound = '未找到该文件,可能物理文件已被删除!';
$lang->file->fileContentEmpty = '上传文件内容为空,请检查后重新上传。';
$lang->file->uploadError[1] = "上传的文件大小超过了限制,请修改 php.ini 中 upload_max_filesize 与 post_max_size 选项限制的值";
$lang->file->uploadError[2] = '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值';
$lang->file->uploadError[3] = '文件只有部分被上传,请重新上传';
$lang->file->uploadError[4] = '没有文件被上传';
$lang->file->uploadError[5] = '上传文件大小为0,请重新上传';
+2
View File
@@ -167,6 +167,8 @@ class fileModel extends model
$files = array();
if(!isset($_FILES[$htmlTagName])) return $files;
if(!is_array($_FILES[$htmlTagName]['error']) and $_FILES[$htmlTagName]['error'] != 0) return $_FILES[$htmlTagName];
$this->app->loadClass('purifier', true);
$config = HTMLPurifier_Config::createDefault();
$config->set('Cache.DefinitionImpl', null);
+1 -1
View File
@@ -92,7 +92,7 @@
if(common::hasPriv($objectType, 'edit', $object))
{
echo "<span class='right-icon'>&nbsp; ";
common::printLink('file', 'edit', "fileID=$file->id", $lang->file->edit, '', "data-width='400' class='fileAction btn btn-link edit iframe text-primary' title='{$lang->file->edit}'");
if($method != 'storyChange') common::printLink('file', 'edit', "fileID=$file->id", $lang->file->edit, '', "data-width='400' class='fileAction btn btn-link edit iframe text-primary' title='{$lang->file->edit}'");
if(common::hasPriv('file', 'delete')) echo html::a('###', $lang->delete, '', "class='fileAction btn btn-link text-primary' onclick='deleteFile($file->id)' title='$lang->delete'");
echo '</span>';
}
+28 -22
View File
@@ -491,15 +491,16 @@ $lang->resource->story = new stdclass();
$lang->resource->story->create = 'create';
$lang->resource->story->batchCreate = 'batchCreate';
$lang->resource->story->edit = 'editAction';
$lang->resource->story->linkStory = 'linkStory';
if($config->URAndSR) $lang->resource->story->linkStory = 'linkStory';
$lang->resource->story->batchEdit = 'batchEdit';
$lang->resource->story->export = 'exportAction';
$lang->resource->story->delete = 'deleteAction';
$lang->resource->story->view = 'view';
$lang->resource->story->change = 'changeAction';
$lang->resource->story->review = 'reviewAction';
$lang->resource->story->submitReview = 'submitReview';
$lang->resource->story->batchReview = 'batchReview';
$lang->resource->story->recall = 'recall';
$lang->resource->story->recall = 'recallAction';
$lang->resource->story->assignTo = 'assignAction';
$lang->resource->story->close = 'closeAction';
$lang->resource->story->batchClose = 'batchClose';
@@ -525,6 +526,7 @@ $lang->story->methodOrder[25] = 'delete';
$lang->story->methodOrder[30] = 'view';
$lang->story->methodOrder[35] = 'change';
$lang->story->methodOrder[40] = 'review';
$lang->story->methodOrder[44] = 'submitReview';
$lang->story->methodOrder[45] = 'batchReview';
$lang->story->methodOrder[50] = 'recall';
$lang->story->methodOrder[55] = 'close';
@@ -538,7 +540,7 @@ $lang->story->methodOrder[90] = 'tasks';
$lang->story->methodOrder[95] = 'bugs';
$lang->story->methodOrder[100] = 'cases';
$lang->story->methodOrder[105] = 'report';
$lang->story->methodOrder[110] = 'linkStory';
if($config->URAndSR) $lang->story->methodOrder[110] = 'linkStory';
$lang->story->methodOrder[115] = 'batchChangeBranch';
$lang->story->methodOrder[120] = 'batchChangeModule';
$lang->story->methodOrder[125] = 'batchToTask';
@@ -552,12 +554,14 @@ if($config->URAndSR)
$lang->resource->requirement->create = 'create';
$lang->resource->requirement->batchCreate = 'batchCreate';
$lang->resource->requirement->edit = 'editAction';
$lang->resource->requirement->linkStory = 'linkStory';
$lang->resource->requirement->batchEdit = 'batchEdit';
$lang->resource->requirement->export = 'exportAction';
$lang->resource->requirement->delete = 'deleteAction';
$lang->resource->requirement->view = 'view';
$lang->resource->requirement->change = 'changeAction';
$lang->resource->requirement->review = 'reviewAction';
$lang->resource->requirement->submitReview = 'submitReview';
$lang->resource->requirement->batchReview = 'batchReview';
$lang->resource->requirement->recall = 'recall';
$lang->resource->requirement->assignTo = 'assignAction';
@@ -570,25 +574,27 @@ if($config->URAndSR)
$lang->resource->requirement->batchChangeModule = 'batchChangeModule';
$lang->resource->requirement->linkRequirements = 'linkRequirementsAB';
$lang->requirement->methodOrder[5] = 'create';
$lang->requirement->methodOrder[10] = 'batchCreate';
$lang->requirement->methodOrder[15] = 'edit';
$lang->requirement->methodOrder[20] = 'export';
$lang->requirement->methodOrder[25] = 'delete';
$lang->requirement->methodOrder[30] = 'view';
$lang->requirement->methodOrder[35] = 'change';
$lang->requirement->methodOrder[40] = 'review';
$lang->requirement->methodOrder[45] = 'batchReview';
$lang->requirement->methodOrder[50] = 'recall';
$lang->requirement->methodOrder[55] = 'close';
$lang->requirement->methodOrder[60] = 'batchClose';
$lang->requirement->methodOrder[65] = 'assignTo';
$lang->requirement->methodOrder[70] = 'batchAssignTo';
$lang->requirement->methodOrder[75] = 'activate';
$lang->requirement->methodOrder[80] = 'report';
$lang->requirement->methodOrder[85] = 'batchChangeBranch';
$lang->requirement->methodOrder[90] = 'batchChangeModule';
$lang->requirement->methodOrder[95] = 'linkRequirements';
$lang->requirement->methodOrder[5] = 'create';
$lang->requirement->methodOrder[10] = 'batchCreate';
$lang->requirement->methodOrder[15] = 'edit';
$lang->requirement->methodOrder[20] = 'export';
$lang->requirement->methodOrder[25] = 'delete';
$lang->requirement->methodOrder[30] = 'view';
$lang->requirement->methodOrder[35] = 'change';
$lang->requirement->methodOrder[40] = 'review';
$lang->requirement->methodOrder[44] = 'submitReview';
$lang->requirement->methodOrder[45] = 'batchReview';
$lang->requirement->methodOrder[50] = 'recall';
$lang->requirement->methodOrder[55] = 'close';
$lang->requirement->methodOrder[60] = 'batchClose';
$lang->requirement->methodOrder[65] = 'assignTo';
$lang->requirement->methodOrder[70] = 'batchAssignTo';
$lang->requirement->methodOrder[75] = 'activate';
$lang->requirement->methodOrder[80] = 'report';
$lang->requirement->methodOrder[85] = 'linkStory';
$lang->requirement->methodOrder[90] = 'batchChangeBranch';
$lang->requirement->methodOrder[95] = 'batchChangeModule';
$lang->requirement->methodOrder[100] = 'linkRequirements';
}
/* Product plan. */
+1 -1
View File
@@ -3868,7 +3868,7 @@ class kanbanModel extends model
{
$menu = array();
$toTaskPriv = strpos('draft,closed', $story->status) !== false ? false : true;
$toTaskPriv = strpos('draft,reviewing,closed', $story->status) !== false ? false : true;
if(common::hasPriv('story', 'edit') and $this->story->isClickable($story, 'edit')) $menu[] = array('label' => $this->lang->story->edit, 'icon' => 'edit', 'url' => helper::createLink('story', 'edit', "storyID=$story->id", '', true), 'size' => '95%');
if(common::hasPriv('story', 'change') and $this->story->isClickable($story, 'change')) $menu[] = array('label' => $this->lang->story->change, 'icon' => 'alter', 'url' => helper::createLink('story', 'change', "storyID=$story->id", '', true), 'size' => '95%');
if(common::hasPriv('story', 'review') and $this->story->isClickable($story, 'review')) $menu[] = array('label' => $this->lang->story->review, 'icon' => 'search', 'url' => helper::createLink('story', 'review', "storyID=$story->id", '', true), 'size' => '95%');
+5 -4
View File
@@ -155,10 +155,11 @@ class messageModel extends model
$moduleName = $objectType == 'case' ? 'testcase' : $objectType;
$moduleName = $objectType == 'kanbancard' ? 'kanban' : $objectType;
$space = common::checkNotCN() ? ' ' : '';
$data = $user->realname . $space . $this->lang->action->label->$actionType . $space . $this->lang->action->objectTypes[$objectType];
$dataID = $objectType == 'kanbancard' ? $object->kanban : $objectID;
$data .= ' ' . html::a($sysURL . helper::createLink($moduleName, 'view', "id=$dataID"), "[#{$objectID}::{$object->$field}]");
$space = common::checkNotCN() ? ' ' : '';
$data = $user->realname . $space . $this->lang->action->label->$actionType . $space . $this->lang->action->objectTypes[$objectType];
$dataID = $objectType == 'kanbancard' ? $object->kanban : $objectID;
$url = helper::createLink($moduleName, 'view', "id=$dataID");
$data .= ' ' . html::a((strpos($url, $sysURL) === 0 ? '' : $sysURL) . $url, "[#{$objectID}::{$object->$field}]");
if($isonlybody) $_GET['onlybody'] = 'yes';
+1 -1
View File
@@ -639,7 +639,7 @@ class mr extends control
}
else
{
$allStories = $this->story->getProductStories($productID, 0, '0', 'draft,active,changed', 'story', 'id_desc', false, array_keys($linkedStories), $pager);
$allStories = $this->story->getProductStories($productID, 0, '0', 'draft,reviewing,active,changing', 'story', 'id_desc', false, array_keys($linkedStories), $pager);
}
$this->view->modules = $modules;
+9 -5
View File
@@ -332,15 +332,16 @@ EOF;
/* Append id for secend sort. */
$sort = common::appendOrder($orderBy);
if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort);
$queryID = ($type == 'bysearch') ? (int)$param : 0;
if($type == 'assignedBy')
{
$stories = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'story');
$stories = $this->my->getAssignedByMe($this->app->user->account, '', $pager, $sort, 'story');
}
elseif($type == 'bysearch')
{
$stories = $this->my->getStoriesBySearch($queryID, $this->app->rawMethod, $orderBy, $pager);
$stories = $this->my->getStoriesBySearch($queryID, $this->app->rawMethod, $sort, $pager);
}
else
{
@@ -396,15 +397,16 @@ EOF;
/* Append id for secend sort. */
$sort = common::appendOrder($orderBy);
if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort);
$queryID = ($type == 'bysearch') ? (int)$param : 0;
if($type == 'assignedBy')
{
$stories = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'requirement');
$stories = $this->my->getAssignedByMe($this->app->user->account, '', $pager, $sort, 'requirement');
}
elseif($type == 'bysearch')
{
$stories = $this->my->getRequirementsBySearch($queryID, $this->app->rawMethod, $orderBy, $pager);
$stories = $this->my->getRequirementsBySearch($queryID, $this->app->rawMethod, $sort, $pager);
}
else
{
@@ -569,9 +571,11 @@ EOF;
/* Append id for secend sort. */
$sort = common::appendOrder($orderBy);
if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort);
if(strpos($sort, 'severity_') !== false) $sort = str_replace('severity_', 'severityOrder_', $sort);
if($type == 'assignedBy')
{
$bugs = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'bug');
$bugs = $this->my->getAssignedByMe($this->app->user->account, '', $pager, $sort, 'bug');
}
else
{
+1
View File
@@ -10,3 +10,4 @@
.table td.c-hours {padding-right: 12px;}
.main-table tbody > tr.table-children > td:first-child::before {width: 3px;}
@-moz-document url-prefix() {.main-table tbody > tr.table-children > td:first-child::before {width: 4px;};}
.c-span {margin-left: 22px;}
+4 -1
View File
@@ -1 +1,4 @@
.c-execution, .c-build {width: 120px;}
.c-execution {width: 200px}
.c-build {width: 120px;}
.c-id {width: 60px;}
.c-status {width: 80px;}
+13 -10
View File
@@ -336,24 +336,27 @@ class myModel extends model
if($objectType == 'task')
{
$objectList = $this->dao->select('t1.*, t2.name as executionName')->from($this->config->objectTables[$module])->alias('t1')
$orderBy = strpos($orderBy, 'pri_') !== false ? str_replace('pri_', 'priOrder_', $orderBy) : 't1.' . $orderBy;
$objectList = $this->dao->select("t1.*, t2.name as executionName, t2.type as executionType, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder")->from($this->config->objectTables[$module])->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on("t1.execution = t2.id")
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.id')->in(array_keys($objectIDList))
->orderBy('t1.' . $orderBy)
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
}
elseif($objectType == 'requirement' or $objectType == 'story' or $objectType == 'bug')
{
$objectList = $this->dao->select('t1.*')->from($this->config->objectTables[$module])->alias('t1')
$orderBy = (strpos($orderBy, 'priOrder') !== false or strpos($orderBy, 'severityOrder') !== false) ? $orderBy : "t1.$orderBy";
$select = strpos($orderBy, 'severity') !== false ? "t1.*,IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder" : "t1.*,IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder";
$objectList = $this->dao->select($select)->from($this->config->objectTables[$module])->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on("t1.product = t2.id")
->where('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.id')->in(array_keys($objectIDList))
->beginIF($objectType == 'requirement' or $objectType == 'story')->andWhere('t1.type')->eq($objectType)->fi()
->orderBy('t1.' . $orderBy)
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
}
@@ -504,7 +507,6 @@ class myModel extends model
{
$rawMethod = $this->app->rawMethod;
$this->loadModel('execution');
$this->app->loadConfig('execution');
$this->config->execution->search['module'] = $rawMethod . 'Task';
$this->config->execution->search['actionURL'] = $actionURL;
@@ -580,7 +582,8 @@ class myModel extends model
$query = preg_replace('/`(\w+)`/', 't1.`$1`', $query);
$query = str_replace('t1.`project`', 't2.`project`', $query);
$tasks = $this->dao->select('t1.*, t2.id as executionID, t2.name as executionName, t2.type as executionType, t3.id as storyID, t3.title as storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion')
$orderBy = str_replace('pri_', 'priOrder_', $orderBy);
$tasks = $this->dao->select("t1.*, t2.id as executionID, t2.name as executionName, t2.type as executionType, t3.id as storyID, t3.title as storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder")
->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on("t1.execution = t2.id")
->leftJoin(TABLE_STORY)->alias('t3')->on('t1.story = t3.id')
@@ -827,7 +830,7 @@ class myModel extends model
$storyIDList[$storyID] = $storyID;
}
$stories = $this->dao->select('distinct t1.*, t2.name as productTitle, t4.title as planTitle')->from(TABLE_STORY)->alias('t1')
$stories = $this->dao->select("distinct t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, t2.name as productTitle, t4.title as planTitle")->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id')
->leftJoin(TABLE_PLANSTORY)->alias('t3')->on('t1.id = t3.plan')
->leftJoin(TABLE_PRODUCTPLAN)->alias('t4')->on('t3.plan = t4.id')
@@ -846,7 +849,7 @@ class myModel extends model
}
else
{
$stories = $this->dao->select('distinct t1.*, t2.name as productTitle, t4.title as planTitle')->from(TABLE_STORY)->alias('t1')
$stories = $this->dao->select("distinct t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, t2.name as productTitle, t4.title as planTitle")->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id')
->leftJoin(TABLE_PLANSTORY)->alias('t3')->on('t1.id = t3.plan')
->leftJoin(TABLE_PRODUCTPLAN)->alias('t4')->on('t3.plan = t4.id')
@@ -946,7 +949,7 @@ class myModel extends model
$requirementIDList[$requirementID] = $requirementID;
}
$requirements = $this->dao->select('distinct t1.*, t2.name as productTitle')->from(TABLE_STORY)->alias('t1')
$requirements = $this->dao->select("distinct t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, t2.name as productTitle")->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id')
->leftJoin(TABLE_STORYREVIEW)->alias('t3')->on('t1.id = t3.story')
->where($myRequirementQuery)
@@ -963,7 +966,7 @@ class myModel extends model
}
else
{
$requirements = $this->dao->select('distinct t1.*, t2.name as productTitle')->from(TABLE_STORY)->alias('t1')
$requirements = $this->dao->select("distinct t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, t2.name as productTitle")->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id')
->leftJoin(TABLE_STORYREVIEW)->alias('t3')->on('t1.id = t3.story')
->where($myRequirementQuery)
+32 -19
View File
@@ -76,6 +76,7 @@
<?php
$storyLink = $this->createLink('story', 'view', "id=$story->id");
$canBeChanged = common::canBeChanged('story', $story);
$spanClass = $canBatchAction ? 'c-span' : '';
?>
<tr>
<td class="c-id">
@@ -89,10 +90,10 @@
</td>
<td class='c-pri'><span class='label-pri <?php echo 'label-pri-' . $story->pri;?>' title='<?php echo zget($lang->story->priList, $story->pri, $story->pri);?>'><?php echo zget($lang->story->priList, $story->pri, $story->pri);?></span></td>
<td class='c-name nobr <?php if(!empty($story->children)) echo "has-child" ?>'>
<?php echo common::hasPriv('requirement', 'view') ? html::a($storyLink, $story->title, null, "style='color: $story->color' data-group='product'") : "<span title='$story->title'>$story->title</span>";?>
<?php echo common::hasPriv('requirement', 'view') ? html::a($storyLink, $story->title, null, "style='color: $story->color' data-group='product' title='$story->title'") : "<span title='$story->title'>$story->title</span>";?>
<?php if(!empty($story->children)) echo '<a class="story-toggle" data-id="' . $story->id . '"><i class="icon icon-angle-double-right"></i></a>';?>
</td>
<td class='c-product'><?php echo $story->productTitle;?></td>
<td class='c-product' title="<?php echo $story->productTitle;?>"><?php echo $story->productTitle;?></td>
<td class='c-user'><?php echo zget($users, $story->openedBy);?></td>
<td class='c-hours' title="<?php echo $story->estimate . ' ' . $lang->hourCommon;?>"><?php echo $story->estimate . $config->hourUnit;?></td>
<td class='c-status'><span class='status-story status-<?php echo $story->status;?>'> <?php echo $this->processStatus('story', $story);?></span></td>
@@ -103,7 +104,15 @@
{
$vars = "story={$story->id}";
echo common::buildIconButton('story', 'change', "$vars&from=&storyType=requirement", $story, 'list', 'alter', '', 'iframe', true);
echo common::buildIconButton('story', 'review', "$vars&from=product&storyType=requirement", $story, 'list', 'search', '', 'iframe', true);
if(strpos('draft,changing', $story->status) !== false)
{
echo common::buildIconButton('story', 'submitReview', "$vars&storyType=requirement", $story, 'list', 'sub-review', '', 'iframe', true);
}
else
{
echo common::buildIconButton('story', 'review', "$vars&from=product&storyType=requirement", $story, 'list', 'search', '', 'iframe', true);
}
echo common::buildIconButton('story', 'recall', "$vars&from=list&storyType=requirement", $story, 'list', 'undo', 'hiddenwin', '', '', '', $lang->story->recall);
echo common::buildIconButton('story', 'close', "$vars&from=&storyType=requirement", $story, 'list', '', '', 'iframe', true);
echo common::buildIconButton('story', 'edit', "$vars&from=default&storyType=requirement", $story, 'list', '', '', 'iframe', true, "data-width='95%'");
@@ -119,19 +128,14 @@
<?php $class .= ($i + 1 == count($story->children)) ? ' table-child-bottom' : '';?>
<tr class='table-children<?php echo $class;?> parent-<?php echo $story->id;?>' data-id='<?php echo $child->id?>' data-status='<?php echo $child->status?>' data-estimate='<?php echo $child->estimate?>'>
<td class="c-id">
<?php if($canBatchAction):?>
<div class="checkbox-primary">
<input type='checkbox' name='storyIdList[<?php echo $child->id;?>]' value='<?php echo $child->id;?>' />
<label></label>
</div>
<?php endif;?>
<span class="<?php echo $spanClass?>"></span>
<?php printf('%03d', $child->id);?>
</td>
<td class='c-pri'><span class='label-pri <?php echo 'label-pri-' . $child->pri;?>' title='<?php echo zget($lang->story->priList, $child->pri, $child->pri);?>'><?php echo zget($lang->story->priList, $child->pri, $child->pri);?></span></td>
<td class='c-name nobr'>
<?php echo '<span class="label label-badge label-light" title="' . $this->lang->story->children .'">SR</span> ' . (common::hasPriv('story', 'view') ? html::a($storyLink, $child->title, null, "style='color: $child->color' data-group='product'") : $child->title);?>
<?php echo '<span class="label label-badge label-light" title="' . $this->lang->story->children .'">SR</span> ' . (common::hasPriv('story', 'view') ? html::a($storyLink, $child->title, null, "style='color: $child->color' data-group='product' title='$child->title'") : $child->title);?>
</td>
<td class='c-product'><?php echo $child->productTitle;?></td>
<td class='c-product' title="<?php echo $child->productTitle;?>"><?php echo $child->productTitle;?></td>
<td class='c-user'><?php echo zget($users, $child->openedBy);?></td>
<td class='c-hours'><?php echo $child->estimate . $config->hourUnit;?></td>
<td class='c-status'><?php echo $child->URChanged ? "<span class='status-story status-changed'>{$this->lang->story->URChanged}</span>" : "<span class='status-story status-$child->status'>" . $this->processStatus('story', $child) . '</span>'?></td>
@@ -147,11 +151,20 @@
}
else
{
common::printIcon('story', 'change', $vars, $child, 'list', 'alter');
common::printIcon('story', 'review', $vars, $child, 'list', 'search');
common::printIcon('story', 'close', $vars, $child, 'list', '', '', 'iframe', true);
common::printIcon('story', 'edit', $vars, $child, 'list');
common::printIcon('story', 'createCase', "productID=$child->product&branch=$child->branch&module=0&from=&param=0&$vars", $child, 'list', 'sitemap');
common::printIcon('story', 'change', "$vars&from=&storyType=story", $child, 'list', 'alter', '', 'iframe', true);
if(strpos('draft,changing', $child->status) !== false)
{
common::printIcon('story', 'submitReview', "$vars&storyType=story", $child, 'list', 'sub-review', '', 'iframe', true);
}
else
{
common::printIcon('story', 'review', "$vars&from=product&storyType=story", $child, 'list', 'search', '', 'iframe', true);
}
common::printIcon('story', 'recall', "$vars&from=list&storyType=story", $child, 'list', 'undo', 'hiddenwin', '', '', '', $lang->story->recall);
common::printIcon('story', 'close', "$vars&from=&storyType=story", $child, 'list', '', '', 'iframe', true);
common::printIcon('story', 'edit', "$vars&from=default&storyType=story", $child, 'list');
}
}
?>
@@ -185,7 +198,7 @@
unset($lang->story->reviewResultList['revert']);
foreach($lang->story->reviewResultList as $key => $result)
{
$actionLink = $this->createLink('story', 'batchReview', "result=$key");
$actionLink = $this->createLink('story', 'batchReview', "result=$key&reason=&storyType=requirement");
if($key == 'reject')
{
echo "<li class='dropdown-submenu'>";
@@ -197,7 +210,7 @@
foreach($lang->story->reasonList as $key => $reason)
{
$actionLink = $this->createLink('story', 'batchReview', "result=reject&reason=$key");
$actionLink = $this->createLink('story', 'batchReview', "result=reject&reason=$key&storyType=requirement");
echo "<li>";
echo html::a('#', $reason, '', "onclick=\"setFormAction('$actionLink', 'hiddenwin')\"");
echo "</li>";
@@ -218,7 +231,7 @@
<button data-toggle="dropdown" type="button" class="btn"><?php echo $lang->story->assignedTo?> <span class="caret"></span></button>
<?php
$withSearch = count($users) > 10;
$actionLink = $this->createLink('story', 'batchAssignTo');
$actionLink = $this->createLink('story', 'batchAssignTo', 'storyType=requirement');
echo html::select('assignedTo', $users, '', 'class="hidden"');
if($withSearch)
{
+21 -3
View File
@@ -105,7 +105,16 @@
{
$vars = "story={$story->id}";
echo common::buildIconButton('story', 'change', $vars, $story, 'list', 'alter', '', 'iframe', true);
echo common::buildIconButton('story', 'review', $vars, $story, 'list', 'search', '', 'iframe', true);
if(strpos('draft,changing', $story->status) !== false)
{
echo common::buildIconButton('story', 'submitReview', $vars, $story, 'list', 'sub-review', '', 'iframe', true);
}
else
{
echo common::buildIconButton('story', 'review', $vars, $story, 'list', 'search', '', 'iframe', true);
}
echo common::buildIconButton('story', 'recall', $vars, $story, 'list', 'undo', 'hiddenwin', '', '', '', $lang->story->recall);
echo common::buildIconButton('story', 'close', $vars, $story, 'list', '', '', 'iframe', true);
echo common::buildIconButton('story', 'edit', $vars, $story, 'list', '', '', 'iframe', true, "data-width='95%'");
@@ -145,8 +154,17 @@
if($canBeChanged)
{
$vars = "story={$child->id}";
common::printIcon('story', 'change', $vars, $child, 'list', 'alter', '', 'iframe', true);
common::printIcon('story', 'review', $vars, $child, 'list', 'search', '', 'iframe', true);
common::printIcon('story', 'change', $vars, $child, 'list', 'alter', '', 'iframe', true);
if(strpos('draft,changing', $child->status) !== false)
{
common::printIcon('story', 'submitReview', $vars, $child, 'list', 'sub-review', '', 'iframe', true);
}
else
{
common::printIcon('story', 'review', $vars, $child, 'list', 'search', '', 'iframe', true);
}
common::printIcon('story', 'recall', $vars, $child, 'list', 'undo', 'hiddenwin', '', '', '', $lang->story->recall);
common::printIcon('story', 'close', $vars, $child, 'list', '', '', 'iframe', true);
common::printIcon('story', 'edit', $vars, $child, 'list', '', '', 'iframe', true, "data-width='95%'");
common::printIcon('story', 'createCase', "productID=$child->product&branch=$child->branch&module=0&from=&param=0&$vars", $child, 'list', 'sitemap', '', 'iframe', true, "data-width='95%'");
+3 -2
View File
@@ -108,8 +108,9 @@
}
else
{
$class = ($task->executionType == 'kanban') ? 'iframe' : '';
echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', true, $task->project), $task->name, null, "class='$class' data-width='80%' style='color: $task->color'");
$onlybody = $task->executionType == 'kanban' ? true : '';
$class = $task->executionType == 'kanban' ? 'iframe' : '';
echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', $onlybody, $task->project), $task->name, null, "class='$class' data-width='80%' style='color: $task->color'");
}
?>
<?php if(!empty($task->children)) echo '<a class="task-toggle" data-id="' . $task->id . '"><i class="icon icon-angle-double-right"></i></a>';?>
+4 -4
View File
@@ -47,12 +47,12 @@
<?php foreach($tasks as $task):?>
<tr>
<td class="c-id"><?php printf('%03d', $task->id);?></td>
<td class='text-left nobr'><?php echo html::a($this->createLink('testtask', 'view', "taskID=$task->id"), $task->name);?></td>
<td class='nobr'><?php echo $task->executionName?></td>
<td class='nobr' title='<?php echo $task->buildName;?>'><?php $task->build == 'trunk' ? print($lang->trunk) : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?></td>
<td class='text-left nobr' title='<?php echo $task->name;?>'><?php echo html::a($this->createLink('testtask', 'view', "taskID=$task->id"), $task->name);?></td>
<td class='nobr' title='<?php echo $task->executionName;?>'><?php echo $task->executionName;?></td>
<td class='nobr' title='<?php echo $task->build == 'trunk' ? $lang->trunk : $task->buildName;?>'><?php $task->build == 'trunk' ? print($lang->trunk) : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?></td>
<td><?php echo $task->begin?></td>
<td><?php echo $task->end?></td>
<td title='<?php echo $task->status?>'><span class="status-task status-<?php echo $task->status?>"><?php echo $this->processStatus('testtask', $task);?></span></td>
<td title='<?php echo $this->processStatus('testtask', $task);?>'><span class="status-task status-<?php echo $task->status?>"><?php echo $this->processStatus('testtask', $task);?></span></td>
<td class='c-actions'>
<?php
common::printIcon('testtask', 'cases', "taskID=$task->id", $task, 'list', 'sitemap', '', '', '', "data-app='qa'");
+1 -1
View File
@@ -17,7 +17,7 @@ $config->port->datetimeFeilds = '';
$config->port->listFields = '';
$config->port->sysLangFields = ',pri,status,type,mode,severity,os,browser,resolution,confirmed,source,reviewResult,stage,change,category';
$config->port->sysDataFields = 'execution,product,user';
$config->port->userFields = 'assignedTo,openedBy,finishedBy,canceledBy,closedBy,lastEditedBy,lastRunner,resolvedBy,reviewedBy';
$config->port->userFields = 'assignedTo,openedBy,finishedBy,canceledBy,closedBy,lastEditedBy,lastRunner,resolvedBy,reviewedBy,mailto';
$config->port->defaultZeroField = 'severity,pri';
$config->port->defaultEmptyField = '';

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