diff --git a/api/task.go b/api/task.go index 4a8f8db..2fc84ce 100644 --- a/api/task.go +++ b/api/task.go @@ -14,15 +14,15 @@ import ( func Task(g *gin.RouterGroup, db database.Database) { l := services.Loader{DB: db} - defaultActive := true - g.GET("/", handler("tasks", func(c *gin.Context) (interface{}, error) { filter := models.TaskFilter{} if setting := c.Query("active"); setting != "" { active := setting == "true" filter.Active = &active - } else { - filter.Active = &defaultActive + } + if setting := c.Query("expiring"); setting != "" { + expiring := setting == "true" + filter.Expiring = &expiring } return l.ListTasks(c, filter) diff --git a/database/postgres/tasks.go b/database/postgres/tasks.go index 320da66..47a8363 100644 --- a/database/postgres/tasks.go +++ b/database/postgres/tasks.go @@ -33,6 +33,13 @@ func (r *taskRepository) List(ctx context.Context, filter models.TaskFilter) ([] if filter.Active != nil { sq = sq.Where(squirrel.Eq{"task.active": *filter.Active}) } + if filter.Expiring != nil { + if *filter.Expiring { + sq = sq.Where("task.end_time IS NOT NULL") + } else { + sq = sq.Where("task.end_time IS NULL") + } + } if filter.IDs != nil { sq = sq.Where(squirrel.Eq{"task.task_id": filter.IDs}) } diff --git a/models/task.go b/models/task.go index 50971b2..055a8cc 100644 --- a/models/task.go +++ b/models/task.go @@ -60,6 +60,7 @@ type TaskResult struct { type TaskFilter struct { UserID string Active *bool + Expiring *bool IDs []string ItemIDs []string ProjectIDs []string diff --git a/svelte-ui/src/clients/stufflog.ts b/svelte-ui/src/clients/stufflog.ts index 556e35c..bdd96c5 100644 --- a/svelte-ui/src/clients/stufflog.ts +++ b/svelte-ui/src/clients/stufflog.ts @@ -1,7 +1,7 @@ import { getJwt } from "./amplify"; import type { GoalFilter, GoalInput, GoalResult, GoalUpdate } from "../models/goal"; import type { ProjectFilter, ProjectInput, ProjectResult, ProjectUpdate } from "../models/project"; -import type { TaskInput, TaskResult, TaskUpdate } from "../models/task"; +import type { TaskFilter, TaskInput, TaskResult, TaskUpdate } from "../models/task"; import type { LogFilter, LogInput, LogResult, LogUpdate } from "../models/log"; import type { GroupInput, GroupResult, GroupUpdate } from "../models/group"; import type { ItemInput, ItemResult, ItemUpdate } from "../models/item"; @@ -134,8 +134,16 @@ export class StufflogClient { return data.task; } - async listTasks(active?: boolean): Promise { - let query = (active != null) ? `?active=${active}` : ""; + async listTasks({active, expiring}: TaskFilter): Promise { + let queries = []; + if (active != null) { + queries.push(`active=${active}`); + } + if (expiring != null) { + queries.push(`expiring=${expiring}`); + } + + const query = queries.length > 0 ? `?${queries.join("&")}` : ""; const data = await this.fetch("GET", `/api/task/${query}`); return data.tasks; diff --git a/svelte-ui/src/components/ProjectEntry.svelte b/svelte-ui/src/components/ProjectEntry.svelte index a767714..e9c8af5 100644 --- a/svelte-ui/src/components/ProjectEntry.svelte +++ b/svelte-ui/src/components/ProjectEntry.svelte @@ -1,5 +1,6 @@ @@ -47,7 +47,9 @@ {/if}
{#each project.tasks as task (task.id)} - + {#if !hideInactive || task.active} + + {/if} {/each}
diff --git a/svelte-ui/src/models/group.ts b/svelte-ui/src/models/group.ts index ced9fca..b5b9b36 100644 --- a/svelte-ui/src/models/group.ts +++ b/svelte-ui/src/models/group.ts @@ -1,9 +1,10 @@ +import type { IconName } from "../external/icons"; import type Item from "./item"; export default interface Group { id: string name: string - icon: string + icon: IconName description: string } diff --git a/svelte-ui/src/models/item.ts b/svelte-ui/src/models/item.ts index 90b7d1a..e874e62 100644 --- a/svelte-ui/src/models/item.ts +++ b/svelte-ui/src/models/item.ts @@ -1,10 +1,11 @@ +import type { IconName } from "../external/icons"; import type Group from "./group"; export default interface Item { id: string groupId: string groupWeight: number - icon: string + icon: IconName name: string description: string } diff --git a/svelte-ui/src/models/project.ts b/svelte-ui/src/models/project.ts index 7f0ad6e..08c3300 100644 --- a/svelte-ui/src/models/project.ts +++ b/svelte-ui/src/models/project.ts @@ -1,10 +1,11 @@ +import type { IconName } from "../external/icons"; import type { TaskResult } from "./task"; export default interface Project { id: string name: string description: string - icon: string + icon: IconName active: boolean createdTime: string endTime?: string @@ -22,7 +23,7 @@ export interface ProjectFilter { export interface ProjectInput { name: string description: string - icon: string + icon: IconName active: boolean endTime?: string | Date } diff --git a/svelte-ui/src/models/task.ts b/svelte-ui/src/models/task.ts index 3207c8c..b6aebc9 100644 --- a/svelte-ui/src/models/task.ts +++ b/svelte-ui/src/models/task.ts @@ -1,3 +1,4 @@ +import type { IconName } from "../external/icons"; import type Item from "./item"; import type Log from "./log"; @@ -8,18 +9,22 @@ export default interface Task { itemAmount: number name: string description: string - icon: string + icon: IconName active: boolean createdTime: string endTime?: string } - export interface TaskResult extends Task { item: Item logs: Log[] completedAmount: number } +export interface TaskFilter { + active?: boolean + expiring?: boolean +} + export interface TaskInput { itemId: string projectId: string diff --git a/svelte-ui/src/pages/FrontPage.svelte b/svelte-ui/src/pages/FrontPage.svelte index ef74cb2..f00b46f 100644 --- a/svelte-ui/src/pages/FrontPage.svelte +++ b/svelte-ui/src/pages/FrontPage.svelte @@ -1,9 +1,13 @@ -
@@ -41,9 +69,12 @@

Upcoming Deadlines

{/if} {#each $fpProjectStore.projects as project (project.id)} - + {/each} - {#if !$fpProjectStore.loading && $fpProjectStore.projects.length === 0} + {#if fakeProject.tasks.length > 0} + + {/if} + {#if fakeProject.tasks.length === 0 && !$fpProjectStore.loading && $fpProjectStore.projects.length === 0} {/if}
diff --git a/svelte-ui/src/pages/ProjectPage.svelte b/svelte-ui/src/pages/ProjectPage.svelte index 878cb7f..5db81fd 100644 --- a/svelte-ui/src/pages/ProjectPage.svelte +++ b/svelte-ui/src/pages/ProjectPage.svelte @@ -28,10 +28,10 @@
- +
{#each $projectStore.projects as project (project.id)} - + {/each} Add Project
diff --git a/svelte-ui/src/stores/project.ts b/svelte-ui/src/stores/project.ts index 62df32d..bcd72ca 100644 --- a/svelte-ui/src/stores/project.ts +++ b/svelte-ui/src/stores/project.ts @@ -25,7 +25,6 @@ function createProjectStore() { }, async load(filter: ProjectFilter) { - console.log(filter); update(v => ({...v, loading: true, stale: false, filter})); const projects = await stuffLogClient.listProjects(filter); update(v => ({...v, loading: false, projects: projects.reverse()})); diff --git a/svelte-ui/src/stores/tasks.ts b/svelte-ui/src/stores/tasks.ts new file mode 100644 index 0000000..c0152c2 --- /dev/null +++ b/svelte-ui/src/stores/tasks.ts @@ -0,0 +1,38 @@ +import { writable } from "svelte/store"; +import stuffLogClient from "../clients/stufflog"; +import type { TaskFilter, TaskResult } from "../models/task"; + +interface TaskStoreData { + loading: boolean + stale: boolean + filter: TaskFilter + tasks: TaskResult[] +} + +function createTaskStore() { + const {update, subscribe} = writable({ + loading: false, + stale: true, + filter: {}, + tasks: [], + }); + + return { + subscribe, + + markStale() { + update(v => ({...v, stale: true})); + }, + + async load(filter: TaskFilter) { + update(v => ({...v, loading: true, stale: false, filter})); + const tasks = await stuffLogClient.listTasks(filter); + update(v => ({...v, loading: false, tasks: [...tasks]})); + }, + } +} + +const taskStore = createTaskStore(); + +export default taskStore; +export const fpTaskStore = createTaskStore(); \ No newline at end of file