Files
pad/internal/models/terminal.go
T
xarmian e21da3c6a4 fix: schema-driven terminal statuses replace hardcoded lists (BUG-17) (#65)
Add `terminal_options` to collection field schemas so each collection
declares which statuses are terminal/finalized. Replaces 10+ inconsistent
hardcoded status lists across backend, CLI, and frontend.

- Add TerminalOptions to FieldDef and centralized helpers in models/terminal.go
- Populate terminal_options on all default and template collections
- Replace hardcoded isDoneStatus/isTerminalItemStatus with schema-aware lookups
- Fix phase progress to count all terminal statuses (not just "done")
- Add terminal status toggle UI in collection field editor (Settings → Fields)
- Redesign collection field editor for cleaner layout and alignment
- Move Platform settings tab before Danger Zone tab
2026-04-04 18:56:30 -04:00

76 lines
2.5 KiB
Go

package models
import "strings"
// DefaultTerminalStatuses is the fallback list used when a collection schema
// does not declare terminal_options on its status field. This is the union of
// all historically hardcoded terminal status values across the codebase.
var DefaultTerminalStatuses = []string{
"done", "completed", "resolved", "cancelled", "rejected",
"wontfix", "fixed", "implemented", "archived", "disabled", "deprecated",
}
// TerminalStatusesFromSchema extracts terminal status options from a
// CollectionSchema. If the status field has TerminalOptions set, returns
// those. Otherwise returns DefaultTerminalStatuses.
func TerminalStatusesFromSchema(schema CollectionSchema) []string {
for _, f := range schema.Fields {
if f.Key == "status" && (f.Type == "select" || f.Type == "multi_select") {
if len(f.TerminalOptions) > 0 {
return f.TerminalOptions
}
break
}
}
return DefaultTerminalStatuses
}
// IsTerminalStatus checks whether a status string is terminal given a schema.
func IsTerminalStatus(status string, schema CollectionSchema) bool {
lower := strings.ToLower(status)
for _, ts := range TerminalStatusesFromSchema(schema) {
if strings.ToLower(ts) == lower {
return true
}
}
return false
}
// IsTerminalStatusDefault checks using the default fallback list (for cases
// where no collection schema is available).
func IsTerminalStatusDefault(status string) bool {
lower := strings.ToLower(status)
for _, ts := range DefaultTerminalStatuses {
if ts == lower {
return true
}
}
return false
}
// TerminalStatusPlaceholders returns a comma-separated placeholder string
// and the corresponding args slice for use in SQL IN clauses.
// Example: TerminalStatusPlaceholders(schema) might return ("?,?,?", ["done","cancelled","rejected"])
func TerminalStatusPlaceholders(schema CollectionSchema) (string, []any) {
statuses := TerminalStatusesFromSchema(schema)
placeholders := make([]string, len(statuses))
args := make([]any, len(statuses))
for i, s := range statuses {
placeholders[i] = "?"
args[i] = strings.ToLower(s)
}
return strings.Join(placeholders, ","), args
}
// DefaultTerminalStatusPlaceholders returns placeholders and args for the
// default terminal statuses list.
func DefaultTerminalStatusPlaceholders() (string, []any) {
placeholders := make([]string, len(DefaultTerminalStatuses))
args := make([]any, len(DefaultTerminalStatuses))
for i, s := range DefaultTerminalStatuses {
placeholders[i] = "?"
args[i] = s
}
return strings.Join(placeholders, ","), args
}