+1
-1
| { | ||
| "name": "rustytime", | ||
| "private": false, | ||
| "version": "0.2.1", | ||
| "version": "0.2.2", | ||
| "license": "AGPL-3.0", | ||
@@ -6,0 +6,0 @@ "type": "module", |
@@ -8,3 +8,3 @@ <script lang="ts"> | ||
| import StatCard from '$lib/components/ui/StatCard.svelte'; | ||
| import { formatDuration, formatRelativeTime, creationDateFormatter } from '$lib/utils/time'; | ||
| import { formatRelativeTime, creationDateFormatter } from '$lib/utils/time'; | ||
@@ -17,3 +17,3 @@ interface Props { | ||
| createdAtFormatted: string; | ||
| createdAtRelative: string | null; | ||
| lastUpdated: string | null; | ||
| repoLabel: string | null; | ||
@@ -40,3 +40,3 @@ }; | ||
| const formattedProjects = $derived.by((): EnhancedProject[] => { | ||
| const sortedProjects = $derived.by((): Project[] => { | ||
| if (!projectsData?.projects) { | ||
@@ -46,5 +46,19 @@ return []; | ||
| return projectsData.projects.map((project) => { | ||
| return [...projectsData.projects].sort((a, b) => { | ||
| const dateA = a.updated_at ? new Date(a.updated_at).getTime() : 0; | ||
| const dateB = b.updated_at ? new Date(b.updated_at).getTime() : 0; | ||
| return dateB - dateA; | ||
| }); | ||
| }); | ||
| const formattedProjects = $derived.by((): EnhancedProject[] => { | ||
| if (!sortedProjects.length) { | ||
| return []; | ||
| } | ||
| return sortedProjects.map((project) => { | ||
| const createdDate = project.created_at ? new Date(project.created_at) : null; | ||
| const isValidDate = createdDate && !Number.isNaN(createdDate.getTime()); | ||
| const updatedDate = project.updated_at ? new Date(project.updated_at) : null; | ||
| const isCreatedAtValid = createdDate && !Number.isNaN(createdDate.getTime()); | ||
| const isUpdatedAtValid = updatedDate && !Number.isNaN(updatedDate.getTime()); | ||
@@ -54,4 +68,4 @@ return { | ||
| createdAtFormatted: | ||
| isValidDate && createdDate ? creationDateFormatter.format(createdDate) : 'Unknown', | ||
| createdAtRelative: isValidDate && createdDate ? formatRelativeTime(createdDate) : null, | ||
| isCreatedAtValid && createdDate ? creationDateFormatter.format(createdDate) : 'Unknown', | ||
| lastUpdated: isUpdatedAtValid && updatedDate ? formatRelativeTime(updatedDate) : null, | ||
| repoLabel: project.repo_url ? formatRepoLabel(project.repo_url) : null | ||
@@ -62,9 +76,8 @@ } satisfies EnhancedProject; | ||
| const totalTrackedSeconds = $derived( | ||
| formattedProjects.reduce( | ||
| (accumulator, project) => accumulator + (project.total_seconds ?? 0), | ||
| 0 | ||
| ) | ||
| ); | ||
| const totalTrackedTime = $derived(formatDuration(totalTrackedSeconds)); | ||
| const lastUpdatedProject = $derived.by<EnhancedProject | null>(() => formattedProjects[0] ?? null); | ||
| const lastUpdatedProjectLabel = $derived.by<string>(() => { | ||
| const project = formattedProjects[0]; | ||
| return project?.lastUpdated ? `Updated ${project.lastUpdated}` : 'Awaiting activity'; | ||
| }); | ||
| const projectCount = $derived(formattedProjects.length); | ||
@@ -88,9 +101,16 @@ const repoCount = $derived( | ||
| <div class="grid grid-cols-1 gap-4 mb-8 sm:grid-cols-2"> | ||
| <StatCard title="Total tracked time" value={totalTrackedTime} /> | ||
| <StatCard | ||
| title="Total projects" | ||
| value={projectCount} | ||
| subvalue="({repoCount} with repositories)" | ||
| subvalue="{repoCount} with repositories" | ||
| /> | ||
| {#if lastUpdatedProject} | ||
| <StatCard | ||
| title="Last updated project" | ||
| value={lastUpdatedProject.name ?? 'Unknown project'} | ||
| subvalue={lastUpdatedProjectLabel} | ||
| /> | ||
| {/if} | ||
| </div> | ||
@@ -135,4 +155,4 @@ | ||
| > | ||
| {#if project.createdAtRelative} | ||
| <span class="text-xs text-ctp-overlay1">{project.createdAtRelative}</span> | ||
| {#if project.lastUpdated} | ||
| <span class="text-xs text-ctp-overlay1">Last updated {project.lastUpdated}</span> | ||
| {/if} | ||
@@ -139,0 +159,0 @@ </div> |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
133478
0.52%