Merge branch 'master' of https://gitlab.zcorp.cc/easycorp/zentaopms into sprint/master_lanzongjun_fixbug
This commit is contained in:
@@ -1,14 +1,4 @@
|
||||
<?php
|
||||
$config->url = new stdclass();
|
||||
$config->url->community = 'https://www.zentao.net';
|
||||
$config->url->ask = 'https://www.zentao.net/ask-browse.html';
|
||||
$config->url->document = 'https://www.zentao.net/help-book-zentaopmshelp.html';
|
||||
$config->url->feedback = 'https://www.zentao.net/forum-board-1074.html';
|
||||
$config->url->faq = 'https://www.zentao.net/ask-faq.html';
|
||||
$config->url->extension = 'https://www.zentao.net/extension-browse.html';
|
||||
$config->url->donation = 'https://www.zentao.net/help-donation.html';
|
||||
$config->url->service = 'https://www.cnezsoft.com/article-browse-1078.html';
|
||||
|
||||
$config->admin->apiRoot = 'https://www.zentao.net';
|
||||
|
||||
$config->admin->log = new stdclass();
|
||||
|
||||
@@ -337,11 +337,12 @@ class backup extends control
|
||||
{
|
||||
$this->app->loadLang('extension');
|
||||
|
||||
$search = dirname($this->app->getBasePath()) . DS;
|
||||
$search = $this->app->getBasePath();
|
||||
$pos = strpos($statusFile, $search);
|
||||
if($pos !== false) $statusFile = substr_replace($statusFile, '', $pos, strlen($search));
|
||||
$okFile = $statusFile;
|
||||
if($pos !== false) $okFile = substr_replace($statusFile, '', $pos, strlen($search));
|
||||
|
||||
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $statusFile, $statusFile);
|
||||
$this->view->error = sprintf($this->lang->extension->noticeOkFile, $okFile, $statusFile);
|
||||
return print($this->display());
|
||||
}
|
||||
|
||||
|
||||
+16
-19
@@ -54,7 +54,7 @@ class build extends control
|
||||
|
||||
if(defined('TUTORIAL')) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true)); // Fix bug #21095.
|
||||
|
||||
$buildID = $this->build->create($executionID, $projectID);
|
||||
$buildID = $this->build->create();
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
$this->loadModel('action')->create('build', $buildID, 'opened');
|
||||
|
||||
@@ -72,6 +72,8 @@ class build extends control
|
||||
if($this->app->tab == 'project')
|
||||
{
|
||||
$this->project->setMenu($projectID);
|
||||
$executions = $this->execution->getPairs($projectID, 'all', 'stagefilter');
|
||||
$executionID = empty($executionID) ? key($executions) : $executionID;
|
||||
$productGroups = $this->product->getProducts($projectID);
|
||||
$branchGroups = $this->project->getBranchesByProject($projectID);
|
||||
$this->session->set('project', $projectID);
|
||||
@@ -79,6 +81,7 @@ class build extends control
|
||||
elseif($this->app->tab == 'execution')
|
||||
{
|
||||
$execution = $this->execution->getByID($executionID);
|
||||
$executions = $this->execution->getPairs($execution->project);
|
||||
$projectID = $execution->project;
|
||||
$productGroups = $this->product->getProducts($executionID);
|
||||
$branchGroups = $this->project->getBranchesByProject($executionID);
|
||||
@@ -89,6 +92,7 @@ class build extends control
|
||||
{
|
||||
$execution = $this->execution->getByID($executionID);
|
||||
$projectID = $execution ? $execution->project : 0;
|
||||
$executions = $this->execution->getPairs($projectID);
|
||||
$productGroups = $this->product->getProducts($executionID);
|
||||
$branchGroups = $this->project->getBranchesByProject($executionID);
|
||||
}
|
||||
@@ -119,6 +123,7 @@ class build extends control
|
||||
$this->view->executionID = $executionID;
|
||||
$this->view->products = $products;
|
||||
$this->view->projectID = $projectID;
|
||||
$this->view->executions = $executions;
|
||||
$this->view->lastBuild = $this->build->getLast($executionID, $projectID);
|
||||
$this->view->productGroups = $productGroups;
|
||||
$this->view->users = $this->user->getPairs('nodeleted|noclosed');
|
||||
@@ -255,7 +260,7 @@ class build extends control
|
||||
|
||||
$bugPager = new pager($type == 'bug' ? $recTotal : 0, $recPerPage, $type == 'bug' ? $pageID : 1);
|
||||
$bugs = $this->dao->select('*')->from(TABLE_BUG)
|
||||
->where('id')->in($build->bugs)
|
||||
->where('id')->in($build->allBugs)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->beginIF($type == 'bug')->orderBy($sort)->fi()
|
||||
->page($bugPager)
|
||||
@@ -264,7 +269,7 @@ class build extends control
|
||||
/* Get stories and stages. */
|
||||
$storyPager = new pager($type == 'story' ? $recTotal : 0, $recPerPage, $type == 'story' ? $pageID : 1);
|
||||
$stories = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_STORY)
|
||||
->where('id')->in($build->stories)
|
||||
->where('id')->in($build->allStories)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->beginIF($type == 'story')->orderBy($sort)->fi()
|
||||
->page($storyPager)
|
||||
@@ -277,10 +282,14 @@ class build extends control
|
||||
if($this->app->tab == 'project')
|
||||
{
|
||||
$this->loadModel('project')->setMenu($build->project);
|
||||
$objectType = 'project';
|
||||
$objectID = $build->project;
|
||||
}
|
||||
elseif($this->app->tab == 'execution')
|
||||
{
|
||||
$this->loadModel('execution')->setMenu($build->execution);
|
||||
$objectType = 'execution';
|
||||
$objectID = $build->execution;
|
||||
}
|
||||
|
||||
$executions = $this->loadModel('execution')->getPairs($this->session->project, 'all', 'empty');
|
||||
@@ -297,18 +306,6 @@ class build extends control
|
||||
|
||||
$this->executeHooks($buildID);
|
||||
|
||||
if($this->app->tab == 'execution')
|
||||
{
|
||||
$objectType = 'execution';
|
||||
$objectID = $build->execution;
|
||||
}
|
||||
else
|
||||
{
|
||||
$objectType = 'project';
|
||||
$objectID = $build->project;
|
||||
}
|
||||
|
||||
|
||||
/* Assign. */
|
||||
$this->view->canBeChanged = common::canBeChanged('build', $build); // Determines whether an object is editable.
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||||
@@ -611,11 +608,11 @@ class build extends control
|
||||
$executionID = $build->execution ? $build->execution : $build->project;
|
||||
if($browseType == 'bySearch')
|
||||
{
|
||||
$allStories = $this->story->getBySearch($build->product, $build->branch, $queryID, 'id', $executionID, 'story', $build->stories, $pager);
|
||||
$allStories = $this->story->getBySearch($build->product, $build->branch, $queryID, 'id', $executionID, 'story', $build->allStories, $pager);
|
||||
}
|
||||
else
|
||||
{
|
||||
$allStories = $this->story->getExecutionStories($executionID, $build->product, 0, 't1.`order`_desc', 'byBranch', $build->branch, 'story', $build->stories, $pager);
|
||||
$allStories = $this->story->getExecutionStories($executionID, $build->product, 0, 't1.`order`_desc', 'byBranch', $build->branch, 'story', $build->allStories, $pager);
|
||||
}
|
||||
|
||||
$this->view->allStories = $allStories;
|
||||
@@ -735,11 +732,11 @@ class build extends control
|
||||
$executionID = $build->execution ? $build->execution : $build->project;
|
||||
if($browseType == 'bySearch')
|
||||
{
|
||||
$allBugs = $this->bug->getBySearch($build->product, $build->branch, $queryID, 'id_desc', $build->bugs, $pager, $build->project);
|
||||
$allBugs = $this->bug->getBySearch($build->product, $build->branch, $queryID, 'id_desc', $build->allBugs, $pager, $build->project);
|
||||
}
|
||||
else
|
||||
{
|
||||
$allBugs = $this->bug->getExecutionBugs($executionID, 0, 'all', $buildID, 'noclosed', 0, 'status_desc,id_desc', $build->bugs, $pager);
|
||||
$allBugs = $this->bug->getExecutionBugs($executionID, 0, 'all', $buildID, 'noclosed', 0, 'status_desc,id_desc', $build->allBugs, $pager);
|
||||
}
|
||||
|
||||
$this->view->allBugs = $allBugs;
|
||||
|
||||
@@ -15,5 +15,55 @@ $().ready(function()
|
||||
$('#builds').chosen();
|
||||
});
|
||||
});
|
||||
|
||||
$('input[name=type]').change(function()
|
||||
{
|
||||
if($(this).val() == 'execution')
|
||||
{
|
||||
$('#execution').closest('tr').show();
|
||||
$('#buildBox').closest('tr').hide();
|
||||
loadProducts($('#execution').val());
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#execution').closest('tr').hide();
|
||||
$('#buildBox').closest('tr').show();
|
||||
loadProducts($('#project').val());
|
||||
}
|
||||
});
|
||||
$('#product').change();
|
||||
});
|
||||
|
||||
/**
|
||||
* Load products.
|
||||
*
|
||||
* @param int $executionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function loadProducts(executionID)
|
||||
{
|
||||
$('#product').remove();
|
||||
$('#product_chosen').remove();
|
||||
$('#branch').remove();
|
||||
$('#branch_chosen').remove();
|
||||
$('#noProduct').remove();
|
||||
$.get(createLink('product', 'ajaxGetProducts', 'executionID=' + executionID), function(data)
|
||||
{
|
||||
if(data)
|
||||
{
|
||||
if(data.indexOf("required") != -1)
|
||||
{
|
||||
$('#productBox').addClass('required');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#productBox').removeClass('required');
|
||||
}
|
||||
|
||||
$('#productBox').append(data);
|
||||
$('#product').chosen();
|
||||
loadBranches($("#product").val());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ $lang->build->project = 'Project';
|
||||
$lang->build->branch = 'Platform/Branch';
|
||||
$lang->build->branchName = '%s';
|
||||
$lang->build->execution = $lang->executionCommon;
|
||||
$lang->build->type = 'Type';
|
||||
$lang->build->builds = 'Linked Builds';
|
||||
$lang->build->name = 'Name';
|
||||
$lang->build->date = 'Datum';
|
||||
@@ -73,3 +74,7 @@ $lang->build->action->buildopened = '$date, erstellt von <strong>$actor</strong>
|
||||
$lang->backhome = 'zurück';
|
||||
|
||||
$lang->build->featureBar['browse']['all'] = 'Build List';
|
||||
|
||||
$lang->build->typeList = array();
|
||||
$lang->build->typeList['execution'] = "{$lang->executionCommon}版本";
|
||||
$lang->build->typeList['project'] = '项目版本';
|
||||
|
||||
@@ -34,6 +34,7 @@ $lang->build->branch = 'Platform/Branch';
|
||||
$lang->build->branchName = '%s';
|
||||
$lang->build->execution = $lang->executionCommon;
|
||||
$lang->build->builds = 'Linked Builds';
|
||||
$lang->build->type = 'Type';
|
||||
$lang->build->name = 'Name';
|
||||
$lang->build->date = 'Date';
|
||||
$lang->build->builder = 'Builder';
|
||||
@@ -73,3 +74,7 @@ $lang->build->action->buildopened = '$date, created by <strong>$actor</strong>,
|
||||
$lang->backhome = 'back';
|
||||
|
||||
$lang->build->featureBar['browse']['all'] = 'Build List';
|
||||
|
||||
$lang->build->typeList = array();
|
||||
$lang->build->typeList['execution'] = "{$lang->executionCommon}版本";
|
||||
$lang->build->typeList['project'] = '项目版本';
|
||||
|
||||
@@ -33,6 +33,7 @@ $lang->build->project = 'Project';
|
||||
$lang->build->branch = 'Plateforme/Branche';
|
||||
$lang->build->branchName = '%s';
|
||||
$lang->build->execution = $lang->executionCommon;
|
||||
$lang->build->type = 'Type';
|
||||
$lang->build->builds = 'Linked Builds';
|
||||
$lang->build->name = 'Nom';
|
||||
$lang->build->date = 'Date';
|
||||
@@ -73,3 +74,7 @@ $lang->build->action->buildopened = '$date, Build <strong>$extra</strong> créé
|
||||
$lang->backhome = 'Retour';
|
||||
|
||||
$lang->build->featureBar['browse']['all'] = 'Build List';
|
||||
|
||||
$lang->build->typeList = array();
|
||||
$lang->build->typeList['execution'] = "{$lang->executionCommon}版本";
|
||||
$lang->build->typeList['project'] = '项目版本';
|
||||
|
||||
@@ -33,6 +33,7 @@ $lang->build->project = '所属项目';
|
||||
$lang->build->branch = '平台/分支';
|
||||
$lang->build->branchName = '所属%s';
|
||||
$lang->build->execution = '所属' . $lang->executionCommon;
|
||||
$lang->build->type = '版本类型';
|
||||
$lang->build->builds = '关联版本';
|
||||
$lang->build->name = '名称编号';
|
||||
$lang->build->date = '打包日期';
|
||||
@@ -71,3 +72,7 @@ $lang->build->action = new stdclass();
|
||||
$lang->build->action->buildopened = '$date, 由 <strong>$actor</strong> 创建版本 <strong>$extra</strong>。' . "\n";
|
||||
|
||||
$lang->backhome = '返回';
|
||||
|
||||
$lang->build->typeList = array();
|
||||
$lang->build->typeList['execution'] = "{$lang->executionCommon}版本";
|
||||
$lang->build->typeList['project'] = '项目版本';
|
||||
|
||||
+20
-33
@@ -31,6 +31,7 @@ class buildModel extends model
|
||||
->fetch();
|
||||
if(!$build) return false;
|
||||
|
||||
$build = $this->linkChildBuilds($build);
|
||||
$build = $this->loadModel('file')->replaceImgURL($build, 'desc');
|
||||
$build->files = $this->file->getByObject('build', $buildID);
|
||||
if($setImgSize) $build->desc = $this->file->setImgSize($build->desc);
|
||||
@@ -302,42 +303,31 @@ class buildModel extends model
|
||||
/**
|
||||
* Create a build
|
||||
*
|
||||
* @param int $executionID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create($executionID = 0, $projectID = 0)
|
||||
public function create()
|
||||
{
|
||||
$build = new stdclass();
|
||||
$build->stories = '';
|
||||
$build->bugs = '';
|
||||
|
||||
if($projectID && !$executionID)
|
||||
{
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
if(!$project->multiple) $executionID = $this->dao->select('id')->from(TABLE_EXECUTION)->where('project')->eq($projectID)->fetch('id');
|
||||
}
|
||||
else if($executionID && !$projectID)
|
||||
{
|
||||
$execution = $this->loadModel('execution')->getByID($executionID);
|
||||
$projectID = $execution->project;
|
||||
}
|
||||
|
||||
$build = fixer::input('post')
|
||||
->setDefault('project', $projectID)
|
||||
->setDefault('project', 0)
|
||||
->setDefault('execution', 0)
|
||||
->setDefault('product', 0)
|
||||
->setDefault('branch', 0)
|
||||
->setDefault('builds', '')
|
||||
->cleanInt('product,branch')
|
||||
->add('execution', $executionID)
|
||||
->add('createdBy', $this->app->user->account)
|
||||
->add('createdDate', helper::now())
|
||||
->stripTags($this->config->build->editor->create['id'], $this->config->allowedTags)
|
||||
->join('builds', ',')
|
||||
->remove('resolvedBy,allchecker,files,labels,uid')
|
||||
->remove('resolvedBy,allchecker,files,labels,type,uid')
|
||||
->get();
|
||||
|
||||
if($this->post->type == 'project') $build->execution = 0;
|
||||
|
||||
$build = $this->loadModel('file')->processImgURL($build, $this->config->build->editor->create['id'], $this->post->uid);
|
||||
$this->dao->insert(TABLE_BUILD)->data($build)
|
||||
->autoCheck()
|
||||
@@ -349,7 +339,6 @@ class buildModel extends model
|
||||
if(!dao::isError())
|
||||
{
|
||||
$buildID = $this->dao->lastInsertID();
|
||||
$this->linkChildBuilds($buildID, $build->builds);
|
||||
$this->file->updateObjectID($this->post->uid, $buildID, 'build');
|
||||
$this->file->saveUpload('build', $buildID);
|
||||
$this->loadModel('score')->create('build', 'create', $buildID);
|
||||
@@ -389,8 +378,6 @@ class buildModel extends model
|
||||
if(isset($build->branch) and $oldBuild->branch != $build->branch) $this->dao->update(TABLE_RELEASE)->set('branch')->eq($build->branch)->where('build')->eq($buildID)->exec();
|
||||
if(!dao::isError())
|
||||
{
|
||||
$addBuilds = array_diff(explode(',', $build->builds), explode(',', $oldBuild->builds));
|
||||
if($addBuilds) $this->linkChildBuilds($buildID, $addBuilds);
|
||||
$this->file->updateObjectID($this->post->uid, $buildID, 'build');
|
||||
return common::createChanges($oldBuild, $build);
|
||||
}
|
||||
@@ -569,28 +556,28 @@ class buildModel extends model
|
||||
/**
|
||||
* Bugs and stories associated with child builds.
|
||||
*
|
||||
* @param int $buildID
|
||||
* @param string $childBuildIDList
|
||||
* @param object $build
|
||||
* @access public
|
||||
* @return void
|
||||
* @return object
|
||||
*/
|
||||
public function linkChildBuilds($buildID, $childBuildIDList)
|
||||
public function linkChildBuilds($build)
|
||||
{
|
||||
$build = $this->dao->select('bugs, stories')->from(TABLE_BUILD)->where('id')->eq($buildID)->fetch();
|
||||
$childBuilds = $this->dao->select('bugs, stories')->from(TABLE_BUILD)->where('id')->in($childBuildIDList)->fetchAll();
|
||||
$build->allBugs = $build->bugs;
|
||||
$build->allStories = $build->stories;
|
||||
$childBuilds = $this->dao->select('bugs, stories')->from(TABLE_BUILD)->where('id')->in($build->builds)->fetchAll();
|
||||
|
||||
foreach($childBuilds as $childBuild)
|
||||
{
|
||||
if($childBuild->bugs) $build->bugs .= ",{$childBuild->bugs}";
|
||||
if($childBuild->stories) $build->stories .= ",{$childBuild->stories}";
|
||||
if($childBuild->bugs) $build->allBugs .= ",{$childBuild->bugs}";
|
||||
if($childBuild->stories) $build->allStories .= ",{$childBuild->stories}";
|
||||
}
|
||||
|
||||
$build->bugs = explode(',', $build->bugs);
|
||||
$build->bugs = join(',', array_unique(array_filter($build->bugs)));
|
||||
$build->stories = explode(',', $build->stories);
|
||||
$build->stories = join(',', array_unique(array_filter($build->stories)));
|
||||
$build->allBugs = explode(',', $build->allBugs);
|
||||
$build->allBugs = join(',', array_unique(array_filter($build->allBugs)));
|
||||
$build->allStories = explode(',', $build->allStories);
|
||||
$build->allStories = join(',', array_unique(array_filter($build->allStories)));
|
||||
|
||||
$this->dao->update(TABLE_BUILD)->data($build)->where('id')->eq($buildID)->exec();
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,14 @@
|
||||
</div>
|
||||
<form class='load-indicator main-form form-ajax' id='dataform' method='post' enctype='multipart/form-data'>
|
||||
<table class='table table-form'>
|
||||
<tr class="<?php echo ($app->tab == 'project' and !empty($multipleProject)) ? '' : 'hidden';?>">
|
||||
<th><?php echo $lang->build->type;?></th>
|
||||
<td><?php echo html::radio('type', $lang->build->typeList, 'execution');?></td>
|
||||
</tr>
|
||||
<tr class="<?php echo !empty($multipleProject) ? '' : 'hidden';?>">
|
||||
<th><?php echo $lang->executionCommon;?></th>
|
||||
<td><?php echo html::select('execution', $executions, $executionID, "onchange='loadProducts(this.value);' class='form-control chosen' required");?></td>
|
||||
</tr>
|
||||
<tr class="<?php echo $hidden;?>">
|
||||
<th><?php echo $lang->build->product;?></th>
|
||||
<?php if(!empty($products)):?>
|
||||
@@ -42,13 +50,11 @@
|
||||
<?php endif;?>
|
||||
<td></td>
|
||||
</tr>
|
||||
<?php if($app->tab == 'project' && !empty($multipleProject)):?>
|
||||
<tr>
|
||||
<tr class='hide'>
|
||||
<th><?php echo $lang->build->builds;?></th>
|
||||
<td id='buildBox'><?php echo html::select('builds[]', array(), '', "class='form-control chosen' multiple");?></td>
|
||||
<td><?php echo $lang->build->notice->autoRelation;?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->build->name;?></th>
|
||||
<td><?php echo html::input('name', '', "class='form-control' required");?></td>
|
||||
@@ -86,6 +92,7 @@
|
||||
<tr>
|
||||
<td colspan="3" class="text-center form-actions">
|
||||
<?php echo html::submitButton();?>
|
||||
<?php echo html::hidden('project', $projectID);?>
|
||||
<?php echo html::backButton();?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -95,10 +95,11 @@ tbody tr td:first-child input {display: none;}
|
||||
</thead>
|
||||
<tbody class='text-center'>
|
||||
<?php foreach($stories as $storyID => $story):?>
|
||||
<?php $unlinkClass = strpos(",$build->stories,", ",$story->id,") !== false ? '' : "disabled";?>
|
||||
<tr>
|
||||
<td class='c-id text-left'>
|
||||
<?php if($canBatchUnlink):?>
|
||||
<?php echo html::checkbox('unlinkStories', array($story->id => sprintf('%03d', $story->id)));?>
|
||||
<?php echo html::checkbox('unlinkStories', array($story->id => sprintf('%03d', $story->id)), '', $unlinkClass);?>
|
||||
<?php else:?>
|
||||
<?php printf('%03d', $story->id);?>
|
||||
<?php endif;?>
|
||||
@@ -138,7 +139,7 @@ tbody tr td:first-child input {display: none;}
|
||||
if($canBeChanged and common::hasPriv($module, 'unlinkStory'))
|
||||
{
|
||||
$unlinkURL = $this->createLink($module, 'unlinkStory', "buildID=$build->id&story=$story->id");
|
||||
echo html::a($unlinkURL, '<i class="icon-unlink"></i>', 'hiddenwin', "class='btn' title='{$lang->build->unlinkStory}'");
|
||||
echo html::a($unlinkURL, '<i class="icon-unlink"></i>', 'hiddenwin', "class='btn' title='{$lang->build->unlinkStory}' $unlinkClass");
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
@@ -194,11 +195,12 @@ tbody tr td:first-child input {display: none;}
|
||||
</thead>
|
||||
<tbody class='text-center'>
|
||||
<?php foreach($bugs as $bug):?>
|
||||
<?php $bugLink = $this->createLink('bug', 'view', "bugID=$bug->id", '', true);?>
|
||||
<?php $bugLink = $this->createLink('bug', 'view', "bugID=$bug->id", '', true);?>
|
||||
<?php $unlinkClass = strpos(",$build->bugs,", ",$bug->id,") !== false ? '' : "disabled";?>
|
||||
<tr>
|
||||
<td class='c-id text-left'>
|
||||
<?php if($canBatchUnlink):?>
|
||||
<?php echo html::checkbox('unlinkBugs', array($bug->id => sprintf('%03d', $bug->id)));?>
|
||||
<?php echo html::checkbox('unlinkBugs', array($bug->id => sprintf('%03d', $bug->id)), '', $unlinkClass);?>
|
||||
<?php else:?>
|
||||
<?php printf('%03d', $bug->id);?>
|
||||
<?php endif;?>
|
||||
@@ -219,7 +221,7 @@ tbody tr td:first-child input {display: none;}
|
||||
if($canBeChanged and common::hasPriv($module, 'unlinkBug'))
|
||||
{
|
||||
$unlinkURL = $this->createLink($module, 'unlinkBug', "buildID=$build->id&bug=$bug->id");
|
||||
echo html::a("###", '<i class="icon-unlink"></i>', '', "onclick='ajaxDelete(\"$unlinkURL\", \"bugList\", confirmUnlinkBug)' class='btn' title='{$lang->build->unlinkBug}'");
|
||||
echo html::a("###", '<i class="icon-unlink"></i>', '', (!$unlinkClass ? "onclick='ajaxDelete(\"$unlinkURL\", \"bugList\", confirmUnlinkBug)'" : '') . "class='btn' title='{$lang->build->unlinkBug}' $unlinkClass");
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
|
||||
@@ -145,7 +145,6 @@ class extension extends control
|
||||
$this->view->upgrade = $upgrade;
|
||||
$this->view->title = $installTitle . $extension;
|
||||
|
||||
|
||||
$statusFile = $this->loadModel('common')->checkSafeFile();
|
||||
if($statusFile)
|
||||
{
|
||||
@@ -186,7 +185,7 @@ class extension extends control
|
||||
$incompatible = $condition->zentao['incompatible'];
|
||||
if($this->extension->checkVersion($incompatible))
|
||||
{
|
||||
$this->view->error = sprintf($this->lang->extension->errorIncompatible);
|
||||
$this->view->error = $this->lang->extension->errorIncompatible;
|
||||
return $this->display();
|
||||
}
|
||||
|
||||
@@ -220,7 +219,7 @@ class extension extends control
|
||||
$noDepends = false;
|
||||
if(isset($installedExts[$code]))
|
||||
{
|
||||
if($this->extension->compare4Limit($installedExts[$code]->version, $limit, 'noBetween'))$noDepends = true;
|
||||
if($this->extension->compare4Limit($installedExts[$code]->version, $limit, 'noBetween')) $noDepends = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -235,7 +234,7 @@ class extension extends control
|
||||
if(!empty($limit['max'])) $extVersion .= ' <=v' . $limit['max'];
|
||||
$extVersion .=')';
|
||||
}
|
||||
if($noDepends)$dependsExt .= $code . $extVersion . ' ' . html::a(inlink('obtain', 'type=bycode¶m=' . helper::safe64Encode($code)), $this->lang->extension->installExt, '_blank') . '<br />';
|
||||
if($noDepends) $dependsExt .= $code . $extVersion . ' ' . html::a(inlink('obtain', 'type=bycode¶m=' . helper::safe64Encode($code)), $this->lang->extension->installExt, '_blank') . '<br />';
|
||||
}
|
||||
|
||||
if($noDepends)
|
||||
|
||||
@@ -525,9 +525,11 @@ class extensionModel extends model
|
||||
/* Extract files. */
|
||||
$packageFile = $this->getPackageFile($extension);
|
||||
$this->app->loadClass('pclzip', true);
|
||||
$zip = new pclzip($packageFile);
|
||||
$files = $zip->listContent();
|
||||
$removePath = $files[0]['filename'];
|
||||
$zip = new pclzip($packageFile);
|
||||
$files = $zip->listContent();
|
||||
$pathinfo = pathinfo($files[0]['filename']);
|
||||
$removePath = isset($pathinfo['dirname']) && $pathinfo['dirname'] != '.' ? $pathinfo['dirname'] : $pathinfo['basename'];
|
||||
|
||||
if($zip->extract(PCLZIP_OPT_PATH, $extensionPath, PCLZIP_OPT_REMOVE_PATH, $removePath) == 0)
|
||||
{
|
||||
$return->result = 'fail';
|
||||
@@ -548,7 +550,7 @@ class extensionModel extends model
|
||||
{
|
||||
$appRoot = $this->app->getAppRoot();
|
||||
$extensionDir = "ext/$extension/";
|
||||
$paths = scandir($extensionDir);
|
||||
$paths = scandir($extensionDir);
|
||||
$copiedFiles = array();
|
||||
|
||||
foreach($paths as $path)
|
||||
|
||||
@@ -3,7 +3,7 @@ $maxUploadSize = strtoupper(ini_get('upload_max_filesize'));
|
||||
js::set('dangerExtensions', ',' . $this->config->file->dangers . ',');
|
||||
js::set('maxUploadSize', $maxUploadSize);
|
||||
?>
|
||||
<div class="file-input-list" data-append-way="before" data-provide="fileInputList" data-each-file-max-size="<?php echo $maxUploadSize; ?>" data-file-size-error="<?php echo sprintf($lang->file->errorFileSize, $maxUploadSize); ?>">
|
||||
<div class="file-input-list" data-append-way="before" data-filedName="<?php echo $filesName;?>" data-provide="fileInputList" data-each-file-max-size="<?php echo $maxUploadSize; ?>" data-file-size-error="<?php echo sprintf($lang->file->errorFileSize, $maxUploadSize); ?>">
|
||||
<div class="file-input">
|
||||
<div class="file-input-edit input-group">
|
||||
<div class="input-group-cell"><i class="icon icon-paper-clip text-muted"></i></div>
|
||||
|
||||
@@ -237,7 +237,6 @@ $lang->project->methodOrder[190] = 'manageRepo';
|
||||
|
||||
$lang->resource->projectbuild = new stdclass();
|
||||
$lang->resource->projectbuild->browse = 'browse';
|
||||
$lang->resource->projectbuild->create = 'create';
|
||||
$lang->resource->projectbuild->edit = 'edit';
|
||||
$lang->resource->projectbuild->view = 'view';
|
||||
$lang->resource->projectbuild->delete = 'delete';
|
||||
@@ -249,7 +248,6 @@ $lang->resource->projectbuild->unlinkBug = 'unlinkBug';
|
||||
$lang->resource->projectbuild->batchUnlinkBug = 'batchUnlinkBug';
|
||||
|
||||
$lang->projectbuild->methodOrder[5] = 'browse';
|
||||
$lang->projectbuild->methodOrder[10] = 'create';
|
||||
$lang->projectbuild->methodOrder[15] = 'edit';
|
||||
$lang->projectbuild->methodOrder[20] = 'view';
|
||||
$lang->projectbuild->methodOrder[25] = 'delete';
|
||||
|
||||
@@ -198,12 +198,13 @@ class holidayModel extends model
|
||||
{
|
||||
if(empty($begin) or empty($end) or $begin == '0000-00-00' or $end == '0000-00-00') return array();
|
||||
|
||||
$this->app->loadConfig('execution');
|
||||
$actualDays = array();
|
||||
$currentDay = $begin;
|
||||
|
||||
$holidays = $this->getHolidays($begin, $end);
|
||||
$workingDays = $this->getWorkingDays($begin, $end);
|
||||
$weekend = isset($this->config->project->weekend) ? $this->config->project->weekend : 2;
|
||||
$weekend = isset($this->config->execution->weekend) ? $this->config->execution->weekend : 2;
|
||||
|
||||
$holidaysFlip = array_flip($holidays);
|
||||
$workingDaysFlip = array_flip($workingDays);
|
||||
|
||||
@@ -564,7 +564,7 @@
|
||||
/* The magic number "111" is the space between dropdown trigger
|
||||
btn and the bottom of screen */
|
||||
var listStyle = {maxHeight: 'initial', top: moreMenuHeight > 111 ? 111 - moreMenuHeight : ''};
|
||||
if($list[0].getBoundingClientRect)
|
||||
if($list[0] && $list[0].getBoundingClientRect)
|
||||
{
|
||||
var btnBounding = $list.prev('a')[0].getBoundingClientRect();
|
||||
if(btnBounding.height)
|
||||
@@ -803,7 +803,7 @@ $(function()
|
||||
{
|
||||
var val = $searchQuery.val();
|
||||
var searchType = changeSearchObject();
|
||||
if(val !== null && val !== "")
|
||||
if(val)
|
||||
{
|
||||
var isQuickGo = !reg.test(val);
|
||||
$dropmenu.toggleClass('show-quick-go', isQuickGo);
|
||||
|
||||
@@ -59,7 +59,7 @@ $lang->misc->zentao->others['meshiot' ] = "<img src='{$config->webRoot}theme/def
|
||||
|
||||
$lang->misc->mobile = "Mobiler Zugriff";
|
||||
$lang->misc->noGDLib = "Bitte benutzen Sie den Browser Ihres Telefons um die Seite <strong>%s</strong> aufzurufen";
|
||||
$lang->misc->copyright = "© 2009 - 2018 <a href='http://easysoft.ltd' target='_blank'>Nature Easy Soft Network Technology Co,LTD</a> Email <a href='mailto:Max@easysoft.ltd'>Max@easysoft.ltd</a>";
|
||||
$lang->misc->copyright = "© 2009 - " . date('Y') . " <a href='https://easysoft.ltd' target='_blank'>Nature Easy Soft Network Technology Co,LTD</a> Email <a href='mailto:Max@easysoft.ltd'>Max@easysoft.ltd</a>";
|
||||
$lang->misc->checkTable = "Prüfe Datentabellen";
|
||||
$lang->misc->needRepair = "Repariere Datentabellen";
|
||||
$lang->misc->repairTable = "Datenbank íst beschädigt. Bitte brüfen und reparieren!";
|
||||
|
||||
@@ -59,7 +59,7 @@ $lang->misc->zentao->others['meshiot' ] = "<img src='{$config->webRoot}theme/def
|
||||
|
||||
$lang->misc->mobile = "Mobile Access";
|
||||
$lang->misc->noGDLib = "Please visit <strong>%s</strong> in the browser of your phone.";
|
||||
$lang->misc->copyright = "© 2009 - 2019 <a href='https://easycorp.ltd/' target='_blank'>EasyCorp</a> Email <a href='mailto:Renee@easycorp.ltd'>Renee@easycorp.ltd</a>";
|
||||
$lang->misc->copyright = "© 2009 - " . date('Y') . " <a href='https://easycorp.ltd/' target='_blank'>EasyCorp</a> Email <a href='mailto:Renee@easycorp.ltd'>Renee@easycorp.ltd</a>";
|
||||
$lang->misc->checkTable = "Check Data Table";
|
||||
$lang->misc->needRepair = "Repair Table";
|
||||
$lang->misc->repairTable = "Database table might be damaged due to power outage. Please check and repair!";
|
||||
|
||||
@@ -59,7 +59,7 @@ $lang->misc->zentao->others['meshiot' ] = "<img src='{$config->webRoot}theme/def
|
||||
|
||||
$lang->misc->mobile = "Accès Mobile";
|
||||
$lang->misc->noGDLib = "SVP visitez <strong>%s</strong> via le navigateur de votre smartphone.";
|
||||
$lang->misc->copyright = "© 2009 - 2019 <a href='http://easysoft.ltd' target='_blank'>Nature Easy Soft</a> Email <a href='mailto:Renee@easysoft.ltd'>Renee@easysoft.ltd</a>";
|
||||
$lang->misc->copyright = "© 2009 - " . date('Y') . " <a href='https://easysoft.ltd' target='_blank'>Nature Easy Soft</a> Email <a href='mailto:Renee@easysoft.ltd'>Renee@easysoft.ltd</a>";
|
||||
$lang->misc->checkTable = "Vérifiez les Données de la Table";
|
||||
$lang->misc->needRepair = "Réparer la Table";
|
||||
$lang->misc->repairTable = "La Base de Données est peut-être endommagée. Elle a besoin d'être vérifiée et éventuellement réparée !";
|
||||
|
||||
@@ -59,7 +59,7 @@ $lang->misc->zentao->others['meshiot' ] = "<img src='{$config->webRoot}theme/def
|
||||
|
||||
$lang->misc->mobile = "Mobile Access";
|
||||
$lang->misc->noGDLib = "Please visit <strong>%s</strong> in the browser of your phone.";
|
||||
$lang->misc->copyright = "© 2009 - 2019 <a href='http://easysoft.ltd' target='_blank'>Nature Easy Soft</a> Email <a href='mailto:Renee@easysoft.ltd'>Renee@easysoft.ltd</a>";
|
||||
$lang->misc->copyright = "© 2009 - " . date('Y') . " <a href='https://easysoft.ltd' target='_blank'>Nature Easy Soft</a> Email <a href='mailto:Renee@easysoft.ltd'>Renee@easysoft.ltd</a>";
|
||||
$lang->misc->checkTable = "Check Data Table";
|
||||
$lang->misc->needRepair = "Repair Table";
|
||||
$lang->misc->repairTable = "Database table might be damaged due to power outage. Vui lòng check and repair!";
|
||||
|
||||
@@ -59,7 +59,7 @@ $lang->misc->zentao->others['meshiot' ] = "<img src='{$config->webRoot}theme/def
|
||||
|
||||
$lang->misc->mobile = "手机访问";
|
||||
$lang->misc->noGDLib = "请用手机浏览器访问:<strong>%s</strong>";
|
||||
$lang->misc->copyright = "© 2009 - 2018 <a href='http://www.cnezsoft.com' target='_blank'>青岛易软天创网络科技有限公司</a> 电话:4006-8899-23 Email:<a href='mailto:co@zentao.net'>co@zentao.net</a> QQ:1492153927";
|
||||
$lang->misc->copyright = "© 2009 - " . date('Y') . " <a href='https://www.easycorp.cn' target='_blank'>青岛易软天创网络科技有限公司</a> 电话:4006-8899-23 Email:<a href='mailto:co@zentao.net'>co@zentao.net</a> QQ:1492153927";
|
||||
$lang->misc->checkTable = "检查修复数据表";
|
||||
$lang->misc->needRepair = "修复表";
|
||||
$lang->misc->repairTable = "数据库表可能因为断电原因损坏,需要检查修复!!";
|
||||
|
||||
@@ -59,7 +59,7 @@ $lang->misc->zentao->others['meshiot' ] = "<img src='{$config->webRoot}theme/def
|
||||
|
||||
$lang->misc->mobile = "手機訪問";
|
||||
$lang->misc->noGDLib = "請用手機瀏覽器訪問:<strong>%s</strong>";
|
||||
$lang->misc->copyright = "© 2009 - 2018 <a href='http://www.cnezsoft.com' target='_blank'>青島易軟天創網絡科技有限公司</a> 電話:4006-8899-23 Email:<a href='mailto:co@zentao.net'>co@zentao.net</a> QQ:1492153927";
|
||||
$lang->misc->copyright = "© 2009 - " . date('Y') . " <a href='https://www.easycorp.cn' target='_blank'>青島易軟天創網絡科技有限公司</a> 電話:4006-8899-23 Email:<a href='mailto:co@zentao.net'>co@zentao.net</a> QQ:1492153927";
|
||||
$lang->misc->checkTable = "檢查修復數據表";
|
||||
$lang->misc->needRepair = "修復表";
|
||||
$lang->misc->repairTable = "資料庫表可能因為斷電原因損壞,需要檢查修復!!";
|
||||
|
||||
@@ -880,6 +880,27 @@ class product extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get products.
|
||||
*
|
||||
* @param int $executionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetProducts($executionID)
|
||||
{
|
||||
$this->loadModel('build');
|
||||
$products = $this->product->getProductPairsByProject($executionID);
|
||||
if(empty($products))
|
||||
{
|
||||
return printf($this->lang->build->noProduct, $this->createLink('execution', 'manageproducts', "executionID=$executionID&from=buildCreate", '', 'true'), 'project');
|
||||
}
|
||||
else
|
||||
{
|
||||
return print(html::select('product', $products, empty($product) ? '' : $product->id, "onchange='loadBranches(this.value);' class='form-control chosen' required data-toggle='modal' data-type='iframe'"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: get projects of a product in html select.
|
||||
*
|
||||
|
||||
@@ -124,7 +124,7 @@ class productModel extends model
|
||||
if($isQaModule) $moduleName = 'bug';
|
||||
if($isFeedbackModel) $moduleName = 'feedback';
|
||||
$dropMenuLink = helper::createLink($moduleName, 'ajaxGetDropMenu', "objectID=$productID&module=$currentModule&method=$currentMethod&extra=$extra");
|
||||
$output = "<div class='btn-group angle-btn'><div class='btn-group'><button data-toggle='dropdown' type='button' class='btn btn-limit' id='currentItem' title='{$currentProduct->name}'><span class='text'>{$currentProduct->name}</span> <span class='caret'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
|
||||
$output = "<div class='btn-group angle-btn'><div class='btn-group'><button data-toggle='dropdown' type='button' class='btn btn-limit' id='currentItem' title='{$currentProduct->name}' style='width: 90%'><span class='text'>{$currentProduct->name}</span> <span class='caret'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
|
||||
$output .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
|
||||
$output .= "</div></div>";
|
||||
if($isMobile) $output = "<a id='currentItem' href=\"javascript:showSearchMenu('product', '$productID', '$currentModule', '$currentMethod', '$extra')\"><span class='text'>{$currentProduct->name}</span> <span class='icon-caret-down'></span></a><div id='currentItemDropMenu' class='hidden affix enter-from-bottom layer'></div>";
|
||||
@@ -140,7 +140,7 @@ class productModel extends model
|
||||
if(!$isMobile)
|
||||
{
|
||||
$dropMenuLink = helper::createLink('branch', 'ajaxGetDropMenu', "objectID=$productID&branch=$branch&module=$currentModule&method=$currentMethod&extra=$extra");
|
||||
$output .= "<div class='btn-group'><button id='currentBranch' data-toggle='dropdown' type='button' class='btn btn-limit'>{$branchName} <span class='caret'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
|
||||
$output .= "<div class='btn-group'><button id='currentBranch' data-toggle='dropdown' type='button' class='btn btn-limit' title='{$branchName}' style='width: 90%'>{$branchName} <span class='caret'></span></button><div id='dropMenu' class='dropdown-menu search-list' data-ride='searchList' data-url='$dropMenuLink'>";
|
||||
$output .= '<div class="input-control search-box has-icon-left has-icon-right search-example"><input type="search" class="form-control search-input" /><label class="input-control-icon-left search-icon"><i class="icon icon-search"></i></label><a class="input-control-icon-right search-clear-btn"><i class="icon icon-close icon-sm"></i></a></div>';
|
||||
$output .= "</div></div>";
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<div id='mainContent' class="main-row">
|
||||
<div class="col-12 main-col">
|
||||
<div class="row">
|
||||
<?php $isRoadmap = common::hasPriv('product', 'roadmap');?>
|
||||
<?php $isRoadmap = (common::hasPriv('product', 'roadmap') and helper::hasFeature('product_roadmap'));?>
|
||||
<?php if($isRoadmap):?>
|
||||
<div class="col-sm-6">
|
||||
<div class="panel block-release">
|
||||
|
||||
@@ -531,22 +531,21 @@ class productplanModel extends model
|
||||
->get();
|
||||
|
||||
$parentPlan = $this->getByID($plan->parent);
|
||||
|
||||
$futureTime = $this->config->productplan->future;
|
||||
|
||||
if($plan->parent > 0)
|
||||
{
|
||||
if($parentPlan->begin !== $this->config->productplan->future)
|
||||
if($parentPlan->begin !== $futureTime)
|
||||
{
|
||||
if($plan->begin < $parentPlan->begin) dao::$errors['begin'] = sprintf($this->lang->productplan->beginLetterParent, $parentPlan->begin);
|
||||
}
|
||||
if($parentPlan->end !== $this->config->productplan->future)
|
||||
if($parentPlan->end !== $futureTime)
|
||||
{
|
||||
if($plan->end !== $this->config->productplan->future and $plan->end > $parentPlan->end) dao::$errors['end'] = sprintf($this->lang->productplan->endGreaterParent, $parentPlan->end);
|
||||
if($plan->end !== $futureTime and $plan->end > $parentPlan->end) dao::$errors['end'] = sprintf($this->lang->productplan->endGreaterParent, $parentPlan->end);
|
||||
}
|
||||
}
|
||||
elseif($oldPlan->parent == -1 and $plan->begin != $this->config->productplan->future)
|
||||
elseif($oldPlan->parent == -1 and ($plan->begin != $futureTime or $plan->end != $futureTime))
|
||||
{
|
||||
$plan->parent = -1;
|
||||
$childPlans = $this->getChildren($planID);
|
||||
$minBegin = $plan->begin;
|
||||
$maxEnd = $plan->end;
|
||||
@@ -556,8 +555,8 @@ class productplanModel extends model
|
||||
if($childPlan->begin < $minBegin) $minBegin = $childPlan->begin;
|
||||
if($childPlan->end > $maxEnd) $maxEnd = $childPlan->end;
|
||||
}
|
||||
if($minBegin < $plan->begin and $minBegin != $this->config->productplan->future) dao::$errors['begin'] = sprintf($this->lang->productplan->beginGreaterChildTip, $oldPlan->title, $plan->begin, $minBegin);
|
||||
if($maxEnd > $plan->end and $maxEnd != $this->config->productplan->future) dao::$errors['end'] = sprintf($this->lang->productplan->endLetterChildTip, $oldPlan->title, $plan->end, $maxEnd);
|
||||
if($minBegin < $plan->begin and $minBegin != $futureTime) dao::$errors['begin'] = sprintf($this->lang->productplan->beginGreaterChildTip, $oldPlan->title, $plan->begin, $minBegin);
|
||||
if($maxEnd > $plan->end and $maxEnd != $futureTime) dao::$errors['end'] = sprintf($this->lang->productplan->endLetterChildTip, $oldPlan->title, $plan->end, $maxEnd);
|
||||
}
|
||||
|
||||
if(dao::isError()) return false;
|
||||
@@ -647,7 +646,11 @@ class productplanModel extends model
|
||||
$childStatus = $this->dao->select('status')->from(TABLE_PRODUCTPLAN)->where('parent')->eq($parentID)->andWhere('deleted')->eq(0)->fetchPairs();
|
||||
|
||||
/* If the subplan is empty, update the plan. */
|
||||
if(empty($childStatus)) $this->dao->update(TABLE_PRODUCTPLAN)->set('parent')->eq(0)->where('id')->eq($parentID)->exec();
|
||||
if(empty($childStatus))
|
||||
{
|
||||
$this->dao->update(TABLE_PRODUCTPLAN)->set('parent')->eq(0)->set('status')->eq('wait')->where('id')->eq($parentID)->exec();
|
||||
return;
|
||||
}
|
||||
|
||||
if(count($childStatus) == 1 and isset($childStatus['wait']))
|
||||
{
|
||||
|
||||
@@ -41,10 +41,14 @@
|
||||
<th><?php echo $lang->productplan->title;?></th>
|
||||
<td><?php echo html::input('title', $plan->title, "class='form-control' required");?></td><td></td><td></td>
|
||||
</tr>
|
||||
<tr <?php echo $plan->parent == '-1' ? "class='hidden'": '';?>>
|
||||
<?php if($plan->parent == '-1'):?>
|
||||
<?php echo html::hidden('parent', $plan->parent);?>
|
||||
<?php else:?>
|
||||
<tr>
|
||||
<th><?php echo $lang->productplan->parent;?></th>
|
||||
<td><?php echo html::select('parent', array('0' => '') + $parentPlanPairs, $plan->parent, "class='form-control chosen'");?>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->productplan->status;?></th>
|
||||
<?php $disabled = $plan->parent == -1 ? "disabled='disabled'" : '' ;?>
|
||||
|
||||
@@ -102,7 +102,7 @@ $lang->programplan->ganttCustom['delay'] = '是否延期';
|
||||
$lang->programplan->ganttCustom['delayDays'] = '延期天数';
|
||||
|
||||
$lang->programplan->error = new stdclass();
|
||||
$lang->programplan->error->percentNumber = '"工作量比例"必须为数字';
|
||||
$lang->programplan->error->percentNumber = '"工作量占比"必须为数字';
|
||||
$lang->programplan->error->planFinishSmall = '"计划完成时间"必须大于"计划开始时间"';
|
||||
$lang->programplan->error->percentOver = '工作量占比累计不应当超过100%';
|
||||
$lang->programplan->error->createdTask = '已分解任务,不可添加子阶段';
|
||||
|
||||
@@ -72,7 +72,7 @@ $lang->programplan->stageCustom->date = '顯示日期';
|
||||
$lang->programplan->stageCustom->task = '顯示任務';
|
||||
|
||||
$lang->programplan->error = new stdclass();
|
||||
$lang->programplan->error->percentNumber = '"工作量比例"必須為數字';
|
||||
$lang->programplan->error->percentNumber = '"工作量占比"必須為數字';
|
||||
$lang->programplan->error->planFinishSmall = '"計劃完成時間"必須大於"計劃開始時間"';
|
||||
$lang->programplan->error->percentOver = '工作量占比累計不應當超過100%';
|
||||
$lang->programplan->error->createdTask = '已分解任務,不可添加子階段';
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
<?php
|
||||
class projectModel extends model
|
||||
{
|
||||
/**
|
||||
* Check the privilege.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function checkPriv($projectID)
|
||||
{
|
||||
if(empty($projectID)) return false;
|
||||
|
||||
/* If is admin, return true. */
|
||||
if($this->app->user->admin) return true;
|
||||
return (strpos(",{$this->app->user->view->projects},", ",{$projectID},") !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Multiple linked products for project.
|
||||
*
|
||||
@@ -3003,7 +3019,7 @@ class projectModel extends model
|
||||
$menu .= "<div class='btn-group'>";
|
||||
$menu .= "<button type='button' class='btn dropdown-toggle' data-toggle='context-dropdown' title='{$this->lang->more}'><i class='icon-ellipsis-v'></i></button>";
|
||||
$menu .= "<ul class='dropdown-menu pull-right text-center' role='menu'>";
|
||||
$menu .= $this->buildMenu($moduleName, 'manageProducts', $params . "&from={$this->app->tab}", $project, 'browse', 'link', '', 'btn-action', '', '', $this->lang->project->manageProducts);
|
||||
if($project->hasProduct) $menu .= $this->buildMenu($moduleName, 'manageProducts', $params . "&from={$this->app->tab}", $project, 'browse', 'link', '', 'btn-action', '', '', $this->lang->project->manageProducts);
|
||||
$menu .= $this->buildMenu('project', 'whitelist', "$params&module=project&from=$from", $project, 'browse', 'shield-check', '', 'btn-action', '', $dataApp);
|
||||
$menu .= $this->buildMenu($moduleName, "delete", $params, $project, 'browse', 'trash', 'hiddenwin', 'btn-action');
|
||||
$menu .= "</ul>";
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#swapper li {padding-top: 0; padding-bottom: 0;}
|
||||
#swapper .tree li>.list-toggle {top: -1px;}
|
||||
|
||||
div#closed {width: 90px; height: 25px; line-height: 25px; background-color: #ddd; color: #3c495c; text-align: center; margin-left: 15px; border-radius: 2px;}
|
||||
#dropMenu div#closed {width: 90px; height: 25px; line-height: 25px; background-color: #ddd; color: #3c495c; text-align: center; margin-left: 15px; border-radius: 2px;}
|
||||
#gray-line {width:230px; height: 1px; margin-left: 10px; margin-bottom:2px; background-color: #ddd;}
|
||||
</style>
|
||||
<?php
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<a class="btn btn-link querybox-toggle" id="bysearchTab"><i class="icon icon-search muted"></i> <?php echo $lang->execution->byQuery;?></a>
|
||||
</div>
|
||||
<div class="btn-toolbar pull-right">
|
||||
<?php if(common::canModify('project', $project)) common::printLink('projectbuild', 'create', "projectID=$projectID", "<i class='icon icon-plus'></i> " . $lang->build->create, '', "class='btn btn-primary' id='createBuild'");?>
|
||||
<?php if(common::canModify('project', $project)) common::printLink('build', 'create', "executionID=&productID=&projectID=$projectID", "<i class='icon icon-plus'></i> " . $lang->build->create, '', "class='btn btn-primary' id='createBuild'");?>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mainContent">
|
||||
|
||||
@@ -66,7 +66,7 @@ class releaseModel extends model
|
||||
->page($pager)
|
||||
->fetchAll();
|
||||
|
||||
$builds = $this->dao->select("t1.id, t1.name, t1.execution, IF(t2.name IS NOT NULL, t2.name, '') AS projectName, IF(t3.name IS NOT NULL, t3.name, '{$this->lang->trunk}') AS branchName")
|
||||
$builds = $this->dao->select("t1.id, t1.name, t1.project, t1.execution, IF(t2.name IS NOT NULL, t2.name, '') AS projectName, IF(t3.name IS NOT NULL, t3.name, '{$this->lang->trunk}') AS branchName")
|
||||
->from(TABLE_BUILD)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
|
||||
->leftJoin(TABLE_BRANCH)->alias('t3')->on('t1.branch = t3.id')
|
||||
|
||||
@@ -63,6 +63,10 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$this->loadModel('project');
|
||||
$this->loadModel('execution');
|
||||
?>
|
||||
<?php foreach($releases as $release):?>
|
||||
<?php $canBeChanged = common::canBeChanged('release', $release);?>
|
||||
<?php $buildCount = count($release->builds);?>
|
||||
@@ -82,7 +86,13 @@
|
||||
<?php if($product->type != 'normal'):?>
|
||||
<span class='label label-outline label-badge'><?php echo $build->branchName;?></span>
|
||||
<?php endif;?>
|
||||
<?php echo html::a($this->createLink($build->execution ? 'build' : 'projectbuild', 'view', "buildID=$build->id"), $build->name);?>
|
||||
<?php
|
||||
$moduleName = $build->execution ? 'build' : 'projectbuild';
|
||||
$canClickable = false;
|
||||
if($moduleName == 'projectbuild' and $this->project->checkPriv($build->project)) $canClickable = true;
|
||||
if($moduleName == 'build' and $this->execution->checkPriv($build->execution)) $canClickable = true;
|
||||
echo $canClickable ? html::a($this->createLink($moduleName, 'view', "buildID=$build->id"), $build->name, '', "data-app='project'") : $build->name;
|
||||
?>
|
||||
</td>
|
||||
<td><?php echo $build->projectName;?></td>
|
||||
<?php if($i == 1):?>
|
||||
|
||||
@@ -356,7 +356,12 @@
|
||||
$buildHtml = array();
|
||||
foreach($release->builds as $build)
|
||||
{
|
||||
$buildHtml[] = html::a($this->createLink($build->execution ? 'build' : 'projectbuild', 'view', "buildID=$build->id"), $build->name, '', "data-app='project'");
|
||||
$moduleName = $build->execution ? 'build' : 'projectbuild';
|
||||
$canClickable = false;
|
||||
if($moduleName == 'projectbuild' and $this->loadModel('project')->checkPriv($build->project)) $canClickable = true;
|
||||
if($moduleName == 'build' and $this->loadModel('execution')->checkPriv($build->execution)) $canClickable = true;
|
||||
|
||||
$buildHtml[] = $canClickable ? html::a($this->createLink($moduleName, 'view', "buildID=$build->id"), $build->name, '', "data-app='project'") : $build->name;
|
||||
}
|
||||
echo join($lang->comma, $buildHtml);
|
||||
?>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
$(function()
|
||||
{
|
||||
scmChanged(scm, true);
|
||||
scmChanged(repoSCM, true);
|
||||
$('#submit').mousedown(function()
|
||||
{
|
||||
$form = $(this).closest('form');
|
||||
@@ -86,6 +86,7 @@ function scmChanged(scm, isFirstRequest = false)
|
||||
if(scm == 'Git' || scm == 'Gitea' || scm == 'Gogs')
|
||||
{
|
||||
$('.account-fields').addClass('hidden');
|
||||
if(['Git', 'Gitea', 'Gogs'].indexOf(repoSCM) === -1) $('#client').val('');
|
||||
|
||||
$('.tips-git').removeClass('hidden');
|
||||
$('.tips-svn').addClass('hidden');
|
||||
|
||||
@@ -253,6 +253,7 @@ class repoModel extends model
|
||||
public function update($id)
|
||||
{
|
||||
$repo = $this->getRepoByID($id);
|
||||
if(!$this->checkConnection()) return false;
|
||||
|
||||
$isPipelineServer = in_array(strtolower($this->post->SCM), $this->config->repo->gitServiceList) ? true : false;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
.user-addon{padding-right: 16px; padding-left: 16px;}
|
||||
</style>
|
||||
<?php endif;?>
|
||||
<?php js::set('scm', $repo->SCM);?>
|
||||
<?php js::set('repoSCM', $repo->SCM);?>
|
||||
<?php js::set('objectID', $objectID);?>
|
||||
<div id='mainContent' class='main-row'>
|
||||
<div class='main-col main-content'>
|
||||
|
||||
@@ -726,6 +726,7 @@ class reportModel extends model
|
||||
->orWhere('RD')->in($accounts)
|
||||
->markRight(1)
|
||||
->fi()
|
||||
->andWhere('shadow')->eq(0)
|
||||
->fetchAll('id');
|
||||
|
||||
/* Get created plans in this year. */
|
||||
@@ -733,6 +734,7 @@ class reportModel extends model
|
||||
->leftJoin(TABLE_ACTION)->alias('t2')->on("t1.id=t2.objectID and t2.objectType='productplan'")
|
||||
->where('LEFT(t2.date, 4)')->eq($year)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->andWhere('t1.product')->in(array_keys($products))
|
||||
->beginIF($accounts)
|
||||
->andWhere('t2.actor')->in($accounts)
|
||||
->fi()
|
||||
@@ -750,11 +752,13 @@ class reportModel extends model
|
||||
$createStoryProducts = $this->dao->select('DISTINCT product')->from(TABLE_STORY)
|
||||
->where('LEFT(openedDate, 4)')->eq($year)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->andWhere('product')->in(array_keys($products))
|
||||
->beginIF($accounts)->andWhere('openedBy')->in($accounts)->fi()
|
||||
->fetchPairs('product', 'product');
|
||||
$closeStoryProducts = $this->dao->select('DISTINCT product')->from(TABLE_STORY)
|
||||
->where('LEFT(closedDate, 4)')->eq($year)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->andWhere('product')->in(array_keys($products))
|
||||
->beginIF($accounts)->andWhere('closedBy')->in($accounts)->fi()
|
||||
->fetchPairs('product', 'product');
|
||||
if($createStoryProducts or $closeStoryProducts)
|
||||
|
||||
@@ -2714,7 +2714,7 @@ class story extends control
|
||||
$this->story->replaceURLang($storyType);
|
||||
|
||||
$this->products = $this->product->getPairs('', 0, '', 'all');
|
||||
if($this->app->tab == 'project')
|
||||
if(strpos('project,execution', $this->app->tab) !== false)
|
||||
{
|
||||
$project = $this->dao->findByID($projectID)->from(TABLE_PROJECT)->fetch();
|
||||
if($project->type == 'project')
|
||||
@@ -2727,10 +2727,11 @@ class story extends control
|
||||
$this->loadModel('execution')->setMenu($projectID);
|
||||
}
|
||||
|
||||
if(!$project->hasProduct and !$project->multiple)
|
||||
if(!$project->hasProduct)
|
||||
{
|
||||
unset($this->lang->story->report->charts['storysPerProduct']);
|
||||
unset($this->lang->story->report->charts['storysPerPlan']);
|
||||
|
||||
if(!$project->multiple) unset($this->lang->story->report->charts['storysPerPlan']);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.c-id {width: 50px;}
|
||||
.c-reason {width: 150px;}
|
||||
.c-reason {width: 210px;}
|
||||
td[id^="duplicateStoryBox"].required:after {top: 6px; right: 2px;}
|
||||
td[id^="duplicateStoryBox"] {overflow: visible;}
|
||||
td.reasons-td {overflow: visible;}
|
||||
|
||||
@@ -12,22 +12,16 @@ function setDuplicateAndChild(resolution, storyID)
|
||||
{
|
||||
$('#childStoryBox' + storyID).hide();
|
||||
$('#duplicateStoryBox' + storyID).show();
|
||||
$('#duplicateStoryTitle').show();
|
||||
$('.form-actions').attr('colspan', 6);
|
||||
}
|
||||
else if(resolution == 'subdivided')
|
||||
{
|
||||
$('#duplicateStoryBox' + storyID).hide();
|
||||
$('#childStoryBox' + storyID).show();
|
||||
$('#duplicateStoryTitle').hide();
|
||||
$('.form-actions').attr('colspan', 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#duplicateStoryBox' + storyID).hide();
|
||||
$('#childStoryBox' + storyID).hide();
|
||||
$('#duplicateStoryTitle').hide();
|
||||
$('.form-actions').attr('colspan', 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4944,6 +4944,9 @@ class storyModel extends model
|
||||
case 'assignedDate':
|
||||
echo helper::isZeroDate($story->assignedDate) ? '' : substr($story->assignedDate, 5, 11);
|
||||
break;
|
||||
case 'activatedDate':
|
||||
echo helper::isZeroDate($story->activatedDate) ? '' : substr($story->activatedDate, 5, 11);
|
||||
break;
|
||||
case 'reviewedBy':
|
||||
echo $story->reviewedBy;
|
||||
break;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
<th class='text-left'><?php echo $lang->story->title;?></th>
|
||||
<th class='c-status'><?php echo $lang->story->status;?></th>
|
||||
<th class='c-reason'><?php echo $lang->story->closedReason;?></th>
|
||||
<th id='duplicateStoryTitle' class='w-p15' style='display:none;'><?php echo $lang->story->duplicateStory;?></th>
|
||||
<th class='w-p30'><?php echo $lang->story->comment;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -44,15 +43,15 @@
|
||||
<td class='pd-0'>
|
||||
<?php echo html::select("closedReasons[$storyID]", $reasonList, 'done', "class=form-control onchange=setDuplicateAndChild(this.value,$storyID) style='min-width: 80px'");?>
|
||||
</td>
|
||||
<td class='pd-0 w-p60 text-left' id='<?php echo 'duplicateStoryBox' . $storyID;?>' <?php if($story->closedReason != 'duplicate') echo "style='display:none'";?>>
|
||||
<?php echo html::select("duplicateStoryIDList[$storyID]", array('' => '') + $productStoryList[$story->product][$story->branch], $story->duplicateStory ? $story->duplicateStory : '', "class='form-control' placeholder='{$lang->bug->duplicateTip}'");?>
|
||||
</td>
|
||||
<td class='pd-0' id='<?php echo 'childStoryBox' . $storyID;?>' <?php if($story->closedReason != 'subdivided') echo "style='display:none'";?>>
|
||||
<?php echo html::input("childStoriesIDList[$storyID]", '', "class='form-control' placeholder='{$lang->idAB}'");?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class='text-left' id='<?php echo 'duplicateStoryBox' . $storyID;?>' <?php if($story->closedReason != 'duplicate') echo "style='display:none'";?>>
|
||||
<?php echo html::select("duplicateStoryIDList[$storyID]", array('' => '') + $productStoryList[$story->product][$story->branch], $story->duplicateStory ? $story->duplicateStory : '', "class='form-control' placeholder='{$lang->bug->duplicateTip}'");?>
|
||||
</td>
|
||||
<td><?php echo html::input("comments[$storyID]", '', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
|
||||
@@ -415,7 +415,7 @@
|
||||
<div class="cell">
|
||||
<div class='tabs'>
|
||||
<ul class='nav nav-tabs'>
|
||||
<?php if($this->config->URAndSR && !$hiddenURS):?>
|
||||
<?php if($this->config->URAndSR and !$hiddenURS):?>
|
||||
<li class='active'><a href='#legendStories' data-toggle='tab'><?php echo $story->type == 'story' ? $lang->story->requirement : $lang->story->story;?></a></li>
|
||||
<?php endif;?>
|
||||
<?php if($story->type == 'story'):?>
|
||||
@@ -424,7 +424,7 @@
|
||||
<li><a href='#legendRelated' data-toggle='tab'><?php echo $lang->story->legendRelated;?></a></li>
|
||||
</ul>
|
||||
<div class='tab-content'>
|
||||
<?php if($this->config->URAndSR && !$hiddenURS):?>
|
||||
<?php if($this->config->URAndSR and !$hiddenURS):?>
|
||||
<div class='tab-pane active' id='legendStories'>
|
||||
<ul class="list-unstyled">
|
||||
<?php
|
||||
@@ -571,7 +571,7 @@
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<?php if($story->type == 'story'):?>
|
||||
<?php if($story->type == 'story' and helper::hasFeature('devops')):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->linkMR;?></th>
|
||||
<td class='pd-0'>
|
||||
|
||||
@@ -322,7 +322,6 @@ class testcase extends control
|
||||
{
|
||||
$this->loadModel('project')->setMenu($this->session->project);
|
||||
$this->app->rawModule = 'qa';
|
||||
$this->lang->project->menu->qa['subMenu']->testcase['subModule'] = 'story';
|
||||
$products = $this->product->getProducts($this->session->project, 'all', '', false);
|
||||
$productID = $this->product->saveState($productID, $products);
|
||||
$this->lang->modulePageNav = $this->product->select($products, $productID, 'testcase', 'zeroCase', "projectID=$projectID", $branchID);
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
#mainContent tr th {background-color: rgb(241, 241, 241);}
|
||||
#mainContent tr td {background-color: rgb(255, 255, 255); border-bottom: 1px solid rgb(238, 238, 238); border-right: 1px solid rgb(238, 238, 238);}
|
||||
|
||||
#useLight {background-color: #ddd!important; padding: 6px 85px;}
|
||||
#useALM {background-color: #ddd!important; padding: 6px 85px;}
|
||||
#useLight, #useALM {border: #93969b 1px solid; padding: 6px 85px;}
|
||||
|
||||
#mainContent .datatable {cursor: default;}
|
||||
.container {padding-top: 20px;}
|
||||
|
||||
Reference in New Issue
Block a user