Add backup/restore guide (#10945)

Signed-off-by: Artyom Savchenko <armisav@gmail.com>
This commit is contained in:
Artyom Savchenko
2026-07-02 13:59:54 +05:00
committed by GitHub
parent ae3b7f6216
commit 4064588585
37 changed files with 289 additions and 19 deletions
+2
View File
@@ -10,6 +10,8 @@
>
> The hosted Huly service is being discontinued because its hosting is no longer being funded. If you keep important data on the hosted platform, export and back it up, and migrate as soon as possible — we can help you move to either a [self-hosted setup](https://github.com/hcengineering/huly-selfhost) or a hosted option.
>
> Not sure how? Follow the [backup & restore guide](docs/guides/backup-restore.en.md) for step-by-step instructions on downloading your backup and restoring it elsewhere.
>
> The service shutdown is expected on **July 20**. Please make sure to export and migrate your data before then rather than wait until the last day.
>
> Have questions or want updates? Join the [Huly community](https://link.huly.io/slack) to discuss migration and stay informed, or email us at [artem@hardcoreeng.com](mailto:artem@hardcoreeng.com) with any questions. This affects only the hosted **Huly** service — self-hosted deployments are not affected.
+136
View File
@@ -0,0 +1,136 @@
# Backup & Restore Guide
Download a workspace backup and restore it into another Huly instance —
whether that's a self-hosted deployment or one of the hosted options. This is
the recommended way to move your data off a hosted workspace before it
becomes unavailable.
> [!TIP]
> Don't want to run your own server? You can also move to one of the
> existing hosted Huly forks instead of self-hosting. We're glad to help
> with the data migration either way — just keep in mind that none of these
> hosting options are free, since keeping servers running costs real money.
> See [Need help?](#need-help) below to get in touch.
## Overview
1. **Download** — from *Settings → Backup* in the workspace you want to move,
grab a full copy of your data.
2. **Restore** — replay that backup into the destination workspace using the
platform's admin tool (`dev/tool`).
## Step 1. Download your backup
Open the workspace and go to:
```
<your-workspace-url>/setting/setting/backup
```
(*Settings → Backup* in the left sidebar.) The page shows when the backup was
last taken, how many snapshots and files it contains, and its total size.
> [!NOTE]
> Backups are taken periodically, not continuously, so the latest backup can
> lag behind your live data by some time. Check **Last backup** on the page
> before you rely on it, and give it time to catch up if you just made
> important changes.
You have two ways to get the files:
- **Download full backup** — bundles every backup file into a single `.zip`
you can keep on your computer. A `RESTORE.md` with restore instructions is
included inside the archive.
- **Copy download script** (+ **Copy token**) — copies a small shell script
that downloads every file with `curl`. The script is safe to save or share:
it does **not** contain your token — it reads it from the
`HULY_BACKUP_TOKEN` environment variable, or prompts for it when you run it.
Either option produces a folder that the restore tool can consume directly
(see Step 2).
> [!TIP]
> **Large workspace?** Prefer the download script over the button. "Download
> full backup" assembles the whole archive in your browser's memory before
> saving it, which can be slow or fail outright once a workspace has a lot of
> data. The script downloads files one by one with `curl`, so it handles
> large backups more reliably.
You can also expand **Backup Snapshots** or **Backup Files** to download
individual files, e.g. to verify access or fetch a single snapshot.
> [!IMPORTANT]
> The **Not backed up** section lists blobs that are intentionally excluded
> from the regular backup (video, audio, and any file larger than the
> server's blob-size limit). Their content isn't in the archive or script
> above — if you need them on the destination, download each one individually
> from that list before you migrate.
## Step 2. Restore into a Huly instance
You'll need a Huly platform you control to restore into — either
[huly-selfhost](https://github.com/hcengineering/huly-selfhost), a
self-hosted deployment built from this monorepo, or another hosted instance
where you have admin access. Create the destination workspace first if it
doesn't exist yet.
Restoring is done with the `backup-restore` command of the platform admin
tool (`@hcengineering/tool`, `dev/tool` in this repo). Exactly how you invoke
it depends on how the destination platform is run:
- **Docker / self-hosted setup** — run it inside your `tool` container
(e.g. `docker compose run --rm tool backup-restore ...` or
`docker compose exec tool ...`, adjusted to your compose service name).
- **Monorepo checkout with Rush** — from `dev/tool`, run it against your
configured environment, e.g. `rushx run-local backup-restore ...` for a
local dev stack, or your own script that sets the same environment
variables against your real databases.
In both cases the command and its arguments are the same:
```
backup-restore <path-to-backup-folder> <target-workspace> [date] --accounts
```
- `<path-to-backup-folder>` — the folder you downloaded/unzipped in Step 1.
- `<target-workspace>` — the destination workspace's identifier.
- `--accounts` — also restores the original users (their profile and social
identities) into the target workspace. Without this flag only documents are
restored, and every member has to be invited again by email.
- `--upgrade` — add this if the destination runs a newer model version than
the backup.
- `-m/--merge` — don't delete documents that are missing from the backup
(useful when merging into a workspace that already has data).
> [!NOTE]
> Restoring accounts (`--accounts`) needs its own connection to the account
> database, configured via the `ACCOUNT_DB_URL` (and optional
> `ACCOUNT_DB_NS`) environment variables. See
> [`server/backup/README.md`](../../server/backup/README.md) for the full
> reference of flags and per-entry-point environment variables.
Once the restore finishes, users sign in with their original email via a
one-time code (OTP) — make sure the destination platform can send mail.
## Need help?
Our team is happy to help with migration. Join the [Huly community](https://link.huly.io/slack) to ask questions and get updates, or email us directly at [artem@hardcoreeng.com](mailto:artem@hardcoreeng.com).
## Troubleshooting
- **401 Unauthorized while downloading** — your token expired, or you're not
an owner/admin of the workspace. Get a fresh token from the Backup page.
- **Members are missing after restore** — re-run with `--accounts` and a
valid `ACCOUNT_DB_URL`; without both, only documents are restored.
- **A file/video is missing on the destination** — check the **Not backed
up** list on the Backup page and download it individually; it isn't part
of the regular backup.
- **Restore fails with a model/version error** — add `--upgrade` if the
destination runs a newer platform version than the source.
## See also
- [`server/backup/README.md`](../../server/backup/README.md) — full CLI
reference for `backup-restore`, including environment variables.
- [huly-selfhost](https://github.com/hcengineering/huly-selfhost) — official
self-hosted distribution.
+2
View File
@@ -141,6 +141,8 @@
"BackupCopyScript": "Kopírovat skript pro stažení",
"BackupCopyToken": "Kopírovat token",
"BackupScriptInfo": "Shellový skript, který stáhne všechny soubory zálohy pomocí curl. Uložte jej a spusťte v terminálu; vyžádá si váš token zálohy, takže ve skriptu nejsou uložena žádná tajemství.",
"BackupRestoreGuide": "Průvodce zálohováním a obnovou",
"BackupRestoreGuideInfo": "Podrobný návod, jak stáhnout tuto zálohu a obnovit ji v jiné instanci Huly.",
"NonBackupedBlobs": "Non Backed up blobs",
"Calendar": "Kalendář",
"StartOfTheWeek": "Začátek týdne",
+2
View File
@@ -147,6 +147,8 @@
"BackupCopyScript": "Download-Skript kopieren",
"BackupCopyToken": "Token kopieren",
"BackupScriptInfo": "Ein Shell-Skript, das alle Sicherungsdateien mit curl herunterlädt. Speichere es und führe es in einem Terminal aus; es fragt nach deinem Sicherungs-Token, sodass keine Geheimnisse im Skript gespeichert werden.",
"BackupRestoreGuide": "Anleitung zu Backup & Wiederherstellung",
"BackupRestoreGuideInfo": "Schritt-für-Schritt-Anleitung zum Herunterladen dieses Backups und zur Wiederherstellung in einer anderen Huly-Instanz.",
"NonBackupedBlobs": "Nicht gesicherte Blobs",
"Calendar": "Kalender",
"StartOfTheWeek": "Wochenstart",
+2
View File
@@ -147,6 +147,8 @@
"BackupCopyScript": "Copy download script",
"BackupCopyToken": "Copy token",
"BackupScriptInfo": "A shell script that downloads every backup file with curl. Save it and run it in a terminal; it prompts for your backup token, so no secrets are stored in the script.",
"BackupRestoreGuide": "Backup & restore guide",
"BackupRestoreGuideInfo": "Step-by-step instructions for downloading this backup and restoring it into another Huly instance.",
"NonBackupedBlobs": "Non Backed up blobs",
"Calendar": "Calendar",
"StartOfTheWeek": "Start of the week",
+2
View File
@@ -138,6 +138,8 @@
"BackupCopyScript": "Copiar script de descarga",
"BackupCopyToken": "Copiar token",
"BackupScriptInfo": "Un script de shell que descarga todos los archivos de la copia de seguridad con curl. Guárdalo y ejecútalo en una terminal; te pedirá tu token de copia de seguridad, por lo que no se almacenan secretos en el script.",
"BackupRestoreGuide": "Guía de copia de seguridad y restauración",
"BackupRestoreGuideInfo": "Instrucciones paso a paso para descargar esta copia de seguridad y restaurarla en otra instancia de Huly.",
"NonBackupedBlobs": "Blobs no respaldados",
"Calendar": "Calendario",
"StartOfTheWeek": "Inicio de la semana",
+2
View File
@@ -147,6 +147,8 @@
"BackupCopyScript": "Copier le script de téléchargement",
"BackupCopyToken": "Copier le jeton",
"BackupScriptInfo": "Un script shell qui télécharge tous les fichiers de sauvegarde avec curl. Enregistrez-le et exécutez-le dans un terminal ; il demande votre jeton de sauvegarde, aucun secret n'est donc stocké dans le script.",
"BackupRestoreGuide": "Guide de sauvegarde et restauration",
"BackupRestoreGuideInfo": "Instructions étape par étape pour télécharger cette sauvegarde et la restaurer sur une autre instance Huly.",
"NonBackupedBlobs": "Non Backed up blobs",
"Calendar": "Calendrier",
"StartOfTheWeek": "Début de semaine",
+2
View File
@@ -147,6 +147,8 @@
"BackupCopyScript": "Copia script di download",
"BackupCopyToken": "Copia token",
"BackupScriptInfo": "Uno script shell che scarica tutti i file di backup con curl. Salvalo ed eseguilo in un terminale; richiederà il tuo token di backup, quindi nello script non vengono memorizzati segreti.",
"BackupRestoreGuide": "Guida a backup e ripristino",
"BackupRestoreGuideInfo": "Istruzioni dettagliate per scaricare questo backup e ripristinarlo in un'altra istanza di Huly.",
"NonBackupedBlobs": "Non Backed up blobs",
"Calendar": "Calendario",
"StartOfTheWeek": "Inizio settimana",
+2
View File
@@ -147,6 +147,8 @@
"BackupCopyScript": "ダウンロードスクリプトをコピー",
"BackupCopyToken": "トークンをコピー",
"BackupScriptInfo": "curl ですべてのバックアップファイルをダウンロードするシェルスクリプトです。保存してターミナルで実行してください。バックアップトークンの入力を求められるため、スクリプトに機密情報は保存されません。",
"BackupRestoreGuide": "バックアップと復元ガイド",
"BackupRestoreGuideInfo": "このバックアップをダウンロードし、別の Huly インスタンスに復元するための手順です。",
"NonBackupedBlobs": "バックアップされていないブロブ",
"Calendar": "カレンダー",
"StartOfTheWeek": "週の開始",
+2
View File
@@ -147,6 +147,8 @@
"BackupCopyScript": "다운로드 스크립트 복사",
"BackupCopyToken": "토큰 복사",
"BackupScriptInfo": "curl로 모든 백업 파일을 다운로드하는 셸 스크립트입니다. 저장한 후 터미널에서 실행하세요. 백업 토큰을 입력하라는 메시지가 표시되므로 스크립트에 비밀 정보가 저장되지 않습니다.",
"BackupRestoreGuide": "백업 및 복원 가이드",
"BackupRestoreGuideInfo": "이 백업을 다운로드하여 다른 Huly 인스턴스로 복원하는 단계별 안내입니다.",
"NonBackupedBlobs": "백업되지 않은 Blob",
"Calendar": "캘린더",
"StartOfTheWeek": "주 시작일",
+2
View File
@@ -147,6 +147,8 @@
"BackupCopyScript": "Kopiuj skrypt pobierania",
"BackupCopyToken": "Kopiuj token",
"BackupScriptInfo": "Skrypt powłoki, który pobiera wszystkie pliki kopii zapasowej za pomocą curl. Zapisz go i uruchom w terminalu; poprosi o token kopii zapasowej, więc w skrypcie nie są przechowywane żadne sekrety.",
"BackupRestoreGuide": "Przewodnik po kopii zapasowej i przywracaniu",
"BackupRestoreGuideInfo": "Instrukcja krok po kroku dotycząca pobierania tej kopii zapasowej i przywracania jej w innej instancji Huly.",
"NonBackupedBlobs": "Pliki nieobjęte kopią zapasową",
"Calendar": "Kalendarz",
"StartOfTheWeek": "Początek tygodnia",
+2
View File
@@ -138,6 +138,8 @@
"BackupCopyScript": "Copiar script de download",
"BackupCopyToken": "Copiar token",
"BackupScriptInfo": "Um script de shell que baixa todos os arquivos de backup com curl. Salve-o e execute-o em um terminal; ele solicitará seu token de backup, então nenhum segredo é armazenado no script.",
"BackupRestoreGuide": "Guia de backup e restauração",
"BackupRestoreGuideInfo": "Instruções passo a passo para baixar este backup e restaurá-lo em outra instância do Huly.",
"NonBackupedBlobs": "Blobs sem backup",
"Calendar": "Calendário",
"StartOfTheWeek": "Início da semana",
+2
View File
@@ -138,6 +138,8 @@
"BackupCopyScript": "Copiar script de transferência",
"BackupCopyToken": "Copiar token",
"BackupScriptInfo": "Um script de shell que transfere todos os ficheiros da cópia de segurança com curl. Guarde-o e execute-o num terminal; irá pedir o seu token da cópia de segurança, pelo que não são armazenados segredos no script.",
"BackupRestoreGuide": "Guia de cópia de segurança e restauro",
"BackupRestoreGuideInfo": "Instruções passo a passo para transferir esta cópia de segurança e restaurá-la noutra instância do Huly.",
"NonBackupedBlobs": "Non Backed up blobs",
"Calendar": "Calendário",
"StartOfTheWeek": "Início da semana",
+2
View File
@@ -152,6 +152,8 @@
"BackupCopyScript": "Копировать скрипт загрузки",
"BackupCopyToken": "Копировать токен",
"BackupScriptInfo": "Скрипт оболочки, который скачивает все файлы резервной копии с помощью curl. Сохраните его и запустите в терминале; он запросит токен резервной копии, поэтому в скрипте не хранятся секреты.",
"BackupRestoreGuide": "Инструкция по резервному копированию и восстановлению",
"BackupRestoreGuideInfo": "Пошаговая инструкция о том, как скачать эту резервную копию и восстановить её в другом инстансе Huly.",
"NonBackupedBlobs": "Не резервируемые блобы",
"Calendar": "Календарь",
"StartOfTheWeek": "Начало недели",
+2
View File
@@ -147,6 +147,8 @@
"BackupCopyScript": "İndirme betiğini kopyala",
"BackupCopyToken": "Jetonu kopyala",
"BackupScriptInfo": "Tüm yedek dosyalarını curl ile indiren bir kabuk betiği. Kaydedip bir terminalde çalıştırın; yedek jetonunuzu ister, bu nedenle betikte hiçbir gizli bilgi saklanmaz.",
"BackupRestoreGuide": "Yedekleme ve geri yükleme kılavuzu",
"BackupRestoreGuideInfo": "Bu yedeği indirmek ve başka bir Huly örneğine geri yüklemek için adım adım talimatlar.",
"NonBackupedBlobs": "Yedeklenmemiş blob'lar",
"Calendar": "Takvim",
"StartOfTheWeek": "Haftanın başlangıcı",
+2
View File
@@ -147,6 +147,8 @@
"BackupCopyScript": "复制下载脚本",
"BackupCopyToken": "复制令牌",
"BackupScriptInfo": "一个使用 curl 下载所有备份文件的 shell 脚本。保存并在终端中运行;它会提示输入您的备份令牌,因此脚本中不会存储任何机密信息。",
"BackupRestoreGuide": "备份与恢复指南",
"BackupRestoreGuideInfo": "关于下载此备份并将其恢复到另一个 Huly 实例的分步说明。",
"NonBackupedBlobs": "未备份的 Blob",
"Calendar": "日历",
"StartOfTheWeek": "本周开始",
@@ -14,6 +14,7 @@
//
import {
backupRestoreGuideLink,
buildStoreZip,
collectBackupFileNames,
crc32,
@@ -116,6 +117,20 @@ describe('generateRestoreReadme', () => {
expect(readme.toLowerCase()).toContain('video')
expect(readme.toLowerCase()).toContain('blob')
})
it('mentions the --accounts flag needed to restore the original users', () => {
expect(readme).toContain('--accounts')
})
it('links to the full backup & restore guide', () => {
expect(readme).toContain(backupRestoreGuideLink)
})
})
describe('backupRestoreGuideLink', () => {
it('is an https link', () => {
expect(backupRestoreGuideLink.startsWith('https://')).toBe(true)
})
})
describe('crc32', () => {
@@ -21,7 +21,13 @@
import { onMount } from 'svelte'
import setting from '../plugin'
import { BackupInfo, BackupSnapshot } from '../types'
import { buildStoreZip, collectBackupFileNames, generateBackupScript, generateRestoreReadme } from '../utils/backup'
import {
backupRestoreGuideLink,
buildStoreZip,
collectBackupFileNames,
generateBackupScript,
generateRestoreReadme
} from '../utils/backup'
let loading = true
@@ -316,6 +322,22 @@
<Button label={tokenCopied ? view.string.Copied : setting.string.BackupCopyToken} on:click={copyToken} />
</div>
</div>
<div class="backup-action">
<div class="backup-action__text">
<div class="backup-action__title">
<Label label={setting.string.BackupRestoreGuide} />
</div>
<div class="backup-action__info">
<Label label={setting.string.BackupRestoreGuideInfo} />
</div>
</div>
<Button
label={setting.string.BackupRestoreGuide}
on:click={() => {
window.open(backupRestoreGuideLink, '_blank', 'noopener,noreferrer')
}}
/>
</div>
</div>
<Expandable bordered>
+17 -2
View File
@@ -15,6 +15,16 @@
import { type BackupInfo } from '../types'
/**
* Link to the full backup & restore guide (download + restore into another
* Huly instance). Shown on the Backup settings page and embedded in the
* generated RESTORE.md so it travels with the backup.
*
* @public
*/
export const backupRestoreGuideLink =
'https://github.com/hcengineering/platform/blob/develop/docs/guides/backup-restore.en.md'
/**
* Shape of the data returned from `<backupUrl>/<workspace>/index.json`.
* Mirrors the inline type used by the backup settings page.
@@ -164,9 +174,12 @@ admin tool.
3. From the platform monorepo, restore the backup into that workspace:
cd dev/tool
rushx tool backup-restore <path-to-this-folder> <target-workspace>
rushx tool backup-restore <path-to-this-folder> <target-workspace> --accounts
Add \`--upgrade\` if the target runs a newer model version.
Add \`--upgrade\` if the target runs a newer model version. Add
\`--accounts\` to also restore the original users (skip it if you'll invite
members manually instead) — it needs its own account-database connection,
see server/backup/README.md.
## Notes
@@ -177,6 +190,8 @@ admin tool.
than the server's blob limit — are listed in \`blob-info.json.gz\` but their
contents are NOT included here; they remain in the source workspace's live
storage.
Full guide, including troubleshooting: ${backupRestoreGuideLink}
`
}
+2
View File
@@ -306,6 +306,8 @@ export default plugin(settingId, {
BackupCopyScript: '' as IntlString,
BackupCopyToken: '' as IntlString,
BackupScriptInfo: '' as IntlString,
BackupRestoreGuide: '' as IntlString,
BackupRestoreGuideInfo: '' as IntlString,
NonBackupedBlobs: '' as IntlString,
AddAttribute: '' as IntlString,
Mailboxes: '' as IntlString,
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": ". Nezapomeňte prosím svá data exportovat a přenést ještě před tímto datem.",
"ShutdownCommunityHint": "Máte dotazy nebo chcete dostávat novinky? Připojte se ke komunitě Huly, kde můžete probrat migraci a zůstat v obraze.",
"JoinCommunityCta": "Připojit se ke komunitě Huly",
"ShutdownContactPrefix": "Máte dotazy? Kontaktujte "
"ShutdownContactPrefix": "Máte dotazy? Kontaktujte ",
"ShutdownBackupGuideHint": "Nevíte, jak přenést svá data? Přečtěte si podrobný návod ke stažení zálohy a jejímu obnovení v jiné instanci Huly.",
"BackupGuideCta": "Průvodce zálohováním a obnovou"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": " erwartet. Bitte exportieren und migrieren Sie Ihre Daten unbedingt vorher.",
"ShutdownCommunityHint": "Haben Sie Fragen oder möchten Sie auf dem Laufenden bleiben? Treten Sie der Huly-Community bei, um die Migration zu besprechen und informiert zu bleiben.",
"JoinCommunityCta": "Der Huly-Community beitreten",
"ShutdownContactPrefix": "Fragen? Kontaktieren Sie "
"ShutdownContactPrefix": "Fragen? Kontaktieren Sie ",
"ShutdownBackupGuideHint": "Nicht sicher, wie Sie Ihre Daten übertragen? Lesen Sie die Schritt-für-Schritt-Anleitung zum Herunterladen eines Backups und zur Wiederherstellung in einer anderen Huly-Instanz.",
"BackupGuideCta": "Anleitung zu Backup & Wiederherstellung"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": ". Please make sure to export and migrate your data before then.",
"ShutdownCommunityHint": "Have questions or want updates? Join the Huly community to discuss migration and stay informed.",
"JoinCommunityCta": "Join the Huly community",
"ShutdownContactPrefix": "Questions? Contact "
"ShutdownContactPrefix": "Questions? Contact ",
"ShutdownBackupGuideHint": "Not sure how to move your data? Read the step-by-step guide for downloading a backup and restoring it into another Huly instance.",
"BackupGuideCta": "Backup & restore guide"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": ". Asegúrate de exportar y migrar tus datos antes de esa fecha.",
"ShutdownCommunityHint": "¿Tienes preguntas o quieres recibir novedades? Únete a la comunidad de Huly para hablar sobre la migración y mantenerte informado.",
"JoinCommunityCta": "Unirse a la comunidad de Huly",
"ShutdownContactPrefix": "¿Preguntas? Contacta con "
"ShutdownContactPrefix": "¿Preguntas? Contacta con ",
"ShutdownBackupGuideHint": "¿No sabes cómo migrar tus datos? Lee la guía paso a paso para descargar una copia de seguridad y restaurarla en otra instancia de Huly.",
"BackupGuideCta": "Guía de copia de seguridad y restauración"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": ". Veuillez veiller à exporter et migrer vos données avant cette date.",
"ShutdownCommunityHint": "Des questions ou envie de suivre les actualités ? Rejoignez la communauté Huly pour discuter de la migration et rester informé.",
"JoinCommunityCta": "Rejoindre la communauté Huly",
"ShutdownContactPrefix": "Des questions ? Contactez "
"ShutdownContactPrefix": "Des questions ? Contactez ",
"ShutdownBackupGuideHint": "Vous ne savez pas comment migrer vos données ? Consultez le guide étape par étape pour télécharger une sauvegarde et la restaurer sur une autre instance Huly.",
"BackupGuideCta": "Guide de sauvegarde et restauration"
}
}
+3 -1
View File
@@ -36,6 +36,8 @@
"ShutdownNextEventAfter": ". Assicurati di esportare e migrare i tuoi dati prima di quella data.",
"ShutdownCommunityHint": "Hai domande o vuoi ricevere aggiornamenti? Unisciti alla community di Huly per parlare della migrazione e restare informato.",
"JoinCommunityCta": "Unisciti alla community di Huly",
"ShutdownContactPrefix": "Domande? Contatta "
"ShutdownContactPrefix": "Domande? Contatta ",
"ShutdownBackupGuideHint": "Non sai come trasferire i tuoi dati? Leggi la guida dettagliata per scaricare un backup e ripristinarlo in un'altra istanza di Huly.",
"BackupGuideCta": "Guida a backup e ripristino"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": " に予定されています。必ずその前にデータをエクスポートして移行してください。",
"ShutdownCommunityHint": "ご質問や最新情報が必要ですか? Huly コミュニティに参加して、移行について相談したり最新情報を受け取ったりできます。",
"JoinCommunityCta": "Huly コミュニティに参加",
"ShutdownContactPrefix": "ご質問は "
"ShutdownContactPrefix": "ご質問は ",
"ShutdownBackupGuideHint": "データの移行方法がわからない場合は、バックアップをダウンロードして別の Huly インスタンスに復元する手順ガイドをご覧ください。",
"BackupGuideCta": "バックアップと復元ガイド"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": "로 예상됩니다. 반드시 그 전에 데이터를 내보내고 이전해 주세요.",
"ShutdownCommunityHint": "궁금한 점이 있거나 소식을 받고 싶으신가요? Huly 커뮤니티에 참여하여 이전에 대해 논의하고 최신 소식을 확인하세요.",
"JoinCommunityCta": "Huly 커뮤니티 참여",
"ShutdownContactPrefix": "문의사항은 "
"ShutdownContactPrefix": "문의사항은 ",
"ShutdownBackupGuideHint": "데이터를 옮기는 방법을 모르시나요? 백업을 다운로드하여 다른 Huly 인스턴스로 복원하는 단계별 가이드를 확인하세요.",
"BackupGuideCta": "백업 및 복원 가이드"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": ". Pamiętaj, aby wyeksportować i przenieść dane przed tą datą.",
"ShutdownCommunityHint": "Masz pytania lub chcesz otrzymywać aktualności? Dołącz do społeczności Huly, aby porozmawiać o migracji i być na bieżąco.",
"JoinCommunityCta": "Dołącz do społeczności Huly",
"ShutdownContactPrefix": "Masz pytania? Skontaktuj się: "
"ShutdownContactPrefix": "Masz pytania? Skontaktuj się: ",
"ShutdownBackupGuideHint": "Nie wiesz, jak przenieść swoje dane? Zapoznaj się z instrukcją krok po kroku dotyczącą pobierania kopii zapasowej i przywracania jej w innej instancji Huly.",
"BackupGuideCta": "Przewodnik po kopii zapasowej i przywracaniu"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": ". Certifique-se de exportar e migrar seus dados antes dessa data.",
"ShutdownCommunityHint": "Tem dúvidas ou quer receber novidades? Junte-se à comunidade do Huly para discutir a migração e ficar por dentro.",
"JoinCommunityCta": "Entrar na comunidade do Huly",
"ShutdownContactPrefix": "Dúvidas? Entre em contato: "
"ShutdownContactPrefix": "Dúvidas? Entre em contato: ",
"ShutdownBackupGuideHint": "Não sabe como migrar seus dados? Consulte o guia passo a passo para baixar um backup e restaurá-lo em outra instância do Huly.",
"BackupGuideCta": "Guia de backup e restauração"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": ". Certifique-se de exportar e migrar os seus dados antes dessa data.",
"ShutdownCommunityHint": "Tem dúvidas ou quer receber novidades? Junte-se à comunidade do Huly para discutir a migração e manter-se informado.",
"JoinCommunityCta": "Juntar-se à comunidade do Huly",
"ShutdownContactPrefix": "Questões? Contacte "
"ShutdownContactPrefix": "Questões? Contacte ",
"ShutdownBackupGuideHint": "Não sabe como migrar os seus dados? Consulte o guia passo a passo para transferir uma cópia de segurança e restaurá-la noutra instância do Huly.",
"BackupGuideCta": "Guia de cópia de segurança e restauro"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": ". Пожалуйста, обязательно экспортируйте и перенесите данные до этой даты.",
"ShutdownCommunityHint": "Есть вопросы или хотите получать обновления? Присоединяйтесь к сообществу Huly, чтобы обсудить миграцию и быть в курсе.",
"JoinCommunityCta": "Вступить в сообщество Huly",
"ShutdownContactPrefix": "Вопросы? Пишите на "
"ShutdownContactPrefix": "Вопросы? Пишите на ",
"ShutdownBackupGuideHint": "Не знаете, как перенести данные? Прочитайте пошаговую инструкцию о том, как скачать резервную копию и восстановить её в другом инстансе Huly.",
"BackupGuideCta": "Резервное копирование и восстановление"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": " tarihinde bekleniyor. Lütfen verilerinizi bu tarihten önce dışa aktarıp taşıdığınızdan emin olun.",
"ShutdownCommunityHint": "Sorularınız mı var ya da güncellemeleri takip etmek mi istiyorsunuz? Göçü konuşmak ve haberdar olmak için Huly topluluğuna katılın.",
"JoinCommunityCta": "Huly topluluğuna katıl",
"ShutdownContactPrefix": "Sorularınız mı var? İletişim: "
"ShutdownContactPrefix": "Sorularınız mı var? İletişim: ",
"ShutdownBackupGuideHint": "Verilerinizi nasıl taşıyacağınızdan emin değil misiniz? Bir yedeği indirip başka bir Huly örneğine geri yüklemek için adım adım kılavuzu okuyun.",
"BackupGuideCta": "Yedekleme ve geri yükleme kılavuzu"
}
}
+3 -1
View File
@@ -44,6 +44,8 @@
"ShutdownNextEventAfter": "。请务必在此日期之前导出并迁移你的数据。",
"ShutdownCommunityHint": "有疑问或想获取最新消息?加入 Huly 社区,讨论迁移并随时了解动态。",
"JoinCommunityCta": "加入 Huly 社区",
"ShutdownContactPrefix": "有疑问?请联系:"
"ShutdownContactPrefix": "有疑问?请联系:",
"ShutdownBackupGuideHint": "不知道如何迁移数据?请阅读分步指南,了解如何下载备份并将其恢复到另一个 Huly 实例。",
"BackupGuideCta": "备份与恢复指南"
}
}
@@ -16,7 +16,7 @@
import { createEventDispatcher } from 'svelte'
import { Button, Label } from '@hcengineering/ui'
import workbench from '../plugin'
import { communityLink, migrationContactEmail } from '../utils'
import { backupGuideLink, communityLink, migrationContactEmail } from '../utils'
const dispatch = createEventDispatcher()
@@ -24,6 +24,11 @@
dispatch('close')
window.open(communityLink, '_blank', 'noopener,noreferrer')
}
function handleOpenBackupGuide (): void {
dispatch('close')
window.open(backupGuideLink, '_blank', 'noopener,noreferrer')
}
</script>
<div class="shutdown-notice-popup">
@@ -48,6 +53,10 @@
<Label label={workbench.string.ShutdownCommunityHint} />
</div>
<div class="hint">
<Label label={workbench.string.ShutdownBackupGuideHint} />
</div>
<div class="hint">
<Label label={workbench.string.ShutdownContactPrefix} /><a href="mailto:{migrationContactEmail}"
>{migrationContactEmail}</a
@@ -55,6 +64,7 @@
</div>
<div class="footer">
<Button label={workbench.string.BackupGuideCta} on:click={handleOpenBackupGuide} />
<Button kind="primary" size="medium" label={workbench.string.JoinCommunityCta} on:click={handleJoinCommunity} />
</div>
</div>
@@ -105,6 +115,7 @@
.footer {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
}
}
</style>
+3 -1
View File
@@ -55,7 +55,9 @@ export default mergeIds(workbenchId, workbench, {
ShutdownNextEventAfter: '' as IntlString,
ShutdownCommunityHint: '' as IntlString,
JoinCommunityCta: '' as IntlString,
ShutdownContactPrefix: '' as IntlString
ShutdownContactPrefix: '' as IntlString,
ShutdownBackupGuideHint: '' as IntlString,
BackupGuideCta: '' as IntlString
},
component: {
SpacePanel: '' as AnyComponent,
+9
View File
@@ -59,6 +59,15 @@ export const communityLink = 'https://link.huly.io/slack'
*/
export const migrationContactEmail = 'artem@hardcoreeng.com'
/**
* Step-by-step guide for downloading a workspace backup and restoring it into
* another Huly instance, linked from the hosting shutdown notice so users can
* migrate their data themselves.
*
* @public
*/
export const backupGuideLink = 'https://github.com/hcengineering/platform/blob/develop/docs/guides/backup-restore.en.md'
export function getSpecialSpaceClass (model: NavigatorModel): Array<Ref<Class<Space>>> {
const spaceResult = model.spaces.map((x) => x.spaceClass)
const result = (model.specials ?? [])