add project to logs, project composition mode to goals and fix unweighted counts for other composition modes.
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
+1
-4
@@ -85,10 +85,7 @@ func Log(g *gin.RouterGroup, db database.Database) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &models.LogResult{
|
return l.FindLog(c.Request.Context(), log.ID)
|
||||||
Log: log,
|
|
||||||
Task: &task.Task,
|
|
||||||
}, nil
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
g.PUT("/:id", handler("log", func(c *gin.Context) (interface{}, error) {
|
g.PUT("/:id", handler("log", func(c *gin.Context) (interface{}, error) {
|
||||||
|
|||||||
+3
-3
@@ -62,9 +62,9 @@ type LogUpdate struct {
|
|||||||
|
|
||||||
type LogResult struct {
|
type LogResult struct {
|
||||||
Log
|
Log
|
||||||
Task *Task `json:"task"`
|
Task *TaskWithProject `json:"task"`
|
||||||
Item *Item `json:"item"`
|
Item *Item `json:"item"`
|
||||||
SecondaryItem *Item `json:"secondaryItem"`
|
SecondaryItem *Item `json:"secondaryItem"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LogFilter struct {
|
type LogFilter struct {
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
|||||||
+54
-4
@@ -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 {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}`};
|
||||||
|
|||||||
@@ -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,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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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[]
|
||||||
|
|||||||
Reference in New Issue
Block a user