1
0
Fork 0

Worker cards design

This commit is contained in:
Pabloader 2026-04-11 14:36:53 +00:00
parent ea55a8fdf4
commit 9d50b7694b
4 changed files with 28 additions and 45 deletions

View File

@ -10,10 +10,13 @@
--text: #f8f8f2;
--text-muted: #75715e;
--text-dim: #cfcfc2;
--text-dark: #1a1a1a;
--yellow: #e6db74;
--orange: #fd971f;
--blue: #66d9ef;
--purple: #ae81ff;
--green: #a3be8c;
--red: #e06c75;
--radius: 4px;
--transition: 0.15s ease;

View File

@ -1,5 +1,3 @@
const API_KEY = 'awoorwa32';
const saveThrottleDelay = 2000;
const pendingSaves = new Map<string, ReturnType<typeof setTimeout>>();
@ -15,12 +13,10 @@ export const loadObject = async <T>(key: string, defaultObject: T): Promise<T> =
let remoteObject: Partial<T> = {};
try {
const response = await fetch(`https://demo.pabloader.ru/storage/${key}?_=${Math.random()}`);
if (response.ok) {
const compressedData = await response.blob();
const decompressedData = await decompressBlob(compressedData);
remoteObject = JSON.parse(await decompressedData.text());
}
// TODO loading from a remote source
const compressedData = new Blob([]);
const decompressedData = await decompressBlob(compressedData);
remoteObject = JSON.parse(await decompressedData.text());
} catch { }
return { ...defaultObject, ...localObject, ...remoteObject };
@ -43,22 +39,9 @@ const doSaveObject = async <T>(key: string, obj: T) => {
} catch { }
try {
const url = new URL('https://demo.pabloader.ru/storage/index.php');
url.searchParams.set('filename', key);
const compressedData = await compressBlob(saveData);
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/gzip',
'Authorization': `Bearer ${API_KEY}`,
},
body: compressedData,
});
if (!response.ok) {
throw new Error('Failed to save context');
}
// TODO saving to remote storage
void compressedData;
} catch {
}
}
@ -68,14 +51,12 @@ export const compressBlob = async (blob: Blob | string): Promise<Blob> => {
blob = new Blob([blob]);
}
const cs = new CompressionStream("gzip");
// @ts-ignore
const compressedStream = blob.stream().pipeThrough(cs);
return await new Response(compressedStream).blob();
}
export const decompressBlob = async (blob: Blob): Promise<Blob> => {
const ds = new DecompressionStream("gzip");
// @ts-ignore
const decompressedStream = blob.stream().pipeThrough(ds);
return await new Response(decompressedStream).blob();
}

View File

@ -17,6 +17,15 @@
border-color: var(--accent-alt) !important;
}
.maintenanceBorder {
border-color: var(--yellow) !important;
}
.ownBadge {
background: var(--accent-alt);
color: var(--text-dark);
}
.offline {
opacity: 0.5;
}
@ -65,24 +74,14 @@
text-transform: uppercase;
}
.online {
background: var(--accent-alt);
color: #1a1a1a;
}
.offlineBadge {
background: var(--bg-active);
color: var(--text-muted);
}
.maintenance {
background: var(--yellow);
color: #1a1a1a;
color: var(--text-dark);
}
.trusted {
background: var(--blue);
color: #1a1a1a;
background: var(--accent);
color: var(--text-dark);
}
.info {

View File

@ -15,6 +15,7 @@ export const WorkerCard = ({ worker, isOwn }: Props) => {
return (
<div class={clsx(styles.card, {
[styles.own]: isOwn,
[styles.maintenanceBorder]: worker.maintenance_mode,
[styles.offline]: !worker.online,
})}>
<div class={styles.header}>
@ -29,14 +30,9 @@ export const WorkerCard = ({ worker, isOwn }: Props) => {
{worker.info ? <span class={styles.infoToggle}>{expanded.value ? ' ▲' : ' ▼'}</span> : null}
</span>
<div class={styles.badges}>
<span class={clsx(styles.badge, {
[styles.online]: worker.online,
[styles.offlineBadge]: !worker.online,
})}>
{worker.online ? 'online' : 'offline'}
</span>
{isOwn && <span class={clsx(styles.badge, styles.ownBadge)}>own</span>}
{worker.maintenance_mode && <span class={clsx(styles.badge, styles.maintenance)}>maintenance</span>}
{worker.trusted && <span class={clsx(styles.badge, styles.trusted)}>trusted</span>}
{!worker.trusted && <span class={clsx(styles.badge, styles.trusted)}>not trusted</span>}
</div>
</div>
@ -77,6 +73,10 @@ export const WorkerCard = ({ worker, isOwn }: Props) => {
<dt>Kudos earned</dt>
<dd>{formatNumber(worker.kudos_rewards)}</dd>
</div>
<div class={styles.detail}>
<dt>Kudos/hour</dt>
<dd>{worker.uptime > 0 ? formatNumber(Math.round((worker.kudos_details.generated / worker.uptime) * 3600)) : '0'}</dd>
</div>
</dl>
</div>
);