diff --git a/api/task.go b/api/task.go index 45c7a78..601efc1 100644 --- a/api/task.go +++ b/api/task.go @@ -68,7 +68,7 @@ func Task(g *gin.RouterGroup, db database.Database) { return &models.TaskResult{ Task: task, - Logs: []*models.Log{}, + Logs: []*models.LogWithSecondaryItem{}, Item: &item.Item, CompletedAmount: 0, }, nil diff --git a/models/log.go b/models/log.go index 62f18c5..e5aa4f1 100644 --- a/models/log.go +++ b/models/log.go @@ -67,14 +67,19 @@ type LogResult struct { SecondaryItem *Item `json:"secondaryItem"` } +type LogWithSecondaryItem struct { + Log + SecondaryItem *Item `json:"secondaryItem,omitempty"` +} + type LogFilter struct { - UserID string + UserID string ProjectGroupIDs []string - ProjectIDs []string - TaskIDs []string - ItemIDs []string - MinTime *time.Time - MaxTime *time.Time + ProjectIDs []string + TaskIDs []string + ItemIDs []string + MinTime *time.Time + MaxTime *time.Time } type LogRepository interface { diff --git a/models/task.go b/models/task.go index 51c98ab..68ae6a7 100644 --- a/models/task.go +++ b/models/task.go @@ -79,10 +79,10 @@ type TaskWithProject struct { type TaskResult struct { Task - Item *Item `json:"item"` - Logs []*Log `json:"logs"` - CompletedAmount int `json:"completedAmount"` - Project *Project `json:"project,omitempty"` + Item *Item `json:"item"` + Logs []*LogWithSecondaryItem `json:"logs"` + CompletedAmount int `json:"completedAmount"` + Project *Project `json:"project,omitempty"` } type TaskFilter struct { diff --git a/services/loader.go b/services/loader.go index 4de6a99..695472d 100644 --- a/services/loader.go +++ b/services/loader.go @@ -251,6 +251,12 @@ func (l *Loader) FindProject(ctx context.Context, id string) (*models.ProjectRes UserID: auth.UserID(ctx), TaskIDs: taskIDs, }) + for _, log := range logs { + if log.SecondaryItemID == nil { + itemIDs.Add(*log.SecondaryItemID) + } + } + if err != nil { return nil, err } @@ -265,12 +271,26 @@ func (l *Loader) FindProject(ctx context.Context, id string) (*models.ProjectRes result.Tasks = make([]*models.TaskResult, len(tasks)) for i, task := range tasks { result.Tasks[i] = &models.TaskResult{ - Logs: []*models.Log{}, + Logs: []*models.LogWithSecondaryItem{}, } result.Tasks[i].Task = *task for _, log := range logs { if log.TaskID == task.ID { - result.Tasks[i].Logs = append(result.Tasks[i].Logs, log) + log := models.LogWithSecondaryItem{ + Log: *log, + SecondaryItem: nil, + } + + if log.SecondaryItemID != nil { + for _, item := range items { + if item.ID == *log.SecondaryItemID { + log.SecondaryItem = item + break + } + } + } + + result.Tasks[i].Logs = append(result.Tasks[i].Logs, &log) } } for _, item := range items { @@ -280,6 +300,10 @@ 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.Tasks[i].CompletedAmount += log.Amount(result.Tasks[i].ItemID) } } @@ -319,6 +343,11 @@ func (l *Loader) ListProjects(ctx context.Context, filter models.ProjectFilter) if err != nil { return nil, err } + for _, log := range logs { + if log.SecondaryItemID != nil { + itemIDs.Add(*log.SecondaryItemID) + } + } items, err := l.DB.Items().List(ctx, models.ItemFilter{ UserID: auth.UserID(ctx), @@ -350,11 +379,25 @@ func (l *Loader) ListProjects(ctx context.Context, filter models.ProjectFilter) taskResult := &models.TaskResult{ Task: *task, - Logs: []*models.Log{}, + Logs: []*models.LogWithSecondaryItem{}, } for _, log := range logs { if log.TaskID == task.ID { - taskResult.Logs = append(taskResult.Logs, log) + log := models.LogWithSecondaryItem{ + Log: *log, + SecondaryItem: nil, + } + + if log.SecondaryItemID != nil { + for _, item := range items { + if item.ID == *log.SecondaryItemID { + log.SecondaryItem = item + break + } + } + } + + taskResult.Logs = append(taskResult.Logs, &log) } } for _, item := range items { @@ -364,6 +407,10 @@ 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 + } + taskResult.CompletedAmount += log.Amount(taskResult.ItemID) } results[i].Tasks = append(results[i].Tasks, taskResult) @@ -468,7 +515,7 @@ func (l *Loader) FindTask(ctx context.Context, id string) (*models.TaskResult, e result.Item, _ = l.DB.Items().Find(ctx, task.ItemID) result.Project, _ = l.DB.Projects().Find(ctx, task.ProjectID) - result.Logs, err = l.DB.Logs().List(ctx, models.LogFilter{ + logs, err := l.DB.Logs().List(ctx, models.LogFilter{ UserID: task.UserID, TaskIDs: []string{task.ID}, }) @@ -476,8 +523,34 @@ func (l *Loader) FindTask(ctx context.Context, id string) (*models.TaskResult, e return nil, err } - for _, log := range result.Logs { + itemIds := stringset.New() + for _, log := range logs { + if log.SecondaryItemID != nil { + itemIds.Add(*log.SecondaryItemID) + } + } + items, err := l.DB.Items().List(ctx, models.ItemFilter{ + UserID: task.UserID, + IDs: itemIds.Strings(), + }) + + for _, log := range logs { result.CompletedAmount += log.Amount(result.ItemID) + log := models.LogWithSecondaryItem{ + Log: *log, + SecondaryItem: nil, + } + + if log.SecondaryItemID != nil { + for _, item := range items { + if item.ID == *log.SecondaryItemID { + log.SecondaryItem = item + break + } + } + } + + result.Logs = append(result.Logs, &log) } return result, nil @@ -509,7 +582,11 @@ func (l *Loader) ListTasks(ctx context.Context, filter models.TaskFilter) ([]*mo if err != nil { return nil, err } - + for _, log := range logs { + if log.SecondaryItemID != nil { + itemIDs.Add(*log.SecondaryItemID) + } + } items, err := l.DB.Items().List(ctx, models.ItemFilter{ UserID: auth.UserID(ctx), IDs: itemIDs.Strings(), @@ -530,13 +607,30 @@ func (l *Loader) ListTasks(ctx context.Context, filter models.TaskFilter) ([]*mo for _, task := range tasks { result := &models.TaskResult{ Task: *task, - Logs: []*models.Log{}, + Logs: []*models.LogWithSecondaryItem{}, } for _, log := range logs { - if log.TaskID == task.ID { - result.Logs = append(result.Logs, log) + if log.TaskID != task.ID { + continue } + + result.CompletedAmount += log.Amount(result.ItemID) + log := models.LogWithSecondaryItem{ + Log: *log, + SecondaryItem: nil, + } + + if log.SecondaryItemID != nil { + for _, item := range items { + if item.ID == *log.SecondaryItemID { + log.SecondaryItem = item + break + } + } + } + + result.Logs = append(result.Logs, &log) } for _, item := range items { diff --git a/svelte-ui/src/components/ItemProgress.svelte b/svelte-ui/src/components/ItemProgress.svelte new file mode 100644 index 0000000..8b777e1 --- /dev/null +++ b/svelte-ui/src/components/ItemProgress.svelte @@ -0,0 +1,108 @@ + + +
+ {#each list as entry (entry.item.id)} +
+
+ +
+
+ {entry.item.name} +
+ {#if entry.target !== 0} +
+ {entry.amount} + / + {entry.target} + {#if entry.extras > 0} + + {entry.extras} + {/if} +
+ + {:else} +
+ ×{entry.extras} +
+ {/if} +
+ {/each} +
+ + \ No newline at end of file diff --git a/svelte-ui/src/components/ProjectEntry.svelte b/svelte-ui/src/components/ProjectEntry.svelte index aa0d7ed..1866446 100644 --- a/svelte-ui/src/components/ProjectEntry.svelte +++ b/svelte-ui/src/components/ProjectEntry.svelte @@ -7,6 +7,7 @@ import stuffLogClient from "../clients/stufflog"; import type { ModalData } from "../stores/modal"; import IS_MOBILE from "../utils/phone-check"; import Icon from "./Icon.svelte"; +import ItemProgress from "./ItemProgress.svelte"; import Option from "./Option.svelte"; import OptionRow from "./OptionRow.svelte"; import ParentEntry from "./ParentEntry.svelte"; @@ -120,6 +121,8 @@ import stuffLogClient from "../clients/stufflog"; {/if} {#if showAllOptions} + + diff --git a/svelte-ui/src/models/log.ts b/svelte-ui/src/models/log.ts index 117cee5..04a8d9f 100644 --- a/svelte-ui/src/models/log.ts +++ b/svelte-ui/src/models/log.ts @@ -20,6 +20,10 @@ export interface LogFilter { projectGroupIds?: string[] } +export interface LogWithSecondaryItem extends Log { + secondaryItem?: Item +} + export interface LogResult extends Log { task: TaskWithProject item: Item diff --git a/svelte-ui/src/models/task.ts b/svelte-ui/src/models/task.ts index 8ce88ae..d790a0b 100644 --- a/svelte-ui/src/models/task.ts +++ b/svelte-ui/src/models/task.ts @@ -1,6 +1,6 @@ import type { IconName } from "../external/icons"; import type Item from "./item"; -import type Log from "./log"; +import type { LogWithSecondaryItem } from "./log"; import type Project from "./project"; export default interface Task { @@ -23,7 +23,7 @@ export interface TaskWithProject extends Task { export interface TaskResult extends Task { item: Item - logs: Log[] + logs: LogWithSecondaryItem[] completedAmount: number project?: Project }