<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="/webapp/favicon.png">
<title>
Cratery
</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<header style="position: sticky; top: 0;">
<nav class="bg-white border-gray-200 px-4 lg:px-6 py-2.5 dark:bg-gray-800">
<div class="flex flex-wrap justify-between items-center mx-auto max-w-screen-xl">
<a href="/webapp/index.html" class="flex items-center">
<picture>
<source srcset="./logo-white.svg" media="(prefers-color-scheme: dark)" />
<source srcset="./logo-black.svg" media="(prefers-color-scheme: light)" />
<img src="./logo-white.svg" class="mr-3 h-6 sm:h-9" style="min-width: 200px;" alt="Cratery Logo" />
</picture>
</a>
<div class="flex items-center lg:order-2">
<a id="link-admin" href="/webapp/admin.html" style="cursor: pointer;" class="text-gray-800 dark:text-white hover:bg-gray-50 focus:ring-4 focus:ring-gray-300 font-medium rounded-lg text-sm px-4 lg:px-5 py-2 lg:py-2.5 mr-2 dark:hover:bg-gray-700 focus:outline-none dark:focus:ring-gray-800">Admin</a>
<a id="link-account" href="/webapp/account.html" style="cursor: pointer;" class="text-gray-800 dark:text-white hover:bg-gray-50 focus:ring-4 focus:ring-gray-300 font-medium rounded-lg text-sm px-4 lg:px-5 py-2 lg:py-2.5 mr-2 dark:hover:bg-gray-700 focus:outline-none dark:focus:ring-gray-800">My Account</a>
<a onclick="doLogout()" style="cursor: pointer;" class="text-gray-800 dark:text-white hover:bg-gray-50 focus:ring-4 focus:ring-gray-300 font-medium rounded-lg text-sm px-4 lg:px-5 py-2 lg:py-2.5 mr-2 dark:hover:bg-gray-700 focus:outline-none dark:focus:ring-gray-800">Logout</a>
</div>
</div>
</nav>
</header>
<body onload="doPageLoad()" class="bg-white dark:bg-gray-800 content-center">
<section class="bg-gray-50 dark:bg-gray-900 py-4 max-w-screen-lg mx-auto">
<div class="p-6 space-y-4 md:space-y-6 sm:p-8 w-full">
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white" style="text-align: center;">
Search for crates
</h1>
<form class="space-y-4 md:space-y-6" onsubmit="onSearch(); return false;" action="">
<div>
<input type="text" name="lookup" id="lookup" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="crate name" required="" autofocus="true">
</div>
<button type="button" class="w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800" onsubmit="onSearch()" onclick="onSearch()">Search</button>
</form>
</div>
<div id="results" class="items-center justify-center px-6 py-8 mx-auto lg:py-0 flex flex-col space-y-4">
</div>
<div class="p-6 mb-4 flex flex-row flex-wrap">
<a href="/webapp/index-outdated.html" class="font-medium text-blue-600 dark:text-blue-500 hover:underline">See crates with outdated dependencies</a>
</div>
<div class="p-6 mb-4 flex flex-row flex-wrap">
<div class="w-1/2">
<div class="block mx-4 p-6 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
<span style="display: inline-block;">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
</svg>
</span>
<span id="stats-total-downloads"></span>
</h5>
<p class="font-normal text-gray-700 dark:text-gray-400">Total downloads</p>
</div>
</div>
<div class="w-1/2">
<div class="block mx-4 p-6 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
<span>📦</span>
<span id="stats-total-crates"></span>
</h5>
<p class="font-normal text-gray-700 dark:text-gray-400">Total published crates</p>
</div>
</div>
</div>
<div class="p-6 mb-4 flex flex-row flex-wrap">
<div class="w-1/3">
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white" style="text-align: center;">
New crates
</h1>
</div>
<div class="w-1/3">
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white" style="text-align: center;">
Most downloaded
</h1>
</div>
<div class="w-1/3">
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white" style="text-align: center;">
Just updated
</h1>
</div>
<div class="w-1/3 flex flex-col" id="stats-crates-newest">
</div>
<div class="w-1/3 flex flex-col" id="stats-crates-most-downloaded">
</div>
<div class="w-1/3 flex flex-col" id="stats-crates-last-updated">
</div>
</div>
</section>
</body>
<footer class="p-4 bg-white md:p-8 lg:p-10 dark:bg-gray-800">
<div class="mx-auto max-w-screen-xl text-center">
<span class="text-sm text-gray-500 sm:text-center dark:text-gray-400">Version <span id="version"></span>, Copyright © <span id="year"></span> <a href="https://cenotelie.fr/" target="_blank" class="hover:underline">Cénotélie</a>. All Rights Reserved.</span>
</div>
</footer>
<link href="/webapp/index.css" rel="stylesheet" />
<script src="/webapp/api.js"></script>
<script src="/webapp/index.js"></script>
<script>
function doPageLoad() {
onPageLoad().then((_) => {
apiGetCratesStats().then(renderStats);
});
}
function renderStats(stats) {
document.getElementById("stats-total-downloads").appendChild(document.createTextNode(stats.totalDownloads.toString()));
document.getElementById("stats-total-crates").appendChild(document.createTextNode(stats.totalCrates.toString()));
const listNewest = document.getElementById("stats-crates-newest");
const listMostDownloaded = document.getElementById("stats-crates-most-downloaded");
const listLastUpdated = document.getElementById("stats-crates-last-updated");
for (const crate of stats.cratesNewest) {
listNewest.appendChild(renderCrateLink(crate, true));
}
for (const crate of stats.cratesMostDownloaded) {
listMostDownloaded.appendChild(renderCrateLink(crate, false));
}
for (const crate of stats.cratesLastUpdated) {
listLastUpdated.appendChild(renderCrateLink(crate, true));
}
}
function renderCrateLink(crate, withVersion, hasWarning) {
const color = hasWarning ? "yellow" : "gray";
const card = document.createElement("a");
card.className = `block m-2 p-2 bg-white border border-${color}-200 rounded-lg shadow hover:bg-${color}-100 dark:bg-${color}-800 dark:border-${color}-700 dark:hover:bg-${color}-700`;
card.href = withVersion ? `/crates/${crate.package}/${crate.version}` : `/crates/${crate.package}`;
const title = document.createElement("h5");
title.className = `mb-1 text-xl font-bold tracking-tight text-${color}-900 dark:text-${color}-100`;
title.appendChild(document.createTextNode(crate.package));
card.appendChild(title);
if (withVersion) {
const sub = document.createElement("p");
sub.className = `font-normal text-${color}-700 dark:text-${color}-400`;
sub.appendChild(document.createTextNode(crate.version));
card.appendChild(sub);
}
return card;
}
function onSearch() {
const search = document.getElementById("lookup").value;
apiLookupCrates(search).then((crates) => {
if (crates === null) {
return;
}
const results = document.getElementById("results");
while (results.children.length > 0) {
results.removeChild(results.lastChild);
}
for (const crate of crates) {
results.appendChild(renderCrate(crate));
}
});
return false;
}
function renderCrate(crate) {
const div = document.createElement("div");
div.className = "w-full p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700";
const a = document.createElement("a");
a.setAttribute("href", `/crates/${crate.name}`);
const h5 = document.createElement("h3");
h5.className = "mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white";
h5.appendChild(document.createTextNode(crate.name));
a.appendChild(h5);
const p1 = document.createElement("p");
p1.className = "mb-3 font-normal text-gray-700 dark:text-gray-400"
p1.appendChild(document.createTextNode(`last version: ${crate.max_version}`));
const p2 = document.createElement("p");
p2.className = "mb-3 font-normal text-gray-700 dark:text-gray-400"
p2.appendChild(document.createTextNode(crate.description));
div.appendChild(a);
div.appendChild(p1);
div.appendChild(p2);
return div;
}
</script>
</html>