Merge branch 'master' of https://github.com/easysoft/zentaopms
This commit is contained in:
+1
-1
@@ -58,7 +58,7 @@ CREATE TABLE IF NOT EXISTS `zt_log` (
|
||||
`url` varchar(255) NOT NULL,
|
||||
`contentType` varchar(40) NOT NULL,
|
||||
`data` text NOT NULL,
|
||||
`status` smallint(5) NOT NULL,
|
||||
`result` text NOT NULL,
|
||||
PRIMARY KEY `id` (`id`),
|
||||
KEY `objectType` (`objectType`),
|
||||
KEY `obejctID` (`objectID`)
|
||||
|
||||
@@ -63,7 +63,7 @@ $lang->action->objectTypes['bug'] = 'Bug';
|
||||
$lang->action->objectTypes['case'] = 'Case';
|
||||
$lang->action->objectTypes['caseresult'] = 'Case Result';
|
||||
$lang->action->objectTypes['stepresult'] = 'Case Steps';
|
||||
$lang->action->objectTypes['testtask'] = 'Test Task';
|
||||
$lang->action->objectTypes['testtask'] = 'Test Build';
|
||||
$lang->action->objectTypes['user'] = 'User';
|
||||
$lang->action->objectTypes['doc'] = 'Document';
|
||||
$lang->action->objectTypes['doclib'] = 'Doc Lib';
|
||||
|
||||
@@ -63,7 +63,7 @@ $lang->action->objectTypes['bug'] = 'Bug';
|
||||
$lang->action->objectTypes['case'] = '用例';
|
||||
$lang->action->objectTypes['caseresult'] = '用例结果';
|
||||
$lang->action->objectTypes['stepresult'] = '用例步骤';
|
||||
$lang->action->objectTypes['testtask'] = '测试任务';
|
||||
$lang->action->objectTypes['testtask'] = '测试版本';
|
||||
$lang->action->objectTypes['user'] = '用户';
|
||||
$lang->action->objectTypes['doc'] = '文档';
|
||||
$lang->action->objectTypes['doclib'] = '文档库';
|
||||
|
||||
@@ -218,7 +218,7 @@ $lang->project->menu = new stdclass();
|
||||
|
||||
$lang->project->menu->list = array('link' => '%s', 'fixed' => true);
|
||||
$lang->project->menu->task = array('link' => 'Task|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'grouptask,importtask,burn,importbug,kanban,printkanban,tree');
|
||||
$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory');
|
||||
$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
|
||||
$lang->project->menu->bug = 'Bug|project|bug|projectID=%s';
|
||||
$lang->project->menu->dynamic = 'Dynamic|project|dynamic|projectID=%s';
|
||||
$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build');
|
||||
|
||||
@@ -218,7 +218,7 @@ $lang->project->menu = new stdclass();
|
||||
|
||||
$lang->project->menu->list = array('link' => '%s', 'fixed' => true);
|
||||
$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task,tree', 'alias' => 'grouptask,importtask,burn,importbug,kanban,printkanban,tree');
|
||||
$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory');
|
||||
$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory,storykanban');
|
||||
$lang->project->menu->bug = 'Bug|project|bug|projectID=%s';
|
||||
$lang->project->menu->dynamic = '动态|project|dynamic|projectID=%s';
|
||||
$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build');
|
||||
|
||||
@@ -1162,6 +1162,8 @@ class commonModel extends model
|
||||
global $app;
|
||||
|
||||
if(!empty($app->user->admin)) return true;
|
||||
if($module = 'todo' and ($method == 'create' or $method == 'batchcreate')) return true;
|
||||
if($module = 'effort' and ($method == 'createforobject' or $method == 'batchcreate')) return true;
|
||||
|
||||
// limited project
|
||||
$limitedProject = false;
|
||||
|
||||
@@ -23,6 +23,18 @@ class entryModel extends model
|
||||
return $this->dao->select('*')->from(TABLE_ENTRY)->where('id')->eq($entryID)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an entry by code.
|
||||
*
|
||||
* @param string $code
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getByCode($code)
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_ENTRY)->where('deleted')->eq('0')->andWhere('code')->eq($code)->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entry list.
|
||||
*
|
||||
@@ -93,4 +105,16 @@ class entryModel extends model
|
||||
|
||||
return common::createChanges($oldEntry, $entry);
|
||||
}
|
||||
|
||||
public function saveLog($entryID, $url)
|
||||
{
|
||||
$log = new stdclass();
|
||||
$log->objectType = 'entry';
|
||||
$log->objectID = $entryID;
|
||||
$log->url = $url;
|
||||
$log->date = helper::now();
|
||||
|
||||
$this->dao->insert(TABLE_LOG)->data($log)->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +55,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->entry->apiIndex;?></th>
|
||||
<td><?php echo common::getSysURL() . DS . "api.php?{$config->moduleVar}=moduleName&{$config->methodVar}=methodName&<span>params=params</span>";?></td>
|
||||
<td></td>
|
||||
<td colspan='2'><?php echo common::getSysURL() . DS . "api.php?{$config->moduleVar}=moduleName&{$config->methodVar}=methodName&<span>params=params</span>&code=code&token=token";?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
|
||||
@@ -55,8 +55,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->entry->apiIndex;?></th>
|
||||
<td><?php echo common::getSysURL() . DS . "api.php?{$config->moduleVar}=moduleName&{$config->methodVar}=methodName&<span>params=params</span>";?></td>
|
||||
<td></td>
|
||||
<td colspan='2'><?php echo common::getSysURL() . DS . "api.php?{$config->moduleVar}=moduleName&{$config->methodVar}=methodName&<span>params=params</span>&token=token";?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
|
||||
@@ -25,3 +25,15 @@ function setNoChecked()
|
||||
})
|
||||
$('#noChecked').val(noCheckValue);
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
$("[name^='allchecker']").change(function()
|
||||
{
|
||||
var click = $(this).attr('onclick');
|
||||
if(click.indexOf('""') >= 0 || click.indexOf('"my"') >= 0)
|
||||
{
|
||||
$('#my-limited').closest('.group-item').find('input').prop("checked", false);
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1425,6 +1425,47 @@ class project extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Story kanban.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function storyKanban($projectID)
|
||||
{
|
||||
/* Save to session. */
|
||||
$uri = $this->app->getURI(true);
|
||||
$this->app->session->set('storyList', $uri);
|
||||
|
||||
/* Compatibility IE8*/
|
||||
if(strpos($this->server->http_user_agent, 'MSIE 8.0') !== false) header("X-UA-Compatible: IE=EmulateIE7");
|
||||
|
||||
$this->project->setMenu($this->projects, $projectID);
|
||||
$project = $this->loadModel('project')->getById($projectID);
|
||||
$stories = $this->loadModel('story')->getProjectStories($projectID);
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story', false);
|
||||
|
||||
/* Get project's product. */
|
||||
$productID = 0;
|
||||
$productPairs = $this->loadModel('product')->getProductsByProject($projectID);
|
||||
if($productPairs) $productID = key($productPairs);
|
||||
|
||||
$this->view->title = $this->lang->project->kanban;
|
||||
$this->view->position[] = html::a($this->createLink('project', 'story', "projectID=$projectID"), $project->name);
|
||||
$this->view->position[] = $this->lang->project->kanban;
|
||||
$this->view->stories = $this->story->getKanbanGroupData($stories);
|
||||
$this->view->realnames = $this->loadModel('user')->getPairs('noletter');
|
||||
$this->view->projectID = $projectID;
|
||||
$this->view->project = $project;
|
||||
$this->view->productID = $productID;
|
||||
|
||||
$kanbanSetting = $this->project->getKanbanSetting($projectID);
|
||||
$this->view->showOption = $kanbanSetting->showOption;
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a project.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#kanbanHeader th{border: 1px solid #ddd; padding:8px;}
|
||||
#kanbanHeader .dropdown {display: inline-block;}
|
||||
#kanbanHeader .dropdown > a {color: #036}
|
||||
#kanbanHeader th{position: relative}
|
||||
#kanbanHeader .actions {position: absolute; right: 0; top: 0; padding: 0px; background: #f1f1f1; border-left: 1px solid #ccc}
|
||||
#kanbanHeader .actions .btn {display: block; border-radius: 0; width: 34px; height: 36px; position: relative; text-align: center; padding: 5px 0; color: #036}
|
||||
#kanbanHeader .actions .btn-text {display: none}
|
||||
|
||||
#kanbanWrapper {table-layout: fixed; border-top: none}
|
||||
#kanbanWrapper > tbody > tr:first-child > td {border-top: none}
|
||||
#kanbanWrapper thead th, #kanbanWrapper thead, #kanbanWrapper thead tr {padding: 0!important; border: none!important; height: 0!important; border-bottom: none!important}
|
||||
#kanbanWrapper tbody td {vertical-align: top; padding: 6px}
|
||||
#kanbanWrapper tbody th {background: #f1f1f1}
|
||||
#kanbanWrapper .board-shadow {height: 0; opacity: 0; transition: opacity 0.2s;}
|
||||
#kanbanWrapper tbody tr.dragging td.col-droppable {background: #fff4e5}
|
||||
#kanbanWrapper tbody tr.dragging td.col-droppable.drop-to {background: #ffeacc}
|
||||
#kanbanWrapper tbody tr.dragging td.col-droppable.drop-to .board-story + .board-shadow {margin-top: 6px;}
|
||||
#kanbanWrapper tbody tr.dragging td.col-droppable.drop-to .board-shadow {height: 28px; background: #999; background: rgba(0,0,0,0.35); opacity: 1;}
|
||||
#kanbanWrapper tbody tr.dragging td.col-droppable.drop-to.drag-from .board-shadow {display: none}
|
||||
#kanbanWrapper .board.drag-from.dragging {opacity: 0.8;}
|
||||
|
||||
.board {background: #333; color: #f1f1f1; color: rgba(255,255,255,0.9); opacity: 1; padding: 3px 6px; transition: all 0.2s; position:relative;}
|
||||
.board + .board {margin-top: 6px;}
|
||||
.board:hover {opacity: 1}
|
||||
.board a {opacity: 0.9; color: inherit}
|
||||
.board a:hover {opacity: 1}
|
||||
.board-title, .board-header, .board-footer {padding: 2px 0}
|
||||
.board-title {padding-right:35px;}
|
||||
.board-actions {position: absolute; right: 3px; top: 3px}
|
||||
.board-actions .btn {color: inherit; margin: 0; min-width: 20px}
|
||||
.board-actions .btn:active, .board-actions .btn:focus, .board-actions .btn:hover {background: #999; color: inherit; background: rgba(255,255,255,.2);}
|
||||
.ie-8 .board-actions .btn {min-width: 10px}
|
||||
.board-actions > .dropdown {display: inline-block; margin-left: -5px;}
|
||||
.board .dropdown-menu {min-width: 80px;}
|
||||
.board .dropdown .caret {border-top-color: #999}
|
||||
.board .dropdown-menu > a {display: block; padding: 3px 15px; color: #333; font-size: 12px}
|
||||
.board .dropdown-menu > a:hover {background: #f1f1f1; color: #1a53ff; text-decoration: none}
|
||||
.board .dropdown-menu > a.disabled, .board .dropdown-menu > a.disabled:hover, .board .dropdown-menu > a.active {color: #aaa; background: none}
|
||||
.board .board-footer {display: none; opacity: 0.6}
|
||||
.board.show-info .board-footer {display: block; margin: 0 -6px -3px -6px; padding: 5px; background: rgba(0,0,0,0.07);}
|
||||
.board-footer .board-id {display: inline-block; border: 1px solid #aaa; font-weight: normal; padding: 0px 4px; text-align: center; min-width: 20px; line-height: 16px; height: 17px; margin-right: 10px; font-size: 12px;}
|
||||
.board-footer .story-pri {margin-right: 10px;}
|
||||
|
||||
.pri-0:before, .pri-3:before {content: "3";}
|
||||
.pri-1:before {content: "1";}
|
||||
.pri-2:before {content: "2";}
|
||||
.pri-4:before {content: "4";}
|
||||
.pri-5:before {content: "5";}
|
||||
.pri-6:before {content: "6";}
|
||||
|
||||
.story-pri {display: inline-block; width: 16px; height: 16px; text-align: center; border-radius: 8px; line-height: 16px; font-size: 12px}
|
||||
.story-pri.pri-0 {background-color:#b56a00;}
|
||||
.story-pri.pri-1 {background-color:#E30413;}
|
||||
.story-pri.pri-2 {background-color:#E84E0E;}
|
||||
.story-pri.pri-3 {background-color:#b56a00;}
|
||||
.story-pri.pri-4 {background-color:#795523;}
|
||||
|
||||
.board-story {color: #dd7503; background-color: #FFF3E0;}
|
||||
.board-story.stage-projected {color:#777;}
|
||||
.board-story.stage-developing {color:#D2322D; background-color: #FFEBEE;}
|
||||
.board-story.stage-developed {color:#229F24; background-color: #E8F5E9;}
|
||||
.board-story.stage-testing {color:#EF6C00; background-color: #FFF3E0;}
|
||||
.board-story.stage-tested {color:#827717; background-color: #F9FBE7}
|
||||
.board-story.stage-released {color:#9C27B0; background-color: #F3E5F5}
|
||||
|
||||
.affix {position:fixed; top:0px; width:95%;z-index:1030;}
|
||||
#kanbanHeader.affix {box-shadow: 0 3px 10px rgba(0,0,0,.1);}
|
||||
#kanbanHeader.affix th {border-bottom: 1px solid #bbb; background: #114f8e; color: #ccc; color: rgba(255,255,255,.8)}
|
||||
#kanbanHeader.affix th {border-color: rgba(255,255,255,.2)}
|
||||
@@ -0,0 +1,130 @@
|
||||
$(function()
|
||||
{
|
||||
var boardID = '';
|
||||
var onlybody = config.requestType == 'GET' ? "&onlybody=yes" : "?onlybody=yes";
|
||||
$(".kanbanFrame").modalTrigger({type: 'iframe', width: '80%', afterShow:function(){ $('#ajaxModal').data('cancel-reload', true)}, afterHidden: function(){refresh()}});
|
||||
|
||||
$.cookie('selfClose', 0, {expires:config.cookieLife, path:config.webRoot});
|
||||
|
||||
var $kanban = $('#kanban');
|
||||
var $kanbanWrapper = $('#kanbanWrapper');
|
||||
|
||||
initBoards();
|
||||
|
||||
var stageMap =
|
||||
{
|
||||
story:
|
||||
{
|
||||
projected : {verified: 'batchChangeStage'},
|
||||
developing : {verified: 'batchChangeStage'},
|
||||
developed : {verified: 'batchChangeStage'},
|
||||
testing : {verified: 'batchChangeStage'},
|
||||
tested : {verified: 'batchChangeStage'},
|
||||
}
|
||||
};
|
||||
|
||||
var lastOperation;
|
||||
|
||||
function dropTo(id, from, to, type)
|
||||
{
|
||||
if(stageMap[type][from] && stageMap[type][from][to])
|
||||
{
|
||||
lastOperation = {id: id, from: from, to: to};
|
||||
$.post(createLink(type, stageMap[type][from][to], 'stage=' + to), {'storyIDList[]':[id]});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function initBoards()
|
||||
{
|
||||
$('.col-droppable').append('<div class="board-shadow"></div>');
|
||||
|
||||
var $boardTasks = $kanban.find('.board-story');
|
||||
$boardTasks.droppable(
|
||||
{
|
||||
target: '.col-droppable',
|
||||
flex: true,
|
||||
before: function(e)
|
||||
{
|
||||
if(e.element.find('.dropdown.open').length) return false;
|
||||
},
|
||||
start: function(e)
|
||||
{
|
||||
e.element.closest('td').addClass('drag-from').closest('tr').addClass('dragging');
|
||||
$kanban.addClass('dragging').find('.board-item-shadow').height(e.element.outerHeight());
|
||||
},
|
||||
drag: function(e)
|
||||
{
|
||||
if(e.isNew)
|
||||
{
|
||||
var $dargShadow = $('.drag-shadow.board-story');
|
||||
for(var stage in stageMap['story'])
|
||||
{
|
||||
$dargShadow.removeClass('board-story-' + stage);
|
||||
}
|
||||
$dargShadow.addClass('board-story-' + e.target.data('id'));
|
||||
}
|
||||
},
|
||||
drop: function(e)
|
||||
{
|
||||
if(e.isNew && e.element.closest('tr').data('id') == e.target.closest('tr').data('id'))
|
||||
{
|
||||
var result = dropTo(e.element.data('id'), e.element.closest('td').data('id'), e.target.data('id'), 'story');
|
||||
if(result !== false)
|
||||
{
|
||||
for(var stage in stageMap['story'])
|
||||
{
|
||||
e.element.removeClass('board-story-' + stage);
|
||||
}
|
||||
e.element.addClass('board-story-' + e.target.data('id')).insertBefore(e.target.find('.board-shadow'));
|
||||
}
|
||||
}
|
||||
},
|
||||
finish: function(e)
|
||||
{
|
||||
$kanban.removeClass('dragging drop-in');
|
||||
$kanbanWrapper.find('tr.dragging').removeClass('dragging').find('.drop-in, .drag-from').removeClass('drop-in drag-from');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refresh()
|
||||
{
|
||||
var selfClose = $.cookie('selfClose');
|
||||
$.cookie('selfClose', 0, {expires:config.cookieLife, path:config.webRoot});
|
||||
if(selfClose == 1)
|
||||
{
|
||||
$('#kanbanWrapper').wrap("<div id='tempDIV'></div>");
|
||||
$('#tempDIV').load(location.href + ' #kanbanWrapper', function()
|
||||
{
|
||||
$('#kanbanWrapper').unwrap();
|
||||
initBoards()
|
||||
$(".kanbanFrame").modalTrigger({type: 'iframe', width: '80%', afterShow:function(){ $('#ajaxModal').data('cancel-reload', true)}, afterHidden: function(){refresh()}});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var fixH = $("#kanbanHeader").offset().top;
|
||||
$(window).scroll(function()
|
||||
{
|
||||
var scroH = $(this).scrollTop();
|
||||
if(scroH>=fixH)
|
||||
{
|
||||
$("#kanbanHeader").addClass('affix');
|
||||
$("#kanbanHeader").width($('#kanbanWrapper').width());
|
||||
}
|
||||
else if(scroH<fixH)
|
||||
{
|
||||
$("#kanbanHeader").removeClass('affix');
|
||||
$("#kanbanHeader").css('width', '100%');
|
||||
}
|
||||
});
|
||||
|
||||
$('#kanban').on('click', '.btn-info-toggle', function()
|
||||
{
|
||||
$btn = $(this);
|
||||
$btn.find('i').toggleClass('icon-angle-down').toggleClass('icon-angle-up');
|
||||
$btn.parents('.board').toggleClass('show-info');
|
||||
});
|
||||
});
|
||||
@@ -20,6 +20,7 @@
|
||||
<div class='actions'>
|
||||
<div class='btn-group'>
|
||||
<?php
|
||||
common::printIcon('project', 'storyKanban', "project=$project->id", '', 'button', 'columns', '', '', '', '', $lang->project->kanban);
|
||||
common::printIcon('story', 'export', "productID=$productID&orderBy=id_desc", '', 'button', '', '', 'export');
|
||||
|
||||
$this->lang->story->create = $this->lang->project->createStory;
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
* The kanban view file of project module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com)
|
||||
* @author Wang Yidong, Zhu Jinyong
|
||||
* @package project
|
||||
* @version $Id: kanban.html.php $
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php js::set('confirmUnlinkStory', $lang->project->confirmUnlinkStory)?>
|
||||
<div id='titlebar'>
|
||||
<div class='heading'><?php echo html::icon($lang->icons['story']);?> <?php echo $lang->project->story;?></div>
|
||||
<div class='actions'>
|
||||
<div class='btn-group'>
|
||||
<?php
|
||||
common::printIcon('project', 'story', "project=$project->id", '', 'button', 'list', '', '', '', '', $lang->project->story);
|
||||
common::printIcon('story', 'export', "productID=$productID&orderBy=id_desc", '', 'button', '', '', 'export');
|
||||
|
||||
$this->lang->story->create = $this->lang->project->createStory;
|
||||
if($productID and !$this->loadModel('story')->checkForceReview()) common::printIcon('story', 'create', "productID=$productID&branch=&moduleID=0&story=0&project=$project->id");
|
||||
|
||||
if(commonModel::isTutorialMode())
|
||||
{
|
||||
$wizardParams = helper::safe64Encode("project=$project->id");
|
||||
echo html::a($this->createLink('tutorial', 'wizard', "module=project&method=linkStory¶ms=$wizardParams"), "<i class='icon-link'></i> {$lang->project->linkStory}",'', "class='btn link-story-btn'");
|
||||
}
|
||||
else
|
||||
{
|
||||
common::printIcon('project', 'linkStory', "project=$project->id", '', 'button', 'link', '', 'link-story-btn');
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div id='querybox' class='show'></div>
|
||||
</div>
|
||||
<?php
|
||||
$cols = array('projected', 'developing', 'developed', 'testing', 'tested', 'verified', 'released');
|
||||
$account = $this->app->user->account
|
||||
?>
|
||||
<div id='kanban'>
|
||||
<table class='boards-layout table' id='kanbanHeader'>
|
||||
<thead>
|
||||
<tr>
|
||||
<?php $endCol = array_pop($cols);?>
|
||||
<?php foreach ($cols as $col):?>
|
||||
<th class='col-<?php echo $col?>'><?php echo $lang->story->stageList[$col];?></th>
|
||||
<?php endforeach;?>
|
||||
<th class='col-<?php echo $endCol?>'><?php echo $lang->story->stageList[$endCol];?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<?php $cols[] = $endCol;?>
|
||||
<table class='boards-layout table active-disabled table-bordered' id='kanbanWrapper'>
|
||||
<thead>
|
||||
<tr>
|
||||
<?php foreach($cols as $col):?><th class='col-<?php echo $col?>'></th><?php endforeach;?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<?php foreach($cols as $col):?>
|
||||
<td class='col-droppable col-<?php echo $col?>' data-id='<?php echo $col?>'>
|
||||
<?php if(!empty($stories[$col])):?>
|
||||
<?php foreach($stories[$col] as $story):?>
|
||||
<div class='board board-story board-story-<?php echo $col ?>;?>' data-id='<?php echo $story->id?>' id='task-<?php echo $story->id?>'>
|
||||
<div class='board-title'>
|
||||
<?php echo html::a($this->createLink('story', 'view', "story=$story->id", '', true), $story->title, '', 'class="kanbanFrame" title="' . $story->title . '"');?>
|
||||
<div class='board-actions'>
|
||||
<button type='button' class='btn btn-mini btn-link btn-info-toggle'><i class='icon-angle-down'></i></button>
|
||||
<div class='dropdown'>
|
||||
<button type='button' class='btn btn-mini btn-link dropdown-toggle' data-toggle='dropdown'>
|
||||
<span class='icon-ellipsis-v'></span>
|
||||
</button>
|
||||
<div class='dropdown-menu' style='left:-20px'>
|
||||
<?php echo (common::hasPriv('project', 'unlinkStory')) ? html::a($this->createLink('project', 'unlinkStory', "story=$story->id"), $lang->project->unlinkStory, 'hiddenwin') : '';?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='board-footer clearfix'>
|
||||
<span class='task-id board-id' title='<?php echo $lang->story->id?>'><?php echo $story->id?></span>
|
||||
<span class='task-pri pri-<?php echo $story->pri?>' title='<?php echo $lang->story->pri?>'></span>
|
||||
<div class='pull-right'>
|
||||
<span class='task-left' title='<?php echo $lang->story->status?>'><?php echo zget($this->lang->story->statusList, $story->status, '');?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach?>
|
||||
<?php endif?>
|
||||
</td>
|
||||
<?php endforeach;?>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<script>
|
||||
var projectID = <?php echo $projectID?>;
|
||||
</script>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -126,7 +126,8 @@
|
||||
{
|
||||
if($product->type !== 'normal')
|
||||
{
|
||||
echo html::a($this->createLink('product', 'browse', "productID=$productID&branch=$product->branch"), $product->name . '/' . $branchGroups[$productID][$product->branch]);
|
||||
$branchName = isset($branchGroups[$productID][$product->branch]) ? '/' . $branchGroups[$productID][$product->branch] : ''
|
||||
echo html::a($this->createLink('product', 'browse', "productID=$productID&branch=$product->branch"), $product->name . $branchName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -2174,6 +2174,21 @@ class storyModel extends model
|
||||
->groupBy('version')->orderBy('value')->fetchAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get kanban group data.
|
||||
*
|
||||
* @param array $stories
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getKanbanGroupData($stories)
|
||||
{
|
||||
$storyGroup = array();
|
||||
foreach($stories as $story) $storyGroup[$story->stage][$story->id] = $story;
|
||||
|
||||
return $storyGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the action clickable.
|
||||
*
|
||||
|
||||
@@ -13,7 +13,7 @@ $config->webhook->objectTypes['story'] = array('opened', 'edited', 'commen
|
||||
$config->webhook->objectTypes['productplan'] = array('opened', 'edited');
|
||||
//$config->webhook->objectTypes['release'] = array('opened', 'edited', 'changestatus');
|
||||
$config->webhook->objectTypes['project'] = array('opened', 'edited', 'started', 'delayed', 'suspended', 'closed', 'activated', 'undeleted');
|
||||
$config->webhook->objectTypes['task'] = array('opened', 'edited', 'commented', 'assigned', 'confirmed', 'started', 'finished', 'editestimate', 'paused', 'canceled', 'restarted', 'closed', 'activated');
|
||||
$config->webhook->objectTypes['task'] = array('opened', 'edited', 'commented', 'assigned', 'confirmed', 'started', 'finished', 'paused', 'canceled', 'restarted', 'closed', 'activated');
|
||||
//$config->webhook->objectTypes['build'] = array('opened', 'edited');
|
||||
$config->webhook->objectTypes['bug'] = array('opened', 'edited', 'commented', 'assigned', 'confirmed', 'bugconfirmed', 'resolved', 'closed', 'activated');
|
||||
$config->webhook->objectTypes['case'] = array('opened', 'edited', 'commented', 'reviewed', 'confirmed');
|
||||
|
||||
@@ -5,7 +5,7 @@ $lang->webhook->api = '接口';
|
||||
$lang->webhook->entry = '应用';
|
||||
$lang->webhook->dingding = '钉钉';
|
||||
$lang->webhook->log = '日志';
|
||||
$lang->webhook->assigend = '指派给';
|
||||
$lang->webhook->assigned = '指派给';
|
||||
|
||||
$lang->webhook->browse = '浏览钩子';
|
||||
$lang->webhook->create = '添加钩子';
|
||||
|
||||
@@ -69,7 +69,7 @@ class webhookModel extends model
|
||||
|
||||
$this->loadModel('action');
|
||||
$actions = $this->dao->select('*')->from(TABLE_ACTION)->where('id')->in($actions)->fetchAll('id');
|
||||
|
||||
$users = $this->loadModel('user')->getPairs('noletter');
|
||||
foreach($logs as $log)
|
||||
{
|
||||
if(!isset($actions[$log->action]))
|
||||
@@ -100,7 +100,7 @@ class webhookModel extends model
|
||||
*/
|
||||
public function getDataList()
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_WEBHOOKDATA)->where('status')->eq('wait')->orderBy('id')->fetchAll('id');
|
||||
return $this->dao->select('*')->from(TABLE_WEBHOOKDATAS)->where('status')->eq('wait')->orderBy('id')->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,6 +317,7 @@ class webhookModel extends model
|
||||
$oldOnlyBody = 'yes';
|
||||
unset($_GET['onlybody']);
|
||||
}
|
||||
if($objectType == 'case') $objectType = 'testcase';
|
||||
$viewLink = helper::createLink($objectType, 'view', "id=$objectID");
|
||||
if($oldOnlyBody) $_GET['onlybody'] = $oldOnlyBody;
|
||||
|
||||
@@ -401,7 +402,7 @@ class webhookModel extends model
|
||||
$webhookData->createdBy = $this->app->user->account;
|
||||
$webhookData->createdDate = helper::now();
|
||||
|
||||
$this->dao->insert(TABLE_WEBHOOKDATA)->data($webhookData)->exec();
|
||||
$this->dao->insert(TABLE_WEBHOOKDATAS)->data($webhookData)->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user