add style for actor tiles

render actors got from backend
backend test code to get actors
This commit is contained in:
2020-12-11 18:23:13 +00:00
parent 707c54e5f5
commit c5d231d9f2
44 changed files with 1017 additions and 344 deletions

View File

@ -0,0 +1,57 @@
import React from 'react';
import PageTitle from '../../elements/PageTitle/PageTitle';
import SideBar, {SideBarTitle} from '../../elements/SideBar/SideBar';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faUser} from '@fortawesome/free-solid-svg-icons';
import style from './ActorPage.module.css';
import VideoContainer from '../../elements/VideoContainer/VideoContainer';
class ActorPage extends React.Component {
constructor(props) {
super(props);
this.state = {data: undefined};
}
render() {
return (
<>
<PageTitle title={this.props.actor.name} subtitle={this.state.data ? this.state.data.length + ' videos' : null}/>
<SideBar>
<div className={style.pic}>
<FontAwesomeIcon style={{color: 'white'}} icon={faUser} size='10x'/>
</div>
<SideBarTitle>Attention: This is an early preview!</SideBarTitle>
</SideBar>
{this.state.data ?
<VideoContainer
data={this.state.data}/> :
<div>No Data found!</div>}
</>
);
}
componentDidMount() {
this.getActorInfo();
}
/**
* request more actor info from backend
*/
getActorInfo() {
// todo 2020-12-4: fetch to db
const req = new FormData();
req.append('action', 'getActorInfo');
req.append('actorid', this.props.actor.actor_id);
fetch('/api/actor.php', {method: 'POST', body: req})
.then((response) => response.json()
.then((result) => {
console.log(result);
this.setState({data: result.videos ? result.videos : []});
}));
}
}
export default ActorPage;

View File

@ -0,0 +1,4 @@
.pic {
text-align: center;
margin-bottom: 25px;
}

View File

@ -0,0 +1,12 @@
import {shallow} from 'enzyme';
import React from 'react';
import ActorPage from './ActorPage';
describe('<ActorPage/>', function () {
it('renders without crashing ', function () {
const wrapper = shallow(<ActorPage actor={{id: 5, name: 'usr1'}}/>);
wrapper.unmount();
});
});

View File

@ -4,7 +4,7 @@ import Tag from '../../elements/Tag/Tag';
import videocontainerstyle from '../../elements/VideoContainer/VideoContainer.module.css';
import {TagPreview} from '../../elements/Preview/Preview';
import NewTagPopup from '../../elements/NewTagPopup/NewTagPopup';
import NewTagPopup from '../../elements/Popups/NewTagPopup/NewTagPopup';
import PageTitle, {Line} from '../../elements/PageTitle/PageTitle';
import VideoContainer from '../../elements/VideoContainer/VideoContainer';
@ -44,26 +44,10 @@ class CategoryPage extends React.Component {
<SideBar>
<SideBarTitle>Default Tags:</SideBarTitle>
<Tag viewbinding={{
changeRootElement: (e) => {
this.loadTag(e.props.category);
}
}}>All</Tag>
<Tag viewbinding={{
changeRootElement: (e) => {
this.loadTag(e.props.category);
}
}}>FullHd</Tag>
<Tag viewbinding={{
changeRootElement: (e) => {
this.loadTag(e.props.category);
}
}}>LowQuality</Tag>
<Tag viewbinding={{
changeRootElement: (e) => {
this.loadTag(e.props.category);
}
}}>HD</Tag>
<Tag onclick={(tag) => {this.loadTag(tag);}}>All</Tag>
<Tag onclick={(tag) => {this.loadTag(tag);}}>FullHd</Tag>
<Tag onclick={(tag) => {this.loadTag(tag);}}>LowQuality</Tag>
<Tag onclick={(tag) => {this.loadTag(tag);}}>HD</Tag>
<Line/>
<button data-testid='btnaddtag' className='btn btn-success' onClick={() => {
this.setState({popupvisible: true});
@ -82,8 +66,7 @@ class CategoryPage extends React.Component {
<>
{this.videodata ?
<VideoContainer
data={this.videodata}
viewbinding={this.props.viewbinding}/> : null}
data={this.videodata}/> : null}
<button data-testid='backbtn' className='btn btn-success'
onClick={this.loadCategoryPageDefault}>Back
</button>
@ -95,7 +78,6 @@ class CategoryPage extends React.Component {
key={m.tag_name}
name={m.tag_name}
tag_id={m.tag_id}
viewbinding={this.props.viewbinding}
categorybinding={this.loadTag}/>
)) :
'loading'}
@ -105,6 +87,7 @@ class CategoryPage extends React.Component {
{this.state.popupvisible ?
<NewTagPopup show={this.state.popupvisible}
onHide={() => {
console.error("setstatecalled!");
this.setState({popupvisible: false});
this.loadTags();
}}/> :

View File

@ -158,8 +158,7 @@ class HomePage extends React.Component {
</SideBar>
{this.state.data.length !== 0 ?
<VideoContainer
data={this.state.data}
viewbinding={this.props.viewbinding}/> :
data={this.state.data}/> :
<div>No Data found!</div>}
<div className={style.rightinfo}>

View File

@ -6,8 +6,13 @@ import plyrstyle from 'plyr-react/dist/plyr.css'
import {Plyr} from 'plyr-react';
import SideBar, {SideBarItem, SideBarTitle} from '../../elements/SideBar/SideBar';
import Tag from '../../elements/Tag/Tag';
import AddTagPopup from '../../elements/AddTagPopup/AddTagPopup';
import AddTagPopup from '../../elements/Popups/AddTagPopup/AddTagPopup';
import PageTitle, {Line} from '../../elements/PageTitle/PageTitle';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faPlusCircle} from '@fortawesome/free-solid-svg-icons';
import AddActorPopup from '../../elements/Popups/AddActorPopup/AddActorPopup';
import ActorTile from '../../elements/ActorTile/ActorTile';
import GlobalInfos from '../../GlobalInfos';
/**
@ -44,13 +49,15 @@ class Player extends React.Component {
length: null,
tags: [],
suggesttag: [],
popupvisible: false
popupvisible: false,
actorpopupvisible: false
};
this.quickAddTag = this.quickAddTag.bind(this);
}
componentDidMount() {
// initial fetch of current movie data
this.fetchMovieData();
}
@ -111,14 +118,18 @@ class Player extends React.Component {
return (
<>
{this.state.popupvisible ?
<AddTagPopup show={this.state.popupvisible}
onHide={() => {
this.setState({popupvisible: false});
}}
<AddTagPopup onHide={() => {this.setState({popupvisible: false});}}
submit={this.quickAddTag}
movie_id={this.state.movie_id}/> :
null
}
{
this.state.actorpopupvisible ?
<AddActorPopup onHide={() => {
this.refetchActors();
this.setState({actorpopupvisible: false});
}} movie_id={this.state.movie_id}/> : null
}
</>
);
}
@ -135,14 +146,11 @@ 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) => (
<Tag
key={m.tag_name}
viewbinding={this.props.viewbinding}>{m.tag_name}</Tag>
<Tag key={m.tag_name}>{m.tag_name}</Tag>
))}
<Line/>
<SideBarTitle>Tag Quickadd:</SideBarTitle>
@ -176,7 +184,9 @@ class Player extends React.Component {
options={this.options}/> :
<div>not loaded yet</div>}
<div className={style.videoactions}>
<button className={style.button} style={{backgroundColor: 'green'}} onClick={() => this.likebtn()}>Like this Video!</button>
<button className={style.button} style={{backgroundColor: 'green'}} onClick={() => this.likebtn()}>
Like this Video!
</button>
<button className={style.button} style={{backgroundColor: '#3574fe'}} onClick={() => this.setState({popupvisible: true})}>
Give this Video a Tag
</button>
@ -185,6 +195,24 @@ class Player extends React.Component {
}}>Delete Video
</button>
</div>
{/* rendering of actor tiles */}
<div className={style.actorcontainer}>
{this.state.actors ?
this.state.actors.map((actr) => (
<ActorTile actor={actr}/>
)) : <></>
}
<div className={style.actorAddTile} onClick={() => {
this.addActor();
}}>
<div className={style.actorAddTile_thumbnail}>
<FontAwesomeIcon style={{
lineHeight: '130px'
}} icon={faPlusCircle} size='5x'/>
</div>
<div className={style.actorAddTile_name}>Add Actor</div>
</div>
</div>
</div>
<button className={style.closebutton} onClick={() => this.closebtn()}>Close</button>
{
@ -224,7 +252,8 @@ class Player extends React.Component {
quality: result.quality,
length: result.length,
tags: result.tags,
suggesttag: result.suggesttag
suggesttag: result.suggesttag,
actors: result.actors
});
console.log(this.state);
});
@ -257,7 +286,7 @@ class Player extends React.Component {
* calls callback to viewbinding to show previous page agains
*/
closebtn() {
this.props.viewbinding.returnToLastElement();
GlobalInfos.getViewBinding().returnToLastElement();
}
/**
@ -273,13 +302,34 @@ class Player extends React.Component {
.then((result) => {
if (result.result === 'success') {
// return to last element if successful
this.props.viewbinding.returnToLastElement();
GlobalInfos.getViewBinding().returnToLastElement();
} else {
console.error('an error occured while liking');
console.error(result);
}
}));
}
/**
* show the actor add popup
*/
addActor() {
this.setState({actorpopupvisible: true});
}
refetchActors() {
const req = new FormData();
req.append('action', 'getActorsOfVideo');
req.append('videoid', this.props.movie_id);
console.log('refrething actors');
fetch('/api/actor.php', {method: 'POST', body: req})
.then((response) => response.json()
.then((result) => {
this.setState({actors: result});
}));
}
}
export default Player;

View File

@ -20,10 +20,36 @@
margin-top: 15px;
}
.button {
padding: 6px;
border-radius: 5px;
margin-right: 15px;
color: white;
border-width: 0;
.actorcontainer {
margin-top: 13px;
}
.button {
border-radius: 5px;
border-width: 0;
color: white;
margin-right: 15px;
padding: 6px;
}
.actorAddTile {
float: left;
padding-left: 25px;
padding-top: 50px;
cursor: pointer;
color: white;
transition: opacity ease 0.5s;
}
.actorAddTile:hover{
opacity: 0.7;
transition: opacity ease 0.5s;
}
.actorAddTile_thumbnail {
height: 90px;
}
.actorAddTile_name {
bottom: 0;
}

View File

@ -78,9 +78,11 @@ describe('<Player/>', function () {
});
it('test delete button', done => {
const wrapper = shallow(<Player viewbinding={{
returnToLastElement: jest.fn()
}}/>);
const wrapper = shallow(<Player/>);
const func = jest.fn();
prepareViewBinding(func)
global.fetch = prepareFetchApi({result: 'success'});
wrapper.find('.videoactions').find('button').at(2).simulate('click');
@ -88,7 +90,7 @@ describe('<Player/>', function () {
process.nextTick(() => {
// refetch is called so fetch called 3 times
expect(global.fetch).toHaveBeenCalledTimes(1);
expect(wrapper.instance().props.viewbinding.returnToLastElement).toHaveBeenCalledTimes(1);
expect(func).toHaveBeenCalledTimes(1);
global.fetch.mockClear();
done();
@ -97,15 +99,9 @@ describe('<Player/>', function () {
it('hide click ', function () {
const wrapper = shallow(<Player/>);
const func = jest.fn();
wrapper.setProps({
viewbinding: {
returnToLastElement: () => {
func();
}
}
});
const func = jest.fn();
prepareViewBinding(func);
expect(func).toHaveBeenCalledTimes(0);
wrapper.find('.closebutton').simulate('click');

View File

@ -31,16 +31,13 @@ class RandomPage extends React.Component {
<SideBar>
<SideBarTitle>Visible Tags:</SideBarTitle>
{this.state.tags.map((m) => (
<Tag
key={m.tag_name}
viewbinding={this.props.viewbinding}>{m.tag_name}</Tag>
<Tag key={m.tag_name}>{m.tag_name}</Tag>
))}
</SideBar>
{this.state.videos.length !== 0 ?
<VideoContainer
data={this.state.videos}
viewbinding={this.props.viewbinding}>
data={this.state.videos}>
<div className={style.Shufflebutton}>
<button onClick={() => this.shuffleclick()} className={style.btnshuffle}>Shuffle</button>
</div>

View File

@ -13,13 +13,13 @@
flex-wrap: wrap;
}
.footer{
.footer {
bottom: 3px;
color: white;
opacity: 0.8;
position: fixed;
right: 0;
bottom: 3px;
width: 110px;
opacity: 0.8;
color: white;
}
/* On screens that are 722px wide or less, make the columns stack on top of each other instead of next to each other */