diff --git a/apps/channels/api_views.py b/apps/channels/api_views.py index bc920537..eccc5028 100644 --- a/apps/channels/api_views.py +++ b/apps/channels/api_views.py @@ -124,7 +124,7 @@ class StreamViewSet(viewsets.ModelViewSet): filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] filterset_class = StreamFilter search_fields = ["name", "channel_group__name"] - ordering_fields = ["name", "channel_group__name"] + ordering_fields = ["name", "channel_group__name", "m3u_account__name"] ordering = ["-name"] def get_permissions(self): diff --git a/frontend/src/components/tables/CustomTable/CustomTableHeader.jsx b/frontend/src/components/tables/CustomTable/CustomTableHeader.jsx index 92643fc9..004687dd 100644 --- a/frontend/src/components/tables/CustomTable/CustomTableHeader.jsx +++ b/frontend/src/components/tables/CustomTable/CustomTableHeader.jsx @@ -105,6 +105,7 @@ const CustomTableHeader = ({ ...(header.column.columnDef.style && header.column.columnDef.style), height: '100%', + width: '100%', paddingRight: header.column.getCanResize() ? '8px' : '0px', // Add padding for resize handle }} > diff --git a/frontend/src/components/tables/StreamsTable.jsx b/frontend/src/components/tables/StreamsTable.jsx index 51b1b39d..f3f4dc20 100644 --- a/frontend/src/components/tables/StreamsTable.jsx +++ b/frontend/src/components/tables/StreamsTable.jsx @@ -183,7 +183,7 @@ const StreamsTable = () => { const [pageCount, setPageCount] = useState(0); const [paginationString, setPaginationString] = useState(''); const [isLoading, setIsLoading] = useState(true); - const [sorting, setSorting] = useState([{ id: 'name', desc: '' }]); + const [sorting, setSorting] = useState([{ id: 'name', desc: false }]); const [selectedStreamIds, setSelectedStreamIds] = useState([]); // Channel numbering modal state @@ -299,6 +299,7 @@ const StreamsTable = () => { ), }, { + header: 'Group', id: 'group', accessorFn: (row) => channelGroups[row.channel_group] @@ -320,6 +321,7 @@ const StreamsTable = () => { ), }, { + header: 'M3U', id: 'm3u', size: columnSizing.m3u || 150, accessorFn: (row) => @@ -386,7 +388,14 @@ const StreamsTable = () => { // Apply sorting if (sorting.length > 0) { - const sortField = sorting[0].id; + const columnId = sorting[0].id; + // Map frontend column IDs to backend field names + const fieldMapping = { + name: 'name', + group: 'channel_group__name', + m3u: 'm3u_account__name', + }; + const sortField = fieldMapping[columnId] || columnId; const sortDirection = sorting[0].desc ? '-' : ''; params.append('ordering', `${sortDirection}${sortField}`); } @@ -692,8 +701,8 @@ const StreamsTable = () => { const sortField = sorting[0]?.id; const sortDirection = sorting[0]?.desc; - if (sortField == column) { - if (sortDirection == false) { + if (sortField === column) { + if (sortDirection === false) { setSorting([ { id: column, @@ -701,7 +710,8 @@ const StreamsTable = () => { }, ]); } else { - setSorting([]); + // Reset to default sort (name ascending) instead of clearing + setSorting([{ id: 'name', desc: false }]); } } else { setSorting([ @@ -726,7 +736,7 @@ const StreamsTable = () => { switch (header.id) { case 'name': return ( - + { variant="unstyled" className="table-input-header" leftSection={} - /> -
- {React.createElement(sortingIcon, { - onClick: () => onSortingChange('name'), + style={{ flex: 1, minWidth: 0 }} + rightSectionPointerEvents="auto" + rightSection={React.createElement(sortingIcon, { + onClick: (e) => { + e.stopPropagation(); + onSortingChange('name'); + }, size: 14, + style: { cursor: 'pointer' }, })} -
+ />
); case 'group': return ( - + { variant="unstyled" className="table-input-header custom-multiselect" clearable + style={{ flex: 1, minWidth: 0 }} + rightSectionPointerEvents="auto" + rightSection={React.createElement(sortingIcon, { + onClick: (e) => { + e.stopPropagation(); + onSortingChange('group'); + }, + size: 14, + style: { cursor: 'pointer' }, + })} /> - +
); case 'm3u': return ( - +