mirror of
https://github.com/sergi0g/cup.git
synced 2025-11-12 23:23:48 -05:00
Redesign UI a bit
This commit is contained in:
1
web/.prettierignore
Normal file
1
web/.prettierignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
index.html
|
||||||
178
web/index.html
178
web/index.html
@@ -34,12 +34,12 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="root">
|
<div id="root">
|
||||||
<div
|
<div
|
||||||
class="flex justify-center min-h-screen bg-{{ theme }}-50 dark:bg-{{ theme }}-950"
|
class="flex justify-center min-h-screen bg-white dark:bg-{{ theme }}-900"
|
||||||
>
|
>
|
||||||
<div class="mx-auto h-full w-full max-w-[80rem] px-4 sm:px-6 lg:px-8">
|
<div class="mx-auto h-full w-full max-w-[80rem] px-4 sm:px-6 lg:px-8">
|
||||||
<div class="mx-auto my-8 h-full max-w-[48rem] flex-col">
|
<div class="mx-auto my-8 h-full max-w-[48rem] flex-col">
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<h1 class="text-5xl font-bold lg:text-6xl dark:text-white">Cup</h1>
|
<h1 class="text-5xl font-bold lg:text-6xl dark:text-white tracking-tight">Cup</h1>
|
||||||
<svg
|
<svg
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="Layer_2"
|
id="Layer_2"
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="shadow-sm bg-white dark:bg-{{ theme }}-900 rounded-md my-8"
|
class="border shadow-sm border-{{theme}}-200 dark:border-{{theme}}-800 my-8 rounded-md"
|
||||||
>
|
>
|
||||||
<dl
|
<dl
|
||||||
class="grid grid-cols-2 gap-1 overflow-hidden *:relative lg:grid-cols-4"
|
class="grid grid-cols-2 gap-1 overflow-hidden *:relative lg:grid-cols-4"
|
||||||
@@ -118,9 +118,9 @@
|
|||||||
class="flex h-full flex-col justify-between gap-x-4 gap-y-2 px-6 py-4 align-baseline lg:min-h-32"
|
class="flex h-full flex-col justify-between gap-x-4 gap-y-2 px-6 py-4 align-baseline lg:min-h-32"
|
||||||
>
|
>
|
||||||
<dt
|
<dt
|
||||||
class="text-{{ theme }}-500 dark:text-{{ theme }}-400 leading-6 font-medium"
|
class="text-{{ theme }}-500 dark:text-{{ theme }}-400 text-sm font-semibold uppercase leading-6"
|
||||||
>
|
>
|
||||||
{{ metric.name | replace: '_', ' ' | capitalize }}
|
{{ metric.name | replace: '_', ' ' }}
|
||||||
</dt>
|
</dt>
|
||||||
<div class="flex items-center justify-between gap-1">
|
<div class="flex items-center justify-between gap-1">
|
||||||
<dd
|
<dd
|
||||||
@@ -135,13 +135,14 @@
|
|||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
class="size-6 shrink-0 text-black dark:text-white"
|
class="size-6 shrink-0 text-black dark:text-white"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/>
|
||||||
<path
|
|
||||||
d="M12 4c4.29 0 7.863 2.429 10.665 7.154l.22 .379l.045 .1l.03 .083l.014 .055l.014 .082l.011 .1v.11l-.014 .111a.992 .992 0 0 1 -.026 .11l-.039 .108l-.036 .075l-.016 .03c-2.764 4.836 -6.3 7.38 -10.555 7.499l-.313 .004c-4.396 0 -8.037 -2.549 -10.868 -7.504a1 1 0 0 1 0 -.992c2.831 -4.955 6.472 -7.504 10.868 -7.504zm0 5a3 3 0 1 0 0 6a3 3 0 0 0 0 -6z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{% when 'up_to_date' %}
|
{% when 'up_to_date' %}
|
||||||
<svg
|
<svg
|
||||||
@@ -149,13 +150,14 @@
|
|||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
class="size-6 shrink-0 text-green-500"
|
class="size-6 shrink-0 text-green-500"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>
|
||||||
<path
|
|
||||||
d="M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{% when 'updates_available' %}
|
{% when 'updates_available' %}
|
||||||
{% assign max_metric = '' %}
|
{% assign max_metric = '' %}
|
||||||
@@ -181,13 +183,14 @@
|
|||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
class="size-6 shrink-0 {{ color }}"
|
class="size-6 shrink-0 {{ color }}"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<circle cx="12" cy="12" r="10"/><path d="m16 12-4-4-4 4"/><path d="M12 16V8"/>
|
||||||
<path
|
|
||||||
d="M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-4.98 3.66l-.163 .01l-.086 .016l-.142 .045l-.113 .054l-.07 .043l-.095 .071l-.058 .054l-4 4l-.083 .094a1 1 0 0 0 1.497 1.32l2.293 -2.293v5.586l.007 .117a1 1 0 0 0 1.993 -.117v-5.585l2.293 2.292l.094 .083a1 1 0 0 0 1.32 -1.497l-4 -4l-.082 -.073l-.089 -.064l-.113 -.062l-.081 -.034l-.113 -.034l-.112 -.02l-.098 -.006z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{% when 'unknown' %}
|
{% when 'unknown' %}
|
||||||
<svg
|
<svg
|
||||||
@@ -195,13 +198,14 @@
|
|||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
class="size-6 text-{{ theme }}-500 shrink-0"
|
class="size-6 text-{{ theme }}-500 shrink-0"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/>
|
||||||
<path
|
|
||||||
d="M12 2c5.523 0 10 4.477 10 10a10 10 0 0 1 -19.995 .324l-.005 -.324l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm0 13a1 1 0 0 0 -.993 .883l-.007 .117l.007 .127a1 1 0 0 0 1.986 0l.007 -.117l-.007 -.127a1 1 0 0 0 -.993 -.883zm1.368 -6.673a2.98 2.98 0 0 0 -3.631 .728a1 1 0 0 0 1.44 1.383l.171 -.18a.98 .98 0 0 1 1.11 -.15a1 1 0 0 1 -.34 1.886l-.232 .012a1 1 0 0 0 .111 1.994a3 3 0 0 0 1.371 -5.673z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{% endcase %}
|
{% endcase %}
|
||||||
</div>
|
</div>
|
||||||
@@ -212,20 +216,24 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="shadow-sm bg-white dark:bg-{{ theme }}-900 rounded-md my-8"
|
class="border shadow-sm border-{{theme}}-200 dark:border-{{theme}}-800 my-8 rounded-md"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex justify-between items-center px-6 py-4 text-{{ theme }}-500"
|
class="flex justify-between items-center px-6 py-4"
|
||||||
>
|
>
|
||||||
<h3>Last checked: {{ last_updated }}</h3>
|
<h3 class="text-{{theme}}-600 dark:text-{{theme}}-500">Last checked: {{ last_updated }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{% for server in server_ids %}
|
{% for server in server_ids %}
|
||||||
{% if server == '' %}
|
{% if server == '' %}
|
||||||
<li class="mb-8 last:mb-0">
|
<li class="mb-8 last:mb-0">
|
||||||
<ul class="dark:divide-{{theme}}-800 divide-y dark:text-white">
|
<ul
|
||||||
|
class="dark:divide-{{theme}}-800 divide-y dark:text-white"
|
||||||
|
>
|
||||||
{% for image in servers[server] %}
|
{% for image in servers[server] %}
|
||||||
<li class="flex items-center gap-4 break-all px-6 py-4 text-start">
|
<li
|
||||||
|
class="flex items-center gap-4 break-all px-6 py-4 text-start hover:bg-{{theme}}-100 hover:dark:bg-{{theme}}-800/50 transition-colors duration-200"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
@@ -236,31 +244,27 @@
|
|||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
class="size-6 shrink-0"
|
class="size-6 shrink-0 text-{{ theme }}-500"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="M12 22V12"/>
|
||||||
<path
|
|
||||||
d="M21 16.008v-8.018a1.98 1.98 0 0 0 -1 -1.717l-7 -4.008a2.016 2.016 0 0 0 -2 0l-7 4.008c-.619 .355 -1 1.01 -1 1.718v8.018c0 .709 .381 1.363 1 1.717l7 4.008a2.016 2.016 0 0 0 2 0l7 -4.008c.619 -.355 1 -1.01 1 -1.718z"
|
|
||||||
/>
|
|
||||||
<path d="M12 22v-10" />
|
|
||||||
<path d="M12 12l8.73 -5.04" />
|
|
||||||
<path d="M3.27 6.96l8.73 5.04" />
|
|
||||||
</svg>
|
</svg>
|
||||||
{{ image.name }}
|
<span class="font-mono">{{ image.name }}</span>
|
||||||
{% case image.status %}
|
{% case image.status %}
|
||||||
{% when 'Up to date' %}
|
{% when 'Up to
|
||||||
|
date' %}
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
class="ml-auto text-green-500"
|
class="ml-auto text-green-500"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>
|
||||||
<path
|
|
||||||
d="M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{% when 'Unknown' %}
|
{% when 'Unknown' %}
|
||||||
<svg
|
<svg
|
||||||
@@ -268,19 +272,21 @@
|
|||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
class="text-{{ theme }}-500 ml-auto"
|
class="text-{{ theme }}-500 ml-auto"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/>
|
||||||
<path
|
|
||||||
d="M12 2c5.523 0 10 4.477 10 10a10 10 0 0 1 -19.995 .324l-.005 -.324l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm0 13a1 1 0 0 0 -.993 .883l-.007 .117l.007 .127a1 1 0 0 0 1.986 0l.007 -.117l-.007 -.127a1 1 0 0 0 -.993 -.883zm1.368 -6.673a2.98 2.98 0 0 0 -3.631 .728a1 1 0 0 0 1.44 1.383l.171 -.18a.98 .98 0 0 1 1.11 -.15a1 1 0 0 1 -.34 1.886l-.232 .012a1 1 0 0 0 .111 1.994a3 3 0 0 0 1.371 -5.673z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% case image.status %}
|
{% case image.status %}
|
||||||
{% when 'Major update' %}
|
{% when 'Major update' %}
|
||||||
{% assign color = 'text-red-500' %}
|
{% assign color = 'text-red-500' %}
|
||||||
{% when 'Minor update' %}
|
{% when 'Minor
|
||||||
|
update' %}
|
||||||
{% assign color = 'text-yellow-500' %}
|
{% assign color = 'text-yellow-500' %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% assign color = 'text-blue-500' %}
|
{% assign color = 'text-blue-500' %}
|
||||||
@@ -290,13 +296,14 @@
|
|||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
class="ml-auto {{ color }}"
|
class="ml-auto {{ color }}"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<circle cx="12" cy="12" r="10"/><path d="m16 12-4-4-4 4"/><path d="M12 16V8"/>
|
||||||
<path
|
|
||||||
d="M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-4.98 3.66l-.163 .01l-.086 .016l-.142 .045l-.113 .054l-.07 .043l-.095 .071l-.058 .054l-4 4l-.083 .094a1 1 0 0 0 1.497 1.32l2.293 -2.293v5.586l.007 .117a1 1 0 0 0 1.993 -.117v-5.585l2.293 2.292l.094 .083a1 1 0 0 0 1.32 -1.497l-4 -4l-.082 -.073l-.089 -.064l-.113 -.062l-.081 -.034l-.113 -.034l-.112 -.02l-.098 -.006z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{% endcase %}
|
{% endcase %}
|
||||||
</li>
|
</li>
|
||||||
@@ -305,12 +312,18 @@
|
|||||||
</li>
|
</li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="mb-4 last:mb-0">
|
<li class="mb-4 last:mb-0">
|
||||||
<p class="my-4 text-lg font-semibold text-{{ theme }}-600 dark:text-{{ theme }}-400 px-6">
|
<p
|
||||||
|
class="my-4 text-lg font-semibold text-{{ theme }}-600 dark:text-{{ theme }}-400 px-6"
|
||||||
|
>
|
||||||
{{ server }}
|
{{ server }}
|
||||||
</p>
|
</p>
|
||||||
<ul class="dark:divide-{{ theme }}-800 divide-y dark:text-white">
|
<ul
|
||||||
|
class="dark:divide-{{ theme }}-800 divide-y dark:text-white"
|
||||||
|
>
|
||||||
{% for image in servers[server] %}
|
{% for image in servers[server] %}
|
||||||
<li class="flex items-center gap-4 break-all px-6 py-4 text-start">
|
<li
|
||||||
|
class="flex items-center gap-4 break-all px-6 py-4 text-start"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
@@ -323,29 +336,25 @@
|
|||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
class="size-6 shrink-0"
|
class="size-6 shrink-0"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="M12 22V12"/>
|
||||||
<path
|
|
||||||
d="M21 16.008v-8.018a1.98 1.98 0 0 0 -1 -1.717l-7 -4.008a2.016 2.016 0 0 0 -2 0l-7 4.008c-.619 .355 -1 1.01 -1 1.718v8.018c0 .709 .381 1.363 1 1.717l7 4.008a2.016 2.016 0 0 0 2 0l7 -4.008c.619 -.355 1 -1.01 1 -1.718z"
|
|
||||||
/>
|
|
||||||
<path d="M12 22v-10" />
|
|
||||||
<path d="M12 12l8.73 -5.04" />
|
|
||||||
<path d="M3.27 6.96l8.73 5.04" />
|
|
||||||
</svg>
|
</svg>
|
||||||
{{ image.name }}
|
{{ image.name }}
|
||||||
{% case image.status %}
|
{% case image.status %}
|
||||||
{% when 'Up to date' %}
|
{% when 'Up to
|
||||||
|
date' %}
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
class="ml-auto text-green-500"
|
class="ml-auto text-green-500"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/>
|
||||||
<path
|
|
||||||
d="M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-1.293 5.953a1 1 0 0 0 -1.32 -.083l-.094 .083l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.403 1.403l.083 .094l2 2l.094 .083a1 1 0 0 0 1.226 0l.094 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{% when 'Unknown' %}
|
{% when 'Unknown' %}
|
||||||
<svg
|
<svg
|
||||||
@@ -353,19 +362,21 @@
|
|||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
class="text-{{ theme }}-500 ml-auto"
|
class="text-{{ theme }}-500 ml-auto"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/>
|
||||||
<path
|
|
||||||
d="M12 2c5.523 0 10 4.477 10 10a10 10 0 0 1 -19.995 .324l-.005 -.324l.004 -.28c.148 -5.393 4.566 -9.72 9.996 -9.72zm0 13a1 1 0 0 0 -.993 .883l-.007 .117l.007 .127a1 1 0 0 0 1.986 0l.007 -.117l-.007 -.127a1 1 0 0 0 -.993 -.883zm1.368 -6.673a2.98 2.98 0 0 0 -3.631 .728a1 1 0 0 0 1.44 1.383l.171 -.18a.98 .98 0 0 1 1.11 -.15a1 1 0 0 1 -.34 1.886l-.232 .012a1 1 0 0 0 .111 1.994a3 3 0 0 0 1.371 -5.673z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% case image.status %}
|
{% case image.status %}
|
||||||
{% when 'Major update' %}
|
{% when 'Major update' %}
|
||||||
{% assign color = 'text-red-500' %}
|
{% assign color = 'text-red-500' %}
|
||||||
{% when 'Minor update' %}
|
{% when 'Minor
|
||||||
|
update' %}
|
||||||
{% assign color = 'text-yellow-500' %}
|
{% assign color = 'text-yellow-500' %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% assign color = 'text-blue-500' %}
|
{% assign color = 'text-blue-500' %}
|
||||||
@@ -375,13 +386,14 @@
|
|||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
fill="currentColor"
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
class="ml-auto {{ color }}"
|
class="ml-auto {{ color }}"
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<circle cx="12" cy="12" r="10"/><path d="m16 12-4-4-4 4"/><path d="M12 16V8"/>
|
||||||
<path
|
|
||||||
d="M17 3.34a10 10 0 1 1 -14.995 8.984l-.005 -.324l.005 -.324a10 10 0 0 1 14.995 -8.336zm-4.98 3.66l-.163 .01l-.086 .016l-.142 .045l-.113 .054l-.07 .043l-.095 .071l-.058 .054l-4 4l-.083 .094a1 1 0 0 0 1.497 1.32l2.293 -2.293v5.586l.007 .117a1 1 0 0 0 1.993 -.117v-5.585l2.293 2.292l.094 .083a1 1 0 0 0 1.32 -1.497l-4 -4l-.082 -.073l-.089 -.064l-.113 -.062l-.081 -.034l-.113 -.034l-.112 -.02l-.098 -.006z"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
{% endcase %}
|
{% endcase %}
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -27,18 +27,18 @@ function App() {
|
|||||||
if (!data) return <Loading onLoad={setData} />;
|
if (!data) return <Loading onLoad={setData} />;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`flex min-h-screen justify-center bg-${theme}-50 dark:bg-${theme}-950`}
|
className={`flex min-h-screen justify-center bg-white dark:bg-${theme}-900`}
|
||||||
>
|
>
|
||||||
<div className="mx-auto h-full w-full max-w-[80rem] px-4 sm:px-6 lg:px-8">
|
<div className="mx-auto h-full w-full max-w-[80rem] px-4 sm:px-6 lg:px-8">
|
||||||
<div className="mx-auto my-8 flex h-full max-w-[48rem] flex-col">
|
<div className="mx-auto my-8 flex h-full max-w-[48rem] flex-col">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<h1 className="text-5xl font-bold lg:text-6xl dark:text-white">
|
<h1 className="text-5xl font-bold tracking-tight lg:text-6xl dark:text-white">
|
||||||
Cup
|
Cup
|
||||||
</h1>
|
</h1>
|
||||||
<Logo />
|
<Logo />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`bg-white shadow-sm dark:bg-${theme}-900 my-8 rounded-md`}
|
className={`border shadow-sm border-${theme}-200 dark:border-${theme}-800 my-8 rounded-md`}
|
||||||
>
|
>
|
||||||
<dl className="grid grid-cols-2 gap-1 overflow-hidden *:relative lg:grid-cols-4">
|
<dl className="grid grid-cols-2 gap-1 overflow-hidden *:relative lg:grid-cols-4">
|
||||||
{Object.entries(data.metrics)
|
{Object.entries(data.metrics)
|
||||||
@@ -55,7 +55,7 @@ function App() {
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`bg-white shadow-sm dark:bg-${theme}-900 my-8 rounded-md`}
|
className={`border shadow-sm border-${theme}-200 dark:border-${theme}-800 my-8 rounded-md`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`flex items-center justify-between px-6 py-4 text-${theme}-500`}
|
className={`flex items-center justify-between px-6 py-4 text-${theme}-500`}
|
||||||
|
|||||||
@@ -9,7 +9,15 @@ import { WithTooltip } from "./Tooltip";
|
|||||||
import type { Image } from "../types";
|
import type { Image } from "../types";
|
||||||
import { theme } from "../theme";
|
import { theme } from "../theme";
|
||||||
import { CodeBlock } from "./CodeBlock";
|
import { CodeBlock } from "./CodeBlock";
|
||||||
import { Box, CircleArrowUp, CircleCheck, HelpCircle, Timer, TriangleAlert, X } from "lucide-react";
|
import {
|
||||||
|
Box,
|
||||||
|
CircleArrowUp,
|
||||||
|
CircleCheck,
|
||||||
|
HelpCircle,
|
||||||
|
Timer,
|
||||||
|
TriangleAlert,
|
||||||
|
X,
|
||||||
|
} from "lucide-react";
|
||||||
|
|
||||||
const clickable_registries = [
|
const clickable_registries = [
|
||||||
"registry-1.docker.io",
|
"registry-1.docker.io",
|
||||||
@@ -44,9 +52,11 @@ export default function Image({ data }: { data: Image }) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button onClick={handleOpen} className="w-full">
|
<button onClick={handleOpen} className="w-full">
|
||||||
<li className="flex items-center gap-4 break-all px-6 py-4 text-start">
|
<li
|
||||||
<Box className="size-6 shrink-0" />
|
className={`flex items-center gap-4 break-all px-6 py-4 text-start hover:bg-${theme}-100 hover:dark:bg-${theme}-800/50 transition-colors duration-200`}
|
||||||
{data.reference}
|
>
|
||||||
|
<Box className={`size-6 shrink-0 text-${theme}-500`} />
|
||||||
|
<span className="font-mono">{data.reference}</span>
|
||||||
<Icon data={data} />
|
<Icon data={data} />
|
||||||
</li>
|
</li>
|
||||||
</button>
|
</button>
|
||||||
@@ -59,14 +69,14 @@ export default function Image({ data }: { data: Image }) {
|
|||||||
<div className="flex min-h-full items-end justify-center text-center sm:items-center sm:p-0">
|
<div className="flex min-h-full items-end justify-center text-center sm:items-center sm:p-0">
|
||||||
<DialogPanel
|
<DialogPanel
|
||||||
transition
|
transition
|
||||||
className={`relative transform overflow-hidden rounded-t-lg bg-white md:rounded-lg dark:bg-${theme}-900 w-full text-left shadow-xl transition-all data-[closed]:translate-y-4 data-[closed]:opacity-0 data-[enter]:duration-300 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in sm:my-8 sm:w-full sm:max-w-lg data-[closed]:sm:translate-y-0 data-[closed]:sm:scale-95 md:max-w-xl lg:max-w-2xl dark:text-white`}
|
className={`relative transform overflow-hidden rounded-t-lg bg-white dark:border dark:border-${theme}-800 md:rounded-lg dark:bg-${theme}-900 w-full text-left shadow-xl transition-all data-[closed]:translate-y-4 data-[closed]:opacity-0 data-[enter]:duration-300 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in sm:my-8 sm:w-full sm:max-w-lg data-[closed]:sm:translate-y-0 data-[closed]:sm:scale-95 md:max-w-xl lg:max-w-2xl dark:text-white`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`flex flex-col gap-3 px-6 py-4 text-${theme}-400 dark:text-${theme}-600`}
|
className={`flex flex-col gap-3 px-6 py-4 text-${theme}-600 dark:text-${theme}-400`}
|
||||||
>
|
>
|
||||||
<div className="mb-4 flex items-center gap-3">
|
<div className="mb-4 flex items-center gap-3">
|
||||||
<Box className="size-6 shrink-0 text-black dark:text-white" />
|
<Box className={`size-6 shrink-0 text-${theme}-500`} />
|
||||||
<DialogTitle className="text-black dark:text-white">
|
<DialogTitle className="font-mono text-black dark:text-white">
|
||||||
{url ? (
|
{url ? (
|
||||||
<>
|
<>
|
||||||
<a
|
<a
|
||||||
@@ -95,28 +105,32 @@ export default function Image({ data }: { data: Image }) {
|
|||||||
)}
|
)}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<button onClick={handleClose} className="ml-auto">
|
<button onClick={handleClose} className="ml-auto">
|
||||||
<X className="size-6 shrink-0 text-gray-500" />
|
<X
|
||||||
|
className={`size-6 shrink-0 text-${theme}-500 transition-colors duration-200 hover:text-black dark:hover:text-white`}
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<DialogIcon data={data} />
|
<DialogIcon data={data} />
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-4 flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Timer className="size-6 shrink-0 text-gray-500" />
|
<Timer className="size-6 shrink-0 text-gray-500" />
|
||||||
<span>
|
<span>
|
||||||
Checked in <b>{data.time}</b> ms
|
Checked in <b>{data.time}</b> ms
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{data.result.error && (
|
{data.result.error && (
|
||||||
<div className="break-before mb-4 flex items-center gap-3 overflow-hidden rounded-md bg-yellow-400/10 px-3 py-2">
|
<div className="break-before mt-4 flex items-center gap-3 overflow-hidden rounded-md bg-yellow-400/10 px-3 py-2">
|
||||||
<TriangleAlert className="size-6 shrink-0 text-yellow-500" />
|
<TriangleAlert className="size-6 shrink-0 text-yellow-500" />
|
||||||
{data.result.error}
|
{data.result.error}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{data.result.has_update && (
|
{data.result.has_update && (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="mt-4 flex flex-col gap-1">
|
||||||
Pull command
|
Pull command
|
||||||
<CodeBlock enableCopy>{new_reference}</CodeBlock>
|
<CodeBlock enableCopy>
|
||||||
|
docker pull {new_reference}
|
||||||
|
</CodeBlock>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import { intlFormatDistance } from "date-fns/intlFormatDistance";
|
import { intlFormatDistance } from "date-fns/intlFormatDistance";
|
||||||
|
import { theme } from "../theme";
|
||||||
|
|
||||||
export function LastChecked({ datetime }: { datetime: string }) {
|
export function LastChecked({ datetime }: { datetime: string }) {
|
||||||
const date = intlFormatDistance(new Date(datetime), new Date());
|
const date = intlFormatDistance(new Date(datetime), new Date());
|
||||||
return <h3>Last checked {date}</h3>;
|
return (
|
||||||
|
<h3 className={`text-${theme}-600 dark:text-${theme}-500`}>
|
||||||
|
Last checked {date}
|
||||||
|
</h3>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { MouseEvent } from "react";
|
import { useState } from "react";
|
||||||
import { WithTooltip } from "./Tooltip";
|
import { WithTooltip } from "./Tooltip";
|
||||||
|
|
||||||
export default function RefreshButton() {
|
export default function RefreshButton() {
|
||||||
const refresh = (event: MouseEvent) => {
|
const [disabled, setDisabled] = useState(false);
|
||||||
const btn = event.currentTarget as HTMLButtonElement;
|
const refresh = () => {
|
||||||
btn.disabled = true;
|
setDisabled(true);
|
||||||
|
|
||||||
const request = new XMLHttpRequest();
|
const request = new XMLHttpRequest();
|
||||||
request.onload = () => {
|
request.onload = () => {
|
||||||
if (request.status === 200) {
|
if (request.status === 200) {
|
||||||
@@ -22,7 +21,7 @@ export default function RefreshButton() {
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<WithTooltip text="Reload">
|
<WithTooltip text="Reload">
|
||||||
<button className="group" onClick={refresh}>
|
<button className="group" onClick={refresh} disabled={disabled}>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ export default function Search({
|
|||||||
onChange("");
|
onChange("");
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className={`w-full px-6 text-${theme}-500`}>
|
<div className={`w-full px-6 text-black dark:text-white`}>
|
||||||
<div
|
<div
|
||||||
className={`flex w-full items-center rounded-md border border-${theme}-300 dark:border-${theme}-700 gap-1 px-2 bg-${theme}-200 dark:bg-${theme}-800 peer flex-nowrap`}
|
className={`flex w-full items-center rounded-md border border-${theme}-200 dark:border-${theme}-700 gap-1 px-2 bg-${theme}-100 dark:bg-${theme}-800 peer flex-nowrap`}
|
||||||
>
|
>
|
||||||
<SearchIcon className="size-5" />
|
<SearchIcon className="size-5" />
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<input
|
<input
|
||||||
className={`h-10 w-full text-sm text-${theme}-600 dark:text-${theme}-400 peer bg-transparent focus:outline-none placeholder:text-${theme}-500`}
|
className={`h-10 w-full text-sm text-${theme}-800 dark:text-${theme}-200 peer bg-transparent focus:outline-none placeholder:text-${theme}-600 placeholder:dark:text-${theme}-400`}
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
@@ -39,7 +39,7 @@ export default function Search({
|
|||||||
{showClear && (
|
{showClear && (
|
||||||
<button
|
<button
|
||||||
onClick={handleClear}
|
onClick={handleClear}
|
||||||
className={`hover:text-${theme}-600 dark:hover:text-${theme}-400`}
|
className={`hover:text-${theme}-600 dark:hover:text-${theme}-400 transition-colors duration-200`}
|
||||||
>
|
>
|
||||||
<X className="size-5" />
|
<X className="size-5" />
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export function Server({
|
|||||||
{name}
|
{name}
|
||||||
</span>
|
</span>
|
||||||
<ChevronDown
|
<ChevronDown
|
||||||
className={`duration-300 size-5 text-${theme}-600 transition-transform group-data-[open]:rotate-180 dark:text-${theme}-400 group-data-[hover]:text-${theme}-800 group-data-[hover]:dark:text-${theme}-200 transition-colors`}
|
className={`size-5 duration-300 text-${theme}-600 transition-transform group-data-[open]:rotate-180 dark:text-${theme}-400 group-data-[hover]:text-${theme}-800 group-data-[hover]:dark:text-${theme}-200 transition-colors`}
|
||||||
/>
|
/>
|
||||||
</DisclosureButton>
|
</DisclosureButton>
|
||||||
<DisclosurePanel
|
<DisclosurePanel
|
||||||
|
|||||||
@@ -17,15 +17,14 @@ export default function Statistic({
|
|||||||
metrics: Data["metrics"];
|
metrics: Data["metrics"];
|
||||||
}) {
|
}) {
|
||||||
if (!metricsToShow.includes(name)) return null;
|
if (!metricsToShow.includes(name)) return null;
|
||||||
let displayName = name.replaceAll("_", " ");
|
const displayName = name.replaceAll("_", " ");
|
||||||
displayName = displayName.slice(0, 1).toUpperCase() + displayName.slice(1); // Capitalize name
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`before:bg-${theme}-200 before:dark:bg-${theme}-800 after:bg-${theme}-200 after:dark:bg-${theme}-800 gi`}
|
className={`before:bg-${theme}-200 before:dark:bg-${theme}-800 after:bg-${theme}-200 after:dark:bg-${theme}-800 gi`}
|
||||||
>
|
>
|
||||||
<div className="flex h-full flex-col justify-between gap-x-4 gap-y-2 px-6 py-4 align-baseline lg:min-h-32">
|
<div className="flex h-full flex-col justify-between gap-x-4 gap-y-2 px-6 py-4 align-baseline lg:min-h-32">
|
||||||
<dt
|
<dt
|
||||||
className={`text-${theme}-500 dark:text-${theme}-400 font-medium leading-6`}
|
className={`text-${theme}-500 dark:text-${theme}-400 text-sm font-semibold uppercase leading-6`}
|
||||||
>
|
>
|
||||||
{displayName}
|
{displayName}
|
||||||
</dt>
|
</dt>
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ export default {
|
|||||||
safelist: [
|
safelist: [
|
||||||
// Generate minimum extra CSS
|
// Generate minimum extra CSS
|
||||||
{
|
{
|
||||||
pattern: /bg-(gray|neutral)-(50|100|200|500)/,
|
pattern: /bg-(gray|neutral)-(50|200|500)/,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: /bg-(gray|neutral)-100/,
|
||||||
|
variants: ["hover"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: /bg-(gray|neutral)-(900|950)/,
|
pattern: /bg-(gray|neutral)-(900|950)/,
|
||||||
@@ -20,10 +24,10 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: /bg-(gray|neutral)-800/,
|
pattern: /bg-(gray|neutral)-800/,
|
||||||
variants: ["before:dark", "after:dark", "dark"],
|
variants: ["before:dark", "after:dark", "dark", "hover:dark"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: /text-(gray|neutral)-(50|300)/,
|
pattern: /text-(gray|neutral)-(50|300|200)/,
|
||||||
variants: ["dark"],
|
variants: ["dark"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -35,9 +39,13 @@ export default {
|
|||||||
variants: ["dark", "dark:hover"],
|
variants: ["dark", "dark:hover"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: /text-(gray|neutral)-500/,
|
pattern: /text-(gray|neutral)-600/,
|
||||||
variants: ["placeholder"],
|
variants: ["placeholder"],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
pattern: /text-(gray|neutral)-400/,
|
||||||
|
variants: ["placeholder:dark"],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
pattern: /text-(gray|neutral)-700/,
|
pattern: /text-(gray|neutral)-700/,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user