* finish task #2552.
This commit is contained in:
+29
-8
@@ -687,7 +687,7 @@ class commonModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Print link icon.
|
||||
* Build icon button.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
@@ -703,7 +703,7 @@ class commonModel extends model
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function printIcon($module, $method, $vars = '', $object = '', $type = 'button', $icon = '', $target = '', $extraClass = '', $onlyBody = false, $misc = '')
|
||||
public static function buildIconButton($module, $method, $vars = '', $object = '', $type = 'button', $icon = '', $target = '', $extraClass = '', $onlyBody = false, $misc = '')
|
||||
{
|
||||
if(isonlybody() and strpos($extraClass, 'showinonlybody') === false) return false;
|
||||
|
||||
@@ -755,34 +755,55 @@ class commonModel extends model
|
||||
{
|
||||
if($app->getViewType() == 'mhtml')
|
||||
{
|
||||
echo html::a($link, $title, $target, "class='$extraClass' data-role='button' data-mini='true' data-inline='true' data-theme='b'", true);
|
||||
return;
|
||||
return html::a($link, $title, $target, "class='$extraClass' data-role='button' data-mini='true' data-inline='true' data-theme='b'", true);
|
||||
}
|
||||
if($type == 'button')
|
||||
{
|
||||
if($method != 'edit' and $method != 'copy' and $method != 'delete')
|
||||
{
|
||||
echo html::a($link, "<i class='$class'></i> " . $title, $target, "class='btn $extraClass' $misc", true);
|
||||
return html::a($link, "<i class='$class'></i> " . $title, $target, "class='btn $extraClass' $misc", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a($link, "<i class='$class'></i>", $target, "class='btn $extraClass' title='$title' $misc", false);
|
||||
return html::a($link, "<i class='$class'></i>", $target, "class='btn $extraClass' title='$title' $misc", false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a($link, "<i class='$class'></i>", $target, "class='btn-icon $extraClass' title='$title' $misc", false);
|
||||
return html::a($link, "<i class='$class'></i>", $target, "class='btn-icon $extraClass' title='$title' $misc", false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($type == 'list')
|
||||
{
|
||||
echo "<button type='button' class='disabled btn-icon $extraClass'><i class='$class' title='$title' $misc></i></button>";
|
||||
return "<button type='button' class='disabled btn-icon $extraClass'><i class='$class' title='$title' $misc></i></button>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print link icon.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @param string $vars
|
||||
* @param object $object
|
||||
* @param string $type button|list
|
||||
* @param string $icon
|
||||
* @param string $target
|
||||
* @param string $extraClass
|
||||
* @param bool $onlyBody
|
||||
* @param string $misc
|
||||
* @static
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public static function printIcon($module, $method, $vars = '', $object = '', $type = 'button', $icon = '', $target = '', $extraClass = '', $onlyBody = false, $misc = '')
|
||||
{
|
||||
echo common::buildIconButton($module, $method, $vars, $object, $type, $icon, $target, $extraClass, $onlyBody, $misc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print backLink and preLink and nextLink.
|
||||
*
|
||||
|
||||
@@ -1220,7 +1220,7 @@ class project extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function tree($projectID, $level = 'pri_asc')
|
||||
public function tree($projectID, $level = '')
|
||||
{
|
||||
$this->project->setMenu($this->projects, $projectID);
|
||||
$project = $this->loadModel('project')->getById($projectID);
|
||||
|
||||
@@ -2,14 +2,19 @@
|
||||
|
||||
#projectTree {margin-bottom: 0}
|
||||
#projectTree > .tree-action-item {display: none!important}
|
||||
#projectTree li > .tree-item-wrapper > .tree-toggle {display: block}
|
||||
#projectTree li > .tree-item-wrapper:hover {display: block; background-color: #edf3fe; cursor: pointer; margin-left: -20px; padding-left: 20px;}
|
||||
#projectTree li {line-height: 30px; padding-top: 0; padding-bottom: 0}
|
||||
#projectTree .item-type-product > .tree-toggle {display: block; background-color: #edf3fe; margin-left: -20px; padding-left: 20px; border-bottom: 1px solid #ddd; cursor: pointer}
|
||||
#projectTree .item-type-product > .tree-toggle:hover {background-color: #eee}
|
||||
#projectTree .item-type-product.open > .tree-toggle {border-bottom: none}
|
||||
#projectTree .item-type-module > .tree-toggle {display: block}
|
||||
#projectTree .item-type-module > .tree-toggle:hover {display: block; background-color: #edf3fe; cursor: pointer; margin-left: -20px; padding-left: 20px;}
|
||||
#projectTree .item-type-product > .tree-item-wrapper {display: block; background-color: #edf3fe; margin-left: -20px; padding-left: 20px; border-bottom: 1px solid #ddd; cursor: pointer}
|
||||
#projectTree .item-type-product > .tree-item-wrapper:hover {background-color: #eee}
|
||||
#projectTree .item-type-product.open > .tree-item-wrapper {border-bottom: none}
|
||||
#projectTree.tree li>.list-toggle:before {content: '\e6bb'}
|
||||
#projectTree.tree li.open>.list-toggle:before {content: '\e6b8';}
|
||||
#projectTree.tree li>.list-toggle {top: 2px}
|
||||
#projectTree .item-type-story > ul > li {padding-left: 10px;}
|
||||
#projectTree.tree li:before {display: none}
|
||||
#projectTree .table-bordered tr > td:first-child, #projectTree .table-bordered tr > th:first-child {border-left: 1px solid #ddd; padding-left: 0; padding-right: 0}
|
||||
#projectTree .item-type-tasks .tree-item-wrapper:hover {background-color: #fff}
|
||||
|
||||
.tree-view-btn {min-width: 36px;}
|
||||
.main > .panel > .panel-heading > .panel-actions {margin-top: -8px; margin-right: -12px;}
|
||||
|
||||
@@ -249,3 +249,10 @@ $lang->project->featurebar['task']['group'] = $lang->project->groups[''];
|
||||
$lang->project->featurebar['grouptask'] = $lang->project->featurebar['task'];
|
||||
$lang->project->featurebar['kanban'] = $lang->project->featurebar['task'];
|
||||
$lang->project->featurebar['burn'] = $lang->project->featurebar['task'];
|
||||
|
||||
$lang->project->treeLevel = array();
|
||||
$lang->project->treeLevel['product'] = array('icon' => 'icon-cube', 'text' => 'Products view');
|
||||
$lang->project->treeLevel['module'] = array('icon' => 'icon-bookmark-empty', 'text' => 'Modules view');
|
||||
$lang->project->treeLevel['story'] = array('icon' => 'icon-lightbulb', 'text' => 'Stories view');
|
||||
$lang->project->treeLevel['task'] = array('icon' => 'icon-tasks', 'text' => 'Tasks view');
|
||||
$lang->project->treeLevel['custom'] = array('icon' => 'icon-align-left', 'text' => 'Custom view');
|
||||
|
||||
@@ -260,3 +260,10 @@ $lang->project->featurebar['task']['group'] = $lang->project->groups[''];
|
||||
$lang->project->featurebar['grouptask'] = $lang->project->featurebar['task'];
|
||||
$lang->project->featurebar['kanban'] = $lang->project->featurebar['task'];
|
||||
$lang->project->featurebar['burn'] = $lang->project->featurebar['task'];
|
||||
|
||||
$lang->project->treeLevel = array();
|
||||
$lang->project->treeLevel['product'] = array('icon' => 'icon-cube', 'text' => '产品视图');
|
||||
$lang->project->treeLevel['module'] = array('icon' => 'icon-bookmark-empty', 'text' => '模块视图');
|
||||
$lang->project->treeLevel['story'] = array('icon' => 'icon-lightbulb', 'text' => '需求视图');
|
||||
$lang->project->treeLevel['task'] = array('icon' => 'icon-tasks', 'text' => '任务视图');
|
||||
$lang->project->treeLevel['custom'] = array('icon' => 'icon-align-left', 'text' => '自定义');
|
||||
|
||||
+34
-14
@@ -1973,13 +1973,14 @@ class projectModel extends model
|
||||
foreach ($stories as $story)
|
||||
{
|
||||
$storyItem = new stdclass();
|
||||
$storyItem->type = 'story';
|
||||
$storyItem->id = 'story' . $story->id;
|
||||
$storyItem->title = $story->title;
|
||||
$storyItem->color = $story->color;
|
||||
$storyItem->pri = $story->pri;
|
||||
$storyItem->storyId = $story->id;
|
||||
$storyItem->url = helper::createLink('story', 'view', "storyID=$story->id&version=$story->version&from=project¶m=$projectID");
|
||||
$storyItem->type = 'story';
|
||||
$storyItem->id = 'story' . $story->id;
|
||||
$storyItem->title = $story->title;
|
||||
$storyItem->color = $story->color;
|
||||
$storyItem->pri = $story->pri;
|
||||
$storyItem->storyId = $story->id;
|
||||
$storyItem->url = helper::createLink('story', 'view', "storyID=$story->id&version=$story->version&from=project¶m=$projectID");
|
||||
$storyItem->taskCreateUrl = helper::createLink('task', 'batchCreate', "projectID={$projectID}&story={$story->id}");
|
||||
|
||||
$storyTasks = $this->task->getStoryTasks($story->id, $projectID);
|
||||
if(!empty($storyTasks))
|
||||
@@ -1988,16 +1989,35 @@ class projectModel extends model
|
||||
foreach ($storyTasks as $task)
|
||||
{
|
||||
$taskItem = new stdclass();
|
||||
$taskItem->type = 'task';
|
||||
$taskItem->id = $task->id;
|
||||
$taskItem->title = $task->name;
|
||||
$taskItem->color = $task->color;
|
||||
$taskItem->pri = $task->pri;
|
||||
$taskItem->url = helper::createLink('task', 'view', "task=$task->id");
|
||||
$taskItem->type = 'task';
|
||||
$taskItem->id = $task->id;
|
||||
$taskItem->title = $task->name;
|
||||
$taskItem->color = $task->color;
|
||||
$taskItem->pri = $task->pri;
|
||||
$taskItem->status = $task->status;
|
||||
$taskItem->url = helper::createLink('task', 'view', "task=$task->id");
|
||||
$taskItem->storyChanged = $task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion;
|
||||
|
||||
$buttons = '';
|
||||
$buttons .= common::buildIconButton('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $task, 'list', '', '', 'iframe', true);
|
||||
$buttons .= common::buildIconButton('task', 'start', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
|
||||
|
||||
$buttons .= common::buildIconButton('task', 'recordEstimate', "taskID=$task->id", $task, 'list', 'time', '', 'iframe', true);
|
||||
if($browseType == 'needconfirm')
|
||||
{
|
||||
$lang->task->confirmStoryChange = $lang->confirm;
|
||||
$buttons .= common::buildIconButton('task', 'confirmStoryChange', "taskid=$task->id", '', 'list', '', 'hiddenwin');
|
||||
}
|
||||
$buttons .= common::buildIconButton('task', 'finish', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
|
||||
$buttons .= common::buildIconButton('task', 'close', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
|
||||
$buttons .= common::buildIconButton('task', 'edit', "taskID=$task->id", '', 'list');
|
||||
|
||||
$taskItem->buttons = $buttons;
|
||||
$taskItems[] = $taskItem;
|
||||
}
|
||||
|
||||
$storyItem->children = $taskItems;
|
||||
$storyItem->children = array();
|
||||
$storyItem->children[] = array('id' => 'tasks' . $story->id, 'tasks' => $taskItems, 'type' => 'tasks', 'actions' => false);
|
||||
}
|
||||
|
||||
$node->children[] = $storyItem;
|
||||
|
||||
@@ -98,9 +98,9 @@
|
||||
$lang->task->confirmStoryChange = $lang->confirm;
|
||||
common::printIcon('task', 'confirmStoryChange', "taskid=$task->id", '', 'list', '', 'hiddenwin');
|
||||
}
|
||||
common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
|
||||
common::printIcon('task', 'close', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
|
||||
common::printIcon('task', 'edit',"taskID=$task->id", '', 'list');
|
||||
common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
|
||||
common::printIcon('task', 'close', "taskID=$task->id", $task, 'list', '', '', 'iframe', true);
|
||||
common::printIcon('task', 'edit', "taskID=$task->id", '', 'list');
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
$hasKanbanPriv = common::hasPriv('project', 'kanban');
|
||||
$hasBurnPriv = common::hasPriv('project', 'burn');
|
||||
$hasGroupTaskPriv = common::hasPriv('project', 'groupTask');
|
||||
$hasTreePriv = common::hasPriv('project', 'tree');
|
||||
?>
|
||||
<?php foreach($app->customMenu['featurebar'] as $type => $featurebar):?>
|
||||
<?php
|
||||
@@ -27,6 +28,8 @@
|
||||
if($hasBrowsePriv and ($type == 'unclosed' or $type == 'all' or $type == 'assignedtome')) echo "<li id='{$type}Tab'>" . html::a(inlink('task', "project=$projectID&type=$type"), $featurebar['link']) . '</li>' ;
|
||||
if($hasKanbanPriv and $type == 'kanban') echo "<li id='kanbanTab'>" . html::a(inlink('kanban', "projectID=$projectID"), $featurebar['link']) . '</li>';
|
||||
if($hasBurnPriv and $type == 'burn' and ($project->type == 'sprint' or $project->type == 'waterfall')) echo "<li id='burnTab'>" . html::a(inlink('burn', "project=$projectID"), $featurebar['link']) . '</li>' ;
|
||||
if($hasTreePriv and $type == 'tree') echo "<li id='treeTab'>"; common::printLink('project', 'tree', "projectID=$projectID", $lang->project->tree, '', '', false); echo '</li>';
|
||||
|
||||
if($hasBrowsePriv and $type == 'status')
|
||||
{
|
||||
echo "<li id='statusTab' class='dropdown'>";
|
||||
|
||||
@@ -20,7 +20,14 @@ js::set('productID', $productID);
|
||||
<div class='main'>
|
||||
<div class='panel'>
|
||||
<div class='panel-heading'>
|
||||
<i class="icon icon-folder-close-alt"></i> <strong><?php echo $project->name ?></strong>
|
||||
<i class='icon icon-folder-close-alt'></i> <strong><?php echo $project->name ?></strong>
|
||||
<div class='panel-actions pull-right'>
|
||||
<div class='btn-group'>
|
||||
<?php foreach ($lang->project->treeLevel as $name => $btnLevel):?>
|
||||
<button type='button' class='btn btn-sm tree-view-btn' data-type='<?php echo $name ?>' data-toggle='tooltip' title='<?php echo $btnLevel['text'] ?>'><i class='icon <?php echo $btnLevel['icon'] ?>'></i></button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-body no-padding'>
|
||||
<ul id='projectTree'></ul>
|
||||
@@ -29,19 +36,21 @@ js::set('productID', $productID);
|
||||
</div>
|
||||
|
||||
<?php js::set('replaceID', 'taskList')?>
|
||||
<script
|
||||
var projectID = <?php echo $projectID?>;>
|
||||
<script>
|
||||
var projectID = <?php echo $projectID?>;
|
||||
$('#project<?php echo $projectID;?>').addClass('active')
|
||||
$('#treeTab').addClass('active');
|
||||
|
||||
$(function()
|
||||
{
|
||||
var data = $.parseJSON('<?php echo json_encode($tree);?>');
|
||||
console.log('DATA', data);
|
||||
var viewLevel = '<?php echo $level ?>' || 'custom';
|
||||
var data = $.parseJSON('<?php echo json_encode($tree, JSON_HEX_QUOT | JSON_HEX_APOS);?>');
|
||||
var $tree = $('#projectTree');
|
||||
var statusMap = $.parseJSON('<?php echo json_encode($lang->task->statusList);?>');
|
||||
var selectCustomLevel = function() {$('.tree-view-btn.active').removeClass('active').filter('[data-type="custom"]').addClass('active');};
|
||||
$tree.tree(
|
||||
{
|
||||
initialState: 'preserve',
|
||||
initialState: !viewLevel || viewLevel === 'custom' ? 'preserve' : 'collapse',
|
||||
data: data,
|
||||
itemWrapper: true,
|
||||
actions:
|
||||
@@ -50,32 +59,81 @@ $(function()
|
||||
{
|
||||
title: '<?php echo $lang->project->batchWBS ?>',
|
||||
template: '<a data-toggle="tooltip" href="javascript:;"><i class="icon icon-sitemap"></i>',
|
||||
templateInList: '<a href="javascript:;"><i class="icon icon-sitemap"></i> <?php echo $lang->project->batchWBS ?></a>'
|
||||
templateInList: '<a href="javascript:;"><i class="icon icon-sitemap"></i> <?php echo $lang->project->batchWBS ?></a>',
|
||||
linkTemplate: '<?php echo helper::createLink('tree', 'edit', "moduleID={0}&type=task"); ?>'
|
||||
},
|
||||
},
|
||||
action: function(event)
|
||||
{
|
||||
var action = event.action, $target = $(event.target), item = event.item;
|
||||
if(action.type === 'add')
|
||||
{
|
||||
window.open(item.taskCreateUrl);
|
||||
}
|
||||
},
|
||||
itemCreator: function($li, item)
|
||||
{
|
||||
$li.closest('li').addClass('item-type-' + item.type);
|
||||
if(item.type === 'product')
|
||||
{
|
||||
$li.append($('<span class="tree-toggle"><i class="icon icon-cube text-muted"></i> ' + item.title + '</span>'));
|
||||
$li.append($('<span><i class="icon icon-cube text-muted"></i> ' + item.title + '</span>')).addClass('tree-toggle');
|
||||
}
|
||||
else if(item.type === 'story')
|
||||
{
|
||||
$li.append('<span class="tree-toggle"><i class="icon icon-lightbulb text-muted"></i> </span>').append($('<a>').attr({href: item.url}).text('#' + item.storyId + ' ' + item.title).css('color', item.color));
|
||||
$li.append('<span><i class="icon icon-lightbulb text-muted"></i> </span>').append($('<a>').attr({href: item.url}).text('#' + item.storyId + ' ' + item.title).css('color', item.color));
|
||||
}
|
||||
else if(item.type === 'task')
|
||||
{
|
||||
$li.append('<span class="pri' + item.pri + '">' + item.pri + '</span> ').append($('<a>').attr({href: item.url}).text('#' + item.id + ' ' + item.title).css('color', item.color));
|
||||
}
|
||||
else if(item.type === 'tasks')
|
||||
{
|
||||
if(item.tasks && item.tasks.length)
|
||||
{
|
||||
var $table = $('<table class="table table-fixed table-bordered table-condensed table-hover table-striped"><tbody></tbody></table>');
|
||||
var $tbody = $table.find('tbody');
|
||||
$.each(item.tasks, function(idx, task)
|
||||
{
|
||||
var $tr = $('<tr class="text-center"/>');
|
||||
$tr.append($('<td width="30"/>').append('<span class="pri' + task.pri + '">' + task.pri + '</span>'));
|
||||
$tr.append($('<td/>').addClass('text-left').append($('<a>').attr({href: task.url}).text('#' + task.id + ' ' + task.title).css('color', task.color)));
|
||||
$tr.append($('<td width="70"/>').addClass(task.storyChanged ? 'warning' : task.status).text(statusMap[task.status]));
|
||||
$tr.append($('<td width="70"/>').addClass(task.storyChanged ? 'warning' : task.status).text(statusMap[task.status]));
|
||||
$tr.append($('<td width="130"/>').html(task.buttons));
|
||||
$tbody.append($tr);
|
||||
});
|
||||
$li.append($table);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$li.append($('<span class="tree-toggle"><i class="icon icon-bookmark-empty text-muted"></i> ' + (item.title || item.name) + '</span>'));
|
||||
$li.addClass('tree-toggle').append($('<span class="tree-toggle"><i class="icon icon-bookmark-empty text-muted"></i> ' + (item.title || item.name) + '</span>'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$tree.find('[data-toggle="tooltip"]').tooltip();
|
||||
$('[data-toggle="tooltip"]').tooltip({container: 'body'});
|
||||
var $currentLevelBtn = $('.tree-view-btn[data-type="' + viewLevel + '"]').addClass('active');
|
||||
if(!$currentLevelBtn.length) selectCustomLevel();
|
||||
|
||||
var tree = $tree.data('zui.tree');
|
||||
$(document).on('click', '.tree-view-btn', function()
|
||||
{
|
||||
$('.tree-view-btn.active').removeClass('active');
|
||||
var level = $(this).addClass('active').data('type');
|
||||
if(level === 'task') tree.expand();
|
||||
if(level === 'product') tree.collapse();
|
||||
else if(level === 'module')
|
||||
{
|
||||
tree.collapse();
|
||||
tree.show($('.item-type-product'));
|
||||
}
|
||||
else if(level === 'story')
|
||||
{
|
||||
tree.collapse();
|
||||
tree.show($('.item-type-module'));
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
Reference in New Issue
Block a user