diff --git a/src/components/Workspace.jsx b/src/components/Workspace.jsx
index 0cbd0e8..a2c5e29 100644
--- a/src/components/Workspace.jsx
+++ b/src/components/Workspace.jsx
@@ -25,11 +25,11 @@ export default function WorkSpace() {
const [width, setWidth] = useState(340);
const [lastSaved, setLastSaved] = useState("");
const { layout } = useLayout();
+ const { settings } = useSettings();
const { types, setTypes } = useTypes();
const { areas, setAreas } = useAreas();
const { tasks, setTasks } = useTasks();
const { notes, setNotes } = useNotes();
- const { settings, setSettings } = useSettings();
const { saveState, setSaveState } = useSaveState();
const { transform, setTransform } = useTransform();
const { tables, relationships, setTables, setRelationships } = useTables();
@@ -41,6 +41,200 @@ export default function WorkSpace() {
if (w > 340) setWidth(w);
};
+ const save = useCallback(async () => {
+ const name = window.name.split(" ");
+ const op = name[0];
+ const saveAsDiagram = window.name === "" || op === "d" || op === "lt";
+
+ if (saveAsDiagram) {
+ if (
+ (id === 0 && window.name === "") ||
+ window.name.split(" ")[0] === "lt"
+ ) {
+ await db.diagrams
+ .add({
+ name: title,
+ lastModified: new Date(),
+ tables: tables,
+ references: relationships,
+ types: types,
+ notes: notes,
+ areas: areas,
+ todos: tasks,
+ pan: transform.pan,
+ zoom: transform.zoom,
+ })
+ .then((id) => {
+ setId(id);
+ window.name = `d ${id}`;
+ setSaveState(State.SAVED);
+ setLastSaved(new Date().toLocaleString());
+ });
+ } else {
+ await db.diagrams
+ .update(id, {
+ name: title,
+ lastModified: new Date(),
+ tables: tables,
+ references: relationships,
+ types: types,
+ notes: notes,
+ areas: areas,
+ todos: tasks,
+ pan: transform.pan,
+ zoom: transform.zoom,
+ })
+ .then(() => {
+ setSaveState(State.SAVED);
+ setLastSaved(new Date().toLocaleString());
+ });
+ }
+ } else {
+ await db.templates
+ .update(id, {
+ title: title,
+ tables: tables,
+ relationships: relationships,
+ types: types,
+ notes: notes,
+ subjectAreas: areas,
+ todos: tasks,
+ pan: transform.pan,
+ zoom: transform.zoom,
+ })
+ .then(() => {
+ setSaveState(State.SAVED);
+ setLastSaved(new Date().toLocaleString());
+ })
+ .catch(() => {
+ setSaveState(State.ERROR);
+ });
+ }
+ }, [
+ tables,
+ relationships,
+ notes,
+ areas,
+ types,
+ title,
+ id,
+ tasks,
+ transform,
+ setSaveState,
+ ]);
+
+ const load = useCallback(async () => {
+ const loadLatestDiagram = async () => {
+ await db.diagrams
+ .orderBy("lastModified")
+ .last()
+ .then((d) => {
+ if (d) {
+ setId(d.id);
+ setTables(d.tables);
+ setRelationships(d.references);
+ setNotes(d.notes);
+ setAreas(d.areas);
+ setTypes(d.types);
+ setTasks(d.todos ?? []);
+ setTransform({ pan: d.pan, zoom: d.zoom });
+ window.name = `d ${d.id}`;
+ } else {
+ window.name = "";
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ });
+ };
+
+ const loadDiagram = async (id) => {
+ await db.diagrams
+ .get(id)
+ .then((diagram) => {
+ if (diagram) {
+ setId(diagram.id);
+ setTitle(diagram.name);
+ setTables(diagram.tables);
+ setTypes(diagram.types);
+ setRelationships(diagram.references);
+ setAreas(diagram.areas);
+ setNotes(diagram.notes);
+ setTasks(diagram.todos ?? []);
+ setTransform({
+ pan: diagram.pan,
+ zoom: diagram.zoom,
+ });
+ setUndoStack([]);
+ setRedoStack([]);
+ window.name = `d ${diagram.id}`;
+ } else {
+ window.name = "";
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ });
+ };
+
+ const loadTemplate = async (id) => {
+ await db.templates
+ .get(id)
+ .then((diagram) => {
+ if (diagram) {
+ setId(diagram.id);
+ setTitle(diagram.title);
+ setTables(diagram.tables);
+ setTypes(diagram.types);
+ setRelationships(diagram.relationships);
+ setAreas(diagram.subjectAreas);
+ setTasks(diagram.todos ?? []);
+ setNotes(diagram.notes);
+ setTransform({
+ zoom: 1,
+ pan: { x: 0, y: 0 },
+ });
+ setUndoStack([]);
+ setRedoStack([]);
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ });
+ };
+
+ if (window.name === "") {
+ loadLatestDiagram();
+ } else {
+ const name = window.name.split(" ");
+ const op = name[0];
+ const id = parseInt(name[1]);
+ switch (op) {
+ case "d": {
+ loadDiagram(id);
+ break;
+ }
+ case "t":
+ case "lt": {
+ loadTemplate(id);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }, [
+ setTransform,
+ setRedoStack,
+ setUndoStack,
+ setRelationships,
+ setTables,
+ setAreas,
+ setNotes,
+ setTypes,
+ setTasks,
+ ]);
+
useEffect(() => {
if (
tables?.length === 0 &&
@@ -69,217 +263,17 @@ export default function WorkSpace() {
setSaveState,
]);
- const save = useCallback(
- async (diagram = true) => {
- if (saveState !== State.SAVING) {
- return;
- }
- if (diagram) {
- if (
- (id === 0 && window.name === "") ||
- window.name.split(" ")[0] === "lt"
- ) {
- db.diagrams
- .add({
- name: title,
- lastModified: new Date(),
- tables: tables,
- references: relationships,
- types: types,
- notes: notes,
- areas: areas,
- todos: tasks,
- pan: transform.pan,
- zoom: transform.zoom,
- })
- .then((id) => {
- setId(id);
- window.name = `d ${id}`;
- setSaveState(State.SAVED);
- setLastSaved(new Date().toLocaleString());
- });
- } else {
- db.diagrams
- .update(id, {
- name: title,
- lastModified: new Date(),
- tables: tables,
- references: relationships,
- types: types,
- notes: notes,
- areas: areas,
- todos: tasks,
- pan: transform.pan,
- zoom: transform.zoom,
- })
- .then(() => {
- setSaveState(State.SAVED);
- setLastSaved(new Date().toLocaleString());
- });
- }
- } else {
- db.templates
- .update(id, {
- title: title,
- tables: tables,
- relationships: relationships,
- types: types,
- notes: notes,
- subjectAreas: areas,
- todos: tasks,
- pan: transform.pan,
- zoom: transform.zoom,
- })
- .then(() => {
- setSaveState(State.SAVED);
- setLastSaved(new Date().toLocaleString());
- })
- .catch(() => {
- setSaveState(State.ERROR);
- });
- }
- },
- [
- tables,
- relationships,
- notes,
- areas,
- types,
- title,
- id,
- saveState,
- tasks,
- transform.zoom,
- transform.pan,
- setSaveState,
- ]
- );
useEffect(() => {
- const name = window.name.split(" ");
- const op = name[0];
- const diagram = window.name === "" || op === "d" || op === "lt";
+ if (saveState !== State.SAVING) return;
- save(diagram);
+ save();
}, [id, saveState, save]);
useEffect(() => {
document.title = "Editor | drawDB";
- const loadLatestDiagram = async () => {
- db.diagrams
- .orderBy("lastModified")
- .last()
- .then((d) => {
- if (d) {
- setId(d.id);
- setTables(d.tables);
- setRelationships(d.references);
- setNotes(d.notes);
- setAreas(d.areas);
- setTypes(d.types);
- setTasks(d.todos ?? []);
- setTransform({ pan: d.pan, zoom: d.zoom });
- window.name = `d ${d.id}`;
- } else {
- window.name = "";
- }
- })
- .catch((error) => {
- console.log(error);
- });
- };
-
- const loadDiagram = async (id) => {
- db.diagrams
- .get(id)
- .then((diagram) => {
- if (diagram) {
- setId(diagram.id);
- setTitle(diagram.name);
- setTables(diagram.tables);
- setTypes(diagram.types);
- setRelationships(diagram.references);
- setAreas(diagram.areas);
- setNotes(diagram.notes);
- setTasks(diagram.todos ?? []);
- setTransform({
- pan: diagram.pan,
- zoom: diagram.zoom,
- });
- setUndoStack([]);
- setRedoStack([]);
- window.name = `d ${diagram.id}`;
- } else {
- window.name = "";
- }
- })
- .catch((error) => {
- console.log(error);
- });
- };
-
- const loadTemplate = async (id) => {
- db.templates
- .get(id)
- .then((diagram) => {
- if (diagram) {
- setId(diagram.id);
- setTitle(diagram.title);
- setTables(diagram.tables);
- setTypes(diagram.types);
- setRelationships(diagram.relationships);
- setAreas(diagram.subjectAreas);
- setTasks(diagram.todos ?? []);
- setNotes(diagram.notes);
- setTransform({
- zoom: 1,
- pan: { x: 0, y: 0 },
- });
- setUndoStack([]);
- setRedoStack([]);
- }
- })
- .catch((error) => {
- console.log(error);
- });
- };
-
- if (window.name == "") {
- console.log("Loading the latest diagram");
- loadLatestDiagram();
- } else {
- const name = window.name.split(" ");
- const op = name[0];
- const did = parseInt(name[1]);
- switch (op) {
- case "d": {
- loadDiagram(did);
- break;
- }
- case "lt": {
- loadTemplate(did);
- break;
- }
- case "t": {
- loadTemplate(did);
- break;
- }
- default:
- break;
- }
- }
- }, [
- setSettings,
- setTransform,
- setRedoStack,
- setUndoStack,
- setRelationships,
- setTables,
- setAreas,
- setNotes,
- setTypes,
- setTasks,
- ]);
+ load();
+ }, [load]);
return (
diff --git a/src/data/shortcuts.js b/src/data/shortcuts.js
new file mode 100644
index 0000000..38cc673
--- /dev/null
+++ b/src/data/shortcuts.js
@@ -0,0 +1,48 @@
+export const shortcuts = [
+ { shortcut: "CTRL+S", title: "Save diagram", description: "" },
+ { shortcut: "CTRL+Shift+S", title: "Save diagram as", description: "" },
+ {
+ shortcut: "CTRL+O",
+ title: "Open a diagram",
+ description: "Load a saved diagram",
+ },
+ { shortcut: "CTRL+C", title: "Copy selected element", description: "" },
+ { shortcut: "CTRL+V", title: "Paste selected element", description: "" },
+ { shortcut: "CTRL+X", title: "Cut selected element", description: "" },
+ { shortcut: "CTRL+D", title: "Duplicate selected element", description: "" },
+ { shortcut: "DEL", title: "Delete selected element", description: "" },
+ { shortcut: "CTRL+E", title: "Edit selected element", description: "" },
+ {
+ shortcut: "CTRL+I",
+ title: "Import a diagram",
+ description: "Import a diagram by uploadng a valid json or dbb file.",
+ },
+ { shortcut: "CTRL+Z", title: "Undo" },
+ { shortcut: "CTRL+Y", title: "Redo" },
+ {
+ shortcut: "CTRL+SHIFT+M",
+ title: "Enable/disable strict mode",
+ description:
+ "Disabling strict mode entails that the diagram will not undergo error or inconsistency checks.",
+ },
+ {
+ shortcut: "CTRL+SHIFT+F",
+ title: "Enable/disable field summaries",
+ description:
+ "Disabling field summaries will prevent the display of details for each field in the table when hovered over.",
+ },
+ { shortcut: "CTRL+SHIFT+G", title: "Show/hide grid" },
+ {
+ shortcut: "CTRL+ALT+C",
+ title: "Copy as image",
+ description: "Save the canvas as an image to the clipboard.",
+ },
+ {
+ shortcut: "CTRL+R",
+ title: "Reset view",
+ description: "Resetting view will set diagram pan to (0, 0).",
+ },
+ { shortcut: "CTRL+UP / Wheel up", title: "Zoom in" },
+ { shortcut: "CTRL+DOWN / Wheel down", title: "Zoom out" },
+ { shortcut: "CTRL+H", title: "Open shortcuts" },
+];
diff --git a/src/data/surveyQuestions.js b/src/data/surveyQuestions.js
new file mode 100644
index 0000000..32f8ce0
--- /dev/null
+++ b/src/data/surveyQuestions.js
@@ -0,0 +1,10 @@
+export const questions = {
+ satisfaction: "How satisfied are you with drawDB?",
+ ease: "How easy was it to get started with drawDB?",
+ wouldRecommend: "How likely are you to recommend drawDB?",
+ hadDifficulty: "Did you encounter any difficulties when navigating drawDB?",
+ difficulty: "What were the difficulties you faced?",
+ triedOtherApps: "Have you tried apps like drawDB?",
+ comparison: "How did you find drawDB as compared to other apps?",
+ occupation: "What is your occupation?",
+};
diff --git a/src/pages/LandingPage.jsx b/src/pages/LandingPage.jsx
index 6b6aebe..2097b47 100644
--- a/src/pages/LandingPage.jsx
+++ b/src/pages/LandingPage.jsx
@@ -14,127 +14,6 @@ import discord from "../assets/discord.png";
import FadeIn from "../animations/FadeIn";
import SlideIn from "../animations/SlideIn";
-const features = [
- {
- title: "Export",
- content: (
-
- Export the DDL script to run on your database or export the diagram as a
- JSON or an image.
-
- ),
- footer: "",
- },
- {
- title: "Import",
- content: (
-
- Already have a diagram? Import a DDL script*, or a JSON file to generate
- or a diagram.
-
- ),
- footer: "*Only MySQL supported, more coming soon.",
- },
- {
- title: "Customizable workspace",
- content: (
-
- Customize the UI to fit your preferences. Select the components you want
- in your view.
-
- ),
- footer: "",
- },
- {
- title: "Keyboard shortcuts",
- content: (
-
- Speed up development with keyboard shortuts. See all available shortcuts
-
- here
-
- .
-
- ),
- footer: "",
- },
- {
- title: "Templates",
- content: (
-
- Start off with pre-built templates. Get a quick start or get inspirition
- for your design.
-
- ),
- footer: "",
- },
- {
- title: "Custom Templates",
- content: (
-
- Have boilerplate structures? Save time by saving them as templates and
- load them when needed.
-
- ),
- footer: "",
- },
- {
- title: "Robust editor",
- content: (
-
- Undo, redo, copy, paste, duplacate and more. Add tables, subject areas,
- and notes.
-
- ),
- footer: "",
- },
- {
- title: "Issue detection",
- content: (
-
- Detect and tackle errors in the diagram to make sure the scripts are
- correct.
-
- ),
- footer: "",
- },
- {
- title: "Relational databases",
- content: (
-
- We support 5 relational databases - MySQL, PostgreSQL, SQLite, MariaDB,
- SQL Server.
-
- ),
- footer: "",
- },
- {
- title: "Object-Relational databases",
- content: (
-
- Add custom types for object-relational databases, or create custom JSON
- schemes and alias types.
-
- ),
- footer: "",
- },
- {
- title: "Presentation mode",
- content: (
-
- Present your diagrams on a big screen during team meetings and
- discussions.
-
- ),
- footer: "",
- },
- {
- title: "Track todos",
- content:
Keep track of tasks and mark them done when finished.
,
- footer: "",
- },
-];
-
export default function LandingPage() {
const [showSurvey, setShowSurvey] = useState(true);
@@ -379,3 +258,124 @@ export default function LandingPage() {
);
}
+
+const features = [
+ {
+ title: "Export",
+ content: (
+
+ Export the DDL script to run on your database or export the diagram as a
+ JSON or an image.
+
+ ),
+ footer: "",
+ },
+ {
+ title: "Import",
+ content: (
+
+ Already have a diagram? Import a DDL script*, or a JSON file to generate
+ or a diagram.
+
+ ),
+ footer: "*Only MySQL supported, more coming soon.",
+ },
+ {
+ title: "Customizable workspace",
+ content: (
+
+ Customize the UI to fit your preferences. Select the components you want
+ in your view.
+
+ ),
+ footer: "",
+ },
+ {
+ title: "Keyboard shortcuts",
+ content: (
+
+ Speed up development with keyboard shortuts. See all available shortcuts
+
+ here
+
+ .
+
+ ),
+ footer: "",
+ },
+ {
+ title: "Templates",
+ content: (
+
+ Start off with pre-built templates. Get a quick start or get inspirition
+ for your design.
+
+ ),
+ footer: "",
+ },
+ {
+ title: "Custom Templates",
+ content: (
+
+ Have boilerplate structures? Save time by saving them as templates and
+ load them when needed.
+
+ ),
+ footer: "",
+ },
+ {
+ title: "Robust editor",
+ content: (
+
+ Undo, redo, copy, paste, duplacate and more. Add tables, subject areas,
+ and notes.
+
+ ),
+ footer: "",
+ },
+ {
+ title: "Issue detection",
+ content: (
+
+ Detect and tackle errors in the diagram to make sure the scripts are
+ correct.
+
+ ),
+ footer: "",
+ },
+ {
+ title: "Relational databases",
+ content: (
+
+ We support 5 relational databases - MySQL, PostgreSQL, SQLite, MariaDB,
+ SQL Server.
+
+ ),
+ footer: "",
+ },
+ {
+ title: "Object-Relational databases",
+ content: (
+
+ Add custom types for object-relational databases, or create custom JSON
+ schemes and alias types.
+
+ ),
+ footer: "",
+ },
+ {
+ title: "Presentation mode",
+ content: (
+
+ Present your diagrams on a big screen during team meetings and
+ discussions.
+
+ ),
+ footer: "",
+ },
+ {
+ title: "Track todos",
+ content: Keep track of tasks and mark them done when finished.
,
+ footer: "",
+ },
+];
\ No newline at end of file
diff --git a/src/pages/Shortcuts.jsx b/src/pages/Shortcuts.jsx
index 9cbc61f..7dd93a7 100644
--- a/src/pages/Shortcuts.jsx
+++ b/src/pages/Shortcuts.jsx
@@ -4,55 +4,7 @@ import logo_dark from "../assets/logo_dark_160.png";
import { AutoComplete, Button } from "@douyinfe/semi-ui";
import { IconSearch, IconSun, IconMoon } from "@douyinfe/semi-icons";
import { Link } from "react-router-dom";
-
-const shortcuts = [
- { shortcut: "CTRL+S", title: "Save diagram", description: "" },
- { shortcut: "CTRL+Shift+S", title: "Save diagram as", description: "" },
- {
- shortcut: "CTRL+O",
- title: "Open a diagram",
- description: "Load a saved diagram",
- },
- { shortcut: "CTRL+C", title: "Copy selected element", description: "" },
- { shortcut: "CTRL+V", title: "Paste selected element", description: "" },
- { shortcut: "CTRL+X", title: "Cut selected element", description: "" },
- { shortcut: "CTRL+D", title: "Duplicate selected element", description: "" },
- { shortcut: "DEL", title: "Delete selected element", description: "" },
- { shortcut: "CTRL+E", title: "Edit selected element", description: "" },
- {
- shortcut: "CTRL+I",
- title: "Import a diagram",
- description: "Import a diagram by uploadng a valid json or dbb file.",
- },
- { shortcut: "CTRL+Z", title: "Undo" },
- { shortcut: "CTRL+Y", title: "Redo" },
- {
- shortcut: "CTRL+SHIFT+M",
- title: "Enable/disable strict mode",
- description:
- "Disabling strict mode entails that the diagram will not undergo error or inconsistency checks.",
- },
- {
- shortcut: "CTRL+SHIFT+F",
- title: "Enable/disable field summaries",
- description:
- "Disabling field summaries will prevent the display of details for each field in the table when hovered over.",
- },
- { shortcut: "CTRL+SHIFT+G", title: "Show/hide grid" },
- {
- shortcut: "CTRL+ALT+C",
- title: "Copy as image",
- description: "Save the canvas as an image to the clipboard.",
- },
- {
- shortcut: "CTRL+R",
- title: "Reset view",
- description: "Resetting view will set diagram pan to (0, 0).",
- },
- { shortcut: "CTRL+UP / Wheel up", title: "Zoom in" },
- { shortcut: "CTRL+DOWN / Wheel down", title: "Zoom out" },
- { shortcut: "CTRL+H", title: "Open shortcuts" },
-];
+import { shortcuts } from "../data/shortcuts";
export default function Shortcuts() {
const [theme, setTheme] = useState("");
diff --git a/src/pages/Survey.jsx b/src/pages/Survey.jsx
index 63a68cb..1291ba8 100644
--- a/src/pages/Survey.jsx
+++ b/src/pages/Survey.jsx
@@ -1,4 +1,4 @@
-import { useEffect, useState, useCallback, useMemo } from "react";
+import { useEffect, useState, useCallback } from "react";
import logo_light from "../assets/logo_light_160.png";
import logo_dark from "../assets/logo_dark_160.png";
import {
@@ -21,23 +21,10 @@ import { CLEAR_EDITOR_COMMAND } from "lexical";
import { Link } from "react-router-dom";
import RichEditor from "../components/LexicalEditor/RichEditor";
import axios from "axios";
+import { questions } from "../data/surveyQuestions";
function SurveyForm({ theme }) {
const [editor] = useLexicalComposerContext();
- const questions = useMemo(
- () => ({
- satisfaction: "How satisfied are you with drawDB?",
- ease: "How easy was it to get started with drawDB?",
- wouldRecommend: "How likely are you to recommend drawDB?",
- hadDifficulty:
- "Did you encounter any difficulties when navigating drawDB?",
- difficulty: "What were the difficulties you faced?",
- triedOtherApps: "Have you tried apps like drawDB?",
- comparison: "How did you find drawDB as compared to other apps?",
- occupation: "What is your occupation?",
- }),
- []
- );
const [form, setForm] = useState({
satisfaction: 5,
ease: 5,
@@ -89,7 +76,7 @@ function SurveyForm({ theme }) {
};
sendMail();
});
- }, [editor, form, questions]);
+ }, [editor, form]);
return (
diff --git a/src/pages/Templates.jsx b/src/pages/Templates.jsx
index 208b436..58f1558 100644
--- a/src/pages/Templates.jsx
+++ b/src/pages/Templates.jsx
@@ -12,6 +12,7 @@ export default function Templates() {
const defaultTemplates = useLiveQuery(() =>
db.templates.where({ custom: 0 }).toArray()
);
+
const customTemplates = useLiveQuery(() =>
db.templates.where({ custom: 1 }).toArray()
);
@@ -110,7 +111,9 @@ export default function Templates() {
key={i}
className="bg-gray-100 hover:translate-y-[-6px] transition-all duration-300 border rounded-md"
>
-
+
+
+