From a187e91c3c475bba7520c37847be5178de66b515 Mon Sep 17 00:00:00 2001 From: Gisle Aune Date: Tue, 19 Jan 2021 22:12:10 +0100 Subject: [PATCH] add task and item filters to goals. --- database/postgres/goals.go | 8 ++-- ...0210119211214_add_goal_columns_filters.sql | 13 ++++++ models/goal.go | 46 ++++++++++++++++++- services/loader.go | 26 +++++++++-- svelte-ui/src/components/Composition.svelte | 19 ++++---- svelte-ui/src/forms/GoalForm.svelte | 14 +++++- svelte-ui/src/models/goal.ts | 15 +++++- svelte-ui/src/models/log.ts | 2 + 8 files changed, 122 insertions(+), 21 deletions(-) create mode 100644 migrations/postgres/20210119211214_add_goal_columns_filters.sql 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"; + + + +
diff --git a/svelte-ui/src/models/goal.ts b/svelte-ui/src/models/goal.ts index 4d95115..73b1ccb 100644 --- a/svelte-ui/src/models/goal.ts +++ b/svelte-ui/src/models/goal.ts @@ -15,6 +15,8 @@ export default interface Goal { description: string unweighted: boolean compositionMode: GoalCompositionMode + taskFilter?: string + itemFilter?: string } export interface GoalFilter { @@ -26,10 +28,15 @@ export interface GoalFilter { export interface GoalResult extends Goal { group: Group items: GoalResultItem[] - logs: LogResult[] + logs: GoalLogResult[] completedAmount: number } +export interface GoalLogResult extends LogResult { + itemCounted: boolean + secondaryItemCounted: boolean +} + interface GoalResultItem extends Item { completedAmount: number } @@ -44,6 +51,8 @@ export interface GoalInput { description: string unweighted: boolean compositionMode: string + taskFilter?: string + itemFilter?: string } export interface GoalUpdate { @@ -56,4 +65,8 @@ export interface GoalUpdate { unweighted?: boolean compositionMode?: string clearItemId?: boolean + taskFilter?: string + clearTaskFilter: boolean + itemFilter?: string + clearItemFilter: boolean } \ No newline at end of file diff --git a/svelte-ui/src/models/log.ts b/svelte-ui/src/models/log.ts index 1dd9c6c..c326b7c 100644 --- a/svelte-ui/src/models/log.ts +++ b/svelte-ui/src/models/log.ts @@ -21,6 +21,8 @@ export interface LogResult extends Log { task: Task item: Item secondaryItem?: Item + itemCounted?: boolean + secondaryItemCounted?: boolean } export interface LogInput {