@trieb.work/payload-plugin-backup-mongodb 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +260 -90
- package/dist/backup-dashboard.css +18 -1
- package/dist/collections/BackupTasks.js +8 -1
- package/dist/collections/BackupTasks.js.map +1 -1
- package/dist/components/BackupDashboard/BackupListCollapsible.client.js.map +1 -1
- package/dist/components/BackupDashboard/BackupSettingsModal.client.js +203 -115
- package/dist/components/BackupDashboard/BackupSettingsModal.client.js.map +1 -1
- package/dist/components/BackupDashboard/CollectionBackupPreviewBody.client.js.map +1 -1
- package/dist/components/BackupDashboard/RestoreBackupDialog.client.js +1 -1
- package/dist/components/BackupDashboard/RestoreBackupDialog.client.js.map +1 -1
- package/dist/components/BackupDashboard/TaskActionButton.client.d.ts +1 -1
- package/dist/components/BackupDashboard/TaskActionButton.client.js +59 -26
- package/dist/components/BackupDashboard/TaskActionButton.client.js.map +1 -1
- package/dist/components/BackupDashboard/backupDashboardInlineCss.js +1 -1
- package/dist/components/BackupDashboard/backupDashboardInlineCss.js.map +1 -1
- package/dist/components/BackupDashboard/index.js +27 -3
- package/dist/components/BackupDashboard/index.js.map +1 -1
- package/dist/core/archive.js.map +1 -1
- package/dist/core/backup.d.ts +4 -3
- package/dist/core/backup.js +50 -43
- package/dist/core/backup.js.map +1 -1
- package/dist/core/backupArchiveRead.d.ts +15 -0
- package/dist/core/backupArchiveRead.js +30 -0
- package/dist/core/backupArchiveRead.js.map +1 -0
- package/dist/core/backupBlobIO.js.map +1 -1
- package/dist/core/backupSettings.js +5 -0
- package/dist/core/backupSettings.js.map +1 -1
- package/dist/core/blobTokenValidate.js.map +1 -1
- package/dist/core/restore.d.ts +5 -2
- package/dist/core/restore.js +133 -89
- package/dist/core/restore.js.map +1 -1
- package/dist/core/restorePreview.d.ts +12 -3
- package/dist/core/restorePreview.js +17 -13
- package/dist/core/restorePreview.js.map +1 -1
- package/dist/core/restoreResult.d.ts +34 -0
- package/dist/core/restoreResult.js +45 -0
- package/dist/core/restoreResult.js.map +1 -0
- package/dist/core/storage/config.d.ts +31 -0
- package/dist/core/storage/config.js +60 -0
- package/dist/core/storage/config.js.map +1 -0
- package/dist/core/storage/index.d.ts +23 -0
- package/dist/core/storage/index.js +25 -0
- package/dist/core/storage/index.js.map +1 -0
- package/dist/core/storage/s3.d.ts +35 -0
- package/dist/core/storage/s3.js +200 -0
- package/dist/core/storage/s3.js.map +1 -0
- package/dist/core/storage/types.d.ts +60 -0
- package/dist/core/storage/types.js +6 -0
- package/dist/core/storage/types.js.map +1 -0
- package/dist/core/storage/vercelBlob.d.ts +25 -0
- package/dist/core/storage/vercelBlob.js +53 -0
- package/dist/core/storage/vercelBlob.js.map +1 -0
- package/dist/core/taskProgress.d.ts +10 -4
- package/dist/core/taskProgress.js +11 -2
- package/dist/core/taskProgress.js.map +1 -1
- package/dist/core/vercelBackupCron.js.map +1 -1
- package/dist/endpoints/index.js +0 -5
- package/dist/endpoints/index.js.map +1 -1
- package/dist/endpoints/paths/admin-backup-download.js +8 -7
- package/dist/endpoints/paths/admin-backup-download.js.map +1 -1
- package/dist/endpoints/paths/admin-delete.js +11 -5
- package/dist/endpoints/paths/admin-delete.js.map +1 -1
- package/dist/endpoints/paths/admin-manual.js +2 -1
- package/dist/endpoints/paths/admin-manual.js.map +1 -1
- package/dist/endpoints/paths/admin-preview.js +9 -2
- package/dist/endpoints/paths/admin-preview.js.map +1 -1
- package/dist/endpoints/paths/admin-restore.js +7 -4
- package/dist/endpoints/paths/admin-restore.js.map +1 -1
- package/dist/endpoints/paths/admin-settings.js +35 -2
- package/dist/endpoints/paths/admin-settings.js.map +1 -1
- package/dist/endpoints/paths/cron-list.js +2 -1
- package/dist/endpoints/paths/cron-list.js.map +1 -1
- package/dist/endpoints/paths/cron-restore.js +14 -4
- package/dist/endpoints/paths/cron-restore.js.map +1 -1
- package/dist/endpoints/paths/cron-run.js +2 -1
- package/dist/endpoints/paths/cron-run.js.map +1 -1
- package/dist/endpoints/shared.d.ts +0 -1
- package/dist/endpoints/shared.js +0 -6
- package/dist/endpoints/shared.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/plugin.js.map +1 -1
- package/dist/publicApiPaths.d.ts +0 -1
- package/dist/publicApiPaths.js +0 -1
- package/dist/publicApiPaths.js.map +1 -1
- package/dist/types.d.ts +0 -5
- package/dist/types.js.map +1 -1
- package/dist/utils/blobName.js.map +1 -1
- package/dist/utils/dashboardRoleAccess.js.map +1 -1
- package/dist/utils/dialogBackdrop.js.map +1 -1
- package/dist/utils/hostname.js.map +1 -1
- package/dist/utils/maskBlobToken.js.map +1 -1
- package/package.json +25 -4
- package/dist/endpoints/paths/admin-seed.d.ts +0 -3
- package/dist/endpoints/paths/admin-seed.js +0 -47
- package/dist/endpoints/paths/admin-seed.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/BackupDashboard/BackupListCollapsible.client.tsx"],"sourcesContent":["'use client'\n\nimport { Button, Collapsible } from '@payloadcms/ui'\nimport { useCallback, useId, useMemo, useRef, useState } from 'react'\n\nimport type { TransformBlobNameResult } from '../../utils/index'\n\nimport { closeNativeDialogOnBackdropPointer } from '../../utils/dialogBackdrop'\nimport { formatBytes, getBackupSortTimeMs, transformBlobName } from '../../utils/index'\nimport { BackupItemActions } from './BackupItemActions.client'\n\nexport interface SerializableBackupBlob {\n downloadUrl: string\n pathname: string\n size: number\n uploadedAt: string\n url: string\n}\n\nexport interface BackupListCollapsibleProps {\n blobs: SerializableBackupBlob[]\n countOtherDb: number\n countOtherHostname: number\n currentDbName: string\n currentHostname: string\n i18nLanguage: string\n}\n\ninterface BackupListFilterState {\n dateFrom: string\n dateTo: string\n label: string\n media: 'all' | 'with' | 'without'\n showOtherDb: boolean\n showOtherHostname: boolean\n source: 'all' | 'cron' | 'manual'\n}\n\nconst defaultFilterState: BackupListFilterState = {\n dateFrom: '',\n dateTo: '',\n label: '',\n media: 'all',\n showOtherDb: true,\n showOtherHostname: false,\n source: 'all',\n}\n\nfunction parseDateInputStartMs(isoDate: string): null | number {\n const parts = isoDate.split('-').map(Number)\n if (parts.length !== 3 || parts.some((n) => !Number.isFinite(n))) {\n return null\n }\n const [y, m, d] = parts\n const t = new Date(y, m - 1, d, 0, 0, 0, 0).getTime()\n return Number.isFinite(t) ? t : null\n}\n\nfunction parseDateInputEndMs(isoDate: string): null | number {\n const parts = isoDate.split('-').map(Number)\n if (parts.length !== 3 || parts.some((n) => !Number.isFinite(n))) {\n return null\n }\n const [y, m, d] = parts\n const t = new Date(y, m - 1, d, 23, 59, 59, 999).getTime()\n return Number.isFinite(t) ? t : null\n}\n\nfunction passesDateMediaSource(\n parsed: TransformBlobNameResult,\n displayMs: number,\n filters: BackupListFilterState,\n): boolean {\n if (filters.dateFrom) {\n const from = parseDateInputStartMs(filters.dateFrom)\n if (from != null && displayMs < from) {\n return false\n }\n }\n if (filters.dateTo) {\n const to = parseDateInputEndMs(filters.dateTo)\n if (to != null && displayMs > to) {\n return false\n }\n }\n if (filters.media === 'with' && parsed.fileType !== 'tar.gz') {\n return false\n }\n if (filters.media === 'without' && parsed.fileType !== 'json') {\n return false\n }\n if (filters.source === 'manual' && parsed.type !== 'manual') {\n return false\n }\n if (filters.source === 'cron' && parsed.type !== 'cron') {\n return false\n }\n const labelQuery = filters.label.trim().toLowerCase()\n if (labelQuery) {\n const blobLabel = (parsed.label ?? '').toLowerCase()\n if (!blobLabel.includes(labelQuery)) {\n return false\n }\n }\n return true\n}\n\nfunction hasNonDefaultFilters(f: BackupListFilterState): boolean {\n return (\n f.dateFrom !== defaultFilterState.dateFrom ||\n f.dateTo !== defaultFilterState.dateTo ||\n f.label !== defaultFilterState.label ||\n f.media !== defaultFilterState.media ||\n f.source !== defaultFilterState.source ||\n f.showOtherDb !== defaultFilterState.showOtherDb ||\n f.showOtherHostname !== defaultFilterState.showOtherHostname\n )\n}\n\nexport const BackupListCollapsible: React.FC<BackupListCollapsibleProps> = ({\n blobs,\n countOtherDb,\n countOtherHostname,\n currentDbName,\n currentHostname,\n i18nLanguage,\n}) => {\n const uid = useId()\n const idDb = `${uid}-show-other-db`\n const idHost = `${uid}-show-other-host`\n const dialogRef = useRef<HTMLDialogElement>(null)\n const [filters, setFilters] = useState<BackupListFilterState>(defaultFilterState)\n\n const visibleRows = useMemo(() => {\n const rows: Array<{\n blob: SerializableBackupBlob\n displayAt: Date\n displayMs: number\n parsed: TransformBlobNameResult\n }> = []\n\n for (const blob of blobs) {\n const parsed = transformBlobName(blob.pathname)\n const { dbName, hostname } = parsed\n const isCurrentDb = currentDbName === dbName\n const isCurrentHostname = currentHostname === hostname\n if (!(filters.showOtherDb || isCurrentDb)) {\n continue\n }\n if (!(filters.showOtherHostname || isCurrentHostname)) {\n continue\n }\n\n const uploadedAt = new Date(blob.uploadedAt)\n const displayMs = getBackupSortTimeMs(parsed, uploadedAt)\n if (!passesDateMediaSource(parsed, displayMs, filters)) {\n continue\n }\n\n rows.push({\n blob,\n displayAt: new Date(displayMs),\n displayMs,\n parsed,\n })\n }\n\n return rows\n }, [blobs, currentDbName, currentHostname, filters])\n\n const openFilterDialog = useCallback(() => {\n dialogRef.current?.showModal()\n }, [])\n\n const closeFilterDialog = useCallback(() => {\n dialogRef.current?.close()\n }, [])\n\n const clearFilters = useCallback(() => {\n setFilters(defaultFilterState)\n }, [])\n\n const hasScopeOptions = countOtherDb > 0 || countOtherHostname > 0\n const filtersActive = hasNonDefaultFilters(filters)\n\n const filtersButton = (\n <Button\n buttonStyle=\"secondary\"\n className={\n filtersActive\n ? 'backup-dashboard__filter-btn backup-dashboard__filter-btn--active'\n : 'backup-dashboard__filter-btn'\n }\n onClick={openFilterDialog}\n type=\"button\"\n >\n Filters\n </Button>\n )\n\n return (\n <>\n <Collapsible\n header={<span className=\"backup-dashboard__collapsible-title\">Backup list</span>}\n initCollapsed={true}\n >\n <div className=\"backup-dashboard__backup-list-toolbar\">{filtersButton}</div>\n {blobs.length === 0 ? (\n <p className=\"backup-dashboard__list-empty\">No backups yet</p>\n ) : visibleRows.length === 0 ? (\n <p className=\"backup-dashboard__list-empty\">No backups match the current filters</p>\n ) : (\n visibleRows.map(({ blob, displayAt, parsed }) => {\n const { type, collectionCount, dbName, fileType, hostname, label } = parsed\n const isCurrentDb = currentDbName === dbName\n const isCurrentHostname = currentHostname === hostname\n\n return (\n <div className=\"backup-item\" key={blob.pathname}>\n <div className=\"backup-item__main\">\n <div className=\"backup-item__primary\">\n <time\n className=\"backup-item__time\"\n dateTime={displayAt.toISOString()}\n suppressHydrationWarning\n >\n {displayAt.toLocaleString(i18nLanguage)}\n </time>\n <span\n className={`backup-item__pill backup-item__pill--kind backup-item__pill--${type === 'cron' ? 'cron' : 'manual'}`}\n >\n {type === 'cron' ? 'Cron backup' : 'Manual backup'}\n </span>\n {label ? (\n <span\n className=\"backup-item__pill backup-item__pill--label\"\n title={`Label: ${label}`}\n >\n <span className=\"backup-item__pill-key\">Label</span>\n {label}\n </span>\n ) : null}\n </div>\n <div className=\"backup-item__meta\">\n <span\n className={`backup-item__pill backup-item__pill--db${isCurrentDb ? '' : ' backup-item__pill--warn'}`}\n >\n <span className=\"backup-item__pill-key\">\n {isCurrentDb ? 'DB' : 'other DB'}\n </span>\n {dbName || 'Unknown'}\n </span>\n <span\n className={`backup-item__pill backup-item__pill--host${isCurrentHostname ? '' : ' backup-item__pill--warn'}`}\n >\n <span className=\"backup-item__pill-key\">Host</span>\n {hostname || 'Unknown'}\n </span>\n {typeof collectionCount === 'number' ? (\n <span className=\"backup-item__pill backup-item__pill--collections\">\n <span className=\"backup-item__pill-key\">Collections</span>\n {collectionCount}\n </span>\n ) : null}\n {fileType === 'tar.gz' ? (\n <span className=\"backup-item__pill backup-item__pill--media\">With media</span>\n ) : fileType === 'json' ? (\n <span className=\"backup-item__pill backup-item__pill--media\">\n Without media\n </span>\n ) : null}\n <span\n className=\"backup-item__pill backup-item__pill--size\"\n title={`${blob.size.toLocaleString(i18nLanguage)} bytes`}\n >\n <span className=\"backup-item__pill-key\">Size</span>\n <span className=\"backup-item__size-value\">{formatBytes(blob.size)}</span>\n </span>\n </div>\n </div>\n <BackupItemActions\n downloadUrl={blob.downloadUrl}\n pathname={blob.pathname}\n url={blob.url}\n />\n </div>\n )\n })\n )}\n </Collapsible>\n\n <dialog\n className=\"backup-confirm-dialog backup-confirm-dialog--backup-list-filters\"\n onPointerDown={(e) => closeNativeDialogOnBackdropPointer(e, dialogRef)}\n ref={dialogRef}\n >\n <h3 className=\"backup-confirm-dialog__title\">Filter backups</h3>\n <p className=\"backup-confirm-dialog__subtitle\">\n All filters apply in the browser only. Current DB and hostname are always shown; enable\n the options below to include backups from other databases or hosts.\n </p>\n <div className=\"backup-confirm-dialog__body backup-list-filters__body\">\n {hasScopeOptions ? (\n <fieldset className=\"backup-list-filters__fieldset\">\n <legend className=\"backup-list-filters__legend\">Scope</legend>\n {countOtherDb > 0 ? (\n <div className=\"field-type checkbox backup-dashboard__collapsible-checkbox backup-list-filters__scope-row\">\n <input\n aria-label={`Show other databases (${countOtherDb} in list)`}\n checked={filters.showOtherDb}\n className=\"checkbox-input__input\"\n id={idDb}\n onChange={(e) => setFilters((f) => ({ ...f, showOtherDb: e.target.checked }))}\n type=\"checkbox\"\n />\n <label className=\"field-label\" htmlFor={idDb}>\n Show other DBs\n <span className=\"backup-list-filters__hint\"> ({countOtherDb} in list)</span>\n </label>\n </div>\n ) : null}\n {countOtherHostname > 0 ? (\n <div className=\"field-type checkbox backup-dashboard__collapsible-checkbox backup-list-filters__scope-row\">\n <input\n aria-label={`Show other hostnames (${countOtherHostname} in list)`}\n checked={filters.showOtherHostname}\n className=\"checkbox-input__input\"\n id={idHost}\n onChange={(e) =>\n setFilters((f) => ({ ...f, showOtherHostname: e.target.checked }))\n }\n type=\"checkbox\"\n />\n <label className=\"field-label\" htmlFor={idHost}>\n Show other Hostnames\n <span className=\"backup-list-filters__hint\">\n {' '}\n ({countOtherHostname} in list)\n </span>\n </label>\n </div>\n ) : null}\n </fieldset>\n ) : null}\n\n <fieldset className=\"backup-list-filters__fieldset\">\n <legend className=\"backup-list-filters__legend\">Label</legend>\n <div className=\"backup-list-filters__row backup-list-filters__row--label\">\n <label className=\"backup-list-filters__label\" htmlFor={`${uid}-label`}>\n Search\n </label>\n <input\n aria-label=\"Filter backups by label text\"\n autoComplete=\"off\"\n className=\"backup-list-filters__text\"\n id={`${uid}-label`}\n onChange={(e) => setFilters((f) => ({ ...f, label: e.target.value }))}\n placeholder=\"Filter by label text\"\n spellCheck={false}\n type=\"text\"\n value={filters.label}\n />\n </div>\n </fieldset>\n\n <fieldset className=\"backup-list-filters__fieldset\">\n <legend className=\"backup-list-filters__legend\">Date range</legend>\n <div className=\"backup-list-filters__row\">\n <label className=\"backup-list-filters__label\" htmlFor={`${uid}-from`}>\n From\n </label>\n <input\n aria-label=\"Filter from date\"\n className=\"backup-list-filters__date\"\n id={`${uid}-from`}\n onChange={(e) => setFilters((f) => ({ ...f, dateFrom: e.target.value }))}\n type=\"date\"\n value={filters.dateFrom}\n />\n </div>\n <div className=\"backup-list-filters__row\">\n <label className=\"backup-list-filters__label\" htmlFor={`${uid}-to`}>\n To\n </label>\n <input\n aria-label=\"Filter to date\"\n className=\"backup-list-filters__date\"\n id={`${uid}-to`}\n onChange={(e) => setFilters((f) => ({ ...f, dateTo: e.target.value }))}\n type=\"date\"\n value={filters.dateTo}\n />\n </div>\n </fieldset>\n\n <fieldset className=\"backup-list-filters__fieldset\">\n <legend className=\"backup-list-filters__legend\">Media</legend>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Media filter: all backups\"\n checked={filters.media === 'all'}\n className=\"radio-input__input\"\n id={`${uid}-media-all`}\n name={`${uid}-media`}\n onChange={() => setFilters((f) => ({ ...f, media: 'all' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-media-all`}>\n All\n </label>\n </div>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Media filter: with media\"\n checked={filters.media === 'with'}\n className=\"radio-input__input\"\n id={`${uid}-media-with`}\n name={`${uid}-media`}\n onChange={() => setFilters((f) => ({ ...f, media: 'with' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-media-with`}>\n With media\n </label>\n </div>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Media filter: without media\"\n checked={filters.media === 'without'}\n className=\"radio-input__input\"\n id={`${uid}-media-without`}\n name={`${uid}-media`}\n onChange={() => setFilters((f) => ({ ...f, media: 'without' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-media-without`}>\n Without media\n </label>\n </div>\n </fieldset>\n\n <fieldset className=\"backup-list-filters__fieldset\">\n <legend className=\"backup-list-filters__legend\">Source</legend>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Source filter: all\"\n checked={filters.source === 'all'}\n className=\"radio-input__input\"\n id={`${uid}-source-all`}\n name={`${uid}-source`}\n onChange={() => setFilters((f) => ({ ...f, source: 'all' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-source-all`}>\n All\n </label>\n </div>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Source filter: manual backups\"\n checked={filters.source === 'manual'}\n className=\"radio-input__input\"\n id={`${uid}-source-manual`}\n name={`${uid}-source`}\n onChange={() => setFilters((f) => ({ ...f, source: 'manual' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-source-manual`}>\n Manual\n </label>\n </div>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Source filter: cron backups\"\n checked={filters.source === 'cron'}\n className=\"radio-input__input\"\n id={`${uid}-source-cron`}\n name={`${uid}-source`}\n onChange={() => setFilters((f) => ({ ...f, source: 'cron' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-source-cron`}>\n Cron\n </label>\n </div>\n </fieldset>\n </div>\n <div className=\"backup-confirm-dialog__actions\">\n <Button buttonStyle=\"secondary\" onClick={clearFilters} type=\"button\">\n Clear filters\n </Button>\n <Button onClick={closeFilterDialog} type=\"button\">\n Done\n </Button>\n </div>\n </dialog>\n </>\n )\n}\n"],"names":["Button","Collapsible","useCallback","useId","useMemo","useRef","useState","closeNativeDialogOnBackdropPointer","formatBytes","getBackupSortTimeMs","transformBlobName","BackupItemActions","defaultFilterState","dateFrom","dateTo","label","media","showOtherDb","showOtherHostname","source","parseDateInputStartMs","isoDate","parts","split","map","Number","length","some","n","isFinite","y","m","d","t","Date","getTime","parseDateInputEndMs","passesDateMediaSource","parsed","displayMs","filters","from","to","fileType","type","labelQuery","trim","toLowerCase","blobLabel","includes","hasNonDefaultFilters","f","BackupListCollapsible","blobs","countOtherDb","countOtherHostname","currentDbName","currentHostname","i18nLanguage","uid","idDb","idHost","dialogRef","setFilters","visibleRows","rows","blob","pathname","dbName","hostname","isCurrentDb","isCurrentHostname","uploadedAt","push","displayAt","openFilterDialog","current","showModal","closeFilterDialog","close","clearFilters","hasScopeOptions","filtersActive","filtersButton","buttonStyle","className","onClick","header","span","initCollapsed","div","p","collectionCount","time","dateTime","toISOString","suppressHydrationWarning","toLocaleString","title","size","downloadUrl","url","dialog","onPointerDown","e","ref","h3","fieldset","legend","input","aria-label","checked","id","onChange","target","htmlFor","autoComplete","value","placeholder","spellCheck","name"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/BackupDashboard/BackupListCollapsible.client.tsx"],"sourcesContent":["'use client'\n\nimport { Button, Collapsible } from '@payloadcms/ui'\nimport { useCallback, useId, useMemo, useRef, useState } from 'react'\n\nimport type { TransformBlobNameResult } from '../../utils/index'\n\nimport { closeNativeDialogOnBackdropPointer } from '../../utils/dialogBackdrop'\nimport { formatBytes, getBackupSortTimeMs, transformBlobName } from '../../utils/index'\nimport { BackupItemActions } from './BackupItemActions.client'\n\nexport interface SerializableBackupBlob {\n downloadUrl: string\n pathname: string\n size: number\n uploadedAt: string\n url: string\n}\n\nexport interface BackupListCollapsibleProps {\n blobs: SerializableBackupBlob[]\n countOtherDb: number\n countOtherHostname: number\n currentDbName: string\n currentHostname: string\n i18nLanguage: string\n}\n\ninterface BackupListFilterState {\n dateFrom: string\n dateTo: string\n label: string\n media: 'all' | 'with' | 'without'\n showOtherDb: boolean\n showOtherHostname: boolean\n source: 'all' | 'cron' | 'manual'\n}\n\nconst defaultFilterState: BackupListFilterState = {\n dateFrom: '',\n dateTo: '',\n label: '',\n media: 'all',\n showOtherDb: true,\n showOtherHostname: false,\n source: 'all',\n}\n\nfunction parseDateInputStartMs(isoDate: string): null | number {\n const parts = isoDate.split('-').map(Number)\n if (parts.length !== 3 || parts.some((n) => !Number.isFinite(n))) {\n return null\n }\n const [y, m, d] = parts\n const t = new Date(y, m - 1, d, 0, 0, 0, 0).getTime()\n return Number.isFinite(t) ? t : null\n}\n\nfunction parseDateInputEndMs(isoDate: string): null | number {\n const parts = isoDate.split('-').map(Number)\n if (parts.length !== 3 || parts.some((n) => !Number.isFinite(n))) {\n return null\n }\n const [y, m, d] = parts\n const t = new Date(y, m - 1, d, 23, 59, 59, 999).getTime()\n return Number.isFinite(t) ? t : null\n}\n\nfunction passesDateMediaSource(\n parsed: TransformBlobNameResult,\n displayMs: number,\n filters: BackupListFilterState,\n): boolean {\n if (filters.dateFrom) {\n const from = parseDateInputStartMs(filters.dateFrom)\n if (from != null && displayMs < from) {\n return false\n }\n }\n if (filters.dateTo) {\n const to = parseDateInputEndMs(filters.dateTo)\n if (to != null && displayMs > to) {\n return false\n }\n }\n if (filters.media === 'with' && parsed.fileType !== 'tar.gz') {\n return false\n }\n if (filters.media === 'without' && parsed.fileType !== 'json') {\n return false\n }\n if (filters.source === 'manual' && parsed.type !== 'manual') {\n return false\n }\n if (filters.source === 'cron' && parsed.type !== 'cron') {\n return false\n }\n const labelQuery = filters.label.trim().toLowerCase()\n if (labelQuery) {\n const blobLabel = (parsed.label ?? '').toLowerCase()\n if (!blobLabel.includes(labelQuery)) {\n return false\n }\n }\n return true\n}\n\nfunction hasNonDefaultFilters(f: BackupListFilterState): boolean {\n return (\n f.dateFrom !== defaultFilterState.dateFrom ||\n f.dateTo !== defaultFilterState.dateTo ||\n f.label !== defaultFilterState.label ||\n f.media !== defaultFilterState.media ||\n f.source !== defaultFilterState.source ||\n f.showOtherDb !== defaultFilterState.showOtherDb ||\n f.showOtherHostname !== defaultFilterState.showOtherHostname\n )\n}\n\nexport const BackupListCollapsible: React.FC<BackupListCollapsibleProps> = ({\n blobs,\n countOtherDb,\n countOtherHostname,\n currentDbName,\n currentHostname,\n i18nLanguage,\n}) => {\n const uid = useId()\n const idDb = `${uid}-show-other-db`\n const idHost = `${uid}-show-other-host`\n const dialogRef = useRef<HTMLDialogElement>(null)\n const [filters, setFilters] = useState<BackupListFilterState>(defaultFilterState)\n\n const visibleRows = useMemo(() => {\n const rows: Array<{\n blob: SerializableBackupBlob\n displayAt: Date\n displayMs: number\n parsed: TransformBlobNameResult\n }> = []\n\n for (const blob of blobs) {\n const parsed = transformBlobName(blob.pathname)\n const { dbName, hostname } = parsed\n const isCurrentDb = currentDbName === dbName\n const isCurrentHostname = currentHostname === hostname\n if (!(filters.showOtherDb || isCurrentDb)) {\n continue\n }\n if (!(filters.showOtherHostname || isCurrentHostname)) {\n continue\n }\n\n const uploadedAt = new Date(blob.uploadedAt)\n const displayMs = getBackupSortTimeMs(parsed, uploadedAt)\n if (!passesDateMediaSource(parsed, displayMs, filters)) {\n continue\n }\n\n rows.push({\n blob,\n displayAt: new Date(displayMs),\n displayMs,\n parsed,\n })\n }\n\n return rows\n }, [blobs, currentDbName, currentHostname, filters])\n\n const openFilterDialog = useCallback(() => {\n dialogRef.current?.showModal()\n }, [])\n\n const closeFilterDialog = useCallback(() => {\n dialogRef.current?.close()\n }, [])\n\n const clearFilters = useCallback(() => {\n setFilters(defaultFilterState)\n }, [])\n\n const hasScopeOptions = countOtherDb > 0 || countOtherHostname > 0\n const filtersActive = hasNonDefaultFilters(filters)\n\n const filtersButton = (\n <Button\n buttonStyle=\"secondary\"\n className={\n filtersActive ?\n 'backup-dashboard__filter-btn backup-dashboard__filter-btn--active'\n : 'backup-dashboard__filter-btn'\n }\n onClick={openFilterDialog}\n type=\"button\"\n >\n Filters\n </Button>\n )\n\n return (\n <>\n <Collapsible\n header={<span className=\"backup-dashboard__collapsible-title\">Backup list</span>}\n initCollapsed={true}\n >\n <div className=\"backup-dashboard__backup-list-toolbar\">{filtersButton}</div>\n {blobs.length === 0 ?\n <p className=\"backup-dashboard__list-empty\">No backups yet</p>\n : visibleRows.length === 0 ?\n <p className=\"backup-dashboard__list-empty\">No backups match the current filters</p>\n : visibleRows.map(({ blob, displayAt, parsed }) => {\n const { type, collectionCount, dbName, fileType, hostname, label } = parsed\n const isCurrentDb = currentDbName === dbName\n const isCurrentHostname = currentHostname === hostname\n\n return (\n <div className=\"backup-item\" key={blob.pathname}>\n <div className=\"backup-item__main\">\n <div className=\"backup-item__primary\">\n <time\n className=\"backup-item__time\"\n dateTime={displayAt.toISOString()}\n suppressHydrationWarning\n >\n {displayAt.toLocaleString(i18nLanguage)}\n </time>\n <span\n className={`backup-item__pill backup-item__pill--kind backup-item__pill--${type === 'cron' ? 'cron' : 'manual'}`}\n >\n {type === 'cron' ? 'Cron backup' : 'Manual backup'}\n </span>\n {label ?\n <span\n className=\"backup-item__pill backup-item__pill--label\"\n title={`Label: ${label}`}\n >\n <span className=\"backup-item__pill-key\">Label</span>\n {label}\n </span>\n : null}\n </div>\n <div className=\"backup-item__meta\">\n <span\n className={`backup-item__pill backup-item__pill--db${isCurrentDb ? '' : ' backup-item__pill--warn'}`}\n >\n <span className=\"backup-item__pill-key\">\n {isCurrentDb ? 'DB' : 'other DB'}\n </span>\n {dbName || 'Unknown'}\n </span>\n <span\n className={`backup-item__pill backup-item__pill--host${isCurrentHostname ? '' : ' backup-item__pill--warn'}`}\n >\n <span className=\"backup-item__pill-key\">Host</span>\n {hostname || 'Unknown'}\n </span>\n {typeof collectionCount === 'number' ?\n <span className=\"backup-item__pill backup-item__pill--collections\">\n <span className=\"backup-item__pill-key\">Collections</span>\n {collectionCount}\n </span>\n : null}\n {fileType === 'tar.gz' ?\n <span className=\"backup-item__pill backup-item__pill--media\">With media</span>\n : fileType === 'json' ?\n <span className=\"backup-item__pill backup-item__pill--media\">\n Without media\n </span>\n : null}\n <span\n className=\"backup-item__pill backup-item__pill--size\"\n title={`${blob.size.toLocaleString(i18nLanguage)} bytes`}\n >\n <span className=\"backup-item__pill-key\">Size</span>\n <span className=\"backup-item__size-value\">{formatBytes(blob.size)}</span>\n </span>\n </div>\n </div>\n <BackupItemActions\n downloadUrl={blob.downloadUrl}\n pathname={blob.pathname}\n url={blob.url}\n />\n </div>\n )\n })\n }\n </Collapsible>\n\n <dialog\n className=\"backup-confirm-dialog backup-confirm-dialog--backup-list-filters\"\n onPointerDown={(e) => closeNativeDialogOnBackdropPointer(e, dialogRef)}\n ref={dialogRef}\n >\n <h3 className=\"backup-confirm-dialog__title\">Filter backups</h3>\n <p className=\"backup-confirm-dialog__subtitle\">\n All filters apply in the browser only. Current DB and hostname are always shown; enable\n the options below to include backups from other databases or hosts.\n </p>\n <div className=\"backup-confirm-dialog__body backup-list-filters__body\">\n {hasScopeOptions ?\n <fieldset className=\"backup-list-filters__fieldset\">\n <legend className=\"backup-list-filters__legend\">Scope</legend>\n {countOtherDb > 0 ?\n <div className=\"field-type checkbox backup-dashboard__collapsible-checkbox backup-list-filters__scope-row\">\n <input\n aria-label={`Show other databases (${countOtherDb} in list)`}\n checked={filters.showOtherDb}\n className=\"checkbox-input__input\"\n id={idDb}\n onChange={(e) => setFilters((f) => ({ ...f, showOtherDb: e.target.checked }))}\n type=\"checkbox\"\n />\n <label className=\"field-label\" htmlFor={idDb}>\n Show other DBs\n <span className=\"backup-list-filters__hint\"> ({countOtherDb} in list)</span>\n </label>\n </div>\n : null}\n {countOtherHostname > 0 ?\n <div className=\"field-type checkbox backup-dashboard__collapsible-checkbox backup-list-filters__scope-row\">\n <input\n aria-label={`Show other hostnames (${countOtherHostname} in list)`}\n checked={filters.showOtherHostname}\n className=\"checkbox-input__input\"\n id={idHost}\n onChange={(e) =>\n setFilters((f) => ({ ...f, showOtherHostname: e.target.checked }))\n }\n type=\"checkbox\"\n />\n <label className=\"field-label\" htmlFor={idHost}>\n Show other Hostnames\n <span className=\"backup-list-filters__hint\">\n {' '}\n ({countOtherHostname} in list)\n </span>\n </label>\n </div>\n : null}\n </fieldset>\n : null}\n\n <fieldset className=\"backup-list-filters__fieldset\">\n <legend className=\"backup-list-filters__legend\">Label</legend>\n <div className=\"backup-list-filters__row backup-list-filters__row--label\">\n <label className=\"backup-list-filters__label\" htmlFor={`${uid}-label`}>\n Search\n </label>\n <input\n aria-label=\"Filter backups by label text\"\n autoComplete=\"off\"\n className=\"backup-list-filters__text\"\n id={`${uid}-label`}\n onChange={(e) => setFilters((f) => ({ ...f, label: e.target.value }))}\n placeholder=\"Filter by label text\"\n spellCheck={false}\n type=\"text\"\n value={filters.label}\n />\n </div>\n </fieldset>\n\n <fieldset className=\"backup-list-filters__fieldset\">\n <legend className=\"backup-list-filters__legend\">Date range</legend>\n <div className=\"backup-list-filters__row\">\n <label className=\"backup-list-filters__label\" htmlFor={`${uid}-from`}>\n From\n </label>\n <input\n aria-label=\"Filter from date\"\n className=\"backup-list-filters__date\"\n id={`${uid}-from`}\n onChange={(e) => setFilters((f) => ({ ...f, dateFrom: e.target.value }))}\n type=\"date\"\n value={filters.dateFrom}\n />\n </div>\n <div className=\"backup-list-filters__row\">\n <label className=\"backup-list-filters__label\" htmlFor={`${uid}-to`}>\n To\n </label>\n <input\n aria-label=\"Filter to date\"\n className=\"backup-list-filters__date\"\n id={`${uid}-to`}\n onChange={(e) => setFilters((f) => ({ ...f, dateTo: e.target.value }))}\n type=\"date\"\n value={filters.dateTo}\n />\n </div>\n </fieldset>\n\n <fieldset className=\"backup-list-filters__fieldset\">\n <legend className=\"backup-list-filters__legend\">Media</legend>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Media filter: all backups\"\n checked={filters.media === 'all'}\n className=\"radio-input__input\"\n id={`${uid}-media-all`}\n name={`${uid}-media`}\n onChange={() => setFilters((f) => ({ ...f, media: 'all' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-media-all`}>\n All\n </label>\n </div>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Media filter: with media\"\n checked={filters.media === 'with'}\n className=\"radio-input__input\"\n id={`${uid}-media-with`}\n name={`${uid}-media`}\n onChange={() => setFilters((f) => ({ ...f, media: 'with' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-media-with`}>\n With media\n </label>\n </div>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Media filter: without media\"\n checked={filters.media === 'without'}\n className=\"radio-input__input\"\n id={`${uid}-media-without`}\n name={`${uid}-media`}\n onChange={() => setFilters((f) => ({ ...f, media: 'without' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-media-without`}>\n Without media\n </label>\n </div>\n </fieldset>\n\n <fieldset className=\"backup-list-filters__fieldset\">\n <legend className=\"backup-list-filters__legend\">Source</legend>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Source filter: all\"\n checked={filters.source === 'all'}\n className=\"radio-input__input\"\n id={`${uid}-source-all`}\n name={`${uid}-source`}\n onChange={() => setFilters((f) => ({ ...f, source: 'all' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-source-all`}>\n All\n </label>\n </div>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Source filter: manual backups\"\n checked={filters.source === 'manual'}\n className=\"radio-input__input\"\n id={`${uid}-source-manual`}\n name={`${uid}-source`}\n onChange={() => setFilters((f) => ({ ...f, source: 'manual' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-source-manual`}>\n Manual\n </label>\n </div>\n <div className=\"field-type radio backup-list-filters__radio-row\">\n <input\n aria-label=\"Source filter: cron backups\"\n checked={filters.source === 'cron'}\n className=\"radio-input__input\"\n id={`${uid}-source-cron`}\n name={`${uid}-source`}\n onChange={() => setFilters((f) => ({ ...f, source: 'cron' }))}\n type=\"radio\"\n />\n <label className=\"field-label\" htmlFor={`${uid}-source-cron`}>\n Cron\n </label>\n </div>\n </fieldset>\n </div>\n <div className=\"backup-confirm-dialog__actions\">\n <Button buttonStyle=\"secondary\" onClick={clearFilters} type=\"button\">\n Clear filters\n </Button>\n <Button onClick={closeFilterDialog} type=\"button\">\n Done\n </Button>\n </div>\n </dialog>\n </>\n )\n}\n"],"names":["Button","Collapsible","useCallback","useId","useMemo","useRef","useState","closeNativeDialogOnBackdropPointer","formatBytes","getBackupSortTimeMs","transformBlobName","BackupItemActions","defaultFilterState","dateFrom","dateTo","label","media","showOtherDb","showOtherHostname","source","parseDateInputStartMs","isoDate","parts","split","map","Number","length","some","n","isFinite","y","m","d","t","Date","getTime","parseDateInputEndMs","passesDateMediaSource","parsed","displayMs","filters","from","to","fileType","type","labelQuery","trim","toLowerCase","blobLabel","includes","hasNonDefaultFilters","f","BackupListCollapsible","blobs","countOtherDb","countOtherHostname","currentDbName","currentHostname","i18nLanguage","uid","idDb","idHost","dialogRef","setFilters","visibleRows","rows","blob","pathname","dbName","hostname","isCurrentDb","isCurrentHostname","uploadedAt","push","displayAt","openFilterDialog","current","showModal","closeFilterDialog","close","clearFilters","hasScopeOptions","filtersActive","filtersButton","buttonStyle","className","onClick","header","span","initCollapsed","div","p","collectionCount","time","dateTime","toISOString","suppressHydrationWarning","toLocaleString","title","size","downloadUrl","url","dialog","onPointerDown","e","ref","h3","fieldset","legend","input","aria-label","checked","id","onChange","target","htmlFor","autoComplete","value","placeholder","spellCheck","name"],"mappings":"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"}
|
|
@@ -86,6 +86,7 @@ export const BackupSettingsModal = ()=>{
|
|
|
86
86
|
});
|
|
87
87
|
const [pluginOverridesRetention, setPluginOverridesRetention] = useState(false);
|
|
88
88
|
const [cronInfo, setCronInfo] = useState(undefined);
|
|
89
|
+
const [storage, setStorage] = useState(undefined);
|
|
89
90
|
const [transferSummary, setTransferSummary] = useState(null);
|
|
90
91
|
const [activeTransfer, setActiveTransfer] = useState(null);
|
|
91
92
|
const [transferLive, setTransferLive] = useState(null);
|
|
@@ -173,6 +174,7 @@ export const BackupSettingsModal = ()=>{
|
|
|
173
174
|
});
|
|
174
175
|
setPluginOverridesRetention(settingsJson.pluginBackupsToKeepOverride === true);
|
|
175
176
|
setCronInfo(settingsJson.cron ?? null);
|
|
177
|
+
setStorage(settingsJson.storage);
|
|
176
178
|
setIncludeMediaBlobs(settingsJson.includeMediaForCron === true);
|
|
177
179
|
const skip = Array.isArray(settingsJson.skipMongoCollections) ? settingsJson.skipMongoCollections : [];
|
|
178
180
|
setSelected(selectedFromSkipMongoNames(previewJson, skip));
|
|
@@ -575,6 +577,88 @@ export const BackupSettingsModal = ()=>{
|
|
|
575
577
|
/*#__PURE__*/ _jsxs("div", {
|
|
576
578
|
className: "backup-confirm-dialog__body restore-preview",
|
|
577
579
|
children: [
|
|
580
|
+
storage ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
581
|
+
children: [
|
|
582
|
+
/*#__PURE__*/ _jsx("p", {
|
|
583
|
+
className: "restore-preview__sticky-heading",
|
|
584
|
+
children: "Storage target"
|
|
585
|
+
}),
|
|
586
|
+
storage.kind === 's3' ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
587
|
+
children: [
|
|
588
|
+
/*#__PURE__*/ _jsxs("p", {
|
|
589
|
+
className: "restore-preview__intro",
|
|
590
|
+
children: [
|
|
591
|
+
"Backups use ",
|
|
592
|
+
/*#__PURE__*/ _jsx("strong", {
|
|
593
|
+
children: "AWS S3"
|
|
594
|
+
}),
|
|
595
|
+
" (or S3-compatible). Selected via the",
|
|
596
|
+
' ',
|
|
597
|
+
/*#__PURE__*/ _jsx("code", {
|
|
598
|
+
children: "BACKUP_STORAGE"
|
|
599
|
+
}),
|
|
600
|
+
" environment variable."
|
|
601
|
+
]
|
|
602
|
+
}),
|
|
603
|
+
storage.s3 ? /*#__PURE__*/ _jsxs("p", {
|
|
604
|
+
className: "restore-preview__intro",
|
|
605
|
+
children: [
|
|
606
|
+
"Bucket ",
|
|
607
|
+
/*#__PURE__*/ _jsx("code", {
|
|
608
|
+
children: storage.s3.bucket
|
|
609
|
+
}),
|
|
610
|
+
" · region",
|
|
611
|
+
' ',
|
|
612
|
+
/*#__PURE__*/ _jsx("code", {
|
|
613
|
+
children: storage.s3.region
|
|
614
|
+
}),
|
|
615
|
+
storage.s3.endpoint ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
616
|
+
children: [
|
|
617
|
+
' ',
|
|
618
|
+
"· endpoint ",
|
|
619
|
+
/*#__PURE__*/ _jsx("code", {
|
|
620
|
+
children: storage.s3.endpoint
|
|
621
|
+
})
|
|
622
|
+
]
|
|
623
|
+
}) : null,
|
|
624
|
+
storage.s3.prefix ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
625
|
+
children: [
|
|
626
|
+
' ',
|
|
627
|
+
"· prefix ",
|
|
628
|
+
/*#__PURE__*/ _jsx("code", {
|
|
629
|
+
children: storage.s3.prefix
|
|
630
|
+
})
|
|
631
|
+
]
|
|
632
|
+
}) : null
|
|
633
|
+
]
|
|
634
|
+
}) : /*#__PURE__*/ _jsxs("p", {
|
|
635
|
+
className: "restore-preview__intro",
|
|
636
|
+
children: [
|
|
637
|
+
"Set ",
|
|
638
|
+
/*#__PURE__*/ _jsx("code", {
|
|
639
|
+
children: "BACKUP_S3_BUCKET"
|
|
640
|
+
}),
|
|
641
|
+
" (and credentials) to finish configuring S3."
|
|
642
|
+
]
|
|
643
|
+
})
|
|
644
|
+
]
|
|
645
|
+
}) : /*#__PURE__*/ _jsxs("p", {
|
|
646
|
+
className: "restore-preview__intro",
|
|
647
|
+
children: [
|
|
648
|
+
"Backups use ",
|
|
649
|
+
/*#__PURE__*/ _jsx("strong", {
|
|
650
|
+
children: "Vercel Blob"
|
|
651
|
+
}),
|
|
652
|
+
" (default). Set",
|
|
653
|
+
' ',
|
|
654
|
+
/*#__PURE__*/ _jsx("code", {
|
|
655
|
+
children: "BACKUP_STORAGE=s3"
|
|
656
|
+
}),
|
|
657
|
+
" in the environment to use AWS S3 instead."
|
|
658
|
+
]
|
|
659
|
+
})
|
|
660
|
+
]
|
|
661
|
+
}) : null,
|
|
578
662
|
phase !== 'idle' ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
579
663
|
children: [
|
|
580
664
|
/*#__PURE__*/ _jsx("p", {
|
|
@@ -738,144 +822,148 @@ export const BackupSettingsModal = ()=>{
|
|
|
738
822
|
})
|
|
739
823
|
]
|
|
740
824
|
}),
|
|
741
|
-
/*#__PURE__*/ _jsxs(
|
|
742
|
-
className: "restore-preview__sticky-heading",
|
|
825
|
+
storage?.kind === 's3' ? null : /*#__PURE__*/ _jsxs(_Fragment, {
|
|
743
826
|
children: [
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
/*#__PURE__*/ _jsx("span", {
|
|
747
|
-
className: "restore-preview__sticky-heading-hint",
|
|
748
|
-
children: "(optional)"
|
|
749
|
-
})
|
|
750
|
-
]
|
|
751
|
-
}),
|
|
752
|
-
/*#__PURE__*/ _jsxs("p", {
|
|
753
|
-
className: "restore-preview__intro",
|
|
754
|
-
children: [
|
|
755
|
-
"Separate Vercel Blob token for ",
|
|
756
|
-
/*#__PURE__*/ _jsx("code", {
|
|
757
|
-
children: "backups/"
|
|
758
|
-
}),
|
|
759
|
-
". Without one, archives share the default media store."
|
|
760
|
-
]
|
|
761
|
-
}),
|
|
762
|
-
/*#__PURE__*/ _jsxs("div", {
|
|
763
|
-
className: "restore-preview__settings-fields",
|
|
764
|
-
children: [
|
|
765
|
-
/*#__PURE__*/ _jsx("label", {
|
|
766
|
-
className: "restore-preview__settings-label",
|
|
767
|
-
htmlFor: "backup-blob-token",
|
|
768
|
-
children: "Backup Blob read/write token"
|
|
769
|
-
}),
|
|
770
|
-
/*#__PURE__*/ _jsxs("div", {
|
|
771
|
-
className: "restore-preview__blob-token-row",
|
|
827
|
+
/*#__PURE__*/ _jsxs("p", {
|
|
828
|
+
className: "restore-preview__sticky-heading",
|
|
772
829
|
children: [
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
autoComplete: "off",
|
|
776
|
-
className: "restore-preview__settings-input restore-preview__settings-input--wide",
|
|
777
|
-
id: "backup-blob-token",
|
|
778
|
-
onChange: (e)=>onChangeBackupBlobToken(e.target.value),
|
|
779
|
-
placeholder: "vercel_blob_rw_...",
|
|
780
|
-
spellCheck: false,
|
|
781
|
-
type: "text",
|
|
782
|
-
value: backupBlobReadWriteToken
|
|
783
|
-
}),
|
|
830
|
+
"Dedicated backup storage",
|
|
831
|
+
' ',
|
|
784
832
|
/*#__PURE__*/ _jsx("span", {
|
|
785
|
-
className: "restore-
|
|
786
|
-
children:
|
|
833
|
+
className: "restore-preview__sticky-heading-hint",
|
|
834
|
+
children: "(optional)"
|
|
787
835
|
})
|
|
788
836
|
]
|
|
789
837
|
}),
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
className: "restore-preview__blob-token-error",
|
|
793
|
-
children: tokenCheck.message
|
|
794
|
-
}) : null,
|
|
795
|
-
savePhase === 'transferring' && transferLive && transferLive.total > 0 ? /*#__PURE__*/ _jsxs("div", {
|
|
796
|
-
"aria-live": "polite",
|
|
797
|
-
className: "restore-preview__transfer-panel",
|
|
838
|
+
/*#__PURE__*/ _jsxs("p", {
|
|
839
|
+
className: "restore-preview__intro",
|
|
798
840
|
children: [
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
children:
|
|
802
|
-
className: "restore-preview__transfer-bar-fill",
|
|
803
|
-
style: {
|
|
804
|
-
width: `${Math.min(100, (transferLive.transferred + transferLive.failed) / transferLive.total * 100)}%`
|
|
805
|
-
}
|
|
806
|
-
})
|
|
841
|
+
"Separate Vercel Blob token for ",
|
|
842
|
+
/*#__PURE__*/ _jsx("code", {
|
|
843
|
+
children: "backups/"
|
|
807
844
|
}),
|
|
808
|
-
|
|
809
|
-
className: "restore-preview__transfer-meta",
|
|
810
|
-
children: [
|
|
811
|
-
"Copying backup files: ",
|
|
812
|
-
transferLive.transferred + transferLive.failed,
|
|
813
|
-
" /",
|
|
814
|
-
' ',
|
|
815
|
-
transferLive.total,
|
|
816
|
-
transferLive.failed > 0 ? ` (${transferLive.failed} failed)` : '',
|
|
817
|
-
transferLive.pathname ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
818
|
-
children: [
|
|
819
|
-
/*#__PURE__*/ _jsx("br", {}),
|
|
820
|
-
/*#__PURE__*/ _jsx("span", {
|
|
821
|
-
className: "restore-preview__transfer-path",
|
|
822
|
-
title: transferLive.pathname,
|
|
823
|
-
children: transferLive.pathname.length > 56 ? `${transferLive.pathname.slice(0, 28)}…${transferLive.pathname.slice(-24)}` : transferLive.pathname
|
|
824
|
-
})
|
|
825
|
-
]
|
|
826
|
-
}) : null
|
|
827
|
-
]
|
|
828
|
-
})
|
|
845
|
+
". Without one, archives share the default media store."
|
|
829
846
|
]
|
|
830
|
-
})
|
|
831
|
-
|
|
847
|
+
}),
|
|
848
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
849
|
+
className: "restore-preview__settings-fields",
|
|
832
850
|
children: [
|
|
851
|
+
/*#__PURE__*/ _jsx("label", {
|
|
852
|
+
className: "restore-preview__settings-label",
|
|
853
|
+
htmlFor: "backup-blob-token",
|
|
854
|
+
children: "Backup Blob read/write token"
|
|
855
|
+
}),
|
|
833
856
|
/*#__PURE__*/ _jsxs("div", {
|
|
834
|
-
className: "
|
|
857
|
+
className: "restore-preview__blob-token-row",
|
|
835
858
|
children: [
|
|
836
859
|
/*#__PURE__*/ _jsx("input", {
|
|
837
|
-
"aria-label": "
|
|
838
|
-
|
|
839
|
-
className: "
|
|
840
|
-
id:
|
|
841
|
-
onChange: (e)=>
|
|
842
|
-
|
|
860
|
+
"aria-label": "Backup Blob read/write token",
|
|
861
|
+
autoComplete: "off",
|
|
862
|
+
className: "restore-preview__settings-input restore-preview__settings-input--wide",
|
|
863
|
+
id: "backup-blob-token",
|
|
864
|
+
onChange: (e)=>onChangeBackupBlobToken(e.target.value),
|
|
865
|
+
placeholder: "vercel_blob_rw_...",
|
|
866
|
+
spellCheck: false,
|
|
867
|
+
type: "text",
|
|
868
|
+
value: backupBlobReadWriteToken
|
|
843
869
|
}),
|
|
844
|
-
/*#__PURE__*/ _jsx("
|
|
845
|
-
className: "
|
|
846
|
-
|
|
847
|
-
children: "Copy existing backup files into this storage when saving"
|
|
848
|
-
}),
|
|
849
|
-
/*#__PURE__*/ _jsx(SettingsHelpTip, {
|
|
850
|
-
multiline: true,
|
|
851
|
-
tip: TIP_TRANSFER_COPY
|
|
870
|
+
/*#__PURE__*/ _jsx("span", {
|
|
871
|
+
className: "restore-preview__blob-token-pill-slot",
|
|
872
|
+
children: tokenStatusPill
|
|
852
873
|
})
|
|
853
874
|
]
|
|
854
875
|
}),
|
|
855
|
-
|
|
856
|
-
|
|
876
|
+
tokenCheck.status === 'invalid' && tokenCheck.message ? /*#__PURE__*/ _jsx("p", {
|
|
877
|
+
"aria-live": "polite",
|
|
878
|
+
className: "restore-preview__blob-token-error",
|
|
879
|
+
children: tokenCheck.message
|
|
880
|
+
}) : null,
|
|
881
|
+
savePhase === 'transferring' && transferLive && transferLive.total > 0 ? /*#__PURE__*/ _jsxs("div", {
|
|
882
|
+
"aria-live": "polite",
|
|
883
|
+
className: "restore-preview__transfer-panel",
|
|
857
884
|
children: [
|
|
858
|
-
/*#__PURE__*/ _jsx("
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
/*#__PURE__*/ _jsx("label", {
|
|
867
|
-
className: "field-label",
|
|
868
|
-
htmlFor: deleteSourceOptId,
|
|
869
|
-
children: "Delete from previous storage after successful copy"
|
|
885
|
+
/*#__PURE__*/ _jsx("div", {
|
|
886
|
+
className: "restore-preview__transfer-bar-track",
|
|
887
|
+
children: /*#__PURE__*/ _jsx("div", {
|
|
888
|
+
className: "restore-preview__transfer-bar-fill",
|
|
889
|
+
style: {
|
|
890
|
+
width: `${Math.min(100, (transferLive.transferred + transferLive.failed) / transferLive.total * 100)}%`
|
|
891
|
+
}
|
|
892
|
+
})
|
|
870
893
|
}),
|
|
871
|
-
/*#__PURE__*/
|
|
872
|
-
|
|
873
|
-
|
|
894
|
+
/*#__PURE__*/ _jsxs("p", {
|
|
895
|
+
className: "restore-preview__transfer-meta",
|
|
896
|
+
children: [
|
|
897
|
+
"Copying backup files: ",
|
|
898
|
+
transferLive.transferred + transferLive.failed,
|
|
899
|
+
" /",
|
|
900
|
+
' ',
|
|
901
|
+
transferLive.total,
|
|
902
|
+
transferLive.failed > 0 ? ` (${transferLive.failed} failed)` : '',
|
|
903
|
+
transferLive.pathname ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
904
|
+
children: [
|
|
905
|
+
/*#__PURE__*/ _jsx("br", {}),
|
|
906
|
+
/*#__PURE__*/ _jsx("span", {
|
|
907
|
+
className: "restore-preview__transfer-path",
|
|
908
|
+
title: transferLive.pathname,
|
|
909
|
+
children: transferLive.pathname.length > 56 ? `${transferLive.pathname.slice(0, 28)}…${transferLive.pathname.slice(-24)}` : transferLive.pathname
|
|
910
|
+
})
|
|
911
|
+
]
|
|
912
|
+
}) : null
|
|
913
|
+
]
|
|
874
914
|
})
|
|
875
915
|
]
|
|
916
|
+
}) : null,
|
|
917
|
+
willSaveNewRawToken ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
918
|
+
children: [
|
|
919
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
920
|
+
className: "field-type checkbox backup-dashboard__collapsible-checkbox restore-preview__blob-transfer-row restore-preview__blob-transfer-row--with-help-tip",
|
|
921
|
+
children: [
|
|
922
|
+
/*#__PURE__*/ _jsx("input", {
|
|
923
|
+
"aria-label": "Copy existing backup files into this storage when saving",
|
|
924
|
+
checked: transferBackupBlobs,
|
|
925
|
+
className: "checkbox-input__input",
|
|
926
|
+
id: transferOptId,
|
|
927
|
+
onChange: (e)=>setTransferBackupBlobs(e.target.checked),
|
|
928
|
+
type: "checkbox"
|
|
929
|
+
}),
|
|
930
|
+
/*#__PURE__*/ _jsx("label", {
|
|
931
|
+
className: "field-label",
|
|
932
|
+
htmlFor: transferOptId,
|
|
933
|
+
children: "Copy existing backup files into this storage when saving"
|
|
934
|
+
}),
|
|
935
|
+
/*#__PURE__*/ _jsx(SettingsHelpTip, {
|
|
936
|
+
multiline: true,
|
|
937
|
+
tip: TIP_TRANSFER_COPY
|
|
938
|
+
})
|
|
939
|
+
]
|
|
940
|
+
}),
|
|
941
|
+
transferBackupBlobs ? /*#__PURE__*/ _jsxs("div", {
|
|
942
|
+
className: "field-type checkbox backup-dashboard__collapsible-checkbox restore-preview__blob-transfer-row restore-preview__blob-transfer-row--with-help-tip",
|
|
943
|
+
children: [
|
|
944
|
+
/*#__PURE__*/ _jsx("input", {
|
|
945
|
+
"aria-label": "Delete from previous storage after successful copy",
|
|
946
|
+
checked: deleteBackupBlobsFromSource,
|
|
947
|
+
className: "checkbox-input__input",
|
|
948
|
+
id: deleteSourceOptId,
|
|
949
|
+
onChange: (e)=>setDeleteBackupBlobsFromSource(e.target.checked),
|
|
950
|
+
type: "checkbox"
|
|
951
|
+
}),
|
|
952
|
+
/*#__PURE__*/ _jsx("label", {
|
|
953
|
+
className: "field-label",
|
|
954
|
+
htmlFor: deleteSourceOptId,
|
|
955
|
+
children: "Delete from previous storage after successful copy"
|
|
956
|
+
}),
|
|
957
|
+
/*#__PURE__*/ _jsx(SettingsHelpTip, {
|
|
958
|
+
multiline: true,
|
|
959
|
+
tip: TIP_TRANSFER_DELETE
|
|
960
|
+
})
|
|
961
|
+
]
|
|
962
|
+
}) : null
|
|
963
|
+
]
|
|
876
964
|
}) : null
|
|
877
965
|
]
|
|
878
|
-
})
|
|
966
|
+
})
|
|
879
967
|
]
|
|
880
968
|
}),
|
|
881
969
|
/*#__PURE__*/ _jsx(CollectionBackupPreviewBody, {
|