Updates to personalization
This commit is contained in:
@@ -32,6 +32,9 @@ function App() {
|
||||
const { data: themePlaylists, isFetched: isThemePlaylistsFetched } = useQueryAPI({
|
||||
endpoint: 'api/themePlaylists',
|
||||
});
|
||||
const { data: personalData, isFetched: isPersonalDataFetched } = useQueryAPI({
|
||||
endpoint: 'api/personalData',
|
||||
});
|
||||
const {
|
||||
theme,
|
||||
setTheme,
|
||||
@@ -78,7 +81,7 @@ function App() {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (allThemes && themeName) {
|
||||
if (allThemes && themeName && personalData) {
|
||||
if (currentThemePlaylist === 'All') {
|
||||
if (themeName === 'random') {
|
||||
handleThemeChange(allThemes, false);
|
||||
@@ -124,6 +127,7 @@ function App() {
|
||||
allThemes,
|
||||
currentThemePlaylist,
|
||||
isThemePlaylistsFetched,
|
||||
isPersonalDataFetched,
|
||||
]);
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -40,7 +40,7 @@ export function SettingsHeader({
|
||||
highlightList: string[];
|
||||
description: string;
|
||||
};
|
||||
searchValue: string | number;
|
||||
searchValue: string | number | undefined;
|
||||
setSearchValue: (searchValue: string | number) => void;
|
||||
searchPlaceholder: string | undefined;
|
||||
isLoading: boolean;
|
||||
|
||||
@@ -137,6 +137,10 @@ export function useMutationAPI() {
|
||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/themes'] });
|
||||
endpoint === 'api/providers' &&
|
||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/providers/default'] });
|
||||
endpoint === 'api/personalData' &&
|
||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/personalData'] });
|
||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/wolEnabled'] });
|
||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/guacamoleEnabled'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -220,6 +220,7 @@ export function Homepage() {
|
||||
closeWeatherModal={closeWeatherModal}
|
||||
openWeatherModal={openWeatherModal}
|
||||
position='top'
|
||||
personal={personal as PersonalData}
|
||||
/>
|
||||
<Header
|
||||
greet={displayedGreeting}
|
||||
@@ -245,6 +246,7 @@ export function Homepage() {
|
||||
closeWeatherModal={closeWeatherModal}
|
||||
openWeatherModal={openWeatherModal}
|
||||
position='center'
|
||||
personal={personal as PersonalData}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@@ -21,13 +21,13 @@ import type {
|
||||
CurrentWeather,
|
||||
ExtendedForecast,
|
||||
GuacamoleClient,
|
||||
PersonalData,
|
||||
Provider,
|
||||
SearchHistoryItem,
|
||||
} from 'types';
|
||||
import RecommendedApplications from './components/RecommendedApplications';
|
||||
import RecommendedBookmarks from './components/RecommendedBookmarks';
|
||||
import SearchSelectItem from './components/SearchSelectItem';
|
||||
import { FaComputer } from 'react-icons/fa6';
|
||||
|
||||
export default function Search({
|
||||
current,
|
||||
@@ -36,6 +36,7 @@ export default function Search({
|
||||
closeWeatherModal,
|
||||
openWeatherModal,
|
||||
position,
|
||||
personal,
|
||||
}: {
|
||||
current: CurrentWeather;
|
||||
extendedForecast: ExtendedForecast[];
|
||||
@@ -43,17 +44,19 @@ export default function Search({
|
||||
closeWeatherModal: () => void;
|
||||
openWeatherModal: () => void;
|
||||
position: string;
|
||||
personal: PersonalData;
|
||||
}) {
|
||||
const { ref, height } = useElementSize();
|
||||
const allIcons: any = { ...fa6, ...vsc, ...si };
|
||||
const { data: providerData, isFetched: providerDataIsFetched } = useQueryAPI({
|
||||
endpoint: 'api/providers',
|
||||
});
|
||||
const [providers, setProviders] = useState<Provider[]>([]);
|
||||
const [guacamoleClients, setGuacamoleClients] = useState<GuacamoleClient[]>([]);
|
||||
const { data: applicationData, isFetching: isApplicationDataFetching } = useQueryAPI({
|
||||
endpoint: 'api/enabledApplications',
|
||||
});
|
||||
const { data: guacamoleHostData, isFetched: guacamoleHostDataIsFetched } = useQueryAPI({
|
||||
endpoint: 'api/guacamoleHost',
|
||||
});
|
||||
const { data: guacamoleClientData, isFetched: guacamoleClientDataIsFetched } =
|
||||
useQueryAPI({
|
||||
endpoint: 'api/guacamoleClients',
|
||||
@@ -65,6 +68,9 @@ export default function Search({
|
||||
useQueryAPI({
|
||||
endpoint: 'api/providers/default',
|
||||
});
|
||||
const [providers, setProviders] = useState<Provider[]>([]);
|
||||
const [guacamoleHost, setGuacamoleHost] = useState<string | undefined>('');
|
||||
const [guacamoleClients, setGuacamoleClients] = useState<GuacamoleClient[]>([]);
|
||||
const [applications, setApplications] = useState<Application[]>([]);
|
||||
const [filteredApplications, setFilteredApplications] = useState<Application[]>([]);
|
||||
const [bookmarks, setBookmarks] = useState<Bookmark[]>([]);
|
||||
@@ -130,7 +136,7 @@ export default function Search({
|
||||
};
|
||||
|
||||
const handleGuacamoleClientLaunchItem = ({ option }: { option: any }) => {
|
||||
const validUrl = `https://sean.bet/guacamole/#/client/${option.clientIdentifier}`;
|
||||
const validUrl = `${guacamoleHost}/#/client/${option.clientIdentifier}`;
|
||||
open(validUrl, '_self');
|
||||
};
|
||||
|
||||
@@ -175,7 +181,7 @@ export default function Search({
|
||||
(client: GuacamoleClient) =>
|
||||
client.clientName.toLowerCase() === item.target.value.toLowerCase().substr(1),
|
||||
);
|
||||
open(`https://sean.bet/guacamole/#/client/${client?.clientIdentifier}`, '_self');
|
||||
open(`${guacamoleHost}/#/client/${client?.clientIdentifier}`, '_self');
|
||||
} else if (urlPattern.test(item.target.value)) {
|
||||
if (/^(https?:\/\/).*/i.test(item.target.value))
|
||||
globalThis.location = item.target.value;
|
||||
@@ -301,7 +307,7 @@ export default function Search({
|
||||
} else {
|
||||
setProviderLabel('Invalid function');
|
||||
}
|
||||
} else if (item.target.value.startsWith('>')) {
|
||||
} else if (item.target.value.startsWith('>') && personal.enableGuacamole === 1) {
|
||||
if (
|
||||
guacamoleClients?.find(
|
||||
(client: GuacamoleClient) =>
|
||||
@@ -335,7 +341,7 @@ export default function Search({
|
||||
};
|
||||
});
|
||||
}
|
||||
if (splittedSearch[0].startsWith('>')) {
|
||||
if (splittedSearch[0].startsWith('>') && personal.enableGuacamole === 1) {
|
||||
return guacamoleClientData
|
||||
.filter((guacamoleClient: GuacamoleClient) =>
|
||||
guacamoleClient.clientName
|
||||
@@ -380,15 +386,16 @@ export default function Search({
|
||||
};
|
||||
|
||||
const renderItem: any = (item: any) => {
|
||||
const Icon = item.option.icon ?
|
||||
(allIcons[
|
||||
item.option.icon
|
||||
? item.option.icon
|
||||
: item.option.prefix === '/g'
|
||||
? 'FaGoogle'
|
||||
: (providers.find((p: Provider) => p.prefix === item.option.prefix)?.icon ??
|
||||
'')
|
||||
]) : (allIcons['FaComputer']);
|
||||
const Icon = item.option.icon
|
||||
? allIcons[
|
||||
item.option.icon
|
||||
? item.option.icon
|
||||
: item.option.prefix === '/g'
|
||||
? 'FaGoogle'
|
||||
: (providers.find((p: Provider) => p.prefix === item.option.prefix)?.icon ??
|
||||
'')
|
||||
]
|
||||
: allIcons.FaComputer;
|
||||
return (searchValue as string).startsWith('!') ? (
|
||||
<Group
|
||||
pos={'relative'}
|
||||
@@ -419,7 +426,7 @@ export default function Search({
|
||||
{item.option.name}
|
||||
</Text>
|
||||
</Group>
|
||||
) : (searchValue as string).startsWith('>') ? (
|
||||
) : (searchValue as string).startsWith('>') && personal.enableGuacamole === 1 ? (
|
||||
<Group
|
||||
pos={'relative'}
|
||||
m={0}
|
||||
@@ -486,6 +493,12 @@ export default function Search({
|
||||
}
|
||||
}, [providerData, providerDataIsFetched]);
|
||||
|
||||
useEffect(() => {
|
||||
if (guacamoleHostData && guacamoleHostDataIsFetched) {
|
||||
setGuacamoleHost(guacamoleHostData[0].guacamoleHost);
|
||||
}
|
||||
}, [guacamoleClientData, guacamoleClientDataIsFetched]);
|
||||
|
||||
useEffect(() => {
|
||||
if (guacamoleClientData && guacamoleClientDataIsFetched) {
|
||||
setGuacamoleClients(guacamoleClientData);
|
||||
|
||||
@@ -16,8 +16,11 @@ function SettingsButton() {
|
||||
const { data: wolClientData, isFetched: wolClientDataIsFetched } = useQueryAPI({
|
||||
endpoint: 'api/wolClients',
|
||||
});
|
||||
const { data: wolEnabledData, isFetched: wolEnabledDataIsFetched } = useQueryAPI({
|
||||
endpoint: 'api/wolEnabled',
|
||||
});
|
||||
const [wolClients, setWolClients] = useState<WolClient[]>([]);
|
||||
|
||||
const [enabled, setEnabled] = useState<number>(0);
|
||||
const { mutateAsync } = useMutationAPI();
|
||||
const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]);
|
||||
const [selectedClient, setSelectedClient] = useState<WolClient>(wolClientData?.[0]);
|
||||
@@ -67,6 +70,11 @@ function SettingsButton() {
|
||||
}
|
||||
}, [wolClientData, wolClientDataIsFetched]);
|
||||
|
||||
useEffect(() => {
|
||||
if (wolEnabledData && wolEnabledDataIsFetched) {
|
||||
setEnabled(wolEnabledData[0].enableWol);
|
||||
}
|
||||
}, [wolEnabledData, wolEnabledDataIsFetched]);
|
||||
return (
|
||||
<Menu
|
||||
classNames={menuClasses}
|
||||
@@ -100,21 +108,23 @@ function SettingsButton() {
|
||||
width: isMobile ? '100%' : undefined,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
pos={'relative'}
|
||||
style={{ filter: wolClients.length === 0 ? 'grayscale(1)' : undefined }}
|
||||
>
|
||||
{wolClients.length === 0 && (
|
||||
<Overlay opacity={0.75} style={{ borderRadius: '10px' }} />
|
||||
)}
|
||||
<WakeOnLan
|
||||
wolClients={wolClients}
|
||||
selectedClient={selectedClient}
|
||||
setSelectedClient={setSelectedClient}
|
||||
handleWakeRequest={handleWakeRequest}
|
||||
/>
|
||||
</Box>
|
||||
<ThemingCard />
|
||||
{enabled === 1 && (
|
||||
<Box
|
||||
pos={'relative'}
|
||||
style={{ filter: wolClients.length === 0 ? 'grayscale(1)' : undefined }}
|
||||
>
|
||||
{wolClients.length === 0 && (
|
||||
<Overlay opacity={0.75} style={{ borderRadius: '10px' }} />
|
||||
)}
|
||||
<WakeOnLan
|
||||
wolClients={wolClients}
|
||||
selectedClient={selectedClient}
|
||||
setSelectedClient={setSelectedClient}
|
||||
handleWakeRequest={handleWakeRequest}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
<ThemingCard wolEnabled={enabled} />
|
||||
</Stack>
|
||||
<Stack>
|
||||
<SettingsCard
|
||||
|
||||
@@ -41,6 +41,7 @@ function SettingsCard({
|
||||
className={stackClasses.menuStack}
|
||||
classNames={stackClasses}
|
||||
pos={'relative'}
|
||||
h={150}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
} from 'styles';
|
||||
import type { Theme, ThemePlaylist } from 'types';
|
||||
|
||||
function ThemingCard() {
|
||||
function ThemingCard({ wolEnabled }: { wolEnabled: number }) {
|
||||
const { data: themePlaylistData } = useQueryAPI({
|
||||
endpoint: 'api/themePlaylists',
|
||||
});
|
||||
@@ -69,19 +69,35 @@ function ThemingCard() {
|
||||
return (
|
||||
<Stack
|
||||
gap={0}
|
||||
justify='space-between'
|
||||
justify={wolEnabled === 0 ? undefined : 'space-between'}
|
||||
className={stackClasses.menuStack}
|
||||
classNames={stackClasses}
|
||||
pos={'relative'}
|
||||
style={{ aspectRatio: isMobile ? undefined : '1/1' }}
|
||||
style={{
|
||||
aspectRatio: isMobile || wolEnabled === 0 ? undefined : '1/1',
|
||||
height: wolEnabled === 0 ? '316px' : '150px',
|
||||
width: '150px',
|
||||
}}
|
||||
>
|
||||
<Menu.Label pb={'2rem'}>Themes</Menu.Label>
|
||||
<Group mt={'-1.5rem'} mb={'-.25rem'} w={'95%'} h={'100%'} gap={0}>
|
||||
<Stack gap={0}>
|
||||
<Group
|
||||
mt={'-1.5rem'}
|
||||
mb={'-.25rem'}
|
||||
w={'95%'}
|
||||
h={wolEnabled === 0 ? undefined : '100%'}
|
||||
gap={0}
|
||||
>
|
||||
<Stack gap={0} h={'fit-content'} w={'73%'}>
|
||||
<Text className={textClasses.currentTheme} classNames={textClasses}>
|
||||
Current theme:
|
||||
</Text>
|
||||
<Text className={textClasses.themeName} classNames={textClasses}>
|
||||
<Text
|
||||
w={'100%'}
|
||||
ml={4}
|
||||
mt={wolEnabled === 0 ? '1rem' : undefined}
|
||||
className={textClasses.themeName}
|
||||
classNames={textClasses}
|
||||
>
|
||||
{text}
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
@@ -22,7 +22,11 @@ function WakeOnLan({
|
||||
pos={'relative'}
|
||||
className={stackClasses.menuStack}
|
||||
classNames={stackClasses}
|
||||
style={{ aspectRatio: isMobile ? undefined : '1/1' }}
|
||||
style={{
|
||||
aspectRatio: isMobile ? undefined : '1/1',
|
||||
height: '150px',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Menu.Label>Wake on LAN</Menu.Label>
|
||||
<Button
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ActionIcon, Divider, Group, ScrollArea, Stack, Tabs, Text } from '@mantine/core';
|
||||
import { useCommonHooks } from 'hooks';
|
||||
import { useCommonHooks, useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FaPaintBrush, FaRegListAlt } from 'react-icons/fa';
|
||||
import {
|
||||
FiArrowLeftCircle,
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
} from 'react-icons/fi';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { actionIconClasses, scrollAreaClasses, tabClasses, textClasses } from 'styles';
|
||||
import type { PersonalData } from 'types';
|
||||
import Applications from './components/Applications/Applications';
|
||||
import Bookmarks from './components/Bookmarks/Bookmarks';
|
||||
import GuacamoleClients from './components/GuacamoleClients/GuacamoleClients';
|
||||
@@ -24,9 +26,20 @@ import { Themes } from './components/Theming/Themes';
|
||||
import WolClients from './components/WoL/WolClients';
|
||||
|
||||
export function Settings() {
|
||||
const endpoint = 'api/personalData';
|
||||
const { data: personalData, isFetched: personalDataIsFetched } = useQueryAPI({
|
||||
endpoint: endpoint,
|
||||
});
|
||||
const [personal, setPersonal] = useState<PersonalData>();
|
||||
const { isMobile, theme } = useCommonHooks();
|
||||
const navigate = useNavigate();
|
||||
const { tabValue } = useParams();
|
||||
|
||||
useEffect(() => {
|
||||
if (personalData && personalDataIsFetched) {
|
||||
setPersonal(personalData[0]);
|
||||
}
|
||||
}, [personalData, personalDataIsFetched]);
|
||||
return (
|
||||
<Stack h={'100%'} gap={0}>
|
||||
<Group gap={0} style={{ position: 'relative', paddingBottom: '1rem' }}>
|
||||
@@ -142,7 +155,7 @@ export function Settings() {
|
||||
<Tabs.Tab px={isMobile ? '.9rem' : undefined} value='history'>
|
||||
{isMobile ? <FiSearch /> : 'Search History'}
|
||||
</Tabs.Tab>
|
||||
{!isMobile && (
|
||||
{!isMobile && (personal?.enableWol || personal?.enableGuacamole) ? (
|
||||
<Group w={'100%'} gap={0} justify='center'>
|
||||
<Divider
|
||||
label='Extras'
|
||||
@@ -159,13 +172,17 @@ export function Settings() {
|
||||
}}
|
||||
/>
|
||||
</Group>
|
||||
)}
|
||||
<Tabs.Tab px={isMobile ? '.9rem' : undefined} value='wolClients'>
|
||||
{isMobile ? <FiMonitor /> : 'WoL Clients'}
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab px={isMobile ? '.9rem' : undefined} value='guacamoleClients'>
|
||||
{isMobile ? <FiMonitor /> : 'Guacamole Clients'}
|
||||
</Tabs.Tab>
|
||||
) : null}
|
||||
{personal?.enableWol ? (
|
||||
<Tabs.Tab px={isMobile ? '.9rem' : undefined} value='wolClients'>
|
||||
{isMobile ? <FiMonitor /> : 'WoL Clients'}
|
||||
</Tabs.Tab>
|
||||
) : null}
|
||||
{personal?.enableGuacamole ? (
|
||||
<Tabs.Tab px={isMobile ? '.9rem' : undefined} value='guacamoleClients'>
|
||||
{isMobile ? <FiMonitor /> : 'Guacamole Clients'}
|
||||
</Tabs.Tab>
|
||||
) : null}
|
||||
</Tabs.List>
|
||||
<Tabs.Panel value='personalization'>
|
||||
<ScrollArea
|
||||
@@ -231,22 +248,26 @@ export function Settings() {
|
||||
<SearchHistory />
|
||||
</ScrollArea>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value='wolClients'>
|
||||
<ScrollArea
|
||||
className={scrollAreaClasses.default}
|
||||
classNames={scrollAreaClasses}
|
||||
>
|
||||
<WolClients />
|
||||
</ScrollArea>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value='guacamoleClients'>
|
||||
<ScrollArea
|
||||
className={scrollAreaClasses.default}
|
||||
classNames={scrollAreaClasses}
|
||||
>
|
||||
<GuacamoleClients />
|
||||
</ScrollArea>
|
||||
</Tabs.Panel>
|
||||
{personal?.enableWol ? (
|
||||
<Tabs.Panel value='wolClients'>
|
||||
<ScrollArea
|
||||
className={scrollAreaClasses.default}
|
||||
classNames={scrollAreaClasses}
|
||||
>
|
||||
<WolClients />
|
||||
</ScrollArea>
|
||||
</Tabs.Panel>
|
||||
) : null}
|
||||
{personal?.enableGuacamole ? (
|
||||
<Tabs.Panel value='guacamoleClients'>
|
||||
<ScrollArea
|
||||
className={scrollAreaClasses.default}
|
||||
classNames={scrollAreaClasses}
|
||||
>
|
||||
<GuacamoleClients />
|
||||
</ScrollArea>
|
||||
</Tabs.Panel>
|
||||
) : null}
|
||||
</Tabs>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
import { Card, Grid, GridCol, LoadingOverlay, Stack, TextInput } from '@mantine/core';
|
||||
import {
|
||||
Card,
|
||||
Grid,
|
||||
GridCol,
|
||||
LoadingOverlay,
|
||||
Stack,
|
||||
Switch,
|
||||
Text,
|
||||
TextInput,
|
||||
} from '@mantine/core';
|
||||
import { useDebouncedValue } from '@mantine/hooks';
|
||||
import { SettingsHeader } from 'components';
|
||||
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { cardClasses, textInputClasses } from 'styles';
|
||||
import { cardClasses, switchClasses, textClasses, textInputClasses } from 'styles';
|
||||
import type { PersonalData } from 'types';
|
||||
|
||||
const PersonalizationSettings = () => {
|
||||
@@ -40,7 +49,6 @@ const PersonalizationSettings = () => {
|
||||
setPersonal(update);
|
||||
}
|
||||
}, [update]);
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<SettingsHeader
|
||||
@@ -175,6 +183,66 @@ const PersonalizationSettings = () => {
|
||||
</Card>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
<Card
|
||||
w={'75%'}
|
||||
className={cardClasses.settingsItem}
|
||||
classNames={cardClasses}
|
||||
style={{ overflow: 'visible' }}
|
||||
>
|
||||
<Stack w={'100%'} px={16}>
|
||||
<Text top={-12} className={textClasses.currentTheme} classNames={textClasses}>
|
||||
Extras
|
||||
</Text>
|
||||
<Switch
|
||||
label={'Enable Wake on LAN'}
|
||||
className={switchClasses.default}
|
||||
classNames={switchClasses}
|
||||
checked={personal?.enableWol === 1}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
enableWol: event.target.checked ? 1 : 0,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
/>
|
||||
<Switch
|
||||
label={'Enable Guacamole Clients'}
|
||||
className={switchClasses.default}
|
||||
classNames={switchClasses}
|
||||
checked={personal?.enableGuacamole === 1}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
enableGuacamole: event.target.checked ? 1 : 0,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
/>
|
||||
{personal?.enableGuacamole === 1 && (
|
||||
<TextInput
|
||||
label={'Guacamole Host'}
|
||||
className={textInputClasses.settingsItem}
|
||||
classNames={textInputClasses}
|
||||
defaultValue={personal?.guacamoleHost}
|
||||
onChange={(event) => {
|
||||
const updatedPersonal = {
|
||||
...personal,
|
||||
guacamoleHost: event.currentTarget.value,
|
||||
};
|
||||
setUpdate(updatedPersonal);
|
||||
}}
|
||||
styles={
|
||||
theme.textShadowsEnabled
|
||||
? {
|
||||
label: { boxShadow: '2px 2px var(--mantine-color-border-0)' },
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</Card>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
}
|
||||
|
||||
.menuStack {
|
||||
height: 150px;
|
||||
background-color: var(--mantine-color-search-0);
|
||||
border-radius: 10px;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.fadeAway {
|
||||
|
||||
@@ -3,4 +3,7 @@ export interface PersonalData {
|
||||
lastName: string;
|
||||
email: string;
|
||||
physicalAddress: string;
|
||||
enableWol: number;
|
||||
enableGuacamole: number;
|
||||
guacamoleHost?: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user