mirror of
https://github.com/wekan/wekan.git
synced 2025-12-16 23:40:13 +01:00
parent
3257110673
commit
324f3f7794
11 changed files with 210 additions and 109 deletions
|
|
@ -550,22 +550,20 @@ BlazeComponent.extendComponent({
|
||||||
// Always reset dragscroll on view switch
|
// Always reset dragscroll on view switch
|
||||||
dragscroll.reset();
|
dragscroll.reset();
|
||||||
|
|
||||||
if (Utils.isTouchScreenOrShowDesktopDragHandles()) {
|
if ($swimlanesDom.data('uiSortable') || $swimlanesDom.data('sortable')) {
|
||||||
$swimlanesDom.sortable({
|
if (Utils.isTouchScreenOrShowDesktopDragHandles()) {
|
||||||
handle: '.js-swimlane-header-handle',
|
$swimlanesDom.sortable('option', 'handle', '.js-swimlane-header-handle');
|
||||||
});
|
} else {
|
||||||
} else {
|
$swimlanesDom.sortable('option', 'handle', '.swimlane-header');
|
||||||
$swimlanesDom.sortable({
|
}
|
||||||
handle: '.swimlane-header',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable drag-dropping if the current user is not a board member
|
// Disable drag-dropping if the current user is not a board member
|
||||||
$swimlanesDom.sortable(
|
$swimlanesDom.sortable(
|
||||||
'option',
|
'option',
|
||||||
'disabled',
|
'disabled',
|
||||||
!ReactiveCache.getCurrentUser()?.isBoardAdmin(),
|
!ReactiveCache.getCurrentUser()?.isBoardAdmin(),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// If there is no data in the board (ie, no lists) we autofocus the list
|
// If there is no data in the board (ie, no lists) we autofocus the list
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,9 @@ template(name="boardList")
|
||||||
i.fa.js-has-spenttime-cards(
|
i.fa.js-has-spenttime-cards(
|
||||||
class="fa-circle{{#if hasOvertimeCards}} has-overtime-card-active{{else}} no-overtime-card-active{{/if}}"
|
class="fa-circle{{#if hasOvertimeCards}} has-overtime-card-active{{else}} no-overtime-card-active{{/if}}"
|
||||||
title="{{#if hasOvertimeCards}}{{_ 'has-overtime-cards'}}{{else}}{{_ 'has-spenttime-cards'}}{{/if}}")
|
title="{{#if hasOvertimeCards}}{{_ 'has-overtime-cards'}}{{else}}{{_ 'has-spenttime-cards'}}{{/if}}")
|
||||||
if isTouchScreenOrShowDesktopDragHandles
|
i.fa.board-handle(
|
||||||
i.fa.board-handle(
|
class="fa-arrows"
|
||||||
class="fa-arrows"
|
title="{{_ 'drag-board'}}")
|
||||||
title="{{_ 'drag-board'}}")
|
|
||||||
else
|
|
||||||
if isSandstorm
|
if isSandstorm
|
||||||
i.fa.js-clone-board(
|
i.fa.js-clone-board(
|
||||||
class="fa-clone"
|
class="fa-clone"
|
||||||
|
|
@ -119,11 +117,9 @@ template(name="boardList")
|
||||||
i.fa.js-has-spenttime-cards(
|
i.fa.js-has-spenttime-cards(
|
||||||
class="fa-circle{{#if hasOvertimeCards}} has-overtime-card-active{{else}} no-overtime-card-active{{/if}}"
|
class="fa-circle{{#if hasOvertimeCards}} has-overtime-card-active{{else}} no-overtime-card-active{{/if}}"
|
||||||
title="{{#if hasOvertimeCards}}{{_ 'has-overtime-cards'}}{{else}}{{_ 'has-spenttime-cards'}}{{/if}}")
|
title="{{#if hasOvertimeCards}}{{_ 'has-overtime-cards'}}{{else}}{{_ 'has-spenttime-cards'}}{{/if}}")
|
||||||
if isTouchScreenOrShowDesktopDragHandles
|
i.fa.board-handle(
|
||||||
i.fa.board-handle(
|
class="fa-arrows"
|
||||||
class="fa-arrows"
|
title="{{_ 'drag-board'}}")
|
||||||
title="{{_ 'drag-board'}}")
|
|
||||||
else
|
|
||||||
if isSandstorm
|
if isSandstorm
|
||||||
a.js-clone-board(
|
a.js-clone-board(
|
||||||
class="fa-clone"
|
class="fa-clone"
|
||||||
|
|
|
||||||
|
|
@ -125,8 +125,7 @@ template(name='checklistItemDetail')
|
||||||
if canModifyCard
|
if canModifyCard
|
||||||
.check-box-container
|
.check-box-container
|
||||||
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||||
if isTouchScreenOrShowDesktopDragHandles
|
span.fa.checklistitem-handle(class="fa-arrows" title="{{_ 'dragChecklistItem'}}")
|
||||||
span.fa.checklistitem-handle(class="fa-arrows" title="{{_ 'dragChecklistItem'}}")
|
|
||||||
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}")
|
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||||
+viewer
|
+viewer
|
||||||
= item.title
|
= item.title
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,9 @@ template(name="minicard")
|
||||||
class="{{#if isLinkedBoard}}linked-board{{/if}}"
|
class="{{#if isLinkedBoard}}linked-board{{/if}}"
|
||||||
class="{{#if colorClass}}minicard-{{colorClass}}{{/if}}")
|
class="{{#if colorClass}}minicard-{{colorClass}}{{/if}}")
|
||||||
if canModifyCard
|
if canModifyCard
|
||||||
if isTouchScreenOrShowDesktopDragHandles
|
a.minicard-details-menu-with-handle.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") | ☰
|
||||||
a.minicard-details-menu-with-handle.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") | ☰
|
.handle
|
||||||
.handle
|
| ↕️
|
||||||
| ↔️
|
|
||||||
else
|
|
||||||
a.minicard-details-menu.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") | ☰
|
|
||||||
.dates
|
.dates
|
||||||
if getReceived
|
if getReceived
|
||||||
.date
|
.date
|
||||||
|
|
|
||||||
|
|
@ -191,6 +191,11 @@ body.list-resizing-active * {
|
||||||
margin-right: 0 !important;
|
margin-right: 0 !important;
|
||||||
/* Ensure proper display */
|
/* Ensure proper display */
|
||||||
display: inline-block !important;
|
display: inline-block !important;
|
||||||
|
/* Ensure it's clickable and shows proper cursor */
|
||||||
|
cursor: move !important;
|
||||||
|
pointer-events: auto !important;
|
||||||
|
/* Add some padding for better clickability */
|
||||||
|
padding: 4px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure buttons maintain original positioning */
|
/* Ensure buttons maintain original positioning */
|
||||||
|
|
|
||||||
|
|
@ -150,26 +150,13 @@ BlazeComponent.extendComponent({
|
||||||
});
|
});
|
||||||
|
|
||||||
this.autorun(() => {
|
this.autorun(() => {
|
||||||
if (Utils.isTouchScreenOrShowDesktopDragHandles()) {
|
|
||||||
$cards.sortable({
|
|
||||||
handle: '.handle',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$cards.sortable({
|
|
||||||
handle: '.minicard',
|
|
||||||
// Prevent sortable from interfering with file drag and drop
|
|
||||||
start: function(event, ui) {
|
|
||||||
// Check if this is a file drag operation
|
|
||||||
const dataTransfer = event.originalEvent?.dataTransfer;
|
|
||||||
if (dataTransfer && dataTransfer.types && dataTransfer.types.includes('Files')) {
|
|
||||||
// Cancel sortable for file drags
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($cards.data('uiSortable') || $cards.data('sortable')) {
|
if ($cards.data('uiSortable') || $cards.data('sortable')) {
|
||||||
|
if (Utils.isTouchScreenOrShowDesktopDragHandles()) {
|
||||||
|
$cards.sortable('option', 'handle', '.handle');
|
||||||
|
} else {
|
||||||
|
$cards.sortable('option', 'handle', '.minicard');
|
||||||
|
}
|
||||||
|
|
||||||
$cards.sortable(
|
$cards.sortable(
|
||||||
'option',
|
'option',
|
||||||
'disabled',
|
'disabled',
|
||||||
|
|
|
||||||
|
|
@ -70,9 +70,9 @@ template(name="listHeader")
|
||||||
| ⬅️
|
| ⬅️
|
||||||
| ➡️
|
| ➡️
|
||||||
a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") | ☰
|
a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") | ☰
|
||||||
if currentUser.isBoardAdmin
|
if currentUser.isBoardMember
|
||||||
if isTouchScreenOrShowDesktopDragHandles
|
unless currentUser.isCommentOnly
|
||||||
a.list-header-handle.handle.js-list-handle | ↔️
|
a.list-header-handle.handle.js-list-handle | ↕️
|
||||||
|
|
||||||
template(name="editListTitleForm")
|
template(name="editListTitleForm")
|
||||||
.list-composer
|
.list-composer
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,8 @@ template(name="swimlaneFixedHeader")
|
||||||
// ⬆️.swimlane-header-collapse-up
|
// ⬆️.swimlane-header-collapse-up
|
||||||
// i.fa.fa-arrow-down.swimlane-header-collapse-down
|
// i.fa.fa-arrow-down.swimlane-header-collapse-down
|
||||||
unless isTouchScreen
|
unless isTouchScreen
|
||||||
if isShowDesktopDragHandles
|
a.swimlane-header-handle.handle.js-swimlane-header-handle
|
||||||
a.swimlane-header-handle.handle.js-swimlane-header-handle
|
| ↕️
|
||||||
| ↕️
|
|
||||||
if isTouchScreen
|
if isTouchScreen
|
||||||
a.swimlane-header-miniscreen-handle.handle.js-swimlane-header-handle
|
a.swimlane-header-miniscreen-handle.handle.js-swimlane-header-handle
|
||||||
| ↕️
|
| ↕️
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { ReactiveCache } from '/imports/reactiveCache';
|
import { ReactiveCache } from '/imports/reactiveCache';
|
||||||
|
import dragscroll from '@wekanteam/dragscroll';
|
||||||
const { calculateIndex } = Utils;
|
const { calculateIndex } = Utils;
|
||||||
|
|
||||||
function currentListIsInThisSwimlane(swimlaneId) {
|
function currentListIsInThisSwimlane(swimlaneId) {
|
||||||
|
|
@ -43,6 +44,20 @@ function currentCardIsInThisList(listId, swimlaneId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function initSortable(boardComponent, $listsDom) {
|
function initSortable(boardComponent, $listsDom) {
|
||||||
|
// Safety check: ensure we have valid DOM elements
|
||||||
|
if (!$listsDom || $listsDom.length === 0) {
|
||||||
|
console.error('initSortable: No valid DOM elements provided');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if sortable is already initialized
|
||||||
|
if ($listsDom.data('uiSortable') || $listsDom.data('sortable')) {
|
||||||
|
console.log('initSortable: Sortable already initialized, skipping');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('initSortable: Initializing sortable for', $listsDom.length, 'elements');
|
||||||
|
|
||||||
// We want to animate the card details window closing. We rely on CSS
|
// We want to animate the card details window closing. We rely on CSS
|
||||||
// transition for the actual animation.
|
// transition for the actual animation.
|
||||||
$listsDom._uihooks = {
|
$listsDom._uihooks = {
|
||||||
|
|
@ -62,20 +77,74 @@ function initSortable(boardComponent, $listsDom) {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
$listsDom.sortable({
|
console.log('Initializing list sortable with', $listsDom.length, 'elements');
|
||||||
connectWith: '.js-swimlane, .js-lists',
|
console.log('Connected elements:', $('.js-swimlane, .js-lists').length);
|
||||||
tolerance: 'pointer',
|
console.log('Available swimlanes:', $('.js-swimlane').map(function() { return $(this).attr('id'); }).get());
|
||||||
helper: 'clone',
|
|
||||||
items: '.js-list:not(.js-list-composer)',
|
// Add click debugging for drag handles
|
||||||
placeholder: 'js-list placeholder',
|
$listsDom.on('mousedown', '.js-list-handle', function(e) {
|
||||||
distance: 7,
|
console.log('List drag handle clicked!', e.target);
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
$listsDom.on('mousedown', '.js-list-header', function(e) {
|
||||||
|
console.log('List header clicked!', e.target);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add debugging for sortable events
|
||||||
|
$listsDom.on('sortstart', function(e, ui) {
|
||||||
|
console.log('Sortable start event fired!', ui.item);
|
||||||
|
});
|
||||||
|
|
||||||
|
$listsDom.on('sortbeforestop', function(e, ui) {
|
||||||
|
console.log('Sortable beforeStop event fired!', ui.item);
|
||||||
|
});
|
||||||
|
|
||||||
|
$listsDom.on('sortstop', function(e, ui) {
|
||||||
|
console.log('Sortable stop event fired!', ui.item);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
$listsDom.sortable({
|
||||||
|
connectWith: '.js-swimlane, .js-lists',
|
||||||
|
tolerance: 'pointer',
|
||||||
|
appendTo: '.board-canvas',
|
||||||
|
helper(evt, item) {
|
||||||
|
const helper = item.clone();
|
||||||
|
helper.css('z-index', 1000);
|
||||||
|
return helper;
|
||||||
|
},
|
||||||
|
items: '.js-list:not(.js-list-composer)',
|
||||||
|
placeholder: 'list placeholder',
|
||||||
|
distance: 3,
|
||||||
|
forcePlaceholderSize: true,
|
||||||
|
cursor: 'move',
|
||||||
start(evt, ui) {
|
start(evt, ui) {
|
||||||
|
console.log('List drag started');
|
||||||
|
ui.helper.css('z-index', 1000);
|
||||||
ui.placeholder.height(ui.helper.height());
|
ui.placeholder.height(ui.helper.height());
|
||||||
ui.placeholder.width(ui.helper.width());
|
ui.placeholder.width(ui.helper.width());
|
||||||
EscapeActions.executeUpTo('popup-close');
|
EscapeActions.executeUpTo('popup-close');
|
||||||
boardComponent.setIsDragging(true);
|
boardComponent.setIsDragging(true);
|
||||||
|
|
||||||
|
// Add visual feedback for list being dragged
|
||||||
|
ui.item.addClass('ui-sortable-helper');
|
||||||
|
|
||||||
|
// Disable dragscroll during list dragging to prevent interference
|
||||||
|
console.log('Disabling dragscroll for list dragging');
|
||||||
|
dragscroll.reset();
|
||||||
|
|
||||||
|
// Also disable dragscroll on all swimlanes during list dragging
|
||||||
|
$('.js-swimlane').each(function() {
|
||||||
|
$(this).removeClass('dragscroll');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
beforeStop(evt, ui) {
|
||||||
|
// Clean up visual feedback
|
||||||
|
ui.item.removeClass('ui-sortable-helper');
|
||||||
},
|
},
|
||||||
stop(evt, ui) {
|
stop(evt, ui) {
|
||||||
|
console.log('List drag stopped');
|
||||||
// To attribute the new index number, we need to get the DOM element
|
// To attribute the new index number, we need to get the DOM element
|
||||||
// of the previous and the following card -- if any.
|
// of the previous and the following card -- if any.
|
||||||
const prevListDom = ui.item.prev('.js-list').get(0);
|
const prevListDom = ui.item.prev('.js-list').get(0);
|
||||||
|
|
@ -83,15 +152,39 @@ function initSortable(boardComponent, $listsDom) {
|
||||||
const sortIndex = calculateIndex(prevListDom, nextListDom, 1);
|
const sortIndex = calculateIndex(prevListDom, nextListDom, 1);
|
||||||
|
|
||||||
const listDomElement = ui.item.get(0);
|
const listDomElement = ui.item.get(0);
|
||||||
const list = Blaze.getData(listDomElement);
|
if (!listDomElement) {
|
||||||
|
console.error('List DOM element not found during drag stop');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let list;
|
||||||
|
try {
|
||||||
|
list = Blaze.getData(listDomElement);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting list data:', error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!list) {
|
||||||
|
console.error('List data not found for element:', listDomElement);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Detect if the list was dropped in a different swimlane
|
// Detect if the list was dropped in a different swimlane
|
||||||
const targetSwimlaneDom = ui.item.closest('.js-swimlane');
|
const targetSwimlaneDom = ui.item.closest('.js-swimlane');
|
||||||
let targetSwimlaneId = null;
|
let targetSwimlaneId = null;
|
||||||
|
|
||||||
|
console.log('Target swimlane DOM:', targetSwimlaneDom.length, targetSwimlaneDom.attr('id'));
|
||||||
|
|
||||||
if (targetSwimlaneDom.length > 0) {
|
if (targetSwimlaneDom.length > 0) {
|
||||||
// List was dropped in a swimlane
|
// List was dropped in a swimlane
|
||||||
targetSwimlaneId = targetSwimlaneDom.attr('id').replace('swimlane-', '');
|
try {
|
||||||
|
targetSwimlaneId = targetSwimlaneDom.attr('id').replace('swimlane-', '');
|
||||||
|
console.log('List dropped in swimlane:', targetSwimlaneId);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting target swimlane ID:', error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// List was dropped in lists view (not swimlanes view)
|
// List was dropped in lists view (not swimlanes view)
|
||||||
// In this case, assign to the default swimlane
|
// In this case, assign to the default swimlane
|
||||||
|
|
@ -100,6 +193,7 @@ function initSortable(boardComponent, $listsDom) {
|
||||||
const defaultSwimlane = currentBoard.getDefaultSwimline();
|
const defaultSwimlane = currentBoard.getDefaultSwimline();
|
||||||
if (defaultSwimlane) {
|
if (defaultSwimlane) {
|
||||||
targetSwimlaneId = defaultSwimlane._id;
|
targetSwimlaneId = defaultSwimlane._id;
|
||||||
|
console.log('List dropped in lists view, using default swimlane:', targetSwimlaneId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -123,6 +217,11 @@ function initSortable(boardComponent, $listsDom) {
|
||||||
|
|
||||||
// Check if the list was dropped in a different swimlane
|
// Check if the list was dropped in a different swimlane
|
||||||
const isDifferentSwimlane = targetSwimlaneId && targetSwimlaneId !== originalSwimlaneId;
|
const isDifferentSwimlane = targetSwimlaneId && targetSwimlaneId !== originalSwimlaneId;
|
||||||
|
console.log('Cross-swimlane check:', {
|
||||||
|
originalSwimlaneId,
|
||||||
|
targetSwimlaneId,
|
||||||
|
isDifferentSwimlane
|
||||||
|
});
|
||||||
|
|
||||||
// If the list was dropped in a different swimlane, update the swimlaneId
|
// If the list was dropped in a different swimlane, update the swimlaneId
|
||||||
if (isDifferentSwimlane) {
|
if (isDifferentSwimlane) {
|
||||||
|
|
@ -152,34 +251,63 @@ function initSortable(boardComponent, $listsDom) {
|
||||||
$listsDom.sortable('cancel');
|
$listsDom.sortable('cancel');
|
||||||
}
|
}
|
||||||
|
|
||||||
Lists.update(list._id, {
|
try {
|
||||||
$set: updateData,
|
Lists.update(list._id, {
|
||||||
});
|
$set: updateData,
|
||||||
|
});
|
||||||
|
console.log('List updated successfully:', list._id, updateData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error updating list:', error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
boardComponent.setIsDragging(false);
|
boardComponent.setIsDragging(false);
|
||||||
|
|
||||||
|
// Re-enable dragscroll after list dragging is complete
|
||||||
|
console.log('Re-enabling dragscroll after list dragging');
|
||||||
|
dragscroll.reset();
|
||||||
|
|
||||||
|
// Re-enable dragscroll on all swimlanes
|
||||||
|
$('.js-swimlane').each(function() {
|
||||||
|
$(this).addClass('dragscroll');
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error initializing list sortable:', error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('List sortable initialization completed successfully');
|
||||||
|
console.log('Sortable data after init:', $listsDom.data('uiSortable') || $listsDom.data('sortable'));
|
||||||
|
|
||||||
boardComponent.autorun(() => {
|
boardComponent.autorun(() => {
|
||||||
if (Utils.isTouchScreenOrShowDesktopDragHandles()) {
|
|
||||||
$listsDom.sortable({
|
|
||||||
handle: '.js-list-handle',
|
|
||||||
connectWith: '.js-swimlane, .js-lists',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$listsDom.sortable({
|
|
||||||
handle: '.js-list-header',
|
|
||||||
connectWith: '.js-swimlane, .js-lists',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const $listDom = $listsDom;
|
const $listDom = $listsDom;
|
||||||
|
console.log('Autorun running, checking sortable status...');
|
||||||
|
console.log('Has uiSortable:', $listDom.data('uiSortable'));
|
||||||
|
console.log('Has sortable:', $listDom.data('sortable'));
|
||||||
if ($listDom.data('uiSortable') || $listDom.data('sortable')) {
|
if ($listDom.data('uiSortable') || $listDom.data('sortable')) {
|
||||||
$listsDom.sortable(
|
if (Utils.isTouchScreenOrShowDesktopDragHandles()) {
|
||||||
'option',
|
$listsDom.sortable('option', 'handle', '.js-list-handle');
|
||||||
'disabled',
|
console.log('List sortable: Using .js-list-handle as handle');
|
||||||
!ReactiveCache.getCurrentUser()?.isBoardAdmin(),
|
console.log('Found drag handles:', $listsDom.find('.js-list-handle').length);
|
||||||
);
|
} else {
|
||||||
|
$listsDom.sortable('option', 'handle', '.js-list-header');
|
||||||
|
console.log('List sortable: Using .js-list-header as handle');
|
||||||
|
console.log('Found list headers:', $listsDom.find('.js-list-header').length);
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentUser = ReactiveCache.getCurrentUser();
|
||||||
|
const canModify = Utils.canModifyBoard();
|
||||||
|
const isDisabled = !canModify;
|
||||||
|
$listsDom.sortable('option', 'disabled', isDisabled);
|
||||||
|
console.log('List sortable disabled:', isDisabled);
|
||||||
|
console.log('Can modify board:', canModify);
|
||||||
|
console.log('Current user:', currentUser ? currentUser.username : 'null');
|
||||||
|
console.log('Is board member:', currentUser ? currentUser.isBoardMember() : 'null');
|
||||||
|
console.log('Is comment only:', currentUser ? currentUser.isCommentOnly() : 'null');
|
||||||
|
} else {
|
||||||
|
console.log('List sortable not initialized yet');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -188,11 +316,15 @@ BlazeComponent.extendComponent({
|
||||||
onRendered() {
|
onRendered() {
|
||||||
const boardComponent = this.parentComponent();
|
const boardComponent = this.parentComponent();
|
||||||
const $listsDom = this.$('.js-lists');
|
const $listsDom = this.$('.js-lists');
|
||||||
|
|
||||||
|
console.log('Swimlane onRendered - DOM elements found:', $listsDom.length);
|
||||||
|
console.log('Swimlane onRendered - DOM element:', $listsDom[0]);
|
||||||
|
|
||||||
if (!Utils.getCurrentCardId()) {
|
if (!Utils.getCurrentCardId()) {
|
||||||
boardComponent.scrollLeft();
|
boardComponent.scrollLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('Calling initSortable...');
|
||||||
initSortable(boardComponent, $listsDom);
|
initSortable(boardComponent, $listsDom);
|
||||||
},
|
},
|
||||||
onCreated() {
|
onCreated() {
|
||||||
|
|
@ -538,11 +670,15 @@ BlazeComponent.extendComponent({
|
||||||
onRendered() {
|
onRendered() {
|
||||||
const boardComponent = this.parentComponent();
|
const boardComponent = this.parentComponent();
|
||||||
const $listsDom = this.$('.js-lists');
|
const $listsDom = this.$('.js-lists');
|
||||||
|
|
||||||
|
console.log('ListsGroup onRendered - DOM elements found:', $listsDom.length);
|
||||||
|
console.log('ListsGroup onRendered - DOM element:', $listsDom[0]);
|
||||||
|
|
||||||
if (!Utils.getCurrentCardId()) {
|
if (!Utils.getCurrentCardId()) {
|
||||||
boardComponent.scrollLeft();
|
boardComponent.scrollLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('ListsGroup calling initSortable...');
|
||||||
initSortable(boardComponent, $listsDom);
|
initSortable(boardComponent, $listsDom);
|
||||||
},
|
},
|
||||||
}).register('listsGroup');
|
}).register('listsGroup');
|
||||||
|
|
|
||||||
|
|
@ -496,30 +496,14 @@ Utils = {
|
||||||
|
|
||||||
// returns if desktop drag handles are enabled
|
// returns if desktop drag handles are enabled
|
||||||
isShowDesktopDragHandles() {
|
isShowDesktopDragHandles() {
|
||||||
if (this.isTouchScreen()) {
|
// Always show drag handles on all displays
|
||||||
return true;
|
return true;
|
||||||
/*
|
|
||||||
const currentUser = ReactiveCache.getCurrentUser();
|
|
||||||
if (currentUser) {
|
|
||||||
return (currentUser.profile || {}).showDesktopDragHandles;
|
|
||||||
} else if (window.localStorage.getItem('showDesktopDragHandles')) {
|
|
||||||
//
|
|
||||||
if (window.localStorage.getItem('showDesktopDragHandles')) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// returns if mini screen or desktop drag handles
|
// returns if mini screen or desktop drag handles
|
||||||
isTouchScreenOrShowDesktopDragHandles() {
|
isTouchScreenOrShowDesktopDragHandles() {
|
||||||
// Always enable drag handles for mobile screens (touch devices)
|
// Always enable drag handles for all displays
|
||||||
return this.isTouchScreen() || this.isMiniScreen();
|
return true;
|
||||||
//return this.isTouchScreen() || this.isShowDesktopDragHandles();
|
|
||||||
//return this.isShowDesktopDragHandles();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
calculateIndexData(prevData, nextData, nItems = 1) {
|
calculateIndexData(prevData, nextData, nItems = 1) {
|
||||||
|
|
|
||||||
|
|
@ -2509,14 +2509,14 @@ var GlobalEmitter = /** @class */ (function () {
|
||||||
// http://stackoverflow.com/a/32954565/96342
|
// http://stackoverflow.com/a/32954565/96342
|
||||||
window.addEventListener('scroll', this.handleScrollProxy = function (ev) {
|
window.addEventListener('scroll', this.handleScrollProxy = function (ev) {
|
||||||
_this.handleScroll($.Event(ev));
|
_this.handleScroll($.Event(ev));
|
||||||
}, true // useCapture
|
}, { passive: true, capture: true } // useCapture with passive for better performance
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
GlobalEmitter.prototype.unbind = function () {
|
GlobalEmitter.prototype.unbind = function () {
|
||||||
this.stopListeningTo($(document));
|
this.stopListeningTo($(document));
|
||||||
window.removeEventListener('touchmove', this.handleTouchMoveProxy, { passive: false } // use same options as addEventListener
|
window.removeEventListener('touchmove', this.handleTouchMoveProxy, { passive: false } // use same options as addEventListener
|
||||||
);
|
);
|
||||||
window.removeEventListener('scroll', this.handleScrollProxy, true // useCapture
|
window.removeEventListener('scroll', this.handleScrollProxy, { passive: true, capture: true } // use same options as addEventListener
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
// Touch Handlers
|
// Touch Handlers
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue