mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 21:00:41 +00:00
f0ace28bf2
- Introduced `shared.ts` with utility functions for API interactions, including JSON parsing, error handling, and content disposition parsing. - Added `vault.ts` to manage vault-related operations such as folder and cipher management, including creation, deletion, and bulk operations. - Implemented encryption and decryption methods for secure data handling within the vault. - Created `backup-settings-repair.ts` to automatically repair backup settings for admin profiles if needed.
71 lines
2.9 KiB
TypeScript
71 lines
2.9 KiB
TypeScript
import { Plus } from 'lucide-preact';
|
|
import type { BackupDestinationRecord, BackupDestinationType } from '@/lib/api/backup';
|
|
import { formatDateTime, getDestinationTypeLabel } from '@/lib/backup-center';
|
|
import { t } from '@/lib/i18n';
|
|
|
|
interface BackupDestinationSidebarProps {
|
|
destinations: BackupDestinationRecord[];
|
|
selectedDestinationId: string | null;
|
|
disableWhileBusy: boolean;
|
|
showAddChooser: boolean;
|
|
onSelectDestination: (destinationId: string) => void;
|
|
onToggleAddChooser: () => void;
|
|
onAddDestination: (type: BackupDestinationType) => void;
|
|
}
|
|
|
|
export function BackupDestinationSidebar(props: BackupDestinationSidebarProps) {
|
|
return (
|
|
<aside className="backup-destination-sidebar">
|
|
<div className="section-head">
|
|
<h3>{t('txt_backup_destinations_title')}</h3>
|
|
</div>
|
|
|
|
<div className="backup-destination-list">
|
|
{props.destinations.map((destination) => {
|
|
const isSelected = destination.id === props.selectedDestinationId;
|
|
const isScheduled = destination.schedule.enabled;
|
|
return (
|
|
<button
|
|
key={destination.id}
|
|
type="button"
|
|
className={`backup-destination-item ${isSelected ? 'active' : ''}`}
|
|
onClick={() => props.onSelectDestination(destination.id)}
|
|
>
|
|
<span className="backup-destination-top">
|
|
<span className="backup-destination-name">{destination.name || getDestinationTypeLabel(destination.type)}</span>
|
|
<span className="backup-destination-type">{getDestinationTypeLabel(destination.type)}</span>
|
|
</span>
|
|
<span className="backup-destination-meta">
|
|
{isScheduled ? t('txt_backup_destination_active_badge') : t('txt_backup_destination_idle_badge')}
|
|
</span>
|
|
<span className="backup-destination-meta">
|
|
{destination.runtime.lastSuccessAt
|
|
? t('txt_backup_destination_last_success', { time: formatDateTime(destination.runtime.lastSuccessAt) })
|
|
: t('txt_backup_destination_never_run')}
|
|
</span>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
<div className="actions backup-destination-addbar">
|
|
<button type="button" className="btn btn-secondary small" disabled={props.disableWhileBusy} onClick={props.onToggleAddChooser}>
|
|
<Plus size={14} className="btn-icon" />
|
|
{t('txt_backup_add_destination')}
|
|
</button>
|
|
</div>
|
|
|
|
{props.showAddChooser ? (
|
|
<div className="backup-add-chooser">
|
|
<button type="button" className="btn btn-secondary small" onClick={() => props.onAddDestination('webdav')}>
|
|
{t('txt_backup_protocol_webdav')}
|
|
</button>
|
|
<button type="button" className="btn btn-secondary small" onClick={() => props.onAddDestination('e3')}>
|
|
{t('txt_backup_protocol_e3')}
|
|
</button>
|
|
</div>
|
|
) : null}
|
|
</aside>
|
|
);
|
|
}
|