Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m51s
67 lines
2.8 KiB
React
67 lines
2.8 KiB
React
import { useEffect, useState } from 'react';
|
|
import api from '../lib/api.js';
|
|
import { IconHash, IconClock, IconFileText, IconRefresh } from '@tabler/icons-react';
|
|
import { formatDateTimeWithRelative } from '../lib/datetime.js';
|
|
|
|
function S3MetaBar({ keys = [], className = '' }) {
|
|
const [meta, setMeta] = useState({});
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const fetchMeta = async () => {
|
|
setLoading(true);
|
|
try {
|
|
const res = await api.get('/s3/last-modified');
|
|
setMeta(res.data || {});
|
|
} catch {
|
|
setMeta({});
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => { fetchMeta(); }, []);
|
|
|
|
const copyMeta = async (k) => {
|
|
try {
|
|
const it = meta[k] || {};
|
|
const text = `etag: ${it?.etag || ''}\nlastModified: ${it?.lastModified || ''}`;
|
|
await navigator.clipboard?.writeText(text);
|
|
window.notify?.success?.('Скопировано в буфер');
|
|
} catch (e) {
|
|
window.notify?.error?.('Не удалось скопировать', String(e));
|
|
}
|
|
};
|
|
|
|
const renderKey = (k) => {
|
|
const it = meta[k];
|
|
return (
|
|
<div key={k} className="d-flex align-items-center gap-2 flex-wrap">
|
|
<span className="badge bg-blue-lt text-blue d-inline-flex align-items-center" title="ETag"><IconHash size={14} className="me-1" /><span className="font-monospace">{it?.etag || '—'}</span></span>
|
|
<span className="badge bg-blue-lt text-blue d-inline-flex align-items-center" title="Время последнего изменения"><IconClock size={14} className="me-1" />{it?.lastModified ? formatDateTimeWithRelative(it.lastModified) : '—'}</span>
|
|
<span className="badge bg-blue-lt text-blue d-inline-flex align-items-center"><IconFileText size={14} className="me-1" />{typeof it?.contentLength === 'number' ? `${it.contentLength} байт` : '—'}</span>
|
|
<button className="btn btn-outline-secondary btn-sm" type="button" onClick={() => copyMeta(k)} title="Копировать ETag/Last-Modified">
|
|
<IconFileText size={14} className="me-1" />Копировать
|
|
</button>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className={`card-footer ${className}`} style={{ position: 'sticky', bottom: 0, zIndex: 5, background: 'var(--tblr-card-bg)', borderTop: '1px solid rgba(0,0,0,.05)' }}>
|
|
<div className="d-flex align-items-center justify-content-between">
|
|
<div className="d-flex flex-column gap-1">
|
|
{keys.length === 0 ? renderKey('domainsNew') : keys.map(renderKey)}
|
|
</div>
|
|
<button className="btn btn-outline-secondary btn-sm" onClick={fetchMeta} disabled={loading}>
|
|
<IconRefresh className={loading ? 'spin' : ''} />
|
|
<span className="ms-1">Обновить</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default S3MetaBar;
|
|
|
|
|