subject area overview

This commit is contained in:
1ilit 2023-09-19 15:48:55 +03:00
parent ce92a35c9f
commit 8da14317e5
6 changed files with 295 additions and 63 deletions

View File

@ -4,7 +4,7 @@ export default function Area(props) {
const [hovered, setHovered] = useState(false); const [hovered, setHovered] = useState(false);
const handleMouseDown = (e, dir) => { const handleMouseDown = (e, dir) => {
props.setResize({id: props.areaData.id, dir: dir}); props.setResize({ id: props.areaData.id, dir: dir });
props.setInitCoords({ props.setInitCoords({
x: props.areaData.x, x: props.areaData.x,
y: props.areaData.y, y: props.areaData.y,
@ -28,53 +28,61 @@ export default function Area(props) {
height={props.areaData.height > 0 ? props.areaData.height : 0} height={props.areaData.height > 0 ? props.areaData.height : 0}
onMouseDown={props.onMouseDown} onMouseDown={props.onMouseDown}
> >
<div className="border-2 border-dashed border-blue-600 opacity-70 bg-slate-400 w-fill h-full select-none cursor-move"> <div
className={`${
hovered
? "border-4 border-dashed border-[#5891db]"
: "border-2 border-slate-400"
} w-full h-full cursor-move rounded relative`}
>
<div
className="opacity-40 w-fill p-2 h-full"
style={{ backgroundColor: props.areaData.color }}
/>
</div>
<div className="text-gray-900 absolute top-2 left-3 select-none">
{props.areaData.name} {props.areaData.name}
</div> </div>
</foreignObject> </foreignObject>
{hovered && ( {hovered && (
<> <>
<rect <circle
x={props.areaData.x - 5} cx={props.areaData.x}
y={props.areaData.y - 5} cy={props.areaData.y}
width={10} r={6}
height={10} fill="white"
fill="lightblue" stroke="#5891db"
stroke="blue" strokeWidth={3}
strokeWidth={1}
cursor="nwse-resize" cursor="nwse-resize"
onMouseDown={(e) => handleMouseDown(e, "tl")} onMouseDown={(e) => handleMouseDown(e, "tl")}
/> />
<rect <circle
x={props.areaData.x + props.areaData.width - 5} cx={props.areaData.x + props.areaData.width}
y={props.areaData.y - 5} cy={props.areaData.y}
width={10} r={6}
height={10} fill="white"
fill="lightblue" stroke="#5891db"
stroke="blue" strokeWidth={3}
strokeWidth={1}
cursor="nesw-resize" cursor="nesw-resize"
onMouseDown={(e) => handleMouseDown(e, "tr")} onMouseDown={(e) => handleMouseDown(e, "tr")}
/> />
<rect <circle
x={props.areaData.x - 5} cx={props.areaData.x}
y={props.areaData.y + props.areaData.height - 5} cy={props.areaData.y + props.areaData.height}
width={10} r={6}
height={10} fill="white"
fill="lightblue" stroke="#5891db"
stroke="blue" strokeWidth={3}
strokeWidth={1}
cursor="nesw-resize" cursor="nesw-resize"
onMouseDown={(e) => handleMouseDown(e, "bl")} onMouseDown={(e) => handleMouseDown(e, "bl")}
/> />
<rect <circle
x={props.areaData.x + props.areaData.width - 5} cx={props.areaData.x + props.areaData.width}
y={props.areaData.y + props.areaData.height - 5} cy={props.areaData.y + props.areaData.height}
width={10} r={6}
height={10} fill="white"
fill="lightblue" stroke="#5891db"
stroke="blue" strokeWidth={3}
strokeWidth={1}
cursor="nwse-resize" cursor="nwse-resize"
onMouseDown={(e) => handleMouseDown(e, "br")} onMouseDown={(e) => handleMouseDown(e, "br")}
/> />

View File

@ -0,0 +1,225 @@
import React, { useContext, useState } from "react";
import {
Empty,
Row,
Col,
AutoComplete,
Button,
Input,
Popover,
Toast,
} from "@douyinfe/semi-ui";
import {
IllustrationNoContent,
IllustrationNoContentDark,
} from "@douyinfe/semi-illustrations";
import {
IconPlus,
IconSearch,
IconCheckboxTick,
IconDeleteStroked,
} from "@douyinfe/semi-icons";
import { defaultTableTheme, tableThemes } from "../data/data";
import { AreaContext } from "../pages/editor";
export default function AreaOverview(props) {
const { areas, setAreas } = useContext(AreaContext);
const [value, setValue] = useState("");
const [filteredResult, setFilteredResult] = useState(
areas.map((t) => {
return t.name;
})
);
const handleStringSearch = (value) => {
setFilteredResult(
areas
.map((t) => {
return t.name;
})
.filter((i) => i.includes(value))
);
};
const updateArea = (aid, updatedValues) => {
setAreas((prev) =>
prev.map((a, i) => {
if (aid === i) {
return {
...a,
...updatedValues,
};
}
return a;
})
);
};
return (
<div>
<Row gutter={6}>
<Col span={16}>
<AutoComplete
data={filteredResult}
value={value}
showClear
prefix={<IconSearch />}
placeholder="Search..."
emptyContent={<div className="p-3">No areas found</div>}
onSearch={(v) => handleStringSearch(v)}
onChange={(v) => setValue(v)}
onSelect={(v) => {
const { id } = areas.find((t) => t.name === v);
document
.getElementById(`scroll_area_${id}`)
.scrollIntoView({ behavior: "smooth" });
}}
className="w-full"
/>
</Col>
<Col span={8}>
<Button
icon={<IconPlus />}
block
onClick={() => {
const newArea = {
id: areas.length,
name: `area_${areas.length}`,
x: 0,
y: 0,
width: 200,
height: 200,
color: defaultTableTheme,
};
setAreas((prev) => [...prev, newArea]);
}}
>
Add area
</Button>
</Col>
</Row>
{areas.length <= 0 ? (
<div className="select-none">
<Empty
image={
<IllustrationNoContent style={{ width: 160, height: 160 }} />
}
darkModeImage={
<IllustrationNoContentDark style={{ width: 160, height: 160 }} />
}
title="No subject areas"
description="Add subject areas to compartmentalize tables!"
/>
</div>
) : (
<div className="p-2">
{areas.map((a, i) => (
<Row
gutter={6}
type="flex"
justify="start"
align="middle"
key={i}
id={`scroll_area_${a.id}`}
className="my-3"
>
<Col span={18}>
<Input
value={a.name}
onChange={(value, e) => updateArea(a.id, { name: value })}
field="name"
/>
</Col>
<Col span={3}>
<Popover
content={
<div>
<div className="flex justify-between items-center p-2">
<div className="font-medium">Theme</div>
<Button
type="tertiary"
size="small"
onClick={() =>
updateArea(i, { color: defaultTableTheme })
}
>
Clear
</Button>
</div>
<hr />
<div className="py-3">
<div>
{tableThemes
.slice(0, Math.ceil(tableThemes.length / 2))
.map((c) => (
<button
key={c}
style={{ backgroundColor: c }}
className="p-3 rounded-full mx-1"
onClick={() => updateArea(i, { color: c })}
>
{a.color === c ? (
<IconCheckboxTick
style={{ color: "white" }}
/>
) : (
<IconCheckboxTick style={{ color: c }} />
)}
</button>
))}
</div>
<div className="mt-3">
{tableThemes
.slice(Math.ceil(tableThemes.length / 2))
.map((c) => (
<button
key={c}
style={{ backgroundColor: c }}
className="p-3 rounded-full mx-1"
onClick={() => updateArea(i, { color: c })}
>
<IconCheckboxTick
style={{
color: a.color === c ? "white" : c,
}}
/>
</button>
))}
</div>
</div>
</div>
}
trigger="click"
position="bottomLeft"
showArrow
>
<div
className="h-[32px] w-[32px] rounded"
style={{ backgroundColor: a.color }}
/>
</Popover>
</Col>
<Col span={3}>
<Button
icon={<IconDeleteStroked />}
type="danger"
onClick={(e) => {
e.stopPropagation();
Toast.success(`Area deleted!`);
setAreas((prev) =>
prev
.filter((e) => e.id !== i)
.map((e, idx) => ({ ...e, id: idx }))
);
}}
// className="delete-button"
></Button>
</Col>
</Row>
))}
</div>
)}
</div>
);
}

View File

@ -590,6 +590,23 @@ export default function ControlPanel(props) {
> >
Issues Issues
</Dropdown.Item> </Dropdown.Item>
<Dropdown.Item
icon={
layout.areas ? (
<IconCheckboxTick />
) : (
<div className="px-2"></div>
)
}
onClick={() =>
setLayout((prev) => ({
...prev,
areas: !prev.areas,
}))
}
>
Subject areas
</Dropdown.Item>
<Dropdown.Item <Dropdown.Item
icon={ icon={
layout.editor ? ( layout.editor ? (

View File

@ -1,4 +1,4 @@
import { React, useContext, useState } from "react"; import { React, useState } from "react";
import CodeMirror from "@uiw/react-codemirror"; import CodeMirror from "@uiw/react-codemirror";
import { createTheme } from "@uiw/codemirror-themes"; import { createTheme } from "@uiw/codemirror-themes";
import { sql } from "@codemirror/lang-sql"; import { sql } from "@codemirror/lang-sql";
@ -8,8 +8,7 @@ import Shape from "./shape";
import { Tabs } from "@douyinfe/semi-ui"; import { Tabs } from "@douyinfe/semi-ui";
import TableOverview from "./table_overview"; import TableOverview from "./table_overview";
import ReferenceOverview from "./reference_overview"; import ReferenceOverview from "./reference_overview";
import { defaultTableTheme } from "../data/data"; import AreaOverview from "./area_overview";
import { AreaContext } from "../pages/editor";
// import { TableContext } from "../pages/editor"; // import { TableContext } from "../pages/editor";
const myTheme = createTheme({ const myTheme = createTheme({
@ -30,13 +29,13 @@ const EditorPanel = (props) => {
const [tab, setTab] = useState("1"); const [tab, setTab] = useState("1");
// const map = useRef(new Map()); // const map = useRef(new Map());
// const {tables, setTables} = useContext(TableContext); // const {tables, setTables} = useContext(TableContext);
const { areas, setAreas } = useContext(AreaContext);
const tabList = [ const tabList = [
{ tab: "Tables", itemKey: "1" }, { tab: "Tables", itemKey: "1" },
{ tab: "Relationships", itemKey: "2" }, { tab: "Relationships", itemKey: "2" },
{ tab: "Shapes", itemKey: "3" }, { tab: "Subject Areas", itemKey: "3" },
{ tab: "Editor", itemKey: "4" }, { tab: "Shapes", itemKey: "4" },
{ tab: "Editor", itemKey: "5" },
]; ];
const contentList = [ const contentList = [
<TableOverview <TableOverview
@ -44,6 +43,7 @@ const EditorPanel = (props) => {
setSelectedTable={props.setSelectedTable} setSelectedTable={props.setSelectedTable}
/>, />,
<ReferenceOverview />, <ReferenceOverview />,
<AreaOverview/>,
<Shape />, <Shape />,
<CodeMirror <CodeMirror
value={props.code} value={props.code}
@ -69,25 +69,6 @@ const EditorPanel = (props) => {
> >
<div className="p-2">{contentList[parseInt(tab) - 1]}</div> <div className="p-2">{contentList[parseInt(tab) - 1]}</div>
</Tabs> </Tabs>
<button
onClick={() => {
const newArea = {
id: areas.length,
name: `area_${areas.length}`,
x: 0,
y: 0,
width: 200,
height: 200,
color: defaultTableTheme,
};
setAreas((prev) => {
const updatedTables = [...prev, newArea];
return updatedTables;
});
}}
>
add area
</button>
<br /> <br />
<button <button
onClick={() => { onClick={() => {

View File

@ -132,15 +132,15 @@ export default function Table(props) {
<Popover <Popover
content={ content={
<div className="text-slate-600"> <div className="text-slate-600">
<p className="mb-2"> <div className="mb-2">
<strong>Comment :</strong>{" "} <strong>Comment :</strong>{" "}
{props.tableData.comment === "" ? ( {props.tableData.comment === "" ? (
"No comment" "No comment"
) : ( ) : (
<div>{props.tableData.comment}</div> <div>{props.tableData.comment}</div>
)} )}
</p> </div>
<p className="text-slate-600"> <div className="text-slate-600">
<strong <strong
className={`${ className={`${
props.tableData.indices.length === 0 ? "" : "block" props.tableData.indices.length === 0 ? "" : "block"
@ -169,7 +169,7 @@ export default function Table(props) {
))} ))}
</div> </div>
)} )}
</p> </div>
</div> </div>
} }
position="rightTop" position="rightTop"

View File

@ -23,6 +23,7 @@ export default function Editor(props) {
sidebar: true, sidebar: true,
services: true, services: true,
tables: true, tables: true,
areas: true,
relationships: true, relationships: true,
issues: true, issues: true,
editor: true, editor: true,