new folder structure for php scripts
renamed api nodes php braces on same line
This commit is contained in:
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 CategoryPage from "./pages/CategoryPage/CategoryPage";
|
||||
|
||||
/**
|
||||
* The main App handles the main tabs and which content to show
|
||||
*/
|
||||
class App extends React.Component {
|
||||
newElement = null;
|
||||
|
||||
@ -31,7 +34,7 @@ class App extends React.Component {
|
||||
const updateRequest = new FormData();
|
||||
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((result) => {
|
||||
// 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() {
|
||||
return {
|
||||
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() {
|
||||
let page;
|
||||
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) {
|
||||
this.newElement = element;
|
||||
|
||||
@ -117,6 +131,9 @@ class App extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* return from page to the previous page before a change
|
||||
*/
|
||||
returnToLastElement() {
|
||||
this.setState({
|
||||
page: "lastpage"
|
||||
|
@ -1,12 +1,12 @@
|
||||
.navitem {
|
||||
float: left;
|
||||
margin-left: 20px;
|
||||
|
||||
cursor: pointer;
|
||||
opacity: 0.6;
|
||||
float: left;
|
||||
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
|
||||
margin-left: 20px;
|
||||
opacity: 0.6;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
@ -18,9 +18,9 @@
|
||||
.navitem::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
transition: width .3s;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.navitem:hover::after {
|
||||
@ -33,22 +33,22 @@
|
||||
}
|
||||
|
||||
.navcontainer {
|
||||
border-bottom-width: 2px;
|
||||
border-style: dotted;
|
||||
border-width: 0;
|
||||
|
||||
padding-bottom: 40px;
|
||||
padding-top: 20px;
|
||||
width: 100%;
|
||||
padding-bottom: 40px;
|
||||
|
||||
border-width: 0;
|
||||
border-style: dotted;
|
||||
border-bottom-width: 2px;
|
||||
}
|
||||
|
||||
.navbrand {
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
float: left;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
text-transform: capitalize;
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,23 +1,37 @@
|
||||
import darktheme from "./AppDarkTheme.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 {
|
||||
#darktheme = true;
|
||||
|
||||
/**
|
||||
* check if the current theme is the dark theme
|
||||
* @returns {boolean} is dark theme?
|
||||
*/
|
||||
isDarkTheme() {
|
||||
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;
|
||||
}
|
||||
|
||||
getThemeStyle(){
|
||||
/**
|
||||
* get the currently selected theme stylesheet
|
||||
* @returns {*} the style object of the current active theme
|
||||
*/
|
||||
getThemeStyle() {
|
||||
return this.isDarkTheme() ? darktheme : lighttheme;
|
||||
}
|
||||
}
|
||||
|
||||
const GlobalInfos = new StaticInfos();
|
||||
//Object.freeze(StaticInfos);
|
||||
|
||||
export default GlobalInfos;
|
||||
|
@ -3,6 +3,9 @@ import Modal from 'react-bootstrap/Modal'
|
||||
import Dropdown from "react-bootstrap/Dropdown";
|
||||
import DropdownButton from "react-bootstrap/DropdownButton";
|
||||
|
||||
/**
|
||||
* component creates overlay to add a new tag to a video
|
||||
*/
|
||||
class AddTagPopup extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
@ -22,7 +25,7 @@ class AddTagPopup extends React.Component {
|
||||
const updateRequest = new FormData();
|
||||
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((result) => {
|
||||
this.setState({
|
||||
@ -68,13 +71,16 @@ class AddTagPopup extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* store the filled in form to the backend
|
||||
*/
|
||||
storeselection() {
|
||||
const updateRequest = new FormData();
|
||||
updateRequest.append('action', 'addTag');
|
||||
updateRequest.append('id', this.state.selection.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((result) => {
|
||||
if (result.result !== "success") {
|
||||
|
@ -2,6 +2,9 @@ import React from "react";
|
||||
import Modal from 'react-bootstrap/Modal'
|
||||
import {Form} from "react-bootstrap";
|
||||
|
||||
/**
|
||||
* creates modal overlay to define a new Tag
|
||||
*/
|
||||
class NewTagPopup extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
@ -45,12 +48,15 @@ class NewTagPopup extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* store the filled in form to the backend
|
||||
*/
|
||||
storeselection() {
|
||||
const updateRequest = new FormData();
|
||||
updateRequest.append('action', 'createTag');
|
||||
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((result) => {
|
||||
if (result.result !== "success") {
|
||||
|
@ -2,14 +2,10 @@ import React from "react";
|
||||
import style from "./PageTitle.module.css"
|
||||
import GlobalInfos from "../../GlobalInfos";
|
||||
|
||||
/**
|
||||
* Component for generating PageTitle with bottom Line
|
||||
*/
|
||||
class PageTitle extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.props = props;
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
|
@ -8,7 +8,7 @@
|
||||
}
|
||||
|
||||
.pageheadersubtitle {
|
||||
margin-left: 20px;
|
||||
font-size: 23pt;
|
||||
margin-left: 20px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
@ -4,6 +4,10 @@ import Player from "../../pages/Player/Player";
|
||||
import {Spinner} from "react-bootstrap";
|
||||
import GlobalInfos from "../../GlobalInfos";
|
||||
|
||||
/**
|
||||
* Component for single preview tile
|
||||
* floating side by side
|
||||
*/
|
||||
class Preview extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
@ -24,7 +28,7 @@ class Preview extends React.Component {
|
||||
updateRequest.append('action', 'readThumbnail');
|
||||
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((result) => {
|
||||
this.setState({
|
||||
@ -36,8 +40,8 @@ class Preview extends React.Component {
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<div className={style.videopreview + ' ' + themeStyle.secbackground + ' '+ themeStyle.preview} onClick={() => this.itemClick()}>
|
||||
<div className={style.previewtitle + ' '+ themeStyle.lighttextcolor}>{this.state.name}</div>
|
||||
<div className={style.videopreview + ' ' + themeStyle.secbackground + ' ' + themeStyle.preview} onClick={() => this.itemClick()}>
|
||||
<div className={style.previewtitle + ' ' + themeStyle.lighttextcolor}>{this.state.name}</div>
|
||||
<div className={style.previewpic}>
|
||||
{this.state.previewpicture !== null ?
|
||||
<img className={style.previewimage}
|
||||
@ -53,6 +57,9 @@ class Preview extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* handle the click event of a tile
|
||||
*/
|
||||
itemClick() {
|
||||
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 {
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
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}>
|
||||
{this.props.name}
|
||||
</div>
|
||||
@ -75,6 +85,9 @@ export class TagPreview extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* handle the click event of a Tag tile
|
||||
*/
|
||||
itemClick() {
|
||||
this.props.categorybinding(this.props.name);
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
.previewtitle {
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
font-size: smaller;
|
||||
font-weight: bold;
|
||||
height: 20px;
|
||||
height: 20px;
|
||||
max-width: 266px;
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.previewpic {
|
||||
|
@ -2,24 +2,33 @@ import React from "react";
|
||||
import style from "./SideBar.module.css"
|
||||
import GlobalInfos from "../../GlobalInfos";
|
||||
|
||||
/**
|
||||
* component for sidebar-info
|
||||
*/
|
||||
class SideBar extends React.Component {
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (<div className={style.sideinfo + ' '+ themeStyle.secbackground}>
|
||||
return (<div className={style.sideinfo + ' ' + themeStyle.secbackground}>
|
||||
{this.props.children}
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The title of the sidebar
|
||||
*/
|
||||
export class SideBarTitle extends React.Component {
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
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 {
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
|
@ -3,6 +3,9 @@ import React from "react";
|
||||
import styles from "./Tag.module.css"
|
||||
import CategoryPage from "../../pages/CategoryPage/CategoryPage";
|
||||
|
||||
/**
|
||||
* A Component representing a single Category tag
|
||||
*/
|
||||
class Tag extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
@ -11,9 +14,13 @@ class Tag extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* click handling for a Tag
|
||||
*/
|
||||
TagClick() {
|
||||
const tag = this.props.children.toString().toLowerCase();
|
||||
|
||||
// call callback functin to switch to category page with specified tag
|
||||
this.props.viewbinding.changeRootElement(
|
||||
<CategoryPage
|
||||
category={tag}
|
||||
|
@ -2,6 +2,10 @@ import React from "react";
|
||||
import Preview from "../Preview/Preview";
|
||||
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 {
|
||||
// stores current index of loaded elements
|
||||
loadindex = 0;
|
||||
@ -43,9 +47,14 @@ class VideoContainer extends React.Component {
|
||||
|
||||
componentWillUnmount() {
|
||||
this.setState({});
|
||||
// unbind scroll listener when unmounting component
|
||||
document.removeEventListener('scroll', this.trackScrolling);
|
||||
}
|
||||
|
||||
/**
|
||||
* load previews to the container
|
||||
* @param nr number of previews to load
|
||||
*/
|
||||
loadPreviewBlock(nr) {
|
||||
console.log("loadpreviewblock called ...")
|
||||
let ret = [];
|
||||
@ -67,9 +76,11 @@ class VideoContainer extends React.Component {
|
||||
this.loadindex += nr;
|
||||
}
|
||||
|
||||
/**
|
||||
* scroll event handler -> load new previews if on bottom
|
||||
*/
|
||||
trackScrolling = () => {
|
||||
// comparison if current scroll position is on bottom
|
||||
// 200 stands for bottom offset to trigger load
|
||||
// comparison if current scroll position is on bottom --> 200 is bottom offset to trigger load
|
||||
if (window.innerHeight + document.documentElement.scrollTop + 200 >= document.documentElement.offsetHeight) {
|
||||
this.loadPreviewBlock(8);
|
||||
}
|
||||
|
@ -8,6 +8,10 @@ import NewTagPopup from "../../elements/NewTagPopup/NewTagPopup";
|
||||
import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
|
||||
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 {
|
||||
constructor(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 (
|
||||
<>
|
||||
<PageTitle
|
||||
@ -61,7 +69,14 @@ class CategoryPage extends React.Component {
|
||||
this.setState({popupvisible: true})
|
||||
}}>Add a new Tag!
|
||||
</button>
|
||||
</SideBar>
|
||||
</SideBar></>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
{this.renderSideBarATitle()}
|
||||
|
||||
{this.state.selected ?
|
||||
<>
|
||||
@ -100,10 +115,18 @@ class CategoryPage extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* load a specific tag into a new previewcontainer
|
||||
* @param tagname
|
||||
*/
|
||||
loadTag = (tagname) => {
|
||||
this.fetchVideoData(tagname);
|
||||
};
|
||||
|
||||
/**
|
||||
* fetch data for a specific tag from backend
|
||||
* @param tag tagname
|
||||
*/
|
||||
fetchVideoData(tag) {
|
||||
console.log(tag);
|
||||
const updateRequest = new FormData();
|
||||
@ -113,7 +136,7 @@ class CategoryPage extends React.Component {
|
||||
console.log("fetching data");
|
||||
|
||||
// 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((result) => {
|
||||
this.videodata = result;
|
||||
@ -125,6 +148,9 @@ class CategoryPage extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* go back to the default category overview
|
||||
*/
|
||||
loadCategoryPageDefault = () => {
|
||||
this.setState({selected: null});
|
||||
this.loadTags();
|
||||
@ -138,7 +164,7 @@ class CategoryPage extends React.Component {
|
||||
updateRequest.append('action', 'getAllTags');
|
||||
|
||||
// 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((result) => {
|
||||
this.setState({loadedtags: result});
|
||||
|
@ -6,6 +6,9 @@ import VideoContainer from "../../elements/VideoContainer/VideoContainer";
|
||||
import style from "./HomePage.module.css"
|
||||
import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
|
||||
|
||||
/**
|
||||
* The home page component showing on the initial pageload
|
||||
*/
|
||||
class HomePage extends React.Component {
|
||||
/** keyword variable needed temporary store search keyword */
|
||||
keyword = "";
|
||||
@ -47,7 +50,7 @@ class HomePage extends React.Component {
|
||||
console.log("fetching data");
|
||||
|
||||
// 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((result) => {
|
||||
this.setState({
|
||||
@ -71,7 +74,7 @@ class HomePage extends React.Component {
|
||||
updateRequest.append('action', 'getStartData');
|
||||
|
||||
// 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((result) => {
|
||||
this.setState({
|
||||
@ -102,7 +105,7 @@ class HomePage extends React.Component {
|
||||
updateRequest.append('keyword', keyword);
|
||||
|
||||
// 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((result) => {
|
||||
this.setState({
|
||||
|
@ -8,6 +8,10 @@ import AddTagPopup from "../../elements/AddTagPopup/AddTagPopup";
|
||||
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 {
|
||||
options = {
|
||||
controls: [
|
||||
@ -59,7 +63,8 @@ class Player extends React.Component {
|
||||
{this.state.quality !== 0 ?
|
||||
<SideBarItem><b>{this.state.quality}p</b> Quality!</SideBarItem> : null}
|
||||
{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/>
|
||||
<SideBarTitle>Tags:</SideBarTitle>
|
||||
{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() {
|
||||
const updateRequest = new FormData();
|
||||
updateRequest.append('action', 'loadVideo');
|
||||
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((result) => {
|
||||
this.setState({
|
||||
@ -129,13 +137,15 @@ class Player extends React.Component {
|
||||
}
|
||||
|
||||
|
||||
/* Click Listener */
|
||||
/**
|
||||
* click handler for the like btn
|
||||
*/
|
||||
likebtn() {
|
||||
const updateRequest = new FormData();
|
||||
updateRequest.append('action', 'addLike');
|
||||
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((result) => {
|
||||
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() {
|
||||
this.props.viewbinding.returnToLastElement();
|
||||
}
|
||||
|
@ -13,8 +13,8 @@
|
||||
float: left;
|
||||
margin-left: 20px;
|
||||
margin-top: 25px;
|
||||
width: 60%;
|
||||
margin-top: 20px;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.videoactions {
|
||||
|
@ -5,6 +5,9 @@ import Tag from "../../elements/Tag/Tag";
|
||||
import PageTitle from "../../elements/PageTitle/PageTitle";
|
||||
import VideoContainer from "../../elements/VideoContainer/VideoContainer";
|
||||
|
||||
/**
|
||||
* Randompage shuffles random viedeopreviews and provides a shuffle btn
|
||||
*/
|
||||
class RandomPage extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
@ -50,17 +53,24 @@ class RandomPage extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* click handler for shuffle btn
|
||||
*/
|
||||
shuffleclick() {
|
||||
this.loadShuffledvideos(4);
|
||||
}
|
||||
|
||||
/**
|
||||
* load random videos from backend
|
||||
* @param nr number of videos to load
|
||||
*/
|
||||
loadShuffledvideos(nr) {
|
||||
const updateRequest = new FormData();
|
||||
updateRequest.append('action', 'getRandomMovies');
|
||||
updateRequest.append('number', nr);
|
||||
|
||||
// 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((result) => {
|
||||
console.log(result);
|
||||
|
@ -3,6 +3,10 @@ import {Button, Col, Form} from "react-bootstrap";
|
||||
import style from "./GeneralSettings.module.css"
|
||||
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 {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -19,22 +23,7 @@ class GeneralSettings extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
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
|
||||
});
|
||||
}));
|
||||
this.loadSettings();
|
||||
}
|
||||
|
||||
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() {
|
||||
const updateRequest = new FormData();
|
||||
updateRequest.append('action', 'saveGeneralSettings');
|
||||
@ -130,7 +144,7 @@ class GeneralSettings extends React.Component {
|
||||
updateRequest.append("tmdbsupport", this.state.tmdbsupport);
|
||||
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((result) => {
|
||||
if (result.success) {
|
||||
|
@ -1,6 +1,10 @@
|
||||
import React from "react";
|
||||
import style from "./MovieSettings.module.css"
|
||||
|
||||
/**
|
||||
* Component for MovieSettings on Settingspage
|
||||
* handles settings concerning to movies in general
|
||||
*/
|
||||
class MovieSettings extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -36,6 +40,9 @@ class MovieSettings extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* starts the reindex process of the videos in the specified folder
|
||||
*/
|
||||
startReindex() {
|
||||
// clear output text before start
|
||||
this.setState({text: []});
|
||||
@ -60,6 +67,9 @@ class MovieSettings extends React.Component {
|
||||
this.myinterval = setInterval(this.updateStatus, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* This interval function reloads the current status of reindexing from backend
|
||||
*/
|
||||
updateStatus = () => {
|
||||
const updateRequest = new FormData();
|
||||
fetch('/api/extractionData.php', {method: 'POST', body: updateRequest})
|
||||
|
@ -4,7 +4,10 @@ import GeneralSettings from "./GeneralSettings";
|
||||
import style from "./SettingsPage.module.css"
|
||||
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 {
|
||||
constructor(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() {
|
||||
switch (this.state.currentpage) {
|
||||
case "general":
|
||||
|
@ -9,6 +9,11 @@ import Adapter from 'enzyme-adapter-react-16';
|
||||
|
||||
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) => {
|
||||
const mockJsonPromise = Promise.resolve(response);
|
||||
const mockFetchPromise = Promise.resolve({
|
||||
@ -17,6 +22,10 @@ global.prepareFetchApi = (response) => {
|
||||
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 = () => {
|
||||
const mockFetchPromise = Promise.reject("myreason");
|
||||
return (jest.fn().mockImplementation(() => mockFetchPromise));
|
||||
|
Reference in New Issue
Block a user