Merge branch 'csstheming' into 'master'
Csstheming See merge request lukas/openmediacenter!8
This commit is contained in:
commit
13336cbf1c
@ -22,13 +22,15 @@ class Settings extends RequestBase {
|
||||
$videopath = $_POST['videopath'];
|
||||
$tvshowpath = $_POST['tvshowpath'];
|
||||
$tmdbsupport = $_POST['tmdbsupport'];
|
||||
$darkmodeenabled = $_POST['darkmodeenabled'];
|
||||
|
||||
$query = "UPDATE settings SET
|
||||
video_path='$videopath',
|
||||
episode_path='$tvshowpath',
|
||||
password='$password',
|
||||
mediacenter_name='$mediacentername',
|
||||
TMDB_grabbing=$tmdbsupport
|
||||
TMDB_grabbing=$tmdbsupport,
|
||||
DarkMode=$darkmodeenabled
|
||||
WHERE 1";
|
||||
|
||||
if ($this->conn->query($query) === true) {
|
||||
@ -44,12 +46,10 @@ class Settings extends RequestBase {
|
||||
$result = $this->conn->query($query);
|
||||
|
||||
$r = mysqli_fetch_assoc($result);
|
||||
if ($r['password'] != "-1") {
|
||||
$r['passwordEnabled'] = true;
|
||||
} else {
|
||||
$r['passwordEnabled'] = false;
|
||||
}
|
||||
|
||||
$r['passwordEnabled'] = $r['password'] != "-1";
|
||||
unset($r['password']);
|
||||
$r['DarkMode'] = (bool)($r['DarkMode'] != '0');
|
||||
echo json_encode($r);
|
||||
});
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ create table settings
|
||||
episode_path varchar(255) null,
|
||||
password varchar(32) default '-1' null,
|
||||
mediacenter_name varchar(32) default 'OpenMediaCenter' null,
|
||||
TMDB_grabbing tinyint null,
|
||||
DarkMode tinyint default 0 null
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
|
12
src/App.css
12
src/App.css
@ -1,12 +0,0 @@
|
||||
.nav-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
color: rgba(255, 255, 255, .5);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav-link:hover {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
39
src/App.js
39
src/App.js
@ -1,10 +1,12 @@
|
||||
import React from 'react';
|
||||
import "./App.css"
|
||||
import HomePage from "./pages/HomePage/HomePage";
|
||||
import RandomPage from "./pages/RandomPage/RandomPage";
|
||||
import GlobalInfos from "./GlobalInfos";
|
||||
|
||||
// include bootstraps css
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import style from './App.module.css'
|
||||
|
||||
import SettingsPage from "./pages/SettingsPage/SettingsPage";
|
||||
import CategoryPage from "./pages/CategoryPage/CategoryPage";
|
||||
|
||||
@ -32,7 +34,9 @@ class App extends React.Component {
|
||||
fetch('/api/Settings.php', {method: 'POST', body: updateRequest})
|
||||
.then((response) => response.json()
|
||||
.then((result) => {
|
||||
console.log(result);
|
||||
// set theme
|
||||
GlobalInfos.enableDarkTheme(result.DarkMode);
|
||||
|
||||
this.setState({
|
||||
generalSettingsLoaded: true,
|
||||
passwordsupport: result.passwordEnabled,
|
||||
@ -79,38 +83,27 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
// add the main theme to the page body
|
||||
document.body.className = themeStyle.backgroundcolor;
|
||||
return (
|
||||
<div className="App">
|
||||
<nav className="navbar navbar-expand-sm bg-primary navbar-dark">
|
||||
<div className="navbar-brand">{this.state.mediacentername}</div>
|
||||
<div className={[style.navcontainer, themeStyle.backgroundcolor, themeStyle.textcolor, themeStyle.hrcolor].join(' ')}>
|
||||
<div className={style.navbrand}>{this.state.mediacentername}</div>
|
||||
|
||||
<ul className="navbar-nav">
|
||||
<li className="nav-item">
|
||||
<div className="nav-link"
|
||||
style={this.state.page === "default" ? {color: "rgba(255,255,255,.75"} : {}}
|
||||
<div className={[style.navitem, themeStyle.navitem, this.state.page === "default" ? style.navitemselected : {}].join(' ')}
|
||||
onClick={() => this.setState({page: "default"})}>Home
|
||||
</div>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<div className="nav-link"
|
||||
style={this.state.page === "random" ? {color: "rgba(255,255,255,.75"} : {}}
|
||||
<div className={[style.navitem, themeStyle.navitem, this.state.page === "random" ? style.navitemselected : {}].join(' ')}
|
||||
onClick={() => this.setState({page: "random"})}>Random Video
|
||||
</div>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<div className="nav-link"
|
||||
style={this.state.page === "categories" ? {color: "rgba(255,255,255,.75"} : {}}
|
||||
<div className={[style.navitem, themeStyle.navitem, this.state.page === "categories" ? style.navitemselected : {}].join(' ')}
|
||||
onClick={() => this.setState({page: "categories"})}>Categories
|
||||
</div>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<div className="nav-link"
|
||||
style={this.state.page === "settings" ? {color: "rgba(255,255,255,.75"} : {}}
|
||||
<div className={[style.navitem, themeStyle.navitem, this.state.page === "settings" ? style.navitemselected : {}].join(' ')}
|
||||
onClick={() => this.setState({page: "settings"})}>Settings
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{this.state.generalSettingsLoaded ? this.MainBody() : "loading"}
|
||||
</div>
|
||||
);
|
||||
|
54
src/App.module.css
Normal file
54
src/App.module.css
Normal file
@ -0,0 +1,54 @@
|
||||
.navitem {
|
||||
float: left;
|
||||
margin-left: 20px;
|
||||
|
||||
cursor: pointer;
|
||||
opacity: 0.6;
|
||||
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.navitem:hover {
|
||||
opacity: 1;
|
||||
transition: opacity .5s;
|
||||
}
|
||||
|
||||
.navitem::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
transition: width .3s;
|
||||
}
|
||||
|
||||
.navitem:hover::after {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.navitemselected {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.navcontainer {
|
||||
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;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
text-transform: capitalize;
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
@ -10,19 +10,19 @@ describe('<App/>', function () {
|
||||
|
||||
it('renders title', () => {
|
||||
const wrapper = shallow(<App/>);
|
||||
expect(wrapper.find('.navbar-brand').text()).toBe('OpenMediaCenter');
|
||||
expect(wrapper.find('.navbrand').text()).toBe('OpenMediaCenter');
|
||||
});
|
||||
|
||||
it('are navlinks correct', function () {
|
||||
const wrapper = shallow(<App/>);
|
||||
expect(wrapper.find('nav').find('li')).toHaveLength(4);
|
||||
expect(wrapper.find('.navitem')).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('simulate video view change ', function () {
|
||||
const wrapper = shallow(<App/>);
|
||||
wrapper.setState({generalSettingsLoaded: true}); // simulate fetch to have already finisheed
|
||||
|
||||
wrapper.instance().changeRootElement(<div id='testit'></div>);
|
||||
wrapper.instance().changeRootElement(<div id='testit'/>);
|
||||
|
||||
expect(wrapper.find("#testit")).toHaveLength(1);
|
||||
});
|
||||
@ -31,7 +31,7 @@ describe('<App/>', function () {
|
||||
const wrapper = shallow(<App/>);
|
||||
wrapper.setState({generalSettingsLoaded: true}); // simulate fetch to have already finisheed
|
||||
|
||||
wrapper.instance().changeRootElement(<div id='testit'></div>);
|
||||
wrapper.instance().changeRootElement(<div id='testit'/>);
|
||||
|
||||
expect(wrapper.find("#testit")).toHaveLength(1);
|
||||
|
||||
@ -44,9 +44,9 @@ describe('<App/>', function () {
|
||||
const wrapper = shallow(<App/>);
|
||||
wrapper.setState({generalSettingsLoaded: true}); // simulate fetch to have already finisheed
|
||||
|
||||
wrapper.find(".nav-link").findWhere(t => t.text() === "Random Video" && t.type() === "div").simulate("click");
|
||||
wrapper.find(".navitem").findWhere(t => t.text() === "Random Video" && t.type() === "div").simulate("click");
|
||||
|
||||
wrapper.instance().changeRootElement(<div id='testit'></div>);
|
||||
wrapper.instance().changeRootElement(<div id='testit'/>);
|
||||
|
||||
expect(wrapper.find("#testit")).toHaveLength(1);
|
||||
|
||||
@ -61,7 +61,7 @@ describe('<App/>', function () {
|
||||
|
||||
wrapper.setState({page: "wrongvalue"});
|
||||
expect(wrapper.find("HomePage")).toHaveLength(0);
|
||||
wrapper.find(".nav-link").findWhere(t => t.text() === "Home" && t.type() === "div").simulate("click");
|
||||
wrapper.find(".navitem").findWhere(t => t.text() === "Home" && t.type() === "div").simulate("click");
|
||||
expect(wrapper.find("HomePage")).toHaveLength(1);
|
||||
});
|
||||
|
||||
@ -70,7 +70,7 @@ describe('<App/>', function () {
|
||||
wrapper.setState({generalSettingsLoaded: true}); // simulate fetch to have already finisheed
|
||||
|
||||
expect(wrapper.find("CategoryPage")).toHaveLength(0);
|
||||
wrapper.find(".nav-link").findWhere(t => t.text() === "Categories" && t.type() === "div").simulate("click");
|
||||
wrapper.find(".navitem").findWhere(t => t.text() === "Categories" && t.type() === "div").simulate("click");
|
||||
expect(wrapper.find("CategoryPage")).toHaveLength(1);
|
||||
});
|
||||
|
||||
@ -79,7 +79,7 @@ describe('<App/>', function () {
|
||||
wrapper.setState({generalSettingsLoaded: true}); // simulate fetch to have already finisheed
|
||||
|
||||
expect(wrapper.find("SettingsPage")).toHaveLength(0);
|
||||
wrapper.find(".nav-link").findWhere(t => t.text() === "Settings" && t.type() === "div").simulate("click");
|
||||
wrapper.find(".navitem").findWhere(t => t.text() === "Settings" && t.type() === "div").simulate("click");
|
||||
expect(wrapper.find("SettingsPage")).toHaveLength(1);
|
||||
});
|
||||
|
||||
|
40
src/AppDarkTheme.module.css
Normal file
40
src/AppDarkTheme.module.css
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* The coloring elements for dark theme
|
||||
*/
|
||||
|
||||
.backgroundcolor {
|
||||
background-color: #141520;
|
||||
}
|
||||
|
||||
.textcolor {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.subtextcolor {
|
||||
color: #dedad6;
|
||||
}
|
||||
|
||||
.lighttextcolor {
|
||||
color: #d5d5d5;
|
||||
}
|
||||
|
||||
.navitem::after {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.hrcolor {
|
||||
border-color: rgba(255, 255, 255, .1);
|
||||
}
|
||||
|
||||
.secbackground {
|
||||
background-color: #3c3d48;
|
||||
}
|
||||
|
||||
.thirdbackground {
|
||||
background-color: #141520;
|
||||
}
|
||||
|
||||
.preview:hover {
|
||||
box-shadow: rgba(255, 255, 255, 0.7) 0 0 0 5px;
|
||||
}
|
||||
|
39
src/AppLightTheme.module.css
Normal file
39
src/AppLightTheme.module.css
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* The coloring elements for light theme
|
||||
*/
|
||||
|
||||
.navitem::after {
|
||||
background: black;
|
||||
}
|
||||
|
||||
.backgroundcolor {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.textcolor {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.subtextcolor {
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
.lighttextcolor {
|
||||
color: #3d3d3d;
|
||||
}
|
||||
|
||||
.hrcolor {
|
||||
border-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.secbackground {
|
||||
background-color: #a8c3ff;
|
||||
}
|
||||
|
||||
.thirdbackground {
|
||||
background-color: #8ca3fc;
|
||||
}
|
||||
|
||||
.preview:hover {
|
||||
box-shadow: rgba(2, 12, 27, 0.7) 0 0 0 5px;
|
||||
}
|
23
src/GlobalInfos.js
Normal file
23
src/GlobalInfos.js
Normal file
@ -0,0 +1,23 @@
|
||||
import darktheme from "./AppDarkTheme.module.css";
|
||||
import lighttheme from "./AppLightTheme.module.css";
|
||||
|
||||
class StaticInfos {
|
||||
#darktheme = true;
|
||||
|
||||
isDarkTheme() {
|
||||
return this.#darktheme;
|
||||
};
|
||||
|
||||
enableDarkTheme(enable = true){
|
||||
this.#darktheme = enable;
|
||||
}
|
||||
|
||||
getThemeStyle(){
|
||||
return this.isDarkTheme() ? darktheme : lighttheme;
|
||||
}
|
||||
}
|
||||
|
||||
const GlobalInfos = new StaticInfos();
|
||||
//Object.freeze(StaticInfos);
|
||||
|
||||
export default GlobalInfos;
|
24
src/GlobalInfos.test.js
Normal file
24
src/GlobalInfos.test.js
Normal file
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
import GlobalInfos from "./GlobalInfos";
|
||||
|
||||
describe('<GlobalInfos/>', function () {
|
||||
it('always same instance ', function () {
|
||||
GlobalInfos.enableDarkTheme(true);
|
||||
|
||||
expect(GlobalInfos.isDarkTheme()).toBe(true);
|
||||
|
||||
GlobalInfos.enableDarkTheme(false);
|
||||
|
||||
expect(GlobalInfos.isDarkTheme()).toBe(false);
|
||||
});
|
||||
|
||||
it('test default theme', function () {
|
||||
expect(GlobalInfos.isDarkTheme()).toBe(false);
|
||||
});
|
||||
|
||||
it('test receive of stylesheet', function () {
|
||||
const style = GlobalInfos.getThemeStyle();
|
||||
|
||||
expect(style.navitem).not.toBeNull();
|
||||
});
|
||||
});
|
@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import style from "./PageTitle.module.css"
|
||||
import GlobalInfos from "../../GlobalInfos";
|
||||
|
||||
class PageTitle extends React.Component {
|
||||
constructor(props) {
|
||||
@ -10,17 +11,33 @@ class PageTitle extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<div className={style.pageheader}>
|
||||
<span className={style.pageheadertitle}>{this.props.title}</span>
|
||||
<span className={style.pageheadersubtitle}>{this.props.subtitle}</span>
|
||||
<div className={style.pageheader + ' ' + themeStyle.backgroundcolor}>
|
||||
<span className={style.pageheadertitle + ' ' + themeStyle.textcolor}>{this.props.title}</span>
|
||||
<span className={style.pageheadersubtitle + ' ' + themeStyle.textcolor}>{this.props.subtitle}</span>
|
||||
<>
|
||||
{this.props.children}
|
||||
</>
|
||||
<hr/>
|
||||
<Line/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* class to override default <hr> color and styling
|
||||
* use this for horizontal lines to use the current active theming
|
||||
*/
|
||||
export class Line extends React.Component {
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<>
|
||||
<hr className={themeStyle.hrcolor}/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PageTitle;
|
@ -1,8 +1,5 @@
|
||||
.pageheader {
|
||||
margin-bottom: 20px;
|
||||
margin-top: 20px;
|
||||
padding-left: 22%;
|
||||
padding-right: 12%;
|
||||
padding: 20px 12% 20px 22%;
|
||||
}
|
||||
|
||||
.pageheadertitle {
|
||||
@ -11,7 +8,7 @@
|
||||
}
|
||||
|
||||
.pageheadersubtitle {
|
||||
font-size: 23pt;
|
||||
margin-left: 20px;
|
||||
font-size: 23pt;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ describe('<Preview/>', function () {
|
||||
it('renders pagetitle prop', function () {
|
||||
const wrapper = shallow(<PageTitle title='testtitle'/>);
|
||||
|
||||
expect(wrapper.find(".pageheader").text()).toBe("testtitle");
|
||||
expect(wrapper.find(".pageheader").text()).toBe("testtitle<Line />");
|
||||
});
|
||||
|
||||
it('renders subtitle prop', function () {
|
||||
|
@ -2,6 +2,7 @@ import React from "react";
|
||||
import style from "./Preview.module.css";
|
||||
import Player from "../../pages/Player/Player";
|
||||
import {Spinner} from "react-bootstrap";
|
||||
import GlobalInfos from "../../GlobalInfos";
|
||||
|
||||
class Preview extends React.Component {
|
||||
constructor(props, context) {
|
||||
@ -33,9 +34,10 @@ class Preview extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<div className={style.videopreview} onClick={() => this.itemClick()}>
|
||||
<div className={style.previewtitle}>{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}
|
||||
@ -63,9 +65,10 @@ class Preview extends React.Component {
|
||||
|
||||
export class TagPreview extends React.Component {
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<div className={style.videopreview + ' ' + style.tagpreview} onClick={() => this.itemClick()}>
|
||||
<div className={style.tagpreviewtitle}>
|
||||
<div className={style.videopreview + ' ' + style.tagpreview + ' ' + themeStyle.secbackground + ' '+ themeStyle.preview} onClick={() => this.itemClick()}>
|
||||
<div className={style.tagpreviewtitle + ' ' + themeStyle.lighttextcolor}>
|
||||
{this.props.name}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,6 @@
|
||||
.previewtitle {
|
||||
color: #3d3d3d;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
font-size: smaller;
|
||||
font-weight: bold;
|
||||
height: 20px;
|
||||
@ -33,10 +34,8 @@
|
||||
}
|
||||
|
||||
.videopreview {
|
||||
background-color: #a8c3ff;
|
||||
border-radius: 20px;
|
||||
cursor: pointer;
|
||||
/*background-color: #7F7F7F;*/
|
||||
float: left;
|
||||
margin-left: 25px;
|
||||
margin-top: 25px;
|
||||
@ -44,7 +43,6 @@
|
||||
}
|
||||
|
||||
.videopreview:hover {
|
||||
box-shadow: rgba(2, 12, 27, 0.7) 0 0 0 5px;
|
||||
opacity: 1;
|
||||
transition: all 300ms;
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
import React from "react";
|
||||
import style from "./SideBar.module.css"
|
||||
import GlobalInfos from "../../GlobalInfos";
|
||||
|
||||
class SideBar extends React.Component {
|
||||
render() {
|
||||
return (<div className={style.sideinfo}>
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (<div className={style.sideinfo + ' '+ themeStyle.secbackground}>
|
||||
{this.props.children}
|
||||
</div>);
|
||||
}
|
||||
@ -11,16 +13,18 @@ class SideBar extends React.Component {
|
||||
|
||||
export class SideBarTitle extends React.Component {
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<div className={style.sidebartitle}>{this.props.children}</div>
|
||||
<div className={style.sidebartitle + ' '+ themeStyle.subtextcolor}>{this.props.children}</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class SideBarItem extends React.Component {
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<div className={style.sidebarinfo}>{this.props.children}</div>
|
||||
<div className={style.sidebarinfo + ' ' + themeStyle.thirdbackground + ' ' + themeStyle.lighttextcolor}>{this.props.children}</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
.sideinfo {
|
||||
background-color: #b4c7fe;
|
||||
border: 2px #3574fe solid;
|
||||
border-radius: 20px;
|
||||
float: left;
|
||||
@ -16,7 +15,6 @@
|
||||
}
|
||||
|
||||
.sidebarinfo {
|
||||
background-color: #8ca3fc;
|
||||
border-radius: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 2px 10px 2px 15px;
|
||||
|
@ -1,8 +0,0 @@
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
margin: 0;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -5,7 +5,7 @@ import videocontainerstyle from "../../elements/VideoContainer/VideoContainer.mo
|
||||
|
||||
import {TagPreview} from "../../elements/Preview/Preview";
|
||||
import NewTagPopup from "../../elements/NewTagPopup/NewTagPopup";
|
||||
import PageTitle from "../../elements/PageTitle/PageTitle";
|
||||
import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
|
||||
import VideoContainer from "../../elements/VideoContainer/VideoContainer";
|
||||
|
||||
class CategoryPage extends React.Component {
|
||||
@ -56,7 +56,7 @@ class CategoryPage extends React.Component {
|
||||
this.loadTag(e.props.category)
|
||||
}
|
||||
}}>HD</Tag>
|
||||
<hr/>
|
||||
<Line/>
|
||||
<button data-testid='btnaddtag' className='btn btn-success' onClick={() => {
|
||||
this.setState({popupvisible: true})
|
||||
}}>Add a new Tag!
|
||||
|
@ -4,7 +4,7 @@ import Tag from "../../elements/Tag/Tag";
|
||||
import VideoContainer from "../../elements/VideoContainer/VideoContainer";
|
||||
|
||||
import style from "./HomePage.module.css"
|
||||
import PageTitle from "../../elements/PageTitle/PageTitle";
|
||||
import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
|
||||
|
||||
class HomePage extends React.Component {
|
||||
/** keyword variable needed temporary store search keyword */
|
||||
@ -138,13 +138,13 @@ class HomePage extends React.Component {
|
||||
</PageTitle>
|
||||
<SideBar>
|
||||
<SideBarTitle>Infos:</SideBarTitle>
|
||||
<hr/>
|
||||
<Line/>
|
||||
<SideBarItem><b>{this.state.sideinfo.videonr}</b> Videos Total!</SideBarItem>
|
||||
<SideBarItem><b>{this.state.sideinfo.fullhdvideonr}</b> FULL-HD Videos!</SideBarItem>
|
||||
<SideBarItem><b>{this.state.sideinfo.hdvideonr}</b> HD Videos!</SideBarItem>
|
||||
<SideBarItem><b>{this.state.sideinfo.sdvideonr}</b> SD Videos!</SideBarItem>
|
||||
<SideBarItem><b>{this.state.sideinfo.tagnr}</b> different Tags!</SideBarItem>
|
||||
<hr/>
|
||||
<Line/>
|
||||
<SideBarTitle>Default Tags:</SideBarTitle>
|
||||
<Tag viewbinding={this.props.viewbinding}>All</Tag>
|
||||
<Tag viewbinding={this.props.viewbinding}>FullHd</Tag>
|
||||
|
@ -1,10 +1,11 @@
|
||||
import React from "react";
|
||||
import style from "./Player.module.css"
|
||||
|
||||
import {PlyrComponent} from 'plyr-react';
|
||||
import SideBar, {SideBarItem, SideBarTitle} from "../../elements/SideBar/SideBar";
|
||||
import Tag from "../../elements/Tag/Tag";
|
||||
import AddTagPopup from "../../elements/AddTagPopup/AddTagPopup";
|
||||
import PageTitle from "../../elements/PageTitle/PageTitle";
|
||||
import PageTitle, {Line} from "../../elements/PageTitle/PageTitle";
|
||||
|
||||
|
||||
class Player extends React.Component {
|
||||
@ -53,14 +54,13 @@ class Player extends React.Component {
|
||||
|
||||
<SideBar>
|
||||
<SideBarTitle>Infos:</SideBarTitle>
|
||||
<hr/>
|
||||
<Line/>
|
||||
<SideBarItem><b>{this.state.likes}</b> Likes!</SideBarItem>
|
||||
{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}
|
||||
<hr/>
|
||||
<SideBarItem><b>{Math.round(this.state.length / 60)}</b> Minutes of length!</SideBarItem>: null}
|
||||
<Line/>
|
||||
<SideBarTitle>Tags:</SideBarTitle>
|
||||
{this.state.tags.map((m) => (
|
||||
<Tag
|
||||
|
@ -14,6 +14,7 @@
|
||||
margin-left: 20px;
|
||||
margin-top: 25px;
|
||||
width: 60%;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.videoactions {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
import {Button, Col, Form} from "react-bootstrap";
|
||||
import style from "./GeneralSettings.module.css"
|
||||
import GlobalInfos from "../../GlobalInfos";
|
||||
|
||||
class GeneralSettings extends React.Component {
|
||||
constructor(props) {
|
||||
@ -37,9 +38,10 @@ class GeneralSettings extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<>
|
||||
<div className={style.GeneralForm}>
|
||||
<div className={style.GeneralForm + ' ' + themeStyle.subtextcolor}>
|
||||
<Form data-testid='mainformsettings' onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
this.saveSettings();
|
||||
@ -70,6 +72,14 @@ class GeneralSettings extends React.Component {
|
||||
}}
|
||||
/>
|
||||
|
||||
{this.state.passwordsupport ?
|
||||
<Form.Group data-testid="passwordfield">
|
||||
<Form.Label>Password</Form.Label>
|
||||
<Form.Control type="password" placeholder="**********" value={this.state.password}
|
||||
onChange={(e) => this.setState({password: e.target.value})}/>
|
||||
</Form.Group> : null
|
||||
}
|
||||
|
||||
<Form.Check
|
||||
type="switch"
|
||||
id="custom-switch-2"
|
||||
@ -81,13 +91,18 @@ class GeneralSettings extends React.Component {
|
||||
}}
|
||||
/>
|
||||
|
||||
{this.state.passwordsupport ?
|
||||
<Form.Group data-testid="passwordfield">
|
||||
<Form.Label>Password</Form.Label>
|
||||
<Form.Control type="password" placeholder="**********" value={this.state.password}
|
||||
onChange={(e) => this.setState({password: e.target.value})}/>
|
||||
</Form.Group> : null
|
||||
}
|
||||
<Form.Check
|
||||
type="switch"
|
||||
id="custom-switch-3"
|
||||
data-testid='darktheme-switch'
|
||||
label="Enable Dark-Theme"
|
||||
checked={GlobalInfos.isDarkTheme()}
|
||||
onChange={() => {
|
||||
GlobalInfos.enableDarkTheme(!GlobalInfos.isDarkTheme());
|
||||
this.forceUpdate();
|
||||
// todo initiate rerender
|
||||
}}
|
||||
/>
|
||||
|
||||
<Form.Group className={style.mediacenternameform} data-testid="nameform">
|
||||
<Form.Label>The name of the Mediacenter</Form.Label>
|
||||
@ -113,6 +128,7 @@ class GeneralSettings extends React.Component {
|
||||
updateRequest.append('tvshowpath', this.state.tvshowpath);
|
||||
updateRequest.append('mediacentername', this.state.mediacentername);
|
||||
updateRequest.append("tmdbsupport", this.state.tmdbsupport);
|
||||
updateRequest.append("darkmodeenabled", GlobalInfos.isDarkTheme());
|
||||
|
||||
fetch('/api/Settings.php', {method: 'POST', body: updateRequest})
|
||||
.then((response) => response.json()
|
||||
|
@ -1,6 +1,7 @@
|
||||
import {shallow} from "enzyme";
|
||||
import React from "react";
|
||||
import GeneralSettings from "./GeneralSettings";
|
||||
import GlobalInfos from "../../GlobalInfos";
|
||||
|
||||
describe('<GeneralSettings/>', function () {
|
||||
it('renders without crashing ', function () {
|
||||
@ -17,6 +18,15 @@ describe('<GeneralSettings/>', function () {
|
||||
expect(wrapper.find("[data-testid='passwordfield']")).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('test theme switchbutton', function () {
|
||||
const wrapper = shallow(<GeneralSettings/>);
|
||||
|
||||
GlobalInfos.enableDarkTheme(false);
|
||||
expect(GlobalInfos.isDarkTheme()).toBe(false);
|
||||
wrapper.find("[data-testid='darktheme-switch']").simulate("change");
|
||||
expect(GlobalInfos.isDarkTheme()).toBe(true);
|
||||
});
|
||||
|
||||
it('test savesettings', done => {
|
||||
const wrapper = shallow(<GeneralSettings/>);
|
||||
|
||||
|
@ -2,6 +2,7 @@ import React from "react";
|
||||
import MovieSettings from "./MovieSettings";
|
||||
import GeneralSettings from "./GeneralSettings";
|
||||
import style from "./SettingsPage.module.css"
|
||||
import GlobalInfos from "../../GlobalInfos";
|
||||
|
||||
|
||||
class SettingsPage extends React.Component {
|
||||
@ -27,10 +28,11 @@ class SettingsPage extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const themestyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<div>
|
||||
<div className={style.SettingsSidebar}>
|
||||
<div className={style.SettingsSidebarTitle}>Settings</div>
|
||||
<div className={style.SettingsSidebar + ' ' + themestyle.secbackground}>
|
||||
<div className={style.SettingsSidebarTitle + ' ' + themestyle.lighttextcolor}>Settings</div>
|
||||
<div onClick={() => this.setState({currentpage: "general"})}
|
||||
className={style.SettingSidebarElement}>General
|
||||
</div>
|
||||
|
@ -1,7 +1,8 @@
|
||||
.SettingsSidebar {
|
||||
background-color: #d3dcef;
|
||||
border-bottom-right-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
float: left;
|
||||
min-height: calc(100vh - 56px);
|
||||
min-height: calc(100vh - 62px);
|
||||
min-width: 110px;
|
||||
padding-top: 20px;
|
||||
width: 10%;
|
||||
@ -23,7 +24,7 @@
|
||||
}
|
||||
|
||||
.SettingSidebarElement {
|
||||
background-color: #a8b2de;
|
||||
background-color: #919fd9;
|
||||
border-radius: 7px;
|
||||
font-weight: bold;
|
||||
margin: 10px 5px 5px;
|
||||
|
Loading…
Reference in New Issue
Block a user