mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
feat: basic implementation of branch statistics
This commit is contained in:
@ -26,6 +26,7 @@ type StatsData struct {
|
||||
Machines []*SummariesEntry `json:"machines"`
|
||||
Projects []*SummariesEntry `json:"projects"`
|
||||
OperatingSystems []*SummariesEntry `json:"operating_systems"`
|
||||
Branches []*SummariesEntry `json:"branches"`
|
||||
}
|
||||
|
||||
func NewStatsFrom(summary *models.Summary, filters *models.Filters) *StatsViewModel {
|
||||
@ -71,11 +72,21 @@ func NewStatsFrom(summary *models.Summary, filters *models.Filters) *StatsViewMo
|
||||
oss[i] = convertEntry(e, summary.TotalTimeBy(models.SummaryOS))
|
||||
}
|
||||
|
||||
branches := make([]*SummariesEntry, len(summary.Branches))
|
||||
for i, e := range summary.Branches {
|
||||
branches[i] = convertEntry(e, summary.TotalTimeBy(models.SummaryBranch))
|
||||
}
|
||||
|
||||
data.Editors = editors
|
||||
data.Languages = languages
|
||||
data.Machines = machines
|
||||
data.Projects = projects
|
||||
data.OperatingSystems = oss
|
||||
data.Branches = branches
|
||||
|
||||
if summary.Branches == nil {
|
||||
data.Branches = nil
|
||||
}
|
||||
|
||||
return &StatsViewModel{
|
||||
Data: data,
|
||||
|
@ -26,6 +26,7 @@ type SummariesData struct {
|
||||
Machines []*SummariesEntry `json:"machines"`
|
||||
OperatingSystems []*SummariesEntry `json:"operating_systems"`
|
||||
Projects []*SummariesEntry `json:"projects"`
|
||||
Branches []*SummariesEntry `json:"branches"`
|
||||
GrandTotal *SummariesGrandTotal `json:"grand_total"`
|
||||
Range *SummariesRange `json:"range"`
|
||||
}
|
||||
@ -92,6 +93,7 @@ func newDataFrom(s *models.Summary) *SummariesData {
|
||||
Machines: make([]*SummariesEntry, len(s.Machines)),
|
||||
OperatingSystems: make([]*SummariesEntry, len(s.OperatingSystems)),
|
||||
Projects: make([]*SummariesEntry, len(s.Projects)),
|
||||
Branches: make([]*SummariesEntry, len(s.Branches)),
|
||||
GrandTotal: &SummariesGrandTotal{
|
||||
Digital: fmt.Sprintf("%d:%d", totalHrs, totalMins),
|
||||
Hours: totalHrs,
|
||||
@ -109,7 +111,7 @@ func newDataFrom(s *models.Summary) *SummariesData {
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(5)
|
||||
wg.Add(6)
|
||||
|
||||
go func(data *SummariesData) {
|
||||
defer wg.Done()
|
||||
@ -146,6 +148,17 @@ func newDataFrom(s *models.Summary) *SummariesData {
|
||||
}
|
||||
}(data)
|
||||
|
||||
go func(data *SummariesData) {
|
||||
defer wg.Done()
|
||||
for i, e := range s.Branches {
|
||||
data.Branches[i] = convertEntry(e, s.TotalTimeBy(models.SummaryBranch))
|
||||
}
|
||||
}(data)
|
||||
|
||||
if s.Branches == nil {
|
||||
data.Branches = nil
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
return data
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ type Duration struct {
|
||||
Editor string `json:"editor"`
|
||||
OperatingSystem string `json:"operating_system"`
|
||||
Machine string `json:"machine"`
|
||||
Branch string `json:"branch"`
|
||||
NumHeartbeats int `json:"-" hash:"ignore"`
|
||||
GroupHash string `json:"-" hash:"ignore"`
|
||||
}
|
||||
@ -30,6 +31,7 @@ func NewDurationFromHeartbeat(h *Heartbeat) *Duration {
|
||||
Editor: h.Editor,
|
||||
OperatingSystem: h.OperatingSystem,
|
||||
Machine: h.Machine,
|
||||
Branch: h.Branch,
|
||||
NumHeartbeats: 1,
|
||||
}
|
||||
return d.Hashed()
|
||||
@ -56,6 +58,8 @@ func (d *Duration) GetKey(t uint8) (key string) {
|
||||
key = d.OperatingSystem
|
||||
case SummaryMachine:
|
||||
key = d.Machine
|
||||
case SummaryBranch:
|
||||
key = d.Branch
|
||||
}
|
||||
|
||||
if key == "" {
|
||||
|
@ -13,6 +13,7 @@ type Filters struct {
|
||||
Editor OrFilter
|
||||
Machine OrFilter
|
||||
Label OrFilter
|
||||
Branch OrFilter
|
||||
}
|
||||
|
||||
type OrFilter []string
|
||||
@ -62,6 +63,8 @@ func (f *Filters) WithMultiple(entity uint8, keys []string) *Filters {
|
||||
f.Machine = append(f.Machine, keys...)
|
||||
case SummaryLabel:
|
||||
f.Label = append(f.Label, keys...)
|
||||
case SummaryBranch:
|
||||
f.Branch = append(f.Branch, keys...)
|
||||
}
|
||||
return f
|
||||
}
|
||||
@ -79,6 +82,8 @@ func (f *Filters) One() (bool, uint8, OrFilter) {
|
||||
return true, SummaryMachine, f.Machine
|
||||
} else if f.Label != nil && f.Label.Exists() {
|
||||
return true, SummaryLabel, f.Label
|
||||
} else if f.Branch != nil && f.Branch.Exists() {
|
||||
return true, SummaryBranch, f.Branch
|
||||
}
|
||||
return false, 0, OrFilter{}
|
||||
}
|
||||
@ -153,6 +158,14 @@ func (f *Filters) WithAliases(resolve AliasReverseResolver) *Filters {
|
||||
}
|
||||
f.Machine = updated
|
||||
}
|
||||
if f.Branch != nil {
|
||||
updated := OrFilter(make([]string, 0, len(f.Branch)))
|
||||
for _, e := range f.Branch {
|
||||
updated = append(updated, e)
|
||||
updated = append(updated, resolve(SummaryBranch, e)...)
|
||||
}
|
||||
f.Branch = updated
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,8 @@ func (h *Heartbeat) GetKey(t uint8) (key string) {
|
||||
key = h.OperatingSystem
|
||||
case SummaryMachine:
|
||||
key = h.Machine
|
||||
case SummaryBranch:
|
||||
key = h.Branch
|
||||
}
|
||||
|
||||
if key == "" {
|
||||
|
@ -14,6 +14,7 @@ const (
|
||||
SummaryOS uint8 = 3
|
||||
SummaryMachine uint8 = 4
|
||||
SummaryLabel uint8 = 5
|
||||
SummaryBranch uint8 = 6
|
||||
)
|
||||
|
||||
const UnknownSummaryKey = "unknown"
|
||||
@ -30,7 +31,8 @@ type Summary struct {
|
||||
Editors SummaryItems `json:"editors" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
|
||||
OperatingSystems SummaryItems `json:"operating_systems" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
|
||||
Machines SummaryItems `json:"machines" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE"`
|
||||
Labels SummaryItems `json:"labels" gorm:"-"` // labels are not persisted, but calculated at runtime, i.e. when summary is retrieved
|
||||
Labels SummaryItems `json:"labels" gorm:"-"` // labels are not persisted, but calculated at runtime, i.e. when summary is retrieved
|
||||
Branches SummaryItems `json:"branches" gorm:"-"` // branches are not persisted, but calculated at runtime in case a project filter is applied
|
||||
NumHeartbeats int `json:"-" gorm:"default:0"`
|
||||
}
|
||||
|
||||
@ -58,10 +60,14 @@ type SummaryParams struct {
|
||||
}
|
||||
|
||||
func SummaryTypes() []uint8 {
|
||||
return []uint8{SummaryProject, SummaryLanguage, SummaryEditor, SummaryOS, SummaryMachine, SummaryLabel}
|
||||
return []uint8{SummaryProject, SummaryLanguage, SummaryEditor, SummaryOS, SummaryMachine, SummaryLabel, SummaryBranch}
|
||||
}
|
||||
|
||||
func NativeSummaryTypes() []uint8 {
|
||||
return []uint8{SummaryProject, SummaryLanguage, SummaryEditor, SummaryOS, SummaryMachine, SummaryBranch}
|
||||
}
|
||||
|
||||
func PersistedSummaryTypes() []uint8 {
|
||||
return []uint8{SummaryProject, SummaryLanguage, SummaryEditor, SummaryOS, SummaryMachine}
|
||||
}
|
||||
|
||||
@ -72,6 +78,7 @@ func (s *Summary) Sorted() *Summary {
|
||||
sort.Sort(sort.Reverse(s.Languages))
|
||||
sort.Sort(sort.Reverse(s.Editors))
|
||||
sort.Sort(sort.Reverse(s.Labels))
|
||||
sort.Sort(sort.Reverse(s.Branches))
|
||||
return s
|
||||
}
|
||||
|
||||
@ -87,6 +94,7 @@ func (s *Summary) MappedItems() map[uint8]*SummaryItems {
|
||||
SummaryOS: &s.OperatingSystems,
|
||||
SummaryMachine: &s.Machines,
|
||||
SummaryLabel: &s.Labels,
|
||||
SummaryBranch: &s.Branches,
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,6 +241,10 @@ func (s *Summary) MaxByToString(entityType uint8) string {
|
||||
|
||||
func (s *Summary) WithResolvedAliases(resolve AliasResolver) *Summary {
|
||||
processAliases := func(origin []*SummaryItem) []*SummaryItem {
|
||||
if origin == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
target := make([]*SummaryItem, 0)
|
||||
|
||||
findItem := func(key string) *SummaryItem {
|
||||
@ -278,6 +290,7 @@ func (s *Summary) WithResolvedAliases(resolve AliasResolver) *Summary {
|
||||
s.OperatingSystems = processAliases(s.OperatingSystems)
|
||||
s.Machines = processAliases(s.Machines)
|
||||
s.Labels = processAliases(s.Labels)
|
||||
s.Branches = processAliases(s.Branches)
|
||||
|
||||
return s
|
||||
}
|
||||
|
Reference in New Issue
Block a user