verstak/cmd/verstak-gui/bindings_suggest.go

130 lines
3.0 KiB
Go

package main
import (
"fmt"
"sort"
"strings"
"verstak/internal/core/activity"
)
// GetSuggestions analyzes today's activity and returns worklog suggestions.
func (a *App) GetSuggestions() ([]activity.Suggestion, error) {
events, err := a.activity.ListTodayEvents()
if err != nil {
return nil, err
}
if len(events) == 0 {
return nil, nil
}
type acc struct {
title string
kind string
events []activity.Event
}
grouped := make(map[string]*acc)
for _, e := range events {
grp, ok := grouped[e.NodeID]
if !ok {
n, err := a.nodes.GetActive(e.NodeID)
title := ""
kind := ""
if err == nil && n != nil {
title = n.Title
kind = n.Type
}
grp = &acc{title: title, kind: kind}
grouped[e.NodeID] = grp
}
grp.events = append(grp.events, e)
}
var suggestions []activity.Suggestion
for nodeID, grp := range grouped {
if grp.title == "" {
continue
}
hasEntries, err := a.worklog.HasTodayEntries(nodeID)
if err != nil || hasEntries {
continue
}
noteCount := 0
fileCount := 0
actionCount := 0
otherCount := 0
for _, e := range grp.events {
switch e.EventType {
case activity.TypeNoteCreated, activity.TypeNoteUpdated, activity.TypeNoteDeleted:
noteCount++
case activity.TypeFileAdded, activity.TypeFileDeleted, activity.TypeFileRenamed,
activity.TypeFileCopied, activity.TypeFileMoved,
activity.TypeFolderAdded, activity.TypeFolderDeleted, activity.TypeFolderRenamed:
fileCount++
case activity.TypeActionCreated, activity.TypeActionDone:
actionCount++
default:
otherCount++
}
}
summary := buildSuggestionSummary(noteCount, fileCount, actionCount, otherCount)
if summary == "" {
continue
}
suggestions = append(suggestions, activity.Suggestion{
NodeID: nodeID,
NodeTitle: grp.title,
Summary: summary,
SuggestedMin: suggestMinutes(noteCount + fileCount + actionCount + otherCount),
EventCount: len(grp.events),
NodeKind: grp.kind,
})
}
sort.Slice(suggestions, func(i, j int) bool {
return suggestions[i].EventCount > suggestions[j].EventCount
})
return suggestions, nil
}
// AcceptSuggestion creates a worklog entry from a suggestion.
func (a *App) AcceptSuggestion(s activity.Suggestion) (*WorklogDTO, error) {
return a.CreateWorklog(s.NodeID, s.Summary, s.SuggestedMin)
}
func buildSuggestionSummary(noteCount, fileCount, actionCount, otherCount int) string {
var parts []string
if noteCount > 0 {
parts = append(parts, fmt.Sprintf("заметки (%d)", noteCount))
}
if fileCount > 0 {
parts = append(parts, fmt.Sprintf("файлы (%d)", fileCount))
}
if actionCount > 0 {
parts = append(parts, fmt.Sprintf("действия (%d)", actionCount))
}
if otherCount > 0 {
parts = append(parts, fmt.Sprintf("события (%d)", otherCount))
}
return strings.Join(parts, ", ")
}
func suggestMinutes(totalEvents int) int {
switch {
case totalEvents >= 15:
return 120
case totalEvents >= 10:
return 90
case totalEvents >= 6:
return 60
case totalEvents >= 3:
return 30
default:
return 15
}
}