edit elements

This commit is contained in:
1ilit 2023-09-19 15:50:28 +03:00
parent d571a09b39
commit 5b5e55e345
8 changed files with 225 additions and 73 deletions

View File

@ -15,19 +15,20 @@ import {
import {
AreaContext,
LayoutContext,
SelectContext,
TabContext,
UndoRedoContext,
} from "../pages/editor";
export default function Area(props) {
const [hovered, setHovered] = useState(false);
const [visible, setVisible] = useState(false);
const [saved, setSaved] = useState(false);
const [editField, setEditField] = useState({});
const { layout } = useContext(LayoutContext);
const { tab, setTab } = useContext(TabContext);
const { updateArea, deleteArea } = useContext(AreaContext);
const { setUndoStack, setRedoStack } = useContext(UndoRedoContext);
const { selectedElement, setSelectedElement } = useContext(SelectContext);
const handleMouseDown = (e, dir) => {
props.setResize({ id: props.areaData.id, dir: dir });
@ -46,7 +47,6 @@ export default function Area(props) {
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => {
setHovered(false);
setVisible(false);
setSaved(false);
}}
>
@ -73,10 +73,26 @@ export default function Area(props) {
<div className="text-gray-900 absolute top-2 left-3 select-none">
{props.areaData.name}
</div>
{hovered && (
{(hovered ||
(selectedElement.element === ObjectType.AREA &&
selectedElement.id === props.areaData.id &&
selectedElement.openDialogue &&
!layout.sidebar)) && (
<div className="absolute top-2 right-3">
<Popover
visible={visible}
visible={
selectedElement.element === ObjectType.AREA &&
selectedElement.id === props.areaData.id &&
selectedElement.openDialogue &&
!layout.sidebar
}
onClickOutSide={() => {
setSelectedElement((prev) => ({
...prev,
openDialogue: false,
}));
}}
stopPropagation
content={
<div>
<div className="font-semibold mb-2 ms-1">
@ -200,7 +216,6 @@ export default function Area(props) {
</div>
</div>
}
trigger="click"
position="rightTop"
showArrow
>
@ -268,7 +283,12 @@ export default function Area(props) {
.getElementById(`scroll_area_${props.areaData.id}`)
.scrollIntoView({ behavior: "smooth" });
} else {
setVisible(true);
setSelectedElement({
element: ObjectType.AREA,
id: props.areaData.id,
openDialogue: true,
openCollapse: false,
});
}
}}
></Button>

View File

@ -9,6 +9,7 @@ import {
SettingsContext,
TableContext,
UndoRedoContext,
SelectContext,
} from "../pages/editor";
import Note from "./note";
@ -19,6 +20,7 @@ export default function Canvas(props) {
const { notes, updateNote } = useContext(NoteContext);
const { settings, setSettings } = useContext(SettingsContext);
const { setUndoStack, setRedoStack } = useContext(UndoRedoContext);
const { selectedElement, setSelectedElement } = useContext(SelectContext);
const [dragging, setDragging] = useState({
element: ObjectType.NONE,
id: -1,
@ -100,6 +102,7 @@ export default function Canvas(props) {
prevY: note.y,
});
}
setSelectedElement({ element: type, id: id, openDialogue: false, openCollapse: false });
};
const handleMouseMove = (e) => {
@ -243,6 +246,7 @@ export default function Canvas(props) {
},
]);
setRedoStack([]);
setSelectedElement({ element: ObjectType.NONE, id: -1 });
}
setPanning({ state: false, x: 0, y: 0 });
setCursor("default");
@ -396,8 +400,14 @@ export default function Canvas(props) {
onMouseDown={(e) =>
handleMouseDownRect(e, table.id, ObjectType.TABLE)
}
selectedTable={props.selectedTable}
setSelectedTable={props.setSelectedTable}
active={
selectedElement.element === ObjectType.TABLE &&
selectedElement.id === table.id
}
moving={
dragging.element === ObjectType.TABLE &&
dragging.id === table.id
}
/>
))}
{linking && (

View File

@ -40,12 +40,14 @@ import {
AreaContext,
LayoutContext,
NoteContext,
SelectContext,
SettingsContext,
TabContext,
TableContext,
UndoRedoContext,
} from "../pages/editor";
import { IconAddTable, IconAddArea, IconAddNote } from "./custom_icons";
import { ObjectType, Action } from "../data/data";
import { ObjectType, Action, Tab } from "../data/data";
import CodeMirror from "@uiw/react-codemirror";
import { json } from "@codemirror/lang-json";
import jsPDF from "jspdf";
@ -95,6 +97,8 @@ export default function ControlPanel(props) {
useContext(AreaContext);
const { undoStack, redoStack, setUndoStack, setRedoStack } =
useContext(UndoRedoContext);
const { selectedElement, setSelectedElement } = useContext(SelectContext);
const { tab, setTab } = useContext(TabContext);
const invertLayout = (component) =>
setLayout((prev) => ({ ...prev, [component]: !prev[component] }));
@ -422,6 +426,60 @@ export default function ControlPanel(props) {
pan: { x: translateX, y: translateY },
}));
};
const edit = () => {
if (selectedElement.element === ObjectType.TABLE) {
if (!layout.sidebar) {
setSelectedElement({
element: ObjectType.TABLE,
id: selectedElement.id,
openDialogue: true,
openCollapse: false,
});
} else {
setTab(Tab.tables);
setSelectedElement({
element: ObjectType.TABLE,
id: selectedElement.id,
openDialogue: false,
openCollapse: true,
});
if (tab !== Tab.tables) return;
document
.getElementById(`scroll_table_${selectedElement.id}`)
.scrollIntoView({ behavior: "smooth" });
}
} else if(selectedElement.element===ObjectType.AREA){
if (layout.sidebar) {
setTab(Tab.subject_areas);
if (tab !== Tab.subject_areas) return;
document
.getElementById(`scroll_area_${selectedElement.id}`)
.scrollIntoView({ behavior: "smooth" });
} else {
setSelectedElement({
element: ObjectType.AREA,
id: selectedElement.id,
openDialogue: true,
openCollapse: false,
});
}
} else if(selectedElement.element===ObjectType.NOTE){
if (layout.sidebar) {
setTab(Tab.notes);
if (tab !== Tab.notes) return;
document
.getElementById(`scroll_note_${selectedElement.id}`)
.scrollIntoView({ behavior: "smooth" });
} else {
setSelectedElement({
element: ObjectType.NOTE,
id: selectedElement.id,
openDialogue: true,
openCollapse: false,
});
}
}
};
const menu = {
File: {
@ -591,22 +649,28 @@ export default function ControlPanel(props) {
},
},
Edit: {
function: () => {},
function: edit,
shortcut: "Ctrl+E",
},
Cut: {
function: () => {},
shortcut: "Ctrl+X",
},
Copy: {
function: () => {},
shortcut: "Ctrl+C",
},
Paste: {
function: () => {},
shortcut: "Ctrl+V",
},
Duplicate: {
function: () => {},
shortcut: "Ctrl+D",
},
Delete: {
function: () => {},
shortcut: "Del",
},
"Copy as image": {
function: copyAsImage,
@ -698,6 +762,7 @@ export default function ControlPanel(props) {
useHotkeys("ctrl+i, meta+i", fileImport, { preventDefault: true });
useHotkeys("ctrl+z, meta+z", undo, { preventDefault: true });
useHotkeys("ctrl+y, meta+y", redo, { preventDefault: true });
useHotkeys("ctrl+e, meta+e", edit, { preventDefault: true });
useHotkeys("ctrl+shift+g, meta+shift+g", viewGrid, { preventDefault: true });
useHotkeys("ctrl+up, meta+up", zoomIn, { preventDefault: true });
useHotkeys("ctrl+down, meta+down", zoomOut, { preventDefault: true });

View File

@ -38,10 +38,7 @@ const EditorPanel = (props) => {
{ tab: "Notes", itemKey: Tab.notes },
];
const contentList = [
<TableOverview
selectedTable={props.selectedTable}
setSelectedTable={props.setSelectedTable}
/>,
<TableOverview />,
<ReferenceOverview />,
<AreaOverview />,
<CodeMirror

View File

@ -4,6 +4,7 @@ import {
NoteContext,
UndoRedoContext,
TabContext,
SelectContext,
} from "../pages/editor";
import { Action, ObjectType, noteThemes, Tab } from "../data/data";
import { Input, Button, Popover, Toast } from "@douyinfe/semi-ui";
@ -16,7 +17,6 @@ import {
export default function Note(props) {
const [editField, setEditField] = useState({});
const [hovered, setHovered] = useState(false);
const [visible, setVisible] = useState(false);
const [saved, setSaved] = useState(false);
const w = 180;
const r = 3;
@ -25,6 +25,7 @@ export default function Note(props) {
const { setUndoStack, setRedoStack } = useContext(UndoRedoContext);
const { layout } = useContext(LayoutContext);
const { tab, setTab } = useContext(TabContext);
const { selectedElement, setSelectedElement } = useContext(SelectContext);
const handleChange = (e) => {
const textarea = document.getElementById(`note_${props.data.id}`);
@ -111,10 +112,26 @@ export default function Note(props) {
className="w-full resize-none outline-none overflow-y-hidden border-none select-none"
style={{ backgroundColor: props.data.color }}
></textarea>
{hovered && (
{(hovered ||
(selectedElement.element === ObjectType.NOTE &&
selectedElement.id === props.data.id &&
selectedElement.openDialogue &&
!layout.sidebar)) && (
<div className="absolute top-2 right-3">
<Popover
visible={visible}
visible={
selectedElement.element === ObjectType.NOTE &&
selectedElement.id === props.data.id &&
selectedElement.openDialogue &&
!layout.sidebar
}
onClickOutSide={() => {
setSelectedElement((prev) => ({
...prev,
openDialogue: false,
}));
}}
stopPropagation
content={
<div>
<div className="font-semibold mb-2 ms-1">Edit note</div>
@ -181,7 +198,6 @@ export default function Note(props) {
</div>
</div>
}
trigger="click"
position="rightTop"
showArrow
>
@ -249,7 +265,12 @@ export default function Note(props) {
.getElementById(`scroll_note_${props.data.id}`)
.scrollIntoView({ behavior: "smooth" });
} else {
setVisible(true);
setSelectedElement({
element: ObjectType.NOTE,
id: props.data.id,
openDialogue: true,
openCollapse: false,
});
}
}}
></Button>

View File

@ -33,6 +33,7 @@ import {
} from "@douyinfe/semi-ui";
import {
LayoutContext,
SelectContext,
SettingsContext,
TabContext,
TableContext,
@ -42,16 +43,17 @@ import {
export default function Table(props) {
const [isHovered, setIsHovered] = useState(false);
const [hoveredField, setHoveredField] = useState(-1);
const [visible, setVisible] = useState(false);
// const [visible, setVisible] = useState(false);
const [editField, setEditField] = useState({});
const { layout } = useContext(LayoutContext);
const { deleteTable, updateTable, updateField } = useContext(TableContext);
const { tab, setTab } = useContext(TabContext);
const { settings } = useContext(SettingsContext);
const height = props.tableData.fields.length * 36 + 50 + 3;
const { setUndoStack, setRedoStack } = useContext(UndoRedoContext);
const [editField, setEditField] = useState({});
const { selectedElement, setSelectedElement } = useContext(SelectContext);
const height = props.tableData.fields.length * 36 + 50 + 7;
return (
<>
<foreignObject
@ -60,7 +62,7 @@ export default function Table(props) {
y={props.tableData.y}
width={200}
height={height}
className="shadow-lg rounded-md cursor-move"
className="drop-shadow-lg rounded-md cursor-move"
onMouseDown={props.onMouseDown}
onMouseEnter={() => {
setIsHovered(true);
@ -74,9 +76,11 @@ export default function Table(props) {
}}
>
<div
className={`border-2 ${
isHovered ? "border-sky-500" : "border-gray-400"
} bg-gray-100 select-none rounded-md w-full`}
className={`border-2 border-gray-400 ${
props.active && !props.moving && "border-blue-500 border-4"
} ${
props.moving && "border-blue-500 border-4 border-dashed"
} bg-gray-100 select-none rounded-lg w-full`}
>
<div
className={`h-[10px] w-full rounded-t-md`}
@ -97,10 +101,20 @@ export default function Table(props) {
}}
onClick={() => {
if (!layout.sidebar) {
setVisible(true);
setSelectedElement({
element: ObjectType.TABLE,
id: props.tableData.id,
openDialogue: true,
openCollapse: false,
});
} else {
setTab(Tab.tables);
props.setSelectedTable(`${props.tableData.id}`);
setSelectedElement({
element: ObjectType.TABLE,
id: props.tableData.id,
openDialogue: false,
openCollapse: true,
});
if (tab !== Tab.tables) return;
document
.getElementById(`scroll_table_${props.tableData.id}`)
@ -157,7 +171,6 @@ export default function Table(props) {
onClick={() => {
Toast.success(`Table deleted!`);
deleteTable(props.tableData.id);
props.setSelectedTable("");
}}
>
Delete table
@ -233,8 +246,13 @@ export default function Table(props) {
<SideSheet
title="Edit table"
size="small"
visible={visible}
onCancel={() => setVisible((prev) => !prev)}
visible={selectedElement.element===ObjectType.TABLE && selectedElement.id===props.tableData.id && selectedElement.openDialogue}
onCancel={() =>
setSelectedElement((prev) => ({
...prev,
openDialogue: !prev.openDialogue,
}))
}
style={{ paddingBottom: "16px" }}
>
<div className="flex items-center">
@ -878,8 +896,6 @@ export default function Table(props) {
onClick={() => {
Toast.success(`Table deleted!`);
deleteTable(props.tableData.id);
props.setSelectedTable("");
setVisible(false);
}}
></Button>
</Col>

View File

@ -33,7 +33,7 @@ import {
IllustrationNoContent,
IllustrationNoContentDark,
} from "@douyinfe/semi-illustrations";
import { TableContext, UndoRedoContext } from "../pages/editor";
import { SelectContext, TableContext, UndoRedoContext } from "../pages/editor";
export default function TableOverview(props) {
const [indexActiveKey, setIndexActiveKey] = useState("");
@ -41,6 +41,7 @@ export default function TableOverview(props) {
const { tables, addTable, deleteTable, updateField, updateTable } =
useContext(TableContext);
const { setUndoStack, setRedoStack } = useContext(UndoRedoContext);
const { selectedElement, setSelectedElement } = useContext(SelectContext);
const [editField, setEditField] = useState({});
const [filteredResult, setFilteredResult] = useState(
tables.map((t) => {
@ -72,7 +73,12 @@ export default function TableOverview(props) {
onChange={(v) => setValue(v)}
onSelect={(v) => {
const { id } = tables.find((t) => t.name === v);
props.setSelectedTable(`${id}`);
setSelectedElement({
element: ObjectType.TABLE,
id: id,
openDialogue: false,
openCollapse: true,
});
document
.getElementById(`scroll_table_${id}`)
.scrollIntoView({ behavior: "smooth" });
@ -87,8 +93,15 @@ export default function TableOverview(props) {
</Col>
</Row>
<Collapse
activeKey={props.selectedTable}
onChange={(k) => props.setSelectedTable(k)}
activeKey={selectedElement.openCollapse ? `${selectedElement.id}` : ""}
onChange={(k) =>
setSelectedElement({
element: ObjectType.TABLE,
id: parseInt(k),
openDialogue: false,
openCollapse: true,
})
}
accordion
>
{tables.length <= 0 ? (
@ -746,7 +759,6 @@ export default function TableOverview(props) {
onClick={() => {
Toast.success(`Table deleted!`);
deleteTable(i);
props.setSelectedTable("");
}}
></Button>
</Col>

View File

@ -20,6 +20,7 @@ export const TabContext = createContext();
export const NoteContext = createContext();
export const SettingsContext = createContext();
export const UndoRedoContext = createContext();
export const SelectContext = createContext();
export default function Editor(props) {
const [code, setCode] = useState("");
@ -29,7 +30,6 @@ export default function Editor(props) {
const [notes, setNotes] = useState([]);
const [resize, setResize] = useState(false);
const [width, setWidth] = useState(340);
const [selectedTable, setSelectedTable] = useState("");
const [tab, setTab] = useState(Tab.tables);
const [layout, setLayout] = useState({
header: true,
@ -52,6 +52,12 @@ export default function Editor(props) {
});
const [undoStack, setUndoStack] = useState([]);
const [redoStack, setRedoStack] = useState([]);
const [selectedElement, setSelectedElement] = useState({
element: ObjectType.NONE,
id: -1,
openDialogue: false,
openCollapse: false,
});
const dragHandler = (e) => {
if (!resize) return;
@ -226,6 +232,14 @@ export default function Editor(props) {
setTables((prev) =>
prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i }))
);
if (id === selectedElement.id) {
setSelectedElement({
element: ObjectType.NONE,
id: -1,
openDialogue: false,
openCollapse: false,
});
}
};
const deleteArea = (id, addToHistory = true) => {
@ -372,39 +386,36 @@ export default function Editor(props) {
<UndoRedoContext.Provider
value={{ undoStack, redoStack, setUndoStack, setRedoStack }}
>
<div className="h-[100vh] overflow-hidden">
<ControlPanel />
<div
className={
layout.header
? `flex h-[calc(100vh-123.93px)]`
: `flex h-[calc(100vh-51.97px)]`
}
onMouseUp={() => setResize(false)}
onMouseMove={dragHandler}
>
<DndProvider backend={HTML5Backend}>
{layout.sidebar && (
<EditorPanel
code={code}
setCode={setCode}
resize={resize}
setResize={setResize}
width={width}
selectedTable={selectedTable}
setSelectedTable={setSelectedTable}
/>
)}
<Canvas
code={code}
setCode={setCode}
selectedTable={selectedTable}
setSelectedTable={setSelectedTable}
/>
</DndProvider>
{layout.services && <Sidebar />}
<SelectContext.Provider
value={{ selectedElement, setSelectedElement }}
>
<div className="h-[100vh] overflow-hidden">
<ControlPanel />
<div
className={
layout.header
? `flex h-[calc(100vh-123.93px)]`
: `flex h-[calc(100vh-51.97px)]`
}
onMouseUp={() => setResize(false)}
onMouseMove={dragHandler}
>
<DndProvider backend={HTML5Backend}>
{layout.sidebar && (
<EditorPanel
code={code}
setCode={setCode}
resize={resize}
setResize={setResize}
width={width}
/>
)}
<Canvas code={code} setCode={setCode} />
</DndProvider>
{layout.services && <Sidebar />}
</div>
</div>
</div>
</SelectContext.Provider>
</UndoRedoContext.Provider>
</SettingsContext.Provider>
</TabContext.Provider>