offscale, extracted from the platform into its own repository
The tailnet plugin — machines, users, pre-auth keys, access policy and device invites. Moved out of officerdev/platform, where it had lived in plugins/ since the plugin system was built. Until now this code existed in exactly one place: the platform repository. That made "gitignore the plugins directory" impossible to do safely, because untracking it would have left 49 files on a single disk with no remote. This repository is what makes that move safe. Same extraction as plugins/music before it: source only, no history. The platform's history still holds every commit that shaped this, and the SHAs cited across the codebase keep resolving — replaying it here would have created a second, divergent account of the same work. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
// Date formatting for the Headscale views. The sidecar already turned protobuf's zero timestamp into null,
|
||||
// so null genuinely means "never" here and every helper says so rather than printing a fake date.
|
||||
|
||||
export function timeAgo(iso: string | null): string {
|
||||
if (!iso) return 'never';
|
||||
const seconds = Math.round((Date.now() - new Date(iso).getTime()) / 1000);
|
||||
if (!Number.isFinite(seconds)) return 'unknown';
|
||||
if (seconds < 0) return 'just now';
|
||||
if (seconds < 60) return 'just now';
|
||||
const minutes = Math.round(seconds / 60);
|
||||
if (minutes < 60) return `${minutes}m ago`;
|
||||
const hours = Math.round(minutes / 60);
|
||||
if (hours < 24) return `${hours}h ago`;
|
||||
const days = Math.round(hours / 24);
|
||||
if (days < 365) return `${days}d ago`;
|
||||
return `${Math.round(days / 365)}y ago`;
|
||||
}
|
||||
|
||||
/** "in 3d" / "5h ago" — signed, for expiry dates that may be either side of now. */
|
||||
export function timeUntil(iso: string | null): string {
|
||||
if (!iso) return 'never';
|
||||
const seconds = Math.round((new Date(iso).getTime() - Date.now()) / 1000);
|
||||
if (!Number.isFinite(seconds)) return 'unknown';
|
||||
if (seconds < 0) return timeAgo(iso);
|
||||
const minutes = Math.round(seconds / 60);
|
||||
if (minutes < 60) return `in ${Math.max(1, minutes)}m`;
|
||||
const hours = Math.round(minutes / 60);
|
||||
if (hours < 24) return `in ${hours}h`;
|
||||
return `in ${Math.round(hours / 24)}d`;
|
||||
}
|
||||
|
||||
export function fullDate(iso: string | null): string {
|
||||
if (!iso) return 'never';
|
||||
return new Date(iso).toLocaleString();
|
||||
}
|
||||
Reference in New Issue
Block a user