mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-25 11:04:07 +00:00
Improve error handling and validation for playlist profiles in M3UProfiles component
This commit is contained in:
parent
72ed1ff4f4
commit
95277679b0
1 changed files with 90 additions and 69 deletions
|
|
@ -29,8 +29,19 @@ const M3UProfiles = ({ playlist = null, isOpen, onClose }) => {
|
|||
const [profiles, setProfiles] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
setProfiles(allProfiles[playlist.id]);
|
||||
}, [allProfiles]);
|
||||
try {
|
||||
// Make sure playlist exists, has an id, and profiles exist for this playlist
|
||||
if (playlist && playlist.id && allProfiles && allProfiles[playlist.id]) {
|
||||
setProfiles(allProfiles[playlist.id]);
|
||||
} else {
|
||||
// Reset profiles if none are available
|
||||
setProfiles([]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error setting profiles:', error);
|
||||
setProfiles([]);
|
||||
}
|
||||
}, [allProfiles, playlist]);
|
||||
|
||||
const editProfile = (profile = null) => {
|
||||
if (profile) {
|
||||
|
|
@ -41,21 +52,36 @@ const M3UProfiles = ({ playlist = null, isOpen, onClose }) => {
|
|||
};
|
||||
|
||||
const deleteProfile = async (id) => {
|
||||
await API.deleteM3UProfile(playlist.id, id);
|
||||
if (!playlist || !playlist.id) return;
|
||||
try {
|
||||
await API.deleteM3UProfile(playlist.id, id);
|
||||
} catch (error) {
|
||||
console.error('Error deleting profile:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleActive = async (values) => {
|
||||
await API.updateM3UProfile(playlist.id, {
|
||||
...values,
|
||||
is_active: !values.is_active,
|
||||
});
|
||||
if (!playlist || !playlist.id) return;
|
||||
try {
|
||||
await API.updateM3UProfile(playlist.id, {
|
||||
...values,
|
||||
is_active: !values.is_active,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error toggling profile active state:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const modifyMaxStreams = async (value, item) => {
|
||||
await API.updateM3UProfile(playlist.id, {
|
||||
...item,
|
||||
max_streams: value,
|
||||
});
|
||||
if (!playlist || !playlist.id) return;
|
||||
try {
|
||||
await API.updateM3UProfile(playlist.id, {
|
||||
...item,
|
||||
max_streams: value,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error updating max streams:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const closeEditor = () => {
|
||||
|
|
@ -63,80 +89,75 @@ const M3UProfiles = ({ playlist = null, isOpen, onClose }) => {
|
|||
setProfileEditorOpen(false);
|
||||
};
|
||||
|
||||
if (!isOpen || !profiles) {
|
||||
// Don't render if modal is not open, or if playlist data is invalid
|
||||
if (!isOpen || !playlist || !playlist.id) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
// Make sure profiles is always an array even if we have no data
|
||||
const profilesArray = Array.isArray(profiles) ? profiles : [];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal opened={isOpen} onClose={onClose} title="Profiles">
|
||||
{profiles
|
||||
// .filter((playlist) => playlist.is_default == false)
|
||||
.map((item) => (
|
||||
<Card
|
||||
key={item.id} // Uncomment/add key prop to fix the list warning
|
||||
// sx={{
|
||||
// display: 'flex',
|
||||
// alignItems: 'center',
|
||||
// marginBottom: 2,
|
||||
// }}
|
||||
>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Group justify="space-between">
|
||||
<Text fw={600}>{item.name}</Text>
|
||||
<Switch
|
||||
checked={item.is_active}
|
||||
onChange={() => toggleActive(item)}
|
||||
disabled={item.is_default}
|
||||
style={{ paddingTop: 6 }}
|
||||
/>
|
||||
</Group>
|
||||
{profilesArray.map((item) => (
|
||||
<Card key={item.id}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Group justify="space-between">
|
||||
<Text fw={600}>{item.name}</Text>
|
||||
<Switch
|
||||
checked={item.is_active}
|
||||
onChange={() => toggleActive(item)}
|
||||
disabled={item.is_default}
|
||||
style={{ paddingTop: 6 }}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Flex gap="sm">
|
||||
<NumberInput
|
||||
label="Max Streams"
|
||||
value={item.max_streams}
|
||||
disabled={item.is_default}
|
||||
onChange={(value) => modifyMaxStreams(value, item)}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
<Flex gap="sm">
|
||||
<NumberInput
|
||||
label="Max Streams"
|
||||
value={item.max_streams}
|
||||
disabled={item.is_default}
|
||||
onChange={(value) => modifyMaxStreams(value, item)}
|
||||
style={{ flex: 1 }}
|
||||
/>
|
||||
|
||||
{!item.is_default && (
|
||||
<Group
|
||||
align="flex-end"
|
||||
gap="xs"
|
||||
style={{ paddingBottom: 8 }}
|
||||
{!item.is_default && (
|
||||
<Group
|
||||
align="flex-end"
|
||||
gap="xs"
|
||||
style={{ paddingBottom: 8 }}
|
||||
>
|
||||
<ActionIcon
|
||||
size="sm"
|
||||
variant="transparent"
|
||||
color={theme.tailwind.yellow[3]}
|
||||
onClick={() => editProfile(item)}
|
||||
>
|
||||
<ActionIcon
|
||||
size="sm"
|
||||
variant="transparent"
|
||||
color={theme.tailwind.yellow[3]}
|
||||
onClick={() => editProfile(item)}
|
||||
>
|
||||
<SquarePen size="=20" />
|
||||
</ActionIcon>
|
||||
<SquarePen size="20" />
|
||||
</ActionIcon>
|
||||
|
||||
<ActionIcon
|
||||
color={theme.tailwind.red[6]}
|
||||
onClick={() => deleteProfile(item.id)}
|
||||
size="small"
|
||||
variant="transparent"
|
||||
>
|
||||
<SquareMinus size="20" />
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
)}
|
||||
</Flex>
|
||||
</Box>
|
||||
</Card>
|
||||
))}
|
||||
<ActionIcon
|
||||
color={theme.tailwind.red[6]}
|
||||
onClick={() => deleteProfile(item.id)}
|
||||
size="small"
|
||||
variant="transparent"
|
||||
>
|
||||
<SquareMinus size="20" />
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
)}
|
||||
</Flex>
|
||||
</Box>
|
||||
</Card>
|
||||
))}
|
||||
|
||||
<Flex mih={50} gap="xs" justify="flex-end" align="flex-end">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
size="small"
|
||||
onClick={editProfile}
|
||||
onClick={() => editProfile()}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
New
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue