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

This commit is contained in:
tanghucheng
2022-07-22 10:53:27 +08:00
59 changed files with 301 additions and 216 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ class productplansEntry extends entry
if(!$productID) return $this->sendError(400, 'No product id.');
$control = $this->loadController('productplan', 'browse');
$control->browse($productID, $this->param('branch', 0), $this->param('status', 'all'), $this->param('order', 'begin_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
$control->browse($productID, $this->param('branch', 0), $this->param('status', 'all'), $this->param('query', 0), $this->param('order', 'begin_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
/* Response */
$data = $this->getData();
+1 -1
View File
@@ -535,7 +535,7 @@ class baseEntry
/* Format array. */
$value = array();
if(is_array($object->$key))
if(is_array($object->$key) or is_object($object->$key))
{
foreach($object->$key as $v) $value[] = $this->cast($v, $type);
}
+2 -3
View File
@@ -320,9 +320,8 @@ class gitea
foreach($list as $node) if($node->path == $entry) $file = $node;
$commits = $this->getCommitsByPath($entry);
if(!empty($commits)) $file->revision = zget($commits[0], 'id', '');
$commits = $this->getCommitsByPath($entry, $revision, $revision);
if(!empty($commits)) $file->revision = zget($commits[0], 'sha', '');
$info->kind = (isset($file->type) and $file->type == 'tree') ? 'dir' : 'file';
}
+19 -6
View File
@@ -157,7 +157,7 @@ class action extends control
$repeatObject = $this->dao->select('*')->from(TABLE_PRODUCT)
->where('id')->ne($oldAction->objectID)
->andWhere("(name = '{$product->name}' and program = {$programID})", true)
->orWhere("code = '{$product->code}'")
->beginIF($product->code)->orWhere("code = '{$product->code}'")->fi()
->markRight(1)
->andWhere('deleted')->eq('0')
->fetch();
@@ -182,13 +182,26 @@ class action extends control
if($repeatObject)
{
$result = preg_match('/_(\d+)$/', $repeatObject->name, $nameMatches);
$replaceName = $result ? preg_replace('/_(\d+)$/', '_' . ($nameMatches[1] + 1), $repeatObject->name) : $repeatObject->name . '_1';
$result = preg_match('/_(\d+)$/', $repeatObject->code, $codeMatches);
$replaceCode = $result ? preg_replace('/_(\d+)$/', '_' . ($codeMatches[1] + 1), $repeatObject->code) : $repeatObject->code . '_1';
$table = $oldAction->objectType == 'product' ? TABLE_PRODUCT : TABLE_PROJECT;
$object = $oldAction->objectType == 'product' ? $product : $project;
$existNames = $this->dao->select('name')->from($table)->where('name')->like($repeatObject->name . '_%')->fetchPairs();
for($i = 1; $i < 10000; $i ++)
{
$replaceName = $repeatObject->name . '_' . $i;
if(!in_array($replaceName, $existNames)) break;
}
$replaceCode = '';
if($object->code)
{
$existCodes = $this->dao->select('code')->from($table)->where('code')->like($repeatObject->code . '_%')->fetchPairs();
for($i = 1; $i < 10000; $i ++)
{
$replaceCode = $repeatObject->code . '_' . $i;
if(!in_array($replaceCode, $existCodes)) break;
}
}
if($repeatObject->name == $object->name and $repeatObject->code and $repeatObject->code == $object->code)
{
if($confirmChange == 'no') return print(js::confirm(sprintf($this->lang->action->repeatChange, $this->lang->{$oldAction->objectType}->common, $replaceName, $replaceCode), $this->createLink('action', 'undelete', "action={$actionID}&browseType={$browseType}&confirmChange=yes")));
+25 -10
View File
@@ -1000,13 +1000,15 @@ class actionModel extends model
elseif($productID == 'all' and is_numeric($projectID))
{
$products = $this->loadModel('product')->getProductPairsByProject($projectID);
$executions = $this->loadModel('execution')->getPairs($projectID) + array(0 => 0);
$executions = $this->loadModel('execution')->getPairs($projectID);
$authedExecutions = isset($authedExecutions) ? array_intersect(array_keys($executions), explode(',', $authedExecutions)) : array_keys($executions);
$productCondition = '';
foreach(array_keys($products) as $product) $productCondition = empty($productCondition) ? "product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'";
$projectCondition = "project = $projectID";
$executionCondition = "execution " . helper::dbIN(array_keys($executions));
$executionCondition = "execution " . helper::dbIN($authedExecutions);
}
elseif(is_numeric($productID) and $projectID == 'all')
{
@@ -1014,15 +1016,18 @@ class actionModel extends model
$projects = $this->product->getProjectPairsByProduct($productID);
$executions = $this->product->getExecutionPairsByProduct($productID);
$productCondition = "product = $productID";
$projectCondition = "project " . helper::dbIN(array_keys($projects));
$executionCondition = "execution " . helper::dbIN(array_keys($executions));
$authedProjects = array_intersect(array_keys($projects), explode(',', $authedProjects));
$authedExecutions = isset($authedExecutions) ? array_intersect(array_keys($executions), explode(',', $authedExecutions)) : array_keys($executions);
$productCondition = "product like '%,$productID,%'";
$projectCondition = 'project ' . helper::dbIN($authedProjects);
$executionCondition = 'execution ' . helper::dbIN($authedExecutions);
}
$condition = "((product =',0,' or product = '0') AND project = '0' AND execution = '0')";
if(!empty($productCondition)) $condition .= ' OR ' . $productCondition;
if(!empty($projectCondition)) $condition .= ' OR ' . $projectCondition;
if(!empty($executionCondition)) $condition .= ' OR ' . $executionCondition;
$condition = "((product =',0,' or product = '0' or product=',,') AND project = '0' AND execution = '0')";
if(!empty($productCondition)) $condition .= " OR $productCondition";
if(!empty($projectCondition)) $condition .= " OR $projectCondition";
if(!empty($executionCondition)) $condition .= " OR $executionCondition";
}
$actionCondition = $this->getActionCondition();
@@ -1092,7 +1097,8 @@ class actionModel extends model
foreach($this->app->user->rights['acls']['actions'] as $moduleName => $actions)
{
if(isset($this->lang->mainNav->$moduleName) and !empty($this->app->user->rights['acls']['views']) and !isset($this->app->user->rights['acls']['views'][$moduleName])) continue;
$actionCondition .= "(`objectType` = '$moduleName' and `action` " . helper::dbIN($actions) . ") or ";
$canViewPrograms = $moduleName == 'program' ? "`objectID` in ({$this->app->user->view->programs}) and " : '';
$actionCondition .= "($canViewPrograms `objectType` = '$moduleName' and `action` " . helper::dbIN($actions) . ") or ";
}
$actionCondition = trim($actionCondition, 'or ');
}
@@ -1214,8 +1220,17 @@ class actionModel extends model
$relatedProjects = $relatedData['relatedProjects'];
$requirements = $relatedData['requirements'];
$aclViews = isset($this->app->user->rights['acls']['views']) ? $this->app->user->rights['acls']['views'] : array();
$authedProjects = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['project']))) ? ",{$this->app->user->view->projects}," : array();
$authedExecutions = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['execution']))) ? ",{$this->app->user->view->sprints},": array();
foreach($actions as $i => $action)
{
if(($action->execution != '0' and strpos($authedExecutions, ",$action->execution,") === false) or ($action->execution == '0' and $action->project != '0' and strpos($authedProjects, ",$action->project,") === false))
{
unset($actions[$i]);
continue;
}
/* Add name field to the actions. */
$action->objectName = isset($objectNames[$action->objectType][$action->objectID]) ? $objectNames[$action->objectType][$action->objectID] : '';
+3 -3
View File
@@ -353,7 +353,7 @@ class api extends control
$this->view->type = $type;
$this->view->groups = $this->loadModel('group')->getPairs();
$this->view->users = $this->user->getPairs('nocode');
$this->view->users = $this->user->getPairs('nocode|noclosed');
$this->display();
}
@@ -388,7 +388,7 @@ class api extends control
$this->view->doc = $doc;
$this->view->groups = $this->loadModel('group')->getPairs();
$this->view->users = $this->user->getPairs('nocode');
$this->view->users = $this->user->getPairs('nocode|noclosed');
$this->display();
}
@@ -636,7 +636,7 @@ class api extends control
if(intval($libID) > 0 and common::hasPriv('api', 'create'))
{
$menu .= "<li>";
$menu .= html::a(helper::createLink('api', 'create', "libID=$libID&moduleID=$moduleID"), "<i class='icon-rich-text icon'></i> " . $this->lang->api->apiDoc, '', "data-app='{$this->app->tab}'");
$menu .= html::a(helper::createLink('api', 'create', "libID=$libID&moduleID=$moduleID"), "<i class='icon-rich-text icon'></i> " . $this->lang->api->createApi, '', "data-app='{$this->app->tab}'");
$menu .= "</li>";
}
+1
View File
@@ -217,6 +217,7 @@ class buildModel extends model
{
$selectedBuilds = $this->dao->select('id, name')->from(TABLE_BUILD)
->where('id')->in($buildIdList)
->beginIF($products)->andWhere('product')->in($products)->fi()
->beginIF($objectType === 'execution')->andWhere('execution')->eq($objectID)->fi()
->beginIF($objectType === 'project')->andWhere('project')->eq($objectID)->fi()
->fetchPairs();
+2 -2
View File
@@ -52,7 +52,7 @@
<th class='c-project required' style="width:100%"><?php echo $lang->execution->projectName;?></th>
<?php endif;?>
<th class='required <?php echo $minWidth?>' style="width:100%"><?php echo $lang->execution->$name;?></th>
<?php if(!isset($config->setCode) and $config->setCode == 1):?>
<?php if(!isset($config->setCode) or $config->setCode == 1):?>
<th class='c-code required'><?php echo $lang->execution->$code;?></th>
<?php endif;?>
<th class='c-user<?php echo zget($visibleFields, 'PM', ' hidden') . zget($requiredFields, 'PM', '', ' required');?>'><?php echo $lang->execution->$PM;?></th>
@@ -86,7 +86,7 @@
<td class='text-left' style='overflow:visible'><?php echo html::select("projects[$executionID]", $allProjects, $executions[$executionID]->project, "class='form-control picker-select' data-lastselected='{$executions[$executionID]->project}' onchange='changeProject(this, $executionID, {$executions[$executionID]->project})'");?></td>
<?php endif;?>
<td title='<?php echo $executions[$executionID]->name?>'><?php echo html::input("names[$executionID]", $executions[$executionID]->name, "id='names{$executionID}' class='form-control'");?></td>
<?php if(!isset($config->setCode) and $config->setCode == 1):?>
<?php if(!isset($config->setCode) or $config->setCode == 1):?>
<td><?php echo html::input("codes[$executionID]", $executions[$executionID]->code, "class='form-control'");?></td>
<?php endif;?>
<td class='text-left<?php echo zget($visibleFields, 'PM', ' hidden')?>' style='overflow:visible'><?php echo html::select("PMs[$executionID]", $pmUsers, $executions[$executionID]->PM, "class='form-control picker-select'");?></td>
+1 -1
View File
@@ -1017,7 +1017,7 @@ class fileModel extends model
{
if($this->config->file->storageType == 'fs')
{
return getimagesize($file->realPath);
return file_exists($file->realPath) ? getimagesize($file->realPath) : 0;
}
else if($this->config->file->storageType == 's3')
{
+2
View File
@@ -8,7 +8,9 @@ $lang->gitea->edit = 'Edit Gitea';
$lang->gitea->view = 'View Gitea';
$lang->gitea->delete = 'Delete Gitea';
$lang->gitea->confirmDelete = 'Do you want to delete this Gitea server?';
$lang->gitea->giteaAvatar = 'Avatar';
$lang->gitea->bindUser = 'Bind User';
$lang->gitea->giteaEmail = 'Email';
$lang->gitea->giteaAccount = 'Gitea Account';
$lang->gitea->zentaoAccount = 'Zentao Account';
$lang->gitea->bindingStatus = 'Binding Status';
+2
View File
@@ -8,7 +8,9 @@ $lang->gitea->edit = 'Edit Gitea';
$lang->gitea->view = 'View Gitea';
$lang->gitea->delete = 'Delete Gitea';
$lang->gitea->confirmDelete = 'Do you want to delete this Gitea server?';
$lang->gitea->giteaAvatar = 'Avatar';
$lang->gitea->bindUser = 'Bind User';
$lang->gitea->giteaEmail = 'Email';
$lang->gitea->giteaAccount = 'Gitea Account';
$lang->gitea->zentaoAccount = 'Zentao Account';
$lang->gitea->bindingStatus = 'Binding Status';
+2
View File
@@ -8,7 +8,9 @@ $lang->gitea->edit = 'Edit Gitea';
$lang->gitea->view = 'View Gitea';
$lang->gitea->delete = 'Delete Gitea';
$lang->gitea->confirmDelete = 'Do you want to delete this Gitea server?';
$lang->gitea->giteaAvatar = 'Avatar';
$lang->gitea->bindUser = 'Bind User';
$lang->gitea->giteaEmail = 'Email';
$lang->gitea->giteaAccount = 'Gitea Account';
$lang->gitea->zentaoAccount = 'Zentao Account';
$lang->gitea->bindingStatus = 'Binding Status';
+2
View File
@@ -8,7 +8,9 @@ $lang->gitea->edit = 'Edit Gitea';
$lang->gitea->view = 'View Gitea';
$lang->gitea->delete = 'Delete Gitea';
$lang->gitea->confirmDelete = 'Do you want to delete this Gitea server?';
$lang->gitea->giteaAvatar = 'Avatar';
$lang->gitea->bindUser = 'Bind User';
$lang->gitea->giteaEmail = 'Email';
$lang->gitea->giteaAccount = 'Gitea Account';
$lang->gitea->zentaoAccount = 'Zentao Account';
$lang->gitea->bindingStatus = 'Binding Status';
+2
View File
@@ -9,7 +9,9 @@ $lang->gitea->view = '查看Gitea';
$lang->gitea->delete = '删除Gitea';
$lang->gitea->confirmDelete = '确认删除该Gitea吗?';
$lang->gitea->bindUser = '绑定用户';
$lang->gitea->giteaAvatar = '头像';
$lang->gitea->giteaAccount = 'Gitea用户';
$lang->gitea->giteaEmail = '邮箱';
$lang->gitea->zentaoAccount = '禅道用户';
$lang->gitea->bindingStatus = '绑定状态';
$lang->gitea->notBind = '未绑定';
+12 -5
View File
@@ -556,15 +556,22 @@ class giteaModel extends model
* Get single branch by API.
*
* @param int $giteaID
* @param int $projectID
* @param string $branch
* @param string $project
* @param string $branchName
* @access public
* @return object
*/
public function apiGetSingleBranch($giteaID, $projectID, $branch)
public function apiGetSingleBranch($giteaID, $project, $branchName)
{
$url = sprintf($this->getApiRoot($giteaID), "/repos/$projectID/branches/$branch");
return json_decode(commonModel::http($url));
$url = sprintf($this->getApiRoot($giteaID), "/repos/$project/branches/$branchName");
$branch = json_decode(commonModel::http($url));
if($branch)
{
$gitea = $this->getByID($giteaID);
$branch->web_url = "{$gitea->url}/$project/src/branch/$branchName";
}
return $branch;
}
/**
+9 -7
View File
@@ -17,12 +17,14 @@
</div>
<form method='post' class='load-indicator main-form form-ajax' enctype='multipart/form-data'>
<div class="table-responsive">
<table class="table table-borderless w-600px">
<table class="table table-borderless w-800px">
<thead>
<tr>
<th colspan='2'><?php echo $lang->gitea->giteaAccount;?></th>
<th class='w-60px'><?php echo $lang->gitea->giteaAvatar;?></th>
<th><?php echo $lang->gitea->giteaAccount;?></th>
<th><?php echo $lang->gitea->giteaEmail;?></th>
<th class='w-150px'><?php echo $lang->gitea->zentaoAccount;?></th>
<th class='w-150px'><?php echo $lang->gitea->bindingStatus;?></th>
<th><?php echo $lang->gitea->bindingStatus;?></th>
</tr>
</thead>
<tbody>
@@ -30,13 +32,13 @@
<?php if(isset($giteaUser->zentaoAccount)) continue;?>
<?php echo html::hidden("giteaUserNames[$giteaUser->account]", $giteaUser->realname);?>
<tr>
<td class='w-60px'><?php echo html::image($giteaUser->avatar, "height=40");?></td>
<td><?php echo html::image($giteaUser->avatar, "height=40");?></td>
<td class='text-left'>
<strong><?php echo $giteaUser->realname;?></strong>
<br>
<?php echo $giteaUser->account;?>
<?php if($giteaUser->email) echo " &lt;" . $giteaUser->email . "&gt;";?>
</td>
<td><?php echo $giteaUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$giteaUser->account]", $userPairs, '', "class='form-control select chosen'" );?></td>
<td><?php echo $lang->gitea->notBind;?></td>
</tr>
@@ -45,13 +47,13 @@
<?php if(!isset($giteaUser->zentaoAccount)) continue;?>
<?php echo html::hidden("giteaUserNames[$giteaUser->account]", $giteaUser->realname);?>
<tr>
<td class='w-60px'><?php echo html::image($giteaUser->avatar, "height=40");?></td>
<td><?php echo html::image($giteaUser->avatar, "height=40");?></td>
<td>
<strong><?php echo $giteaUser->realname;?></strong>
<br>
<?php echo $giteaUser->account;?>
<?php if($giteaUser->email) echo " &lt;" . $giteaUser->email . "&gt;";?>
</td>
<td><?php echo $giteaUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$giteaUser->account]", $userPairs, $giteaUser->zentaoAccount, "class='form-control select chosen'" );?></td>
<td>
<?php if(isset($bindedUsers[$giteaUser->zentaoAccount])):?>
+2
View File
@@ -12,7 +12,9 @@ $lang->gitlab->bindProduct = 'Import Product';
$lang->gitlab->importIssue = 'Import Issue';
$lang->gitlab->delete = 'Delete GitLab';
$lang->gitlab->confirmDelete = 'Do you want to delete this GitLab server?';
$lang->gitlab->gitlabAvatar = 'Avatar';
$lang->gitlab->gitlabAccount = 'GitLab Account';
$lang->gitlab->gitlabEmail = 'Email';
$lang->gitlab->zentaoAccount = 'Zentao Account';
$lang->gitlab->bindingStatus = 'Binding Status';
$lang->gitlab->notBind = 'Not bind';
+2
View File
@@ -12,7 +12,9 @@ $lang->gitlab->bindProduct = 'Import Product';
$lang->gitlab->importIssue = 'Import Issue';
$lang->gitlab->delete = 'Delete GitLab';
$lang->gitlab->confirmDelete = 'Do you want to delete this GitLab server?';
$lang->gitlab->gitlabAvatar = 'Avatar';
$lang->gitlab->gitlabAccount = 'GitLab Account';
$lang->gitlab->gitlabEmail = 'Email';
$lang->gitlab->zentaoAccount = 'Zentao Account';
$lang->gitlab->bindingStatus = 'Binding Status';
$lang->gitlab->notBind = 'Not bind';
+2
View File
@@ -12,7 +12,9 @@ $lang->gitlab->bindProduct = 'Import Product';
$lang->gitlab->importIssue = 'Import Issue';
$lang->gitlab->delete = 'Delete GitLab';
$lang->gitlab->confirmDelete = 'Do you want to delete this GitLab server?';
$lang->gitlab->gitlabAvatar = 'Avatar';
$lang->gitlab->gitlabAccount = 'GitLab Account';
$lang->gitlab->gitlabEmail = 'Email';
$lang->gitlab->zentaoAccount = 'Zentao Account';
$lang->gitlab->bindingStatus = 'Binding Status';
$lang->gitlab->notBind = 'Not bind';
+2
View File
@@ -12,7 +12,9 @@ $lang->gitlab->bindProduct = 'Import Product';
$lang->gitlab->importIssue = 'Import Issue';
$lang->gitlab->delete = 'Delete GitLab';
$lang->gitlab->confirmDelete = 'Do you want to delete this GitLab server?';
$lang->gitlab->gitlabAvatar = 'Avatar';
$lang->gitlab->gitlabAccount = 'GitLab Account';
$lang->gitlab->gitlabEmail = 'Email';
$lang->gitlab->zentaoAccount = 'Zentao Account';
$lang->gitlab->bindingStatus = 'Binding Status';
$lang->gitlab->notBind = 'Not bind';
+2
View File
@@ -12,7 +12,9 @@ $lang->gitlab->bindProduct = '关联产品';
$lang->gitlab->importIssue = '关联issue';
$lang->gitlab->delete = '删除GitLab';
$lang->gitlab->confirmDelete = '确认删除该GitLab吗?';
$lang->gitlab->gitlabAvatar = '头像';
$lang->gitlab->gitlabAccount = 'GitLab用户';
$lang->gitlab->gitlabEmail = '邮箱';
$lang->gitlab->zentaoAccount = '禅道用户';
$lang->gitlab->bindingStatus = '绑定状态';
$lang->gitlab->notBind = '未绑定';
+9 -7
View File
@@ -17,12 +17,14 @@
</div>
<form method='post' class='load-indicator main-form form-ajax' enctype='multipart/form-data'>
<div class="table-responsive">
<table class="table table-borderless w-600px">
<table class="table table-borderless w-800px">
<thead>
<tr>
<th colspan='2'><?php echo $lang->gitlab->gitlabAccount;?></th>
<th class='w-60px'><?php echo $lang->gitlab->gitlabAvatar;?></th>
<th><?php echo $lang->gitlab->gitlabAccount;?></th>
<th><?php echo $lang->gitlab->gitlabEmail;?></th>
<th class='w-150px'><?php echo $lang->gitlab->zentaoAccount;?></th>
<th class='w-150px'><?php echo $lang->gitlab->bindingStatus;?></th>
<th><?php echo $lang->gitlab->bindingStatus;?></th>
</tr>
</thead>
<tbody>
@@ -30,13 +32,13 @@
<?php if(isset($gitlabUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gitlabUserNames[$gitlabUser->id]", $gitlabUser->realname);?>
<tr>
<td class='w-60px'><?php echo html::image($gitlabUser->avatar, "height=40");?></td>
<td><?php echo html::image($gitlabUser->avatar, "height=40");?></td>
<td class='text-left'>
<strong><?php echo $gitlabUser->realname;?></strong>
<br>
<?php echo $gitlabUser->account;?>
<?php if($gitlabUser->email) echo " &lt;" . $gitlabUser->email . "&gt;";?>
</td>
<td><?php echo $gitlabUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$gitlabUser->id]", $userPairs, '', "class='form-control select chosen'" );?></td>
<td><?php echo $lang->gitlab->notBind;?></td>
</tr>
@@ -45,13 +47,13 @@
<?php if(!isset($gitlabUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gitlabUserNames[$gitlabUser->id]", $gitlabUser->realname);?>
<tr>
<td class='w-60px'><?php echo html::image($gitlabUser->avatar, "height=40");?></td>
<td><?php echo html::image($gitlabUser->avatar, "height=40");?></td>
<td>
<strong><?php echo $gitlabUser->realname;?></strong>
<br>
<?php echo $gitlabUser->account;?>
<?php if($gitlabUser->email) echo " &lt;" . $gitlabUser->email . "&gt;";?>
</td>
<td><?php echo $gitlabUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$gitlabUser->id]", $userPairs, $gitlabUser->zentaoAccount, "class='form-control select chosen'" );?></td>
<td>
<?php if(isset($bindedUsers[$gitlabUser->zentaoAccount])):?>
+1 -1
View File
@@ -1527,7 +1527,7 @@ class kanbanModel extends model
$cardList = array();
if($browseType == 'story') $cardList = $this->loadModel('story')->getExecutionStories($executionID, 0, 0, 't1.`order`_desc', 'allStory');
if($browseType == 'bug') $cardList = $this->loadModel('bug')->getExecutionBugs($executionID);
if($browseType == 'task') $cardList = $this->loadModel('execution')->getKanbanTasks($executionID, "id");
if($browseType == 'task') $cardList = $this->loadModel('execution')->getKanbanTasks($executionID);
if($browseType == 'task' and $groupBy == 'assignedTo')
{
+15 -7
View File
@@ -106,11 +106,19 @@ class mr extends control
$repoID = $this->loadModel('repo')->saveState(0);
$repo = $this->repo->getRepoByID($repoID);
$this->loadModel('gitea');
if($repo->SCM == 'Gitea')
{
$project = $this->gitea->apiGetSingleProject($repo->gitService, $repo->project);
if(empty($project) or !$project->allow_merge_commits) $repo = array();
}
$hosts = $this->loadModel('pipeline')->getList(array('gitea', 'gitlab'));
if(!$this->app->user->admin)
{
$gitlabUsers = $this->loadModel('gitlab')->getGitLabListByAccount();
$giteaUsers = $this->loadModel('gitea')->getGiteaListByAccount();
$giteaUsers = $this->gitea->getGiteaListByAccount();
foreach($hosts as $hostID => $host)
{
if($host->type == 'gitLab' and isset($gitlabUsers[$hostID])) continue;
@@ -465,7 +473,7 @@ class mr extends control
$this->view->MR = $MR;
$this->view->action = $action;
$this->view->actions = $this->loadModel('action')->getList('mrapproval', $MRID);
$this->view->actions = $this->loadModel('action')->getList('mr', $MRID);
$this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed');
$this->display();
}
@@ -524,9 +532,9 @@ class mr extends control
$bugPager = new pager(0, $recPerPage, $type == 'bug' ? $pageID : 1);
$taskPager = new pager(0, $recPerPage, $type == 'task' ? $pageID : 1);
$stories = $this->mr->getLinkList($MRID, $product->id, 'story', $orderBy, $storyPager);
$bugs = $this->mr->getLinkList($MRID, $product->id, 'bug', $orderBy, $bugPager);
$tasks = $this->mr->getLinkList($MRID, $product->id, 'task', $orderBy, $taskPager);
$stories = $this->mr->getLinkList($MRID, $product->id, 'story', $type == 'story' ? $orderBy : '', $storyPager);
$bugs = $this->mr->getLinkList($MRID, $product->id, 'bug', $type == 'bug' ? $orderBy : '', $bugPager);
$tasks = $this->mr->getLinkList($MRID, $product->id, 'task', $type == 'task' ? $orderBy : '', $taskPager);
$this->view->title = $this->lang->mr->common . $this->lang->colon . $this->lang->mr->link;
$this->view->MR = $MR;
@@ -575,7 +583,7 @@ class mr extends control
$this->app->loadLang('productplan');
$product = $this->loadModel('product')->getById($productID);
$modules = $this->loadModel('tree')->getOptionMenu($productID, $viewType = 'story');
$modules = $this->loadModel('tree')->getOptionMenu($productID, 'story');
/* Load pager. */
$this->app->loadClass('pager', $static = true);
@@ -619,7 +627,7 @@ class mr extends control
}
else
{
$allStories = $this->story->getProductStories($productID, 0, $moduleID = '0', $status = 'draft,active,changed', 'story', 'id_desc', $hasParent = false, array_keys($linkedStories), $pager);
$allStories = $this->story->getProductStories($productID, 0, '0', 'draft,active,changed', 'story', 'id_desc', false, array_keys($linkedStories), $pager);
}
$this->view->modules = $modules;
-1
View File
@@ -11,7 +11,6 @@ table.diff {margin-bottom: 0px;}
.diff .line-all, .diff .line-all {background: #FFF;}
.diff .w-num {width: 25px; border-right: 1px solid #E4E4E4; color: #999; border-left: 1px solid #E4E4E4; color: #999; font-weight: normal;}
.repoCode .diff tr .comment-btn .icon-wrapper {left: -23px;}
.repoCode .diff tr.over td.line-all, .repoCode .diff tr.over td.line-all {background: #f8eec7;}
.repoCode .diff tr.over td.line-new, .repoCode .diff tr.over td.line-new {background: #8eff8e;}
.repoCode .diff tr.over td.line-old, .repoCode .diff tr.over td.line-old {background: #f6b2b2;}
+1
View File
@@ -68,6 +68,7 @@ $(function()
$.get(repoUrl, function(response)
{
$('#repoID').html('').append(response);
$('#repoID').val(repo.id);
$('#repoID').chosen().trigger("chosen:updated");;
});
+2
View File
@@ -119,6 +119,7 @@ $lang->mr->apiErrorMap[3] = "401 Unauthorized";
$lang->mr->apiErrorMap[4] = "403 Forbidden";
$lang->mr->apiErrorMap[5] = "/(pull request already exists for these targets).*/";
$lang->mr->apiErrorMap[6] = "Invalid PullRequest: There are no changes between the head and the base";
$lang->mr->apiErrorMap[7] = "/(user doesn't have access to repo).*/";
$lang->mr->errorLang[1] = 'The source project branch cannot be the same as the target project branch';
$lang->mr->errorLang[2] = 'Another open merge request already exists for this source branch: ID%u';
@@ -126,6 +127,7 @@ $lang->mr->errorLang[3] = "Unauthorized";
$lang->mr->errorLang[4] = 'Permission denied';
$lang->mr->errorLang[5] = 'Another open merge request already exists for this source branch';
$lang->mr->errorLang[6] = 'The source project branch cannot be the same as the target project branch';
$lang->mr->errorLang[7] = "user doesn't have access to repo";
$lang->mr->from = "from";
$lang->mr->to = "to";
+2
View File
@@ -119,6 +119,7 @@ $lang->mr->apiErrorMap[3] = "401 Unauthorized";
$lang->mr->apiErrorMap[4] = "403 Forbidden";
$lang->mr->apiErrorMap[5] = "/(pull request already exists for these targets).*/";
$lang->mr->apiErrorMap[6] = "Invalid PullRequest: There are no changes between the head and the base";
$lang->mr->apiErrorMap[7] = "/(user doesn't have access to repo).*/";
$lang->mr->errorLang[1] = 'The source project branch cannot be the same as the target project branch';
$lang->mr->errorLang[2] = 'Another open merge request already exists for this source branch: ID%u';
@@ -126,6 +127,7 @@ $lang->mr->errorLang[3] = "Unauthorized";
$lang->mr->errorLang[4] = 'Permission denied';
$lang->mr->errorLang[5] = 'Another open merge request already exists for this source branch';
$lang->mr->errorLang[6] = 'The source project branch cannot be the same as the target project branch';
$lang->mr->errorLang[7] = "user doesn't have access to repo";
$lang->mr->from = "from";
$lang->mr->to = "to";
+2
View File
@@ -119,6 +119,7 @@ $lang->mr->apiErrorMap[3] = "401 Unauthorized";
$lang->mr->apiErrorMap[4] = "403 Forbidden";
$lang->mr->apiErrorMap[5] = "/(pull request already exists for these targets).*/";
$lang->mr->apiErrorMap[6] = "Invalid PullRequest: There are no changes between the head and the base";
$lang->mr->apiErrorMap[7] = "/(user doesn't have access to repo).*/";
$lang->mr->errorLang[1] = 'The source project branch cannot be the same as the target project branch';
$lang->mr->errorLang[2] = 'Another open merge request already exists for this source branch: ID%u';
@@ -126,6 +127,7 @@ $lang->mr->errorLang[3] = "Unauthorized";
$lang->mr->errorLang[4] = 'Permission denied';
$lang->mr->errorLang[5] = 'Another open merge request already exists for this source branch';
$lang->mr->errorLang[6] = 'The source project branch cannot be the same as the target project branch';
$lang->mr->errorLang[7] = "user doesn't have access to repo";
$lang->mr->from = "from";
$lang->mr->to = "to";
+2
View File
@@ -119,6 +119,7 @@ $lang->mr->apiErrorMap[3] = "401 Unauthorized";
$lang->mr->apiErrorMap[4] = "403 Forbidden";
$lang->mr->apiErrorMap[5] = "/(pull request already exists for these targets).*/";
$lang->mr->apiErrorMap[6] = "Invalid PullRequest: There are no changes between the head and the base";
$lang->mr->apiErrorMap[7] = "/(user doesn't have access to repo).*/";
$lang->mr->errorLang[1] = 'The source project branch cannot be the same as the target project branch';
$lang->mr->errorLang[2] = 'Another open merge request already exists for this source branch: ID%u';
@@ -126,6 +127,7 @@ $lang->mr->errorLang[3] = "Unauthorized";
$lang->mr->errorLang[4] = 'Permission denied';
$lang->mr->errorLang[5] = 'Another open merge request already exists for this source branch';
$lang->mr->errorLang[6] = 'The source project branch cannot be the same as the target project branch';
$lang->mr->errorLang[7] = "user doesn't have access to repo";
$lang->mr->from = "from";
$lang->mr->to = "to";
+2
View File
@@ -119,6 +119,7 @@ $lang->mr->apiErrorMap[3] = "401 Unauthorized";
$lang->mr->apiErrorMap[4] = "403 Forbidden";
$lang->mr->apiErrorMap[5] = "/(pull request already exists for these targets).*/";
$lang->mr->apiErrorMap[6] = "Invalid PullRequest: There are no changes between the head and the base";
$lang->mr->apiErrorMap[7] = "/(user doesn't have access to repo).*/";
$lang->mr->errorLang[1] = '源项目分支与目标项目分支不能相同';
$lang->mr->errorLang[2] = '存在另外一个同样的合并请求在源项目分支中: ID%u';
@@ -126,6 +127,7 @@ $lang->mr->errorLang[3] = '权限不足';
$lang->mr->errorLang[4] = '权限不足';
$lang->mr->errorLang[5] = '存在另外一个同样的合并请求在源项目分支中';
$lang->mr->errorLang[6] = '源项目分支与目标项目分支不能相同';
$lang->mr->errorLang[7] = '您无权合并改版本库';
$lang->mr->from = "从";
$lang->mr->to = "合并到";
+3 -3
View File
@@ -991,8 +991,8 @@ class mrModel extends model
$apiRoot = $this->loadModel('gitea')->getApiRoot($hostID);
$url = sprintf($apiRoot, "/repos/$projectID/pulls/$MRID/merge");
$merege = ($MR and $MR->squash == '1') ? 'squash' : 'merge';
$data = array('Do' => $merge);
$merge = ($MR and $MR->squash == '1') ? 'squash' : 'merge';
$data = array('Do' => $merge);
if($MR and $MR->removeSourceBranch == '1') $data['delete_branch_after_merge'] = true;
$rowMR = json_decode(commonModel::http($url, $data, array(), array(), 'json', 'POST'));
@@ -1213,7 +1213,7 @@ class mrModel extends model
public function approve($MR, $action = 'approve', $comment = '')
{
$this->loadModel('action');
$actionID = $this->action->create('mrapproval', $MR->id, $action);
$actionID = $this->action->create('mr', $MR->id, $action);
$oldMR = $MR;
if(isset($MR->status) and $MR->status == 'opened')
+1 -1
View File
@@ -24,7 +24,7 @@
<table class='table table-form'>
<tr>
<th><?php echo $lang->mr->server;?></th>
<td class='required'><?php echo html::select('hostID', array('') + $hostPairs, $repo->gitService, "class='form-control chosen'");?></td>
<td class='required'><?php echo html::select('hostID', array('') + $hostPairs, zget($repo, 'gitService', ''), "class='form-control chosen'");?></td>
</tr>
<tr>
<th style="white-space: nowrap;"><?php echo $lang->mr->sourceProject;?></th>
+1 -1
View File
@@ -47,7 +47,7 @@
</td>
<td><span class='label-pri <?php echo 'label-pri-' . $story->pri;?>' title='<?php echo zget($lang->story->priList, $story->pri, $story->pri)?>'><?php echo zget($lang->story->priList, $story->pri, $story->pri)?></span></td>
<td><?php echo $story->planTitle;?></td>
<td title='<?php echo $modules[$story->module]?>' class='text-left'><?php echo $modules[$story->module];?></td>
<td title='<?php echo zget($modules, $story->module, '/')?>' class='text-left'><?php echo zget($modules, $story->module, '/');?></td>
<td class='text-left nobr' title='<?php echo $story->title?>'>
<?php
if($story->parent > 0) echo "<span class='label label-badge label-light' title={$lang->story->children}>{$lang->story->childrenAB}</span>";
+1
View File
@@ -332,6 +332,7 @@ class myModel extends model
->andWhere('objectType')->eq($module)
->andWhere('action')->eq('assigned')
->fetchAll('objectID');
if(empty($objectIDList)) return array();
$objectList = $this->dao->select('*')->from($this->config->objectTables[$module])
->where('deleted')->eq(0)
+1 -1
View File
@@ -234,7 +234,7 @@ class program extends control
$this->action->logHistory($actionID, $changes);
}
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inLink('browse')));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->session->programList ? $this->session->programList : inLink('browse')));
}
$program = $this->program->getByID($programID);
+1 -1
View File
@@ -43,7 +43,7 @@
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->program->noProgram;?></span>
<?php common::printLink('program', 'create', '', "<i class='icon icon-plus'></i> " . $lang->program->create, '', "class='btn btn-info'");?>
<?php if($status == 'all') common::printLink('program', 'create', '', "<i class='icon icon-plus'></i> " . $lang->program->create, '', "class='btn btn-info'");?>
</p>
</div>
<?php else:?>
+12 -2
View File
@@ -217,8 +217,9 @@ class programplanModel extends model
if(empty($selectCustom)) $selectCustom = $this->loadModel('setting')->getItem("owner={$owner}&module={$module}&section={$section}&key={$object}");
$tasks = array();
$tasks = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIdList)->fetchAll('id');
$tasks = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIdList)->fetchAll('id');
$taskTeams = $this->dao->select('root,account')->from(TABLE_TEAM)->where('type')->eq('task')->andWhere('root')->in(array_keys($tasks))->fetchGroup('root', 'account');
$users = $this->loadModel('user')->getPairs('noletter');
if($baselineID)
{
@@ -272,6 +273,15 @@ class programplanModel extends model
$data->endDate = $end;
$data->duration = 0;
/* If multi task then show the teams. */
if($task->mode == 'multi' and !empty($taskTeams[$task->id]))
{
$teams = array_keys($taskTeams[$task->id]);
$assigneds = array();
foreach($teams as $assignedTo) $assigneds[] = zget($users, $assignedTo);
$data->owner_id = join(',', $assigneds);
}
if($data->endDate > $data->start_date) $data->duration = helper::diffDate($data->endDate, $data->start_date) + 1;
if($data->start_date) $data->start_date = date('d-m-Y', strtotime($data->start_date));
if($data->start_date == '' or $data->endDate == '') $data->duration = 0;
+33 -5
View File
@@ -53,6 +53,17 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;}
.gantt_critical_task{background:#e63030 !important; border-color:#9d3a3a !important;}
.gantt_marker .gantt_marker_content {left: -15px; background-color: #f51e1e;}
.gantt_row.task-item{cursor: pointer;}
#ganttDownload, #ganttHeader {display: none;}
#ganttContainer {margin-top: 10px;}
#mainContent:before {background: #fff;}
#mainContent.loading {overflow: hidden}
#mainContent.loading #ganttView {overflow: hidden}
#mainContent.loading #ganttHeader {display: block; padding-bottom: 20px; margin: 0; height: 46px;}
#mainContent.loading #ganttDownload {display: inline}
#mainContent.loading #ganttContainer {padding: 40px;}
#mainContent.loading .scrollVer_cell,
#mainContent.loading .scrollVer_cell {display: none;}
</style>
<?php js::set('customUrl', $this->createLink('programplan', 'ajaxCustom'));?>
<?php js::set('dateDetails', $dateDetails);?>
@@ -89,7 +100,7 @@ var loadingPrefixText = '<?php echo $lang->programplan->exporting;?>';
* Get remote script for export.
*
* @param string $url
* @param function $sucessCallback
* @param function $successCallback
* @param function $errorCallback
* @access public
* @return void
@@ -125,7 +136,7 @@ function updateProgress(progress)
* Draw gantt to canvas.
*
* @param string $exportType
* @param function $sucessCallback
* @param function $successCallback
* @param function $errorCallback
* @access public
* @return void
@@ -169,7 +180,17 @@ function drawGanttToCanvas(exportType, successCallback, errorCallback)
height: ''
});
$ganttView.css('height', oldHeight);
if(canvas) canvas.remove();
if(canvas)
{
try
{
canvas.removeNode(true)
}
catch(err)
{
canvas.remove()
};
}
};
var delayTime = Math.max(1000, Math.floor(10 * (ganttHeight * ganttWidth) / 100000));
var progressTimer;
@@ -225,7 +246,14 @@ function drawGanttToCanvas(exportType, successCallback, errorCallback)
{
updateProgress(0.95);
var imageUrl = URL.createObjectURL(blob);
$('#ganttDownload').attr({href: imageUrl})[0].click();
if(navigator.msSaveBlob)
{
navigator.msSaveOrOpenBlob(blob, 'gantt-export-<?php echo $projectID;?>.png');
}
else
{
$('#ganttDownload').attr({href: imageUrl})[0].click();
}
if(successCallback) successCallback(imageUrl);
afterFinish(canvas);
});
@@ -249,7 +277,7 @@ function drawGanttToCanvas(exportType, successCallback, errorCallback)
function exportGantt(exportType)
{
var $mainContent = $('#mainContent');
$mainContent.addClass('loading').css('height', Math.max(200, Math.floor($(window).height() - $('#footer').outerHeight() - $('#header').outerHeight() - 38)));
$mainContent.addClass('loading').css('height', Math.max(200, Math.floor($(window).height() - $('#footer').outerHeight() - $('#header').outerHeight() - $('#mainMenu').outerHeight() - 38)));
$('#ganttExportDate').text(new Date().format('yyyy-MM-dd hh:mm:ss'));
var afterFinish = function(url)
{
+53 -85
View File
@@ -310,48 +310,27 @@ class projectModel extends model
->groupBy('t2.project')
->fetchAll('project');
$leftTasks = $this->dao->select('t2.parent as project, count(*) as tasks')->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution = t2.id')
->where('t2.project')->in($projectIdList)
->andWhere('t2.deleted')->eq(0)
->andWhere('t1.deleted')->eq(0)
->andWhere('t1.status')->in('wait,doing,pause')
->groupBy('t2.project')
->fetchPairs();
$allStories = $this->getTotalStoriesByProject($projectIdList, 'story');
$doneStories = $this->getTotalStoriesByProject($projectIdList, 'story', 'closed');
$leftStories = $this->getTotalStoriesByProject($projectIdList, 'story', 'active');
$leftBugs = $this->getTotalBugByProject($projectIdList, 'active');
$allBugs = $this->getTotalBugByProject($projectIdList, 'all');
$doneBugs = $this->getTotalBugByProject($projectIdList, 'resolved');
$leftTasks = $this->getTotalTaskByProject($projectIdList, 'undone');
$allTasks = $this->getTotalTaskByProject($projectIdList, 'all');
$waitTasks = $this->getTotalTaskByProject($projectIdList, 'wait');
$doingTasks = $this->getTotalTaskByProject($projectIdList, 'doing');
$rndDoneTasks = $this->getTotalTaskByProject($projectIdList, 'done');
$liteDoneTasks = $this->getTotalTaskByProject($projectIdList, 'donelite');
$storySummary = $this->getTotalStoriesByProject($projectIdList);
$taskSummary = $this->getTotalTaskByProject($projectIdList);
$bugSummary = $this->getTotalBugByProject($projectIdList);
foreach($projects as $projectID => $project)
{
$project->consumed = isset($hours[$projectID]) ? (float)$hours[$projectID]->consumed : 0;
$project->estimate = isset($hours[$projectID]) ? (float)$hours[$projectID]->estimate : 0;
$project->teamCount = isset($teams[$projectID]) ? $teams[$projectID] : 0;
$project->leftTasks = isset($leftTasks[$projectID]) ? $leftTasks[$projectID] : 0;
$project->leftBugs = isset($leftBugs[$projectID]) ? $leftBugs[$projectID] : 0;
$project->allBugs = isset($allBugs[$projectID]) ? $allBugs[$projectID] : 0;
$project->doneBugs = isset($doneBugs[$projectID]) ? $doneBugs[$projectID] : 0;
$project->allStories = isset($allStories[$projectID]) ? $allStories[$projectID] : 0;
$project->doneStories = isset($doneStories[$projectID]) ? $doneStories[$projectID] : 0;
$project->leftStories = isset($leftStories[$projectID]) ? $leftStories[$projectID] : 0;
$project->leftTasks = isset($leftTasks[$projectID]) ? $leftTasks[$projectID] : 0;
$project->allTasks = isset($allTasks[$projectID]) ? $allTasks[$projectID] : 0;
$project->waitTasks = isset($waitTasks[$projectID]) ? $waitTasks[$projectID] : 0;
$project->doingTasks = isset($doingTasks[$projectID]) ? $doingTasks[$projectID] : 0;
$project->rndDoneTasks = isset($rndDoneTasks[$projectID]) ? $rndDoneTasks[$projectID] : 0;
$project->liteDoneTasks = isset($liteDoneTasks[$projectID]) ? $liteDoneTasks[$projectID] : 0;
$project->leftBugs = isset($bugSummary[$projectID]) ? $bugSummary[$projectID]->leftBugs : 0;
$project->allBugs = isset($bugSummary[$projectID]) ? $bugSummary[$projectID]->allBugs : 0;
$project->doneBugs = isset($bugSummary[$projectID]) ? $bugSummary[$projectID]->doneBugs : 0;
$project->allStories = isset($storySummary[$projectID]) ? $storySummary[$projectID]->allStories: 0;
$project->doneStories = isset($storySummary[$projectID]) ? $storySummary[$projectID]->doneStories: 0;
$project->leftStories = isset($storySummary[$projectID]) ? $storySummary[$projectID]->leftStories: 0;
$project->leftTasks = isset($taskSummary[$projectID]) ? $taskSummary[$projectID]->leftTasks : 0;
$project->allTasks = isset($taskSummary[$projectID]) ? $taskSummary[$projectID]->allTasks : 0;
$project->waitTasks = isset($taskSummary[$projectID]) ? $taskSummary[$projectID]->waitTasks : 0;
$project->doingTasks = isset($taskSummary[$projectID]) ? $taskSummary[$projectID]->doingTasks : 0;
$project->rndDoneTasks = isset($taskSummary[$projectID]) ? $taskSummary[$projectID]->doneTasks : 0;
$project->liteDoneTasks = isset($taskSummary[$projectID]) ? $taskSummary[$projectID]->litedoneTasks : 0;
if(is_float($project->consumed)) $project->consumed = round($project->consumed, 1);
if(is_float($project->estimate)) $project->estimate = round($project->estimate, 1);
@@ -364,23 +343,52 @@ class projectModel extends model
* Get the number of stories associated with the project.
*
* @param array $projectIdList
* @param string $type story|requirement
* @param string $status all|closed|active
* @access public
* @return int
*/
public function getTotalStoriesByProject($projectIdList = 0, $type = 'story', $status = 'all')
public function getTotalStoriesByProject($projectIdList = 0)
{
return $this->dao->select('t1.project, count(t2.id) as stories')->from(TABLE_PROJECTSTORY)->alias('t1')
return $this->dao->select("t1.project, count(t2.id) as allStories, count(if(t2.status = 'active' or t2.status = 'changed', 1, null)) as leftStories, count(if(t2.status = 'closed' and t2.closedReason = 'done', 1, null)) as doneStories")->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
->where('t1.project')->in($projectIdList)
->andWhere('t2.type')->eq($type)
->beginIF($status == 'active')->andWhere('t2.status')->in('active,changed')->fi()
->beginIF($status == 'closed')->andWhere('t2.status')->eq('closed')->fi()
->beginIF($status == 'closed')->andWhere('t2.closedReason')->eq('done')->fi()
->andWhere('t2.type')->eq('story')
->andWhere('deleted')->eq('0')
->groupBy('project')
->fetchPairs();
->fetchAll('project');
}
/**
* Get associated bugs by project.
*
* @param array $projectIdList
* @access public
* @return array
*/
public function getTotalBugByProject($projectIdList)
{
return $this->dao->select("project, count(id) as allBugs, count(if(status = 'active', 1, null)) as leftBugs, count(if(status = 'resolved', 1, null)) as doneBugs")->from(TABLE_BUG)
->where('project')->in($projectIdList)
->andWhere('deleted')->eq(0)
->groupBy('project')
->fetchAll('project');
}
/**
* Get associated tasks by project.
*
* @param array $projectIdList
* @access public
* @return array
*/
public function getTotalTaskByProject($projectIdList)
{
return $this->dao->select("t1.project, count(t1.id) as allTasks, count(if(t1.status = 'wait', 1, null)) as waitTasks, count(if(t1.status = 'doing', 1, null)) as doingTasks, count(if(t1.status = 'done', 1, null)) as doneTasks, count(if(t1.status = 'wait' or t1.status = 'pause' or t1.status = 'cancel', 1, null)) as leftTasks, count(if(t1.status = 'done' or t1.status = 'closed', 1, null)) as litedoneTasks")->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution=t2.id')
->where('t1.project')->in($projectIdList)
->andWhere('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->groupBy('project')
->fetchAll('project');
}
/**
@@ -772,46 +780,6 @@ class projectModel extends model
->fetchPairs('id', 'name');
}
/**
* Get associated bugs by project.
*
* @param array $projectIdList
* @param string $status active|resolved|all
* @access public
* @return array
*/
public function getTotalBugByProject($projectIdList, $status)
{
return $this->dao->select('project, count(*) as bugs')->from(TABLE_BUG)
->where('project')->in($projectIdList)
->andWhere('deleted')->eq(0)
->beginIF($status != 'all')->andWhere('status')->eq($status)->fi()
->groupBy('project')
->fetchPairs('project');
}
/**
* Get associated tasks by project.
*
* @param array $projectIdList
* @param string $status all|done|undone
* @access public
* @return array
*/
public function getTotalTaskByProject($projectIdList, $status)
{
return $this->dao->select('t1.project, count(t1.id) as tasks')->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution=t2.id')
->where('t1.project')->in($projectIdList)
->andWhere('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
->beginIF($status == 'donelite')->andWhere('t1.status')->in('done,closed')->fi()
->beginIF($status == 'undone')->andWhere('t1.status')->in('wait,pause,cancel')->fi()
->beginIF(strpos(',wait,doing,done,', ",$status,") !== false)->andWhere('t1.status')->eq($status)->fi()
->groupBy('t1.project')
->fetchPairs('project');
}
/**
* Get branches by project id.
*
+2 -2
View File
@@ -26,7 +26,7 @@
<th class='c-id'><?php echo $lang->idAB;?></th>
<th class='c-parent'><?php echo $lang->project->parent;?></th>
<th class='c-name required'><?php echo $lang->project->name;?></th>
<?php if(!isset($config->setCode) and $config->setCode == 1):?>
<?php if(!isset($config->setCode) or $config->setCode == 1):?>
<th class='c-name required'><?php echo $lang->project->code;?></th>
<?php endif?>
<th class="c-user-box <?php echo strpos($requiredFields, 'PM') !== false ? 'required' : '';?>"> <?php echo $lang->project->PM;?></th>
@@ -53,7 +53,7 @@
<td><?php echo html::select("parents[$projectID]", $programs, $project->parent, "class='form-control chosen' data-id='$projectID' data-name='{$project->name}' data-parent='{$project->parent}'");?></td>
<?php endif;?>
<td title='<?php echo $project->name;?>'><?php echo html::input("names[$projectID]", $project->name, "class='form-control'");?></td>
<?php if(!isset($config->setCode) and $config->setCode == 1):?>
<?php if(!isset($config->setCode) or $config->setCode == 1):?>
<td title='<?php echo $project->code;?>'><?php echo html::input("codes[$projectID]", $project->code, "class='form-control'");?></td>
<?php endif;?>
<td><?php echo html::select("PMs[$projectID]", $PMUsers, $project->PM, "class='form-control chosen'");?></td>
+1
View File
@@ -80,6 +80,7 @@ class repo extends control
{
$repoID = $this->repo->saveState(0, $objectID);
if($this->viewType !== 'json') $this->commonAction($repoID, $objectID);
if(common::hasPriv('repo', 'create')) $this->lang->TRActions = html::a(helper::createLink('repo', 'create'), "<i class='icon icon-plus'></i> " . $this->lang->repo->create, '', "class='btn btn-primary'");
$repoList = $this->repo->getList(0, '', $orderBy);
$sonarRepoList = $this->loadModel('job')->getSonarqubeByRepo(array_keys($repoList));
+1
View File
@@ -1,3 +1,4 @@
.change ul {margin: 8px; margin-left: 1.5em;}
.change li {list-style: none;}
.panel-heading {border-bottom: 1px solid #ddd;}
.back-btn {margin-right: 5px !important;}
+1 -1
View File
@@ -2,7 +2,7 @@
.code .content {border: 1px solid #CCC; padding: 0;}
.repoCode pre {margin: 0; padding: 0; background: white; border: none;}
tr,th,td {border-bottom: none;}
.repoCode pre > table > tbody > tr > th {border: none; background-color: #ECECEC; width: 40px; text-align: right; vertical-align: top;}
.repoCode pre > table > tbody > tr > th {border-right: 1px solid #E4E4E4; width: 40px; text-align: right; vertical-align: top;}
.repoCode pre > table > tbody > tr > th, .repoCode pre > table > tbody > tr > td {padding: 1px 3px;}
.repoCode pre .commentContent {line-height: 1.4;}
.repoCode pre > table {border: 0px; width: 100%;}
+2 -2
View File
@@ -213,7 +213,7 @@ class repoModel extends model
->andWhere('client')->eq($data->client)
->andWhere('path')->eq($data->path)
->fetch();
if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->id);
if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->name);
if(dao::isError()) return false;
}
@@ -312,7 +312,7 @@ class repoModel extends model
->andWhere('path')->eq($data->path)
->andWhere('id')->ne($id)
->fetch();
if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->id);
if(!empty($repo)) dao::$errors['serviceProject'] = sprintf($this->lang->error->unique, $this->lang->repo->serviceProject, $repo->name);
if(dao::isError()) return false;
}
+7 -7
View File
@@ -98,7 +98,7 @@
<tr>
<th class='c-icon'></th>
<th class='c-name'><?php echo $lang->repo->name?></th>
<th class='text-center c-version'><?php echo $lang->repo->revisions?></th>
<th class='c-version'><?php echo $lang->repo->revisions?></th>
<th class='c-date'><?php echo $lang->repo->time?></th>
<th class='c-user'><?php echo $lang->repo->committer?></th>
<th><?php echo $lang->repo->comment?></th>
@@ -112,13 +112,13 @@
<span class="<?php echo $info->kind == 'dir' ? 'directory' : 'file';?> mini-icon"></span>
</td>
<td>
<?php
$infoPath = trim($path . '/' . $info->name, '/');
$link = $info->kind == 'dir' ? $this->repo->createLink('browse', "repoID=$repoID&branchID=$base64BranchID&objectID=$objectID&path=" . $this->repo->encodePath($infoPath)) : $this->repo->createLink('view', "repoID=$repoID&objectID=$objectID&entry=" . $this->repo->encodePath($infoPath));
echo html::a($link, $info->name, '', "title='{$info->name}' data-app={$app->tab}");
?>
<?php
$infoPath = trim($path . '/' . $info->name, '/');
$link = $info->kind == 'dir' ? $this->repo->createLink('browse', "repoID=$repoID&branchID=$base64BranchID&objectID=$objectID&path=" . $this->repo->encodePath($infoPath)) : $this->repo->createLink('view', "repoID=$repoID&objectID=$objectID&entry=" . $this->repo->encodePath($infoPath));
echo html::a($link, $info->name, '', "title='{$info->name}' data-app={$app->tab}");
?>
</td>
<td align='center'><?php echo $repo->SCM == 'Subversion' ? $info->revision : substr($info->revision, 0, 10);?></td>
<td><?php echo $repo->SCM == 'Subversion' ? $info->revision : substr($info->revision, 0, 10);?></td>
<td><?php echo substr($info->date, 0, 10)?></td>
<td><?php echo $info->account?></td>
<?php $comment = htmlSpecialString($info->comment, ENT_QUOTES);?>
+2 -7
View File
@@ -11,11 +11,6 @@
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id="mainMenu" class="clearfix">
<div class='pull-right'>
<?php if(common::hasPriv('repo', 'create')) echo html::a(helper::createLink('repo', 'create'), "<i class='icon icon-plus'></i> " . $this->lang->repo->create, '', "class='btn btn-primary'");?>
</div>
</div>
<div id='mainContent'>
<form class='main-table' id='ajaxForm' method='post'>
<table id='repoList' class='table has-sort-head table-fixed'>
@@ -27,13 +22,13 @@
<th class='c-name text-left'><?php common::printOrderLink('name', $orderBy, $vars, $lang->repo->name); ?></th>
<th class='c-product text-left'><?php common::printOrderLink('product', $orderBy, $vars, $lang->repo->product); ?></th>
<th class='text-left'><?php echo $lang->repo->path; ?></th>
<th class='c-actions-7'><?php echo $lang->actions; ?></th>
<th class='c-actions-3'><?php echo $lang->actions; ?></th>
</tr>
</thead>
<tbody>
<?php foreach($repoList as $repo):?>
<tr>
<td class='text-center'><?php echo $repo->id; ?></td>
<td class='text'><?php echo $repo->id; ?></td>
<td class='text'><?php echo zget($lang->repo->scmList, $repo->SCM); ?></td>
<td class='text' title='<?php echo $repo->name; ?>'><?php echo html::a($this->createLink('repo', 'browse', "repoID={$repo->id}&branchID=&objectID=$objectID"), $repo->name);?></td>
<?php
+16 -16
View File
@@ -21,7 +21,7 @@ $typeInfo = $type == 'file' ? '&type=file' : '';
<div class='btn-toolbar pull-left'>
<?php if(!isonlybody()):?>
<?php $browseLink = $app->session->revisionList != false ? $app->session->revisionList : $this->repo->createLink('browse', "repoID={$repoID}&branchID=" . helper::safe64Encode(base64_encode($branchID)) . "&objectID=$objectID{$preDir}");?>
<?php echo html::a($browseLink, "<i class='icon icon-back'></i> " . $lang->goback, '', "class='btn btn-link'");?>
<?php echo html::a($browseLink, "<i class='icon icon-back'></i> " . $lang->goback, '', "class='btn btn-link back-btn'");?>
<div class="divider"></div>
<?php endif;?>
<div class="page-title">
@@ -42,8 +42,8 @@ $typeInfo = $type == 'file' ? '&type=file' : '';
<table class='table no-margin'>
<?php foreach($changes as $path => $change):?>
<tr>
<td><?php echo "<span class='label label-info label-badge'>" . $change['action'] . '</span> ' . $path?></td>
<td class='w-80px text-center'><?php echo zget($change, 'view', '') . zget($change, 'diff', '')?></td>
<td><?php echo "<span class='label label-info label-badge'>" . $change['action'] . '</span> ' . $path;?></td>
<td class='w-80px text-center'><?php echo zget($change, 'view', '') . zget($change, 'diff', '');?></td>
</tr>
<?php endforeach;?>
</table>
@@ -54,30 +54,30 @@ $typeInfo = $type == 'file' ? '&type=file' : '';
<div class='side-col col-4'>
<div class='cell'>
<div class='detail'>
<div class='detail-title'><?php echo $lang->repo->info?></div>
<div class='detail-title'><?php echo $lang->repo->info;?></div>
<div class='detail-content'>
<table class='table table-data'>
<tr>
<th class='w-80px'><?php echo $lang->repo->committer?></th>
<td><?php echo $log->committer?></td>
<th class='w-80px'><?php echo $lang->repo->committer;?></th>
<td><?php echo $log->committer;?></td>
</tr>
<tr>
<th><?php echo $lang->repo->revisionA?></th>
<td><?php echo $log->revision?></td>
<th><?php echo $lang->repo->revisionA;?></th>
<td><?php echo substr($log->revision, 0, 10);?></td>
</tr>
<?php if($repo->SCM != 'Subversion'):?>
<tr>
<th><?php echo $lang->repo->commit?></th>
<td><?php echo $log->commit?></td>
<th><?php echo $lang->repo->commit;?></th>
<td><?php echo $log->commit;?></td>
</tr>
<?php endif;?>
<tr>
<th><?php echo $lang->repo->comment?></th>
<td><?php echo $log->comment?></td>
<th><?php echo $lang->repo->comment;?></th>
<td><?php echo $log->comment;?></td>
</tr>
<tr>
<th><?php echo $lang->repo->time?></th>
<td><?php echo $log->time?></td>
<th><?php echo $lang->repo->time;?></th>
<td><?php echo $log->time;?></td>
</tr>
</table>
</div>
@@ -87,8 +87,8 @@ $typeInfo = $type == 'file' ? '&type=file' : '';
</div>
<div id="mainActions" class='main-actions'>
<nav class="container">
<?php if(!empty($preAndNext->pre)) echo html::a($this->repo->createLink('revision', "repoID=$repoID&objectID=$objectID&revision={$preAndNext->pre}" . $pathInfo . $typeInfo, 'html'), "<i class='icon-pre icon-chevron-left'></i>", '', "data-app='{$app->tab}' id='prevPage' class='btn btn-info' title='{$preAndNext->pre}'")?>
<?php if(!empty($preAndNext->next)) echo html::a($this->repo->createLink('revision', "repoID=$repoID&objectID=$objectID&revision={$preAndNext->next}" . $pathInfo . $typeInfo, 'html'), "<i class='icon-pre icon-chevron-right'></i>", '', "data-app='{$app->tab}' id='nextPage' class='btn btn-info' title='{$preAndNext->next}'")?>
<?php if(!empty($preAndNext->pre)) echo html::a($this->repo->createLink('revision', "repoID=$repoID&objectID=$objectID&revision={$preAndNext->pre}" . $pathInfo . $typeInfo, 'html'), "<i class='icon-pre icon-chevron-left'></i>", '', "data-app='{$app->tab}' id='prevPage' class='btn btn-info' title='{$preAndNext->pre}'");?>
<?php if(!empty($preAndNext->next)) echo html::a($this->repo->createLink('revision', "repoID=$repoID&objectID=$objectID&revision={$preAndNext->next}" . $pathInfo . $typeInfo, 'html'), "<i class='icon-pre icon-chevron-right'></i>", '', "data-app='{$app->tab}' id='nextPage' class='btn btn-info' title='{$preAndNext->next}'");?>
</nav>
</div>
<?php include '../../common/view/footer.html.php';?>
+6
View File
@@ -10,3 +10,9 @@
#dataform .priBox, #dataform .estimateBox {width: 120px;}
#dataform .categoryBox {width: 150px;}
#dataform .needNotReviewBox {width: 130px;}
.input-group-addon.assignedTo {min-width: 77px;}
.input-group .source {display: flex; width: 50%;}
.input-group .sourceNote {display: flex; width: 50%;}
.source .input-group-addon, .sourceNote .input-group-addon {padding-top: 9px;}
#sourceNoteBox {width: 80px;}
#moduleIdBox .input-group-addon {min-width: 77px;}
+11 -7
View File
@@ -90,12 +90,16 @@ foreach(explode(',', $config->story->create->requiredFields) as $field)
</td>
<td colspan="2" class="sourceTd <?php echo $hiddenSource?> sourceBox">
<div class="input-group">
<div class="input-group">
<div class="input-group-addon" style="min-width: 77px;"><?php echo $lang->story->source;?></div>
<?php echo html::select('source', $lang->story->sourceList, $source, "class='form-control chosen'");?>
<span class='input-group-addon' id='sourceNoteBox'><?php echo $lang->story->sourceNote;?></span>
<?php $sourceNoteWidth = isonlybody() ? "style='width: 89px;'" : "style='width: 180px;'"?>
<?php echo html::input('sourceNote', $sourceNote, "class='form-control' $sourceNoteWidth");?>
<div class="input-group" style='display: flex;'>
<div class='source'>
<div class="input-group-addon" style="min-width: 77px;"><?php echo $lang->story->source;?></div>
<?php echo html::select('source', $lang->story->sourceList, $source, "class='form-control chosen'");?>
</div>
<div class='sourceNote'>
<div class='input-group-addon' id='sourceNoteBox'><?php echo $lang->story->sourceNote;?></div>
<?php $sourceNoteWidth = isonlybody() ? "style='width: 89px;'" : ""?>
<?php echo html::input('sourceNote', $sourceNote, "class='form-control' $sourceNoteWidth");?>
</div>
</div>
</div>
</td>
@@ -126,7 +130,7 @@ foreach(explode(',', $config->story->create->requiredFields) as $field)
</td>
<td colspan='<?php echo $type == 'story' ? 2 : 1;?>' id='assignedToBox' class='hidden'>
<div class='input-group'>
<div class="input-group-addon"><?php echo $lang->story->assignedTo;?></div>
<div class="input-group-addon assignedTo"><?php echo $lang->story->assignedTo;?></div>
<?php echo html::select('assignedTo', $users, '', "class='form-control picker-select'");?>
</div>
</td>
+1 -1
View File
@@ -164,7 +164,7 @@
<td><?php echo $child->id;?></td>
<td>
<?php
echo "<span class='pri-" . $child->pri . "'>";
echo "<span class='label-pri label-pri-" . $child->pri . "'>";
echo $child->pri == '0' ? '' : zget($this->lang->story->priList, $child->pri, $child->pri);
echo "</span>";
?>
+1 -1
View File
@@ -116,7 +116,7 @@ $config->task->datatable->fieldList['left']['required'] = 'no';
$config->task->datatable->fieldList['progress']['title'] = 'progressAB';
$config->task->datatable->fieldList['progress']['fixed'] = 'no';
$config->task->datatable->fieldList['progress']['width'] = '50';
$config->task->datatable->fieldList['progress']['width'] = '80';
$config->task->datatable->fieldList['progress']['required'] = 'no';
$config->task->datatable->fieldList['progress']['sort'] = 'no';
$config->task->datatable->fieldList['progress']['name'] = $lang->task->progress;
+1 -6
View File
@@ -12,12 +12,7 @@ $(function()
*/
function loadAll(executionID)
{
if(!changeExecutionConfirmed)
{
firstChoice = confirm(confirmChangeExecution);
changeExecutionConfirmed = true; // Only notice the user one time.
}
if(changeExecutionConfirmed && firstChoice)
if(confirm(confirmChangeExecution))
{
loadModuleMenu(executionID);
loadExecutionStories(executionID);
+1 -1
View File
@@ -49,7 +49,7 @@ $lang->task->case = 'Fall';
$lang->task->confirmStoryChange = "Storyäanderung bestätigen";
$lang->task->storyChange = "Story Changed";
$lang->task->progress = 'Fortschritt';
$lang->task->progressAB = '%';
$lang->task->progressAB = 'Fortschritt';
$lang->task->progressTips = 'Genutzt/(Genutzt+Rest)';
$lang->task->copy = 'Aufgabe kopieren';
$lang->task->waitTask = 'Waiting Task';
+1 -1
View File
@@ -49,7 +49,7 @@ $lang->task->case = 'Linked Case';
$lang->task->confirmStoryChange = "Confirm Change";
$lang->task->storyChange = "Story Changed";
$lang->task->progress = 'Progress';
$lang->task->progressAB = '%';
$lang->task->progressAB = 'Progress';
$lang->task->progressTips = 'Cost/(Cost+Left)';
$lang->task->copy = 'Copy Task';
$lang->task->waitTask = 'Waiting Task';
+1 -1
View File
@@ -49,7 +49,7 @@ $lang->task->case = 'Associée CasTest';
$lang->task->confirmStoryChange = "Confirmer Changement";
$lang->task->storyChange = "Story Changée";
$lang->task->progress = 'Progression';
$lang->task->progressAB = '%';
$lang->task->progressAB = 'Progression';
$lang->task->progressTips = 'Coût/(Coût+Reste)';
$lang->task->copy = 'Copier Tâche';
$lang->task->waitTask = 'Tâche en attente';
+1 -1
View File
@@ -47,7 +47,7 @@ $lang->task->case = 'Tình huống liên kết';
$lang->task->confirmStoryChange = "Xác nhận thay đổi";
$lang->task->storyChange = "Câu chuyện đã thay đổi";
$lang->task->progress = 'Tiến độ';
$lang->task->progressAB = '%';
$lang->task->progressAB = 'Tiến độ';
$lang->task->progressTips = 'Đã làm/(Đã làm + Còn lại)';
$lang->task->copy = 'Copy nhiệm vụ';
$lang->task->waitTask = 'Đang đợi nhiệm vụ';
-1
View File
@@ -23,7 +23,6 @@
<?php js::set('team', $task->team);?>
<?php js::set('members', $members);?>
<?php js::set('confirmChangeExecution', $lang->task->confirmChangeExecution);?>
<?php js::set('changeExecutionConfirmed', false);?>
<?php js::set('newRowCount', count($task->team) < 6 ? 6 - count($task->team) : 1);?>
<?php js::set('teamMemberError', $lang->task->error->teamMember);?>
<?php js::set('totalLeftError', sprintf($this->lang->task->error->leftEmptyAB, $this->lang->task->statusList[$task->status]));?>
+7 -7
View File
@@ -2812,7 +2812,7 @@ class userModel extends model
public function getPersonalData($account = '')
{
if(empty($account)) $account = $this->app->user->account;
$count = 'count(*) AS count';
$count = 'count(id) AS count';
$personalData = array();
$personalData['createdTodos'] = $this->dao->select($count)->from(TABLE_TODO)->where('account')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
@@ -2823,13 +2823,13 @@ class userModel extends model
$personalData['createdCases'] = $this->dao->select($count)->from(TABLE_CASE)->where('openedBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
if($this->config->edition == 'max')
{
$personalData['createdRisks'] = $this->dao->select($count)->from(TABLE_RISK)->where('createdBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
$personalData['resolvedRisks'] = $this->dao->select($count)->from(TABLE_RISK)->where('resolvedBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
$personalData['createdIssues'] = $this->dao->select($count)->from(TABLE_ISSUE)->where('createdBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
$personalData['resolvedIssues'] = $this->dao->select($count)->from(TABLE_ISSUE)->where('resolvedBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
$personalData['createdRisks'] = $this->dao->select($count)->from(TABLE_RISK)->where('createdBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
$personalData['resolvedRisks'] = $this->dao->select($count)->from(TABLE_RISK)->where('resolvedBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
$personalData['createdIssues'] = $this->dao->select($count)->from(TABLE_ISSUE)->where('createdBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
$personalData['resolvedIssues'] = $this->dao->select($count)->from(TABLE_ISSUE)->where('resolvedBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
}
$personalData['createdDocs'] = $this->dao->select($count)->from(TABLE_DOC)->where('addedBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
$personalData['finishedTasks'] = $this->dao->select($count)->from(TABLE_TASK)->where('deleted')->eq('0')
$personalData['createdDocs'] = $this->dao->select($count)->from(TABLE_DOC)->where('addedBy')->eq($account)->andWhere('deleted')->eq('0')->fetch('count');
$personalData['finishedTasks'] = $this->dao->select($count)->from(TABLE_TASK)->where('deleted')->eq('0')
->andWhere('finishedBy', true)->eq($account)
->orWhere('finishedList')->like("%,{$account},%")
->markRight(1)