mirror of
https://github.com/zadam/trilium.git
synced 2025-10-26 07:46:30 +01:00
chore(react/collections/table): add back insert above/below
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { BoardViewData } from ".";
|
import { BoardViewData } from ".";
|
||||||
|
import appContext from "../../../components/app_context";
|
||||||
import FNote from "../../../entities/fnote";
|
import FNote from "../../../entities/fnote";
|
||||||
import attributes from "../../../services/attributes";
|
import attributes from "../../../services/attributes";
|
||||||
import { executeBulkActions } from "../../../services/bulk_action";
|
import { executeBulkActions } from "../../../services/bulk_action";
|
||||||
@@ -29,9 +30,9 @@ export default class BoardApi {
|
|||||||
title: "New item"
|
title: "New item"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (newNote) {
|
if (newNote && newBranch) {
|
||||||
await this.changeColumn(newNote.noteId, column);
|
await this.changeColumn(newNote.noteId, column);
|
||||||
this.setBranchIdToEdit(newBranch?.branchId);
|
this.startEditing(newBranch?.branchId);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to create new item:", error);
|
console.error("Failed to create new item:", error);
|
||||||
@@ -56,6 +57,36 @@ export default class BoardApi {
|
|||||||
this.saveConfig(this.viewConfig);
|
this.saveConfig(this.viewConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async insertRowAtPosition(
|
||||||
|
column: string,
|
||||||
|
relativeToBranchId: string,
|
||||||
|
direction: "before" | "after") {
|
||||||
|
const { note, branch } = await note_create.createNote(this.parentNote.noteId, {
|
||||||
|
activate: false,
|
||||||
|
targetBranchId: relativeToBranchId,
|
||||||
|
target: direction,
|
||||||
|
title: "New item"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!note || !branch) {
|
||||||
|
throw new Error("Failed to create note");
|
||||||
|
}
|
||||||
|
|
||||||
|
const { noteId } = note;
|
||||||
|
await this.changeColumn(noteId, column);
|
||||||
|
this.startEditing(branch.branchId);
|
||||||
|
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
|
openNote(noteId: string) {
|
||||||
|
appContext.triggerCommand("openInPopup", { noteIdOrPath: noteId });
|
||||||
|
}
|
||||||
|
|
||||||
|
startEditing(branchId: string) {
|
||||||
|
this.setBranchIdToEdit(branchId);
|
||||||
|
}
|
||||||
|
|
||||||
dismissEditingTitle() {
|
dismissEditingTitle() {
|
||||||
this.setBranchIdToEdit(undefined);
|
this.setBranchIdToEdit(undefined);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,12 +53,12 @@ export function openNoteContextMenu(api: Api, event: ContextMenuEvent, noteId: s
|
|||||||
{
|
{
|
||||||
title: t("board_view.insert-above"),
|
title: t("board_view.insert-above"),
|
||||||
uiIcon: "bx bx-list-plus",
|
uiIcon: "bx bx-list-plus",
|
||||||
// handler: () => boardView.insertItemAtPosition(column, branchId, "before")
|
handler: () => api.insertRowAtPosition(column, branchId, "before")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("board_view.insert-below"),
|
title: t("board_view.insert-below"),
|
||||||
uiIcon: "bx bx-empty",
|
uiIcon: "bx bx-empty",
|
||||||
// handler: () => boardView.insertItemAtPosition(column, branchId, "after")
|
handler: () => api.insertRowAtPosition(column, branchId, "after")
|
||||||
},
|
},
|
||||||
{ title: "----" },
|
{ title: "----" },
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,35 +29,6 @@ export default class BoardApi {
|
|||||||
return this.byColumn.get(column);
|
return this.byColumn.get(column);
|
||||||
}
|
}
|
||||||
|
|
||||||
openNote(noteId: string) {
|
|
||||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: noteId });
|
|
||||||
}
|
|
||||||
|
|
||||||
async insertRowAtPosition(
|
|
||||||
column: string,
|
|
||||||
relativeToBranchId: string,
|
|
||||||
direction: "before" | "after",
|
|
||||||
open: boolean = true) {
|
|
||||||
const { note } = await note_create.createNote(this._parentNoteId, {
|
|
||||||
activate: false,
|
|
||||||
targetBranchId: relativeToBranchId,
|
|
||||||
target: direction,
|
|
||||||
title: "New item"
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!note) {
|
|
||||||
throw new Error("Failed to create note");
|
|
||||||
}
|
|
||||||
|
|
||||||
const { noteId } = note;
|
|
||||||
await this.changeColumn(noteId, column);
|
|
||||||
if (open) {
|
|
||||||
this.openNote(noteId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return note;
|
|
||||||
}
|
|
||||||
|
|
||||||
async renameColumn(oldValue: string, newValue: string, noteIds: string[]) {
|
async renameColumn(oldValue: string, newValue: string, noteIds: string[]) {
|
||||||
// Change the value in the notes.
|
// Change the value in the notes.
|
||||||
await executeBulkActions(noteIds, [
|
await executeBulkActions(noteIds, [
|
||||||
@@ -80,7 +51,7 @@ export default class BoardApi {
|
|||||||
|
|
||||||
|
|
||||||
async reorderColumns(newColumnOrder: string[]) {
|
async reorderColumns(newColumnOrder: string[]) {
|
||||||
// Update the column order in persisted data
|
// Update the co lumn order in persisted data
|
||||||
if (!this.persistedData.columns) {
|
if (!this.persistedData.columns) {
|
||||||
this.persistedData.columns = [];
|
this.persistedData.columns = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -380,100 +380,4 @@ export class DifferentialBoardRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startInlineEditing(noteId: string): void {
|
|
||||||
// Use setTimeout to ensure the card is rendered before trying to edit it
|
|
||||||
setTimeout(() => {
|
|
||||||
const $card = this.$container.find(`[data-note-id="${noteId}"]`);
|
|
||||||
if ($card.length) {
|
|
||||||
this.makeCardEditable($card, noteId);
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
private makeCardEditable($card: JQuery<HTMLElement>, noteId: string): void {
|
|
||||||
if ($card.hasClass('editing')) {
|
|
||||||
return; // Already editing
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the current title (get text without icon)
|
|
||||||
const $icon = $card.find('.icon');
|
|
||||||
const currentTitle = $card.text().trim();
|
|
||||||
|
|
||||||
// Add editing class and store original click handler
|
|
||||||
$card.addClass('editing');
|
|
||||||
$card.off('click'); // Remove any existing click handlers temporarily
|
|
||||||
|
|
||||||
// Create input element
|
|
||||||
const $input = $('<input>')
|
|
||||||
.attr('type', 'text')
|
|
||||||
.val(currentTitle)
|
|
||||||
.css({
|
|
||||||
background: 'transparent',
|
|
||||||
border: 'none',
|
|
||||||
outline: 'none',
|
|
||||||
fontFamily: 'inherit',
|
|
||||||
fontSize: 'inherit',
|
|
||||||
color: 'inherit',
|
|
||||||
flex: '1',
|
|
||||||
minWidth: '0',
|
|
||||||
padding: '0',
|
|
||||||
marginLeft: '0.25em'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a flex container to keep icon and input inline
|
|
||||||
const $editContainer = $('<div>')
|
|
||||||
.css({
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
width: '100%'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Replace content with icon + input in flex container
|
|
||||||
$editContainer.append($icon.clone(), $input);
|
|
||||||
$card.empty().append($editContainer);
|
|
||||||
$input.focus().select();
|
|
||||||
|
|
||||||
const finishEdit = async (save = true) => {
|
|
||||||
if (!$card.hasClass('editing')) {
|
|
||||||
return; // Already finished
|
|
||||||
}
|
|
||||||
|
|
||||||
$card.removeClass('editing');
|
|
||||||
|
|
||||||
let finalTitle = currentTitle;
|
|
||||||
if (save) {
|
|
||||||
const newTitle = $input.val() as string;
|
|
||||||
if (newTitle.trim() && newTitle !== currentTitle) {
|
|
||||||
try {
|
|
||||||
// Update the note title using the board view's server call
|
|
||||||
import('../../../services/server').then(async ({ default: server }) => {
|
|
||||||
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to update note title:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore the card content
|
|
||||||
const iconClass = $card.attr('data-icon-class') || 'bx bx-file';
|
|
||||||
const $newIcon = $('<span>').addClass('icon').addClass(iconClass);
|
|
||||||
$card.text(finalTitle);
|
|
||||||
$card.prepend($newIcon);
|
|
||||||
|
|
||||||
// Re-attach click handler for quick edit (for existing cards)
|
|
||||||
$card.on('click', () => appContext.triggerCommand("openInPopup", { noteIdOrPath: noteId }));
|
|
||||||
};
|
|
||||||
|
|
||||||
$input.on('blur', () => finishEdit(true));
|
|
||||||
$input.on('keydown', (e) => {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
e.preventDefault();
|
|
||||||
finishEdit(true);
|
|
||||||
} else if (e.key === 'Escape') {
|
|
||||||
e.preventDefault();
|
|
||||||
finishEdit(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,27 +219,6 @@ export default class BoardView extends ViewMode<BoardData> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async insertItemAtPosition(column: string, relativeToBranchId: string, direction: "before" | "after"): Promise<void> {
|
|
||||||
try {
|
|
||||||
// Create the note without opening it
|
|
||||||
const newNote = await this.api?.insertRowAtPosition(column, relativeToBranchId, direction, false);
|
|
||||||
|
|
||||||
if (newNote) {
|
|
||||||
// Refresh the board to show the new item
|
|
||||||
await this.renderList();
|
|
||||||
|
|
||||||
// Start inline editing of the newly created card
|
|
||||||
this.startInlineEditingCard(newNote.noteId);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to insert new item:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private startInlineEditingCard(noteId: string) {
|
|
||||||
this.renderer?.startInlineEditing(noteId);
|
|
||||||
}
|
|
||||||
|
|
||||||
forceFullRefresh() {
|
forceFullRefresh() {
|
||||||
this.renderer?.forceFullRender();
|
this.renderer?.forceFullRender();
|
||||||
return this.renderList();
|
return this.renderList();
|
||||||
|
|||||||
Reference in New Issue
Block a user