Starting guac clients
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
import {
|
||||
Button,
|
||||
Grid,
|
||||
GridCol,
|
||||
Group,
|
||||
LoadingOverlay,
|
||||
Popover,
|
||||
Stack,
|
||||
TextInput,
|
||||
} from '@mantine/core';
|
||||
import { isNotEmpty, useForm } from '@mantine/form';
|
||||
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
||||
import { AddItemModal, NoItemsFound, SettingsHeader } from 'components';
|
||||
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { popoverClasses, textInputClasses } from 'styles';
|
||||
import type { GuacamoleClient } from 'types';
|
||||
import DebouncedGuacamoleClient from './DebouncedGuacamoleClient';
|
||||
import GuacamoleClientSettingsItem from './GuacamoleClientSettingsItem';
|
||||
|
||||
const GuacamoleClients = () => {
|
||||
const defaultGuacamoleClient: GuacamoleClient = {
|
||||
id: undefined,
|
||||
clientName: '',
|
||||
clientIdentifier: '',
|
||||
enabled: 1,
|
||||
};
|
||||
const form = useForm({
|
||||
initialValues: defaultGuacamoleClient,
|
||||
validate: {
|
||||
clientName: isNotEmpty('Client Name is required'),
|
||||
clientIdentifier: isNotEmpty('Client Identifier is required'),
|
||||
},
|
||||
});
|
||||
const endpoint = 'api/guacamoleClients';
|
||||
const {
|
||||
data: guacamoleClientsData,
|
||||
isFetched: guacamoleClientsIsFetched,
|
||||
isFetching: guacamoleClientsIsFetching,
|
||||
} = useQueryAPI({
|
||||
endpoint: endpoint,
|
||||
});
|
||||
const [guacamoleClients, setGuacamoleClients] = useState<GuacamoleClient[]>([]);
|
||||
const { mutateAsync } = useMutationAPI();
|
||||
const { isMobile, theme } = useCommonHooks();
|
||||
const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false);
|
||||
const [searchValue, setSearchValue] = useState<string | number>('');
|
||||
const [debouncedSearch] = useDebouncedValue(searchValue, 500);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const handleClose = () => {
|
||||
closeModal();
|
||||
form.reset();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (guacamoleClientsData && guacamoleClientsIsFetched) {
|
||||
setGuacamoleClients(
|
||||
guacamoleClientsData.filter((a: GuacamoleClient) =>
|
||||
a.clientName.toLowerCase().includes((debouncedSearch as string).toLowerCase()),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (debouncedSearch === searchValue) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [guacamoleClientsData, guacamoleClientsIsFetched, debouncedSearch]);
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<AddItemModal
|
||||
modalOpened={modalOpened}
|
||||
handleClose={handleClose}
|
||||
title={'Add a new Guacamole Client'}
|
||||
body={
|
||||
<form
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
mutateAsync({
|
||||
method: 'POST',
|
||||
endpoint: endpoint,
|
||||
body: { ...values, enabled: 1 },
|
||||
});
|
||||
handleClose();
|
||||
})}
|
||||
>
|
||||
<Stack gap={0} w={'100%'} align='center'>
|
||||
<Group w={'100%'} justify='center'>
|
||||
<TextInput
|
||||
key={form.key('clientName')}
|
||||
{...form.getInputProps('clientName')}
|
||||
label={'Client Name'}
|
||||
placeholder='eg. Workstation'
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
withAsterisk
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
<TextInput
|
||||
key={form.key('clientIdentifier')}
|
||||
{...form.getInputProps('clientIdentifier')}
|
||||
label={'clientIdentifier'}
|
||||
placeholder='eg. MzIAYwBteXNxbA'
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
withAsterisk
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Group>
|
||||
<Group mt={'1rem'}>
|
||||
<Button type='submit' color={'green'}>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
color={'red'}
|
||||
styles={{ label: { color: 'black' } }}
|
||||
onClick={handleClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</form>
|
||||
}
|
||||
/>
|
||||
<SettingsHeader
|
||||
setDragging={undefined}
|
||||
openModal={openModal}
|
||||
title={'Guacamole Clients'}
|
||||
tooltip={{
|
||||
title: 'Guacamole clients can be configured here.',
|
||||
highlightList: ['Clients', 'homepage', 'Guacamole'],
|
||||
description: 'Clients can be connected to from the homepage.',
|
||||
}}
|
||||
searchValue={searchValue}
|
||||
setSearchValue={setSearchValue}
|
||||
searchPlaceholder={'Search Clients...'}
|
||||
isLoading={isLoading}
|
||||
setIsLoading={setIsLoading}
|
||||
/>
|
||||
<Stack
|
||||
mt={isMobile ? '10rem' : '6rem'}
|
||||
mb={isMobile ? '6rem' : '1rem'}
|
||||
w={'100%'}
|
||||
align='center'
|
||||
>
|
||||
<LoadingOverlay
|
||||
visible={guacamoleClientsIsFetching}
|
||||
zIndex={180}
|
||||
overlayProps={{ blur: 5 }}
|
||||
loaderProps={{
|
||||
color: 'var(--mantine-color-primary-0)',
|
||||
type: 'bars',
|
||||
size: 'xl',
|
||||
}}
|
||||
/>
|
||||
<Grid columns={18} w={'75%'}>
|
||||
{guacamoleClients.length > 0 ? (
|
||||
guacamoleClients?.map((client: GuacamoleClient) => (
|
||||
<GridCol w={'100%'} span={isMobile ? 18 : 6} key={client.id}>
|
||||
<Popover
|
||||
withArrow
|
||||
withOverlay
|
||||
trapFocus
|
||||
closeOnClickOutside={!isOpen}
|
||||
classNames={popoverClasses}
|
||||
middlewares={{ shift: { padding: 20 } }}
|
||||
position='bottom'
|
||||
offset={isMobile ? -100 : 0}
|
||||
>
|
||||
<Popover.Target>
|
||||
<Group justify='center'>
|
||||
<GuacamoleClientSettingsItem client={client} />
|
||||
</Group>
|
||||
</Popover.Target>
|
||||
<Popover.Dropdown w={isMobile ? '90%' : undefined}>
|
||||
<DebouncedGuacamoleClient
|
||||
guacamoleClient={client}
|
||||
setIsOpen={setIsOpen}
|
||||
/>
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
</GridCol>
|
||||
))
|
||||
) : (
|
||||
<GridCol
|
||||
w={'100%'}
|
||||
span={18}
|
||||
style={{ display: 'flex', justifyContent: 'center' }}
|
||||
>
|
||||
<NoItemsFound />
|
||||
</GridCol>
|
||||
)}
|
||||
</Grid>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
export default GuacamoleClients;
|
||||
Reference in New Issue
Block a user