Worker cards design
This commit is contained in:
parent
ea55a8fdf4
commit
9d50b7694b
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
// 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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue