Merge branch 'settingsinfobar' into 'master'
add new InfoHeader on settingspage with general infos about database and items See merge request lukas/openmediacenter!18
This commit is contained in:
commit
ee073c0dab
@ -1,4 +1,43 @@
|
|||||||
version: "2"
|
version: "2"
|
||||||
|
plugins:
|
||||||
|
csslint:
|
||||||
|
enabled: true
|
||||||
|
coffeelint:
|
||||||
|
enabled: true
|
||||||
|
duplication:
|
||||||
|
enabled: true
|
||||||
|
config:
|
||||||
|
languages:
|
||||||
|
- ruby
|
||||||
|
- javascript
|
||||||
|
- python
|
||||||
|
- php
|
||||||
|
eslint:
|
||||||
|
enabled: true
|
||||||
|
channel: __ESLINT_CHANNEL__
|
||||||
|
fixme:
|
||||||
|
enabled: true
|
||||||
|
rubocop:
|
||||||
|
enabled: true
|
||||||
|
exclude_patterns:
|
||||||
|
- config/
|
||||||
|
- db/
|
||||||
|
- dist/
|
||||||
|
- features/
|
||||||
|
- "**/node_modules/"
|
||||||
|
- script/
|
||||||
|
- "**/spec/"
|
||||||
|
- "**/test/"
|
||||||
|
- "**/tests/"
|
||||||
|
- Tests/
|
||||||
|
- "**/vendor/"
|
||||||
|
- "**/*_test.go"
|
||||||
|
- "**/*.d.ts"
|
||||||
|
- "**/*.min.js"
|
||||||
|
- "**/*.min.css"
|
||||||
|
- "**/__tests__/"
|
||||||
|
- "**/__mocks__/"
|
||||||
|
- "**/*.test.js"
|
||||||
checks:
|
checks:
|
||||||
argument-count:
|
argument-count:
|
||||||
config:
|
config:
|
||||||
|
@ -21,6 +21,7 @@ prepare:
|
|||||||
stage: prepare
|
stage: prepare
|
||||||
script:
|
script:
|
||||||
- npm install --progress=false
|
- npm install --progress=false
|
||||||
|
- npm update --progress=false
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
|
@ -14,12 +14,35 @@ class Settings extends RequestBase {
|
|||||||
/**
|
/**
|
||||||
* handle settings stuff to load from db
|
* handle settings stuff to load from db
|
||||||
*/
|
*/
|
||||||
private function getFromDB(){
|
private function getFromDB() {
|
||||||
/**
|
/**
|
||||||
* load currently set settings form db for init of settings page
|
* load currently set settings form db for init of settings page
|
||||||
*/
|
*/
|
||||||
$this->addActionHandler("loadGeneralSettings", function () {
|
$this->addActionHandler("loadGeneralSettings", function () {
|
||||||
$query = "SELECT * from settings";
|
// query settings and infotile values
|
||||||
|
$query = "
|
||||||
|
SELECT (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM videos
|
||||||
|
) AS videonr,
|
||||||
|
(
|
||||||
|
SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS Size
|
||||||
|
FROM information_schema.TABLES
|
||||||
|
WHERE TABLE_SCHEMA = '" . Database::getInstance()->getDatabaseName() . "'
|
||||||
|
GROUP BY table_schema
|
||||||
|
) AS dbsize,
|
||||||
|
(
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM tags
|
||||||
|
) AS difftagnr,
|
||||||
|
(
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM video_tags
|
||||||
|
) AS tagsadded,
|
||||||
|
settings.*
|
||||||
|
FROM settings
|
||||||
|
LIMIT 1
|
||||||
|
";
|
||||||
|
|
||||||
$result = $this->conn->query($query);
|
$result = $this->conn->query($query);
|
||||||
|
|
||||||
@ -51,7 +74,7 @@ class Settings extends RequestBase {
|
|||||||
/**
|
/**
|
||||||
* handle setting stuff to save to db
|
* handle setting stuff to save to db
|
||||||
*/
|
*/
|
||||||
private function saveToDB(){
|
private function saveToDB() {
|
||||||
/**
|
/**
|
||||||
* save changed settings to db
|
* save changed settings to db
|
||||||
*/
|
*/
|
||||||
|
16
package.json
16
package.json
@ -3,12 +3,16 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap": "^4.5.0",
|
"@fortawesome/fontawesome-svg-core": "^1.2.30",
|
||||||
|
"@fortawesome/free-regular-svg-icons": "^5.15.1",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^5.15.1",
|
||||||
|
"@fortawesome/react-fontawesome": "^0.1.11",
|
||||||
|
"bootstrap": "^4.5.3",
|
||||||
"plyr-react": "^2.2.0",
|
"plyr-react": "^2.2.0",
|
||||||
"react": "^16.13.1",
|
"react": "^16.14.0",
|
||||||
"react-bootstrap": "^1.0.1",
|
"react-bootstrap": "^1.3.0",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.14.0",
|
||||||
"react-scripts": "^3.4.1"
|
"react-scripts": "^3.4.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
@ -49,7 +53,7 @@
|
|||||||
"@testing-library/react": "^9.5.0",
|
"@testing-library/react": "^9.5.0",
|
||||||
"@testing-library/user-event": "^7.2.1",
|
"@testing-library/user-event": "^7.2.1",
|
||||||
"enzyme": "^3.11.0",
|
"enzyme": "^3.11.0",
|
||||||
"enzyme-adapter-react-16": "^1.15.2",
|
"enzyme-adapter-react-16": "^1.15.5",
|
||||||
"jest-junit": "^10.0.0"
|
"jest-junit": "^10.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.navcontainer {
|
.navcontainer {
|
||||||
border-bottom-width: 2px;
|
border-width: 0 0 2px 0;
|
||||||
border-style: dotted;
|
border-style: dotted;
|
||||||
border-width: 0;
|
|
||||||
|
|
||||||
padding-bottom: 40px;
|
padding-bottom: 40px;
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
|
@ -39,7 +39,7 @@ describe('<AddTagPopup/>', function () {
|
|||||||
global.fetch = prepareFetchApi({result: "success"});
|
global.fetch = prepareFetchApi({result: "success"});
|
||||||
|
|
||||||
wrapper.setProps({
|
wrapper.setProps({
|
||||||
submit: jest.fn((arg1, arg2) => {}),
|
submit: jest.fn(() => {}),
|
||||||
onHide: jest.fn()
|
onHide: jest.fn()
|
||||||
}, () => {
|
}, () => {
|
||||||
wrapper.instance().addTag(1, "test");
|
wrapper.instance().addTag(1, "test");
|
||||||
@ -62,7 +62,7 @@ describe('<AddTagPopup/>', function () {
|
|||||||
global.fetch = prepareFetchApi({result: "fail"});
|
global.fetch = prepareFetchApi({result: "fail"});
|
||||||
|
|
||||||
wrapper.setProps({
|
wrapper.setProps({
|
||||||
submit: jest.fn((arg1, arg2) => {}),
|
submit: jest.fn(() => {}),
|
||||||
onHide: jest.fn()
|
onHide: jest.fn()
|
||||||
}, () => {
|
}, () => {
|
||||||
wrapper.instance().addTag(1, "test");
|
wrapper.instance().addTag(1, "test");
|
||||||
|
34
src/elements/InfoHeaderItem/InfoHeaderItem.js
Normal file
34
src/elements/InfoHeaderItem/InfoHeaderItem.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import React from "react";
|
||||||
|
import style from './InfoHeaderItem.module.css';
|
||||||
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
|
import {Spinner} from "react-bootstrap";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* a component to display one of the short quickinfo tiles on dashboard
|
||||||
|
*/
|
||||||
|
class InfoHeaderItem extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div onClick={() => {
|
||||||
|
// call clicklistener if defined
|
||||||
|
if (this.props.onClick != null) this.props.onClick();
|
||||||
|
}} className={style.infoheaderitem} style={{backgroundColor: this.props.backColor}}>
|
||||||
|
<div className={style.icon}>
|
||||||
|
<FontAwesomeIcon style={{
|
||||||
|
verticalAlign: "middle",
|
||||||
|
lineHeight: "130px"
|
||||||
|
}} icon={this.props.icon} size='5x'/>
|
||||||
|
</div>
|
||||||
|
{this.props.text !== null && this.props.text !== undefined ?
|
||||||
|
<>
|
||||||
|
<div className={style.maintext}>{this.props.text}</div>
|
||||||
|
<div className={style.subtext}>{this.props.subtext}</div>
|
||||||
|
</>
|
||||||
|
: <span className={style.loadAnimation}><Spinner animation='border'/></span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InfoHeaderItem;
|
58
src/elements/InfoHeaderItem/InfoHeaderItem.module.css
Normal file
58
src/elements/InfoHeaderItem/InfoHeaderItem.module.css
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* styling for tile */
|
||||||
|
.infoheaderitem {
|
||||||
|
background-color: lightblue;
|
||||||
|
border-radius: 5px;
|
||||||
|
flex: calc(25% - 10px);
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On screens that are 1317px wide or less, go from four columns to two columns */
|
||||||
|
@media screen and (max-width: 1317px) {
|
||||||
|
.infoheaderitem {
|
||||||
|
flex: calc(50% - 10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* change opacity of icon when hovering whole tile */
|
||||||
|
.infoheaderitem:hover .icon {
|
||||||
|
opacity: 0.75;
|
||||||
|
transition: opacity linear 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* change cursor on hover */
|
||||||
|
.infoheaderitem:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
float: left;
|
||||||
|
height: 130px;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 17px;
|
||||||
|
margin-top: 20px;
|
||||||
|
opacity: 0.5;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* big main text in tile */
|
||||||
|
.maintext {
|
||||||
|
font-size: x-large;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* small subtext in tile */
|
||||||
|
.subtext {
|
||||||
|
font-size: large;
|
||||||
|
margin-top: 5px;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loadAnimation {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 145px;
|
||||||
|
margin-left: calc(25% - 15px);
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
43
src/elements/InfoHeaderItem/InfoHeaderItem.test.js
Normal file
43
src/elements/InfoHeaderItem/InfoHeaderItem.test.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import {shallow} from "enzyme";
|
||||||
|
import React from "react";
|
||||||
|
import InfoHeaderItem from "./InfoHeaderItem";
|
||||||
|
|
||||||
|
describe('<InfoHeaderItem/>', function () {
|
||||||
|
it('renders without crashing ', function () {
|
||||||
|
const wrapper = shallow(<InfoHeaderItem/>);
|
||||||
|
wrapper.unmount();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders correct text', function () {
|
||||||
|
const wrapper = shallow(<InfoHeaderItem text='mytext'/>);
|
||||||
|
expect(wrapper.find(".maintext").text()).toBe("mytext");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders correct subtext', function () {
|
||||||
|
const wrapper = shallow(<InfoHeaderItem text='mimi' subtext='testtext'/>);
|
||||||
|
expect(wrapper.find(".subtext").text()).toBe("testtext");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test no subtext if no text defined', function () {
|
||||||
|
const wrapper = shallow(<InfoHeaderItem subtext='testi'/>);
|
||||||
|
expect(wrapper.find(".subtext")).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test custom click handler', function () {
|
||||||
|
const func = jest.fn();
|
||||||
|
const wrapper = shallow(<InfoHeaderItem onClick={() => func()}/>);
|
||||||
|
expect(func).toBeCalledTimes(0);
|
||||||
|
wrapper.simulate("click");
|
||||||
|
expect(func).toBeCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test insertion of loading spinner', function () {
|
||||||
|
const wrapper = shallow(<InfoHeaderItem text={null}/>);
|
||||||
|
expect(wrapper.find("Spinner").length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('test loading spinner if undefined', function () {
|
||||||
|
const wrapper = shallow(<InfoHeaderItem/>);
|
||||||
|
expect(wrapper.find("Spinner").length).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
@ -18,21 +18,21 @@ class NewTagPopup extends React.Component {
|
|||||||
<Modal
|
<Modal
|
||||||
show={this.props.show}
|
show={this.props.show}
|
||||||
onHide={this.props.onHide}
|
onHide={this.props.onHide}
|
||||||
size="lg"
|
size='lg'
|
||||||
aria-labelledby="contained-modal-title-vcenter"
|
aria-labelledby='contained-modal-title-vcenter'
|
||||||
centered>
|
centered>
|
||||||
<Modal.Header closeButton>
|
<Modal.Header closeButton>
|
||||||
<Modal.Title id="contained-modal-title-vcenter">
|
<Modal.Title id='contained-modal-title-vcenter'>
|
||||||
Create a new Tag!
|
Create a new Tag!
|
||||||
</Modal.Title>
|
</Modal.Title>
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
<Form.Group>
|
<Form.Group>
|
||||||
<Form.Label>Tag Name:</Form.Label>
|
<Form.Label>Tag Name:</Form.Label>
|
||||||
<Form.Control id='namefield' type="text" placeholder="Enter Tag name" onChange={(v) => {
|
<Form.Control id='namefield' type='text' placeholder='Enter Tag name' onChange={(v) => {
|
||||||
this.value = v.target.value
|
this.value = v.target.value
|
||||||
}}/>
|
}}/>
|
||||||
<Form.Text className="text-muted">
|
<Form.Text className='text-muted'>
|
||||||
This Tag will automatically show up on category page.
|
This Tag will automatically show up on category page.
|
||||||
</Form.Text>
|
</Form.Text>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
@ -48,7 +48,7 @@ class Preview extends React.Component {
|
|||||||
<img className={style.previewimage}
|
<img className={style.previewimage}
|
||||||
src={this.state.previewpicture}
|
src={this.state.previewpicture}
|
||||||
alt='Pic loading.'/> :
|
alt='Pic loading.'/> :
|
||||||
<span className={style.loadAnimation}><Spinner animation="border"/></span>}
|
<span className={style.loadAnimation}><Spinner animation='border'/></span>}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className={style.previewbottom}>
|
<div className={style.previewbottom}>
|
||||||
|
@ -10,7 +10,7 @@ class Tag extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<button className={styles.tagbtn} onClick={() => this.TagClick()}
|
<button className={styles.tagbtn} onClick={() => this.TagClick()}
|
||||||
data-testid="Test-Tag">{this.props.children}</button>
|
data-testid='Test-Tag'>{this.props.children}</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ class CategoryPage extends React.Component {
|
|||||||
<VideoContainer
|
<VideoContainer
|
||||||
data={this.videodata}
|
data={this.videodata}
|
||||||
viewbinding={this.props.viewbinding}/> : null}
|
viewbinding={this.props.viewbinding}/> : null}
|
||||||
<button data-testid='backbtn' className="btn btn-success"
|
<button data-testid='backbtn' className='btn btn-success'
|
||||||
onClick={this.loadCategoryPageDefault}>Back
|
onClick={this.loadCategoryPageDefault}>Back
|
||||||
</button>
|
</button>
|
||||||
</> :
|
</> :
|
||||||
|
@ -98,7 +98,7 @@ describe('<CategoryPage/>', function () {
|
|||||||
const func = jest.fn();
|
const func = jest.fn();
|
||||||
CategoryPage.prototype.fetchVideoData = func;
|
CategoryPage.prototype.fetchVideoData = func;
|
||||||
|
|
||||||
shallow(<CategoryPage category="fullhd"/>);
|
shallow(<CategoryPage category='fullhd'/>);
|
||||||
|
|
||||||
expect(func).toBeCalledTimes(1);
|
expect(func).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
@ -106,7 +106,7 @@ describe('<CategoryPage/>', function () {
|
|||||||
it('test sidebar tag clicks', function () {
|
it('test sidebar tag clicks', function () {
|
||||||
const func = jest.fn();
|
const func = jest.fn();
|
||||||
|
|
||||||
const wrapper = mount(<CategoryPage category="fullhd"/>);
|
const wrapper = mount(<CategoryPage category='fullhd'/>);
|
||||||
wrapper.instance().loadTag = func;
|
wrapper.instance().loadTag = func;
|
||||||
|
|
||||||
console.log(wrapper.debug());
|
console.log(wrapper.debug());
|
||||||
|
@ -131,12 +131,12 @@ class HomePage extends React.Component {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.searchVideos(this.keyword);
|
this.searchVideos(this.keyword);
|
||||||
}}>
|
}}>
|
||||||
<input data-testid='searchtextfield' className="form-control mr-sm-2"
|
<input data-testid='searchtextfield' className='form-control mr-sm-2'
|
||||||
type="text" placeholder="Search"
|
type='text' placeholder='Search'
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
this.keyword = e.target.value
|
this.keyword = e.target.value
|
||||||
}}/>
|
}}/>
|
||||||
<button data-testid='searchbtnsubmit' className="btn btn-success" type="submit">Search</button>
|
<button data-testid='searchbtnsubmit' className='btn btn-success' type='submit'>Search</button>
|
||||||
</form>
|
</form>
|
||||||
</PageTitle>
|
</PageTitle>
|
||||||
<SideBar>
|
<SideBar>
|
||||||
|
@ -167,8 +167,10 @@ class Player extends React.Component {
|
|||||||
<div>not loaded yet</div>}
|
<div>not loaded yet</div>}
|
||||||
<div className={style.videoactions}>
|
<div className={style.videoactions}>
|
||||||
<button className='btn btn-primary' onClick={() => this.likebtn()}>Like this Video!</button>
|
<button className='btn btn-primary' onClick={() => this.likebtn()}>Like this Video!</button>
|
||||||
<button className='btn btn-info' onClick={() => this.setState({popupvisible: true})}>Give this Video a Tag</button>
|
<button className='btn btn-info' onClick={() => this.setState({popupvisible: true})}>Give this
|
||||||
<button className='btn btn-danger' onClick={() =>{this.deleteVideo()}}>Delete Video</button>
|
Video a Tag
|
||||||
|
</button>
|
||||||
|
<button className='btn btn-danger' onClick={() => {this.deleteVideo()}}>Delete Video</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button className={style.closebutton} onClick={() => this.closebtn()}>Close</button>
|
<button className={style.closebutton} onClick={() => this.closebtn()}>Close</button>
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
margin-top: 25px;
|
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
width: 60%;
|
width: 60%;
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,7 @@ class RandomPage extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<PageTitle
|
<PageTitle title='Random Videos'
|
||||||
title='Random Videos'
|
|
||||||
subtitle='4pc'/>
|
subtitle='4pc'/>
|
||||||
|
|
||||||
<SideBar>
|
<SideBar>
|
||||||
|
@ -2,6 +2,9 @@ import React from "react";
|
|||||||
import {Button, Col, Form} from "react-bootstrap";
|
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";
|
||||||
|
import InfoHeaderItem from "../../elements/InfoHeaderItem/InfoHeaderItem";
|
||||||
|
import {faArchive, faBalanceScaleLeft, faRulerVertical} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import {faAddressCard} from "@fortawesome/free-regular-svg-icons";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component for Generalsettings tag on Settingspage
|
* Component for Generalsettings tag on Settingspage
|
||||||
@ -18,7 +21,12 @@ class GeneralSettings extends React.Component {
|
|||||||
videopath: "",
|
videopath: "",
|
||||||
tvshowpath: "",
|
tvshowpath: "",
|
||||||
mediacentername: "",
|
mediacentername: "",
|
||||||
password: ""
|
password: "",
|
||||||
|
|
||||||
|
videonr: null,
|
||||||
|
dbsize: null,
|
||||||
|
difftagnr: null,
|
||||||
|
tagsadded: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,31 +38,49 @@ class GeneralSettings extends React.Component {
|
|||||||
const themeStyle = GlobalInfos.getThemeStyle();
|
const themeStyle = GlobalInfos.getThemeStyle();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div className={style.infoheader}>
|
||||||
|
<InfoHeaderItem backColor='lightblue'
|
||||||
|
text={this.state.videonr}
|
||||||
|
subtext='Videos in Gravity'
|
||||||
|
icon={faArchive}/>
|
||||||
|
<InfoHeaderItem backColor='yellow'
|
||||||
|
text={this.state.dbsize !== undefined ? this.state.dbsize + " MB" : undefined}
|
||||||
|
subtext='Database size'
|
||||||
|
icon={faRulerVertical}/>
|
||||||
|
<InfoHeaderItem backColor='green'
|
||||||
|
text={this.state.difftagnr}
|
||||||
|
subtext='different Tags'
|
||||||
|
icon={faAddressCard}/>
|
||||||
|
<InfoHeaderItem backColor='orange'
|
||||||
|
text={this.state.tagsadded}
|
||||||
|
subtext='tags added'
|
||||||
|
icon={faBalanceScaleLeft}/>
|
||||||
|
</div>
|
||||||
<div className={style.GeneralForm + ' ' + themeStyle.subtextcolor}>
|
<div className={style.GeneralForm + ' ' + themeStyle.subtextcolor}>
|
||||||
<Form data-testid='mainformsettings' onSubmit={(e) => {
|
<Form data-testid='mainformsettings' onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.saveSettings();
|
this.saveSettings();
|
||||||
}}>
|
}}>
|
||||||
<Form.Row>
|
<Form.Row>
|
||||||
<Form.Group as={Col} data-testid="videpathform">
|
<Form.Group as={Col} data-testid='videpathform'>
|
||||||
<Form.Label>Video Path</Form.Label>
|
<Form.Label>Video Path</Form.Label>
|
||||||
<Form.Control type="text" placeholder="/var/www/html/video" value={this.state.videopath}
|
<Form.Control type='text' placeholder='/var/www/html/video' value={this.state.videopath}
|
||||||
onChange={(ee) => this.setState({videopath: ee.target.value})}/>
|
onChange={(ee) => this.setState({videopath: ee.target.value})}/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<Form.Group as={Col} data-testid="tvshowpath">
|
<Form.Group as={Col} data-testid='tvshowpath'>
|
||||||
<Form.Label>TV Show Path</Form.Label>
|
<Form.Label>TV Show Path</Form.Label>
|
||||||
<Form.Control type='text' placeholder="/var/www/html/tvshow"
|
<Form.Control type='text' placeholder='/var/www/html/tvshow'
|
||||||
value={this.state.tvshowpath}
|
value={this.state.tvshowpath}
|
||||||
onChange={(e) => this.setState({tvshowpath: e.target.value})}/>
|
onChange={(e) => this.setState({tvshowpath: e.target.value})}/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
</Form.Row>
|
</Form.Row>
|
||||||
|
|
||||||
<Form.Check
|
<Form.Check
|
||||||
type="switch"
|
type='switch'
|
||||||
id="custom-switch"
|
id='custom-switch'
|
||||||
data-testid='passwordswitch'
|
data-testid='passwordswitch'
|
||||||
label="Enable Password support"
|
label='Enable Password support'
|
||||||
checked={this.state.passwordsupport}
|
checked={this.state.passwordsupport}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
this.setState({passwordsupport: !this.state.passwordsupport})
|
this.setState({passwordsupport: !this.state.passwordsupport})
|
||||||
@ -62,18 +88,18 @@ class GeneralSettings extends React.Component {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{this.state.passwordsupport ?
|
{this.state.passwordsupport ?
|
||||||
<Form.Group data-testid="passwordfield">
|
<Form.Group data-testid='passwordfield'>
|
||||||
<Form.Label>Password</Form.Label>
|
<Form.Label>Password</Form.Label>
|
||||||
<Form.Control type="password" placeholder="**********" value={this.state.password}
|
<Form.Control type='password' placeholder='**********' value={this.state.password}
|
||||||
onChange={(e) => this.setState({password: e.target.value})}/>
|
onChange={(e) => this.setState({password: e.target.value})}/>
|
||||||
</Form.Group> : null
|
</Form.Group> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
<Form.Check
|
<Form.Check
|
||||||
type="switch"
|
type='switch'
|
||||||
id="custom-switch-2"
|
id='custom-switch-2'
|
||||||
data-testid='tmdb-switch'
|
data-testid='tmdb-switch'
|
||||||
label="Enable TMDB video grabbing support"
|
label='Enable TMDB video grabbing support'
|
||||||
checked={this.state.tmdbsupport}
|
checked={this.state.tmdbsupport}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
this.setState({tmdbsupport: !this.state.tmdbsupport})
|
this.setState({tmdbsupport: !this.state.tmdbsupport})
|
||||||
@ -81,10 +107,10 @@ class GeneralSettings extends React.Component {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Form.Check
|
<Form.Check
|
||||||
type="switch"
|
type='switch'
|
||||||
id="custom-switch-3"
|
id='custom-switch-3'
|
||||||
data-testid='darktheme-switch'
|
data-testid='darktheme-switch'
|
||||||
label="Enable Dark-Theme"
|
label='Enable Dark-Theme'
|
||||||
checked={GlobalInfos.isDarkTheme()}
|
checked={GlobalInfos.isDarkTheme()}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
GlobalInfos.enableDarkTheme(!GlobalInfos.isDarkTheme());
|
GlobalInfos.enableDarkTheme(!GlobalInfos.isDarkTheme());
|
||||||
@ -93,13 +119,13 @@ class GeneralSettings extends React.Component {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Form.Group className={style.mediacenternameform} data-testid="nameform">
|
<Form.Group className={style.mediacenternameform} data-testid='nameform'>
|
||||||
<Form.Label>The name of the Mediacenter</Form.Label>
|
<Form.Label>The name of the Mediacenter</Form.Label>
|
||||||
<Form.Control type="text" placeholder="Mediacentername" value={this.state.mediacentername}
|
<Form.Control type='text' placeholder='Mediacentername' value={this.state.mediacentername}
|
||||||
onChange={(e) => this.setState({mediacentername: e.target.value})}/>
|
onChange={(e) => this.setState({mediacentername: e.target.value})}/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<Button variant="primary" type="submit">
|
<Button variant='primary' type='submit'>
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
</Form>
|
</Form>
|
||||||
@ -125,7 +151,12 @@ class GeneralSettings extends React.Component {
|
|||||||
mediacentername: result.mediacenter_name,
|
mediacentername: result.mediacenter_name,
|
||||||
password: result.password,
|
password: result.password,
|
||||||
passwordsupport: result.passwordEnabled,
|
passwordsupport: result.passwordEnabled,
|
||||||
tmdbsupport: result.TMDB_grabbing
|
tmdbsupport: result.TMDB_grabbing,
|
||||||
|
|
||||||
|
videonr: result.videonr,
|
||||||
|
dbsize: result.dbsize,
|
||||||
|
difftagnr: result.difftagnr,
|
||||||
|
tagsadded: result.tagsadded
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -142,7 +173,7 @@ class GeneralSettings extends React.Component {
|
|||||||
updateRequest.append('tvshowpath', this.state.tvshowpath);
|
updateRequest.append('tvshowpath', this.state.tvshowpath);
|
||||||
updateRequest.append('mediacentername', this.state.mediacentername);
|
updateRequest.append('mediacentername', this.state.mediacentername);
|
||||||
updateRequest.append("tmdbsupport", this.state.tmdbsupport);
|
updateRequest.append("tmdbsupport", this.state.tmdbsupport);
|
||||||
updateRequest.append("darkmodeenabled", GlobalInfos.isDarkTheme());
|
updateRequest.append("darkmodeenabled", GlobalInfos.isDarkTheme().toString());
|
||||||
|
|
||||||
fetch('/api/settings.php', {method: 'POST', body: updateRequest})
|
fetch('/api/settings.php', {method: 'POST', body: updateRequest})
|
||||||
.then((response) => response.json()
|
.then((response) => response.json()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
.GeneralForm {
|
.GeneralForm {
|
||||||
|
margin-top: 55px;
|
||||||
width: 60%;
|
width: 60%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6,3 +7,16 @@
|
|||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
width: 40%;
|
width: 40%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.infoheader {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On screens that are 722px wide or less, make the columns stack on top of each other instead of next to each other */
|
||||||
|
@media screen and (max-width: 722px) {
|
||||||
|
.infoheader {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -109,4 +109,9 @@ describe('<GeneralSettings/>', function () {
|
|||||||
wrapper.find("[data-testid='tmdb-switch']").simulate("change");
|
wrapper.find("[data-testid='tmdb-switch']").simulate("change");
|
||||||
expect(wrapper.state().tmdbsupport).toBe(false);
|
expect(wrapper.state().tmdbsupport).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('test insertion of 4 infoheaderitems', function () {
|
||||||
|
const wrapper = shallow(<GeneralSettings/>);
|
||||||
|
expect(wrapper.find("InfoHeaderItem").length).toBe(4);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
border-bottom-right-radius: 10px;
|
border-bottom-right-radius: 10px;
|
||||||
border-top-right-radius: 10px;
|
border-top-right-radius: 10px;
|
||||||
float: left;
|
float: left;
|
||||||
min-height: calc(100vh - 62px);
|
margin-top: 10px;
|
||||||
|
min-height: calc(100vh - 70px);
|
||||||
min-width: 110px;
|
min-width: 110px;
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
width: 10%;
|
width: 10%;
|
||||||
|
Loading…
Reference in New Issue
Block a user