From d2341cdc52fdb1e5eff37ae85220f5220c411852 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Tue, 16 Jan 2024 16:15:10 -0600 Subject: [PATCH] I'm pretending to be liveview --- flake.lock | 8 +++---- flake.nix | 2 +- islands/TodoList.tsx | 47 ++++++++++++++++++++++++++++++++++------- models.ts | 13 ++++++++---- routes/api/todo/done.ts | 21 +++++++++++++----- routes/index.tsx | 26 +++++++++++++++++++++-- 6 files changed, 93 insertions(+), 24 deletions(-) diff --git a/flake.lock b/flake.lock index 1d18f97..115cd7d 100644 --- a/flake.lock +++ b/flake.lock @@ -2,17 +2,17 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1701718080, - "narHash": "sha256-6ovz0pG76dE0P170pmmZex1wWcQoeiomUZGggfH9XPs=", + "lastModified": 1705316053, + "narHash": "sha256-J2Ey5mPFT8gdfL2XC0JTZvKaBw/b2pnyudEXFvl+dQM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2c7f3c0fb7c08a0814627611d9d7d45ab6d75335", + "rev": "c3e128f3c0ecc1fb04aef9f72b3dcc2f6cecf370", "type": "github" }, "original": { "owner": "NixOS", + "ref": "nixos-unstable", "repo": "nixpkgs", - "rev": "2c7f3c0fb7c08a0814627611d9d7d45ab6d75335", "type": "github" } }, diff --git a/flake.nix b/flake.nix index a1a2c15..e0e76b7 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - inputs.nixpkgs.url = "github:NixOS/nixpkgs?rev=2c7f3c0fb7c08a0814627611d9d7d45ab6d75335"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; outputs = { self, nixpkgs, diff --git a/islands/TodoList.tsx b/islands/TodoList.tsx index 875e92f..3612a69 100644 --- a/islands/TodoList.tsx +++ b/islands/TodoList.tsx @@ -6,12 +6,15 @@ import { Avatar } from '@homeman/components/Avatar.tsx' export interface Props { user: UserWithTodos onNewButtonClicked: JSX.MouseEventHandler + onTodoDone: (id: string) => Promise } export function TodoList( - { onNewButtonClicked, user: { avatarUrl, assignedTodos, name, color } }: + { onTodoDone, onNewButtonClicked, user: { avatarUrl, name, color, ...user } }: Props, ) { + const doneTodos = user.assignedTodos.filter((t) => t.doneAt != null) + const inProgressTodos = user.assignedTodos.filter((t) => t.doneAt == null) const todoItem = ( { id, doneAt, className, description, hideDone }: & Pick @@ -22,26 +25,40 @@ export function TodoList( ) => (
  • - {JSON.stringify(doneAt)} {description} {(hideDone || doneAt != null) ? '' : ( )} + {(!hideDone && doneAt != null) + ? ( + + ) + : ''}
  • ) return ( @@ -61,14 +78,28 @@ export function TodoList( + New
      - {assignedTodos.length < 1 + {inProgressTodos.length < 1 ? todoItem({ + id: '', + doneAt: null, description: 'All clear! 🎉', className: 'text-center', hideDone: true, }) - : assignedTodos.map(todoItem)} + : inProgressTodos.map(todoItem)}
    + {doneTodos.length > 0 + ? ( + + +{doneTodos.length} completed todos +
    +
      + {doneTodos.map(todoItem)} +
    +
    +
    + ) + : ''} ) } diff --git a/models.ts b/models.ts index 0204955..b095e11 100644 --- a/models.ts +++ b/models.ts @@ -1,8 +1,11 @@ import { z } from 'https://deno.land/x/zod@v3.21.4/mod.ts' -import { createPentagon } from 'https://deno.land/x/pentagon@v0.1.5/mod.ts' +import { + createPentagon, + TableDefinition, +} from 'https://deno.land/x/pentagon@v0.1.5/mod.ts' // import { ulid } from 'https://deno.land/x/ulid@v0.3.0/mod.ts' -const kv = await Deno.openKv('homeman.db') +export const kv = await Deno.openKv('homeman.db') // const todos = kv.list({ prefix: ['todos'] }) // const deleteme = [] @@ -41,7 +44,7 @@ const Todo = z.object({ export const TodoModel = Todo export type Todo = z.infer -export const db = createPentagon(kv, { +export const schema: Record = { users: { schema: User, relations: { @@ -54,7 +57,9 @@ export const db = createPentagon(kv, { assignee: ['users', User, 'assigneeUserId', 'id'], }, }, -}) +} + +export const db = createPentagon(kv, schema) // const daddy: User = { // id: ulid(), diff --git a/routes/api/todo/done.ts b/routes/api/todo/done.ts index f0c200e..45df6c7 100644 --- a/routes/api/todo/done.ts +++ b/routes/api/todo/done.ts @@ -3,12 +3,23 @@ import { db, TodoModel } from '@homeman/models.ts' const Model = TodoModel.pick({ id: true }) +async function markDone(id: string) { + const todo = await db.todos.findFirst({ where: { id } }) + todo.doneAt = new Date() + return await db.todos.update({ where: { id }, data: todo }) +} + +async function markNotDone(id: string) { + return await db.todos.update({ where: { id }, data: { doneAt: null } }) +} + export const handler: Handlers = { - async POST(req, _ctx) { + async PUT(req, _ctx) { const { id } = Model.parse(await req.json()) - const todo = await db.todos.findFirst({ where: { id } }) - todo.doneAt = new Date() - const newTodo = await db.todos.update({ where: { id }, data: todo }) - return new Response(JSON.stringify(newTodo)) + return new Response(JSON.stringify(await markDone(id))) + }, + async DELETE(req, _ctx) { + const { id } = Model.parse(await req.json()) + return new Response(JSON.stringify(await markNotDone(id))) }, } diff --git a/routes/index.tsx b/routes/index.tsx index c69798b..ade88c6 100644 --- a/routes/index.tsx +++ b/routes/index.tsx @@ -1,12 +1,23 @@ import { Handlers, PageProps } from '$fresh/server.ts' -import { db, Todo, UserWithTodos } from '@homeman/models.ts' +import { db, kv, schema, Todo, UserWithTodos } from '@homeman/models.ts' import Dashboard from '@homeman/islands/Dashboard.tsx' +import { useSignal } from '@preact/signals' +import { useEffect } from 'preact/hooks' interface Data { users: Record unassignedTodos: Todo[] } +const allTableNames = Object.keys(schema).map((s) => [s]) +async function watcher() { + console.log('watching:', allTableNames) + for await (const entry of kv.watch(allTableNames)) { + console.log('entry:', entry) + } +} +watcher() + export const handler: Handlers = { async GET(_req, ctx) { const users = Object.fromEntries( @@ -22,5 +33,16 @@ export const handler: Handlers = { } export default function Home({ data }: PageProps) { - return + const rdata = useSignal(data) + useEffect(() => { + async function watcher() { + console.log('watcher watching...') + for await (const entry of kv.watch(allTableNames)) { + console.log('entry:', entry) + } + } + watcher().catch(console.error) + }, [rdata]) + console.log('Home rendered') + return }