* 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
300 lines
10 KiB
Markdown
300 lines
10 KiB
Markdown
# UI Rules and Guidelines
|
|
|
|
## Layout Requirements
|
|
|
|
All layouts / forms must be in seperate files regarding their domain or entity.
|
|
|
|
### Screen Layout Structure
|
|
|
|
All screens must follow this consistent layout:
|
|
|
|
1. **Title at the Top** (1 row, fixed height)
|
|
- Centered bold text: `[::b]Title Text`
|
|
- Use `tview.NewTextView()` with `SetTextAlign(tview.AlignCenter)`
|
|
- Enable dynamic colors: `SetDynamicColors(true)`
|
|
|
|
2. **Content in the Middle** (flexible height)
|
|
- Tables, lists, forms, or info displays
|
|
- Uses flex weight of 1 for dynamic sizing
|
|
|
|
3. **Action Buttons at the Bottom** (1 row, fixed height)
|
|
- Must be in a horizontal flex container
|
|
- Action buttons before Back button
|
|
- Back button is always last
|
|
|
|
### Form Layout Structure
|
|
|
|
All forms must follow this button order:
|
|
|
|
1. **Save Button** (always first)
|
|
- Label: "Save"
|
|
- Primary action that commits changes
|
|
|
|
2. **Delete Button** (optional, only for edit forms)
|
|
- Label: "Delete"
|
|
- Only shown when editing existing items (not for new items)
|
|
- Must show confirmation dialog before deletion
|
|
|
|
3. **Back Button** (always last)
|
|
- Label: "Back"
|
|
- Returns to previous screen without saving
|
|
|
|
**Button Order Examples:**
|
|
- **New Item Forms:** Save, Back
|
|
- **Edit Item Forms:** Save, Delete, Back
|
|
|
|
## Tab Navigation
|
|
|
|
All screens must implement circular tab navigation:
|
|
|
|
1. **Tab Key** - Moves focus to the next focusable element
|
|
2. **Shift+Tab (BackTab)** - Moves focus to the previous focusable element
|
|
3. **At the End** - Tab cycles back to the first element
|
|
4. **At the Start** - Shift+Tab cycles back to the last element
|
|
|
|
**Navigation Flow Pattern:**
|
|
- Each widget must handle both Tab and BackTab
|
|
- First widget: BackTab → Last widget, Tab → Second widget
|
|
- Middle widgets: BackTab → Previous widget, Tab → Next widget
|
|
- Last widget: BackTab → Previous widget, Tab → First widget
|
|
|
|
## Keyboard Shortcuts
|
|
|
|
### Standard Keys
|
|
|
|
- **ESC** - Cancel current operation or go back to previous screen
|
|
- **Tab** - Move focus forward (circular)
|
|
- **Shift+Tab** - Move focus backward (circular)
|
|
- **Enter** - Activate/select current item in tables and lists
|
|
|
|
### Letter Key Shortcuts
|
|
|
|
- **'n'** - New (create new item)
|
|
- **'b'** - Back (return to previous screen)
|
|
- **'e'** - Edit (edit current item)
|
|
- **'d'** - Delete (delete current item)
|
|
- **'c'** - Edit Column (in table editor)
|
|
- **'s'** - Manage Schemas (in main menu)
|
|
- **'t'** - Manage Tables (in main menu)
|
|
- **'q'** - Quit/Exit (in main menu)
|
|
|
|
## Consistency Requirements
|
|
|
|
1. **Layout Structure** - All screens: Title (top) → Content (middle) → Buttons (bottom)
|
|
2. **Title Format** - Bold (`[::b]`), centered, dynamic colors enabled
|
|
3. **Tables** - Fixed headers (row 0), borders enabled, selectable rows
|
|
4. **Buttons** - Include keyboard shortcuts in labels (e.g., "Back [b]")
|
|
5. **Forms** - Button order: Save, Delete (if edit), Back
|
|
6. **Destructive Actions** - Always show confirmation dialogs
|
|
7. **ESC Key** - All screens support ESC to go back
|
|
8. **Action Buttons** - Positioned before Back button, in logical order
|
|
9. **Data Refresh** - Always refresh the previous screen when returning from a form or dialog
|
|
|
|
## Widget Naming Conventions
|
|
|
|
- **Tables:** `schemaTable`, `tableTable`, `colTable`
|
|
- **Buttons:** Prefix with `btn` (e.g., `btnBack`, `btnDelete`, `btnNewSchema`)
|
|
- **Flex containers:** `btnFlex` for button containers, `flex` for main layout
|
|
- **Forms:** `form`
|
|
- **Lists:** `list`, `tableList`
|
|
- **Text views:** `title`, `info`
|
|
- Use camelCase for all variable names
|
|
|
|
## Page Naming Conventions
|
|
|
|
Use descriptive kebab-case names:
|
|
|
|
- **Main screens:** `main`, `schemas`, `tables`, `schema-editor`, `table-editor`, `column-editor`
|
|
- **Load/Save screens:** `load-database`, `save-database`
|
|
- **Creation dialogs:** `new-schema`, `new-table`, `new-column`, `new-table-from-list`
|
|
- **Edit dialogs:** `edit-schema`, `edit-table`
|
|
- **Confirmations:** `confirm-delete-schema`, `confirm-delete-table`, `confirm-delete-column`
|
|
- **Exit confirmations:** `exit-confirm`, `exit-editor-confirm`
|
|
- **Status dialogs:** `error-dialog`, `success-dialog`
|
|
|
|
## Dialog and Confirmation Rules
|
|
|
|
### Confirmation Dialogs
|
|
|
|
1. **Delete Confirmations** - Required for all destructive actions
|
|
- Show item name in confirmation text
|
|
- Buttons: "Cancel", "Delete"
|
|
- ESC key dismisses dialog
|
|
|
|
2. **Exit Confirmations** - Required when exiting forms with potential unsaved changes
|
|
- Text: "Exit without saving changes?"
|
|
- Buttons: "Cancel", "No, exit without saving"
|
|
- ESC key confirms exit
|
|
|
|
3. **Save Confirmations** - Optional, based on context
|
|
- Use for critical data changes
|
|
- Clear description of what will be saved
|
|
|
|
### Dialog Behavior
|
|
|
|
- All dialogs must capture ESC key for dismissal
|
|
- Modal dialogs overlay current screen
|
|
- Confirmation dialogs use `tview.NewModal()`
|
|
- Remove dialog page after action completes
|
|
|
|
## Data Refresh Rules
|
|
|
|
When returning from any form or dialog, the previous screen must be refreshed to show updated data. If Tables exists in the screen, their data must be updated:
|
|
|
|
1. **After Save** - Remove and recreate the previous screen to display updated data
|
|
2. **After Delete** - Remove and recreate the previous screen to display remaining data
|
|
3. **After Cancel/Back** - Remove and recreate the previous screen (data may have changed)
|
|
4. **Implementation Pattern** - Remove the current page, remove the previous page, then recreate the previous page with fresh data
|
|
|
|
**Why This Matters:**
|
|
- Ensures users see their changes immediately
|
|
- Prevents stale data from being displayed
|
|
- Maintains data consistency across the UI
|
|
- Avoids confusion from seeing outdated information
|
|
|
|
**Example Flow:**
|
|
```
|
|
User on Schema List → Opens Edit Schema Form → Saves Changes →
|
|
Returns to Schema List (refreshed with updated schema data)
|
|
```
|
|
|
|
## Big Loading/Saving Operations
|
|
|
|
When loading big changes, files or data, always give a load completed or load error dialog.
|
|
Do the same with saving.
|
|
This informs the user what happens.
|
|
When data is dirty, always ask the user to save when trying to exit.
|
|
|
|
### Load/Save Screens
|
|
|
|
- **Load Screen** (`load-database`) - Shown when no source is specified via command line
|
|
- Format dropdown (dbml, dctx, drawdb, graphql, json, yaml, gorm, bun, drizzle, prisma, typeorm, pgsql)
|
|
- File path input (for file-based formats)
|
|
- Connection string input (for database formats like pgsql)
|
|
- Load button [l] - Loads the database
|
|
- Create New button [n] - Creates a new empty database
|
|
- Exit button [q] - Exits the application
|
|
- ESC key exits the application
|
|
|
|
- **Save Screen** (`save-database`) - Accessible from main menu with 'w' key
|
|
- Format dropdown (same as load screen)
|
|
- File path input
|
|
- Help text explaining format requirements
|
|
- Save button [s] - Saves the database
|
|
- Back button [b] - Returns to main menu
|
|
- ESC key returns to main menu
|
|
- Pre-populated with existing save configuration if available
|
|
|
|
### Status Dialogs
|
|
|
|
- **Error Dialog** (`error-dialog`) - Shows error messages with OK button and ESC to dismiss
|
|
- **Success Dialog** (`success-dialog`) - Shows success messages with OK button, ESC to dismiss, and optional callback on close
|
|
|
|
## Screen Organization
|
|
|
|
Organize UI code into these files:
|
|
|
|
### UI Files (Screens and Dialogs)
|
|
|
|
- **editor.go** - Core `SchemaEditor` struct, constructor, `Run()` method, helper functions
|
|
- **main_menu.go** - Main menu screen
|
|
- **load_save_screens.go** - Database load and save screens
|
|
- **database_screens.go** - Database edit form
|
|
- **schema_screens.go** - Schema list, schema editor, new/edit schema dialogs
|
|
- **table_screens.go** - Tables list, table editor, new/edit table dialogs
|
|
- **column_screens.go** - Column editor, new column dialog
|
|
- **domain_screens.go** - Domain list, domain editor, new/edit domain dialogs
|
|
- **dialogs.go** - Confirmation dialogs (exit, delete)
|
|
|
|
### Data Operations Files (Business Logic)
|
|
|
|
- **schema_dataops.go** - Schema CRUD operations (Create, Read, Update, Delete)
|
|
- **table_dataops.go** - Table CRUD operations
|
|
- **column_dataops.go** - Column CRUD operations
|
|
|
|
## Code Separation Rules
|
|
|
|
### UI vs Business Logic
|
|
|
|
1. **UI Files** - Handle only presentation and user interaction
|
|
- Display data in tables, lists, and forms
|
|
- Capture user input
|
|
- Navigate between screens
|
|
- Show/hide dialogs
|
|
- Call dataops methods for actual data changes
|
|
|
|
2. **Dataops Files** - Handle only business logic and data manipulation
|
|
- Create, read, update, delete operations
|
|
- Data validation
|
|
- Data structure manipulation
|
|
- Return created/updated objects or success/failure status
|
|
- No UI code or tview references
|
|
|
|
### Implementation Pattern
|
|
|
|
#### Creating New Items
|
|
|
|
**Bad (Direct Data Manipulation in UI):**
|
|
```go
|
|
form.AddButton("Save", func() {
|
|
schema := &models.Schema{Name: name, Description: desc, ...}
|
|
se.db.Schemas = append(se.db.Schemas, schema)
|
|
})
|
|
```
|
|
|
|
**Good (Using Dataops Methods):**
|
|
```go
|
|
form.AddButton("Save", func() {
|
|
se.CreateSchema(name, description)
|
|
})
|
|
```
|
|
|
|
#### Editing Existing Items
|
|
|
|
**Bad (Modifying Data in onChange Callbacks):**
|
|
```go
|
|
form.AddInputField("Name", column.Name, 40, nil, func(value string) {
|
|
column.Name = value // Changes immediately as user types!
|
|
})
|
|
form.AddButton("Save", func() {
|
|
// Data already changed, just refresh screen
|
|
})
|
|
```
|
|
|
|
**Good (Local Variables + Dataops on Save):**
|
|
```go
|
|
// Store original values
|
|
originalName := column.Name
|
|
newName := column.Name
|
|
|
|
form.AddInputField("Name", column.Name, 40, nil, func(value string) {
|
|
newName = value // Store in local variable
|
|
})
|
|
|
|
form.AddButton("Save", func() {
|
|
// Apply changes only when Save is clicked
|
|
se.UpdateColumn(schemaIndex, tableIndex, originalName, newName, ...)
|
|
// Then refresh screen
|
|
})
|
|
|
|
form.AddButton("Back", func() {
|
|
// Discard changes - don't apply local variables
|
|
// Just refresh screen
|
|
})
|
|
```
|
|
|
|
### Why This Matters
|
|
|
|
**Edit Forms Must Use Local Variables:**
|
|
1. **Deferred Changes** - Changes only apply when Save is clicked
|
|
2. **Cancellable** - Back button discards changes without saving
|
|
3. **Handles Renames** - Original name preserved to update map keys correctly
|
|
4. **User Expectations** - Save means "commit changes", Back means "cancel"
|
|
|
|
This separation ensures:
|
|
- Cleaner, more maintainable code
|
|
- Reusable business logic
|
|
- Easier testing
|
|
- Clear separation of concerns
|
|
- Proper change management (save vs cancel)
|