fix: linting + ssh & api icons

This commit is contained in:
he3als
2024-11-17 11:32:28 +00:00
parent 6939add7b9
commit c95d6c4402
14 changed files with 171 additions and 118 deletions

1
.gitignore vendored
View File

@@ -4,7 +4,6 @@
!.env.example
.env*
.vagrant/
.vscode/
storage/framework/*
/.idea
/nbproject

3
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
}

8
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"prettier.endOfLine": "lf",
"editor.formatOnSave": true,
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}

View File

@@ -13,6 +13,7 @@ import requestPasswordResetEmail from '@/api/auth/requestPasswordResetEmail';
import { httpErrorToHuman } from '@/api/http';
import useFlash from '@/plugins/useFlash';
import Logo from '../elements/PyroLogo';
interface Values {

View File

@@ -1,4 +1,5 @@
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { format } from 'date-fns';
import { useEffect, useState } from 'react';
@@ -15,8 +16,6 @@ import getApiKeys, { ApiKey } from '@/api/account/getApiKeys';
import { useFlashKey } from '@/plugins/useFlash';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
export default () => {
const [deleteIdentifier, setDeleteIdentifier] = useState('');
const [keys, setKeys] = useState<ApiKey[]>([]);
@@ -46,12 +45,12 @@ export default () => {
return (
<PageContentBlock title={'Account API'}>
{/* Flash messages will now appear at the top of the page */}
<FlashMessageRender byKey="account" />
<div className="md:flex flex-nowrap my-10 space-x-8">
<ContentBox title={'Create API Key'} className="flex-none w-full md:w-1/2">
<FlashMessageRender byKey='account' />
<div className='md:flex flex-nowrap my-10 space-x-8'>
<ContentBox title={'Create API Key'} className='flex-none w-full md:w-1/2'>
<CreateApiKeyForm onKeyCreated={(key) => setKeys((s) => [...s!, key])} />
</ContentBox>
<ContentBox title={'API Keys'} className="flex-1 overflow-hidden mt-8 md:mt-0">
<ContentBox title={'API Keys'} className='flex-1 overflow-hidden mt-8 md:mt-0'>
<SpinnerOverlay visible={loading} />
<Dialog.Confirm
title={'Delete API Key'}
@@ -63,29 +62,30 @@ export default () => {
All requests using the <Code>{deleteIdentifier}</Code> key will be invalidated.
</Dialog.Confirm>
{keys.length === 0 ? (
<p className="text-center text-sm text-gray-500">
<p className='text-center text-sm text-gray-500'>
{loading ? 'Loading...' : 'No API keys exist for this account.'}
</p>
) : (
keys.map((key) => (
<div key={key.identifier} className="flex flex-col mb-6 space-y-4">
<div className="flex items-center justify-between space-x-4 border border-gray-300 rounded-lg p-4 transition duration-200">
<div className="flex-1">
<p className="text-sm font-medium">{key.description}</p>
<p className="text-xs text-gray-500 uppercase">
Last used: {key.lastUsedAt ? format(key.lastUsedAt, 'MMM d, yyyy HH:mm') : 'Never'}
<div key={key.identifier} className='flex flex-col mb-6 space-y-4'>
<div className='flex items-center justify-between space-x-4 border border-gray-300 rounded-lg p-4 transition duration-200'>
<div className='flex-1'>
<p className='text-sm font-medium'>{key.description}</p>
<p className='text-xs text-gray-500 uppercase'>
Last used:{' '}
{key.lastUsedAt ? format(key.lastUsedAt, 'MMM d, yyyy HH:mm') : 'Never'}
</p>
</div>
<p className="text-sm text-gray-600 hidden md:block">
<code className="font-mono py-1 px-2 bg-gray-800 rounded text-white">
<p className='text-sm text-gray-600 hidden md:block'>
<code className='font-mono py-1 px-2 bg-gray-800 rounded text-white'>
{key.identifier}
</code>
</p>
<button
className="p-2 text-red-500 hover:text-red-700"
className='p-2 text-red-500 hover:text-red-700'
onClick={() => setDeleteIdentifier(key.identifier)}
>
<FontAwesomeIcon icon={faTrashAlt} size="lg" />
<FontAwesomeIcon icon={faTrashAlt} size='lg' />
</button>
</div>
</div>

View File

@@ -1,11 +1,12 @@
import { faClone } from '@fortawesome/free-solid-svg-icons';
import { useContext } from 'react';
import ModalContext from '@/context/ModalContext';
import { faClone } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { useContext } from 'react';
import FlashMessageRender from '@/components/FlashMessageRender';
import Button from '@/components/elements/Button';
import CopyOnClick from '@/components/elements/CopyOnClick';
import FlashMessageRender from '@/components/FlashMessageRender';
import asModal from '@/hoc/asModal';
interface Props {
@@ -16,39 +17,40 @@ const ApiKeyModal = ({ apiKey }: Props) => {
const { dismiss } = useContext(ModalContext);
return (
<div className="p-6 space-y-6 max-w-lg mx-auto rounded-lg shadow-lg ">
<div className='p-6 space-y-6 max-w-lg mx-auto rounded-lg shadow-lg '>
{/* Flash message section */}
<FlashMessageRender byKey="account" />
<FlashMessageRender byKey='account' />
{/* Modal Header */}
<p className="text-sm text-white-600 mt-2 ">
The API key you have requested is shown below. Please store it in a safe place, as it will not be shown again.
<p className='text-sm text-white-600 mt-2 '>
The API key you have requested is shown below. Please store it in a safe place, as it will not be shown
again.
</p>
{/* API Key Display Section */}
<div className="relative mt-6">
<pre className="bg-gray-900 text-white p-4 rounded-lg font-mono overflow-x-auto">
<div className='relative mt-6'>
<pre className='bg-gray-900 text-white p-4 rounded-lg font-mono overflow-x-auto'>
<CopyOnClick text={apiKey}>
<code className="text-sm break-words">{apiKey}</code>
<code className='text-sm break-words'>{apiKey}</code>
</CopyOnClick>
{/* Copy button with icon */}
<div className="absolute top-2 right-2">
<div className='absolute top-2 right-2'>
<FontAwesomeIcon
icon={faClone}
size="lg"
className="text-gray-400 hover:text-gray-600 cursor-pointer"
size='lg'
className='text-gray-400 hover:text-gray-600 cursor-pointer'
/>
</div>
</pre>
</div>
{/* Action Buttons */}
<div className="flex justify-end space-x-4">
<div className='flex justify-end space-x-4'>
<Button
type="button"
type='button'
onClick={() => dismiss()}
className="bg-red-600 text-white hover:bg-red-700 px-6 py-2 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500"
className='bg-red-600 text-white hover:bg-red-700 px-6 py-2 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500'
>
Close
</Button>
@@ -61,6 +63,6 @@ ApiKeyModal.displayName = 'ApiKeyModal';
export default asModal<Props>({
title: 'Your API Key',
closeOnEscape: true, // Allows closing the modal by pressing Escape
closeOnBackground: true, // Allows closing by clicking outside the modal
closeOnEscape: true, // Allows closing the modal by pressing Escape
closeOnBackground: true, // Allows closing by clicking outside the modal
})(ApiKeyModal);

View File

@@ -3,12 +3,12 @@ import { Field, Form, Formik, FormikHelpers } from 'formik';
import { useState } from 'react';
import { object, string } from 'yup';
import FlashMessageRender from '@/components/FlashMessageRender';
import ApiKeyModal from '@/components/dashboard/ApiKeyModal';
import Button from '@/components/elements/Button';
import FormikFieldWrapper from '@/components/elements/FormikFieldWrapper';
import Input from '@/components/elements/Input';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import FlashMessageRender from '@/components/FlashMessageRender';
import createApiKey from '@/api/account/createApiKey';
import { ApiKey } from '@/api/account/getApiKeys';
@@ -45,7 +45,7 @@ export default ({ onKeyCreated }: { onKeyCreated: (key: ApiKey) => void }) => {
return (
<>
{/* Flash Messages */}
<FlashMessageRender byKey="account" />
<FlashMessageRender byKey='account' />
{/* Modal for API Key */}
<ApiKeyModal visible={apiKey.length > 0} onModalDismissed={() => setApiKey('')} apiKey={apiKey} />
@@ -60,33 +60,33 @@ export default ({ onKeyCreated }: { onKeyCreated: (key: ApiKey) => void }) => {
})}
>
{({ isSubmitting }) => (
<Form className="space-y-6">
<Form className='space-y-6'>
{/* Show spinner overlay when submitting */}
<SpinnerOverlay visible={isSubmitting} />
{/* Description Field */}
<FormikFieldWrapper
label="Description"
name="description"
description="A description of this API key."
label='Description'
name='description'
description='A description of this API key.'
>
<Field name="description" as={Input} />
<Field name='description' as={Input} />
</FormikFieldWrapper>
{/* Allowed IPs Field */}
<FormikFieldWrapper
label="Allowed IPs"
name="allowedIps"
description="Leave blank to allow any IP address to use this API key, otherwise provide each IP address on a new line."
label='Allowed IPs'
name='allowedIps'
description='Leave blank to allow any IP address to use this API key, otherwise provide each IP address on a new line.'
>
<Field name="allowedIps" as={Input} />
<Field name='allowedIps' as={Input} />
</FormikFieldWrapper>
{/* Submit Button below form fields */}
<div className="flex justify-end mt-6">
<div className='flex justify-end mt-6'>
<Button
type="submit"
className="bg-red-600 text-white hover:bg-red-700 px-6 py-2 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500"
type='submit'
className='bg-red-600 text-white hover:bg-red-700 px-6 py-2 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500'
disabled={isSubmitting}
>
{isSubmitting ? 'Creating...' : 'Create API Key'}

View File

@@ -1,9 +1,11 @@
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { format } from 'date-fns';
import { useEffect, useState } from 'react';
import FlashMessageRender from '@/components/FlashMessageRender';
import CreateSSHKeyForm from '@/components/dashboard/ssh/CreateSSHKeyForm';
import DeleteSSHKeyButton from '@/components/dashboard/ssh/DeleteSSHKeyButton';
import Code from '@/components/elements/Code';
import ContentBox from '@/components/elements/ContentBox';
import PageContentBlock from '@/components/elements/PageContentBlock';
@@ -13,8 +15,6 @@ import { Dialog } from '@/components/elements/dialog';
import { useSSHKeys } from '@/api/account/ssh-keys';
import { useFlashKey } from '@/plugins/useFlash';
import DeleteSSHKeyButton from '@/components/dashboard/ssh/DeleteSSHKeyButton';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
export default () => {
const [deleteIdentifier, setDeleteIdentifier] = useState('');
@@ -36,14 +36,14 @@ export default () => {
return (
<PageContentBlock title={'SSH Keys'}>
<FlashMessageRender byKey={'account'} />
<div className="md:flex flex-nowrap my-10 space-x-8">
<div className='md:flex flex-nowrap my-10 space-x-8'>
{/* Create SSH Key Section */}
<ContentBox title={'Add SSH Key'} className="flex-none w-full md:w-1/2">
<ContentBox title={'Add SSH Key'} className='flex-none w-full md:w-1/2'>
<CreateSSHKeyForm />
</ContentBox>
{/* SSH Keys List Section */}
<ContentBox title={'SSH Keys'} className="flex-1 overflow-hidden mt-8 md:mt-0">
<ContentBox title={'SSH Keys'} className='flex-1 overflow-hidden mt-8 md:mt-0'>
<SpinnerOverlay visible={!data && isValidating} />
<Dialog.Confirm
title={'Delete SSH Key'}
@@ -55,29 +55,29 @@ export default () => {
Deleting this key will revoke access for any system using it.
</Dialog.Confirm>
{!data || data.length === 0 ? (
<p className="text-center text-sm text-gray-500">
<p className='text-center text-sm text-gray-500'>
{!data ? 'Loading...' : 'No SSH keys exist for this account.'}
</p>
) : (
data.map((key) => (
<div key={key.fingerprint} className="flex flex-col mb-6 space-y-4">
<div className="flex items-center justify-between space-x-4 border border-gray-300 rounded-lg p-4 transition duration-200">
<div className="flex-1">
<p className="text-sm font-medium">{key.name}</p>
<p className="text-xs text-gray-500 uppercase">
<div key={key.fingerprint} className='flex flex-col mb-6 space-y-4'>
<div className='flex items-center justify-between space-x-4 border border-gray-300 rounded-lg p-4 transition duration-200'>
<div className='flex-1'>
<p className='text-sm font-medium'>{key.name}</p>
<p className='text-xs text-gray-500 uppercase'>
Added on: {format(key.createdAt, 'MMM d, yyyy HH:mm')}
</p>
</div>
<p className="text-sm text-gray-600 hidden md:block">
<code className="font-mono py-1 px-2 bg-gray-800 rounded text-white">
<p className='text-sm text-gray-600 hidden md:block'>
<code className='font-mono py-1 px-2 bg-gray-800 rounded text-white'>
SHA256: {key.fingerprint}
</code>
</p>
<button
className="p-2 text-red-500 hover:text-red-700"
className='p-2 text-red-500 hover:text-red-700'
onClick={() => setDeleteIdentifier(key.fingerprint)}
>
<FontAwesomeIcon icon={faTrashAlt} size="lg" />
<FontAwesomeIcon icon={faTrashAlt} size='lg' />
</button>
</div>
</div>

View File

@@ -3,11 +3,11 @@ import { Field, Form, Formik, FormikHelpers } from 'formik';
import { useState } from 'react';
import { object, string } from 'yup';
import FlashMessageRender from '@/components/FlashMessageRender';
import Button from '@/components/elements/Button';
import FormikFieldWrapper from '@/components/elements/FormikFieldWrapper';
import Input from '@/components/elements/Input';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import FlashMessageRender from '@/components/FlashMessageRender';
import { createSSHKey } from '@/api/account/ssh-keys';
import { useSSHKeys } from '@/api/account/ssh-keys';
@@ -32,7 +32,7 @@ export default () => {
resetForm();
setSubmitting(false);
setSshKey(`${key.name}`);
mutate((data) => (data || []).concat(key)); // Update the list of SSH keys after creation
mutate((data) => (data || []).concat(key)); // Update the list of SSH keys after creation
})
.catch((error) => {
console.error(error);
@@ -44,7 +44,7 @@ export default () => {
return (
<>
{/* Flash Messages */}
<FlashMessageRender byKey="account" />
<FlashMessageRender byKey='account' />
{/* Modal for SSH Key */}
{/* Add your modal logic here to display the SSH key details after creation */}
@@ -59,33 +59,33 @@ export default () => {
})}
>
{({ isSubmitting }) => (
<Form className="space-y-6">
<Form className='space-y-6'>
{/* Show spinner overlay when submitting */}
<SpinnerOverlay visible={isSubmitting} />
{/* SSH Key Name Field */}
<FormikFieldWrapper
label="SSH Key Name"
name="name"
description="A name to identify this SSH key."
label='SSH Key Name'
name='name'
description='A name to identify this SSH key.'
>
<Field name="name" as={Input} />
<Field name='name' as={Input} />
</FormikFieldWrapper>
{/* Public Key Field */}
<FormikFieldWrapper
label="Public Key"
name="publicKey"
description="Enter your public SSH key."
label='Public Key'
name='publicKey'
description='Enter your public SSH key.'
>
<Field name="publicKey" as={Input} />
<Field name='publicKey' as={Input} />
</FormikFieldWrapper>
{/* Submit Button below form fields */}
<div className="flex justify-end mt-6">
<div className='flex justify-end mt-6'>
<Button
type="submit"
className="bg-red-600 text-white hover:bg-red-700 px-6 py-2 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500"
type='submit'
className='bg-red-600 text-white hover:bg-red-700 px-6 py-2 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500'
disabled={isSubmitting}
>
{isSubmitting ? 'Creating...' : 'Create SSH Key'}

View File

@@ -2,14 +2,12 @@ import { useState } from 'react';
import Code from '@/components/elements/Code';
import { Dialog } from '@/components/elements/dialog';
import HugeIconsTrash from '@/components/elements/hugeicons/Trash';
import { deleteSSHKey, useSSHKeys } from '@/api/account/ssh-keys';
import { useFlashKey } from '@/plugins/useFlash';
import HugeIconsTrash from '@/components/elements/hugeicons/Trash';
export default ({ name, fingerprint }: { name: string; fingerprint: string }) => {
const { clearAndAddHttpError } = useFlashKey('account');
const [visible, setVisible] = useState(false);
@@ -38,9 +36,7 @@ export default ({ name, fingerprint }: { name: string; fingerprint: string }) =>
>
Removing the <Code>{name}</Code> SSH key will invalidate its usage across the Panel.
</Dialog.Confirm>
<button className={`ml-4 p-2 text-sm`} onClick={() => setVisible(true)}>
</button>
<button className={`ml-4 p-2 text-sm`} onClick={() => setVisible(true)}></button>
</>
);
};

View File

@@ -2,12 +2,36 @@ import { HugeIconProps } from './props';
const HugeIconsApi = (props: HugeIconProps) => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" color="#ffffff" fill="none">
<path d="M2.5 12C2.5 7.52166 2.5 5.28249 3.89124 3.89124C5.28249 2.5 7.52166 2.5 12 2.5C16.4783 2.5 18.7175 2.5 20.1088 3.89124C21.5 5.28249 21.5 7.52166 21.5 12C21.5 16.4783 21.5 18.7175 20.1088 20.1088C18.7175 21.5 16.4783 21.5 12 21.5C7.52166 21.5 5.28249 21.5 3.89124 20.1088C2.5 18.7175 2.5 16.4783 2.5 12Z" stroke="currentColor" stroke-width="1.5" />
<path d="M6 13.5L7.5 9L9.375 13.5M6 13.5L5.5 15M6 13.5H9.375M9.375 13.5L10 15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M12.5 12V9.7C12.5 9.51387 12.5 9.42081 12.5245 9.34549C12.5739 9.19327 12.6933 9.07393 12.8455 9.02447C12.9208 9 13.0139 9 13.2 9H14.5C15.3284 9 16 9.67157 16 10.5C16 11.3284 15.3284 12 14.5 12H12.5ZM12.5 12V15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M18.5 9V15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 24 24'
width='24'
height='24'
fill='none'
color={props.fill}
className={'h-6 w-6' + (props.className ? ` ${props.className}` : '')}
>
<path
d='M2.5 12C2.5 7.52166 2.5 5.28249 3.89124 3.89124C5.28249 2.5 7.52166 2.5 12 2.5C16.4783 2.5 18.7175 2.5 20.1088 3.89124C21.5 5.28249 21.5 7.52166 21.5 12C21.5 16.4783 21.5 18.7175 20.1088 20.1088C18.7175 21.5 16.4783 21.5 12 21.5C7.52166 21.5 5.28249 21.5 3.89124 20.1088C2.5 18.7175 2.5 16.4783 2.5 12Z'
stroke='currentColor'
strokeWidth='1.5'
/>
<path
d='M6 13.5L7.5 9L9.375 13.5M6 13.5L5.5 15M6 13.5H9.375M9.375 13.5L10 15'
stroke='currentColor'
strokeWidth='1.5'
strokeLinecap='round'
strokeLinejoin='round'
/>
<path
d='M12.5 12V9.7C12.5 9.51387 12.5 9.42081 12.5245 9.34549C12.5739 9.19327 12.6933 9.07393 12.8455 9.02447C12.9208 9 13.0139 9 13.2 9H14.5C15.3284 9 16 9.67157 16 10.5C16 11.3284 15.3284 12 14.5 12H12.5ZM12.5 12V15'
stroke='currentColor'
strokeWidth='1.5'
strokeLinecap='round'
strokeLinejoin='round'
/>
<path d='M18.5 9V15' stroke='currentColor' strokeWidth='1.5' strokeLinecap='round' strokeLinejoin='round' />
</svg>
);
};

View File

@@ -2,10 +2,30 @@ import { HugeIconProps } from './props';
const HugeIconsSsh = (props: HugeIconProps) => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" color="#ffffff" fill="none">
<path d="M15.5 14.5C18.8137 14.5 21.5 11.8137 21.5 8.5C21.5 5.18629 18.8137 2.5 15.5 2.5C12.1863 2.5 9.5 5.18629 9.5 8.5C9.5 9.38041 9.68962 10.2165 10.0303 10.9697L2.5 18.5V21.5H5.5V19.5H7.5V17.5H9.5L13.0303 13.9697C13.7835 14.3104 14.6196 14.5 15.5 14.5Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M17.5 6.5L16.5 7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 24 24'
width='24'
height='24'
fill='none'
color={props.fill}
className={'h-6 w-6' + (props.className ? ` ${props.className}` : '')}
>
<path
d='M15.5 14.5C18.8137 14.5 21.5 11.8137 21.5 8.5C21.5 5.18629 18.8137 2.5 15.5 2.5C12.1863 2.5 9.5 5.18629 9.5 8.5C9.5 9.38041 9.68962 10.2165 10.0303 10.9697L2.5 18.5V21.5H5.5V19.5H7.5V17.5H9.5L13.0303 13.9697C13.7835 14.3104 14.6196 14.5 15.5 14.5Z'
stroke='currentColor'
strokeWidth='1.5'
strokeLinecap='round'
strokeLinejoin='round'
/>
<path
d='M17.5 6.5L16.5 7.5'
stroke='currentColor'
strokeWidth='1.5'
strokeLinecap='round'
strokeLinejoin='round'
/>
</svg>
);
};

View File

@@ -1,3 +1,5 @@
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Actions, useStoreActions } from 'easy-peasy';
import { useState } from 'react';
@@ -9,8 +11,6 @@ import deleteSubuser from '@/api/server/users/deleteSubuser';
import { ApplicationStore } from '@/state';
import { ServerContext } from '@/state/server';
import { Subuser } from '@/state/server/subusers';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons';
export default ({ subuser }: { subuser: Subuser }) => {
const [loading, setLoading] = useState(false);

View File

@@ -16,24 +16,21 @@ import MainSidebar from '@/components/elements/MainSidebar';
import MainWrapper from '@/components/elements/MainWrapper';
import Logo from '@/components/elements/PyroLogo';
import { NotFound } from '@/components/elements/ScreenBlock';
import HugeIconsApi from '@/components/elements/hugeicons/Api';
import HugeIconsDashboardSettings from '@/components/elements/hugeicons/DashboardSettings';
import HugeIconsHome from '@/components/elements/hugeicons/Home';
import HugeIconsApi from '@/components/elements/hugeicons/Api';
import HugeIconsSsh from '@/components/elements/hugeicons/Ssh';
import http from '@/api/http';
export default () => {
const location = useLocation();
const rootAdmin = useStoreState((state) => state.user.data!.rootAdmin);
const [isSidebarVisible, setSidebarVisible] = useState(false);
const [isSidebarVisible, setSidebarVisible] = useState(false);
const toggleSidebar = () => {
setSidebarVisible(!isSidebarVisible); // Toggle sidebar visibility
setSidebarVisible(!isSidebarVisible); // Toggle sidebar visibility
};
const onTriggerLogout = () => {
@@ -72,7 +69,6 @@ export default () => {
return '0';
};
const top = calculateTop(location.pathname);
const [height, setHeight] = useState('40px');
@@ -83,21 +79,28 @@ export default () => {
return () => clearTimeout(timeoutId);
}, [top]);
return (
<Fragment key={'dashboard-router'}>
<button
id="sidebarToggle"
id='sidebarToggle'
className={`lg:hidden fixed top-4 left-4 z-50 bg-transparent p-2 rounded-md text-white ${
isSidebarVisible ? 'left-[300px]' : 'left-4'
}`}
onClick={toggleSidebar}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
<svg
xmlns='http://www.w3.org/2000/svg'
fill='none'
viewBox='0 0 24 24'
strokeWidth='1.5'
stroke='currentColor'
className='size-6'
>
<path
strokeLinecap='round'
strokeLinejoin='round'
d='M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5'
/>
</svg>
</button>
@@ -163,7 +166,7 @@ export default () => {
</NavLink>
<NavLink to={'/account/api'} end className='flex flex-row items-center' ref={NavigationApi}>
<HugeIconsApi fill='currentColor' />
<p>Api Keys</p>
<p>API Keys</p>
</NavLink>
<NavLink to={'/account/ssh'} end className='flex flex-row items-center' ref={NavigationSSH}>
<HugeIconsSsh fill='currentColor' />
@@ -173,9 +176,7 @@ export default () => {
<HugeIconsDashboardSettings fill='currentColor' />
<p>Settings</p>
</NavLink>
</ul>
</MainSidebar>
<Suspense fallback={null}>
@@ -201,7 +202,6 @@ export default () => {
</main>
</MainWrapper>
</Suspense>
</Fragment>
);
</Fragment>
);
};