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 +1 -1
- package/controllers/importController.js +13 -1
- package/package.json +1 -1
- package/public/app.js +6 -3
- package/routes/apiRoutes.js +1 -0
- package/services/importService.js +13 -3
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|

|
|
9
9
|
|
|
10
|
-
KanbanQube is a local-first Kanban board app
|
|
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
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(
|
|
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
|
|
227
|
+
return payload;
|
|
225
228
|
}
|
|
226
229
|
|
|
227
230
|
function wireEvents() {
|
package/routes/apiRoutes.js
CHANGED
|
@@ -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
|
};
|