This commit is contained in:
tianshujie
2022-06-16 17:11:07 +08:00
19 changed files with 236 additions and 44 deletions
+2
View File
@@ -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';
+42 -5
View File
@@ -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);
+58
View File
@@ -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();
}
}
}
});
}
/**
+2 -2
View File
@@ -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;
+1
View File
@@ -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">
+1
View File
@@ -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'>
+2
View File
@@ -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;
+1 -1
View File
@@ -4220,7 +4220,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';
+19 -12
View File
@@ -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&param=$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>
+1
View File
@@ -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 : '';
+8 -7
View File
@@ -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.';
+8 -7
View File
@@ -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将被隐藏。';
+1 -1
View File
@@ -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;}
-1
View File
@@ -2160,7 +2160,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;
}
+2 -2
View File
@@ -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;?>
+7 -4
View File
@@ -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();
}
+1 -1
View File
@@ -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);
}
+1 -1
View File
@@ -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')
+79
View File
@@ -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;
}
}