WoL Update

This commit is contained in:
Sean Edmunds
2025-01-28 11:51:44 -06:00
parent f2073f951d
commit 6031394c59
8 changed files with 144 additions and 16 deletions

View File

@@ -0,0 +1,50 @@
import type { MRT_ColumnDef } from 'mantine-react-table';
import { useMemo } from 'react';
export function WolClientColumns() {
const columns = useMemo<MRT_ColumnDef<any>[]>(
() => [
{
accessorFn: (row) => {
if (row.id) {
return `${row.id}`;
}
return '';
},
enableEditing: false,
id: 'id',
header: 'ID',
size: 50,
Cell: ({ renderedCellValue }) => renderedCellValue,
Header: ({ column }) => column.columnDef.header,
},
{
accessorFn: (row) => {
if (row.hostname) {
return `${row.hostname}`;
}
return '';
},
id: 'hostname',
header: 'Hostname',
Cell: ({ renderedCellValue }) => renderedCellValue,
Header: ({ column }) => column.columnDef.header,
},
{
accessorFn: (row) => {
if (row.macAddress) {
return `${row.macAddress}`;
}
return '';
},
id: 'macAddress',
header: 'MAC Address',
Cell: ({ renderedCellValue }) => renderedCellValue,
Header: ({ column }) => column.columnDef.header,
},
],
[],
);
return columns;
}

View File

@@ -9,3 +9,4 @@ export { CategoryColumns } from './DataTable/columns/CategoryColumns';
export { MessagesColumns } from './DataTable/columns/MessagesColumns'; export { MessagesColumns } from './DataTable/columns/MessagesColumns';
export { PersonalizationColumns } from './DataTable/columns/PersonalizationColumns'; export { PersonalizationColumns } from './DataTable/columns/PersonalizationColumns';
export { SearchProviderColumns } from './DataTable/columns/SearchProviderColumns'; export { SearchProviderColumns } from './DataTable/columns/SearchProviderColumns';
export { WolClientColumns } from './DataTable/columns/WolClientColumns';

View File

@@ -45,11 +45,3 @@ export function containsProtocol(str: any) {
const pattern = /^(https?:\/\/).*/i; const pattern = /^(https?:\/\/).*/i;
return !!pattern.test(str); return !!pattern.test(str);
} }
export function runWakeCommand() {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
};
fetch(`/${import.meta.env.VITE_BASE_URL}/api/wakeDakota`, requestOptions);
}

View File

@@ -1,3 +1,3 @@
export { useQueryAPI, useWeatherAPI, useMutationAPI } from './useAPI'; export { useQueryAPI, useWeatherAPI, useMutationAPI } from './useAPI';
export { date, greet, runWakeCommand, validURL, containsProtocol } from './helpers'; export { date, greet, validURL, containsProtocol } from './helpers';
export { useCommonHooks } from './useCommonHooks'; export { useCommonHooks } from './useCommonHooks';

View File

@@ -56,6 +56,12 @@ export function useCommonHooks() {
isFetching: providersIsFetching, isFetching: providersIsFetching,
isLoading: providersIsLoading, isLoading: providersIsLoading,
} = useQueryAPI({ endpoint: 'api/providers' }); } = useQueryAPI({ endpoint: 'api/providers' });
const {
data: wolClients,
isFetched: wolClientsIsFetched,
isFetching: wolClientsIsFetching,
isLoading: wolClientsIsLoading,
} = useQueryAPI({ endpoint: 'api/wolClients' });
const { data: basicWeather } = useWeatherAPI({ endpoint: 'baseline' }); const { data: basicWeather } = useWeatherAPI({ endpoint: 'baseline' });
const { data: weather } = useWeatherAPI({ endpoint: 'current' }); const { data: weather } = useWeatherAPI({ endpoint: 'current' });
const { data: forecast } = useWeatherAPI({ endpoint: 'forecast' }); const { data: forecast } = useWeatherAPI({ endpoint: 'forecast' });
@@ -147,6 +153,14 @@ export function useCommonHooks() {
} }
}, [providers, providersIsFetched]); }, [providers, providersIsFetched]);
const [wolClientsData, setWolClientsData] = useState<any>([]);
useEffect(() => {
if (wolClients && wolClientsIsFetched) {
setWolClientsData(wolClients);
}
}, [wolClients, wolClientsIsFetched]);
return { return {
isMobile, isMobile,
theme, theme,
@@ -203,6 +217,11 @@ export function useCommonHooks() {
personalIsFetched, personalIsFetched,
personalIsFetching, personalIsFetching,
personalIsLoading, personalIsLoading,
wolClients,
wolClientsData,
wolClientsIsFetched,
wolClientsIsFetching,
wolClientsIsLoading,
notify, notify,
}; };
} }

View File

@@ -4,11 +4,12 @@ import {
Group, Group,
Menu, Menu,
MultiSelect, MultiSelect,
Select,
Stack, Stack,
Text, Text,
Tooltip, Tooltip,
} from '@mantine/core'; } from '@mantine/core';
import { runWakeCommand, useCommonHooks, useQueryAPI } from 'hooks'; import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { FaDice } from 'react-icons/fa'; import { FaDice } from 'react-icons/fa';
import { FiMenu, FiMonitor, FiSettings, FiShuffle } from 'react-icons/fi'; import { FiMenu, FiMonitor, FiSettings, FiShuffle } from 'react-icons/fi';
@@ -23,6 +24,7 @@ import {
function SettingsButton() { function SettingsButton() {
const { data, isFetched } = useQueryAPI({ endpoint: 'api/appCategories' }); const { data, isFetched } = useQueryAPI({ endpoint: 'api/appCategories' });
const { mutateAsync: wakeRequest } = useMutationAPI();
const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]); const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]);
const navigate = useNavigate(); const navigate = useNavigate();
const { const {
@@ -36,19 +38,30 @@ function SettingsButton() {
bookmarkFilter, bookmarkFilter,
setBookmarkFilter, setBookmarkFilter,
isMobile, isMobile,
wolClients,
notify, notify,
} = useCommonHooks(); } = useCommonHooks();
const [selectedClient, setSelectedClient] = useState<any>(wolClients?.[0]);
const handleWakeRequest = () => {
wakeRequest({
method: 'POST',
endpoint: 'api/wakeClient',
body: selectedClient || wolClients?.[0],
});
};
useEffect(() => { useEffect(() => {
if (data) { if (data) {
const list: [any] = const list: [any] = data.map((category: any) => {
data.map((category: any) => { return { value: category.filterName, label: category.filterName };
return { value: category.filterName, label: category.filterName }; });
}) || [];
list.unshift({ value: 'All', label: 'All' }); list.unshift({ value: 'All', label: 'All' });
setCategories(list); setCategories(list);
} }
}, [data, isFetched]); }, [data, isFetched]);
return ( return (
<Menu <Menu
classNames={menuClasses} classNames={menuClasses}
@@ -88,16 +101,35 @@ function SettingsButton() {
<Button <Button
classNames={buttonClasses} classNames={buttonClasses}
className={buttonClasses.wakeButton} className={buttonClasses.wakeButton}
disabled={!wolClients?.length}
onClick={() => { onClick={() => {
runWakeCommand(); handleWakeRequest();
notify('Wake command sent'); notify('Wake command sent');
}} }}
> >
<Stack gap={0} align='center'> <Stack gap={0} align='center'>
<FiMonitor size={40} /> <FiMonitor size={40} />
<Text>Dakota</Text>
</Stack> </Stack>
</Button> </Button>
<Select
labelProps={{ display: 'none' }}
placeholder='Pick a host...'
defaultValue={wolClients?.[0]?.hostname}
data={
wolClients?.map((wolClient: any) => {
return {
value: wolClient.hostname,
label: `${wolClient.hostname} (${wolClient.macAddress})`,
hostname: wolClient.hostname,
macAddress: wolClient.macAddress,
};
}) || []
}
classNames={selectClasses}
comboboxProps={{ withinPortal: false }}
onChange={(_value, option: any) => setSelectedClient(option)}
onLoad={(option: any) => setSelectedClient(option)}
/>
</Stack> </Stack>
<Stack <Stack
gap={0} gap={0}

View File

@@ -7,6 +7,7 @@ import {
FiEdit, FiEdit,
FiGlobe, FiGlobe,
FiMail, FiMail,
FiMonitor,
FiSearch, FiSearch,
FiUser, FiUser,
} from 'react-icons/fi'; } from 'react-icons/fi';
@@ -19,6 +20,7 @@ import Messages from './components/Messages';
import Personalization from './components/Personalization'; import Personalization from './components/Personalization';
import SearchProviders from './components/SearchProviders'; import SearchProviders from './components/SearchProviders';
import Themes from './components/Themes'; import Themes from './components/Themes';
import WolClients from './components/WolClients';
export function Settings() { export function Settings() {
const { isMobile } = useCommonHooks(); const { isMobile } = useCommonHooks();
@@ -60,6 +62,9 @@ export function Settings() {
<Tabs.Tab value='providers'> <Tabs.Tab value='providers'>
{isMobile ? <FiSearch /> : 'Search Providers'} {isMobile ? <FiSearch /> : 'Search Providers'}
</Tabs.Tab> </Tabs.Tab>
<Tabs.Tab value='wolClients'>
{isMobile ? <FiMonitor /> : 'WoL Clients'}
</Tabs.Tab>
</Tabs.List> </Tabs.List>
<Tabs.Panel value='personalization'> <Tabs.Panel value='personalization'>
<Personalization /> <Personalization />
@@ -82,6 +87,9 @@ export function Settings() {
<Tabs.Panel value='providers'> <Tabs.Panel value='providers'>
<SearchProviders /> <SearchProviders />
</Tabs.Panel> </Tabs.Panel>
<Tabs.Panel value='wolClients'>
<WolClients />
</Tabs.Panel>
</Tabs> </Tabs>
</Stack> </Stack>
); );

View File

@@ -0,0 +1,26 @@
import { Stack, Text } from '@mantine/core';
import { DataTable, WolClientColumns } from 'components';
import { useCommonHooks } from 'hooks';
import { textClasses } from 'styles';
const WolClientSettings = () => {
const endpoint = 'api/wolClients';
const { wolClientsData, wolClientsIsFetching, wolClientsIsLoading } = useCommonHooks();
return (
<Stack>
<Text className={textClasses.settingsSubTitle} classNames={textClasses}>
WoL Clients
</Text>
<DataTable
tableName='WoL Clients'
columns={WolClientColumns()}
tableData={wolClientsData}
isFetching={wolClientsIsFetching}
isLoading={wolClientsIsLoading}
endpoint={endpoint}
/>
</Stack>
);
};
export default WolClientSettings;