mirror of
https://github.com/RWejlgaard/org.git
synced 2026-05-06 04:34:45 +00:00
adding setting for default state of new items
This commit is contained in:
parent
43573a6e79
commit
3c7b64417b
3 changed files with 129 additions and 23 deletions
|
|
@ -83,6 +83,7 @@ type StateConfig struct {
|
||||||
// StatesConfig holds TODO state configurations
|
// StatesConfig holds TODO state configurations
|
||||||
type StatesConfig struct {
|
type StatesConfig struct {
|
||||||
States []StateConfig `toml:"states"`
|
States []StateConfig `toml:"states"`
|
||||||
|
DefaultNewTaskState string `toml:"default_new_task_state"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UIConfig holds UI-related configurations
|
// UIConfig holds UI-related configurations
|
||||||
|
|
@ -151,6 +152,7 @@ func DefaultConfig() *Config {
|
||||||
{Name: "BLOCK", Color: "196"},
|
{Name: "BLOCK", Color: "196"},
|
||||||
{Name: "DONE", Color: "34"},
|
{Name: "DONE", Color: "34"},
|
||||||
},
|
},
|
||||||
|
DefaultNewTaskState: "TODO",
|
||||||
},
|
},
|
||||||
UI: UIConfig{
|
UI: UIConfig{
|
||||||
HelpTextWidth: 22,
|
HelpTextWidth: 22,
|
||||||
|
|
@ -355,6 +357,9 @@ func (c *Config) fillDefaults() {
|
||||||
if len(c.States.States) == 0 {
|
if len(c.States.States) == 0 {
|
||||||
c.States.States = defaults.States.States
|
c.States.States = defaults.States.States
|
||||||
}
|
}
|
||||||
|
if c.States.DefaultNewTaskState == "" {
|
||||||
|
c.States.DefaultNewTaskState = defaults.States.DefaultNewTaskState
|
||||||
|
}
|
||||||
|
|
||||||
// Fill UI if zero values
|
// Fill UI if zero values
|
||||||
if c.UI.HelpTextWidth == 0 {
|
if c.UI.HelpTextWidth == 0 {
|
||||||
|
|
@ -542,3 +547,26 @@ func (c *Config) GetAllKeybindings() map[string][]string {
|
||||||
"tag_item": c.Keybindings.TagItem,
|
"tag_item": c.Keybindings.TagItem,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDefaultNewTaskState returns the default state for new tasks
|
||||||
|
// Returns empty string if configured as "none" or if the configured state doesn't exist
|
||||||
|
func (c *Config) GetDefaultNewTaskState() string {
|
||||||
|
// Empty string means no state
|
||||||
|
if c.States.DefaultNewTaskState == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate that the configured state exists
|
||||||
|
for _, state := range c.States.States {
|
||||||
|
if state.Name == c.States.DefaultNewTaskState {
|
||||||
|
return c.States.DefaultNewTaskState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If configured state doesn't exist, fall back to first state or empty
|
||||||
|
if len(c.States.States) > 0 {
|
||||||
|
return c.States.States[0].Name
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -345,10 +345,13 @@ func (m uiModel) updateCapture(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
case tea.KeyEnter:
|
case tea.KeyEnter:
|
||||||
title := strings.TrimSpace(m.textinput.Value())
|
title := strings.TrimSpace(m.textinput.Value())
|
||||||
if title != "" {
|
if title != "" {
|
||||||
|
// Get default state from config
|
||||||
|
defaultState := model.TodoState(m.config.GetDefaultNewTaskState())
|
||||||
|
|
||||||
// Create new TODO at top level
|
// Create new TODO at top level
|
||||||
newItem := &model.Item{
|
newItem := &model.Item{
|
||||||
Level: 1,
|
Level: 1,
|
||||||
State: model.StateTODO,
|
State: defaultState,
|
||||||
Title: title,
|
Title: title,
|
||||||
Notes: []string{},
|
Notes: []string{},
|
||||||
Children: []*model.Item{},
|
Children: []*model.Item{},
|
||||||
|
|
@ -387,10 +390,13 @@ func (m uiModel) updateAddSubTask(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
case tea.KeyEnter:
|
case tea.KeyEnter:
|
||||||
title := strings.TrimSpace(m.textinput.Value())
|
title := strings.TrimSpace(m.textinput.Value())
|
||||||
if title != "" && m.editingItem != nil {
|
if title != "" && m.editingItem != nil {
|
||||||
|
// Get default state from config
|
||||||
|
defaultState := model.TodoState(m.config.GetDefaultNewTaskState())
|
||||||
|
|
||||||
// Create new sub-task
|
// Create new sub-task
|
||||||
newItem := &model.Item{
|
newItem := &model.Item{
|
||||||
Level: m.editingItem.Level + 1,
|
Level: m.editingItem.Level + 1,
|
||||||
State: model.StateTODO,
|
State: defaultState,
|
||||||
Title: title,
|
Title: title,
|
||||||
Notes: []string{},
|
Notes: []string{},
|
||||||
Children: []*model.Item{},
|
Children: []*model.Item{},
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ func (m *uiModel) getSettingsItemCount() int {
|
||||||
case settingsSectionTags:
|
case settingsSectionTags:
|
||||||
return len(m.config.Tags.Tags) + 1 // +1 for "Add new tag" option
|
return len(m.config.Tags.Tags) + 1 // +1 for "Add new tag" option
|
||||||
case settingsSectionStates:
|
case settingsSectionStates:
|
||||||
return len(m.config.States.States) + 1 // +1 for "Add new state" option
|
return len(m.config.States.States) + 2 // +1 for "Default new task state" setting, +1 for "Add new state" option
|
||||||
case settingsSectionKeybindings:
|
case settingsSectionKeybindings:
|
||||||
return len(m.config.GetAllKeybindings())
|
return len(m.config.GetAllKeybindings())
|
||||||
default:
|
default:
|
||||||
|
|
@ -161,10 +161,20 @@ func (m *uiModel) startSettingsEdit() {
|
||||||
m.textinput.Focus()
|
m.textinput.Focus()
|
||||||
|
|
||||||
case settingsSectionStates:
|
case settingsSectionStates:
|
||||||
if m.settingsCursor >= len(m.config.States.States) {
|
// First item is the default new task state setting
|
||||||
|
if m.settingsCursor == 0 {
|
||||||
|
m.textinput.SetValue(m.config.States.DefaultNewTaskState)
|
||||||
|
m.textinput.Placeholder = "Enter state name or leave empty for none"
|
||||||
|
m.textinput.Focus()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
state := m.config.States.States[m.settingsCursor]
|
|
||||||
|
// Adjust for the default state setting offset
|
||||||
|
stateIndex := m.settingsCursor - 1
|
||||||
|
if stateIndex >= len(m.config.States.States) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state := m.config.States.States[stateIndex]
|
||||||
m.textinput.SetValue(state.Name + "," + state.Color)
|
m.textinput.SetValue(state.Name + "," + state.Color)
|
||||||
m.textinput.Placeholder = "name,color (e.g., TODO,202)"
|
m.textinput.Placeholder = "name,color (e.g., TODO,202)"
|
||||||
m.textinput.Focus()
|
m.textinput.Focus()
|
||||||
|
|
@ -223,13 +233,33 @@ func (m *uiModel) saveSettingsEdit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
case settingsSectionStates:
|
case settingsSectionStates:
|
||||||
if m.settingsCursor >= len(m.config.States.States) {
|
// First item is the default new task state setting
|
||||||
|
if m.settingsCursor == 0 {
|
||||||
|
newDefault := strings.TrimSpace(m.textinput.Value())
|
||||||
|
// Convert to uppercase
|
||||||
|
newDefault = strings.ToUpper(newDefault)
|
||||||
|
m.config.States.DefaultNewTaskState = newDefault
|
||||||
|
if newDefault == "" {
|
||||||
|
m.setStatus("Default new task state set to 'none' (saved)")
|
||||||
|
} else {
|
||||||
|
m.setStatus(fmt.Sprintf("Default new task state set to '%s' (saved)", newDefault))
|
||||||
|
}
|
||||||
|
// Auto-save
|
||||||
|
if err := m.config.Save(); err != nil {
|
||||||
|
m.setStatus(fmt.Sprintf("Error auto-saving config: %v", err))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust for the default state setting offset
|
||||||
|
stateIndex := m.settingsCursor - 1
|
||||||
|
if stateIndex >= len(m.config.States.States) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Parse "name,color" format
|
// Parse "name,color" format
|
||||||
parts := strings.Split(m.textinput.Value(), ",")
|
parts := strings.Split(m.textinput.Value(), ",")
|
||||||
if len(parts) >= 2 {
|
if len(parts) >= 2 {
|
||||||
state := &m.config.States.States[m.settingsCursor]
|
state := &m.config.States.States[stateIndex]
|
||||||
state.Name = strings.TrimSpace(parts[0])
|
state.Name = strings.TrimSpace(parts[0])
|
||||||
state.Color = strings.TrimSpace(parts[1])
|
state.Color = strings.TrimSpace(parts[1])
|
||||||
m.setStatus(fmt.Sprintf("Updated state '%s' (saved)", state.Name))
|
m.setStatus(fmt.Sprintf("Updated state '%s' (saved)", state.Name))
|
||||||
|
|
@ -316,18 +346,27 @@ func (m *uiModel) deleteSettingsItem() {
|
||||||
}
|
}
|
||||||
|
|
||||||
case settingsSectionStates:
|
case settingsSectionStates:
|
||||||
if m.settingsCursor >= len(m.config.States.States) {
|
// Cannot delete the default new task state setting (first item)
|
||||||
|
if m.settingsCursor == 0 {
|
||||||
|
m.setStatus("Cannot delete default state setting (use Enter to edit)")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
state := m.config.States.States[m.settingsCursor]
|
|
||||||
|
// Adjust for the default state setting offset
|
||||||
|
stateIndex := m.settingsCursor - 1
|
||||||
|
if stateIndex >= len(m.config.States.States) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state := m.config.States.States[stateIndex]
|
||||||
m.config.RemoveState(state.Name)
|
m.config.RemoveState(state.Name)
|
||||||
m.setStatus(fmt.Sprintf("Deleted state '%s' (saved)", state.Name))
|
m.setStatus(fmt.Sprintf("Deleted state '%s' (saved)", state.Name))
|
||||||
|
|
||||||
// Adjust cursor if needed
|
// Adjust cursor if needed
|
||||||
if m.settingsCursor >= len(m.config.States.States) {
|
// +1 for the default state setting
|
||||||
m.settingsCursor = len(m.config.States.States) - 1
|
if m.settingsCursor >= len(m.config.States.States)+1 {
|
||||||
if m.settingsCursor < 0 {
|
m.settingsCursor = len(m.config.States.States)
|
||||||
m.settingsCursor = 0
|
if m.settingsCursor < 1 {
|
||||||
|
m.settingsCursor = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -465,11 +504,30 @@ func (m *uiModel) viewSettingsTags() string {
|
||||||
func (m *uiModel) viewSettingsStates() string {
|
func (m *uiModel) viewSettingsStates() string {
|
||||||
var content strings.Builder
|
var content strings.Builder
|
||||||
|
|
||||||
|
// First show the default new task state setting
|
||||||
|
line := ""
|
||||||
|
if m.settingsCursor == 0 && !m.textinput.Focused() {
|
||||||
|
line += "▶ "
|
||||||
|
} else {
|
||||||
|
line += " "
|
||||||
|
}
|
||||||
|
line += "Default new task state: "
|
||||||
|
if m.config.States.DefaultNewTaskState == "" {
|
||||||
|
line += m.styles.statusStyle.Render("(none)")
|
||||||
|
} else {
|
||||||
|
// Try to get the color for this state
|
||||||
|
color := m.config.GetStateColor(m.config.States.DefaultNewTaskState)
|
||||||
|
stateStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(color))
|
||||||
|
line += stateStyle.Render(m.config.States.DefaultNewTaskState)
|
||||||
|
}
|
||||||
|
content.WriteString(line + "\n\n")
|
||||||
|
|
||||||
|
// Then show all configured states
|
||||||
for i, state := range m.config.States.States {
|
for i, state := range m.config.States.States {
|
||||||
line := ""
|
line := ""
|
||||||
|
|
||||||
// Cursor
|
// Cursor (offset by 1 because of the default state setting)
|
||||||
if i == m.settingsCursor && !m.textinput.Focused() {
|
if i+1 == m.settingsCursor && !m.textinput.Focused() {
|
||||||
line += "▶ "
|
line += "▶ "
|
||||||
} else {
|
} else {
|
||||||
line += " "
|
line += " "
|
||||||
|
|
@ -484,7 +542,7 @@ func (m *uiModel) viewSettingsStates() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new state option
|
// Add new state option
|
||||||
if m.settingsCursor == len(m.config.States.States) && !m.textinput.Focused() {
|
if m.settingsCursor == len(m.config.States.States)+1 && !m.textinput.Focused() {
|
||||||
content.WriteString("▶ ")
|
content.WriteString("▶ ")
|
||||||
} else {
|
} else {
|
||||||
content.WriteString(" ")
|
content.WriteString(" ")
|
||||||
|
|
@ -666,10 +724,17 @@ func (m *uiModel) moveSettingsItemUp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
case settingsSectionStates:
|
case settingsSectionStates:
|
||||||
if m.settingsCursor > 0 && m.settingsCursor < len(m.config.States.States) {
|
// Cannot reorder the default state setting (first item)
|
||||||
|
if m.settingsCursor <= 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust for the default state setting offset
|
||||||
|
stateIndex := m.settingsCursor - 1
|
||||||
|
if stateIndex > 0 && stateIndex < len(m.config.States.States) {
|
||||||
// Swap with previous item
|
// Swap with previous item
|
||||||
m.config.States.States[m.settingsCursor], m.config.States.States[m.settingsCursor-1] =
|
m.config.States.States[stateIndex], m.config.States.States[stateIndex-1] =
|
||||||
m.config.States.States[m.settingsCursor-1], m.config.States.States[m.settingsCursor]
|
m.config.States.States[stateIndex-1], m.config.States.States[stateIndex]
|
||||||
m.settingsCursor--
|
m.settingsCursor--
|
||||||
// Auto-save
|
// Auto-save
|
||||||
if err := m.config.Save(); err != nil {
|
if err := m.config.Save(); err != nil {
|
||||||
|
|
@ -703,10 +768,17 @@ func (m *uiModel) moveSettingsItemDown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
case settingsSectionStates:
|
case settingsSectionStates:
|
||||||
if m.settingsCursor >= 0 && m.settingsCursor < len(m.config.States.States)-1 {
|
// Cannot reorder the default state setting (first item)
|
||||||
|
if m.settingsCursor == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust for the default state setting offset
|
||||||
|
stateIndex := m.settingsCursor - 1
|
||||||
|
if stateIndex >= 0 && stateIndex < len(m.config.States.States)-1 {
|
||||||
// Swap with next item
|
// Swap with next item
|
||||||
m.config.States.States[m.settingsCursor], m.config.States.States[m.settingsCursor+1] =
|
m.config.States.States[stateIndex], m.config.States.States[stateIndex+1] =
|
||||||
m.config.States.States[m.settingsCursor+1], m.config.States.States[m.settingsCursor]
|
m.config.States.States[stateIndex+1], m.config.States.States[stateIndex]
|
||||||
m.settingsCursor++
|
m.settingsCursor++
|
||||||
// Auto-save
|
// Auto-save
|
||||||
if err := m.config.Save(); err != nil {
|
if err := m.config.Save(); err != nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue