Skip to content

Commit f9f6520

Browse files
committed
Revamp WLED device page & other improvements
1 parent 05567e2 commit f9f6520

7 files changed

Lines changed: 114 additions & 84 deletions

File tree

src/renderer/components/shared/DeviceSelector.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ export interface DeviceSelectorConfig<TDevice, TRawDevice = TDevice> {
2525
columns: GridColDef[];
2626
/** Config key where selected device IDs are stored */
2727
configKey: keyof IConfig;
28-
/** Refresh interval in milliseconds (default: 2000) */
29-
refreshInterval?: number;
3028
}
3129

3230
interface DeviceSelectorProps<TDevice, TRawDevice = TDevice> {
@@ -63,7 +61,7 @@ export function DeviceSelector<TDevice, TRawDevice = TDevice>({
6361
selectedDevices: data.selectedDevices,
6462
};
6563
},
66-
{ refreshInterval: selectorConfig.refreshInterval ?? 2000 },
64+
{ refreshInterval: 2000 },
6765
);
6866

6967
const { data: integrationState, error: integrationError } = useSWR(

src/renderer/pages/EventEditor.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ export function EventEditorPage() {
138138
{
139139
field: "edit",
140140
headerName: "Tools",
141-
width: 120,
141+
width: 130,
142+
sortable: false,
143+
filterable: false,
142144
renderCell: (params) => (
143145
<ToolsCell
144146
params={params}
@@ -165,7 +167,6 @@ export function EventEditorPage() {
165167
triggers: triggers.join(", "),
166168
actions: event.actions.length,
167169
amount: event.amount,
168-
edit: "Edit",
169170
};
170171
});
171172
}, [config]);

src/renderer/pages/HomeAssistantDeviceSelector.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
DeviceSelectorConfig,
66
} from "../components/shared/DeviceSelector";
77

8-
interface HomeAssistantDevice {
8+
interface IHomeAssistantDevice {
99
entity_id: string;
1010
state: string;
1111
attributes: {
@@ -21,7 +21,7 @@ const columns: GridColDef[] = [
2121

2222
const selectorConfig: DeviceSelectorConfig<
2323
{ id: string; name: string; state: string },
24-
HomeAssistantDevice
24+
IHomeAssistantDevice
2525
> = {
2626
integrationName: "homeAssistant",
2727
swrKey: "homeAssistantDevices",

src/renderer/pages/IkeaTradfriDeviceSelector.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
} from "../components/shared/DeviceSelector";
77
import { IGetTradfriDevicesResponse } from "../../shared/integrations/tradfri_types";
88

9-
type IkeaTradfriDevice = IGetTradfriDevicesResponse["devices"][number];
9+
type IIkeaTradfriDevice = IGetTradfriDevicesResponse["devices"][number];
1010

1111
const columns: GridColDef[] = [
1212
{ field: "name", headerName: "Name", flex: 1, minWidth: 200 },
@@ -17,7 +17,7 @@ const columns: GridColDef[] = [
1717

1818
const selectorConfig: DeviceSelectorConfig<
1919
{ id: string; name: string; state: string; spectrum: string },
20-
IkeaTradfriDevice
20+
IIkeaTradfriDevice
2121
> = {
2222
integrationName: "tradfri",
2323
swrKey: "ikeaTradfriDevices",

src/renderer/pages/PhilipsHueDeviceSelector.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
DeviceSelectorConfig,
66
} from "../components/shared/DeviceSelector";
77

8-
interface PhilipsHueDevice {
8+
interface IPhilipsHueDevice {
99
id: string;
1010
name: string;
1111
state: boolean;
@@ -19,7 +19,7 @@ const columns: GridColDef[] = [
1919

2020
const selectorConfig: DeviceSelectorConfig<
2121
{ id: string; name: string; state: string },
22-
PhilipsHueDevice
22+
IPhilipsHueDevice
2323
> = {
2424
integrationName: "philipsHue",
2525
swrKey: "philipsHueDevices",

src/renderer/pages/PhilipsHueGroupSelector.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
DeviceSelectorConfig,
66
} from "../components/shared/DeviceSelector";
77

8-
interface PhilipsHueGroup {
8+
interface IPhilipsHueGroup {
99
id: string;
1010
name: string;
1111
state: boolean;
@@ -19,7 +19,7 @@ const columns: GridColDef[] = [
1919

2020
const selectorConfig: DeviceSelectorConfig<
2121
{ id: string; name: string; state: string },
22-
PhilipsHueGroup
22+
IPhilipsHueGroup
2323
> = {
2424
integrationName: "philipsHue",
2525
swrKey: "philipsHueGroups",

src/renderer/pages/WLEDDeviceSelector.tsx

Lines changed: 102 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
import React, { useCallback, useState } from "react";
2-
import { Box, Button, Stack, TextField, Typography } from "@mui/material";
2+
import {
3+
Box,
4+
Button,
5+
TextField,
6+
Paper,
7+
List,
8+
ListItem,
9+
ListItemText,
10+
IconButton,
11+
InputAdornment,
12+
Alert,
13+
} from "@mui/material";
14+
import { AddRounded, DeleteRounded, DevicesRounded } from "@mui/icons-material";
315
import { useConfig } from "../hooks/useConfig";
416
import { ContentLayout } from "../components/layouts/ContentLayout";
517

@@ -36,81 +48,100 @@ export function WLEDDeviceSelector() {
3648
[alreadySelectedDevices],
3749
);
3850

51+
const handleSubmit = useCallback(() => {
52+
if (isValidDevice(inputValue)) {
53+
handleAddDevice(inputValue);
54+
setInputValue("");
55+
}
56+
}, [inputValue, isValidDevice, handleAddDevice]);
57+
3958
return (
40-
<ContentLayout title="Configure WLED Devices" titleVariant="h2" container>
59+
<ContentLayout container title="" hideTitle>
4160
<Box
42-
display="flex"
43-
flexDirection="column"
44-
justifyContent="center"
45-
alignItems="center"
46-
padding={2}
61+
sx={{
62+
display: "flex",
63+
flexDirection: "column",
64+
gap: 2,
65+
my: 2,
66+
}}
4767
>
48-
<Stack spacing={2} direction="row" alignItems="center">
49-
<TextField
50-
label="WLED Device IP/Hostname"
51-
error={(inputValue && !isValidDevice(inputValue)) as boolean}
52-
// helperText={
53-
// (inputValue &&
54-
// !isValidDevice(inputValue) &&
55-
// "Invalid IP address/hostname or already added") ||
56-
// undefined
57-
// } causes bug in button alignment
58-
value={inputValue}
59-
onChange={(e) => setInputValue(e.target.value)}
60-
onKeyDown={(e) => {
61-
if (e.key === "Enter" && isValidDevice(inputValue)) {
62-
handleAddDevice(inputValue);
63-
setInputValue("");
64-
}
65-
}}
66-
/>
67-
68-
<Button
69-
variant="contained"
70-
disabled={!isValidDevice(inputValue)}
71-
sx={{ alignSelf: "center" }}
72-
onClick={() => {
73-
if (isValidDevice(inputValue)) {
74-
handleAddDevice(inputValue);
75-
setInputValue("");
76-
}
77-
}}
78-
>
79-
Add
80-
</Button>
81-
</Stack>
68+
<TextField
69+
placeholder="Enter WLED device IP or hostname..."
70+
value={inputValue}
71+
onChange={(e) => setInputValue(e.target.value)}
72+
onKeyDown={(e) => {
73+
if (e.key === "Enter") {
74+
handleSubmit();
75+
}
76+
}}
77+
error={inputValue !== "" && !isValidDevice(inputValue)}
78+
helperText={
79+
inputValue !== "" && !isValidDevice(inputValue)
80+
? "Invalid IP/hostname or already added"
81+
: " "
82+
}
83+
fullWidth
84+
slotProps={{
85+
input: {
86+
startAdornment: (
87+
<InputAdornment position="start">
88+
<DevicesRounded />
89+
</InputAdornment>
90+
),
91+
endAdornment: (
92+
<InputAdornment position="end">
93+
<Button
94+
variant="contained"
95+
disabled={!isValidDevice(inputValue)}
96+
onClick={handleSubmit}
97+
startIcon={<AddRounded />}
98+
>
99+
Add
100+
</Button>
101+
</InputAdornment>
102+
),
103+
},
104+
}}
105+
sx={{ maxWidth: 600 }}
106+
/>
82107

83-
<Typography variant="h4" gutterBottom sx={{ marginTop: 5 }}>
84-
Added Devices
85-
</Typography>
86-
87-
{alreadySelectedDevices.length === 0 && (
88-
<Typography variant="body1" gutterBottom color="text.secondary">
89-
No devices added
90-
</Typography>
108+
{alreadySelectedDevices.length > 0 ? (
109+
<Paper elevation={2}>
110+
<List disablePadding>
111+
{alreadySelectedDevices.map((deviceIp, index) => (
112+
<ListItem
113+
key={deviceIp}
114+
divider={index < alreadySelectedDevices.length - 1}
115+
secondaryAction={
116+
<IconButton
117+
edge="end"
118+
aria-label="delete"
119+
onClick={() => handleRemoveDevice(deviceIp)}
120+
color="error"
121+
>
122+
<DeleteRounded />
123+
</IconButton>
124+
}
125+
>
126+
<ListItemText
127+
primary={deviceIp}
128+
slotProps={{
129+
primary: {
130+
fontFamily: "monospace",
131+
fontSize: "0.95rem",
132+
},
133+
}}
134+
/>
135+
</ListItem>
136+
))}
137+
</List>
138+
</Paper>
139+
) : (
140+
<Alert severity="info">
141+
No devices added yet. Enter an IP address or hostname above to add a
142+
WLED device.
143+
</Alert>
91144
)}
92-
93-
<Stack spacing={2}>
94-
{alreadySelectedDevices.map((deviceIp) => (
95-
<Box key={deviceIp} display="flex" justifyContent="space-between">
96-
<Typography
97-
variant="body1"
98-
sx={{ alignSelf: "center", overflow: "hidden", mr: 2 }}
99-
>
100-
{deviceIp}
101-
</Typography>
102-
<Button
103-
variant="contained"
104-
color="error"
105-
size="small"
106-
sx={{ height: "100%", alignSelf: "center" }}
107-
onClick={() => handleRemoveDevice(deviceIp)}
108-
>
109-
Remove
110-
</Button>
111-
</Box>
112-
))}
113-
</Stack>
114145
</Box>
115146
</ContentLayout>
116147
);

0 commit comments

Comments
 (0)