chore(ui): replaced all server ui icons with gravity-ui icons

This commit is contained in:
Naterfute
2025-11-02 20:26:55 -08:00
parent 03cbf3657e
commit 37af850a40
22 changed files with 301 additions and 222 deletions

View File

@@ -1,3 +1,4 @@
import { ArrowDownToLine, ClockArrowRotateLeft, Funnel, Magnifier, Xmark } from '@gravity-ui/icons';
import { useEffect, useMemo, useState } from 'react';
import FlashMessageRender from '@/components/FlashMessageRender';
@@ -7,11 +8,6 @@ import Select from '@/components/elements/Select';
import ServerContentBlock from '@/components/elements/ServerContentBlock';
import Spinner from '@/components/elements/Spinner';
import ActivityLogEntry from '@/components/elements/activity/ActivityLogEntry';
import HugeIconsDownload from '@/components/elements/hugeicons/Download';
import HugeIconsFilter from '@/components/elements/hugeicons/Filter';
import HugeIconsHistory from '@/components/elements/hugeicons/History';
import HugeIconsSearch from '@/components/elements/hugeicons/Search';
import HugeIconsX from '@/components/elements/hugeicons/X';
import { Input } from '@/components/elements/inputs';
import PaginationFooter from '@/components/elements/table/PaginationFooter';
@@ -178,7 +174,7 @@ const ServerActivityLogContainer = () => {
className='flex items-center gap-2'
title='Toggle Filters (Ctrl+F)'
>
<HugeIconsFilter className='w-4 h-4' fill='currentColor' />
<Funnel width={22} height={22} className='w-4 h-4' fill='currentColor' />
Filters
{hasActiveFilters && <span className='w-2 h-2 bg-brand rounded-full'></span>}
</ActionButton>
@@ -189,7 +185,7 @@ const ServerActivityLogContainer = () => {
className='flex items-center gap-2'
title='Export CSV (Ctrl+E)'
>
<HugeIconsDownload className='w-4 h-4' fill='currentColor' />
<ArrowDownToLine width={22} height={22} className='w-4 h-4' fill='currentColor' />
Export
</ActionButton>
</div>
@@ -214,7 +210,12 @@ const ServerActivityLogContainer = () => {
<div className='bg-gradient-to-b from-[#ffffff08] to-[#ffffff05] border-[1px] border-[#ffffff12] rounded-xl p-4 hover:border-[#ffffff20] transition-all duration-150 shadow-sm'>
<div className='flex items-center gap-2 mb-4'>
<div className='w-5 h-5 rounded-lg bg-[#ffffff11] flex items-center justify-center'>
<HugeIconsFilter className='w-2.5 h-2.5 text-zinc-400' fill='currentColor' />
<Funnel
width={22}
height={22}
className='w-2.5 h-2.5 text-zinc-400'
fill='currentColor'
/>
</div>
<h3 className='text-base font-semibold text-zinc-100'>Filters</h3>
</div>
@@ -223,7 +224,9 @@ const ServerActivityLogContainer = () => {
<div>
<label className='block text-sm font-medium text-zinc-300 mb-2'>Search</label>
<div className='relative'>
<HugeIconsSearch
<Magnifier
width={22}
height={22}
className='absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-zinc-400 pointer-events-none z-10'
fill='currentColor'
/>
@@ -291,7 +294,7 @@ const ServerActivityLogContainer = () => {
onClick={clearAllFilters}
className='flex items-center gap-2 w-full'
>
<HugeIconsX className='w-4 h-4' fill='currentColor' />
<Xmark width={22} height={22} className='w-4 h-4' fill='currentColor' />
Clear All Filters
</ActionButton>
)}
@@ -312,7 +315,12 @@ const ServerActivityLogContainer = () => {
<div className='bg-gradient-to-b from-[#ffffff08] to-[#ffffff05] border-[1px] border-[#ffffff12] rounded-xl p-4 hover:border-[#ffffff20] transition-all duration-150 shadow-sm'>
<div className='flex items-center gap-2 mb-4'>
<div className='w-5 h-5 rounded-lg bg-[#ffffff11] flex items-center justify-center'>
<HugeIconsHistory className='w-2.5 h-2.5 text-zinc-400' fill='currentColor' />
<ClockArrowRotateLeft
width={22}
height={22}
className=' text-zinc-400'
fill='currentColor'
/>
</div>
<h3 className='text-base font-semibold text-zinc-100'>Events</h3>
{filteredData?.items && (
@@ -326,7 +334,12 @@ const ServerActivityLogContainer = () => {
<Spinner centered />
) : !filteredData?.items?.length ? (
<div className='text-center py-12'>
<HugeIconsHistory className='w-16 h-16 text-zinc-600 mb-4' fill='currentColor' />
<ClockArrowRotateLeft
width={22}
height={22}
className=' text-zinc-600 mb-4'
fill='currentColor'
/>
<h3 className='text-lg font-semibold text-zinc-300 mb-2'>
{hasActiveFilters ? 'No Matching Activity' : 'No Server Activity Yet'}
</h3>

View File

@@ -1,6 +1,16 @@
import { useEffect, useState } from 'react';
import {
ArrowDownToLine,
Bars,
CloudArrowUpIn,
Pencil,
Shield,
TrashBin,
TriangleExclamation,
} from '@gravity-ui/icons';
import { useStoreState } from 'easy-peasy';
import { useEffect, useState } from 'react';
import FlashMessageRender from '@/components/FlashMessageRender';
import ActionButton from '@/components/elements/ActionButton';
import Can from '@/components/elements/Can';
import {
@@ -10,28 +20,19 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/elements/DropdownMenu';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import Spinner from '@/components/elements/Spinner';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import { Dialog } from '@/components/elements/dialog';
import HugeIconsAlert from '@/components/elements/hugeicons/Alert';
import HugeIconsCloudUp from '@/components/elements/hugeicons/CloudUp';
import HugeIconsDelete from '@/components/elements/hugeicons/Delete';
import HugeIconsFileDownload from '@/components/elements/hugeicons/FileDownload';
import HugeIconsFileSecurity from '@/components/elements/hugeicons/FileSecurity';
import HugeIconsPencil from '@/components/elements/hugeicons/Pencil';
import HugeIconsHamburger from '@/components/elements/hugeicons/hamburger';
import FlashMessageRender from '@/components/FlashMessageRender';
import http, { httpErrorToHuman } from '@/api/http';
import {
getServerBackupDownloadUrl,
} from '@/api/server/backups';
import { getServerBackupDownloadUrl } from '@/api/server/backups';
import { ServerBackup } from '@/api/server/types';
import { ApplicationStore } from '@/state';
import { ServerContext } from '@/state/server';
import useFlash from '@/plugins/useFlash';
import { useUnifiedBackups } from './useUnifiedBackups';
interface Props {
@@ -244,11 +245,15 @@ const BackupContextMenu = ({ backup }: Props) => {
>
This backup will no longer be protected from automated or accidental deletions.
</Dialog.Confirm>
<Dialog open={modal === 'restore'} onClose={() => {
setModal('');
setRestorePassword('');
setRestoreTotpCode('');
}} title='Restore Backup'>
<Dialog
open={modal === 'restore'}
onClose={() => {
setModal('');
setRestorePassword('');
setRestoreTotpCode('');
}}
title='Restore Backup'
>
<FlashMessageRender byKey={'backup:restore'} />
<div className='space-y-4'>
<div className='space-y-2'>
@@ -261,7 +266,12 @@ const BackupContextMenu = ({ backup }: Props) => {
<div className='p-4 bg-red-500/10 border border-red-500/20 rounded-lg'>
<div className='flex items-start space-x-3'>
<HugeIconsAlert fill='currentColor' className='w-5 h-5 text-red-400 flex-shrink-0 mt-0.5' />
<TriangleExclamation
width={22}
height={22}
fill='currentColor'
className=' text-red-400 flex-shrink-0 mt-0.5'
/>
<div className='space-y-1'>
<h4 className='text-sm text-red-200 font-medium'>
Destructive Action - Complete Server Restore
@@ -274,16 +284,16 @@ const BackupContextMenu = ({ backup }: Props) => {
</div>
</div>
<div className="space-y-3">
<div className='space-y-3'>
<div>
<label htmlFor="restore-password" className="block text-sm font-medium text-zinc-300 mb-1">
<label htmlFor='restore-password' className='block text-sm font-medium text-zinc-300 mb-1'>
Password
</label>
<input
id="restore-password"
type="password"
className="w-full px-4 py-2 rounded-lg outline-hidden bg-[#ffffff17] text-sm border border-zinc-700 focus:border-brand"
placeholder="Enter your password"
id='restore-password'
type='password'
className='w-full px-4 py-2 rounded-lg outline-hidden bg-[#ffffff17] text-sm border border-zinc-700 focus:border-brand'
placeholder='Enter your password'
value={restorePassword}
onChange={(e) => setRestorePassword(e.target.value)}
disabled={loading}
@@ -292,14 +302,14 @@ const BackupContextMenu = ({ backup }: Props) => {
{hasTwoFactor && (
<div>
<label htmlFor="restore-totp" className="block text-sm font-medium text-zinc-300 mb-1">
<label htmlFor='restore-totp' className='block text-sm font-medium text-zinc-300 mb-1'>
Two-Factor Authentication Code
</label>
<input
id="restore-totp"
type="text"
className="w-full px-4 py-2 rounded-lg outline-hidden bg-[#ffffff17] text-sm border border-zinc-700 focus:border-brand"
placeholder="6-digit code"
id='restore-totp'
type='text'
className='w-full px-4 py-2 rounded-lg outline-hidden bg-[#ffffff17] text-sm border border-zinc-700 focus:border-brand'
placeholder='6-digit code'
maxLength={6}
value={restoreTotpCode}
onChange={(e) => setRestoreTotpCode(e.target.value.replace(/[^0-9]/g, ''))}
@@ -311,55 +321,80 @@ const BackupContextMenu = ({ backup }: Props) => {
</div>
<Dialog.Footer>
<ActionButton onClick={() => {
setModal('');
setRestorePassword('');
setRestoreTotpCode('');
}} variant='secondary' disabled={loading}>
<ActionButton
onClick={() => {
setModal('');
setRestorePassword('');
setRestoreTotpCode('');
}}
variant='secondary'
disabled={loading}
>
Cancel
</ActionButton>
<ActionButton onClick={() => doRestorationAction()} variant='danger' disabled={countdown > 0 || loading}>
<ActionButton
onClick={() => doRestorationAction()}
variant='danger'
disabled={countdown > 0 || loading}
>
{loading && <Spinner size='small' />}
{loading ? 'Restoring...' : countdown > 0 ? `Delete All & Restore (${countdown}s)` : 'Delete All & Restore Backup'}
{loading
? 'Restoring...'
: countdown > 0
? `Delete All & Restore (${countdown}s)`
: 'Delete All & Restore Backup'}
</ActionButton>
</Dialog.Footer>
</Dialog>
<Dialog open={modal === 'delete'} onClose={() => {
setModal('');
setDeletePassword('');
setDeleteTotpCode('');
}} title={`Delete "${backup.name}"`}>
<Dialog
open={modal === 'delete'}
onClose={() => {
setModal('');
setDeletePassword('');
setDeleteTotpCode('');
}}
title={`Delete "${backup.name}"`}
>
<FlashMessageRender byKey={'backup:delete'} />
<div className="space-y-4">
<p className="text-sm text-zinc-300">
<div className='space-y-4'>
<p className='text-sm text-zinc-300'>
This is a permanent operation. The backup cannot be recovered once deleted.
</p>
<div className="p-4 bg-red-500/10 border border-red-500/20 rounded-lg">
<div className="flex items-start gap-3">
<svg className="w-5 h-5 text-red-400 mt-0.5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
<div className='p-4 bg-red-500/10 border border-red-500/20 rounded-lg'>
<div className='flex items-start gap-3'>
<svg
className='w-5 h-5 text-red-400 mt-0.5 flex-shrink-0'
fill='none'
viewBox='0 0 24 24'
stroke='currentColor'
>
<path
strokeLinecap='round'
strokeLinejoin='round'
strokeWidth={2}
d='M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z'
/>
</svg>
<div className="text-sm">
<p className="font-medium text-red-300">Warning</p>
<p className="text-red-400 mt-1">
<div className='text-sm'>
<p className='font-medium text-red-300'>Warning</p>
<p className='text-red-400 mt-1'>
The backup file and its snapshot will be permanently deleted.
</p>
</div>
</div>
</div>
<div className="space-y-3">
<div className='space-y-3'>
<div>
<label htmlFor="delete-password" className="block text-sm font-medium text-zinc-300 mb-1">
<label htmlFor='delete-password' className='block text-sm font-medium text-zinc-300 mb-1'>
Password
</label>
<input
id="delete-password"
type="password"
className="w-full px-4 py-2 rounded-lg outline-hidden bg-[#ffffff17] text-sm border border-zinc-700 focus:border-brand"
placeholder="Enter your password"
id='delete-password'
type='password'
className='w-full px-4 py-2 rounded-lg outline-hidden bg-[#ffffff17] text-sm border border-zinc-700 focus:border-brand'
placeholder='Enter your password'
value={deletePassword}
onChange={(e) => setDeletePassword(e.target.value)}
disabled={loading}
@@ -368,14 +403,14 @@ const BackupContextMenu = ({ backup }: Props) => {
{hasTwoFactor && (
<div>
<label htmlFor="delete-totp" className="block text-sm font-medium text-zinc-300 mb-1">
<label htmlFor='delete-totp' className='block text-sm font-medium text-zinc-300 mb-1'>
Two-Factor Authentication Code
</label>
<input
id="delete-totp"
type="text"
className="w-full px-4 py-2 rounded-lg outline-hidden bg-[#ffffff17] text-sm border border-zinc-700 focus:border-brand"
placeholder="6-digit code"
id='delete-totp'
type='text'
className='w-full px-4 py-2 rounded-lg outline-hidden bg-[#ffffff17] text-sm border border-zinc-700 focus:border-brand'
placeholder='6-digit code'
maxLength={6}
value={deleteTotpCode}
onChange={(e) => setDeleteTotpCode(e.target.value.replace(/[^0-9]/g, ''))}
@@ -398,11 +433,7 @@ const BackupContextMenu = ({ backup }: Props) => {
>
Cancel
</ActionButton>
<ActionButton
variant='danger'
onClick={doDeletion}
disabled={loading}
>
<ActionButton variant='danger' onClick={doDeletion} disabled={loading}>
{loading && <Spinner size='small' />}
{loading ? 'Deleting...' : 'Delete Backup'}
</ActionButton>
@@ -418,30 +449,32 @@ const BackupContextMenu = ({ backup }: Props) => {
disabled={loading}
className='flex items-center justify-center w-8 h-8 p-0 hover:bg-zinc-700'
>
<HugeIconsHamburger className='h-4 w-4' fill='currentColor' />
<div>
<Bars width={22} height={22} fill='currentColor' />
</div>
</ActionButton>
</DropdownMenuTrigger>
<DropdownMenuContent align='end' className='w-48'>
<Can action={'backup.download'}>
<DropdownMenuItem onClick={doDownload} className='cursor-pointer'>
<HugeIconsFileDownload className='h-4 w-4 mr-2' fill='currentColor' />
<ArrowDownToLine width={22} height={22} className='mr-2' fill='currentColor' />
Download
</DropdownMenuItem>
</Can>
<Can action={'backup.restore'}>
<DropdownMenuItem onClick={() => setModal('restore')} className='cursor-pointer'>
<HugeIconsCloudUp className='h-4 w-4 mr-2' fill='currentColor' />
<CloudArrowUpIn width={22} height={22} className=' mr-2' fill='currentColor' />
Restore
</DropdownMenuItem>
</Can>
<Can action={'backup.delete'}>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => setModal('rename')} className='cursor-pointer'>
<HugeIconsPencil className='h-4 w-4 mr-2' fill='currentColor' />
<Pencil width={22} height={22} className=' mr-2' fill='currentColor' />
Rename
</DropdownMenuItem>
<DropdownMenuItem onClick={onLockToggle} className='cursor-pointer'>
<HugeIconsFileSecurity className='h-4 w-4 mr-2' fill='currentColor' />
<Shield width={22} height={22} className=' mr-2' fill='currentColor' />
{backup.isLocked ? 'Unlock' : 'Lock'}
</DropdownMenuItem>
{!backup.isLocked && (
@@ -451,7 +484,7 @@ const BackupContextMenu = ({ backup }: Props) => {
onClick={() => setModal('delete')}
className='cursor-pointer text-red-400 focus:text-red-300'
>
<HugeIconsDelete className='h-4 w-4 mr-2' fill='currentColor' />
<TrashBin width={22} height={22} className=' mr-2' fill='currentColor' />
Delete
</DropdownMenuItem>
</>
@@ -467,7 +500,7 @@ const BackupContextMenu = ({ backup }: Props) => {
disabled={loading}
className='flex items-center gap-2'
>
<HugeIconsDelete className='h-4 w-4' fill='currentColor' />
<TrashBin width={22} height={22} fill='currentColor' />
<span className='hidden sm:inline'>Delete</span>
</ActionButton>
)}

View File

@@ -1,11 +1,9 @@
import { Cloud, CloudArrowUpIn, Lock } from '@gravity-ui/icons';
import { format, formatDistanceToNow } from 'date-fns';
import Can from '@/components/elements/Can';
import { Checkbox } from '@/components/elements/CheckboxNew';
import Spinner from '@/components/elements/Spinner';
import HugeIconsSquareLock from '@/components/elements/hugeicons/SquareLock';
import HugeIconsStorage from '@/components/elements/hugeicons/Storage';
import HugeIconsRefresh from '@/components/elements/hugeicons/Refresh';
import { PageListItem } from '@/components/elements/pages/PageList';
import { bytesToString } from '@/lib/formatters';
@@ -46,7 +44,6 @@ interface Props {
const BackupItem = ({ backup, isSelected = false, onToggleSelect, isSelectable = false, retryBackup }: Props) => {
const { addFlash, clearFlashes } = useFlash();
const handleRetry = async () => {
if (!backup.canRetry) return;
@@ -75,11 +72,11 @@ const BackupItem = ({ backup, isSelected = false, onToggleSelect, isSelectable =
if (isActive) {
return <Spinner size={'small'} />;
} else if (backup.isLocked) {
return <HugeIconsSquareLock className='text-red-400 w-4 h-4' fill='currentColor' />;
return <Lock width={22} height={22} className='text-red-400 ' fill='currentColor' />;
} else if (backup.status === 'completed' || backup.isSuccessful) {
return <HugeIconsStorage className='text-green-400 w-4 h-4' fill='currentColor' />;
return <Cloud width={22} height={22} className='text-green-400 ' fill='currentColor' />;
} else {
return <HugeIconsStorage className='text-red-400 w-4 h-4' fill='currentColor' />;
return <Cloud width={22} height={22} className='text-red-400 ' fill='currentColor' />;
}
};
@@ -172,9 +169,8 @@ const BackupItem = ({ backup, isSelected = false, onToggleSelect, isSelectable =
</div>
<div className='w-full bg-zinc-700 rounded-full h-2'>
<div
className={`h-2 rounded-full transition-all duration-300 ${
backup.status === 'completed' ? 'bg-green-500' : 'bg-blue-500'
}`}
className={`h-2 rounded-full transition-all duration-300 ${backup.status === 'completed' ? 'bg-green-500' : 'bg-blue-500'
}`}
style={{ width: `${backup.progress || 0}%` }}
/>
</div>
@@ -187,7 +183,6 @@ const BackupItem = ({ backup, isSelected = false, onToggleSelect, isSelectable =
)}
{backup.checksum && <p className='text-xs text-zinc-400 font-mono truncate'>{backup.checksum}</p>}
</div>
{/* Size info for completed backups */}
@@ -226,7 +221,7 @@ const BackupItem = ({ backup, isSelected = false, onToggleSelect, isSelectable =
className='p-2 rounded-lg bg-blue-500/10 border border-blue-500/20 text-blue-400 hover:bg-blue-500/20 transition-colors'
title='Retry backup'
>
<HugeIconsRefresh className='w-4 h-4' />
<CloudArrowUpIn width={22} height={22} />
</button>
</Can>
)}
@@ -250,7 +245,7 @@ const BackupItem = ({ backup, isSelected = false, onToggleSelect, isSelectable =
jobMessage: backup.message,
jobId: '',
jobError: null,
object: 'backup' as const
object: 'backup' as const,
}}
/>
)}
@@ -261,4 +256,5 @@ const BackupItem = ({ backup, isSelected = false, onToggleSelect, isSelectable =
);
};
export default BackupItem;
export default BackupItem;

View File

@@ -43,8 +43,8 @@ const ServerConsoleContainer = () => {
{isNodeUnderMaintenance
? 'The node of this server is currently under maintenance and all actions are unavailable.'
: isInstalling
? 'This server is currently running its installation process and most actions are unavailable.'
: 'This server is currently being transferred to another node and all actions are unavailable.'}
? 'This server is currently running its installation process and most actions are unavailable.'
: 'This server is currently being transferred to another node and all actions are unavailable.'}
</Alert>
</div>
)}

View File

@@ -1,9 +1,9 @@
import { ArrowsRotateRight } from '@gravity-ui/icons';
import { Actions, useStoreActions } from 'easy-peasy';
import { useState } from 'react';
import ActionButton from '@/components/elements/ActionButton';
import Spinner from '@/components/elements/Spinner';
import HugeIconsRefresh from '@/components/elements/hugeicons/Refresh';
import { httpErrorToHuman } from '@/api/http';
import { ServerDatabase } from '@/api/server/databases/getServerDatabases';
@@ -51,8 +51,8 @@ const RotatePasswordButton = ({
return (
<ActionButton onClick={rotate} className='flex-none'>
<div className='flex justify-center items-center h-4 w-4'>
{!loading && <HugeIconsRefresh className='h-4 w-4' />}
<div className='flex justify-center items-center'>
{!loading && <ArrowsRotateRight width={22} height={22} />}
{loading && <Spinner size={'small'} />}
</div>
</ActionButton>

View File

@@ -1,3 +1,4 @@
import { ChevronDown, ChevronUp } from '@gravity-ui/icons';
import { useEffect, useState } from 'react';
import ActionButton from '@/components/elements/ActionButton';
@@ -12,8 +13,6 @@ import {
} from '@/components/elements/DropdownMenu';
import Modal from '@/components/elements/Modal';
import Spinner from '@/components/elements/Spinner';
import HugeIconsArrowDown from '@/components/elements/hugeicons/ArrowDown';
import HugeIconsArrowUp from '@/components/elements/hugeicons/ArrowUp';
import { SocketEvent, SocketRequest } from '@/components/server/events';
import setSelectedDockerImage from '@/api/server/setSelectedDockerImage';
@@ -112,12 +111,9 @@ const JavaVersionModalFeature = () => {
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ') || 'Select a version'}
{dropDownOpen ? (
<HugeIconsArrowUp fill={'currentColor'} className={`ml-2 w-[16px] h-[16px]`} />
<ChevronUp fill={'currentColor'} className={`ml-2 w-[16px] h-[16px]`} />
) : (
<HugeIconsArrowDown
fill={'currentColor'}
className={`ml-2 w-[16px] h-[16px]`}
/>
<ChevronDown fill={'currentColor'} className={`ml-2 w-[16px] h-[16px]`} />
)}
</button>
</DropdownMenuTrigger>

View File

@@ -1,3 +1,4 @@
import { Check, Link, TriangleExclamation } from '@gravity-ui/icons';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { toast } from 'sonner';
@@ -5,9 +6,6 @@ import ActionButton from '@/components/elements/ActionButton';
import Modal from '@/components/elements/Modal';
import Spinner from '@/components/elements/Spinner';
import { Alert } from '@/components/elements/alert';
import HugeIconsAlert from '@/components/elements/hugeicons/Alert';
import HugeIconsCheck from '@/components/elements/hugeicons/Check';
import HugeIconsLink from '@/components/elements/hugeicons/Link';
import { SocketEvent } from '@/components/server/events';
import { debounce, isCrashLine } from '@/lib/mclogsUtils';
@@ -286,7 +284,12 @@ const AnalysisModal = ({
<div className='space-y-6'>
<div className='bg-red-500/10 border border-red-500/20 rounded-lg p-4'>
<div className='flex items-start gap-3'>
<HugeIconsAlert className='w-6 h-6 text-red-400 flex-shrink-0 mt-0.5' fill='currentColor' />
<TriangleExclamation
width={22}
height={22}
className='w-6 h-6 text-red-400 flex-shrink-0 mt-0.5'
fill='currentColor'
/>
<div className='flex-1'>
<h3 className='font-semibold text-red-400 text-lg'>Analysis Failed</h3>
<p className='text-neutral-300 mt-2'>{error}</p>
@@ -320,7 +323,7 @@ const AnalysisModal = ({
rel='noopener noreferrer'
className='text-sm text-blue-400 hover:text-blue-300 flex items-center gap-1.5 transition-colors'
>
<HugeIconsLink className='w-4 h-4' />
<Link width={22} height={22} className='w-4 h-4' />
Powered by mclo.gs
</a>
</div>
@@ -370,7 +373,12 @@ const AnalysisModal = ({
return (
<div className='bg-green-500/10 border border-green-500/20 rounded-lg p-4 mb-6'>
<div className='flex items-start gap-3'>
<HugeIconsCheck className='w-6 h-6 text-green-400 flex-shrink-0 mt-0.5' fill='currentColor' />
<Check
width={22}
height={22}
className='w-6 h-6 text-green-400 flex-shrink-0 mt-0.5'
fill='currentColor'
/>
<div>
<h3 className='font-semibold text-green-400 text-lg'>No Issues Detected</h3>
<p className='text-neutral-300 mt-2'>
@@ -392,7 +400,9 @@ const AnalysisModal = ({
<div key={idx} className='bg-red-500/10 border border-red-500/20 rounded-lg overflow-hidden'>
<div className='p-4'>
<div className='flex items-start gap-3'>
<HugeIconsAlert
<TriangleExclamation
width={22}
height={22}
className='w-5 h-5 text-red-400 flex-shrink-0 mt-0.5'
fill='currentColor'
/>
@@ -444,7 +454,12 @@ const AnalysisModal = ({
{allSolutions.map((solution, idx) => (
<div key={idx} className='flex items-start gap-3'>
<div className='bg-green-500/20 rounded-full p-1 flex-shrink-0 mt-0.5'>
<HugeIconsCheck className='w-4 h-4 text-green-400' fill='currentColor' />
<Check
width={22}
height={22}
className='w-4 h-4 text-green-400'
fill='currentColor'
/>
</div>
<div className='flex-1'>
<p className='text-neutral-200 leading-relaxed'>{solution.message}</p>

View File

@@ -1,8 +1,8 @@
import { TrashBin } from '@gravity-ui/icons';
import { useState } from 'react';
import ActionButton from '@/components/elements/ActionButton';
import { Dialog } from '@/components/elements/dialog';
import HugeIconsDelete from '@/components/elements/hugeicons/Delete';
import deleteServerAllocation from '@/api/server/network/deleteServerAllocation';
import getServerAllocations from '@/api/swr/getServerAllocations';
@@ -55,7 +55,7 @@ const DeleteAllocationButton = ({ allocation }: Props) => {
onClick={() => setConfirm(true)}
className='flex items-center gap-2'
>
<HugeIconsDelete className='h-4 w-4' fill='currentColor' />
<TrashBin width={22} height={22} fill='currentColor' />
<span className='hidden sm:inline'>Delete</span>
</ActionButton>
</>

View File

@@ -6,9 +6,6 @@ import * as yup from 'yup';
import FlashMessageRender from '@/components/FlashMessageRender';
import ActionButton from '@/components/elements/ActionButton';
import FormikFieldWrapper from '@/components/elements/FormikFieldWrapper';
import Input from '@/components/elements/Input';
import Select from '@/components/elements/Select';
import HugeIconsLink from '@/components/elements/hugeicons/Link';
import {
SubdomainInfo,

View File

@@ -1,9 +1,9 @@
import { TriangleExclamation } from '@gravity-ui/icons';
import React, { useEffect, useState } from 'react';
import ActionButton from '@/components/elements/ActionButton';
import Spinner from '@/components/elements/Spinner';
import { Dialog } from '@/components/elements/dialog';
import HugeIconsAlert from '@/components/elements/hugeicons/Alert';
import {
UI_CONFIG,
@@ -111,7 +111,9 @@ const OperationProgressModal: React.FC<Props> = ({
</div>
);
case 'error':
return <HugeIconsAlert fill='currentColor' className='w-5 h-5 text-red-400' />;
return (
<TriangleExclamation width={22} height={22} fill='currentColor' className='w-5 h-5 text-red-400' />
);
default:
return <Spinner size={'small'} />;
}
@@ -131,7 +133,7 @@ const OperationProgressModal: React.FC<Props> = ({
return (
<Dialog
open={visible}
onClose={canClose ? handleClose : () => {}}
onClose={canClose ? handleClose : () => { }}
preventExternalClose={!canClose}
hideCloseIcon={!canClose}
title={operationType}
@@ -150,7 +152,12 @@ const OperationProgressModal: React.FC<Props> = ({
{error ? (
<div className='space-y-4'>
<div className='flex items-center justify-center space-x-3'>
<HugeIconsAlert fill='currentColor' className='w-6 h-6 text-red-400' />
<TriangleExclamation
width={22}
height={22}
fill='currentColor'
className='w-6 h-6 text-red-400'
/>
<span className='text-red-400 font-semibold text-lg'>Error</span>
</div>
<div className='p-4 bg-red-500/10 border border-red-500/20 rounded-lg'>
@@ -213,7 +220,12 @@ const OperationProgressModal: React.FC<Props> = ({
{isFailedStatus(operation.status) && (
<div className='p-4 bg-red-500/10 border border-red-500/20 rounded-lg'>
<div className='flex items-center justify-center space-x-2 mb-2'>
<HugeIconsAlert fill='currentColor' className='w-5 h-5 text-red-400' />
<TriangleExclamation
width={22}
height={22}
fill='currentColor'
className='w-5 h-5 text-red-400'
/>
<p className='text-sm text-red-300 font-medium'>Operation failed</p>
</div>
{operation.message && (

View File

@@ -1,5 +1,6 @@
import ModalContext from '@/context/ModalContext';
import { TZDate } from '@date-fns/tz';
import { Link, TriangleExclamation } from '@gravity-ui/icons';
import { format } from 'date-fns';
import { useStoreState } from 'easy-peasy';
import { Form, Formik, FormikHelpers } from 'formik';
@@ -10,8 +11,6 @@ import ActionButton from '@/components/elements/ActionButton';
import Field from '@/components/elements/Field';
import FormikSwitchV2 from '@/components/elements/FormikSwitchV2';
import ItemContainer from '@/components/elements/ItemContainer';
import HugeIconsAlert from '@/components/elements/hugeicons/Alert';
import HugeIconsLink from '@/components/elements/hugeicons/Link';
import asModal from '@/hoc/asModal';
@@ -192,7 +191,9 @@ const EditScheduleModal = ({ schedule }: Props) => {
{timezoneInfo.isDifferent && (
<div className={'bg-blue-900/20 border border-blue-400/30 rounded-lg p-4 my-2'}>
<div className={'flex items-start gap-3'}>
<HugeIconsAlert
<TriangleExclamation
width={22}
height={22}
fill='currentColor'
className={'text-blue-400 mt-0.5 flex-shrink-0 h-5 w-5'}
/>
@@ -243,7 +244,7 @@ const EditScheduleModal = ({ schedule }: Props) => {
// onChange={() => setShowCheetsheet((s) => !s)}
labelClasses='cursor-pointer'
>
<HugeIconsLink fill='currentColor' className={`px-5 h-5 w-5`} />
<Link width={22} height={22} fill='currentColor' className={`px-5 h-5 w-5`} />
</ItemContainer>
</a>
{/* This table would be pretty awkward to make look nice

View File

@@ -1,6 +1,6 @@
import { Calendar } from '@gravity-ui/icons';
import { format } from 'date-fns';
import HugeIconsCalendar from '@/components/elements/hugeicons/Calendar';
import ScheduleCronRow from '@/components/server/schedules/ScheduleCronRow';
import { Schedule } from '@/api/server/schedules/getServerSchedules';
@@ -9,7 +9,7 @@ const ScheduleRow = ({ schedule }: { schedule: Schedule }) => (
<>
<div className={`flex-auto`}>
<div className='flex flex-row flex-none align-middle items-center gap-6'>
<HugeIconsCalendar className='flex-none' fill='currentColor' />
<Calendar width={25} height={25} className='flex-none' fill='currentColor' />
<div>
<div className='flex flex-row items-center gap-2 text-lg'>
<p>{schedule.name}</p>

View File

@@ -1,4 +1,4 @@
import { ComponentType } from 'react';
import { CircleQuestion, CloudArrowUpIn, PencilToLine, Power, Terminal, TrashBin } from '@gravity-ui/icons';
import { useState } from 'react';
import ActionButton from '@/components/elements/ActionButton';
@@ -6,13 +6,6 @@ import Can from '@/components/elements/Can';
import ConfirmationModal from '@/components/elements/ConfirmationModal';
import ItemContainer from '@/components/elements/ItemContainer';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import HugeIconsCopy from '@/components/elements/hugeicons/Copy';
import HugeIconsPencil from '@/components/elements/hugeicons/Pencil';
import HugeIconsPower from '@/components/elements/hugeicons/Power';
import HugeIconsQuestion from '@/components/elements/hugeicons/Question';
import HugeIconsTerminal from '@/components/elements/hugeicons/Terminal';
import HugeIconsTrash from '@/components/elements/hugeicons/Trash';
import { HugeIconProps } from '@/components/elements/hugeicons/props';
import TaskDetailsModal from '@/components/server/schedules/TaskDetailsModal';
import { httpErrorToHuman } from '@/api/http';
@@ -28,16 +21,16 @@ interface Props {
task: Task;
}
const getActionDetails = (action: string): [string, ComponentType<HugeIconProps>, boolean?] => {
const getActionDetails = (action: string): [string, any, boolean?] => {
switch (action) {
case 'command':
return ['Send Command', HugeIconsTerminal, true];
return ['Send Command', Terminal, true];
case 'power':
return ['Send Power Action', HugeIconsPower];
return ['Send Power Action', Power];
case 'backup':
return ['Create Backup', HugeIconsCopy];
return ['Create Backup', CloudArrowUpIn];
default:
return ['Unknown Action', HugeIconsQuestion];
return ['Unknown Action', CircleQuestion];
}
};
@@ -132,7 +125,7 @@ const ScheduleTaskRow = ({ schedule, task }: Props) => {
onClick={() => setIsEditing(true)}
aria-label='Edit scheduled task'
>
<HugeIconsPencil fill='currentColor' />
<PencilToLine width={22} height={22} fill='currentColor' />
Edit
</ActionButton>
</Can>
@@ -144,7 +137,7 @@ const ScheduleTaskRow = ({ schedule, task }: Props) => {
className='flex items-center gap-2'
aria-label='Delete scheduled task'
>
<HugeIconsTrash fill='currentColor' className='w-4 h-4' />
<TrashBin width={22} height={22} fill='currentColor' className='w-4 h-4' />
<span className='hidden sm:inline'>Delete</span>
</ActionButton>
</Can>

View File

@@ -25,7 +25,6 @@ import useFlash from '@/plugins/useFlash';
// TODO: Port modern dropdowns to Formik and integrate them
// import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem } from '@/components/elements/DropdownMenu';
// import { DropdownMenuTrigger } from '@radix-ui/react-dropdown-menu';
// import HugeIconsArrowUp from '@/components/elements/hugeicons/ArrowUp';
const Label = styled.label`
display: inline-block;

View File

@@ -1,3 +1,4 @@
import { Box, TriangleExclamation } from '@gravity-ui/icons';
import { useEffect, useMemo, useState } from 'react';
import isEqual from 'react-fast-compare';
import { toast } from 'sonner';
@@ -16,8 +17,6 @@ import ServerContentBlock from '@/components/elements/ServerContentBlock';
import Spinner from '@/components/elements/Spinner';
import { Switch } from '@/components/elements/SwitchV2';
import TitledGreyBox from '@/components/elements/TitledGreyBox';
import HugeIconsAlert from '@/components/elements/hugeicons/Alert';
import HugeIconsEggs from '@/components/elements/hugeicons/Egg';
import OperationProgressModal from '@/components/server/operations/OperationProgressModal';
import { httpErrorToHuman } from '@/api/http';
@@ -508,8 +507,8 @@ const SoftwareContainer = () => {
selectedDockerImage && eggPreview.docker_images
? eggPreview.docker_images[selectedDockerImage]
: eggPreview.default_docker_image && eggPreview.docker_images
? eggPreview.docker_images[eggPreview.default_docker_image]
: '';
? eggPreview.docker_images[eggPreview.default_docker_image]
: '';
// Filter out empty environment variables to prevent validation issues
const filteredEnvironment: Record<string, string> = {};
@@ -617,7 +616,12 @@ const SoftwareContainer = () => {
<div className='flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4'>
<div className='flex items-center gap-3 sm:gap-4 min-w-0 flex-1'>
<div className='w-10 h-10 sm:w-12 sm:h-12 bg-[#ffffff11] rounded-lg flex items-center justify-center flex-shrink-0'>
<HugeIconsEggs fill='currentColor' className='w-5 h-5 sm:w-6 sm:h-6 text-neutral-300' />
<Box
width={22}
height={22}
fill='currentColor'
className='w-5 h-5 sm:w-6 sm:h-6 text-neutral-300'
/>
</div>
<div className='min-w-0 flex-1'>
{currentEggName ? (
@@ -884,11 +888,10 @@ const SoftwareContainer = () => {
handleVariableChange(variable.env_variable, e.target.value)
}
placeholder={variable.default_value || 'Enter value...'}
className={`w-full px-3 py-2 bg-[#ffffff08] border rounded-lg text-sm text-neutral-200 placeholder:text-neutral-500 focus:outline-none transition-colors ${
variableErrors[variable.env_variable]
className={`w-full px-3 py-2 bg-[#ffffff08] border rounded-lg text-sm text-neutral-200 placeholder:text-neutral-500 focus:outline-none transition-colors ${variableErrors[variable.env_variable]
? 'border-red-500 focus:border-red-500'
: 'border-[#ffffff12] focus:border-brand'
}`}
}`}
/>
{variableErrors[variable.env_variable] && (
<p className='text-xs text-red-400 mt-1'>
@@ -928,7 +931,8 @@ const SoftwareContainer = () => {
Create Backup
</label>
<p className='text-xs text-neutral-400 leading-relaxed'>
{backupLimit !== 0 && (backupLimit === null || (backups?.backupCount || 0) < backupLimit)
{backupLimit !== 0 &&
(backupLimit === null || (backups?.backupCount || 0) < backupLimit)
? 'Automatically create a backup before applying changes'
: backupLimit === 0
? 'Backups are disabled for this server'
@@ -939,7 +943,10 @@ const SoftwareContainer = () => {
<Switch
checked={shouldBackup}
onCheckedChange={setShouldBackup}
disabled={backupLimit === 0 || (backupLimit !== null && (backups?.backupCount || 0) >= backupLimit)}
disabled={
backupLimit === 0 ||
(backupLimit !== null && (backups?.backupCount || 0) >= backupLimit)
}
/>
</div>
</div>
@@ -1087,24 +1094,23 @@ const SoftwareContainer = () => {
{eggPreview.warnings.map((warning, index) => (
<div
key={index}
className={`p-4 border rounded-lg ${
warning.severity === 'error'
className={`p-4 border rounded-lg ${warning.severity === 'error'
? 'bg-red-500/10 border-red-500/20'
: 'bg-amber-500/10 border-amber-500/20'
}`}
}`}
>
<div className='flex items-start gap-3'>
<HugeIconsAlert
<TriangleExclamation
width={22}
height={22}
fill='currentColor'
className={`w-5 h-5 flex-shrink-0 mt-0.5 ${
warning.severity === 'error' ? 'text-red-400' : 'text-amber-400'
}`}
className={`w-5 h-5 flex-shrink-0 mt-0.5 ${warning.severity === 'error' ? 'text-red-400' : 'text-amber-400'
}`}
/>
<div>
<h4
className={`font-semibold mb-2 ${
warning.severity === 'error' ? 'text-red-400' : 'text-amber-400'
}`}
className={`font-semibold mb-2 ${warning.severity === 'error' ? 'text-red-400' : 'text-amber-400'
}`}
>
{warning.type === 'subdomain_incompatible'
? 'Subdomain Will Be Deleted'
@@ -1121,7 +1127,9 @@ const SoftwareContainer = () => {
{/* General Warning */}
<div className='p-4 bg-amber-500/10 border border-amber-500/20 rounded-lg'>
<div className='flex items-start gap-3'>
<HugeIconsAlert
<TriangleExclamation
width={22}
height={22}
fill='currentColor'
className='w-5 h-5 text-amber-400 flex-shrink-0 mt-0.5'
/>
@@ -1232,7 +1240,12 @@ const SoftwareContainer = () => {
>
<div className='space-y-4'>
<div className='flex items-start gap-3 p-4 bg-red-500/10 border border-red-500/20 rounded-lg'>
<HugeIconsAlert fill='currentColor' className='w-5 h-5 text-red-400 flex-shrink-0 mt-0.5' />
<TriangleExclamation
width={22}
height={22}
fill='currentColor'
className='w-5 h-5 text-red-400 flex-shrink-0 mt-0.5'
/>
<div>
<h4 className='text-red-400 font-semibold mb-2'>DANGER: No Backup Selected</h4>
<p className='text-sm text-neutral-300'>

View File

@@ -1,3 +1,4 @@
import { ChevronDown, ChevronUp, Lock } from '@gravity-ui/icons';
import debounce from 'debounce';
import { memo, useState } from 'react';
import isEqual from 'react-fast-compare';
@@ -13,9 +14,6 @@ import {
import InputSpinner from '@/components/elements/InputSpinner';
import { Switch } from '@/components/elements/SwitchV2';
import { Input } from '@/components/elements/TextInput';
import HugeIconsArrowDown from '@/components/elements/hugeicons/ArrowDown';
import HugeIconsArrowUp from '@/components/elements/hugeicons/ArrowUp';
import HugeIconsSquareLock from '@/components/elements/hugeicons/SquareLock';
import { ServerEggVariable } from '@/api/server/types';
import updateStartupVariable from '@/api/server/updateStartupVariable';
@@ -77,7 +75,9 @@ const VariableBox = ({ variable }: Props) => {
<div className='flex flex-col items-baseline sm:flex-row sm:justify-between gap-2 sm:gap-3'>
<div className='flex items-center gap-2 min-w-0'>
{!variable.isEditable && (
<HugeIconsSquareLock
<Lock
width={22}
height={22}
fill={'currentColor'}
className='text-neutral-500 w-4 h-4 flex-shrink-0'
/>
@@ -101,8 +101,8 @@ const VariableBox = ({ variable }: Props) => {
? 'Enabled'
: 'Disabled'
: variable.serverValue === '1'
? 'On'
: 'Off'}
? 'On'
: 'Off'}
</span>
<Switch
disabled={!canEdit || !variable.isEditable}
@@ -134,12 +134,16 @@ const VariableBox = ({ variable }: Props) => {
{variable.serverValue}
</span>
{dropDownOpen ? (
<HugeIconsArrowUp
<ChevronUp
width={22}
height={22}
fill={'currentColor'}
className='w-[14px] h-[14px] opacity-60 flex-shrink-0'
/>
) : (
<HugeIconsArrowDown
<ChevronDown
width={22}
height={22}
fill={'currentColor'}
className='w-[14px] h-[14px] opacity-60 flex-shrink-0'
/>

View File

@@ -1,10 +1,10 @@
import { ChevronLeft } from '@gravity-ui/icons';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import ActionButton from '@/components/elements/ActionButton';
import { MainPageHeader } from '@/components/elements/MainPageHeader';
import ServerContentBlock from '@/components/elements/ServerContentBlock';
import HugeIconsArrowLeft from '@/components/elements/hugeicons/ArrowLeft';
import UserFormComponent from '@/components/server/users/UserFormComponent';
import { ServerContext } from '@/state/server';
@@ -32,7 +32,7 @@ const CreateUserContainer = () => {
className='flex items-center gap-2'
disabled={isSubmitting}
>
<HugeIconsArrowLeft className='w-4 h-4' fill='currentColor' />
<ChevronLeft width={22} height={22} fill='currentColor' />
Back to Users
</ActionButton>
</MainPageHeader>

View File

@@ -1,11 +1,10 @@
import { ChevronLeft, Person } from '@gravity-ui/icons';
import { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import ActionButton from '@/components/elements/ActionButton';
import { MainPageHeader } from '@/components/elements/MainPageHeader';
import ServerContentBlock from '@/components/elements/ServerContentBlock';
import HugeIconsArrowLeft from '@/components/elements/hugeicons/ArrowLeft';
import HugeIconsUser from '@/components/elements/hugeicons/User';
import UserFormComponent from '@/components/server/users/UserFormComponent';
import { ServerContext } from '@/state/server';
@@ -47,7 +46,7 @@ const EditUserContainer = () => {
onClick={() => navigate(`/server/${serverId}/users`)}
className='flex items-center gap-2'
>
<HugeIconsArrowLeft className='w-4 h-4' fill='currentColor' />
<ChevronLeft width={22} height={22} fill='currentColor' />
Back to Users
</ActionButton>
</MainPageHeader>
@@ -68,14 +67,14 @@ const EditUserContainer = () => {
onClick={() => navigate(`/server/${serverId}/users`)}
className='flex items-center gap-2'
>
<HugeIconsArrowLeft className='w-4 h-4' fill='currentColor' />
<ChevronLeft width={22} height={22} className='w-4 h-4' fill='currentColor' />
Back to Users
</ActionButton>
</MainPageHeader>
<div className='flex flex-col items-center justify-center py-12 px-4'>
<div className='text-center'>
<div className='w-16 h-16 mx-auto mb-4 rounded-full bg-[#ffffff11] flex items-center justify-center'>
<HugeIconsUser className='w-8 h-8 text-zinc-400' fill='currentColor' />
<Person width={22} height={22} className='w-8 h-8 text-zinc-400' fill='currentColor' />
</div>
<h3 className='text-lg font-medium text-zinc-200 mb-2'>User not found</h3>
<p className='text-sm text-zinc-400 max-w-sm'>
@@ -96,7 +95,7 @@ const EditUserContainer = () => {
className='flex items-center gap-2'
disabled={isSubmitting}
>
<HugeIconsArrowLeft className='w-4 h-4' fill='currentColor' />
<ChevronLeft width={22} height={22} className='w-4 h-4' fill='currentColor' />
Back to Users
</ActionButton>
</MainPageHeader>

View File

@@ -1,9 +1,9 @@
import { TrashBin } from '@gravity-ui/icons';
import { Actions, useStoreActions } from 'easy-peasy';
import { useState } from 'react';
import ActionButton from '@/components/elements/ActionButton';
import ConfirmationModal from '@/components/elements/ConfirmationModal';
import HugeIconsTrash from '@/components/elements/hugeicons/Trash';
import { httpErrorToHuman } from '@/api/http';
import deleteSubuser from '@/api/server/users/deleteSubuser';
@@ -55,7 +55,7 @@ const RemoveSubuserButton = ({ subuser }: { subuser: Subuser }) => {
onClick={() => setShowConfirmation(true)}
aria-label='Delete subuser'
>
<HugeIconsTrash fill='currentColor' className='w-4 h-4' />
<TrashBin width={22} height={22} fill='currentColor' className='w-4 h-4' />
Delete
</ActionButton>
</>

View File

@@ -1,3 +1,4 @@
import { AntennaSignal, Calendar, Copy, Database, FolderOpen, Gear, Person, Server, Shield } from '@gravity-ui/icons';
import { Actions, useStoreActions, useStoreState } from 'easy-peasy';
import { Form, Formik } from 'formik';
import { useEffect, useState } from 'react';
@@ -7,15 +8,6 @@ import FlashMessageRender from '@/components/FlashMessageRender';
import ActionButton from '@/components/elements/ActionButton';
import Can from '@/components/elements/Can';
import Field from '@/components/elements/Field';
import HugeIconsCalendar from '@/components/elements/hugeicons/Calendar';
import HugeIconsCopy from '@/components/elements/hugeicons/Copy';
import HugeIconsDatabase from '@/components/elements/hugeicons/Database';
import HugeIconsFile from '@/components/elements/hugeicons/File';
import HugeIconsNetworkAntenna from '@/components/elements/hugeicons/NetworkAntenna';
import HugeIconsServer from '@/components/elements/hugeicons/Server';
import HugeIconsSettings from '@/components/elements/hugeicons/Settings';
import HugeIconsShield from '@/components/elements/hugeicons/Shield';
import HugeIconsUser from '@/components/elements/hugeicons/User';
import PermissionRow from '@/components/server/users/PermissionRow';
import createOrUpdateSubuser from '@/api/server/users/createOrUpdateSubuser';
@@ -94,23 +86,23 @@ const UserFormComponent = ({ subuser, onSuccess, onCancel, flashKey, isSubmittin
const getPermissionIcon = (key: string) => {
switch (key) {
case 'control':
return HugeIconsServer;
return Server;
case 'user':
return HugeIconsUser;
return Person;
case 'file':
return HugeIconsFile;
return FolderOpen;
case 'backup':
return HugeIconsCopy;
return Copy;
case 'allocation':
return HugeIconsNetworkAntenna;
return AntennaSignal;
case 'startup':
return HugeIconsSettings;
return Gear;
case 'database':
return HugeIconsDatabase;
return Database;
case 'schedule':
return HugeIconsCalendar;
return Calendar;
default:
return HugeIconsShield;
return Shield;
}
};
@@ -141,7 +133,12 @@ const UserFormComponent = ({ subuser, onSuccess, onCancel, flashKey, isSubmittin
<div className='bg-gradient-to-b from-[#ffffff08] to-[#ffffff05] border border-[#ffffff12] rounded-xl p-6'>
<div className='flex items-center gap-3 mb-6'>
<div className='w-10 h-10 rounded-lg bg-brand/20 flex items-center justify-center'>
<HugeIconsUser fill='currentColor' className='w-5 h-5 text-brand' />
<Person
width={22}
height={22}
fill='currentColor'
className='w-5 h-5 text-brand'
/>
</div>
<h3 className='text-xl font-semibold text-zinc-100'>User Information</h3>
</div>
@@ -160,7 +157,12 @@ const UserFormComponent = ({ subuser, onSuccess, onCancel, flashKey, isSubmittin
<div className='flex items-center justify-between mb-6'>
<div className='flex items-center gap-3'>
<div className='w-10 h-10 rounded-lg bg-brand/20 flex items-center justify-center'>
<HugeIconsSettings fill='currentColor' className='w-5 h-5 text-brand' />
<Gear
width={22}
height={22}
fill='currentColor'
className='w-5 h-5 text-brand'
/>
</div>
<h3 className='text-xl font-semibold text-zinc-100'>Detailed Permissions</h3>
</div>
@@ -190,7 +192,12 @@ const UserFormComponent = ({ subuser, onSuccess, onCancel, flashKey, isSubmittin
{!isRootAdmin && loggedInPermissions[0] !== '*' && (
<div className='mb-6 p-4 bg-brand/10 border border-brand/20 rounded-lg'>
<div className='flex items-center gap-3 mb-2'>
<HugeIconsShield fill='currentColor' className='w-5 h-5 text-brand' />
<Shield
width={22}
height={22}
fill='currentColor'
className='w-5 h-5 text-brand'
/>
<span className='text-sm font-semibold text-brand'>Permission Restriction</span>
</div>
<p className='text-sm text-zinc-300 leading-relaxed'>
@@ -210,8 +217,10 @@ const UserFormComponent = ({ subuser, onSuccess, onCancel, flashKey, isSubmittin
const Icon = getPermissionIcon(key);
return (
<Icon
width={22}
height={22}
fill='currentColor'
className='w-4 h-4 text-brand flex-shrink-0 mt-0.5'
className=' text-brand flex-shrink-0 mt-0.5'
/>
);
})()}

View File

@@ -1,9 +1,9 @@
import { Pencil } from '@gravity-ui/icons';
import { useStoreState } from 'easy-peasy';
import { useNavigate } from 'react-router-dom';
import ActionButton from '@/components/elements/ActionButton';
import Can from '@/components/elements/Can';
import HugeIconsPencil from '@/components/elements/hugeicons/Pencil';
import { PageListItem } from '@/components/elements/pages/PageList';
import RemoveSubuserButton from '@/components/server/users/RemoveSubuserButton';
@@ -53,7 +53,7 @@ const UserRow = ({ subuser }: Props) => {
onClick={handleEditClick}
aria-label='Edit subuser'
>
<HugeIconsPencil className='w-4 h-4' fill='currentColor' />
<Pencil width={22} height={22} fill='currentColor' />
Edit
</ActionButton>
</Can>

View File

@@ -1,3 +1,4 @@
import { Person, Plus } from '@gravity-ui/icons';
import { Actions, useStoreActions, useStoreState } from 'easy-peasy';
import { For } from 'million/react';
import { useEffect, useState } from 'react';
@@ -8,8 +9,6 @@ import ActionButton from '@/components/elements/ActionButton';
import Can from '@/components/elements/Can';
import { MainPageHeader } from '@/components/elements/MainPageHeader';
import ServerContentBlock from '@/components/elements/ServerContentBlock';
import HugeIconsPlus from '@/components/elements/hugeicons/Plus';
import HugeIconsUser from '@/components/elements/hugeicons/User';
import { PageListContainer } from '@/components/elements/pages/PageList';
import UserRow from '@/components/server/users/UserRow';
@@ -68,7 +67,7 @@ const UsersContainer = () => {
onClick={() => navigate(`/server/${serverId}/users/new`)}
className='flex items-center gap-2'
>
<HugeIconsPlus className='w-4 h-4' fill='currentColor' />
<Plus width={22} height={22} className='w-4 h-4' fill='currentColor' />
New User
</ActionButton>
</Can>
@@ -102,7 +101,7 @@ const UsersContainer = () => {
onClick={() => navigate(`/server/${serverId}/users/new`)}
className='flex items-center gap-2'
>
<HugeIconsPlus className='w-4 h-4' fill='currentColor' />
<Plus width={22} height={22} className='w-4 h-4' fill='currentColor' />
New User
</ActionButton>
</Can>
@@ -118,7 +117,7 @@ const UsersContainer = () => {
<div className='flex flex-col items-center justify-center min-h-[60vh] py-12 px-4'>
<div className='text-center'>
<div className='w-16 h-16 mx-auto mb-4 rounded-full bg-[#ffffff11] flex items-center justify-center'>
<HugeIconsUser className='w-8 h-8 text-zinc-400' fill='currentColor' />
<Person width={22} height={22} className='w-8 h-8 text-zinc-400' fill='currentColor' />
</div>
<h3 className='text-lg font-medium text-zinc-200 mb-2'>No users found</h3>
<p className='text-sm text-zinc-400 max-w-sm'>