Merge branch 'master' of https://gitlab.zcorp.cc/easycorp/zentaopms into importExport

This commit is contained in:
tanghucheng
2022-07-13 14:38:40 +08:00
45 changed files with 4191 additions and 56 deletions
+1 -1
View File
@@ -1 +1 @@
17.2
17.3
+1 -1
View File
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
if(!function_exists('getWebRoot')){function getWebRoot(){}}
/* 基本设置。Basic settings. */
$config->version = '17.2'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->version = '17.3'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->liteVersion = '1.2'; // 迅捷版版本。 The version of Lite.
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
File diff suppressed because it is too large Load Diff
+93
View File
@@ -1,3 +1,96 @@
2022-07-13 17.3
完成的需求
14130 点击按钮执行升级后禁用升级按钮
14578 总计消耗不为0时再次点击完成任务后消耗工时可以填写为0
15349 产品模块的维护增加历史记录
26444 重新激活父任务时需要同步更新子任务的历史记录
27723 年度总结按部门查看增加权限控制
30114 实现禅道中累积流图的帮助功能
30121 实现禅道执行视图下的需求累积流图
30128 实现禅道执行视图下的任务累积流图
30190 创建看板时增加复制看板功能
31342 批量创建任务表单的右侧增加添加和删除行的操作
31746 Scrum看板中任务看板按需求分组时需求以卡片方式展示
31848 删除测试测试单列表中操作按钮中间的小竖线
32329 跨应用跳转页面时直接展示跳转后的页面
32584 瀑布项目阶段列表中阶段名称前增加展开、收起按钮
32834 任务创建页面修改自定义表单后不影响已录入内容
32994 时间设置错误提示删除日历自动展开效果
33003 非所有标签的列表内容为空时,删除新建操作
33085 需求提交页面修改自定义表单后不影响已录入内容
33132 修改干系人新增页面中用户字段未定义提示
33168 复制执行页面增加项目的选择菜单
33170 BUG提交页面修改自定义表单后不影响已录入内容
33171 用例提交页面修改自定义表单后不影响已录入内容
33180 批量提需求表单的右侧增加添加和删除行的操作
33181 批量提Bug表单的右侧增加添加和删除行的操作
33182 批量建用例表单的右侧增加添加和删除行的操作
33307 加大bug提交页面中操作系统输入框的宽度
33308 加大bug提交页面中“关键词“字段标题框宽度
33415 用例库中的用例可以多次导入到同一个产品的不同模块
33418 瀑布项目阶段设置页面里程碑字段居中显示
33419 瀑布项目阶段设置页面中操作字段居中显示
33438 缩短组织下团队列表页面姓名跟用户名字段的间距
33445 bug提交页面中刷新按钮改为图标显示
33446 列表中日期没有定义时展示为空
33448 缩小bug编辑页面中标题输入框宽度
33516 后台全局设置中文档模板列表的的删除按钮改为垃圾桶样式
33519 后台自定义页面修改提示语样式
33540 优化搜索条件保存按钮样式
33542 用例列表页面的执行时间格式调整
33547 项目测试单列表的报告列表按钮修改
33607 项目集列表中对展开和收起的状态做记录
33617 瀑布项目阶段列表增加显示任务设置
33673 我参与标签中能显示我负责和我在团队中的空间和看板
33705 项目中测试的Bug列表增加产品模块功能
33706 执行中测试的Bug列表增加产品模块功能
33707 执行中测试的用例列表增加产品模块功能
33775 详情页面中附件增加预览和下载按钮
33777 研发需求变更页面增加附件编辑操作
33782 地盘仪表盘待处理区块对齐调整
33807 产品矩阵列表居左显示
33879 阶段列表中展示任务列表
33896 实现禅道执行视图下的Bug累积流图
33939 后台通知设置页面中“评论”字段修改为“备注”
33953 项目创建页面中,关联产品下拉框增加不可点击状态
33970 测试仪表盘测试统计区块中统计字体颜色调整
33972 增加国际版地盘任务列表页面截止日期字段的宽度
33973 计划详情列表中返回路径优化
33983 我的地盘日程中右侧任务和软需切换样式调整
33986 产品发布创建页面里程碑选中状态修改
33987 执行任务列表预计、消耗、剩余、进度字段居右显示
33988 执行任务列表"截止"字段居左显示
33999 统计产品页面删除“筛选条件"字段
34028 后台二次开发API列表页面表头字段加粗
34029 执行任务列表页面“完成者”字段内容过多时省略显示
34036 专业研发看板项目的执行模块添加累积流图入口
34038 累积流图中增加更新按钮
34048 累积流图页增加下拉框支持切换类型
34049 累积流图展示平均周期时间和吞吐率
34050 累积流图中增加悬浮样式
34138 scrum看板页面卡片局部刷新
34139 通用看板页面卡片局部刷新
34140 看板项目专业研发看板编辑区域后自动刷新
34142 专业研发看板页面卡片局部刷新
34266 修改产品计划详情页面提研发需求按钮的下拉菜单为右对齐
34349 国际版地盘仪表盘添加区块弹窗中待办和待处理的英文修改
34350 国际版中编辑和详情页面附件重命名的英文修改为Rename
34354 修改产品研发需求提交页面中附件操作按钮颜色
34367 累积流图增加隐藏周末按钮
34387 需求提交页面产品分支输入框显示完整
34497 邮箱修改密码优化格式校验提示语
34580 任务详情编辑页面中,团队设置弹窗增加关闭按钮
34609 修改产品分支合并的提示样式
34610 当所有标签的列表内容均为空时,增加新建按钮
34611 修改后台系统安全设置页面的提示语样式
修复的Bug
23123 项目/执行的Bug页左上角下拉组件未显示多分支产品的分支下拉
23827 批量编辑项目时,提示文案不清晰
24923 英文下项目集下新增干系人页面字段名称换行
24976 内禅3.3版本需求列表需求名称显示3个点
24981 隐藏来源没有同步隐藏其关联的文本框
25070 后台-自定义-必填项-任务-建任务页面设置最初预计为必填项,创建多人任务团队成员预计工时为空也可以保存
2022-06-29 17.2
完成的需求
12709 创建某一类型的待办时,若无指派给我的内容列表提示用户
+31 -2
View File
@@ -12,10 +12,11 @@ public function __construct($appName = '')
* @param int $browseType
* @param int $groupBy
* @param string $searchValue
* @param string $orderBy
* @access public
* @return array
*/
public function getKanban4Group($executionID, $browseType, $groupBy, $searchValue = '')
public function getKanban4Group($executionID, $browseType, $groupBy, $searchValue = '', $orderBy = 'pri_asc')
{
/* Get card data. */
$cardList = array();
@@ -23,7 +24,8 @@ public function getKanban4Group($executionID, $browseType, $groupBy, $searchValu
if($browseType == 'bug') $cardList = $this->loadModel('bug')->getExecutionBugs($executionID);
if($browseType == 'task') $cardList = $this->loadModel('execution')->getKanbanTasks($executionID, "id");
$lanes = $this->getLanes4Group($executionID, $browseType, $groupBy, $cardList);
if($groupBy == 'story' and $browseType == 'task' and !isset($this->lang->kanban->orderList[$orderBy])) $orderBy = 'pri_asc';
$lanes = $this->getLanes4Group($executionID, $browseType, $groupBy, $cardList, $orderBy);
if(empty($lanes)) return array();
$execution = $this->loadModel('execution')->getByID($executionID);
@@ -70,6 +72,33 @@ public function getKanban4Group($executionID, $browseType, $groupBy, $searchValu
$laneData['type'] = $browseType;
$laneData['defaultCardType'] = $browseType;
if($browseType == 'task' and $groupBy == 'story')
{
$columnData[0]['id'] = 0;
$columnData[0]['type'] = 'story';
$columnData[0]['name'] = zget($this->lang->kanban->orderList, $orderBy, '');
$columnData[0]['color'] = '#333';
$columnData[0]['limit'] = '-1';
$columnData[0]['laneType'] = $browseType;
$columnData[0]['asParent'] = false;
$columnData[0]['parentType'] = '';
$columnData[0]['actions'] = array();
if(empty($searchValue) or strpos($lane->name, $searchValue) !== false)
{
$cardData = array();
$cardData['id'] = $laneID;
$cardData['title'] = $lane->name;
$cardData['order'] = 1;
$cardData['pri'] = $lane->pri;
$cardData['estimate'] = '';
$cardData['assignedTo'] = $lane->assignedTo;
$cardData['deadline'] = '';
$cardData['severity'] = '';
$laneData['cards']['story'][] = $cardData;
}
}
/* Construct kanban column data. */
foreach($columns as $column)
{
@@ -21,6 +21,9 @@ class project extends control
if($this->execution->isClickable($kanban, 'delete')) $executionActions[$kanbanID][] = 'delete';
}
$allExecution = $this->execution->getList($projectID, 'all', 'all');
$this->view->allExecutionsNum = count($allExecution);
$this->view->title = $this->lang->project->kanban;
$this->view->kanbanList = array_values($kanbanList);
@@ -30,7 +30,7 @@
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->execution->noExecution;?></span>
<?php if(common::hasPriv('execution', 'create') and $status == "all"):?>
<?php if(common::hasPriv('execution', 'create') and empty($allExecutionsNum)):?>
<?php echo html::a($this->createLink('execution', 'create', "projectID=$projectID"), "<i class='icon icon-plus'></i> " . $lang->project->createKanban, '', "class='btn btn-info' data-app='project'");?>
<?php endif;?>
</p>
+9 -2
View File
@@ -966,8 +966,9 @@ class baseJS
{
$cancleAction = "$cancleTarget.location = '$cancleURL';";
}
$js .= <<<EOT
if(strpos($_SERVER['HTTP_USER_AGENT'], 'xuanxuan') === false)
{
$js .= <<<EOT
if(confirm("$message"))
{
$confirmAction
@@ -977,6 +978,12 @@ else
$cancleAction
}
EOT;
}
else
{
$js .= $confirmAction;
}
$js .= self::end();
return $js;
}
+1 -1
View File
@@ -73,7 +73,7 @@ class actionModel extends model
if($this->post->uid) $this->file->updateObjectID($this->post->uid, $objectID, $objectType);
/* Call the message notification function. */
$this->loadModel('message')->send(strtolower($objectType), $objectID, $actionType, $actionID, $actor);
$this->loadModel('message')->send(strtolower($objectType), $objectID, $actionType, $actionID, $actor, $extra);
/* Add index for global search. */
$this->saveIndex($objectType, $objectID, $actionType);
+1 -1
View File
@@ -425,6 +425,7 @@ $lang->bug->placeholder->newBuildName = 'Nom Nouv Build';
$lang->bug->featureBar['browse']['all'] = $lang->bug->allBugs;
$lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed;
$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
$lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
@@ -432,7 +433,6 @@ $lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
$lang->bug->moreSelects['assignedbyme'] = $lang->bug->assignedByMe;
$lang->bug->moreSelects['openedbyme'] = $lang->bug->openedByMe;
$lang->bug->moreSelects['unconfirmed'] = $lang->bug->unconfirmed;
$lang->bug->moreSelects['assigntonull'] = $lang->bug->assignToNull;
$lang->bug->moreSelects['longlifebugs'] = $lang->bug->longLifeBugs;
-2
View File
@@ -811,8 +811,6 @@ function tips()
function renderHeaderCol($column, column, $header, kanbanData)
{
if(groupBy == 'story' && column.type == 'story') return;
console.log(groupBy);
console.log(column.type);
/* Render group header. */
var privs = kanbanData.actions;
var columnPrivs = kanbanData.columns[0].actions;
+1 -2
View File
@@ -434,8 +434,7 @@ $lang->execution->charts->cfd = new stdclass();
$lang->execution->charts->cfd->cfdTip = "<p>
1. The CFDCumulative Flow Diagramreflects the trend of accumulated workload at each stage over time.<br>
2. The horizontal axis represents the date, and the vertical axis represents the number of work items.<br>
3. To learn about the team's delivery, you can calculate the WIP quantity, delivery rate and average lead time through the CFD.
<p>";
3. To learn about the team's delivery, you can calculate the WIP quantity, delivery rate and average lead time through the CFD. <p>";
$lang->execution->charts->cfd->cycleTime = 'Average cycle time';
$lang->execution->charts->cfd->cycleTimeTip = 'Average cycle time of each card from development start to completion';
$lang->execution->charts->cfd->throughput = 'Throughput Rate';
+1 -2
View File
@@ -434,8 +434,7 @@ $lang->execution->charts->cfd = new stdclass();
$lang->execution->charts->cfd->cfdTip = "<p>
1. The CFDCumulative Flow Diagramreflects the trend of accumulated workload at each stage over time.<br>
2. The horizontal axis represents the date, and the vertical axis represents the number of work items.<br>
3. To learn about the team's delivery, you can calculate the WIP quantity, delivery rate and average lead time through the CFD.
<p>";
3. To learn about the team's delivery, you can calculate the WIP quantity, delivery rate and average lead time through the CFD. <p>";
$lang->execution->charts->cfd->cycleTime = 'Average cycle time';
$lang->execution->charts->cfd->cycleTimeTip = 'Average cycle time of each card from development start to completion';
$lang->execution->charts->cfd->throughput = 'Throughput Rate';
+3 -3
View File
@@ -300,10 +300,7 @@ $lang->execution->statusSelects[''] = 'Plus...';
$lang->execution->statusSelects['wait'] = 'En Attente';
$lang->execution->statusSelects['doing'] = 'En Cours';
$lang->execution->statusSelects['undone'] = 'Non terminées';
$lang->execution->statusSelects['myinvolved'] = $lang->execution->myInvolved;
$lang->execution->statusSelects['finishedbyme'] = 'Terminées par moi';
$lang->execution->statusSelects['assignedbyme'] = $lang->execution->assignedByMe;
$lang->execution->statusSelects['needconfirm'] = 'A confirmer';
$lang->execution->statusSelects['done'] = 'Faites';
$lang->execution->statusSelects['closed'] = 'Fermées';
$lang->execution->statusSelects['cancel'] = 'Annulées';
@@ -503,6 +500,9 @@ $lang->execution->typeList['kanban'] = 'Kanban';
$lang->execution->featureBar['task']['all'] = $lang->execution->allTasks;
$lang->execution->featureBar['task']['unclosed'] = $lang->execution->unclosed;
$lang->execution->featureBar['task']['assignedtome'] = $lang->execution->assignedToMe;
$lang->execution->featureBar['task']['myinvolved'] = $lang->execution->myInvolved;
$lang->execution->featureBar['task']['assignedbyme'] = $lang->execution->assignedByMe;
$lang->execution->featureBar['task']['needconfirm'] = 'Changed';
$lang->execution->featureBar['task']['status'] = $lang->execution->statusSelects[''];
$lang->execution->featureBar['all']['all'] = $lang->execution->all;
+3 -1
View File
@@ -59,10 +59,12 @@ class messageModel extends model
* @param int $objectID
* @param string $actionType
* @param int $actionID
* @param string $actor
* @param string $extra
* @access public
* @return void
*/
public function send($objectType, $objectID, $actionType, $actionID, $actor = '')
public function send($objectType, $objectID, $actionType, $actionID, $actor = '', $extra = '')
{
$objectType = strtolower($objectType);
$messageSetting = $this->config->message->setting;
+2
View File
@@ -103,6 +103,7 @@ $lang->misc->feature->themeDesc = '<p>ZenTao 15.0+ a new "Youth Blue" theme
$lang->misc->feature->visionsDesc = "<p>The concept of interface has been added since 16.5. Users can deal with R & D affairs in <span style='color: #0c60e1'>[R&D]</span> and daily office affairs in <span style='color: #0c60e1'>[Lite]</span>.</p><p>You can view the current interface on the avatar, and click the name of the interface to view and switch other interfaces.</p>";
$lang->misc->feature->visionsImage = 'theme/default/images/main/visions_en.png';
$lang->misc->releaseDate['17.3'] = '2022-07-13';
$lang->misc->releaseDate['17.2'] = '2022-06-29';
$lang->misc->releaseDate['17.1'] = '2022-06-16';
$lang->misc->releaseDate['17.0'] = '2022-06-02';
@@ -184,6 +185,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['17.3'][] = array('title' => "UI optimization of the modules such as statistics and background, the use case library will synchronize the function optimization information. Fix bugs.", 'desc' => '');
$lang->misc->feature->all['17.2'][] = array('title' => "Adjust the display of agile project block; optimize the UI of programs, projects and tests; optimize the detailed experience. Fix bugs.", 'desc' => '');
$lang->misc->feature->all['17.1'][] = array('title' => "Modify the interaction problem of execution, project module. Complete customer's high priority requirements. The detail experience is optimized, fix bugs.", 'desc' => '');
$lang->misc->feature->all['17.0'][] = array('title' => 'The detail experience is optimized, fix bugs.', 'desc' => '');
+2
View File
@@ -103,6 +103,7 @@ $lang->misc->feature->themeDesc = '<p>ZenTao 15.0+ a new "Youth Blue" theme
$lang->misc->feature->visionsDesc = "<p>The concept of interface has been added since 16.5. Users can deal with R & D affairs in <span style='color: #0c60e1'>[R&D]</span> and daily office affairs in <span style='color: #0c60e1'>[Lite]</span>.</p><p>You can view the current interface on the avatar, and click the name of the interface to view and switch other interfaces.</p>";
$lang->misc->feature->visionsImage = 'theme/default/images/main/visions_en.png';
$lang->misc->releaseDate['17.3'] = '2022-07-13';
$lang->misc->releaseDate['17.2'] = '2022-06-29';
$lang->misc->releaseDate['17.1'] = '2022-06-16';
$lang->misc->releaseDate['17.0'] = '2022-06-02';
@@ -184,6 +185,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['17.3'][] = array('title' => "UI optimization of the modules such as statistics and background, the use case library will synchronize the function optimization information. Fix bugs.", 'desc' => '');
$lang->misc->feature->all['17.2'][] = array('title' => "Adjust the display of agile project block; optimize the UI of programs, projects and tests; optimize the detailed experience. Fix bugs.", 'desc' => '');
$lang->misc->feature->all['17.1'][] = array('title' => "Modify the interaction problem of execution, project module. Complete customer's high priority requirements. The detail experience is optimized, fix bugs.", 'desc' => '');
$lang->misc->feature->all['17.0'][] = array('title' => 'The detail experience is optimized, fix bugs.', 'desc' => '');
+2
View File
@@ -103,6 +103,7 @@ $lang->misc->feature->themeDesc = '<p>ZenTao 15.0+ a new "Youth Blue" theme
$lang->misc->feature->visionsDesc = "<p>The concept of interface has been added since 16.5. Users can deal with R & D affairs in <span style='color: #0c60e1'>[R&D]</span> and daily office affairs in <span style='color: #0c60e1'>[Lite]</span>.</p><p>You can view the current interface on the avatar, and click the name of the interface to view and switch other interfaces.</p>";
$lang->misc->feature->visionsImage = 'theme/default/images/main/visions_en.png';
$lang->misc->releaseDate['17.3'] = '2022-07-13';
$lang->misc->releaseDate['17.2'] = '2022-06-29';
$lang->misc->releaseDate['17.1'] = '2022-06-16';
$lang->misc->releaseDate['17.0'] = '2022-06-02';
@@ -184,6 +185,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['17.3'][] = array('title' => "UI optimization of the modules such as statistics and background, the use case library will synchronize the function optimization information. Fix bugs.", 'desc' => '');
$lang->misc->feature->all['17.2'][] = array('title' => "Adjust the display of agile project block; optimize the UI of programs, projects and tests; optimize the detailed experience. Fix bugs.", 'desc' => '');
$lang->misc->feature->all['17.1'][] = array('title' => "Modify the interaction problem of execution, project module. Complete customer's high priority requirements. The detail experience is optimized, fix bugs.", 'desc' => '');
$lang->misc->feature->all['17.0'][] = array('title' => 'The detail experience is optimized, fix bugs.', 'desc' => '');
+2
View File
@@ -103,6 +103,7 @@ $lang->misc->feature->themeDesc = "<p>禅道15系列上线了全新的“
$lang->misc->feature->visionsDesc = "<p>从16.5开始增加了界面概念,用户可以在<span style='color:#0c60e1'>[研发综合界面]</span>中处理研发事务、在<span style='color:#0c60e1'>[迅捷界面]</span>处理日常办公事务。</p><p>在头像右侧即可查看当前所处界面,点击当前界面名称可查看和切换其他的界面。</p>";
$lang->misc->feature->visionsImage = 'theme/default/images/main/visions.png';
$lang->misc->releaseDate['17.3'] = '2022-07-13';
$lang->misc->releaseDate['17.2'] = '2022-06-29';
$lang->misc->releaseDate['17.1'] = '2022-06-16';
$lang->misc->releaseDate['17.0'] = '2022-06-02';
@@ -184,6 +185,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['17.3'][] = array('title' => '统计、后台等模块的UI优化,用例库同步用例信息功能优化。修复Bug。', 'desc' => '');
$lang->misc->feature->all['17.2'][] = array('title' => '调整敏捷项目区块的展示,项目集、项目和测试相关UI优化,细节体验优化。修复Bug。', 'desc' => '');
$lang->misc->feature->all['17.1'][] = array('title' => '修改执行、项目模块的交互问题,完成客户巴高优先级需求,细节体验优化。修复Bug。', 'desc' => '');
$lang->misc->feature->all['17.0'][] = array('title' => '细节体验优化。修复Bug。', 'desc' => '');
+2 -2
View File
@@ -207,6 +207,8 @@ $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;
@@ -215,9 +217,7 @@ $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['openedbyme'] = $lang->product->openedByMe;
$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe;
$lang->product->moreSelects['reviewedbyme'] = $lang->product->reviewedByMe;
$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe;
$lang->product->moreSelects['activestory'] = $lang->product->activeStory;
$lang->product->moreSelects['changedstory'] = $lang->product->changedStory;
+1 -1
View File
@@ -72,7 +72,7 @@ class productplan extends control
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $planID));
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => 'parent.refreshPlan()'));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('productplan', 'browse', "productID=$productID&branch=$branchID&browseType=wait")));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('productplan', 'browse', "productID=$productID&branch=$branchID&browseType=all")));
}
$this->commonAction($productID, $branchID);
+1
View File
@@ -23,6 +23,7 @@ $lang->programplan->createSubPlan = 'Create Sub Plan';
$lang->programplan->parent = 'Parent Stage';
$lang->programplan->emptyParent = 'N/A';
$lang->programplan->name = 'Stage Name';
$lang->programplan->status = 'Stage Progress';
$lang->programplan->PM = 'Stage Manager';
$lang->programplan->acl = 'Access Control';
$lang->programplan->subStageName = 'Sub Stage Name';
+1
View File
@@ -23,6 +23,7 @@ $lang->programplan->createSubPlan = 'Create Sub Stage';
$lang->programplan->parent = 'Parent Stage';
$lang->programplan->emptyParent = 'N/A';
$lang->programplan->name = 'Stage Name';
$lang->programplan->status = 'Stage Progress';
$lang->programplan->PM = 'Stage Manager';
$lang->programplan->acl = 'Access Control';
$lang->programplan->subStageName = 'Sub Stage Name';
+1
View File
@@ -23,6 +23,7 @@ $lang->programplan->createSubPlan = 'Create Sub Plan';
$lang->programplan->parent = 'Parent Stage';
$lang->programplan->emptyParent = 'N/A';
$lang->programplan->name = 'Stage Name';
$lang->programplan->status = 'Stage Progress';
$lang->programplan->PM = 'Stage Manager';
$lang->programplan->acl = 'Access Control';
$lang->programplan->subStageName = 'Sub Stage Name';
+3
View File
@@ -981,6 +981,9 @@ class project extends control
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$allExecution = $this->project->getStats($projectID, 'all');
$this->view->allExecutionNum = count($allExecution);
$this->view->title = $this->lang->execution->allExecutions;
$this->view->position[] = $this->lang->execution->allExecutions;
+11
View File
@@ -146,6 +146,17 @@ $(function()
});
$(document).on('change', "select[id^='branch']", disableSelectedBranch);
if(requiredFields.indexOf('budget') >= 0 && budget == 0)
{
$('#budget').removeAttr('disabled');
$('td .checkbox-primary').addClass('hidden');
}
if(requiredFields.indexOf('budget') >= 0 && budget != 0)
{
$('td .checkbox-primary').addClass('hidden');
}
});
/**
+2 -1
View File
@@ -27,6 +27,7 @@
<?php js::set('productName', $lang->product->name);?>
<?php js::set('manageProducts', $lang->project->manageProducts);?>
<?php $requiredFields = $config->project->create->requiredFields;?>
<?php js::set('requiredFields', $requiredFields);?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
@@ -77,7 +78,7 @@
</div>
</td>
<td>
<div class='checkbox-primary c-future'>
<div class="checkbox-primary c-future <?php echo strpos($requiredFields, 'budget') !== false ? 'hidden' : '';?>">
<input type='checkbox' id='future' name='future' value='1' />
<label for='future'><?php echo $lang->project->future;?></label>
</div>
+2
View File
@@ -28,6 +28,8 @@
<?php js::set('multiBranchProducts', $multiBranchProducts);?>
<?php $aclList = $project->parent ? $lang->project->subAclList : $lang->project->aclList;?>
<?php $requiredFields = $config->project->edit->requiredFields;?>
<?php js::set('requiredFields', $requiredFields);?>
<?php js::set('budget', $project->budget);?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
+1 -1
View File
@@ -39,7 +39,7 @@
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->execution->noExecution;?></span>
<?php if($status == "all"):?>
<?php if(empty($allExecutionNum)):?>
<?php if(common::hasPriv('programplan', 'create') and $isStage):?>
<?php echo html::a($this->createLink('programplan', 'create', "projectID=$projectID&productID=$productID"), "<i class='icon icon-plus'></i> " . $lang->programplan->create, '', "class='btn btn-info'");?>
<?php else: ?>
+7 -5
View File
@@ -127,7 +127,8 @@ function loadExecutionStories(executionID)
*/
function loadModuleMenu(executionID)
{
var link = createLink('tree', 'ajaxGetOptionMenu', 'rootID=' + executionID + '&viewtype=task');
var extra = $('#showAllModule').prop('checked') ? 'allModule' : '';
var link = createLink('tree', 'ajaxGetOptionMenu', 'rootID=' + executionID + '&viewtype=task&branch=0&rootModuleID=0&returnType=html&fieldID=&needManage=0&extra=' + extra);
$('#moduleIdBox').load(link, function(){$('#module').chosen();});
}
@@ -274,7 +275,7 @@ function setLane(regionID)
}
/* Get select of stories.*/
function setStories(moduleID)
function setStories(moduleID, executionID)
{
link = createLink('story', 'ajaxGetExecutionStories', 'executionID=' + executionID + '&productID=0&branch=all&moduleID=' + moduleID + '&storyID=0&number=&type=full&status=unclosed');
$.get(link, function(stories)
@@ -501,11 +502,12 @@ $(document).ready(function()
$('#showAllModule').change(function()
{
var moduleID = $('#moduleIdBox #module').val();
var extra = $(this).prop('checked') ? 'allModule' : '';
var executionID = $('#execution').val();
var moduleID = $('#moduleIdBox #module').val();
var extra = $(this).prop('checked') ? 'allModule' : '';
$('#moduleIdBox').load(createLink('tree', 'ajaxGetOptionMenu', "rootID=" + executionID + '&viewType=task&branch=0&rootModuleID=0&returnType=html&fieldID=&needManage=0&extra=' + extra), function()
{
$('#moduleIdBox #module').val(moduleID).chosen();
$('#module').val(moduleID).chosen();
});
});
});
+1 -2
View File
@@ -13,7 +13,6 @@
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php include '../../common/view/sortable.html.php';?>
<?php js::set('executionID', $execution->id);?>
<?php js::set('toTaskList', !empty($task->id));?>
<?php js::set('blockID', $blockID);?>
<?php js::set('teamMemberError', $lang->task->error->teamMember);?>
@@ -60,7 +59,7 @@ foreach(explode(',', $config->task->create->requiredFields) as $field)
</tr>
<tr>
<th><?php echo $lang->task->module;?></th>
<td id='moduleIdBox'><?php echo html::select('module', $moduleOptionMenu, $task->module, "class='form-control chosen' onchange='setStories(this.value)'");?></td>
<td id='moduleIdBox'><?php echo html::select('module', $moduleOptionMenu, $task->module, "class='form-control chosen' onchange='setStories(this.value, $execution->id)'");?></td>
<td>
<div class="checkbox-primary c-modulel">
<input type="checkbox" id="showAllModule" <?php if($showAllModule) echo 'checked';?>><label for="showAllModule" class="no-margin"><?php echo $lang->task->allModule;?></label>
+1 -1
View File
@@ -261,7 +261,7 @@ js::set('suiteID', $suiteID);
<h4 class="modal-title"><?php echo $lang->testcase->importToLib;?></h4>
</div>
<div class="modal-body">
<form method='post' class='form-ajax' action='<?php echo $this->createLink('testcase', 'importToLib');?>'>
<form method='post' class='form-ajax not-watch' action='<?php echo $this->createLink('testcase', 'importToLib');?>'>
<table class='table table-form'>
<tr>
<td class='select-lib'><?php echo $lang->testcase->selectLibAB;?></td>
+3 -2
View File
@@ -517,7 +517,7 @@ class tree extends control
{
$changeFunc = '';
if($viewType == 'bug' or $viewType == 'case') $changeFunc = "onchange='loadModuleRelated()'";
if($viewType == 'task') $changeFunc = "onchange='setStories(this.value)'";
if($viewType == 'task') $changeFunc = "onchange='setStories(this.value, $rootID)'";
$field = $fieldID ? "modules[$fieldID]" : 'module';
$currentModule = $this->tree->getById($currentModuleID);
@@ -539,7 +539,8 @@ class tree extends control
if($returnType == 'mhtml')
{
$changeFunc = '';
if($viewType == 'task' or $viewType == 'bug' or $viewType == 'case') $changeFunc = "onchange='loadModuleRelated()'";
if($viewType == 'bug' or $viewType == 'case') $changeFunc = "onchange='loadModuleRelated()'";
if($viewType == 'task') $changeFunc = "onchange='setStories(this.value, $rootID)'";
$field = $fieldID ? "modules[$fieldID]" : 'module';
$output = html::select("$field", $optionMenu, '', "class='input' $changeFunc");
die($output);
+2
View File
@@ -20,6 +20,7 @@ $config->upgrade->maxVersion['max3_1_beta2'] = '17_0_beta2';
$config->upgrade->maxVersion['max3_1'] = '17_0';
$config->upgrade->maxVersion['max3_2'] = '17_1';
$config->upgrade->maxVersion['max3_3'] = '17_2';
$config->upgrade->maxVersion['max3_4'] = '17_3';
$config->upgrade->bizVersion = array();
$config->upgrade->bizVersion['biz1_0'] = '9_5_1';
@@ -78,6 +79,7 @@ $config->upgrade->bizVersion['biz7_0_beta2'] = '17_0_beta2';
$config->upgrade->bizVersion['biz7_0'] = '17_0';
$config->upgrade->bizVersion['biz7_1'] = '17_1';
$config->upgrade->bizVersion['biz7_2'] = '17_2';
$config->upgrade->bizVersion['biz7_3'] = '17_3';
$config->upgrade->proVersion = array();
$config->upgrade->proVersion['pro1_0'] = '3_1';
+3
View File
@@ -161,6 +161,7 @@ $lang->upgrade->fromVersions['17_0_beta2'] = '17.0.beta2';
$lang->upgrade->fromVersions['17_0'] = '17.0';
$lang->upgrade->fromVersions['17_1'] = '17.1';
$lang->upgrade->fromVersions['17_2'] = '17.2';
$lang->upgrade->fromVersions['17_3'] = '17.3';
global $config;
/* Lite. */
@@ -326,6 +327,7 @@ $lang->upgrade->fromVersions['biz7_0_beta2'] = 'Biz7.0.beta2';
$lang->upgrade->fromVersions['biz7_0'] = 'Biz7.0';
$lang->upgrade->fromVersions['biz7_1'] = 'Biz7.1';
$lang->upgrade->fromVersions['biz7_2'] = 'Biz7.2';
$lang->upgrade->fromVersions['biz7_3'] = 'Biz7.3';
/* Max. */
$lang->upgrade->fromVersions['max2_0_beta4'] = 'Max2.0.beta4';
@@ -347,3 +349,4 @@ $lang->upgrade->fromVersions['max3_1_beta1'] = 'Max3.1.beta1';
$lang->upgrade->fromVersions['max3_1_beta2'] = 'Max3.1.beta2';
$lang->upgrade->fromVersions['max3_1'] = 'Max3.1';
$lang->upgrade->fromVersions['max3_2'] = 'Max3.2';
$lang->upgrade->fromVersions['max3_3'] = 'Max3.3';
+6 -5
View File
@@ -528,10 +528,6 @@ class upgradeModel extends model
$this->moveProjectAdmins();
$this->addStoryViewPriv();
break;
case '17_2':
$this->addReviewIssusApprovalData();
break;
}
$this->deletePatch();
@@ -696,6 +692,9 @@ class upgradeModel extends model
case 'max3_0':
$this->moveResult2Node();
break;
case 'max3_3':
$this->addReviewIssusApprovalData();
break;
}
}
@@ -973,6 +972,8 @@ class upgradeModel extends model
$confirmContent .= file_get_contents($this->getUpgradeFile('17.1'));
$xuanxuanSql = $this->app->getAppRoot() . 'db' . DS . 'upgradexuanxuan5.6.sql';
$confirmContent .= file_get_contents($xuanxuanSql);
case '17_2':
$confirmContent .= file_get_contents($this->getUpgradeFile('17.2'));
}
return $confirmContent;
@@ -6541,7 +6542,7 @@ class upgradeModel extends model
/* Add approval data. */
foreach($reviewIssues as $reviewIssue)
{
{
if(!isset($approvalsPairs[$reviewIssue->review]->approval)) continue;
$this->dao->update(TABLE_REVIEWISSUE)
->set('approval')->eq($approvalsPairs[$reviewIssue->review]->approval)
+2
View File
@@ -10,3 +10,5 @@ body {background: #1183fb linear-gradient(-90deg, #0a48d1 0%, #1183fb 100%); bac
#forgetForm .form-actions {padding-bottom: 20px;}
.required:after {top: 32px; right: -15px;}
.resetBox {float: right; font-size: 8px; margin-right: 2px;}
#forgetForm .form-actions > .btn-wide {min-width: 45%;}
#forgetForm .form-actions > a.btn-wide {margin-right: 0px;}
+2
View File
@@ -11,3 +11,5 @@ body {background: #1183fb linear-gradient(-90deg, #0a48d1 0%, #1183fb 100%); bac
.required:after {top: 32px; right: -15px;}
#resetPanel .form-group .input-group {width: 100%}
#resetPanel .form-group .input-group.required:after {top: 6px;}
#resetPanel .form-actions > .btn-wide {min-width: 45%;}
#resetPanel .form-actions > a.btn-wide {margin-right: 0px;}
@@ -207,14 +207,22 @@ class xuanxuanIm extends imModel
foreach($userMessages as $message)
{
/* Group by $message->content->content->objectType, ...->parentType, ...->action, ...->actor */
$contentData = json_decode($message->content);
$contentData = json_decode($contentData->content);
$contentDataOuter = json_decode($message->content);
$contentData = json_decode($contentDataOuter->content);
if(isset($contentData->contentType) && $contentData->contentType == 'text')
{
$messageGroups[$contentData->contentType][] = $message;
continue;
}
$messageGroups["$contentData->objectType-$contentData->parentType-$contentData->action-$contentData->actor"][] = $message;
if ($contentData->objectType == 'story' && $contentData->action == 'reviewed')
{
$extra = explode(',', $contentDataOuter->extra)[0];
$messageGroups["$contentData->objectType-$contentData->parentType-$contentData->action-$contentData->actor-$extra"][] = $message;
}
else
{
$messageGroups["$contentData->objectType-$contentData->parentType-$contentData->action-$contentData->actor"][] = $message;
}
}
foreach($messageGroups as $groupKey => $messages)
{
@@ -225,25 +233,24 @@ class xuanxuanIm extends imModel
$notificationContent = json_decode($notification->content);
$notificationInnerContent = json_decode($notificationContent->content);
/* Inner content: array($parentID => array($content1, $content2)) */
$objectGroups = array($notificationInnerContent->parent => array($notificationInnerContent));
/* Inner content: array($id => array($content1, $content2)) */
$objectGroups = array($notificationInnerContent->id => array($notificationInnerContent));
foreach($messages as $message)
{
$messageContent = json_decode($message->content);
$messageInnerContent = json_decode($messageContent->content);
$objectGroups[$messageInnerContent->parent][] = $messageInnerContent;
$objectGroups[$messageInnerContent->id][] = $messageInnerContent;
}
$objectTotal = 0;
foreach($objectGroups as $parent => $objectGroup)
foreach($objectGroups as $id => $objectGroup)
{
$object = current($objectGroup);
$object->count = count($objectGroup);
$object->url = $object->parentURL;
unset($object->title);
$objectGroups[$parent] = $object;
$objectTotal += $object->count;
$objectGroups[$id] = $object;
}
$objectTotal = count($objectGroups);
$notificationContent->content = json_encode(array_values($objectGroups));
/* Hack alert: title count replacement currently assumes that default count is 1. */
$notification->title = substr_replace($notification->title, "$objectTotal", strrpos($notification->title, '1'), 1);
@@ -3,7 +3,10 @@ $lang->message->typeList['xuanxuan'] = 'Chat';
$lang->message->sender = 'ZenTao';
$lang->message->notifyTitle = '%s %s%d %s';
$lang->message->notifyTitle = '%s %s%d %s';
$lang->message->notifyPassTitle = '%s passed %d stories';
$lang->message->notifyClarifyTitle = '%s clarify %d stories';
$lang->message->notifyRejectTitle = '%s reject %d stories';
$lang->message->mr = new stdClass();
$lang->message->mr->logTitle = 'Build log';
@@ -3,7 +3,10 @@ $lang->message->typeList['xuanxuan'] = 'Chat';
$lang->message->sender = 'ZenTao';
$lang->message->notifyTitle = '%s %s%d %s';
$lang->message->notifyTitle = '%s %s%d %s';
$lang->message->notifyPassTitle = '%s passed %d stories';
$lang->message->notifyClarifyTitle = '%s clarify %d stories';
$lang->message->notifyRejectTitle = '%s reject %d stories';
$lang->message->mr = new stdClass();
$lang->message->mr->logTitle = 'Build log';
@@ -3,7 +3,10 @@ $lang->message->typeList['xuanxuan'] = 'Chat';
$lang->message->sender = 'ZenTao';
$lang->message->notifyTitle = '%s %s%d %s';
$lang->message->notifyTitle = '%s %s%d %s';
$lang->message->notifyPassTitle = '%s passed %d stories';
$lang->message->notifyClarifyTitle = '%s clarify %d stories';
$lang->message->notifyRejectTitle = '%s reject %d stories';
$lang->message->mr = new stdClass();
$lang->message->mr->logTitle = 'Build log';
@@ -3,7 +3,10 @@ $lang->message->typeList['xuanxuan'] = '聊天';
$lang->message->sender = '禅道项目管理';
$lang->message->notifyTitle = '%s %s%d个%s';
$lang->message->notifyTitle = '%s %s%d个%s';
$lang->message->notifyPassTitle = '%s 通过了%d个研发需求';
$lang->message->notifyClarifyTitle = '%s 驳回了%d个研发需求';
$lang->message->notifyRejectTitle = '%s 拒绝了%d个研发需求';
$lang->message->mr = new stdClass();
$lang->message->mr->logTitle = '构建日志';
@@ -1,7 +1,7 @@
<?php
class xuanxuanMessage extends messageModel
{
public function send($objectType, $objectID, $actionType, $actionID, $actor = '')
public function send($objectType, $objectID, $actionType, $actionID, $actor = '', $extra = '')
{
$messageSetting = $this->config->message->setting;
if(is_string($messageSetting)) $messageSetting = json_decode($messageSetting, true);
@@ -44,6 +44,22 @@ class xuanxuanMessage extends messageModel
->fetch();
$field = $this->config->action->objectNameFields[$objectType];
$title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyTitle, $this->app->user->realname, $this->lang->action->label->$actionType, 1, $this->lang->action->objectTypes[$objectType]);
if ($objectType == 'story' && $actionType == 'reviewed' && !empty($extra))
{
$notifyType = strtolower(explode(',', $extra)[0]);
if ($notifyType == 'pass')
{
$title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyPassTitle, $this->app->user->realname, 1);
}
else if($notifyType == 'clarify')
{
$title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyClarifyTitle, $this->app->user->realname, 1);
}
else if($notifyType == 'reject')
{
$title = $objectType == 'mr' ? '' : sprintf($this->lang->message->notifyRejectTitle, $this->app->user->realname, 1);
}
}
$server = $this->loadModel('im')->getServer('zentao');
$onlybody = isset($_GET['onlybody']) ? $_GET['onlybody'] : '';
@@ -52,7 +68,7 @@ class xuanxuanMessage extends messageModel
$url = $server . helper::createLink($objectType == 'kanbancard' ? 'kanban' : $objectType, 'view', "id=$dataID", 'html');
$target = '';
if(!empty($object->assignedTo)) $target .= $object->assignedTo;
if(!empty($object->assignedTo)) $target .= $object->assignedTo == 'closed' ? $object->openedBy : $object->assignedTo;
if(!empty($object->mailto)) $target .= ",{$object->mailto}";
if(($objectType == 'mr' or $objectType == 'kanbancard') and !empty($object->createdBy)) $target .= ",{$object->createdBy}";
$target = trim($target, ',');
@@ -130,6 +146,7 @@ class xuanxuanMessage extends messageModel
$contentData->actions = array();
$contentData->url = "xxc:openInApp/zentao-integrated/" . urlencode($url);
}
$contentData->extra = $extra;
$content = json_encode($contentData);
$avatarUrl = $server . $this->app->getWebRoot() . 'favicon.ico';
@@ -1,2 +1,2 @@
<?php
$this->loadExtension('xuanxuan')->send($objectType, $objectID, $actionType, $actionID, $actor);
$this->loadExtension('xuanxuan')->send($objectType, $objectID, $actionType, $actionID, $actor, $extra);