kanbanqube 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  ![KanbanQube preview](promo.jpg)
9
9
 
10
- KanbanQube is a local-first Kanban board app backed by normal files in a vault folder. It is designed for personal or team workflows where the board should live in a regular directory, optionally inside a Git repository, so changes can be versioned and synced with the tools you already use.
10
+ KanbanQube is a local-first Kanban board app for solo users and very small teams. A board lives as normal files in a regular vault folder on your machine and can optionally be placed inside a Git repository, so changes can be versioned and synced with tools you already use.
11
11
 
12
12
  The app provides lanes, cards, labels, checklists, comments, card covers, file attachments, archived cards, search, and a card-detail view. Uploaded files are stored in an `uploads/` folder, while board data is split into per-object JSON files under `board/` so Git can merge independent card and checklist edits more cleanly.
13
13
 
@@ -12,8 +12,20 @@ function createImportController(boardService, importService) {
12
12
  response.json(await boardService.saveBoard(importedBoard));
13
13
  }
14
14
 
15
+ async function importDemoBoard(_request, response) {
16
+ const currentBoard = await boardService.loadBoard();
17
+ if ((currentBoard.cards || []).length > 0) {
18
+ response.status(409).json({ error: "Demo board can only be loaded when the board has no cards." });
19
+ return;
20
+ }
21
+
22
+ const demoBoard = await importService.readDemoBoard();
23
+ response.json(await boardService.saveBoard(demoBoard));
24
+ }
25
+
15
26
  return {
16
- importBoard
27
+ importBoard,
28
+ importDemoBoard
17
29
  };
18
30
  }
19
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kanbanqube",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Local-first Kanban board backed by normal files",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Mathias Conradt",
package/public/app.js CHANGED
@@ -217,11 +217,14 @@ function isBoardEmpty() {
217
217
  }
218
218
 
219
219
  async function loadDemoBoard() {
220
- const response = await fetch(DEMO_BOARD_PATH);
220
+ const response = await fetch("/api/demo-board", {
221
+ method: "POST"
222
+ });
223
+ const payload = await response.json();
221
224
  if (!response.ok) {
222
- throw new Error("Could not load demo board.");
225
+ throw new Error(payload.error || "Could not load demo board.");
223
226
  }
224
- return response.json();
227
+ return payload;
225
228
  }
226
229
 
227
230
  function wireEvents() {
@@ -22,6 +22,7 @@ function createApiRoutes(services) {
22
22
  router.post("/uploads", asyncHandler(uploadController.uploadFiles));
23
23
  router.delete("/uploads/:fileName", asyncHandler(uploadController.deleteUpload));
24
24
  router.post("/import", asyncHandler(importController.importBoard));
25
+ router.post("/demo-board", asyncHandler(importController.importDemoBoard));
25
26
  router.post("/sync", asyncHandler(syncController.syncBoard));
26
27
  router.get("/sync-status", syncController.syncStatus);
27
28
 
@@ -1,11 +1,13 @@
1
1
  "use strict";
2
2
 
3
+ const fs = require("node:fs/promises");
3
4
  const { multipartBoundary, parseMultipartBody } = require("../utils/multipart");
4
5
  const { readBody } = require("../utils/requestBody");
5
6
 
6
- function createImportService() {
7
+ function createImportService(config = {}) {
7
8
  return {
8
- readImportedBoard
9
+ readImportedBoard,
10
+ readDemoBoard: () => readDemoBoard(config)
9
11
  };
10
12
  }
11
13
 
@@ -23,7 +25,15 @@ async function readImportedBoard(request) {
23
25
  return request.body && typeof request.body === "object" ? request.body : {};
24
26
  }
25
27
 
28
+ async function readDemoBoard(config) {
29
+ if (!config.demoBoardFilePath) {
30
+ throw new Error("Demo board is not available.");
31
+ }
32
+ return JSON.parse(await fs.readFile(config.demoBoardFilePath, "utf8"));
33
+ }
34
+
26
35
  module.exports = {
27
36
  createImportService,
28
- readImportedBoard
37
+ readImportedBoard,
38
+ readDemoBoard
29
39
  };