Fix dark mode parziale e fix remove film e episode

This commit is contained in:
Lovi 2024-12-13 17:18:32 +01:00
parent c093687e9f
commit 29f8edf7a4
11 changed files with 92 additions and 37 deletions

View File

@ -1,17 +1,18 @@
Per testare Per testare
1. Installare requirements 0. Installare nodejs "https://nodejs.org/en/download/package-manager"
2. Inserire url per mongodb e creare database 1. Installare requirements "pip install -r "requirements.txt"
3. Runnare server.py 2. Inserire url per mongodb "https://www.mongodb.com/it-it"
3. Eseguire server.py con "python server.py"
4. Spostarsi su client\dashboard 4. Spostarsi su client\dashboard
5. Eseguire npm install, npm run build, npm install -g serve 5. Eseguire npm install, npm run build, npm install -g serve
Cosa da fare Cosa da fare
- Dark mode su tutta la pagina - MIgliorare dark mode.
- Aggiungere documentazione - Aggiungere documentazione.
- Bottone download intera stagione - Migliorare controlli.
- Messaggio con richiesta se scaricare le nuove stagione quando si fa il check in watchlist - Aggiungere bottone per scaricare una stagione intera.
- Migliore player in case watch con bottone - Messaggio con richiesta se scaricare le nuove stagione quando si fa il check in watchlist.
- Coda di download con bottone aggiungere alla coda (complessa) - Migliore player in case watch con bottone.
- Coda di download con bottone aggiungere alla coda.
... ...

View File

@ -8,12 +8,21 @@
gap: 20px; gap: 20px;
} }
.search-results-container {
background-color: var(--background-color);
color: var(--text-color);
}
.search-result-item { .search-result-item {
cursor: pointer; background-color: #f0f0f0; /* Default (light mode) */
transition: transform 0.3s ease; color: var(--text-color);
border-radius: 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
overflow: hidden; }
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
@media (prefers-color-scheme: dark) {
.search-result-item {
background-color: #1e1e1e;
}
} }
.search-result-item:hover { .search-result-item:hover {

View File

@ -35,11 +35,11 @@ function App() {
<Router> <Router>
<Navbar toggleTheme={toggleTheme} theme={theme} /> <Navbar toggleTheme={toggleTheme} theme={theme} />
<Routes> <Routes>
<Route path="/" element={<Dashboard />} /> <Route path="/" element={<Dashboard theme={theme} />} />
<Route path="/search" element={<SearchResults />} /> <Route path="/search" element={<SearchResults theme={theme} />} />
<Route path="/title/:id" element={<TitleDetail />} /> <Route path="/title/:id" element={<TitleDetail theme={theme} />} />
<Route path="/watchlist" element={<Watchlist />} /> <Route path="/watchlist" element={<Watchlist theme={theme} />} />
<Route path="/downloads" element={<Downloads />} /> <Route path="/downloads" element={<Downloads theme={theme} />} />
</Routes> </Routes>
</Router> </Router>
); );

View File

@ -1,11 +1,12 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import axios from 'axios'; import axios from 'axios';
import { Container, Button, Form, InputGroup } from 'react-bootstrap'; import { Container, Button, Form, InputGroup } from 'react-bootstrap';
import SearchBar from './SearchBar.js'; import SearchBar from './SearchBar.js';
import { API_URL } from './ApiUrl.js'; import { API_URL } from './ApiUrl.js';
const Dashboard = () => { const Dashboard = ({ theme }) => {
const [items, setItems] = useState([]); const [items, setItems] = useState([]);
useEffect(() => { useEffect(() => {
@ -26,7 +27,10 @@ const Dashboard = () => {
}; };
return ( return (
<Container fluid className="p-4"> <Container fluid className="p-4" style={{
backgroundColor: theme === 'dark' ? '#121212' : '#ffffff',
color: theme === 'dark' ? '#ffffff' : '#000000'
}}>
<h1 className="mb-4">Dashboard</h1> <h1 className="mb-4">Dashboard</h1>
<div className="d-flex justify-content-between align-items-center mb-4"> <div className="d-flex justify-content-between align-items-center mb-4">
@ -37,4 +41,9 @@ const Dashboard = () => {
); );
}; };
Dashboard.propTypes = {
toggleTheme: PropTypes.func.isRequired,
theme: PropTypes.oneOf(['light', 'dark']).isRequired,
};
export default Dashboard; export default Dashboard;

View File

@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import axios from 'axios'; import axios from 'axios';
import { Container, Row, Col, Card, Button, Badge, Modal } from 'react-bootstrap'; import { Container, Row, Col, Card, Button, Badge, Modal } from 'react-bootstrap';
import { FaTrash, FaPlay } from 'react-icons/fa'; import { FaTrash, FaPlay } from 'react-icons/fa';
@ -6,7 +7,7 @@ import { Link } from 'react-router-dom';
import { SERVER_PATH_URL, SERVER_DELETE_URL, API_URL } from './ApiUrl'; import { SERVER_PATH_URL, SERVER_DELETE_URL, API_URL } from './ApiUrl';
const Downloads = () => { const Downloads = ({ theme }) => {
const [downloads, setDownloads] = useState([]); const [downloads, setDownloads] = useState([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [showPlayer, setShowPlayer] = useState(false); const [showPlayer, setShowPlayer] = useState(false);
@ -28,7 +29,7 @@ const Downloads = () => {
const handleDeleteEpisode = async (id, season, episode) => { const handleDeleteEpisode = async (id, season, episode) => {
try { try {
await axios.delete(`${SERVER_DELETE_URL}/episode`, { await axios.delete(`${SERVER_DELETE_URL}/episode`, {
params: { id, season, episode } params: { series_id: id, season_number: season, episode_number: episode }
}); });
fetchDownloads(); // Refresh the list fetchDownloads(); // Refresh the list
} catch (error) { } catch (error) {
@ -40,7 +41,7 @@ const Downloads = () => {
const handleDeleteMovie = async (id) => { const handleDeleteMovie = async (id) => {
try { try {
await axios.delete(`${SERVER_DELETE_URL}/movie`, { await axios.delete(`${SERVER_DELETE_URL}/movie`, {
params: { id } params: { movie_id: id }
}); });
fetchDownloads(); // Refresh the list fetchDownloads(); // Refresh the list
} catch (error) { } catch (error) {
@ -80,7 +81,10 @@ const Downloads = () => {
}, {}); }, {});
return ( return (
<Container fluid className="p-0"> <Container fluid className="p-0" style={{
backgroundColor: theme === 'dark' ? '#121212' : '#ffffff',
color: theme === 'dark' ? '#ffffff' : '#000000'
}}>
<Container className="mt-4"> <Container className="mt-4">
<h2 className="mb-4">My Downloads</h2> <h2 className="mb-4">My Downloads</h2>
@ -195,4 +199,9 @@ const Downloads = () => {
); );
}; };
Downloads.propTypes = {
toggleTheme: PropTypes.func.isRequired,
theme: PropTypes.oneOf(['light', 'dark']).isRequired,
};
export default Downloads; export default Downloads;

View File

@ -22,7 +22,7 @@ const SearchBar = ({ onSearch }) => {
}; };
return ( return (
<Form onSubmit={handleSearch} className="w-100"> <Form onSubmit={handleSearch} className="w-100" >
<InputGroup> <InputGroup>
<Form.Control <Form.Control
type="text" type="text"

View File

@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { useLocation, useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import axios from 'axios'; import axios from 'axios';
import { Container, Row, Col, Card, Spinner } from 'react-bootstrap'; import { Container, Row, Col, Card, Spinner } from 'react-bootstrap';
@ -6,7 +7,7 @@ import { Container, Row, Col, Card, Spinner } from 'react-bootstrap';
import SearchBar from './SearchBar.js'; import SearchBar from './SearchBar.js';
import { API_URL } from './ApiUrl.js'; import { API_URL } from './ApiUrl.js';
const SearchResults = () => { const SearchResults = ({ theme }) => {
const [results, setResults] = useState([]); const [results, setResults] = useState([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const location = useLocation(); const location = useLocation();
@ -44,7 +45,10 @@ const SearchResults = () => {
}; };
return ( return (
<Container fluid className="p-4"> <Container fluid className="p-4" style={{
backgroundColor: theme === 'dark' ? '#121212' : '#ffffff',
color: theme === 'dark' ? '#ffffff' : '#000000'
}}>
<div className="mb-4"> <div className="mb-4">
<SearchBar /> <SearchBar />
</div> </div>
@ -91,4 +95,10 @@ const SearchResults = () => {
); );
}; };
SearchResults.propTypes = {
toggleTheme: PropTypes.func.isRequired,
theme: PropTypes.oneOf(['light', 'dark']).isRequired,
};
export default SearchResults; export default SearchResults;

View File

@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import PropTypes from 'prop-types';
import axios from 'axios'; import axios from 'axios';
import { Container, Row, Col, Image, Button, Dropdown, Modal, Alert } from 'react-bootstrap'; import { Container, Row, Col, Image, Button, Dropdown, Modal, Alert } from 'react-bootstrap';
import { FaDownload, FaPlay, FaPlus, FaTrash } from 'react-icons/fa'; import { FaDownload, FaPlay, FaPlus, FaTrash } from 'react-icons/fa';
@ -8,7 +9,7 @@ import SearchBar from './SearchBar.js';
import { API_URL, SERVER_WATCHLIST_URL, SERVER_PATH_URL } from './ApiUrl.js'; import { API_URL, SERVER_WATCHLIST_URL, SERVER_PATH_URL } from './ApiUrl.js';
const TitleDetail = () => { const TitleDetail = ({ theme }) => {
const [titleDetails, setTitleDetails] = useState(null); const [titleDetails, setTitleDetails] = useState(null);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [selectedSeason, setSelectedSeason] = useState(1); const [selectedSeason, setSelectedSeason] = useState(1);
@ -233,7 +234,10 @@ const TitleDetail = () => {
} }
return ( return (
<Container fluid className="p-0"> <Container fluid className="p-0" style={{
backgroundColor: theme === 'dark' ? '#121212' : '#ffffff',
color: theme === 'dark' ? '#ffffff' : '#000000'
}}>
<SearchBar /> <SearchBar />
{/* Background Image */} {/* Background Image */}
@ -406,4 +410,9 @@ const TitleDetail = () => {
); );
}; };
TitleDetail.propTypes = {
toggleTheme: PropTypes.func.isRequired,
theme: PropTypes.oneOf(['light', 'dark']).isRequired,
};
export default TitleDetail; export default TitleDetail;

View File

@ -1,16 +1,17 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import axios from 'axios'; import axios from 'axios';
import PropTypes from 'prop-types';
import { Container, Row, Col, Card, Button, Badge, Alert } from 'react-bootstrap'; import { Container, Row, Col, Card, Button, Badge, Alert } from 'react-bootstrap';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { FaTrash } from 'react-icons/fa'; import { FaTrash } from 'react-icons/fa';
import { SERVER_WATCHLIST_URL } from './ApiUrl'; import { SERVER_WATCHLIST_URL } from './ApiUrl';
const Watchlist = () => { const Watchlist = ({ theme }) => {
const [watchlistItems, setWatchlistItems] = useState([]); const [watchlistItems, setWatchlistItems] = useState([]);
const [newSeasons, setNewSeasons] = useState([]); const [newSeasons, setNewSeasons] = useState([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [newSeasonsMessage, setNewSeasonsMessage] = useState(""); // Stato per il messaggio delle nuove stagioni const [newSeasonsMessage, setNewSeasonsMessage] = useState("");
// Funzione per recuperare i dati della watchlist // Funzione per recuperare i dati della watchlist
const fetchWatchlistData = async () => { const fetchWatchlistData = async () => {
@ -93,7 +94,10 @@ const Watchlist = () => {
} }
return ( return (
<Container fluid className="p-0"> <Container fluid className="p-0" style={{
backgroundColor: theme === 'dark' ? '#121212' : '#ffffff',
color: theme === 'dark' ? '#ffffff' : '#000000'
}}>
<Container className="mt-4"> <Container className="mt-4">
<h2 className="mb-4">My Watchlist</h2> <h2 className="mb-4">My Watchlist</h2>
@ -162,4 +166,9 @@ const Watchlist = () => {
); );
}; };
Watchlist.propTypes = {
toggleTheme: PropTypes.func.isRequired,
theme: PropTypes.oneOf(['light', 'dark']).isRequired,
};
export default Watchlist; export default Watchlist;

View File

@ -13,5 +13,4 @@ qbittorrent-api
python-qbittorrent python-qbittorrent
googlesearch-python googlesearch-python
pymongo pymongo
fastapi fastapi
pyclean

View File

@ -449,7 +449,7 @@ async def remove_episode(series_id: int = Query(...), season_number: int = Query
return {"success": True} return {"success": True}
@app.delete("/server/delete/movie") @app.delete("/server/delete/movie")
async def remove_movie(movie_id: int = Query(...)): async def remove_movie(movie_id: str = Query(...)):
movie = downloads_collection.find_one({'type': 'movie', 'id': movie_id}, {'_id': 0, 'path': 1}) movie = downloads_collection.find_one({'type': 'movie', 'id': movie_id}, {'_id': 0, 'path': 1})
if not movie: if not movie: