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