Add enums tab

This commit is contained in:
1ilit
2024-06-30 13:19:21 +03:00
parent 259835892a
commit 810afe4bc0
13 changed files with 313 additions and 18 deletions

View 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>
);
}

View 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>
);
}

View 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"
/>
);
}

View File

@@ -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]);