diff --git a/dist/main.js b/dist/main.js index fdb4781b..8f7e63af 100644 --- a/dist/main.js +++ b/dist/main.js @@ -39172,6 +39172,14 @@ class KanbanView extends obsidian.TextFileView { }, }, board.settings).open(); }); + }) + .addItem((item) => { + item + .setTitle("Archive all completed cards") + .setIcon("sheets-in-box") + .onClick(() => { + this.archiveCompletedCards(); + }); }) .addSeparator(); super.onMoreOptionsMenu(menu); @@ -39203,6 +39211,30 @@ class KanbanView extends obsidian.TextFileView { this.dataBridge.setExternal(board); } } + archiveCompletedCards() { + const archived = []; + const board = this.dataBridge.data; + const lanes = board.lanes.map((lane) => { + return update$2(lane, { + items: { + $set: lane.items.filter((item) => { + if (item.data.isComplete) { + archived.push(item); + } + return !item.data.isComplete; + }), + }, + }); + }); + this.dataBridge.setExternal(update$2(board, { + lanes: { + $set: lanes, + }, + archive: { + $push: archived, + }, + })); + } constructKanban() { var _a; reactDom.unmountComponentAtNode(this.contentEl); @@ -39327,6 +39359,43 @@ class KanbanPlugin extends obsidian.Plugin { name: "Create new board", callback: () => this.newKanban(), }); + this.addCommand({ + id: "archive-completed-cards", + name: "Archive completed cards in the active board", + callback: () => { + const view = this.app.workspace.getActiveViewOfType(KanbanView); + if (view) { + view.archiveCompletedCards(); + } + else { + new obsidian.Notice("Error: current file is not a Kanban board", 5000); + } + }, + }); + this.addCommand({ + id: "convert-to-kanban", + name: "Convert empty note to Kanban", + callback: () => __awaiter(this, void 0, void 0, function* () { + const activeLeaf = this.app.workspace.activeLeaf; + const activeFile = this.app.workspace.getActiveFile(); + if (activeFile && activeFile.stat.size === 0) { + const frontmatter = [ + "---", + "", + `${frontMatterKey}: basic`, + "", + "---", + "", + "", + ].join("\n"); + yield this.app.vault.modify(activeFile, frontmatter); + this.setKanbanView(activeLeaf); + } + else { + new obsidian.Notice("Error: cannot create Kanban, the current note is not empty", 5000); + } + }), + }); this.registerEvent(this.app.workspace.on("file-menu", (menu, file, source, leaf) => { // Add a menu item to the folder context menu to create a board if (file instanceof obsidian.TFolder) { diff --git a/src/KanbanView.tsx b/src/KanbanView.tsx index 287c5dc9..28db3488 100644 --- a/src/KanbanView.tsx +++ b/src/KanbanView.tsx @@ -12,7 +12,7 @@ import { import { boardToMd, mdToBoard } from "./parser"; import { Kanban } from "./components/Kanban"; import { DataBridge } from "./DataBridge"; -import { Board } from "./components/types"; +import { Board, Item } from "./components/types"; import KanbanPlugin from "./main"; import { KanbanSettings, SettingsModal } from "./Settings"; @@ -46,7 +46,10 @@ export class KanbanView extends TextFileView implements HoverParent { ReactDOM.unmountComponentAtNode(this.contentEl); } - getSetting(key: keyof KanbanSettings, suppliedLocalSettings?: KanbanSettings) { + getSetting( + key: keyof KanbanSettings, + suppliedLocalSettings?: KanbanSettings + ) { const localSetting = suppliedLocalSettings ? suppliedLocalSettings[key] : this.dataBridge.getData().settings[key]; @@ -95,13 +98,21 @@ export class KanbanView extends TextFileView implements HoverParent { setTimeout(() => { this.setViewData(this.data, true); - }, 100) + }, 100); }, }, board.settings ).open(); }); }) + .addItem((item) => { + item + .setTitle("Archive all completed cards") + .setIcon("sheets-in-box") + .onClick(() => { + this.archiveCompletedCards(); + }); + }) .addSeparator(); super.onMoreOptionsMenu(menu); @@ -140,6 +151,36 @@ export class KanbanView extends TextFileView implements HoverParent { } } + archiveCompletedCards() { + const archived: Item[] = []; + const board = this.dataBridge.data; + + const lanes = board.lanes.map((lane) => { + return update(lane, { + items: { + $set: lane.items.filter((item) => { + if (item.data.isComplete) { + archived.push(item); + } + + return !item.data.isComplete; + }), + }, + }); + }); + + this.dataBridge.setExternal( + update(board, { + lanes: { + $set: lanes, + }, + archive: { + $push: archived, + }, + }) + ); + } + constructKanban() { ReactDOM.unmountComponentAtNode(this.contentEl); ReactDOM.render( diff --git a/src/main.ts b/src/main.ts index 9bcbf099..1e352ca9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,6 +6,7 @@ import { ViewState, MarkdownView, Menu, + Notice, } from "obsidian"; import { around } from "monkey-around"; @@ -172,6 +173,50 @@ export default class KanbanPlugin extends Plugin { callback: () => this.newKanban(), }); + this.addCommand({ + id: "archive-completed-cards", + name: "Archive completed cards in the active board", + callback: () => { + const view = this.app.workspace.getActiveViewOfType(KanbanView); + + if (view) { + view.archiveCompletedCards(); + } else { + new Notice("Error: current file is not a Kanban board", 5000); + } + }, + }); + + this.addCommand({ + id: "convert-to-kanban", + name: "Convert empty note to Kanban", + callback: async () => { + const activeLeaf = this.app.workspace.activeLeaf; + const activeFile = this.app.workspace.getActiveFile(); + + if (activeFile && activeFile.stat.size === 0) { + const frontmatter = [ + "---", + "", + `${frontMatterKey}: basic`, + "", + "---", + "", + "", + ].join("\n"); + + await this.app.vault.modify(activeFile, frontmatter); + + this.setKanbanView(activeLeaf); + } else { + new Notice( + "Error: cannot create Kanban, the current note is not empty", + 5000 + ); + } + }, + }); + this.registerEvent( this.app.workspace.on("file-menu", (menu, file: TFile, source, leaf) => { // Add a menu item to the folder context menu to create a board