diff --git a/database/postgres/goals.go b/database/postgres/goals.go
index 845fe66..4e890a6 100644
--- a/database/postgres/goals.go
+++ b/database/postgres/goals.go
@@ -74,10 +74,10 @@ func (r *goalRepository) Insert(ctx context.Context, goal models.Goal) error {
_, err := r.db.NamedExecContext(ctx, `
INSERT INTO goal (
goal_id, user_id, group_id, amount, start_time, end_time, name, description,
- composition_mode, unweighted, item_id
+ composition_mode, unweighted, item_id, task_filter, item_filter
) VALUES (
:goal_id, :user_id, :group_id, :amount, :start_time, :end_time, :name, :description,
- :composition_mode, :unweighted, :item_id
+ :composition_mode, :unweighted, :item_id, :task_filter, :item_filter
)
`, &goal)
if err != nil {
@@ -97,7 +97,9 @@ func (r *goalRepository) Update(ctx context.Context, goal models.Goal) error {
description=:description,
composition_mode=:composition_mode,
unweighted=:unweighted,
- item_id=:item_id
+ item_id=:item_id,
+ task_filter=:task_filter,
+ item_filter=:item_filter
WHERE goal_id=:goal_id
`, &goal)
if err != nil {
diff --git a/migrations/postgres/20210119211214_add_goal_columns_filters.sql b/migrations/postgres/20210119211214_add_goal_columns_filters.sql
new file mode 100644
index 0000000..7f0c558
--- /dev/null
+++ b/migrations/postgres/20210119211214_add_goal_columns_filters.sql
@@ -0,0 +1,13 @@
+-- +goose Up
+-- +goose StatementBegin
+ALTER TABLE goal
+ ADD COLUMN task_filter TEXT DEFAULT NULL,
+ ADD COLUMN item_filter TEXT DEFAULT NULL;
+-- +goose StatementEnd
+
+-- +goose Down
+-- +goose StatementBegin
+ALTER TABLE goal
+ DROP COLUMN task_filter,
+ DROP COLUMN item_filter;
+-- +goose StatementEnd
diff --git a/models/goal.go b/models/goal.go
index 683d532..7393ce2 100644
--- a/models/goal.go
+++ b/models/goal.go
@@ -2,6 +2,7 @@ package models
import (
"context"
+ "strings"
"time"
)
@@ -17,6 +18,25 @@ type Goal struct {
Name string `json:"name" db:"name"`
Description string `json:"description" db:"description"`
CompositionMode string `json:"compositionMode" db:"composition_mode"`
+ TaskFilter *string `json:"taskFilter" db:"task_filter"`
+ ItemFilter *string `json:"itemFilter" db:"item_filter"`
+}
+
+func (goal *Goal) Accepts(item *Item, task *Task) bool {
+ if item.GroupID != goal.GroupID {
+ return false
+ }
+ if goal.ItemID != nil && item.ID != *goal.ItemID {
+ return false
+ }
+ if goal.TaskFilter != nil && !strings.Contains(strings.ToLower(task.Name), *goal.TaskFilter) {
+ return false
+ }
+ if goal.ItemFilter != nil && !strings.Contains(strings.ToLower(item.Name), *goal.ItemFilter) {
+ return false
+ }
+
+ return true
}
func (goal *Goal) Update(update GoalUpdate) {
@@ -47,6 +67,18 @@ func (goal *Goal) Update(update GoalUpdate) {
if update.ClearItemID {
goal.ItemID = nil
}
+ if update.TaskFilter != nil {
+ goal.TaskFilter = update.TaskFilter
+ }
+ if update.ClearTaskFilter {
+ goal.TaskFilter = nil
+ }
+ if update.ItemFilter != nil {
+ goal.ItemFilter = update.ItemFilter
+ }
+ if update.ClearItemFilter {
+ goal.ItemFilter = nil
+ }
}
type GoalUpdate struct {
@@ -56,19 +88,29 @@ type GoalUpdate struct {
Name *string `json:"name"`
Description *string `json:"description"`
ItemID *string `json:"itemId"`
+ ClearItemID bool `json:"clearItemID"`
Unweighted *bool `json:"unweighted"`
CompositionMode *string `json:"compositionMode"`
- ClearItemID bool `json:"clearItemID"`
+ TaskFilter *string `json:"taskFilter"`
+ ClearTaskFilter bool `json:"clearTaskFilter"`
+ ItemFilter *string `json:"itemFilter"`
+ ClearItemFilter bool `json:"clearItemFilter"`
}
type GoalResult struct {
Goal
Group *Group `json:"group"`
Items []*GoalResultItem `json:"items"`
- Logs []*LogResult `json:"logs"`
+ Logs []*GoalResultLog `json:"logs"`
CompletedAmount int `json:"completedAmount"`
}
+type GoalResultLog struct {
+ LogResult
+ ItemCounted bool `json:"itemCounted"`
+ SecondaryItemCounted bool `json:"secondaryItemCounted"`
+}
+
type GoalResultItem struct {
Item
CompletedAmount int `json:"completedAmount"`
diff --git a/services/loader.go b/services/loader.go
index 802e878..d1e9d7f 100644
--- a/services/loader.go
+++ b/services/loader.go
@@ -535,11 +535,12 @@ func (l *Loader) populateGoals(ctx context.Context, goal *models.Goal) (*models.
}
// Apply logs
- result.Logs = make([]*models.LogResult, 0, len(logs))
+ result.Logs = make([]*models.GoalResultLog, 0, len(logs))
for _, log := range logs {
- resultLog := &models.LogResult{
- Log: *log,
+ resultLog := &models.GoalResultLog{
+ LogResult: models.LogResult{Log: *log},
}
+ contributes := false
for _, task := range tasks {
if task.ID == log.TaskID {
@@ -550,7 +551,7 @@ func (l *Loader) populateGoals(ctx context.Context, goal *models.Goal) (*models.
for _, item := range result.Items {
amount := log.Amount(item.ID)
- if amount > 0 && (goal.ItemID == nil || *goal.ItemID == item.ID) {
+ if amount > 0 && goal.Accepts(&item.Item, resultLog.Task) {
item.CompletedAmount += amount
if goal.Unweighted {
@@ -558,21 +559,36 @@ func (l *Loader) populateGoals(ctx context.Context, goal *models.Goal) (*models.
} else {
result.CompletedAmount += amount * item.GroupWeight
}
+
+ contributes = true
+ } else {
+ amount = 0
}
if item.ID == log.ItemID {
resultLog.Item = &item.Item
+
+ if amount > 0 {
+ resultLog.ItemCounted = true
+ }
+
if log.SecondaryItemID == nil {
break
}
}
if log.SecondaryItemID != nil && item.ID == *log.SecondaryItemID {
+ if amount > 0 {
+ resultLog.SecondaryItemCounted = true
+ }
+
resultLog.SecondaryItem = &item.Item
}
}
- result.Logs = append(result.Logs, resultLog)
+ if contributes {
+ result.Logs = append(result.Logs, resultLog)
+ }
}
}
diff --git a/svelte-ui/src/components/Composition.svelte b/svelte-ui/src/components/Composition.svelte
index 0c38e9d..06e62b8 100644
--- a/svelte-ui/src/components/Composition.svelte
+++ b/svelte-ui/src/components/Composition.svelte
@@ -1,7 +1,6 @@
diff --git a/svelte-ui/src/forms/GoalForm.svelte b/svelte-ui/src/forms/GoalForm.svelte
index d21ce56..6001960 100644
--- a/svelte-ui/src/forms/GoalForm.svelte
+++ b/svelte-ui/src/forms/GoalForm.svelte
@@ -49,7 +49,9 @@ import type { GroupResult } from "../models/group";
let compositionMode = goal.compositionMode;
let startTime = formatFormTime(goal.startTime);
let endTime = formatFormTime(goal.endTime);
-
+ let taskFilter = goal.taskFilter || "";
+ let itemFilter = goal.itemFilter || "";
+
let error = null;
let loading = false;
let selectedGroup: GroupResult = null;
@@ -62,6 +64,8 @@ import type { GroupResult } from "../models/group";
startTime: new Date(startTime),
endTime: new Date(endTime),
itemId: itemId || null,
+ taskFilter: taskFilter.toLowerCase() || null,
+ itemFilter: itemFilter.toLowerCase() || null,
groupId, name, description, amount, unweighted, compositionMode
}).then(() => {
markStale("goal");
@@ -86,6 +90,10 @@ import type { GroupResult } from "../models/group";
endTime: new Date(endTime),
itemId: itemId || null,
clearItemId: itemId === "",
+ taskFilter: taskFilter.toLowerCase() || null,
+ clearTaskFilter: taskFilter === "",
+ itemFilter: itemFilter.toLowerCase() || null,
+ clearItemFilter: itemFilter === "",
name, description, amount, compositionMode, unweighted,
}).then(() => {
markStale("goal");
@@ -128,6 +136,10 @@ import type { GroupResult } from "../models/group";
+
+
+
+