* implement kanban pages with kanban component.
This commit is contained in:
@@ -1159,31 +1159,25 @@ class product extends control
|
||||
$kanbanGroup = $this->product->getStats4Kanban();
|
||||
extract($kanbanGroup);
|
||||
|
||||
$products = array();
|
||||
$myProducts = array();
|
||||
$otherProducts = array();
|
||||
foreach($productList as $productID => $product)
|
||||
{
|
||||
if($product->status == 'normal' and $product->PO == $this->app->user->account)
|
||||
{
|
||||
$myProducts[$product->program][$productID] = $productID;
|
||||
}
|
||||
elseif($product->status == 'normal' and !($product->PO == $this->app->user->account))
|
||||
{
|
||||
$otherProducts[$product->program][$productID] = $productID;
|
||||
}
|
||||
if($product->status != 'normal') continue;
|
||||
if($product->PO == $this->app->user->account) $myProducts[$product->program][] = $productID;
|
||||
else $otherProducts[$product->program][] = $productID;
|
||||
}
|
||||
|
||||
$products['myProducts'] = $myProducts;
|
||||
$products['otherProducts'] = $otherProducts;
|
||||
$kanbanList = array();
|
||||
if(!empty($myProducts)) $kanbanList['my'] = $myProducts;
|
||||
if(!empty($otherProducts)) $kanbanList['other'] = $otherProducts;
|
||||
|
||||
$this->view->title = $this->lang->product->kanban;
|
||||
$this->view->products = $products;
|
||||
$this->view->kanbanList = $kanbanList;
|
||||
$this->view->programList = array(0 => $this->lang->product->emptyProgram) + $programList;
|
||||
$this->view->productList = $productList;
|
||||
$this->view->planList = $planList;
|
||||
$this->view->projectList = $projectList;
|
||||
$this->view->executionList = $executionList;
|
||||
$this->view->projectProduct = $projectProduct;
|
||||
$this->view->latestExecutions = $projectLatestExecutions;
|
||||
$this->view->hourList = $hourList;
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#kanban {padding: 10px;}
|
||||
.table caption {background: #fff; border-top-left-radius: 2px; border-top-right-radius: 2px; margin-bottom: 0; font-weight: 500; padding-top: 0;}
|
||||
.table th {border: 2px solid #fff;}
|
||||
.table td {border-top: 5px solid #fff; border-bottom: 5px solid #fff; border-left: 2px solid #fff; border-right: 2px solid #fff;}
|
||||
.table tbody tr:last-child td {border-bottom: unset;}
|
||||
td.plan, td.release, td.project, td.execution, td.classicProject {vertical-align: top !important;}
|
||||
td.program {padding-top: 10px !important; padding-bottom: 10px !important;}
|
||||
.main-table tbody>tr>td:first-child, .main-table thead>tr>th:first-child {padding: 0 4px 10px 4px;}
|
||||
|
||||
.main-table tbody>tr>td {padding: 0 10px 10px;}
|
||||
.table .program {writing-mode: vertical-lr; padding-left: 4px !important; color: #fff;}
|
||||
td.product {padding-top: 10px !important;}
|
||||
td.project, td.execution {padding: 0 0 10px 0 !important;}
|
||||
td > div:not(.board) > .board-item:first-child {margin-top: 10px;}
|
||||
td > div.board:first-child {margin-top: 5px;}
|
||||
.fix-table-copy-wrapper thead > tr > th:first-child {background: none!important;}
|
||||
|
||||
.board-item {border: 1px solid #ebebeb; padding: 3px 10px; cursor: default; border-radius: 2px; background-color: #fff; text-align: left;}
|
||||
.board-item:hover {border-color: #ccc;}
|
||||
.board {padding: 0 10px;}
|
||||
.board + .board {margin-top: 5px;}
|
||||
.board-item + .board-item {margin-top: 10px;}
|
||||
.project .board, .execution .board {padding-top: 5px; border-top: 2px solid #fff;}
|
||||
.project .board:first-child, .execution .board:first-child {padding-top: 5px; border-top: unset;}
|
||||
.release .board-item {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center;}
|
||||
.emptyBoard {padding: 3px 10px; cursor: default;}
|
||||
|
||||
.project .table-row > .table-col:last-child, .execution .table-row > .table-col:last-child, .classicProject .table-row > .table-col:last-child{width: 24px; padding-top: 2px;}
|
||||
|
||||
.scroll {overflow-x: hidden; overflow-y: auto;}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Process kanban data
|
||||
* @param {string} key Kanban key, used as kanban id
|
||||
* @param {Object} programsData Programs data
|
||||
* @returns {Object} kanban data
|
||||
*/
|
||||
function processKanbanData(key, programsData)
|
||||
{
|
||||
var kanbanId = key;
|
||||
|
||||
/* Generate columns */
|
||||
var columns = [];
|
||||
$.each(kanbanColumns, function(_, column)
|
||||
{
|
||||
columns.push($.extend({}, column,
|
||||
{
|
||||
kanban: kanbanId,
|
||||
id: kanbanId + '-' + column.type,
|
||||
}));
|
||||
});
|
||||
|
||||
/* Format lanes data */
|
||||
var lanes = [];
|
||||
$.each(programsData, function(programId, programProducts)
|
||||
{
|
||||
var programName = programList[programId];
|
||||
var subLanes = [];
|
||||
programProducts.forEach(function(productID)
|
||||
{
|
||||
var product = productList[productID];
|
||||
var items = {};
|
||||
|
||||
/* unclosed products */
|
||||
var productItem = {id: 'product-' + productID, _id: productID, name: product.name};
|
||||
items.unclosedProduct = [productItem];
|
||||
|
||||
/* plans */
|
||||
items.unexpiredPlan = [];
|
||||
var plans = planList[productID];
|
||||
if(plans)
|
||||
{
|
||||
$.each(plans, function(planID, plan)
|
||||
{
|
||||
items.unexpiredPlan.push($.extend({}, plan, {id: 'plan-' + planID, _id: planID}));
|
||||
});
|
||||
}
|
||||
|
||||
/* doing projects */
|
||||
if(kanbanColumns.doingProject)
|
||||
{
|
||||
items.doingProject = [];
|
||||
var productProjects = projectProduct[productID];
|
||||
if(productProjects)
|
||||
{
|
||||
$.each(productProjects, function(projectID)
|
||||
{
|
||||
var project = projectList[projectID];
|
||||
if(!project) return;
|
||||
var projectItem = $.extend({}, project, {id: 'project-' + projectID, _id: projectID});
|
||||
items.doingProject.push(projectItem);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* doing execution */
|
||||
items.doingExecution = [];
|
||||
var productProjects = projectProduct[productID];
|
||||
if(productProjects)
|
||||
{
|
||||
$.each(productProjects, function(projectID)
|
||||
{
|
||||
var execution = latestExecutions[projectID];
|
||||
if(!execution) return;
|
||||
var executionItem = $.extend({}, execution, {id: 'execution-' + execution.id, _id: execution.id});
|
||||
items.doingExecution.push(executionItem);
|
||||
});
|
||||
}
|
||||
|
||||
/* normal release */
|
||||
items.normalRelease = [];
|
||||
var releases = releaseList[productID];
|
||||
if(releases)
|
||||
{
|
||||
$.each(releases, function(releaseID, release)
|
||||
{
|
||||
if(!release) return;
|
||||
var releaseItem = $.extend({}, release, {id: 'release-' + releaseID, _id: releaseID});
|
||||
items.normalRelease.push(releaseItem);
|
||||
});
|
||||
}
|
||||
|
||||
subLanes.push({id: kanbanId + '-' + programId + '-' + productID, items: items});
|
||||
});
|
||||
|
||||
lanes.push({id: programId, kanban: kanbanId, name: programName, subLanes: subLanes});
|
||||
});
|
||||
|
||||
return {id: kanbanId, columns: columns, lanes: lanes};
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
/* Init all kanbans */
|
||||
$.each(kanbanList, function(key, programsData)
|
||||
{
|
||||
$('#kanban-' + key).kanban({data: processKanbanData(key, programsData)});
|
||||
});
|
||||
});
|
||||
@@ -2,228 +2,64 @@
|
||||
/**
|
||||
* The html product kanban file of kanban method of product module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @copyright Copyright 2021-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Fangzhou Hu <hufangzhou@easycorp.ltd>
|
||||
* @author Hao Sun <sunhao@easycorp.ltd>
|
||||
* @package ZenTaoPMS
|
||||
* @version $Id
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id="kanban" class="main-table fade auto-fade-in" data-ride="table" data-checkable="false" data-group="true">
|
||||
<?php if(empty($productList)):?>
|
||||
<div class="table-empty-tip">
|
||||
<p><span class="text-muted"><?php echo $lang->noData;?></span></p>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<?php foreach($products as $type => $programs):?>
|
||||
<?php if(empty($programs)) continue;?>
|
||||
<div class="cell">
|
||||
<table class="table text-center" style="border-radius: 0; background: #efefef;">
|
||||
<caption><?php echo $type == 'myProducts' ? $lang->product->myProduct : $lang->product->otherProduct;?></caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<?php
|
||||
$rowspan = $config->systemMode == 'new' ? "rowspan='2'" : '';
|
||||
$colspan = $config->systemMode == 'new' ? "colspan='2'" : '';
|
||||
?>
|
||||
<?php if($config->systemMode == 'new'):?>
|
||||
<th <?php echo $rowspan;?> class="w-20px" style="border-right: 0; border-left: 0; background: #32C5FF;"></th>
|
||||
<?php endif;?>
|
||||
<th <?php echo $rowspan;?> style="border-left: 0px;"><?php echo $lang->product->unclosedProduct;?></th>
|
||||
<th <?php echo $rowspan;?>><?php echo $lang->product->unexpiredPlan;?></th>
|
||||
<th <?php echo $colspan;?>><?php echo $lang->product->doing;?></th>
|
||||
<th <?php echo $rowspan;?>><?php echo $lang->product->normalRelease;?></th>
|
||||
</tr>
|
||||
<?php if($config->systemMode == 'new'):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->product->doingProject;?></th>
|
||||
<th><?php echo $lang->product->doingExecution;?></th>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $colorIndex = 0;?>
|
||||
<?php foreach($programs as $programID => $programProduct):?>
|
||||
<?php $i = 0;?>
|
||||
<?php foreach($programProduct as $productID):?>
|
||||
<?php
|
||||
$scroll = '';
|
||||
$doingCounts = isset($projectProduct[$productID]) ? count($projectProduct[$productID]) : 0;
|
||||
$planCounts = isset($planList[$productID]) ? count($planList[$productID]) : 0;
|
||||
$releaseCount = isset($releaseList[$productID]) ? count($releaseList[$productID]) : 0;
|
||||
if(($doingCounts < $planCounts or $doingCounts < $releaseCount) and ($planCounts > 5 or $releaseCount > 5)) $scroll = 'scroll';
|
||||
?>
|
||||
<tr>
|
||||
<?php if($i == 0 and $config->systemMode == 'new'):?>
|
||||
<td rowspan="<?php echo count($programs[$programID])?>" class="program text-ellipsis" style="background: <?php echo $this->lang->product->kanbanColorList[$colorIndex];?>"><?php echo zget($programList, $programID);?></td>
|
||||
<?php endif;?>
|
||||
<td class="product">
|
||||
<?php if(common::hasPriv('product', 'browse')):?>
|
||||
<?php echo "<span>" . html::a($this->createLink('product', 'browse', "productID=$productID"), $productList[$productID]->name, '', "title={$productList[$productID]->name}") . '</span>';?>
|
||||
<?php else:?>
|
||||
<?php echo "<span title={$productList[$productID]->name}>{$productList[$productID]->name}</span>";?>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
<td class="plan">
|
||||
<div class="<?php echo $scroll;?>">
|
||||
<?php if(isset($planList[$productID])):?>
|
||||
<?php foreach($planList[$productID] as $planID => $plan):?>
|
||||
<div class="board-item text-ellipsis">
|
||||
<?php if(common::hasPriv('productplan', 'view')):?>
|
||||
<?php echo html::a($this->createLink('productplan', 'view', "planID=$planID"), $plan->title, '', "title={$plan->title}");?>
|
||||
<?php else:?>
|
||||
<?php echo "<span title={$plan->title}>{$plan->title}</span>"?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</td>
|
||||
<?php if($config->systemMode == 'new'):?>
|
||||
<td class="project">
|
||||
<?php if(isset($projectProduct[$productID])):?>
|
||||
<?php foreach($projectProduct[$productID] as $projectID => $project):?>
|
||||
<?php if(!isset($projectList[$projectID])) continue;?>
|
||||
<div class="board">
|
||||
<?php $borderStyle = isset($project->delay) ? 'border-left: 3px solid red' : 'border-left: 3px solid #0bd986';?>
|
||||
<div class="board-item" style="<?php echo $borderStyle;?>">
|
||||
<div class="table-row">
|
||||
<div class="table-col text-ellipsis">
|
||||
<?php if(common::hasPriv('project', 'index')):?>
|
||||
<?php echo html::a($this->createLink('project', 'index', "projectID=$projectID"), $projectList[$projectID]->name, '', "title={$projectList[$projectID]->name}");?>
|
||||
<?php else:?>
|
||||
<?php echo "<span title={$projectList[$projectID]->name}>{$projectList[$projectID]->name}</span>"?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<div class="table-col">
|
||||
<div class="c-progress">
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#3CB371' data-value='<?php echo round($projectList[$projectID]->hours->progress);?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo round($projectList[$projectID]->hours->progress);?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
<td class="execution">
|
||||
<?php if(isset($projectProduct[$productID])):?>
|
||||
<?php foreach($projectProduct[$productID] as $projectID => $project):?>
|
||||
<div class="board">
|
||||
<?php
|
||||
$borderStyle = '';
|
||||
if(isset($latestExecutions[$projectID]))
|
||||
{
|
||||
$delay = helper::diffDate(helper::today(), $latestExecutions[$projectID]->end);
|
||||
$borderStyle = $delay > 0 ? 'border-left: 3px solid red' : 'border-left: 3px solid #0bd986';
|
||||
}
|
||||
?>
|
||||
<?php $boardStyle = isset($latestExecutions[$projectID]) ? 'board-item' : 'emptyBoard';?>
|
||||
<?php $executionID = isset($latestExecutions[$projectID]) ? $latestExecutions[$projectID]->id : 0;?>
|
||||
<?php $executionName = isset($latestExecutions[$projectID]) ? $latestExecutions[$projectID]->name : ''?>
|
||||
<div class="<?php echo $boardStyle;?> text-ellipsis" style="<?php echo $borderStyle;?>">
|
||||
<div class="table-row">
|
||||
<div class="table-col text-ellipsis">
|
||||
<?php if(isset($latestExecutions[$projectID])):?>
|
||||
<?php if(common::hasPriv('execution', 'task')):?>
|
||||
<?php echo html::a($this->createLink('execution', 'task', "executionID=$executionID"), $executionName, '', "title={$executionName}");?>
|
||||
<?php else:?>
|
||||
<?php echo "<span title=$executionName>$executionName</span>";?>
|
||||
<?php endif;?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<div class="table-col">
|
||||
<?php if(isset($latestExecutions[$projectID])):?>
|
||||
<div class="c-progress">
|
||||
<?php $hourList[$executionID] = isset($hourList[$executionID]) ? $hourList[$executionID] : $emptyHour; ?>
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#3CB371' data-value='<?php echo round($hourList[$executionID]->progress);?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo round($hourList[$executionID]->progress);?></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
<?php if($config->systemMode == 'classic'):?>
|
||||
<td class="classicProject">
|
||||
<div>
|
||||
<?php if(isset($executionList[$productID])):?>
|
||||
<?php foreach($executionList[$productID] as $executionID => $execution):?>
|
||||
<?php
|
||||
$borderStyle = '';
|
||||
$delay = helper::diffDate(helper::today(), $execution->end);
|
||||
$borderStyle = $delay > 0 ? 'border-left: 3px solid red' : 'border-left: 3px solid #0bd986';
|
||||
?>
|
||||
<div class="board-item" style="<?php echo $borderStyle;?>">
|
||||
<div class="table-row">
|
||||
<div class="table-col text-ellipsis">
|
||||
<?php if(common::hasPriv('execution', 'task')):?>
|
||||
<?php echo html::a($this->createLink('execution', 'task', "executionID=$executionID"), $execution->name, '', "title={$execution->name} class='text-ellipsis'");?>
|
||||
<?php else:?>
|
||||
<?php echo "<span title={$execution->name}>{$execution->name}</span>"?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<div class="table-col">
|
||||
<div class="c-progress">
|
||||
<?php $hourList[$executionID] = isset($hourList[$executionID]) ? $hourList[$executionID] : $emptyHour; ?>
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#3CB371' data-value='<?php echo round($hourList[$executionID]->progress);?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo round($hourList[$executionID]->progress);?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
<td class="release">
|
||||
<div class="<?php echo $scroll;?>">
|
||||
<?php if(isset($releaseList[$productID])):?>
|
||||
<?php foreach($releaseList[$productID] as $releaseID => $release):?>
|
||||
<div class="board-item">
|
||||
<?php if(common::hasPriv('release', 'view')):?>
|
||||
<?php echo html::a($this->createLink('release', 'view', "releaseID=$releaseID"), $release->name, '', "title={$release->name} class='text-ellipsis'");?>
|
||||
<?php else:?>
|
||||
<?php echo "<span title={$release->name}>{$release->name}</span>"?>
|
||||
<?php endif;?>
|
||||
<?php if($release->marker) echo " <span><i class='icon icon-flag red'></i></span>";?>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</td>
|
||||
<?php $i ++;?>
|
||||
</tr>
|
||||
<?php endforeach;?>
|
||||
<?php $colorIndex = $colorIndex == 9 ? 0 : ++ $colorIndex;?>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
<?php include '../../common/view/kanban.html.php';?>
|
||||
<?php if(empty($kanbanList)):?>
|
||||
<div class="table-empty-tip cell">
|
||||
<p class="text-muted"><?php echo $lang->noData;?></p>
|
||||
</div>
|
||||
<script>
|
||||
$(function()
|
||||
<?php else:?>
|
||||
<div id='kanbanList'>
|
||||
<?php foreach($kanbanList as $type => $programs):?>
|
||||
<div class='panel kanban-panel'>
|
||||
<div class='panel-heading'>
|
||||
<strong><?php echo $type == 'my' ? $lang->product->myProduct : $lang->product->otherProduct;?></strong>
|
||||
</div>
|
||||
<div class='panel-body'>
|
||||
<div id='kanban-<?php echo $type;?>' class='kanban'></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php
|
||||
$kanbanColumns = array();
|
||||
$kanbanColumns['unclosedProduct'] = array('name' => $lang->product->unclosedProduct, 'type' => 'unclosedProduct');
|
||||
$kanbanColumns['unexpiredPlan'] = array('name' => $lang->product->unexpiredPlan, 'type' => 'unexpiredPlan');
|
||||
if($config->systemMode == 'new')
|
||||
{
|
||||
$('.board').height($('.project .board').height());
|
||||
|
||||
$('.table div.scroll').each(function()
|
||||
{
|
||||
var count = $(this).parent().siblings('td.project').children('.board').length >= 5 ? $(this).parent().siblings('td.project').children('.board').length : 5;
|
||||
var preHeight = $(this).parent().siblings('td.project').children('.board').length >= 5 ? $('.board').outerHeight(true) : $(this).find('.board-item').outerHeight(true);
|
||||
$(this).css('max-height', preHeight * count);
|
||||
})
|
||||
})
|
||||
</script>
|
||||
$kanbanColumns['doingProject'] = array('name' => $lang->product->doingProject, 'type' => 'doingProject');
|
||||
$kanbanColumns['doingExecution'] = array('name' => $lang->product->doingExecution, 'type' => 'doingExecution');
|
||||
}
|
||||
else
|
||||
{
|
||||
$kanbanColumns['doingExecution'] = array('name' => $lang->product->doing, 'type' => 'doingExecution');
|
||||
}
|
||||
$kanbanColumns['normalRelease'] = array('name' => $lang->product->normalRelease, 'type' => 'normalRelease');
|
||||
$userPrivs = array();
|
||||
$userPrivs['product'] = common::hasPriv('product', 'browse');
|
||||
$userPrivs['productplan'] = common::hasPriv('productplan', 'view');
|
||||
$userPrivs['project'] = common::hasPriv('project', 'index');
|
||||
$userPrivs['execution'] = common::hasPriv('execution', 'task');
|
||||
$userPrivs['release'] = common::hasPriv('release', 'view');
|
||||
js::set('kanbanColumns', $kanbanColumns);
|
||||
js::set('userPrivs', $userPrivs);
|
||||
js::set('kanbanList', $kanbanList);
|
||||
js::set('programList', $programList);
|
||||
js::set('productList', $productList);
|
||||
js::set('planList', $planList);
|
||||
js::set('projectList', $projectList);
|
||||
js::set('projectProduct', $projectProduct);
|
||||
js::set('latestExecutions', $latestExecutions);
|
||||
js::set('releaseList', $releaseList);
|
||||
js::set('hourList', $hourList);
|
||||
js::set('doingText', $lang->product->doing);
|
||||
?>
|
||||
<?php endif; ?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Process kanban data
|
||||
* @param {string} key Kanban key, used as kanban id
|
||||
* @param {Object} programsData Programs data
|
||||
* @returns {Object} kanban data
|
||||
*/
|
||||
function processKanbanData(key, programsData)
|
||||
{
|
||||
var kanbanId = key;
|
||||
|
||||
/* Generate columns */
|
||||
var columns = [];
|
||||
$.each(kanbanColumns, function(_, column)
|
||||
{
|
||||
columns.push($.extend({}, column,
|
||||
{
|
||||
kanban: kanbanId,
|
||||
id: kanbanId + '-' + column.type,
|
||||
}));
|
||||
});
|
||||
|
||||
/* Format lanes data */
|
||||
var lanes = [];
|
||||
$.each(programsData, function(programId, program)
|
||||
{
|
||||
var subLanes = [];
|
||||
|
||||
$.each(program.products, function(productID, product)
|
||||
{
|
||||
var items = {};
|
||||
|
||||
/* unclosed products */
|
||||
var productItem = {id: 'product-' + productID, _id: productID, name: product.name};
|
||||
items.unclosedProduct = [productItem];
|
||||
|
||||
/* plans */
|
||||
items.unexpiredPlan = [];
|
||||
var plans = product.plans;
|
||||
if(plans)
|
||||
{
|
||||
$.each(plans, function(planID, plan)
|
||||
{
|
||||
items.unexpiredPlan.push($.extend({}, plan, {id: 'plan-' + planID, _id: planID}));
|
||||
});
|
||||
}
|
||||
|
||||
/* wait projects */
|
||||
items.waitProject = [];
|
||||
var waitProjects = product.projects && product.projects.wait;
|
||||
if(waitProjects)
|
||||
{
|
||||
$.each(waitProjects, function(projectID, project)
|
||||
{
|
||||
var projectItem = $.extend({}, project, {id: 'project-' + projectID, _id: projectID});
|
||||
items.waitProject.push(projectItem);
|
||||
});
|
||||
}
|
||||
|
||||
/* doing projects and executions */
|
||||
items.doingProject = [];
|
||||
items.doingExecution = [];
|
||||
var doingProjects = product.projects && product.projects.doing;
|
||||
if(doingProjects)
|
||||
{
|
||||
$.each(doingProjects, function(projectID, project)
|
||||
{
|
||||
var projectItem = $.extend({}, project, {id: 'project-' + projectID, _id: projectID});
|
||||
items.doingProject.push(projectItem);
|
||||
|
||||
var execution = project.execution;
|
||||
if(!execution) return;
|
||||
var executionItem = $.extend({}, execution, {id: 'execution-' + execution.id, _id: execution.id});
|
||||
items.doingExecution.push(executionItem);
|
||||
});
|
||||
}
|
||||
|
||||
/* normal release */
|
||||
items.normalRelease = [];
|
||||
var releases = product.releases;
|
||||
if(releases)
|
||||
{
|
||||
$.each(releases, function(releaseID, release)
|
||||
{
|
||||
if(!release) return;
|
||||
var releaseItem = $.extend({}, release, {id: 'release-' + releaseID, _id: releaseID});
|
||||
items.normalRelease.push(releaseItem);
|
||||
});
|
||||
}
|
||||
|
||||
subLanes.push({id: kanbanId + '-' + programId + '-' + productID, items: items});
|
||||
});
|
||||
|
||||
var programItem = $.extend({}, program, {id: programId, kanban: kanbanId, subLanes: subLanes});
|
||||
lanes.push(programItem);
|
||||
});
|
||||
|
||||
return {id: kanbanId, columns: columns, lanes: lanes};
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
/* Init all kanbans */
|
||||
$.each(kanbanGroup, function(key, programsData)
|
||||
{
|
||||
var $kanban = $('#kanban-' + key);
|
||||
if(!$kanban.length) return;
|
||||
$kanban.kanban({data: processKanbanData(key, programsData)});
|
||||
});
|
||||
});
|
||||
@@ -1,182 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* The html template file of kanban method of program module of ZenTaoPMS.
|
||||
* The html product kanban file of kanban method of product module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @copyright Copyright 2021-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Guangming Sun<sunguangming@cnezsoft.com>
|
||||
* @author Hao Sun <sunhao@easycorp.ltd>
|
||||
* @package ZenTaoPMS
|
||||
* @version $Id
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id="kanban" class="main-table fade auto-fade-in" data-ride="table" data-checkable="false" data-group="true">
|
||||
<?php foreach($kanbanGroup as $type => $programGroup):?>
|
||||
<?php if(empty($programGroup)) continue;?>
|
||||
<?php $colorIndex = 0;?>
|
||||
<div class="cell">
|
||||
<div class='detail'>
|
||||
<div class='detail-title'><?php echo $lang->program->kanban->typeList[$type];?></div>
|
||||
<div class='detail-content'>
|
||||
<table class="table no-margin table-grouped text-center" style='background: #efefef;'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th rowspan='2' class='w-20px' style='background: #32C5FF; border: none'></th>
|
||||
<th rowspan='2'><?php echo $lang->program->kanban->openProducts;?></th>
|
||||
<th rowspan='2'><?php echo $lang->program->kanban->unexpiredPlans;?></th>
|
||||
<th rowspan='2'><?php echo $lang->program->kanban->waitingProjects;?></th>
|
||||
<th colspan='2'><?php echo $lang->program->statusList['doing'];?></th>
|
||||
<th rowspan='2'><?php echo $lang->program->kanban->normalReleases;?></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->program->kanban->doingProjects;?></th>
|
||||
<th><?php echo $lang->program->kanban->doingExecutions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($programGroup as $programID => $program):?>
|
||||
<tr>
|
||||
<td class='lane-name text-ellipsis' style='background: <?php echo $lang->program->kanban->laneColorList[$colorIndex];?>; color: #fff; border: none;' rowspan='<?php echo $program->rowspan;?>' title=<?php echo $program->name;?>><?php echo $program->name;?></td>
|
||||
<?php $i = 0;?>
|
||||
<?php if(!empty($program->products)):?>
|
||||
<?php foreach($program->products as $productID => $product):?>
|
||||
<?php
|
||||
$scroll = '';
|
||||
$doingCounts = isset($product->projects['doing']) ? count($product->projects['doing']) : 0;
|
||||
$planCounts = isset($product->plans) ? count($product->plans) : 0;
|
||||
$releaseCount = isset($product->releases) ? count($product->releases) : 0;
|
||||
if(($doingCounts < $planCounts || $doingCounts < $releaseCount) and ($planCounts > 5 or $releaseCount > 5)) $scroll = 'scroll';
|
||||
?>
|
||||
<?php if($i != 0) echo '<tr>';?>
|
||||
<td title=<?php echo $product->name;?> rowspan='<?php echo $product->rowspan;?>'><?php echo $product->name;?></td>
|
||||
<td class='normal-plan' rowspan='<?php echo $product->rowspan;?>'>
|
||||
<div class="<?php echo $scroll;?>">
|
||||
<?php foreach($product->plans as $planID => $plan):?>
|
||||
<div class='board-item'>
|
||||
<div class='table-row'>
|
||||
<div class='table-col text-ellipsis text-left'>
|
||||
<?php echo html::a($this->createLink('productplan', 'view', "planID=$plan->id"), $plan->title);?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
</td>
|
||||
<td class='wait-project' rowspan='<?php echo $product->rowspan?>'>
|
||||
<div class="<?php echo $scroll;?>">
|
||||
<?php if(isset($product->projects['wait'])):?>
|
||||
<?php foreach($product->projects['wait'] as $projectID => $project):?>
|
||||
<div class='board-item' style='border-left: 3px solid #0991FF'>
|
||||
<div class='table-row'>
|
||||
<div class='table-col text-ellipsis text-left'>
|
||||
<?php echo html::a($this->createLink('project', 'index', "projectID=$project->id"), $project->name);?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</td>
|
||||
<?php if(isset($product->projects['doing'])):?>
|
||||
<?php $index = 0;?>
|
||||
<?php foreach($product->projects['doing'] as $projectID => $project):?>
|
||||
<?php if($index != 0) echo "<tr>";?>
|
||||
<td class='doing-td project'>
|
||||
<div class='board'>
|
||||
<div class='board-item' <?php echo "style='border-left: 3px solid " . (isset($project->delay) ? 'red' : "#0BD986") . "'";?>>
|
||||
<div class='table-row'>
|
||||
<div class='table-col'>
|
||||
<?php echo html::a($this->createLink('project', 'index', "projectID=$project->id"), $project->name);?>
|
||||
</div>
|
||||
<div class='table-col'>
|
||||
<div class="c-progress">
|
||||
<?php $projectProgress = isset($project->hours->progress) ? $project->hours->progress : 0;?>
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#3CB371' data-value='<?php echo round($projectProgress);?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo round($projectProgress);?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class='doing-td execution'>
|
||||
<?php if(!empty($project->execution)):?>
|
||||
<div class='board'>
|
||||
<div class='board-item' <?php echo "style='border-left: 3px solid " . (isset($project->execution->delay) ? 'red' : "#0BD986") . "'";?>>
|
||||
<div class='table-row'>
|
||||
<div class='table-col'>
|
||||
<?php echo html::a($this->createLink('execution', 'task', "executionID={$project->execution->id}"), $project->execution->name);?>
|
||||
</div>
|
||||
<div class='table-col'>
|
||||
<div class="c-progress">
|
||||
<?php $executionProgress = isset($project->execution->hours->progress) ? $project->execution->hours->progress : 0;?>
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#3CB371' data-value='<?php echo round($executionProgress);?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo round($executionProgress);?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
<?php if($index == 0):?>
|
||||
<td class='normal-release' rowspan=<?php echo $product->rowspan;?>>
|
||||
<div class="<?php echo $scroll;?>">
|
||||
<?php foreach($product->releases as $releaseID => $release):?>
|
||||
<div class='board-item'>
|
||||
<div class='table-row'>
|
||||
<div class='table-col'>
|
||||
<?php $flag = $release->marker ? " <icon class='icon icon-flag red' title='{$lang->release->marker}'></icon> " : '';?>
|
||||
<?php echo html::a($this->createLink('release', 'view', "releaseID=$release->id"), $release->name . $flag);?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
<?php if($index != 0) echo "</tr>";?>
|
||||
<?php $index ++;?>
|
||||
<?php endforeach;?>
|
||||
<?php else:?>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<?php endif;?>
|
||||
<?php if($i != 0) echo '</tr>';?>
|
||||
<?php $i ++;?>
|
||||
<?php endforeach;?>
|
||||
<?php else:?>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<?php endif;?>
|
||||
</tr>
|
||||
<?php $colorIndex ++;?>
|
||||
<?php if($colorIndex > 9) $colorIndex = 0;?>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php include '../../common/view/kanban.html.php';?>
|
||||
<?php if(empty($kanbanGroup)):?>
|
||||
<div class="table-empty-tip cell">
|
||||
<p class="text-muted"><?php echo $lang->noData;?></p>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div id='kanbanList'>
|
||||
<?php foreach($kanbanGroup as $type => $programs):?>
|
||||
<?php if(empty($programs)) continue;?>
|
||||
<div class='panel kanban-panel'>
|
||||
<div class='panel-heading'>
|
||||
<strong><?php echo $lang->program->kanban->typeList[$type];?></strong>
|
||||
</div>
|
||||
<div class='panel-body'>
|
||||
<div id='kanban-<?php echo $type;?>' class='kanban'></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<script>
|
||||
$(function()
|
||||
{
|
||||
$('.table div.scroll').each(function()
|
||||
{
|
||||
var count = $(this).closest('tr').find('td:first').attr('rowspan') >= 5 ? $(this).closest('tr').find('td:first').attr('rowspan') : 5;
|
||||
var projectTdHeight = $(this).closest('tr').find('td.project .board').outerHeight(true) + 20;
|
||||
var maxHeight = count > 5 ? projectTdHeight * count : projectTdHeight * count - 40;
|
||||
$(this).css('max-height', maxHeight);
|
||||
})
|
||||
})
|
||||
</script>
|
||||
<?php
|
||||
$kanbanColumns = array();
|
||||
$kanbanColumns['unclosedProduct'] = array('name' => $lang->program->kanban->openProducts, 'type' => 'unclosedProduct');
|
||||
$kanbanColumns['unexpiredPlan'] = array('name' => $lang->program->kanban->unexpiredPlans, 'type' => 'unexpiredPlan');
|
||||
$kanbanColumns['waitProject'] = array('name' => $lang->program->kanban->waitingProjects, 'type' => 'waitProject');
|
||||
$kanbanColumns['doingProject'] = array('name' => $lang->program->kanban->doingProjects, 'type' => 'doingProject');
|
||||
$kanbanColumns['doingExecution'] = array('name' => $lang->program->kanban->doingExecutions, 'type' => 'doingExecution');
|
||||
$kanbanColumns['normalRelease'] = array('name' => $lang->program->kanban->normalReleases, 'type' => 'normalRelease');
|
||||
$userPrivs = array();
|
||||
$userPrivs['product'] = common::hasPriv('product', 'browse');
|
||||
$userPrivs['productplan'] = common::hasPriv('productplan', 'view');
|
||||
$userPrivs['project'] = common::hasPriv('project', 'index');
|
||||
$userPrivs['execution'] = common::hasPriv('execution', 'task');
|
||||
$userPrivs['release'] = common::hasPriv('release', 'view');
|
||||
js::set('kanbanColumns', $kanbanColumns);
|
||||
js::set('userPrivs', $userPrivs);
|
||||
js::set('kanbanGroup', $kanbanGroup);
|
||||
js::set('doingText', $lang->program->statusList['doing']);
|
||||
?>
|
||||
<?php endif; ?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
+62
-23
@@ -1,27 +1,66 @@
|
||||
/**
|
||||
* Process kanban data
|
||||
* @param {string} key Kanban key, used as kanban id
|
||||
* @param {Object} programGroup Group data
|
||||
* @returns {Object} kanban data
|
||||
*/
|
||||
function processKanbanData(key, programGroup)
|
||||
{
|
||||
var kanbanId = key;
|
||||
|
||||
/* Generate columns */
|
||||
var columns = [];
|
||||
$.each(kanbanColumns, function(_, column)
|
||||
{
|
||||
columns.push($.extend({}, column,
|
||||
{
|
||||
kanban: kanbanId,
|
||||
id: kanbanId + '-' + column.type,
|
||||
}));
|
||||
});
|
||||
/* Format lanes data */
|
||||
var lanes = [];
|
||||
$.each(programGroup, function(programId, statusMap)
|
||||
{
|
||||
var programName = programPairs[programId];
|
||||
var items = {doingExecution: []};
|
||||
|
||||
/* Projects and executions */
|
||||
['wait', 'doing', 'closed'].forEach(function(status)
|
||||
{
|
||||
var itemsList = [];
|
||||
var statusProjects = statusMap[status];
|
||||
if(statusProjects)
|
||||
{
|
||||
$.each(statusProjects, function(projectID, project)
|
||||
{
|
||||
itemsList.push($.extend({}, project, {id: 'project-' + projectID, _id: projectID}));
|
||||
|
||||
if(status === 'doing')
|
||||
{
|
||||
var execution = latestExecutions[projectID];
|
||||
if(execution)
|
||||
{
|
||||
var executionItem = $.extend({}, execution, {id: 'execution-' + execution.id, _id: execution.id});
|
||||
items.doingExecution = [executionItem];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
items[status + 'Project'] = itemsList;
|
||||
});
|
||||
|
||||
lanes.push({id: programId, kanban: kanbanId, name: programName, items: items});
|
||||
});
|
||||
|
||||
return {id: kanbanId, columns: columns, lanes: lanes};
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
$("div[class^='board-doing-']").height($('.board-doing-project').height());
|
||||
|
||||
$('.board-program').each(function()
|
||||
/* Init all kanbans */
|
||||
$.each(kanbanGroup, function(key, programGroup)
|
||||
{
|
||||
var boardWaitCount = $(this).find('.board-wait .board-item').length;
|
||||
var boardClosedCount = $(this).find('.board-closed .board-item').length;
|
||||
var boardDoingCount = $(this).find('.board-doing-project .board-item').length;
|
||||
|
||||
if((boardWaitCount > 5 || boardClosedCount > 5) && (boardWaitCount > boardDoingCount || boardClosedCount > boardDoingCount))
|
||||
{
|
||||
var boardHeight = 0;
|
||||
if(boardDoingCount >= 5)
|
||||
{
|
||||
boardHeight = $('.board-doing-project').outerHeight(true) * boardDoingCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
var boardHeight = $(this).find('.board-project .board-item').outerHeight(true) * 5;
|
||||
}
|
||||
|
||||
$(this).find('.board-project').css("height", boardHeight);
|
||||
$(this).find('.board-project').css("overflow", 'auto');
|
||||
}
|
||||
$('#kanban-' + key).kanban({data: processKanbanData(key, programGroup)});
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,144 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* The project kanban view file of project module of ZenTaoPMS.
|
||||
* The html product kanban file of kanban method of product module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Qiyu Xie
|
||||
* @package project
|
||||
* @version $Id: kanban.html.php $
|
||||
* @copyright Copyright 2021-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Hao Sun <sunhao@easycorp.ltd>
|
||||
* @package ZenTaoPMS
|
||||
* @version $Id
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php $colorIndex = 0;?>
|
||||
<?php include '../../common/view/kanban.html.php';?>
|
||||
<?php if(empty($kanbanGroup)):?>
|
||||
<div class="table-empty-tip">
|
||||
<p><span class="text-muted"><?php echo $lang->project->empty;?></span></p>
|
||||
<div class="table-empty-tip cell">
|
||||
<p class="text-muted"><?php echo $lang->project->empty;?></p>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<?php foreach($kanbanGroup as $type => $projectGroup):?>
|
||||
<?php if(empty($projectGroup)) continue;?>
|
||||
<div id="kanban" class="main-table fade auto-fade-in" data-ride="table" data-checkable="false" data-group="true">
|
||||
<div class="cell">
|
||||
<div class='detail'>
|
||||
<div class='detail-title'><?php echo $lang->project->typeList[$type];?></div>
|
||||
<div class='detail-content'>
|
||||
<table class='table no-margin' style='background-color: #efefef;'>
|
||||
<thead class='text-center'>
|
||||
<tr>
|
||||
<th rowspan='2' style="border-right: unset !important" class='w-20px'></th>
|
||||
<th rowspan='2' style="border-left: unset !important"><?php echo $lang->project->waitProjects;?></th>
|
||||
<th colspan='2'><?php echo $lang->project->statusList['doing'];?></th>
|
||||
<th rowspan='2'><?php echo $lang->project->closedProjects;?></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->doingProjects;?></th>
|
||||
<th><?php echo $lang->project->doingExecutions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($projectGroup as $programID => $statusList):?>
|
||||
<tr class='board-program'>
|
||||
<td class='text-center' title='<?php echo zget($programPairs, $programID);?>' style='background: <?php echo $lang->project->laneColorList[$colorIndex];?>; color: #fff; padding-left: 2px; writing-mode: vertical-lr;'><?php echo zget($programPairs, $programID);?></td>
|
||||
<?php foreach(array('wait','doing','closed') as $status):?>
|
||||
<?php if($status == 'doing'):?>
|
||||
<td class='board-doing'>
|
||||
<?php if(isset($statusList[$status])):?>
|
||||
<?php foreach($statusList[$status] as $project):?>
|
||||
<div class='board-doing-project'>
|
||||
<div class='board-item' <?php echo "style='border-left: 3px solid " . (isset($project->delay) ? 'red' : "#0BD986") . "'";?>>
|
||||
<div class='table-row'>
|
||||
<div class='table-col'>
|
||||
<?php
|
||||
if(common::hasPriv('project', 'index'))
|
||||
{
|
||||
echo html::a($this->createLink('project', 'index', "projectID=$project->id"), $project->name, '', "title='{$project->name}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<span title='{$project->name}'>{$project->name}</span>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class='table-col'>
|
||||
<div class="c-progress">
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#3CB371' data-value='<?php echo round($project->hours->progress);?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo round($project->hours->progress);?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
<td class='board-doing'>
|
||||
<?php if(isset($statusList[$status])):?>
|
||||
<?php foreach($statusList[$status] as $project):?>
|
||||
<div class='board-doing-execution'>
|
||||
<?php if(isset($latestExecutions[$project->id])):?>
|
||||
<?php $execution = $latestExecutions[$project->id];?>
|
||||
<div class='board-item' <?php echo "style='border-left: 3px solid " . (isset($execution->delay) ? 'red' : "#0BD986") . "'";?>>
|
||||
<div class='table-row'>
|
||||
<div class='table-col'>
|
||||
<?php
|
||||
if(common::hasPriv('execution', 'task'))
|
||||
{
|
||||
echo html::a($this->createLink('execution', 'task', "executionID=$execution->id"), $execution->name, '', "title='{$execution->name}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<span title='{$execution->name}'>{$execution->name}</span>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class='table-col'>
|
||||
<div class="c-progress">
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#3CB371' data-value='<?php echo round($execution->hours->progress);?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo round($execution->hours->progress);?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
<?php else:?>
|
||||
<td class='board-<?php echo $status;?>'>
|
||||
<div class='board-project'>
|
||||
<?php if(isset($statusList[$status])):?>
|
||||
<?php foreach($statusList[$status] as $project):?>
|
||||
<div class='board-item' <?php echo "style='border-left: 3px solid " . $lang->execution->statusColorList[$status] . "'";?>>
|
||||
<?php
|
||||
if(common::hasPriv('project', 'index'))
|
||||
{
|
||||
echo html::a($this->createLink('project', 'index', "projectID=$project->id"), $project->name, '', "title='{$project->name}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<span title='{$project->name}'>{$project->name}</span>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</td>
|
||||
<?php endif;?>
|
||||
<?php endforeach;?>
|
||||
</tr>
|
||||
<?php $colorIndex ++;?>
|
||||
<?php if($colorIndex > 9) $colorIndex = 0;?>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id='kanbanList'>
|
||||
<?php foreach($kanbanGroup as $type => $projectGroup):?>
|
||||
<div class='panel kanban-panel'>
|
||||
<div class='panel-heading'>
|
||||
<strong><?php echo $lang->project->typeList[$type];?></strong>
|
||||
</div>
|
||||
<div class='panel-body'>
|
||||
<div id='kanban-<?php echo $type;?>' class='kanban'></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
<?php endif;?>
|
||||
<?php
|
||||
$kanbanColumns = array();
|
||||
$kanbanColumns['waitProject'] = array('name' => $lang->project->waitProjects, 'type' => 'waitProject');
|
||||
$kanbanColumns['doingProject'] = array('name' => $lang->project->doingProjects, 'type' => 'doingProject');
|
||||
$kanbanColumns['doingExecution'] = array('name' => $lang->project->doingExecutions, 'type' => 'doingExecution');
|
||||
$kanbanColumns['closedProject'] = array('name' => $lang->project->closedProjects, 'type' => 'closedProject');
|
||||
$userPrivs = array();
|
||||
$userPrivs['project'] = common::hasPriv('project', 'index');
|
||||
$userPrivs['execution'] = common::hasPriv('execution', 'task');
|
||||
js::set('kanbanColumns', $kanbanColumns);
|
||||
js::set('userPrivs', $userPrivs);
|
||||
js::set('kanbanGroup', $kanbanGroup);
|
||||
js::set('latestExecutions', $latestExecutions);
|
||||
js::set('programPairs', $programPairs);
|
||||
js::set('doingText', $lang->project->statusList['doing']);
|
||||
?>
|
||||
<?php endif; ?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
Reference in New Issue
Block a user