Fix gists being controlled on button load

This commit is contained in:
1ilit 2024-08-31 19:49:43 +04:00
parent 65a86ee4f5
commit ed7fd87f7a
4 changed files with 116 additions and 68 deletions

View File

@ -1,4 +1,4 @@
import { useState } from "react";
import { useContext, useState } from "react";
import {
IconCaretdown,
IconChevronRight,
@ -71,7 +71,7 @@ import { exportSQL } from "../../utils/exportSQL";
import { databases } from "../../data/databases";
import { jsonToMermaid } from "../../utils/exportAs/mermaid";
import { isRtl } from "../../i18n/utils/rtl";
import Share from "./Modal/Share";
import { IdContext } from "../Workspace";
export default function ControlPanel({
diagramId,
@ -114,6 +114,7 @@ export default function ControlPanel({
const { selectedElement, setSelectedElement } = useSelect();
const { transform, setTransform } = useTransform();
const { t, i18n } = useTranslation();
const { setGistId } = useContext(IdContext);
const navigate = useNavigate();
const invertLayout = (component) =>
@ -783,6 +784,7 @@ export default function ControlPanel({
setEnums([]);
setUndoStack([]);
setRedoStack([]);
setGistId("");
})
.catch(() => Toast.error(t("oops_smth_went_wrong")));
},
@ -1372,12 +1374,11 @@ export default function ControlPanel({
onClick={() => setModal(MODAL.SHARE)}
>
{t("share")}
</Button>{" "}
</Button>
</div>
)}
{layout.toolbar && toolbar()}
</div>
<Share modal={modal} setModal={setModal}/>
<Modal
modal={modal}
exportData={exportData}

View File

@ -33,6 +33,7 @@ import ImportDiagram from "./ImportDiagram";
import ImportSource from "./ImportSource";
import SetTableWidth from "./SetTableWidth";
import Language from "./Language";
import Share from "./Share";
import CodeMirror from "@uiw/react-codemirror";
import { sql } from "@codemirror/lang-sql";
import { vscodeDark } from "@uiw/codemirror-theme-vscode";
@ -256,7 +257,6 @@ export default function Modal({
};
const getModalBody = () => {
if (modal === MODAL.SHARE) return;
switch (modal) {
case MODAL.IMPORT:
return (
@ -341,8 +341,8 @@ export default function Modal({
return <SetTableWidth />;
case MODAL.LANGUAGE:
return <Language />;
// case MODAL.SHARE:
// return <Share setModal={setModal} />;
case MODAL.SHARE:
return <Share title={title} />;
case MODAL.GITHUB_TOKEN:
return <GithubToken token={token} setToken={setToken} />;
default:
@ -354,7 +354,7 @@ export default function Modal({
<SemiUIModal
style={isRtl(i18n.language) ? { direction: "rtl" } : {}}
title={getModalTitle(modal)}
visible={modal !== MODAL.NONE && modal !== MODAL.SHARE}
visible={modal !== MODAL.NONE}
onOk={getModalOnOk}
afterClose={() => {
setExportData(() => ({

View File

@ -1,16 +1,27 @@
import { Button, Input, Modal, Spin, Toast } from "@douyinfe/semi-ui";
import { MODAL } from "../../../data/constants";
import { Button, Input, Spin, Toast } from "@douyinfe/semi-ui";
import { useCallback, useContext, useEffect, useState, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { Octokit } from "octokit";
import { IdContext } from "../../Workspace";
import { IconLink } from "@douyinfe/semi-icons";
import { isRtl } from "../../../i18n/utils/rtl";
import {
useAreas,
useDiagram,
useEnums,
useNotes,
useTypes,
} from "../../../hooks";
import { databases } from "../../../data/databases";
export default function Share({ modal, setModal }) {
const { t, i18n } = useTranslation();
export default function Share({ title }) {
const { t } = useTranslation();
const { gistId, setGistId } = useContext(IdContext);
const [loading, setLoading] = useState(false);
const [loading, setLoading] = useState(true);
const { tables, relationships, database } = useDiagram();
const { notes } = useNotes();
const { areas } = useAreas();
const { types } = useTypes();
const { enums } = useEnums();
const userToken = localStorage.getItem("github_token");
const octokit = useMemo(() => {
@ -23,6 +34,19 @@ export default function Share({ modal, setModal }) {
[gistId],
);
const diagramToString = useCallback(() => {
return JSON.stringify({
tables: tables,
relationships: relationships,
notes: notes,
subjectAreas: areas,
database: database,
...(databases[database].hasTypes && { types: types }),
...(databases[database].hasEnums && { enums: enums }),
title: title,
});
}, [areas, notes, tables, relationships, database, title, enums, types]);
const updateGist = useCallback(async () => {
setLoading(true);
try {
@ -30,8 +54,8 @@ export default function Share({ modal, setModal }) {
gist_id: gistId,
description: "drawDB diagram",
files: {
"test.json": {
content: '{"Hello":"SEAMAN"}',
"share.json": {
content: diagramToString(),
},
},
headers: {
@ -43,7 +67,7 @@ export default function Share({ modal, setModal }) {
} finally {
setLoading(false);
}
}, [gistId, octokit]);
}, [gistId, octokit, diagramToString]);
const generateLink = useCallback(async () => {
setLoading(true);
@ -52,8 +76,8 @@ export default function Share({ modal, setModal }) {
description: "drawDB diagram",
public: false,
files: {
"test.json": {
content: '{"Hello":"WORLD"}',
"share.json": {
content: diagramToString(),
},
},
headers: {
@ -66,7 +90,7 @@ export default function Share({ modal, setModal }) {
} finally {
setLoading(false);
}
}, [octokit, setGistId]);
}, [octokit, setGistId, diagramToString]);
useEffect(() => {
const updateOrGenerateLink = async () => {
@ -83,7 +107,7 @@ export default function Share({ modal, setModal }) {
}
};
updateOrGenerateLink();
}, [gistId, generateLink, setModal, updateGist]);
}, [gistId, generateLink, updateGist]);
const copyLink = () => {
navigator.clipboard
@ -96,48 +120,32 @@ export default function Share({ modal, setModal }) {
});
};
if (loading)
return (
<div className="text-blue-500 text-center">
<Spin size="middle" />
<div>{t("loading")}</div>
</div>
);
return (
<Modal
visible={modal === MODAL.SHARE}
style={isRtl(i18n.language) ? { direction: "rtl" } : {}}
title={t("share")}
footer={<></>}
onCancel={() => setModal(MODAL.NONE)}
centered
closeOnEsc={true}
cancelText={t("cancel")}
width={600}
bodyStyle={{
maxHeight: window.innerHeight - 280,
overflow: "auto",
direction: "ltr",
}}
>
{loading ? (
<div className="text-blue-500 text-center">
<Spin size="middle" />
<div>{t("loading")}</div>
</div>
) : (
<div>
<div className="flex gap-3">
<Input value={url} size="large" />
<Button
size="large"
theme="solid"
icon={<IconLink />}
onClick={copyLink}
>
{t("copy_link")}
</Button>
</div>
<hr className="opacity-20 mt-3 mb-1" />
<div className="text-xs">
* Sharing this link will not create a live real-time collaboration
session
</div>
</div>
)}
</Modal>
<div>
<div className="flex gap-3">
<Input value={url} size="large" />
<Button
size="large"
theme="solid"
icon={<IconLink />}
onClick={copyLink}
>
{t("copy_link")}
</Button>
</div>
<hr className="opacity-20 mt-3 mb-1" />
<div className="text-xs">
* Sharing this link will not create a live real-time collaboration
session
</div>
</div>
);
}

View File

@ -1,4 +1,10 @@
import { useState, useEffect, useCallback, createContext } from "react";
import {
useState,
useEffect,
useCallback,
createContext,
useMemo,
} from "react";
import ControlPanel from "./EditorHeader/ControlPanel";
import Canvas from "./EditorCanvas/Canvas";
import { CanvasContextProvider } from "../context/CanvasContext";
@ -23,6 +29,8 @@ import { Modal } from "@douyinfe/semi-ui";
import { useTranslation } from "react-i18next";
import { databases } from "../data/databases";
import { isRtl } from "../i18n/utils/rtl";
import { useSearchParams } from "react-router-dom";
import { Octokit } from "octokit";
export const IdContext = createContext({ gistId: "" });
@ -54,7 +62,13 @@ export default function WorkSpace() {
} = useDiagram();
const { undoStack, redoStack, setUndoStack, setRedoStack } = useUndoRedo();
const { t, i18n } = useTranslation();
let [searchParams] = useSearchParams();
const userToken = localStorage.getItem("github_token");
const octokit = useMemo(() => {
return new Octokit({
auth: userToken ?? import.meta.env.VITE_GITHUB_ACCESS_TOKEN,
});
}, [userToken]);
const handleResize = (e) => {
if (!resize) return;
const w = isRtl(i18n.language) ? window.innerWidth - e.clientX : e.clientX;
@ -307,6 +321,24 @@ export default function WorkSpace() {
selectedDb,
]);
const loadFromGist = useCallback(
async (shareId) => {
try {
const res = await octokit.request(`GET /gists/${shareId}`, {
gist_id: shareId,
headers: {
"X-GitHub-Api-Version": "2022-11-28",
},
});
const diagramSrc = res.data.files["share.json"].content;
console.log(diagramSrc);
} catch (e) {
console.log(e);
}
},
[octokit],
);
useEffect(() => {
if (
tables?.length === 0 &&
@ -336,7 +368,9 @@ export default function WorkSpace() {
]);
useEffect(() => {
setSaveState(State.SAVING);
if (gistId && gistId !== "") {
setSaveState(State.SAVING);
}
}, [gistId, setSaveState]);
useEffect(() => {
@ -348,8 +382,13 @@ export default function WorkSpace() {
useEffect(() => {
document.title = "Editor | drawDB";
load();
}, [load]);
const shareId = searchParams.get("shareId");
if (shareId) {
loadFromGist(shareId);
} else {
load();
}
}, [load, searchParams, loadFromGist]);
return (
<div className="h-full flex flex-col overflow-hidden theme">