Adds components for showing Docker stats and markdown docs

This commit is contained in:
Alicia Sykes
2023-04-22 21:06:32 +01:00
parent 112a8b62b3
commit eb3e5e5ade
2 changed files with 162 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
<script lang="ts">
import type { DockerHubResponse } from '$src/Types';
export let info: DockerHubResponse;
const formatBigNumber = (num: number): string => {
if (!num) return '';
const units = ['k', 'M', 'B'];
let unitIndex = 0;
let value = num;
while (value >= 1000 && unitIndex < units.length) {
value /= 1000;
unitIndex++;
}
const decimalPlaces = num < 10000 || (num >= 100000 && num < 1000000) ? 0 : 1;
return num < 1000 ? num.toString() : value.toFixed(decimalPlaces) + units[unitIndex - 1];
};
const formatDate = (dateTime: string): string => {
if (!dateTime) return '';
const date = new Date(dateTime);
return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'short',
day: '2-digit',
}).format(date);
};
const timeAgo = (dateTime: string): string => {
if (!dateTime) return '';
const elapsed = Date.now() - new Date(dateTime).getTime();
const msPer = [60000, 3600000, 86400000, 2592000000, 31536000000];
const units = ['minute', 'hour', 'day', 'month', 'year'];
for (let i = 0; i < msPer.length; i++) {
if (elapsed < msPer[i]) {
const value = Math.floor(elapsed / (i > 0 ? msPer[i - 1] : 1));
return value === 0 ? 'just now' : `${value} ${units[i - 1] || 'minute'}${value > 1 ? 's' : ''} ago`;
}
}
return `${Math.floor(elapsed / msPer[4])} years ago`;
};
const makeRenderData = () => {
const results = [
{ label: 'Pulls', value: formatBigNumber(info.pull_count) },
{ label: 'Stars', value: formatBigNumber(info.star_count) },
{ label: 'User', value: info.hub_user },
{ label: 'Created', value: formatDate(info.date_registered) },
{ label: 'Updated', value: timeAgo(info.last_updated) },
{ label: 'Status', value: info.status_description }
];
return results;
};
</script>
<div class="stats">
{#each makeRenderData() as stat}
<div class="row">
<span class="lbl">{stat.label}: </span>
<span>{stat.value}</span>
</div>
{/each}
</div>
<style lang="scss">
.stats {
background: var(--card-2);
padding: 1rem;
border-radius: 6px;
.lbl {
font-weight: 500;
margin-right: 0.5rem;
}
}
</style>

85
src/lib/MdContent.svelte Normal file
View File

@@ -0,0 +1,85 @@
<script lang="ts">
import { slide } from 'svelte/transition';
import snarkdown from 'snarkdown';
export let content: string;
export let multiContent: { name: string, content: string, description: string, visible: false }[];
let showDocs = false;
const toggleDocs = () => {
showDocs = !showDocs;
};
</script>
<section class="docker-docs">
<h2>Container Documentation</h2>
{#if content}
<button on:click={toggleDocs}>{ showDocs ? 'Hide' : 'Expand' } Content</button>
{#if showDocs}
<p transition:slide>{@html snarkdown(content)}</p>
{/if}
{:else if multiContent && multiContent.length > 0}
{#each multiContent as { name, description, content, visible }}
<h3>{name} Documentation</h3>
<p class="desc">{description || ''}</p>
<button on:click={() => visible = !visible}>{ visible ? 'Hide' : 'Expand' } {name}</button>
{#if visible}
<p transition:slide>{@html snarkdown(content)}</p>
{/if}
{/each}
{/if}
</section>
<style lang="scss">
.docker-docs {
background: var(--card);
padding: 1rem;
border-radius: 6px;
margin: 1rem auto;
max-width: 1000px;
transition: all 0.2s ease-in-out;
button {
background: var(--background);
padding: 0.25rem 0.5rem;
border-radius: 6px;
border: none;
color: var(--foreground);
font-family: Kanit;
font-size: 1.2rem;
cursor: pointer;
transition: all 0.2s ease-in-out;
&:hover {
background: var(--gradient);
transform: scale(1.1) rotate(-1deg);
}
}
h2 {
font-size: 2rem;
margin: 0;
}
h3 {
margin: 0.5rem 0;
text-transform: capitalize;
}
.desc {
opacity: 0.7;
margin: 0.5rem 0;
font-style: italic;
}
:global(img) {
max-width: 100%;
}
:global(a) {
color: var(--accent);
text-decoration: none;
}
:global(pre) {
background: var(--card-2);
padding: 1rem;
border-radius: 6px;
overflow: auto;
}
}
</style>