Files
relspecgo/pkg/ui/column_screens.go
Hein 1795eb64d1
Some checks failed
CI / Test (1.24) (push) Failing after 1m3s
CI / Lint (push) Failing after -27m11s
CI / Build (push) Successful in 40s
Integration Tests / Integration Tests (push) Failing after -28m11s
CI / Test (1.25) (push) Failing after -26m33s
feat(ui): 🎨 Implement schema and table management screens
* Add schema management screen with list and editor
* Implement table management screen with list and editor
* Create data operations for schema and table management
* Define UI rules and guidelines for consistency
* Ensure circular tab navigation and keyboard shortcuts
* Add forms for creating and editing schemas and tables
* Implement confirmation dialogs for destructive actions
2026-01-04 18:29:29 +02:00

209 lines
6.3 KiB
Go

package ui
import (
"fmt"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"git.warky.dev/wdevs/relspecgo/pkg/models"
)
// showColumnEditor shows editor for a specific column
func (se *SchemaEditor) showColumnEditor(schemaIndex, tableIndex, colIndex int, column *models.Column) {
form := tview.NewForm()
// Store original name to handle renames
originalName := column.Name
// Local variables to collect changes
newName := column.Name
newType := column.Type
newIsPK := column.IsPrimaryKey
newIsNotNull := column.NotNull
newDefault := column.Default
newDescription := column.Description
// Column type options: PostgreSQL, MySQL, SQL Server, and common SQL types
columnTypes := []string{
// Numeric Types
"SMALLINT", "INTEGER", "BIGINT", "INT", "TINYINT", "FLOAT", "REAL", "DOUBLE PRECISION",
"DECIMAL(10,2)", "NUMERIC", "DECIMAL", "NUMERIC(10,2)",
// Character Types
"CHAR", "VARCHAR", "VARCHAR(255)", "TEXT", "NCHAR", "NVARCHAR", "NVARCHAR(255)",
// Boolean
"BOOLEAN", "BOOL", "BIT",
// Date/Time Types
"DATE", "TIME", "TIMESTAMP", "TIMESTAMP WITH TIME ZONE", "INTERVAL",
"DATETIME", "DATETIME2", "DATEFIRST",
// UUID and JSON
"UUID", "GUID", "JSON", "JSONB",
// Binary Types
"BYTEA", "BLOB", "IMAGE", "VARBINARY", "VARBINARY(MAX)", "BINARY",
// PostgreSQL Special Types
"int4range", "int8range", "numrange", "tsrange", "tstzrange", "daterange",
"HSTORE", "CITEXT", "INET", "MACADDR", "POINT", "LINE", "LSEG", "BOX", "PATH", "POLYGON", "CIRCLE",
// Array Types
"INTEGER ARRAY", "VARCHAR ARRAY", "TEXT ARRAY", "BIGINT ARRAY",
// MySQL Specific
"MEDIUMINT", "DOUBLE", "FLOAT(10,2)",
// SQL Server Specific
"MONEY", "SMALLMONEY", "SQL_VARIANT",
}
selectedTypeIndex := 0
// Add existing type if not already in the list
typeExists := false
for i, opt := range columnTypes {
if opt == column.Type {
selectedTypeIndex = i
typeExists = true
break
}
}
if !typeExists && column.Type != "" {
columnTypes = append(columnTypes, column.Type)
selectedTypeIndex = len(columnTypes) - 1
}
form.AddInputField("Column Name", column.Name, 40, nil, func(value string) {
newName = value
})
form.AddDropDown("Type", columnTypes, selectedTypeIndex, func(option string, index int) {
newType = option
})
form.AddCheckbox("Primary Key", column.IsPrimaryKey, func(checked bool) {
newIsPK = checked
})
form.AddCheckbox("Not Null", column.NotNull, func(checked bool) {
newIsNotNull = checked
})
defaultStr := ""
if column.Default != nil {
defaultStr = fmt.Sprintf("%v", column.Default)
}
form.AddInputField("Default Value", defaultStr, 40, nil, func(value string) {
newDefault = value
})
form.AddTextArea("Description", column.Description, 40, 5, 0, func(value string) {
newDescription = value
})
form.AddButton("Save", func() {
// Apply changes using dataops
se.UpdateColumn(schemaIndex, tableIndex, originalName, newName, newType, newIsPK, newIsNotNull, newDefault, newDescription)
se.pages.RemovePage("column-editor")
se.pages.SwitchToPage("table-editor")
})
form.AddButton("Delete", func() {
se.showDeleteColumnConfirm(schemaIndex, tableIndex, originalName)
})
form.AddButton("Back", func() {
// Discard changes - don't apply them
se.pages.RemovePage("column-editor")
se.pages.SwitchToPage("table-editor")
})
form.SetBorder(true).SetTitle(" Edit Column ").SetTitleAlign(tview.AlignLeft)
form.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyEscape {
se.showExitConfirmation("column-editor", "table-editor")
return nil
}
return event
})
se.pages.AddPage("column-editor", form, true, true)
}
// showNewColumnDialog shows dialog to create a new column
func (se *SchemaEditor) showNewColumnDialog(schemaIndex, tableIndex int) {
form := tview.NewForm()
columnName := ""
dataType := "VARCHAR(255)"
// Column type options: PostgreSQL, MySQL, SQL Server, and common SQL types
columnTypes := []string{
// Numeric Types
"SMALLINT", "INTEGER", "BIGINT", "INT", "TINYINT", "FLOAT", "REAL", "DOUBLE PRECISION",
"DECIMAL(10,2)", "NUMERIC", "DECIMAL", "NUMERIC(10,2)",
// Character Types
"CHAR", "VARCHAR", "VARCHAR(255)", "TEXT", "NCHAR", "NVARCHAR", "NVARCHAR(255)",
// Boolean
"BOOLEAN", "BOOL", "BIT",
// Date/Time Types
"DATE", "TIME", "TIMESTAMP", "TIMESTAMP WITH TIME ZONE", "INTERVAL",
"DATETIME", "DATETIME2", "DATEFIRST",
// UUID and JSON
"UUID", "GUID", "JSON", "JSONB",
// Binary Types
"BYTEA", "BLOB", "IMAGE", "VARBINARY", "VARBINARY(MAX)", "BINARY",
// PostgreSQL Special Types
"int4range", "int8range", "numrange", "tsrange", "tstzrange", "daterange",
"HSTORE", "CITEXT", "INET", "MACADDR", "POINT", "LINE", "LSEG", "BOX", "PATH", "POLYGON", "CIRCLE",
// Array Types
"INTEGER ARRAY", "VARCHAR ARRAY", "TEXT ARRAY", "BIGINT ARRAY",
// MySQL Specific
"MEDIUMINT", "DOUBLE", "FLOAT(10,2)",
// SQL Server Specific
"MONEY", "SMALLMONEY", "SQL_VARIANT",
}
selectedTypeIndex := 0
form.AddInputField("Column Name", "", 40, nil, func(value string) {
columnName = value
})
form.AddDropDown("Data Type", columnTypes, selectedTypeIndex, func(option string, index int) {
dataType = option
})
form.AddCheckbox("Primary Key", false, nil)
form.AddCheckbox("Not Null", false, nil)
form.AddCheckbox("Unique", false, nil)
form.AddButton("Save", func() {
if columnName == "" {
return
}
// Get form values
isPK := form.GetFormItemByLabel("Primary Key").(*tview.Checkbox).IsChecked()
isNotNull := form.GetFormItemByLabel("Not Null").(*tview.Checkbox).IsChecked()
se.CreateColumn(schemaIndex, tableIndex, columnName, dataType, isPK, isNotNull)
table := se.db.Schemas[schemaIndex].Tables[tableIndex]
se.pages.RemovePage("new-column")
se.pages.RemovePage("table-editor")
se.showTableEditor(schemaIndex, tableIndex, table)
})
form.AddButton("Back", func() {
table := se.db.Schemas[schemaIndex].Tables[tableIndex]
se.pages.RemovePage("new-column")
se.pages.RemovePage("table-editor")
se.showTableEditor(schemaIndex, tableIndex, table)
})
form.SetBorder(true).SetTitle(" New Column ").SetTitleAlign(tview.AlignLeft)
form.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyEscape {
se.showExitConfirmation("new-column", "table-editor")
return nil
}
return event
})
se.pages.AddPage("new-column", form, true, true)
}