diff --git a/src/components/EditorCanvas/Canvas.jsx b/src/components/EditorCanvas/Canvas.jsx
index e0c1695e5..035fc2eda 100644
--- a/src/components/EditorCanvas/Canvas.jsx
+++ b/src/components/EditorCanvas/Canvas.jsx
@@ -1,4 +1,4 @@
-import { useRef, useState, useEffect } from "react";
+import { useRef, useState, useEffect, useCallback } from "react";
import {
Action,
RelationshipType,
@@ -15,6 +15,7 @@ import {
} from "../../data/constants";
import { dbToTypes } from "../../data/datatypes";
import { Toast, Modal, Input, InputNumber } from "@douyinfe/semi-ui";
+import ColorPicker from "../ColorPicker";
import Table from "./Table";
import Area from "./Area";
import Relationship from "./Relationship";
@@ -269,6 +270,14 @@ export default function Canvas() {
field: null,
});
+ const [fieldForeignKeyColorModal, setFieldForeignKeyColorModal] = useState({
+ visible: false,
+ tableId: null,
+ fieldId: null,
+ field: null,
+ currentColor: "",
+ });
+
// Field properties modal internal state
const [fieldPropertiesPrecision, setFieldPropertiesPrecision] = useState("");
const [fieldPropertiesAccuracy, setFieldPropertiesAccuracy] = useState("");
@@ -1073,7 +1082,8 @@ export default function Canvas() {
if (!match) {
return {
valid: false,
- message: "Invalid format. Use (x,y) where x is 0 or 1, and y is greater than 1 or *",
+ message:
+ "Invalid format. Use (x,y) where x is 0 or 1, and y is greater than 1 or *",
};
}
@@ -1817,6 +1827,99 @@ export default function Canvas() {
setFieldPropertiesAccuracy("");
};
+ const handleSetFieldForeignKeyColor = () => {
+ if (
+ fieldContextMenu.tableId !== null &&
+ fieldContextMenu.fieldId !== null
+ ) {
+ const table = tables.find((t) => t.id === fieldContextMenu.tableId);
+ const field = table?.fields.find(
+ (f) => f.id === fieldContextMenu.fieldId,
+ );
+
+ setFieldForeignKeyColorModal({
+ visible: true,
+ tableId: fieldContextMenu.tableId,
+ fieldId: fieldContextMenu.fieldId,
+ field: field,
+ currentColor: field?.fkColor || settings.defaultFkColor,
+ });
+ handleFieldContextMenuClose();
+ }
+ };
+
+ const handleFieldForeignKeyColorConfirm = useCallback(
+ (color) => {
+ const { tableId, fieldId } = fieldForeignKeyColorModal;
+
+ pushUndo({
+ action: Action.EDIT,
+ element: ObjectType.TABLE,
+ component: "field",
+ tid: tableId,
+ fid: fieldId,
+ undo: {
+ fkColor:
+ tables
+ .find((t) => t.id === tableId)
+ ?.fields.find((f) => f.id === fieldId)?.fkColor || null,
+ },
+ redo: { fkColor: color },
+ message: t("edit_table", {
+ tableName: tables.find((t) => t.id === tableId)?.name || "",
+ extra: "[foreign key color]",
+ }),
+ });
+
+ updateField(tableId, fieldId, { fkColor: color });
+ setFieldForeignKeyColorModal({
+ visible: false,
+ tableId: null,
+ fieldId: null,
+ field: null,
+ currentColor: "",
+ });
+ },
+ [fieldForeignKeyColorModal, pushUndo, tables, t, updateField],
+ );
+
+ const handleFieldForeignKeyColorCancel = useCallback(() => {
+ setFieldForeignKeyColorModal({
+ visible: false,
+ tableId: null,
+ fieldId: null,
+ field: null,
+ currentColor: "",
+ });
+ }, []);
+
+ // Handle keyboard events for FK color modal
+ useEffect(() => {
+ if (!fieldForeignKeyColorModal.visible) return;
+
+ const handleKeyDown = (e) => {
+ if (e.key === "Enter") {
+ e.preventDefault();
+ handleFieldForeignKeyColorConfirm(
+ fieldForeignKeyColorModal.currentColor,
+ );
+ } else if (e.key === "Escape") {
+ e.preventDefault();
+ handleFieldForeignKeyColorCancel();
+ }
+ };
+
+ document.addEventListener("keydown", handleKeyDown);
+ return () => {
+ document.removeEventListener("keydown", handleKeyDown);
+ };
+ }, [
+ fieldForeignKeyColorModal.visible,
+ fieldForeignKeyColorModal.currentColor,
+ handleFieldForeignKeyColorConfirm,
+ handleFieldForeignKeyColorCancel,
+ ]);
+
const handleEditNoteContent = () => {
if (noteContextMenu.noteId !== null) {
// Focus on the textarea for the note
@@ -3411,6 +3514,7 @@ export default function Canvas() {
onToggleUnique={handleToggleFieldUnique}
onToggleAutoIncrement={handleToggleFieldAutoIncrement}
onEditProperties={handleFieldEditProperties}
+ onSetForeignKeyColor={handleSetFieldForeignKeyColor}
/>
{e.name} @@ -610,7 +610,7 @@ export default function Table(props) { fieldData.foreignK ? "font-medium" : "" }`} style={{ - color: fieldData.foreignK ? settings.defaultFkColor : 'inherit' + color: fieldData.foreignK ? (fieldData.fkColor || settings.defaultFkColor) : 'inherit' }} > {fieldData.name} diff --git a/src/components/EditorSidePanel/TablesTab/FieldDetails.jsx b/src/components/EditorSidePanel/TablesTab/FieldDetails.jsx index f013555d8..6718f2a5c 100644 --- a/src/components/EditorSidePanel/TablesTab/FieldDetails.jsx +++ b/src/components/EditorSidePanel/TablesTab/FieldDetails.jsx @@ -6,13 +6,15 @@ import { TagInput, Checkbox, Toast, + Popover, } from "@douyinfe/semi-ui"; import { Action, ObjectType } from "../../../data/constants"; import { IconDeleteStroked } from "@douyinfe/semi-icons"; -import { useDiagram, useUndoRedo } from "../../../hooks"; +import { useDiagram, useUndoRedo, useSettings } from "../../../hooks"; import { useTranslation } from "react-i18next"; import { dbToTypes } from "../../../data/datatypes"; import { databases } from "../../../data/databases"; +import ColorPicker from "../../ColorPicker"; export default function FieldDetails({ data, tid, index }) { const { t } = useTranslation(); @@ -20,6 +22,7 @@ export default function FieldDetails({ data, tid, index }) { const { pushUndo } = useUndoRedo(); const { updateField, deleteField } = useDiagram(); const [editField, setEditField] = useState({}); + const { settings } = useSettings(); return (