diff --git a/frontend/src/components/PageHeaderActions.jsx b/frontend/src/components/PageHeaderActions.jsx
index 3dc1406..590d94d 100644
--- a/frontend/src/components/PageHeaderActions.jsx
+++ b/frontend/src/components/PageHeaderActions.jsx
@@ -8,6 +8,7 @@ import {
IconEraser
} from '@tabler/icons-react';
import PortalDropdown from './PortalDropdown.jsx';
+import { IconClock } from '@tabler/icons-react';
function PageHeaderActions({
loading = false,
@@ -25,6 +26,7 @@ function PageHeaderActions({
onSave,
disableSave = false,
onHistory,
+ lastModified,
onOnlineUpdate,
onBackgroundUpdate,
}) {
@@ -144,7 +146,16 @@ function PageHeaderActions({
)}
{onHistory && (
-
+
+
+ {lastModified && (
+
+ )}
+
)}
diff --git a/frontend/src/components/S3MetaBar.jsx b/frontend/src/components/S3MetaBar.jsx
index 5a81f75..7276b4a 100644
--- a/frontend/src/components/S3MetaBar.jsx
+++ b/frontend/src/components/S3MetaBar.jsx
@@ -20,6 +20,17 @@ function S3MetaBar({ keys = [], className = '' }) {
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 (
@@ -27,12 +38,15 @@ function S3MetaBar({ keys = [], className = '' }) {
{it?.etag || '—'}
{it?.lastModified ? new Date(it.lastModified).toLocaleString() : '—'}
{typeof it?.contentLength === 'number' ? `${it.contentLength} байт` : '—'}
+
);
};
return (
-
+
{keys.length === 0 ? renderKey('domainsNew') : keys.map(renderKey)}