Add shortcuts page
This commit is contained in:
parent
a51d5cf03d
commit
6509d42478
@ -2,6 +2,7 @@ import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
|||||||
import Editor from "./pages/editor";
|
import Editor from "./pages/editor";
|
||||||
import LandingPage from "./pages/landing_page";
|
import LandingPage from "./pages/landing_page";
|
||||||
import Survey from "./pages/survey";
|
import Survey from "./pages/survey";
|
||||||
|
import Shortcuts from "./pages/shortcuts";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
@ -11,6 +12,7 @@ function App() {
|
|||||||
<Route path="/" element={<LandingPage />} />
|
<Route path="/" element={<LandingPage />} />
|
||||||
<Route path="/editor" element={<Editor name="Untitled" />} />
|
<Route path="/editor" element={<Editor name="Untitled" />} />
|
||||||
<Route path="/survey" element={<Survey />} />
|
<Route path="/survey" element={<Survey />} />
|
||||||
|
<Route path="/shortcuts" element={<Shortcuts/>}/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
</>
|
</>
|
||||||
|
BIN
src/assets/logo_dark_46.png
Normal file
BIN
src/assets/logo_dark_46.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
@ -966,7 +966,8 @@ export default function ControlPanel(props) {
|
|||||||
},
|
},
|
||||||
Help: {
|
Help: {
|
||||||
Shortcuts: {
|
Shortcuts: {
|
||||||
function: () => {},
|
function: () => window.open("/shortcuts", "_blank"),
|
||||||
|
shortcut: "Ctrl+H",
|
||||||
},
|
},
|
||||||
"Ask us on discord": {
|
"Ask us on discord": {
|
||||||
function: () => {},
|
function: () => {},
|
||||||
@ -1003,6 +1004,9 @@ export default function ControlPanel(props) {
|
|||||||
});
|
});
|
||||||
useHotkeys("ctrl+alt+c, meta+alt+c", copyAsImage, { preventDefault: true });
|
useHotkeys("ctrl+alt+c, meta+alt+c", copyAsImage, { preventDefault: true });
|
||||||
useHotkeys("ctrl+r, meta+r", resetView, { preventDefault: true });
|
useHotkeys("ctrl+r, meta+r", resetView, { preventDefault: true });
|
||||||
|
useHotkeys("ctrl+h, meta+h", () => window.open("/shortcuts", "_blank"), {
|
||||||
|
preventDefault: true,
|
||||||
|
});
|
||||||
useHotkeys("ctrl+alt+w, meta+alt+w", fitWindow, { preventDefault: true });
|
useHotkeys("ctrl+alt+w, meta+alt+w", fitWindow, { preventDefault: true });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -1200,7 +1204,7 @@ export default function ControlPanel(props) {
|
|||||||
|
|
||||||
function toolbar() {
|
function toolbar() {
|
||||||
return (
|
return (
|
||||||
<div className="py-1 px-5 flex justify-between items-center rounded-xl my-1 sm:mx-1 md:mx-6 select-none overflow-x-hidden toolbar-theme">
|
<div className="py-1 px-5 flex justify-between items-center rounded-xl my-1 sm:mx-1 3xl:mx-6 select-none overflow-x-hidden toolbar-theme">
|
||||||
<div className="flex justify-start items-center">
|
<div className="flex justify-start items-center">
|
||||||
{layoutDropdown()}
|
{layoutDropdown()}
|
||||||
<Divider layout="vertical" margin="8px" />
|
<Divider layout="vertical" margin="8px" />
|
||||||
|
@ -53,6 +53,11 @@
|
|||||||
background-color: var(--semi-color-bg-3);
|
background-color: var(--semi-color-bg-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-theme{
|
||||||
|
color: var(--semi-color-text-1);
|
||||||
|
background-color: rgba(var(--semi-grey-1), 1);
|
||||||
|
}
|
||||||
|
|
||||||
.toolbar-theme {
|
.toolbar-theme {
|
||||||
background-color: rgba(var(--semi-grey-1), 1);
|
background-color: rgba(var(--semi-grey-1), 1);
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ export default function LandingPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<div className="md:py-5 px-6 flex justify-between">
|
<div className="py-5 px-6 flex justify-between">
|
||||||
<div className="md:flex md:items-center md:justify-start">
|
<div className="flex items-center justify-start">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img src={logo} alt="logo" className="me-2" />
|
<img src={logo} alt="logo" className="me-2" />
|
||||||
</Link>
|
</Link>
|
||||||
|
185
src/pages/shortcuts.jsx
Normal file
185
src/pages/shortcuts.jsx
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import logo_light from "../assets/logo_light_46.png";
|
||||||
|
import logo_dark from "../assets/logo_dark_46.png";
|
||||||
|
import { AutoComplete, Button } from "@douyinfe/semi-ui";
|
||||||
|
import { IconSearch, IconSun, IconMoon } from "@douyinfe/semi-icons";
|
||||||
|
|
||||||
|
const shortcuts = [
|
||||||
|
{ 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" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Shortcuts() {
|
||||||
|
const [theme, setTheme] = useState("");
|
||||||
|
const [value, setValue] = useState("");
|
||||||
|
const [filteredResult, setFilteredResult] = useState(
|
||||||
|
shortcuts.map((t) => {
|
||||||
|
return t.shortcut;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleStringSearch = (value) => {
|
||||||
|
setFilteredResult(
|
||||||
|
shortcuts
|
||||||
|
.filter(
|
||||||
|
(i) =>
|
||||||
|
i.shortcut.toLowerCase().includes(value.toLowerCase()) ||
|
||||||
|
i.title.toLowerCase().includes(value.toLowerCase())
|
||||||
|
)
|
||||||
|
.map((i) => i.shortcut)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const t = localStorage.getItem("theme");
|
||||||
|
setTheme(t);
|
||||||
|
if (t === "dark") {
|
||||||
|
const body = document.body;
|
||||||
|
if (body.hasAttribute("theme-mode")) {
|
||||||
|
body.setAttribute("theme-mode", "dark");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const body = document.body;
|
||||||
|
if (body.hasAttribute("theme-mode")) {
|
||||||
|
body.setAttribute("theme-mode", "light");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.title = "Shortcuts - drawDB";
|
||||||
|
document.body.setAttribute("class", "theme");
|
||||||
|
}, [setTheme]);
|
||||||
|
|
||||||
|
const changeTheme = () => {
|
||||||
|
const body = document.body;
|
||||||
|
const t = body.getAttribute("theme-mode");
|
||||||
|
if (t === "dark") {
|
||||||
|
if (body.hasAttribute("theme-mode")) {
|
||||||
|
body.setAttribute("theme-mode", "light");
|
||||||
|
setTheme("light");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (body.hasAttribute("theme-mode")) {
|
||||||
|
body.setAttribute("theme-mode", "dark");
|
||||||
|
setTheme("dark");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="sm:py-3 py-5 px-6 flex justify-between items-center">
|
||||||
|
<div className="flex items-center justify-start">
|
||||||
|
<img
|
||||||
|
src={theme === "dark" ? logo_dark : logo_light}
|
||||||
|
alt="logo"
|
||||||
|
className="me-2 sm:h-[28px] md:h-[46px]"
|
||||||
|
/>
|
||||||
|
<div className="ms-4 sm:text-base 3xl:text-lg font-semibold">
|
||||||
|
Keyboard shortcuts
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Button
|
||||||
|
icon={
|
||||||
|
theme === "dark" ? (
|
||||||
|
<IconSun size="extra-large" />
|
||||||
|
) : (
|
||||||
|
<IconMoon size="extra-large" />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
theme="borderless"
|
||||||
|
onClick={changeTheme}
|
||||||
|
></Button>
|
||||||
|
<div className="ms-2 lg:inline md:inline sm:hidden">
|
||||||
|
<AutoComplete
|
||||||
|
prefix={<IconSearch />}
|
||||||
|
placeholder="Search..."
|
||||||
|
data={filteredResult}
|
||||||
|
value={value}
|
||||||
|
onSearch={(v) => handleStringSearch(v)}
|
||||||
|
emptyContent={
|
||||||
|
<div className="p-3 popover-theme">No shortcuts found</div>
|
||||||
|
}
|
||||||
|
onChange={(v) => setValue(v)}
|
||||||
|
onSelect={(v) => {}}
|
||||||
|
></AutoComplete>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr
|
||||||
|
className={theme === "dark" ? "border-zinc-700" : "border-zinc-300"}
|
||||||
|
/>
|
||||||
|
<div className="w-full mt-4 mx-auto sm:inline-block hidden text-center">
|
||||||
|
<AutoComplete
|
||||||
|
prefix={<IconSearch />}
|
||||||
|
placeholder="Search..."
|
||||||
|
className="w-[80%]"
|
||||||
|
data={filteredResult}
|
||||||
|
value={value}
|
||||||
|
onSearch={(v) => handleStringSearch(v)}
|
||||||
|
emptyContent={
|
||||||
|
<div className="p-3 popover-theme">No shortcuts found</div>
|
||||||
|
}
|
||||||
|
onChange={(v) => setValue(v)}
|
||||||
|
onSelect={(v) => {}}
|
||||||
|
></AutoComplete>
|
||||||
|
</div>
|
||||||
|
<div className="grid sm:grid-cols-1 lg:grid-cols-2 3xl:grid-cols-3 m-6 gap-5 select-none">
|
||||||
|
{shortcuts.map((s, i) => (
|
||||||
|
<div className="p-3 card-theme rounded" key={i}>
|
||||||
|
<div className="flex justify-between sm:text-sm">
|
||||||
|
<div className="font-semibold me-2">{s.shortcut}</div>
|
||||||
|
<div>{s.title}</div>
|
||||||
|
</div>
|
||||||
|
{s.description && (
|
||||||
|
<>
|
||||||
|
<hr
|
||||||
|
className={`${
|
||||||
|
theme === "dark" ? "border-zinc-600" : "border-zinc-400"
|
||||||
|
} my-2`}
|
||||||
|
/>
|
||||||
|
<div className="sm:text-xs text-sm">{s.description}</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -4,7 +4,15 @@ module.exports = {
|
|||||||
"./src/**/*.{js,jsx,ts,tsx}",
|
"./src/**/*.{js,jsx,ts,tsx}",
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
screens: {
|
||||||
|
'3xl': {'max': '2047px'},
|
||||||
|
'2xl': {'max': '1535px'},
|
||||||
|
'xl': {'max': '1279px'},
|
||||||
|
'lg': {'max': '1023px'},
|
||||||
|
'md': {'max': '767px'},
|
||||||
|
'sm': {'max': '639px'}
|
||||||
|
},
|
||||||
|
extend: {}
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user