4.12.0: Добавлены записи за день на экране статистики
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m28s

This commit is contained in:
poignatov
2026-02-03 18:26:21 +03:00
parent c3d366b9c2
commit 36dd96976f
6 changed files with 534 additions and 11 deletions

View File

@@ -177,6 +177,19 @@ type FullStatisticsItem struct {
MaxGoalScore float64 `json:"max_goal_score"`
}
type TodayEntryNode struct {
ProjectName string `json:"project_name"`
Score float64 `json:"score"`
Index int `json:"index"`
}
type TodayEntry struct {
ID int `json:"id"`
Text string `json:"text"`
CreatedDate string `json:"created_date"`
Nodes []TodayEntryNode `json:"nodes"`
}
type TodoistWebhook struct {
EventName string `json:"event_name"`
EventData map[string]interface{} `json:"event_data"`
@@ -3740,6 +3753,7 @@ func main() {
protected.HandleFunc("/project/delete", app.deleteProjectHandler).Methods("POST", "OPTIONS")
protected.HandleFunc("/project/create", app.createProjectHandler).Methods("POST", "OPTIONS")
protected.HandleFunc("/d2dc349a-0d13-49b2-a8f0-1ab094bfba9b", app.getFullStatisticsHandler).Methods("GET", "OPTIONS")
protected.HandleFunc("/api/today-entries", app.getTodayEntriesHandler).Methods("GET", "OPTIONS")
// Integrations
protected.HandleFunc("/api/integrations/telegram", app.getTelegramIntegrationHandler).Methods("GET", "OPTIONS")
@@ -6185,6 +6199,128 @@ func (a *App) getFullStatisticsHandler(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(statistics)
}
// getTodayEntriesHandler возвращает entries с nodes за сегодняшний день
func (a *App) getTodayEntriesHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
setCORSHeaders(w)
w.WriteHeader(http.StatusOK)
return
}
setCORSHeaders(w)
userID, ok := getUserIDFromContext(r)
if !ok {
sendErrorWithCORS(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Получаем опциональные параметры из query string
projectName := r.URL.Query().Get("project")
var projectFilter *string
if projectName != "" {
projectFilter = &projectName
}
// Получаем дату из query string (формат: YYYY-MM-DD), если не указана - используем сегодня
dateParam := r.URL.Query().Get("date")
var targetDate time.Time
if dateParam != "" {
parsedDate, err := time.Parse("2006-01-02", dateParam)
if err != nil {
log.Printf("Error parsing date parameter: %v", err)
sendErrorWithCORS(w, "Invalid date format. Use YYYY-MM-DD", http.StatusBadRequest)
return
}
targetDate = parsedDate
} else {
targetDate = time.Now()
}
// Запрос для получения entries с nodes за указанный день
// Используем подзапрос для получения nodes с правильными индексами
query := `
WITH entry_nodes AS (
SELECT
e.id as entry_id,
e.text,
e.created_date,
p.name as project_name,
n.score,
ROW_NUMBER() OVER (PARTITION BY e.id ORDER BY n.id) - 1 as node_index
FROM entries e
JOIN nodes n ON n.entry_id = e.id
JOIN projects p ON n.project_id = p.id
WHERE DATE(n.created_date) = DATE($3)
AND e.user_id = $1
AND n.user_id = $1
AND p.user_id = $1
AND p.deleted = FALSE
AND ($2::text IS NULL OR p.name = $2)
)
SELECT
entry_id,
text,
created_date,
json_agg(
json_build_object(
'project_name', project_name,
'score', score,
'index', node_index
) ORDER BY node_index
) as nodes
FROM entry_nodes
GROUP BY entry_id, text, created_date
ORDER BY created_date DESC
`
rows, err := a.DB.Query(query, userID, projectFilter, targetDate)
if err != nil {
log.Printf("Error querying today entries: %v", err)
sendErrorWithCORS(w, fmt.Sprintf("Error querying today entries: %v", err), http.StatusInternalServerError)
return
}
defer rows.Close()
entries := make([]TodayEntry, 0)
for rows.Next() {
var entry TodayEntry
var createdDate time.Time
var nodesJSON string
err := rows.Scan(
&entry.ID,
&entry.Text,
&createdDate,
&nodesJSON,
)
if err != nil {
log.Printf("Error scanning today entry row: %v", err)
continue
}
// Парсим JSON с nodes
if err := json.Unmarshal([]byte(nodesJSON), &entry.Nodes); err != nil {
log.Printf("Error unmarshaling nodes JSON: %v", err)
continue
}
// Форматируем дату в ISO 8601
entry.CreatedDate = createdDate.Format(time.RFC3339)
entries = append(entries, entry)
}
if err := rows.Err(); err != nil {
log.Printf("Error iterating today entries rows: %v", err)
sendErrorWithCORS(w, fmt.Sprintf("Error iterating rows: %v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(entries)
}
// getTelegramIntegrationHandler возвращает текущую telegram интеграцию с deep link
func (a *App) getTelegramIntegrationHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {