Merge branch 'kanban' into 'sprint/177_tianshujie_45815'

# Conflicts:
#   module/kanban/lang/en.php
#   module/kanban/lang/zh-cn.php
This commit is contained in:
孙广明
2021-12-10 02:18:54 +00:00
15 changed files with 499 additions and 95 deletions
+1
View File
@@ -15,6 +15,7 @@ include 'chosen.html.php';
<?php echo isset($lang->switcherMenu) ? $lang->switcherMenu : '';?>
</div>
<nav id='navbar'><?php $activeMenu = commonModel::printMainMenu();?></nav>
<div id='headerActions'><?php if(isset($lang->headerActions)) echo $lang->headerActions;?></div>
<div id='toolbar'>
<div id='userMenu'>
<ul id="userNav" class="nav nav-default">
+3 -1
View File
@@ -4,6 +4,7 @@ $config->kanban = new stdclass();
$config->kanban->require = new stdclass();
$config->kanban->require->createregion = 'name';
$config->kanban->require->createlane = 'name';
$config->kanban->setwip = new stdclass();
$config->kanban->setlane = new stdclass();
@@ -83,4 +84,5 @@ $config->kanban->taskColumnStatusList['pause'] = 'pause';
$config->kanban->taskColumnStatusList['canceled'] = 'cancel';
$config->kanban->taskColumnStatusList['closed'] = 'closed';
$config->kanban->laneColorList = array('#7ec5ff', '#333', '#2b529c', '#e48600', '#d2323d', '#229f24', '#777', '#d2691e', '#008b8b', '#2e8b57', '#4169e1', '#4b0082', '#fa8072', '#ba55d3', '#2e8b57', '#6b8e23');
$config->kanban->laneColorList = array('#7ec5ff', '#333', '#2b529c', '#e48600', '#d2323d', '#229f24', '#777', '#d2691e', '#008b8b', '#2e8b57', '#4169e1', '#4b0082', '#fa8072', '#ba55d3', '#2e8b57', '#6b8e23');
$config->kanban->columnColorList = array('#333', '#2b519c', '#e48610', '#d2313d', '#2a9f23', '#777', '#d2691e', '#2e8b8b', '#2f8b58', '#4168e0', '#4b0082', '#f58072', '#ba55d3', '#6a8e22');
+60 -5
View File
@@ -70,13 +70,14 @@ class kanban extends control
*/
public function editSpace($spaceID)
{
$this->loadModel('action');
if(!empty($_POST))
{
$changes = $this->kanban->updateSpace($spaceID);
if(dao::isError()) die(js::error(dao::getError()));
$actionID = $this->loadModel('action')->create('kanbanSpace', $spaceID, 'edited');
$actionID = $this->action->create('kanbanSpace', $spaceID, 'edited');
$this->action->logHistory($actionID, $changes);
die(js::reload('parent.parent'));
@@ -110,7 +111,36 @@ class kanban extends control
$this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed');
$this->view->spaceID = $spaceID;
$this->view->spacePairs = array('' => '') + $this->kanban->getSpacePairs();
$this->display();
}
/**
* Edit a kanban.
*
* @param int $kanbanID
* @access public
* @return void
*/
public function edit($kanbanID = 0)
{
$this->loadModel('action');
if(!empty($_POST))
{
$changes = $this->kanban->update($kanbanID);
if(dao::isError()) die(js::error(dao::getError()));
$actionID = $this->action->create('kanban', $kanbanID, 'edited');
$this->action->logHistory($actionID, $changes);
die(js::reload('parent.parent'));
}
$this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed');
$this->view->spacePairs = array('' => '') + $this->kanban->getSpacePairs();
$this->view->kanban = $this->kanban->getByID($kanbanID);
$this->display();
}
@@ -146,21 +176,46 @@ class kanban extends control
/**
* View a kanban.
*
* @param int $kanbanID
*
* @param int $kanbanID
* @access public
* @return void
*/
public function view($kanbanID)
{
$kanban = $this->kanban->getByID($kanbanID);
$this->kanban->setHeaderActions($kanban);
$this->view->title = $this->lang->kanban->view;
$this->view->regions = $this->kanban->getKanbanData($kanbanID);
$this->view->kanban = $kanban;
$this->display();
}
/**
* Create a lane for a kanban.
*
* @param int $kanbanID
* @param int $regionID
* @access public
* @return void
*/
public function createLane($kanbanID, $regionID)
{
if(!empty($_POST))
{
$laneID = $this->kanban->createLane($kanbanID, $regionID, $lane = null);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'callback' => 'closeModalAndUpdateKanban', 'callback_params' => $regionID));
}
$this->view->lanes = $this->kanban->getLanePairsByRegion($regionID);
$this->display();
}
/**
* Set WIP.
*
+4
View File
@@ -0,0 +1,4 @@
.color-picker-item {width: 20px; height: 20px; margin-right: 10px; border-radius: 50% 50%; float: left; cursor: pointer; text-align: center; line-height: 20px;}
.color-picker-item > .icon {color: #fff; display: none}
.checked > .icon {display: inline-block;}
+36
View File
@@ -1,3 +1,8 @@
$(function()
{
if(typeof acl != 'undefined' && acl != null) setWhite(acl);
});
/**
* Set white list.
*
@@ -28,3 +33,34 @@ function setMailto(field, value)
$('#team').chosen();
})
}
/**
* Initialize custom color selector.
*
* @access public
* @return void
*/
function initColorPicker()
{
var colorList = ['#272E33', '#3DC6FD', '#2B529C', '#E48600', '#D2323D', '#229F24', '#777777', '#D2691E', '#008B8B', '#2E8B57', '#4169E1', '#4B0082', '#FA8072', '#BA55D3', '#6B8E23'];
var selectedColor = $('input[name=color]').val();
if(selectedColor && $.inArray(selectedColor.toUpperCase(), colorList) == -1) colorList.unshift(selectedColor);
colorList.forEach(function(color, index)
{
var itemClass = color.toUpperCase() == $('input[name=color]').val().toUpperCase() ? 'color-picker-item checked' : 'color-picker-item';
var colorItem = "<div class='" + itemClass + "' data-color='" + color + "' style='background: " + color + "'>";
colorItem += "<i class='icon icon-check'></i>";
colorItem += "</div>";
$('#color-picker').append(colorItem);
});
$('.color-picker-item').click(function()
{
var color = $(this).attr('data-color');
$('input[name=color]').val(color);
$(this).addClass('checked');
$(this).siblings().removeClass('checked');
})
}
+10
View File
@@ -0,0 +1,10 @@
$(document).ready(function()
{
initColorPicker();
$('input[name=mode]').change(function()
{
$('#otherLane').parents('tr').toggle($(this).val() == 'sameAsOther');
});
})
+7 -7
View File
@@ -20,7 +20,7 @@ function loadMore(type)
*/
function fullScreen()
{
var element = document.getElementById('mainContent');
var element = document.getElementById('kanban');
var requestMethod = element.requestFullScreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullscreen;
if(requestMethod)
{
@@ -624,15 +624,15 @@ function createColumnMenu(options)
if(!privs.length) return [];
var items = [];
if(privs.includes('setWIP')) items.push({label: kanbanLang.WIP, icon: '', url: createLink('kanban', 'setWIP', 'columnID=' + column.id), attrs: {'data-toggle': 'modal'}});
if(privs.includes('editColumn')) items.push({label: kanbanLang.editColumn, icon: '', url: createLink('kanban', 'editColumn', 'columnID=' + column.id), attrs: {'data-toggle': 'modal'}});
if(privs.includes('setWIP')) items.push({label: kanbanLang.WIP, icon: '', url: createLink('kanban', 'setWIP', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal'}});
if(privs.includes('editColumn')) items.push({label: kanbanLang.editColumn, icon: '', url: createLink('kanban', 'setColumn', 'columnID=' + column.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
if(privs.includes('createColumn'))
{
items.push({label: kanbanLang.createColumnOnLeft, icon: '', url: createLink('kanban', 'createColumn', 'columnID=' + column.id + '&position=left'), attrs: {'data-toggle': 'modal'}});
items.push({label: kanbanLang.createColumnOnRight, icon: '', url: createLink('kanban', 'createColumn', 'columnID=' + column.id + '&position=right'), attrs: {'data-toggle': 'modal'}});
items.push({label: kanbanLang.createColumnOnLeft, icon: '', url: createLink('kanban', 'createColumn', 'columnID=' + column.id + '&position=left'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
items.push({label: kanbanLang.createColumnOnRight, icon: '', 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: '', url: createLink('kanban', 'copyColumn', 'columnID=' + column.id), attrs: {'data-toggle': 'modal'}});
if(privs.includes('splitColumn')) items.push({label: kanbanLang.splitColumn, icon: '', url: createLink('kanban', 'splitColumn', 'columnID=' + column.id), attrs: {'data-toggle': 'modal'}});
if(privs.includes('copyColumn')) items.push({label: kanbanLang.copyColumn, icon: '', url: createLink('kanban', 'copyColumn', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal'}});
if(privs.includes('splitColumn')) items.push({label: kanbanLang.splitColumn, icon: '', url: createLink('kanban', 'splitColumn', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal'}});
if(privs.includes('archiveColumn')) items.push({label: kanbanLang.archiveColumn, icon: '', url: createLink('kanban', 'archiveColumn', 'columnID=' + column.id), className: 'confirmer', attrs: {'data-confirmTitle': kanbancolumnLang.confirmArchive, 'data-confirmDetail': kanbancolumnLang.confirmArchiveDetail, 'data-confirmButton': lang.archive, 'data-confirming': lang.archiving}});
if(privs.includes('deleteColumn')) items.push({label: kanbanLang.deleteColumn, icon: '', url: createLink('kanban', 'deleteColumn', 'columnID=' + column.id), className: 'confirmer', attrs: {'data-confirmTitle': kanbancolumnLang.confirmDelete, 'data-confirmDetail': kanbancolumnLang.confirmDeleteDetail}});
+47 -15
View File
@@ -28,16 +28,24 @@ $lang->kanban->sortCard = 'Sort Card';
$lang->kanban->setting = 'Setting';
/* Fields. */
$lang->kanban->space = 'Space';
$lang->kanban->name = 'Name';
$lang->kanban->owner = 'Owner';
$lang->kanban->team = 'Team';
$lang->kanban->desc = 'Description';
$lang->kanban->acl = 'ACL';
$lang->kanban->closed = 'Closed';
$lang->kanban->space = 'Space';
$lang->kanban->name = 'Name';
$lang->kanban->owner = 'Owner';
$lang->kanban->team = 'Team';
$lang->kanban->desc = 'Description';
$lang->kanban->acl = 'ACL';
$lang->kanban->whitelist = 'White List';
$lang->kanban->status = 'Status';
$lang->kanban->createdBy = 'Created By';
$lang->kanban->createdDate = 'Created Date';
$lang->kanban->lastEditedBy = 'Edited By';
$lang->kanban->lastEditedDate = 'Edited Date';
$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->empty = 'No Kanban';
$lang->kanban->teamSumCount = '%s people in total';
$lang->kanban->aclList['open'] = 'Open (Accessible with space view permissions)';
$lang->kanban->aclList['private'] = 'Private (For the kanban team, whitelist members and space owner only)';
@@ -99,6 +107,9 @@ $lang->kanban->laneGroup = 'Lane Group';
$lang->kanban->cardsSort = 'Cards Sortting';
$lang->kanban->moreAction = 'More Action';
$lang->kanban->noGroup = 'None';
$lang->kanban->limitExceeded = 'Limit Exceeded';
$lang->kanban->fullScreen = 'Full Screen';
$lang->kanban->setting = 'Setting';
$lang->kanban->error = new stdclass();
$lang->kanban->error->mustBeInt = 'The WIPs must be positive integer.';
@@ -146,12 +157,20 @@ $lang->kanban->taskColumn['canceled'] = 'Canceled';
$lang->kanban->taskColumn['closed'] = 'Closed';
$lang->kanbanspace = new stdclass();
$lang->kanbanspace->common = 'Kanban Space';
$lang->kanbanspace->name = 'Name';
$lang->kanbanspace->owner = 'Owner';
$lang->kanbanspace->team = 'Team';
$lang->kanbanspace->desc = 'Description';
$lang->kanbanspace->acl = 'ACL';
$lang->kanbanspace->common = 'Kanban Space';
$lang->kanbanspace->name = 'Name';
$lang->kanbanspace->owner = 'Owner';
$lang->kanbanspace->team = 'Team';
$lang->kanbanspace->desc = 'Description';
$lang->kanbanspace->acl = 'ACL';
$lang->kanbanspace->whitelist = 'White List';
$lang->kanbanspace->status = 'Status';
$lang->kanbanspace->createdBy = 'Created By';
$lang->kanbanspace->createdDate = 'Created Date';
$lang->kanbanspace->lastEditedBy = 'Edited By';
$lang->kanbanspace->lastEditedDate = 'Edited Date';
$lang->kanbanspace->closedBy = 'Closed By';
$lang->kanbanspace->closedDate = 'Closed Date';
$lang->kanbanspace->empty = 'No Space';
@@ -168,9 +187,22 @@ $lang->kanbancolumn->name = $lang->kanban->columnName;
$lang->kanbancolumn->limit = $lang->kanban->WIPCount;
$lang->kanbanlane = new stdclass();
$lang->kanbanlane->name = $lang->kanban->laneName;
$lang->kanbanlane->common = 'Lane';
$lang->kanbanlane->default = 'Default Lane';
$lang->kanbanlane->column = 'Lane Kanban column';
$lang->kanbanlane->otherlane = 'Select the lane that shares the Kanban column';
$lang->kanbanlane->color = 'Lane color';
$lang->kanbanlane->modeList['sameAsOther'] = 'Use the same Kanban column as other lanes';
$lang->kanbanlane->modeList['independent'] = 'Independent Kanban column is adopted';
$lang->kanbanlane->name = $lang->kanban->laneName;
$lang->kanbanlane->common = 'Lane';
$lang->kanbanlane->default = 'Default Lane';
$lang->kanbanregion = new stdclass();
$lang->kanbanregion->name = 'Kanban Region';
$lang->kanbanregion->default = 'Default Region';
$lang->kanbancard = new stdclass();
+42 -19
View File
@@ -28,16 +28,23 @@ $lang->kanban->sortCard = '卡片排序';
$lang->kanban->setting = '设置';
/* Fields. */
$lang->kanban->space = '所属空间';
$lang->kanban->name = '看板名称';
$lang->kanban->owner = '负责人';
$lang->kanban->team = '团队';
$lang->kanban->desc = '看板描述';
$lang->kanban->acl = '访问控制';
$lang->kanban->closed = '已关闭';
$lang->kanban->empty = '暂时没有看板';
$lang->kanban->teamSumCount = '共%s人';
$lang->kanban->space = '所属空间';
$lang->kanban->name = '看板名称';
$lang->kanban->owner = '负责人';
$lang->kanban->team = '团队';
$lang->kanban->desc = '空间描述';
$lang->kanban->acl = '访问控制';
$lang->kanban->whitelist = '白名单';
$lang->kanban->status = '状态';
$lang->kanban->createdBy = '由谁创建';
$lang->kanban->createdDate = '创建日期';
$lang->kanban->lastEditedBy = '最后修改';
$lang->kanban->lastEditedDate = '最后修改日期';
$lang->kanban->closedBy = '由谁关闭';
$lang->kanban->closedDate = '关闭日期';
$lang->kanban->closed = '已关闭';
$lang->kanban->empty = '暂时没有看板';
$lang->kanban->teamSumCount = '共%s人';
$lang->kanban->aclList['open'] = '继承空间访问权限(能访问当前空间,即可访问)';
$lang->kanban->aclList['private'] = '私有(看板团队成员、白名单、空间负责人可访问)';
@@ -100,6 +107,8 @@ $lang->kanban->cardsSort = '卡片排序';
$lang->kanban->moreAction = '更多操作';
$lang->kanban->noGroup = '无';
$lang->kanban->limitExceeded = '超出在制品限制';
$lang->kanban->fullScreen = '全屏';
$lang->kanban->setting = '设置';
$lang->kanban->error = new stdclass();
$lang->kanban->error->mustBeInt = '在制品数量必须是正整数。';
@@ -147,12 +156,20 @@ $lang->kanban->taskColumn['canceled'] = '已取消';
$lang->kanban->taskColumn['closed'] = '已关闭';
$lang->kanbanspace = new stdclass();
$lang->kanbanspace->common = '看板空间';
$lang->kanbanspace->name = '空间名称';
$lang->kanbanspace->owner = '负责人';
$lang->kanbanspace->team = '团队';
$lang->kanbanspace->desc = '空间描述';
$lang->kanbanspace->acl = '访问控制';
$lang->kanbanspace->common = '看板空间';
$lang->kanbanspace->name = '空间名称';
$lang->kanbanspace->owner = '负责人';
$lang->kanbanspace->team = '团队';
$lang->kanbanspace->desc = '空间描述';
$lang->kanbanspace->acl = '访问控制';
$lang->kanbanspace->whitelist = '白名单';
$lang->kanbanspace->status = '状态';
$lang->kanbanspace->createdBy = '由谁创建';
$lang->kanbanspace->createdDate = '创建日期';
$lang->kanbanspace->lastEditedBy = '最后修改';
$lang->kanbanspace->lastEditedDate = '最后修改日期';
$lang->kanbanspace->closedBy = '由谁关闭';
$lang->kanbanspace->closedDate = '关闭日期';
$lang->kanbanspace->empty = '暂时没有空间';
@@ -169,9 +186,15 @@ $lang->kanbancolumn->name = $lang->kanban->columnName;
$lang->kanbancolumn->limit = $lang->kanban->WIPCount;
$lang->kanbanlane = new stdclass();
$lang->kanbanlane->name = $lang->kanban->laneName;
$lang->kanbanlane->common = '泳道';
$lang->kanbanlane->default = '默认泳道';
$lang->kanbanlane->name = $lang->kanban->laneName;
$lang->kanbanlane->common = '泳道';
$lang->kanbanlane->default = '默认泳道';
$lang->kanbanlane->column = '泳道看板列';
$lang->kanbanlane->otherlane = '选择共享看板列的泳道';
$lang->kanbanlane->color = '泳道颜色';
$lang->kanbanlane->modeList['sameAsOther'] = '与其他泳道使用相同看板列';
$lang->kanbanlane->modeList['independent'] = '采用独立的看板列';
$lang->kanbanregion = new stdclass();
$lang->kanbanregion->name = '看板区域';
+172 -47
View File
@@ -15,8 +15,8 @@ class kanbanModel extends model
{
/**
* Init a kanban.
*
* @param int $kanbanID
*
* @param int $kanbanID
* @param string $type default|new
* @access public
* @return void
@@ -41,11 +41,11 @@ class kanbanModel extends model
/**
* Create a kanban group.
*
* @param int $kanbanID
* @param int $regionID
*
* @param int $kanbanID
* @param int $regionID
* @access public
* @return int
* @return int
*/
public function createGroup($kanbanID, $regionID)
{
@@ -73,10 +73,10 @@ class kanbanModel extends model
/**
* Create a default kanban region.
*
* @param object $kanban
*
* @param object $kanban
* @access public
* @return int
* @return int
*/
public function createDefaultRegion($kanban)
{
@@ -92,11 +92,11 @@ class kanbanModel extends model
/**
* Create a new region.
*
* @param object $kanban
* @param object $region
*
* @param object $kanban
* @param object $region
* @access public
* @return int
* @return int
*/
public function createRegion($kanban, $region = null)
{
@@ -104,7 +104,7 @@ class kanbanModel extends model
$order = 1;
if(!$region)
{
{
$maxOrder = $this->dao->select('MAX(`order`) AS maxOrder')->from(TABLE_KANBANORDER)
->where('objectType')->eq('region')
->andWhere('parentID')->eq($kanban->id)
@@ -137,12 +137,12 @@ class kanbanModel extends model
/**
* Create default lane.
*
* @param object $kanban
*
* @param object $kanban
* @param int $regionID
* @param int $groupID
* @access public
* @return int
* @return int
*/
public function createDefaultLane($kanban, $regionID, $groupID)
{
@@ -152,6 +152,7 @@ class kanbanModel extends model
$lane->region = $regionID;
$lane->type = 'common';
$lane->lastEditedTime = helper::now();
$lane->color = '#7ec5ff';
$this->dao->insert(TABLE_KANBANLANE)->data($lane)->exec();
$laneID = $this->dao->lastInsertId();
@@ -162,8 +163,8 @@ class kanbanModel extends model
/**
* Create default kanban columns.
*
* @param object $kanban
*
* @param object $kanban
* @param int $regionID
* @param int $groupID
* @access public
@@ -180,6 +181,7 @@ class kanbanModel extends model
$column->name = $columnName;
$column->type = $index;
$column->limit = -1;
$column->color = '#333';
$this->dao->insert(TABLE_KANBANCOLUMN)->data($column)->exec();
@@ -192,13 +194,13 @@ class kanbanModel extends model
/**
* Save kanban object order.
*
* @param int $parentID
* @param string $parentType
* @param int $objectID
* @param string $objectType
* @param string $account
* @param int $order
*
* @param int $parentID
* @param string $parentType
* @param int $objectID
* @param string $objectType
* @param string $account
* @param int $order
* @access public
* @return void
*/
@@ -217,11 +219,11 @@ class kanbanModel extends model
}
/**
* Get kanban by id.
*
* @param int $kanbanID
* Get kanban by id.
*
* @param int $kanbanID
* @access public
* @return object
* @return object
*/
public function getByID($kanbanID)
{
@@ -230,8 +232,8 @@ class kanbanModel extends model
/**
* Get kanban data.
*
* @param int $kanbanID
*
* @param int $kanbanID
* @access public
* @return void
*/
@@ -281,13 +283,13 @@ class kanbanModel extends model
/**
* Get ordered region pairs.
*
* @param int $kanbanID
*
* @param int $kanbanID
* @access public
* @return array
* @return array
*/
public function getRegionPairs($kanbanID)
{
{
return $this->dao->select('id,name')->from(TABLE_KANBANREGION)
->where('kanban')->eq($kanbanID)
->andWhere('deleted')->eq('0')
@@ -297,10 +299,10 @@ class kanbanModel extends model
/**
* Get kanban group by regions.
*
* @param array $regions
*
* @param array $regions
* @access public
* @return array
* @return array
*/
public function getGroupGroupByRegions($regions)
{
@@ -312,10 +314,10 @@ class kanbanModel extends model
/**
* Get lane group by regions.
*
* @param array $regions
*
* @param array $regions
* @access public
* @return array
* @return array
*/
public function getLaneGroupByRegions($regions)
{
@@ -342,11 +344,11 @@ class kanbanModel extends model
}
/**
* Get column group by regions.
*
* @param array $regions
* Get column group by regions.
*
* @param array $regions
* @access public
* @return array
* @return array
*/
public function getColumnGroupByRegions($regions)
{
@@ -386,7 +388,7 @@ class kanbanModel extends model
$columnData[$group][] = $parentColumn;
foreach($columnGroup[$group] as $column)
{
if($column->parent == $parentColumn->id)
if($column->parent == $parentColumn->id)
{
$parentColumn->asParent = true;
@@ -401,6 +403,34 @@ class kanbanModel extends model
return $columnData;
}
/**
* Set kanban headerActions.
*
* @param object $kanban
* @access public
* @return void
*/
public function setHeaderActions($kanban)
{
$actions = '';
$actions .= "<div class='btn-group'>";
$actions .= "<a href='javascript:fullScreen();' id='fullScreenBtn' class='btn btn-link'><i class='icon icon-fullscreen'></i> {$this->lang->kanban->fullScreen}</a>";
$actions .= "<a data-toggle='dropdown' class='btn btn-link dropdown-toggle' 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')) $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>';
$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'") . '</li>';
if(common::hasPriv('kanban', 'close')) $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', '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) $actions .= "<div class='divider'></div>" . $kanbanActions;
$actions .= "</ul>";
$actions .= "</div>";
$this->lang->headerActions = $actions;
}
/**
* Get Kanban by execution id.
*
@@ -669,6 +699,72 @@ class kanbanModel extends model
}
/**
* Get lane pairs by region id.
*
* @param array $regionID
* @access public
* @return array
*/
public function getLanePairsByRegion($regionID)
{
return $this->dao->select('id, name')->from(TABLE_KANBANLANE)
->where('deleted')->eq('0')
->andWhere('region')->eq($regionID)
->fetchPairs();
}
/**
* Create a lane.
*
* @param int $kanbanID
* @param int $regionID
* @param object $lane
* @access public
* @return int
*/
public function createLane($kanbanID, $regionID, $lane = null)
{
if(empty($lane))
{
$maxOrder = $this->dao->select('MAX(`order`) AS maxOrder')->from(TABLE_KANBANLANE)
->where('region')->eq($regionID)
->fetch('maxOrder');
$lane = fixer::input('post')
->add('region', $regionID)
->add('order', $maxOrder + 1)
->add('lastEditedTime', helper::today())
->add('type', 'common')
->setDefault('color', '#3DC6FD')
->get();
$mode = zget($lane, 'mode', '');
if($mode == 'sameAsOther')
{
$otherLane = zget($lane, 'otherLane', 0);
if($otherLane) $lane->group = $this->dao->select('`group`')->from(TABLE_KANBANLANE)->where('id')->eq($otherLane)->fetch('group');
}
elseif($mode == 'independent')
{
$groupID = $this->createGroup($kanbanID, $regionID);
$this->createDefaultColumns($kanban, $regionID, $groupID);
$lane->group = $groupID;
}
}
$this->dao->insert(TABLE_KANBANLANE)->data($lane, $skip = 'mode,otherLane')
->batchCheck($this->config->kanban->require->createlane, 'notempty')
->autoCheck()
->checkIF(!empty($lane->name), 'name', 'unique', "`type`='common'")
->exec();
if(dao::isError()) return false;
$laneID = $this->dao->lastInsertID();
$this->loadModel('action')->create('kanbanLane', $laneID, 'Created');
return $laneID;
}
* Create a kanban.
*
* @access public
@@ -703,6 +799,35 @@ class kanbanModel extends model
}
}
/**
* Update a kanban.
*
* @param int $kanbanID
* @access public
* @return array
*/
public function update($kanbanID)
{
$kanbanID = (int)$kanbanID;
$account = $this->app->user->account;
$oldKanban = $this->getByID($kanbanID);
$kanban = fixer::input('post')
->setDefault('lastEditedBy', $account)
->setDefault('lastEditedDate', helper::now())
->join('whitelist', ',')
->join('team', ',')
->remove('uid,contactListMenu')
->get();
$this->dao->update(TABLE_KANBAN)->data($kanban)
->autoCheck()
->batchCheck($this->config->kanban->edit->requiredFields, 'notempty')
->where('id')->eq($kanbanID)
->exec();
if(!dao::isError()) return common::createChanges($oldKanban, $kanban);
}
/**
* Close a kanban.
*
+1 -1
View File
@@ -4,7 +4,7 @@
*
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Mengyi Liu <fujia@cnezsoft.com>
* @author Mengyi Liu <liumengyi@easycorp.ltd>
* @package kanban
* @version $Id: close.html.php 935 2021-12-09 10:49:24Z $
* @link https://www.zentao.net
+46
View File
@@ -0,0 +1,46 @@
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2>
<?php echo $lang->kanban->createLane;?>
</h2>
</div>
<form class='load-indicator main-form' method='post' target='hiddenwin'>
<table class='table table-form'>
<tbody>
<tr>
<th class="w-140px"><?php echo $lang->kanbanlane->name;?></th>
<td>
<div class='required required-wrapper'></div>
<?php echo html::input('name', '', "class='form-control'");?>
</td>
</tr>
<tr>
<th><?php echo $lang->kanbanlane->column;?></th>
<td><?php echo html::radio('mode', $lang->kanbanlane->modeList, 'sameAsOther');?></td>
</tr>
<tr>
<th><?php echo $lang->kanbanlane->otherlane;?></th>
<td><?php echo html::select('otherLane', $lanes, '', "class='form-control chosen'");?></td>
</tr>
<tr>
<th><?php echo $lang->kanbanlane->color;?></th>
<td>
<div id='color-picker'></div>
<?php echo html::input('color', '#3DC6FD', "class='hidden'");?>
</td>
</tr>
<tr>
<th></th>
<td class='form-actions'>
<?php echo html::submitButton();?>
<?php echo html::backButton($lang->cancel);?>
</td>
</tr>
</tbody>
</table>
</form>
</div>
<?php include '../../common/view/footer.html.php';?>
+64
View File
@@ -0,0 +1,64 @@
<?php
/**
* The edit file of kanban module of ZenTaoPMS.
*
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Mengyi Liu <liumengyi@easycorp.ltd>
* @package kanban
* @version $Id: edit.html.php 935 2021-12-09 16:15:24Z $
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('acl', $kanban->acl);?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->kanban->edit;?></h2>
</div>
<form class='form-indicator main-form' method='post' target='hiddenwin' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->kanban->space;?></th>
<td><?php echo html::select('space', $spacePairs, $kanban->space, "class='form-control chosen'");?></td>
</tr>
<tr>
<th><?php echo $lang->kanban->name;?></th>
<td><?php echo html::input('name', $kanban->name, "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->kanban->owner;?></th>
<td><?php echo html::select('owner', $users, $kanban->owner, "class='form-control chosen'");?></td>
</tr>
<tr>
<th><?php echo $lang->kanban->team;?></th>
<td colspan='2'>
<div class="input-group">
<?php echo html::select('team[]', $users, $kanban->team, "class='form-control chosen' multiple");?>
<?php echo $this->fetch('my', 'buildContactLists');?>
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->kanban->desc;?></th>
<td colspan='2'>
<?php echo $this->fetch('user', 'ajaxPrintTemplates', 'type=kanban&link=desc');?>
<?php echo html::textarea('desc', $kanban->desc, "rows='10' class='form-control'");?>
</td>
</tr>
<tr>
<th><?php echo $lang->kanban->acl;?></th>
<td colspan='2'><?php echo nl2br(html::radio('acl', $lang->kanban->aclList, $kanban->acl, "onclick='setWhite(this.value);'", 'block'));?></td>
</tr>
<tr id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, $kanban->whitelist, 'class="form-control chosen" multiple');?></td>
</tr>
<tr>
<td colspan='3' class='text-center form-actions'><?php echo html::submitButton();?></td>
</tr>
</table>
</form>
</div>
<?php include '../../common/view/footer.html.php';?>
+1
View File
@@ -12,6 +12,7 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('acl', $space->acl);?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->kanban->editSpace;?></h2>
+5
View File
@@ -74,3 +74,8 @@ a.showMoreImage:hover {opacity: 1;}
#modules li>a, #modules ul>li>a {overflow: hidden; white-space: nowrap;}
.fixed-head-table{z-index:1000;}
#headerActions {position: absolute; top: 9px; right: 130px; border-right: 2px solid rgba(255, 255, 255, 0.3);}
#headerActions .btn-group > .btn{ color: #fff; margin-right: 8px; border-radius: 4px !important;}
#headerActions .btn-group > .btn.active, .btn:active, .open .dropdown-toggle.btn {background: rgba(0,0,0,0.15) !important;}
#headerActions #kanbanActionMenu {left: 55px}