new folder structure for php scripts
renamed api nodes php braces on same line
This commit is contained in:
		
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							@@ -8,14 +8,18 @@ Feel free to contribute or open an issue here: https://gitlab.heili.eu/lukas/ope
 | 
				
			|||||||
## What is this?
 | 
					## What is this?
 | 
				
			||||||
Open Media Center is an open source solution for a mediacenter in your home network.
 | 
					Open Media Center is an open source solution for a mediacenter in your home network.
 | 
				
			||||||
Transform your webserver into a mediaserver.
 | 
					Transform your webserver into a mediaserver.
 | 
				
			||||||
It's based on Reactjs and PHP is used as backend.
 | 
					It's based on Reactjs and PHP is used for backend.
 | 
				
			||||||
It is optimized for general videos as well as for movies. 
 | 
					It is optimized for general videos as well as for movies. 
 | 
				
			||||||
For grabbing movie data TMDB is used. 
 | 
					For grabbing movie data TMDB is used. 
 | 
				
			||||||
For organizing videos tags are used.
 | 
					With the help of tags you can organize your video gravity.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Here you can see an example main page:
 | 
					Here you can see an example main page in light mode:
 | 
				
			||||||
 | 
					
 | 
				
			||||||

 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and in dark mode:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Installation
 | 
					## Installation
 | 
				
			||||||
First of all clone the repository.
 | 
					First of all clone the repository.
 | 
				
			||||||
@@ -32,9 +36,9 @@ You need also to setup a Database with the structure described in [SQL Style Ref
 | 
				
			|||||||
The login data to this database needs to be specified in the `api/Database.php` file.
 | 
					The login data to this database needs to be specified in the `api/Database.php` file.
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
## Usage
 | 
					## Usage
 | 
				
			||||||
To index Videos run on your server: `php extractvideopreviews.php`.
 | 
					Now you can access your MediaCenter via your servers global ip (:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Now you can access your MediaCenter via the servers global ip (:
 | 
					At the settings tab you can set the correct videopath on server and click reindex afterwards. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Contact
 | 
					## Contact
 | 
				
			||||||
Any contribution is appreciated. 
 | 
					Any contribution is appreciated. 
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								api/Tags.php
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								api/Tags.php
									
									
									
									
									
								
							@@ -1,30 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
require_once 'RequestBase.php';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Tags extends RequestBase {
 | 
					 | 
				
			||||||
    function initHandlers() {
 | 
					 | 
				
			||||||
        $this->addActionHandler("getAllTags", function () {
 | 
					 | 
				
			||||||
            $query = "SELECT tag_name,tag_id from tags";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $result = $this->conn->query($query);
 | 
					 | 
				
			||||||
            $rows = array();
 | 
					 | 
				
			||||||
            while ($r = mysqli_fetch_assoc($result)) {
 | 
					 | 
				
			||||||
                array_push($rows, $r);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            echo json_encode($rows);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->addActionHandler("createTag", function (){
 | 
					 | 
				
			||||||
            $query = "INSERT INTO tags (tag_name) VALUES ('" . $_POST['tagname'] . "')";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ($this->conn->query($query) === TRUE) {
 | 
					 | 
				
			||||||
                echo('{"result":"success"}');
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                echo('{"result":"' . $this->conn->error . '"}');
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$tags = new Tags();
 | 
					 | 
				
			||||||
$tags->handleAction();
 | 
					 | 
				
			||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
require 'Database.php';
 | 
					require_once './src/Database.php';
 | 
				
			||||||
require 'TMDBMovie.php';
 | 
					require_once './src/TMDBMovie.php';
 | 
				
			||||||
require 'SSettings.php';
 | 
					require_once './src/SSettings.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// allow UTF8 characters
 | 
					// allow UTF8 characters
 | 
				
			||||||
setlocale(LC_ALL, 'en_US.UTF-8');
 | 
					setlocale(LC_ALL, 'en_US.UTF-8');
 | 
				
			||||||
@@ -226,8 +226,7 @@ writeLog("-42"); // terminating characters to stop webui requesting infos
 | 
				
			|||||||
 * @param $video string name including extension
 | 
					 * @param $video string name including extension
 | 
				
			||||||
 * @return object all infos as object
 | 
					 * @return object all infos as object
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function _get_video_attributes($video)
 | 
					function _get_video_attributes($video) {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    $command = "mediainfo \"../videos/prn/$video\" --Output=JSON";
 | 
					    $command = "mediainfo \"../videos/prn/$video\" --Output=JSON";
 | 
				
			||||||
    $output = shell_exec($command);
 | 
					    $output = shell_exec($command);
 | 
				
			||||||
    return json_decode($output);
 | 
					    return json_decode($output);
 | 
				
			||||||
@@ -238,8 +237,7 @@ function _get_video_attributes($video)
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param string $message message to write
 | 
					 * @param string $message message to write
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function writeLog(string $message)
 | 
					function writeLog(string $message) {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    file_put_contents("/tmp/output.log", $message, FILE_APPEND);
 | 
					    file_put_contents("/tmp/output.log", $message, FILE_APPEND);
 | 
				
			||||||
    flush();
 | 
					    flush();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -249,8 +247,7 @@ function writeLog(string $message)
 | 
				
			|||||||
 * @param string $tagname the name of the tag
 | 
					 * @param string $tagname the name of the tag
 | 
				
			||||||
 * @return integer the id of the inserted tag
 | 
					 * @return integer the id of the inserted tag
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function tagExists(string $tagname)
 | 
					function tagExists(string $tagname) {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    global $conn;
 | 
					    global $conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $query = "SELECT * FROM tags WHERE tag_name='$tagname'";
 | 
					    $query = "SELECT * FROM tags WHERE tag_name='$tagname'";
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								api/settings.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								api/settings.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					require_once './src/handlers/Settings.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$sett = new Settings();
 | 
				
			||||||
 | 
					$sett->handleAction();
 | 
				
			||||||
@@ -5,8 +5,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * Class with all neccessary stuff for the Database connections.
 | 
					 * Class with all neccessary stuff for the Database connections.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class Database
 | 
					class Database {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    private static ?Database $instance = null;
 | 
					    private static ?Database $instance = null;
 | 
				
			||||||
    private mysqli $conn;
 | 
					    private mysqli $conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,8 +15,7 @@ class Database
 | 
				
			|||||||
    private string $dbname = "mediacenter";
 | 
					    private string $dbname = "mediacenter";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The db connection is established in the private constructor.
 | 
					    // The db connection is established in the private constructor.
 | 
				
			||||||
    private function __construct()
 | 
					    private function __construct() {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // Create connection
 | 
					        // Create connection
 | 
				
			||||||
        $this->conn = new mysqli($this->servername, $this->username, $this->password, $this->dbname);
 | 
					        $this->conn = new mysqli($this->servername, $this->username, $this->password, $this->dbname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,8 +30,7 @@ class Database
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Database dbobject
 | 
					     * @return Database dbobject
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static function getInstance()
 | 
					    public static function getInstance() {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (!self::$instance) {
 | 
					        if (!self::$instance) {
 | 
				
			||||||
            self::$instance = new Database();
 | 
					            self::$instance = new Database();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -46,8 +43,7 @@ class Database
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return mysqli mysqli instance
 | 
					     * @return mysqli mysqli instance
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getConnection()
 | 
					    public function getConnection() {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this->conn;
 | 
					        return $this->conn;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -55,7 +51,7 @@ class Database
 | 
				
			|||||||
     * get name of current active database
 | 
					     * get name of current active database
 | 
				
			||||||
     * @return string name
 | 
					     * @return string name
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getDatabaseName(){
 | 
					    public function getDatabaseName() {
 | 
				
			||||||
        return $this->dbname;
 | 
					        return $this->dbname;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,7 +1,10 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SSettings
 | 
					/**
 | 
				
			||||||
{
 | 
					 * Class SSettings
 | 
				
			||||||
 | 
					 * class handling all Settings used by php scripts
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class SSettings {
 | 
				
			||||||
    private ?Database $database;
 | 
					    private ?Database $database;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -11,6 +14,10 @@ class SSettings
 | 
				
			|||||||
        $this->database = Database::getInstance();
 | 
					        $this->database = Database::getInstance();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * get the videopath saved in db
 | 
				
			||||||
 | 
					     * @return string videopath
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public function getVideoPath() {
 | 
					    public function getVideoPath() {
 | 
				
			||||||
        $query = "SELECT video_path from settings";
 | 
					        $query = "SELECT video_path from settings";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -24,14 +31,13 @@ class SSettings
 | 
				
			|||||||
     * check if TMDB is enableds
 | 
					     * check if TMDB is enableds
 | 
				
			||||||
     * @return bool isenabled?
 | 
					     * @return bool isenabled?
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function isTMDBGrabbingEnabled(): bool
 | 
					    public function isTMDBGrabbingEnabled(): bool {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $query = "SELECT TMDB_grabbing from settings";
 | 
					        $query = "SELECT TMDB_grabbing from settings";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $result = $this->database->getConnection()->query($query);
 | 
					        $result = $this->database->getConnection()->query($query);
 | 
				
			||||||
        if(!$result){
 | 
					        if (!$result) {
 | 
				
			||||||
            return true; // if undefined in db --> default true
 | 
					            return true; // if undefined in db --> default true
 | 
				
			||||||
        }else{
 | 
					        } else {
 | 
				
			||||||
            $r = mysqli_fetch_assoc($result);
 | 
					            $r = mysqli_fetch_assoc($result);
 | 
				
			||||||
            return $r['TMDB_grabbing'] == '1';
 | 
					            return $r['TMDB_grabbing'] == '1';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -1,10 +1,13 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TMDBMovie
 | 
					/**
 | 
				
			||||||
{
 | 
					 * Class TMDBMovie
 | 
				
			||||||
 | 
					 * class to handle all interactions with the tmdb api
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class TMDBMovie {
 | 
				
			||||||
 | 
					    public $picturebase = "https://image.tmdb.org/t/p/w500";
 | 
				
			||||||
    private $apikey = "9fd90530b11447f5646f8e6fb4733fb4";
 | 
					    private $apikey = "9fd90530b11447f5646f8e6fb4733fb4";
 | 
				
			||||||
    private $baseurl = "https://api.themoviedb.org/3/";
 | 
					    private $baseurl = "https://api.themoviedb.org/3/";
 | 
				
			||||||
    public $picturebase = "https://image.tmdb.org/t/p/w500";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * search for a specific movie
 | 
					     * search for a specific movie
 | 
				
			||||||
@@ -12,8 +15,7 @@ class TMDBMovie
 | 
				
			|||||||
     * @param string $moviename moviename
 | 
					     * @param string $moviename moviename
 | 
				
			||||||
     * @return object movie object or null if not found
 | 
					     * @return object movie object or null if not found
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function searchMovie(string $moviename)
 | 
					    public function searchMovie(string $moviename) {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $reply = json_decode(file_get_contents($this->baseurl . "search/movie?api_key=" . $this->apikey . "&query=" . urlencode($moviename)));
 | 
					        $reply = json_decode(file_get_contents($this->baseurl . "search/movie?api_key=" . $this->apikey . "&query=" . urlencode($moviename)));
 | 
				
			||||||
        if ($reply->total_results == 0) {
 | 
					        if ($reply->total_results == 0) {
 | 
				
			||||||
            // no results found
 | 
					            // no results found
 | 
				
			||||||
@@ -29,8 +31,7 @@ class TMDBMovie
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return array of all available genres
 | 
					     * @return array of all available genres
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function getAllGenres()
 | 
					    public function getAllGenres() {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $reply = json_decode(file_get_contents($this->baseurl . "genre/movie/list?api_key=" . $this->apikey));
 | 
					        $reply = json_decode(file_get_contents($this->baseurl . "genre/movie/list?api_key=" . $this->apikey));
 | 
				
			||||||
        return $reply->genres;
 | 
					        return $reply->genres;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -1,14 +1,9 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
require_once 'Database.php';
 | 
					require_once 'src/Database.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
abstract class RequestBase {
 | 
					abstract class RequestBase {
 | 
				
			||||||
    private array $actions = array();
 | 
					 | 
				
			||||||
    protected mysqli $conn;
 | 
					    protected mysqli $conn;
 | 
				
			||||||
 | 
					    private array $actions = array();
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * add the action handlers in this abstract method
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    abstract function initHandlers();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * adds a new action handler to the current api file
 | 
					     * adds a new action handler to the current api file
 | 
				
			||||||
@@ -38,4 +33,18 @@ abstract class RequestBase {
 | 
				
			|||||||
            echo('{data:"error"}');
 | 
					            echo('{data:"error"}');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Send response message and exit script
 | 
				
			||||||
 | 
					     * @param $message string the response message
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    function commitMessage($message){
 | 
				
			||||||
 | 
					        echo $message;
 | 
				
			||||||
 | 
					        exit(0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * add the action handlers in this abstract method
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    abstract function initHandlers();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,8 +1,23 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
require 'RequestBase.php';
 | 
					require_once 'RequestBase.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class Settings
 | 
				
			||||||
 | 
					 * Backend for the Settings page
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class Settings extends RequestBase {
 | 
					class Settings extends RequestBase {
 | 
				
			||||||
    function initHandlers() {
 | 
					    function initHandlers() {
 | 
				
			||||||
 | 
					        $this->getFromDB();
 | 
				
			||||||
 | 
					        $this->saveToDB();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * handle settings stuff to load from db
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private function getFromDB(){
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * load currently set settings form db for init of settings page
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
        $this->addActionHandler("loadGeneralSettings", function () {
 | 
					        $this->addActionHandler("loadGeneralSettings", function () {
 | 
				
			||||||
            $query = "SELECT * from settings";
 | 
					            $query = "SELECT * from settings";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,6 +31,30 @@ class Settings extends RequestBase {
 | 
				
			|||||||
            echo json_encode($r);
 | 
					            echo json_encode($r);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * load initial data for home page load to check if pwd is set
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        $this->addActionHandler("loadInitialData", function () {
 | 
				
			||||||
 | 
					            $query = "SELECT * from settings";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $result = $this->conn->query($query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $r = mysqli_fetch_assoc($result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $r['passwordEnabled'] = $r['password'] != "-1";
 | 
				
			||||||
 | 
					            unset($r['password']);
 | 
				
			||||||
 | 
					            $r['DarkMode'] = (bool)($r['DarkMode'] != '0');
 | 
				
			||||||
 | 
					            $this->commitMessage(json_encode($r));
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * handle setting stuff to save to db
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private function saveToDB(){
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * save changed settings to db
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
        $this->addActionHandler("saveGeneralSettings", function () {
 | 
					        $this->addActionHandler("saveGeneralSettings", function () {
 | 
				
			||||||
            $mediacentername = $_POST['mediacentername'];
 | 
					            $mediacentername = $_POST['mediacentername'];
 | 
				
			||||||
            $password = $_POST['password'];
 | 
					            $password = $_POST['password'];
 | 
				
			||||||
@@ -34,26 +73,10 @@ class Settings extends RequestBase {
 | 
				
			|||||||
                    WHERE 1";
 | 
					                    WHERE 1";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($this->conn->query($query) === true) {
 | 
					            if ($this->conn->query($query) === true) {
 | 
				
			||||||
                echo '{"success": true}';
 | 
					                $this->commitMessage('{"success": true}');
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                echo '{"success": true}';
 | 
					                $this->commitMessage('{"success": true}');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->addActionHandler("loadInitialData", function () {
 | 
					 | 
				
			||||||
            $query = "SELECT * from settings";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $result = $this->conn->query($query);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $r = mysqli_fetch_assoc($result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $r['passwordEnabled'] = $r['password'] != "-1";
 | 
					 | 
				
			||||||
            unset($r['password']);
 | 
					 | 
				
			||||||
            $r['DarkMode'] = (bool)($r['DarkMode'] != '0');
 | 
					 | 
				
			||||||
            echo json_encode($r);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
$sett = new Settings();
 | 
					 | 
				
			||||||
$sett->handleAction();
 | 
					 | 
				
			||||||
							
								
								
									
										66
									
								
								api/src/handlers/Tags.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								api/src/handlers/Tags.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					require_once 'RequestBase.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class Tags
 | 
				
			||||||
 | 
					 * backend to handle Tag database interactions
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class Tags extends RequestBase {
 | 
				
			||||||
 | 
					    function initHandlers() {
 | 
				
			||||||
 | 
					        $this->addToDB();
 | 
				
			||||||
 | 
					        $this->getFromDB();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function getFromDB(){
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * returns all available tags from database
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        $this->addActionHandler("getAllTags", function () {
 | 
				
			||||||
 | 
					            $query = "SELECT tag_name,tag_id from tags";
 | 
				
			||||||
 | 
					            $result = $this->conn->query($query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $rows = array();
 | 
				
			||||||
 | 
					            while ($r = mysqli_fetch_assoc($result)) {
 | 
				
			||||||
 | 
					                array_push($rows, $r);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $this->commitMessage(json_encode($rows));
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function addToDB(){
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * creates a new tag
 | 
				
			||||||
 | 
					         * query requirements:
 | 
				
			||||||
 | 
					         * * tagname -- name of the new tag
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        $this->addActionHandler("createTag", function () {
 | 
				
			||||||
 | 
					            $query = "INSERT INTO tags (tag_name) VALUES ('" . $_POST['tagname'] . "')";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($this->conn->query($query) === TRUE) {
 | 
				
			||||||
 | 
					                $this->commitMessage('{"result":"success"}');
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $this->commitMessage('{"result":"' . $this->conn->error . '"}');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * adds a new tag to an existing video
 | 
				
			||||||
 | 
					         *
 | 
				
			||||||
 | 
					         * query requirements:
 | 
				
			||||||
 | 
					         * * movieid  -- the id of the video to add the tag to
 | 
				
			||||||
 | 
					         * * id -- the tag id which tag to add
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        $this->addActionHandler("addTag", function () {
 | 
				
			||||||
 | 
					            $movieid = $_POST['movieid'];
 | 
				
			||||||
 | 
					            $tagid = $_POST['id'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $query = "INSERT INTO video_tags(tag_id, video_id) VALUES ('$tagid','$movieid')";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ($this->conn->query($query) === TRUE) {
 | 
				
			||||||
 | 
					                $this->commitMessage('{"result":"success"}');
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $this->commitMessage('{"result":"' . $this->conn->error . '"}');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,8 +1,11 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
require_once 'Database.php';
 | 
					require_once 'src/SSettings.php';
 | 
				
			||||||
require_once 'SSettings.php';
 | 
					 | 
				
			||||||
require_once 'RequestBase.php';
 | 
					require_once 'RequestBase.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Class Video
 | 
				
			||||||
 | 
					 * backend for all interactions with videoloads and receiving of video infos
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class Video extends RequestBase {
 | 
					class Video extends RequestBase {
 | 
				
			||||||
    private string $videopath;
 | 
					    private string $videopath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -13,6 +16,15 @@ class Video extends RequestBase {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function initHandlers() {
 | 
					    function initHandlers() {
 | 
				
			||||||
 | 
					        $this->getVideos();
 | 
				
			||||||
 | 
					        $this->loadVideos();
 | 
				
			||||||
 | 
					        $this->addToVideo();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * function handles load of all videos and search for videos
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private function getVideos() {
 | 
				
			||||||
        $this->addActionHandler("getMovies", function () {
 | 
					        $this->addActionHandler("getMovies", function () {
 | 
				
			||||||
            $query = "SELECT movie_id,movie_name FROM videos ORDER BY create_date DESC, movie_name";
 | 
					            $query = "SELECT movie_id,movie_name FROM videos ORDER BY create_date DESC, movie_name";
 | 
				
			||||||
            if (isset($_POST['tag'])) {
 | 
					            if (isset($_POST['tag'])) {
 | 
				
			||||||
@@ -31,7 +43,7 @@ class Video extends RequestBase {
 | 
				
			|||||||
                array_push($rows, $r);
 | 
					                array_push($rows, $r);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            echo(json_encode($rows));
 | 
					            $this->commitMessage(json_encode($rows));
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->addActionHandler("getRandomMovies", function () {
 | 
					        $this->addActionHandler("getRandomMovies", function () {
 | 
				
			||||||
@@ -59,7 +71,7 @@ class Video extends RequestBase {
 | 
				
			|||||||
                array_push($return->tags, $r);
 | 
					                array_push($return->tags, $r);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            echo(json_encode($return));
 | 
					            $this->commitMessage(json_encode($return));
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->addActionHandler("getSearchKeyWord", function () {
 | 
					        $this->addActionHandler("getSearchKeyWord", function () {
 | 
				
			||||||
@@ -74,9 +86,14 @@ class Video extends RequestBase {
 | 
				
			|||||||
                array_push($rows, $r);
 | 
					                array_push($rows, $r);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            echo(json_encode($rows));
 | 
					            $this->commitMessage(json_encode($rows));
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * function to handle stuff for loading specific videos and startdata
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private function loadVideos() {
 | 
				
			||||||
        $this->addActionHandler("loadVideo", function () {
 | 
					        $this->addActionHandler("loadVideo", function () {
 | 
				
			||||||
            $query = "SELECT movie_name,movie_id,movie_url,thumbnail,poster,likes,quality,length FROM videos WHERE movie_id='" . $_POST['movieid'] . "'";
 | 
					            $query = "SELECT movie_name,movie_id,movie_url,thumbnail,poster,likes,quality,length FROM videos WHERE movie_id='" . $_POST['movieid'] . "'";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -110,23 +127,7 @@ class Video extends RequestBase {
 | 
				
			|||||||
                array_push($arr['tags'], $r);
 | 
					                array_push($arr['tags'], $r);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            echo(json_encode($arr));
 | 
					            $this->commitMessage(json_encode($arr));
 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->addActionHandler("getDbSize", function () {
 | 
					 | 
				
			||||||
            $dbname = Database::getInstance()->getDatabaseName();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $query = "SELECT table_schema AS \"Database\", 
 | 
					 | 
				
			||||||
                        ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS \"Size\" 
 | 
					 | 
				
			||||||
                        FROM information_schema.TABLES 
 | 
					 | 
				
			||||||
                        WHERE TABLE_SCHEMA='$dbname'
 | 
					 | 
				
			||||||
                        GROUP BY table_schema;";
 | 
					 | 
				
			||||||
            $result = $this->conn->query($query);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ($result->num_rows == 1) {
 | 
					 | 
				
			||||||
                $row = $result->fetch_assoc();
 | 
					 | 
				
			||||||
                echo '{"data":"' . $row["Size"] . 'MB"}';
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->addActionHandler("readThumbnail", function () {
 | 
					        $this->addActionHandler("readThumbnail", function () {
 | 
				
			||||||
@@ -135,38 +136,7 @@ class Video extends RequestBase {
 | 
				
			|||||||
            $result = $this->conn->query($query);
 | 
					            $result = $this->conn->query($query);
 | 
				
			||||||
            $row = $result->fetch_assoc();
 | 
					            $row = $result->fetch_assoc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            echo($row["thumbnail"]);
 | 
					            $this->commitMessage($row["thumbnail"]);
 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->addActionHandler("getTags", function () {
 | 
					 | 
				
			||||||
            // todo add this to loadVideo maybe
 | 
					 | 
				
			||||||
            $movieid = $_POST['movieid'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $query = "SELECT tag_name FROM video_tags 
 | 
					 | 
				
			||||||
                        INNER JOIN tags t on video_tags.tag_id = t.tag_id 
 | 
					 | 
				
			||||||
                        WHERE video_id='$movieid'";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $result = $this->conn->query($query);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $rows = array();
 | 
					 | 
				
			||||||
            $rows['tags'] = array();
 | 
					 | 
				
			||||||
            while ($r = mysqli_fetch_assoc($result)) {
 | 
					 | 
				
			||||||
                array_push($rows['tags'], $r['tag_name']);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            echo(json_encode($rows));
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->addActionHandler("addLike", function () {
 | 
					 | 
				
			||||||
            $movieid = $_POST['movieid'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $query = "update videos set likes = likes + 1 where movie_id = '$movieid'";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ($this->conn->query($query) === TRUE) {
 | 
					 | 
				
			||||||
                echo('{"result":"success"}');
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                echo('{"result":"' . $this->conn->error . '"}');
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->addActionHandler("getStartData", function () {
 | 
					        $this->addActionHandler("getStartData", function () {
 | 
				
			||||||
@@ -213,34 +183,24 @@ class Video extends RequestBase {
 | 
				
			|||||||
            $r = mysqli_fetch_assoc($result);
 | 
					            $r = mysqli_fetch_assoc($result);
 | 
				
			||||||
            $arr['tags'] = $r['nr'];
 | 
					            $arr['tags'] = $r['nr'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            echo(json_encode($arr));
 | 
					            $this->commitMessage(json_encode($arr));
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->addActionHandler("getAllTags", function () {
 | 
					    /**
 | 
				
			||||||
            $query = "SELECT tag_name,tag_id from tags";
 | 
					     * function to handle api handlers for stuff to add to video or database
 | 
				
			||||||
            $result = $this->conn->query($query);
 | 
					     */
 | 
				
			||||||
 | 
					    private function addToVideo() {
 | 
				
			||||||
            $rows = array();
 | 
					        $this->addActionHandler("addLike", function () {
 | 
				
			||||||
            while ($r = mysqli_fetch_assoc($result)) {
 | 
					 | 
				
			||||||
                array_push($rows, $r);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            echo(json_encode($rows));
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->addActionHandler("addTag", function () {
 | 
					 | 
				
			||||||
            $movieid = $_POST['movieid'];
 | 
					            $movieid = $_POST['movieid'];
 | 
				
			||||||
            $tagid = $_POST['id'];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $query = "INSERT INTO video_tags(tag_id, video_id) VALUES ('$tagid','$movieid')";
 | 
					            $query = "update videos set likes = likes + 1 where movie_id = '$movieid'";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($this->conn->query($query) === TRUE) {
 | 
					            if ($this->conn->query($query) === TRUE) {
 | 
				
			||||||
                echo('{"result":"success"}');
 | 
					                $this->commitMessage('{"result":"success"}');
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                echo('{"result":"' . $this->conn->error . '"}');
 | 
					                $this->commitMessage('{"result":"' . $this->conn->error . '"}');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
$video = new Video();
 | 
					 | 
				
			||||||
$video->handleAction();
 | 
					 | 
				
			||||||
							
								
								
									
										5
									
								
								api/tags.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								api/tags.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					include_once './src/handlers/Tags.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$tags = new Tags();
 | 
				
			||||||
 | 
					$tags->handleAction();
 | 
				
			||||||
							
								
								
									
										5
									
								
								api/video.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								api/video.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					include_once './src/handlers/Video.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$video = new Video();
 | 
				
			||||||
 | 
					$video->handleAction();
 | 
				
			||||||
							
								
								
									
										19
									
								
								src/App.js
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/App.js
									
									
									
									
									
								
							@@ -10,6 +10,9 @@ import style from './App.module.css'
 | 
				
			|||||||
import SettingsPage from "./pages/SettingsPage/SettingsPage";
 | 
					import SettingsPage from "./pages/SettingsPage/SettingsPage";
 | 
				
			||||||
import CategoryPage from "./pages/CategoryPage/CategoryPage";
 | 
					import CategoryPage from "./pages/CategoryPage/CategoryPage";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The main App handles the main tabs and which content to show
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class App extends React.Component {
 | 
					class App extends React.Component {
 | 
				
			||||||
    newElement = null;
 | 
					    newElement = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -31,7 +34,7 @@ class App extends React.Component {
 | 
				
			|||||||
        const updateRequest = new FormData();
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
        updateRequest.append('action', 'loadInitialData');
 | 
					        updateRequest.append('action', 'loadInitialData');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fetch('/api/Settings.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/settings.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json()
 | 
					            .then((response) => response.json()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    // set theme
 | 
					                    // set theme
 | 
				
			||||||
@@ -47,6 +50,10 @@ class App extends React.Component {
 | 
				
			|||||||
                }));
 | 
					                }));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * create a viewbinding to call APP functions from child elements
 | 
				
			||||||
 | 
					     * @returns a set of callback functions
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    constructViewBinding() {
 | 
					    constructViewBinding() {
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            changeRootElement: this.changeRootElement,
 | 
					            changeRootElement: this.changeRootElement,
 | 
				
			||||||
@@ -54,6 +61,10 @@ class App extends React.Component {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * load the selected component into the main view
 | 
				
			||||||
 | 
					     * @returns {JSX.Element} body element of selected page
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    MainBody() {
 | 
					    MainBody() {
 | 
				
			||||||
        let page;
 | 
					        let page;
 | 
				
			||||||
        if (this.state.page === "default") {
 | 
					        if (this.state.page === "default") {
 | 
				
			||||||
@@ -109,6 +120,9 @@ class App extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * render a new root element into the main body
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    changeRootElement(element) {
 | 
					    changeRootElement(element) {
 | 
				
			||||||
        this.newElement = element;
 | 
					        this.newElement = element;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -117,6 +131,9 @@ class App extends React.Component {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * return from page to the previous page before a change
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    returnToLastElement() {
 | 
					    returnToLastElement() {
 | 
				
			||||||
        this.setState({
 | 
					        this.setState({
 | 
				
			||||||
            page: "lastpage"
 | 
					            page: "lastpage"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,12 @@
 | 
				
			|||||||
.navitem {
 | 
					.navitem {
 | 
				
			||||||
    float: left;
 | 
					 | 
				
			||||||
    margin-left: 20px;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cursor: pointer;
 | 
					    cursor: pointer;
 | 
				
			||||||
    opacity: 0.6;
 | 
					    float: left;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    font-size: large;
 | 
					    font-size: large;
 | 
				
			||||||
    font-weight: bold;
 | 
					    font-weight: bold;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    margin-left: 20px;
 | 
				
			||||||
 | 
					    opacity: 0.6;
 | 
				
			||||||
    text-transform: capitalize;
 | 
					    text-transform: capitalize;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -18,9 +18,9 @@
 | 
				
			|||||||
.navitem::after {
 | 
					.navitem::after {
 | 
				
			||||||
    content: '';
 | 
					    content: '';
 | 
				
			||||||
    display: block;
 | 
					    display: block;
 | 
				
			||||||
    width: 0;
 | 
					 | 
				
			||||||
    height: 2px;
 | 
					    height: 2px;
 | 
				
			||||||
    transition: width .3s;
 | 
					    transition: width .3s;
 | 
				
			||||||
 | 
					    width: 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.navitem:hover::after {
 | 
					.navitem:hover::after {
 | 
				
			||||||
@@ -33,22 +33,22 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.navcontainer {
 | 
					.navcontainer {
 | 
				
			||||||
 | 
					    border-bottom-width: 2px;
 | 
				
			||||||
 | 
					    border-style: dotted;
 | 
				
			||||||
 | 
					    border-width: 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    padding-bottom: 40px;
 | 
				
			||||||
    padding-top: 20px;
 | 
					    padding-top: 20px;
 | 
				
			||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
    padding-bottom: 40px;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    border-width: 0;
 | 
					 | 
				
			||||||
    border-style: dotted;
 | 
					 | 
				
			||||||
    border-bottom-width: 2px;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.navbrand {
 | 
					.navbrand {
 | 
				
			||||||
    margin-left: 20px;
 | 
					    float: left;
 | 
				
			||||||
    margin-right: 20px;
 | 
					 | 
				
			||||||
    font-size: large;
 | 
					    font-size: large;
 | 
				
			||||||
    font-weight: bold;
 | 
					    font-weight: bold;
 | 
				
			||||||
 | 
					    margin-left: 20px;
 | 
				
			||||||
 | 
					    margin-right: 20px;
 | 
				
			||||||
    text-transform: capitalize;
 | 
					    text-transform: capitalize;
 | 
				
			||||||
    float: left;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,23 +1,37 @@
 | 
				
			|||||||
import darktheme from "./AppDarkTheme.module.css";
 | 
					import darktheme from "./AppDarkTheme.module.css";
 | 
				
			||||||
import lighttheme from "./AppLightTheme.module.css";
 | 
					import lighttheme from "./AppLightTheme.module.css";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This class is available for all components in project
 | 
				
			||||||
 | 
					 * it contains general infos about app - like theme
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class StaticInfos {
 | 
					class StaticInfos {
 | 
				
			||||||
    #darktheme = true;
 | 
					    #darktheme = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * check if the current theme is the dark theme
 | 
				
			||||||
 | 
					     * @returns {boolean} is dark theme?
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    isDarkTheme() {
 | 
					    isDarkTheme() {
 | 
				
			||||||
        return this.#darktheme;
 | 
					        return this.#darktheme;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    enableDarkTheme(enable = true){
 | 
					    /**
 | 
				
			||||||
 | 
					     * setter to enable or disable the dark or light theme
 | 
				
			||||||
 | 
					     * @param enable enable the dark theme?
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    enableDarkTheme(enable = true) {
 | 
				
			||||||
        this.#darktheme = enable;
 | 
					        this.#darktheme = enable;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getThemeStyle(){
 | 
					    /**
 | 
				
			||||||
 | 
					     * get the currently selected theme stylesheet
 | 
				
			||||||
 | 
					     * @returns {*} the style object of the current active theme
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    getThemeStyle() {
 | 
				
			||||||
        return this.isDarkTheme() ? darktheme : lighttheme;
 | 
					        return this.isDarkTheme() ? darktheme : lighttheme;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const GlobalInfos = new StaticInfos();
 | 
					const GlobalInfos = new StaticInfos();
 | 
				
			||||||
//Object.freeze(StaticInfos);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default GlobalInfos;
 | 
					export default GlobalInfos;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,9 @@ import Modal from 'react-bootstrap/Modal'
 | 
				
			|||||||
import Dropdown from "react-bootstrap/Dropdown";
 | 
					import Dropdown from "react-bootstrap/Dropdown";
 | 
				
			||||||
import DropdownButton from "react-bootstrap/DropdownButton";
 | 
					import DropdownButton from "react-bootstrap/DropdownButton";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * component creates overlay to add a new tag to a video
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class AddTagPopup extends React.Component {
 | 
					class AddTagPopup extends React.Component {
 | 
				
			||||||
    constructor(props, context) {
 | 
					    constructor(props, context) {
 | 
				
			||||||
        super(props, context);
 | 
					        super(props, context);
 | 
				
			||||||
@@ -22,7 +25,7 @@ class AddTagPopup extends React.Component {
 | 
				
			|||||||
        const updateRequest = new FormData();
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
        updateRequest.append('action', 'getAllTags');
 | 
					        updateRequest.append('action', 'getAllTags');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fetch('/api/videoload.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/tags.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json())
 | 
					            .then((response) => response.json())
 | 
				
			||||||
            .then((result) => {
 | 
					            .then((result) => {
 | 
				
			||||||
                this.setState({
 | 
					                this.setState({
 | 
				
			||||||
@@ -68,13 +71,16 @@ class AddTagPopup extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * store the filled in form to the backend
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    storeselection() {
 | 
					    storeselection() {
 | 
				
			||||||
        const updateRequest = new FormData();
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
        updateRequest.append('action', 'addTag');
 | 
					        updateRequest.append('action', 'addTag');
 | 
				
			||||||
        updateRequest.append('id', this.state.selection.id);
 | 
					        updateRequest.append('id', this.state.selection.id);
 | 
				
			||||||
        updateRequest.append('movieid', this.props.movie_id);
 | 
					        updateRequest.append('movieid', this.props.movie_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fetch('/api/videoload.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/tags.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json()
 | 
					            .then((response) => response.json()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    if (result.result !== "success") {
 | 
					                    if (result.result !== "success") {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,9 @@ import React from "react";
 | 
				
			|||||||
import Modal from 'react-bootstrap/Modal'
 | 
					import Modal from 'react-bootstrap/Modal'
 | 
				
			||||||
import {Form} from "react-bootstrap";
 | 
					import {Form} from "react-bootstrap";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * creates modal overlay to define a new Tag
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class NewTagPopup extends React.Component {
 | 
					class NewTagPopup extends React.Component {
 | 
				
			||||||
    constructor(props, context) {
 | 
					    constructor(props, context) {
 | 
				
			||||||
        super(props, context);
 | 
					        super(props, context);
 | 
				
			||||||
@@ -45,12 +48,15 @@ class NewTagPopup extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * store the filled in form to the backend
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    storeselection() {
 | 
					    storeselection() {
 | 
				
			||||||
        const updateRequest = new FormData();
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
        updateRequest.append('action', 'createTag');
 | 
					        updateRequest.append('action', 'createTag');
 | 
				
			||||||
        updateRequest.append('tagname', this.value);
 | 
					        updateRequest.append('tagname', this.value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fetch('/api/Tags.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/tags.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json())
 | 
					            .then((response) => response.json())
 | 
				
			||||||
            .then((result) => {
 | 
					            .then((result) => {
 | 
				
			||||||
                if (result.result !== "success") {
 | 
					                if (result.result !== "success") {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,14 +2,10 @@ import React from "react";
 | 
				
			|||||||
import style from "./PageTitle.module.css"
 | 
					import style from "./PageTitle.module.css"
 | 
				
			||||||
import GlobalInfos from "../../GlobalInfos";
 | 
					import GlobalInfos from "../../GlobalInfos";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Component for generating PageTitle with bottom Line
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class PageTitle extends React.Component {
 | 
					class PageTitle extends React.Component {
 | 
				
			||||||
    constructor(props) {
 | 
					 | 
				
			||||||
        super(props);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.props = props;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        const themeStyle = GlobalInfos.getThemeStyle();
 | 
					        const themeStyle = GlobalInfos.getThemeStyle();
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.pageheadersubtitle {
 | 
					.pageheadersubtitle {
 | 
				
			||||||
    margin-left: 20px;
 | 
					 | 
				
			||||||
    font-size: 23pt;
 | 
					    font-size: 23pt;
 | 
				
			||||||
 | 
					    margin-left: 20px;
 | 
				
			||||||
    opacity: 0.6;
 | 
					    opacity: 0.6;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,10 @@ import Player from "../../pages/Player/Player";
 | 
				
			|||||||
import {Spinner} from "react-bootstrap";
 | 
					import {Spinner} from "react-bootstrap";
 | 
				
			||||||
import GlobalInfos from "../../GlobalInfos";
 | 
					import GlobalInfos from "../../GlobalInfos";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Component for single preview tile
 | 
				
			||||||
 | 
					 * floating side by side
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class Preview extends React.Component {
 | 
					class Preview extends React.Component {
 | 
				
			||||||
    constructor(props, context) {
 | 
					    constructor(props, context) {
 | 
				
			||||||
        super(props, context);
 | 
					        super(props, context);
 | 
				
			||||||
@@ -24,7 +28,7 @@ class Preview extends React.Component {
 | 
				
			|||||||
        updateRequest.append('action', 'readThumbnail');
 | 
					        updateRequest.append('action', 'readThumbnail');
 | 
				
			||||||
        updateRequest.append('movieid', this.props.movie_id);
 | 
					        updateRequest.append('movieid', this.props.movie_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fetch('/api/videoload.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/video.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.text()
 | 
					            .then((response) => response.text()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    this.setState({
 | 
					                    this.setState({
 | 
				
			||||||
@@ -36,8 +40,8 @@ class Preview extends React.Component {
 | 
				
			|||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        const themeStyle = GlobalInfos.getThemeStyle();
 | 
					        const themeStyle = GlobalInfos.getThemeStyle();
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className={style.videopreview + ' ' + themeStyle.secbackground + ' '+ themeStyle.preview} onClick={() => this.itemClick()}>
 | 
					            <div className={style.videopreview + ' ' + themeStyle.secbackground + ' ' + themeStyle.preview} onClick={() => this.itemClick()}>
 | 
				
			||||||
                <div className={style.previewtitle + ' '+ themeStyle.lighttextcolor}>{this.state.name}</div>
 | 
					                <div className={style.previewtitle + ' ' + themeStyle.lighttextcolor}>{this.state.name}</div>
 | 
				
			||||||
                <div className={style.previewpic}>
 | 
					                <div className={style.previewpic}>
 | 
				
			||||||
                    {this.state.previewpicture !== null ?
 | 
					                    {this.state.previewpicture !== null ?
 | 
				
			||||||
                        <img className={style.previewimage}
 | 
					                        <img className={style.previewimage}
 | 
				
			||||||
@@ -53,6 +57,9 @@ class Preview extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * handle the click event of a tile
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    itemClick() {
 | 
					    itemClick() {
 | 
				
			||||||
        console.log("item clicked!" + this.state.name);
 | 
					        console.log("item clicked!" + this.state.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -63,11 +70,14 @@ class Preview extends React.Component {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Component for a Tag-name tile (used in category page)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export class TagPreview extends React.Component {
 | 
					export class TagPreview extends React.Component {
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        const themeStyle = GlobalInfos.getThemeStyle();
 | 
					        const themeStyle = GlobalInfos.getThemeStyle();
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className={style.videopreview + ' ' + style.tagpreview + ' ' + themeStyle.secbackground + ' '+ themeStyle.preview} onClick={() => this.itemClick()}>
 | 
					            <div className={style.videopreview + ' ' + style.tagpreview + ' ' + themeStyle.secbackground + ' ' + themeStyle.preview} onClick={() => this.itemClick()}>
 | 
				
			||||||
                <div className={style.tagpreviewtitle + ' ' + themeStyle.lighttextcolor}>
 | 
					                <div className={style.tagpreviewtitle + ' ' + themeStyle.lighttextcolor}>
 | 
				
			||||||
                    {this.props.name}
 | 
					                    {this.props.name}
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
@@ -75,6 +85,9 @@ export class TagPreview extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * handle the click event of a Tag tile
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    itemClick() {
 | 
					    itemClick() {
 | 
				
			||||||
        this.props.categorybinding(this.props.name);
 | 
					        this.props.categorybinding(this.props.name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,11 @@
 | 
				
			|||||||
.previewtitle {
 | 
					.previewtitle {
 | 
				
			||||||
    height: 20px;
 | 
					 | 
				
			||||||
    text-align: center;
 | 
					 | 
				
			||||||
    font-size: smaller;
 | 
					    font-size: smaller;
 | 
				
			||||||
    font-weight: bold;
 | 
					    font-weight: bold;
 | 
				
			||||||
    height: 20px;
 | 
					    height: 20px;
 | 
				
			||||||
 | 
					    height: 20px;
 | 
				
			||||||
    max-width: 266px;
 | 
					    max-width: 266px;
 | 
				
			||||||
    text-align: center;
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.previewpic {
 | 
					.previewpic {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,24 +2,33 @@ import React from "react";
 | 
				
			|||||||
import style from "./SideBar.module.css"
 | 
					import style from "./SideBar.module.css"
 | 
				
			||||||
import GlobalInfos from "../../GlobalInfos";
 | 
					import GlobalInfos from "../../GlobalInfos";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * component for sidebar-info
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class SideBar extends React.Component {
 | 
					class SideBar extends React.Component {
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        const themeStyle = GlobalInfos.getThemeStyle();
 | 
					        const themeStyle = GlobalInfos.getThemeStyle();
 | 
				
			||||||
        return (<div className={style.sideinfo + ' '+ themeStyle.secbackground}>
 | 
					        return (<div className={style.sideinfo + ' ' + themeStyle.secbackground}>
 | 
				
			||||||
            {this.props.children}
 | 
					            {this.props.children}
 | 
				
			||||||
        </div>);
 | 
					        </div>);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The title of the sidebar
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export class SideBarTitle extends React.Component {
 | 
					export class SideBarTitle extends React.Component {
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        const themeStyle = GlobalInfos.getThemeStyle();
 | 
					        const themeStyle = GlobalInfos.getThemeStyle();
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <div className={style.sidebartitle + ' '+ themeStyle.subtextcolor}>{this.props.children}</div>
 | 
					            <div className={style.sidebartitle + ' ' + themeStyle.subtextcolor}>{this.props.children}</div>
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * An item of the sidebar
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export class SideBarItem extends React.Component {
 | 
					export class SideBarItem extends React.Component {
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        const themeStyle = GlobalInfos.getThemeStyle();
 | 
					        const themeStyle = GlobalInfos.getThemeStyle();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,9 @@ import React from "react";
 | 
				
			|||||||
import styles from "./Tag.module.css"
 | 
					import styles from "./Tag.module.css"
 | 
				
			||||||
import CategoryPage from "../../pages/CategoryPage/CategoryPage";
 | 
					import CategoryPage from "../../pages/CategoryPage/CategoryPage";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A Component representing a single Category tag
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class Tag extends React.Component {
 | 
					class Tag extends React.Component {
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
@@ -11,9 +14,13 @@ class Tag extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * click handling for a Tag
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    TagClick() {
 | 
					    TagClick() {
 | 
				
			||||||
        const tag = this.props.children.toString().toLowerCase();
 | 
					        const tag = this.props.children.toString().toLowerCase();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // call callback functin to switch to category page with specified tag
 | 
				
			||||||
        this.props.viewbinding.changeRootElement(
 | 
					        this.props.viewbinding.changeRootElement(
 | 
				
			||||||
            <CategoryPage
 | 
					            <CategoryPage
 | 
				
			||||||
                category={tag}
 | 
					                category={tag}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,10 @@ import React from "react";
 | 
				
			|||||||
import Preview from "../Preview/Preview";
 | 
					import Preview from "../Preview/Preview";
 | 
				
			||||||
import style from "./VideoContainer.module.css"
 | 
					import style from "./VideoContainer.module.css"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A videocontainer storing lots of Preview elements
 | 
				
			||||||
 | 
					 * includes scroll handling and loading of preview infos
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class VideoContainer extends React.Component {
 | 
					class VideoContainer extends React.Component {
 | 
				
			||||||
    // stores current index of loaded elements
 | 
					    // stores current index of loaded elements
 | 
				
			||||||
    loadindex = 0;
 | 
					    loadindex = 0;
 | 
				
			||||||
@@ -43,9 +47,14 @@ class VideoContainer extends React.Component {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    componentWillUnmount() {
 | 
					    componentWillUnmount() {
 | 
				
			||||||
        this.setState({});
 | 
					        this.setState({});
 | 
				
			||||||
 | 
					        // unbind scroll listener when unmounting component
 | 
				
			||||||
        document.removeEventListener('scroll', this.trackScrolling);
 | 
					        document.removeEventListener('scroll', this.trackScrolling);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * load previews to the container
 | 
				
			||||||
 | 
					     * @param nr number of previews to load
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    loadPreviewBlock(nr) {
 | 
					    loadPreviewBlock(nr) {
 | 
				
			||||||
        console.log("loadpreviewblock called ...")
 | 
					        console.log("loadpreviewblock called ...")
 | 
				
			||||||
        let ret = [];
 | 
					        let ret = [];
 | 
				
			||||||
@@ -67,9 +76,11 @@ class VideoContainer extends React.Component {
 | 
				
			|||||||
        this.loadindex += nr;
 | 
					        this.loadindex += nr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * scroll event handler -> load new previews if on bottom
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    trackScrolling = () => {
 | 
					    trackScrolling = () => {
 | 
				
			||||||
        // comparison if current scroll position is on bottom
 | 
					        // comparison if current scroll position is on bottom --> 200 is bottom offset to trigger load
 | 
				
			||||||
        // 200 stands for bottom offset to trigger load
 | 
					 | 
				
			||||||
        if (window.innerHeight + document.documentElement.scrollTop + 200 >= document.documentElement.offsetHeight) {
 | 
					        if (window.innerHeight + document.documentElement.scrollTop + 200 >= document.documentElement.offsetHeight) {
 | 
				
			||||||
            this.loadPreviewBlock(8);
 | 
					            this.loadPreviewBlock(8);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,10 @@ import NewTagPopup from "../../elements/NewTagPopup/NewTagPopup";
 | 
				
			|||||||
import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
 | 
					import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
 | 
				
			||||||
import VideoContainer from "../../elements/VideoContainer/VideoContainer";
 | 
					import VideoContainer from "../../elements/VideoContainer/VideoContainer";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Component for Category Page
 | 
				
			||||||
 | 
					 * Contains a Tag Overview and loads specific Tag videos in VideoContainer
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class CategoryPage extends React.Component {
 | 
					class CategoryPage extends React.Component {
 | 
				
			||||||
    constructor(props, context) {
 | 
					    constructor(props, context) {
 | 
				
			||||||
        super(props, context);
 | 
					        super(props, context);
 | 
				
			||||||
@@ -27,7 +31,11 @@ class CategoryPage extends React.Component {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    /**
 | 
				
			||||||
 | 
					     * render the Title and SideBar component for the Category page
 | 
				
			||||||
 | 
					     * @returns {JSX.Element} corresponding jsx element for Title and Sidebar
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    renderSideBarATitle() {
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <>
 | 
					            <>
 | 
				
			||||||
                <PageTitle
 | 
					                <PageTitle
 | 
				
			||||||
@@ -61,7 +69,14 @@ class CategoryPage extends React.Component {
 | 
				
			|||||||
                        this.setState({popupvisible: true})
 | 
					                        this.setState({popupvisible: true})
 | 
				
			||||||
                    }}>Add a new Tag!
 | 
					                    }}>Add a new Tag!
 | 
				
			||||||
                    </button>
 | 
					                    </button>
 | 
				
			||||||
                </SideBar>
 | 
					                </SideBar></>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render() {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <>
 | 
				
			||||||
 | 
					                {this.renderSideBarATitle()}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                {this.state.selected ?
 | 
					                {this.state.selected ?
 | 
				
			||||||
                    <>
 | 
					                    <>
 | 
				
			||||||
@@ -100,10 +115,18 @@ class CategoryPage extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * load a specific tag into a new previewcontainer
 | 
				
			||||||
 | 
					     * @param tagname
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    loadTag = (tagname) => {
 | 
					    loadTag = (tagname) => {
 | 
				
			||||||
        this.fetchVideoData(tagname);
 | 
					        this.fetchVideoData(tagname);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * fetch data for a specific tag from backend
 | 
				
			||||||
 | 
					     * @param tag tagname
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    fetchVideoData(tag) {
 | 
					    fetchVideoData(tag) {
 | 
				
			||||||
        console.log(tag);
 | 
					        console.log(tag);
 | 
				
			||||||
        const updateRequest = new FormData();
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
@@ -113,7 +136,7 @@ class CategoryPage extends React.Component {
 | 
				
			|||||||
        console.log("fetching data");
 | 
					        console.log("fetching data");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // fetch all videos available
 | 
					        // fetch all videos available
 | 
				
			||||||
        fetch('/api/videoload.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/video.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json()
 | 
					            .then((response) => response.json()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    this.videodata = result;
 | 
					                    this.videodata = result;
 | 
				
			||||||
@@ -125,6 +148,9 @@ class CategoryPage extends React.Component {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * go back to the default category overview
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    loadCategoryPageDefault = () => {
 | 
					    loadCategoryPageDefault = () => {
 | 
				
			||||||
        this.setState({selected: null});
 | 
					        this.setState({selected: null});
 | 
				
			||||||
        this.loadTags();
 | 
					        this.loadTags();
 | 
				
			||||||
@@ -138,7 +164,7 @@ class CategoryPage extends React.Component {
 | 
				
			|||||||
        updateRequest.append('action', 'getAllTags');
 | 
					        updateRequest.append('action', 'getAllTags');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // fetch all videos available
 | 
					        // fetch all videos available
 | 
				
			||||||
        fetch('/api/Tags.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/tags.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json()
 | 
					            .then((response) => response.json()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    this.setState({loadedtags: result});
 | 
					                    this.setState({loadedtags: result});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,9 @@ import VideoContainer from "../../elements/VideoContainer/VideoContainer";
 | 
				
			|||||||
import style from "./HomePage.module.css"
 | 
					import style from "./HomePage.module.css"
 | 
				
			||||||
import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
 | 
					import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The home page component showing on the initial pageload
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class HomePage extends React.Component {
 | 
					class HomePage extends React.Component {
 | 
				
			||||||
    /** keyword variable needed temporary store search keyword */
 | 
					    /** keyword variable needed temporary store search keyword */
 | 
				
			||||||
    keyword = "";
 | 
					    keyword = "";
 | 
				
			||||||
@@ -47,7 +50,7 @@ class HomePage extends React.Component {
 | 
				
			|||||||
        console.log("fetching data");
 | 
					        console.log("fetching data");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // fetch all videos available
 | 
					        // fetch all videos available
 | 
				
			||||||
        fetch('/api/videoload.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/video.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json()
 | 
					            .then((response) => response.json()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    this.setState({
 | 
					                    this.setState({
 | 
				
			||||||
@@ -71,7 +74,7 @@ class HomePage extends React.Component {
 | 
				
			|||||||
        updateRequest.append('action', 'getStartData');
 | 
					        updateRequest.append('action', 'getStartData');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // fetch all videos available
 | 
					        // fetch all videos available
 | 
				
			||||||
        fetch('/api/videoload.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/video.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json()
 | 
					            .then((response) => response.json()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    this.setState({
 | 
					                    this.setState({
 | 
				
			||||||
@@ -102,7 +105,7 @@ class HomePage extends React.Component {
 | 
				
			|||||||
        updateRequest.append('keyword', keyword);
 | 
					        updateRequest.append('keyword', keyword);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // fetch all videos available
 | 
					        // fetch all videos available
 | 
				
			||||||
        fetch('/api/videoload.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/video.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json()
 | 
					            .then((response) => response.json()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    this.setState({
 | 
					                    this.setState({
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,10 @@ import AddTagPopup from "../../elements/AddTagPopup/AddTagPopup";
 | 
				
			|||||||
import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
 | 
					import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Player page loads when a video is selected to play and handles the video view
 | 
				
			||||||
 | 
					 * and actions such as tag adding and liking
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class Player extends React.Component {
 | 
					class Player extends React.Component {
 | 
				
			||||||
    options = {
 | 
					    options = {
 | 
				
			||||||
        controls: [
 | 
					        controls: [
 | 
				
			||||||
@@ -59,7 +63,8 @@ class Player extends React.Component {
 | 
				
			|||||||
                    {this.state.quality !== 0 ?
 | 
					                    {this.state.quality !== 0 ?
 | 
				
			||||||
                        <SideBarItem><b>{this.state.quality}p</b> Quality!</SideBarItem> : null}
 | 
					                        <SideBarItem><b>{this.state.quality}p</b> Quality!</SideBarItem> : null}
 | 
				
			||||||
                    {this.state.length !== 0 ?
 | 
					                    {this.state.length !== 0 ?
 | 
				
			||||||
                        <SideBarItem><b>{Math.round(this.state.length / 60)}</b> Minutes of length!</SideBarItem>: null}
 | 
					                        <SideBarItem><b>{Math.round(this.state.length / 60)}</b> Minutes of
 | 
				
			||||||
 | 
					                            length!</SideBarItem> : null}
 | 
				
			||||||
                    <Line/>
 | 
					                    <Line/>
 | 
				
			||||||
                    <SideBarTitle>Tags:</SideBarTitle>
 | 
					                    <SideBarTitle>Tags:</SideBarTitle>
 | 
				
			||||||
                    {this.state.tags.map((m) => (
 | 
					                    {this.state.tags.map((m) => (
 | 
				
			||||||
@@ -98,12 +103,15 @@ class Player extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * fetch all the required infos of a video from backend
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    fetchMovieData() {
 | 
					    fetchMovieData() {
 | 
				
			||||||
        const updateRequest = new FormData();
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
        updateRequest.append('action', 'loadVideo');
 | 
					        updateRequest.append('action', 'loadVideo');
 | 
				
			||||||
        updateRequest.append('movieid', this.props.movie_id);
 | 
					        updateRequest.append('movieid', this.props.movie_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fetch('/api/videoload.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/video.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json())
 | 
					            .then((response) => response.json())
 | 
				
			||||||
            .then((result) => {
 | 
					            .then((result) => {
 | 
				
			||||||
                this.setState({
 | 
					                this.setState({
 | 
				
			||||||
@@ -129,13 +137,15 @@ class Player extends React.Component {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Click Listener */
 | 
					    /**
 | 
				
			||||||
 | 
					     * click handler for the like btn
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    likebtn() {
 | 
					    likebtn() {
 | 
				
			||||||
        const updateRequest = new FormData();
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
        updateRequest.append('action', 'addLike');
 | 
					        updateRequest.append('action', 'addLike');
 | 
				
			||||||
        updateRequest.append('movieid', this.props.movie_id);
 | 
					        updateRequest.append('movieid', this.props.movie_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fetch('/api/videoload.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/video.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json()
 | 
					            .then((response) => response.json()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    if (result.result === "success") {
 | 
					                    if (result.result === "success") {
 | 
				
			||||||
@@ -147,6 +157,10 @@ class Player extends React.Component {
 | 
				
			|||||||
                }));
 | 
					                }));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * closebtn click handler
 | 
				
			||||||
 | 
					     * calls callback to viewbinding to show previous page agains
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    closebtn() {
 | 
					    closebtn() {
 | 
				
			||||||
        this.props.viewbinding.returnToLastElement();
 | 
					        this.props.viewbinding.returnToLastElement();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,8 +13,8 @@
 | 
				
			|||||||
    float: left;
 | 
					    float: left;
 | 
				
			||||||
    margin-left: 20px;
 | 
					    margin-left: 20px;
 | 
				
			||||||
    margin-top: 25px;
 | 
					    margin-top: 25px;
 | 
				
			||||||
    width: 60%;
 | 
					 | 
				
			||||||
    margin-top: 20px;
 | 
					    margin-top: 20px;
 | 
				
			||||||
 | 
					    width: 60%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.videoactions {
 | 
					.videoactions {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,9 @@ import Tag from "../../elements/Tag/Tag";
 | 
				
			|||||||
import PageTitle from "../../elements/PageTitle/PageTitle";
 | 
					import PageTitle from "../../elements/PageTitle/PageTitle";
 | 
				
			||||||
import VideoContainer from "../../elements/VideoContainer/VideoContainer";
 | 
					import VideoContainer from "../../elements/VideoContainer/VideoContainer";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Randompage shuffles random viedeopreviews and provides a shuffle btn
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class RandomPage extends React.Component {
 | 
					class RandomPage extends React.Component {
 | 
				
			||||||
    constructor(props, context) {
 | 
					    constructor(props, context) {
 | 
				
			||||||
        super(props, context);
 | 
					        super(props, context);
 | 
				
			||||||
@@ -50,17 +53,24 @@ class RandomPage extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * click handler for shuffle btn
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    shuffleclick() {
 | 
					    shuffleclick() {
 | 
				
			||||||
        this.loadShuffledvideos(4);
 | 
					        this.loadShuffledvideos(4);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * load random videos from backend
 | 
				
			||||||
 | 
					     * @param nr number of videos to load
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    loadShuffledvideos(nr) {
 | 
					    loadShuffledvideos(nr) {
 | 
				
			||||||
        const updateRequest = new FormData();
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
        updateRequest.append('action', 'getRandomMovies');
 | 
					        updateRequest.append('action', 'getRandomMovies');
 | 
				
			||||||
        updateRequest.append('number', nr);
 | 
					        updateRequest.append('number', nr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // fetch all videos available
 | 
					        // fetch all videos available
 | 
				
			||||||
        fetch('/api/videoload.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/video.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json()
 | 
					            .then((response) => response.json()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    console.log(result);
 | 
					                    console.log(result);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,10 @@ import {Button, Col, Form} from "react-bootstrap";
 | 
				
			|||||||
import style from "./GeneralSettings.module.css"
 | 
					import style from "./GeneralSettings.module.css"
 | 
				
			||||||
import GlobalInfos from "../../GlobalInfos";
 | 
					import GlobalInfos from "../../GlobalInfos";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Component for Generalsettings tag on Settingspage
 | 
				
			||||||
 | 
					 * handles general settings of mediacenter which concerns to all pages
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class GeneralSettings extends React.Component {
 | 
					class GeneralSettings extends React.Component {
 | 
				
			||||||
    constructor(props) {
 | 
					    constructor(props) {
 | 
				
			||||||
        super(props);
 | 
					        super(props);
 | 
				
			||||||
@@ -19,22 +23,7 @@ class GeneralSettings extends React.Component {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentDidMount() {
 | 
					    componentDidMount() {
 | 
				
			||||||
        const updateRequest = new FormData();
 | 
					        this.loadSettings();
 | 
				
			||||||
        updateRequest.append('action', 'loadGeneralSettings');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fetch('/api/Settings.php', {method: 'POST', body: updateRequest})
 | 
					 | 
				
			||||||
            .then((response) => response.json()
 | 
					 | 
				
			||||||
                .then((result) => {
 | 
					 | 
				
			||||||
                    console.log(result);
 | 
					 | 
				
			||||||
                    this.setState({
 | 
					 | 
				
			||||||
                        videopath: result.video_path,
 | 
					 | 
				
			||||||
                        tvshowpath: result.episode_path,
 | 
					 | 
				
			||||||
                        mediacentername: result.mediacenter_name,
 | 
					 | 
				
			||||||
                        password: result.password,
 | 
					 | 
				
			||||||
                        passwordsupport: result.passwordEnabled,
 | 
					 | 
				
			||||||
                        tmdbsupport: result.TMDB_grabbing
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                }));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
@@ -119,6 +108,31 @@ class GeneralSettings extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * inital load of already specified settings from backend
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    loadSettings() {
 | 
				
			||||||
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
 | 
					        updateRequest.append('action', 'loadGeneralSettings');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fetch('/api/settings.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
 | 
					            .then((response) => response.json()
 | 
				
			||||||
 | 
					                .then((result) => {
 | 
				
			||||||
 | 
					                    console.log(result);
 | 
				
			||||||
 | 
					                    this.setState({
 | 
				
			||||||
 | 
					                        videopath: result.video_path,
 | 
				
			||||||
 | 
					                        tvshowpath: result.episode_path,
 | 
				
			||||||
 | 
					                        mediacentername: result.mediacenter_name,
 | 
				
			||||||
 | 
					                        password: result.password,
 | 
				
			||||||
 | 
					                        passwordsupport: result.passwordEnabled,
 | 
				
			||||||
 | 
					                        tmdbsupport: result.TMDB_grabbing
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                }));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * save the selected and typed settings to the backend
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    saveSettings() {
 | 
					    saveSettings() {
 | 
				
			||||||
        const updateRequest = new FormData();
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
        updateRequest.append('action', 'saveGeneralSettings');
 | 
					        updateRequest.append('action', 'saveGeneralSettings');
 | 
				
			||||||
@@ -130,7 +144,7 @@ class GeneralSettings extends React.Component {
 | 
				
			|||||||
        updateRequest.append("tmdbsupport", this.state.tmdbsupport);
 | 
					        updateRequest.append("tmdbsupport", this.state.tmdbsupport);
 | 
				
			||||||
        updateRequest.append("darkmodeenabled", GlobalInfos.isDarkTheme());
 | 
					        updateRequest.append("darkmodeenabled", GlobalInfos.isDarkTheme());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fetch('/api/Settings.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/settings.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
            .then((response) => response.json()
 | 
					            .then((response) => response.json()
 | 
				
			||||||
                .then((result) => {
 | 
					                .then((result) => {
 | 
				
			||||||
                    if (result.success) {
 | 
					                    if (result.success) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,10 @@
 | 
				
			|||||||
import React from "react";
 | 
					import React from "react";
 | 
				
			||||||
import style from "./MovieSettings.module.css"
 | 
					import style from "./MovieSettings.module.css"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Component for MovieSettings on Settingspage
 | 
				
			||||||
 | 
					 * handles settings concerning to movies in general
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class MovieSettings extends React.Component {
 | 
					class MovieSettings extends React.Component {
 | 
				
			||||||
    constructor(props) {
 | 
					    constructor(props) {
 | 
				
			||||||
        super(props);
 | 
					        super(props);
 | 
				
			||||||
@@ -36,6 +40,9 @@ class MovieSettings extends React.Component {
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * starts the reindex process of the videos in the specified folder
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    startReindex() {
 | 
					    startReindex() {
 | 
				
			||||||
        // clear output text before start
 | 
					        // clear output text before start
 | 
				
			||||||
        this.setState({text: []});
 | 
					        this.setState({text: []});
 | 
				
			||||||
@@ -60,6 +67,9 @@ class MovieSettings extends React.Component {
 | 
				
			|||||||
        this.myinterval = setInterval(this.updateStatus, 1000);
 | 
					        this.myinterval = setInterval(this.updateStatus, 1000);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * This interval function reloads the current status of reindexing from backend
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    updateStatus = () => {
 | 
					    updateStatus = () => {
 | 
				
			||||||
        const updateRequest = new FormData();
 | 
					        const updateRequest = new FormData();
 | 
				
			||||||
        fetch('/api/extractionData.php', {method: 'POST', body: updateRequest})
 | 
					        fetch('/api/extractionData.php', {method: 'POST', body: updateRequest})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,10 @@ import GeneralSettings from "./GeneralSettings";
 | 
				
			|||||||
import style from "./SettingsPage.module.css"
 | 
					import style from "./SettingsPage.module.css"
 | 
				
			||||||
import GlobalInfos from "../../GlobalInfos";
 | 
					import GlobalInfos from "../../GlobalInfos";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The Settingspage handles all kinds of settings for the mediacenter
 | 
				
			||||||
 | 
					 * and is basically a wrapper for child-tabs
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
class SettingsPage extends React.Component {
 | 
					class SettingsPage extends React.Component {
 | 
				
			||||||
    constructor(props, context) {
 | 
					    constructor(props, context) {
 | 
				
			||||||
        super(props, context);
 | 
					        super(props, context);
 | 
				
			||||||
@@ -14,6 +17,10 @@ class SettingsPage extends React.Component {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * load the selected tab
 | 
				
			||||||
 | 
					     * @returns {JSX.Element|string} the jsx element of the selected tab
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    getContent() {
 | 
					    getContent() {
 | 
				
			||||||
        switch (this.state.currentpage) {
 | 
					        switch (this.state.currentpage) {
 | 
				
			||||||
            case "general":
 | 
					            case "general":
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,11 @@ import Adapter from 'enzyme-adapter-react-16';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
configure({adapter: new Adapter()});
 | 
					configure({adapter: new Adapter()});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * prepares fetch api for a virtual test call
 | 
				
			||||||
 | 
					 * @param response the response fetch should give you back
 | 
				
			||||||
 | 
					 * @returns {jest.Mock<any, any>} a jest mock function simulating a fetch
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
global.prepareFetchApi = (response) => {
 | 
					global.prepareFetchApi = (response) => {
 | 
				
			||||||
    const mockJsonPromise = Promise.resolve(response);
 | 
					    const mockJsonPromise = Promise.resolve(response);
 | 
				
			||||||
    const mockFetchPromise = Promise.resolve({
 | 
					    const mockFetchPromise = Promise.resolve({
 | 
				
			||||||
@@ -17,6 +22,10 @@ global.prepareFetchApi = (response) => {
 | 
				
			|||||||
    return (jest.fn().mockImplementation(() => mockFetchPromise));
 | 
					    return (jest.fn().mockImplementation(() => mockFetchPromise));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * prepares a failing virtual fetch api call
 | 
				
			||||||
 | 
					 * @returns {jest.Mock<any, any>} a jest moch function simulating a failing fetch call
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
global.prepareFailingFetchApi = () => {
 | 
					global.prepareFailingFetchApi = () => {
 | 
				
			||||||
    const mockFetchPromise = Promise.reject("myreason");
 | 
					    const mockFetchPromise = Promise.reject("myreason");
 | 
				
			||||||
    return (jest.fn().mockImplementation(() => mockFetchPromise));
 | 
					    return (jest.fn().mockImplementation(() => mockFetchPromise));
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user