Merge branch 'master' of https://gitlab.zcorp.cc/easycorp/zentaopms into sprint/master_lanzongjun_fixbug
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* The mr entry point 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 liyuchun <liyuchun@easysoft.ltd>
|
||||
* @package repo
|
||||
* @version 1
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
class mrEntry extends baseEntry
|
||||
{
|
||||
/**
|
||||
* Create mr.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
$fields = 'repoID,jobID,sourceBranch,targetBranch,diffs,mergeStatus';
|
||||
$this->batchSetPost($fields);
|
||||
$postData = fixer::input('post')->get();
|
||||
|
||||
$this->loadController('mr', 'create');
|
||||
$MRID = $this->loadModel('mr')->apiCreate();
|
||||
if(dao::isError()) $this->sendError(400, dao::getError());
|
||||
|
||||
$MR = $this->mr->getByID($MRID);
|
||||
$this->send(201, $MR);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
|
||||
if(!function_exists('getWebRoot')){function getWebRoot(){}}
|
||||
|
||||
/* 基本设置。Basic settings. */
|
||||
$config->version = '17.0'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
|
||||
$config->version = '17.1'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
|
||||
$config->liteVersion = '1.0'; // 迅捷版版本。 The version of Lite.
|
||||
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
|
||||
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
|
||||
|
||||
@@ -154,6 +154,7 @@ $routes['/docs/:id'] = 'doc';
|
||||
$routes['/repos'] = 'repos';
|
||||
$routes['/repos/rules'] = 'reporules';
|
||||
$routes['/jobs'] = 'jobs';
|
||||
$routes['/mr'] = 'mr';
|
||||
|
||||
$routes['/modules'] = 'modules';
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,3 +11,5 @@ DELETE FROM `zt_workflowaction` WHERE `module`='task' AND `action`='browse';
|
||||
DELETE FROM `zt_workflowaction` WHERE `module`='build' AND `action`='browse';
|
||||
|
||||
ALTER TABLE `zt_projectproduct` MODIFY COLUMN `plan` varchar(255) NOT NULL;
|
||||
|
||||
UPDATE `zt_project` SET status = 'closed' WHERE status='done';
|
||||
|
||||
@@ -1,3 +1,89 @@
|
||||
2022-06-16 17.1
|
||||
完成的需求
|
||||
33060 Scrum看板中增加搜索功能
|
||||
32812 需求检索条件中增加类别字段
|
||||
32710 地盘贡献的文档列表增加搜索功能
|
||||
32707 地盘贡献的用例列表增加搜索功能
|
||||
32706 地盘贡献的Bug列表增加搜索功能
|
||||
32705 地盘贡献的软件需求列表增加搜索功能
|
||||
32704 地盘贡献的用户需求列表增加搜索功能
|
||||
32703 地盘贡献的任务列表增加搜索功能
|
||||
31315 地盘待处理的任务列表增加搜索功能
|
||||
31314 地盘待处理的会议列表增加搜索功能
|
||||
31311 地盘待处理的用例列表增加搜索功能
|
||||
31310 地盘待处理的Bug列表增加搜索功能
|
||||
31309 地盘待处理的软件需求列表增加搜索功能
|
||||
31308 地盘待处理的用户需求列表增加搜索功能
|
||||
30964 产品计划列表增加搜索功能
|
||||
29722 专业研发看板中增加搜索功能
|
||||
25835 回收站增加搜索功能
|
||||
33296 创建和编辑执行保存成功后提示用户是否导入计划关联的相关需求
|
||||
33177 创建和编辑项目时允许关联同一个产品的多个计划
|
||||
33099 执行需求列表中提需求不受启用评审流程的限制
|
||||
33098 指定人提交的软件需求必须评审时由谁评审为必填项
|
||||
32574 执行列表中增加自定义列和高级表格功能
|
||||
31670 执行概况中增加所属项目集和项目信息
|
||||
31669 项目概况中增加所属项目集信息
|
||||
30711 专业研发看板中需求、任务、Bug支持在当前泳道列中上下拖拽排序
|
||||
30682 产品列表中可以显示所有产品线名称
|
||||
29852 Scrum看板中需求、任务、Bug支持在列中上下拖拽排序
|
||||
27150 创建和编辑执行时允许关联同一个产品的多个计划
|
||||
57190 地盘待处理的反馈列表增加搜索功能
|
||||
57189 地盘待处理列表增加指派给我的反馈功能
|
||||
57188 导入Excel功能支持xls格式
|
||||
57181 执行甘特图增加显示设置功能
|
||||
57180 组织下的日志列表支持点击查看详情
|
||||
57179 导入任务的模板中日期格式支持xxxx/xx/xx
|
||||
57178 Bug导入导出字段中增加反馈者和通知邮箱字段
|
||||
57177 项目导出后所属项目集显示完整层级
|
||||
57176 执行甘特图增加按照指派给、进度、开始日期、结束日期、持续天数排序功能
|
||||
57174 模版文件中的必填字段提示根据后台自定义设置的必填项进行提示
|
||||
57175 反馈检索标签后面增加上数字显示
|
||||
33536 批量编辑项目页面增加代号字段
|
||||
33470 更新日志页面优化
|
||||
33262 需求描述模块右上角打印最终判定结果
|
||||
33261 需求描述模块右上角打印评分展开、收起按钮
|
||||
33260 实现MSCWA评分模块功能
|
||||
33259 没有最终评定结果时评分展开、收起按钮显示规则
|
||||
33184 测试单的用例列表中搜索条件增加套件的检索字段
|
||||
33104 将MSCWA评分功能打包成插件在官网发布
|
||||
33102 需求列表中增加最终分数和MSCWA字段
|
||||
33101 需求列表搜索中增加最终分数和MSCWA检索条件
|
||||
33100 MSCWA评分功能增加权限控制
|
||||
32676 执行失败的用例可以关联一个已有的Bug
|
||||
33129 专业研发看板支持转入Bug
|
||||
33025 更新接口库中禅道API文档
|
||||
32106 完善产品投入统计表的统计维度
|
||||
30765 专业研发看板支持转入任务
|
||||
28469 组织日志中增加所属项目筛选条件
|
||||
9206 自定义必填项中增加反馈的必填设置功能
|
||||
30075 反馈的相关操作增加通知功能
|
||||
28471 日志统计表按部门搜索时可以统计到子部门
|
||||
30532 瀑布项目创建评审可以选择项目库中的文档
|
||||
32709 地盘贡献的风险列表增加搜索功能
|
||||
32708 地盘贡献的问题列表增加搜索功能
|
||||
31313 地盘待处理的风险列表增加搜索功能
|
||||
31312 地盘待处理的问题列表增加搜索功能
|
||||
解决的Bug
|
||||
23586 导入任务的相关需求字段显示不全
|
||||
23568 评审的动态缺少语言项
|
||||
23538 需求优先级下拉菜单显示异常
|
||||
23410 scrum看板和专业研发看板中按指派人分组查看任务时,指派给无中数据有误
|
||||
23298 创建版本库后没有关闭项目中的创建页面
|
||||
23253 创建项目集,提示连接超时
|
||||
23251 PHP8.0点击登录后,页面无响应
|
||||
23184 用例库导入用例变更后点击更新同步时前置条件没有更新
|
||||
23026 专业研发看板不关联产品时需求和Bug泳道没有提示
|
||||
23419 通用看板,设置和创建看板没有对齐
|
||||
23427 进入通用看板,默认显示“我参与的”标签页下的空间
|
||||
23432 专业研发看板中创建任务页面抄送给提示信息显示不完整
|
||||
23434 设置按钮下拉列表文案加上“空间”二字
|
||||
23540 设置空间页面团队处样式建议优化
|
||||
23543 迅捷界面项目看板没有对任务开始截止日期显示进行优化
|
||||
23554 用户有泳道设置的权限升级后默认也应该有设置背景色和修改泳道名的权限
|
||||
23558 进入执行Bug详情页会进入测试Bug中
|
||||
23560 项目-测试用例列表有报错
|
||||
|
||||
2022-06-02 17.0
|
||||
修复的bug
|
||||
22948 执行需求列表中列名称显示遮挡
|
||||
@@ -40,6 +126,7 @@
|
||||
32972 实现导出用户模板功能
|
||||
32440 实现导出用户功能
|
||||
15620 实现导入用户功能
|
||||
|
||||
2022-05-26 17.0.beta2
|
||||
修复的bug
|
||||
22755 导入用例确认页面相关研发需求没有必填项标识
|
||||
@@ -134,6 +221,7 @@
|
||||
29765 已关闭的看板可以进行激活操作
|
||||
28566 一级导航中项目集、产品、项目、执行菜单根据个性化设置中的选项权限依次判断
|
||||
14741 用例导出增加执行人和执行时间字段
|
||||
|
||||
2022-05-06 17.0.beta1
|
||||
修复的bug
|
||||
11398 批量移除需求的权限无法单独设置
|
||||
|
||||
@@ -429,13 +429,13 @@ $lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
|
||||
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
|
||||
$lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
|
||||
$lang->bug->featureBar['browse']['assignedbyme'] = $lang->bug->assignedByMe;
|
||||
|
||||
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
|
||||
$lang->bug->featureBar['browse']['more'] = $lang->more;
|
||||
|
||||
$lang->bug->moreSelects['unconfirmed'] = $lang->bug->unconfirmed;
|
||||
$lang->bug->moreSelects['assigntonull'] = $lang->bug->assignToNull;
|
||||
$lang->bug->moreSelects['longlifebugs'] = $lang->bug->longLifeBugs;
|
||||
$lang->bug->moreSelects['toclosed'] = $lang->bug->toClosed;
|
||||
$lang->bug->moreSelects['postponedbugs'] = $lang->bug->postponedBugs;
|
||||
$lang->bug->moreSelects['overduebugs'] = $lang->bug->overdueBugs;
|
||||
$lang->bug->moreSelects['needconfirm'] = $lang->bug->needConfirm;
|
||||
|
||||
@@ -3087,7 +3087,7 @@ class bugModel extends model
|
||||
case 'id':
|
||||
if($canBatchAction)
|
||||
{
|
||||
echo html::checkbox('bugIDList', array($bug->id => '')) . html::a(helper::createLink('bug', 'view', "bugID=$bug->id"), sprintf('%03d', $bug->id));
|
||||
echo html::checkbox('bugIDList', array($bug->id => '')) . html::a(helper::createLink('bug', 'view', "bugID=$bug->id"), sprintf('%03d', $bug->id), '', "data-app='{$this->app->tab}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3389,7 +3389,7 @@ class bugModel extends model
|
||||
if($type == 'view' && $this->app->tab != 'product')
|
||||
{
|
||||
$menu .= $this->buildMenu('bug', 'toStory', $toStoryParams, $bug, $type, $this->lang->icons['story'], '', '', '', "data-app='product' id='tostory'", $this->lang->bug->toStory);
|
||||
if(common::hasPriv('task', 'create')) $menu .= html::a('#toTask', "<i class='icon icon-check'></i><span class='text'>{$this->lang->bug->toTask}</span>", '', "data-app='qa' data-toggle='modal' class='btn btn-link'");
|
||||
if(common::hasPriv('task', 'create') and !isonlybody()) $menu .= html::a('#toTask', "<i class='icon icon-check'></i><span class='text'>{$this->lang->bug->toTask}</span>", '', "data-app='qa' data-toggle='modal' class='btn btn-link'");
|
||||
$menu .= $this->buildMenu('bug', 'createCase', $convertParams, $bug, $type, 'sitemap');
|
||||
}
|
||||
if($type == 'view')
|
||||
|
||||
@@ -97,17 +97,17 @@
|
||||
<?php if($branchProduct):?>
|
||||
<td style='overflow:visible'>
|
||||
<?php $disabled = (isset($productList) and $productList[$bug->product]->type == 'normal') ? "disabled='disabled'" : '';?>
|
||||
<?php echo html::select("branches[$bugID]", !empty($disabled) ? array() : $branchTagOption[$bug->product], $bug->branch, "class='form-control picker-select' $disabled onchange='setBranchRelated(this.value, $bug->product, $bug->id)'");?>
|
||||
<?php echo html::select("branches[$bugID]", !empty($disabled) ? array() : $branchTagOption[$bug->product], $bug->branch, "class='form-control picker-select' data-drop-width='auto' $disabled onchange='setBranchRelated(this.value, $bug->product, $bug->id)'");?>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
<td><?php echo html::select("modules[$bugID]", isset($modules[$bug->product][$bug->branch]) ? $modules[$bug->product][$bug->branch] : array(0 => '/'), $bug->module, "class='form-control picker-select'");?></td>
|
||||
<td class='<?php echo zget($visibleFields, 'productplan', ' hidden')?>' style='overflow:visible'><?php echo html::select("plans[$bugID]", $plans, $bug->plan, "class='form-control picker-select'");?></td>
|
||||
<td class='<?php echo zget($visibleFields, 'assignedTo', ' hidden')?>' style='overflow:visible'><?php echo html::select("assignedTos[$bugID]", $users, $bug->assignedTo, "class='form-control picker-select'");?></td>
|
||||
<td><?php echo html::select("modules[$bugID]", isset($modules[$bug->product][$bug->branch]) ? $modules[$bug->product][$bug->branch] : array(0 => '/'), $bug->module, "class='form-control picker-select' data-drop-width='auto'");?></td>
|
||||
<td class='<?php echo zget($visibleFields, 'productplan', ' hidden')?>' style='overflow:visible'><?php echo html::select("plans[$bugID]", $plans, $bug->plan, "class='form-control picker-select' data-drop-width='auto'");?></td>
|
||||
<td class='<?php echo zget($visibleFields, 'assignedTo', ' hidden')?>' style='overflow:visible'><?php echo html::select("assignedTos[$bugID]", $users, $bug->assignedTo, "class='form-control picker-select' data-drop-width='auto'");?></td>
|
||||
<td class='<?php echo zget($visibleFields, 'deadline', ' hidden')?>' style='overflow:visible'><?php echo html::input("deadlines[$bugID]", $bug->deadline, "class='form-control form-date'");?></td>
|
||||
<td <?php echo zget($visibleFields, 'os', "class='hidden'")?>><?php echo html::select("os[$bugID]", $osList, $bug->os, 'class=form-control');?></td>
|
||||
<td <?php echo zget($visibleFields, 'browser', "class='hidden'")?>><?php echo html::select("browsers[$bugID]", $browserList, $bug->browser, 'class=form-control');?></td>
|
||||
<td <?php echo zget($visibleFields, 'keywords', "class='hidden'")?>><?php echo html::input("keywords[$bugID]", $bug->keywords, 'class=form-control');?></td>
|
||||
<td class='<?php echo zget($visibleFields, 'resolvedBy', ' hidden')?>' style='overflow:visible'><?php echo html::select("resolvedBys[$bugID]", $users, $bug->resolvedBy, "class='form-control picker-select'");?></td>
|
||||
<td class='<?php echo zget($visibleFields, 'resolvedBy', ' hidden')?>' style='overflow:visible'><?php echo html::select("resolvedBys[$bugID]", $users, $bug->resolvedBy, "class='form-control picker-select' data-drop-width='auto'");?></td>
|
||||
<td <?php echo zget($visibleFields, 'resolution', "class='hidden'")?>>
|
||||
<table class='table-borderless table no-margin'>
|
||||
<tr>
|
||||
|
||||
+10
-3
@@ -55,7 +55,7 @@ class commonModel extends model
|
||||
|
||||
if($this->config->systemMode == 'new')
|
||||
{
|
||||
if($thisModule == 'task')
|
||||
if($thisModule == 'task' or $thisModule == 'effort')
|
||||
{
|
||||
$taskID = $objectID;
|
||||
$execution = $this->syncExecutionStatus($taskID);
|
||||
@@ -2356,7 +2356,8 @@ EOD;
|
||||
($module == 'user' && strpos('|login|deny|logout|reset|', "|{$method}|") !== false) ||
|
||||
($module == 'my' && strpos('|changepassword|preference|', "|{$method}|") !== false) ||
|
||||
($module == 'file' && strpos('|read|download|uploadimages|ajaxwopifiles|', "|{$method}|") !== false) ||
|
||||
($module == 'sso' && $method == 'login'))
|
||||
($module == 'sso' && $method == 'login') ||
|
||||
($module == 'traincourse' && $method == 'ajaxuploadlargefile'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -3103,7 +3104,7 @@ EOD;
|
||||
return;
|
||||
}
|
||||
|
||||
if($currentModule == $tab && $currentMethod== 'create')
|
||||
if($currentModule == $tab && $currentMethod == 'create')
|
||||
{
|
||||
$lang->menu = $lang->$tab->homeMenu;
|
||||
return;
|
||||
@@ -3127,6 +3128,12 @@ EOD;
|
||||
$lang->menu = $lang->$tab->homeMenu;
|
||||
return;
|
||||
}
|
||||
|
||||
if(isset($menu['subModule']) and strpos(",{$menu['subModule']},", ",$currentModule,") !== false)
|
||||
{
|
||||
$lang->menu = $lang->$tab->homeMenu;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Default, display menu. */
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
<style>
|
||||
.histories-list > li {word-break: break-word; word-wrap: break-word;}
|
||||
.history-changes del {padding-left: 3px;}
|
||||
#actionbox > .detail-content {width:100%; max-height: 800px; overflow: scroll;}
|
||||
#actionbox {margin: unset;}
|
||||
#actionbox .detail-title {padding-left: 10px;}
|
||||
#actionbox > .detail-content {padding-left: 10px; width:100%; max-height: 800px; overflow: scroll;}
|
||||
</style>
|
||||
<script>
|
||||
$(function()
|
||||
|
||||
@@ -26,9 +26,9 @@ $(function()
|
||||
}
|
||||
else if(typeof(from) != 'undefined')
|
||||
{
|
||||
<?php $from = isset($from) ? $from : '';?>
|
||||
<?php $from = ($from == 'project' and isset($isStage) and $isStage) ? 'stage' : $from;?>
|
||||
$dropmenu.append("<li><a href='<?php echo $this->createLink('datatable', 'ajaxCustom', 'id=' . $this->moduleName . '&method=' . $this->methodName . "&extra=$from")?>' data-toggle='modal' data-type='ajax'><?php echo $lang->datatable->custom?></a></li>");
|
||||
<?php $fromPage = isset($fromPage) ? $fromPage : '';?>
|
||||
<?php $fromPage = ($fromPage == 'project' and isset($isStage) and $isStage) ? 'stage' : $fromPage;?>
|
||||
$dropmenu.append("<li><a href='<?php echo $this->createLink('datatable', 'ajaxCustom', 'id=' . $this->moduleName . '&method=' . $this->methodName . "&extra=$fromPage")?>' data-toggle='modal' data-type='ajax'><?php echo $lang->datatable->custom?></a></li>");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+42
-5
@@ -827,19 +827,56 @@ class doc extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get doclib whitelist.
|
||||
* Ajax get whitelist.
|
||||
*
|
||||
* @param int $doclibID
|
||||
* @param string $acl open|custom|private
|
||||
* @param string $control user|group
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function ajaxGetWhitelist($doclibID, $acl)
|
||||
public function ajaxGetWhitelist($doclibID, $acl = '', $control = '')
|
||||
{
|
||||
$doclib = $this->doc->getLibById($doclibID);
|
||||
$users = $this->user->getPairs('noletter|noempty|noclosed');
|
||||
|
||||
$doclib = $this->doc->getLibById($doclibID);
|
||||
$users = $this->user->getPairs('noletter|noempty|noclosed');
|
||||
$selectedUser = $doclib->users;
|
||||
|
||||
if($control == 'group')
|
||||
{
|
||||
$groups = $this->loadModel('group')->getPairs();
|
||||
$selectedGroup = $doclib->groups;
|
||||
if($doclib->acl == 'custom')
|
||||
{
|
||||
foreach($groups as $groupID => $group)
|
||||
{
|
||||
if(strpos($doclib->groups, (string)$groupID) === false) unset($groups[$groupID]);
|
||||
}
|
||||
return print(html::select('groups[]', $groups, $selectedGroup, "class='form-control chosen' multiple"));
|
||||
}
|
||||
if($doclib->acl == 'open') return print(html::select('groups[]', $groups, $selectedGroup, "class='form-control chosen' multiple"));
|
||||
if($doclib->acl == 'private') echo 'private';
|
||||
if($doclib->acl == 'default') echo 'default';
|
||||
return false;
|
||||
}
|
||||
|
||||
if($control == 'user')
|
||||
{
|
||||
foreach($users as $account => $user)
|
||||
{
|
||||
if(($doclib->acl == 'custom' or $doclib->acl == 'private') and strpos($doclib->users, (string)$account) === false ) unset($users[$account]);
|
||||
}
|
||||
|
||||
if($doclib->acl == 'custom')
|
||||
{
|
||||
return print(html::select('users[]', $users, $selectedUser, "multiple class='form-control"));
|
||||
}
|
||||
if($doclib->acl == 'open') return print(html::select('users[]', $users, $selectedUser, "multiple class='form-control"));
|
||||
if($doclib->acl == 'private') echo 'private';
|
||||
if($doclib->acl == 'default') echo 'default';
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Sync whitelist when doclib permissions changed. */
|
||||
if($doclib->acl != 'custom' and !empty($doclib->project) and $acl == 'custom')
|
||||
{
|
||||
$project = $this->loadModel('project')->getById($doclib->project);
|
||||
|
||||
@@ -21,15 +21,18 @@ function loadModules(libID)
|
||||
*/
|
||||
function toggleAcl(acl, type)
|
||||
{
|
||||
var libID = $('#lib').val();
|
||||
if(acl == 'custom')
|
||||
{
|
||||
$('#whiteListBox').removeClass('hidden');
|
||||
$('#groupBox').removeClass('hidden');
|
||||
if(type == 'doc') loadWhitelist(libID);
|
||||
}
|
||||
else if(acl == 'private')
|
||||
{
|
||||
$('#whiteListBox').removeClass('hidden');
|
||||
$('#groupBox').addClass('hidden');
|
||||
if(type == 'doc') loadWhitelist(libID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -78,6 +81,61 @@ function loadDocModule(libID)
|
||||
$('#module_chosen').remove();
|
||||
$('#module').chosen();
|
||||
});
|
||||
|
||||
loadWhitelist(libID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load whitelist by libID.
|
||||
*
|
||||
* @param int $libID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function loadWhitelist(libID)
|
||||
{
|
||||
var groupLink = createLink('doc', 'ajaxGetWhitelist', 'libID=' + libID + '&acl=&control=group');
|
||||
var userLink = createLink('doc', 'ajaxGetWhitelist', 'libID=' + libID + '&acl=&control=user');
|
||||
$.post(groupLink, function(groups)
|
||||
{
|
||||
if(!(groups == 'default' || groups == 'private'))
|
||||
{
|
||||
$('#groups').replaceWith(groups);
|
||||
$('#groups_chosen').remove();
|
||||
$('#groups').chosen();
|
||||
}
|
||||
});
|
||||
|
||||
$.post(userLink, function(users)
|
||||
{
|
||||
if(users != 'default')
|
||||
{
|
||||
if(users == 'private')
|
||||
{
|
||||
$('#aclopen').parent('.radio-inline').addClass('hidden');
|
||||
$('#aclcustom').parent('.radio-inline').addClass('hidden');
|
||||
$('#aclprivate').prop('checked', true);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#aclopen').parent('.radio-inline').removeClass('hidden');
|
||||
$('#aclcustom').parent('.radio-inline').removeClass('hidden');
|
||||
$('#aclprivate').prop('checked', false);
|
||||
|
||||
$('#users').replaceWith(users);
|
||||
$('#users_chosen').remove();
|
||||
$('#whiteListBox .picker').remove();
|
||||
if($('#users option').length < maxCount)
|
||||
{
|
||||
$('#users').chosen();
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#users').picker();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1084,7 +1084,7 @@ class docModel extends model
|
||||
if(strpos(",{$object->users},", $account) !== false) return true;
|
||||
}
|
||||
|
||||
if(strpos($extra, 'notdoc') === false)
|
||||
if(strpos($extra, 'notdoc') !== false)
|
||||
{
|
||||
static $extraDocLibs;
|
||||
if($extraDocLibs === null) $extraDocLibs = $this->getPrivLibsByDoc();
|
||||
@@ -1118,7 +1118,7 @@ class docModel extends model
|
||||
if($extraDocLibs === null) $extraDocLibs = $this->getPrivLibsByDoc();
|
||||
|
||||
static $libs;
|
||||
if($libs === null) $libs = $this->getLibs('all', 'notdoc');
|
||||
if($libs === null) $libs = $this->getLibs('all');
|
||||
if(isset($libs[$object->lib]) and isset($extraDocLibs[$object->lib])) unset($extraDocLibs[$object->lib]);
|
||||
|
||||
if($object->acl == 'open' and !isset($extraDocLibs[$object->lib])) return true;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php js::set('maxCount', $this->config->maxCount);?>
|
||||
<?php if($docType != '' and strpos($config->doc->officeTypes, $docType) !== false):?>
|
||||
<?php include '../../common/view/header.lite.html.php';?>
|
||||
<div id="mainContent" class="main-content">
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<?php js::set('confirmUpdateContent', $lang->doc->confirmUpdateContent);?>
|
||||
<?php js::set('docID', $doc->id);?>
|
||||
<?php js::set('draft', $doc->draft);?>
|
||||
<?php js::set('maxCount', $this->config->maxCount);?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
|
||||
@@ -139,7 +139,7 @@ $config->execution->gantt->linkType['end']['end'] = 2;
|
||||
$config->execution->gantt->linkType['begin']['end'] = 3;
|
||||
|
||||
$config->execution->datatable = new stdclass();
|
||||
$config->execution->datatable->defaultField = array('id', 'name', 'code', 'project', 'PM', 'status', 'progress', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn');
|
||||
$config->execution->datatable->defaultField = array('id', 'name', 'code', 'project', 'PM', 'status', 'progress', 'percent', 'attribute', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn', 'actions');
|
||||
|
||||
$config->execution->datatable->fieldList['id']['title'] = 'idAB';
|
||||
$config->execution->datatable->fieldList['id']['fixed'] = 'left';
|
||||
@@ -153,7 +153,7 @@ $config->execution->datatable->fieldList['name']['required'] = 'yes';
|
||||
|
||||
$config->execution->datatable->fieldList['code']['title'] = 'code';
|
||||
$config->execution->datatable->fieldList['code']['fixed'] = 'no';
|
||||
$config->execution->datatable->fieldList['code']['width'] = '90';
|
||||
$config->execution->datatable->fieldList['code']['width'] = '95';
|
||||
$config->execution->datatable->fieldList['code']['required'] = 'no';
|
||||
|
||||
$config->execution->datatable->fieldList['project']['title'] = 'project';
|
||||
@@ -168,18 +168,18 @@ $config->execution->datatable->fieldList['PM']['required'] = 'no';
|
||||
|
||||
$config->execution->datatable->fieldList['status']['title'] = 'status';
|
||||
$config->execution->datatable->fieldList['status']['fixed'] = 'no';
|
||||
$config->execution->datatable->fieldList['status']['width'] = '80';
|
||||
$config->execution->datatable->fieldList['status']['width'] = '100';
|
||||
$config->execution->datatable->fieldList['status']['required'] = 'no';
|
||||
|
||||
$config->execution->datatable->fieldList['progress']['title'] = 'progress';
|
||||
$config->execution->datatable->fieldList['progress']['fixed'] = 'no';
|
||||
$config->execution->datatable->fieldList['progress']['width'] = '40';
|
||||
$config->execution->datatable->fieldList['progress']['width'] = '70';
|
||||
$config->execution->datatable->fieldList['progress']['required'] = 'no';
|
||||
$config->execution->datatable->fieldList['progress']['sort'] = 'no';
|
||||
|
||||
$config->execution->datatable->fieldList['percent']['title'] = 'percent';
|
||||
$config->execution->datatable->fieldList['percent']['fixed'] = 'no';
|
||||
$config->execution->datatable->fieldList['percent']['width'] = '80';
|
||||
$config->execution->datatable->fieldList['percent']['width'] = '85';
|
||||
$config->execution->datatable->fieldList['percent']['required'] = 'no';
|
||||
$config->execution->datatable->fieldList['percent']['sort'] = 'no';
|
||||
|
||||
@@ -196,12 +196,12 @@ $config->execution->datatable->fieldList['openedDate']['required'] = 'no';
|
||||
|
||||
$config->execution->datatable->fieldList['begin']['title'] = 'begin';
|
||||
$config->execution->datatable->fieldList['begin']['fixed'] = 'no';
|
||||
$config->execution->datatable->fieldList['begin']['width'] = '85';
|
||||
$config->execution->datatable->fieldList['begin']['width'] = '100';
|
||||
$config->execution->datatable->fieldList['begin']['required'] = 'no';
|
||||
|
||||
$config->execution->datatable->fieldList['end']['title'] = 'end';
|
||||
$config->execution->datatable->fieldList['end']['fixed'] = 'no';
|
||||
$config->execution->datatable->fieldList['end']['width'] = '85';
|
||||
$config->execution->datatable->fieldList['end']['width'] = '90';
|
||||
$config->execution->datatable->fieldList['end']['required'] = 'no';
|
||||
|
||||
$config->execution->datatable->fieldList['realBegan']['title'] = 'realBegan';
|
||||
@@ -224,7 +224,7 @@ $config->execution->datatable->fieldList['estimate']['sort'] = 'no';
|
||||
|
||||
$config->execution->datatable->fieldList['consumed']['title'] = 'consumed';
|
||||
$config->execution->datatable->fieldList['consumed']['fixed'] = 'no';
|
||||
$config->execution->datatable->fieldList['consumed']['width'] = '70';
|
||||
$config->execution->datatable->fieldList['consumed']['width'] = '75';
|
||||
$config->execution->datatable->fieldList['consumed']['required'] = 'no';
|
||||
$config->execution->datatable->fieldList['consumed']['sort'] = 'no';
|
||||
|
||||
|
||||
@@ -740,6 +740,7 @@ class execution extends control
|
||||
else
|
||||
{
|
||||
$this->session->set('executionStoryBrowseType', $type);
|
||||
$this->session->set('storyBrowseType', $type, 'execution');
|
||||
}
|
||||
|
||||
/* Save session. */
|
||||
@@ -1026,6 +1027,7 @@ class execution extends control
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', false);
|
||||
|
||||
$cases = $this->testcase->appendData($cases, 'case');
|
||||
$cases = $this->loadModel('story')->checkNeedConfirm($cases);
|
||||
|
||||
$this->view->title = $this->lang->execution->testcase;
|
||||
$this->view->executionID = $executionID;
|
||||
@@ -1574,6 +1576,9 @@ class execution extends control
|
||||
return print(js::confirm($this->lang->execution->importEditPlanStory, inlink('edit', "executionID=$executionID&action=edit&extra=&newPlans=$newPlans&confirm=yes"), inlink('view', "executionID=$executionID")));
|
||||
}
|
||||
|
||||
/* Set menu. */
|
||||
$this->execution->setMenu($executionID);
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$oldPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($executionID)->andWhere('plan')->ne(0)->fetchPairs('plan');
|
||||
@@ -1636,9 +1641,6 @@ class execution extends control
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "executionID=$executionID")));
|
||||
}
|
||||
|
||||
/* Set menu. */
|
||||
$this->execution->setMenu($executionID);
|
||||
|
||||
$executions = array('' => '') + $this->executions;
|
||||
$managers = $this->execution->getDefaultManagers($executionID);
|
||||
|
||||
@@ -3476,16 +3478,6 @@ class execution extends control
|
||||
$parents = array();
|
||||
if($parentIdList) $parents = $this->execution->getByIdList($parentIdList);
|
||||
|
||||
$isStage = (isset($project->model) and $project->model == 'waterfall') ? true : false;
|
||||
if($isStage)
|
||||
{
|
||||
$this->config->execution->datatable->defaultField = array('id', 'name', 'PM', 'status', 'progress', 'percent', 'attribute', 'begin', 'end', 'realBegan', 'realEnd', 'actions');
|
||||
}
|
||||
elseif($this->app->tab == 'project')
|
||||
{
|
||||
$this->config->execution->datatable->defaultField = array('id', 'name', 'code', 'PM', 'status', 'progress', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn');
|
||||
}
|
||||
|
||||
$this->view->executionStats = $executionStats;
|
||||
$this->view->productList = $this->loadModel('product')->getProductPairsByProject($projectID);
|
||||
$this->view->productID = $productID;
|
||||
@@ -3497,7 +3489,8 @@ class execution extends control
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||||
$this->view->status = $status;
|
||||
$this->view->from = $from;
|
||||
$this->view->isStage = $isStage;
|
||||
$this->view->isStage = (isset($project->model) and $project->model == 'waterfall') ? true : false;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -3909,4 +3902,30 @@ class execution extends control
|
||||
|
||||
echo true;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: Gets the start date of the project to which the execution belongs.
|
||||
*
|
||||
* @param int $executionID
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function ajaxGetProjectStartDate($executionID = 0)
|
||||
{
|
||||
if($this->config->systemMode == 'new')
|
||||
{
|
||||
$execution = $this->dao->select('id,project')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch();
|
||||
$project = $this->dao->select('begin,end')->from(TABLE_PROJECT)->where('id')->eq($execution->project)->fetch();
|
||||
if(empty($project))
|
||||
{
|
||||
echo '';
|
||||
return false;
|
||||
}
|
||||
|
||||
$date = array();
|
||||
$date['begin'] = $project->begin;
|
||||
$date['end'] = $project->end;
|
||||
echo json_encode($date);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
body {margin-bottom: 25px;}
|
||||
.table-responsive {overflow-y: hidden !important;}
|
||||
#product_chosen .chosen-single {width: 180px;}
|
||||
|
||||
.table-children {border-left: 2px solid #cbd0db; border-right: 2px solid #cbd0db;}
|
||||
@@ -14,6 +15,7 @@ body {margin-bottom: 25px;}
|
||||
.main-table tbody > tr.table-children > td:first-child::before {width: 3px;}
|
||||
td.hours {text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
|
||||
td.flex {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center; margin-bottom: -1px;}
|
||||
td.datatable-cell.flex {margin-bottom: -2px;}
|
||||
td.flex span.label-badge {margin-left: 5px; min-width: 50px;}
|
||||
td.flex span.label-badge.label-light {min-width: 22px;}
|
||||
td.flex span.project-type-label {margin-left: 5px; min-width: 36px;}
|
||||
@@ -30,5 +32,5 @@ td.flex span.project-type-label {min-width: 40px;}
|
||||
|
||||
.c-project{text-overflow: unset !important;}
|
||||
canvas {height: 28px;}
|
||||
.parent.has-child.c-name.flex, .table-child-bottom > .c-name.flex {border-bottom: 1px solid #cbd0db;}
|
||||
.parent.has-child.c-name.flex {margin-bottom: -2px;}
|
||||
.parent.has-child.c-name.flex, .table-child-bottom > .c-name.flex {border-bottom: 1px solid #cbd0db !important;}
|
||||
.parent.has-child.c-name.flex {margin-bottom: -2px !important;}
|
||||
|
||||
@@ -8,7 +8,8 @@ $(function()
|
||||
});
|
||||
|
||||
var nameWidth = $('#executionsForm thead th.c-name').width();
|
||||
if(nameWidth < 150 && !useDatatable) $('#executionsForm thead th.c-name').css('width', '150px');
|
||||
if(isCNLang && nameWidth < 150 && !useDatatable) $('#executionsForm thead th.c-name').css('width', '150px');
|
||||
if(!isCNLang && nameWidth < 200 && !useDatatable) $('#executionsForm thead th.c-name').css('width', '200px');
|
||||
|
||||
toggleFold('#executionsForm', unfoldExecutions, projectID, 'execution');
|
||||
|
||||
|
||||
@@ -236,7 +236,8 @@ function createLaneMenu(options)
|
||||
if(!privs.length) return [];
|
||||
|
||||
var items = [];
|
||||
if(privs.includes('setLane')) items.push({label: kanbanLang.setLane, icon: 'edit', url: createLink('kanban', 'setLane', 'laneID=' + lane.id + '&executionID=0&from=kanban'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '635px'}});
|
||||
if(privs.includes('editLaneName')) items.push({label: kanbanLang.editLaneName, icon: 'edit', url: createLink('kanban', 'editLaneName', 'laneID=' + lane.id + '&executionID=0&from=kanban'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '635px'}});
|
||||
if(privs.includes('editLaneColor')) items.push({label: kanbanLang.editLaneColor, icon: 'color', url: createLink('kanban', 'editLaneColor', 'laneID=' + lane.id + '&executionID=0&from=kanban'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '635px'}});
|
||||
if(privs.includes('deleteLane')) items.push({label: kanbanLang.deleteLane, icon: 'trash', url: createLink('kanban', 'deleteLane', 'lane=' + lane.id), attrs: {'target': 'hiddenwin'}});
|
||||
|
||||
var bounds = options.$trigger[0].getBoundingClientRect();
|
||||
@@ -794,13 +795,14 @@ function renderHeaderCol($column, column, $header, kanbanData)
|
||||
function renderLaneName($lane, lane, $kanban, columns, kanban)
|
||||
{
|
||||
if(groupBy != 'default') return;
|
||||
var canSet = lane.actions.includes('setLane');
|
||||
var canSort = lane.actions.includes('sortLane') && kanban.lanes.length > 1;
|
||||
var canDelete = lane.actions.includes('deleteLane');
|
||||
var canEditLaneColor = lane.actions.includes('editLaneColor');
|
||||
var canEditLaneName = lane.actions.includes('editLaneName');
|
||||
var canSort = lane.actions.includes('sortLane') && kanban.lanes.length > 1;
|
||||
var canDelete = lane.actions.includes('deleteLane');
|
||||
|
||||
$lane.parent().toggleClass('sort', canSort);
|
||||
|
||||
if(!$lane.children('.actions').length && (canSet || canDelete))
|
||||
if(!$lane.children('.actions').length && (canEditLaneColor || canEditLaneName || canDelete))
|
||||
{
|
||||
$([
|
||||
'<div class="actions" title="' + kanbanLang.more + '">',
|
||||
|
||||
@@ -270,8 +270,8 @@ $lang->execution->treeOnlyTask = 'Show Task Only';
|
||||
$lang->execution->treeOnlyStory = 'Show Story Only';
|
||||
$lang->execution->storyKanban = 'Story Kanban';
|
||||
$lang->execution->storySort = 'Rank Story';
|
||||
$lang->execution->importPlanStory = $lang->executionCommon . ' is created!\nDo you want to import stories that have been linked to the plan?';
|
||||
$lang->execution->importEditPlanStory = $lang->executionCommon . ' is edited!\nDo you want to import stories that have been linked to the plan?';
|
||||
$lang->execution->importPlanStory = $lang->executionCommon . ' is created!\nDo you want to import stories that have been linked to the plan? The stories in the draft will be automatically filtered out when imported.';
|
||||
$lang->execution->importEditPlanStory = $lang->executionCommon . ' is edited!\nDo you want to import stories that have been linked to the plan? The stories in the draft will be automatically filtered out when imported.';
|
||||
$lang->execution->needLinkProducts = 'The execution has not been linked with any product, and the related functions cannot be used. Please link the product first and try again.';
|
||||
$lang->execution->iteration = 'Iterations';
|
||||
$lang->execution->iterationInfo = '%s Iterations';
|
||||
|
||||
@@ -270,8 +270,8 @@ $lang->execution->treeOnlyTask = '树状图只看任务';
|
||||
$lang->execution->treeOnlyStory = "树状图只看{$lang->SRCommon}";
|
||||
$lang->execution->storyKanban = "{$lang->SRCommon}看板";
|
||||
$lang->execution->storySort = "{$lang->SRCommon}排序";
|
||||
$lang->execution->importPlanStory = '创建' . $lang->executionCommon . '成功!\n是否导入计划关联的相关' . $lang->SRCommon . '?';
|
||||
$lang->execution->importEditPlanStory = '编辑' . $lang->executionCommon . '成功!\n是否导入计划关联的相关' . $lang->SRCommon . '?';
|
||||
$lang->execution->importPlanStory = '创建' . $lang->executionCommon . '成功!\n是否导入计划关联的相关' . $lang->SRCommon . '?导入时将自动过滤掉草稿状态的' . $lang->SRCommon . '。';
|
||||
$lang->execution->importEditPlanStory = '编辑' . $lang->executionCommon . '成功!\n是否导入计划关联的相关' . $lang->SRCommon . '?导入时将自动过滤掉草稿状态的' . $lang->SRCommon . '。';
|
||||
$lang->execution->needLinkProducts = '该执行还未关联任何产品,相关功能无法使用,请先关联产品后再试。';
|
||||
$lang->execution->iteration = '版本迭代';
|
||||
$lang->execution->iterationInfo = '迭代%s次';
|
||||
|
||||
@@ -2024,6 +2024,8 @@ class executionModel extends model
|
||||
$data->product = $productID;
|
||||
$data->branch = $branch;
|
||||
$data->plan = isset($plans[$productID][$branch]) ? implode(',', $plans[$productID][$branch]) : $oldPlan;
|
||||
$data->plan = trim($data->plan, ',');
|
||||
$data->plan = empty($data->plan) ? 0 : ",$data->plan,";
|
||||
$this->dao->insert(TABLE_PROJECTPRODUCT)->data($data)->exec();
|
||||
$existedProducts[$productID][$branch] = true;
|
||||
}
|
||||
@@ -2535,7 +2537,6 @@ class executionModel extends model
|
||||
|
||||
$planStories = array();
|
||||
$planProducts = array();
|
||||
$count = 0;
|
||||
$this->loadModel('story');
|
||||
if(!empty($plans))
|
||||
{
|
||||
@@ -2552,7 +2553,6 @@ class executionModel extends model
|
||||
{
|
||||
if($story->status == 'draft')
|
||||
{
|
||||
$count++;
|
||||
unset($planStory[$id]);
|
||||
continue;
|
||||
}
|
||||
@@ -2567,7 +2567,6 @@ class executionModel extends model
|
||||
$projectID = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch('project');
|
||||
$this->linkStory($executionID, $planStories, $planProducts);
|
||||
if($this->config->systemMode == 'new') $this->linkStory($projectID, $planStories, $planProducts);
|
||||
if($count != 0) echo js::alert(sprintf($this->lang->execution->haveDraft, $count)) . js::locate(helper::createLink('execution', 'create', "projectID=$projectID&executionID=$executionID"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3103,7 +3102,6 @@ class executionModel extends model
|
||||
if($currentTime > time() and !$todayTag)
|
||||
{
|
||||
$todayTag = $i + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!isset($sets[$current]) and $mode == 'noempty')
|
||||
@@ -4167,7 +4165,7 @@ class executionModel extends model
|
||||
$id = $col->id;
|
||||
$onlyChildStage = ($execution->grade == 2 and $execution->project != $execution->parent);
|
||||
|
||||
if(!$isStage and $col->id == 'actions') return;
|
||||
if(!$isStage and in_array($col->id, array('percent', 'attribute', 'actions'))) return;
|
||||
if(($this->config->systemMode == 'classic' or ($this->config->systemMode == 'new' and $this->app->tab != 'execution')) and $col->id == 'project') return;
|
||||
|
||||
if($col->show)
|
||||
@@ -4221,7 +4219,7 @@ class executionModel extends model
|
||||
{
|
||||
echo "<div class='checkbox-primary'><input type='checkbox' name='executionIDList[$execution->id]' value='$execution->id' autocomplete='off'/><label></label></div>";
|
||||
}
|
||||
echo printf('%03d', $execution->id);
|
||||
echo sprintf('%03d', $execution->id);
|
||||
break;
|
||||
case 'name':
|
||||
$label = $execution->type == 'stage' ? 'label-warning' : 'label-info';
|
||||
|
||||
@@ -26,6 +26,7 @@ $unfoldExecutions = zget($unfoldExecutions, $projectID, array());
|
||||
js::set('unfoldExecutions', $unfoldExecutions);
|
||||
js::set('unfoldAll', $lang->execution->treeLevel['all']);
|
||||
js::set('foldAll', $lang->execution->treeLevel['root']);
|
||||
js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
|
||||
?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
@@ -106,7 +107,11 @@ js::set('foldAll', $lang->execution->treeLevel['root']);
|
||||
$hasActions = false;
|
||||
foreach($setting as $key => $value)
|
||||
{
|
||||
if($value->id == 'actions') $hasActions = true;
|
||||
if($value->id == 'actions')
|
||||
{
|
||||
$hasActions = true;
|
||||
$value->show = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$hasActions)
|
||||
@@ -126,9 +131,9 @@ js::set('foldAll', $lang->execution->treeLevel['root']);
|
||||
|
||||
foreach($setting as $key => $value)
|
||||
{
|
||||
if($value->show || $value->id == 'actions')
|
||||
if($value->show)
|
||||
{
|
||||
if($isStage and $value->id == 'actions') $value->show = true;
|
||||
if(!$isStage and in_array($value->id, array('percent', 'attribute', 'actions'))) continue;
|
||||
if(($config->systemMode == 'classic' or ($config->systemMode == 'new' and $this->app->tab != 'execution')) and $value->id == 'project') continue;
|
||||
|
||||
$this->datatable->printHead($value, $orderBy, $vars, $canBatchEdit);
|
||||
|
||||
@@ -144,8 +144,6 @@ js::set('emptyEnd', $lang->programplan->emptyEnd);
|
||||
js::set('planFinishSmall', $lang->programplan->error->planFinishSmall);
|
||||
js::set('errorBegin', $lang->execution->errorLetterProject);
|
||||
js::set('errorEnd', $lang->execution->errorGreaterProject);
|
||||
js::set('projectBeginDate', $project->begin);
|
||||
js::set('projectEndDate', $project->end);
|
||||
?>
|
||||
|
||||
<script>
|
||||
@@ -157,8 +155,9 @@ $('#executionForm').submit(function()
|
||||
var beginDate = $(this).val();
|
||||
var beginDateID = $(this).attr('id');
|
||||
|
||||
var nameID = beginDateID.replace('begins', 'names');
|
||||
var endDateID = beginDateID.replace('begins', 'ends');
|
||||
var nameID = beginDateID.replace('begins', 'names');
|
||||
var endDateID = beginDateID.replace('begins', 'ends');
|
||||
var executionID = beginDateID.replace('begins', '');
|
||||
$('#help' + beginDateID).remove();
|
||||
$('#help' + endDateID).remove();
|
||||
|
||||
@@ -166,6 +165,25 @@ $('#executionForm').submit(function()
|
||||
var nameVal = $('#' + nameID).val()
|
||||
if(!nameVal) return;
|
||||
|
||||
var projectBeginDate = '0000-00-00';
|
||||
var projectEndDate = '2059-12-31';
|
||||
|
||||
$.ajax(
|
||||
{
|
||||
url: createLink('execution', 'ajaxGetProjectStartDate', "executionID=" + executionID),
|
||||
dataType: 'json',
|
||||
method: 'post',
|
||||
async: false,
|
||||
success: function(data)
|
||||
{
|
||||
if(data)
|
||||
{
|
||||
projectBeginDate = data.begin;
|
||||
projectEndDate = data.end;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Check if the begin date is empty.
|
||||
if(!beginDate)
|
||||
{
|
||||
@@ -216,7 +234,11 @@ $('#executionForm').submit(function()
|
||||
}
|
||||
});
|
||||
|
||||
if(!submitForm) return false;
|
||||
if(!submitForm)
|
||||
{
|
||||
setTimeout(function(){$('#submit').removeAttr('disabled')}, 500);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
{
|
||||
if(common::hasPriv('story', 'view'))
|
||||
{
|
||||
echo html::a($this->createLink('story', 'view', "storyid=$task->storyID"), $task->storyTitle);
|
||||
echo html::a($this->createLink('story', 'view', "storyid=$task->storyID"), $task->storyTitle, '', "class='preview'", true, isonlybody());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<th class='c-date'> <?php common::printOrderLink('lastRunDate', $orderBy, $vars, $lang->testtask->lastRunTime);?></th>
|
||||
<th class='c-result'><?php common::printOrderLink('lastRunResult', $orderBy, $vars, $lang->testtask->lastRunResult);?></th>
|
||||
<th class='c-status'><?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
|
||||
<th class='c-actions-5 text-center'> <?php echo $lang->actions;?></th>
|
||||
<th class='c-actions-6 text-center'><?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -40,7 +40,6 @@
|
||||
<?php
|
||||
$caseID = $type == 'assigntome' ? $case->case : $case->id;
|
||||
$runID = $type == 'assigntome' ? $case->id : 0;
|
||||
$canBeChanged = common::canBeChanged('testcase', $case);
|
||||
?>
|
||||
<tr>
|
||||
<td class="c-id">
|
||||
@@ -55,18 +54,26 @@
|
||||
<td><?php echo zget($users, $case->lastRunner);?></td>
|
||||
<td><?php if(!helper::isZeroDate($case->lastRunDate)) echo date(DT_MONTHTIME1, strtotime($case->lastRunDate));?></td>
|
||||
<td class='<?php echo $case->lastRunResult;?>'><?php if($case->lastRunResult) echo $lang->testcase->resultList[$case->lastRunResult];?></td>
|
||||
<td class='<?php if(isset($run)) echo $run->status;?>'><?php echo $this->processStatus('testcase', $case);?></td>
|
||||
<td>
|
||||
<?php
|
||||
if($case->needconfirm)
|
||||
{
|
||||
echo "<span class='status-story status-changed' title='{$this->lang->story->changed}'>{$this->lang->story->changed}</span>";
|
||||
}
|
||||
elseif(isset($case->fromCaseVersion) and $case->fromCaseVersion > $case->version and !$case->needconfirm)
|
||||
{
|
||||
echo "<span class='status-story status-changed' title='{$this->lang->testcase->changed}'>{$this->lang->testcase->changed}</span>";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<span class='status-testcase status-{$case->status}'>" . $this->processStatus('testcase', $case) . "</span>";
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td class='c-actions'>
|
||||
<?php
|
||||
if($canBeChanged)
|
||||
{
|
||||
$disabled = $case->status == 'wait' ? 'disabled' : '';
|
||||
common::printIcon('testcase', 'createBug', "product=$case->product&branch=$case->branch&extra=caseID=$caseID,version=$case->version,runID=$runID,executionID=$executionID", $case, 'list', 'bug', '', 'iframe', '', "data-width='90%'", '', $case->project);
|
||||
common::printIcon('testcase', 'create', "productID=$case->product&branch=$case->branch&moduleID=$case->module&from=testcase¶m=$caseID", $case, 'list', 'copy', '', '', '', '', '', $case->project);
|
||||
common::printIcon('testtask', 'runCase', "runID=$runID&caseID=$caseID&version=$case->version", '', 'list', 'play', '', "iframe $disabled", true, "data-width='95%'", '', $case->project);
|
||||
common::printIcon('testtask', 'results', "runID=$runID&caseID=$caseID", '', 'list', 'list-alt', '', 'iframe', true, "data-width='95%'", '', $case->project);
|
||||
common::printIcon('testcase', 'edit', "caseID=$caseID&comment=false&executionID=$executionID", $case, 'list', 'edit', '', '', '', '', '', $case->project);
|
||||
}
|
||||
$case->browseType = $type;
|
||||
echo $this->testcase->buildOperateMenu($case, 'browse');
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
$planIDList = explode(',', $planIDList);
|
||||
foreach($planIDList as $planID)
|
||||
{
|
||||
if(isset($planGroups[$productID][$planID])) echo '<div class="col-xs-12">' . html::a($this->createLink('productplan', 'view', "planID={$planID}"), $product->name . '/' . $planGroups[$productID][$planID]) . '</div>';
|
||||
if(isset($planGroups[$productID][$planID])) echo '<div class="col-xs-12">' . "<i class='icon icon-calendar text-muted'></i> " . html::a($this->createLink('productplan', 'view', "planID={$planID}"), $product->name . '/' . $planGroups[$productID][$planID]) . '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1404,7 +1404,6 @@ $lang->sonarqube->methodOrder[50] = 'browseIssue';
|
||||
/* merge request. */
|
||||
$lang->resource->mr = new stdclass();
|
||||
$lang->resource->mr->create = 'create';
|
||||
$lang->resource->mr->apiCreate = 'apiCreate';
|
||||
$lang->resource->mr->browse = 'browse';
|
||||
$lang->resource->mr->edit = 'edit';
|
||||
$lang->resource->mr->delete = 'delete';
|
||||
|
||||
@@ -615,6 +615,7 @@ class kanban extends control
|
||||
}
|
||||
|
||||
$kanban = $from == 'execution' ? $this->loadModel('execution')->getByID($kanbanID) : $this->kanban->getByID($kanbanID);
|
||||
if($from == 'execution') $this->lang->kanbanlane->heightTypeList['auto'] = $this->lang->kanbanlane->heightByCard;
|
||||
|
||||
$this->view->heightType = $kanban->displayCards > 2 ? 'custom' : 'auto';
|
||||
$this->view->displayCards = $kanban->displayCards ? $kanban->displayCards : '';
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#mainContent {padding-left: 0px; height: 500px;}
|
||||
#contactListMenu_chosen {float: left;}
|
||||
#teamBox .input-group .input-group-btn {vertical-align: unset;}
|
||||
#contactListMenu_chosen {vertical-align: unset;}
|
||||
#teamBox .input-group .input-group-btn {vertical-align: top;}
|
||||
|
||||
@@ -102,7 +102,8 @@
|
||||
.cardcolor {width:40px; height: 14px; float: left; margin-left: 5px; margin-right: 5px; margin-top: 2px; border-radius: 2px;}
|
||||
#cardcolormenu {padding:2px 2px; width: 100px;}
|
||||
|
||||
.position {margin-top: -6px;}
|
||||
.region-header {margin-top: -6px;}
|
||||
.region-header > .icon{padding: 6px; margin-left:2px;}
|
||||
.kanban-col[data-type=ADD] {display: none;}
|
||||
.kanban-col[data-type=EMPTY] {display: none;}
|
||||
.kanban-col {padding-right: 0px !important;}
|
||||
|
||||
@@ -1387,7 +1387,7 @@ $(function()
|
||||
$(this).toggleClass('icon-angle-top icon-angle-down');
|
||||
$(this).parents('.region').find('.kanban').toggle();
|
||||
hideKanbanAction();
|
||||
resetRegionHeight($(this).hasClass('icon-chevron-double-up') ? 'open' : 'close');
|
||||
resetRegionHeight($(this).hasClass('icon-angle-top') ? 'open' : 'close');
|
||||
});
|
||||
|
||||
$('.region-header').on('click', '.action', hideKanbanAction);
|
||||
@@ -1700,6 +1700,7 @@ function resetRegionHeight(fold)
|
||||
{
|
||||
$('.region').css('height', regionHeaderHeight);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$(document).on('click', '.dropdown-menu', function()
|
||||
|
||||
@@ -308,13 +308,14 @@ $lang->kanbancolumn->confirmDeleteChild = 'Are you sure to delete this column? A
|
||||
$lang->kanbancolumn->confirmRestore = 'Are you sure you want to restore this Kanban column? After restoring the Kanban column, the Kanban column and all tasks in the Kanban column will be restored to the previous position at the same time.';
|
||||
|
||||
$lang->kanbanlane = new stdclass();
|
||||
$lang->kanbanlane->name = $lang->kanban->laneName;
|
||||
$lang->kanbanlane->common = 'Lane';
|
||||
$lang->kanbanlane->default = 'Default Lane';
|
||||
$lang->kanbanlane->column = 'Lane Kanban Column';
|
||||
$lang->kanbanlane->otherlane = 'Select Existed Lane';
|
||||
$lang->kanbanlane->color = 'Lane Color';
|
||||
$lang->kanbanlane->WIPType = 'Lane WIP Type';
|
||||
$lang->kanbanlane->name = $lang->kanban->laneName;
|
||||
$lang->kanbanlane->common = 'Lane';
|
||||
$lang->kanbanlane->default = 'Default Lane';
|
||||
$lang->kanbanlane->column = 'Lane Kanban Column';
|
||||
$lang->kanbanlane->otherlane = 'Select Existed Lane';
|
||||
$lang->kanbanlane->color = 'Lane Color';
|
||||
$lang->kanbanlane->WIPType = 'Lane WIP Type';
|
||||
$lang->kanbanlane->heightByCard = 'Adaptive (Adaptive to card height)';
|
||||
|
||||
$lang->kanbanlane->confirmDelete = 'Are you sure to delete this lane? After deleting the lane, all data (columns and cards) in the lane will also be deleted.';
|
||||
$lang->kanbanlane->confirmDeleteTip = 'Are you sure to delete this lane? After deleting the lane, all %s in the lane will be hidden.';
|
||||
|
||||
@@ -308,13 +308,14 @@ $lang->kanbancolumn->confirmDeleteChild = '您确认删除该列吗?删除列
|
||||
$lang->kanbancolumn->confirmRestore = '您确定要还原该看板列吗?还原后,该看板列将回到之前的位置。';
|
||||
|
||||
$lang->kanbanlane = new stdclass();
|
||||
$lang->kanbanlane->name = $lang->kanban->laneName;
|
||||
$lang->kanbanlane->common = '泳道';
|
||||
$lang->kanbanlane->default = '默认泳道';
|
||||
$lang->kanbanlane->column = '泳道看板列';
|
||||
$lang->kanbanlane->otherlane = '选择共享看板列的泳道';
|
||||
$lang->kanbanlane->color = '泳道颜色';
|
||||
$lang->kanbanlane->WIPType = '泳道在制品类型';
|
||||
$lang->kanbanlane->name = $lang->kanban->laneName;
|
||||
$lang->kanbanlane->common = '泳道';
|
||||
$lang->kanbanlane->default = '默认泳道';
|
||||
$lang->kanbanlane->column = '泳道看板列';
|
||||
$lang->kanbanlane->otherlane = '选择共享看板列的泳道';
|
||||
$lang->kanbanlane->color = '泳道颜色';
|
||||
$lang->kanbanlane->WIPType = '泳道在制品类型';
|
||||
$lang->kanbanlane->heightByCard = '自适应(根据卡片高度自适应)';
|
||||
|
||||
$lang->kanbanlane->confirmDelete = '您确认删除该泳道吗?删除泳道后,该泳道中所有数据(列、卡片)也会被删除。';
|
||||
$lang->kanbanlane->confirmDeleteTip = '您确认删除该泳道吗?删除泳道后,该泳道中所有的%s将被隐藏。';
|
||||
|
||||
@@ -57,7 +57,7 @@ $canCreateLane = commonModel::hasPriv('kanban', 'createLane');
|
||||
<div class="region<?php if($canSortRegion) echo ' sort';?>" data-id="<?php echo $region->id;?>">
|
||||
<div class="region-header dropdown">
|
||||
<strong><?php echo $region->name;?></strong>
|
||||
<button class="btn btn-link action position"><i class="icon icon-angle-top" data-id="<?php echo $region->id;?>"></i></button>
|
||||
<i class="icon icon-angle-top btn-link" data-id="<?php echo $region->id;?>"></i>
|
||||
<div class='region-actions'>
|
||||
<?php if(($canEditRegion || $canCreateLane || $canDeleteRegion) and !(isset($this->config->CRKanban) and $this->config->CRKanban == '0' and $kanban->status == 'closed')):?>
|
||||
<button class="btn btn-link action" type="button" data-toggle="dropdown"><i class="icon icon-ellipsis-v"></i></button>
|
||||
|
||||
@@ -142,7 +142,7 @@ class message extends control
|
||||
else
|
||||
{
|
||||
echo <<<EOT
|
||||
<div class='alert alert-info with-icon alert-dismissable' style='width:380px; position:fixed; bottom:25px; right:15px; z-index: 9999;'>
|
||||
<div class='alert alert-info with-icon alert-dismissable' style='width:380px; position:fixed; margin-bottom:0px; bottom:0px; right:15px; z-index: 9999;'>
|
||||
<i class='icon icon-envelope-o'> </i>
|
||||
<div class='content'>{$messages}</div>
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
|
||||
@@ -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.1'] = '2022-06-16';
|
||||
$lang->misc->releaseDate['17.0'] = '2022-06-02';
|
||||
$lang->misc->releaseDate['17.0.beta2'] = '2022-05-26';
|
||||
$lang->misc->releaseDate['17.0.beta1'] = '2022-05-06';
|
||||
@@ -182,6 +183,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.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' => '');
|
||||
$lang->misc->feature->all['17.0.beta2'][] = array('title' => 'The detail experience is optimized, fix bugs.', 'desc' => '');
|
||||
$lang->misc->feature->all['17.0.beta1'][] = array('title' => "Complete customer's high priority requirements", 'desc' => '');
|
||||
|
||||
@@ -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.1'] = '2022-06-16';
|
||||
$lang->misc->releaseDate['17.0'] = '2022-06-02';
|
||||
$lang->misc->releaseDate['17.0.beta2'] = '2022-05-26';
|
||||
$lang->misc->releaseDate['17.0.beta1'] = '2022-05-06';
|
||||
@@ -182,6 +183,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.1'][] = array('title' => '修改执行、项目模块的交互问题,完成客户巴高优先级需求,细节体验优化。修复Bug。', 'desc' => '');
|
||||
$lang->misc->feature->all['17.0'][] = array('title' => '细节体验优化。修复Bug。', 'desc' => '');
|
||||
$lang->misc->feature->all['17.0.beta2'][] = array('title' => '细节体验优化。修复Bug。', 'desc' => '');
|
||||
$lang->misc->feature->all['17.0.beta1'][] = array('title' => '完成客户巴高优先级需求。修复Bug。', 'desc' => '');
|
||||
|
||||
@@ -99,30 +99,6 @@ class mr extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create MR function by api.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function apiCreate()
|
||||
{
|
||||
if($_POST)
|
||||
{
|
||||
$this->mr->apiCreate();
|
||||
|
||||
$response['result'] = 'success';
|
||||
$response['message'] = $this->lang->saveSuccess;
|
||||
if(dao::isError())
|
||||
{
|
||||
$response['result'] = 'fail';
|
||||
$response['message'] = join("\n", dao::getError());
|
||||
}
|
||||
|
||||
return $this->send($response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit MR function.
|
||||
*
|
||||
|
||||
+14
-18
@@ -249,32 +249,30 @@ class mrModel extends model
|
||||
public function apiCreate()
|
||||
{
|
||||
$postData = fixer::input('post')->get();
|
||||
$postData = (object)$postData->data;
|
||||
|
||||
$repo = $this->loadModel('repo')->getRepoByUrl($postData->RepoUrl);
|
||||
if(empty($repo['data']))
|
||||
$repo = $this->dao->findByID($postData->repoID)->from(TABLE_REPO)->fetch();
|
||||
if(empty($repo))
|
||||
{
|
||||
dao::$errors[] = $repo['message'];
|
||||
dao::$errors[] = 'No matched gitlab.';
|
||||
return false;
|
||||
}
|
||||
$repo = $repo['data'];
|
||||
|
||||
/* Process and insert mr data. */
|
||||
$MR = new stdClass();
|
||||
$MR->gitlabID = $repo->client;
|
||||
$MR->sourceProject = $repo->path;
|
||||
$MR->sourceBranch = $postData->RepoSrcBranch;
|
||||
$MR->sourceBranch = $postData->sourceBranch;
|
||||
$MR->targetProject = $repo->path;
|
||||
$MR->targetBranch = $postData->RepoDistBranch;
|
||||
$MR->diffs = $this->post->data['DiffMsg'];
|
||||
$MR->title = $this->lang->mr->common . ' ' . $postData->RepoSrcBranch . $this->lang->mr->to . $postData->RepoDistBranch ;
|
||||
$MR->targetBranch = $postData->targetBranch;
|
||||
$MR->diffs = $postData->diffs;
|
||||
$MR->title = $this->lang->mr->common . ' ' . $postData->sourceBranch . $this->lang->mr->to . $postData->targetBranch ;
|
||||
$MR->repoID = $repo->id;
|
||||
$MR->jobID = isset($repo->job->id) ? $repo->job->id : 0;
|
||||
$MR->jobID = $postData->jobID;
|
||||
$MR->status = 'opened';
|
||||
$MR->synced = '0';
|
||||
$MR->needCI = '1';
|
||||
$MR->hasNoConflict = $postData->MergeStatus ? '0' : '1';
|
||||
$MR->mergeStatus = $postData->MergeStatus ? 'can_be_merged' : 'cannot_be_merged';
|
||||
$MR->hasNoConflict = $postData->mergeStatus ? '0' : '1';
|
||||
$MR->mergeStatus = $postData->mergeStatus ? 'can_be_merged' : 'cannot_be_merged';
|
||||
$MR->createdBy = $this->app->user->account;
|
||||
$MR->createdDate = date('Y-m-d H:i:s');
|
||||
|
||||
@@ -303,11 +301,9 @@ class mrModel extends model
|
||||
/* Exec Job */
|
||||
if($MR->hasNoConflict == '0' && $MR->mergeStatus == 'can_be_merged' && $MR->jobID)
|
||||
{
|
||||
$extraParam = array();
|
||||
if(!empty($repo->fileServerUrl)) $extraParam = array('ZENTAO_REPOPATH' => $repo->fileServerUrl);
|
||||
|
||||
$pipeline = $this->loadModel('job')->exec($MR->jobID, $extraParam);
|
||||
$newMR = new stdClass();
|
||||
$extraParam = array('sourceBranch' => $MR->sourceBranch, 'targetBranch' => $MR->targetBranch);
|
||||
$pipeline = $this->loadModel('job')->exec($MR->jobID, $extraParam);
|
||||
$newMR = new stdClass();
|
||||
if(!empty($pipeline->queue))
|
||||
{
|
||||
$compile = $this->loadModel('compile')->getByQueue($pipeline->queue);
|
||||
@@ -325,7 +321,7 @@ class mrModel extends model
|
||||
$this->dao->update(TABLE_MR)->data($newMR)->where('id')->eq($MRID)->autoCheck()->exec();
|
||||
if(dao::isError()) return false;
|
||||
}
|
||||
return true;
|
||||
return $MRID;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+13
-10
@@ -462,33 +462,35 @@ class product extends control
|
||||
if(!empty($unmodifiableProjects)) $canChangeProgram = false;
|
||||
|
||||
/* Get the projects linked with this product. */
|
||||
$projectPairs = $this->dao->select('t2.id,t2.name')->from(TABLE_PROJECTPRODUCT)->alias('t1')
|
||||
$projects = $this->dao->select('t2.id,t2.name,t2.path')->from(TABLE_PROJECTPRODUCT)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
|
||||
->where('t1.product')->eq($productID)
|
||||
->andWhere('t2.type')->eq('project')
|
||||
->andWhere('t2.deleted')->eq('0')
|
||||
->fetchPairs();
|
||||
->fetchAll('id');
|
||||
|
||||
if(!empty($projectPairs))
|
||||
$projectPathList = array();
|
||||
if(!empty($projects))
|
||||
{
|
||||
foreach($projectPairs as $projectID => $projectName)
|
||||
foreach($projects as $projectID => $project)
|
||||
{
|
||||
$projectPathList[$projectID] = $project->path;
|
||||
if($canChangeProgram)
|
||||
{
|
||||
$products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->fetchPairs();
|
||||
if(count($products) == 1)
|
||||
{
|
||||
$singleLinkProjects[$projectID] = $projectName;
|
||||
$singleLinkProjects[$projectID] = $project->name;
|
||||
}
|
||||
|
||||
if(count($products) > 1)
|
||||
{
|
||||
$multipleLinkProjects[$projectID] = $projectName;
|
||||
$multipleLinkProjects[$projectID] = $project->name;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isset($unmodifiableProjects[$projectID])) $linkStoriesProjects[$projectID] = $projectName;
|
||||
if(isset($unmodifiableProjects[$projectID])) $linkStoriesProjects[$projectID] = $project->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -579,6 +581,7 @@ class product extends control
|
||||
$this->view->singleLinkProjects = $singleLinkProjects;
|
||||
$this->view->multipleLinkProjects = $multipleLinkProjects;
|
||||
$this->view->linkStoriesProjects = $linkStoriesProjects;
|
||||
$this->view->projectPathList = $projectPathList;
|
||||
|
||||
unset($this->lang->product->typeList['']);
|
||||
$this->display();
|
||||
@@ -1255,10 +1258,10 @@ class product extends control
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
/* Process product structure. */
|
||||
if($this->config->systemMode == 'classic' and $orderBy == 'program_asc') $orderBy = 'order_desc';
|
||||
$productStats = $this->product->getStats($orderBy, $pager, $browseType, '', 'story', '', $queryID);
|
||||
$productStructure = $this->product->statisticProgram($productStats);
|
||||
$productLines = $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('deleted')->eq(0)->orderBy('`order`')->fetchAll();
|
||||
array_multisort(array_column($productLines, 'order'), SORT_ASC, $productLines);
|
||||
$productLines = $this->dao->select('*')->from(TABLE_MODULE)->where('type')->eq('line')->andWhere('deleted')->eq(0)->orderBy('`order` asc')->fetchAll();
|
||||
$programLines = array();
|
||||
|
||||
foreach($productLines as $index => $productLine)
|
||||
@@ -1267,7 +1270,7 @@ class product extends control
|
||||
$programLines[$productLine->root][$productLine->id] = $productLine->name;
|
||||
}
|
||||
|
||||
$actionURL = $this->createLink('product', 'all', "browseType=bySearch&orderBy=order_asc&queryID=myQueryID");
|
||||
$actionURL = $this->createLink('product', 'all', "browseType=bySearch&orderBy=order_desc&queryID=myQueryID");
|
||||
$this->product->buildProductSearchForm($param, $actionURL);
|
||||
|
||||
$this->view->title = $this->lang->product->common;
|
||||
|
||||
@@ -43,7 +43,7 @@ th.c-story {width: 290px;}
|
||||
th.c-bug {width: 200px;}
|
||||
th.c-plan {width: 45px;}
|
||||
th.c-release {width: 50px;}
|
||||
th.c-actions {width: 60px;}
|
||||
th.c-actions {width: 50px;}
|
||||
[lang='en'] .en-wrap-text {white-space: normal; height: 24px; line-height: 1; font-size: 12px;}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,15 @@ $(function()
|
||||
$('#program').change(function()
|
||||
{
|
||||
var programID = $(this).val();
|
||||
if(!canChangeProgram || singleLinkProjects.length !== 0 || multipleLinkProjects.length !== 0)
|
||||
var canChange = true;
|
||||
for(var i = 0; i < linkStoriesProjectIDList.length; i ++)
|
||||
{
|
||||
var projectID = linkStoriesProjectIDList[i];
|
||||
var path = projectPathList[projectID];
|
||||
if(path.indexOf(',' + programID + ',') < 0) canChange = false;
|
||||
}
|
||||
|
||||
if(!canChange && (!canChangeProgram || singleLinkProjects.length !== 0 || multipleLinkProjects.length !== 0))
|
||||
{
|
||||
$('#changeProgram').modal({show: true});
|
||||
if(!canChangeProgram)
|
||||
|
||||
@@ -89,7 +89,7 @@ $lang->product->programChangeTip = "如下项目只关联了该{$lang->produ
|
||||
$lang->product->notChangeProgramTip = "该{$lang->productCommon}的{$lang->SRCommon}已经关联到如下项目,请取消关联后再操作";
|
||||
$lang->product->confirmChangeProgram = "如下项目既关联了该{$lang->productCommon}又关联了其他{$lang->productCommon},请确认是否继续关联该{$lang->productCommon},勾选后将取消与其他{$lang->productCommon}的关联关系,同时转移至新项目集下。";
|
||||
$lang->product->changeProgramError = "该{$lang->productCommon}的{$lang->SRCommon}已经关联到项目,请取消关联后再操作";
|
||||
$lang->product->changeLineError = "产品线下已有产品,不可修改所属项目集";
|
||||
$lang->product->changeLineError = "产品线下已有产品,不可修改所属项目集。";
|
||||
$lang->product->programEmpty = '项目集不能为空';
|
||||
$lang->product->nameIsDuplicate = "『%s』产品线已经存在,请重新设置!";
|
||||
$lang->product->nameIsDuplicated = "产品线已经有『%s』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。";
|
||||
|
||||
@@ -760,25 +760,6 @@ class productModel extends model
|
||||
->remove('uid,changeProjects,contactListMenu')
|
||||
->get();
|
||||
|
||||
if($this->config->systemMode == 'new')
|
||||
{
|
||||
if($product->program != $oldProduct->program)
|
||||
{
|
||||
/* Link the projects stories under this product. */
|
||||
$unmodifiableProjects = $this->dao->select('t1.*')->from(TABLE_PROJECTSTORY)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
|
||||
->where('t1.product')->eq($productID)
|
||||
->andWhere('t2.type')->eq('project')
|
||||
->andWhere('t2.deleted')->eq('0')
|
||||
->fetchPairs('project', 'product');
|
||||
if(!empty($unmodifiableProjects))
|
||||
{
|
||||
dao::$errors[] = $this->lang->product->changeProgramError;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$product = $this->loadModel('file')->processImgURL($product, $this->config->product->editor->edit['id'], $this->post->uid);
|
||||
$programID = isset($product->program) ? $product->program : '';
|
||||
$this->dao->update(TABLE_PRODUCT)->data($product)->autoCheck()
|
||||
@@ -917,13 +898,16 @@ class productModel extends model
|
||||
$data = fixer::input('post')->get();
|
||||
|
||||
/* When there are products under the line, the program cannot be modified */
|
||||
foreach($oldLines as $oldLine)
|
||||
if($this->config->systemMode == 'new')
|
||||
{
|
||||
$oldLineID = 'id' . $oldLine->id;
|
||||
if($data->programs[$oldLineID] != $oldLine->root)
|
||||
foreach($oldLines as $oldLine)
|
||||
{
|
||||
$product = $this->dao->select('*')->from(TABLE_PRODUCT)->where('line')->eq($oldLine->id)->fetch();
|
||||
if(!empty($product)) return print(js::error($this->lang->product->changeLineError));
|
||||
$oldLineID = 'id' . $oldLine->id;
|
||||
if($data->programs[$oldLineID] != $oldLine->root)
|
||||
{
|
||||
$product = $this->dao->select('*')->from(TABLE_PRODUCT)->where('line')->eq($oldLine->id)->fetch();
|
||||
if(!empty($product)) return print(js::error($this->lang->product->changeLineError));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2157,7 +2141,6 @@ class productModel extends model
|
||||
$menu .= $this->buildMenu('product', 'edit', $params, $product, $type);
|
||||
|
||||
if($type == 'view') $menu .= $this->buildMenu('product', 'delete', $params, $product, $type, 'trash', 'hiddenwin');
|
||||
if($type == 'browse' && common::hasPriv('product', 'updateOrder')) $menu .= "<i class='icon icon-move text-blue'></i>";
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
<?php if($canBatchEdit):?>
|
||||
<td class='c-checkbox'><?php echo html::checkbox('productIDList', array($product->id => ''));?></td>
|
||||
<?php endif;?>
|
||||
<td class="c-name text-left table-nest-title" title='<?php echo $product->name?>'>
|
||||
<td class="c-name text-left sort-handler table-nest-title" title='<?php echo $product->name?>'>
|
||||
<?php
|
||||
$productLink = html::a($this->createLink('product', 'browse', 'productID=' . $product->id), $product->name);
|
||||
echo "<span class='table-nest-icon icon icon-product'></span>" . $productLink;
|
||||
@@ -229,7 +229,7 @@
|
||||
<td><?php echo $product->plans;?></td>
|
||||
<td><?php echo $product->releases;?></td>
|
||||
<?php foreach($extendFields as $extendField) echo "<td>" . $this->loadModel('flow')->getFieldValue($extendField, $product) . "</td>";?>
|
||||
<td class='c-actions sort-handler'><?php echo $this->product->buildOperateMenu($product, 'browse');?></td>
|
||||
<td class='c-actions'><?php echo $this->product->buildOperateMenu($product, 'browse');?></td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
<?php js::set('canChangeProgram', $canChangeProgram);?>
|
||||
<?php js::set('singleLinkProjects', $singleLinkProjects);?>
|
||||
<?php js::set('multipleLinkProjects', $multipleLinkProjects);?>
|
||||
<?php js::set('linkStoriesProjectIDList', array_keys($linkStoriesProjects));?>
|
||||
<?php js::set('projectPathList', $projectPathList);?>
|
||||
<style>
|
||||
#changeProgram .icon-project {padding-right: 5px;}
|
||||
</style>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
tbody.sortable > tr > td.sort-handler .table-nest-toggle:before {cursor: pointer !important;}
|
||||
.table .avatar {display: inline-block; top: 6px;}
|
||||
|
||||
label[for^="projectIdList"]:before {top: 1px; width:14px; height:14px;}
|
||||
label[for^="projectIdList"]:after {width: 14px; height:14px;}
|
||||
tbody.sortable > tr > td.sort-handler {color: #3c4353 !important;}
|
||||
|
||||
@@ -13,3 +12,5 @@ tbody.sortable > tr > td.sort-handler {color: #3c4353 !important;}
|
||||
.has-prefix > a {padding-left: 5px;}
|
||||
|
||||
.has-suffix > a {max-width: calc(100% - 100px); padding-right: 5px; color: #0c60e1; display: inline-block; max-width: calc(100% - 50px);}
|
||||
|
||||
div.checkbox-primary + span.table-nest-icon {margin-left:0px !important;}
|
||||
|
||||
@@ -47,16 +47,16 @@ $(function()
|
||||
|
||||
function showEditCheckbox(show)
|
||||
{
|
||||
$('.icon-project,.icon-waterfall,.icon-scrum').each(function()
|
||||
$('.icon-project,.icon-waterfall,.icon-scrum,.icon-kanban').each(function()
|
||||
{
|
||||
$this = $(this);
|
||||
$tr = $(this).closest('tr');
|
||||
projectID = $tr.attr('data-id');
|
||||
if(show)
|
||||
{
|
||||
$tr.find('td:first').prepend("<div class='checkbox-primary'><input type='checkbox' name='projectIdList[]' value='" + projectID + "' id='projectIdList" + projectID + "'/><label for='projectIdList" + projectID + "'></lable></div>");
|
||||
|
||||
var marginLeft = $tr.find('td:first').find('span.table-nest-icon').css('margin-left');
|
||||
|
||||
$tr.find('td:first').prepend("<div class='checkbox-primary'><input type='checkbox' name='projectIdList[]' value='" + projectID + "' id='projectIdList" + projectID + "'/><label for='projectIdList" + projectID + "'></lable></div>");
|
||||
$tr.find('td:first').find('.checkbox-primary').css('margin-left', marginLeft).css('width', '14');
|
||||
$tr.find('td:first').find('span.table-nest-icon').css('margin-left', '0');
|
||||
}
|
||||
|
||||
@@ -1326,7 +1326,7 @@ class programModel extends model
|
||||
{
|
||||
$parent = $this->dao->select('id,parent,path,grade')->from(TABLE_PROGRAM)->where('id')->eq($parentID)->fetch();
|
||||
|
||||
$childNodes = $this->dao->select('id,parent,path,grade')->from(TABLE_PROGRAM)
|
||||
$childNodes = $this->dao->select('id,parent,path,grade,type')->from(TABLE_PROGRAM)
|
||||
->where('path')->like("{$oldPath}%")
|
||||
->andWhere('deleted')->eq(0)
|
||||
->orderBy('grade')
|
||||
@@ -1335,13 +1335,16 @@ class programModel extends model
|
||||
/* Process child node path and grade field. */
|
||||
foreach($childNodes as $childNode)
|
||||
{
|
||||
$path = substr($childNode->path, strpos($childNode->path, ",{$programID},"));
|
||||
$grade = $childNode->grade - $oldGrade + 1;
|
||||
$path = substr($childNode->path, strpos($childNode->path, ",{$programID},"));
|
||||
|
||||
/* Only program and project sets update grade. */
|
||||
$grade = in_array($childNode->type, array('program', 'project')) ? $childNode->grade - $oldGrade + 1 : $childNode->grade;
|
||||
if($parent)
|
||||
{
|
||||
$path = rtrim($parent->path, ',') . $path;
|
||||
$grade = $parent->grade + $grade;
|
||||
$grade = in_array($childNode->type, array('program', 'project'))? $parent->grade + $grade : $grade;
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_PROGRAM)->set('path')->eq($path)->set('grade')->eq($grade)->where('id')->eq($childNode->id)->exec();
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +285,11 @@ $('#planForm').submit(function()
|
||||
}
|
||||
});
|
||||
|
||||
if(!submitForm) return false;
|
||||
if(!submitForm)
|
||||
{
|
||||
setTimeout(function(){$('#submit').removeAttr('disabled')}, 500);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -78,7 +78,7 @@ class project extends control
|
||||
if($this->config->edition != 'open') list($fields, $projects) = $this->loadModel('workflowfield')->appendDataFromFlow($fields, $projects);
|
||||
$this->post->set('fields', $fields);
|
||||
$this->post->set('rows', $projects);
|
||||
$this->post->set('kind', 'project');
|
||||
$this->post->set('kind', $this->lang->project->common);
|
||||
$this->fetch('file', 'export2' . $this->post->fileType, $_POST);
|
||||
}
|
||||
|
||||
@@ -710,8 +710,6 @@ class project extends control
|
||||
return print(js::locate($this->session->projectList, 'parent'));
|
||||
}
|
||||
|
||||
if($this->app->tab == 'program') $this->loadModel('program')->setMenu(0);
|
||||
|
||||
if(!$this->post->projectIdList) return print(js::locate($this->session->projectList, 'parent'));
|
||||
$projectIdList = $this->post->projectIdList;
|
||||
$projects = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->in($projectIdList)->fetchAll('id');
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#productsBox a {border-radius: 2px !important;}
|
||||
#productsBox .col-sm-4 {padding-right: 5px;}
|
||||
#productsBox .addProduct {padding-left: 0px !important;}
|
||||
#productsBox > .required:after{right: -6px !important;}
|
||||
#productsBox .required:after{right: -6px !important;}
|
||||
#productsBox .input-group-addon > div {display: inline-block !important;}
|
||||
#plansBox .row {display: inline-table; width: 102%;}
|
||||
#plansBox .col-sm-4 {float: none; display: inline-block; padding-right: 5px;}
|
||||
|
||||
@@ -2130,6 +2130,9 @@ class projectModel extends model
|
||||
$data->product = $productID;
|
||||
$data->branch = $branch;
|
||||
$data->plan = isset($plans[$productID][$branch]) ? implode(',', $plans[$productID][$branch]) : $oldPlan;
|
||||
$data->plan = trim($data->plan, ',');
|
||||
$data->plan = empty($data->plan) ? 0 : ",$data->plan,";
|
||||
|
||||
$this->dao->insert(TABLE_PROJECTPRODUCT)->data($data)->exec();
|
||||
$existedProducts[$productID][$branch] = true;
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
<?php $planIDList = explode(',', $planIDList);?>
|
||||
<?php foreach($planIDList as $planID):?>
|
||||
<?php if(isset($planGroup[$productID][$planID])):?>
|
||||
<div class="col-xs-12"><?php echo html::a($this->createLink('productplan', 'view', "planID={$planID}"), $product->name . '/' . $planGroup[$productID][$planID]);?></div>
|
||||
<div class="col-xs-12"><?php echo html::a($this->createLink('productplan', 'view', "planID={$planID}"), "<i class='icon icon-calendar text-muted'></i> " . $product->name . '/' . $planGroup[$productID][$planID]);?></div>
|
||||
<?php endif;?>
|
||||
<?php endforeach;?>
|
||||
<?php endforeach;?>
|
||||
|
||||
@@ -552,6 +552,10 @@ class repoModel extends model
|
||||
->andWhere('deleted')->eq('0')
|
||||
->orderBy('id_desc')
|
||||
->fetchAll();
|
||||
foreach($matchedRepos as $key => $repo)
|
||||
{
|
||||
if(!$this->checkPriv($repo)) unset($matchedRepos[$key]);
|
||||
}
|
||||
if(empty($matchedRepos)) return array('status' => 'fail', 'message' => 'No matched gitlab.');
|
||||
|
||||
return array('status' => 'success', 'repos' => $matchedRepos);
|
||||
|
||||
@@ -2902,7 +2902,7 @@ class storyModel extends model
|
||||
$storyIdList = $this->dao->select('story')->from(TABLE_PROJECTSTORY)->where('project')->in(array_keys($executions))->fetchPairs();
|
||||
}
|
||||
|
||||
$type = ($type == 'bymodule' and $this->session->storyBrowseType) ? $this->session->storyBrowseType : $type;
|
||||
$type = (strpos('bymodule|byproduct', $type) !== false and $this->session->storyBrowseType) ? $this->session->storyBrowseType : $type;
|
||||
|
||||
$stories = $this->dao->select('distinct t1.*, t2.*,t3.type as productType,t2.version as version')->from(TABLE_PROJECTSTORY)->alias('t1')
|
||||
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
|
||||
|
||||
@@ -73,14 +73,14 @@ foreach(explode(',', $showFields) as $field)
|
||||
<td class='text-left<?php echo zget($visibleFields, 'branch', ' hidden')?>'>
|
||||
<?php $disabled = $products[$story->product]->type == 'normal' ? "disabled='disabled'" : '';?>
|
||||
<?php if($products[$story->product]->type == 'normal') $branchTagOption[$story->product] = array();?>
|
||||
<?php echo html::select("branches[$storyID]", $branchTagOption[$story->product], $story->branch, "class='form-control picker-select' onchange='loadBranches($story->product, this.value, $storyID);' $disabled");?>
|
||||
<?php echo html::select("branches[$storyID]", $branchTagOption[$story->product], $story->branch, "class='form-control picker-select' data-drop-width='auto' onchange='loadBranches($story->product, this.value, $storyID);' $disabled");?>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'module')?>'>
|
||||
<?php echo html::select("modules[$storyID]", zget($moduleList, $story->id, array(0 => '/')), $story->module, "class='form-control picker-select'");?>
|
||||
<?php echo html::select("modules[$storyID]", zget($moduleList, $story->id, array(0 => '/')), $story->module, "class='form-control picker-select' data-drop-width='auto'");?>
|
||||
</td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'plan', ' hidden')?>'>
|
||||
<?php echo html::select("plans[$storyID]", isset($plans[$story->product][$story->branch]) ? array('' => '') + $plans[$story->product][$story->branch] : '', $story->plan, "class='form-control picker-select'");?>
|
||||
<?php echo html::select("plans[$storyID]", isset($plans[$story->product][$story->branch]) ? array('' => '') + $plans[$story->product][$story->branch] : '', $story->plan, "class='form-control picker-select' data-drop-width='auto'");?>
|
||||
</td>
|
||||
<td title='<?php echo $story->title?>'>
|
||||
<div class="input-group">
|
||||
@@ -100,15 +100,15 @@ foreach(explode(',', $showFields) as $field)
|
||||
</td>
|
||||
|
||||
<td <?php echo zget($visibleFields, 'estimate', "class='hidden'")?>><?php echo html::input("estimates[$storyID]", $story->estimate, "class='form-control'"); ?></td>
|
||||
<td><?php echo html::select("category[$storyID]", $lang->story->categoryList, $story->category, 'class=form-control picker-select');?></td>
|
||||
<td><?php echo html::select("category[$storyID]", $lang->story->categoryList, $story->category, 'class="form-control picker-select" data-drop-width="auto"');?></td>
|
||||
<td <?php echo zget($visibleFields, 'pri', "class='hidden'")?>><?php echo html::select("pris[$storyID]", $priList, $story->pri, 'class=form-control');?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'assignedTo', ' hidden')?>'><?php echo html::select("assignedTo[$storyID]", $users, $story->assignedTo, "class='form-control picker-select'");?></td>
|
||||
<td <?php echo zget($visibleFields, 'source', "class='hidden'")?>><?php echo html::select("sources[$storyID]", $sourceList, $story->source, "class='form-control picker-select' id='source_$storyID'");?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'assignedTo', ' hidden')?>'><?php echo html::select("assignedTo[$storyID]", $users, $story->assignedTo, "class='form-control picker-select' data-drop-width='auto'");?></td>
|
||||
<td <?php echo zget($visibleFields, 'source', "class='hidden'")?>><?php echo html::select("sources[$storyID]", $sourceList, $story->source, "class='form-control picker-select' data-drop-width='auto' id='source_$storyID'");?></td>
|
||||
<?php
|
||||
if($story->source == 'meeting' or $story->source == 'researchreport')
|
||||
{
|
||||
$objects = $story->source == 'meeting' ? $meetings : $researchReports;
|
||||
$html = html::select("sourceNote[$storyID]", $objects, $story->sourceNote, "class='form-control picker-select' id='sourceNote_$storyID'");
|
||||
$html = html::select("sourceNote[$storyID]", $objects, $story->sourceNote, "class='form-control picker-select' data-drop-width='auto' id='sourceNote_$storyID'");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -118,7 +118,7 @@ foreach(explode(',', $showFields) as $field)
|
||||
<td class='<?php echo zget($visibleFields, 'source', 'hidden')?>' data-id="<?php echo $story->sourceNote;?>"><?php echo $html;?></td>
|
||||
<td class='story-<?php echo $story->status;?>'><?php echo $this->processStatus('story', $story);?></td>
|
||||
<td <?php echo zget($visibleFields, 'stage', "class='hidden'")?>><?php echo html::select("stages[$storyID]", $stageList, $story->stage, 'class="form-control"' . ($story->status == 'draft' ? ' disabled="disabled"' : ''));?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'closedBy', ' hidden')?>'><?php echo html::select("closedBys[$storyID]", $users, $story->closedBy, "class='form-control" . ($story->status == 'closed' ? " picker-select'" : "' disabled='disabled'"));?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'closedBy', ' hidden')?>'><?php echo html::select("closedBys[$storyID]", $users, $story->closedBy, "class='form-control" . ($story->status == 'closed' ? " picker-select' data-drop-width='auto'" : "' disabled='disabled'"));?></td>
|
||||
|
||||
<?php if($story->status == 'closed'):?>
|
||||
<td <?php echo zget($visibleFields, 'closedReason', "class='hidden'")?>>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<th class='w-80px'><?php echo $lang->story->reviewedBy;?></th>
|
||||
<td colspan="2">
|
||||
<div class="input-group">
|
||||
<?php echo html::select('reviewer[]', $productReviewers, $reviewer, 'class="form-control chosen" multiple');?>
|
||||
<?php echo html::select('reviewer[]', $productReviewers, $reviewer, "class='form-control chosen' multiple" . ($this->story->checkForceReview() ? ' required' : ''));?>
|
||||
<?php if(!$this->story->checkForceReview()):?>
|
||||
<span class="input-group-addon">
|
||||
<?php echo html::checkbox('needNotReview', $lang->story->needNotReview, '', "id='needNotReview' {$needReview}");?>
|
||||
|
||||
@@ -124,8 +124,8 @@ js::set('dittoNotice', $dittoNotice);
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'module', ' hidden')?>' style='overflow:visible'><?php echo html::select("modules[$taskID]", $modules, $tasks[$taskID]->module, "class='form-control picker-select'")?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'assignedTo', ' hidden')?>' style='overflow:visible'><?php echo html::select("assignedTos[$taskID]", $taskMembers, $tasks[$taskID]->assignedTo, "class='form-control picker-select' {$disableAssignedTo}");?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'module', ' hidden')?>' style='overflow:visible'><?php echo html::select("modules[$taskID]", $modules, $tasks[$taskID]->module, "class='form-control picker-select' data-drop-width='auto'")?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'assignedTo', ' hidden')?>' style='overflow:visible'><?php echo html::select("assignedTos[$taskID]", $taskMembers, $tasks[$taskID]->assignedTo, "class='form-control picker-select' data-drop-width='auto' {$disableAssignedTo}");?></td>
|
||||
<td><?php echo html::select("types[$taskID]", $typeList, $tasks[$taskID]->type, "class='form-control'");?></td>
|
||||
<td <?php echo zget($visibleFields, 'status', "class='hidden'")?>><?php echo html::select("statuses[$taskID]", $statusList, $tasks[$taskID]->status, "class='form-control' {$disableHour}");?></td>
|
||||
<td <?php echo zget($visibleFields, 'estStarted', "class='hidden'")?>><?php echo html::input("estStarteds[$taskID]", helper::isZeroDate($tasks[$taskID]->estStarted) ? '' : $tasks[$taskID]->estStarted, "class='form-control text-center form-date'");?></td>
|
||||
@@ -134,9 +134,9 @@ js::set('dittoNotice', $dittoNotice);
|
||||
<td <?php echo zget($visibleFields, 'estimate', "class='hidden'")?>><?php echo html::input("estimates[$taskID]", $tasks[$taskID]->estimate, "class='form-control text-center' {$disableHour}");?></td>
|
||||
<td <?php echo zget($visibleFields, 'record', "class='hidden'")?>><?php echo html::input("consumeds[$taskID]", 0, "class='form-control text-center' {$disableHour}");?></td>
|
||||
<td <?php echo zget($visibleFields, 'left', "class='hidden'")?>><?php echo html::input("lefts[$taskID]", $tasks[$taskID]->left, "class='form-control text-center' {$disableHour}");?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'finishedBy', ' hidden')?>' style='overflow:visible'><?php echo html::select("finishedBys[$taskID]", $members, $tasks[$taskID]->finishedBy, "class='form-control picker-select'");?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'canceledBy', ' hidden')?>' style='overflow:visible'><?php echo html::select("canceledBys[$taskID]", $members, $tasks[$taskID]->canceledBy, "class='form-control picker-select'");?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'closedBy', ' hidden')?>' style='overflow:visible'><?php echo html::select("closedBys[$taskID]", $members, $tasks[$taskID]->closedBy, "class='form-control picker-select'");?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'finishedBy', ' hidden')?>' style='overflow:visible'><?php echo html::select("finishedBys[$taskID]", $members, $tasks[$taskID]->finishedBy, "class='form-control picker-select' data-drop-width='auto'");?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'canceledBy', ' hidden')?>' style='overflow:visible'><?php echo html::select("canceledBys[$taskID]", $members, $tasks[$taskID]->canceledBy, "class='form-control picker-select' data-drop-width='auto'");?></td>
|
||||
<td class='text-left<?php echo zget($visibleFields, 'closedBy', ' hidden')?>' style='overflow:visible'><?php echo html::select("closedBys[$taskID]", $members, $tasks[$taskID]->closedBy, "class='form-control picker-select' data-drop-width='auto'");?></td>
|
||||
<td <?php echo zget($visibleFields, 'closedReason', "class='hidden'")?>>
|
||||
<?php
|
||||
$reasonList[''] = '';
|
||||
|
||||
@@ -285,18 +285,16 @@
|
||||
<table class='table table-data'>
|
||||
<?php if($case->fromBug):?>
|
||||
<tr>
|
||||
<th class='thWidth'><?php echo $lang->testcase->fromBug;?></th>
|
||||
<td><?php echo html::a($this->createLink('bug', 'view', "bugID=$case->fromBug", '', true), $case->fromBugTitle, '', "class='iframe' data-width='80%'");?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<?php if($case->toBugs):?>
|
||||
<tr>
|
||||
<th class='thWidth' valign="top"><?php echo $lang->testcase->toBug;?></th>
|
||||
<td>
|
||||
<?php
|
||||
foreach($case->toBugs as $bugID => $bugTitle)
|
||||
{
|
||||
echo '<p style="margin-bottom:0;">' . html::a($this->createLink('bug', 'view', "bugID=$bugID", '', true), $bugTitle, '', "class='iframe' data-width='80%'") . '</p>';
|
||||
echo '<p style="margin-bottom:0;">' . html::a($this->createLink('bug', 'view', "bugID=$bugID", '', true), "#$bugID " . $bugTitle, '', "class='iframe' data-width='80%'") . '</p>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
|
||||
@@ -18,6 +18,7 @@ $config->upgrade->maxVersion['max3_0'] = '16_5';
|
||||
$config->upgrade->maxVersion['max3_1_beta1'] = '17_0_beta1';
|
||||
$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->bizVersion = array();
|
||||
$config->upgrade->bizVersion['biz1_0'] = '9_5_1';
|
||||
@@ -74,6 +75,7 @@ $config->upgrade->bizVersion['biz6_5'] = '16_5';
|
||||
$config->upgrade->bizVersion['biz7_0_beta1'] = '17_0_beta1';
|
||||
$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->proVersion = array();
|
||||
$config->upgrade->proVersion['pro1_0'] = '3_1';
|
||||
|
||||
@@ -159,6 +159,7 @@ $lang->upgrade->fromVersions['16_5'] = '16.5';
|
||||
$lang->upgrade->fromVersions['17_0_beta1'] = '17.0.beta1';
|
||||
$lang->upgrade->fromVersions['17_0_beta2'] = '17.0.beta2';
|
||||
$lang->upgrade->fromVersions['17_0'] = '17.0';
|
||||
$lang->upgrade->fromVersions['17_1'] = '17.1';
|
||||
|
||||
/* Lite. */
|
||||
$lang->upgrade->fromVersions['lite1_0'] = 'Lite1.0';
|
||||
@@ -320,6 +321,7 @@ $lang->upgrade->fromVersions['biz6_5'] = 'Biz6.5';
|
||||
$lang->upgrade->fromVersions['biz7_0_beta1'] = 'Biz7.0.beta1';
|
||||
$lang->upgrade->fromVersions['biz7_0_beta2'] = 'Biz7.0.beta2';
|
||||
$lang->upgrade->fromVersions['biz7_0'] = 'Biz7.0';
|
||||
$lang->upgrade->fromVersions['biz7_1'] = 'Biz7.1';
|
||||
|
||||
/* Max. */
|
||||
$lang->upgrade->fromVersions['max2_0_beta4'] = 'Max2.0.beta4';
|
||||
@@ -339,3 +341,4 @@ $lang->upgrade->fromVersions['max3_0_beta1'] = 'Max3.0.beta1';
|
||||
$lang->upgrade->fromVersions['max3_0'] = 'Max3.0';
|
||||
$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';
|
||||
|
||||
@@ -513,6 +513,7 @@ class upgradeModel extends model
|
||||
break;
|
||||
case '17_0':
|
||||
$this->replaceSetLanePriv();
|
||||
$this->updateProjectData();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6358,4 +6359,82 @@ class upgradeModel extends model
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update path and grade of program, project and execution.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function updateProjectData()
|
||||
{
|
||||
/* Process programs. */
|
||||
$programs = $this->dao->select('id,parent,grade,path')->from(TABLE_PROJECT)->where('type')->eq('program')->orderBy('parent_asc')->fetchAll('id');
|
||||
foreach($programs as $program)
|
||||
{
|
||||
if(!$program->parent)
|
||||
{
|
||||
$program->grade = 1;
|
||||
$program->path = ",$program->id,";
|
||||
}
|
||||
else
|
||||
{
|
||||
$program->grade = $programs[$program->parent]->grade + 1;
|
||||
$program->path = $programs[$program->parent]->path . "$program->id,";
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_PROGRAM)
|
||||
->set('path')->eq($program->path)
|
||||
->set('grade')->eq($program->grade)
|
||||
->where('id')->eq($program->id)->exec();
|
||||
}
|
||||
|
||||
/* Process projects. */
|
||||
$projects = $this->dao->select('id,project,parent,grade,path')->from(TABLE_PROJECT)->where('type')->eq('project')->orderBy('parent_asc')->fetchAll('id');
|
||||
foreach($projects as $project)
|
||||
{
|
||||
if(!$project->parent)
|
||||
{
|
||||
$project->grade = 1;
|
||||
$project->path = ",$project->id,";
|
||||
}
|
||||
else
|
||||
{
|
||||
$project->grade = $programs[$project->parent]->grade + 1;
|
||||
$project->path = $programs[$project->parent]->path . "$project->id,";
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_PROJECT)
|
||||
->set('path')->eq($project->path)
|
||||
->set('grade')->eq($project->grade)
|
||||
->where('id')->eq($project->id)->exec();
|
||||
}
|
||||
|
||||
/* Process executions. */
|
||||
$sprints = $this->dao->select('id,project,parent,grade,path')->from(TABLE_PROJECT)
|
||||
->where('type')->ne('project')
|
||||
->andWhere('type')->ne('program')
|
||||
->orderBy('parent_asc')->fetchAll('id');
|
||||
|
||||
foreach($sprints as $sprint)
|
||||
{
|
||||
if($sprint->parent == $sprint->project)
|
||||
{
|
||||
$sprint->grade = 1;
|
||||
$sprint->path = ",$sprint->project,$sprint->id,";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sprint->grade = 2;
|
||||
$sprint->path = $sprints[$sprint->parent]->path . "$sprint->id,";
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_EXECUTION)
|
||||
->set('path')->eq($sprint->path)
|
||||
->set('grade')->eq($sprint->grade)
|
||||
->where('id')->eq($sprint->id)->exec();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1490,6 +1490,7 @@ class userModel extends model
|
||||
}
|
||||
|
||||
$this->dao->insert(TABLE_USERCONTACT)->data($data)
|
||||
->check('listName', 'unique', "account = '{$data->account}'")
|
||||
->autoCheck()
|
||||
->exec();
|
||||
if(dao::isError()) return false;
|
||||
|
||||
Reference in New Issue
Block a user