5.10.1: Не сбрасывать подзадачи при быстрой прогрессии
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m22s

This commit is contained in:
poignatov
2026-03-04 15:11:11 +03:00
parent 81dc23b501
commit 98427f5d0e
4 changed files with 64 additions and 44 deletions

View File

@@ -1 +1 @@
5.10.0
5.10.1

View File

@@ -435,8 +435,8 @@ type PostponeTaskRequest struct {
type SaveDraftRequest struct {
ProgressionValue *float64 `json:"progression_value,omitempty"`
ChildrenTaskIDs []int `json:"children_task_ids,omitempty"` // только checked подзадачи
AutoComplete bool `json:"auto_complete"`
ChildrenTaskIDs *[]int `json:"children_task_ids,omitempty"` // только checked подзадачи, nil = не менять
AutoComplete *bool `json:"auto_complete,omitempty"` // nil = не менять
}
type TaskDraft struct {
@@ -9412,11 +9412,15 @@ func (a *App) saveTaskDraftHandler(w http.ResponseWriter, r *http.Request) {
if err == sql.ErrNoRows {
// Создаем новый драфт
autoComplete := false
if req.AutoComplete != nil {
autoComplete = *req.AutoComplete
}
err = tx.QueryRow(`
INSERT INTO task_drafts (task_id, user_id, progression_value, auto_complete, created_at, updated_at)
VALUES ($1, $2, $3, $4, NOW(), NOW())
RETURNING id
`, taskID, userID, progressionValue, req.AutoComplete).Scan(&draftID)
`, taskID, userID, progressionValue, autoComplete).Scan(&draftID)
if err != nil {
log.Printf("Error creating draft: %v", err)
@@ -9429,36 +9433,50 @@ func (a *App) saveTaskDraftHandler(w http.ResponseWriter, r *http.Request) {
return
} else {
// Обновляем существующий драфт
// При обновлении очищаем auto_complete если параметр false
autoComplete := req.AutoComplete
_, err = tx.Exec(`
UPDATE task_drafts
SET progression_value = $1, auto_complete = $2, updated_at = NOW()
WHERE id = $3
`, progressionValue, autoComplete, draftID)
// Обновляем только те поля, которые переданы
if req.ProgressionValue != nil || req.AutoComplete != nil {
if req.AutoComplete != nil {
// Обновляем оба поля
_, err = tx.Exec(`
UPDATE task_drafts
SET progression_value = COALESCE($1, progression_value), auto_complete = $2, updated_at = NOW()
WHERE id = $3
`, progressionValue, *req.AutoComplete, draftID)
} else {
// Обновляем только progression_value
_, err = tx.Exec(`
UPDATE task_drafts
SET progression_value = $1, updated_at = NOW()
WHERE id = $2
`, progressionValue, draftID)
}
if err != nil {
log.Printf("Error updating draft: %v", err)
sendErrorWithCORS(w, fmt.Sprintf("Error updating draft: %v", err), http.StatusInternalServerError)
return
if err != nil {
log.Printf("Error updating draft: %v", err)
sendErrorWithCORS(w, fmt.Sprintf("Error updating draft: %v", err), http.StatusInternalServerError)
return
}
}
// Удаляем все старые записи подзадач
_, err = tx.Exec("DELETE FROM task_draft_subtasks WHERE task_draft_id = $1", draftID)
if err != nil {
log.Printf("Error deleting old draft subtasks: %v", err)
sendErrorWithCORS(w, fmt.Sprintf("Error deleting old draft subtasks: %v", err), http.StatusInternalServerError)
return
// Удаляем и обновляем записи подзадач только если они были переданы
if req.ChildrenTaskIDs != nil {
_, err = tx.Exec("DELETE FROM task_draft_subtasks WHERE task_draft_id = $1", draftID)
if err != nil {
log.Printf("Error deleting old draft subtasks: %v", err)
sendErrorWithCORS(w, fmt.Sprintf("Error deleting old draft subtasks: %v", err), http.StatusInternalServerError)
return
}
}
}
// Вставляем новые записи подзадач (только checked подзадачи)
if len(req.ChildrenTaskIDs) > 0 {
if req.ChildrenTaskIDs != nil && len(*req.ChildrenTaskIDs) > 0 {
childrenIDs := *req.ChildrenTaskIDs
// Проверяем, что все подзадачи принадлежат этой задаче
placeholders := make([]string, len(req.ChildrenTaskIDs))
args := make([]interface{}, len(req.ChildrenTaskIDs)+1)
placeholders := make([]string, len(childrenIDs))
args := make([]interface{}, len(childrenIDs)+1)
args[0] = taskID
for i, id := range req.ChildrenTaskIDs {
for i, id := range childrenIDs {
placeholders[i] = fmt.Sprintf("$%d", i+2)
args[i+1] = id
}
@@ -9485,7 +9503,7 @@ func (a *App) saveTaskDraftHandler(w http.ResponseWriter, r *http.Request) {
}
// Вставляем только валидные подзадачи
for _, subtaskID := range req.ChildrenTaskIDs {
for _, subtaskID := range childrenIDs {
if validSubtaskIDs[subtaskID] {
_, err = tx.Exec(`
INSERT INTO task_draft_subtasks (task_draft_id, subtask_id)
@@ -10019,7 +10037,8 @@ func (a *App) completeTaskAtEndOfDayHandler(w http.ResponseWriter, r *http.Reque
}
// Устанавливаем auto_complete = true
req.AutoComplete = true
autoCompleteTrue := true
req.AutoComplete = &autoCompleteTrue
// Используем ту же логику что и saveTaskDraftHandler
// Начинаем транзакцию
@@ -10046,7 +10065,7 @@ func (a *App) completeTaskAtEndOfDayHandler(w http.ResponseWriter, r *http.Reque
INSERT INTO task_drafts (task_id, user_id, progression_value, auto_complete, created_at, updated_at)
VALUES ($1, $2, $3, $4, NOW(), NOW())
RETURNING id
`, taskID, userID, progressionValue, req.AutoComplete).Scan(&draftID)
`, taskID, userID, progressionValue, *req.AutoComplete).Scan(&draftID)
if err != nil {
log.Printf("Error creating draft: %v", err)
@@ -10063,7 +10082,7 @@ func (a *App) completeTaskAtEndOfDayHandler(w http.ResponseWriter, r *http.Reque
UPDATE task_drafts
SET progression_value = $1, auto_complete = $2, updated_at = NOW()
WHERE id = $3
`, progressionValue, req.AutoComplete, draftID)
`, progressionValue, *req.AutoComplete, draftID)
if err != nil {
log.Printf("Error updating draft: %v", err)
@@ -10071,22 +10090,25 @@ func (a *App) completeTaskAtEndOfDayHandler(w http.ResponseWriter, r *http.Reque
return
}
// Удаляем все старые записи подзадач
_, err = tx.Exec("DELETE FROM task_draft_subtasks WHERE task_draft_id = $1", draftID)
if err != nil {
log.Printf("Error deleting old draft subtasks: %v", err)
sendErrorWithCORS(w, fmt.Sprintf("Error deleting old draft subtasks: %v", err), http.StatusInternalServerError)
return
// Удаляем все старые записи подзадач только если они были переданы
if req.ChildrenTaskIDs != nil {
_, err = tx.Exec("DELETE FROM task_draft_subtasks WHERE task_draft_id = $1", draftID)
if err != nil {
log.Printf("Error deleting old draft subtasks: %v", err)
sendErrorWithCORS(w, fmt.Sprintf("Error deleting old draft subtasks: %v", err), http.StatusInternalServerError)
return
}
}
}
// Вставляем новые записи подзадач (только checked подзадачи)
if len(req.ChildrenTaskIDs) > 0 {
if req.ChildrenTaskIDs != nil && len(*req.ChildrenTaskIDs) > 0 {
childrenIDs := *req.ChildrenTaskIDs
// Проверяем, что все подзадачи принадлежат этой задаче
placeholders := make([]string, len(req.ChildrenTaskIDs))
args := make([]interface{}, len(req.ChildrenTaskIDs)+1)
placeholders := make([]string, len(childrenIDs))
args := make([]interface{}, len(childrenIDs)+1)
args[0] = taskID
for i, id := range req.ChildrenTaskIDs {
for i, id := range childrenIDs {
placeholders[i] = fmt.Sprintf("$%d", i+2)
args[i+1] = id
}
@@ -10113,7 +10135,7 @@ func (a *App) completeTaskAtEndOfDayHandler(w http.ResponseWriter, r *http.Reque
}
// Вставляем только валидные подзадачи
for _, subtaskID := range req.ChildrenTaskIDs {
for _, subtaskID := range childrenIDs {
if validSubtaskIDs[subtaskID] {
_, err = tx.Exec(`
INSERT INTO task_draft_subtasks (task_draft_id, subtask_id)

View File

@@ -1,6 +1,6 @@
{
"name": "play-life-web",
"version": "5.10.0",
"version": "5.10.1",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -566,9 +566,7 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
'Content-Type': 'application/json',
},
body: JSON.stringify({
progression_value: newValue,
auto_complete: false,
children_task_ids: []
progression_value: newValue
}),
})