import React, { useState, useEffect, CSSProperties } from "react"; import { X, Plus, TableOfContents } from "lucide-react"; // import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'; import DarkSelect from "./DarkSelect.js"; import ModernTooltip from "./ModernTooltip.js"; import Stores from "./data/Stores.js"; const NewModelForm = () => { const COLUMN_DEFAULTS = window.COLUMN_DEFAULTS; const DEFAULT_LINE = { column_type: "string", column_name: "", default: "", unique: false, foreign_key: false, index: "", index_algorithm: "default", nullable: true, }; const [formRows, setFormRows] = useState([DEFAULT_LINE]); const [showOptions, setShowOptions] = useState({}); const handleAddRow = (event) => { event.preventDefault(); // Don't add if the name is empty: if (formRows.at(-1).column_name === "") { return; } setFormRows([...formRows, { ...DEFAULT_LINE }]); }; const handleDeleteRow = (index, event) => { event.preventDefault(); // Don't delete if there is only one row: if (formRows.length === 1) { return; } setFormRows(formRows.filter((row, rowIndex) => rowIndex !== index)); }; const handleInputChange = (index, event) => { const { name, value } = event.target; const updatedRows = [...formRows]; let newValue = value; // Sanitise default input: if (name === "column_name") { newValue = Stores().snakeCase(newValue); newValue = newValue.trim(); } updatedRows[index][name] = newValue; // Reset default if change. if (name === "column_type") { // result index: // result default: updatedRows[index].index = ""; updatedRows[index].default = ""; // close modal: setShowOptions({ [index]: false }); } if (name === "default" && newValue !== "") { updatedRows[index].nullable = false; } // For the selector of the referenced model: if ( name === "column_type" && value === "references" && Stores().APP_MODELS[0] ) { updatedRows[index].column_name = Stores().APP_MODELS[0].underscore; updatedRows[index].foreign_key = true; } if ( updatedRows[index].column_type !== "references" && updatedRows[index].foreign_key === true ) { updatedRows[index].foreign_key = false; } // Reset unique if no index is selected: if (name === "index" && newValue === "") { updatedRows[index].unique = false; updatedRows[index].index_algorithm = "default"; } setFormRows(updatedRows); }; const handleCheckboxChange = (index, event) => { const { name, checked, value } = event.target; const updatedRows = [...formRows]; let finalValue = checked; if (name === "nullable" && checked && updatedRows[index].default !== "") { return false; } if (name === "unique" && checked && updatedRows[index].index === "") { updatedRows[index].index = "default"; } if ( name === "index_algorithm" && checked && updatedRows[index].index != "" ) { finalValue = value === "concurrently" ? "concurrently" : "default"; } updatedRows[index][name] = finalValue; setFormRows(updatedRows); }; const handleOptionClick = (index, option) => { const updatedRows = [...formRows]; updatedRows[index].default = option.value; if (updatedRows[index].default !== "") { updatedRows[index].nullable = false; } else { updatedRows[index].nullable = true; } setFormRows(updatedRows); setShowOptions({ [index]: false }); }; const handleShowOptions = (index, event) => { event.preventDefault(); if (showOptions[index]) { setShowOptions({ [index]: false }); } else { setShowOptions({ [index]: true }); } }; const addToForm = () => { // Add the form to the hidden input: document.getElementById("form_attributes").value = JSON.stringify(formRows); }; useEffect(() => { addToForm(); }, [formRows]); // This effect depends on formRows return (
{formRows.map((row, index) => ( {row.column_type === "references" ? ( ) : ( )} ))}
Name Type Default value Index Options
{ const syntheticEvent = { target: { name: "column_name", value: selectedOption.value, }, }; handleInputChange(index, syntheticEvent); }} />
handleInputChange(index, event)} />
{ if (selectedOption && selectedOption.value) { const syntheticEvent = { target: { name: "column_type", value: selectedOption.value, }, }; handleInputChange(index, syntheticEvent); } }} />
{row.column_type !== "references" && (
handleInputChange(index, event)} /> {COLUMN_DEFAULTS[row.column_type] && (
)} {COLUMN_DEFAULTS[row.column_type] && showOptions[index] && (
{COLUMN_DEFAULTS[row.column_type] && COLUMN_DEFAULTS[row.column_type].map((option) => (
handleOptionClick(index, option)} className="hover:bg-localtower-900 p-2 active:opacity-60 cursor-pointer flex flex-row gap-2 items-center" >
{option.label}
{option.example}
))}
)}
)}
{row.column_type !== "references" && (
{ const syntheticEvent = { target: { name: "index", value: selectedOption.value, }, }; handleInputChange(index, syntheticEvent); }} />
)}
{row.column_type !== "references" && ( )} {row.column_type !== "references" && ( )}
handleDeleteRow(index, event)} className="text-xs px-1.5 py-1.5" />
); }; export default NewModelForm;