forked from Mirrors/Dispatcharr
Merge pull request #707 from bobey6/main
Enhancement: Add sort by 'Group' or 'M3U' buttons to Streams
This commit is contained in:
commit
6a96b6b485
3 changed files with 51 additions and 16 deletions
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<Flex gap="sm">
|
||||
<Flex align="center" style={{ width: '100%', flex: 1 }}>
|
||||
<TextInput
|
||||
name="name"
|
||||
placeholder="Name"
|
||||
|
|
@ -737,19 +747,23 @@ const StreamsTable = () => {
|
|||
variant="unstyled"
|
||||
className="table-input-header"
|
||||
leftSection={<Search size={14} opacity={0.5} />}
|
||||
/>
|
||||
<Center>
|
||||
{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' },
|
||||
})}
|
||||
</Center>
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
case 'group':
|
||||
return (
|
||||
<Box onClick={handleSelectClick} style={{ width: '100%' }}>
|
||||
<Flex align="center" style={{ width: '100%', flex: 1 }}>
|
||||
<MultiSelect
|
||||
placeholder="Group"
|
||||
searchable
|
||||
|
|
@ -761,13 +775,23 @@ const StreamsTable = () => {
|
|||
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' },
|
||||
})}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
case 'm3u':
|
||||
return (
|
||||
<Box onClick={handleSelectClick}>
|
||||
<Flex align="center" style={{ width: '100%', flex: 1 }}>
|
||||
<Select
|
||||
placeholder="M3U"
|
||||
searchable
|
||||
|
|
@ -782,8 +806,18 @@ const StreamsTable = () => {
|
|||
}))}
|
||||
variant="unstyled"
|
||||
className="table-input-header"
|
||||
style={{ flex: 1, minWidth: 0 }}
|
||||
rightSectionPointerEvents="auto"
|
||||
rightSection={React.createElement(sortingIcon, {
|
||||
onClick: (e) => {
|
||||
e.stopPropagation();
|
||||
onSortingChange('m3u');
|
||||
},
|
||||
size: 14,
|
||||
style: { cursor: 'pointer' },
|
||||
})}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue