mirror of
https://github.com/ruilisi/fortune-sheet.git
synced 2025-01-09 04:07:33 +08:00
135 lines
3.5 KiB
TypeScript
135 lines
3.5 KiB
TypeScript
import React, {
|
|
useState,
|
|
useCallback,
|
|
useEffect,
|
|
useRef,
|
|
useMemo,
|
|
} from "react";
|
|
import { Meta, StoryFn } from "@storybook/react";
|
|
import { Sheet, Op, Selection, colors } from "@fortune-sheet/core";
|
|
import { Workbook, WorkbookInstance } from "@fortune-sheet/react";
|
|
import { v4 as uuidv4 } from "uuid";
|
|
import { hashCode } from "./utils";
|
|
|
|
export default {
|
|
component: Workbook,
|
|
} as Meta<typeof Workbook>;
|
|
|
|
const Template: StoryFn<typeof Workbook> = ({ ...args }) => {
|
|
const [data, setData] = useState<Sheet[]>();
|
|
const [error, setError] = useState(false);
|
|
const wsRef = useRef<WebSocket>();
|
|
const workbookRef = useRef<WorkbookInstance>(null);
|
|
const lastSelection = useRef<any>();
|
|
const { username, userId } = useMemo(() => {
|
|
const _userId = uuidv4();
|
|
return { username: `User-${_userId.slice(0, 3)}`, userId: _userId };
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const socket = new WebSocket("ws://localhost:8081/ws");
|
|
wsRef.current = socket;
|
|
|
|
socket.onopen = () => {
|
|
socket.send(JSON.stringify({ req: "getData" }));
|
|
};
|
|
socket.onmessage = (e) => {
|
|
const msg = JSON.parse(e.data);
|
|
if (msg.req === "getData") {
|
|
setData(msg.data.map((d: any) => ({ id: d._id, ...d })));
|
|
} else if (msg.req === "op") {
|
|
workbookRef.current?.applyOp(msg.data);
|
|
} else if (msg.req === "addPresences") {
|
|
workbookRef.current?.addPresences(msg.data);
|
|
} else if (msg.req === "removePresences") {
|
|
workbookRef.current?.removePresences(msg.data);
|
|
}
|
|
};
|
|
socket.onerror = () => {
|
|
setError(true);
|
|
};
|
|
}, []);
|
|
|
|
const onOp = useCallback((op: Op[]) => {
|
|
const socket = wsRef.current;
|
|
if (!socket) return;
|
|
socket.send(JSON.stringify({ req: "op", data: op }));
|
|
}, []);
|
|
|
|
const onChange = useCallback((d: Sheet[]) => {
|
|
setData(d);
|
|
}, []);
|
|
|
|
const afterSelectionChange = useCallback(
|
|
(sheetId: string, selection: Selection) => {
|
|
const socket = wsRef.current;
|
|
if (!socket) return;
|
|
const s = {
|
|
r: selection.row[0],
|
|
c: selection.column[0],
|
|
};
|
|
if (
|
|
lastSelection.current?.r === s.r &&
|
|
lastSelection.current?.c === s.c
|
|
) {
|
|
return;
|
|
}
|
|
lastSelection.current = s;
|
|
socket.send(
|
|
JSON.stringify({
|
|
req: "addPresences",
|
|
data: [
|
|
{
|
|
sheetId,
|
|
username,
|
|
userId,
|
|
color: colors[Math.abs(hashCode(userId)) % colors.length],
|
|
selection: s,
|
|
},
|
|
],
|
|
})
|
|
);
|
|
},
|
|
[userId, username]
|
|
);
|
|
|
|
if (error)
|
|
return (
|
|
<div style={{ padding: 16 }}>
|
|
<p>Failed to connect to websocket server.</p>
|
|
<p>
|
|
Please note that this collabration demo connects to a local websocket
|
|
server (ws://localhost:8081/ws).
|
|
</p>
|
|
<p>
|
|
To make this work:
|
|
<ol>
|
|
<li>Clone the project</li>
|
|
<li>Run server in backend-demo/: node index.js</li>
|
|
<li>Make sure you also have mongodb running locally</li>
|
|
<li>Try again</li>
|
|
</ol>
|
|
</p>
|
|
</div>
|
|
);
|
|
|
|
if (!data) return <div />;
|
|
|
|
return (
|
|
<div style={{ width: "100%", height: "100vh" }}>
|
|
<Workbook
|
|
ref={workbookRef}
|
|
{...args}
|
|
data={data}
|
|
onChange={onChange}
|
|
onOp={onOp}
|
|
hooks={{
|
|
afterSelectionChange,
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const Example = Template.bind({});
|