+
{
- {/* {copySuccess &&
{copySuccess}} */}
+ {/* Snackbar for feedback */}
{
);
};
-export default Example;
+export default ChannelsTable;
diff --git a/frontend/src/components/tables/StreamsTable.js b/frontend/src/components/tables/StreamsTable.js
index ba7766c1..a3591fcf 100644
--- a/frontend/src/components/tables/StreamsTable.js
+++ b/frontend/src/components/tables/StreamsTable.js
@@ -12,18 +12,21 @@ import {
Button,
} from '@mui/material';
import useStreamsStore from '../../store/streams';
+import useChannelsStore from '../../store/channels'; // NEW: Import channels store
import API from '../../api';
+// Make sure your api.js exports getAuthToken as a named export:
+// e.g. export const getAuthToken = async () => { ... }
+import { getAuthToken } from '../../api';
import {
Delete as DeleteIcon,
Edit as EditIcon,
Add as AddIcon,
} from '@mui/icons-material';
import { TableHelper } from '../../helpers';
-import utils from '../../utils';
import StreamForm from '../forms/Stream';
import usePlaylistsStore from '../../store/playlists';
-const Example = () => {
+const StreamsTable = () => {
const [rowSelection, setRowSelection] = useState([]);
const [stream, setStream] = useState(null);
const [modalOpen, setModalOpen] = useState(false);
@@ -31,16 +34,9 @@ const Example = () => {
const { playlists } = usePlaylistsStore();
const columns = useMemo(
- //column definitions...
() => [
- {
- header: 'Name',
- accessorKey: 'name',
- },
- {
- header: 'Group',
- accessorKey: 'group_name',
- },
+ { header: 'Name', accessorKey: 'name' },
+ { header: 'Group', accessorKey: 'group_name' },
{
header: 'M3U',
size: 100,
@@ -51,12 +47,11 @@ const Example = () => {
[playlists]
);
- //optionally access the underlying virtualizer instance
const rowVirtualizerInstanceRef = useRef(null);
-
const [isLoading, setIsLoading] = useState(true);
const [sorting, setSorting] = useState([]);
+ // Fallback: Individual creation (optional)
const createChannelFromStream = async (stream) => {
await API.createChannelFromStream({
channel_name: stream.name,
@@ -65,9 +60,9 @@ const Example = () => {
});
};
- // @TODO: bulk create is broken, returning a 404
+ // Bulk creation: create channels from selected streams in one API call
const createChannelsFromStreams = async () => {
- setIsLoading(true);
+ // Get all selected streams from the table
const selected = table
.getRowModel()
.rows.filter((row) => row.getIsSelected());
@@ -109,7 +104,6 @@ const Example = () => {
}, []);
useEffect(() => {
- //scroll to the top of the table when the sorting changes
try {
rowVirtualizerInstanceRef.current?.scrollToIndex?.(0);
} catch (error) {
@@ -119,7 +113,6 @@ const Example = () => {
const table = useMaterialReactTable({
...TableHelper.defaultProperties,
-
columns,
data: streams,
enablePagination: false,
@@ -132,14 +125,14 @@ const Example = () => {
sorting,
rowSelection,
},
- rowVirtualizerInstanceRef, //optional
- rowVirtualizerOptions: { overscan: 5 }, //optionally customize the row virtualizer
+ rowVirtualizerInstanceRef,
+ rowVirtualizerOptions: { overscan: 5 },
enableRowActions: true,
renderRowActions: ({ row }) => (
<>
editStream(row.original)}
disabled={row.original.m3u_account}
sx={{ p: 0 }}
@@ -147,16 +140,16 @@ const Example = () => {
deleteStream(row.original.id)}
sx={{ p: 0 }}
>
createChannelFromStream(row.original)}
sx={{ p: 0 }}
>
@@ -166,46 +159,38 @@ const Example = () => {
),
muiTableContainerProps: {
sx: {
- height: 'calc(100vh - 75px)', // Subtract padding to avoid cutoff
- overflowY: 'auto', // Internal scrolling for the table
+ height: 'calc(100vh - 75px)',
+ overflowY: 'auto',
},
},
renderTopToolbarCustomActions: ({ table }) => (
-
+
Streams
editStream()}
>
- {/* Small icon size */}
+
- {/* Small icon size */}
+
@@ -214,16 +199,7 @@ const Example = () => {
});
return (
-
+
{
);
};
-export default Example;
+export default StreamsTable;
diff --git a/frontend/src/pages/Guide.js b/frontend/src/pages/Guide.js
index c7de50b8..fca295c4 100644
--- a/frontend/src/pages/Guide.js
+++ b/frontend/src/pages/Guide.js
@@ -164,7 +164,7 @@ export default function TVChannelGuide({ startDate, endDate }) {
return;
}
// Build a playable stream URL for that channel
- const url = window.location.origin + '/output/stream/' + matched.id;
+ const url = window.location.origin + '/output/stream/' + matched.channel_number;
showVideo(url);
// Optionally close the modal