From 43b55e2d9913a71ffec5a1998079e7ea2dd4be3c Mon Sep 17 00:00:00 2001 From: dekzter Date: Mon, 8 Dec 2025 08:38:39 -0500 Subject: [PATCH] first run at hiding disabled channels in channel profiles --- apps/channels/api_views.py | 21 ++++++++++++++++ .../src/components/tables/ChannelsTable.jsx | 24 +++++++++++++++---- .../ChannelsTable/ChannelTableHeader.jsx | 14 +++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/apps/channels/api_views.py b/apps/channels/api_views.py index eccc5028..4cfe9777 100644 --- a/apps/channels/api_views.py +++ b/apps/channels/api_views.py @@ -419,6 +419,27 @@ class ChannelViewSet(viewsets.ModelViewSet): group_names = channel_group.split(",") qs = qs.filter(channel_group__name__in=group_names) + channel_profile_id = self.request.query_params.get("channel_profile_id") + show_disabled_param = self.request.query_params.get("show_disabled", None) + + if channel_profile_id: + try: + profile_id_int = int(channel_profile_id) + # If show_disabled is present, include all memberships for that profile. + # If absent, restrict to enabled=True. + if show_disabled_param is None: + qs = qs.filter( + channelprofilemembership__channel_profile_id=profile_id_int, + channelprofilemembership__enabled=True, + ) + else: + qs = qs.filter( + channelprofilemembership__channel_profile_id=profile_id_int + ) + except (ValueError, TypeError): + # Ignore invalid profile id values + pass + if self.request.user.user_level < 10: qs = qs.filter(user_level__lte=self.request.user.user_level) diff --git a/frontend/src/components/tables/ChannelsTable.jsx b/frontend/src/components/tables/ChannelsTable.jsx index 9b9958f7..949b9760 100644 --- a/frontend/src/components/tables/ChannelsTable.jsx +++ b/frontend/src/components/tables/ChannelsTable.jsx @@ -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 }) => { + ({ rowId, selectedProfileId, selectedTableIds, setSelectedTableIds }) => { // Directly extract the channels set once to avoid re-renders on every change. const isEnabled = useChannelsStore( useCallback( @@ -79,16 +79,20 @@ const ChannelEnabledSwitch = React.memo( ) ); - const handleToggle = () => { + const handleToggle = async () => { if (selectedTableIds.length > 1) { - API.updateProfileChannels( + await API.updateProfileChannels( selectedTableIds, selectedProfileId, !isEnabled ); } else { - API.updateProfileChannel(rowId, selectedProfileId, !isEnabled); + await API.updateProfileChannel(rowId, selectedProfileId, !isEnabled); } + + setSelectedTableIds([]); + + return API.requeryChannels(); }; return ( @@ -289,6 +293,7 @@ const ChannelsTable = ({}) => { const [selectedProfile, setSelectedProfile] = useState( profiles[selectedProfileId] ); + const [showDisabled, setShowDisabled] = useState(true); const [paginationString, setPaginationString] = useState(''); const [filters, setFilters] = useState({ @@ -369,6 +374,12 @@ 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); + } // Apply sorting if (sorting.length > 0) { @@ -401,7 +412,7 @@ const ChannelsTable = ({}) => { pageSize: pagination.pageSize, }); setAllRowIds(ids); - }, [pagination, sorting, debouncedFilters]); + }, [pagination, sorting, debouncedFilters, showDisabled, selectedProfileId]); const stopPropagation = useCallback((e) => { e.stopPropagation(); @@ -728,6 +739,7 @@ const ChannelsTable = ({}) => { rowId={row.original.id} selectedProfileId={selectedProfileId} selectedTableIds={table.getState().selectedTableIds} + setSelectedTableIds={table.setSelectedTableIds} /> ); }, @@ -1326,6 +1338,8 @@ const ChannelsTable = ({}) => { deleteChannels={deleteChannels} selectedTableIds={table.selectedTableIds} table={table} + showDisabled={showDisabled} + setShowDisabled={setShowDisabled} /> {/* Table or ghost empty state inside Paper */} diff --git a/frontend/src/components/tables/ChannelsTable/ChannelTableHeader.jsx b/frontend/src/components/tables/ChannelsTable/ChannelTableHeader.jsx index b7e04d7d..d3376b4d 100644 --- a/frontend/src/components/tables/ChannelsTable/ChannelTableHeader.jsx +++ b/frontend/src/components/tables/ChannelsTable/ChannelTableHeader.jsx @@ -26,6 +26,8 @@ import { SquarePen, SquarePlus, Settings, + Eye, + EyeOff, } from 'lucide-react'; import API from '../../../api'; import { notifications } from '@mantine/notifications'; @@ -102,6 +104,8 @@ const ChannelTableHeader = ({ editChannel, deleteChannels, selectedTableIds, + showDisabled, + setShowDisabled, }) => { const theme = useMantineTheme(); @@ -208,6 +212,10 @@ const ChannelTableHeader = ({ ); }; + const toggleShowDisabled = () => { + setShowDisabled(!showDisabled); + }; + return ( @@ -226,6 +234,12 @@ const ChannelTableHeader = ({ + + + +