174 lines
4.1 KiB
Go
174 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"sort"
|
|
"time"
|
|
|
|
"verstak/internal/core/activity"
|
|
"verstak/internal/core/nodes"
|
|
syncsvc "verstak/internal/core/sync"
|
|
"verstak/internal/i18n"
|
|
)
|
|
|
|
func (a *App) ListSections() []SectionDTO {
|
|
return []SectionDTO{
|
|
{ID: "today", Label: i18n.TF("ru", "nav.today")},
|
|
{ID: "inbox", Label: i18n.TF("ru", "nav.inbox")},
|
|
{ID: "activity", Label: i18n.TF("ru", "nav.activity")},
|
|
{ID: "clients", Label: i18n.TF("ru", "nav.clients")},
|
|
{ID: "projects", Label: i18n.TF("ru", "nav.projects")},
|
|
{ID: "recipes", Label: i18n.TF("ru", "nav.recipes")},
|
|
{ID: "documents", Label: i18n.TF("ru", "nav.documents")},
|
|
{ID: "archive", Label: i18n.TF("ru", "nav.archive")},
|
|
}
|
|
}
|
|
|
|
func (a *App) ListTodayView() (*TodayDashboardDTO, error) {
|
|
aeByParent, err := a.activity.ListTodayEventsByParent()
|
|
if err != nil {
|
|
aeByParent = nil
|
|
}
|
|
todayNodes, _ := a.nodes.ListTodayNodes()
|
|
|
|
type rawEvent struct {
|
|
NodeID string
|
|
EventType string
|
|
TargetType string
|
|
TargetID string
|
|
TargetPath string
|
|
Title string
|
|
CreatedAt string
|
|
}
|
|
type caseInfo struct {
|
|
Node nodes.Node
|
|
Events []rawEvent
|
|
}
|
|
caseMap := make(map[string]*caseInfo)
|
|
|
|
ensureCase := func(caseID string) *caseInfo {
|
|
if ci, ok := caseMap[caseID]; ok {
|
|
return ci
|
|
}
|
|
ci := &caseInfo{Events: nil}
|
|
if n, err := a.nodes.GetActive(caseID); err == nil {
|
|
ci.Node = *n
|
|
}
|
|
caseMap[caseID] = ci
|
|
return ci
|
|
}
|
|
|
|
for pid, events := range aeByParent {
|
|
ci := ensureCase(pid)
|
|
for _, e := range events {
|
|
ci.Events = append(ci.Events, rawEvent{
|
|
NodeID: e.NodeID,
|
|
EventType: e.EventType,
|
|
TargetType: e.TargetType,
|
|
TargetID: e.TargetID,
|
|
TargetPath: e.TargetPath,
|
|
Title: e.Title,
|
|
CreatedAt: e.CreatedAt,
|
|
})
|
|
}
|
|
}
|
|
|
|
for _, n := range todayNodes {
|
|
_ = ensureCase(n.ID)
|
|
if ci := caseMap[n.ID]; ci.Node.ID == "" {
|
|
ci.Node = n
|
|
}
|
|
}
|
|
|
|
var groups []TodayGroupDTO
|
|
var flatEvents []EventDTO
|
|
summary := SummaryDTO{}
|
|
|
|
for _, ci := range caseMap {
|
|
if ci.Node.ID == "" {
|
|
continue
|
|
}
|
|
summary.ChangedCases++
|
|
|
|
dtoEvents := make([]EventDTO, 0, len(ci.Events))
|
|
for _, re := range ci.Events {
|
|
dtoEvents = append(dtoEvents, EventDTO{
|
|
ID: ci.Node.ID + "/" + re.NodeID + "/" + re.CreatedAt,
|
|
NodeID: re.NodeID,
|
|
EventType: re.EventType,
|
|
TargetType: re.TargetType,
|
|
TargetID: re.TargetID,
|
|
TargetPath: re.TargetPath,
|
|
Title: re.Title,
|
|
CreatedAt: re.CreatedAt,
|
|
})
|
|
switch re.EventType {
|
|
case activity.TypeNoteCreated, activity.TypeNoteUpdated:
|
|
summary.Notes++
|
|
case activity.TypeFileAdded, activity.TypeFileDeleted, activity.TypeFileRenamed, activity.TypeFileCopied, activity.TypeFileMoved:
|
|
summary.Files++
|
|
}
|
|
}
|
|
|
|
last := ci.Node.UpdatedAt.Format(time.RFC3339)
|
|
for _, e := range dtoEvents {
|
|
if e.CreatedAt > last {
|
|
last = e.CreatedAt
|
|
}
|
|
}
|
|
|
|
groups = append(groups, TodayGroupDTO{
|
|
NodeID: ci.Node.ID,
|
|
NodeTitle: ci.Node.Title,
|
|
NodeKind: ci.Node.Type,
|
|
Section: ci.Node.Section,
|
|
LastActivityAt: last,
|
|
Events: dtoEvents,
|
|
})
|
|
flatEvents = append(flatEvents, dtoEvents...)
|
|
}
|
|
|
|
sort.Slice(groups, func(i, j int) bool {
|
|
return groups[i].LastActivityAt > groups[j].LastActivityAt
|
|
})
|
|
sort.Slice(flatEvents, func(i, j int) bool {
|
|
return flatEvents[i].CreatedAt > flatEvents[j].CreatedAt
|
|
})
|
|
|
|
return &TodayDashboardDTO{
|
|
Date: time.Now().Format("2006-01-02"),
|
|
Summary: summary,
|
|
Groups: groups,
|
|
Events: flatEvents,
|
|
}, nil
|
|
}
|
|
|
|
func (a *App) ListActivityFeed(limit, offset int) ([]EventDTO, error) {
|
|
events, err := a.activity.ListRecent(limit, offset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]EventDTO, len(events))
|
|
for i, e := range events {
|
|
result[i] = toEventDTO(e)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (a *App) ListActivityByNode(nodeID string, limit, offset int) ([]EventDTO, error) {
|
|
events, err := a.activity.ListByNode(nodeID, limit, offset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]EventDTO, len(events))
|
|
for i, e := range events {
|
|
result[i] = toEventDTO(e)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (a *App) CountActivityByNode(nodeID string) (int, error) {
|
|
return a.activity.CountByNode(nodeID)
|
|
}
|
|
|
|
var _ = syncsvc.EntityNode
|