diff --git a/package-lock.json b/package-lock.json index 5f9d59c..9a5926d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "frontend", "version": "0.1.0", "dependencies": { + "@codemirror/lang-json": "^6.0.1", "@codemirror/lang-sql": "^6.5.0", "@douyinfe/semi-ui": "^2.36.0", "@lezer/highlight": "^1.1.5", @@ -2152,6 +2153,15 @@ "@lezer/common": "^1.0.0" } }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz", + "integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, "node_modules/@codemirror/lang-sql": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.5.2.tgz", @@ -3721,6 +3731,15 @@ "@lezer/common": "^1.0.0" } }, + "node_modules/@lezer/json": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.1.tgz", + "integrity": "sha512-nkVC27qiEZEjySbi6gQRuMwa2sDu2PtfjSgz0A4QF81QyRGm3kb2YRzLcOPcTEtmcwvrX/cej7mlhbwViA4WJw==", + "dependencies": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, "node_modules/@lezer/lr": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.7.tgz", diff --git a/package.json b/package.json index b1a890c..42a92d3 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@codemirror/lang-json": "^6.0.1", "@codemirror/lang-sql": "^6.5.0", "@douyinfe/semi-ui": "^2.36.0", "@lezer/highlight": "^1.1.5", diff --git a/src/components/control_panel.jsx b/src/components/control_panel.jsx index f28c9dd..8d38938 100644 --- a/src/components/control_panel.jsx +++ b/src/components/control_panel.jsx @@ -22,22 +22,40 @@ import { Image, Modal, Spin, + Input, } from "@douyinfe/semi-ui"; import { toPng, toJpeg, toSvg } from "html-to-image"; import { saveAs } from "file-saver"; import { enterFullscreen, exitFullscreen } from "../utils"; -import { LayoutContext, SettingsContext } from "../pages/editor"; +import { + AreaContext, + LayoutContext, + NoteContext, + SettingsContext, + TableContext, +} from "../pages/editor"; import { AddTable, AddArea, AddNote } from "./custom_icons"; +import { defaultTableTheme, defaultNoteTheme } from "../data/data"; +import CodeMirror from "@uiw/react-codemirror"; +import { json } from "@codemirror/lang-json"; export default function ControlPanel(props) { - const [visible, setVisible] = useState(false); - const [dataUrl, setDataUrl] = useState(""); - const [filename, setFilename] = useState( - `diagram_${new Date().toISOString()}` - ); - const [extension, setExtension] = useState(""); + const MODAL = { + NONE: 0, + IMG: 1, + CODE: 2, + }; + const [visible, setVisible] = useState(MODAL.NONE); + const [exportData, setExportData] = useState({ + data: "", + filename: `diagram_${new Date().toISOString()}`, + extension: "", + }); const { layout, setLayout } = useContext(LayoutContext); const { setSettings } = useContext(SettingsContext); + const { relationships, tables, setTables } = useContext(TableContext); + const { notes, setNotes } = useContext(NoteContext); + const { areas, setAreas } = useContext(AreaContext); const menu = { File: { @@ -74,37 +92,66 @@ export default function ControlPanel(props) { { PNG: () => { toPng(document.getElementById("canvas")).then(function (dataUrl) { - setDataUrl(dataUrl); + setExportData((prev) => ({ + ...prev, + data: dataUrl, + extension: "png", + })); }); - setVisible(true); - setExtension("png"); + setVisible(MODAL.IMG); }, }, { JPEG: () => { toJpeg(document.getElementById("canvas"), { quality: 0.95 }).then( function (dataUrl) { - setDataUrl(dataUrl); + setExportData((prev) => ({ + ...prev, + data: dataUrl, + extension: "jpeg", + })); } ); - setVisible(true); - setExtension("jpeg"); + setVisible(MODAL.IMG); + }, + }, + { + JSON: () => { + setVisible(MODAL.CODE); + + const result = JSON.stringify( + { + tables: tables, + relationships: relationships, + notes: notes, + "subject areas": areas, + }, + null, + 2 + ); + setExportData((prev) => ({ + ...prev, + data: result, + extension: "json", + })); }, }, - { XML: () => {} }, { SVG: () => { const filter = (node) => node.tagName !== "i"; toSvg(document.getElementById("canvas"), { filter: filter }).then( function (dataUrl) { - setDataUrl(dataUrl); + setExportData((prev) => ({ + ...prev, + data: dataUrl, + extension: "svg", + })); } ); - setVisible(true); - setExtension("svg"); + setVisible(MODAL.IMG); }, }, - { PDF: () => {} }, + { IFRAME: () => {} }, ], function: () => {}, }, @@ -316,39 +363,94 @@ export default function ControlPanel(props) { -
+ setTables((prev) => [ + ...prev, + { + id: prev.length, + name: `table_${prev.length}`, + x: 0, + y: 0, + fields: [ + { + name: "id", + type: "UUID", + default: "", + check: "", + primary: true, + unique: true, + notNull: true, + increment: true, + comment: "", + }, + ], + comment: "", + indices: [], + color: defaultTableTheme, + }, + ]) + } > -
-
+
-
+
+ saveAs(dataUrl, `${filename}.${extension}`)} - afterClose={() => { - setFilename(`diagram_${new Date().toISOString()}`); - setDataUrl(""); + visible={visible !== MODAL.NONE} + onOk={() => { + if (visible === MODAL.IMG) { + saveAs( + exportData.data, + `${exportData.filename}.${exportData.extension}` + ); + } else if (visible === MODAL.CODE) { + const blob = new Blob([exportData.data], { + type: "text/plain;charset=utf-8", + }); + saveAs(blob, `${exportData.filename}.${exportData.extension}`); + } }} - onCancel={() => setVisible(false)} + afterClose={() => { + setExportData((prev) => ({ + data: "", + extension: "", + filename: `diagram_${new Date().toISOString()}`, + })); + }} + onCancel={() => setVisible(MODAL.NONE)} centered closeOnEsc={true} okText="Export" cancelText="Cancel" - width={470} + width={520} > - {dataUrl !== "" || dataUrl ? ( - Diagram + {exportData.data !== "" || exportData.data ? ( + visible === MODAL.IMG ? ( + Diagram + ) : ( +
+ +
+ ) ) : (
- +
)} -
{ - setFilename((prev) => - value.values["filename"] !== undefined - ? value.values["filename"] - : prev - ); - }} - > - {`.${extension}`}} - initValue={filename} - /> - +
Filename :
+ {`.${exportData.extension}`}} + onChange={(value) => + setExportData((prev) => ({ ...prev, filename: value })) + } + field="filename" + />
);