Add sorting, user assignment, and UI improvements

Features:
- Add work item sorting by ID, Type, State (keys 1, 2, 3)
- Add user assignment modal with team member filtering (key a)
- Add parent work item title display in details panel
- Preserve sort order and selection on panel reload

UI improvements:
- Remove zebra striping from work items list
- Remove priority column from list and details
- Align metadata fields in details panel
- Add markdown rendering for descriptions (using glamour)
- Add state colors: To Do (orange), In Progress (purple), Done (green), Testing (yellow)

🤖 Generated with [Claude Code](https://claude.ai/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Samuel Enocsson
2025-12-04 22:31:28 +01:00
parent 2555afce19
commit 7c488b2d83
7 changed files with 682 additions and 12 deletions
+51
View File
@@ -0,0 +1,51 @@
package api
import (
"fmt"
"github.com/samuelenocsson/devops-tui/internal/models"
)
// teamMembersResponse represents the response from team members API
type teamMembersResponse struct {
Value []teamMemberItem `json:"value"`
Count int `json:"count"`
}
type teamMemberItem struct {
Identity identityRef `json:"identity"`
}
type identityRef struct {
DisplayName string `json:"displayName"`
UniqueName string `json:"uniqueName"`
ID string `json:"id"`
}
// GetTeamMembers fetches all members of the configured team
func (c *Client) GetTeamMembers() ([]models.TeamMember, error) {
// Azure DevOps API: GET https://dev.azure.com/{org}/_apis/projects/{project}/teams/{team}/members
url := fmt.Sprintf("https://dev.azure.com/%s/_apis/projects/%s/teams/%s/members?api-version=%s",
c.organization, c.project, c.team, apiVersion)
resp, err := c.doRequest("GET", url, nil)
if err != nil {
return nil, err
}
var apiResp teamMembersResponse
if err := decode(resp, &apiResp); err != nil {
return nil, err
}
members := make([]models.TeamMember, 0, len(apiResp.Value))
for _, item := range apiResp.Value {
members = append(members, models.TeamMember{
ID: item.Identity.ID,
DisplayName: item.Identity.DisplayName,
UniqueName: item.Identity.UniqueName,
})
}
return members, nil
}