diff --git a/models/project.go b/models/project.go index 38229ce..3f2c5aa 100644 --- a/models/project.go +++ b/models/project.go @@ -99,7 +99,13 @@ type ProjectUpdate struct { type ProjectResult struct { Project - Tasks []*TaskResult `json:"tasks"` + Tasks []*TaskResult `json:"tasks"` + Subtractions []ProjectSubtraction `json:"subtractions"` +} + +type ProjectSubtraction struct { + Item Item `json:"item"` + Amount int `json:"amount"` } type ProjectFilter struct { diff --git a/services/loader.go b/services/loader.go index 9f917b1..2d35b91 100644 --- a/services/loader.go +++ b/services/loader.go @@ -234,7 +234,7 @@ func (l *Loader) FindProject(ctx context.Context, id string) (*models.ProjectRes if project.UserID != auth.UserID(ctx) { return nil, slerrors.NotFound("Goal") } - result := &models.ProjectResult{Project: *project} + result := &models.ProjectResult{Project: *project, Subtractions: []models.ProjectSubtraction{}} tasks, err := l.DB.Tasks().List(ctx, models.TaskFilter{ UserID: auth.UserID(ctx), @@ -301,10 +301,19 @@ func (l *Loader) FindProject(ctx context.Context, id string) (*models.ProjectRes } for _, log := range result.Tasks[i].Logs { if project.StartTime != nil && log.LoggedTime.Before(*project.StartTime) { - continue + result.Subtractions = append(result.Subtractions, models.ProjectSubtraction{ + Item: *result.Tasks[i].Item, + Amount: log.ItemAmount, + }) + if log.SecondaryItemID != nil { + result.Subtractions = append(result.Subtractions, models.ProjectSubtraction{ + Item: *log.SecondaryItem, + Amount: log.SecondaryItemAmount, + }) + } } - result.Tasks[i].CompletedAmount += log.Amount(result.Tasks[i].ItemID) + result.Tasks[i].CompletedAmount += log.Amount(log.ItemID) } } @@ -359,7 +368,7 @@ func (l *Loader) ListProjects(ctx context.Context, filter models.ProjectFilter) results := make([]*models.ProjectResult, len(projects)) for i, project := range projects { - results[i] = &models.ProjectResult{Project: *project} + results[i] = &models.ProjectResult{Project: *project, Subtractions: []models.ProjectSubtraction{}} results[i].Tasks = make([]*models.TaskResult, 0, 16) for _, task := range tasks { if task.ProjectID != project.ID { @@ -408,7 +417,16 @@ func (l *Loader) ListProjects(ctx context.Context, filter models.ProjectFilter) } for _, log := range taskResult.Logs { if project.StartTime != nil && log.LoggedTime.Before(*project.StartTime) { - continue + results[i].Subtractions = append(results[i].Subtractions, models.ProjectSubtraction{ + Item: *taskResult.Item, + Amount: log.ItemAmount, + }) + if log.SecondaryItem != nil { + results[i].Subtractions = append(results[i].Subtractions, models.ProjectSubtraction{ + Item: *log.SecondaryItem, + Amount: log.SecondaryItemAmount, + }) + } } taskResult.CompletedAmount += log.Amount(taskResult.ItemID) diff --git a/svelte-ui/src/components/ItemProgress.svelte b/svelte-ui/src/components/ItemProgress.svelte index 4d81bbc..7741bed 100644 --- a/svelte-ui/src/components/ItemProgress.svelte +++ b/svelte-ui/src/components/ItemProgress.svelte @@ -9,6 +9,7 @@ import type { LogResult } from "../models/log"; amount: number target: number extras: number + subs: number noTarget?: boolean } @@ -26,7 +27,7 @@ import type { LogResult } from "../models/log"; for (const task of project.tasks) { let entry = list.find(e => e.item.id === task.item.id); if (entry == null) { - entry = {item: task.item, amount: 0, target: 0, extras: 0}; + entry = {item: task.item, amount: 0, target: 0, extras: 0, subs: 0}; list.push(entry); } @@ -47,7 +48,7 @@ import type { LogResult } from "../models/log"; if (log.secondaryItem != null) { let entry = list.find(e => e.item.id === log.secondaryItemId); if (entry == null) { - entry = {item: log.secondaryItem, amount: 0, target: 0, extras: 0}; + entry = {item: log.secondaryItem, amount: 0, target: 0, extras: 0, subs: 0}; list.push(entry); } @@ -55,6 +56,17 @@ import type { LogResult } from "../models/log"; } } } + + for (const {item, amount} of project.subtractions) { + const entry = list.find(e => e.item.id === item.id); + if (entry == null) { + continue + } + + entry.subs += amount; + entry.target -= amount; + entry.amount -= amount; + } } for (const log of logs) { @@ -67,7 +79,7 @@ import type { LogResult } from "../models/log"; if (item != null) { let entry = list.find(e => e.item.id === item.id); if (entry == null) { - entry = {item, amount: 0, target: 0, extras: 0, noTarget: true}; + entry = {item, amount: 0, target: 0, extras: 0, noTarget: true, subs: 0}; list.push(entry); } @@ -86,7 +98,7 @@ import type { LogResult } from "../models/log"; } else { return b.target - a.target; } - }).filter(l => l.extras > 0 || (l.target > 0 || l.noTarget)); + }).filter(e => e.extras > 0 || (e.target > 0 || e.subs > 0 || e.noTarget)); } @@ -120,6 +132,11 @@ import type { LogResult } from "../models/log"; ×{entry.extras} {/if} + {#if entry.subs > 0} +
+ –{entry.subs} +
+ {/if} {/each} @@ -166,4 +183,7 @@ import type { LogResult } from "../models/log"; div.ItemProgress div.entry .extras { color: #484; } + div.ItemProgress div.entry .subs { + color: #852a24; + } \ No newline at end of file diff --git a/svelte-ui/src/components/ProgressNumbers.svelte b/svelte-ui/src/components/ProgressNumbers.svelte index ab88954..b7aadba 100644 --- a/svelte-ui/src/components/ProgressNumbers.svelte +++ b/svelte-ui/src/components/ProgressNumbers.svelte @@ -23,6 +23,11 @@ progressTarget = Math.max((project.tasks||[]).map(t => t.itemAmount * (t.item.groupWeight || 1)).reduce((n,m) => n+m, 0), 1); + for (const {item, amount} of (project.subtractions||[])) { + progressAmount -= item.groupWeight * amount; + progressTarget -= item.groupWeight * amount; + } + progressAmount = Math.max(progressAmount - project.subtractAmount, 0); progressTarget = Math.max(progressTarget - project.subtractAmount, 0); diff --git a/svelte-ui/src/components/ProjectProgress.svelte b/svelte-ui/src/components/ProjectProgress.svelte index c2382ed..ce3e009 100644 --- a/svelte-ui/src/components/ProjectProgress.svelte +++ b/svelte-ui/src/components/ProjectProgress.svelte @@ -1,4 +1,6 @@