mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 21:47:20 +00:00
What’s in this PR 1) Smarter default sorting for issues (used by the TUI) New ghapi.SortIssuesForDisplay helper that orders issues by: Priority label (P0 → P1 → P2 → none) Presence of customer-* / prospect-* labels Type labels (story → bug → ~sub-task → others) Issue number (descending) This is applied before filtering so views start in a meaningful order. [GitHub](https://github.com/fleetdm/fleet/pull/32694/files) Implementation lives in tools/github-manage/pkg/ghapi/sort.go. Comprehensive tests cover all combinations, tie-breakers, and stability. GitHub +1 2) Estimates: show the sum for the current selection The header now displays Σest sel=<sum> for the currently selected issues, both in filtered and unfiltered views, making quick capacity checks easier. [GitHub](https://github.com/fleetdm/fleet/pull/32694/files) 3) Better progress UI for workflows Task list is now windowed (last ~10 items) with auto-scroll to the currently running or most recently finished task, plus “earlier/more tasks” ellipses and a progress counter at the bottom. This keeps the view focused during long runs. [GitHub](https://github.com/fleetdm/fleet/pull/32694/files) 4) Project estimates fetch now includes total count Switched from GetEstimatedTicketsForProject to GetEstimatedTicketsForProjectWithTotal, so we can show totalAvailable alongside rawFetched/limit. [GitHub](https://github.com/fleetdm/fleet/pull/32694/files) --------- Co-authored-by: Jordan Montgomery <elijah.jordan.montgomery@gmail.com>
91 lines
2.7 KiB
Go
91 lines
2.7 KiB
Go
// Package ghapi provides views for managed searches and display templates for GitHub issues.
|
|
|
|
package ghapi
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
type ViewType string
|
|
|
|
const (
|
|
ISSUE_LIST ViewType = "issue_list"
|
|
ISSUE_DETAIL ViewType = "issue_detail"
|
|
PROJECT_DETAIL ViewType = "project_detail"
|
|
MDM_LABEL = "#g-mdm"
|
|
)
|
|
|
|
type View struct {
|
|
Type ViewType `json:"type"`
|
|
Title string `json:"title"`
|
|
Filters []string `json:"filters,omitempty"` // Search filters for issues
|
|
}
|
|
|
|
// NewView creates a new view with the specified type, title, and optional filters.
|
|
func NewView(viewType ViewType, title string, filters ...string) *View {
|
|
return &View{
|
|
Type: viewType,
|
|
Title: title,
|
|
Filters: filters,
|
|
}
|
|
}
|
|
|
|
// GetMDMTicketsEstimated returns estimated tickets from the MDM project.
|
|
func GetMDMTicketsEstimated() ([]ProjectItem, error) {
|
|
return GetEstimatedTicketsForProject(58, 500)
|
|
}
|
|
|
|
// GetEstimatedTicketsForProject gets estimated tickets from the drafting project filtered by the project's label.
|
|
func GetEstimatedTicketsForProject(projectID, limit int) ([]ProjectItem, error) {
|
|
items, _, err := GetEstimatedTicketsForProjectWithTotal(projectID, limit)
|
|
return items, err
|
|
}
|
|
|
|
// GetEstimatedTicketsForProjectWithTotal returns filtered estimated issues and the total
|
|
// number of items in the drafting project (unfiltered). This allows callers to warn when
|
|
// the drafting project's total exceeds the fetch limit (some estimated items might be
|
|
// beyond the first page).
|
|
func GetEstimatedTicketsForProjectWithTotal(projectID, limit int) ([]ProjectItem, int, error) {
|
|
// Get the label for this project
|
|
label, exists := ProjectLabels[projectID]
|
|
if !exists {
|
|
return nil, 0, fmt.Errorf("no label mapping found for project ID %d. Available projects: %v", projectID, getProjectIDsWithLabels())
|
|
}
|
|
|
|
// Grab issues from Drafting project
|
|
draftingProjectID := Aliases["draft"]
|
|
estimatedName, err := FindFieldValueByName(draftingProjectID, "Status", "estimated")
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
issues, total, err := GetProjectItemsWithTotal(draftingProjectID, limit)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
// filter down to issues that are estimated with the specified label
|
|
var estimatedIssues []ProjectItem
|
|
for _, issue := range issues {
|
|
if issue.Labels != nil {
|
|
for _, issueLabel := range issue.Labels {
|
|
if issueLabel == label {
|
|
if issue.Status == estimatedName {
|
|
estimatedIssues = append(estimatedIssues, issue)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return estimatedIssues, total, nil
|
|
}
|
|
|
|
// getProjectIDsWithLabels returns a slice of project IDs that have label mappings.
|
|
func getProjectIDsWithLabels() []int {
|
|
ids := make([]int, 0, len(ProjectLabels))
|
|
for id := range ProjectLabels {
|
|
ids = append(ids, id)
|
|
}
|
|
return ids
|
|
}
|