mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-30 02:23:47 +00:00
refactor: simplify RemnaWave sync tab - keep only panel sync
This commit is contained in:
@@ -664,9 +664,6 @@ interface SyncTabProps {
|
|||||||
onRunAutoSync: () => void;
|
onRunAutoSync: () => void;
|
||||||
onSyncFromPanel: () => void;
|
onSyncFromPanel: () => void;
|
||||||
onSyncToPanel: () => void;
|
onSyncToPanel: () => void;
|
||||||
onValidate: () => void;
|
|
||||||
onCleanup: () => void;
|
|
||||||
onSyncStatuses: () => void;
|
|
||||||
syncResults: Record<string, { success: boolean; message?: string } | null>;
|
syncResults: Record<string, { success: boolean; message?: string } | null>;
|
||||||
loadingStates: Record<string, boolean>;
|
loadingStates: Record<string, boolean>;
|
||||||
}
|
}
|
||||||
@@ -677,9 +674,6 @@ function SyncTab({
|
|||||||
onRunAutoSync,
|
onRunAutoSync,
|
||||||
onSyncFromPanel,
|
onSyncFromPanel,
|
||||||
onSyncToPanel,
|
onSyncToPanel,
|
||||||
onValidate,
|
|
||||||
onCleanup,
|
|
||||||
onSyncStatuses,
|
|
||||||
syncResults,
|
syncResults,
|
||||||
loadingStates,
|
loadingStates,
|
||||||
}: SyncTabProps) {
|
}: SyncTabProps) {
|
||||||
@@ -703,135 +697,98 @@ function SyncTab({
|
|||||||
<SyncIcon />
|
<SyncIcon />
|
||||||
{t('admin.remnawave.sync.autoSync', 'Auto Sync')}
|
{t('admin.remnawave.sync.autoSync', 'Auto Sync')}
|
||||||
</h3>
|
</h3>
|
||||||
<span
|
<div className="flex items-center gap-2">
|
||||||
className={`rounded-full px-2 py-0.5 text-xs ${
|
<span
|
||||||
autoSyncStatus.enabled
|
className={`rounded-full px-2 py-0.5 text-xs ${
|
||||||
? 'bg-success-500/20 text-success-400'
|
autoSyncStatus.enabled
|
||||||
: 'bg-dark-600 text-dark-400'
|
? 'bg-success-500/20 text-success-400'
|
||||||
}`}
|
: 'bg-dark-600 text-dark-400'
|
||||||
>
|
}`}
|
||||||
{autoSyncStatus.enabled ? 'Enabled' : 'Disabled'}
|
>
|
||||||
</span>
|
{autoSyncStatus.enabled ? 'Enabled' : 'Disabled'}
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
onClick={onRunAutoSync}
|
||||||
|
disabled={loadingStates.autoSync || autoSyncStatus.is_running}
|
||||||
|
className="flex items-center gap-1.5 rounded-lg bg-accent-500/20 px-3 py-1.5 text-sm text-accent-400 transition-colors hover:bg-accent-500/30 disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<RefreshIcon spinning={loadingStates.autoSync || autoSyncStatus.is_running} />
|
||||||
|
{t('admin.remnawave.sync.runNow', 'Run Now')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-4 text-sm lg:grid-cols-4">
|
<div className="grid grid-cols-2 gap-3 text-sm lg:grid-cols-4">
|
||||||
<div>
|
<div className="rounded-lg bg-dark-700/50 p-3">
|
||||||
<p className="text-dark-500">Schedule</p>
|
<p className="text-xs text-dark-500">
|
||||||
<p className="text-dark-200">
|
{t('admin.remnawave.sync.schedule', 'Schedule')}
|
||||||
|
</p>
|
||||||
|
<p className="mt-1 text-dark-200">
|
||||||
{autoSyncStatus.times.length > 0 ? autoSyncStatus.times.join(', ') : '—'}
|
{autoSyncStatus.times.length > 0 ? autoSyncStatus.times.join(', ') : '—'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="rounded-lg bg-dark-700/50 p-3">
|
||||||
<p className="text-dark-500">Next Run</p>
|
<p className="text-xs text-dark-500">
|
||||||
<p className="text-dark-200">
|
{t('admin.remnawave.sync.nextRun', 'Next Run')}
|
||||||
|
</p>
|
||||||
|
<p className="mt-1 text-dark-200">
|
||||||
{autoSyncStatus.next_run ? new Date(autoSyncStatus.next_run).toLocaleString() : '—'}
|
{autoSyncStatus.next_run ? new Date(autoSyncStatus.next_run).toLocaleString() : '—'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="rounded-lg bg-dark-700/50 p-3">
|
||||||
<p className="text-dark-500">Last Run</p>
|
<p className="text-xs text-dark-500">
|
||||||
<p className="text-dark-200">
|
{t('admin.remnawave.sync.lastRun', 'Last Run')}
|
||||||
|
</p>
|
||||||
|
<p className="mt-1 text-dark-200">
|
||||||
{autoSyncStatus.last_run_finished_at
|
{autoSyncStatus.last_run_finished_at
|
||||||
? new Date(autoSyncStatus.last_run_finished_at).toLocaleString()
|
? new Date(autoSyncStatus.last_run_finished_at).toLocaleString()
|
||||||
: '—'}
|
: '—'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="rounded-lg bg-dark-700/50 p-3">
|
||||||
<p className="text-dark-500">Status</p>
|
<p className="text-xs text-dark-500">{t('admin.remnawave.sync.status', 'Status')}</p>
|
||||||
<p
|
<p
|
||||||
className={
|
className={`mt-1 ${
|
||||||
autoSyncStatus.is_running
|
autoSyncStatus.is_running
|
||||||
? 'text-warning-400'
|
? 'text-warning-400'
|
||||||
: autoSyncStatus.last_run_success
|
: autoSyncStatus.last_run_success
|
||||||
? 'text-success-400'
|
? 'text-success-400'
|
||||||
: 'text-dark-200'
|
: 'text-dark-200'
|
||||||
}
|
}`}
|
||||||
>
|
>
|
||||||
{autoSyncStatus.is_running
|
{autoSyncStatus.is_running
|
||||||
? 'Running...'
|
? t('admin.remnawave.sync.running', 'Running...')
|
||||||
: autoSyncStatus.last_run_success
|
: autoSyncStatus.last_run_success
|
||||||
? 'Success'
|
? t('admin.remnawave.sync.success', 'Success')
|
||||||
: autoSyncStatus.last_run_error || '—'}
|
: autoSyncStatus.last_run_error || '—'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
|
||||||
onClick={onRunAutoSync}
|
|
||||||
disabled={loadingStates.autoSync || autoSyncStatus.is_running}
|
|
||||||
className="mt-4 flex items-center gap-2 rounded-lg bg-accent-500/20 px-4 py-2 text-accent-400 transition-colors hover:bg-accent-500/30 disabled:opacity-50"
|
|
||||||
>
|
|
||||||
<RefreshIcon spinning={loadingStates.autoSync || autoSyncStatus.is_running} />
|
|
||||||
{t('admin.remnawave.sync.runNow', 'Run Now')}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Manual Sync Options */}
|
{/* Manual Sync */}
|
||||||
<div>
|
<div className="grid gap-3 sm:grid-cols-2">
|
||||||
<h3 className="mb-3 text-sm font-medium text-dark-300">
|
<SyncCard
|
||||||
{t('admin.remnawave.sync.manual', 'Manual Sync')}
|
title={t('admin.remnawave.sync.fromPanel', 'Sync from Panel')}
|
||||||
</h3>
|
description={t(
|
||||||
<div className="space-y-3">
|
'admin.remnawave.sync.fromPanelDesc',
|
||||||
<SyncCard
|
'Import users from RemnaWave panel to bot',
|
||||||
title={t('admin.remnawave.sync.fromPanel', 'Sync from Panel')}
|
)}
|
||||||
description={t(
|
onAction={onSyncFromPanel}
|
||||||
'admin.remnawave.sync.fromPanelDesc',
|
isLoading={loadingStates.fromPanel}
|
||||||
'Import users from RemnaWave panel to bot database',
|
lastResult={syncResults.fromPanel}
|
||||||
)}
|
/>
|
||||||
onAction={onSyncFromPanel}
|
<SyncCard
|
||||||
isLoading={loadingStates.fromPanel}
|
title={t('admin.remnawave.sync.toPanel', 'Sync to Panel')}
|
||||||
lastResult={syncResults.fromPanel}
|
description={t(
|
||||||
/>
|
'admin.remnawave.sync.toPanelDesc',
|
||||||
<SyncCard
|
'Export users from bot to RemnaWave panel',
|
||||||
title={t('admin.remnawave.sync.toPanel', 'Sync to Panel')}
|
)}
|
||||||
description={t(
|
onAction={onSyncToPanel}
|
||||||
'admin.remnawave.sync.toPanelDesc',
|
isLoading={loadingStates.toPanel}
|
||||||
'Export users from bot database to RemnaWave panel',
|
lastResult={syncResults.toPanel}
|
||||||
)}
|
/>
|
||||||
onAction={onSyncToPanel}
|
|
||||||
isLoading={loadingStates.toPanel}
|
|
||||||
lastResult={syncResults.toPanel}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Subscriptions */}
|
|
||||||
<div>
|
|
||||||
<h3 className="mb-3 text-sm font-medium text-dark-300">
|
|
||||||
{t('admin.remnawave.sync.subscriptions', 'Subscriptions')}
|
|
||||||
</h3>
|
|
||||||
<div className="space-y-3">
|
|
||||||
<SyncCard
|
|
||||||
title={t('admin.remnawave.sync.validate', 'Validate')}
|
|
||||||
description={t(
|
|
||||||
'admin.remnawave.sync.validateDesc',
|
|
||||||
'Check and fix subscription inconsistencies',
|
|
||||||
)}
|
|
||||||
onAction={onValidate}
|
|
||||||
isLoading={loadingStates.validate}
|
|
||||||
lastResult={syncResults.validate}
|
|
||||||
/>
|
|
||||||
<SyncCard
|
|
||||||
title={t('admin.remnawave.sync.cleanup', 'Cleanup')}
|
|
||||||
description={t(
|
|
||||||
'admin.remnawave.sync.cleanupDesc',
|
|
||||||
'Remove orphaned subscriptions without users',
|
|
||||||
)}
|
|
||||||
onAction={onCleanup}
|
|
||||||
isLoading={loadingStates.cleanup}
|
|
||||||
lastResult={syncResults.cleanup}
|
|
||||||
/>
|
|
||||||
<SyncCard
|
|
||||||
title={t('admin.remnawave.sync.statuses', 'Sync Statuses')}
|
|
||||||
description={t(
|
|
||||||
'admin.remnawave.sync.statusesDesc',
|
|
||||||
'Synchronize subscription statuses with panel',
|
|
||||||
)}
|
|
||||||
onAction={onSyncStatuses}
|
|
||||||
isLoading={loadingStates.statuses}
|
|
||||||
lastResult={syncResults.statuses}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -1074,11 +1031,6 @@ export default function AdminRemnawave() {
|
|||||||
handleSyncAction('fromPanel', () => adminRemnawaveApi.syncFromPanel('all'))
|
handleSyncAction('fromPanel', () => adminRemnawaveApi.syncFromPanel('all'))
|
||||||
}
|
}
|
||||||
onSyncToPanel={() => handleSyncAction('toPanel', adminRemnawaveApi.syncToPanel)}
|
onSyncToPanel={() => handleSyncAction('toPanel', adminRemnawaveApi.syncToPanel)}
|
||||||
onValidate={() => handleSyncAction('validate', adminRemnawaveApi.validateSubscriptions)}
|
|
||||||
onCleanup={() => handleSyncAction('cleanup', adminRemnawaveApi.cleanupSubscriptions)}
|
|
||||||
onSyncStatuses={() =>
|
|
||||||
handleSyncAction('statuses', adminRemnawaveApi.syncSubscriptionStatuses)
|
|
||||||
}
|
|
||||||
syncResults={syncResults}
|
syncResults={syncResults}
|
||||||
loadingStates={loadingStates}
|
loadingStates={loadingStates}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user