Add tm_server with SQLite, Svelte UI, and task-master TUI sync.
Introduces the web backend (auth, RBAC, project tokens, revisions), YouTrack-or-taskmaster backend choice in the TUI, and a first-pass embedded Svelte UI. The frontend is functional but needs a major rework. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+44
-10
@@ -19,6 +19,7 @@ import (
|
||||
"task/internal/ticket"
|
||||
"task/internal/ui/views"
|
||||
"task/internal/version"
|
||||
"task/internal/tmsync"
|
||||
"task/internal/youtrack"
|
||||
"task/internal/ytsync"
|
||||
)
|
||||
@@ -826,6 +827,14 @@ func (m Model) updateEditProject(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
m.projectEdit.PrevField()
|
||||
return m, textinput.Blink
|
||||
|
||||
case msg.Type == tea.KeyLeft:
|
||||
m.projectEdit.CycleBackend(-1)
|
||||
return m, nil
|
||||
|
||||
case msg.Type == tea.KeyRight:
|
||||
m.projectEdit.CycleBackend(1)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keys.Enter):
|
||||
if err := m.projectEdit.Validate(m.projectEditMeta); err != nil {
|
||||
m.setError(err)
|
||||
@@ -842,10 +851,10 @@ func (m Model) updateEditProject(msg tea.KeyMsg) (tea.Model, tea.Cmd) {
|
||||
return m, nil
|
||||
}
|
||||
m.mode = ModeProjects
|
||||
if meta.YouTrack != nil && meta.YouTrack.Configured() {
|
||||
m.setStatus(fmt.Sprintf("saved YouTrack settings for %s", id))
|
||||
if meta.SyncConfigured() {
|
||||
m.setStatus(fmt.Sprintf("saved %s sync for %s", meta.EffectiveBackend(), id))
|
||||
} else {
|
||||
m.setStatus(fmt.Sprintf("cleared YouTrack settings for %s", id))
|
||||
m.setStatus(fmt.Sprintf("cleared sync settings for %s", id))
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
@@ -866,12 +875,21 @@ func (m *Model) openProjectEdit(projectID string) error {
|
||||
|
||||
func (m *Model) openSyncMenu(projectID string) {
|
||||
m.syncProjectID = projectID
|
||||
label := "Sync"
|
||||
if meta, err := m.projects.LoadMeta(projectID); err == nil {
|
||||
switch meta.EffectiveBackend() {
|
||||
case project.BackendTaskMaster:
|
||||
label = "task-master"
|
||||
case project.BackendYouTrack:
|
||||
label = "YouTrack"
|
||||
}
|
||||
}
|
||||
m.syncMenu = views.NewSyncMenu(m.width, views.StatusMenuStyles{
|
||||
Box: m.styles.StatusMenuBox,
|
||||
Title: m.styles.StatusMenuTitle,
|
||||
Selected: m.styles.StatusMenuSelected,
|
||||
Normal: m.styles.StatusMenuNormal,
|
||||
})
|
||||
}, label)
|
||||
m.mode = ModeSync
|
||||
}
|
||||
|
||||
@@ -925,11 +943,27 @@ func (m Model) startSyncAction(projectID string, action views.SyncAction) (tea.M
|
||||
return m, func() tea.Msg {
|
||||
var pull, push ytsync.Result
|
||||
var err error
|
||||
switch action {
|
||||
case views.SyncActionPush:
|
||||
push, err = ytsync.PushProject(context.Background(), projects, store, timeStore, projectID)
|
||||
default:
|
||||
pull, err = ytsync.PullProject(context.Background(), projects, store, timeStore, projectID)
|
||||
meta, merr := projects.LoadMeta(projectID)
|
||||
if merr != nil {
|
||||
err = merr
|
||||
} else {
|
||||
switch meta.EffectiveBackend() {
|
||||
case project.BackendTaskMaster:
|
||||
syncer := &tmsync.Syncer{Store: store, TimeStore: timeStore}
|
||||
switch action {
|
||||
case views.SyncActionPush:
|
||||
push, err = syncer.Push(context.Background(), projectID, *meta.TaskMaster)
|
||||
default:
|
||||
pull, err = syncer.Pull(context.Background(), projectID, *meta.TaskMaster)
|
||||
}
|
||||
default:
|
||||
switch action {
|
||||
case views.SyncActionPush:
|
||||
push, err = ytsync.PushProject(context.Background(), projects, store, timeStore, projectID)
|
||||
default:
|
||||
pull, err = ytsync.PullProject(context.Background(), projects, store, timeStore, projectID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return syncFinishedMsg{projectID: projectID, action: action, pull: pull, push: push, err: err}
|
||||
}
|
||||
@@ -1451,7 +1485,7 @@ func (m *Model) openProjects() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
yt[p.ID] = meta.YouTrack != nil && meta.YouTrack.Configured()
|
||||
yt[p.ID] = meta.SyncConfigured()
|
||||
}
|
||||
m.projectList = views.NewProjectListWithYT(projects, m.cfg.ActiveProject, yt, m.width, bodyH)
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user