Manage layout

This commit is contained in:
1ilit 2023-09-19 15:48:34 +03:00
parent b0737e1a89
commit a2aa12f598
4 changed files with 322 additions and 195 deletions

View File

@ -22,9 +22,7 @@ import {
import { toPng, toJpeg, toSvg } from "html-to-image";
import { saveAs } from "file-saver";
export default function ControlPanel() {
const [showToolBar, setShowToolBar] = useState(true);
export default function ControlPanel(props) {
const [visible, setVisible] = useState(false);
const [dataUrl, setDataUrl] = useState("");
const [filename, setFilename] = useState(
@ -249,157 +247,12 @@ export default function ControlPanel() {
return (
<>
{showToolBar && (
<nav className="flex justify-between pt-1 items-center whitespace-nowrap">
<div className="flex justify-start items-center text-slate-800">
<Link to="/">
<img
width={54}
src={icon}
alt="logo"
className="ms-8 min-w-[54px]"
/>
</Link>
<div className="ms-1 mt-1">
<div className="text-xl ms-3">Project1 / Untitled</div>
<div className="flex justify-between items-center">
<div className="flex justify-start text-md select-none me-2">
{Object.keys(menu).map((category) => (
<Dropdown
key={category}
position="bottomLeft"
style={{ width: "200px" }}
render={
<Dropdown.Menu>
{Object.keys(menu[category]).map((item, index) => {
if (menu[category][item].children.length > 0) {
return (
<Dropdown
style={{ width: "120px" }}
key={item}
position={"rightTop"}
render={
<Dropdown.Menu>
{menu[category][item].children.map(
(e, i) => (
<Dropdown.Item
key={i}
onClick={Object.values(e)[0]}
>
{Object.keys(e)[0]}
</Dropdown.Item>
)
)}
</Dropdown.Menu>
}
>
<Dropdown.Item
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
onClick={menu[category][item].function}
>
{item}
<IconChevronRight />
</Dropdown.Item>
</Dropdown>
);
}
return (
<Dropdown.Item
key={index}
onClick={menu[category][item].function}
>
{item}
</Dropdown.Item>
);
})}
</Dropdown.Menu>
}
>
<div className="px-3 py-1 hover:bg-gray-100 rounded">
{category}
</div>
</Dropdown>
))}
</div>
<Button size="small" type="tertiary">
Last saved {new Date().toISOString()}
</Button>
</div>
</div>
</div>
<div className="flex justify-around items-center text-md me-8">
<AvatarGroup maxCount={3} size="default">
<Avatar color="red" alt="Lisa LeBlanc">
LL
</Avatar>
<Avatar color="green" alt="Caroline Xiao">
CX
</Avatar>
<Avatar color="amber" alt="Rafal Matin">
RM
</Avatar>
<Avatar alt="Zank Lance">ZL</Avatar>
<Avatar alt="Youself Zhang">YZ</Avatar>
</AvatarGroup>
<Button
type="primary"
style={{
fontSize: "16px",
marginLeft: "12px",
marginRight: "12px",
}}
size="large"
icon={<IconShareStroked />}
>
Share
</Button>
<Avatar size="default" alt="Buni Zhang">
BZ
</Avatar>
</div>
</nav>
{props.layout.header && (
header()
)}
<div className="p-2 px-5 flex justify-between items-center rounded-xl bg-slate-100 my-1 mx-6 text-slate-700 select-none">
<div className="flex justify-start items-center">
<Dropdown
position="bottomLeft"
style={{ width: "180px" }}
render={
<Dropdown.Menu>
<Dropdown.Item
icon={
showToolBar ? (
<IconCheckboxTick />
) : (
<div className="px-2"></div>
)
}
onClick={() => setShowToolBar((prev) => !prev)}
>
Header
</Dropdown.Item>
<Dropdown.Item icon={<IconCheckboxTick />}>
Overview
</Dropdown.Item>
<Dropdown.Item icon={<IconCheckboxTick />}>
Services
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item icon={<IconCheckboxTick />}>
Fullscreen
</Dropdown.Item>
</Dropdown.Menu>
}
trigger="click"
>
<div className="py-1 px-2 hover:bg-slate-200 rounded">
<i className="fa-solid fa-table-list"></i> <IconCaretdown />
</div>
</Dropdown>
{layoutDropdown()}
<Divider layout="vertical" margin="8px" />
<Dropdown
style={{ width: "180px" }}
@ -496,8 +349,12 @@ export default function ControlPanel() {
<i className="fa-solid fa-code-branch"></i>
</button>
</div>
<button onClick={(e) => setShowToolBar((prev) => !prev)}>
{showToolBar ? <IconChevronUp /> : <IconChevronDown />}
<button
onClick={(e) =>
props.setLayout((prev) => ({ ...prev, header: !prev.header }))
}
>
{props.layout.header ? <IconChevronUp /> : <IconChevronDown />}
</button>
</div>
<Modal
@ -537,4 +394,280 @@ export default function ControlPanel() {
</Modal>
</>
);
function header() {
return <nav className="flex justify-between pt-1 items-center whitespace-nowrap">
<div className="flex justify-start items-center text-slate-800">
<Link to="/">
<img
width={54}
src={icon}
alt="logo"
className="ms-8 min-w-[54px]" />
</Link>
<div className="ms-1 mt-1">
<div className="text-xl ms-3">Project1 / Untitled</div>
<div className="flex justify-between items-center">
<div className="flex justify-start text-md select-none me-2">
{Object.keys(menu).map((category) => (
<Dropdown
key={category}
position="bottomLeft"
style={{ width: "200px" }}
render={<Dropdown.Menu>
{Object.keys(menu[category]).map((item, index) => {
if (menu[category][item].children.length > 0) {
return (
<Dropdown
style={{ width: "120px" }}
key={item}
position={"rightTop"}
render={<Dropdown.Menu>
{menu[category][item].children.map(
(e, i) => (
<Dropdown.Item
key={i}
onClick={Object.values(e)[0]}
>
{Object.keys(e)[0]}
</Dropdown.Item>
)
)}
</Dropdown.Menu>}
>
<Dropdown.Item
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
onClick={menu[category][item].function}
>
{item}
<IconChevronRight />
</Dropdown.Item>
</Dropdown>
);
}
return (
<Dropdown.Item
key={index}
onClick={menu[category][item].function}
>
{item}
</Dropdown.Item>
);
})}
</Dropdown.Menu>}
>
<div className="px-3 py-1 hover:bg-gray-100 rounded">
{category}
</div>
</Dropdown>
))}
</div>
<Button size="small" type="tertiary">
Last saved {new Date().toISOString()}
</Button>
</div>
</div>
</div>
<div className="flex justify-around items-center text-md me-8">
<AvatarGroup maxCount={3} size="default">
<Avatar color="red" alt="Lisa LeBlanc">
LL
</Avatar>
<Avatar color="green" alt="Caroline Xiao">
CX
</Avatar>
<Avatar color="amber" alt="Rafal Matin">
RM
</Avatar>
<Avatar alt="Zank Lance">ZL</Avatar>
<Avatar alt="Youself Zhang">YZ</Avatar>
</AvatarGroup>
<Button
type="primary"
style={{
fontSize: "16px",
marginLeft: "12px",
marginRight: "12px",
}}
size="large"
icon={<IconShareStroked />}
>
Share
</Button>
<Avatar size="default" alt="Buni Zhang">
BZ
</Avatar>
</div>
</nav>;
}
function layoutDropdown() {
return (
<Dropdown
position="bottomLeft"
style={{ width: "180px" }}
render={
<Dropdown.Menu>
<Dropdown.Item
icon={
props.layout.header ? (
<IconCheckboxTick />
) : (
<div className="px-2"></div>
)
}
onClick={() =>
props.setLayout((prev) => ({
...prev,
header: !prev.header,
}))
}
>
Header
</Dropdown.Item>
<Dropdown
position={"rightTop"}
render={
<Dropdown.Menu>
<Dropdown.Item
icon={
props.layout.tables ? (
<IconCheckboxTick />
) : (
<div className="px-2"></div>
)
}
onClick={() =>
props.setLayout((prev) => ({
...prev,
tables: !prev.tables,
}))
}
>
Tables
</Dropdown.Item>
<Dropdown.Item
icon={
props.layout.relationships ? (
<IconCheckboxTick />
) : (
<div className="px-2"></div>
)
}
onClick={() =>
props.setLayout((prev) => ({
...prev,
relationships: !prev.relationships,
}))
}
>
Relationships
</Dropdown.Item>
<Dropdown.Item
icon={
props.layout.issues ? (
<IconCheckboxTick />
) : (
<div className="px-2"></div>
)
}
onClick={() =>
props.setLayout((prev) => ({
...prev,
issues: !prev.issues,
}))
}
>
Issues
</Dropdown.Item>
<Dropdown.Item
icon={
props.layout.editor ? (
<IconCheckboxTick />
) : (
<div className="px-2"></div>
)
}
onClick={() =>
props.setLayout((prev) => ({
...prev,
editor: !prev.editor,
}))
}
>
Editor
</Dropdown.Item>
<Dropdown.Item
icon={
props.layout.shapes ? (
<IconCheckboxTick />
) : (
<div className="px-2"></div>
)
}
onClick={() =>
props.setLayout((prev) => ({
...prev,
shapes: !prev.shapes,
}))
}
>
Shapes
</Dropdown.Item>
</Dropdown.Menu>
}
>
<Dropdown.Item
icon={
props.layout.sidebar ? (
<IconCheckboxTick />
) : (
<div className="px-2"></div>
)
}
onClick={() =>
props.setLayout((prev) => ({
...prev,
sidebar: !prev.sidebar,
}))
}
>
Sidebar
</Dropdown.Item>
</Dropdown>
<Dropdown.Item
icon={
props.layout.services ? (
<IconCheckboxTick />
) : (
<div className="px-2"></div>
)
}
onClick={() =>
props.setLayout((prev) => ({
...prev,
services: !prev.services,
}))
}
>
Services
</Dropdown.Item>
<Dropdown.Divider />
<Dropdown.Item icon={<IconCheckboxTick />}>
Fullscreen
</Dropdown.Item>
</Dropdown.Menu>
}
trigger="click"
>
<div className="py-1 px-2 hover:bg-slate-200 rounded">
<i className="fa-solid fa-table-list"></i> <IconCaretdown />
</div>
</Dropdown>
);
}
}

View File

@ -5,7 +5,7 @@ export default function Relationship(props) {
const calcPath = (x1, x2, y1, y2) => {
let r = 16;
const offsetX = 8;
const tableWidth = 240;
const tableWidth = 220;
const midX = (x2 + x1 + tableWidth) / 2;
const endX = x2 + tableWidth < x1 ? x2 + tableWidth - offsetX * 2 : x2;

View File

@ -93,7 +93,7 @@ export default function Table(props) {
key={props.id}
x={props.tableData.x}
y={props.tableData.y}
width={240}
width={220}
height={height}
style={{ cursor: "move" }}
onMouseDown={props.onMouseDown}
@ -111,34 +111,15 @@ export default function Table(props) {
<div
className={`border-2 ${
isHovered ? "border-sky-500" : "border-gray-500"
} bg-gray-300 select-none rounded-md`}
} bg-gray-200 select-none rounded-md`}
>
<div
style={{ backgroundColor: props.tableData.color }}
className={`p-3 font-bold text-slate-800 h-[40px] rounded-t-md flex justify-between items-center`}
// style={{ backgroundColor: props.tableData.color }}
className="p-3 bg-gray-300 font-bold text-slate-800 h-[40px] rounded-t-md flex justify-between items-center"
>
{
<form
onSubmit={(e) => e.preventDefault()}
onMouseEnter={() =>
props.setOnRect({
tableId: props.id,
field: -1,
})
}
>
<div
// type="text"
// value={name}
// onChange={(e) => setName(e.target.value)}
className={`p-1 select-text w-[100px] bg-gray-400 focus:bg-gray-200 ${
false
? "ring-2 ring-red-600"
: "focus:ring-2 focus:ring-sky-500 "
}`}
>{props.tableData.name}</div>
</form>
}
<div className="p-1">
{props.tableData.name}
</div>
{isHovered && (
<div className="flex justify-end items-center">
<button className="btn bg-sky-800 text-white text-xs py-1 px-2 me-2 opacity-80">
@ -499,3 +480,4 @@ export default function Table(props) {
</g>
);
}

View File

@ -13,6 +13,16 @@ export default function Editor(props) {
const [areas, setAreas] = useState([]);
const [resize, setResize] = useState(false);
const [width, setWidth] = useState(340);
const [layout, setLayout] = useState({
header: true,
sidebar: true,
services: true,
tables: true,
relationships: true,
issues: true,
editor: true,
shapes: true,
});
const dragHandler = (e) => {
if (!resize) return;
@ -22,13 +32,14 @@ export default function Editor(props) {
return (
<>
<ControlPanel />
<ControlPanel layout={layout} setLayout={setLayout} />
<div
className={`flex h-full`}
onMouseUp={() => setResize(false)}
onMouseMove={dragHandler}
>
<DndProvider backend={HTML5Backend}>
{layout.sidebar && (
<EditorPanel
tables={tables}
setTables={setTables}
@ -42,6 +53,7 @@ export default function Editor(props) {
setResize={setResize}
width={width}
/>
)}
<Canvas
tables={tables}
setTables={setTables}
@ -53,7 +65,7 @@ export default function Editor(props) {
setAreas={setAreas}
/>
</DndProvider>
<Sidebar />
{layout.services && <Sidebar />}
</div>
</>
);