Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m41s
184 lines
4.9 KiB
React
184 lines
4.9 KiB
React
import {
|
|
IconTrash,
|
|
IconEdit,
|
|
IconCopy,
|
|
IconX,
|
|
IconNetwork,
|
|
IconDownload,
|
|
IconCheck
|
|
} from '@tabler/icons-react';
|
|
|
|
export default function ServerBulkActions({
|
|
selectedCount,
|
|
onClearSelection,
|
|
onBulkDelete,
|
|
onBulkChangeTunnel,
|
|
onBulkExport,
|
|
onBulkCopyLinks,
|
|
tunnelTypes = ['GRE', 'IPSec', 'WireGuard', 'OpenVPN']
|
|
}) {
|
|
if (selectedCount === 0) return null;
|
|
|
|
return (
|
|
<div
|
|
className="server-bulk-actions position-sticky rounded-3 shadow-lg mx-auto px-3 py-2"
|
|
style={{
|
|
bottom: '20px',
|
|
zIndex: 1050,
|
|
maxWidth: '720px',
|
|
animation: 'slideUp 0.2s ease',
|
|
background: 'linear-gradient(135deg, #1e293b 0%, #334155 100%)',
|
|
border: '1px solid rgba(255,255,255,0.1)'
|
|
}}
|
|
>
|
|
<div className="d-flex align-items-center justify-content-between gap-3">
|
|
{/* Счётчик выбранных */}
|
|
<div className="d-flex align-items-center gap-2">
|
|
<span
|
|
className="badge fs-6"
|
|
style={{
|
|
background: '#3b82f6',
|
|
color: '#fff',
|
|
padding: '6px 10px'
|
|
}}
|
|
>
|
|
{selectedCount}
|
|
</span>
|
|
<span style={{ color: '#e2e8f0', fontWeight: 500 }}>выбрано</span>
|
|
</div>
|
|
|
|
{/* Действия */}
|
|
<div className="d-flex align-items-center gap-2">
|
|
{/* Смена типа туннеля */}
|
|
<div className="dropdown">
|
|
<button
|
|
className="bulk-btn dropdown-toggle"
|
|
type="button"
|
|
data-bs-toggle="dropdown"
|
|
>
|
|
<IconNetwork size={15} />
|
|
<span>Туннель</span>
|
|
</button>
|
|
<div className="dropdown-menu dropdown-menu-dark">
|
|
<div className="dropdown-header">Сменить тип туннеля</div>
|
|
{tunnelTypes.map(tunnel => (
|
|
<button
|
|
key={tunnel}
|
|
className="dropdown-item"
|
|
onClick={() => onBulkChangeTunnel(tunnel)}
|
|
>
|
|
{tunnel}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Копировать ссылки */}
|
|
<button
|
|
className="bulk-btn"
|
|
onClick={onBulkCopyLinks}
|
|
title="Скопировать ссылки"
|
|
>
|
|
<IconCopy size={15} />
|
|
<span>Ссылки</span>
|
|
</button>
|
|
|
|
{/* Экспорт */}
|
|
<button
|
|
className="bulk-btn"
|
|
onClick={onBulkExport}
|
|
title="Экспорт"
|
|
>
|
|
<IconDownload size={15} />
|
|
<span>Экспорт</span>
|
|
</button>
|
|
|
|
<div style={{ width: '1px', height: '20px', background: 'rgba(255,255,255,0.2)', margin: '0 4px' }} />
|
|
|
|
{/* Удалить */}
|
|
<button
|
|
className="bulk-btn bulk-btn-danger"
|
|
onClick={onBulkDelete}
|
|
title="Удалить"
|
|
>
|
|
<IconTrash size={15} />
|
|
<span>Удалить</span>
|
|
</button>
|
|
|
|
{/* Отменить выделение */}
|
|
<button
|
|
className="bulk-btn-close"
|
|
onClick={onClearSelection}
|
|
title="Снять выделение"
|
|
>
|
|
<IconX size={16} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<style>{`
|
|
@keyframes slideUp {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.bulk-btn {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 6px 12px;
|
|
border: none;
|
|
border-radius: 6px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
color: #e2e8f0;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.15s ease;
|
|
}
|
|
|
|
.bulk-btn:hover {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
color: #fff;
|
|
}
|
|
|
|
.bulk-btn-danger {
|
|
background: rgba(239, 68, 68, 0.2);
|
|
color: #fca5a5;
|
|
}
|
|
|
|
.bulk-btn-danger:hover {
|
|
background: rgba(239, 68, 68, 0.4);
|
|
color: #fef2f2;
|
|
}
|
|
|
|
.bulk-btn-close {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 28px;
|
|
height: 28px;
|
|
padding: 0;
|
|
border: none;
|
|
border-radius: 6px;
|
|
background: rgba(255, 255, 255, 0.05);
|
|
color: #94a3b8;
|
|
cursor: pointer;
|
|
transition: all 0.15s ease;
|
|
}
|
|
|
|
.bulk-btn-close:hover {
|
|
background: rgba(255, 255, 255, 0.15);
|
|
color: #fff;
|
|
}
|
|
`}</style>
|
|
</div>
|
|
);
|
|
}
|