Merge branch 'sprint/sunhao/optimize_kanban' into 'master'
* Fix bugs for kanban, include bug #17938, bug #19116, bug #18935, bug #18985, bug #19078. See merge request easycorp/zentaopms!2482
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
.region .kanban .form-actions .btn {margin-right: 10px; min-width: 50px;}
|
||||
|
||||
.region .kanban-board + .kanban-board {margin-top: 20px;}
|
||||
.region .kanban-board > .kanban-header > .kanban-group-header {padding: 8px 2px; width: 20px;}
|
||||
.region .kanban-board > .kanban-header > .kanban-group-header {padding: 7px 0; width: 20px; text-align: center;}
|
||||
.region .kanban-board > .kanban-header > .kanban-group-header:hover {cursor: move;}
|
||||
.region .kanban-board.sort > .kanban-header {padding-left: 0;}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
.region .kanban-header-col > .title > .count {opacity: .5; font-weight: bold; color: #8b91a2;}
|
||||
.region .kanban-header-col > .title > .error {color: #333333; padding-left: 2px; font-size: 10px; padding-top: 1px; padding-right: 2px;}
|
||||
.kanban-affixed .kanban-header-col > .title > .text {color: #fff!important}
|
||||
.region .kanban-header-col > .actions {position: relative; right: -5px;}
|
||||
.region .kanban-header-col > .actions {position: relative;}
|
||||
.region .kanban-header-parent-col > .actions {position: absolute; right: 0px;}
|
||||
.region .kanban-header-sub-cols .actions {position: absolute; right: 0px;}
|
||||
|
||||
@@ -56,8 +56,6 @@
|
||||
.region .kanban-lane-col {max-height: unset !important; overflow: auto; position: relative;}
|
||||
.region .kanban-lane-col.has-scrollbar > .kanban-lane-actions {position: absolute; background-color: inherit; bottom: 0; left: 0; right: 0;}
|
||||
|
||||
.region .kanban-lane-items {overflow: overlay !important; padding-bottom: 10px;}
|
||||
|
||||
.kanban-item {position: relative}
|
||||
.kanban-item > .kanban-card > .title {display: block; line-height: 18px;}
|
||||
.kanban-item > .kanban-card > .title:hover {color: #2272eb}
|
||||
@@ -79,7 +77,7 @@
|
||||
.kanban-item .has-color .actions .icon-more-v,
|
||||
.kanban-item .has-color .info > .label-pri,
|
||||
.kanban-item .has-color .info > .estimate,
|
||||
.kanban-item .has-color .info > .user .lable-teamSumCount,
|
||||
.kanban-item .has-color .info > .user .label-teamSumCount,
|
||||
.kanban-item .has-color .info > .label-light {color: #FFFFFF;}
|
||||
.kanban-item .has-color .info > .label-pri {border-color: #FFFFFF;}
|
||||
.kanban-item .has-color .progress-box > .progress-number {color: #FFFFFF;}
|
||||
@@ -100,8 +98,14 @@
|
||||
.kanban-col[data-type=ADD] {display: none;}
|
||||
.kanban-col[data-type=EMPTY] {display: none;}
|
||||
.kanban-col {padding-right: 0px !important;}
|
||||
.kanban-col.drag-shadow {background-color: #ededed !important; border-color: #ededed!important; box-shadow: 0 4px 10px 0 rgb(0,0,0, 0.05), 0 4px 20px 0 rgb(0,0,0, .3); min-height: 30px!important;}
|
||||
.kanban-col.drag-shadow .kanban-header-col {min-height: 30px!important;}
|
||||
.kanban-header-has-parent .kanban-header-cols > .kanban-col.drag-shadow,
|
||||
.kanban-col.kanban-header-parent-col.drag-shadow {min-height: 64px!important;}
|
||||
.kanban-col.drag-shadow > .actions {visibility: hidden!important;}
|
||||
.kanban-item .title {padding-right: 10px;}
|
||||
.gray .actions {display:none;}
|
||||
.kanban-cols-sorting .kanban-item {visibility: hidden!important;}
|
||||
|
||||
.kanban-card .header .executionName {display: flex; width: 100%; float: left;}
|
||||
.kanban-card .header .executionName .title {padding-right: 0px; margin-right: 5px; overflow: hidden; white-space: nowrap;}
|
||||
|
||||
+55
-54
@@ -40,7 +40,7 @@ function fullScreen()
|
||||
$('.action').hide();
|
||||
$('.kanban-group-header').hide();
|
||||
$(".title").attr("disabled", true).css("pointer-events", "none");
|
||||
$('#kanban').sortable('destroy');
|
||||
window.sortableDisabled = true;
|
||||
$.cookie('isFullScreen', 1);
|
||||
};
|
||||
|
||||
@@ -82,7 +82,7 @@ function exitFullScreen()
|
||||
$('.action').show();
|
||||
$('.kanban-group-header').show();
|
||||
$(".title").attr("disabled", false).css("pointer-events", "auto");
|
||||
initSortable();
|
||||
window.sortableDisabled = false;
|
||||
$.cookie('isFullScreen', 0);
|
||||
}
|
||||
|
||||
@@ -130,10 +130,7 @@ function renderHeaderCol($column, column, $header, kanbanData)
|
||||
}
|
||||
}
|
||||
|
||||
var regionID = $column.closest('.kanban').data('id');
|
||||
var groupID = $column.closest('.kanban-board').data('id');
|
||||
var laneID = column.$kanbanData.lanes[0].id ? column.$kanbanData.lanes[0].id : 0;
|
||||
var columnID = $column.closest('.kanban-col').data('id');
|
||||
var printMoreBtn = (columnPrivs.includes('setColumn') || columnPrivs.includes('setWIP') || columnPrivs.includes('createColumn') || columnPrivs.includes('copyColumn') || columnPrivs.includes('archiveColumn') || columnPrivs.includes('deleteColumn') || columnPrivs.includes('splitColumn'));
|
||||
|
||||
/* Render more menu. */
|
||||
@@ -146,7 +143,7 @@ function renderHeaderCol($column, column, $header, kanbanData)
|
||||
var $actions = $column.children('.actions');
|
||||
if(column.parent != -1)
|
||||
{
|
||||
addItemBtn = ['<a data-contextmenu="columnCreate" data-action="addItem" data-column="' + column.id + '" data-lane="' + laneID + '" class="text-primary">', '<i class="icon icon-expand-alt"></i>', '</a>'].join('');
|
||||
addItemBtn = ['<button data-contextmenu="columnCreate" data-action="addItem" data-column="' + column.id + '" data-lane="' + laneID + '" class="btn btn-link">', '<i class="icon icon-expand-alt text-primary"></i>', '</button>'].join('');
|
||||
}
|
||||
|
||||
var moreAction = ' <button class="btn btn-link action" title="' + kanbanLang.moreAction + '" data-contextmenu="column" data-column="' + column.id + '"><i class="icon icon-ellipsis-v"></i></button>';
|
||||
@@ -238,7 +235,6 @@ function renderLaneName($lane, lane, $kanban, columns, kanban)
|
||||
function renderUsersAvatar(users, itemID, size)
|
||||
{
|
||||
var avatarSizeClass = 'avatar-' + (size || 'md');
|
||||
//var link = createLink('kanban', 'assigncard', 'id=' + itemID, '', true);
|
||||
|
||||
if(users.length == 0 || (users.length == 1 && users[0] == ''))
|
||||
{
|
||||
@@ -1019,19 +1015,20 @@ function handleKanbanAction(action, $element, event, kanban)
|
||||
|
||||
function processMinusBtn()
|
||||
{
|
||||
var columnCount = $('#splitTable .child-column').size();
|
||||
var $table = $('#splitTable');
|
||||
var columnCount = $table.find('.child-column').length;
|
||||
if(columnCount > 2 && columnCount < 10)
|
||||
{
|
||||
$('#splitTable .btn-plus').show();
|
||||
$('#splitTable .btn-close').show();
|
||||
$table.find('.btn-plus').show();
|
||||
$table.find('.btn-close').show();
|
||||
}
|
||||
else if(columnCount <= 2)
|
||||
{
|
||||
$('#splitTable .btn-close').hide();
|
||||
$table.find('.btn-close').hide();
|
||||
}
|
||||
else if(columnCount >= 10)
|
||||
{
|
||||
$('#splitTable .btn-plus').hide();
|
||||
$table.find('.btn-plus').hide();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1192,6 +1189,28 @@ function calcColHeight(col, lane, colCards, colHeight, kanban)
|
||||
return (displayCards * (options.cardHeight + options.cardSpace) + options.cardSpace);
|
||||
}
|
||||
|
||||
/** Handle sort cards */
|
||||
function handleSortCards(event)
|
||||
{
|
||||
var newLaneID = event.element.closest('.kanban-lane').data('id');
|
||||
var newColID = event.element.closest('.kanban-col').data('id');
|
||||
var orders = [];
|
||||
event.list.each(function(_, item){orders.push(item.item.data('id'));});
|
||||
var url = createLink('kanban', 'sortCard', 'kanbanID=' + kanbanID + '&laneID=' + newLaneID + '&columnID=' + newColID + '&cards=' + orders.join(','));
|
||||
|
||||
$.getJSON(url, function(response)
|
||||
{
|
||||
if(response.result === 'fail')
|
||||
{
|
||||
if(typeof response.message === 'string' && response.message.length)
|
||||
{
|
||||
bootbox.alert(response.message);
|
||||
}
|
||||
setTimeout(function(){return location.reload()}, 3000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Define menu creators */
|
||||
window.menuCreators =
|
||||
{
|
||||
@@ -1228,12 +1247,13 @@ function initKanban($kanban)
|
||||
onRenderLaneName: renderLaneName,
|
||||
onRenderHeaderCol: renderHeaderCol,
|
||||
onRenderCount: renderCount,
|
||||
sortable: handleSortCards,
|
||||
droppable:
|
||||
{
|
||||
target: findDropColumns,
|
||||
finish: handleFinishDrop,
|
||||
mouseButton: 'left'
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
$kanban.on('click', '.action-cancel', hideKanbanAction);
|
||||
@@ -1354,7 +1374,6 @@ $(function()
|
||||
$('.color0 .cardcolor').css('border', '1px solid #fff');
|
||||
});
|
||||
|
||||
|
||||
/* Init sortable */
|
||||
initSortable();
|
||||
|
||||
@@ -1364,31 +1383,30 @@ $(function()
|
||||
function initSortable()
|
||||
{
|
||||
var sortType = '';
|
||||
var oldLaneID = '';
|
||||
var oldColID = '';
|
||||
var $cards = null;
|
||||
$('#kanban').sortable(
|
||||
{
|
||||
selector: '.region, .kanban-board, .kanban-lane, .kanban-item.sort, .kanban-col',
|
||||
trigger: '.region.sort > .region-header, .kanban-board.sort > .kanban-header > .kanban-group-header, .kanban-lane.sort > .kanban-lane-name, .kanban-item.sort, .kanban-header-col.sort',
|
||||
selector: '.region, .kanban-board, .kanban-lane, .kanban-col',
|
||||
trigger: '.region.sort > .region-header, .kanban-board.sort > .kanban-header > .kanban-group-header, .kanban-lane.sort > .kanban-lane-name, .kanban-header-col.sort',
|
||||
container: function($ele)
|
||||
{
|
||||
return $ele.parent();
|
||||
},
|
||||
targetSelector: function($ele)
|
||||
{
|
||||
var $parent = $ele.parent();
|
||||
/* Sort regions. */
|
||||
if($ele.hasClass('region'))
|
||||
{
|
||||
sortType = 'region';
|
||||
return $ele.parent().children('.region');
|
||||
return $parent.children('.region');
|
||||
}
|
||||
|
||||
/* Sort boards. */
|
||||
if($ele.hasClass('kanban-board'))
|
||||
{
|
||||
sortType = 'board';
|
||||
return $ele.parent().children('.kanban-board');
|
||||
return $parent.children('.kanban-board');
|
||||
}
|
||||
|
||||
/* Sort lanes. */
|
||||
@@ -1397,23 +1415,19 @@ function initSortable()
|
||||
sortType = 'lane';
|
||||
$cards = $ele.find('.kanban-item');
|
||||
|
||||
return $ele.parent().children('.kanban-lane');
|
||||
return $parent.children('.kanban-lane');
|
||||
}
|
||||
|
||||
/* Sort columns. */
|
||||
if($ele.hasClass('kanban-col'))
|
||||
{
|
||||
sortType = 'column';
|
||||
return $ele.parent().children('.kanban-col');
|
||||
}
|
||||
|
||||
/* Sort cards. */
|
||||
if($ele.hasClass('kanban-item'))
|
||||
{
|
||||
sortType = 'card';
|
||||
return $ele.parent().children('.kanban-item');
|
||||
return $parent.children('.kanban-col');
|
||||
}
|
||||
},
|
||||
before: function() {
|
||||
return !window.sortableDisabled;
|
||||
},
|
||||
start: function(e)
|
||||
{
|
||||
if(sortType == 'region')
|
||||
@@ -1428,17 +1442,11 @@ function initSortable()
|
||||
$('.region').find('.kanban').hide();
|
||||
hideKanbanAction();
|
||||
}
|
||||
|
||||
if(sortType == 'column')
|
||||
else if(sortType === 'column')
|
||||
{
|
||||
$('.kanban-item').addClass('hidden');
|
||||
}
|
||||
|
||||
if(sortType == 'card')
|
||||
{
|
||||
oldLaneID = e.element.closest('.kanban-lane').data('id');
|
||||
oldColID = e.element.closest('.kanban-col').data('id');
|
||||
e.element.closest('.kanban-board').addClass('kanban-cols-sorting');
|
||||
}
|
||||
$('#kanban').attr('data-sort-by', sortType);
|
||||
},
|
||||
finish: function(e)
|
||||
{
|
||||
@@ -1464,7 +1472,7 @@ function initSortable()
|
||||
|
||||
url = createLink('kanban', 'sortRegion', 'regions=' + orders.join(','));
|
||||
}
|
||||
if(sortType == 'board')
|
||||
else if(sortType == 'board')
|
||||
{
|
||||
regionID = e.element.closest('.region').data('id');
|
||||
e.list.each(function(index, data)
|
||||
@@ -1474,7 +1482,7 @@ function initSortable()
|
||||
|
||||
url = createLink('kanban', 'sortGroup', 'region=' + regionID + '&groups=' + orders.join(','));
|
||||
}
|
||||
if(sortType == 'lane')
|
||||
else if(sortType == 'lane')
|
||||
{
|
||||
var groupID = e.element.closest('.kanban-board').data('id');
|
||||
e.list.each(function(index, data)
|
||||
@@ -1485,7 +1493,7 @@ function initSortable()
|
||||
regionID = e.element.closest('.region').data('id');
|
||||
url = createLink('kanban', 'sortLane', 'region=' + regionID + '&lanes=' + orders.join(','));
|
||||
}
|
||||
if(sortType == 'column')
|
||||
else if(sortType == 'column')
|
||||
{
|
||||
var groupID = e.element.closest('.kanban-board').data('id');
|
||||
e.list.each(function(index, data)
|
||||
@@ -1496,35 +1504,28 @@ function initSortable()
|
||||
regionID = e.element.closest('.region').data('id');
|
||||
url = createLink('kanban', 'sortColumn', 'region=' + regionID + '&kanbanID=' + kanban.id + '&columns=' + orders.join(','));
|
||||
}
|
||||
if(sortType == 'card')
|
||||
{
|
||||
var newLaneID = e.element.closest('.kanban-lane').data('id');
|
||||
var newColID = e.element.closest('.kanban-col').data('id');
|
||||
e.list.each(function(index, data)
|
||||
{
|
||||
if(data.item.data('item') != undefined && data.item.data('item').column == newColID && data.item.data('item').lane == newLaneID) orders.push(data.item.data('item').id);
|
||||
});
|
||||
if(newLaneID == oldLaneID && newColID == oldColID && orders.length > 0) url = createLink('kanban', 'sortCard', 'kanbanID=' + kanbanID + '&laneID=' + newLaneID + '&columnID=' + newColID + '&cards=' + orders.join(','));
|
||||
}
|
||||
if(!url) return true;
|
||||
|
||||
$.getJSON(url, function(response)
|
||||
{
|
||||
if(response.result == 'fail' && response.message.length)
|
||||
if(response.result == 'fail')
|
||||
{
|
||||
bootbox.alert(response.message);
|
||||
if(typeof response.message === 'string' && response.message.length)
|
||||
{
|
||||
bootbox.alert(response.message);
|
||||
}
|
||||
setTimeout(function(){return location.reload()}, 3000);
|
||||
}
|
||||
else if (sortType == 'column')
|
||||
{
|
||||
updateRegion(regionID, response[regionID]);
|
||||
}
|
||||
$('.kanban-item').removeClass('hidden');
|
||||
});
|
||||
},
|
||||
always: function(e)
|
||||
{
|
||||
if(sortType == 'lane') $cards.show();
|
||||
$('#kanban').find('.kanban-cols-sorting').removeClass('kanban-cols-sorting');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<?php foreach($stories as $story):?>
|
||||
<tr>
|
||||
<td><?php echo sprintf('%03d', $story->id) . html::hidden('stories[]', $story->id)?></td>
|
||||
<td><span class='label-pri lable-pri-<?php echo $story->pri?>' title='<?php echo zget($lang->story->priList, $story->pri);?>'><?php echo zget($lang->story->priList, $story->pri);?></span></td>
|
||||
<td><span class='label-pri label-pri-<?php echo $story->pri?>' title='<?php echo zget($lang->story->priList, $story->pri);?>'><?php echo zget($lang->story->priList, $story->pri);?></span></td>
|
||||
<td class='text-left c-name' title='<?php echo $story->title?>'><?php echo html::a($sysURL . $this->createLink('story', 'view', "storyID=$story->id", '', true), $story->title, '', "data-toggle='modal' data-type='iframe' data-width='90%'");?></td>
|
||||
<td><?php echo zget($users, $story->openedBy);?></td>
|
||||
<td><?php echo zget($users, $story->assignedTo);?></td>
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ use PHP_CodeSniffer_Tokens as Tokens;
|
||||
*
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @link https://www.php.net/manual/en/migration71.new-features.php#migration71.new-features.nullable-types
|
||||
* @link https://www.php.net/manual/en/migration71.new-features.php#migration71.new-features.nullabel-types
|
||||
* @link https://wiki.php.net/rfc/nullable_types
|
||||
* @link https://www.php.net/manual/en/functions.arguments.php#example-146
|
||||
*
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6
-6
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user