6.27.3: Фикс сброса автовыполнения и прогресс
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m28s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m28s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -353,6 +353,7 @@ type Task struct {
|
|||||||
HasProgression bool `json:"has_progression"`
|
HasProgression bool `json:"has_progression"`
|
||||||
AutoComplete bool `json:"auto_complete"`
|
AutoComplete bool `json:"auto_complete"`
|
||||||
DefaultAutoComplete bool `json:"default_auto_complete"`
|
DefaultAutoComplete bool `json:"default_auto_complete"`
|
||||||
|
HasDraft bool `json:"has_draft"`
|
||||||
DefaultProgress *float64 `json:"default_progress,omitempty"`
|
DefaultProgress *float64 `json:"default_progress,omitempty"`
|
||||||
DraftProgressionValue *float64 `json:"draft_progression_value,omitempty"`
|
DraftProgressionValue *float64 `json:"draft_progression_value,omitempty"`
|
||||||
DraftSubtasksCount *int `json:"draft_subtasks_count,omitempty"`
|
DraftSubtasksCount *int `json:"draft_subtasks_count,omitempty"`
|
||||||
@@ -396,6 +397,7 @@ type TaskDetail struct {
|
|||||||
DictionaryIDs []int `json:"dictionary_ids,omitempty"`
|
DictionaryIDs []int `json:"dictionary_ids,omitempty"`
|
||||||
PurchaseBoards []PurchaseBoardInfo `json:"purchase_boards,omitempty"`
|
PurchaseBoards []PurchaseBoardInfo `json:"purchase_boards,omitempty"`
|
||||||
// Draft fields (only present if draft exists)
|
// Draft fields (only present if draft exists)
|
||||||
|
HasDraft bool `json:"has_draft"`
|
||||||
DraftProgressionValue *float64 `json:"draft_progression_value,omitempty"`
|
DraftProgressionValue *float64 `json:"draft_progression_value,omitempty"`
|
||||||
DraftSubtasks []DraftSubtask `json:"draft_subtasks,omitempty"`
|
DraftSubtasks []DraftSubtask `json:"draft_subtasks,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -8822,7 +8824,8 @@ func (a *App) fetchTasksForUser(userID int) ([]Task, error) {
|
|||||||
) as subtask_project_names,
|
) as subtask_project_names,
|
||||||
COALESCE(td.auto_complete, FALSE) as auto_complete,
|
COALESCE(td.auto_complete, FALSE) as auto_complete,
|
||||||
td.progression_value as draft_progression_value,
|
td.progression_value as draft_progression_value,
|
||||||
CASE WHEN td.id IS NOT NULL THEN (SELECT COUNT(*) FROM task_draft_subtasks tds WHERE tds.task_draft_id = td.id) ELSE NULL END as draft_subtasks_count
|
CASE WHEN td.id IS NOT NULL THEN (SELECT COUNT(*) FROM task_draft_subtasks tds WHERE tds.task_draft_id = td.id) ELSE NULL END as draft_subtasks_count,
|
||||||
|
CASE WHEN td.id IS NOT NULL THEN TRUE ELSE FALSE END as has_draft
|
||||||
FROM tasks t
|
FROM tasks t
|
||||||
LEFT JOIN task_drafts td ON td.task_id = t.id AND td.user_id = $1
|
LEFT JOIN task_drafts td ON td.task_id = t.id AND td.user_id = $1
|
||||||
WHERE t.user_id = $1 AND t.parent_task_id IS NULL AND t.deleted = FALSE
|
WHERE t.user_id = $1 AND t.parent_task_id IS NULL AND t.deleted = FALSE
|
||||||
@@ -8866,6 +8869,7 @@ func (a *App) fetchTasksForUser(userID int) ([]Task, error) {
|
|||||||
var autoComplete bool
|
var autoComplete bool
|
||||||
var draftProgressionValue sql.NullFloat64
|
var draftProgressionValue sql.NullFloat64
|
||||||
var draftSubtasksCount sql.NullInt64
|
var draftSubtasksCount sql.NullInt64
|
||||||
|
var hasDraft bool
|
||||||
|
|
||||||
err := rows.Scan(
|
err := rows.Scan(
|
||||||
&task.ID,
|
&task.ID,
|
||||||
@@ -8889,6 +8893,7 @@ func (a *App) fetchTasksForUser(userID int) ([]Task, error) {
|
|||||||
&autoComplete,
|
&autoComplete,
|
||||||
&draftProgressionValue,
|
&draftProgressionValue,
|
||||||
&draftSubtasksCount,
|
&draftSubtasksCount,
|
||||||
|
&hasDraft,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error scanning task: %v", err)
|
log.Printf("Error scanning task: %v", err)
|
||||||
@@ -8937,6 +8942,7 @@ func (a *App) fetchTasksForUser(userID int) ([]Task, error) {
|
|||||||
task.GroupName = &groupNameVal
|
task.GroupName = &groupNameVal
|
||||||
}
|
}
|
||||||
task.AutoComplete = autoComplete
|
task.AutoComplete = autoComplete
|
||||||
|
task.HasDraft = hasDraft
|
||||||
if draftProgressionValue.Valid {
|
if draftProgressionValue.Valid {
|
||||||
task.DraftProgressionValue = &draftProgressionValue.Float64
|
task.DraftProgressionValue = &draftProgressionValue.Float64
|
||||||
}
|
}
|
||||||
@@ -9253,8 +9259,10 @@ func (a *App) getTaskDetailHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
WHERE task_id = $1 AND user_id = $2
|
WHERE task_id = $1 AND user_id = $2
|
||||||
`, taskID, userID).Scan(&draftProgressionValue, &draftAutoComplete)
|
`, taskID, userID).Scan(&draftProgressionValue, &draftAutoComplete)
|
||||||
|
|
||||||
|
hasDraft := false
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Драфт существует, загружаем данные
|
// Драфт существует, загружаем данные
|
||||||
|
hasDraft = true
|
||||||
if draftProgressionValue.Valid {
|
if draftProgressionValue.Valid {
|
||||||
draftProgressionValuePtr = &draftProgressionValue.Float64
|
draftProgressionValuePtr = &draftProgressionValue.Float64
|
||||||
}
|
}
|
||||||
@@ -9307,6 +9315,7 @@ func (a *App) getTaskDetailHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
Task: task,
|
Task: task,
|
||||||
Rewards: rewards,
|
Rewards: rewards,
|
||||||
Subtasks: subtasks,
|
Subtasks: subtasks,
|
||||||
|
HasDraft: hasDraft,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Устанавливаем DraftProgressionValue если он был загружен
|
// Устанавливаем DraftProgressionValue если он был загружен
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "play-life-web",
|
"name": "play-life-web",
|
||||||
"version": "6.27.2",
|
"version": "6.27.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -733,10 +733,9 @@ function TaskDetail({ taskId, onClose, onRefresh, onTaskCompleted, onNavigate })
|
|||||||
// Обновляем значение чекбокса при изменении taskDetail
|
// Обновляем значение чекбокса при изменении taskDetail
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (taskDetail && taskDetail.task) {
|
if (taskDetail && taskDetail.task) {
|
||||||
// Если есть драфт (auto_complete или draft_progression_value), используем значение из драфта
|
// Если есть драфт, используем значение из драфта
|
||||||
// Иначе используем default_auto_complete как начальное значение
|
// Иначе используем default_auto_complete как начальное значение
|
||||||
const hasDraft = taskDetail.task.auto_complete || taskDetail.draft_progression_value != null
|
const autoCompleteValue = taskDetail.has_draft
|
||||||
const autoCompleteValue = hasDraft
|
|
||||||
? Boolean(taskDetail.task.auto_complete)
|
? Boolean(taskDetail.task.auto_complete)
|
||||||
: Boolean(taskDetail.task.default_auto_complete)
|
: Boolean(taskDetail.task.default_auto_complete)
|
||||||
setCompleteAtEndOfDay(autoCompleteValue)
|
setCompleteAtEndOfDay(autoCompleteValue)
|
||||||
|
|||||||
@@ -747,8 +747,8 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
|
|||||||
// Сортируем невыполненные задачи: автовыполнение первыми, затем по алфавиту (name ASC), затем по id ASC
|
// Сортируем невыполненные задачи: автовыполнение первыми, затем по алфавиту (name ASC), затем по id ASC
|
||||||
group.notCompleted.sort((a, b) => {
|
group.notCompleted.sort((a, b) => {
|
||||||
// Задачи с автовыполнением (включая default_auto_complete) идут первыми
|
// Задачи с автовыполнением (включая default_auto_complete) идут первыми
|
||||||
const aAuto = a.auto_complete || a.default_auto_complete
|
const aAuto = a.has_draft ? a.auto_complete : a.auto_complete || a.default_auto_complete
|
||||||
const bAuto = b.auto_complete || b.default_auto_complete
|
const bAuto = b.has_draft ? b.auto_complete : b.auto_complete || b.default_auto_complete
|
||||||
if (aAuto && !bAuto) return -1
|
if (aAuto && !bAuto) return -1
|
||||||
if (!aAuto && bAuto) return 1
|
if (!aAuto && bAuto) return 1
|
||||||
|
|
||||||
@@ -762,8 +762,8 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
|
|||||||
// Сортируем выполненные задачи: автовыполнение первыми, затем бесконечные, затем по next_show_at ASC (ранние в начале), NULL в начале
|
// Сортируем выполненные задачи: автовыполнение первыми, затем бесконечные, затем по next_show_at ASC (ранние в начале), NULL в начале
|
||||||
group.completed.sort((a, b) => {
|
group.completed.sort((a, b) => {
|
||||||
// Задачи с автовыполнением (включая default_auto_complete) идут первыми
|
// Задачи с автовыполнением (включая default_auto_complete) идут первыми
|
||||||
const aAuto = a.auto_complete || a.default_auto_complete
|
const aAuto = a.has_draft ? a.auto_complete : a.auto_complete || a.default_auto_complete
|
||||||
const bAuto = b.auto_complete || b.default_auto_complete
|
const bAuto = b.has_draft ? b.auto_complete : b.auto_complete || b.default_auto_complete
|
||||||
if (aAuto && !bAuto) return -1
|
if (aAuto && !bAuto) return -1
|
||||||
if (!aAuto && bAuto) return 1
|
if (!aAuto && bAuto) return 1
|
||||||
|
|
||||||
@@ -851,7 +851,7 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
|
|||||||
>
|
>
|
||||||
<div className="task-item-content">
|
<div className="task-item-content">
|
||||||
<div
|
<div
|
||||||
className={`task-checkmark ${showDetailOnCheckmark ? 'task-checkmark-detail' : ''} ${(task.auto_complete || task.default_auto_complete) ? 'task-checkmark-auto-complete' : ''}`}
|
className={`task-checkmark ${showDetailOnCheckmark ? 'task-checkmark-detail' : ''} ${(task.has_draft ? task.auto_complete : task.auto_complete || task.default_auto_complete) ? 'task-checkmark-auto-complete' : ''}`}
|
||||||
onClick={(e) => handleCheckmarkClick(task, e)}
|
onClick={(e) => handleCheckmarkClick(task, e)}
|
||||||
title={isTest ? 'Запустить тест' : (isPurchase ? 'Открыть закупки' : (showDetailOnCheckmark ? 'Открыть детали' : 'Выполнить задачу'))}
|
title={isTest ? 'Запустить тест' : (isPurchase ? 'Открыть закупки' : (showDetailOnCheckmark ? 'Открыть детали' : 'Выполнить задачу'))}
|
||||||
>
|
>
|
||||||
@@ -919,7 +919,7 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
|
|||||||
<path d="M6 10 L9 13 L14 7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="checkmark-check" />
|
<path d="M6 10 L9 13 L14 7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="checkmark-check" />
|
||||||
</svg>
|
</svg>
|
||||||
)}
|
)}
|
||||||
{(task.auto_complete || task.default_auto_complete) && !isTest && !isWishlist && (
|
{(task.has_draft ? task.auto_complete : task.auto_complete || task.default_auto_complete) && !isTest && !isWishlist && (
|
||||||
<svg
|
<svg
|
||||||
className="task-checkmark-auto-complete-icon"
|
className="task-checkmark-auto-complete-icon"
|
||||||
width="16"
|
width="16"
|
||||||
@@ -1005,8 +1005,8 @@ function TaskList({ onNavigate, data, loading, backgroundLoading, error, onRetry
|
|||||||
<polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline>
|
<polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline>
|
||||||
<polyline points="17 6 23 6 23 12"></polyline>
|
<polyline points="17 6 23 6 23 12"></polyline>
|
||||||
</svg>
|
</svg>
|
||||||
{task.draft_progression_value != null && (
|
{(task.draft_progression_value != null || (task.has_draft ? task.auto_complete : task.auto_complete || task.default_auto_complete)) && (
|
||||||
<span className="task-progression-value">{task.draft_progression_value}</span>
|
<span className="task-progression-value">{task.draft_progression_value ?? task.default_progress ?? task.progression_base}</span>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user