Skip to content

Commit c18a52e

Browse files
feat: whiteboard database persistance
Closes #3
1 parent 601d64c commit c18a52e

File tree

9 files changed

+146
-5
lines changed

9 files changed

+146
-5
lines changed

tldraw_whiteboard/api.py

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import frappe
2+
3+
4+
@frappe.whitelist()
5+
def save_user_whiteboard_state(state: str):
6+
"""Save the logged in user's whiteboard state to the database."""
7+
exists = frappe.db.exists("User Whiteboard State", frappe.session.user)
8+
9+
if not exists:
10+
doc = frappe.new_doc("User Whiteboard State")
11+
doc.user = frappe.session.user
12+
doc.state = state
13+
doc.insert(ignore_permissions=True)
14+
else:
15+
frappe.db.set_value(
16+
"User Whiteboard State", frappe.session.user, "state", state
17+
)
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import * as React from "react";
2-
import { Tldraw } from '@tldraw/tldraw'
3-
2+
import { Tldraw } from "@tldraw/tldraw";
3+
import DBStateManager from "./DBStateManager";
44

55
export function App() {
66
return (
7-
<div style={{ position: 'fixed', inset: 0, marginTop: "48px" }}>
8-
<Tldraw persistenceKey={frappe.session.user} />
7+
<div style={{ position: "fixed", inset: 0, marginTop: "48px" }}>
8+
<Tldraw persistenceKey={frappe.session.user}>
9+
<DBStateManager />
10+
</Tldraw>
911
</div>
1012
);
11-
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import * as React from "react";
2+
import { useEditor } from "@tldraw/tldraw";
3+
4+
// save the document every 5 seconds
5+
const DB_SAVE_INTERVAL = 5000;
6+
7+
export default function DBStateManager() {
8+
const editor = useEditor();
9+
10+
function saveToDB(state) {
11+
frappe.call({
12+
method: "tldraw_whiteboard.api.save_user_whiteboard_state",
13+
args: {
14+
state: state,
15+
},
16+
});
17+
}
18+
19+
function loadStateFromDBifExists() {
20+
frappe.db
21+
.get_value("User Whiteboard State", frappe.session.user, "state")
22+
.then(({ message }) => {
23+
if (message?.state) {
24+
editor.store.loadSnapshot(JSON.parse(message.state));
25+
}
26+
});
27+
}
28+
29+
React.useEffect(() => {
30+
loadStateFromDBifExists();
31+
const interval = setInterval(() => {
32+
const snapshot = editor.store.getSnapshot();
33+
const savable = JSON.stringify(snapshot);
34+
35+
saveToDB(savable);
36+
}, DB_SAVE_INTERVAL);
37+
return () => clearInterval(interval);
38+
}, [editor]);
39+
40+
return <></>;
41+
}

tldraw_whiteboard/tldraw_whiteboard/doctype/__init__.py

Whitespace-only changes.

tldraw_whiteboard/tldraw_whiteboard/doctype/user_whiteboard_state/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2023, Build With Hussain and Contributors
2+
# See license.txt
3+
4+
# import frappe
5+
from frappe.tests.utils import FrappeTestCase
6+
7+
8+
class TestUserWhiteboardState(FrappeTestCase):
9+
pass
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) 2023, Build With Hussain and contributors
2+
// For license information, please see license.txt
3+
4+
// frappe.ui.form.on("User Whiteboard State", {
5+
// refresh(frm) {
6+
7+
// },
8+
// });
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"actions": [],
3+
"allow_rename": 1,
4+
"autoname": "field:user",
5+
"creation": "2023-12-12 16:49:41.103775",
6+
"doctype": "DocType",
7+
"engine": "InnoDB",
8+
"field_order": [
9+
"user",
10+
"state"
11+
],
12+
"fields": [
13+
{
14+
"fieldname": "user",
15+
"fieldtype": "Link",
16+
"in_list_view": 1,
17+
"label": "User",
18+
"options": "User",
19+
"reqd": 1,
20+
"unique": 1
21+
},
22+
{
23+
"default": "{}",
24+
"fieldname": "state",
25+
"fieldtype": "JSON",
26+
"label": "State",
27+
"read_only": 1
28+
}
29+
],
30+
"index_web_pages_for_search": 1,
31+
"links": [],
32+
"modified": "2023-12-12 16:50:40.005164",
33+
"modified_by": "Administrator",
34+
"module": "Tldraw Whiteboard",
35+
"name": "User Whiteboard State",
36+
"naming_rule": "By fieldname",
37+
"owner": "Administrator",
38+
"permissions": [
39+
{
40+
"create": 1,
41+
"delete": 1,
42+
"email": 1,
43+
"export": 1,
44+
"print": 1,
45+
"read": 1,
46+
"report": 1,
47+
"role": "System Manager",
48+
"share": 1,
49+
"write": 1
50+
}
51+
],
52+
"sort_field": "modified",
53+
"sort_order": "DESC",
54+
"states": []
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2023, Build With Hussain and contributors
2+
# For license information, please see license.txt
3+
4+
# import frappe
5+
from frappe.model.document import Document
6+
7+
8+
class UserWhiteboardState(Document):
9+
pass

0 commit comments

Comments
 (0)