Abstract notes out of editor

This commit is contained in:
1ilit 2024-03-12 23:36:49 +02:00
parent d06074451e
commit 54c043204a
7 changed files with 169 additions and 142 deletions

View File

@ -1,9 +1,8 @@
import { useContext, useRef, useState, useEffect } from "react"; import { useRef, useState, useEffect } from "react";
import Table from "./Table"; import Table from "./Table";
import { Action, Cardinality, Constraint, ObjectType } from "../data/data"; import { Action, Cardinality, Constraint, ObjectType } from "../data/data";
import Area from "./Area"; import Area from "./Area";
import Relationship from "./Relationship"; import Relationship from "./Relationship";
import { NoteContext } from "../pages/Editor";
import Note from "./Note"; import Note from "./Note";
import { Toast } from "@douyinfe/semi-ui"; import { Toast } from "@douyinfe/semi-ui";
import useSettings from "../hooks/useSettings"; import useSettings from "../hooks/useSettings";
@ -12,11 +11,12 @@ import useTables from "../hooks/useTables";
import useUndoRedo from "../hooks/useUndoRedo"; import useUndoRedo from "../hooks/useUndoRedo";
import useSelect from "../hooks/useSelect"; import useSelect from "../hooks/useSelect";
import useAreas from "../hooks/useAreas"; import useAreas from "../hooks/useAreas";
import useNotes from "../hooks/useNotes";
export default function Canvas() { export default function Canvas() {
const { tables, updateTable, relationships, addRelationship } = useTables(); const { tables, updateTable, relationships, addRelationship } = useTables();
const { areas, updateArea } = useAreas(); const { areas, updateArea } = useAreas();
const { notes, updateNote } = useContext(NoteContext); const { notes, updateNote } = useNotes();
const { settings } = useSettings(); const { settings } = useSettings();
const { setUndoStack, setRedoStack } = useUndoRedo(); const { setUndoStack, setRedoStack } = useUndoRedo();
const { transform, setTransform } = useTransform(); const { transform, setTransform } = useTransform();

View File

@ -44,7 +44,6 @@ import {
jsonToSQLServer, jsonToSQLServer,
} from "../utils/toSQL"; } from "../utils/toSQL";
import { import {
NoteContext,
StateContext, StateContext,
TabContext, TabContext,
TypeContext, TypeContext,
@ -71,6 +70,7 @@ import { enterFullscreen, exitFullscreen } from "../utils/fullscreen";
import { ddbDiagramIsValid, jsonDiagramIsValid } from "../utils/validateSchema"; import { ddbDiagramIsValid, jsonDiagramIsValid } from "../utils/validateSchema";
import { dataURItoBlob } from "../utils/utils"; import { dataURItoBlob } from "../utils/utils";
import useAreas from "../hooks/useAreas"; import useAreas from "../hooks/useAreas";
import useNotes from "../hooks/useNotes";
export default function ControlPanel({ export default function ControlPanel({
diagramId, diagramId,
@ -138,7 +138,7 @@ export default function ControlPanel({
const { types, addType, deleteType, updateType, setTypes } = const { types, addType, deleteType, updateType, setTypes } =
useContext(TypeContext); useContext(TypeContext);
const { notes, setNotes, updateNote, addNote, deleteNote } = const { notes, setNotes, updateNote, addNote, deleteNote } =
useContext(NoteContext); useNotes();
const { areas, setAreas, updateArea, addArea, deleteArea } = useAreas(); const { areas, setAreas, updateArea, addArea, deleteArea } = useAreas();
const { undoStack, redoStack, setUndoStack, setRedoStack } = useUndoRedo(); const { undoStack, redoStack, setUndoStack, setRedoStack } = useUndoRedo();
const { selectedElement, setSelectedElement } = useSelect(); const { selectedElement, setSelectedElement } = useSelect();

View File

@ -1,5 +1,5 @@
import { useContext, useState } from "react"; import { useContext, useState } from "react";
import { NoteContext, TabContext, StateContext } from "../pages/Editor"; import { TabContext, StateContext } from "../pages/Editor";
import { Action, ObjectType, noteThemes, Tab, State } from "../data/data"; import { Action, ObjectType, noteThemes, Tab, State } from "../data/data";
import { Input, Button, Popover, Toast } from "@douyinfe/semi-ui"; import { Input, Button, Popover, Toast } from "@douyinfe/semi-ui";
import { import {
@ -10,6 +10,7 @@ import {
import useLayout from "../hooks/useLayout"; import useLayout from "../hooks/useLayout";
import useUndoRedo from "../hooks/useUndoRedo"; import useUndoRedo from "../hooks/useUndoRedo";
import useSelect from "../hooks/useSelect"; import useSelect from "../hooks/useSelect";
import useNotes from "../hooks/useNotes";
export default function Note(props) { export default function Note(props) {
const [editField, setEditField] = useState({}); const [editField, setEditField] = useState({});
@ -17,7 +18,7 @@ export default function Note(props) {
const w = 180; const w = 180;
const r = 3; const r = 3;
const fold = 24; const fold = 24;
const { updateNote, deleteNote } = useContext(NoteContext); const { updateNote, deleteNote } = useNotes();
const { setUndoStack, setRedoStack } = useUndoRedo(); const { setUndoStack, setRedoStack } = useUndoRedo();
const { setState } = useContext(StateContext); const { setState } = useContext(StateContext);
const { layout } = useLayout(); const { layout } = useLayout();

View File

@ -1,4 +1,4 @@
import { useContext, useState } from "react"; import { useState } from "react";
import { import {
Empty, Empty,
Row, Row,
@ -21,12 +21,12 @@ import {
IconSearch, IconSearch,
IconCheckboxTick, IconCheckboxTick,
} from "@douyinfe/semi-icons"; } from "@douyinfe/semi-icons";
import { NoteContext } from "../pages/Editor";
import { noteThemes, Action, ObjectType } from "../data/data"; import { noteThemes, Action, ObjectType } from "../data/data";
import useUndoRedo from "../hooks/useUndoRedo"; import useUndoRedo from "../hooks/useUndoRedo";
import useNotes from "../hooks/useNotes";
export default function NotesOverview() { export default function NotesOverview() {
const { notes, updateNote, addNote, deleteNote } = useContext(NoteContext); const { notes, updateNote, addNote, deleteNote } = useNotes();
const { setUndoStack, setRedoStack } = useUndoRedo(); const { setUndoStack, setRedoStack } = useUndoRedo();
const [value, setValue] = useState(""); const [value, setValue] = useState("");
const [editField, setEditField] = useState({}); const [editField, setEditField] = useState({});

View File

@ -0,0 +1,96 @@
import { createContext, useState } from "react";
import useTransform from "../hooks/useTransform";
import { Action, ObjectType, defaultNoteTheme } from "../data/data";
import useUndoRedo from "../hooks/useUndoRedo";
import useSelect from "../hooks/useSelect";
export const NotesContext = createContext(null);
export default function NotesContextProvider({ children }) {
const [notes, setNotes] = useState([]);
const { transform } = useTransform();
const { setUndoStack, setRedoStack } = useUndoRedo();
const { selectedElement, setSelectedElement } = useSelect();
const addNote = (addToHistory = true, data) => {
if (data) {
setNotes((prev) => {
const temp = prev.slice();
temp.splice(data.id, 0, data);
return temp.map((t, i) => ({ ...t, id: i }));
});
} else {
setNotes((prev) => [
...prev,
{
id: prev.length,
x: -transform.pan.x,
y: -transform.pan.y,
title: `note_${prev.length}`,
content: "",
color: defaultNoteTheme,
height: 88,
},
]);
}
if (addToHistory) {
setUndoStack((prev) => [
...prev,
{
action: Action.ADD,
element: ObjectType.NOTE,
message: `Add new note`,
},
]);
setRedoStack([]);
}
};
const deleteNote = (id, addToHistory = true) => {
if (addToHistory) {
setUndoStack((prev) => [
...prev,
{
action: Action.DELETE,
element: ObjectType.NOTE,
data: notes[id],
message: `Delete note`,
},
]);
setRedoStack([]);
}
setNotes((prev) =>
prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i }))
);
if (id === selectedElement.id) {
setSelectedElement({
element: ObjectType.NONE,
id: -1,
openDialogue: false,
openCollapse: false,
});
}
};
const updateNote = (id, values) => {
setNotes((prev) =>
prev.map((t) => {
if (t.id === id) {
return {
...t,
...values,
};
}
return t;
})
);
};
return (
<NotesContext.Provider
value={{ notes, setNotes, updateNote, addNote, deleteNote }}
>
{children}
</NotesContext.Provider>
);
}

6
src/hooks/useNotes.js Normal file
View File

@ -0,0 +1,6 @@
import { useContext } from "react";
import { NotesContext } from "../context/NotesContext";
export default function useNotes() {
return useContext(NotesContext);
}

View File

@ -2,7 +2,7 @@ import { useState, createContext, useEffect, useCallback } from "react";
import ControlPanel from "../components/ControlPanel"; import ControlPanel from "../components/ControlPanel";
import Canvas from "../components/Canvas"; import Canvas from "../components/Canvas";
import SidePanel from "../components/SidePanel"; import SidePanel from "../components/SidePanel";
import { Tab, defaultNoteTheme, Action, ObjectType, State } from "../data/data"; import { Tab, Action, ObjectType, State } from "../data/data";
import { db } from "../data/db"; import { db } from "../data/db";
import useLayout from "../hooks/useLayout"; import useLayout from "../hooks/useLayout";
import LayoutContextProvider from "../context/LayoutContext"; import LayoutContextProvider from "../context/LayoutContext";
@ -15,13 +15,13 @@ import useUndoRedo from "../hooks/useUndoRedo";
import UndoRedoContextProvider from "../context/UndoRedoContext"; import UndoRedoContextProvider from "../context/UndoRedoContext";
import SelectContextProvider from "../context/SelectContext"; import SelectContextProvider from "../context/SelectContext";
import AreasContextProvider from "../context/AreasContext"; import AreasContextProvider from "../context/AreasContext";
import useSelect from "../hooks/useSelect";
import Controls from "../components/Controls"; import Controls from "../components/Controls";
import useAreas from "../hooks/useAreas"; import useAreas from "../hooks/useAreas";
import useNotes from "../hooks/useNotes";
import NotesContextProvider from "../context/NotesContext";
export const StateContext = createContext(); export const StateContext = createContext();
export const TabContext = createContext(); export const TabContext = createContext();
export const NoteContext = createContext();
export const TaskContext = createContext(); export const TaskContext = createContext();
export const TypeContext = createContext(); export const TypeContext = createContext();
@ -32,9 +32,11 @@ export default function Editor() {
<UndoRedoContextProvider> <UndoRedoContextProvider>
<SelectContextProvider> <SelectContextProvider>
<AreasContextProvider> <AreasContextProvider>
<TablesContextProvider> <NotesContextProvider>
<WorkSpace /> <TablesContextProvider>
</TablesContextProvider> <WorkSpace />
</TablesContextProvider>
</NotesContextProvider>
</AreasContextProvider> </AreasContextProvider>
</SelectContextProvider> </SelectContextProvider>
</UndoRedoContextProvider> </UndoRedoContextProvider>
@ -48,18 +50,17 @@ function WorkSpace() {
const [title, setTitle] = useState("Untitled Diagram"); const [title, setTitle] = useState("Untitled Diagram");
const [state, setState] = useState(State.NONE); const [state, setState] = useState(State.NONE);
const [lastSaved, setLastSaved] = useState(""); const [lastSaved, setLastSaved] = useState("");
const { tables, relationships, setTables, setRelationships } = useTables();
const [notes, setNotes] = useState([]);
const [types, setTypes] = useState([]); const [types, setTypes] = useState([]);
const [resize, setResize] = useState(false); const [resize, setResize] = useState(false);
const [width, setWidth] = useState(340); const [width, setWidth] = useState(340);
const [tab, setTab] = useState(Tab.tables); const [tab, setTab] = useState(Tab.tables);
const { layout } = useLayout();
const { settings, setSettings } = useSettings();
const { transform, setTransform } = useTransform();
const { selectedElement, setSelectedElement } = useSelect();
const { areas, setAreas } = useAreas();
const [tasks, setTasks] = useState([]); const [tasks, setTasks] = useState([]);
const { layout } = useLayout();
const { areas, setAreas } = useAreas();
const { settings, setSettings } = useSettings();
const { notes, setNotes } = useNotes();
const { transform, setTransform } = useTransform();
const { tables, relationships, setTables, setRelationships } = useTables();
const { undoStack, redoStack, setUndoStack, setRedoStack } = useUndoRedo(); const { undoStack, redoStack, setUndoStack, setRedoStack } = useUndoRedo();
const dragHandler = (e) => { const dragHandler = (e) => {
@ -121,80 +122,6 @@ function WorkSpace() {
); );
}; };
const addNote = (addToHistory = true, data) => {
if (data) {
setNotes((prev) => {
const temp = prev.slice();
temp.splice(data.id, 0, data);
return temp.map((t, i) => ({ ...t, id: i }));
});
} else {
setNotes((prev) => [
...prev,
{
id: prev.length,
x: -transform.pan.x,
y: -transform.pan.y,
title: `note_${prev.length}`,
content: "",
color: defaultNoteTheme,
height: 88,
},
]);
}
if (addToHistory) {
setUndoStack((prev) => [
...prev,
{
action: Action.ADD,
element: ObjectType.NOTE,
message: `Add new note`,
},
]);
setRedoStack([]);
}
};
const deleteNote = (id, addToHistory = true) => {
if (addToHistory) {
setUndoStack((prev) => [
...prev,
{
action: Action.DELETE,
element: ObjectType.NOTE,
data: notes[id],
message: `Delete note`,
},
]);
setRedoStack([]);
}
setNotes((prev) =>
prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i }))
);
if (id === selectedElement.id) {
setSelectedElement({
element: ObjectType.NONE,
id: -1,
openDialogue: false,
openCollapse: false,
});
}
};
const updateNote = (id, values) => {
setNotes((prev) =>
prev.map((t) => {
if (t.id === id) {
return {
...t,
...values,
};
}
return t;
})
);
};
const updateTask = (id, values) => const updateTask = (id, values) =>
setTasks((prev) => setTasks((prev) =>
prev.map((task, i) => (id === i ? { ...task, ...values } : task)) prev.map((task, i) => (id === i ? { ...task, ...values } : task))
@ -433,59 +360,56 @@ function WorkSpace() {
setRelationships, setRelationships,
setTables, setTables,
setAreas, setAreas,
setNotes,
]); ]);
return ( return (
<StateContext.Provider value={{ state, setState }}> <StateContext.Provider value={{ state, setState }}>
<NoteContext.Provider <TabContext.Provider value={{ tab, setTab }}>
value={{ notes, setNotes, updateNote, addNote, deleteNote }} <TypeContext.Provider
> value={{
<TabContext.Provider value={{ tab, setTab }}> types,
<TypeContext.Provider setTypes,
value={{ addType,
types, updateType,
setTypes, deleteType,
addType, }}
updateType, >
deleteType, <div className="h-[100vh] flex flex-col overflow-hidden theme">
}} <TaskContext.Provider value={{ tasks, setTasks, updateTask }}>
> <ControlPanel
<div className="h-[100vh] flex flex-col overflow-hidden theme"> diagramId={id}
<TaskContext.Provider value={{ tasks, setTasks, updateTask }}> setDiagramId={setId}
<ControlPanel title={title}
diagramId={id} setTitle={setTitle}
setDiagramId={setId} lastSaved={lastSaved}
title={title} setLastSaved={setLastSaved}
setTitle={setTitle} />
lastSaved={lastSaved} </TaskContext.Provider>
setLastSaved={setLastSaved} <div
className="flex h-full overflow-y-auto"
onMouseUp={() => setResize(false)}
onMouseMove={dragHandler}
>
{layout.sidebar && (
<SidePanel
resize={resize}
setResize={setResize}
width={width}
/> />
</TaskContext.Provider> )}
<div <div className="relative w-full h-full overflow-hidden">
className="flex h-full overflow-y-auto" <Canvas state={state} setState={setState} />
onMouseUp={() => setResize(false)} {!(layout.sidebar || layout.toolbar || layout.header) && (
onMouseMove={dragHandler} <div className="fixed right-5 bottom-4">
> <Controls />
{layout.sidebar && ( </div>
<SidePanel
resize={resize}
setResize={setResize}
width={width}
/>
)} )}
<div className="relative w-full h-full overflow-hidden">
<Canvas state={state} setState={setState} />
{!(layout.sidebar || layout.toolbar || layout.header) && (
<div className="fixed right-5 bottom-4">
<Controls />
</div>
)}
</div>
</div> </div>
</div> </div>
</TypeContext.Provider> </div>
</TabContext.Provider> </TypeContext.Provider>
</NoteContext.Provider> </TabContext.Provider>
</StateContext.Provider> </StateContext.Provider>
); );
} }