* Finish task #45827.
This commit is contained in:
@@ -5,6 +5,7 @@ $config->kanban = new stdclass();
|
||||
$config->kanban->require = new stdclass();
|
||||
$config->kanban->require->createregion = 'name';
|
||||
$config->kanban->require->createlane = 'name';
|
||||
$config->kanban->require->createcolumn = 'name';
|
||||
|
||||
$config->kanban->setwip = new stdclass();
|
||||
$config->kanban->setlane = new stdclass();
|
||||
|
||||
@@ -218,6 +218,32 @@ class kanban extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a column for a kanban.
|
||||
*
|
||||
* @param int $columnID
|
||||
* @param string $position left|right
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function createColumn($columnID, $position = 'left')
|
||||
{
|
||||
$column = $this->kanban->getColumnByID($columnID);
|
||||
|
||||
if($_POST)
|
||||
{
|
||||
$order = $position == 'left' ? $column->order : $column->order + 1;
|
||||
$this->kanban->createColumn($column->region, null, $order);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent', 'callback' => 'closeModalAndUpdateKanban', 'callback_params' => $column->region));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->kanban->createColumn;
|
||||
$this->view->column = $column;
|
||||
$this->view->position = $position;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set WIP.
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
$(document).ready(function()
|
||||
{
|
||||
$.setAjaxForm('#createColumnForm');
|
||||
|
||||
initColorPicker();
|
||||
|
||||
$(document).on('click', '#noLimit', function()
|
||||
{
|
||||
if($(this).prop('checked'))
|
||||
{
|
||||
$(this).parents('td').find('input[name^=limit]').val('');
|
||||
$(this).parents('td').find('input[name^=limit]').attr('readonly', true);
|
||||
}
|
||||
else
|
||||
{
|
||||
$(this).parents('td').find('input[name^=limit]').removeAttr('readonly');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function setWIPLimit()
|
||||
{
|
||||
var count = $('#WIPCount').val();
|
||||
if($('#noLimit').attr('checked') == 'checked') count = -1;;
|
||||
|
||||
$('#limit').val(count);
|
||||
}
|
||||
@@ -627,8 +627,6 @@ function createColumnMenu(options)
|
||||
if(privs.includes('editColumn')) items.push({label: kanbanLang.editColumn, icon: 'edit', url: createLink('kanban', 'setColumn', 'columnID=' + column.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
|
||||
if(privs.includes('setWIP')) items.push({label: kanbanLang.setWIP, icon: 'alert', url: createLink('kanban', 'setWIP', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width' : '500px'}});
|
||||
if(privs.includes('splitColumn')) items.push({label: kanbanLang.splitColumn, icon: 'col-split', url: createLink('kanban', 'splitColumn', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal'}});
|
||||
if(privs.includes('setWIP')) items.push({label: kanbanLang.setWIP, icon: '', url: createLink('kanban', 'setWIP', 'columnID=' + column.id + '&executionID=0&from=kanban'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '500px'}});
|
||||
if(privs.includes('editColumn')) items.push({label: kanbanLang.editColumn, icon: '', url: createLink('kanban', 'setColumn', 'columnID=' + column.id + '&executionID=0&from=kanban', '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
|
||||
if(privs.includes('createColumn'))
|
||||
{
|
||||
items.push({label: kanbanLang.createColumnOnLeft, icon: 'col-add-left', url: createLink('kanban', 'createColumn', 'columnID=' + column.id + '&position=left'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
|
||||
|
||||
@@ -51,6 +51,9 @@ $lang->kanban->closedDate = '关闭日期';
|
||||
$lang->kanban->empty = '暂时没有看板';
|
||||
$lang->kanban->teamSumCount = '共%s人';
|
||||
|
||||
$lang->kanban->createColumnOnLeft = '在左侧添加看板列';
|
||||
$lang->kanban->createColumnOnRight = '在右侧添加看板列';
|
||||
|
||||
$lang->kanban->aclList['open'] = '继承空间访问权限(能访问当前空间,即可访问)';
|
||||
$lang->kanban->aclList['private'] = '私有(看板团队成员、白名单、空间负责人可访问)';
|
||||
|
||||
@@ -191,6 +194,7 @@ $lang->kanbanspace->featureBar['closed'] = '已关闭';
|
||||
$lang->kanbancolumn = new stdclass();
|
||||
$lang->kanbancolumn->name = $lang->kanban->columnName;
|
||||
$lang->kanbancolumn->limit = $lang->kanban->WIPCount;
|
||||
$lang->kanbancolumn->color = '看板列颜色';
|
||||
|
||||
$lang->kanbanlane = new stdclass();
|
||||
$lang->kanbanlane->name = $lang->kanban->laneName;
|
||||
|
||||
+119
-7
@@ -180,18 +180,104 @@ class kanbanModel extends model
|
||||
$column->group = $groupID;
|
||||
$column->name = $columnName;
|
||||
$column->type = $index;
|
||||
$column->order = $index;
|
||||
$column->limit = -1;
|
||||
$column->color = '#333';
|
||||
|
||||
$this->dao->insert(TABLE_KANBANCOLUMN)->data($column)->exec();
|
||||
|
||||
$this->saveOrder($regionID, 'region', $this->dao->lastInsertID(), 'column', '', $index);
|
||||
$this->createColumn($regionID, $column);
|
||||
$index ++;
|
||||
//$this->saveOrder($regionID, 'region', $this->dao->lastInsertID(), 'column', '', $index);
|
||||
}
|
||||
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a column.
|
||||
*
|
||||
* @param int $regionID
|
||||
* @param object $column
|
||||
* @param int $order
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function createColumn($regionID, $column = null, $order = 0)
|
||||
{
|
||||
if(empty($column))
|
||||
{
|
||||
$column = fixer::input('post')
|
||||
->add('region', $regionID)
|
||||
->setIF($order, 'order', $order)
|
||||
->setDefault('color', '#272E33')
|
||||
->get();
|
||||
if(!$order)
|
||||
{
|
||||
$maxOrder = $this->dao->select('MAX(`order`) AS maxOrder')->from(TABLE_KANBANCOLUMN)
|
||||
->where('`group`')->eq($column->group)
|
||||
->fetch('maxOrder');
|
||||
$column->order = $maxOrder + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$column->limit && empty($column->noLimit)) dao::$errors['limit'][] = sprintf($this->lang->error->notempty, $this->lang->kanban->WIP);
|
||||
if(dao::isError()) return false;
|
||||
|
||||
$limit = (int)$column->limit;
|
||||
if(!empty($column->parent))
|
||||
{
|
||||
/* Create a child column. */
|
||||
$parentColumn = $this->getColumnByID($column->parent);
|
||||
if($parentColumn->limit)
|
||||
{
|
||||
/* The WIP of the child column is infinite or greater than the WIP of the parent column. */
|
||||
if(!$limit || $limit > $parentColumn->limit)
|
||||
{
|
||||
dao::$errors['limit'][] = $this->lang->kanban->error->parentLimitNote;
|
||||
return false;
|
||||
}
|
||||
|
||||
$childColumns = $this->getColumnsByParent($column->parent);
|
||||
foreach($childColumns as $childColumn)
|
||||
{
|
||||
$limit += (int)$childColumn->limit;
|
||||
if($limit > $parentColumn->limit)
|
||||
{
|
||||
/* The total WIP of the child columns is greater than the WIP of the parent column. */
|
||||
dao::$errors['limit'][] = $this->lang->kanban->error->childLimitNote;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$column->limit = (int)$column->limit;
|
||||
|
||||
if($order)
|
||||
{
|
||||
/* It means copy a column or insert a column before or after a column. */
|
||||
$this->dao->update(TABLE_KANBANCOLUMN)
|
||||
->set('`order` = `order` + 1')
|
||||
->where('`group`')->eq($column->group)
|
||||
->andWhere('`order`')->ge($order)
|
||||
->exec();
|
||||
}
|
||||
|
||||
$this->dao->insert(TABLE_KANBANCOLUMN)->data($column, 'noLimit,position,copyItems')
|
||||
->batchCheck($this->config->kanban->require->createcolumn, 'notempty')
|
||||
->autoCheck()
|
||||
->exec();
|
||||
if(dao::isError()) return false;
|
||||
|
||||
$columnID = $this->dao->lastInsertID();
|
||||
|
||||
$maxType = $this->dao->select('type')->from(TABLE_KANBANCOLUMN)->where('`group`')->eq($column->group)->orderBy('type_desc')->limit(1)->fetch('type');
|
||||
$this->dao->update(TABLE_KANBANCOLUMN)->set('type')->eq($maxType + 1)->where('id')->eq($columnID)->exec();
|
||||
|
||||
$this->loadModel('action')->create('kanbanColumn', $columnID, 'Created');
|
||||
|
||||
return $columnID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save kanban object order.
|
||||
*
|
||||
@@ -602,9 +688,17 @@ class kanbanModel extends model
|
||||
{
|
||||
if($object->acl == 'private')
|
||||
{
|
||||
$aclUsers = $object->owner . $object->team . $object->whitelist;
|
||||
if($objectType == 'kanban') $aclUsers .= ',' . $spaceOwnerPairs[$object->space];
|
||||
if(strpos(",$aclUsers,", ",$account,") === false) unset($objects[$objectID]);
|
||||
$remove = true;
|
||||
if($object->owner == $account) $remove = false;
|
||||
if(strpos(",{$object->team},", ",$account,") !== false) $remove = false;
|
||||
if(strpos(",{$object->whitelist},", ",$account,") !== false) $remove = false;
|
||||
if($objectType == 'kanban')
|
||||
{
|
||||
$parentOwner = isset($spaceOwnerPairs[$object->space]) ? $spaceOwnerPairs[$object->space] : '';
|
||||
if(strpos(",$parentOwner,", ",$account,") !== false) $remove = false;
|
||||
}
|
||||
|
||||
if($remove) unset($objects[$objectID]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1517,7 +1611,7 @@ class kanbanModel extends model
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getColumnById($columnID)
|
||||
public function getColumnByID($columnID)
|
||||
{
|
||||
$column = $this->dao->select('t1.*, t2.type as laneType')->from(TABLE_KANBANCOLUMN)->alias('t1')
|
||||
->leftjoin(TABLE_KANBANLANE)->alias('t2')->on('t1.lane=t2.id')
|
||||
@@ -1547,6 +1641,24 @@ class kanbanModel extends model
|
||||
->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get child columns by parent id.
|
||||
*
|
||||
* @param int $parentID
|
||||
* @param string $archived
|
||||
* @param string $deleted
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnsByParent($parentID, $archived = '0', $deleted = '0')
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_KANBANCOLUMN)
|
||||
->where('parent')->eq($parentID)
|
||||
->andWhere('archived')->eq($archived)
|
||||
->andWhere('deleted')->eq($deleted)
|
||||
->orderBy('order')
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get lane by id.
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* The create lane view file of kanban module of ZentaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2020 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Guangming Sun<sunguangming@easycorp.ltd>
|
||||
* @package kanban
|
||||
* @version $Id$
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.lite.html.php';?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
<h2><?php echo $lang->kanban->createColumn;?></h2>
|
||||
</div>
|
||||
<form id='createColumnForm' method='post' class='form-ajax' action='<?php echo inlink('createColumn', "columnID=$column->id&position=$position");?>' onsubmit='return setWIPLimit();'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th class="w-120px"><?php echo $lang->kanbancolumn->name;?></th>
|
||||
<td>
|
||||
<div class='required required-wrapper'></div>
|
||||
<?php echo html::input('name', '', "class='form-control'");?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='child-column'>
|
||||
<th><?php echo $lang->kanban->WIPCount;?></th>
|
||||
<td>
|
||||
<div class='required required-wrapper'></div>
|
||||
<div class='input-group'>
|
||||
<?php echo html::number('limit', '', "min='1' class='form-control'" . ($column->limit ? '' : "readonly"));?>
|
||||
<span class='input-group-addon'>
|
||||
<label class='checkbox-inline'>
|
||||
<input type='checkbox' name='noLimit' id='noLimit' value='-1' <?php if(!$column->limit) echo "checked";?>/> <?php echo $this->lang->kanban->noLimit;?>
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->kanbancolumn->color;?></th>
|
||||
<td><div id='color-picker'></div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='2' class='form-actions text-center'>
|
||||
<?php echo html::hidden('color', '#272E33');?>
|
||||
<?php echo html::hidden('group', $column->group);?>
|
||||
<?php echo html::hidden('parent', $column->parent);?>
|
||||
<?php echo html::submitButton();?>
|
||||
<?php echo html::commonButton($lang->cancel, "data-dismiss='modal'", 'btn btn-wide');?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.lite.html.php';?>
|
||||
@@ -29,11 +29,11 @@ $canCreateLane = commonModel::hasPriv('kanban', 'createLane');
|
||||
<label class="label label-region"><?php echo $this->lang->kanbanlane->common . ' ' . $region->laneCount;?></label>
|
||||
<i class="icon icon-double-angle-up"></i>
|
||||
<?php if($canEditRegion || $canCreateLane || $canDeleteRegion):?>
|
||||
<button class="btn btn-link action" type="button" data-toggle="dropdown"><i class="icon icon-more-v"></i></button>
|
||||
<button class="btn btn-link action" type="button" data-toggle="dropdown"><i class="icon icon-ellipsis-v"></i></button>
|
||||
<ul class="dropdown-menu pull-right">
|
||||
<?php if($canEditRegion) echo '<li>' . html::a(inlink('editRegion', "regionID={$region->id}"), $this->lang->kanban->editRegion, "data-toggle='modal'") . '</li>';?>
|
||||
<?php if($canCreateLane) echo '<li>' . html::a(inlink('createLane', "kanbanID={$project->id}®ionID={$region->id}"), $this->lang->kanban->createLane, "data-toggle='modal'") . '</li>';?>
|
||||
<?php if($canDeleteRegion) echo '<li>' . html::a(inlink('deleteRegion', "regionID={$region->id}"), $this->lang->kanban->deleteRegion, "class='confirmer' data-confirmTitle='{$lang->kanbanregion->confirmDelete}' data-confirmDetail='{$lang->kanbanregion->confirmDeleteDetail}'") . '</li>';?>
|
||||
<?php if($canEditRegion) echo '<li>' . html::a(inlink('editRegion', "regionID={$region->id}", '', 1), $this->lang->kanban->editRegion, '', 'class="iframe"') . '</li>';?>
|
||||
<?php if($canCreateLane) echo '<li>' . html::a(inlink('createLane', "kanbanID={$kanban->id}®ionID={$region->id}", '', 1), $this->lang->kanban->createLane, '', "class='iframe'") . '</li>';?>
|
||||
<?php if($canDeleteRegion) echo '<li>' . html::a(inlink('deleteRegion', "regionID={$region->id}"), $this->lang->kanban->deleteRegion, "hiddenwin") . '</li>';?>
|
||||
</ul>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user