activity
This commit is contained in:
parent
6ac231ce36
commit
ed7e1349b5
38
packages/cubby/src/components/Projects.tsx
Normal file
38
packages/cubby/src/components/Projects.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
interface ProjectData {
|
||||
name: string
|
||||
mtime: Date
|
||||
status: "recent" | "active" | "inactive"
|
||||
}
|
||||
|
||||
interface ProjectsProps {
|
||||
projects: ProjectData[]
|
||||
}
|
||||
|
||||
export function Projects({ projects }: ProjectsProps) {
|
||||
const statusText = (status: "recent" | "active" | "inactive") => {
|
||||
switch (status) {
|
||||
case "recent": return "Modified in the last 2 weeks"
|
||||
case "active": return "Modified in the last month"
|
||||
case "inactive": return "Modified over a month ago"
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Projects</h1>
|
||||
<ul>
|
||||
{projects.map(project => <li key={project.name}>
|
||||
<abbr style={{ fontSize: "12px", borderBottom: "none", cursor: "default" }} title={statusText(project.status)}>
|
||||
{project.status === "recent" ? "🟢" : project.status === "active" ? "🟡" : "🔴"}
|
||||
</abbr>
|
||||
<a
|
||||
href={`/p/${project.name}`}
|
||||
title={`Last modified ${project.mtime.toLocaleString()}`}
|
||||
>
|
||||
{project.name}
|
||||
</a>
|
||||
</li>)}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
import { Hono } from "hono"
|
||||
import { serveStatic } from "hono/bun"
|
||||
import { render } from "preact-render-to-string"
|
||||
import { marked } from "marked"
|
||||
import { $ } from "bun"
|
||||
import { readdirSync } from "fs"
|
||||
import { mkdir, readdir } from 'node:fs/promises'
|
||||
import { basename, join } from 'path'
|
||||
import { Layout } from "./components/Layout"
|
||||
import { Project } from "./components/Project"
|
||||
import { Projects } from "./components/Projects"
|
||||
|
||||
const PROJECTS_DIR = ".."
|
||||
const WORKSHOP_REPO = "https://github.com/probablycorey/the-workshop"
|
||||
|
|
@ -28,7 +29,7 @@ app.use("*", async (c, next) => {
|
|||
const start = Date.now()
|
||||
await next()
|
||||
const end = Date.now()
|
||||
console.log(`${c.req.method} ${c.req.url} - ${c.res.status} (${end - start}ms)`)
|
||||
console.log(`${c.res.status} ${c.req.method} ${c.req.url} (${end - start}ms)`)
|
||||
})
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -36,8 +37,7 @@ app.use("*", async (c, next) => {
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
api.get('/projects', async c => {
|
||||
const names = await projects()
|
||||
return c.json(names)
|
||||
return c.json(await projectsWithDates())
|
||||
})
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -45,15 +45,8 @@ api.get('/projects', async c => {
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
app.get("/", async (c) => {
|
||||
const names = await projects()
|
||||
return c.html(tsx(
|
||||
<div>
|
||||
<h1>Projects</h1>
|
||||
<ul>
|
||||
{names.map(name => <li key={name}><a href={`/p/${name}`}>{name}</a></li>)}
|
||||
</ul>
|
||||
</div>
|
||||
))
|
||||
const projects = await projectsWithDates()
|
||||
return c.html(tsx(<Projects projects={projects} />))
|
||||
})
|
||||
|
||||
app.get("/p/:name", async (c) => {
|
||||
|
|
@ -140,6 +133,24 @@ async function projects(): Promise<string[]> {
|
|||
return subdirs
|
||||
}
|
||||
|
||||
async function projectsWithDates(): Promise<{ name: string, mtime: Date, status: "recent" | "active" | "inactive" }[]> {
|
||||
const names = await projects()
|
||||
const projectsWithDates = await Promise.all(names.map(async name => {
|
||||
const lastModified = await mtime(name)
|
||||
const daysSince = (Date.now() - lastModified.getTime()) / (24 * 60 * 60 * 1000)
|
||||
const status: "recent" | "active" | "inactive" = daysSince <= 14 ? "recent" : daysSince <= 30 ? "active" : "inactive"
|
||||
return { name, mtime: lastModified, status }
|
||||
}))
|
||||
const sorted = projectsWithDates.sort((a, b) => b.mtime.getTime() - a.mtime.getTime())
|
||||
return sorted
|
||||
}
|
||||
|
||||
async function mtime(project: string): Promise<Date> {
|
||||
const proc = await $`cd ${PROJECTS_DIR} && git log -1 --format=%ct -- ${project}`.quiet()
|
||||
if (proc.exitCode !== 0) return new Date(0)
|
||||
return new Date(parseInt(proc.stdout.toString().trim()) * 1000)
|
||||
}
|
||||
|
||||
function tsx(node: any) {
|
||||
return "<!DOCTYPE html>" + render(<Layout>{node}</Layout>)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user