mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-30 05:25:00 +02:00
QFix: Backup info page (#7703)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
@@ -122,14 +122,14 @@
|
||||
"OwnerOrMaintainerRequired": "Musíte být vlastníkem nebo správcem pracovního prostoru",
|
||||
"Backup": "Záloha",
|
||||
"BackupLast": "Poslední záloha",
|
||||
"BackupTotalSnapshots": "Celkem snímků",
|
||||
"BackupTotalSnapshots": "Celkový počet snímků",
|
||||
"BackupTotalFiles": "Soubory",
|
||||
"BackupSize": "Velikost zálohy",
|
||||
"BackupLinkInfo": "Záložní adresář je dostupný na",
|
||||
"BackupBearerTokenInfo": "Pro přístup k záloze je vyžadován přístupový token. Klikněte na tlačítko pro zkopírování tokenu do schránky.",
|
||||
"BackupSnapshots": "Snímky",
|
||||
"BackupFileDownload": "Stáhnout",
|
||||
"BackupFiles": "Soubory",
|
||||
"BackupNoBackup": "Žádná záloha není k dispozici"
|
||||
"BackupLinkInfo": "URL adresář zálohy, který lze stáhnout rekurzivně pomocí nástrojů jako wget nebo curl.",
|
||||
"BackupBearerTokenInfo": "Přístup k záloze vyžaduje bearer token.",
|
||||
"BackupSnapshots": "Snímky záloh",
|
||||
"BackupFileDownload": "Stáhnout soubor",
|
||||
"BackupFiles": "Soubory záloh",
|
||||
"BackupNoBackup": "V současné době nejsou k dispozici žádné zálohy."
|
||||
}
|
||||
}
|
||||
@@ -122,14 +122,14 @@
|
||||
"OwnerOrMaintainerRequired": "Sie müssen Eigentümer oder Betreuer des Arbeitsbereichs sein",
|
||||
"Backup": "Sicherung",
|
||||
"BackupLast": "Letzte Sicherung",
|
||||
"BackupTotalSnapshots": "Gesamtanzahl Snapshots",
|
||||
"BackupTotalSnapshots": "Gesamtanzahl der Schnappschüsse",
|
||||
"BackupTotalFiles": "Dateien",
|
||||
"BackupSize": "Sicherungsgröße",
|
||||
"BackupLinkInfo": "Ein Sicherungsverzeichnis ist verfügbar unter",
|
||||
"BackupBearerTokenInfo": "Für den Zugriff auf die Sicherung wird ein Bearer-Token benötigt. Bitte klicken Sie auf die Schaltfläche 'Kopieren', um den Token in die Zwischenablage zu kopieren.",
|
||||
"BackupSnapshots": "Snapshots",
|
||||
"BackupFileDownload": "Herunterladen",
|
||||
"BackupFiles": "Dateien",
|
||||
"BackupNoBackup": "Keine Sicherung verfügbar"
|
||||
"BackupLinkInfo": "Die URL eines Sicherungsverzeichnisses, das rekursiv mit Tools wie wget oder curl heruntergeladen werden kann.",
|
||||
"BackupBearerTokenInfo": "Ein Bearer-Token ist erforderlich, um auf die Sicherung zuzugreifen.",
|
||||
"BackupSnapshots": "Sicherungsschnappschüsse",
|
||||
"BackupFileDownload": "Datei herunterladen",
|
||||
"BackupFiles": "Sicherungsdateien",
|
||||
"BackupNoBackup": "Derzeit sind keine Sicherungen verfügbar."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,11 +125,11 @@
|
||||
"BackupTotalSnapshots": "Total Snapshots",
|
||||
"BackupTotalFiles": "Files",
|
||||
"BackupSize": "Backup size",
|
||||
"BackupLinkInfo": "A backup directory is available at",
|
||||
"BackupBearerTokenInfo": "A bearer token is required to access the backup. Please click copy to clipboard button to copy the token." ,
|
||||
"BackupSnapshots": "Snapshots",
|
||||
"BackupFileDownload": "Download",
|
||||
"BackupFiles": "Files",
|
||||
"BackupNoBackup": "No backup available"
|
||||
"BackupLinkInfo": "The URL of a backup directory that can be downloaded recursively using tools like wget or curl.",
|
||||
"BackupBearerTokenInfo": "A bearer token is required to access the backup.",
|
||||
"BackupSnapshots": "Backup Snapshots",
|
||||
"BackupFileDownload": "Download File",
|
||||
"BackupFiles": "Backup Files",
|
||||
"BackupNoBackup": "No backups are currently available."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,14 +113,14 @@
|
||||
"OwnerOrMaintainerRequired": "Necesitas ser Propietario o Mantenedor del espacio de trabajo",
|
||||
"Backup": "Copia de seguridad",
|
||||
"BackupLast": "Última copia de seguridad",
|
||||
"BackupTotalSnapshots": "Total de instantáneas",
|
||||
"BackupTotalSnapshots": "Total instantáneas",
|
||||
"BackupTotalFiles": "Archivos",
|
||||
"BackupSize": "Tamaño de la copia",
|
||||
"BackupLinkInfo": "El directorio de copias de seguridad está disponible en",
|
||||
"BackupBearerTokenInfo": "Se requiere un token de acceso para acceder a la copia de seguridad. Por favor, haga clic en el botón para copiar el token al portapapeles.",
|
||||
"BackupSnapshots": "Instantáneas",
|
||||
"BackupFileDownload": "Descargar",
|
||||
"BackupFiles": "Archivos",
|
||||
"BackupNoBackup": "No hay copias de seguridad disponibles"
|
||||
"BackupSize": "Tamaño de la copia de seguridad",
|
||||
"BackupLinkInfo": "La URL de un directorio de copia de seguridad que se puede descargar de forma recursiva usando herramientas como wget o curl.",
|
||||
"BackupBearerTokenInfo": "Se requiere un token de portador para acceder a la copia de seguridad.",
|
||||
"BackupSnapshots": "Instantáneas de copia de seguridad",
|
||||
"BackupFileDownload": "Descargar archivo",
|
||||
"BackupFiles": "Archivos de copia de seguridad",
|
||||
"BackupNoBackup": "No hay copias de seguridad disponibles actualmente."
|
||||
}
|
||||
}
|
||||
@@ -125,11 +125,11 @@
|
||||
"BackupTotalSnapshots": "Total des instantanés",
|
||||
"BackupTotalFiles": "Fichiers",
|
||||
"BackupSize": "Taille de la sauvegarde",
|
||||
"BackupLinkInfo": "Un répertoire de sauvegarde est disponible à",
|
||||
"BackupBearerTokenInfo": "Un jeton d'authentification est nécessaire pour accéder à la sauvegarde. Veuillez cliquer sur le bouton pour copier le jeton dans le presse-papiers.",
|
||||
"BackupSnapshots": "Instantanés",
|
||||
"BackupFileDownload": "Télécharger",
|
||||
"BackupFiles": "Fichiers",
|
||||
"BackupNoBackup": "Aucune sauvegarde disponible"
|
||||
"BackupLinkInfo": "L'URL d'un répertoire de sauvegarde pouvant être téléchargé de manière récursive à l'aide d'outils comme wget ou curl.",
|
||||
"BackupBearerTokenInfo": "Un jeton d'accès est requis pour accéder à la sauvegarde.",
|
||||
"BackupSnapshots": "Instantanés de sauvegarde",
|
||||
"BackupFileDownload": "Télécharger le fichier",
|
||||
"BackupFiles": "Fichiers de sauvegarde",
|
||||
"BackupNoBackup": "Aucune sauvegarde n'est actuellement disponible."
|
||||
}
|
||||
}
|
||||
@@ -125,11 +125,11 @@
|
||||
"BackupTotalSnapshots": "Totale istantanee",
|
||||
"BackupTotalFiles": "File",
|
||||
"BackupSize": "Dimensione backup",
|
||||
"BackupLinkInfo": "Una directory di backup è disponibile in",
|
||||
"BackupBearerTokenInfo": "È richiesto un token di accesso per accedere al backup. Fare clic sul pulsante per copiare il token negli appunti.",
|
||||
"BackupSnapshots": "Istantanee",
|
||||
"BackupFileDownload": "Scarica",
|
||||
"BackupFiles": "File",
|
||||
"BackupNoBackup": "Nessun backup disponibile"
|
||||
"BackupLinkInfo": "L'URL di una directory di backup che può essere scaricata ricorsivamente utilizzando strumenti come wget o curl.",
|
||||
"BackupBearerTokenInfo": "È richiesto un token di accesso per accedere al backup.",
|
||||
"BackupSnapshots": "Istantanee di backup",
|
||||
"BackupFileDownload": "Scarica file",
|
||||
"BackupFiles": "File di backup",
|
||||
"BackupNoBackup": "Non sono attualmente disponibili backup."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,14 +113,14 @@
|
||||
"OwnerOrMaintainerRequired": "Precisa de ser proprietário ou mantenedor do espaço de trabalho",
|
||||
"Backup": "Backup",
|
||||
"BackupLast": "Último backup",
|
||||
"BackupTotalSnapshots": "Total de instantâneos",
|
||||
"BackupTotalSnapshots": "Total de Snapshots",
|
||||
"BackupTotalFiles": "Arquivos",
|
||||
"BackupSize": "Tamanho do backup",
|
||||
"BackupLinkInfo": "Um diretório de backup está disponível em",
|
||||
"BackupBearerTokenInfo": "É necessário um token de acesso para acessar o backup. Clique no botão para copiar o token para a área de transferência.",
|
||||
"BackupSnapshots": "Instantâneos",
|
||||
"BackupFileDownload": "Baixar",
|
||||
"BackupFiles": "Arquivos",
|
||||
"BackupNoBackup": "Nenhum backup disponível"
|
||||
"BackupLinkInfo": "A URL de um diretório de backup que pode ser baixado recursivamente usando ferramentas como wget ou curl.",
|
||||
"BackupBearerTokenInfo": "É necessário um token bearer para acessar o backup.",
|
||||
"BackupSnapshots": "Snapshots de Backup",
|
||||
"BackupFileDownload": "Baixar Arquivo",
|
||||
"BackupFiles": "Arquivos de Backup",
|
||||
"BackupNoBackup": "Não há backups disponíveis no momento."
|
||||
}
|
||||
}
|
||||
@@ -121,16 +121,16 @@
|
||||
"WorkspaceName": "Название рабочего пространства",
|
||||
"Workspace": "Рабочее пространство",
|
||||
"OwnerOrMaintainerRequired": "Вы должны иметь роль Владельца/Сопровождаемого",
|
||||
"Backup": "Резервная копия",
|
||||
"BackupLast": "Последняя резервная копия",
|
||||
"Backup": "Резервное копирование",
|
||||
"BackupLast": "Последнее резервное копирование",
|
||||
"BackupTotalSnapshots": "Всего снимков",
|
||||
"BackupTotalFiles": "Файлы",
|
||||
"BackupSize": "Размер резервной копии",
|
||||
"BackupLinkInfo": "Директория резервных копий доступна по адресу",
|
||||
"BackupBearerTokenInfo": "Для доступа к резервной копии требуется токен авторизации. Пожалуйста, нажмите кнопку, чтобы скопировать токен в буфер обмена.",
|
||||
"BackupSnapshots": "Снимки",
|
||||
"BackupFileDownload": "Скачать",
|
||||
"BackupFiles": "Файлы",
|
||||
"BackupNoBackup": "Резервные копии отсутствуют"
|
||||
"BackupLinkInfo": "URL-адрес каталога резервной копии, который можно скачать рекурсивно с помощью инструментов, таких как wget или curl.",
|
||||
"BackupBearerTokenInfo": "Для доступа к резервной копии требуется токен доступа.",
|
||||
"BackupSnapshots": "Снимки резервной копии",
|
||||
"BackupFileDownload": "Скачать файл",
|
||||
"BackupFiles": "Файлы резервной копии",
|
||||
"BackupNoBackup": "В настоящее время резервные копии недоступны."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,15 +121,15 @@
|
||||
"Workspace": "工作区",
|
||||
"OwnerOrMaintainerRequired": "您需要成为工作空间所有者或维护者",
|
||||
"Backup": "备份",
|
||||
"BackupLast": "最近备份",
|
||||
"BackupLast": "上次备份",
|
||||
"BackupTotalSnapshots": "快照总数",
|
||||
"BackupTotalFiles": "文件",
|
||||
"BackupTotalFiles": "文件数量",
|
||||
"BackupSize": "备份大小",
|
||||
"BackupLinkInfo": "备份目录位于",
|
||||
"BackupBearerTokenInfo": "访问备份需要访问令牌。请点击复制按钮将令牌复制到剪贴板。",
|
||||
"BackupSnapshots": "快照",
|
||||
"BackupFileDownload": "下载",
|
||||
"BackupFiles": "文件",
|
||||
"BackupNoBackup": "暂无可用备份"
|
||||
"BackupLinkInfo": "可以使用 wget 或 curl 等工具递归下载的备份目录的 URL。",
|
||||
"BackupBearerTokenInfo": "访问备份需要一个持票者令牌。",
|
||||
"BackupSnapshots": "备份快照",
|
||||
"BackupFileDownload": "下载文件",
|
||||
"BackupFiles": "备份文件",
|
||||
"BackupNoBackup": "当前没有可用的备份。"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
import { onMount } from 'svelte'
|
||||
import setting from '../plugin'
|
||||
import { BackupInfo, BackupSnapshot } from '../types'
|
||||
import Expand from '@hcengineering/ui/src/components/icons/Expand.svelte'
|
||||
|
||||
let loading = true
|
||||
|
||||
@@ -108,9 +109,9 @@
|
||||
if (diffHours < 24) {
|
||||
if (diffHours === 0) {
|
||||
const diffMinutes = Math.floor(diffMs / (1000 * 60))
|
||||
return `- ${diffMinutes} minutes ago`
|
||||
return `${diffMinutes} minutes ago`
|
||||
}
|
||||
return `- ${diffHours} hours ago`
|
||||
return `${diffHours} hours ago`
|
||||
}
|
||||
|
||||
return ''
|
||||
@@ -142,6 +143,7 @@
|
||||
}
|
||||
}
|
||||
let copied = false
|
||||
let copied2 = false
|
||||
|
||||
$: snapshots = backupInfo?.info?.snapshots ?? []
|
||||
</script>
|
||||
@@ -172,47 +174,48 @@
|
||||
<span class="flex-row-center">
|
||||
<Label label={setting.string.BackupSize} />: {getBackupSize(backupInfo?.files ?? [])}
|
||||
</span>
|
||||
|
||||
<div class="mt-2">
|
||||
<div class="flex-row-center mt-2">
|
||||
<Label label={setting.string.BackupLinkInfo} />:
|
||||
<a href={getFileUrl('index.html')} target="_blank" rel="noopener noreferrer">
|
||||
<Link label="index.html">
|
||||
{getFileUrl('index.html')}
|
||||
</Link>
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<Label label={setting.string.BackupBearerTokenInfo} />
|
||||
</div>
|
||||
<Button
|
||||
label={copied ? view.string.Copied : view.string.CopyToClipboard}
|
||||
on:click={() => {
|
||||
void navigator.clipboard.writeText(token).then(() => {
|
||||
copied = true
|
||||
setTimeout(() => {
|
||||
copied = false
|
||||
}, 2500)
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Expandable bordered>
|
||||
<svelte:fragment slot="title">
|
||||
<div class="flex-no-shrink flex-row-center">
|
||||
<div class="flex-no-shrink flex-row-center p-1">
|
||||
<Label label={setting.string.BackupSnapshots} />:
|
||||
{snapshots.length}
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
<div class="p-1">
|
||||
<div class="file-item">
|
||||
<div class="file-name">{'index.json'}</div>
|
||||
<div class="file-info">
|
||||
<span class="file-size">
|
||||
{getSize(JSON.stringify(backupInfo).length)}
|
||||
</span>
|
||||
<div class="file-actions">
|
||||
<Button label={setting.string.BackupFileDownload} on:click={() => downloadFile('index.json')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="file-item">
|
||||
<div class="file-name">{'backup.json.gz'}</div>
|
||||
<div class="file-info">
|
||||
<span class="file-size">
|
||||
{getSize(fileSizes.get('backup.json.gz') ?? 0)}
|
||||
</span>
|
||||
<div class="file-actions">
|
||||
<Button label={setting.string.BackupFileDownload} on:click={() => downloadFile('backup.json.gz')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if backupInfo?.info?.snapshots}
|
||||
{#each backupInfo.info.snapshots as snapshot, i}
|
||||
{@const snLen = backupInfo.info.snapshots.length}
|
||||
{#each backupInfo.info.snapshots.reverse() as snapshot, i}
|
||||
<div class="flex-no-shrink">
|
||||
<Expandable expandable bordered>
|
||||
<svelte:fragment slot="title">
|
||||
<div class="flex-row-center">
|
||||
#{i}
|
||||
<div class="flex-row-center ml-1">
|
||||
#{snLen - i}
|
||||
{formatDate(snapshot.date)}
|
||||
{formatAgoHours(snapshot.date)} -
|
||||
{getSnapshotSummary(snapshot)}
|
||||
@@ -241,6 +244,22 @@
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{#each data.snapshots ?? [] as filename}
|
||||
<div class="file-item">
|
||||
<div class="file-name">{filename}</div>
|
||||
<div class="file-info">
|
||||
<span class="file-size">
|
||||
{getSize(fileSizes.get(filename) ?? 0)}
|
||||
</span>
|
||||
<div class="file-actions">
|
||||
<Button
|
||||
label={setting.string.BackupFileDownload}
|
||||
on:click={() => downloadFile(filename)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -260,27 +279,67 @@
|
||||
{/if}
|
||||
</Expandable>
|
||||
|
||||
<Expandable bordered>
|
||||
<Expandable expanded={true} bordered>
|
||||
<svelte:fragment slot="title">
|
||||
<div class="flex-no-shrink flex-row-center">
|
||||
<Label label={setting.string.BackupFiles} />:
|
||||
{backupInfo?.files.length}
|
||||
{getBackupSize(backupInfo?.files ?? [])}
|
||||
<div class="p-1">
|
||||
<Label label={setting.string.BackupFiles} />
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
{#each backupInfo?.files ?? [] as file}
|
||||
<div class="p-1">
|
||||
<div class="file-item">
|
||||
<div class="file-name">{file.name}</div>
|
||||
<div class="file-name">{'index.json'}</div>
|
||||
<div class="file-info">
|
||||
<span class="file-size">
|
||||
{getSize(file.size ?? 0)}
|
||||
</span>
|
||||
<div class="file-actions">
|
||||
<Button label={setting.string.BackupFileDownload} on:click={() => downloadFile(file.name)} />
|
||||
<Button label={setting.string.BackupFileDownload} on:click={() => downloadFile('index.json')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
<div class="file-item">
|
||||
<div class="file-name">{'index.html'}</div>
|
||||
<div class="file-info">
|
||||
<div class="file-actions">
|
||||
<Button label={setting.string.BackupFileDownload} on:click={() => downloadFile('index.html')} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<div class="flex-row-center mt-2 flex-between">
|
||||
<div class="wrap">
|
||||
<Label label={setting.string.BackupLinkInfo} />
|
||||
<div class="select-text anti-component p-3 border-b-1 border-divider-color">
|
||||
{getFileUrl('index.html')}
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
label={copied ? view.string.Copied : view.string.CopyToClipboard}
|
||||
on:click={() => {
|
||||
void navigator.clipboard.writeText(getFileUrl('index.html')).then(() => {
|
||||
copied = true
|
||||
setTimeout(() => {
|
||||
copied = false
|
||||
}, 2500)
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-2 flex-row-center flex-between">
|
||||
<Label label={setting.string.BackupBearerTokenInfo} />
|
||||
|
||||
<Button
|
||||
label={copied2 ? view.string.Copied : view.string.CopyToClipboard}
|
||||
on:click={() => {
|
||||
void navigator.clipboard.writeText(token).then(() => {
|
||||
copied2 = true
|
||||
setTimeout(() => {
|
||||
copied2 = false
|
||||
}, 2500)
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Expandable>
|
||||
{/if}
|
||||
</Scroller>
|
||||
@@ -305,14 +364,14 @@
|
||||
.files-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
gap: 0.05rem;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
padding: 0.05rem;
|
||||
background-color: var(--theme-bg-accent);
|
||||
border-radius: 0.25rem;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user