my prefect server setup
prefect-metrics.waow.tech
python
orchestration
1import type { Card } from '$lib/types';
2
3const PALETTE = [
4 'bg-red-900/60 text-red-300 border-red-700/40',
5 'bg-orange-900/60 text-orange-300 border-orange-700/40',
6 'bg-amber-900/60 text-amber-300 border-amber-700/40',
7 'bg-emerald-900/60 text-emerald-300 border-emerald-700/40',
8 'bg-teal-900/60 text-teal-300 border-teal-700/40',
9 'bg-sky-900/60 text-sky-300 border-sky-700/40',
10 'bg-violet-900/60 text-violet-300 border-violet-700/40',
11 'bg-pink-900/60 text-pink-300 border-pink-700/40'
12];
13
14function hash(s: string): number {
15 let h = 0;
16 for (let i = 0; i < s.length; i++) {
17 h = ((h << 5) - h + s.charCodeAt(i)) | 0;
18 }
19 return Math.abs(h);
20}
21
22export function hashColor(s: string): string {
23 return PALETTE[hash(s) % PALETTE.length];
24}
25
26export function timeAgo(iso: string): string {
27 const ms = Date.now() - new Date(iso).getTime();
28 const sec = Math.floor(ms / 1000);
29 if (sec < 60) return 'just now';
30 const min = Math.floor(sec / 60);
31 if (min < 60) return `${min}m ago`;
32 const hr = Math.floor(min / 60);
33 if (hr < 24) return `${hr}h ago`;
34 const days = Math.floor(hr / 24);
35 if (days < 30) return `${days}d ago`;
36 const months = Math.floor(days / 30);
37 if (months < 12) return `${months}mo ago`;
38 return `${Math.floor(months / 12)}y ago`;
39}
40
41export interface TextSegment {
42 text?: string;
43 code?: string;
44}
45
46export function parseInlineCode(text: string): TextSegment[] {
47 const segments: TextSegment[] = [];
48 const re = /`([^`]+)`/g;
49 let last = 0;
50 let match: RegExpExecArray | null;
51 while ((match = re.exec(text)) !== null) {
52 if (match.index > last) {
53 segments.push({ text: text.slice(last, match.index) });
54 }
55 segments.push({ code: match[1] });
56 last = re.lastIndex;
57 }
58 if (last < text.length) {
59 segments.push({ text: text.slice(last) });
60 }
61 return segments;
62}
63
64export function authorUrl(card: Card): string | null {
65 const user = card.meta.user;
66 if (!user) return null;
67 switch (card.source) {
68 case 'github':
69 return `https://github.com/${user}`;
70 case 'tangled':
71 return `https://tangled.org/${user}`;
72 default:
73 return null;
74 }
75}
76
77export function originUrl(card: Card): string | null {
78 const repo = card.meta.repo;
79 if (!repo) return null;
80 switch (card.source) {
81 case 'github':
82 return `https://github.com/${repo}`;
83 case 'tangled':
84 return `https://tangled.org/zzstoatzz.io/${repo}`;
85 default:
86 return null;
87 }
88}