From 803164791f1232c999023493df29375370f1261f Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Thu, 11 Sep 2025 19:25:17 +0300 Subject: [PATCH] chore(react/collections/table): reintroduce column context menu --- .../src/widgets/collections/board/api.ts | 22 +++++++++++++- .../widgets/collections/board/context_menu.ts | 29 +++++++++++++++++++ .../src/widgets/collections/board/index.tsx | 9 +++++- .../widgets/view_widgets/board_view/api.ts | 12 -------- .../view_widgets/board_view/context_menu.ts | 25 ---------------- 5 files changed, 58 insertions(+), 39 deletions(-) create mode 100644 apps/client/src/widgets/collections/board/context_menu.ts diff --git a/apps/client/src/widgets/collections/board/api.ts b/apps/client/src/widgets/collections/board/api.ts index 600c5ebd1..7088198de 100644 --- a/apps/client/src/widgets/collections/board/api.ts +++ b/apps/client/src/widgets/collections/board/api.ts @@ -1,12 +1,18 @@ +import { BoardViewData } from "."; import FNote from "../../../entities/fnote"; import attributes from "../../../services/attributes"; +import { executeBulkActions } from "../../../services/bulk_action"; import note_create from "../../../services/note_create"; +import { ColumnMap } from "./data"; export default class BoardApi { constructor( + private byColumn: ColumnMap | undefined, private parentNote: FNote, - private statusAttribute: string + private statusAttribute: string, + private viewConfig: BoardViewData, + private saveConfig: (newConfig: BoardViewData) => void ) {}; async createNewItem(column: string) { @@ -36,5 +42,19 @@ export default class BoardApi { await attributes.setLabel(noteId, this.statusAttribute, newColumn); } + async removeColumn(column: string) { + // Remove the value from the notes. + const noteIds = this.byColumn?.get(column)?.map(item => item.note.noteId) || []; + await executeBulkActions(noteIds, [ + { + name: "deleteLabel", + labelName: this.statusAttribute + } + ]); + + this.viewConfig.columns = (this.viewConfig.columns ?? []).filter(col => col.value !== column); + this.saveConfig(this.viewConfig); + } + } diff --git a/apps/client/src/widgets/collections/board/context_menu.ts b/apps/client/src/widgets/collections/board/context_menu.ts new file mode 100644 index 000000000..cdbe6b5e9 --- /dev/null +++ b/apps/client/src/widgets/collections/board/context_menu.ts @@ -0,0 +1,29 @@ +import contextMenu, { ContextMenuEvent } from "../../../menus/context_menu"; +import dialog from "../../../services/dialog"; +import { t } from "../../../services/i18n"; +import Api from "./api"; + +export function openColumnContextMenu(api: Api, event: ContextMenuEvent, column: string) { + event.preventDefault(); + event.stopPropagation(); + + contextMenu.show({ + x: event.pageX, + y: event.pageY, + items: [ + { + title: t("board_view.delete-column"), + uiIcon: "bx bx-trash", + async handler() { + const confirmed = await dialog.confirm(t("board_view.delete-column-confirmation")); + if (!confirmed) { + return; + } + + await api.removeColumn(column); + } + } + ], + selectMenuItemHandler() {} + }); +} diff --git a/apps/client/src/widgets/collections/board/index.tsx b/apps/client/src/widgets/collections/board/index.tsx index b5f4ea603..209f2b106 100644 --- a/apps/client/src/widgets/collections/board/index.tsx +++ b/apps/client/src/widgets/collections/board/index.tsx @@ -10,6 +10,8 @@ import { t } from "../../../services/i18n"; import Api from "./api"; import FormTextBox from "../../react/FormTextBox"; import branchService from "../../../services/branches"; +import { openColumnContextMenu } from "./context_menu"; +import { ContextMenuEvent } from "../../../menus/context_menu"; export interface BoardViewData { columns?: BoardColumnData[]; @@ -29,7 +31,7 @@ export default function BoardView({ note: parentNote, noteIds, viewConfig, saveC const [ draggedColumn, setDraggedColumn ] = useState<{ column: string, index: number } | null>(null); const [ columnDropPosition, setColumnDropPosition ] = useState(null); const api = useMemo(() => { - return new Api(parentNote, statusAttribute); + return new Api(byColumn, parentNote, statusAttribute, viewConfig ?? {}, saveConfig); }, [ parentNote, statusAttribute ]); function refresh() { @@ -283,12 +285,17 @@ function Column({ setDraggedCard(null); }, [draggedCard, draggedColumn, dropPosition, columnItems, column, statusAttribute, setDraggedCard, setDropTarget, setDropPosition, onCardDrop]); + const handleContextMenu = useCallback((e: ContextMenuEvent) => { + openColumnContextMenu(api, e, column); + }, [ api, column ]); + return (

item.note.noteId) || []; - await executeBulkActions(noteIds, [ - { - name: "deleteLabel", - labelName: this._statusAttribute - } - ]); - this.persistedData.columns = (this.persistedData.columns ?? []).filter(col => col.value !== column); - this.viewStorage.store(this.persistedData); - } async reorderColumns(newColumnOrder: string[]) { // Update the column order in persisted data diff --git a/apps/client/src/widgets/view_widgets/board_view/context_menu.ts b/apps/client/src/widgets/view_widgets/board_view/context_menu.ts index 62cf43e65..378c508a2 100644 --- a/apps/client/src/widgets/view_widgets/board_view/context_menu.ts +++ b/apps/client/src/widgets/view_widgets/board_view/context_menu.ts @@ -16,32 +16,7 @@ export function setupContextMenu({ $container, api, boardView }: ShowNoteContext $container.on("contextmenu", ".board-note", showNoteContextMenu); $container.on("contextmenu", ".board-column h3", showColumnContextMenu); - function showColumnContextMenu(event: ContextMenuEvent) { - event.preventDefault(); - event.stopPropagation(); - const $el = $(event.currentTarget); - const column = $el.closest(".board-column").data("column"); - - contextMenu.show({ - x: event.pageX, - y: event.pageY, - items: [ - { - title: t("board_view.delete-column"), - uiIcon: "bx bx-trash", - async handler() { - const confirmed = await dialog.confirm(t("board_view.delete-column-confirmation")); - if (!confirmed) { - return; - } - - await api.removeColumn(column); - } - } - ], - selectMenuItemHandler() {} - }); } function showNoteContextMenu(event: ContextMenuEvent) {