Merge branch 'sprint_200'
This commit is contained in:
+4
-1
@@ -1,3 +1,6 @@
|
||||
DELETE from zt_report where `code` = 'product-invest';
|
||||
ALTER TABLE `zt_review` ADD docVersion smallint(6) NOT NULL AFTER `doc`;
|
||||
|
||||
DELETE FROM `zt_workflowaction` WHERE `module`='story' AND `action`='browse';
|
||||
DELETE FROM `zt_workflowaction` WHERE `module`='task' AND `action`='browse';
|
||||
DELETE FROM `zt_workflowaction` WHERE `module`='build' AND `action`='browse';
|
||||
DELETE FROM `zt_workflowaction` WHERE `module`='build' AND `action`='browse';
|
||||
+1
-1
@@ -6791,7 +6791,6 @@ CREATE OR REPLACE VIEW `ztv_daybugresolve` AS select count(*) AS `bugresolve`,le
|
||||
CREATE OR REPLACE VIEW `ztv_dayactions` AS select count(*) AS `actions`,left(`zt_action`.`date`,10) AS `day` from `zt_action` group by left(`zt_action`.`date`,10);
|
||||
|
||||
REPLACE INTO `zt_report` (`code`, `name`, `module`, `sql`, `vars`, `langs`, `params`, `step`, `desc`, `addedBy`, `addedDate`) VALUES
|
||||
('product-invest', '{\"zh-cn\":\"\\u4ea7\\u54c1\\u6295\\u5165\\u8868\",\"zh-tw\":\"\\u7522\\u54c1\\u6295\\u5165\\u8868\",\"en\":\"Product Investment\"}', ',product', 'select t1.id,t1.name,1 as projects, round(t3.consumed,2) as consumed from TABLE_PRODUCT as t1\r\n left join TABLE_PROJECTPRODUCT as t2 on t1.id=t2.product\r\n left join ztv_projectsummary as t3 on t2.project=t3.project\r\n left join TABLE_PROJECT as t4 on t2.project=t4.id\r\n left join TABLE_PROGRAM as t5 on t1.program=t5.id\r\n where t1.deleted=\'0\' and t4.deleted=\'0\' and t4.type=\'project\'\r\norder by t5.`order` asc, t1.line desc, t1.`order` asc', '', '{\"projects\":{\"zh-cn\":\"\\u9879\\u76ee\\u6570\",\"zh-tw\":\"\\u9879\\u76ee\\u6570\",\"en\":\"Projects\"},\"consumed\":{\"zh-cn\":\"\\u5df2\\u6d88\\u8017\\u5de5\\u65f6\",\"zh-tw\":\"\\u5df2\\u6d88\\u8017\\u5de5\\u65f6\",\"en\":\"Cost(h)\"}}', '{\"group1\":\"name\",\"group2\":\"\",\"reportField\":[\"projects\",\"consumed\"],\"reportType\":[\"sum\",\"sum\"],\"sumAppend\":[\"projects\",\"consumed\"]}', 2, '{\"zh-cn\":\"\\u5217\\u51fa\\u6bcf\\u4e2a\\u4ea7\\u54c1\\u7684\\u9879\\u76ee\\u603b\\u6570\\uff0c\\u5df2\\u7ecf\\u6d88\\u8017\\u7684\\u5de5\\u65f6\\u3002\",\"zh-tw\":\"\\u5217\\u51fa\\u6bcf\\u500b\\u7522\\u54c1\\u7684\\u9805\\u76ee\\u7e3d\\u6578\\uff0c\\u5df2\\u7d93\\u6d88\\u8017\\u7684\\u5de5\\u6642\\u3002\",\"en\":\"Number of projects and consumed hours.\"}', 'admin', '2015-07-20 14:21:31'),
|
||||
('product-progress', '{\"zh-cn\":\"\\u4ea7\\u54c1\\u5b8c\\u6210\\u5ea6\\u7edf\\u8ba1\\u8868\",\"zh-tw\":\"\\u7522\\u54c1\\u5b8c\\u6210\\u5ea6\\u7d71\\u8a08\\u8868\",\"en\":\"Product Progress\"}', ',product', 'select t1.*,t2.name, (case when t1.status = \'closed\' or t1.stage = \'released\' then 1 else 0 end) as done, 1 as count from TABLE_STORY as t1 \r\nleft join TABLE_PRODUCT as t2 on t1.product=t2.id \r\nleft join TABLE_PROGRAM as t3 on t2.program=t3.id \r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\'\r\norder by t3.`order` asc, t2.line desc, t2.`order` asc', '', '{\"count\":{\"zh-cn\":\"\\u9700\\u6c42\\u6570\",\"zh-tw\":\"\\u9700\\u6c42\\u6570\",\"en\":\"Stories\"},\"done\":{\"zh-cn\":\"\\u5b8c\\u6210\\u6570\",\"zh-tw\":\"\\u5b8c\\u6210\\u6570\",\"en\":\"Done\"}}', '{\"group1\":\"name\",\"group2\":\"\",\"reportField\":[\"count\",\"done\"],\"reportType\":[\"sum\",\"sum\"],\"sumAppend\":[\"count\",\"done\"],\"percent\":{\"1\":\"1\"},\"contrast\":{\"1\":\"count\"},\"showAlone\":{\"1\":\"1\"}}', 2, '{\"zh-cn\":\"\\u6309\\u7167\\u4ea7\\u54c1\\u5217\\u51fa\\u9700\\u6c42\\u603b\\u6570\\uff0c\\u5b8c\\u6210\\u7684\\u603b\\u6570(\\u72b6\\u6001\\u662f\\u5173\\u95ed\\uff0c\\u6216\\u8005\\u7814\\u53d1\\u9636\\u6bb5\\u662f\\u53d1\\u5e03)\\uff0c\\u5b8c\\u6210\\u7684\\u767e\\u5206\\u6bd4\\u3002\",\"zh-tw\":\"\\u6309\\u7167\\u7522\\u54c1\\u5217\\u51fa\\u9700\\u6c42\\u7e3d\\u6578\\uff0c\\u5b8c\\u6210\\u7684\\u7e3d\\u6578(\\u72c0\\u614b\\u662f\\u95dc\\u9589\\uff0c\\u6216\\u8005\\u7814\\u767c\\u968e\\u6bb5\\u662f\\u767c\\u5e03)\\uff0c\\u5b8c\\u6210\\u7684\\u767e\\u5206\\u6bd4\\u3002\",\"en\":\"Number of total stories,done stories(state is closed, or stage is released), percent of completion.\"}', 'admin', '2015-07-21 15:07:48'),
|
||||
('story-status', '{\"zh-cn\":\"\\u4ea7\\u54c1\\u9700\\u6c42\\u72b6\\u6001\\u5206\\u5e03\\u8868\",\"zh-tw\":\"\\u7522\\u54c1\\u9700\\u6c42\\u72c0\\u614b\\u5206\\u5e03\\u8868\",\"en\":\"Story Status\"}', ',product', 'select t1.*,t2.name from TABLE_STORY as t1\r\n left join TABLE_PRODUCT as t2 on t1.product=t2.id \r\nleft join TABLE_PROGRAM as t3 on t2.program=t3.id \r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\'\r\norder by t3.`order` asc, t2.line desc, t2.`order` asc', '', '', '{\"group1\":\"name\",\"group2\":\"\",\"reportField\":[\"status\"],\"reportType\":[\"count\"],\"sumAppend\":[\"\"],\"reportTotal\":[\"1\"]}', 2, '{\"zh-cn\":\"\\u6309\\u7167\\u4ea7\\u54c1\\u5217\\u51fa\\u9700\\u6c42\\u603b\\u6570\\uff0c\\u72b6\\u6001\\u7684\\u5206\\u5e03\\u60c5\\u51b5\\u3002\",\"zh-tw\":\"\\u6309\\u7167\\u7522\\u54c1\\u5217\\u51fa\\u9700\\u6c42\\u7e3d\\u6578\\uff0c\\u72c0\\u614b\\u7684\\u5206\\u5e03\\u60c5\\u6cc1\\u3002\",\"en\":\"Total number and status distribution of stories.\"}', 'admin', '2015-07-21 15:35:38'),
|
||||
('story-stage', '{\"zh-cn\":\"\\u4ea7\\u54c1\\u9700\\u6c42\\u9636\\u6bb5\\u5206\\u5e03\\u8868\",\"zh-tw\":\"\\u7522\\u54c1\\u9700\\u6c42\\u968e\\u6bb5\\u5206\\u5e03\\u8868\",\"en\":\"Story Stage\"}', ',product', 'select t1.*,t2.name from TABLE_STORY as t1\r\n left join TABLE_PRODUCT as t2 on t1.product=t2.id \r\nleft join TABLE_PROGRAM as t3 on t2.program=t3.id \r\nwhere t1.deleted=\'0\' and t2.deleted=\'0\'\r\norder by t3.`order` asc, t2.line desc, t2.`order` asc', '', '', '{\"group1\":\"name\",\"group2\":\"\",\"reportField\":[\"stage\"],\"reportType\":[\"count\"],\"sumAppend\":[\"\"],\"reportTotal\":[\"1\"]}', 2, '{\"zh-cn\":\"\\u6309\\u7167\\u4ea7\\u54c1\\u5217\\u51fa\\u9700\\u6c42\\u603b\\u6570\\uff0c\\u7814\\u53d1\\u9636\\u6bb5\\u7684\\u5206\\u5e03\\u60c5\\u51b5\\u3002\",\"zh-tw\":\"\\u6309\\u7167\\u7522\\u54c1\\u5217\\u51fa\\u9700\\u6c42\\u7e3d\\u6578\\uff0c\\u7814\\u767c\\u968e\\u6bb5\\u7684\\u5206\\u5e03\\u60c5\\u6cc1\\u3002\",\"en\":\"Total number and stage distribution of stories \"}', 'admin', '2015-07-21 15:38:34'),
|
||||
@@ -9420,6 +9419,7 @@ CREATE TABLE IF NOT EXISTS `zt_review` (
|
||||
`object` mediumint(8) NOT NULL,
|
||||
`template` mediumint(8) NOT NULL,
|
||||
`doc` mediumint(8) DEFAULT NULL,
|
||||
`docVersion` smallint(6) DEFAULT NULL,
|
||||
`status` char(30) NOT NULL,
|
||||
`reviewedBy` varchar(255) NOT NULL,
|
||||
`auditedBy` varchar(255) NOT NULL,
|
||||
|
||||
@@ -105,7 +105,7 @@ class model extends baseModel
|
||||
$conditions = json_decode($action->conditions);
|
||||
if($action->extensionType == 'extend')
|
||||
{
|
||||
$title = $action->name;
|
||||
if($icon != 'copy' and $methodName != 'create') $title = $action->name;
|
||||
if($conditions) $enabled = $this->loadModel('flow')->checkConditions($conditions, $data);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1878,6 +1878,8 @@ class bugModel extends model
|
||||
if(!empty($this->config->isINT)) $firstLetter = '';
|
||||
$users[$account] = $firstLetter . ($user->realname ? $user->realname : $user->account);
|
||||
}
|
||||
|
||||
$users = $this->loadModel('user')->processAccountSort($users);
|
||||
return array('' => '') + $users;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
<div class='cell'>
|
||||
<div class='list-group'>
|
||||
<?php
|
||||
$reruiredModules = ksort($config->custom->requiredModules);
|
||||
foreach($requiredModules as $requiredModule)
|
||||
ksort($config->custom->requiredModules);
|
||||
foreach($config->custom->requiredModules as $requiredModule)
|
||||
{
|
||||
$requiredModuleName = zget($lang->custom->moduleName, $requiredModule, $lang->$requiredModule->common);
|
||||
echo html::a(inlink('required', "module=$requiredModule"), $requiredModuleName, '', "id='{$requiredModule}Tab'");
|
||||
|
||||
Regular → Executable
+22
@@ -792,6 +792,28 @@ class doc extends control
|
||||
return print($select);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get docs by lib.
|
||||
*
|
||||
* @param int $libID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetDocs($libID)
|
||||
{
|
||||
if(!$libID) return print(html::select('doc', '', '', "class='form-control chosen'"));
|
||||
|
||||
$docIdList = $this->doc->getPrivDocs($libID, 0);
|
||||
$docs = $this->dao->select('id, title')->from(TABLE_DOC)
|
||||
->where('lib')->eq($libID)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->andWhere('id')->in($docIdList)
|
||||
->orderBy('`order` asc')
|
||||
->fetchPairs();
|
||||
|
||||
return print(html::select('doc', $docs, '', "class='form-control chosen'"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax save draft.
|
||||
*
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
}
|
||||
elseif($doc->contentType == 'markdown')
|
||||
{
|
||||
echo "<textarea id='markdownContent' /></textarea>";
|
||||
echo "<textarea id='markdownContent'></textarea>";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -116,7 +116,7 @@ js::set('docID', $doc->id);
|
||||
}
|
||||
elseif($doc->contentType == 'markdown')
|
||||
{
|
||||
echo "<textarea id='markdownContent' /></textarea>";
|
||||
echo "<textarea id='markdownContent'></textarea>";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1496,7 +1496,7 @@ class execution extends control
|
||||
$this->view->name = $name;
|
||||
$this->view->code = $code;
|
||||
$this->view->team = $team;
|
||||
$this->view->teams = array(0 => '', $projectID => (isset($project->name) ? $project->name : '')) + $this->execution->getCanCopyObjects((int)$projectID);
|
||||
$this->view->teams = array(0 => '') + $this->execution->getCanCopyObjects((int)$projectID);
|
||||
$this->view->allProjects = array(0 => '') + $this->project->getPairsByModel('all', 0, 'noclosed');
|
||||
$this->view->executionID = $executionID;
|
||||
$this->view->productID = $productID;
|
||||
@@ -2730,7 +2730,7 @@ class execution extends control
|
||||
|
||||
$currentMembers = $this->execution->getTeamMembers($executionID);
|
||||
$members2Import = $this->execution->getMembers2Import($team2Import, array_keys($currentMembers));
|
||||
$teams2Import = $this->loadModel('personnel')->getCopiedObjects($executionID, 'sprint');
|
||||
$teams2Import = $this->loadModel('personnel')->getCopiedObjects($executionID, 'sprint', true);
|
||||
$teams2Import = array('' => '') + $teams2Import;
|
||||
|
||||
/* Append users for get users. */
|
||||
|
||||
@@ -695,6 +695,17 @@ function renderCount($count, count, column)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alert to link product.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function tips()
|
||||
{
|
||||
bootbox.alert(needLinkProducts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render header of a column.
|
||||
*/
|
||||
@@ -729,10 +740,11 @@ function renderHeaderCol($column, column, $header, kanbanData)
|
||||
var printMoreBtn = (columnPrivs.includes('setColumn') || columnPrivs.includes('setWIP'));
|
||||
|
||||
/* Render more menu. */
|
||||
if(((column.type == 'backlog' && hasStoryButton) || (column.type == 'wait' && hasTaskButton) || (column.type == 'unconfirmed' && hasBugButton)) && $actions.children('.text-primary').length == 0)
|
||||
if(column.type == 'backlog' || column.type == 'wait' || column.type == 'unconfirmed' && $actions.children('.text-primary').length == 0)
|
||||
{
|
||||
var tips = productID ? '' : 'onclick="tips()"';
|
||||
$actions.append([
|
||||
'<a data-contextmenu="columnCreate" data-type="' + column.type + '" data-kanban="' + kanban.id + '" data-parent="' + (column.parentType || '') + '" class="text-primary">',
|
||||
'<a data-contextmenu="columnCreate" data-type="' + column.type + '" data-kanban="' + kanban.id + '" data-parent="' + (column.parentType || '') + '" class="text-primary"' + ((column.type !== 'wait') ? tips : '') + '>',
|
||||
'<i class="icon icon-expand-alt"></i>',
|
||||
'</a>'
|
||||
].join(''));
|
||||
@@ -795,14 +807,16 @@ function updateRegion(regionID, regionData = [])
|
||||
if(!regionData) regionData = regions[regionID];
|
||||
|
||||
var data = groupBy == 'default' ? regionData.groups : regionData;
|
||||
if(data == null)
|
||||
if(data == null || data.length == 0)
|
||||
{
|
||||
$("div[data-id^=" + regionID + "].region").hide();
|
||||
if(groupBy == 'default') $("div[data-id^=" + regionID + "].region").hide();
|
||||
if(groupBy != 'default') $("div[data-id^=" + regionID + "].kanban").hide();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$("div[data-id^=" + regionID + "].region").show();
|
||||
if(groupBy == 'default') $("div[data-id^=" + regionID + "].region").show();
|
||||
if(groupBy != 'default') $("div[data-id^=" + regionID + "].kanban").show();
|
||||
}
|
||||
$region.empty();
|
||||
$region.data('zui.kanban').render(data);
|
||||
|
||||
@@ -300,6 +300,17 @@ function renderColumnCount($count, count, col)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alert to link product.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function tips()
|
||||
{
|
||||
bootbox.alert(needLinkProducts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render header column
|
||||
* @param {JQuery} $col Header column element
|
||||
@@ -318,10 +329,11 @@ function renderHeaderCol($col, col, $header, kanban)
|
||||
if(priv.canCreateTask || priv.canBatchCreateTask) printTaskButton = true;
|
||||
if(priv.canCreateBug || priv.canBatchCreateBug) printBugButton = true;
|
||||
|
||||
if((col.type === 'backlog' && printStoryButton) || (col.type === 'wait' && printTaskButton) || (col.type == 'unconfirmed' && printBugButton))
|
||||
if(col.type === 'backlog' || col.type === 'wait' || col.type == 'unconfirmed')
|
||||
{
|
||||
var tips = productID ? '' : 'onclick="tips()"';
|
||||
$actions.append([
|
||||
'<a data-contextmenu="columnCreate" data-type="' + col.type + '" data-kanban="' + kanban.id + '" data-parent="' + (col.parentType || '') + '" class="text-primary">',
|
||||
'<a data-contextmenu="columnCreate" data-type="' + col.type + '" data-kanban="' + kanban.id + '" data-parent="' + (col.parentType || '') + '" class="text-primary"' + ((col.laneType !== 'task') ? tips : '') + '>',
|
||||
'<i class="icon icon-expand-alt"></i>',
|
||||
'</a>'
|
||||
].join(''));
|
||||
|
||||
@@ -271,6 +271,7 @@ $lang->execution->treeOnlyStory = 'Show Story Only';
|
||||
$lang->execution->storyKanban = 'Story Kanban';
|
||||
$lang->execution->storySort = 'Rank Story';
|
||||
$lang->execution->importPlanStory = $lang->executionCommon . ' is created!\nDo you want to import stories that have been linked to the plan?';
|
||||
$lang->execution->needLinkProducts = 'The execution has not been linked with any product, and the related functions cannot be used. Please link the product first and try again.';
|
||||
$lang->execution->iteration = 'Iterations';
|
||||
$lang->execution->iterationInfo = '%s Iterations';
|
||||
$lang->execution->viewAll = 'View All';
|
||||
@@ -396,6 +397,7 @@ $lang->execution->projectNotEmpty = 'Project cannot be empty.';
|
||||
$lang->execution->confirmStoryToTask = $lang->SRCommon . '%s are converted to tasks in the current. Do you want to convert them anyways?';
|
||||
$lang->execution->ge = "『%s』should be >= actual begin『%s』.";
|
||||
$lang->execution->storyDragError = "The {$lang->SRCommon} is still a draft or has been changed, please drag it after the review";
|
||||
$lang->execution->countTip = ' (%s member)';
|
||||
$lang->execution->pleaseInput = "Enter";
|
||||
|
||||
/* Statistics. */
|
||||
|
||||
@@ -51,7 +51,7 @@ $lang->execution->canceledBy = '由谁取消';
|
||||
$lang->execution->canceledDate = '取消日期';
|
||||
$lang->execution->begin = '计划开始';
|
||||
$lang->execution->end = '计划完成';
|
||||
$lang->execution->dateRange = '起始日期';
|
||||
$lang->execution->dateRange = '计划起止日期';
|
||||
$lang->execution->realBeganAB = '实际开始';
|
||||
$lang->execution->realEndAB = '实际完成';
|
||||
$lang->execution->realBegan = '实际开始日期';
|
||||
@@ -271,6 +271,7 @@ $lang->execution->treeOnlyStory = "树状图只看{$lang->SRCommon}";
|
||||
$lang->execution->storyKanban = "{$lang->SRCommon}看板";
|
||||
$lang->execution->storySort = "{$lang->SRCommon}排序";
|
||||
$lang->execution->importPlanStory = '创建' . $lang->executionCommon . '成功!\n是否导入计划关联的相关' . $lang->SRCommon . '?';
|
||||
$lang->execution->needLinkProducts = '该执行还未关联任何产品,相关功能无法使用,请先关联产品后再试。';
|
||||
$lang->execution->iteration = '版本迭代';
|
||||
$lang->execution->iterationInfo = '迭代%s次';
|
||||
$lang->execution->viewAll = '查看所有';
|
||||
@@ -396,6 +397,7 @@ $lang->execution->projectNotEmpty = '所属项目不能为空。';
|
||||
$lang->execution->confirmStoryToTask = '%s' . $lang->SRCommon . '已经在当前' . $lang->execution->common . '中转了任务,请确认是否重复转任务。';
|
||||
$lang->execution->ge = "『%s』应当不小于实际开始时间『%s』。";
|
||||
$lang->execution->storyDragError = "该{$lang->SRCommon}还是草稿或已变更状态,请评审通过后再拖动";
|
||||
$lang->execution->countTip = '(%s人)';
|
||||
$lang->execution->pleaseInput = "请输入";
|
||||
|
||||
/* 统计。*/
|
||||
|
||||
@@ -2753,14 +2753,31 @@ class executionModel extends model
|
||||
|
||||
$objectPairs = $this->dao->select('id,name')->from(TABLE_PROJECT)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('project', true)->eq($projectID)
|
||||
->andWhere('type')->ne('project')
|
||||
->andWhere('(project')->eq($projectID)
|
||||
->orWhere('id')->eq($projectID)
|
||||
->markRight(1)
|
||||
->orWhere('id')->eq($projectID)
|
||||
->orderBy('type_asc,openedDate_desc')
|
||||
->limit('9')
|
||||
->fetchPairs();
|
||||
|
||||
$countPairs = $this->dao->select('root, COUNT(*) as count')->from(TABLE_TEAM)
|
||||
->where('( type')->eq('project')
|
||||
->andWhere('root')->eq($projectID)
|
||||
->markRight(1)
|
||||
->orWhere('( type')->eq('execution')
|
||||
->andWhere('root')->in(array_keys($objectPairs))
|
||||
->markRight(1)
|
||||
->groupBy('root')
|
||||
->fetchPairs('root');
|
||||
|
||||
foreach($objectPairs as $objectID => $objectName)
|
||||
{
|
||||
$memberCount = zget($countPairs, $objectID, 0);
|
||||
$countTip = $memberCount > 1 ? str_replace('member', 'members', $this->lang->execution->countTip) : $this->lang->execution->countTip;
|
||||
$objectPairs[$objectID] = $objectName . sprintf($countTip, $memberCount);
|
||||
}
|
||||
|
||||
return $objectPairs;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ js::set('vision', $this->config->vision);
|
||||
js::set('productCount', count($productNames));
|
||||
js::set('executionID', $execution->id);
|
||||
js::set('reviewStoryParis', $reviewStoryParis);
|
||||
js::set('needLinkProducts', $lang->execution->needLinkProducts);
|
||||
js::set('rdSearchValue', '');
|
||||
|
||||
$canSortRegion = commonModel::hasPriv('kanban', 'sortRegion') && count($regions) > 1;
|
||||
@@ -110,9 +111,6 @@ js::set('priv',
|
||||
'canUnlinkStory' => common::hasPriv('execution', 'unlinkStory'),
|
||||
)
|
||||
);
|
||||
js::set('hasStoryButton', $hasStoryButton);
|
||||
js::set('hasBugButton', $hasBugButton);
|
||||
js::set('hasTaskButton', $hasTaskButton);
|
||||
?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
|
||||
@@ -213,4 +213,5 @@ js::set('priv',
|
||||
<?php js::set('fluidBoard', $execution->fluidBoard);?>
|
||||
<?php js::set('displayCards', $execution->displayCards);?>
|
||||
<?php js::set('reviewStoryParis', $reviewStoryParis);?>
|
||||
<?php js::set('needLinkProducts', $lang->execution->needLinkProducts);?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#spaceList .spaceActions > a{margin-left: 10px;}
|
||||
.space .menu {margin-left: 5px; margin-right:5px;}
|
||||
.space .table-empty-tip {padding: 40px 10px;}
|
||||
.space .spaceTitle.pull-left {overflow: hidden; white-space: nowrap; max-width: calc(100% - 150px)}
|
||||
.space .spaceTitle.pull-left {overflow: hidden; white-space: nowrap; max-width: calc(100% - 255px)}
|
||||
.spaceName {font-size: 16px; font-weight: bold;}
|
||||
.spaceTitle .icon-cube {font-size: 16px;}
|
||||
.spaceDesc {font-size: 13px; color: #838A9D; margin: -5px 0 5px 18px;}
|
||||
#more .setting {margin-left: -25px; min-width: 80px}
|
||||
|
||||
@@ -16,7 +18,7 @@
|
||||
.kanbans .panel {margin: 0 0; border: 1px solid #DCDCDC; border-radius: 4px; box-shadow: none; cursor: pointer; height: 160px; margin-bottom: 5px;}
|
||||
.kanbans .panel:hover {border-color: #006AF1; box-shadow: 0 0 10px 0 rgba(0,0,100,.25);}
|
||||
.kanbans .panel-heading {padding: 4px 2px 10px 16px;}
|
||||
.kanbans .kanban-name {overflow: hidden; white-space:nowrap; width: 88%; float: left; padding-top: 8px;}
|
||||
.kanbans .kanban-name {overflow: hidden; white-space:nowrap; width: 78%; float: left; padding-top: 8px;}
|
||||
.kanbans .panel .label-closed {background: #AAA !important; color: #FFF; margin-top:-1px !important;}
|
||||
.kanbans .kanban-actions {float: right; visibility: hidden;}
|
||||
.kanbans .kanban-actions .dropdown-menu.pull-right {top:31px; right: -84px; left: auto;}
|
||||
@@ -36,6 +38,8 @@
|
||||
.kanbans .kanban-members > span:after {right: -4px;}
|
||||
.kanbans .kanban-members-total {display: inline-block; margin-left: 6px; position: relative; top: 3px}
|
||||
.kanbans .kanbanAcl {position: absolute; right: 0px; bottom: 2px; color: #838a9d;}
|
||||
.kanbans .kanban-label {margin: 6px 6px 0px 0px; float: left; color: #ff8a53; border: 1px solid #ff8a53;}
|
||||
@media screen and (max-width: 1366px){.kanbans .kanban-name {width: 68%;}}
|
||||
|
||||
a.disabled {pointer-events: none;}
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
.dropdown-menu > li {padding: 0 10px;}
|
||||
.dropdown-menu > li > a > .icon {position: relative; left: -5px;}
|
||||
|
||||
#kanbanContainer {padding-bottom: 0; margin-bottom: 0;}
|
||||
#kanbanContainer {padding-bottom: 0; margin-bottom: 0; border: unset;}
|
||||
#kanbanContainer.fullscreen {overflow: auto;}
|
||||
|
||||
.region {border: 1px solid #dcdcdc; background-color: #fff;}
|
||||
.region {border: 0px solid #dcdcdc; background-color: #fff;}
|
||||
.region + .region {margin-top: 20px;}
|
||||
.region .region-header {padding: 10px;}
|
||||
.region .region-header strong {font-size: 14px; color: #999EAB}
|
||||
@@ -136,3 +136,7 @@
|
||||
@-moz-document url-prefix(){ .region .kanban-lane-items{scrollbar-width:thin; padding:5px 0px 5px 5px !important;} .region .kanban-card .info .user{right: -6px !important;}}
|
||||
#archivedCards .table-empty-tip {border-style: hidden;}
|
||||
#archivedColumns .table-empty-tip {border-style: hidden;}
|
||||
|
||||
#main > .container {padding: 0px 0px 0px 10px; margin: -10px 0px 0px 0px;}
|
||||
@media screen and (max-width: 1366px){#main > .container {padding: 0px 10px 0px 10px; margin: -10px 0px 0px 0px;}}
|
||||
.panel-body {padding: 0px;}
|
||||
|
||||
@@ -1116,6 +1116,7 @@ function createCardMenu(options)
|
||||
|
||||
var items = [];
|
||||
if(privs.includes('editCard') && card.fromType == '') items.push({label: kanbanLang.editCard, icon: 'edit', url: createLink('kanban', 'editCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
|
||||
if(privs.includes('deleteCard')) items.push({label: card.fromType == '' ? kanbanLang.deleteCard : kanbanLang.removeCard, icon: card.fromType == '' ? 'trash' : 'unlink', url: createLink('kanban', 'deleteCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
|
||||
if(privs.includes('performable') && kanban.performable == 1)
|
||||
{
|
||||
if(card.status == 'done')
|
||||
@@ -1127,6 +1128,25 @@ function createCardMenu(options)
|
||||
items.push({label: kanbanLang.finishCard, icon: 'checked', onClick: function(){finishCard(card.id, card.kanban, card.region);}});
|
||||
}
|
||||
}
|
||||
if(privs.includes('archiveCard') && kanban.archived == '1') items.push({label: kanbanLang.archiveCard, icon: 'card-archive', url: createLink('kanban', 'archiveCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
|
||||
|
||||
var editCard = (privs.includes('editCard') && card.fromType == '') ? true : false;
|
||||
var deleteCard = privs.includes('deleteCard');
|
||||
var archiveCard = (privs.includes('archiveCard') && kanban.archived == '1') ? true : false;
|
||||
|
||||
var performable = (privs.includes('performable') && kanban.performable == 1) ? true : false;
|
||||
|
||||
var moveCard = privs.includes('moveCard');
|
||||
var setCardColor = privs.includes('setCardColor');
|
||||
|
||||
var basicActions = (editCard || deleteCard || archiveCard) ? true : false;
|
||||
var otherActions = (moveCard || setCardColor) ? true : false;
|
||||
|
||||
if((performable || basicActions) && otherActions)
|
||||
{
|
||||
items.push({type: 'divider'});
|
||||
}
|
||||
|
||||
if(privs.includes('moveCard'))
|
||||
{
|
||||
var moveCardItems = [];
|
||||
@@ -1150,7 +1170,7 @@ function createCardMenu(options)
|
||||
moveCardItems = moveCardItems.reverse();
|
||||
items.push({label: kanbanLang.moveCard, icon: 'move', items: moveCardItems});
|
||||
}
|
||||
if(privs.includes('archiveCard') && kanban.archived == '1') items.push({label: kanbanLang.archiveCard, icon: 'card-archive', url: createLink('kanban', 'archiveCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
|
||||
|
||||
if(privs.includes('setCardColor'))
|
||||
{
|
||||
var cardColoritems = [];
|
||||
@@ -1164,7 +1184,6 @@ function createCardMenu(options)
|
||||
};
|
||||
items.push({label: kanbanLang.cardColor, icon: 'color', items: cardColoritems});
|
||||
}
|
||||
if(privs.includes('deleteCard')) items.push({label: card.fromType == '' ? kanbanLang.deleteCard : kanbanLang.removeCard, icon: card.fromType == '' ? 'trash' : 'unlink', url: createLink('kanban', 'deleteCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
|
||||
|
||||
var bounds = options.$trigger[0].getBoundingClientRect();
|
||||
items.$options = {x: bounds.right, y: bounds.top};
|
||||
@@ -1180,6 +1199,15 @@ function createColumnMenu(options)
|
||||
var items = [];
|
||||
if(privs.includes('setColumn')) items.push({label: kanbanLang.editColumn, icon: 'edit', url: createLink('kanban', 'setColumn', 'columnID=' + column.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
|
||||
if(privs.includes('setWIP')) items.push({label: kanbanLang.setWIP, icon: 'alert', url: createLink('kanban', 'setWIP', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width' : '500px'}});
|
||||
|
||||
var basicActions = (privs.includes('setColumn') || privs.includes('setWIP')) ? true : false;
|
||||
var columnActions = (privs.includes('splitColumn') || privs.includes('createColumn') || privs.includes('copyColumn')) ? true : false;
|
||||
|
||||
if(basicActions && columnActions)
|
||||
{
|
||||
items.push({type: 'divider'});
|
||||
}
|
||||
|
||||
if(privs.includes('splitColumn')) items.push({label: kanbanLang.splitColumn, icon: 'col-split', url: createLink('kanban', 'splitColumn', 'columnID=' + column.id, '', true), className: 'iframe', attrs: {'data-toggle': 'modal'}});
|
||||
if(privs.includes('createColumn'))
|
||||
{
|
||||
@@ -1187,6 +1215,13 @@ function createColumnMenu(options)
|
||||
items.push({label: kanbanLang.createColumnOnRight, icon: 'col-add-right', url: createLink('kanban', 'createColumn', 'columnID=' + column.id + '&position=right'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
|
||||
}
|
||||
if(privs.includes('copyColumn')) items.push({label: kanbanLang.copyColumn, icon: 'copy', url: createLink('kanban', 'copyColumn', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal'}});
|
||||
|
||||
var otherActions = ((privs.includes('archiveColumn') && kanban.archived == '1') || privs.includes('deleteColumn')) ? true : false;
|
||||
if(columnActions && otherActions)
|
||||
{
|
||||
items.push({type: 'divider'});
|
||||
}
|
||||
|
||||
if(privs.includes('archiveColumn') && kanban.archived == '1') items.push({label: kanbanLang.archiveColumn, icon: 'card-archive', url: createLink('kanban', 'archiveColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}});
|
||||
if(privs.includes('deleteColumn')) items.push({label: kanbanLang.deleteColumn, icon: 'trash', url: createLink('kanban', 'deleteColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}});
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
/* Actions. */
|
||||
$lang->kanban->noCard = 'No card';
|
||||
$lang->kanban->create = 'Create Kanban';
|
||||
$lang->kanban->createSpace = 'Create Space';
|
||||
$lang->kanban->editSpace = 'Edit Space';
|
||||
@@ -80,6 +81,7 @@ $lang->kanban->importBuild = 'Build';
|
||||
$lang->kanban->allKanban = 'All Kanban';
|
||||
$lang->kanban->allProjects = 'All ' . ($this->config->systemMode == 'classic' ? $lang->executionCommon : 'Projects');
|
||||
$lang->kanban->allProducts = 'All Products';
|
||||
$lang->kanban->mine = 'Mine';
|
||||
|
||||
/* Fields. */
|
||||
$lang->kanban->space = 'Space';
|
||||
@@ -99,7 +101,8 @@ $lang->kanban->closed = 'Closed';
|
||||
$lang->kanban->closedBy = 'Closed By';
|
||||
$lang->kanban->closedDate = 'Closed Date';
|
||||
$lang->kanban->empty = 'No Kanban';
|
||||
$lang->kanban->teamSumCount = '%s people in total';
|
||||
$lang->kanban->teamSumCount = '%s Pers';
|
||||
$lang->kanban->cardsCount = '%s Card';
|
||||
$lang->kanban->cardCount = 'Card Count';
|
||||
$lang->kanban->activatedBy = 'Activated By';
|
||||
$lang->kanban->activatedDate = 'Activated Date';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
/* Actions. */
|
||||
$lang->kanban->noCard = '暂无卡片';
|
||||
$lang->kanban->create = '创建看板';
|
||||
$lang->kanban->createSpace = '创建空间';
|
||||
$lang->kanban->editSpace = '设置空间';
|
||||
@@ -80,6 +81,7 @@ $lang->kanban->importBuild = '版本';
|
||||
$lang->kanban->allKanban = '所有看板';
|
||||
$lang->kanban->allProjects = '所有' . ($this->config->systemMode == 'classic' ? $lang->executionCommon : '项目');
|
||||
$lang->kanban->allProducts = '所有产品';
|
||||
$lang->kanban->mine = '我负责';
|
||||
|
||||
/* Fields. */
|
||||
$lang->kanban->space = '所属空间';
|
||||
@@ -100,6 +102,7 @@ $lang->kanban->closedBy = '由谁关闭';
|
||||
$lang->kanban->closedDate = '关闭日期';
|
||||
$lang->kanban->empty = '暂时没有看板';
|
||||
$lang->kanban->teamSumCount = '共%s人';
|
||||
$lang->kanban->cardsCount = '共%s张卡片';
|
||||
$lang->kanban->cardCount = '卡片数量';
|
||||
$lang->kanban->activatedBy = '由谁激活';
|
||||
$lang->kanban->activatedDate = '激活日期';
|
||||
|
||||
+43
-14
@@ -1414,14 +1414,12 @@ class kanbanModel extends model
|
||||
|
||||
if($lane->type == 'task')
|
||||
{
|
||||
if($searchValue != '' and strpos($object->name, $searchValue) === false) continue;
|
||||
$cardData['name'] = $object->name;
|
||||
$cardData['status'] = $object->status;
|
||||
$cardData['left'] = $object->left;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($searchValue != '' and strpos($object->title, $searchValue) === false) continue;
|
||||
$cardData['title'] = $object->title;
|
||||
}
|
||||
|
||||
@@ -3070,28 +3068,41 @@ class kanbanModel extends model
|
||||
{
|
||||
$actions .= "<a data-toggle='dropdown' $btnColor class='btn btn-link dropdown-toggle setting' type='button'>" . '<i class="icon icon-cog-outline"></i> ' . $this->lang->kanban->setting . '</a>';
|
||||
$actions .= "<ul id='kanbanActionMenu' class='dropdown-menu text-left'>";
|
||||
if(common::hasPriv('kanban', 'createRegion') and $CRKanban) $actions .= '<li>' . html::a(helper::createLink('kanban', 'createRegion', "kanbanID=$kanban->id", '', true), '<i class="icon icon-plus"></i>' . $this->lang->kanban->createRegion, '', "class='iframe btn btn-link'") . '</li>';
|
||||
$importWidth = $this->app->getClientLang() == 'en' ? '700' : '550';
|
||||
if(common::hasPriv('kanban', 'import') and $CRKanban) $actions .= '<li>' . html::a(helper::createLink('kanban', 'import', "kanbanID=$kanban->id", '', true), '<i class="icon icon-import"></i>' . $this->lang->kanban->import, '', "class='iframe btn btn-link' data-width=$importWidth") . '</li>';
|
||||
if(common::hasPriv('kanban', 'enableArchived') and $CRKanban) $actions .= '<li>' . html::a(helper::createLink('kanban', 'enableArchived', "kanbanID=$kanban->id", '', true), '<i class="icon icon-card-archive"></i>' . $this->lang->kanban->archived, '', "class='iframe btn btn-link' data-width=400") . '</li>';
|
||||
|
||||
$columnActions = '';
|
||||
if(common::hasPriv('kanban', 'setColumnWidth') and $CRKanban) $columnActions .= '<li>' . html::a(helper::createLink('kanban', 'setColumnWidth', "kanbanID=$kanban->id", '', true), '<i class="icon icon-size-width"></i>' . $this->lang->kanban->columnWidth, '', "class='iframe btn btn-link' data-width=400") . '</li>';
|
||||
if($printSetHeightBtn and $CRKanban)
|
||||
{
|
||||
$width = $this->app->getClientLang() == 'en' ? '750' : '650';
|
||||
$actions .= '<li>' . html::a(helper::createLink('kanban', 'setLaneHeight', "kanbanID=$kanban->id", '', true), '<i class="icon icon-size-height"></i>' . $this->lang->kanban->laneHeight, '', "class='iframe btn btn-link' data-width='$width'") . '</li>';
|
||||
|
||||
$width = $this->app->getClientLang() == 'en' ? '750' : '650';
|
||||
$columnActions .= '<li>' . html::a(helper::createLink('kanban', 'setLaneHeight', "kanbanID=$kanban->id", '', true), '<i class="icon icon-size-height"></i>' . $this->lang->kanban->laneHeight, '', "class='iframe btn btn-link' data-width='$width'") . '</li>';
|
||||
}
|
||||
if(common::hasPriv('kanban', 'setColumnWidth') and $CRKanban) $actions .= '<li>' . html::a(helper::createLink('kanban', 'setColumnWidth', "kanbanID=$kanban->id", '', true), '<i class="icon icon-size-width"></i>' . $this->lang->kanban->columnWidth, '', "class='iframe btn btn-link' data-width=400") . '</li>';
|
||||
if(common::hasPriv('kanban', 'performable') and $CRKanban) $actions .= '<li>' . html::a(helper::createLink('kanban', 'performable', "kanbanID=$kanban->id", '', true), '<i class="icon icon-checked"></i>' . $this->lang->kanban->manageProgress, '', "class='iframe btn btn-link' data-width=40%") . '</li>';
|
||||
$actions .= $columnActions;
|
||||
|
||||
$commonActions = '';
|
||||
if(common::hasPriv('kanban', 'createRegion') and $CRKanban) $commonActions .= '<li>' . html::a(helper::createLink('kanban', 'createRegion', "kanbanID=$kanban->id", '', true), '<i class="icon icon-plus"></i>' . $this->lang->kanban->createRegion, '', "class='iframe btn btn-link'") . '</li>';
|
||||
$importWidth = $this->app->getClientLang() == 'en' ? '700' : '550';
|
||||
if(common::hasPriv('kanban', 'import') and $CRKanban) $commonActions .= '<li>' . html::a(helper::createLink('kanban', 'import', "kanbanID=$kanban->id", '', true), '<i class="icon icon-import"></i>' . $this->lang->kanban->import, '', "class='iframe btn btn-link' data-width=$importWidth") . '</li>';
|
||||
if(common::hasPriv('kanban', 'enableArchived') and $CRKanban) $commonActions .= '<li>' . html::a(helper::createLink('kanban', 'enableArchived', "kanbanID=$kanban->id", '', true), '<i class="icon icon-card-archive"></i>' . $this->lang->kanban->archived, '', "class='iframe btn btn-link' data-width=400") . '</li>';
|
||||
if(common::hasPriv('kanban', 'performable') and $CRKanban) $commonActions .= '<li>' . html::a(helper::createLink('kanban', 'performable', "kanbanID=$kanban->id", '', true), '<i class="icon icon-checked"></i>' . $this->lang->kanban->manageProgress, '', "class='iframe btn btn-link' data-width=40%") . '</li>';
|
||||
|
||||
if($columnActions and $commonActions)
|
||||
{
|
||||
$actions .= "<li class='divider'></li>";
|
||||
}
|
||||
$actions .= $commonActions;
|
||||
|
||||
$kanbanActions = '';
|
||||
if(common::hasPriv('kanban', 'edit')) $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'edit', "kanbanID=$kanban->id", '', true), '<i class="icon icon-edit"></i>' . $this->lang->kanban->edit, '', "class='iframe btn btn-link' data-width='75%'") . '</li>';
|
||||
if(common::hasPriv('kanban', 'close') and $kanban->status == 'active') $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'close', "kanbanID=$kanban->id", '', true), '<i class="icon icon-off"></i>' . $this->lang->kanban->close, '', "class='iframe btn btn-link'") . '</li>';
|
||||
if(common::hasPriv('kanban', 'activate') and $kanban->status == 'closed') $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'activate', "kanbanID=$kanban->id", '', true), '<i class="icon icon-magic"></i>' . $this->lang->kanban->activate, '', "class='iframe btn btn-link'") . '</li>';
|
||||
if(common::hasPriv('kanban', 'delete')) $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'delete', "kanbanID=$kanban->id"), '<i class="icon icon-trash"></i>' . $this->lang->kanban->delete, 'hiddenwin', "class='btn btn-link'") . '</li>';
|
||||
if($kanbanActions)
|
||||
|
||||
if($commonActions and $kanbanActions)
|
||||
{
|
||||
$actions .= $printRegionBtn ? "<li class='divider'></li>" . $kanbanActions : $kanbanActions;
|
||||
$actions .= "<li class='divider'></li>";
|
||||
}
|
||||
$actions .= $kanbanActions;
|
||||
|
||||
$actions .= "</ul>";
|
||||
}
|
||||
|
||||
@@ -3429,11 +3440,29 @@ class kanbanModel extends model
|
||||
*/
|
||||
public function getGroupBySpaceList($spaceIdList, $kanbanIdList = '')
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_KANBAN)
|
||||
$spaceList = $this->dao->select('*')->from(TABLE_KANBAN)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('space')->in($spaceIdList)
|
||||
->beginIF($kanbanIdList)->andWhere('id')->in($kanbanIdList)->fi()
|
||||
->fetchGroup('space', 'id');
|
||||
|
||||
$kanbanIDList = array();
|
||||
foreach($spaceList as $kanbanList) $kanbanIDList = array_merge_recursive($kanbanIDList, array_keys($kanbanList));
|
||||
$cardsCount = $this->dao->select('kanban, COUNT(*) as count')->from(TABLE_KANBANCARD)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('kanban')->in($kanbanIDList)
|
||||
->groupBy('kanban')
|
||||
->fetchPairs('kanban');
|
||||
|
||||
foreach($spaceList as $kanbanList)
|
||||
{
|
||||
foreach($kanbanList as $kanban)
|
||||
{
|
||||
$kanban->cardsCount = zget($cardsCount, $kanban->id, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return $spaceList;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,12 +40,12 @@
|
||||
<div class='spaceTitle pull-left'>
|
||||
<div><i class='icon-cube'></i></div>
|
||||
<div>
|
||||
<h4 title="<?php echo $space->name;?>">
|
||||
<p class='spaceName' title="<?php echo $space->name;?>">
|
||||
<?php if($space->status == 'closed'):?>
|
||||
<span class="label label-closed"><?php echo $lang->kanban->closed;?></span>
|
||||
<?php endif;?>
|
||||
<?php echo $space->name;?>
|
||||
</h4>
|
||||
</p>
|
||||
</div>
|
||||
<p class="spaceDesc text-ellipsis text-primary" title='<?php echo empty($space->desc) ? $lang->kanban->emptyDesc : $space->desc;?>'><?php echo empty($space->desc) ? $lang->kanban->emptyDesc : $space->desc;?></p>
|
||||
</div>
|
||||
@@ -72,6 +72,9 @@
|
||||
<div class='col' data-id='<?php echo $kanbanID?>'>
|
||||
<div class='panel' data-url='<?php echo $this->createLink('kanban', 'view', "kanbanID=$kanbanID");?>'>
|
||||
<div class='panel-heading'>
|
||||
<?php if($kanban->space == 2 and $kanban->owner == $this->app->user->account):?>
|
||||
<span class="label label-outline label-info kanban-label"><?php echo $lang->kanban->mine;?></span>
|
||||
<?php endif;?>
|
||||
<div class='kanban-name'>
|
||||
<?php if($kanban->status == 'closed'):?>
|
||||
<span class="label label-closed"><?php echo $lang->kanban->closed;?></span>
|
||||
@@ -158,7 +161,10 @@
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class='kanban-members-total pull-left'><?php echo sprintf($lang->kanban->teamSumCount, $teamCount);?></div>
|
||||
<?php $teamCountLang = ($teamCount > 1) ? $lang->kanban->teamSumCount : str_replace("Pers", "Person", $lang->kanban->teamSumCount);?>
|
||||
<div class='kanban-members-total pull-left'><?php echo sprintf($teamCountLang, $teamCount);?></div>
|
||||
<?php $cardsCount = ($kanban->cardsCount > 1) ? str_replace("Card", "Cards", $lang->kanban->cardsCount) : $lang->kanban->cardsCount;?>
|
||||
<div class='kanban-members-total pull-right'><?php echo empty($kanban->cardsCount) ? $lang->kanban->noCard : sprintf($cardsCount, $kanban->cardsCount);?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+37
-30
@@ -75,18 +75,19 @@ class my extends control
|
||||
/**
|
||||
* My work view.
|
||||
*
|
||||
* @param string $mode
|
||||
* @param string $type
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @param string $mode
|
||||
* @param string $type
|
||||
* @param string|int $param
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function work($mode = 'task', $type = 'assignedTo', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
public function work($mode = 'task', $type = 'assignedTo', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
echo $this->fetch('my', $mode, "type=$type&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID");
|
||||
echo $this->fetch('my', $mode, "type=$type¶m=$param&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID");
|
||||
|
||||
$this->showWorkCount($recTotal, $recPerPage, $pageID);
|
||||
}
|
||||
@@ -210,20 +211,21 @@ EOF;
|
||||
/**
|
||||
* My contribute view.
|
||||
*
|
||||
* @param string $mode
|
||||
* @param string $type
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @param string $mode
|
||||
* @param string $type
|
||||
* @param string|int $param
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function contribute($mode = 'task', $type = 'openedBy', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
public function contribute($mode = 'task', $type = 'openedBy', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
if(($mode == 'issue' or $mode == 'risk') and $type == 'openedBy') $type = 'createdBy';
|
||||
|
||||
echo $this->fetch('my', $mode, "type=$type&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID");
|
||||
echo $this->fetch('my', $mode, "type=$type¶m=$param&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -596,15 +598,16 @@ EOF;
|
||||
/**
|
||||
* My test case.
|
||||
*
|
||||
* @param string $type assigntome|openedbyme
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @param string $type assigntome|openedbyme
|
||||
* @param string|int $param
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function testcase($type = 'assigntome', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
public function testcase($type = 'assigntome', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
$this->loadModel('testcase');
|
||||
$this->loadModel('testtask');
|
||||
@@ -620,20 +623,24 @@ EOF;
|
||||
|
||||
/* Append id for secend sort. */
|
||||
$sort = common::appendOrder($orderBy);
|
||||
$queryID = ($type == 'bysearch') ? (int)$param : 0;
|
||||
|
||||
$cases = array();
|
||||
if($type == 'assigntome')
|
||||
{
|
||||
$cases = $this->testcase->getByAssignedTo($this->app->user->account, $sort, $pager, 'skip');
|
||||
}
|
||||
elseif($type == 'openedbyme')
|
||||
{
|
||||
$cases = $this->testcase->getByOpenedBy($this->app->user->account, $sort, $pager, 'skip');
|
||||
}
|
||||
if($type == 'assigntome') $cases = $this->testcase->getByAssignedTo($this->app->user->account, $sort, $pager, 'skip');
|
||||
if($type == 'openedbyme') $cases = $this->testcase->getByOpenedBy($this->app->user->account, $sort, $pager, 'skip');
|
||||
if($type == 'bysearch' and $this->app->rawMethod == 'contribute') $cases = $this->my->getTestcasesBySearch($queryID, 'openedbyme', $orderBy, $pager);
|
||||
if($type == 'bysearch' and $this->app->rawMethod == 'work') $cases = $this->my->getTestcasesBySearch($queryID, 'assigntome', $orderBy, $pager);
|
||||
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', $type == 'assigntome' ? false : true);
|
||||
|
||||
$cases = $this->testcase->appendData($cases, $type == 'assigntome' ? 'run' : 'case');
|
||||
|
||||
/* Build the search form. */
|
||||
$currentMethod = $this->app->rawMethod;
|
||||
$actionURL = $this->createLink('my', $currentMethod, "mode=testcase&type=bysearch¶m=myQueryID&orderBy={$orderBy}&recTotal={$recTotal}&recPerPage={$recPerPage}&pageID={$pageID}");
|
||||
$this->config->testcase->search['onMenuBar'] = 'yes';
|
||||
$this->my->buildTestcaseSearchForm($queryID, $actionURL, $currentMethod);
|
||||
|
||||
/* Assign. */
|
||||
$this->view->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->myTestCase;
|
||||
$this->view->position[] = $this->lang->my->myTestCase;
|
||||
|
||||
@@ -43,6 +43,7 @@ $lang->my->testcase = 'My Case';
|
||||
$lang->my->storyConcept = 'Story Concept';
|
||||
$lang->my->pri = 'Priority';
|
||||
$lang->my->alert = 'You can click on your profile at the top right and select "Preference" to modify your information. ';
|
||||
$lang->my->assignedToMe = 'AssignedToMe';
|
||||
|
||||
$lang->my->indexAction = 'My Index';
|
||||
$lang->my->calendarAction = 'My Calendar';
|
||||
|
||||
@@ -43,6 +43,7 @@ $lang->my->testcase = '我的用例';
|
||||
$lang->my->storyConcept = $config->URAndSR ? '默认需求概念组合' : '默认需求概念';
|
||||
$lang->my->pri = '优先级';
|
||||
$lang->my->alert = '后续您可以点击右上方的头像,选择“个性化设置”修改信息。';
|
||||
$lang->my->assignedToMe = '指派给我';
|
||||
|
||||
$lang->my->indexAction = '地盘仪表盘';
|
||||
$lang->my->calendarAction = '我的日程';
|
||||
|
||||
@@ -374,4 +374,88 @@ class myModel extends model
|
||||
}
|
||||
return $objectList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build search form.
|
||||
*
|
||||
* @param int $queryID
|
||||
* @param string $actionURL
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function buildTestCaseSearchForm($queryID, $actionURL, $type)
|
||||
{
|
||||
$products = $this->dao->select('id,name')->from(TABLE_PRODUCT)
|
||||
->where('deleted')->eq(0)
|
||||
->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->products)->fi()
|
||||
->orderBy('order_asc')
|
||||
->fetchPairs();
|
||||
|
||||
$queryName = $type == 'contribute' ? 'contributeTestcase' : 'workTestcase';
|
||||
$this->app->loadConfig('testcase');
|
||||
$this->config->testcase->search['module'] = $queryName;
|
||||
$this->config->testcase->search['queryID'] = $queryID;
|
||||
$this->config->testcase->search['actionURL'] = $actionURL;
|
||||
$this->config->testcase->search['params']['product']['values'] = $products;
|
||||
$this->config->testcase->search['params']['lib']['values'] = $this->loadModel('caselib')->getLibraries();
|
||||
|
||||
unset($this->config->testcase->search['fields']['module']);
|
||||
|
||||
$this->loadModel('search')->setSearchParams($this->config->testcase->search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get testcases by search.
|
||||
*
|
||||
* @param int $queryID
|
||||
* @param string $type
|
||||
* @param string $orderBy
|
||||
* @param int $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTestcasesBySearch($queryID, $type, $orderBy, $pager)
|
||||
{
|
||||
$queryName = $type == 'openedbyme' ? 'contributeTestcaseQuery' : 'workTestcaseQuery';
|
||||
if($queryID)
|
||||
{
|
||||
$query = $this->loadModel('search')->getQuery($queryID);
|
||||
if($query)
|
||||
{
|
||||
$this->session->set($queryName, $query->sql);
|
||||
$this->session->set($queryName . 'Form', $query->form);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->session->set($queryName, ' 1 = 1');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->session->$queryName == false) $this->session->set($queryName, ' 1 = 1');
|
||||
}
|
||||
|
||||
$myTestcaseQuery = $this->session->$queryName;
|
||||
$myTestcaseQuery = preg_replace('/`(\w+)`/', 't1.`$1`', $myTestcaseQuery);
|
||||
|
||||
if($type == 'openedbyme')
|
||||
{
|
||||
$cases = $this->dao->select('*')->from(TABLE_CASE)->alias('t1')
|
||||
->where($myTestcaseQuery)
|
||||
->andWhere('t1.openedBy')->eq($this->app->user->account)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->orderBy($orderBy)->page($pager)->fetchAll('id');
|
||||
}
|
||||
else
|
||||
{
|
||||
$cases = $this->dao->select('t1.*')->from(TABLE_CASE)->alias('t1')
|
||||
->leftJoin(TABLE_TESTRUN)->alias('t2')->on('t1.id = t2.case')
|
||||
->where($myTestcaseQuery)
|
||||
->andWhere('t2.assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->orderBy($orderBy)->page($pager)->fetchAll('id');
|
||||
}
|
||||
return $cases;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,20 @@
|
||||
<div class="btn-toolbar pull-left">
|
||||
<?php
|
||||
$recTotalLabel = " <span class='label label-light label-badge'>{$pager->recTotal}</span>";
|
||||
if($app->rawMethod == 'contribute') echo html::a(inlink($app->rawMethod, "mode=$mode&type=openedbyme"), "<span class='text'>{$lang->testcase->openedByMe}</span>" . ($type == 'openedbyme' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'openedbyme' ? ' btn-active-text' : '') . "'");
|
||||
if($app->rawMethod == 'contribute')
|
||||
{
|
||||
echo html::a(inlink($app->rawMethod, "mode=$mode&type=openedbyme"), "<span class='text'>{$lang->testcase->openedByMe}</span>" . ($type == 'openedbyme' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'openedbyme' ? ' btn-active-text' : '') . "'");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a(inlink($app->rawMethod, "mode=$mode&type=assigntome"), "<span class='text'>{$lang->my->assignedToMe}</span>" . ($type == 'assigntome' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assigntome' ? ' btn-active-text' : '') . "'");
|
||||
}
|
||||
?>
|
||||
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i><?php $this->loadModel('search');echo $lang->search->common;?></a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="mainContent">
|
||||
<div class="cell<?php if($type == 'bysearch') echo ' show';?>" id="queryBox" data-module=<?php echo ($app->rawMethod == 'contribute' ? 'contributeTestcase' : 'workTestcase');?>></div>
|
||||
<?php if(empty($cases)):?>
|
||||
<div class="table-empty-tip">
|
||||
<p><span class="text-muted"><?php echo $lang->testcase->noCase;?></span></p>
|
||||
|
||||
@@ -38,3 +38,4 @@ $lang->personnel->copy = 'Copy Whitelist';
|
||||
|
||||
$lang->personnel->openedPGMTip = 'The program is public and can be accessed by users with Program privileges.';
|
||||
$lang->personnel->selectObjectTips = 'Select %s to copy its whitelist';
|
||||
$lang->personnel->countTip = ' (%s member)';
|
||||
|
||||
@@ -38,3 +38,4 @@ $lang->personnel->copy = 'Copy Whitelist';
|
||||
|
||||
$lang->personnel->openedPGMTip = 'The program is public and can be accessed by users with Program privileges.';
|
||||
$lang->personnel->selectObjectTips = 'Select %s to copy its whitelist';
|
||||
$lang->personnel->countTip = ' (%s member)';
|
||||
|
||||
@@ -38,3 +38,4 @@ $lang->personnel->copy = 'Copy Whitelist';
|
||||
|
||||
$lang->personnel->openedPGMTip = 'The program is public and can be accessed by users with Program privileges.';
|
||||
$lang->personnel->selectObjectTips = 'Select %s to copy its whitelist';
|
||||
$lang->personnel->countTip = ' (%s member)';
|
||||
|
||||
@@ -38,3 +38,4 @@ $lang->personnel->copy = 'Copy Whitelist';
|
||||
|
||||
$lang->personnel->openedPGMTip = 'The program is public and can be accessed by users with Program privileges.';
|
||||
$lang->personnel->selectObjectTips = 'Select %s to copy its whitelist';
|
||||
$lang->personnel->countTip = ' (%s member)';
|
||||
|
||||
@@ -38,3 +38,4 @@ $lang->personnel->copy = '复制白名单';
|
||||
|
||||
$lang->personnel->openedPGMTip = '该项目集是公开状态,有项目集视图权限的人员即可访问。';
|
||||
$lang->personnel->selectObjectTips = '请选择一个%s白名单来复制';
|
||||
$lang->personnel->countTip = '(%s人)';
|
||||
|
||||
@@ -38,3 +38,4 @@ $lang->personnel->copy = '複製白名單';
|
||||
|
||||
$lang->personnel->openedPGMTip = '該項目集是公開狀態,有項目集視圖權限的人員即可訪問。';
|
||||
$lang->personnel->selectObjectTips = '請選擇一個%s白名單來複制';
|
||||
$lang->personnel->countTip = '(%s人)';
|
||||
|
||||
@@ -466,10 +466,11 @@ class personnelModel extends model
|
||||
*
|
||||
* @param int $objectID
|
||||
* @param int $objectType
|
||||
* @param bool $addCount
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getCopiedObjects($objectID, $objectType)
|
||||
public function getCopiedObjects($objectID, $objectType, $addCount = false)
|
||||
{
|
||||
$objects = array();
|
||||
|
||||
@@ -512,6 +513,28 @@ class personnelModel extends model
|
||||
}
|
||||
|
||||
unset($objects[$objectID]);
|
||||
|
||||
if($addCount)
|
||||
{
|
||||
$objectType = $objectType == 'sprint' ? 'execution' : $objectType;
|
||||
$countPairs = $this->dao->select('root, COUNT(*) as count')->from(TABLE_TEAM)
|
||||
->where('type')->eq($objectType)
|
||||
->andWhere('root')->in(array_keys($objects))
|
||||
->beginIF($objectType == 'execution')
|
||||
->orWhere('( type')->eq('project')
|
||||
->andWhere('root')->eq($parentID)->markRight(1)
|
||||
->fi()
|
||||
->groupBy('root')
|
||||
->fetchPairs('root');
|
||||
|
||||
foreach($objects as $objectID => $objectName)
|
||||
{
|
||||
$memberCount = zget($countPairs, $objectID, 0);
|
||||
$countTip = $memberCount > 1 ? str_replace('member', 'members', $this->lang->personnel->countTip) : $this->lang->personnel->countTip;
|
||||
$objects[$objectID] = $objectName . sprintf($countTip, $memberCount);
|
||||
}
|
||||
}
|
||||
|
||||
return $objects;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ $config->product->search['fields']['estimate'] = $lang->story->estimate;
|
||||
$config->product->search['fields']['source'] = $lang->story->source;
|
||||
$config->product->search['fields']['sourceNote'] = $lang->story->sourceNote;
|
||||
$config->product->search['fields']['fromBug'] = $lang->story->fromBug;
|
||||
$config->product->search['fields']['category'] = $lang->story->category;
|
||||
|
||||
$config->product->search['fields']['openedBy'] = $lang->story->openedBy;
|
||||
$config->product->search['fields']['reviewedBy'] = $lang->story->reviewedBy;
|
||||
@@ -68,6 +69,7 @@ $config->product->search['params']['estimate'] = array('operator' => '=',
|
||||
$config->product->search['params']['source'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->story->sourceList);
|
||||
$config->product->search['params']['sourceNote'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
|
||||
$config->product->search['params']['fromBug'] = array('operator' => '=', 'control' => 'input', 'values' => '');
|
||||
$config->product->search['params']['category'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->story->categoryList);
|
||||
|
||||
$config->product->search['params']['openedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
|
||||
$config->product->search['params']['reviewedBy'] = array('operator' => 'include', 'control' => 'select', 'values' => 'users');
|
||||
|
||||
@@ -30,6 +30,6 @@ $config->productplan->search['fields']['end'] = $lang->productplan->end;
|
||||
$config->productplan->search['params']['id'] = array('operator' => '=', 'control' => 'input', 'values' => '');
|
||||
$config->productplan->search['params']['title'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
|
||||
$config->productplan->search['params']['branch'] = array('operator' => '=', 'control' => 'select', 'values' => '');
|
||||
$config->productplan->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->productplan->statusList);
|
||||
$config->productplan->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => array('' => '') + $lang->productplan->statusList);
|
||||
$config->productplan->search['params']['begin'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
|
||||
$config->productplan->search['params']['end'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
|
||||
|
||||
@@ -1455,7 +1455,7 @@ class project extends control
|
||||
$this->view->depts = array('' => '') + $this->dept->getOptionMenu();
|
||||
$this->view->currentMembers = $currentMembers;
|
||||
$this->view->members2Import = $members2Import;
|
||||
$this->view->teams2Import = array('' => '') + $this->loadModel('personnel')->getCopiedObjects($projectID, 'project');
|
||||
$this->view->teams2Import = array('' => '') + $this->loadModel('personnel')->getCopiedObjects($projectID, 'project', true);
|
||||
$this->view->copyProjectID = $copyProjectID;
|
||||
$this->display();
|
||||
}
|
||||
@@ -1993,4 +1993,20 @@ class project extends control
|
||||
}
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX: get executions of a project in html select.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param int $executionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetExecutions($projectID, $executionID = 0)
|
||||
{
|
||||
$executions = array('' => '') + $this->loadModel('execution')->getPairs($projectID, 'all');
|
||||
|
||||
if($this->app->getViewType() == 'json') return print(json_encode($executionList));
|
||||
return print(html::select('execution', $executions, $executionID, "class='form-control'"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ $lang->story->sourceNote = '来源备注';
|
||||
$lang->story->fromBug = '来源Bug';
|
||||
$lang->story->title = "{$lang->SRCommon}名称";
|
||||
$lang->story->type = "需求类型";
|
||||
$lang->story->category = "类型";
|
||||
$lang->story->category = "类别";
|
||||
$lang->story->color = '标题颜色';
|
||||
$lang->story->toBug = '转Bug';
|
||||
$lang->story->spec = "描述";
|
||||
|
||||
@@ -2986,7 +2986,7 @@ class storyModel extends model
|
||||
->beginIF($moduleIdList)->andWhere('t2.module')->in($moduleIdList)->fi()
|
||||
->beginIF($status == 'unclosed')->andWhere('t2.status')->ne('closed')->fi()
|
||||
->beginIF($status == 'review')->andWhere('t2.status')->in('draft,changed')->fi()
|
||||
->orderBy('t1.`order` desc')
|
||||
->orderBy('t1.`order` desc, t1.`story` desc')
|
||||
->fetchAll('id');
|
||||
return empty($stories) ? array() : $this->formatStories($stories, $type);
|
||||
}
|
||||
|
||||
@@ -5,3 +5,6 @@
|
||||
.pull-left{max-width: 80%;}
|
||||
.MRThWidth {width: 90px !important;}
|
||||
.btn-edit-comment {z-index: 100;}
|
||||
|
||||
#assignedTo a {border-color: transparent;}
|
||||
#assignedTo a:hover {border-color: rgba(0,0,0,.2);}
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
<th class='w-40px'> <?php echo $lang->task->lblPri;?></th>
|
||||
<th> <?php echo $lang->task->name;?></th>
|
||||
<th class='w-100px'><?php echo $lang->task->deadline;?></th>
|
||||
<th class='w-80px'> <?php echo $lang->task->assignedTo;?></th>
|
||||
<th class='w-120px'> <?php echo $lang->task->assignedTo;?></th>
|
||||
<th class='w-80px'> <?php echo $lang->task->status;?></th>
|
||||
<th class='w-60px visible-lg'><?php echo $lang->task->consumedAB . $lang->task->lblHour;?></th>
|
||||
<th class='w-60px visible-lg'><?php echo $lang->task->leftAB . $lang->task->lblHour;?></th>
|
||||
@@ -132,13 +132,12 @@
|
||||
</td>
|
||||
<td class='text-left' title='<?php echo $child->name;?>'><a class="iframe" data-width="90%" href="<?php echo $this->createLink('task', 'view', "taskID=$child->id", '', true); ?>"><?php echo $child->name;?></a></td>
|
||||
<td><?php echo $child->deadline;?></td>
|
||||
<td><?php echo zget($users, $child->assignedTo);?></td>
|
||||
<td id='assignedTo'><?php $this->task->printAssignedHtml($child, $users);?></td>
|
||||
<td><?php echo $this->processStatus('task', $child);?></td>
|
||||
<td class='visible-lg'><?php echo $child->consumed;?></td>
|
||||
<td class='visible-lg'><?php echo $child->left;?></td>
|
||||
<td class='c-actions'>
|
||||
<?php
|
||||
common::printIcon('task', 'assignTo', "executionID=$child->execution&taskID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true);
|
||||
common::printIcon('task', 'start', "taskID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true);
|
||||
common::printIcon('task', 'activate', "taskID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true);
|
||||
common::printIcon('task', 'close', "taskID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true);
|
||||
|
||||
@@ -609,7 +609,7 @@ class testcaseModel extends model
|
||||
*/
|
||||
public function getByAssignedTo($account, $orderBy = 'id_desc', $pager = null, $auto = 'no')
|
||||
{
|
||||
return $this->dao->select('t1.*,t2.project,t2.pri,t2.title,t2.type,t2.openedBy,t2.color,t2.product,t2.branch,t2.module,t2.status,t3.name as taskName')->from(TABLE_TESTRUN)->alias('t1')
|
||||
return $this->dao->select('t1.task,t1.case,t1.version,t1.assignedTo,t1.lastRunner,t1.lastRunDate,t1.lastRunResult,t1.status,t2.id as id,t2.project,t2.pri,t2.title,t2.type,t2.openedBy,t2.color,t2.product,t2.branch,t2.module,t2.status,t3.name as taskName')->from(TABLE_TESTRUN)->alias('t1')
|
||||
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id')
|
||||
->leftJoin(TABLE_TESTTASK)->alias('t3')->on('t1.task = t3.id')
|
||||
->where('t1.assignedTo')->eq($account)
|
||||
|
||||
+17
-8
@@ -239,6 +239,8 @@ class tree extends control
|
||||
$datasource = $this->loadModel('workflowdatasource', 'flow')->getByID($datasourceID);
|
||||
if($datasource)
|
||||
{
|
||||
$this->app->rawModule = 'workflowdatasource';
|
||||
|
||||
$title = $datasource->name;
|
||||
$position[] = $datasource->name;
|
||||
|
||||
@@ -250,18 +252,25 @@ class tree extends control
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
/* viewType is workflow building category. */
|
||||
else if(strpos($viewType, '_') !== false)
|
||||
{
|
||||
$manageChild = 'manage' . ucfirst($viewType) . 'Child';
|
||||
$params = explode('_', $viewType);
|
||||
if(count($params) == 2)
|
||||
{
|
||||
$this->app->rawModule = $params[0];
|
||||
|
||||
$title = $this->lang->tree->common;
|
||||
$position[] = $this->lang->tree->common;
|
||||
$manageChild = 'manage' . ucfirst($viewType) . 'Child';
|
||||
|
||||
$this->lang->tree->$manageChild = $title;
|
||||
$title = $this->lang->tree->common;
|
||||
$position[] = $this->lang->tree->common;
|
||||
|
||||
$root = new stdclass();
|
||||
$root->name = $title;
|
||||
$this->view->root = $root;
|
||||
$this->lang->tree->$manageChild = $title;
|
||||
|
||||
$root = new stdclass();
|
||||
$root->name = $title;
|
||||
$this->view->root = $root;
|
||||
}
|
||||
}
|
||||
|
||||
$parentModules = $this->tree->getParents($currentModuleID);
|
||||
|
||||
@@ -943,7 +943,8 @@ class upgradeModel extends model
|
||||
case '16_5_beta1': $confirmContent .= file_get_contents($this->getUpgradeFile('16.5.beta1'));
|
||||
case '16_5': $confirmContent .= file_get_contents($this->getUpgradeFile('16.5'));
|
||||
case '17_0_beta1': $confirmContent .= file_get_contents($this->getUpgradeFile('17.0.beta1'));
|
||||
case '17_0_beta2':
|
||||
case '17_0_beta2': $confirmContent .= file_get_contents($this->getUpgradeFile('17.0.beta2'));
|
||||
case '17_0': $confirmContent .= file_get_contents($this->getUpgradeFile('17.0'));
|
||||
}
|
||||
|
||||
return $confirmContent;
|
||||
|
||||
@@ -136,6 +136,9 @@ class userModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
/* Put the current user first. */
|
||||
$users = $this->processAccountSort($users);
|
||||
|
||||
/* Append empty, closed, and guest users. */
|
||||
if(strpos($params, 'noempty') === false) $users = array('' => '') + $users;
|
||||
if(strpos($params, 'noclosed') === false) $users = $users + array('closed' => 'Closed');
|
||||
@@ -2623,6 +2626,10 @@ class userModel extends model
|
||||
if(!empty($this->config->isINT)) $firstLetter = '';
|
||||
$users[$account] = $firstLetter . ($user->realname ? $user->realname : $user->account);
|
||||
}
|
||||
|
||||
/* Put the current user first. */
|
||||
$users = $this->processAccountSort($users);
|
||||
|
||||
return array('' => '') + $users;
|
||||
}
|
||||
|
||||
@@ -2828,4 +2835,23 @@ class userModel extends model
|
||||
$admins = explode(',', trim($company->admins, ','));
|
||||
$this->app->user = $this->dao->select('*')->from(TABLE_USER)->where('account')->eq($admins[0])->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the current user first.
|
||||
*
|
||||
* @param array $users
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function processAccountSort($users = array())
|
||||
{
|
||||
if(isset($users[$this->app->user->account]))
|
||||
{
|
||||
$currentUser = array();
|
||||
$currentUser[$this->app->user->account] = $users[$this->app->user->account];
|
||||
unset($users[$this->app->user->account]);
|
||||
$users = $currentUser + $users;
|
||||
}
|
||||
return $users;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* ZUI: ZUI Kanban View - v1.10.0 - 2022-06-02
|
||||
* ZUI: ZUI Kanban View - v1.10.0 - 2022-06-08
|
||||
* http://openzui.com
|
||||
* GitHub: https://github.com/easysoft/zui.git
|
||||
* Copyright (c) 2022 cnezsoft.com; Licensed MIT
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user