feat(views/board): drag columns by the title and not by a handle

This commit is contained in:
Elian Doran 2025-07-25 11:56:44 +03:00
parent 2b062e938e
commit 69f12a2916
No known key found for this signature in database
3 changed files with 34 additions and 84 deletions

View File

@ -20,11 +20,17 @@ export class ColumnDragHandler implements BaseDragHandler {
}
setupColumnDrag($columnEl: JQuery<HTMLElement>, columnValue: string) {
const $dragHandle = $columnEl.find('.column-drag-handle');
const $titleEl = $columnEl.find('h3[data-column-value]');
$dragHandle.attr("draggable", "true");
$titleEl.attr("draggable", "true");
$titleEl.on("dragstart", (e) => {
// Only start dragging if the target is not an input (for inline editing)
if ($(e.target).is('input') || $titleEl.hasClass('editing')) {
e.preventDefault();
return false;
}
$dragHandle.on("dragstart", (e) => {
this.context.draggedColumn = columnValue;
this.context.draggedColumnElement = $columnEl;
$columnEl.addClass("column-dragging");
@ -42,7 +48,7 @@ export class ColumnDragHandler implements BaseDragHandler {
this.setupGlobalColumnDragTracking();
});
$dragHandle.on("dragend", () => {
$titleEl.on("dragend", () => {
$columnEl.removeClass("column-dragging");
this.context.draggedColumn = null;
this.context.draggedColumnElement = null;
@ -51,7 +57,7 @@ export class ColumnDragHandler implements BaseDragHandler {
});
}
setupColumnDropZone($columnEl: JQuery<HTMLElement>, columnValue: string) {
setupColumnDropZone($columnEl: JQuery<HTMLElement>, _columnValue: string) {
$columnEl.on("dragover", (e) => {
// Only handle column drops when a column is being dragged
if (this.context.draggedColumn && !this.context.draggedNote) {
@ -205,11 +211,15 @@ export class ColumnDragHandler implements BaseDragHandler {
if ($nextColumn.length > 0) {
// Insert before the next column
const nextColumnValue = $nextColumn.attr('data-column');
insertIndex = newOrder.indexOf(nextColumnValue!);
if (nextColumnValue) {
insertIndex = newOrder.indexOf(nextColumnValue);
}
} else if ($prevColumn.length > 0) {
// Insert after the previous column
const prevColumnValue = $prevColumn.attr('data-column');
insertIndex = newOrder.indexOf(prevColumnValue!) + 1;
if (prevColumnValue) {
insertIndex = newOrder.indexOf(prevColumnValue) + 1;
}
} else {
// Insert at the beginning
insertIndex = 0;

View File

@ -293,28 +293,18 @@ export class DifferentialBoardRenderer {
.addClass("board-column")
.attr("data-column", column);
// Create header with drag handle
// Create header
const $titleEl = $("<h3>").attr("data-column-value", column);
// Create drag handle
const $dragHandle = $("<span>")
.addClass("column-drag-handle icon bx bx-menu")
.attr("title", "Drag to reorder column");
// Create title text
const $titleText = $("<span>").text(column);
// Create title content container
const $titleContent = $("<div>")
.addClass("column-title-content")
.append($dragHandle, $titleText);
// Create edit icon
const $editIcon = $("<span>")
.addClass("edit-icon icon bx bx-edit-alt")
.attr("title", "Click to edit column title");
$titleEl.append($titleContent, $editIcon);
$titleEl.append($titleText, $editIcon);
$columnEl.append($titleEl);
// Setup column dragging

View File

@ -48,7 +48,7 @@ const TPL = /*html*/`
margin-bottom: 0.75em;
padding: 0.5em 0.5em 0.5em 0.5em;
border-bottom: 1px solid var(--main-border-color);
cursor: pointer;
cursor: grab;
position: relative;
transition: background-color 0.2s ease, border-radius 0.2s ease;
display: flex;
@ -58,6 +58,14 @@ const TPL = /*html*/`
background-color: transparent;
}
.board-view-container .board-column h3:active {
cursor: grabbing;
}
.board-view-container .board-column h3.editing {
cursor: default;
}
.board-view-container .board-column h3:hover {
background-color: var(--hover-item-background-color);
border-radius: 4px;
@ -69,36 +77,6 @@ const TPL = /*html*/`
border-radius: 4px;
}
.board-view-container .board-column h3 .column-title-content {
display: flex;
align-items: center;
flex: 1;
min-width: 0; /* Allow text to truncate */
}
.board-view-container .board-column h3 .column-drag-handle {
margin-right: 0.5em;
color: var(--muted-text-color);
cursor: grab;
opacity: 0;
transition: opacity 0.2s ease;
padding: 0.25em;
border-radius: 3px;
}
.board-view-container .board-column h3:hover .column-drag-handle {
opacity: 1;
}
.board-view-container .board-column h3 .column-drag-handle:hover {
background-color: var(--main-background-color);
color: var(--main-text-color);
}
.board-view-container .board-column h3 .column-drag-handle:active {
cursor: grabbing;
}
.board-view-container .board-column.column-dragging {
opacity: 0.6;
transform: scale(0.98);
@ -370,10 +348,10 @@ export default class BoardView extends ViewMode<BoardData> {
}
private setupBoardInteractions() {
// Handle column title editing - listen for clicks on the title content, not the drag handle
this.$container.on('click', 'h3[data-column-value] .column-title-content span:not(.column-drag-handle)', (e) => {
// Handle column title editing - double-click on h3 to edit
this.$container.on('dblclick', 'h3[data-column-value]', (e) => {
e.stopPropagation();
const $titleEl = $(e.currentTarget).closest('h3[data-column-value]');
const $titleEl = $(e.currentTarget);
const columnValue = $titleEl.attr('data-column-value');
if (columnValue) {
const columnItems = this.api?.getColumn(columnValue) || [];
@ -381,24 +359,6 @@ export default class BoardView extends ViewMode<BoardData> {
}
});
// Also handle clicks on the h3 element itself (but not on the drag handle)
this.$container.on('click', 'h3[data-column-value]', (e) => {
// Only proceed if the click wasn't on the drag handle or edit icon
if (!$(e.target).hasClass('column-drag-handle') &&
!$(e.target).hasClass('edit-icon') &&
!$(e.target).hasClass('bx-menu') &&
!$(e.target).hasClass('bx-edit-alt')) {
e.stopPropagation();
const $titleEl = $(e.currentTarget);
const columnValue = $titleEl.attr('data-column-value');
if (columnValue) {
const columnItems = this.api?.getColumn(columnValue) || [];
this.startEditingColumnTitle($titleEl, columnValue, columnItems);
}
}
});
// Handle add column button
this.$container.on('click', '.board-add-column', (e) => {
e.stopPropagation();
@ -407,21 +367,12 @@ export default class BoardView extends ViewMode<BoardData> {
}
private createTitleStructure(title: string): { $titleText: JQuery<HTMLElement>; $editIcon: JQuery<HTMLElement> } {
const $dragHandle = $("<span>")
.addClass("column-drag-handle icon bx bx-menu")
.attr("title", "Drag to reorder column");
const $titleText = $("<span>").text(title);
const $titleContent = $("<div>")
.addClass("column-title-content")
.append($dragHandle, $titleText);
const $editIcon = $("<span>")
.addClass("edit-icon icon bx bx-edit-alt")
.attr("title", "Click to edit column title");
.attr("title", "Double-click to edit column title");
return { $titleText: $titleContent, $editIcon };
return { $titleText, $editIcon };
}
private startEditingColumnTitle($titleEl: JQuery<HTMLElement>, columnValue: string, columnItems: { branch: any; note: any; }[]) {
@ -429,8 +380,7 @@ export default class BoardView extends ViewMode<BoardData> {
return; // Already editing
}
const $titleContent = $titleEl.find(".column-title-content");
const $titleSpan = $titleContent.find("span").last(); // Get the text span, not the drag handle
const $titleSpan = $titleEl.find("span").first(); // Get the text span
const currentTitle = $titleSpan.text();
$titleEl.addClass("editing");