mirror of
https://github.com/chartdb/chartdb.git
synced 2025-11-06 23:13:27 +00:00
feat: add sticky notes (#967)
* feat: add sticky notes * feat: add sticky notes
This commit is contained in:
@@ -24,6 +24,7 @@ import { defaultSchemas } from '@/lib/data/default-schemas';
|
||||
import { useEventEmitter } from 'ahooks';
|
||||
import type { DBDependency } from '@/lib/domain/db-dependency';
|
||||
import type { Area } from '@/lib/domain/area';
|
||||
import type { Note } from '@/lib/domain/note';
|
||||
import { storageInitialValue } from '../storage-context/storage-context';
|
||||
import { useDiff } from '../diff-context/use-diff';
|
||||
import type { DiffCalculatedEvent } from '../diff-context/diff-context';
|
||||
@@ -67,6 +68,7 @@ export const ChartDBProvider: React.FC<
|
||||
const [customTypes, setCustomTypes] = useState<DBCustomType[]>(
|
||||
diagram?.customTypes ?? []
|
||||
);
|
||||
const [notes, setNotes] = useState<Note[]>(diagram?.notes ?? []);
|
||||
|
||||
const { events: diffEvents } = useDiff();
|
||||
|
||||
@@ -147,6 +149,7 @@ export const ChartDBProvider: React.FC<
|
||||
dependencies,
|
||||
areas,
|
||||
customTypes,
|
||||
notes,
|
||||
}),
|
||||
[
|
||||
diagramId,
|
||||
@@ -158,6 +161,7 @@ export const ChartDBProvider: React.FC<
|
||||
dependencies,
|
||||
areas,
|
||||
customTypes,
|
||||
notes,
|
||||
diagramCreatedAt,
|
||||
diagramUpdatedAt,
|
||||
]
|
||||
@@ -171,6 +175,7 @@ export const ChartDBProvider: React.FC<
|
||||
setDependencies([]);
|
||||
setAreas([]);
|
||||
setCustomTypes([]);
|
||||
setNotes([]);
|
||||
setDiagramUpdatedAt(updatedAt);
|
||||
|
||||
resetRedoStack();
|
||||
@@ -183,6 +188,7 @@ export const ChartDBProvider: React.FC<
|
||||
db.deleteDiagramDependencies(diagramId),
|
||||
db.deleteDiagramAreas(diagramId),
|
||||
db.deleteDiagramCustomTypes(diagramId),
|
||||
db.deleteDiagramNotes(diagramId),
|
||||
]);
|
||||
}, [db, diagramId, resetRedoStack, resetUndoStack]);
|
||||
|
||||
@@ -197,6 +203,7 @@ export const ChartDBProvider: React.FC<
|
||||
setDependencies([]);
|
||||
setAreas([]);
|
||||
setCustomTypes([]);
|
||||
setNotes([]);
|
||||
resetRedoStack();
|
||||
resetUndoStack();
|
||||
|
||||
@@ -207,6 +214,7 @@ export const ChartDBProvider: React.FC<
|
||||
db.deleteDiagramDependencies(diagramId),
|
||||
db.deleteDiagramAreas(diagramId),
|
||||
db.deleteDiagramCustomTypes(diagramId),
|
||||
db.deleteDiagramNotes(diagramId),
|
||||
]);
|
||||
}, [db, diagramId, resetRedoStack, resetUndoStack]);
|
||||
|
||||
@@ -1528,6 +1536,130 @@ export const ChartDBProvider: React.FC<
|
||||
[db, diagramId, setAreas, getArea, addUndoAction, resetRedoStack]
|
||||
);
|
||||
|
||||
// Note operations
|
||||
const addNotes: ChartDBContext['addNotes'] = useCallback(
|
||||
async (notes: Note[], options = { updateHistory: true }) => {
|
||||
setNotes((currentNotes) => [...currentNotes, ...notes]);
|
||||
|
||||
const updatedAt = new Date();
|
||||
setDiagramUpdatedAt(updatedAt);
|
||||
|
||||
await Promise.all([
|
||||
...notes.map((note) => db.addNote({ diagramId, note })),
|
||||
db.updateDiagram({ id: diagramId, attributes: { updatedAt } }),
|
||||
]);
|
||||
|
||||
if (options.updateHistory) {
|
||||
addUndoAction({
|
||||
action: 'addNotes',
|
||||
redoData: { notes },
|
||||
undoData: { noteIds: notes.map((n) => n.id) },
|
||||
});
|
||||
resetRedoStack();
|
||||
}
|
||||
},
|
||||
[db, diagramId, setNotes, addUndoAction, resetRedoStack]
|
||||
);
|
||||
|
||||
const addNote: ChartDBContext['addNote'] = useCallback(
|
||||
async (note: Note, options = { updateHistory: true }) => {
|
||||
return addNotes([note], options);
|
||||
},
|
||||
[addNotes]
|
||||
);
|
||||
|
||||
const createNote: ChartDBContext['createNote'] = useCallback(
|
||||
async (attributes) => {
|
||||
const note: Note = {
|
||||
id: generateId(),
|
||||
content: '',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 200,
|
||||
height: 150,
|
||||
color: '#ffe374', // Default warm yellow
|
||||
...attributes,
|
||||
};
|
||||
|
||||
await addNote(note);
|
||||
|
||||
return note;
|
||||
},
|
||||
[addNote]
|
||||
);
|
||||
|
||||
const getNote: ChartDBContext['getNote'] = useCallback(
|
||||
(id: string) => notes.find((note) => note.id === id) ?? null,
|
||||
[notes]
|
||||
);
|
||||
|
||||
const removeNotes: ChartDBContext['removeNotes'] = useCallback(
|
||||
async (ids: string[], options = { updateHistory: true }) => {
|
||||
const prevNotes = [
|
||||
...notes.filter((note) => ids.includes(note.id)),
|
||||
];
|
||||
|
||||
setNotes((notes) => notes.filter((note) => !ids.includes(note.id)));
|
||||
|
||||
const updatedAt = new Date();
|
||||
setDiagramUpdatedAt(updatedAt);
|
||||
|
||||
await Promise.all([
|
||||
...ids.map((id) => db.deleteNote({ diagramId, id })),
|
||||
db.updateDiagram({ id: diagramId, attributes: { updatedAt } }),
|
||||
]);
|
||||
|
||||
if (prevNotes.length > 0 && options.updateHistory) {
|
||||
addUndoAction({
|
||||
action: 'removeNotes',
|
||||
redoData: { noteIds: ids },
|
||||
undoData: { notes: prevNotes },
|
||||
});
|
||||
resetRedoStack();
|
||||
}
|
||||
},
|
||||
[db, diagramId, setNotes, notes, addUndoAction, resetRedoStack]
|
||||
);
|
||||
|
||||
const removeNote: ChartDBContext['removeNote'] = useCallback(
|
||||
async (id: string, options = { updateHistory: true }) => {
|
||||
return removeNotes([id], options);
|
||||
},
|
||||
[removeNotes]
|
||||
);
|
||||
|
||||
const updateNote: ChartDBContext['updateNote'] = useCallback(
|
||||
async (
|
||||
id: string,
|
||||
note: Partial<Note>,
|
||||
options = { updateHistory: true }
|
||||
) => {
|
||||
const prevNote = getNote(id);
|
||||
|
||||
setNotes((notes) =>
|
||||
notes.map((n) => (n.id === id ? { ...n, ...note } : n))
|
||||
);
|
||||
|
||||
const updatedAt = new Date();
|
||||
setDiagramUpdatedAt(updatedAt);
|
||||
|
||||
await Promise.all([
|
||||
db.updateDiagram({ id: diagramId, attributes: { updatedAt } }),
|
||||
db.updateNote({ id, attributes: note }),
|
||||
]);
|
||||
|
||||
if (!!prevNote && options.updateHistory) {
|
||||
addUndoAction({
|
||||
action: 'updateNote',
|
||||
redoData: { noteId: id, note },
|
||||
undoData: { noteId: id, note: prevNote },
|
||||
});
|
||||
resetRedoStack();
|
||||
}
|
||||
},
|
||||
[db, diagramId, setNotes, getNote, addUndoAction, resetRedoStack]
|
||||
);
|
||||
|
||||
const highlightCustomTypeId = useCallback(
|
||||
(id?: string) => setHighlightedCustomTypeId(id),
|
||||
[setHighlightedCustomTypeId]
|
||||
@@ -1554,6 +1686,7 @@ export const ChartDBProvider: React.FC<
|
||||
setDiagramCreatedAt(diagram.createdAt);
|
||||
setDiagramUpdatedAt(diagram.updatedAt);
|
||||
setHighlightedCustomTypeId(undefined);
|
||||
setNotes(diagram.notes ?? []);
|
||||
|
||||
events.emit({ action: 'load_diagram', data: { diagram } });
|
||||
|
||||
@@ -1574,6 +1707,7 @@ export const ChartDBProvider: React.FC<
|
||||
setDiagramUpdatedAt,
|
||||
setHighlightedCustomTypeId,
|
||||
events,
|
||||
setNotes,
|
||||
resetRedoStack,
|
||||
resetUndoStack,
|
||||
]
|
||||
@@ -1597,6 +1731,7 @@ export const ChartDBProvider: React.FC<
|
||||
includeDependencies: true,
|
||||
includeAreas: true,
|
||||
includeCustomTypes: true,
|
||||
includeNotes: true,
|
||||
});
|
||||
|
||||
if (diagram) {
|
||||
@@ -1762,6 +1897,7 @@ export const ChartDBProvider: React.FC<
|
||||
relationships,
|
||||
dependencies,
|
||||
areas,
|
||||
notes,
|
||||
currentDiagram,
|
||||
schemas,
|
||||
events,
|
||||
@@ -1825,6 +1961,13 @@ export const ChartDBProvider: React.FC<
|
||||
updateCustomType,
|
||||
highlightCustomTypeId,
|
||||
highlightedCustomType,
|
||||
createNote,
|
||||
addNote,
|
||||
addNotes,
|
||||
getNote,
|
||||
removeNote,
|
||||
removeNotes,
|
||||
updateNote,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user