mirror of
https://github.com/drawdb-io/drawdb.git
synced 2026-02-12 02:00:40 +08:00
Add enums tab
This commit is contained in:
85
src/components/EditorSidePanel/EnumsTab/EnumDetails.jsx
Normal file
85
src/components/EditorSidePanel/EnumsTab/EnumDetails.jsx
Normal file
@@ -0,0 +1,85 @@
|
||||
import { useState } from "react";
|
||||
import { Button, Input, TagInput } from "@douyinfe/semi-ui";
|
||||
import { IconDeleteStroked } from "@douyinfe/semi-icons";
|
||||
import { useEnums, useUndoRedo } from "../../../hooks";
|
||||
import { Action, ObjectType } from "../../../data/constants";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function EnumDetails({ data, i }) {
|
||||
const { t } = useTranslation();
|
||||
const { deleteEnum, updateEnum } = useEnums();
|
||||
const { setUndoStack, setRedoStack } = useUndoRedo();
|
||||
const [editField, setEditField] = useState({});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className="flex justify-center items-center gap-2"
|
||||
id={`scroll_enum_${data.id}`}
|
||||
>
|
||||
<div className="font-semibold">{t("Name")}: </div>
|
||||
<Input
|
||||
value={data.name}
|
||||
placeholder={t("name")}
|
||||
onChange={(value) => updateEnum(data.id, { name: value })}
|
||||
onFocus={(e) => setEditField({ name: e.target.value })}
|
||||
onBlur={(e) => {
|
||||
if (e.target.value === editField.name) return;
|
||||
setUndoStack((prev) => [
|
||||
...prev,
|
||||
{
|
||||
action: Action.EDIT,
|
||||
element: ObjectType.ENUM,
|
||||
aid: i,
|
||||
undo: editField,
|
||||
redo: { name: e.target.value },
|
||||
message: t("edit_enum", {
|
||||
enumName: e.target.value,
|
||||
extra: "[name]",
|
||||
}),
|
||||
},
|
||||
]);
|
||||
setRedoStack([]);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<TagInput
|
||||
separator={[",", ", ", " ,"]}
|
||||
value={data.values}
|
||||
addOnBlur
|
||||
className="my-2"
|
||||
placeholder={t("values")}
|
||||
onChange={(v) => updateEnum(i, { values: v })}
|
||||
onFocus={() => setEditField({ values: data.values })}
|
||||
onBlur={() => {
|
||||
if (JSON.stringify(editField.values) === JSON.stringify(data.values))
|
||||
return;
|
||||
setUndoStack((prev) => [
|
||||
...prev,
|
||||
{
|
||||
action: Action.EDIT,
|
||||
element: ObjectType.TABLE,
|
||||
component: "field",
|
||||
eid: i,
|
||||
undo: editField,
|
||||
redo: { values: data.values },
|
||||
message: t("edit_enum", {
|
||||
enumName: data.name,
|
||||
extra: "[values]",
|
||||
}),
|
||||
},
|
||||
]);
|
||||
setRedoStack([]);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
block
|
||||
icon={<IconDeleteStroked />}
|
||||
type="danger"
|
||||
onClick={() => deleteEnum(i, true)}
|
||||
>
|
||||
{t("delete")}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
39
src/components/EditorSidePanel/EnumsTab/EnumsTab.jsx
Normal file
39
src/components/EditorSidePanel/EnumsTab/EnumsTab.jsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Button, Collapse } from "@douyinfe/semi-ui";
|
||||
import { useEnums } from "../../../hooks";
|
||||
import { IconPlus } from "@douyinfe/semi-icons";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import SearchBar from "./SearchBar";
|
||||
import EnumDetails from "./EnumDetails";
|
||||
|
||||
export default function EnumsTab() {
|
||||
const { enums, addEnum } = useEnums();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex gap-2">
|
||||
<SearchBar />
|
||||
<div>
|
||||
<Button icon={<IconPlus />} block onClick={() => addEnum()}>
|
||||
{t("add_enum")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Collapse>
|
||||
{enums.map((e, i) => (
|
||||
<Collapse.Panel
|
||||
key={e.name + i}
|
||||
header={
|
||||
<div className="overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
{e.name}
|
||||
</div>
|
||||
}
|
||||
itemKey={`${i}`}
|
||||
>
|
||||
<EnumDetails data={e} i={i} />
|
||||
</Collapse.Panel>
|
||||
))}
|
||||
</Collapse>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
41
src/components/EditorSidePanel/EnumsTab/SearchBar.jsx
Normal file
41
src/components/EditorSidePanel/EnumsTab/SearchBar.jsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { useState } from "react";
|
||||
import { AutoComplete } from "@douyinfe/semi-ui";
|
||||
import { IconSearch } from "@douyinfe/semi-icons";
|
||||
import { useEnums } from "../../../hooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function SearchBar() {
|
||||
const { enums } = useEnums();
|
||||
const [value, setValue] = useState("");
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [filteredResult, setFilteredResult] = useState(
|
||||
enums.map((e) => e.name),
|
||||
);
|
||||
|
||||
const handleStringSearch = (value) => {
|
||||
setFilteredResult(
|
||||
enums.map((e) => e.name).filter((i) => i.includes(value)),
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AutoComplete
|
||||
data={filteredResult}
|
||||
value={value}
|
||||
showClear
|
||||
prefix={<IconSearch />}
|
||||
placeholder={t("search")}
|
||||
onSearch={(v) => handleStringSearch(v)}
|
||||
emptyContent={<div className="p-3 popover-theme">{t("not_found")}</div>}
|
||||
onChange={(v) => setValue(v)}
|
||||
onSelect={(v) => {
|
||||
const i = enums.findIndex((t) => t.name === v);
|
||||
document
|
||||
.getElementById(`scroll_enum_${i}`)
|
||||
.scrollIntoView({ behavior: "smooth" });
|
||||
}}
|
||||
className="w-full"
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Tabs, TabPane } from "@douyinfe/semi-ui";
|
||||
import { DB, Tab } from "../../data/constants";
|
||||
import { Tab } from "../../data/constants";
|
||||
import { useLayout, useSelect, useTables } from "../../hooks";
|
||||
import RelationshipsTab from "./RelationshipsTab/RelationshipsTab";
|
||||
import TypesTab from "./TypesTab/TypesTab";
|
||||
@@ -9,6 +9,8 @@ import NotesTab from "./NotesTab/NotesTab";
|
||||
import TablesTab from "./TablesTab/TablesTab";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMemo } from "react";
|
||||
import { databases } from "../../data/databases";
|
||||
import EnumsTab from "./EnumsTab/EnumsTab";
|
||||
|
||||
export default function SidePanel({ width, resize, setResize }) {
|
||||
const { layout } = useLayout();
|
||||
@@ -27,13 +29,23 @@ export default function SidePanel({ width, resize, setResize }) {
|
||||
{ tab: t("subject_areas"), itemKey: Tab.AREAS, component: <AreasTab /> },
|
||||
{ tab: t("notes"), itemKey: Tab.NOTES, component: <NotesTab /> },
|
||||
];
|
||||
if (database === DB.GENERIC || database === DB.POSTGRES) {
|
||||
|
||||
if (databases[database].hasTypes) {
|
||||
tabs.push({
|
||||
tab: t("types"),
|
||||
itemKey: Tab.TYPES,
|
||||
component: <TypesTab />,
|
||||
});
|
||||
}
|
||||
|
||||
if (databases[database].hasEnums) {
|
||||
tabs.push({
|
||||
tab: t("enums"),
|
||||
itemKey: Tab.ENUMS,
|
||||
component: <EnumsTab />,
|
||||
});
|
||||
}
|
||||
|
||||
return tabs;
|
||||
}, [t, database]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user