Merge branch 'master_xieqiyu_draftStory' into 'master'
Master xieqiyu draft story See merge request easycorp/zentaopms!5060
This commit is contained in:
+4
-4
@@ -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
@@ -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 />', ''),
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
UPDATE `zt_story` SET `status` = 'reviewing' WHERE `status` = 'changed';
|
||||
ALTER TABLE `zt_story` MODIFY `status` enum('','changed','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`;
|
||||
|
||||
+1
-1
@@ -1442,7 +1442,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',
|
||||
|
||||
@@ -147,7 +147,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,6 +221,7 @@ $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. */
|
||||
@@ -275,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';
|
||||
@@ -387,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;
|
||||
|
||||
@@ -221,6 +221,7 @@ $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. */
|
||||
@@ -275,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';
|
||||
@@ -387,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;
|
||||
|
||||
@@ -221,6 +221,7 @@ $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. */
|
||||
@@ -275,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 ';
|
||||
@@ -387,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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -221,6 +221,7 @@ $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";
|
||||
|
||||
/* 用来描述和父子任务相关的操作历史记录。*/
|
||||
@@ -275,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 = '确认了';
|
||||
@@ -387,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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -3996,7 +3996,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]);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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 = '周';
|
||||
|
||||
@@ -2688,7 +2688,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 +2783,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;
|
||||
|
||||
@@ -498,8 +498,9 @@ $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';
|
||||
|
||||
@@ -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%');
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -149,8 +149,8 @@ $config->product->report->planLabels = array();
|
||||
$config->product->report->planLabels[] = '';
|
||||
|
||||
$config->product->statisticFields = array();
|
||||
$config->product->statisticFields['requirements'] = array('draftRequirements', 'activeRequirements', 'changedRequirements', 'closedRequirements');
|
||||
$config->product->statisticFields['stories'] = array('draftStories', 'activeStories', 'changedStories', 'closedStories');
|
||||
$config->product->statisticFields['requirements'] = array('draftRequirements', 'activeRequirements', 'changingRequirements', 'closedRequirements');
|
||||
$config->product->statisticFields['stories'] = array('draftStories', 'activeStories', 'changingStories', 'closedStories');
|
||||
$config->product->statisticFields['bugs'] = array('unResolvedBugs', 'closedBugs', 'fixedBugs');
|
||||
$config->product->statisticFields['plans'] = array('plans');
|
||||
$config->product->statisticFields['releases'] = array('releases');
|
||||
|
||||
+13
-13
@@ -1450,27 +1450,27 @@ class product extends control
|
||||
$productStats = $this->product->getStats('program_desc,line_desc,' . $orderBy, null, $status);
|
||||
foreach($productStats as $i => $product)
|
||||
{
|
||||
$product->line = zget($lines, $product->line, '');
|
||||
$product->line = zget($lines, $product->line, '');
|
||||
if($this->config->URAndSR)
|
||||
{
|
||||
$product->activeRequirements = (int) $product->requirements['active'];
|
||||
$product->changedRequirements = (int) $product->requirements['changed'];
|
||||
$product->changedRequirements = (int) $product->requirements['changing'];
|
||||
$product->draftRequirements = (int) $product->requirements['draft'];
|
||||
$product->closedRequirements = (int) $product->requirements['closed'];
|
||||
$product->totalRequirements = $product->activeRequirements + $product->changedRequirements + $product->draftRequirements + $product->closedRequirements;
|
||||
$product->requireCompleteRate = ($product->totalRequirements == 0 ? 0 : round($product->closedRequirements / $product->totalRequirements, 3) * 100) . '%';
|
||||
}
|
||||
$product->activeStories = (int)$product->stories['active'];
|
||||
$product->changedStories = (int)$product->stories['changed'];
|
||||
$product->draftStories = (int)$product->stories['draft'];
|
||||
$product->closedStories = (int)$product->stories['closed'];
|
||||
$product->totalStories = $product->activeStories + $product->changedStories + $product->draftStories + $product->closedStories;
|
||||
$product->storyCompleteRate = ($product->totalStories == 0 ? 0 : round($product->closedStories / $product->totalStories, 3) * 100) . '%';
|
||||
$product->unResolvedBugs = (int)$product->unResolved;
|
||||
$product->assignToNullBugs = (int)$product->assignToNull;
|
||||
$product->closedBugs = (int)$product->closedBugs;
|
||||
$product->bugFixedRate = (($product->unResolved + $product->fixedBugs) == 0 ? 0 : round($product->fixedBugs / ($product->unResolved + $product->fixedBugs), 3) * 100) . '%';
|
||||
$product->program = $product->programName;
|
||||
$product->activeStories = (int)$product->stories['active'];
|
||||
$product->changedStories = (int)$product->stories['changing'];
|
||||
$product->draftStories = (int)$product->stories['draft'];
|
||||
$product->closedStories = (int)$product->stories['closed'];
|
||||
$product->totalStories = $product->activeStories + $product->changedStories + $product->draftStories + $product->closedStories;
|
||||
$product->storyCompleteRate = ($product->totalStories == 0 ? 0 : round($product->closedStories / $product->totalStories, 3) * 100) . '%';
|
||||
$product->unResolvedBugs = (int)$product->unResolved;
|
||||
$product->assignToNullBugs = (int)$product->assignToNull;
|
||||
$product->closedBugs = (int)$product->closedBugs;
|
||||
$product->bugFixedRate = (($product->unResolved + $product->fixedBugs) == 0 ? 0 : round($product->fixedBugs / ($product->unResolved + $product->fixedBugs), 3) * 100) . '%';
|
||||
$product->program = $product->programName;
|
||||
|
||||
/* get rowspan data */
|
||||
if($lastProgram == '' or $product->program != $lastProgram)
|
||||
|
||||
+31
-29
@@ -134,21 +134,22 @@ $lang->product->createdDate = 'Created Date';
|
||||
$lang->product->createdVersion = 'Created Version';
|
||||
$lang->product->mailto = 'Mailto';
|
||||
|
||||
$lang->product->searchStory = 'Suche';
|
||||
$lang->product->assignedToMe = 'Mir zuweisen';
|
||||
$lang->product->openedByMe = 'Von mir erstellt';
|
||||
$lang->product->reviewedByMe = 'Von mir geprüft';
|
||||
$lang->product->reviewByMe = 'ReviewByMe';
|
||||
$lang->product->closedByMe = 'Von mir geschlossen';
|
||||
$lang->product->draftStory = 'Entwurf';
|
||||
$lang->product->activeStory = 'Aktiviert';
|
||||
$lang->product->changedStory = 'Geändert';
|
||||
$lang->product->willClose = 'Zu schließen';
|
||||
$lang->product->closedStory = 'Geschlossen';
|
||||
$lang->product->unclosed = 'Offen';
|
||||
$lang->product->unplan = 'Warten';
|
||||
$lang->product->viewByUser = 'By User';
|
||||
$lang->product->assignedByMe = 'AssignedByMe';
|
||||
$lang->product->searchStory = 'Suche';
|
||||
$lang->product->assignedToMe = 'Mir zuweisen';
|
||||
$lang->product->openedByMe = 'Von mir erstellt';
|
||||
$lang->product->reviewedByMe = 'Von mir geprüft';
|
||||
$lang->product->reviewByMe = 'ReviewByMe';
|
||||
$lang->product->closedByMe = 'Von mir geschlossen';
|
||||
$lang->product->draftStory = 'Entwurf';
|
||||
$lang->product->activeStory = 'Aktiviert';
|
||||
$lang->product->changingStory = 'Ändern';
|
||||
$lang->product->reviewingStory = 'Wird geprüft';
|
||||
$lang->product->willClose = 'Zu schließen';
|
||||
$lang->product->closedStory = 'Geschlossen';
|
||||
$lang->product->unclosed = 'Offen';
|
||||
$lang->product->unplan = 'Warten';
|
||||
$lang->product->viewByUser = 'By User';
|
||||
$lang->product->assignedByMe = 'AssignedByMe';
|
||||
|
||||
/* Product Kanban. */
|
||||
$lang->product->myProduct = 'Products Ownedbyme';
|
||||
@@ -206,22 +207,23 @@ $lang->product->noModule = '<div>Kein Modul</div><div>Jetzt verwalten</div
|
||||
$lang->product->noProduct = 'Kein Produkt. ';
|
||||
$lang->product->noMatched = '"%s" kann nicht gefunden werden.' . $lang->productCommon;
|
||||
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe;
|
||||
$lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe;
|
||||
$lang->product->featureBar['browse']['reviewbyme'] = $lang->product->reviewByMe;
|
||||
$lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory;
|
||||
$lang->product->featureBar['browse']['more'] = $lang->more;
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe;
|
||||
$lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe;
|
||||
$lang->product->featureBar['browse']['reviewbyme'] = $lang->product->reviewByMe;
|
||||
$lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory;
|
||||
$lang->product->featureBar['browse']['reviewingstory'] = $lang->product->reviewingStory;
|
||||
$lang->product->featureBar['browse']['more'] = $lang->more;
|
||||
|
||||
$lang->product->featureBar['all']['all'] = $lang->product->allProduct;
|
||||
$lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed'];
|
||||
|
||||
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changedstory'] = $lang->product->changedStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changingstory'] = $lang->product->changingStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
|
||||
+31
-29
@@ -134,21 +134,22 @@ $lang->product->createdDate = 'createdDate';
|
||||
$lang->product->createdVersion = 'Created Version';
|
||||
$lang->product->mailto = 'Mailto';
|
||||
|
||||
$lang->product->searchStory = 'Search';
|
||||
$lang->product->assignedToMe = 'AssignedToMe';
|
||||
$lang->product->openedByMe = 'CreatedByMe';
|
||||
$lang->product->reviewedByMe = 'ReviewedByMe';
|
||||
$lang->product->reviewByMe = 'ReviewByMe';
|
||||
$lang->product->closedByMe = 'ClosedByMe';
|
||||
$lang->product->draftStory = 'Draft';
|
||||
$lang->product->activeStory = 'Activated';
|
||||
$lang->product->changedStory = 'Changed';
|
||||
$lang->product->willClose = 'ToBeClosed';
|
||||
$lang->product->closedStory = 'Closed';
|
||||
$lang->product->unclosed = 'Open';
|
||||
$lang->product->unplan = 'Unplanned';
|
||||
$lang->product->viewByUser = 'By User';
|
||||
$lang->product->assignedByMe = 'AssignedByMe';
|
||||
$lang->product->searchStory = 'Search';
|
||||
$lang->product->assignedToMe = 'AssignedToMe';
|
||||
$lang->product->openedByMe = 'CreatedByMe';
|
||||
$lang->product->reviewedByMe = 'ReviewedByMe';
|
||||
$lang->product->reviewByMe = 'ReviewByMe';
|
||||
$lang->product->closedByMe = 'ClosedByMe';
|
||||
$lang->product->draftStory = 'Draft';
|
||||
$lang->product->activeStory = 'Activated';
|
||||
$lang->product->changingStory = 'Changing';
|
||||
$lang->product->reviewingStory = 'Reviewing';
|
||||
$lang->product->willClose = 'ToBeClosed';
|
||||
$lang->product->closedStory = 'Closed';
|
||||
$lang->product->unclosed = 'Open';
|
||||
$lang->product->unplan = 'Unplanned';
|
||||
$lang->product->viewByUser = 'By User';
|
||||
$lang->product->assignedByMe = 'AssignedByMe';
|
||||
|
||||
/* Product Kanban. */
|
||||
$lang->product->myProduct = 'Products Ownedbyme';
|
||||
@@ -206,22 +207,23 @@ $lang->product->noModule = '<div>You have no modules. </div><div>Manage No
|
||||
$lang->product->noProduct = "No {$lang->productCommon} yet. ";
|
||||
$lang->product->noMatched = '"%s" cannot be found.' . $lang->productCommon;
|
||||
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe;
|
||||
$lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe;
|
||||
$lang->product->featureBar['browse']['reviewbyme'] = $lang->product->reviewByMe;
|
||||
$lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory;
|
||||
$lang->product->featureBar['browse']['more'] = $lang->more;
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe;
|
||||
$lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe;
|
||||
$lang->product->featureBar['browse']['reviewbyme'] = $lang->product->reviewByMe;
|
||||
$lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory;
|
||||
$lang->product->featureBar['browse']['reviewingstory'] = $lang->product->reviewingStory;
|
||||
$lang->product->featureBar['browse']['more'] = $lang->more;
|
||||
|
||||
$lang->product->featureBar['all']['all'] = $lang->product->allProduct;
|
||||
$lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed'];
|
||||
|
||||
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changedstory'] = $lang->product->changedStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changingstory'] = $lang->product->changingStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
|
||||
+31
-29
@@ -134,21 +134,22 @@ $lang->product->createdDate = 'Créé le';
|
||||
$lang->product->createdVersion = 'Created Version';
|
||||
$lang->product->mailto = 'Mailto';
|
||||
|
||||
$lang->product->searchStory = 'Recherche';
|
||||
$lang->product->assignedToMe = 'Affectées à Moi';
|
||||
$lang->product->openedByMe = 'Créées par Moi';
|
||||
$lang->product->reviewedByMe = 'Validées par Moi';
|
||||
$lang->product->reviewByMe = 'ReviewByMe';
|
||||
$lang->product->closedByMe = 'Fermées par Moi';
|
||||
$lang->product->draftStory = 'A étudier';
|
||||
$lang->product->activeStory = 'Actives';
|
||||
$lang->product->changedStory = 'Changées';
|
||||
$lang->product->willClose = 'A Fermer';
|
||||
$lang->product->closedStory = 'Fermées';
|
||||
$lang->product->unclosed = 'Ouvertes';
|
||||
$lang->product->unplan = 'Non planifiées';
|
||||
$lang->product->viewByUser = 'Par Utilisateur';
|
||||
$lang->product->assignedByMe = 'AssignedByMe';
|
||||
$lang->product->searchStory = 'Recherche';
|
||||
$lang->product->assignedToMe = 'Affectées à Moi';
|
||||
$lang->product->openedByMe = 'Créées par Moi';
|
||||
$lang->product->reviewedByMe = 'Validées par Moi';
|
||||
$lang->product->reviewByMe = 'ReviewByMe';
|
||||
$lang->product->closedByMe = 'Fermées par Moi';
|
||||
$lang->product->draftStory = 'A étudier';
|
||||
$lang->product->activeStory = 'Actives';
|
||||
$lang->product->changingStory = 'Changement en cours';
|
||||
$lang->product->reviewingStory = 'Examen en cours';
|
||||
$lang->product->willClose = 'A Fermer';
|
||||
$lang->product->closedStory = 'Fermées';
|
||||
$lang->product->unclosed = 'Ouvertes';
|
||||
$lang->product->unplan = 'Non planifiées';
|
||||
$lang->product->viewByUser = 'Par Utilisateur';
|
||||
$lang->product->assignedByMe = 'AssignedByMe';
|
||||
|
||||
/* Product Kanban. */
|
||||
$lang->product->myProduct = 'Products Ownedbyme';
|
||||
@@ -206,22 +207,23 @@ $lang->product->noModule = "<div>Vous n'avez aucun modules. </div><div>Gé
|
||||
$lang->product->noProduct = "No {$lang->productCommon} à ce jour. ";
|
||||
$lang->product->noMatched = '"%s" cannot be found.' . $lang->productCommon;
|
||||
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe;
|
||||
$lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe;
|
||||
$lang->product->featureBar['browse']['reviewbyme'] = $lang->product->reviewByMe;
|
||||
$lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory;
|
||||
$lang->product->featureBar['browse']['more'] = $lang->more;
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe;
|
||||
$lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe;
|
||||
$lang->product->featureBar['browse']['reviewbyme'] = $lang->product->reviewByMe;
|
||||
$lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory;
|
||||
$lang->product->featureBar['browse']['reviewingstory'] = $lang->product->reviewingStory;
|
||||
$lang->product->featureBar['browse']['more'] = $lang->more;
|
||||
|
||||
$lang->product->featureBar['all']['all'] = $lang->product->allProduct;
|
||||
$lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed'];
|
||||
|
||||
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changedstory'] = $lang->product->changedStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changingstory'] = $lang->product->changingStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
|
||||
+27
-25
@@ -115,19 +115,20 @@ $lang->product->iterationView = 'Chi tiết';
|
||||
$lang->product->createdBy = 'Người tạo';
|
||||
$lang->product->createdDate = 'Ngày tạo';
|
||||
|
||||
$lang->product->searchStory = 'Tìm kiếm';
|
||||
$lang->product->assignedToMe = 'Giao cho bạn';
|
||||
$lang->product->openedByMe = 'Tạo bởi bạn';
|
||||
$lang->product->reviewedByMe = 'Duyệt bởi bạn';
|
||||
$lang->product->closedByMe = 'Đóng bởi bạn';
|
||||
$lang->product->draftStory = 'Nháp';
|
||||
$lang->product->activeStory = 'Đã kích hoạt';
|
||||
$lang->product->changedStory = 'Đã thay đổi';
|
||||
$lang->product->willClose = 'Đã đóng';
|
||||
$lang->product->closedStory = 'Đã đóng';
|
||||
$lang->product->unclosed = 'Mở';
|
||||
$lang->product->unplan = 'Chưa kế hoạch';
|
||||
$lang->product->viewByUser = 'Theo người dùng';
|
||||
$lang->product->searchStory = 'Tìm kiếm';
|
||||
$lang->product->assignedToMe = 'Giao cho bạn';
|
||||
$lang->product->openedByMe = 'Tạo bởi bạn';
|
||||
$lang->product->reviewedByMe = 'Duyệt bởi bạn';
|
||||
$lang->product->closedByMe = 'Đóng bởi bạn';
|
||||
$lang->product->draftStory = 'Nháp';
|
||||
$lang->product->activeStory = 'Đã kích hoạt';
|
||||
$lang->product->changingStory = 'Biến';
|
||||
$lang->product->reviewingStory = 'Đang xem xét';
|
||||
$lang->product->willClose = 'Đã đóng';
|
||||
$lang->product->closedStory = 'Đã đóng';
|
||||
$lang->product->unclosed = 'Mở';
|
||||
$lang->product->unplan = 'Chưa kế hoạch';
|
||||
$lang->product->viewByUser = 'Theo người dùng';
|
||||
|
||||
$lang->product->allStory = 'Tất cả ';
|
||||
$lang->product->allProduct = 'Tất cả';
|
||||
@@ -165,20 +166,21 @@ $lang->product->noModule = '<div>Chưa có Module. </div><div>Quản lý n
|
||||
$lang->product->noProduct = "Không có {$lang->productCommon} nào.";
|
||||
$lang->product->noMatched = '"%s" không thể tìm thấy ' . $lang->productCommon;
|
||||
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe;
|
||||
$lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe;
|
||||
$lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory;
|
||||
$lang->product->featureBar['browse']['more'] = $lang->more;
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe;
|
||||
$lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe;
|
||||
$lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory;
|
||||
$lang->product->featureBar['browse']['reviewingstory'] = $lang->product->reviewingStory;
|
||||
$lang->product->featureBar['browse']['more'] = $lang->more;
|
||||
|
||||
$lang->product->featureBar['all']['all'] = $lang->product->allProduct;
|
||||
$lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed'];
|
||||
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changedstory'] = $lang->product->changedStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changingstory'] = $lang->product->changingStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
|
||||
@@ -134,21 +134,22 @@ $lang->product->createdDate = '创建日期';
|
||||
$lang->product->createdVersion = '创建版本';
|
||||
$lang->product->mailto = '抄送给';
|
||||
|
||||
$lang->product->searchStory = '搜索';
|
||||
$lang->product->assignedToMe = '指给我';
|
||||
$lang->product->openedByMe = '我创建';
|
||||
$lang->product->reviewedByMe = '我评审';
|
||||
$lang->product->reviewByMe = '待我评审';
|
||||
$lang->product->closedByMe = '我关闭';
|
||||
$lang->product->draftStory = '草稿';
|
||||
$lang->product->activeStory = '激活';
|
||||
$lang->product->changedStory = '已变更';
|
||||
$lang->product->willClose = '待关闭';
|
||||
$lang->product->closedStory = '已关闭';
|
||||
$lang->product->unclosed = '未关闭';
|
||||
$lang->product->unplan = "未计划";
|
||||
$lang->product->viewByUser = '按用户查看';
|
||||
$lang->product->assignedByMe = '我指派';
|
||||
$lang->product->searchStory = '搜索';
|
||||
$lang->product->assignedToMe = '指给我';
|
||||
$lang->product->openedByMe = '我创建';
|
||||
$lang->product->reviewedByMe = '我评审';
|
||||
$lang->product->reviewByMe = '待我评审';
|
||||
$lang->product->closedByMe = '我关闭';
|
||||
$lang->product->draftStory = '草稿';
|
||||
$lang->product->activeStory = '激活';
|
||||
$lang->product->changingStory = '变更中';
|
||||
$lang->product->reviewingStory = '评审中';
|
||||
$lang->product->willClose = '待关闭';
|
||||
$lang->product->closedStory = '已关闭';
|
||||
$lang->product->unclosed = '未关闭';
|
||||
$lang->product->unplan = "未计划";
|
||||
$lang->product->viewByUser = '按用户查看';
|
||||
$lang->product->assignedByMe = '我指派';
|
||||
|
||||
/* Product Kanban. */
|
||||
$lang->product->myProduct = '我负责的' . $lang->productCommon;
|
||||
@@ -206,22 +207,23 @@ $lang->product->noModule = "<div>您现在还没有模块信息</div><div>
|
||||
$lang->product->noProduct = "暂时没有{$lang->productCommon}。";
|
||||
$lang->product->noMatched = '找不到包含"%s"的' . $lang->productCommon;
|
||||
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe;
|
||||
$lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe;
|
||||
$lang->product->featureBar['browse']['reviewbyme'] = $lang->product->reviewByMe;
|
||||
$lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory;
|
||||
$lang->product->featureBar['browse']['more'] = $lang->more;
|
||||
$lang->product->featureBar['browse']['allstory'] = $lang->product->allStory;
|
||||
$lang->product->featureBar['browse']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['browse']['assignedtome'] = $lang->product->assignedToMe;
|
||||
$lang->product->featureBar['browse']['openedbyme'] = $lang->product->openedByMe;
|
||||
$lang->product->featureBar['browse']['reviewedbyme'] = $lang->product->reviewedByMe;
|
||||
$lang->product->featureBar['browse']['reviewbyme'] = $lang->product->reviewByMe;
|
||||
$lang->product->featureBar['browse']['draftstory'] = $lang->product->draftStory;
|
||||
$lang->product->featureBar['browse']['reviewingstory'] = $lang->product->reviewingStory;
|
||||
$lang->product->featureBar['browse']['more'] = $lang->more;
|
||||
|
||||
$lang->product->featureBar['all']['all'] = '所有' . $lang->productCommon;
|
||||
$lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed'];
|
||||
|
||||
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changedstory'] = $lang->product->changedStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changingstory'] = $lang->product->changingStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
|
||||
@@ -126,20 +126,20 @@ $lang->product->createdDate = '創建日期';
|
||||
$lang->product->createdVersion = '創建版本';
|
||||
$lang->product->mailto = '抄送給';
|
||||
|
||||
$lang->product->searchStory = '搜索';
|
||||
$lang->product->assignedToMe = '指給我';
|
||||
$lang->product->openedByMe = '我創建';
|
||||
$lang->product->reviewedByMe = '我評審';
|
||||
$lang->product->reviewByMe = '待我評審';
|
||||
$lang->product->closedByMe = '我關閉';
|
||||
$lang->product->draftStory = '草稿';
|
||||
$lang->product->activeStory = '激活';
|
||||
$lang->product->changedStory = '已變更';
|
||||
$lang->product->willClose = '待關閉';
|
||||
$lang->product->closedStory = '已關閉';
|
||||
$lang->product->unclosed = '未關閉';
|
||||
$lang->product->unplan = "未計劃";
|
||||
$lang->product->viewByUser = '按用戶查看';
|
||||
$lang->product->searchStory = '搜索';
|
||||
$lang->product->assignedToMe = '指給我';
|
||||
$lang->product->openedByMe = '我創建';
|
||||
$lang->product->reviewedByMe = '我評審';
|
||||
$lang->product->reviewByMe = '待我評審';
|
||||
$lang->product->closedByMe = '我關閉';
|
||||
$lang->product->draftStory = '草稿';
|
||||
$lang->product->activeStory = '激活';
|
||||
$lang->product->changingStory = '變更中';
|
||||
$lang->product->willClose = '待關閉';
|
||||
$lang->product->closedStory = '已關閉';
|
||||
$lang->product->unclosed = '未關閉';
|
||||
$lang->product->unplan = "未計劃";
|
||||
$lang->product->viewByUser = '按用戶查看';
|
||||
|
||||
/* Product Kanban. */
|
||||
$lang->product->myProduct = '我負責的' . $lang->productCommon;
|
||||
@@ -210,8 +210,8 @@ $lang->product->featureBar['all']['all'] = '所有' . $lang->productCommon;
|
||||
$lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed;
|
||||
$lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed'];
|
||||
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changedstory'] = $lang->product->changedStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
|
||||
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
|
||||
$lang->product->moreSelects['changingstory'] = $lang->product->changingStory;
|
||||
$lang->product->moreSelects['willclose'] = $lang->product->willClose;
|
||||
$lang->product->moreSelects['closedstory'] = $lang->product->closedStory;
|
||||
|
||||
@@ -1019,7 +1019,8 @@ class productModel extends model
|
||||
if($browseType == 'closedbyme') $stories = $this->story->getByClosedBy($productID, $branch, $modules, $this->app->user->account, $type, $sort, $pager);
|
||||
if($browseType == 'draftstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'draft', $type, $sort, $pager);
|
||||
if($browseType == 'activestory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'active', $type, $sort, $pager);
|
||||
if($browseType == 'changedstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'changed', $type, $sort, $pager);
|
||||
if($browseType == 'changingstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'changing', $type, $sort, $pager);
|
||||
if($browseType == 'reviewingstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'reviewing', $type, $sort, $pager);
|
||||
if($browseType == 'willclose') $stories = $this->story->get2BeClosed($productID, $branch, $modules, $type, $sort, $pager);
|
||||
if($browseType == 'closedstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'closed', $type, $sort, $pager);
|
||||
if($browseType == 'assignedbyme') $stories = $this->story->getByAssignedBy($productID, $branch, $modules, $this->app->user->account, $type, $sort, $pager);
|
||||
|
||||
@@ -113,12 +113,12 @@
|
||||
<?php if($this->config->URAndSR):?>
|
||||
<td><?php echo $program['draftRequirements'];?></td>
|
||||
<td><?php echo $program['activeRequirements'];?></td>
|
||||
<td><?php echo $program['changedRequirements'];?></td>
|
||||
<td><?php echo $program['changingRequirements'];?></td>
|
||||
<td><?php echo $program['totalRequirements'] == 0 ? 0 : round($program['closedRequirements'] / $program['totalRequirements'], 3) * 100;?>%</td>
|
||||
<?php endif;?>
|
||||
<td><?php echo $program['draftStories'];?></td>
|
||||
<td><?php echo $program['activeStories'];?></td>
|
||||
<td><?php echo $program['changedStories'];?></td>
|
||||
<td><?php echo $program['changingStories'];?></td>
|
||||
<td><?php echo $program['totalStories'] == 0 ? 0 : round($program['closedStories'] / $program['totalStories'], 3) * 100;?>%</td>
|
||||
<td><?php echo $program['unResolvedBugs'];?></td>
|
||||
<td><?php echo $program['closedBugs'];?></td>
|
||||
@@ -158,12 +158,12 @@
|
||||
<?php if($this->config->URAndSR):?>
|
||||
<td><?php echo isset($line['draftRequirements']) ? $line['draftRequirements'] : 0;?></td>
|
||||
<td><?php echo isset($line['activeRequirements']) ? $line['activeRequirements'] : 0;?></td>
|
||||
<td><?php echo isset($line['changedRequirements']) ? $line['changedRequirements'] : 0;?></td>
|
||||
<td><?php echo isset($line['changingRequirements']) ? $line['changingRequirements'] : 0;?></td>
|
||||
<td><?php echo (isset($line['totalRequirements']) and $line['totalRequirements'] != 0) ? round($line['closedRequirements'] / $line['totalRequirements'], 3) * 100 : 0;?>%</td>
|
||||
<?php endif;?>
|
||||
<td><?php echo isset($line['draftStories']) ? $line['draftStories'] : 0;?></td>
|
||||
<td><?php echo isset($line['activeStories']) ? $line['activeStories'] : 0;?></td>
|
||||
<td><?php echo isset($line['changedStories']) ? $line['changedStories'] : 0;?></td>
|
||||
<td><?php echo isset($line['changingStories']) ? $line['changingStories'] : 0;?></td>
|
||||
<td><?php echo (isset($line['totalStories']) and $line['totalStories'] != 0) ? round($line['closedStories'] / $line['totalStories'], 3) * 100 : 0;?>%</td>
|
||||
<td><?php echo isset($line['unResolvedBugs']) ? $line['unResolvedBugs'] : 0;?></td>
|
||||
<td><?php echo isset($line['closedBugs']) ? $line['closedBugs'] : 0;?></td>
|
||||
@@ -179,8 +179,8 @@
|
||||
<?php if(isset($line['products']) and is_array($line['products'])):?>
|
||||
<?php foreach($line['products'] as $productID => $product):?>
|
||||
<?php
|
||||
$totalStories = $product->stories['active'] + $product->stories['closed'] + $product->stories['draft'] + $product->stories['changed'];
|
||||
$totalRequirements = $product->requirements['active'] + $product->requirements['closed'] + $product->requirements['draft'] + $product->requirements['changed'];
|
||||
$totalStories = $product->stories['active'] + $product->stories['closed'] + $product->stories['draft'] + $product->stories['changing'];
|
||||
$totalRequirements = $product->requirements['active'] + $product->requirements['closed'] + $product->requirements['draft'] + $product->requirements['changing'];
|
||||
|
||||
$trClass = '';
|
||||
if($product->line)
|
||||
@@ -217,12 +217,12 @@
|
||||
<?php if($this->config->URAndSR):?>
|
||||
<td><?php echo $product->requirements['draft'];?></td>
|
||||
<td><?php echo $product->requirements['active'];?></td>
|
||||
<td><?php echo $product->requirements['changed'];?></td>
|
||||
<td><?php echo $product->requirements['changing'];?></td>
|
||||
<td><?php echo $totalRequirements == 0 ? 0 : round($product->requirements['closed'] / $totalRequirements, 3) * 100;?>%</td>
|
||||
<?php endif;?>
|
||||
<td><?php echo $product->stories['draft'];?></td>
|
||||
<td><?php echo $product->stories['active'];?></td>
|
||||
<td><?php echo $product->stories['changed'];?></td>
|
||||
<td><?php echo $product->stories['changing'];?></td>
|
||||
<td><?php echo $totalStories == 0 ? 0 : round($product->stories['closed'] / $totalStories, 3) * 100;?>%</td>
|
||||
<td><?php echo $product->unResolved;?></td>
|
||||
<td><?php echo $product->closedBugs;?></td>
|
||||
|
||||
@@ -141,14 +141,6 @@
|
||||
<th class='c-bugs'><?php echo $lang->product->bugs?></th>
|
||||
<td><strong><?php echo $product->bugs?></strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->statusList['changed'] . $space . $lang->story->common;?></th>
|
||||
<td><strong><?php echo $product->stories['changed']?></strong></td>
|
||||
<th><?php echo $lang->product->releases?></th>
|
||||
<td><strong><?php echo $product->releases?></strong></td>
|
||||
<th><?php echo $lang->product->cases?></th>
|
||||
<td><strong><?php echo $product->cases?></strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->statusList['draft'] . $space . $lang->story->common;?></th>
|
||||
<td><strong><?php echo $product->stories['draft']?></strong></td>
|
||||
@@ -158,8 +150,16 @@
|
||||
<td><strong><?php echo $product->docs?></strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->statusList['closed'] . $space . $lang->story->common;?></th>
|
||||
<td><strong><?php echo $product->stories['closed']?></strong></td>
|
||||
<th><?php echo $lang->story->statusList['changing'] . $space . $lang->story->common;?></th>
|
||||
<td><strong><?php echo $product->stories['changing']?></strong></td>
|
||||
<th><?php echo $lang->product->releases?></th>
|
||||
<td><strong><?php echo $product->releases?></strong></td>
|
||||
<th><?php echo $lang->product->cases?></th>
|
||||
<td><strong><?php echo $product->cases?></strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->statusList['reviewing'] . $space . $lang->story->common;?></th>
|
||||
<td><strong><?php echo $product->stories['reviewing']?></strong></td>
|
||||
<?php if($config->systemMode == 'new'):?>
|
||||
<th><?php echo $lang->product->projects?></th>
|
||||
<td><strong><?php echo $product->projects?></strong></td>
|
||||
|
||||
@@ -688,7 +688,7 @@ class productplan extends control
|
||||
}
|
||||
else
|
||||
{
|
||||
$allStories = $this->story->getProductStories($this->view->product->id, $plan->branch ? "0,{$plan->branch}" : 0, $moduleID = '0', $status = 'draft,active,changed', 'story', 'id_desc', $hasParent = false, array_keys($planStories), $pager);
|
||||
$allStories = $this->story->getProductStories($this->view->product->id, $plan->branch ? "0,{$plan->branch}" : 0, '0', 'draft,reviewing,active,changing', 'story', 'id_desc', $hasParent = false, array_keys($planStories), $pager);
|
||||
}
|
||||
|
||||
$modules = $this->loadModel('tree')->getOptionMenu($plan->product, 'story', 0, 'all');
|
||||
|
||||
@@ -1025,7 +1025,7 @@ class productplanModel extends model
|
||||
{
|
||||
foreach($planStory as $id => $story)
|
||||
{
|
||||
if($story->status == 'draft')
|
||||
if($story->status == 'draft' or $story->status == 'reviewing')
|
||||
{
|
||||
unset($planStory[$id]);
|
||||
continue;
|
||||
|
||||
@@ -76,8 +76,8 @@
|
||||
<tbody class="sortable" id="productTableList">
|
||||
<?php foreach($products as $product):?>
|
||||
<?php
|
||||
$totalStories = $product->stories['active'] + $product->stories['closed'] + $product->stories['draft'] + $product->stories['changed'];
|
||||
$totalRequirements = $product->requirements['active'] + $product->requirements['closed'] + $product->requirements['draft'] + $product->requirements['changed'];
|
||||
$totalStories = $product->stories['active'] + $product->stories['closed'] + $product->stories['draft'] + $product->stories['changing'];
|
||||
$totalRequirements = $product->requirements['active'] + $product->requirements['closed'] + $product->requirements['draft'] + $product->requirements['changing'];
|
||||
?>
|
||||
<tr class="text-center" data-id='<?php echo $product->id ?>' data-order='<?php echo $product->code;?>'>
|
||||
<td class='c-id text-left'>
|
||||
@@ -91,12 +91,12 @@
|
||||
<?php if($this->config->URAndSR):?>
|
||||
<td><?php echo $product->requirements['draft'];?></td>
|
||||
<td><?php echo $product->requirements['active'];?></td>
|
||||
<td><?php echo $product->requirements['changed'];?></td>
|
||||
<td><?php echo $product->requirements['changing'];?></td>
|
||||
<td><?php echo $totalRequirements == 0 ? 0 : round($product->requirements['closed'] / $totalRequirements, 3) * 100;?>%</td>
|
||||
<?php endif;?>
|
||||
<td><?php echo $product->stories['draft'];?></td>
|
||||
<td><?php echo $product->stories['active'];?></td>
|
||||
<td><?php echo $product->stories['changed'];?></td>
|
||||
<td><?php echo $product->stories['changing'];?></td>
|
||||
<td><?php echo $totalStories == 0 ? 0 : round($product->stories['closed'] / $totalStories, 3) * 100;?>%</td>
|
||||
<td><?php echo $product->unResolved;?></td>
|
||||
<td><?php echo $product->closedBugs;?></td>
|
||||
|
||||
@@ -476,7 +476,7 @@ class project extends control
|
||||
{
|
||||
foreach($planStory as $id => $story)
|
||||
{
|
||||
if($story->status == 'draft')
|
||||
if($story->status == 'draft' or $story->status == 'reviewing')
|
||||
{
|
||||
unset($planStory[$id]);
|
||||
continue;
|
||||
|
||||
@@ -350,7 +350,7 @@ class projectModel extends model
|
||||
*/
|
||||
public function getTotalStoriesByProject($projectIdList = 0)
|
||||
{
|
||||
return $this->dao->select("t1.project, count(t2.id) as allStories, count(if(t2.status = 'active' or t2.status = 'changed', 1, null)) as leftStories, count(if(t2.status = 'closed' and t2.closedReason = 'done', 1, null)) as doneStories")->from(TABLE_PROJECTSTORY)->alias('t1')
|
||||
return $this->dao->select("t1.project, count(t2.id) as allStories, count(if(t2.status = 'active' or t2.status = 'changing', 1, null)) as leftStories, count(if(t2.status = 'closed' and t2.closedReason = 'done', 1, null)) as doneStories")->from(TABLE_PROJECTSTORY)->alias('t1')
|
||||
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
|
||||
->where('t1.project')->in($projectIdList)
|
||||
->andWhere('t2.type')->eq('story')
|
||||
|
||||
@@ -26,7 +26,9 @@ global $app;
|
||||
$app->loadLang('product');
|
||||
$lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory;
|
||||
$lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory;
|
||||
$lang->projectstory->featureBar['story']['draft'] = $lang->product->draftStory;
|
||||
$lang->projectstory->featureBar['story']['reviewing'] = $lang->product->reviewingStory;
|
||||
$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory;
|
||||
$lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory;
|
||||
$lang->projectstory->featureBar['story']['linkedExecution'] = 'Linked ' . $lang->execution->common;
|
||||
$lang->projectstory->featureBar['story']['unlinkedExecution'] = 'Unlinked ' . $lang->execution->common;
|
||||
|
||||
@@ -26,7 +26,9 @@ global $app;
|
||||
$app->loadLang('product');
|
||||
$lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory;
|
||||
$lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory;
|
||||
$lang->projectstory->featureBar['story']['draft'] = $lang->product->draftStory;
|
||||
$lang->projectstory->featureBar['story']['reviewing'] = $lang->product->reviewingStory;
|
||||
$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory;
|
||||
$lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory;
|
||||
$lang->projectstory->featureBar['story']['linkedExecution'] = 'Linked ' . $lang->execution->common;
|
||||
$lang->projectstory->featureBar['story']['unlinkedExecution'] = 'Unlinked ' . $lang->execution->common;
|
||||
|
||||
@@ -26,7 +26,9 @@ global $app;
|
||||
$app->loadLang('product');
|
||||
$lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory;
|
||||
$lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory;
|
||||
$lang->projectstory->featureBar['story']['draft'] = $lang->product->draftStory;
|
||||
$lang->projectstory->featureBar['story']['reviewing'] = $lang->product->reviewingStory;
|
||||
$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory;
|
||||
$lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory;
|
||||
$lang->projectstory->featureBar['story']['linkedExecution'] = 'Linked ' . $lang->execution->common;
|
||||
$lang->projectstory->featureBar['story']['unlinkedExecution'] = 'Unlinked ' . $lang->execution->common;
|
||||
|
||||
@@ -18,7 +18,11 @@ $lang->projectstory->batchUnlinkTip = 'Other requirements are removed. The follo
|
||||
|
||||
global $app;
|
||||
$app->loadLang('product');
|
||||
$lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory;
|
||||
$lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory;
|
||||
$lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory;
|
||||
$lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory;
|
||||
$lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->projectstory->featureBar['story']['draft'] = $lang->product->draftStory;
|
||||
$lang->projectstory->featureBar['story']['reviewing'] = $lang->product->reviewingStory;
|
||||
$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory;
|
||||
$lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory;
|
||||
$lang->projectstory->featureBar['story']['linkedExecution'] = 'Linked ' . $lang->execution->common;
|
||||
$lang->projectstory->featureBar['story']['unlinkedExecution'] = 'Unlinked ' . $lang->execution->common;
|
||||
|
||||
@@ -26,7 +26,9 @@ global $app;
|
||||
$app->loadLang('product');
|
||||
$lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory;
|
||||
$lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory;
|
||||
$lang->projectstory->featureBar['story']['draft'] = $lang->product->draftStory;
|
||||
$lang->projectstory->featureBar['story']['reviewing'] = $lang->product->reviewingStory;
|
||||
$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory;
|
||||
$lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory;
|
||||
$lang->projectstory->featureBar['story']['linkedExecution'] = '已关联' . $lang->execution->common;
|
||||
$lang->projectstory->featureBar['story']['unlinkedExecution'] = '未关联' . $lang->execution->common;
|
||||
|
||||
@@ -26,7 +26,7 @@ global $app;
|
||||
$app->loadLang('product');
|
||||
$lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory;
|
||||
$lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed;
|
||||
$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory;
|
||||
$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory;
|
||||
$lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory;
|
||||
$lang->projectstory->featureBar['story']['linkedExecution'] = '已關聯' . $lang->execution->common;
|
||||
$lang->projectstory->featureBar['story']['unlinkedExecution'] = '未關聯' . $lang->execution->common;
|
||||
|
||||
@@ -48,8 +48,9 @@
|
||||
<th class="c-date"><?php echo $lang->productplan->begin;?></th>
|
||||
<th class="c-date"><?php echo $lang->productplan->end;?></th>
|
||||
<th class="c-count"><?php echo $lang->story->statusList['draft'];?></th>
|
||||
<th class="c-count"><?php echo $lang->story->statusList['reviewing'];?></th>
|
||||
<th class="c-count"><?php echo $lang->story->statusList['active'];?></th>
|
||||
<th class="c-count"><?php echo $lang->story->statusList['changed'];?></th>
|
||||
<th class="c-count"><?php echo $lang->story->statusList['changing'];?></th>
|
||||
<th class="c-count"><?php echo $lang->story->statusList['closed'];?></th>
|
||||
<th class="c-count"><?php echo $lang->report->total;?></th>
|
||||
</tr>
|
||||
@@ -71,16 +72,18 @@
|
||||
<td class="<?php echo $class;?>"><?php echo $plan->begin == '2030-01-01' ? $lang->productplan->future : $plan->begin;?></td>
|
||||
<td class="<?php echo $class;?>"><?php echo $plan->end == '2030-01-01' ? $lang->productplan->future : $plan->end;?></td>
|
||||
<?php
|
||||
$draftCount = isset($plan->status['draft']) ? $plan->status['draft'] : 0;
|
||||
$activeCount = isset($plan->status['active']) ? $plan->status['active'] : 0;
|
||||
$changedCount = isset($plan->status['changed']) ? $plan->status['changed'] : 0;
|
||||
$closedCount = isset($plan->status['closed']) ? $plan->status['closed'] : 0;
|
||||
$draftCount = isset($plan->status['draft']) ? $plan->status['draft'] : 0;
|
||||
$reviewingCount = isset($plan->status['reviewing']) ? $plan->status['reviewing'] : 0;
|
||||
$activeCount = isset($plan->status['active']) ? $plan->status['active'] : 0;
|
||||
$changedCount = isset($plan->status['changing']) ? $plan->status['changing'] : 0;
|
||||
$closedCount = isset($plan->status['closed']) ? $plan->status['closed'] : 0;
|
||||
?>
|
||||
<td class="<?php echo $class;?>"><?php echo $draftCount;?></td>
|
||||
<td class="<?php echo $class;?>"><?php echo $reviewingCount;?></td>
|
||||
<td class="<?php echo $class;?>"><?php echo $activeCount;?></td>
|
||||
<td class="<?php echo $class;?>"><?php echo $changedCount;?></td>
|
||||
<td class="<?php echo $class;?>"><?php echo $closedCount;?></td>
|
||||
<td class="<?php echo $class;?>"><?php echo $draftCount + $activeCount + $changedCount + $closedCount;?></td>
|
||||
<td class="<?php echo $class;?>"><?php echo $draftCount + $reviewingCount + $activeCount + $changedCount + $closedCount;?></td>
|
||||
<?php if($id != 1) echo "</tr>"?>
|
||||
<?php $id ++;?>
|
||||
<?php $color = !$color;?>
|
||||
@@ -95,6 +98,7 @@
|
||||
<td class="<?php echo $class;?>">0</td>
|
||||
<td class="<?php echo $class;?>">0</td>
|
||||
<td class="<?php echo $class;?>">0</td>
|
||||
<td class="<?php echo $class;?>">0</td>
|
||||
<?php $color = !$color;?>
|
||||
<?php endif;?>
|
||||
</tr>
|
||||
|
||||
@@ -22,7 +22,7 @@ $config->story->review->requiredFields = '';
|
||||
$config->story->editor = new stdclass();
|
||||
$config->story->editor->create = array('id' => 'spec,verify', 'tools' => 'simpleTools');
|
||||
$config->story->editor->change = array('id' => 'spec,verify,comment', 'tools' => 'simpleTools');
|
||||
$config->story->editor->edit = array('id' => 'comment', 'tools' => 'simpleTools');
|
||||
$config->story->editor->edit = array('id' => 'spec,verify,comment', 'tools' => 'simpleTools');
|
||||
$config->story->editor->view = array('id' => 'comment,lastComment', 'tools' => 'simpleTools');
|
||||
$config->story->editor->close = array('id' => 'comment', 'tools' => 'simpleTools');
|
||||
$config->story->editor->review = array('id' => 'comment', 'tools' => 'simpleTools');
|
||||
|
||||
+122
-53
@@ -189,7 +189,7 @@ class story extends control
|
||||
|
||||
$message = $this->executeHooks($storyID);
|
||||
if($message) $this->lang->saveSuccess = $message;
|
||||
$response['message'] = $this->lang->saveSuccess;
|
||||
$response['message'] = $this->post->status == 'draft' ? $this->lang->story->saveDraftSuccess : $this->lang->saveSuccess;
|
||||
|
||||
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $storyID));
|
||||
|
||||
@@ -747,6 +747,8 @@ class story extends control
|
||||
*/
|
||||
public function edit($storyID, $kanbanGroup = 'default', $storyType = 'story')
|
||||
{
|
||||
$story = $this->story->getById($storyID, 0, true);
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$changes = $this->story->update($storyID);
|
||||
@@ -757,8 +759,8 @@ class story extends control
|
||||
$actionID = $this->action->create('story', $storyID, $action, $this->post->comment);
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
|
||||
$story = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch();
|
||||
if(isset($_POST['reviewer'])) $this->story->recordReviewAction($story);
|
||||
$editedStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch();
|
||||
if(isset($_POST['reviewer']) and $story->status == 'reviewing') $this->story->recordReviewAction($editedStory);
|
||||
}
|
||||
|
||||
$this->executeHooks($storyID);
|
||||
@@ -813,7 +815,6 @@ class story extends control
|
||||
$products = $myProducts + $othersProducts;
|
||||
|
||||
/* Assign. */
|
||||
$story = $this->story->getById($storyID, 0, true);
|
||||
$product = $this->product->getById($story->product);
|
||||
$stories = $this->story->getParentStoryPairs($story->product, $story->parent);
|
||||
if(isset($stories[$storyID])) unset($stories[$storyID]);
|
||||
@@ -821,15 +822,6 @@ class story extends control
|
||||
/* Get users. */
|
||||
$users = $this->user->getPairs('pofirst|nodeleted|noclosed', "$story->assignedTo,$story->openedBy,$story->closedBy");
|
||||
|
||||
$isShowReviewer = false;
|
||||
$reviewerList = $this->story->getReviewerPairs($story->id, $story->version);
|
||||
$reviewerList = array_keys($reviewerList);
|
||||
$reviewedBy = explode(',', trim($story->reviewedBy, ','));
|
||||
if(array_diff($reviewerList, $reviewedBy) and strpos('draft,changed', $story->status) !== false) $isShowReviewer = true;
|
||||
|
||||
$reviewedReviewer = array();
|
||||
foreach($reviewedBy as $reviewer) $reviewedReviewer[] = zget($users, $reviewer);
|
||||
|
||||
if($this->app->tab == 'project' or $this->app->tab == 'execution')
|
||||
{
|
||||
$objectID = $this->app->tab == 'project' ? $this->session->project : $this->session->execution;
|
||||
@@ -847,6 +839,12 @@ class story extends control
|
||||
$branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : '');
|
||||
}
|
||||
|
||||
/* Get story reviewers. */
|
||||
$reviewedReviewer = array();
|
||||
$reviewerList = $this->story->getReviewerPairs($story->id, $story->version);
|
||||
$reviewedBy = explode(',', trim($story->reviewedBy, ','));
|
||||
foreach($reviewedBy as $reviewer) $reviewedReviewer[] = zget($users, $reviewer);
|
||||
|
||||
/* Get product reviewers. */
|
||||
$productReviewers = $product->reviewer;
|
||||
if(!$productReviewers and $product->acl != 'open') $productReviewers = $this->loadModel('user')->getProductViewListUsers($product, '', '', '', '');
|
||||
@@ -864,10 +862,10 @@ class story extends control
|
||||
$this->view->products = $products;
|
||||
$this->view->branchOption = $branchOption;
|
||||
$this->view->branchTagOption = $branchTagOption;
|
||||
$this->view->reviewers = implode(',', $reviewerList);
|
||||
$this->view->reviewers = array_keys($reviewerList);
|
||||
$this->view->reviewedReviewer = $reviewedReviewer;
|
||||
$this->view->productReviewers = $this->user->getPairs('noclosed|nodeleted', $reviewerList, 0, $productReviewers);
|
||||
$this->view->isShowReviewer = $isShowReviewer;
|
||||
$this->view->productReviewers = $this->user->getPairs('noclosed|nodeleted', array_keys($reviewerList), 0, $productReviewers);
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -1151,7 +1149,7 @@ class story extends control
|
||||
$this->view->title = $this->lang->story->change . "STORY" . $this->lang->colon . $this->view->story->title;
|
||||
$this->view->users = $this->user->getPairs('pofirst|nodeleted|noclosed', $this->view->story->assignedTo);
|
||||
$this->view->position[] = $this->lang->story->change;
|
||||
$this->view->needReview = ($this->app->user->account == $this->view->product->PO || $this->config->story->needReview == 0) ? "checked='checked'" : "";
|
||||
$this->view->needReview = (($this->app->user->account == $this->view->product->PO or $this->config->story->needReview == 0) and empty($reviewer)) ? "checked='checked'" : "";
|
||||
$this->view->reviewer = implode(',', array_keys($reviewer));
|
||||
$this->view->productReviewers = $this->user->getPairs('noclosed|nodeleted', $reviewer, 0, $productReviewers);
|
||||
$this->view->files = $this->loadModel('file')->getByObject($story->type, $storyID);
|
||||
@@ -1207,7 +1205,7 @@ class story extends control
|
||||
|
||||
/* Assign. */
|
||||
$this->view->title = $this->lang->story->activate . "STORY" . $this->lang->colon . $this->view->story->title;
|
||||
$this->view->users = $this->user->getPairs('pofirst|nodeleted', $this->view->story->closedBy);
|
||||
$this->view->users = $this->user->getPairs('pofirst|nodeleted|noclosed', $this->view->story->closedBy);
|
||||
$this->view->position[] = $this->lang->story->activate;
|
||||
$this->display();
|
||||
}
|
||||
@@ -1454,9 +1452,9 @@ class story extends control
|
||||
$reviewers = $this->story->getReviewerPairs($storyID, $story->version);
|
||||
$this->lang->story->resultList = $this->lang->story->reviewResultList;
|
||||
|
||||
if($story->status == 'draft' and $story->version == 1) unset($this->lang->story->resultList['revert']);
|
||||
if($story->status == 'reviewing' and $story->version == 1) unset($this->lang->story->resultList['revert']);
|
||||
|
||||
if($story->status == 'changed') unset($this->lang->story->resultList['reject']);
|
||||
if($story->status == 'changing') unset($this->lang->story->resultList['reject']);
|
||||
|
||||
if(count($reviewers) > 1) unset($this->lang->story->resultList['revert']);
|
||||
|
||||
@@ -1470,6 +1468,7 @@ class story extends control
|
||||
$this->view->actions = $this->action->getList('story', $storyID);
|
||||
$this->view->users = $this->loadModel('user')->getPairs('nodeleted|noletter', "$story->lastEditedBy,$story->openedBy");
|
||||
$this->view->reviewers = $reviewers;
|
||||
$this->view->isLastOne = count(array_diff(array_keys($reviewers), explode(',', $story->reviewedBy))) == 1 ? true : false;
|
||||
|
||||
/* Get the affcected things. */
|
||||
$this->story->getAffectedScope($this->view->story);
|
||||
@@ -1503,24 +1502,85 @@ class story extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Recall the story review.
|
||||
* Recall the story review or story change.
|
||||
*
|
||||
* @param int $storyID
|
||||
* @param string $from
|
||||
* @param string $from list
|
||||
* @param string $confirm no|yes
|
||||
* @param string $storyType story|requirement
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function recall($storyID, $from = 'list', $storyType = 'story')
|
||||
public function recall($storyID, $from = 'list', $confirm = 'no', $storyType = 'story')
|
||||
{
|
||||
$story = $this->story->getById($storyID);
|
||||
$this->story->recall($storyID);
|
||||
$this->loadModel('action')->create('story', $storyID, 'Recalled');
|
||||
|
||||
if($from == 'view') return print(js::locate($this->createLink('story', 'view', "storyID={$storyID}&from=view")));
|
||||
if($confirm == 'no')
|
||||
{
|
||||
$confirmTips = $story->status == 'changing' ? $this->lang->story->confirmRecallChange : $this->lang->story->confirmRecallReview;
|
||||
return print(js::confirm($confirmTips, $this->createLink('story', 'recall', "storyID=$storyID&from=$from&confirm=yes&storyType=$storyType")));
|
||||
}
|
||||
else
|
||||
{
|
||||
if($story->status == 'changing') $this->story->recallChange($storyID);
|
||||
if($story->status == 'reviewing') $this->story->recallReview($storyID);
|
||||
|
||||
$locateLink = $this->session->storyList ? $this->session->storyList : $this->createLink('product', 'browse', "productID={$story->product}");
|
||||
echo js::locate($locateLink, 'parent');
|
||||
$action = $story->status == 'changing' ? 'recalledChange' : 'Recalled';
|
||||
$this->loadModel('action')->create('story', $storyID, $action);
|
||||
|
||||
if($from == 'view') return print(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent'));
|
||||
|
||||
$locateLink = $this->session->storyList ? $this->session->storyList : $this->createLink('product', 'browse', "productID={$story->product}");
|
||||
return print(js::locate($locateLink, 'parent'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit review.
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function submitReview($storyID)
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$changes = $this->story->submitReview($storyID);
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
|
||||
if($changes)
|
||||
{
|
||||
$actionID = $this->loadModel('action')->create('story', $storyID, 'submitReview');
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
if(isonlybody()) return print(js::closeModal('parent.parent', 'this'));
|
||||
return print(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent'));
|
||||
}
|
||||
|
||||
/* Get story and product. */
|
||||
$story = $this->story->getById($storyID);
|
||||
$product = $this->product->getById($story->product);
|
||||
|
||||
/* Set menu. */
|
||||
$this->product->setMenu($story->product, $story->branch);
|
||||
|
||||
/* Get reviewers. */
|
||||
$reviewers = $product->reviewer;
|
||||
if(!$reviewers and $product->acl != 'open') $reviewers = $this->loadModel('user')->getProductViewListUsers($product, '', '', '', '');
|
||||
|
||||
/* Get story reviewer. */
|
||||
$reviewerList = $this->story->getReviewerPairs($story->id, $story->version);
|
||||
$story->reviewer = array_keys($reviewerList);
|
||||
|
||||
$this->view->story = $story;
|
||||
$this->view->actions = $this->action->getList('story', $storyID);
|
||||
$this->view->reviewers = $this->user->getPairs('noclosed|nodeleted', '', 0, $reviewers);
|
||||
$this->view->users = $this->user->getPairs('noclosed|noletter');
|
||||
$this->view->needReview = (($this->app->user->account == $product->PO || $this->config->story->needReview == 0) and empty($story->reviewer)) ? "checked='checked'" : "";
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1534,6 +1594,8 @@ class story extends control
|
||||
*/
|
||||
public function close($storyID, $from = '', $storyType = 'story')
|
||||
{
|
||||
$story = $this->story->getById($storyID);
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$changes = $this->story->close($storyID);
|
||||
@@ -1542,7 +1604,11 @@ class story extends control
|
||||
|
||||
if($changes)
|
||||
{
|
||||
$actionID = $this->action->create('story', $storyID, 'Closed', $this->post->comment, ucfirst($this->post->closedReason) . ($this->post->duplicateStory ? ':' . (int)$this->post->duplicateStory : ''));
|
||||
$preStatus = $story->status;
|
||||
$isChanged = $story->changedBy ? true : false;
|
||||
if($preStatus == 'reviewing') $preStatus = $isChanged ? 'changing' : 'draft';
|
||||
|
||||
$actionID = $this->action->create('story', $storyID, 'Closed', $this->post->comment, ucfirst($this->post->closedReason) . ($this->post->duplicateStory ? ':' . (int)$this->post->duplicateStory : '') . "|$preStatus");
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
|
||||
@@ -1588,7 +1654,6 @@ class story extends control
|
||||
}
|
||||
|
||||
/* Get story and product. */
|
||||
$story = $this->story->getById($storyID);
|
||||
$product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id')->fetch();
|
||||
|
||||
$this->story->replaceURLang($story->type);
|
||||
@@ -1625,30 +1690,12 @@ class story extends control
|
||||
*/
|
||||
public function batchClose($productID = 0, $executionID = 0, $storyType = 'story', $from = '')
|
||||
{
|
||||
if($this->post->comments)
|
||||
{
|
||||
$data = fixer::input('post')->get();
|
||||
$allChanges = $this->story->batchClose();
|
||||
|
||||
if($allChanges)
|
||||
{
|
||||
foreach($allChanges as $storyID => $changes)
|
||||
{
|
||||
$actionID = $this->action->create('story', $storyID, 'Closed', htmlSpecialString($this->post->comments[$storyID]), ucfirst($this->post->closedReasons[$storyID]) . ($this->post->duplicateStoryIDList[$storyID] ? ':' . (int)$this->post->duplicateStoryIDList[$storyID] : ''));
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
}
|
||||
|
||||
if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther');
|
||||
return print(js::locate($this->session->storyList, 'parent'));
|
||||
}
|
||||
|
||||
if(!$this->post->storyIdList) return print(js::locate($this->session->storyList, 'parent'));
|
||||
$storyIdList = $this->post->storyIdList;
|
||||
$storyIdList = array_unique($storyIdList);
|
||||
|
||||
/* Get edited stories. */
|
||||
$stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($storyIdList)->fetchAll('id');
|
||||
$stories = $this->story->getByList($storyIdList);
|
||||
foreach($stories as $story)
|
||||
{
|
||||
if($story->parent == -1)
|
||||
@@ -1663,6 +1710,28 @@ class story extends control
|
||||
}
|
||||
}
|
||||
|
||||
if($this->post->comments)
|
||||
{
|
||||
$data = fixer::input('post')->get();
|
||||
$allChanges = $this->story->batchClose();
|
||||
|
||||
if($allChanges)
|
||||
{
|
||||
foreach($allChanges as $storyID => $changes)
|
||||
{
|
||||
$preStatus = $stories[$storyID]->status;
|
||||
$isChanged = $stories[$storyID]->changedBy ? true : false;
|
||||
if($preStatus == 'reviewing') $preStatus = $isChanged ? 'changing' : 'draft';
|
||||
|
||||
$actionID = $this->action->create('story', $storyID, 'Closed', htmlSpecialString($this->post->comments[$storyID]), ucfirst($this->post->closedReasons[$storyID]) . ($this->post->duplicateStoryIDList[$storyID] ? ':' . (int)$this->post->duplicateStoryIDList[$storyID] : '') . "|$preStatus");
|
||||
$this->action->logHistory($actionID, $changes);
|
||||
}
|
||||
}
|
||||
|
||||
if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther');
|
||||
return print(js::locate($this->session->storyList, 'parent'));
|
||||
}
|
||||
|
||||
$errorTips = '';
|
||||
if(isset($closedStory)) $errorTips .= sprintf($this->lang->story->closedStory, join(',', $closedStory));
|
||||
if(isset($skipStory)) $errorTips .= sprintf($this->lang->story->skipStory, join(',', $skipStory));
|
||||
@@ -2513,9 +2582,9 @@ class story extends control
|
||||
{
|
||||
$oldStory = $this->dao->findById((int)$params['storyID'])->from(TABLE_STORY)->fetch();
|
||||
$status = $oldStory->status;
|
||||
if($params['changed'] and $oldStory->status == 'active' and empty($params['needNotReview'])) $status = 'changed';
|
||||
if($params['changed'] and $oldStory->status == 'active' and $this->story->checkForceReview()) $status = 'changed';
|
||||
if($params['changed'] and $oldStory->status == 'draft' and $params['needNotReview']) $status = 'active';
|
||||
if($params['changing'] and $oldStory->status == 'active' and empty($params['needNotReview'])) $status = 'changing';
|
||||
if($params['changing'] and $oldStory->status == 'active' and $this->story->checkForceReview()) $status = 'changing';
|
||||
if($params['changing'] and $oldStory->status == 'draft' and $params['needNotReview']) $status = 'active';
|
||||
}
|
||||
elseif($method == 'review')
|
||||
{
|
||||
@@ -2538,7 +2607,7 @@ class story extends control
|
||||
*/
|
||||
public function ajaxGetAssignedTo($type = '', $storyID = 0, $assignees = '')
|
||||
{
|
||||
$users = $this->loadModel('user')->getPairs('noletter|noclosed');
|
||||
$users = $this->loadModel('user')->getPairs('noclosed');
|
||||
|
||||
if($type == 'create')
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#product + .picker{min-width: 400px}
|
||||
#dataform .priBox, #dataform .estimateBox {width: 120px;}
|
||||
#dataform .categoryBox {width: 150px;}
|
||||
#dataform .needNotReviewBox {width: 130px;}
|
||||
.needNotReviewBox {width: 130px; display: inline-block; padding: 7px;}
|
||||
.input-group-addon.assignedTo {min-width: 77px;}
|
||||
.input-group .source {display: flex; width: 50%;}
|
||||
.input-group .sourceNote {display: flex; width: 50%;}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#product_chosen .chosen-single{border-right-width:1px}
|
||||
#product_chosen .chosen-single {border-right-width: 1px}
|
||||
.linkStoryTitle {white-space: nowrap; text-overflow: ellipsis;}
|
||||
.linkStoryTd > ul {margin-top: -10px;}
|
||||
.titleBox {margin: 0px 10px 10px 10px;}
|
||||
.needNotReviewBox {width: 130px;}
|
||||
.needNotReviewBox span.input-group-addon {border: 1px solid #dcdcdc; border-left-width: 0px;}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.needNotReviewBox {width: 130px;}
|
||||
.needNotReviewBox span.input-group-addon {border: 1px solid #dcdcdc; border-left-width: 0px;}
|
||||
.table > tbody > tr > th {vertical-align: top; padding-top: 13px;}
|
||||
@@ -14,6 +14,21 @@ $(function()
|
||||
saveCustomFields('batchCreateFields', 8, $name, 200);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#saveButton').on('click', function()
|
||||
{
|
||||
$('#saveButton').attr('disabled', true);
|
||||
$('#saveDraftButton').attr('disabled', true);
|
||||
$('#batchCreateForm').submit();
|
||||
});
|
||||
|
||||
$('#saveDraftButton').on('click', function()
|
||||
{
|
||||
$('#saveButton').attr('disabled', true);
|
||||
$('#saveDraftButton').attr('disabled', true);
|
||||
$('<input />').attr('type', 'hidden').attr('name', 'status').attr('value', 'draft').appendTo('#batchCreateForm');
|
||||
$('#batchCreateForm').submit();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '.chosen-with-drop', function()
|
||||
|
||||
@@ -2,7 +2,7 @@ $(function()
|
||||
{
|
||||
$('#needNotReview').on('change', function()
|
||||
{
|
||||
$('#reviewer').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated');
|
||||
$('#reviewer').text('').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated');
|
||||
if($(this).is(':checked'))
|
||||
{
|
||||
$('.input-group-addon').removeClass('required');
|
||||
@@ -11,41 +11,7 @@ $(function()
|
||||
{
|
||||
$('.input-group-addon').addClass('required');
|
||||
}
|
||||
|
||||
loadAssignedTo();
|
||||
});
|
||||
$('#needNotReview').change();
|
||||
|
||||
if($('#reviewer').val()) loadAssignedTo();
|
||||
|
||||
if($('.tabs .tab-content .tab-pane.active').children().length == 0) $('.tabs .nav-tabs li.active').css('border-bottom', '1px solid #ccc');
|
||||
});
|
||||
|
||||
/**
|
||||
* Load assignedTo.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function loadAssignedTo()
|
||||
{
|
||||
var assignees = $('#reviewer').val();
|
||||
var link = createLink('story', 'ajaxGetAssignedTo', 'type=change&storyID=' + storyID + '&assignees=' + assignees);
|
||||
$.post(link, function(data)
|
||||
{
|
||||
$('#assignedTo').replaceWith(data);
|
||||
$('#assignedToBox .picker').remove();
|
||||
$('#assignedTo').picker();
|
||||
});
|
||||
|
||||
if($('#needNotReview').is(':checked'))
|
||||
{
|
||||
$('#assignedToBox').removeClass('hidden');
|
||||
$('#reviewerBox').attr('colspan', 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#assignedToBox').addClass('hidden');
|
||||
$('#reviewerBox').attr('colspan', 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,40 @@ $(function()
|
||||
$("#navbar .nav li[data-id=" + storyType + ']').addClass('active');
|
||||
$('#subNavbar li[data-id="' + storyType + '"]').addClass('active');
|
||||
}
|
||||
|
||||
$('#saveButton').on('click', function()
|
||||
{
|
||||
$('#saveButton').attr('disabled', true);
|
||||
$('#saveDraftButton').attr('disabled', true);
|
||||
|
||||
var storyStatus = !$('#reviewer').val() || $('#needNotReview').is(':checked') ? 'active' : 'reviewing';
|
||||
$('<input />').attr('type', 'hidden').attr('name', 'status').attr('value', storyStatus).appendTo('#dataform');
|
||||
$('#dataform').submit();
|
||||
|
||||
setTimeout(function()
|
||||
{
|
||||
$('#saveButton').removeAttr('disabled');
|
||||
$('#saveDraftButton').removeAttr('disabled');
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
$('#saveDraftButton').on('click', function()
|
||||
{
|
||||
$('#saveButton').attr('disabled', true);
|
||||
$('#saveDraftButton').attr('disabled', true);
|
||||
|
||||
storyStatus = 'draft';
|
||||
if(typeof(page) != 'undefined' && page == 'change') storyStatus = 'changing';
|
||||
if(typeof(page) !== 'undefined' && page == 'edit' && $('#status').val() == 'changing') storyStatus = 'changing';
|
||||
$('<input />').attr('type', 'hidden').attr('name', 'status').attr('value', storyStatus).appendTo('#dataform');
|
||||
$('#dataform').submit();
|
||||
|
||||
setTimeout(function()
|
||||
{
|
||||
$('#saveButton').removeAttr('disabled');
|
||||
$('#saveDraftButton').removeAttr('disabled');
|
||||
}, 1000);
|
||||
});
|
||||
})
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,23 +2,25 @@ $(function()
|
||||
{
|
||||
$('#needNotReview').on('change', function()
|
||||
{
|
||||
$('#reviewer').text('').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated');
|
||||
$('#reviewer').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated');
|
||||
|
||||
if($(this).is(':checked'))
|
||||
{
|
||||
$('#reviewerBox').closest('tr').addClass('hidden');
|
||||
$('#reviewerBox').removeClass('required');
|
||||
$('#dataform #needNotReview').val(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#reviewerBox').closest('tr').removeClass('hidden');
|
||||
$('#reviewerBox').addClass('required');
|
||||
$('#dataform #needNotReview').val(0);
|
||||
}
|
||||
loadAssignedTo();
|
||||
|
||||
getStatus('create', "product=" + $('#product').val() + ",execution=" + executionID + ",needNotReview=" + ($(this).prop('checked') ? 1 : 0));
|
||||
});
|
||||
$('#needNotReview').change();
|
||||
|
||||
if($('#reviewer').val()) loadAssignedTo();
|
||||
|
||||
// init pri selector
|
||||
$('#pri').on('change', function()
|
||||
{
|
||||
@@ -36,14 +38,12 @@ $(function()
|
||||
if($.inArray(source, feedbackSource) != -1)
|
||||
{
|
||||
$('#feedbackBox').removeClass('hidden');
|
||||
$('#reviewerBox').attr('colspan', $('#assignedToBox').hasClass('hidden') ? 2 : 1);
|
||||
$('#assignedToBox').attr('colspan', 1);
|
||||
$('#source, #sourceNoteBox').closest('td').attr('colspan', 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#feedbackBox').addClass('hidden');
|
||||
$('#reviewerBox').attr('colspan', $('#assignedToBox').hasClass('hidden') ? 4 : 2);
|
||||
$('#assignedToBox').attr('colspan', 2);
|
||||
$('#source, #sourceNoteBox').closest('td').attr('colspan', 2);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -56,22 +56,6 @@ $(function()
|
||||
$('#formSettingForm .btn-primary').click(function()
|
||||
{
|
||||
saveCustomFields('createFields');
|
||||
|
||||
setTimeout(function()
|
||||
{
|
||||
var showFieldList = showFields + ',';
|
||||
if(showFieldList.indexOf(',source,') >= 0)
|
||||
{
|
||||
$('#source').trigger("change");
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#feedbackBox').addClass('hidden');
|
||||
$('#reviewerBox').attr('colspan', $('#assignedToBox').hasClass('hidden') ? 4 : 2);
|
||||
$('#assignedToBox').attr('colspan', 2);
|
||||
}
|
||||
}, 100);
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
@@ -92,18 +76,6 @@ function loadAssignedTo()
|
||||
$('#assignedToBox .picker').remove();
|
||||
$('#assignedTo').picker();
|
||||
});
|
||||
|
||||
var colspan = $('#assignedToBox').attr('colspan');
|
||||
if($('#needNotReview').is(':checked'))
|
||||
{
|
||||
$('#assignedToBox').removeClass('hidden');
|
||||
$('#reviewerBox').attr('colspan', colspan);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#assignedToBox').addClass('hidden');
|
||||
$('#reviewerBox').attr('colspan', colspan * 2);
|
||||
}
|
||||
}
|
||||
|
||||
function refreshPlan()
|
||||
|
||||
+36
-11
@@ -1,24 +1,49 @@
|
||||
$(function()
|
||||
{
|
||||
$('.main-side #branch').closest('td').find('#product_chosen .chosen-single').css('width', '153px');
|
||||
$('#reviewer_chosen .search-choice').each(function()
|
||||
{
|
||||
if(reviewedReviewer.indexOf($(this).find('span').text()) != -1) $(this).css('pointer-events', 'none');
|
||||
})
|
||||
|
||||
$('#reviewer').change(function()
|
||||
if(storyStatus == 'reviewing')
|
||||
{
|
||||
if($('#reviewer_chosen .search-choice').length === 1)
|
||||
$('#reviewer').next().find('.picker-selection').each(function()
|
||||
{
|
||||
alert(reviewerNotEmpty);
|
||||
$('#reviewer').val(reviewers);
|
||||
$('#reviewer').trigger('chosen:updated');
|
||||
if(reviewedReviewer.indexOf($(this).find('span').text()) != -1) $(this).css('pointer-events', 'none');
|
||||
});
|
||||
|
||||
$('#reviewer').change(function()
|
||||
{
|
||||
if($('#reviewer').next().find('.picker-selection').length === 0)
|
||||
{
|
||||
alert(reviewerNotEmpty);
|
||||
$('#reviewer').val(reviewers);
|
||||
$('#reviewer').trigger('chosen:updated');
|
||||
}
|
||||
else
|
||||
{
|
||||
reviewers = $('#reviewer').val();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#reviewer').change(function()
|
||||
{
|
||||
if(!$('#reviewer').val()) $('#needNotReview').attr('checked', true).change();
|
||||
});
|
||||
}
|
||||
|
||||
$('#needNotReview').on('change', function()
|
||||
{
|
||||
$('#reviewer').text('').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated');
|
||||
if($(this).is(':checked'))
|
||||
{
|
||||
$('#reviewerBox').removeClass('required');
|
||||
}
|
||||
else
|
||||
{
|
||||
reviewers = $('#reviewer').val();
|
||||
$('#reviewerBox').addClass('required');
|
||||
}
|
||||
})
|
||||
});
|
||||
if(!$('#reviewer').val()) $('#needNotReview').change();
|
||||
|
||||
$('#source').on('change', function()
|
||||
{
|
||||
|
||||
@@ -7,11 +7,6 @@ function switchShow(result)
|
||||
$('#rejectedReasonBox').show();
|
||||
$('#preVersionBox').hide();
|
||||
$('#assignedToBox').hide();
|
||||
if(isMultiple)
|
||||
{
|
||||
$('#assignedToBox').show();
|
||||
loadAssignedTo();
|
||||
}
|
||||
}
|
||||
else if(result == 'revert')
|
||||
{
|
||||
@@ -19,8 +14,7 @@ function switchShow(result)
|
||||
$('#rejectedReasonBox').hide();
|
||||
$('#duplicateStoryBox').hide();
|
||||
$('#childStoriesBox').hide();
|
||||
$('#assignedToBox').show();
|
||||
loadAssignedTo();
|
||||
if(isLastOne) $('#assignedToBox').show();
|
||||
}
|
||||
else if(result == 'clarify')
|
||||
{
|
||||
@@ -29,8 +23,7 @@ function switchShow(result)
|
||||
$('#duplicateStoryBox').hide();
|
||||
$('#childStoriesBox').hide();
|
||||
$('#rejectedReasonBox').hide();
|
||||
$('#assignedToBox').show();
|
||||
loadAssignedTo();
|
||||
if(isLastOne) $('#assignedToBox').show();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -39,13 +32,11 @@ function switchShow(result)
|
||||
$('#duplicateStoryBox').hide();
|
||||
$('#childStoriesBox').hide();
|
||||
$('#rejectedReasonBox').hide();
|
||||
$('#assignedToBox').hide();
|
||||
if(isLastOne) $('#assignedToBox').show();
|
||||
if(result == 'pass')
|
||||
{
|
||||
$('#priBox').show();
|
||||
$('#estimateBox').show();
|
||||
$('#assignedToBox').show();
|
||||
loadAssignedTo();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
$(function()
|
||||
{
|
||||
$('#needNotReview').on('change', function()
|
||||
{
|
||||
$('#reviewer').text('').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated');
|
||||
if($(this).is(':checked'))
|
||||
{
|
||||
$('#reviewerBox').removeClass('required');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#reviewerBox').addClass('required');
|
||||
}
|
||||
});
|
||||
if(!$('#reviewer').val()) $('#needNotReview').change();
|
||||
});
|
||||
+26
-11
@@ -23,10 +23,14 @@ $lang->story->change = "Ändern";
|
||||
$lang->story->changed = 'Geändert';
|
||||
$lang->story->assignTo = 'Assign';
|
||||
$lang->story->review = 'Prüfen';
|
||||
$lang->story->submitReview = "Submit Review";
|
||||
$lang->story->recall = 'Revoke';
|
||||
$lang->story->recallChange = 'Undo Changes';
|
||||
$lang->story->recallAction = 'Undo';
|
||||
$lang->story->needReview = 'Need Review';
|
||||
$lang->story->batchReview = 'Mehere prüfen';
|
||||
$lang->story->edit = "Bearbeiten";
|
||||
$lang->story->editDraft = "Entwurf bearbeiten";
|
||||
$lang->story->batchEdit = "Mehere bearbeiten";
|
||||
$lang->story->subdivide = 'Aufteilen';
|
||||
$lang->story->link = 'Link';
|
||||
@@ -70,6 +74,8 @@ $lang->story->batchToTask = 'Batch Convert to Task';
|
||||
$lang->story->convertRelations = 'Convert Relations';
|
||||
$lang->story->undetermined = 'undetermined';
|
||||
$lang->story->order = 'Order';
|
||||
$lang->story->saveDraft = 'Save as draft';
|
||||
$lang->story->doNotSubmit = 'Do Not Submit';
|
||||
|
||||
$lang->story->editAction = "Edit {$lang->SRCommon}";
|
||||
$lang->story->changeAction = "Change Story";
|
||||
@@ -82,12 +88,13 @@ $lang->story->deleteAction = "Delete Story";
|
||||
$lang->story->exportAction = "Export Story";
|
||||
$lang->story->reportAction = "Story Report";
|
||||
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->float = "『%s』should be positive number, decimals included.";
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->float = "『%s』should be positive number, decimals included.";
|
||||
$lang->story->saveDraftSuccess = 'Save as draft succeeded.';
|
||||
|
||||
$lang->story->id = 'ID';
|
||||
$lang->story->parent = 'Parent';
|
||||
@@ -130,6 +137,8 @@ $lang->story->closedBy = 'Geschlossen von';
|
||||
$lang->story->closedDate = 'Geschlossen am';
|
||||
$lang->story->closedReason = 'Geschlossen weil';
|
||||
$lang->story->rejectedReason = 'Abgelehnt weil';
|
||||
$lang->story->changedBy = 'ChangedBy';
|
||||
$lang->story->changedDate = 'ChangedDate';
|
||||
$lang->story->reviewedBy = 'Prüfer';
|
||||
$lang->story->reviewer = $lang->story->reviewedBy;
|
||||
$lang->story->reviewers = 'Reviewers';
|
||||
@@ -182,11 +191,12 @@ $lang->story->needNotReviewList[1] = 'Need Not Review';
|
||||
$lang->story->useList[0] = 'Ja';
|
||||
$lang->story->useList[1] = 'Nein';
|
||||
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = 'Entwurf';
|
||||
$lang->story->statusList['active'] = 'Aktiv';
|
||||
$lang->story->statusList['closed'] = 'Geschlossen';
|
||||
$lang->story->statusList['changed'] = 'Geändert';
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = 'Entwurf';
|
||||
$lang->story->statusList['reviewing'] = 'Wird geprüft';
|
||||
$lang->story->statusList['active'] = 'Aktiv';
|
||||
$lang->story->statusList['closed'] = 'Geschlossen';
|
||||
$lang->story->statusList['changing'] = 'Geändert';
|
||||
|
||||
$lang->story->stageList[''] = '';
|
||||
$lang->story->stageList['wait'] = 'Wartend';
|
||||
@@ -295,6 +305,8 @@ $lang->story->estimateMustBePlus = 'Estimated value cannot be negative';
|
||||
$lang->story->confirmChangeBranch = $lang->SRCommon . ' %s is linked to the plan of its linked branch. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan of its linked branch. Do you want to continue edit ' . $lang->SRCommon . '?';
|
||||
$lang->story->confirmChangePlan = $lang->SRCommon . ' %s is linked to the branch of its plan. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan. Do you want to continue edit branch ?';
|
||||
$lang->story->errorDuplicateStory = $lang->SRCommon . '%s not exist';
|
||||
$lang->story->confirmRecallChange = "After undo the change, the story content will revert to the version before the change. Are you sure you want to undo?";
|
||||
$lang->story->confirmRecallReview = "Are you sure you want to withdraw the review?";
|
||||
|
||||
$lang->story->form = new stdclass();
|
||||
$lang->story->form->area = 'Story Bereich';
|
||||
@@ -325,6 +337,7 @@ $lang->story->action->linkrelatedstory = array('main' => '$date, verknüpft
|
||||
$lang->story->action->subdividestory = array('main' => '$date, aufgeteilt von <strong>$actor</strong> mit Story <strong>$extra</strong>.');
|
||||
$lang->story->action->unlinkrelatedstory = array('main' => '$date, Verknüpfung aufgelöst durch <strong>$actor</strong> von Story <strong>$extra</strong>.');
|
||||
$lang->story->action->unlinkchildstory = array('main' => '$date, Verknüpfung aufgelöst durch <strong>$actor</strong> Story <strong>$extra</strong>.');
|
||||
$lang->story->action->recalledchange = array('main' => '$date, Undo changes by <strong>\$actor</strong>.');
|
||||
|
||||
/* Statistical statement. */
|
||||
$lang->story->report = new stdclass();
|
||||
@@ -452,6 +465,8 @@ $lang->story->subDivideTip['notActive'] = 'The Story is not active and cannot be
|
||||
|
||||
$lang->story->featureBar['browse']['all'] = $lang->all;
|
||||
$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed;
|
||||
$lang->story->featureBar['browse']['draft'] = $lang->story->statusList['draft'];
|
||||
$lang->story->featureBar['browse']['reviewing'] = $lang->story->statusList['reviewing'];
|
||||
|
||||
$lang->requirement->common = $lang->URCommon;
|
||||
$lang->requirement->create = 'Create Requirement';
|
||||
|
||||
+26
-11
@@ -23,10 +23,14 @@ $lang->story->change = "Change";
|
||||
$lang->story->changed = 'Change';
|
||||
$lang->story->assignTo = 'Assign';
|
||||
$lang->story->review = 'Review';
|
||||
$lang->story->submitReview = "Submit Review";
|
||||
$lang->story->recall = 'Revoke';
|
||||
$lang->story->recallChange = 'Undo Changes';
|
||||
$lang->story->recallAction = 'Undo';
|
||||
$lang->story->needReview = 'Need Review';
|
||||
$lang->story->batchReview = 'Batch Review';
|
||||
$lang->story->edit = "Edit Story";
|
||||
$lang->story->editDraft = "Edit Draft";
|
||||
$lang->story->batchEdit = "Batch Edit";
|
||||
$lang->story->subdivide = 'Decompose';
|
||||
$lang->story->link = 'Link';
|
||||
@@ -70,6 +74,8 @@ $lang->story->batchToTask = 'Batch Convert to Task';
|
||||
$lang->story->convertRelations = 'Convert Relations';
|
||||
$lang->story->undetermined = 'undetermined';
|
||||
$lang->story->order = 'Order';
|
||||
$lang->story->saveDraft = 'Save as draft';
|
||||
$lang->story->doNotSubmit = 'Do Not Submit';
|
||||
|
||||
$lang->story->editAction = "Edit {$lang->SRCommon}";
|
||||
$lang->story->changeAction = "Change {$lang->SRCommon}";
|
||||
@@ -82,12 +88,13 @@ $lang->story->deleteAction = "Delete {$lang->SRCommon}";
|
||||
$lang->story->exportAction = "Export {$lang->SRCommon}";
|
||||
$lang->story->reportAction = "Report";
|
||||
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->float = "『%s』should have positive number, or decimals.";
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->float = "『%s』should have positive number, or decimals.";
|
||||
$lang->story->saveDraftSuccess = 'Save as draft succeeded.';
|
||||
|
||||
$lang->story->id = 'ID';
|
||||
$lang->story->parent = 'Parent';
|
||||
@@ -130,6 +137,8 @@ $lang->story->closedBy = 'ClosedBy';
|
||||
$lang->story->closedDate = 'ClosedDate';
|
||||
$lang->story->closedReason = 'Reason';
|
||||
$lang->story->rejectedReason = 'Reject Reason';
|
||||
$lang->story->changedBy = 'ChangedBy';
|
||||
$lang->story->changedDate = 'ChangedDate';
|
||||
$lang->story->reviewedBy = 'ReviewedBy';
|
||||
$lang->story->reviewer = $lang->story->reviewedBy;
|
||||
$lang->story->reviewers = 'Reviewers';
|
||||
@@ -182,11 +191,12 @@ $lang->story->needNotReviewList[1] = 'No Review';
|
||||
$lang->story->useList[0] = 'Yes';
|
||||
$lang->story->useList[1] = 'No';
|
||||
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = 'Draft';
|
||||
$lang->story->statusList['active'] = 'Active';
|
||||
$lang->story->statusList['closed'] = 'Closed';
|
||||
$lang->story->statusList['changed'] = 'Changed';
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = 'Draft';
|
||||
$lang->story->statusList['reviewing'] = 'Reviewing';
|
||||
$lang->story->statusList['active'] = 'Active';
|
||||
$lang->story->statusList['closed'] = 'Closed';
|
||||
$lang->story->statusList['changing'] = 'Changing';
|
||||
|
||||
$lang->story->stageList[''] = '';
|
||||
$lang->story->stageList['wait'] = 'Waiting';
|
||||
@@ -295,6 +305,8 @@ $lang->story->estimateMustBePlus = 'Estimated value cannot be negative';
|
||||
$lang->story->confirmChangeBranch = $lang->SRCommon . ' %s is linked to the plan of its linked branch. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan of its linked branch. Do you want to continue edit ' . $lang->SRCommon . '?';
|
||||
$lang->story->confirmChangePlan = $lang->SRCommon . ' %s is linked to the branch of its plan. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan. Do you want to continue edit branch ?';
|
||||
$lang->story->errorDuplicateStory = $lang->SRCommon . '%s not exist';
|
||||
$lang->story->confirmRecallChange = "After undo the change, the story content will revert to the version before the change. Are you sure you want to undo?";
|
||||
$lang->story->confirmRecallReview = "Are you sure you want to withdraw the review?";
|
||||
|
||||
$lang->story->form = new stdclass();
|
||||
$lang->story->form->area = 'Scope';
|
||||
@@ -325,6 +337,7 @@ $lang->story->action->linkrelatedstory = array('main' => '$date, linked by
|
||||
$lang->story->action->subdividestory = array('main' => '$date, decomposed by <strong>$actor</strong> to Story <strong>$extra</strong>.');
|
||||
$lang->story->action->unlinkrelatedstory = array('main' => '$date, unlinked by <strong>$actor</strong> from Story <strong>$extra</strong>.');
|
||||
$lang->story->action->unlinkchildstory = array('main' => '$date, unlinked by <strong>$actor</strong> Decomposed Story <strong>$extra</strong>.');
|
||||
$lang->story->action->recalledchange = array('main' => '$date, Undo changes by <strong>\$actor</strong>.');
|
||||
|
||||
/* Statistical statement. */
|
||||
$lang->story->report = new stdclass();
|
||||
@@ -452,6 +465,8 @@ $lang->story->subDivideTip['notActive'] = 'The Story is not active and cannot be
|
||||
|
||||
$lang->story->featureBar['browse']['all'] = $lang->all;
|
||||
$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed;
|
||||
$lang->story->featureBar['browse']['draft'] = $lang->story->statusList['draft'];
|
||||
$lang->story->featureBar['browse']['reviewing'] = $lang->story->statusList['reviewing'];
|
||||
|
||||
$lang->requirement->common = $lang->URCommon;
|
||||
$lang->requirement->create = 'Create Requirement';
|
||||
|
||||
+28
-13
@@ -23,10 +23,14 @@ $lang->story->change = "Changer";
|
||||
$lang->story->changed = 'Changée';
|
||||
$lang->story->assignTo = 'Affecter';
|
||||
$lang->story->review = 'Valider';
|
||||
$lang->story->submitReview = "Submit Review";
|
||||
$lang->story->recall = 'Revoke';
|
||||
$lang->story->recallChange = 'Undo Changes';
|
||||
$lang->story->recallAction = 'Undo';
|
||||
$lang->story->needReview = 'Validation requise';
|
||||
$lang->story->batchReview = 'Validation par lot';
|
||||
$lang->story->edit = "Editer Story";
|
||||
$lang->story->editDraft = "Modifier le projet";
|
||||
$lang->story->batchEdit = "Editer par Lot";
|
||||
$lang->story->subdivide = 'Décomposer';
|
||||
$lang->story->link = 'Link';
|
||||
@@ -70,6 +74,8 @@ $lang->story->batchToTask = 'Batch Convert to Task';
|
||||
$lang->story->convertRelations = 'Convert Relations';
|
||||
$lang->story->undetermined = 'undetermined';
|
||||
$lang->story->order = 'Order';
|
||||
$lang->story->saveDraft = 'Save as draft';
|
||||
$lang->story->doNotSubmit = 'Do Not Submit';
|
||||
|
||||
$lang->story->editAction = "Edit {$lang->SRCommon}";
|
||||
$lang->story->changeAction = "Changer Story";
|
||||
@@ -82,12 +88,13 @@ $lang->story->deleteAction = "Supprimer Story";
|
||||
$lang->story->exportAction = "Exporter Story";
|
||||
$lang->story->reportAction = "Rapport de Story";
|
||||
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->float = "『 %s 』doit avoir des nombres positifs ou décimaux.";
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->float = "『 %s 』doit avoir des nombres positifs ou décimaux.";
|
||||
$lang->story->saveDraftSuccess = 'Save as draft succeeded.';
|
||||
|
||||
$lang->story->id = 'ID';
|
||||
$lang->story->parent = 'Parent';
|
||||
@@ -130,6 +137,8 @@ $lang->story->closedBy = 'Fermée par';
|
||||
$lang->story->closedDate = 'Date Fermeture';
|
||||
$lang->story->closedReason = 'Raison';
|
||||
$lang->story->rejectedReason = 'Raison du Rejet';
|
||||
$lang->story->changedBy = 'ChangedBy';
|
||||
$lang->story->changedDate = 'ChangedDate';
|
||||
$lang->story->reviewedBy = 'Validée par';
|
||||
$lang->story->reviewer = $lang->story->reviewedBy;
|
||||
$lang->story->reviewers = 'Reviewers';
|
||||
@@ -182,11 +191,12 @@ $lang->story->needNotReviewList[1] = 'Need Not Review';
|
||||
$lang->story->useList[0] = 'Oui';
|
||||
$lang->story->useList[1] = 'Non';
|
||||
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = 'Brouillon';
|
||||
$lang->story->statusList['active'] = 'Active';
|
||||
$lang->story->statusList['closed'] = 'Fermée';
|
||||
$lang->story->statusList['changed'] = 'Changée';
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = 'Brouillon';
|
||||
$lang->story->statusList['reviewing'] = 'Examen en cours';
|
||||
$lang->story->statusList['active'] = 'Active';
|
||||
$lang->story->statusList['closed'] = 'Fermée';
|
||||
$lang->story->statusList['changing'] = 'Changée';
|
||||
|
||||
$lang->story->stageList[''] = '';
|
||||
$lang->story->stageList['wait'] = 'En Attente';
|
||||
@@ -295,6 +305,8 @@ $lang->story->estimateMustBePlus = 'Estimated value cannot be negative';
|
||||
$lang->story->confirmChangeBranch = $lang->SRCommon . ' %s is linked to the plan of its linked branch. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan of its linked branch. Do you want to continue edit ' . $lang->SRCommon . '?';
|
||||
$lang->story->confirmChangePlan = $lang->SRCommon . ' %s is linked to the branch of its plan. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan. Do you want to continue edit branch ?';
|
||||
$lang->story->errorDuplicateStory = $lang->SRCommon . '%s not exist';
|
||||
$lang->story->confirmRecallChange = "After undo the change, the story content will revert to the version before the change. Are you sure you want to undo?";
|
||||
$lang->story->confirmRecallReview = "Are you sure you want to withdraw the review?";
|
||||
|
||||
$lang->story->form = new stdclass();
|
||||
$lang->story->form->area = 'Périmètre';
|
||||
@@ -325,6 +337,7 @@ $lang->story->action->linkrelatedstory = array('main' => '$date, associée
|
||||
$lang->story->action->subdividestory = array('main' => '$date, décomposée par <strong>$actor</strong> en Story <strong>$extra</strong>.');
|
||||
$lang->story->action->unlinkrelatedstory = array('main' => '$date, dissociée par <strong>$actor</strong> de la Story <strong>$extra</strong>.');
|
||||
$lang->story->action->unlinkchildstory = array('main' => '$date, dissociée par <strong>$actor</strong> de la sous-Story <strong>$extra</strong>.');
|
||||
$lang->story->action->recalledchange = array('main' => '$date, Undo changes by <strong>\$actor</strong>.');
|
||||
|
||||
/* Statistical statement. */
|
||||
$lang->story->report = new stdclass();
|
||||
@@ -450,8 +463,10 @@ $lang->story->subDivideTip['planned'] = 'Cette Story est planifiée et ne peut
|
||||
$lang->story->subDivideTip['projected'] = 'Cette Story a été créée et ne peut être subdivisée.';
|
||||
$lang->story->subDivideTip['notActive'] = "Cette Story n'est pas active et ne peut être subdivisée.";
|
||||
|
||||
$lang->story->featureBar['browse']['all'] = $lang->all;
|
||||
$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed;
|
||||
$lang->story->featureBar['browse']['all'] = $lang->all;
|
||||
$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed;
|
||||
$lang->story->featureBar['browse']['draft'] = $lang->story->statusList['draft'];
|
||||
$lang->story->featureBar['browse']['reviewing'] = $lang->story->statusList['reviewing'];
|
||||
|
||||
$lang->requirement->common = $lang->URCommon;
|
||||
$lang->requirement->create = 'Create Requirement';
|
||||
|
||||
+32
-12
@@ -23,10 +23,14 @@ $lang->story->change = "Thay đổi";
|
||||
$lang->story->changed = "Đã đổi";
|
||||
$lang->story->assignTo = 'Giao cho';
|
||||
$lang->story->review = 'Xét duyệt';
|
||||
$lang->story->submitReview = "Submit Review";
|
||||
$lang->story->recall = 'Revoke';
|
||||
$lang->story->recallChange = 'Undo Changes';
|
||||
$lang->story->recallAction = 'Undo';
|
||||
$lang->story->needReview = 'Duyệt nhu cầu';
|
||||
$lang->story->batchReview = 'Duyệt hàng loạt';
|
||||
$lang->story->edit = "Sửa câu chuyện";
|
||||
$lang->story->editDraft = "Sửa soạn thảo";
|
||||
$lang->story->batchEdit = "Sửa hàng loạt";
|
||||
$lang->story->subdivide = 'Phân rã';
|
||||
$lang->story->link = 'Link';
|
||||
@@ -68,6 +72,8 @@ $lang->story->batchToTask = 'Batch Convert to Task';
|
||||
$lang->story->convertRelations = 'Convert Relations';
|
||||
$lang->story->undetermined = 'undetermined';
|
||||
$lang->story->order = 'Order';
|
||||
$lang->story->saveDraft = 'Save as draft';
|
||||
$lang->story->doNotSubmit = 'Do Not Submit';
|
||||
|
||||
$lang->story->editAction = "Edit {$lang->SRCommon}";
|
||||
$lang->story->changeAction = "Change {$lang->SRCommon}";
|
||||
@@ -80,11 +86,13 @@ $lang->story->deleteAction = "Delete {$lang->SRCommon}";
|
||||
$lang->story->exportAction = "Export {$lang->SRCommon}";
|
||||
$lang->story->reportAction = "Report";
|
||||
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "This action will create a task with the same name as the selected {$lang->SRCommon} and link {$lang->SRCommon} to the task. The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "This action will create a task with the same name as the selected {$lang->SRCommon} and link {$lang->SRCommon} to the task. The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->float = "『%s』should be positive number, decimals included.";
|
||||
$lang->story->saveDraftSuccess = 'Save as draft succeeded.';
|
||||
|
||||
$lang->story->id = 'ID';
|
||||
$lang->story->parent = 'Mẹ';
|
||||
@@ -124,6 +132,8 @@ $lang->story->closedBy = 'Người đóng';
|
||||
$lang->story->closedDate = 'Ngày đóng';
|
||||
$lang->story->closedReason = 'Lý do';
|
||||
$lang->story->rejectedReason = 'Lý do từ chối';
|
||||
$lang->story->changedBy = 'ChangedBy';
|
||||
$lang->story->changedDate = 'ChangedDate';
|
||||
$lang->story->reviewedBy = 'Người duyệt';
|
||||
$lang->story->reviewer = $lang->story->reviewedBy;
|
||||
$lang->story->reviewers = 'Reviewers';
|
||||
@@ -175,11 +185,12 @@ $lang->story->needNotReviewList[1] = 'Need Not Review';
|
||||
$lang->story->useList[0] = 'Có';
|
||||
$lang->story->useList[1] = 'Không';
|
||||
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = 'Nháp';
|
||||
$lang->story->statusList['active'] = 'Kích hoạt';
|
||||
$lang->story->statusList['closed'] = 'Đã đóng';
|
||||
$lang->story->statusList['changed'] = 'Đã thay đổi';
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = 'Nháp';
|
||||
$lang->story->statusList['reviewing'] = 'Đang xem xét';
|
||||
$lang->story->statusList['active'] = 'Kích hoạt';
|
||||
$lang->story->statusList['closed'] = 'Đã đóng';
|
||||
$lang->story->statusList['changing'] = 'Đã thay đổi';
|
||||
|
||||
$lang->story->stageList[''] = '';
|
||||
$lang->story->stageList['wait'] = 'Đang đợi';
|
||||
@@ -286,6 +297,8 @@ $lang->story->estimateMustBePlus = 'Estimated value cannot be negative';
|
||||
$lang->story->confirmChangeBranch = $lang->SRCommon . ' %s is linked to the plan of its linked branch. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan of its linked branch. Do you want to continue edit ' . $lang->SRCommon . '?';
|
||||
$lang->story->confirmChangePlan = $lang->SRCommon . ' %s is linked to the branch of its plan. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan. Do you want to continue edit branch ?';
|
||||
$lang->story->errorDuplicateStory = $lang->SRCommon . '%s not exist';
|
||||
$lang->story->confirmRecallChange = "After undo the change, the story content will revert to the version before the change. Are you sure you want to undo?";
|
||||
$lang->story->confirmRecallReview = "Are you sure you want to withdraw the review?";
|
||||
|
||||
$lang->story->form = new stdclass();
|
||||
$lang->story->form->area = 'Phạm vi';
|
||||
@@ -316,6 +329,7 @@ $lang->story->action->linkrelatedstory = array('main' => '$date, liên kế
|
||||
$lang->story->action->subdividestory = array('main' => '$date, được phân rã bởi <strong>$actor</strong> tới Câu chuyện <strong>$extra</strong>.');
|
||||
$lang->story->action->unlinkrelatedstory = array('main' => '$date, bị hủy bởi <strong>$actor</strong> từ Câu chuyện <strong>$extra</strong>.');
|
||||
$lang->story->action->unlinkchildstory = array('main' => '$date, bị hủy bởi <strong>$actor</strong> Câu chuyện được phân rã <strong>$extra</strong>.');
|
||||
$lang->story->action->recalledchange = array('main' => '$date, Undo changes by <strong>\$actor</strong>.');
|
||||
|
||||
/* Statistical statement. */
|
||||
$lang->story->report = new stdclass();
|
||||
@@ -441,5 +455,11 @@ $lang->story->subDivideTip['planned'] = 'The Story has been planned and cannot
|
||||
$lang->story->subDivideTip['projected'] = 'The Story has been initiated and cannot be subdivided.';
|
||||
$lang->story->subDivideTip['notActive'] = 'The Story is not active and cannot be subdivided.';
|
||||
|
||||
$lang->story->featureBar['browse']['all'] = $lang->all;
|
||||
$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed;
|
||||
$lang->story->featureBar['browse']['all'] = $lang->all;
|
||||
$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed;
|
||||
$lang->story->featureBar['browse']['draft'] = $lang->story->statusList['draft'];
|
||||
$lang->story->featureBar['browse']['reviewing'] = $lang->story->statusList['reviewing'];
|
||||
|
||||
$lang->story->recallList = array();
|
||||
$lang->story->recallList['recallReview'] = $lang->story->recall;
|
||||
$lang->story->recallList['recallChange'] = $lang->story->recallChange;
|
||||
|
||||
+28
-13
@@ -23,10 +23,14 @@ $lang->story->change = "变更";
|
||||
$lang->story->changed = "{$lang->SRCommon}变更";
|
||||
$lang->story->assignTo = '指派';
|
||||
$lang->story->review = '评审';
|
||||
$lang->story->submitReview = "提交评审";
|
||||
$lang->story->recall = '撤销评审';
|
||||
$lang->story->recallChange = '撤销变更';
|
||||
$lang->story->recallAction = '撤销';
|
||||
$lang->story->needReview = '需要评审';
|
||||
$lang->story->batchReview = '批量评审';
|
||||
$lang->story->edit = "编辑";
|
||||
$lang->story->editDraft = "编辑草稿";
|
||||
$lang->story->batchEdit = "批量编辑";
|
||||
$lang->story->subdivide = '细分';
|
||||
$lang->story->link = '关联';
|
||||
@@ -70,6 +74,8 @@ $lang->story->batchToTask = '批量转任务';
|
||||
$lang->story->convertRelations = '换算关系';
|
||||
$lang->story->undetermined = '待定';
|
||||
$lang->story->order = '排序';
|
||||
$lang->story->saveDraft = '存为草稿';
|
||||
$lang->story->doNotSubmit = '保存暂不提交';
|
||||
|
||||
$lang->story->editAction = "编辑{$lang->SRCommon}";
|
||||
$lang->story->changeAction = "变更{$lang->SRCommon}";
|
||||
@@ -82,12 +88,13 @@ $lang->story->deleteAction = "删除{$lang->SRCommon}";
|
||||
$lang->story->exportAction = "导出{$lang->SRCommon}";
|
||||
$lang->story->reportAction = "统计报表";
|
||||
|
||||
$lang->story->skipStory = '需求:%s 为父需求,将不会被关闭。';
|
||||
$lang->story->closedStory = '需求:%s 已关闭,将不会被关闭。';
|
||||
$lang->story->batchToTaskTips = "已关闭的需求不会转为任务。";
|
||||
$lang->story->successToTask = '批量转任务成功';
|
||||
$lang->story->storyRound = '第 %s 轮估算';
|
||||
$lang->story->float = "『%s』应当是正数,可以是小数。";
|
||||
$lang->story->skipStory = '需求:%s 为父需求,将不会被关闭。';
|
||||
$lang->story->closedStory = '需求:%s 已关闭,将不会被关闭。';
|
||||
$lang->story->batchToTaskTips = "已关闭的需求不会转为任务。";
|
||||
$lang->story->successToTask = '批量转任务成功';
|
||||
$lang->story->storyRound = '第 %s 轮估算';
|
||||
$lang->story->float = "『%s』应当是正数,可以是小数。";
|
||||
$lang->story->saveDraftSuccess = '存为草稿成功';
|
||||
|
||||
$lang->story->id = '编号';
|
||||
$lang->story->parent = '父需求';
|
||||
@@ -130,6 +137,8 @@ $lang->story->closedBy = '由谁关闭';
|
||||
$lang->story->closedDate = '关闭日期';
|
||||
$lang->story->closedReason = '关闭原因';
|
||||
$lang->story->rejectedReason = '拒绝原因';
|
||||
$lang->story->changedBy = '由谁变更';
|
||||
$lang->story->changedDate = '变更时间';
|
||||
$lang->story->reviewedBy = '由谁评审';
|
||||
$lang->story->reviewer = $lang->story->reviewedBy;
|
||||
$lang->story->reviewers = '评审人员';
|
||||
@@ -182,11 +191,12 @@ $lang->story->needNotReviewList[1] = '不需要评审';
|
||||
$lang->story->useList[0] = '不使用';
|
||||
$lang->story->useList[1] = '使用';
|
||||
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = '草稿';
|
||||
$lang->story->statusList['active'] = '激活';
|
||||
$lang->story->statusList['closed'] = '已关闭';
|
||||
$lang->story->statusList['changed'] = '已变更';
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = '草稿';
|
||||
$lang->story->statusList['reviewing'] = '评审中';
|
||||
$lang->story->statusList['active'] = '激活';
|
||||
$lang->story->statusList['closed'] = '已关闭';
|
||||
$lang->story->statusList['changing'] = '变更中';
|
||||
|
||||
$lang->story->stageList[''] = '';
|
||||
$lang->story->stageList['wait'] = '未开始';
|
||||
@@ -295,6 +305,8 @@ $lang->story->estimateMustBePlus = '估算值不能是负数';
|
||||
$lang->story->confirmChangeBranch = $lang->SRCommon . '%s已关联在之前所属分支的计划中,调整分支后,' . $lang->SRCommon . '将从之前所属分支的计划中移除,请确认是否继续修改上述' . $lang->SRCommon . '的分支。';
|
||||
$lang->story->confirmChangePlan = $lang->SRCommon . '%s已关联在之前计划的所属分支中,调整分支后,' . $lang->SRCommon . '将会从计划中移除,请确认是否继续修改计划的所属分支。';
|
||||
$lang->story->errorDuplicateStory = $lang->SRCommon . '%s不存在';
|
||||
$lang->story->confirmRecallChange = "撤销变更后,需求内容会回退至变更前的版本,您确定要撤销吗?";
|
||||
$lang->story->confirmRecallReview = "您确定要撤回评审吗?";
|
||||
|
||||
$lang->story->form = new stdclass();
|
||||
$lang->story->form->area = "该{$lang->SRCommon}所属范围";
|
||||
@@ -325,6 +337,7 @@ $lang->story->action->linkrelatedstory = array('main' => "\$date, 由 <stro
|
||||
$lang->story->action->subdividestory = array('main' => "\$date, 由 <strong>\$actor</strong> 细分为{$lang->SRCommon} <strong>\$extra</strong>。");
|
||||
$lang->story->action->unlinkrelatedstory = array('main' => "\$date, 由 <strong>\$actor</strong> 移除相关{$lang->SRCommon} <strong>\$extra</strong>。");
|
||||
$lang->story->action->unlinkchildstory = array('main' => "\$date, 由 <strong>\$actor</strong> 移除细分{$lang->SRCommon} <strong>\$extra</strong>。");
|
||||
$lang->story->action->recalledchange = array('main' => "\$date, 由 <strong>\$actor</strong> 撤销变更。");
|
||||
|
||||
/* 统计报表。*/
|
||||
$lang->story->report = new stdclass();
|
||||
@@ -450,8 +463,10 @@ $lang->story->subDivideTip['planned'] = '该需求已计划,无法进行细
|
||||
$lang->story->subDivideTip['projected'] = '该需求已立项,无法进行细分操作';
|
||||
$lang->story->subDivideTip['notActive'] = '需求不是激活状态,无法进行细分操作';
|
||||
|
||||
$lang->story->featureBar['browse']['all'] = $lang->all;
|
||||
$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed;
|
||||
$lang->story->featureBar['browse']['all'] = $lang->all;
|
||||
$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed;
|
||||
$lang->story->featureBar['browse']['draft'] = $lang->story->statusList['draft'];
|
||||
$lang->story->featureBar['browse']['reviewing'] = $lang->story->statusList['reviewing'];
|
||||
|
||||
$lang->requirement->common = $lang->URCommon;
|
||||
$lang->requirement->create = "提{$lang->URCommon}";
|
||||
|
||||
@@ -173,11 +173,12 @@ $lang->story->needNotReviewList[1] = '不需要評審';
|
||||
$lang->story->useList[0] = '不使用';
|
||||
$lang->story->useList[1] = '使用';
|
||||
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = '草稿';
|
||||
$lang->story->statusList['active'] = '激活';
|
||||
$lang->story->statusList['closed'] = '已關閉';
|
||||
$lang->story->statusList['changed'] = '已變更';
|
||||
$lang->story->statusList[''] = '';
|
||||
$lang->story->statusList['draft'] = '草稿';
|
||||
$lang->story->statusList['reviewing'] = '评审中';
|
||||
$lang->story->statusList['active'] = '激活';
|
||||
$lang->story->statusList['closed'] = '已關閉';
|
||||
$lang->story->statusList['changing'] = '變更中';
|
||||
|
||||
$lang->story->stageList[''] = '';
|
||||
$lang->story->stageList['wait'] = '未開始';
|
||||
|
||||
+257
-95
@@ -202,7 +202,7 @@ class storyModel extends model
|
||||
if(isset($_POST['reviewer'])) $_POST['reviewer'] = array_filter($_POST['reviewer']);
|
||||
if(!$this->post->needNotReview and empty($_POST['reviewer']))
|
||||
{
|
||||
dao::$errors[] = $this->lang->story->errorEmptyReviewedBy;
|
||||
dao::$errors['reviewer'] = $this->lang->story->errorEmptyReviewedBy;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -211,11 +211,9 @@ class storyModel extends model
|
||||
->cleanInt('product,module,pri,plan')
|
||||
->callFunc('title', 'trim')
|
||||
->add('version', 1)
|
||||
->add('status', 'draft')
|
||||
->setDefault('plan,verify,notifyEmail', '')
|
||||
->setDefault('openedBy', $this->app->user->account)
|
||||
->setDefault('openedDate', $now)
|
||||
->setIF($this->post->needNotReview, 'status', 'active')
|
||||
->setIF($this->post->plan > 0, 'stage', 'planned')
|
||||
->setIF($this->post->estimate, 'estimate', (float)$this->post->estimate)
|
||||
->setIF(!in_array($this->post->source, $this->config->story->feedbackSource), 'feedbackBy', '')
|
||||
@@ -232,8 +230,8 @@ class storyModel extends model
|
||||
$result = $this->loadModel('common')->removeDuplicate('story', $story, "product={$story->product}");
|
||||
if(isset($result['stop']) and $result['stop']) return array('status' => 'exists', 'id' => $result['duplicate']);
|
||||
|
||||
if($this->checkForceReview()) $story->status = 'draft';
|
||||
if($story->status == 'draft') $story->stage = $this->post->plan > 0 ? 'planned' : 'wait';
|
||||
if($story->status != 'draft' and $this->checkForceReview()) $story->status = 'reviewing';
|
||||
if(strpos('draft,reviewing', $story->status) !== false) $story->stage = $this->post->plan > 0 ? 'planned' : 'wait';
|
||||
$story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->create['id'], $this->post->uid);
|
||||
|
||||
$requiredFields = "," . $this->config->story->create->requiredFields . ",";
|
||||
@@ -285,7 +283,6 @@ class storyModel extends model
|
||||
/* Save the story reviewer to storyreview table. */
|
||||
if(isset($_POST['reviewer']))
|
||||
{
|
||||
$assignedTo = '';
|
||||
foreach($this->post->reviewer as $reviewer)
|
||||
{
|
||||
if(empty($reviewer)) continue;
|
||||
@@ -295,10 +292,7 @@ class storyModel extends model
|
||||
$reviewData->version = 1;
|
||||
$reviewData->reviewer = $reviewer;
|
||||
$this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec();
|
||||
|
||||
if(empty($assignedTo)) $assignedTo = $reviewer;
|
||||
}
|
||||
if($assignedTo) $this->dao->update(TABLE_STORY)->set('assignedTo')->eq($assignedTo)->set('assignedDate')->eq(helper::now())->where('id')->eq($storyID)->exec();
|
||||
}
|
||||
|
||||
/* Project or execution linked story. */
|
||||
@@ -469,6 +463,13 @@ class storyModel extends model
|
||||
$mails = array();
|
||||
$stories = fixer::input('post')->get();
|
||||
|
||||
$saveDraft = false;
|
||||
if(isset($stories->status))
|
||||
{
|
||||
if($stories->status == 'draft') $saveDraft = true;
|
||||
unset($stories->status);
|
||||
}
|
||||
|
||||
$result = $this->loadModel('common')->removeDuplicate('story', $stories, "product={$productID}");
|
||||
$stories = $result['data'];
|
||||
|
||||
@@ -510,7 +511,7 @@ class storyModel extends model
|
||||
$story->category = $stories->category[$i];
|
||||
$story->pri = $stories->pri[$i];
|
||||
$story->estimate = $stories->estimate[$i];
|
||||
$story->status = (empty($stories->reviewer[$i]) and !$forceReview) ? 'active' : 'draft';
|
||||
$story->status = $saveDraft ? 'draft' : ((empty($stories->reviewer[$i]) and !$forceReview) ? 'active' : 'reviewing');
|
||||
$story->stage = ($this->app->tab == 'project' or $this->app->tab == 'execution') ? 'projected' : 'wait';
|
||||
$story->keywords = $stories->keywords[$i];
|
||||
$story->sourceNote = $stories->sourceNote[$i];
|
||||
@@ -695,10 +696,7 @@ class storyModel extends model
|
||||
->setDefault('lastEditedBy', $this->app->user->account)
|
||||
->add('id', $storyID)
|
||||
->add('lastEditedDate', $now)
|
||||
->setIF(!$this->post->assignedTo, 'assignedTo', '')
|
||||
->setIF($specChanged, 'version', $oldStory->version + 1)
|
||||
->setIF($specChanged and $oldStory->status == 'active' and $this->post->needNotReview == false, 'status', 'changed')
|
||||
->setIF($oldStory->status == 'draft' and $this->post->needNotReview, 'status', 'active')
|
||||
->setIF($specChanged, 'reviewedBy', '')
|
||||
->setIF($specChanged, 'changedBy', $this->app->user->account)
|
||||
->setIF($specChanged, 'changedDate', $now)
|
||||
@@ -706,10 +704,11 @@ class storyModel extends model
|
||||
->setIF($specChanged, 'closedReason', '')
|
||||
->setIF($specChanged and $oldStory->reviewedBy, 'reviewedDate', '0000-00-00')
|
||||
->setIF($specChanged and $oldStory->closedBy, 'closedDate', '0000-00-00')
|
||||
->setIF(!$specChanged, 'status', $oldStory->status)
|
||||
->stripTags($this->config->story->editor->change['id'], $this->config->allowedTags)
|
||||
->remove('files,labels,reviewer,comment,needNotReview,uid')
|
||||
->get();
|
||||
if($specChanged and isset($story->status) && $story->status == 'active' and $this->checkForceReview()) $story->status = 'changed';
|
||||
|
||||
$story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->change['id'], $this->post->uid);
|
||||
$this->dao->update(TABLE_STORY)->data($story, 'spec,verify')
|
||||
->autoCheck()
|
||||
@@ -750,7 +749,6 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
/* Update the reviewer. */
|
||||
$assignedTo = '';
|
||||
foreach($_POST['reviewer'] as $reviewer)
|
||||
{
|
||||
$reviewData = new stdclass();
|
||||
@@ -758,16 +756,16 @@ class storyModel extends model
|
||||
$reviewData->version = $story->version;
|
||||
$reviewData->reviewer = $reviewer;
|
||||
$this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec();
|
||||
|
||||
if(empty($assignedTo)) $assignedTo = $reviewer;
|
||||
}
|
||||
if($assignedTo and $assignedTo != $oldStory->assignedTo) $this->dao->update(TABLE_STORY)->set('assignedTo')->eq($assignedTo)->set('assignedDate')->eq(helper::now())->where('id')->eq($storyID)->exec();
|
||||
|
||||
if($reviewerHasChanged)
|
||||
{
|
||||
$oldStory->reviewers = implode(',', array_keys($oldStoryReviewers));
|
||||
$story->reviewers = implode(',', $_POST['reviewer']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->file->updateObjectID($this->post->uid, $storyID, 'story');
|
||||
|
||||
$oldStory->reviewers = implode(',', array_keys($oldStoryReviewers));
|
||||
$story->reviewers = implode(',', $_POST['reviewer']);
|
||||
return common::createChanges($oldStory, $story);
|
||||
}
|
||||
}
|
||||
@@ -789,17 +787,30 @@ class storyModel extends model
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->checkForceReview() and empty($_POST['reviewer']))
|
||||
{
|
||||
dao::$errors[] = $this->lang->story->errorEmptyReviewedBy;
|
||||
return false;
|
||||
}
|
||||
|
||||
$oldSpec = $this->dao->select('title,spec,verify')->from(TABLE_STORYSPEC)->where('story')->eq((int)$storyID)->andWhere('version')->eq($oldStory->version)->fetch();
|
||||
$oldStory->title = isset($oldSpec->title) ? $oldSpec->title : '';
|
||||
$oldStory->spec = isset($oldSpec->spec) ? $oldSpec->spec : '';
|
||||
$oldStory->verify = isset($oldSpec->verify) ? $oldSpec->verify : '';
|
||||
|
||||
$story = fixer::input('post')
|
||||
->cleanInt('product,module,pri,duplicateStory')
|
||||
->cleanFloat('estimate')
|
||||
->setDefault('assignedDate', $oldStory->assignedDate)
|
||||
->setDefault('lastEditedBy', $this->app->user->account)
|
||||
->setDefault('reviewedBy', $oldStory->reviewedBy)
|
||||
->setDefault('title', $oldStory->title)
|
||||
->setDefault('spec', $oldStory->spec)
|
||||
->setDefault('verify', $oldStory->verify)
|
||||
->setDefault('mailto', '')
|
||||
->add('id', $storyID)
|
||||
->add('lastEditedDate', $now)
|
||||
->setDefault('plan,notifyEmail', '')
|
||||
->setDefault('status', $oldStory->status)
|
||||
->setDefault('product', $oldStory->product)
|
||||
->setDefault('branch', $oldStory->branch)
|
||||
->setIF(!$this->post->linkStories, 'linkStories', '')
|
||||
@@ -812,16 +823,16 @@ class storyModel extends model
|
||||
->setIF(!in_array($this->post->source, $this->config->story->feedbackSource), 'notifyEmail', '')
|
||||
->setIF(!empty($_POST['plan'][0]) and $oldStory->stage == 'wait', 'stage', 'planned')
|
||||
->stripTags($this->config->story->editor->edit['id'], $this->config->allowedTags)
|
||||
->join('reviewedBy', ',')
|
||||
->join('mailto', ',')
|
||||
->join('linkStories', ',')
|
||||
->join('linkRequirements', ',')
|
||||
->join('childStories', ',')
|
||||
->remove('files,labels,comment,contactListMenu,stages,reviewer')
|
||||
->remove('files,labels,comment,contactListMenu,stages,reviewer,needNotReview')
|
||||
->get();
|
||||
|
||||
if($oldStory->type == 'story' and !isset($story->linkStories)) $story->linkStories = '';
|
||||
if($oldStory->type == 'requirement' and !isset($story->linkRequirements)) $story->linkRequirements = '';
|
||||
if($oldStory->status == 'changing' and $story->status == 'draft') $story->status = 'changing';
|
||||
|
||||
if(isset($story->plan) and is_array($story->plan)) $story->plan = trim(join(',', $story->plan), ',');
|
||||
if(isset($_POST['branch']) and $_POST['branch'] == 0) $story->branch = 0;
|
||||
@@ -858,9 +869,9 @@ class storyModel extends model
|
||||
if(isset($story->stage) and $oldStory->stage != $story->stage) $story->stagedBy = (strpos('tested|verified|released|closed', $story->stage) !== false) ? $this->app->user->account : '';
|
||||
$story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->edit['id'], $this->post->uid);
|
||||
|
||||
if(isset($_POST['reviewer']))
|
||||
if(isset($_POST['reviewer']) or isset($_POST['needNotReview']))
|
||||
{
|
||||
$_POST['reviewer'] = array_filter($_POST['reviewer']);
|
||||
$_POST['reviewer'] = isset($_POST['needNotReview']) ? array() : array_filter($_POST['reviewer']);
|
||||
$oldReviewer = $this->getReviewerPairs($storyID, $oldStory->version);
|
||||
if(array_diff($_POST['reviewer'], array_keys($oldReviewer)) or array_diff(array_keys($oldReviewer), $_POST['reviewer']))
|
||||
{
|
||||
@@ -877,8 +888,11 @@ class storyModel extends model
|
||||
$this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec();
|
||||
}
|
||||
|
||||
$story->reviewedBy = $oldStory->reviewedBy;
|
||||
$story = $this->updateStoryByReview($storyID, $oldStory, $story);
|
||||
if($story->status == 'reviewing')
|
||||
{
|
||||
$story->reviewedBy = $oldStory->reviewedBy;
|
||||
$story = $this->updateStoryByReview($storyID, $oldStory, $story);
|
||||
}
|
||||
}
|
||||
|
||||
$oldStory->reviewers = implode(',', array_keys($oldReviewer));
|
||||
@@ -886,7 +900,7 @@ class storyModel extends model
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_STORY)
|
||||
->data($story, 'reviewers')
|
||||
->data($story, 'reviewers,spec,verify')
|
||||
->autoCheck()
|
||||
->checkIF(isset($story->closedBy), 'closedReason', 'notempty')
|
||||
->checkIF(isset($story->closedReason) and $story->closedReason == 'done', 'stage', 'notempty')
|
||||
@@ -897,6 +911,15 @@ class storyModel extends model
|
||||
|
||||
if(!dao::isError())
|
||||
{
|
||||
if($story->spec != $oldStory->spec or $story->verify != $oldStory->verify or $story->title != $oldStory->title)
|
||||
{
|
||||
$data = new stdclass();
|
||||
$data->title = $story->title;
|
||||
$data->spec = $story->spec;
|
||||
$data->verify = $story->verify;
|
||||
$this->dao->update(TABLE_STORYSPEC)->data($data)->where('story')->eq((int)$storyID)->andWhere('version')->eq($oldStory->version)->exec();
|
||||
}
|
||||
|
||||
if($story->product != $oldStory->product)
|
||||
{
|
||||
$this->updateStoryProduct($storyID, $story->product);
|
||||
@@ -1063,10 +1086,10 @@ class storyModel extends model
|
||||
if(empty($childrenStatus)) return $this->dao->update(TABLE_STORY)->set('parent')->eq('0')->where('id')->eq($parentID)->exec();
|
||||
|
||||
$status = $oldParentStory->status;
|
||||
if(count($childrenStatus) == 1 and $oldParentStory->status != 'changed')
|
||||
if(count($childrenStatus) == 1 and $oldParentStory->status != 'changing')
|
||||
{
|
||||
$status = current($childrenStatus);
|
||||
if($status == 'draft' or $status == 'changed') $status = 'active';
|
||||
if($status == 'draft' or $status == 'changing') $status = 'active';
|
||||
}
|
||||
elseif(count($childrenStatus) != 1 and $oldParentStory->status == 'closed')
|
||||
{
|
||||
@@ -1298,7 +1321,7 @@ class storyModel extends model
|
||||
$story->version = $story->title == $oldStory->title ? $oldStory->version : $oldStory->version + 1;
|
||||
if($story->stage != $oldStory->stage) $story->stagedBy = (strpos('tested|verified|released|closed', $story->stage) !== false) ? $this->app->user->account : '';
|
||||
|
||||
if($story->title != $oldStory->title and $story->status != 'draft') $story->status = 'changed';
|
||||
if($story->title != $oldStory->title and $story->status != 'draft') $story->status = 'changing';
|
||||
if($story->closedBy != false and $oldStory->closedDate == '') $story->closedDate = $now;
|
||||
if($story->closedReason != false and $oldStory->closedDate == '') $story->closedDate = $now;
|
||||
if($story->closedBy != false or $story->closedReason != false) $story->status = 'closed';
|
||||
@@ -1388,8 +1411,6 @@ class storyModel extends model
|
||||
*/
|
||||
public function review($storyID)
|
||||
{
|
||||
if($this->post->result == 'revert' and $this->post->preVersion == false) return print(js::alert($this->lang->story->mustChoosePreVersion));
|
||||
|
||||
if(strpos($this->config->story->review->requiredFields, 'comment') !== false and !$this->post->comment)
|
||||
{
|
||||
dao::$errors[] = sprintf($this->lang->error->notempty, $this->lang->comment);
|
||||
@@ -1412,15 +1433,16 @@ class storyModel extends model
|
||||
->setDefault('reviewedDate', $date)
|
||||
->stripTags($this->config->story->editor->review['id'], $this->config->allowedTags)
|
||||
->setIF(!$this->post->assignedTo, 'assignedTo', '')
|
||||
->setIF($this->post->result == 'revert', 'version', $this->post->preVersion)
|
||||
->setIF($this->post->result == 'clarify', 'assignedTo', $oldStory->lastEditedBy ? $oldStory->lastEditedBy : $oldStory->openedBy)
|
||||
->setIF($this->post->result == 'revert', 'version', $oldStory->version - 1)
|
||||
->removeIF($this->post->result != 'reject', 'closedReason, duplicateStory, childStories')
|
||||
->removeIF($this->post->result == 'reject' and $this->post->closedReason != 'duplicate', 'duplicateStory')
|
||||
->removeIF($this->post->result == 'reject' and $this->post->closedReason != 'subdivided', 'childStories')
|
||||
->add('reviewedBy', $oldStory->reviewedBy . ',' . $this->app->user->account)
|
||||
->add('id', $storyID)
|
||||
->remove('result,preVersion,comment')
|
||||
->remove('result,comment')
|
||||
->get();
|
||||
|
||||
$story->reviewedBy = implode(',', array_unique(explode(',', $story->reviewedBy)));
|
||||
$story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->review['id'], $this->post->uid);
|
||||
|
||||
/* Fix bug #671. */
|
||||
@@ -1447,7 +1469,7 @@ class storyModel extends model
|
||||
->where('id')->eq($storyID)->exec();
|
||||
if($this->post->result == 'revert')
|
||||
{
|
||||
$preTitle = $this->dao->select('title')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($this->post->preVersion)->fetch('title');
|
||||
$preTitle = $this->dao->select('title')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($oldStory->version - 1)->fetch('title');
|
||||
$this->dao->update(TABLE_STORY)->set('title')->eq($preTitle)->where('id')->eq($storyID)->exec();
|
||||
|
||||
/* Delete versions that is after this version. */
|
||||
@@ -1491,7 +1513,7 @@ class storyModel extends model
|
||||
$oldStory = $oldStories[$storyID];
|
||||
$isSuperReviewer = strpos(',' . trim(zget($this->config->story, 'superReviewers', ''), ',') . ',', ',' . $this->app->user->account . ',');
|
||||
|
||||
if($oldStory->status != 'draft' and $oldStory->status != 'changed') continue;
|
||||
if($oldStory->status != 'draft' and $oldStory->status != 'changing') continue;
|
||||
if(!in_array($this->app->user->account, array_keys($reviewerList[$storyID])) and $isSuperReviewer === false) continue;
|
||||
if(isset($hasResult[$storyID]) and $hasResult[$storyID]->version == $oldStories[$storyID]->version) continue;
|
||||
|
||||
@@ -1547,13 +1569,92 @@ class storyModel extends model
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function recall($storyID)
|
||||
public function recallReview($storyID)
|
||||
{
|
||||
$story = $this->getById($storyID);
|
||||
$this->dao->update(TABLE_STORY)->set('status')->eq('draft')->where('id')->eq($storyID)->exec();
|
||||
$story = $this->getById($storyID);
|
||||
$isChanged = $story->changedBy ? true : false;
|
||||
$status = $isChanged ? 'changing' : 'draft';
|
||||
$this->dao->update(TABLE_STORY)->set('status')->eq($status)->where('id')->eq($storyID)->exec();
|
||||
$this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($story->version)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recall the story change.
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function recallChange($storyID)
|
||||
{
|
||||
$story = $this->getById($storyID);
|
||||
$preVersion = $story->version - 1;
|
||||
|
||||
/* Update story title and version and status. */
|
||||
$preTitle = $this->dao->select('title')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($preVersion)->fetch('title');
|
||||
$this->dao->update(TABLE_STORY)->set('title')->eq($preTitle)->set('version')->eq($preVersion)->set('status')->eq('active')->where('id')->eq($storyID)->exec();
|
||||
|
||||
/* Delete versions that is after this version. */
|
||||
$this->dao->delete()->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($story->version)->exec();
|
||||
$this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($story->version)->exec();
|
||||
|
||||
$this->dao->delete()->from(TABLE_FILE)->where('objectType')->eq('story')->andWhere('objectID')->eq($storyID)->andWhere('extra')->eq($story->version)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit review.
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return array|bool
|
||||
*/
|
||||
public function submitReview($storyID)
|
||||
{
|
||||
if(isset($_POST['reviewer'])) $_POST['reviewer'] = array_filter($_POST['reviewer']);
|
||||
if(!$this->post->needNotReview and empty($_POST['reviewer']))
|
||||
{
|
||||
dao::$errors[] = $this->lang->story->errorEmptyReviewedBy;
|
||||
return false;
|
||||
}
|
||||
|
||||
$oldStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch();
|
||||
$reviewerList = $this->getReviewerPairs($oldStory->id, $oldStory->version);
|
||||
$oldStory->reviewer = implode(',', array_keys($reviewerList));
|
||||
|
||||
$story = fixer::input('post')
|
||||
->setDefault('status', 'active')
|
||||
->setDefault('reviewer', '')
|
||||
->remove('needNotReview')
|
||||
->join('reviewer', ',')
|
||||
->get();
|
||||
|
||||
$this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($oldStory->version)->exec();
|
||||
|
||||
if(isset($_POST['reviewer']))
|
||||
{
|
||||
$assignedTo = '';
|
||||
foreach($this->post->reviewer as $reviewer)
|
||||
{
|
||||
if(empty($reviewer)) continue;
|
||||
|
||||
$reviewData = new stdclass();
|
||||
$reviewData->story = $storyID;
|
||||
$reviewData->version = $oldStory->version;
|
||||
$reviewData->reviewer = $reviewer;
|
||||
$this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec();
|
||||
|
||||
if(empty($assignedTo)) $assignedTo = $reviewer;
|
||||
}
|
||||
if($assignedTo) $this->dao->update(TABLE_STORY)->set('assignedTo')->eq($assignedTo)->set('assignedDate')->eq(helper::now())->where('id')->eq($storyID)->exec();
|
||||
$story->status = 'reviewing';
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_STORY)->set('status')->eq($story->status)->where('id')->eq($storyID)->exec();
|
||||
if(!dao::isError()) return common::createChanges($oldStory, $story);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subdivide story
|
||||
*
|
||||
@@ -2253,6 +2354,8 @@ class storyModel extends model
|
||||
->add('closedDate', '0000-00-00')
|
||||
->add('reviewedBy', '')
|
||||
->add('reviewedDate', '0000-00-00')
|
||||
->add('changedBy', '')
|
||||
->add('changedDate', '0000-00-00')
|
||||
->add('duplicateStory', 0)
|
||||
->add('childStories', '')
|
||||
->setDefault('lastEditedBy', $this->app->user->account)
|
||||
@@ -2262,10 +2365,14 @@ class storyModel extends model
|
||||
->stripTags($this->config->story->editor->activate['id'], $this->config->allowedTags)
|
||||
->remove('comment')
|
||||
->get();
|
||||
|
||||
/* Get status after activation. */
|
||||
$story->status = $this->getActivateStatus($storyID);
|
||||
|
||||
$story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->activate['id'], $this->post->uid);
|
||||
$this->dao->update(TABLE_STORY)->data($story)->autoCheck()->checkFlow()->where('id')->eq($storyID)->exec();
|
||||
|
||||
if($this->post->status == 'active') $this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->exec();
|
||||
if($story->status == 'active') $this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->exec();
|
||||
|
||||
$this->setStage($storyID);
|
||||
|
||||
@@ -2828,7 +2935,7 @@ class storyModel extends model
|
||||
->beginIF($fieldName == 'reviewBy')
|
||||
->andWhere('t2.reviewer')->eq($this->app->user->account)
|
||||
->andWhere('t2.result')->eq('')
|
||||
->andWhere('t1.status')->in('draft,changed')
|
||||
->andWhere('t1.status')->eq('reviewing')
|
||||
->fi()
|
||||
->beginIF($fieldName == 'assignedBy')->andWhere('t1.id')->in($actionIDList)->andWhere('t1.status')->ne('closed')->fi()
|
||||
->orderBy($orderBy)
|
||||
@@ -2949,15 +3056,6 @@ class storyModel extends model
|
||||
if(empty($normalProducts) and empty($branchProducts)) $storyQuery .= '1 = 1';
|
||||
$storyQuery .= ') ';
|
||||
|
||||
if($this->app->moduleName == 'release' or $this->app->moduleName == 'build')
|
||||
{
|
||||
$storyQuery .= " AND `status` NOT IN ('draft')"; // Fix bug #990.
|
||||
}
|
||||
else
|
||||
{
|
||||
$storyQuery .= " AND `status` NOT IN ('draft', 'closed')";
|
||||
}
|
||||
|
||||
if($this->app->rawModule == 'build' and $this->app->rawMethod == 'linkstory') $storyQuery .= " AND `parent` != '-1'";
|
||||
}
|
||||
elseif(strpos($storyQuery, $allBranch) !== false)
|
||||
@@ -2970,6 +3068,15 @@ class storyModel extends model
|
||||
}
|
||||
$storyQuery = preg_replace("/`plan` +LIKE +'%([0-9]+)%'/i", "CONCAT(',', `plan`, ',') LIKE '%,$1,%'", $storyQuery);
|
||||
|
||||
if($this->app->moduleName == 'release' or $this->app->moduleName == 'build')
|
||||
{
|
||||
$storyQuery .= " AND `status` NOT IN ('draft', 'reviewing')"; // Fix bug #990.
|
||||
}
|
||||
else
|
||||
{
|
||||
$storyQuery .= " AND `status` NOT IN ('draft', 'reviewing', 'closed')";
|
||||
}
|
||||
|
||||
return $this->getBySQL($queryProductID, $storyQuery, $orderBy, $pager, $type);
|
||||
}
|
||||
|
||||
@@ -3177,16 +3284,16 @@ class storyModel extends model
|
||||
->beginIF($execution->type == 'project')
|
||||
->beginIF(!empty($productID))->andWhere('t1.product')->eq($productID)
|
||||
->beginIF($type == 'bybranch' and $branchParam !== '')->andWhere('t2.branch')->in("0,$branchParam")->fi()
|
||||
->beginIF(strpos('changed|closed', $type) !== false)->andWhere('t2.status')->eq($type)->fi()
|
||||
->beginIF(strpos('draft|reviewing|changing|closed', $type) !== false)->andWhere('t2.status')->eq($type)->fi()
|
||||
->beginIF($type == 'unclosed')->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi()
|
||||
->beginIF($type == 'linkedexecution')->andWhere('t2.id')->in($storyIdList)->fi()
|
||||
->beginIF($type == 'unlinkedexecution')->andWhere('t2.id')->notIn($storyIdList)->fi()
|
||||
->fi()
|
||||
->beginIF($execution->type != 'project')
|
||||
->beginIF(!empty($productParam))->andWhere('t1.product')->eq($productParam)->fi()
|
||||
->beginIF($this->session->executionStoryBrowseType and strpos('changed|', $this->session->executionStoryBrowseType) !== false)->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi()
|
||||
->beginIF($this->session->executionStoryBrowseType and strpos('changing|', $this->session->executionStoryBrowseType) !== false)->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi()
|
||||
->fi()
|
||||
->beginIF($this->session->storyBrowseType and strpos('changed|', $this->session->storyBrowseType) !== false)->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi()
|
||||
->beginIF($this->session->storyBrowseType and strpos('changing|', $this->session->storyBrowseType) !== false)->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi()
|
||||
->beginIF($modules)->andWhere('t2.module')->in($modules)->fi()
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->andWhere('t3.deleted')->eq(0)
|
||||
@@ -3249,7 +3356,7 @@ class storyModel extends model
|
||||
->beginIF($branch !== 'all')->andWhere('t2.branch')->in("0,$branch")->fi()
|
||||
->beginIF($moduleIdList)->andWhere('t2.module')->in($moduleIdList)->fi()
|
||||
->beginIF($status == 'unclosed')->andWhere('t2.status')->ne('closed')->fi()
|
||||
->beginIF($status == 'review')->andWhere('t2.status')->in('draft,changed')->fi()
|
||||
->beginIF($status == 'review')->andWhere('t2.status')->in('draft,changing')->fi()
|
||||
->beginIF($status == 'active')->andWhere('t2.status')->eq('active')->fi()
|
||||
->orderBy('t1.`order` desc, t1.`story` desc')
|
||||
->fetchAll('id');
|
||||
@@ -3401,7 +3508,7 @@ class storyModel extends model
|
||||
->beginIF($type != 'closedBy' and $this->app->moduleName == 'block')->andWhere('t1.status')->ne('closed')->fi()
|
||||
->beginIF($type != 'all')
|
||||
->beginIF($type == 'assignedTo')->andWhere('t1.assignedTo')->eq($account)->fi()
|
||||
->beginIF($type == 'reviewBy')->andWhere('t3.reviewer')->eq($account)->andWhere('t3.result')->eq('')->andWhere('t1.status')->in('draft,changed')->fi()
|
||||
->beginIF($type == 'reviewBy')->andWhere('t3.reviewer')->eq($account)->andWhere('t3.result')->eq('')->andWhere('t1.status')->in('reviewing,changing')->fi()
|
||||
->beginIF($type == 'openedBy')->andWhere('t1.openedBy')->eq($account)->fi()
|
||||
->beginIF($type == 'reviewedBy')->andWhere("CONCAT(',', t1.reviewedBy, ',')")->like("%,$account,%")->fi()
|
||||
->beginIF($type == 'closedBy')->andWhere('t1.closedBy')->eq($account)->fi()
|
||||
@@ -4073,15 +4180,15 @@ class storyModel extends model
|
||||
|
||||
$isSuperReviewer = strpos(',' . trim(zget($config->story, 'superReviewers', ''), ',') . ',', ',' . $app->user->account . ',');
|
||||
|
||||
if($action == 'change') return ($isSuperReviewer !== false or count($story->reviewer) == 0 or count($story->notReview) == 0) and $story->status != 'closed';
|
||||
if($action == 'review') return (($isSuperReviewer !== false or in_array($app->user->account, $story->notReview)) and ($story->status == 'draft' or $story->status == 'changed'));
|
||||
if($action == 'recall') return empty($story->reviewedBy) and strpos('draft,changed', $story->status) !== false and !empty($story->reviewer) and ($app->user->account == $story->openedBy);
|
||||
if($action == 'change') return ($isSuperReviewer !== false or $story->status == 'active');
|
||||
if($action == 'review') return (($isSuperReviewer !== false or in_array($app->user->account, $story->notReview)) and $story->status == 'reviewing');
|
||||
if($action == 'recall') return strpos('reviewing,changing', $story->status) !== false;
|
||||
if($action == 'close') return $story->status != 'closed';
|
||||
if($action == 'activate') return $story->status == 'closed';
|
||||
if($action == 'assignto') return $story->status != 'closed';
|
||||
if($action == 'createcase') return $story->type != 'requirement';
|
||||
if($action == 'batchcreate' and $story->parent > 0) return false;
|
||||
if($action == 'batchcreate' and $story->type == 'requirement' and $story->status != 'closed') return $story->status != 'draft';
|
||||
if($action == 'batchcreate' and $story->type == 'requirement' and $story->status != 'closed') return strpos('draft,reviewing,changing', $story->status) === false;
|
||||
if($action == 'batchcreate' and $config->vision == 'lite' and ($story->status == 'active' and ($story->stage == 'wait' or $story->stage == 'projected'))) return true;
|
||||
if($action == 'batchcreate' and ($story->status != 'active' or $story->stage != 'wait' or !empty($story->plan))) return false;
|
||||
|
||||
@@ -4109,44 +4216,54 @@ class storyModel extends model
|
||||
if($story->URChanged) return $this->buildMenu('story', 'processStoryChange', $params, $story, $type, 'ok', '', 'iframe', true, '', $this->lang->confirm);
|
||||
|
||||
$isClick = $this->isClickable($story, 'change');
|
||||
$title = (!$isClick and $story->status != 'closed') ? $this->lang->story->changeTip : '';
|
||||
$title = (!$isClick and $story->status != 'closed' and $story->status != 'draft') ? $this->lang->story->changeTip : '';
|
||||
$menu .= $this->buildMenu('story', 'change', $params . "&from=$story->from&storyType=$story->type", $story, $type, 'alter', '', 'showinonlybody', false, '', $title);
|
||||
|
||||
$isClick = $this->isClickable($story, 'review');
|
||||
$title = $this->lang->story->review;
|
||||
if(!$isClick and $story->status != 'closed')
|
||||
if(strpos('draft,changing', $story->status) !== false)
|
||||
{
|
||||
if($story->status == 'active')
|
||||
{
|
||||
$title = $this->lang->story->reviewTip['active'];
|
||||
}
|
||||
elseif($storyReviewer and in_array($this->app->user->account, $storyReviewer))
|
||||
{
|
||||
$title = $this->lang->story->reviewTip['reviewed'];
|
||||
}
|
||||
elseif($storyReviewer and !in_array($this->app->user->account, $storyReviewer))
|
||||
{
|
||||
$title = $this->lang->story->reviewTip['notReviewer'];
|
||||
}
|
||||
elseif(empty($storyReviewer))
|
||||
{
|
||||
$title = $this->lang->story->reviewTip['recalled'];
|
||||
}
|
||||
$menu .= $this->buildMenu('story', 'submitReview', "storyID=$story->id", $story, $type, 'sub-review', '', 'iframe', true, "data-width='50%'");
|
||||
}
|
||||
$menu .= $this->buildMenu('story', 'review', $params . "&from=$story->from&storyType=$story->type", $story, $type, 'search', '', 'showinonlybody', false, '', $title);
|
||||
$title = $this->lang->story->recall;
|
||||
else
|
||||
{
|
||||
$isClick = $this->isClickable($story, 'review');
|
||||
$title = $this->lang->story->review;
|
||||
if(!$isClick and $story->status != 'closed')
|
||||
{
|
||||
if($story->status == 'active')
|
||||
{
|
||||
$title = $this->lang->story->reviewTip['active'];
|
||||
}
|
||||
elseif($storyReviewer and in_array($this->app->user->account, $storyReviewer))
|
||||
{
|
||||
$title = $this->lang->story->reviewTip['reviewed'];
|
||||
}
|
||||
elseif($storyReviewer and !in_array($this->app->user->account, $storyReviewer))
|
||||
{
|
||||
$title = $this->lang->story->reviewTip['notReviewer'];
|
||||
}
|
||||
elseif(empty($storyReviewer))
|
||||
{
|
||||
$title = $this->lang->story->reviewTip['recalled'];
|
||||
}
|
||||
}
|
||||
$menu .= $this->buildMenu('story', 'review', $params . "&from=$story->from&storyType=$story->type", $story, $type, 'search', '', 'showinonlybody', false, '', $title);
|
||||
}
|
||||
|
||||
$isClick = $this->isClickable($story, 'recall');
|
||||
$title = $story->status == 'changing' ? $this->lang->story->recallChange : $this->lang->story->recall;
|
||||
if(!$isClick and $story->status != 'closed')
|
||||
{
|
||||
if($story->status == 'draft' and empty($storyReviewer)) $title = $this->lang->story->recallTip['recalled'];
|
||||
if($story->status == 'draft' and !empty($storyReviewer)) $title = $this->lang->story->recallTip['reviewed'];
|
||||
if(empty($story->reviewedBy) and strpos('draft,changed', $story->status) !== false and !empty($story->reviewer) and $this->app->user->account != $story->openedBy) $title = $this->lang->story->recallTip['notOpenedBy'];
|
||||
if(empty($story->reviewedBy) and strpos('draft,changing', $story->status) !== false and !empty($story->reviewer) and $this->app->user->account != $story->openedBy) $title = $this->lang->story->recallTip['notOpenedBy'];
|
||||
if($story->status == 'active' and empty($story->reviewer)) $title = $this->lang->story->recallTip['actived'];
|
||||
}
|
||||
$menu .= $this->buildMenu('story', 'recall', $params . "&from=list&storyType=$story->type", $story, $type, 'undo', 'hiddenwin', 'showinonlybody', '', '', $title);
|
||||
|
||||
$menu .= $this->buildMenu('story', 'recall', $params . "&from=list&confirm=no&storyType=$story->type", $story, $type, 'undo', 'hiddenwin', 'showinonlybody', false, '', $title);
|
||||
|
||||
$menu .= $this->buildMenu('story', 'close', $params . "&from=&storyType=$story->type", $story, $type, '', '', 'iframe', true);
|
||||
$menu .= $this->buildMenu('story', 'edit', $params . "&from=$story->from&storyType=$story->type", $story, $type, '', '', 'showinonlybody');
|
||||
|
||||
$tab = $this->app->tab == 'project' ? 'project' : 'qa';
|
||||
if($story->type != 'requirement' and $this->config->vision != 'lite') $menu .= $this->buildMenu('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=¶m=0&$params", $story, $type, 'sitemap', '', 'showinonlybody', false, "data-app='$tab'");
|
||||
|
||||
@@ -4181,7 +4298,11 @@ class storyModel extends model
|
||||
if($type == 'view')
|
||||
{
|
||||
$menu .= $this->buildMenu('story', 'change', $params . "&from=&storyType=$story->type", $story, $type, 'alter', '', 'showinonlybody');
|
||||
$menu .= $this->buildMenu('story', 'recall', $params . "&from=view&storyType=$story->type", $story, $type, 'undo', '', 'showinonlybody');
|
||||
if($story->status == 'draft') $menu .= $this->buildMenu('story', 'submitReview', $params, $story, $type, 'sub-review', '', 'showinonlybody iframe', true, "data-width='50%'");
|
||||
|
||||
$title = $story->status == 'changing' ? $this->lang->story->recallChange : $this->lang->story->recall;
|
||||
$menu .= $this->buildMenu('story', 'recall', $params . "&from=view&confirm=no&storyType=$story->type", $story, $type, 'undo', 'hiddenwin', 'showinonlybody', false, '', $title);
|
||||
|
||||
$menu .= $this->buildMenu('story', 'review', $params . "&from=product&storyType=$story->type", $story, $type, 'search', '', 'showinonlybody');
|
||||
|
||||
if(!isonlybody()) $menu .= $this->buildMenu('story', 'batchCreate', "productID=$story->product&branch=$story->branch&moduleID=$story->module&$params&executionID=0&plan=0&storyType=story", $story, $type, 'split', '', 'divideStory', true, "data-toggle='modal' data-type='iframe' data-width='95%'", $this->lang->story->subdivide);
|
||||
@@ -4243,14 +4364,14 @@ class storyModel extends model
|
||||
|
||||
if(common::hasPriv('story', 'review'))
|
||||
{
|
||||
$reviewDisabled = in_array($this->app->user->account, $story->notReview) and ($story->status == 'draft' or $story->status == 'changed') ? '' : 'disabled';
|
||||
$reviewDisabled = in_array($this->app->user->account, $story->notReview) and ($story->status == 'draft' or $story->status == 'changing') ? '' : 'disabled';
|
||||
$story->from = 'execution';
|
||||
$menu .= common::printIcon('story', 'review', "story={$story->id}&from=story", $story, 'list', 'search', '', $reviewDisabled, false, "data-group=execution");
|
||||
}
|
||||
|
||||
if(common::hasPriv('story', 'recall'))
|
||||
{
|
||||
$recallDisabled = empty($story->reviewedBy) and strpos('draft,changed', $story->status) !== false and !empty($story->reviewer) ? '' : 'disabled';
|
||||
$recallDisabled = empty($story->reviewedBy) and strpos('draft,changing', $story->status) !== false and !empty($story->reviewer) ? '' : 'disabled';
|
||||
$menu .= common::printIcon('story', 'recall', "story={$story->id}", $story, 'list', 'undo', 'hiddenwin', $recallDisabled, '', '', $this->lang->story->recall);
|
||||
}
|
||||
|
||||
@@ -5425,23 +5546,32 @@ class storyModel extends model
|
||||
public function setStatusByReviewRules($reviewerList)
|
||||
{
|
||||
$status = '';
|
||||
$results = '';
|
||||
$passCount = 0;
|
||||
$rejectCount = 0;
|
||||
$reviewRule = $this->config->story->reviewRules;
|
||||
foreach($reviewerList as $reviewer => $reviewResult)
|
||||
{
|
||||
if($reviewResult == 'clarify') return 'draft';
|
||||
|
||||
$passCount = $reviewResult == 'pass' ? $passCount + 1 : $passCount;
|
||||
$rejectCount = $reviewResult == 'reject' ? $rejectCount + 1 : $rejectCount;
|
||||
|
||||
$results .= $reviewResult . ',';
|
||||
}
|
||||
|
||||
if($reviewRule == 'allpass')
|
||||
{
|
||||
if(strpos($results, 'reject') !== false) return 'closed';
|
||||
|
||||
if($passCount == count($reviewerList)) $status = 'active';
|
||||
if($rejectCount == count($reviewerList)) $status = 'closed';
|
||||
}
|
||||
|
||||
if($reviewRule == 'halfpass')
|
||||
{
|
||||
if($rejectCount == floor(count($revireList) / 2)) return 'closed';
|
||||
|
||||
if($passCount >= floor(count($reviewerList) / 2) + 1) $status = 'active';
|
||||
if($rejectCount >= floor(count($reviewerList) / 2) + 1) $status = 'closed';
|
||||
}
|
||||
@@ -5478,9 +5608,10 @@ class storyModel extends model
|
||||
|
||||
if($result != 'revert')
|
||||
{
|
||||
if($story->status == 'closed') $this->action->create('story', $story->id, 'ReviewRejected');
|
||||
$isChanged = $story->changedBy ? true : false;
|
||||
if($story->status == 'closed') $this->action->create('story', $story->id, 'ReviewRejected', '', $isChanged ? 'changing' : 'draft');
|
||||
if($story->status == 'active') $this->action->create('story', $story->id, 'ReviewPassed');
|
||||
if(!array_diff(array_keys($reviewers), $reviewedBy) and ($story->status == 'draft' or $story->status == 'changed')) $this->action->create('story', $story->id, 'ReviewClarified');
|
||||
if(!array_diff(array_keys($reviewers), $reviewedBy) and ($story->status == 'draft' or $story->status == 'changing')) $this->action->create('story', $story->id, 'ReviewClarified');
|
||||
}
|
||||
|
||||
return $actionID;
|
||||
@@ -5505,7 +5636,12 @@ class storyModel extends model
|
||||
$reviewedBy = explode(',', trim($story->reviewedBy, ','));
|
||||
if(!array_diff(array_keys($reviewerList), $reviewedBy))
|
||||
{
|
||||
$status = $this->post->result == 'revert' ? 'active' : $this->setStatusByReviewRules($reviewerList);
|
||||
$status = $this->post->result == 'revert' ? 'active' : $this->setStatusByReviewRules($reviewerList);
|
||||
|
||||
/* When the review result of the changed story is clarify, the status should be changing. */
|
||||
$isChanged = $oldStory->changedBy ? true : false;
|
||||
$status = ($isChanged and $status == 'draft') ? 'changing' : $status;
|
||||
|
||||
$story->status = $status ? $status : $oldStory->status;
|
||||
if($story->status == 'closed')
|
||||
{
|
||||
@@ -5534,12 +5670,14 @@ class storyModel extends model
|
||||
*/
|
||||
public function superReview($storyID, $oldStory, $story, $result = '', $reason = '')
|
||||
{
|
||||
$now = helper::now();
|
||||
$status = '';
|
||||
$result = isset($_POST['result']) ? $this->post->result : $result;
|
||||
if(empty($result)) return $story;
|
||||
|
||||
$now = helper::now();
|
||||
$status = $oldStory->status;
|
||||
if(strpos('revert,pass', $result) !== false) $status = 'active';
|
||||
if($result == 'reject') $status = 'closed';
|
||||
if($result == 'clarify' or empty($status)) $status = $oldStory->status;
|
||||
if($result == 'clarify') $status = 'draft';
|
||||
|
||||
$story->status = $status;
|
||||
|
||||
@@ -5779,6 +5917,30 @@ class storyModel extends model
|
||||
return $stories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the story status after activation.
|
||||
*
|
||||
* @param int $storyID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function getActivateStatus($storyID)
|
||||
{
|
||||
$status = 'active';
|
||||
$lastRecord = $this->dao->select('action,extra')->from(TABLE_ACTION)
|
||||
->where('objectType')->eq('story')
|
||||
->andWhere('objectID')->eq($storyID)
|
||||
->orderBy('id_desc')
|
||||
->fetch();
|
||||
|
||||
$lastAction = $lastRecord->action;
|
||||
$preStatus = $lastRecord->extra;
|
||||
if(strpos($preStatus, '|') !== false) $preStatus = substr($preStatus, strpos($preStatus, '|') + 1);
|
||||
if(strpos('closed,reviewrejected', $lastAction) !== false) $status = $preStatus;
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get reviewer pairs for story .
|
||||
*
|
||||
|
||||
@@ -28,16 +28,6 @@
|
||||
<th class='w-80px'><?php echo $lang->story->assignedTo;?></th>
|
||||
<td class='w-p45'><?php echo html::select('assignedTo', $users, $story->closedBy, 'class="form-control chosen"');?></td><td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->status;?></th>
|
||||
<td>
|
||||
<?php
|
||||
unset($lang->story->statusList['']);
|
||||
unset($lang->story->statusList['closed']);
|
||||
echo html::select('status', $lang->story->statusList, 'active', 'class="form-control chosen"');
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php $this->printExtendFields($story, 'table');?>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->comment;?></th>
|
||||
|
||||
@@ -131,7 +131,8 @@
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="<?php echo count($visibleFields) + 3?>" class="text-center form-actions">
|
||||
<?php echo html::submitButton($lang->save);?>
|
||||
<?php echo html::commonButton($lang->story->saveDraft, "id='saveDraftButton'", 'btn btn-secondary btn-wide');?>
|
||||
<?php echo html::commonButton($lang->save, "id='saveButton'", 'btn btn-primary btn-wide');?>
|
||||
<?php echo html::backButton();?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
<small><?php echo $lang->arrow . ' ' . $lang->story->change;?></small>
|
||||
</h2>
|
||||
</div>
|
||||
<form class="main-form" method='post' enctype='multipart/form-data' target='hiddenwin'>
|
||||
<form class="main-form" method='post' enctype='multipart/form-data' target='hiddenwin' id='dataform'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th class='w-80px'><?php echo $lang->story->reviewedBy;?></th>
|
||||
<td colspan='2' id='reviewerBox'>
|
||||
<td id='reviewerBox'>
|
||||
<div class="input-group">
|
||||
<?php echo html::select('reviewer[]', $productReviewers, $reviewer, "class='form-control picker-select' multiple" . ($this->story->checkForceReview() ? ' required' : ''));?>
|
||||
<?php if(!$this->story->checkForceReview()):?>
|
||||
@@ -34,12 +34,6 @@
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</td>
|
||||
<td colspan='1' id='assignedToBox' class='hidden'>
|
||||
<div class='input-group'>
|
||||
<div class="input-group-addon"><?php echo $lang->story->assignedTo;?></div>
|
||||
<?php echo html::select('assignedTo', $users, '', "class='form-control picker-select'");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='hide'>
|
||||
<th><?php echo $lang->story->status;?></th>
|
||||
@@ -48,7 +42,7 @@
|
||||
<?php $this->printExtendFields($story, 'table');?>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->title;?></th>
|
||||
<td colspan='2'>
|
||||
<td>
|
||||
<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>
|
||||
<ul class="dropdown-menu clearfix">
|
||||
@@ -61,33 +55,34 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->spec;?></th>
|
||||
<td colspan='2'><?php echo html::textarea('spec', htmlSpecialString($story->spec), 'rows=8 class="form-control"');?><span class='help-block'><?php echo $lang->story->specTemplate;?></span></td>
|
||||
<td><?php echo html::textarea('spec', htmlSpecialString($story->spec), 'rows=8 class="form-control"');?><span class='help-block'><?php echo $lang->story->specTemplate;?></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->verify;?></th>
|
||||
<td colspan='2'><?php echo html::textarea('verify', htmlSpecialString($story->verify), 'rows=6 class="form-control"');?></td>
|
||||
<td><?php echo html::textarea('verify', htmlSpecialString($story->verify), 'rows=6 class="form-control"');?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->comment;?></th>
|
||||
<td colspan='2'><?php echo html::textarea('comment', '', 'rows=5 class="form-control"');?></td>
|
||||
<td><?php echo html::textarea('comment', '', 'rows=5 class="form-control"');?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->attatch;?></th>
|
||||
<td colspan='2'>
|
||||
<td>
|
||||
<?php echo $this->fetch('file', 'printFiles', array('files' => $files, 'fieldset' => 'true', 'object' => $story, 'method' => 'change'));?>
|
||||
<?php echo $this->fetch('file', 'buildform');?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->checkAffection;?></th>
|
||||
<td colspan='2'><?php include './affected.html.php';?></td>
|
||||
<td><?php include './affected.html.php';?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan='2' class='text-center form-actions'>
|
||||
<td class='text-center form-actions'>
|
||||
<?php
|
||||
echo html::hidden('lastEditedDate', $story->lastEditedDate);
|
||||
echo html::submitButton();
|
||||
echo html::commonButton($lang->save, "id='saveButton'", 'btn btn-primary btn-wide');
|
||||
echo html::commonButton($lang->story->doNotSubmit, "id='saveDraftButton'", 'btn btn-secondary btn-wide');
|
||||
if(!isonlybody()) echo html::backButton();
|
||||
?>
|
||||
</td>
|
||||
@@ -107,4 +102,5 @@
|
||||
<?php js::set('changed', 0);?>
|
||||
<?php js::set('storyType', $story->type);?>
|
||||
<?php js::set('rawModule', $this->app->rawModule);?>
|
||||
<?php js::set('page', $this->app->rawMethod);?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -34,6 +34,14 @@ foreach(explode(',', $config->story->create->requiredFields) as $field)
|
||||
<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 class="pull-right btn-toolbar">
|
||||
<?php $customLink = $this->createLink('custom', 'ajaxSaveCustomFields', 'module=story§ion=custom&key=createFields')?>
|
||||
<?php include '../../common/view/customfield.html.php';?>
|
||||
@@ -88,64 +96,24 @@ foreach(explode(',', $config->story->create->requiredFields) as $field)
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="2" class="sourceTd <?php echo $hiddenSource?> sourceBox">
|
||||
<div class="input-group">
|
||||
<div class="input-group" style='display: flex;'>
|
||||
<div class='source'>
|
||||
<div class="input-group-addon" style="min-width: 77px;"><?php echo $lang->story->source;?></div>
|
||||
<?php echo html::select('source', $lang->story->sourceList, $source, "class='form-control chosen'");?>
|
||||
</div>
|
||||
<div class='sourceNote'>
|
||||
<div class='input-group-addon' id='sourceNoteBox'><?php echo $lang->story->sourceNote;?></div>
|
||||
<?php $sourceNoteWidth = isonlybody() ? "style='width: 89px;'" : ""?>
|
||||
<?php echo html::input('sourceNote', $sourceNote, "class='form-control' $sourceNoteWidth");?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->reviewedBy;?></th>
|
||||
<td colspan='<?php echo $type == 'story' ? 4 : 2;?>' id='reviewerBox'>
|
||||
<div class="table-row">
|
||||
<?php if(!$this->story->checkForceReview()):?>
|
||||
<div class="table-col">
|
||||
<?php echo html::select('reviewer[]', $reviewers, empty($needReview) ? $product->PO : '', "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 $needReview;?>/>
|
||||
<label for='needNotReview'><?php echo $lang->story->needNotReview;?></label>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div class="table-col">
|
||||
<?php echo html::select('reviewer[]', $reviewers, empty($needReview) ? $product->PO : '', "class='form-control picker-select' multiple required");?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</td>
|
||||
<td colspan='<?php echo $type == 'story' ? 2 : 1;?>' id='assignedToBox' class='hidden'>
|
||||
<td colspan='<?php echo $type == 'story' ? 2 : 1;?>' id='assignedToBox'>
|
||||
<div class='input-group'>
|
||||
<div class="input-group-addon assignedTo"><?php echo $lang->story->assignedTo;?></div>
|
||||
<?php echo html::select('assignedTo', $users, '', "class='form-control picker-select'");?>
|
||||
</div>
|
||||
</td>
|
||||
<?php if($type == 'requirement'):?>
|
||||
<td colspan="2" class="sourceTd <?php echo $hiddenSource?> sourceBox">
|
||||
</tr>
|
||||
<tr class='sourceBox <?php echo $hiddenSource;?>'>
|
||||
<th><?php echo $lang->story->source;?></th>
|
||||
<td colspan='2'>
|
||||
<?php echo html::select('source', $lang->story->sourceList, $source, "class='form-control chosen'");?>
|
||||
</td>
|
||||
<td colspan="2" class="sourceTd">
|
||||
<div class="input-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon" style="min-width: 77px;"><?php echo $lang->story->source;?></div>
|
||||
<?php echo html::select('source', $lang->story->sourceList, $source, "class='form-control chosen'");?>
|
||||
<span class='input-group-addon' id="sourceNoteBox"><?php echo $lang->story->sourceNote;?></span>
|
||||
<?php echo html::input('sourceNote', $sourceNote, "class='form-control' style='width:140px;'");?>
|
||||
</div>
|
||||
<div class='input-group-addon' id='sourceNoteBox'><?php echo $lang->story->sourceNote;?></div>
|
||||
<?php echo html::input('sourceNote', $sourceNote, "class='form-control'");?>
|
||||
</div>
|
||||
</td>
|
||||
<?php else:?>
|
||||
<td colspan="2" id='feedbackBox' class='hidden'>
|
||||
<div class="input-group">
|
||||
<div class="input-group">
|
||||
@@ -156,7 +124,41 @@ foreach(explode(',', $config->story->create->requiredFields) as $field)
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
</tr>
|
||||
<?php else:?>
|
||||
<tr>
|
||||
<th class='planTh'><?php echo $lang->story->assignedTo;?></th>
|
||||
<td colspan='2' id='assignedToBox'>
|
||||
<?php echo html::select('assignedTo', $users, '', "class='form-control picker-select'");?>
|
||||
</td>
|
||||
<td colspan="2" class="sourceTd <?php echo $hiddenSource?> sourceBox">
|
||||
<div class="input-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon" style="min-width: 77px;"><?php echo $lang->story->source;?></div>
|
||||
<?php echo html::select('source', $lang->story->sourceList, $source, "class='form-control chosen'");?>
|
||||
<span class='input-group-addon' id="sourceNoteBox"><?php echo $lang->story->sourceNote;?></span>
|
||||
<?php echo html::input('sourceNote', $sourceNote, "class='form-control' style='width:140px;'");?>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->reviewedBy;?></th>
|
||||
<td colspan='2' id='reviewerBox'>
|
||||
<div class="table-row">
|
||||
<?php if(!$this->story->checkForceReview()):?>
|
||||
<div class="table-col">
|
||||
<?php echo html::select('reviewer[]', $reviewers, empty($needReview) ? $product->PO : '', "class='form-control picker-select' multiple");?>
|
||||
</div>
|
||||
<?php echo html::hidden('needNotReview', 1);?>
|
||||
<?php else:?>
|
||||
<div class="table-col">
|
||||
<?php echo html::select('reviewer[]', $reviewers, empty($needReview) ? $product->PO : '', "class='form-control picker-select' multiple required");?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php if($type == 'story'):?>
|
||||
<?php if($this->config->URAndSR):?>
|
||||
@@ -270,10 +272,6 @@ foreach(explode(',', $config->story->create->requiredFields) as $field)
|
||||
<th><?php echo $lang->story->verify;?></th>
|
||||
<td colspan="4"><?php echo html::textarea('verify', $verify, "rows='6' class='form-control kindeditor' hidefocus='true'");?></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>
|
||||
@@ -300,7 +298,9 @@ foreach(explode(',', $config->story->create->requiredFields) as $field)
|
||||
<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::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 $gobackLink ? html::a($gobackLink, $lang->goback, '', 'class="btn btn-wide"') : html::backButton('', $source == 'bug' ? 'data-app=qa' : '');?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
<?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 +35,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,16 +44,46 @@
|
||||
</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 strpos('draft,changing', $story->status) !== false ? html::textarea('spec', htmlSpecialString($story->spec), "rows='5' class='form-control'") : $story->spec;?>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
<div class='detail'>
|
||||
<div class='detail-title'><?php echo $lang->story->verify;?></div>
|
||||
<div class='detail-content article-content'><?php echo $story->verify;?></div>
|
||||
<div class='detail-content article-content'>
|
||||
<?php echo strpos('draft,changing', $story->status) !== false ? html::textarea('verify', htmlSpecialString($story->verify), "rows='5' class='form-control'") : $story->verify;?>
|
||||
</div>
|
||||
</div>
|
||||
<?php $this->printExtendFields($story, 'div', 'position=left');?>
|
||||
<div class='detail'>
|
||||
@@ -64,7 +95,15 @@
|
||||
<div class='actions form-actions text-center'>
|
||||
<?php
|
||||
echo html::hidden('lastEditedDate', $story->lastEditedDate);
|
||||
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>
|
||||
@@ -153,7 +192,7 @@
|
||||
<?php echo html::hidden('status', $story->status);?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php if($story->status != 'draft' and $story->type == 'story'):?>
|
||||
<?php if(strpos('draft,changing', $story->status) !== false and $story->type == 'story'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->stage;?></th>
|
||||
<td>
|
||||
@@ -220,7 +259,7 @@
|
||||
<?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 picker-select" multiple')?></td>
|
||||
@@ -241,15 +280,14 @@
|
||||
|
||||
<?php $this->printExtendFields($story, 'div', 'position=right');?>
|
||||
|
||||
<?php if($story->status == 'closed'):?>
|
||||
<div class='detail'>
|
||||
<div class='detail-title'><?php echo $lang->story->legendMisc;?></div>
|
||||
<table class='table table-form'>
|
||||
<?php if($story->status == 'closed'):?>
|
||||
<tr id='duplicateStoryBox'>
|
||||
<th class='w-90px'><?php echo $lang->story->duplicateStory;?></th>
|
||||
<td><?php echo html::input('duplicateStory', $story->duplicateStory == 0 ? '' : $story->duplicateStory, "class='form-control'");?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr class='text-top'>
|
||||
<th class='thWidth'><?php echo $lang->story->linkStory;?></th>
|
||||
<td>
|
||||
@@ -280,6 +318,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
<th><?php echo $lang->story->reviewResult;?></th>
|
||||
<td class='required'><?php echo html::select('result', $lang->story->resultList, '', 'class="form-control chosen" onchange="switchShow(this.value)"');?></td><td></td>
|
||||
</tr>
|
||||
<tr id='assignedToBox' class='hide'>
|
||||
<tr id='assignedToBox' <?php echo $isLastOne ? '' : "class='hide'";?>>
|
||||
<th><?php echo $lang->story->assignedTo;?></th>
|
||||
<td><?php echo html::select('assignedTo', $users, '', "class='form-control picker-select'");?></td><td></td>
|
||||
<td><?php echo html::select('assignedTo', $users, $story->assignedTo, "class='form-control picker-select'");?></td><td></td>
|
||||
</tr>
|
||||
<tr id='rejectedReasonBox' class='hide'>
|
||||
<th><?php echo $lang->story->rejectedReason;?></th>
|
||||
@@ -55,12 +55,6 @@
|
||||
<th><?php echo $lang->story->childStories;?></th>
|
||||
<td><?php echo html::input('childStories', '', "class='form-control'");?></td><td></td>
|
||||
</tr>
|
||||
<?php if($story->status == 'changed' or ($story->status == 'draft' and $story->version > 1)):?>
|
||||
<tr id='preVersionBox' class='hide'>
|
||||
<th><?php echo $lang->story->preVersion;?></th>
|
||||
<td colspan='2'><?php echo html::radio('preVersion', array_combine(range($story->version - 1, 1), range($story->version - 1, 1)), $story->version - 1);?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr class='hide'>
|
||||
<th><?php echo $lang->story->status;?></th>
|
||||
<td><?php echo html::hidden('status', $story->status);?></td>
|
||||
@@ -90,4 +84,5 @@
|
||||
<?php js::set('storyType', $story->type);?>
|
||||
<?php js::set('rawModule', $this->app->rawModule);?>
|
||||
<?php js::set('isMultiple', count($reviewers) == 1 ? false : true);?>
|
||||
<?php js::set('isLastOne', $isLastOne);?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* The submit review file of story module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Qiyu Xie <xieqiyu@cnezsoft.com>
|
||||
* @package story
|
||||
* @version $Id: submitreview.html.php 935 2022-07-20 09:49:24Z $
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/kindeditor.html.php';?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2>
|
||||
<span class='label label-id'><?php echo $story->id;?></span>
|
||||
<?php echo isonlybody() ? ("<span title='$story->title'>" . $story->title . '</span>') : html::a($this->createLink('story', 'view', 'story=' . $story->id), $story->title);?>
|
||||
<?php if(!isonlybody()):?>
|
||||
<small> <?php echo $lang->arrow . $lang->story->submitReview;?></small>
|
||||
<?php endif;?>
|
||||
</h2>
|
||||
</div>
|
||||
<form method='post' target='hiddenwin'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th class='w-80px'><?php echo $lang->story->reviewedBy;?></th>
|
||||
<td colspan='2' id='reviewerBox' <?php if(!empty($story->reviewer)) echo "class='required'";?>>
|
||||
<div class="table-row">
|
||||
<?php if(!$this->story->checkForceReview()):?>
|
||||
<div class="table-col">
|
||||
<?php echo html::select('reviewer[]', $reviewers, $story->reviewer, "class='form-control picker-select' multiple");?>
|
||||
</div>
|
||||
<div class="table-col needNotReviewBox">
|
||||
<span class="input-group-addon">
|
||||
<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 else:?>
|
||||
<div class="table-col">
|
||||
<?php echo html::select('reviewer[]', $reviewers, $story->reviewer, "class='form-control picker-select' multiple required");?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='3' class='text-center form-actions'>
|
||||
<?php echo html::hidden('id', $story->id);?>
|
||||
<?php echo html::submitButton();?>
|
||||
<?php echo html::linkButton($lang->goback, $this->session->storyList, '', '', 'btn btn-wide');?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<hr class='small' />
|
||||
<?php include '../../common/view/action.html.php';?>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
+20
-18
@@ -98,24 +98,26 @@ class tutorialModel extends model
|
||||
{
|
||||
$product = $this->getProduct();
|
||||
$product->stories = array();
|
||||
$product->stories[0] = '';
|
||||
$product->stories[1] = 'draft';
|
||||
$product->stories[2] = 'active';
|
||||
$product->stories[3] = 'closed';
|
||||
$product->stories[4] = 'changed';
|
||||
$product->stories[''] = 0;
|
||||
$product->stories['draft'] = 0;
|
||||
$product->stories['active'] = 0;
|
||||
$product->stories['closed'] = 0;
|
||||
$product->stories['changed'] = 0;
|
||||
$product->requirements = $product->stories;
|
||||
$product->plans = 0;
|
||||
$product->releases = 0;
|
||||
$product->bugs = 0;
|
||||
$product->unResolved = 0;
|
||||
$product->closedBugs = 0;
|
||||
$product->fixedBugs = 0;
|
||||
$product->assignToNull = 0;
|
||||
$product->stories[0] = '';
|
||||
$product->stories[1] = 'draft';
|
||||
$product->stories[2] = 'reviewing';
|
||||
$product->stories[3] = 'active';
|
||||
$product->stories[4] = 'closed';
|
||||
$product->stories[5] = 'changing';
|
||||
$product->stories[''] = 0;
|
||||
$product->stories['draft'] = 0;
|
||||
$product->stories['reviewing'] = 0;
|
||||
$product->stories['active'] = 0;
|
||||
$product->stories['closed'] = 0;
|
||||
$product->stories['changing'] = 0;
|
||||
$product->requirements = $product->stories;
|
||||
$product->plans = 0;
|
||||
$product->releases = 0;
|
||||
$product->bugs = 0;
|
||||
$product->unResolved = 0;
|
||||
$product->closedBugs = 0;
|
||||
$product->fixedBugs = 0;
|
||||
$product->assignToNull = 0;
|
||||
|
||||
$productStat[$product->program][$product->line]['products'][$product->id] = $product;
|
||||
return $productStat;
|
||||
|
||||
@@ -547,6 +547,9 @@ class upgradeModel extends model
|
||||
$this->updateOSAndBrowserOfBug();
|
||||
$this->addURPriv();
|
||||
break;
|
||||
case '17_5':
|
||||
$this->updateStoryStatus();
|
||||
break;
|
||||
}
|
||||
|
||||
$this->deletePatch();
|
||||
@@ -7051,6 +7054,23 @@ class upgradeModel extends model
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update story status.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function updateStoryStatus()
|
||||
{
|
||||
/* After cancel the review of changed story, the story status should be 'changing'. */
|
||||
$this->dao->update(TABLE_STORY)->set('status')->eq('changing')->where('status')->eq('draft')->andWhere('version')->gt(1)->exec();
|
||||
|
||||
/* Other stories in draft status should be 'reviewing'. */
|
||||
$this->dao->update(TABLE_STORY)->set('status')->eq('reviewing')->where('status')->eq('draft')->exec();
|
||||
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change FULLTEXT index for searchindex table.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user