mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-01-23 02:35:14 +00:00
Merge branch 'main' into dev
This commit is contained in:
commit
20182c7ebf
5 changed files with 11 additions and 123 deletions
|
|
@ -8,7 +8,6 @@ from drf_yasg.utils import swagger_auto_schema
|
|||
from drf_yasg import openapi
|
||||
from django.shortcuts import get_object_or_404, get_list_or_404
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
import os, json, requests, logging
|
||||
from urllib.parse import unquote
|
||||
from apps.accounts.permissions import (
|
||||
|
|
@ -421,36 +420,10 @@ class ChannelViewSet(viewsets.ModelViewSet):
|
|||
group_names = channel_group.split(",")
|
||||
qs = qs.filter(channel_group__name__in=group_names)
|
||||
|
||||
filters = {}
|
||||
q_filters = Q()
|
||||
|
||||
channel_profile_id = self.request.query_params.get("channel_profile_id")
|
||||
show_disabled_param = self.request.query_params.get("show_disabled", None)
|
||||
only_streamless = self.request.query_params.get("only_streamless", None)
|
||||
|
||||
if channel_profile_id:
|
||||
try:
|
||||
profile_id_int = int(channel_profile_id)
|
||||
filters["channelprofilemembership__channel_profile_id"] = profile_id_int
|
||||
|
||||
if show_disabled_param is None:
|
||||
filters["channelprofilemembership__enabled"] = True
|
||||
except (ValueError, TypeError):
|
||||
# Ignore invalid profile id values
|
||||
pass
|
||||
|
||||
if only_streamless:
|
||||
q_filters &= Q(streams__isnull=True)
|
||||
|
||||
if self.request.user.user_level < 10:
|
||||
filters["user_level__lte"] = self.request.user.user_level
|
||||
qs = qs.filter(user_level__lte=self.request.user.user_level)
|
||||
|
||||
if filters:
|
||||
qs = qs.filter(**filters)
|
||||
if q_filters:
|
||||
qs = qs.filter(q_filters)
|
||||
|
||||
return qs.distinct()
|
||||
return qs
|
||||
|
||||
def get_serializer_context(self):
|
||||
context = super().get_serializer_context()
|
||||
|
|
|
|||
|
|
@ -2326,7 +2326,7 @@ def xc_get_epg(request, user, short=False):
|
|||
|
||||
if short == False:
|
||||
program_output["now_playing"] = 1 if start <= django_timezone.now() <= end else 0
|
||||
program_output["has_archive"] = 0
|
||||
program_output["has_archive"] = "0"
|
||||
|
||||
output['epg_listings'].append(program_output)
|
||||
|
||||
|
|
|
|||
|
|
@ -36,14 +36,6 @@ if ! [[ "$DISPATCHARR_PORT" =~ ^[0-9]+$ ]]; then
|
|||
fi
|
||||
sed -i "s/NGINX_PORT/${DISPATCHARR_PORT}/g" /etc/nginx/sites-enabled/default
|
||||
|
||||
# Configure nginx based on IPv6 availability
|
||||
if ip -6 addr show | grep -q "inet6"; then
|
||||
echo "✅ IPv6 is available, enabling IPv6 in nginx"
|
||||
else
|
||||
echo "⚠️ IPv6 not available, disabling IPv6 in nginx"
|
||||
sed -i '/listen \[::\]:/d' /etc/nginx/sites-enabled/default
|
||||
fi
|
||||
|
||||
# NOTE: mac doesn't run as root, so only manage permissions
|
||||
# if this script is running as root
|
||||
if [ "$(id -u)" = "0" ]; then
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ const epgUrlBase = `${window.location.protocol}//${window.location.host}/output/
|
|||
const hdhrUrlBase = `${window.location.protocol}//${window.location.host}/hdhr`;
|
||||
|
||||
const ChannelEnabledSwitch = React.memo(
|
||||
({ rowId, selectedProfileId, selectedTableIds, setSelectedTableIds }) => {
|
||||
({ rowId, selectedProfileId, selectedTableIds }) => {
|
||||
// Directly extract the channels set once to avoid re-renders on every change.
|
||||
const isEnabled = useChannelsStore(
|
||||
useCallback(
|
||||
|
|
@ -79,20 +79,16 @@ const ChannelEnabledSwitch = React.memo(
|
|||
)
|
||||
);
|
||||
|
||||
const handleToggle = async () => {
|
||||
const handleToggle = () => {
|
||||
if (selectedTableIds.length > 1) {
|
||||
await API.updateProfileChannels(
|
||||
API.updateProfileChannels(
|
||||
selectedTableIds,
|
||||
selectedProfileId,
|
||||
!isEnabled
|
||||
);
|
||||
} else {
|
||||
await API.updateProfileChannel(rowId, selectedProfileId, !isEnabled);
|
||||
API.updateProfileChannel(rowId, selectedProfileId, !isEnabled);
|
||||
}
|
||||
|
||||
setSelectedTableIds([]);
|
||||
|
||||
return API.requeryChannels();
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -293,9 +289,6 @@ const ChannelsTable = ({}) => {
|
|||
const [selectedProfile, setSelectedProfile] = useState(
|
||||
profiles[selectedProfileId]
|
||||
);
|
||||
const [showDisabled, setShowDisabled] = useState(true);
|
||||
const [showOnlyStreamlessChannels, setShowOnlyStreamlessChannels] =
|
||||
useState(false);
|
||||
|
||||
const [paginationString, setPaginationString] = useState('');
|
||||
const [filters, setFilters] = useState({
|
||||
|
|
@ -376,15 +369,6 @@ const ChannelsTable = ({}) => {
|
|||
params.append('page', pagination.pageIndex + 1);
|
||||
params.append('page_size', pagination.pageSize);
|
||||
params.append('include_streams', 'true');
|
||||
if (selectedProfileId !== '0') {
|
||||
params.append('channel_profile_id', selectedProfileId);
|
||||
}
|
||||
if (showDisabled === true) {
|
||||
params.append('show_disabled', true);
|
||||
}
|
||||
if (showOnlyStreamlessChannels === true) {
|
||||
params.append('only_streamless', true);
|
||||
}
|
||||
|
||||
// Apply sorting
|
||||
if (sorting.length > 0) {
|
||||
|
|
@ -417,14 +401,7 @@ const ChannelsTable = ({}) => {
|
|||
pageSize: pagination.pageSize,
|
||||
});
|
||||
setAllRowIds(ids);
|
||||
}, [
|
||||
pagination,
|
||||
sorting,
|
||||
debouncedFilters,
|
||||
showDisabled,
|
||||
selectedProfileId,
|
||||
showOnlyStreamlessChannels,
|
||||
]);
|
||||
}, [pagination, sorting, debouncedFilters]);
|
||||
|
||||
const stopPropagation = useCallback((e) => {
|
||||
e.stopPropagation();
|
||||
|
|
@ -751,7 +728,6 @@ const ChannelsTable = ({}) => {
|
|||
rowId={row.original.id}
|
||||
selectedProfileId={selectedProfileId}
|
||||
selectedTableIds={table.getState().selectedTableIds}
|
||||
setSelectedTableIds={table.setSelectedTableIds}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
|
@ -1350,10 +1326,6 @@ const ChannelsTable = ({}) => {
|
|||
deleteChannels={deleteChannels}
|
||||
selectedTableIds={table.selectedTableIds}
|
||||
table={table}
|
||||
showDisabled={showDisabled}
|
||||
setShowDisabled={setShowDisabled}
|
||||
showOnlyStreamlessChannels={showOnlyStreamlessChannels}
|
||||
setShowOnlyStreamlessChannels={setShowOnlyStreamlessChannels}
|
||||
/>
|
||||
|
||||
{/* Table or ghost empty state inside Paper */}
|
||||
|
|
|
|||
|
|
@ -12,22 +12,20 @@ import {
|
|||
Text,
|
||||
TextInput,
|
||||
Tooltip,
|
||||
UnstyledButton,
|
||||
useMantineTheme,
|
||||
} from '@mantine/core';
|
||||
import {
|
||||
ArrowDown01,
|
||||
Binary,
|
||||
Check,
|
||||
CircleCheck,
|
||||
Ellipsis,
|
||||
EllipsisVertical,
|
||||
SquareMinus,
|
||||
SquarePen,
|
||||
SquarePlus,
|
||||
Settings,
|
||||
Eye,
|
||||
EyeOff,
|
||||
Filter,
|
||||
Square,
|
||||
SquareCheck,
|
||||
} from 'lucide-react';
|
||||
import API from '../../../api';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
|
|
@ -104,10 +102,6 @@ const ChannelTableHeader = ({
|
|||
editChannel,
|
||||
deleteChannels,
|
||||
selectedTableIds,
|
||||
showDisabled,
|
||||
setShowDisabled,
|
||||
showOnlyStreamlessChannels,
|
||||
setShowOnlyStreamlessChannels,
|
||||
}) => {
|
||||
const theme = useMantineTheme();
|
||||
|
||||
|
|
@ -214,14 +208,6 @@ const ChannelTableHeader = ({
|
|||
);
|
||||
};
|
||||
|
||||
const toggleShowDisabled = () => {
|
||||
setShowDisabled(!showDisabled);
|
||||
};
|
||||
|
||||
const toggleShowOnlyStreamlessChannels = () => {
|
||||
setShowOnlyStreamlessChannels(!showOnlyStreamlessChannels);
|
||||
};
|
||||
|
||||
return (
|
||||
<Group justify="space-between">
|
||||
<Group gap={5} style={{ paddingLeft: 10 }}>
|
||||
|
|
@ -250,41 +236,6 @@ const ChannelTableHeader = ({
|
|||
}}
|
||||
>
|
||||
<Flex gap={6}>
|
||||
<Menu shadow="md" width={200}>
|
||||
<Menu.Target>
|
||||
<Button size="xs" variant="default" onClick={() => {}}>
|
||||
<Filter size={18} />
|
||||
</Button>
|
||||
</Menu.Target>
|
||||
|
||||
<Menu.Dropdown>
|
||||
<Menu.Item
|
||||
onClick={toggleShowDisabled}
|
||||
leftSection={
|
||||
showDisabled ? <Eye size={18} /> : <EyeOff size={18} />
|
||||
}
|
||||
disabled={selectedProfileId === '0'}
|
||||
>
|
||||
<Text size="xs">
|
||||
{showDisabled ? 'Hide Disabled' : 'Show Disabled'}
|
||||
</Text>
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item
|
||||
onClick={toggleShowOnlyStreamlessChannels}
|
||||
leftSection={
|
||||
showOnlyStreamlessChannels ? (
|
||||
<SquareCheck size={18} />
|
||||
) : (
|
||||
<Square size={18} />
|
||||
)
|
||||
}
|
||||
>
|
||||
<Text size="xs">Only Empty Channels</Text>
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
|
||||
<Button
|
||||
leftSection={<SquarePen size={18} />}
|
||||
variant="default"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue