latest frontend changes

This commit is contained in:
kappa118 2025-03-01 20:00:17 -05:00
parent f32adc7abc
commit 105df86af9
6 changed files with 94 additions and 16 deletions

View file

@ -28,6 +28,7 @@ import Settings from './pages/Settings';
import StreamProfiles from './pages/StreamProfiles';
import useAuthStore from './store/auth';
import logo from './images/logo.png';
import Alert from './components/Alert';
// NEW: import the floating PiP component
import FloatingVideo from './components/FloatingVideo';
@ -110,8 +111,8 @@ const App = () => {
flexDirection: 'column',
ml: `${open ? drawerWidth : miniDrawerWidth}px`,
transition: 'width 0.3s, margin-left 0.3s',
// height: '100vh',
backgroundColor: '#495057',
height: '100%',
}}
>
<Box
@ -149,6 +150,9 @@ const App = () => {
</Box>
</Router>
{/* Global Snackbar for system-wide messages */}
<Alert />
{/* Always-available floating video; remains visible across page changes */}
<FloatingVideo />
</ThemeProvider>

View file

@ -0,0 +1,26 @@
import React, { useState } from 'react';
import { Snackbar, Alert, Button } from '@mui/material';
import useAlertStore from '../store/alerts';
const AlertPopup = () => {
const { open, message, severity, hideAlert } = useAlertStore();
const handleClose = () => {
hideAlert();
};
return (
<Snackbar
open={open}
autoHideDuration={3000}
onClose={handleClose}
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
>
<Alert onClose={handleClose} severity={severity} sx={{ width: '100%' }}>
{message}
</Alert>
</Snackbar>
);
};
export default AlertPopup;

View file

@ -1,5 +1,5 @@
// Modal.js
import React, { useEffect } from "react";
import React, { useEffect } from 'react';
import {
TextField,
Button,
@ -9,22 +9,23 @@ import {
DialogTitle,
DialogContent,
DialogActions,
} from "@mui/material";
import { useFormik } from "formik";
import * as Yup from "yup";
import API from "../../api";
} from '@mui/material';
import { useFormik } from 'formik';
import * as Yup from 'yup';
import API from '../../api';
import useSettingsStore from '../../store/settings';
const UserAgent = ({ userAgent = null, isOpen, onClose }) => {
const formik = useFormik({
initialValues: {
user_agent_name: "",
user_agent: "",
description: "",
user_agent_name: '',
user_agent: '',
description: '',
is_active: true,
},
validationSchema: Yup.object({
user_agent_name: Yup.string().required("Name is required"),
user_agent: Yup.string().required("User-Agent is required"),
user_agent_name: Yup.string().required('Name is required'),
user_agent: Yup.string().required('User-Agent is required'),
}),
onSubmit: async (values, { setSubmitting, resetForm }) => {
if (userAgent?.id) {
@ -60,8 +61,8 @@ const UserAgent = ({ userAgent = null, isOpen, onClose }) => {
<Dialog open={isOpen} onClose={onClose}>
<DialogTitle
sx={{
backgroundColor: "primary.main",
color: "primary.contrastText",
backgroundColor: 'primary.main',
color: 'primary.contrastText',
}}
>
User-Agent
@ -132,7 +133,7 @@ const UserAgent = ({ userAgent = null, isOpen, onClose }) => {
color="primary"
disabled={formik.isSubmitting}
>
{formik.isSubmitting ? <CircularProgress size={24} /> : "Submit"}
{formik.isSubmitting ? <CircularProgress size={24} /> : 'Submit'}
</Button>
</DialogActions>
</form>

View file

@ -30,6 +30,8 @@ import useEPGsStore from '../../store/epgs';
import StreamProfileForm from '../forms/StreamProfile';
import useStreamProfilesStore from '../../store/streamProfiles';
import { TableHelper } from '../../helpers';
import useSettingsStore from '../../store/settings';
import useAlertStore from '../../store/alerts';
const StreamProfiles = () => {
const [profile, setProfile] = useState(null);
@ -40,6 +42,8 @@ const StreamProfiles = () => {
const [activeFilterValue, setActiveFilterValue] = useState('all');
const streamProfiles = useStreamProfilesStore((state) => state.profiles);
const { settings } = useSettingsStore();
const { showAlert } = useAlertStore();
const columns = useMemo(
//column definitions...
@ -112,8 +116,13 @@ const StreamProfiles = () => {
setProfileModalOpen(true);
};
const deleteStreamProfile = async (ids) => {
await API.deleteStreamProfile(ids);
const deleteStreamProfile = async (id) => {
if (id == settings['default-stream-profile'].value) {
showAlert('Cannot delete default stream-profile', 'error');
return;
}
await API.deleteStreamProfile(id);
};
const closeStreamProfileForm = () => {

View file

@ -26,6 +26,8 @@ import {
import useUserAgentsStore from '../../store/userAgents';
import UserAgentForm from '../forms/UserAgent';
import { TableHelper } from '../../helpers';
import useSettingsStore from '../../store/settings';
import useAlertStore from '../../store/alerts';
const UserAgentsTable = () => {
const [userAgent, setUserAgent] = useState(null);
@ -34,6 +36,8 @@ const UserAgentsTable = () => {
const [activeFilterValue, setActiveFilterValue] = useState('all');
const userAgents = useUserAgentsStore((state) => state.userAgents);
const { settings } = useSettingsStore();
const { showAlert } = useAlertStore();
const columns = useMemo(
//column definitions...
@ -108,8 +112,18 @@ const UserAgentsTable = () => {
const deleteUserAgent = async (ids) => {
if (Array.isArray(ids)) {
if (ids.includes(settings['default-user-agent'].value)) {
showAlert('Cannot delete default user-agent', 'error');
return;
}
await API.deleteUserAgents(ids);
} else {
if (ids == settings['default-user-agent'].value) {
showAlert('Cannot delete default user-agent', 'error');
return;
}
await API.deleteUserAgent(ids);
}
};

View file

@ -0,0 +1,24 @@
// frontend/src/store/useAlertStore.js
import { create } from 'zustand';
/**
* Global store to track whether a floating video is visible and which URL is playing.
*/
const useAlertStore = create((set) => ({
open: false,
message: '',
severity: 'info',
showAlert: (message, severity = 'info') =>
set({
open: true,
message,
severity,
}),
hideAlert: () => {
set({ open: false });
},
}));
export default useAlertStore;