Browse Source

add project to logs, project composition mode to goals and fix unweighted counts for other composition modes.

main
Gisle Aune 4 years ago
parent
commit
589f7a9132
  1. 5
      api/log.go
  2. 6
      models/log.go
  3. 5
      models/task.go
  4. 58
      services/loader.go
  5. 7
      svelte-ui/src/components/ChildEntry.svelte
  6. 26
      svelte-ui/src/components/Composition.svelte
  7. 1
      svelte-ui/src/forms/GoalForm.svelte
  8. 2
      svelte-ui/src/models/goal.ts
  9. 4
      svelte-ui/src/models/log.ts
  10. 5
      svelte-ui/src/models/task.ts

5
api/log.go

@ -85,10 +85,7 @@ func Log(g *gin.RouterGroup, db database.Database) {
return nil, err return nil, err
} }
return &models.LogResult{
Log: log,
Task: &task.Task,
}, nil
return l.FindLog(c.Request.Context(), log.ID)
})) }))
g.PUT("/:id", handler("log", func(c *gin.Context) (interface{}, error) { g.PUT("/:id", handler("log", func(c *gin.Context) (interface{}, error) {

6
models/log.go

@ -62,9 +62,9 @@ type LogUpdate struct {
type LogResult struct { type LogResult struct {
Log Log
Task *Task `json:"task"`
Item *Item `json:"item"`
SecondaryItem *Item `json:"secondaryItem"`
Task *TaskWithProject `json:"task"`
Item *Item `json:"item"`
SecondaryItem *Item `json:"secondaryItem"`
} }
type LogFilter struct { type LogFilter struct {

5
models/task.go

@ -72,6 +72,11 @@ type TaskLink struct {
ProjectID string `json:"projectId" db:"project_id"` ProjectID string `json:"projectId" db:"project_id"`
} }
type TaskWithProject struct {
Task
Project *Project `json:"project,omitempty"`
}
type TaskResult struct { type TaskResult struct {
Task Task
Item *Item `json:"item"` Item *Item `json:"item"`

58
services/loader.go

@ -126,7 +126,20 @@ func (l *Loader) FindLog(ctx context.Context, id string) (*models.LogResult, err
Task: nil, Task: nil,
} }
result.Task, _ = l.DB.Tasks().Find(ctx, id)
task, err := l.DB.Tasks().Find(ctx, id)
if err != nil {
return nil, err
}
project, err := l.DB.Projects().Find(ctx, id)
if err != nil {
return nil, err
}
result.Task = &models.TaskWithProject{
Task: *task,
Project: project,
}
result.Item, _ = l.DB.Items().Find(ctx, log.ItemID) result.Item, _ = l.DB.Items().Find(ctx, log.ItemID)
if log.SecondaryItemID != nil { if log.SecondaryItemID != nil {
result.SecondaryItem, _ = l.DB.Items().Find(ctx, *log.SecondaryItemID) result.SecondaryItem, _ = l.DB.Items().Find(ctx, *log.SecondaryItemID)
@ -144,6 +157,7 @@ func (l *Loader) ListLogs(ctx context.Context, filter models.LogFilter) ([]*mode
taskIDs := stringset.New() taskIDs := stringset.New()
itemIDs := stringset.New() itemIDs := stringset.New()
projectIDs := stringset.New()
for _, log := range logs { for _, log := range logs {
taskIDs.Add(log.TaskID) taskIDs.Add(log.TaskID)
itemIDs.Add(log.ItemID) itemIDs.Add(log.ItemID)
@ -158,6 +172,9 @@ func (l *Loader) ListLogs(ctx context.Context, filter models.LogFilter) ([]*mode
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, task := range tasks {
projectIDs.Add(task.ProjectID)
}
items, err := l.DB.Items().List(ctx, models.ItemFilter{ items, err := l.DB.Items().List(ctx, models.ItemFilter{
UserID: auth.UserID(ctx), UserID: auth.UserID(ctx),
IDs: itemIDs.Strings(), IDs: itemIDs.Strings(),
@ -165,6 +182,13 @@ func (l *Loader) ListLogs(ctx context.Context, filter models.LogFilter) ([]*mode
if err != nil { if err != nil {
return nil, err return nil, err
} }
projects, err := l.DB.Projects().List(ctx, models.ProjectFilter{
UserID: auth.UserID(ctx),
IDs: projectIDs.Strings(),
})
if err != nil {
return nil, err
}
results := make([]*models.LogResult, len(logs)) results := make([]*models.LogResult, len(logs))
for i, log := range logs { for i, log := range logs {
@ -175,11 +199,20 @@ func (l *Loader) ListLogs(ctx context.Context, filter models.LogFilter) ([]*mode
for _, task := range tasks { for _, task := range tasks {
if task.ID == log.TaskID { if task.ID == log.TaskID {
results[i].Task = task
results[i].Task = &models.TaskWithProject{Task: *task}
break break
} }
} }
if results[i].Task != nil {
for _, project := range projects {
if project.ID == results[i].Task.ProjectID {
results[i].Task.Project = project
break
}
}
}
for _, item := range items { for _, item := range items {
if item.ID == log.ItemID { if item.ID == log.ItemID {
results[i].Item = item results[i].Item = item
@ -545,6 +578,15 @@ func (l *Loader) populateGoals(ctx context.Context, goal *models.Goal) (*models.
return nil, err return nil, err
} }
projectIDs := stringset.New()
for _, task := range tasks {
projectIDs.Add(task.ProjectID)
}
projects, err := l.DB.Projects().List(ctx, models.ProjectFilter{
UserID: userID,
IDs: projectIDs.Strings(),
})
// Apply logs // Apply logs
result.Logs = make([]*models.GoalResultLog, 0, len(logs)) result.Logs = make([]*models.GoalResultLog, 0, len(logs))
for _, log := range logs { for _, log := range logs {
@ -555,14 +597,22 @@ func (l *Loader) populateGoals(ctx context.Context, goal *models.Goal) (*models.
for _, task := range tasks { for _, task := range tasks {
if task.ID == log.TaskID { if task.ID == log.TaskID {
resultLog.Task = task
resultLog.Task = &models.TaskWithProject{Task: *task}
for _, project := range projects {
if project.ID == task.ProjectID {
resultLog.Task.Project = project
break
}
}
break break
} }
} }
for _, item := range result.Items { for _, item := range result.Items {
amount := log.Amount(item.ID) amount := log.Amount(item.ID)
if amount > 0 && goal.Accepts(&item.Item, resultLog.Task) {
if amount > 0 && goal.Accepts(&item.Item, &resultLog.Task.Task) {
item.CompletedAmount += amount item.CompletedAmount += amount
if goal.Unweighted { if goal.Unweighted {

7
svelte-ui/src/components/ChildEntry.svelte

@ -29,8 +29,11 @@
} }
interface EntryCommonSub { interface EntryCommonSub {
id?: string
name: string name: string
icon: IconName icon: IconName
project?: EntryCommonSub
tags?: string[]
} }
export let entry: EntryCommon = null; export let entry: EntryCommon = null;
@ -64,6 +67,10 @@
<a href={`/questlog#${actualParent.id}`}>{actualParent.name}</a> <a href={`/questlog#${actualParent.id}`}>{actualParent.name}</a>
</div> </div>
{/if} {/if}
{:else if (entry.task && entry.task.project != null)}
<div class="actual-parent">
<a href={`/questlog#${entry.task.project.id}`}>{entry.task.project.name}</a>
</div>
{/if} {/if}
<div class="name">{displayName}</div> <div class="name">{displayName}</div>
<div class="separator"></div> <div class="separator"></div>

26
svelte-ui/src/components/Composition.svelte

@ -9,11 +9,24 @@
} }
export let logs: LogResult[] = []; export let logs: LogResult[] = [];
export let unweighted: boolean = false;
export let mode: GoalCompositionMode = "item"; export let mode: GoalCompositionMode = "item";
export let ignoreZeroWeight: boolean = false; export let ignoreZeroWeight: boolean = false;
let list: CompositionItem[] = []; let list: CompositionItem[] = [];
function calculateAmount(log: LogResult, unweighted: boolean) {
let amount = 0;
if (log.itemCounted) {
amount += log.itemAmount * (unweighted ? 1 : log.item.groupWeight);
}
if (log.secondaryItemCounted) {
amount += log.secondaryItemAmount * (unweighted ? 1 : log.secondaryItem.groupWeight);
}
return amount;
}
$: { $: {
const map: {[k: string]: CompositionItem} = {} const map: {[k: string]: CompositionItem} = {}
@ -41,11 +54,22 @@
} }
} }
} }
} else if (mode === "project") {
for (const log of logs) {
const project = log.task.project;
const amount = calculateAmount(log, unweighted);
if (!map[project.id]) {
map[project.id] = {name: project.name, amount, link: `/questlog#${project.id}`};
} else {
map[project.id].amount += amount;
}
}
} else { } else {
for (const log of logs) { for (const log of logs) {
const task = log.task; const task = log.task;
const amount = log.secondaryItem ? log.secondaryItemAmount + log.itemAmount : log.itemAmount;
const amount = calculateAmount(log, unweighted);
if (!map[task.id]) { if (!map[task.id]) {
map[task.id] = {name: task.name, amount, link: `/questlog#${task.projectId}`}; map[task.id] = {name: task.name, amount, link: `/questlog#${task.projectId}`};

1
svelte-ui/src/forms/GoalForm.svelte

@ -132,6 +132,7 @@ import DateRangeSelect from "../components/DateRangeSelect.svelte";
<select name="compositionMode" bind:value={compositionMode} disabled={deletion}> <select name="compositionMode" bind:value={compositionMode} disabled={deletion}>
<option value="item" selected={"item" === compositionMode}>Item</option> <option value="item" selected={"item" === compositionMode}>Item</option>
<option value="task" selected={"task" === compositionMode}>Task</option> <option value="task" selected={"task" === compositionMode}>Task</option>
<option value="project" selected={"project" === compositionMode}>Project</option>
</select> </select>
<DateRangeSelect disabled={deletion} bind:fromValue={startTime} bind:toValue={endTime} /> <DateRangeSelect disabled={deletion} bind:fromValue={startTime} bind:toValue={endTime} />
<label for="taskFilter">Task Filter (Optional)</label> <label for="taskFilter">Task Filter (Optional)</label>

2
svelte-ui/src/models/goal.ts

@ -2,7 +2,7 @@ import type Group from "./group";
import type Item from "./item"; import type Item from "./item";
import type { LogResult } from "./log"; import type { LogResult } from "./log";
export type GoalCompositionMode = "task" | "item"
export type GoalCompositionMode = "task" | "project" | "item"
export default interface Goal { export default interface Goal {
id: string id: string

4
svelte-ui/src/models/log.ts

@ -1,5 +1,5 @@
import type Item from "./item"; import type Item from "./item";
import type Task from "./task";
import type { TaskWithProject } from "./task";
export default interface Log { export default interface Log {
id: string id: string
@ -18,7 +18,7 @@ export interface LogFilter {
} }
export interface LogResult extends Log { export interface LogResult extends Log {
task: Task
task: TaskWithProject
item: Item item: Item
secondaryItem?: Item secondaryItem?: Item
itemCounted?: boolean itemCounted?: boolean

5
svelte-ui/src/models/task.ts

@ -16,6 +16,11 @@ export default interface Task {
endTime?: string endTime?: string
statusTag?: string statusTag?: string
} }
export interface TaskWithProject extends Task {
project?: Project
}
export interface TaskResult extends Task { export interface TaskResult extends Task {
item: Item item: Item
logs: Log[] logs: Log[]

Loading…
Cancel
Save