only load non assigned tags

fix custom onClick events
This commit is contained in:
Lukas Heiligenbrunner 2020-09-26 18:43:30 +00:00
parent b36327b332
commit 8f88aa3c02
5 changed files with 191 additions and 49 deletions

View File

@ -95,7 +95,10 @@ class Video extends RequestBase {
*/
private function loadVideos() {
$this->addActionHandler("loadVideo", function () {
$query = "SELECT movie_name,movie_id,movie_url,thumbnail,poster,likes,quality,length FROM videos WHERE movie_id='" . $_POST['movieid'] . "'";
$video_id = $_POST['movieid'];
$query = " SELECT movie_name,movie_id,movie_url,thumbnail,poster,likes,quality,length
FROM videos WHERE movie_id=$video_id";
$result = $this->conn->query($query);
$row = $result->fetch_assoc();
@ -112,7 +115,7 @@ class Video extends RequestBase {
// todo drop video url from db -- maybe one with and one without extension
// extension hardcoded here!!!
$arr["movie_url"] = str_replace("?", "%3F", $this->videopath . $row["movie_name"] . ".mp4");
$arr["likes"] = $row["likes"];
$arr["likes"] = (int) $row["likes"];
$arr["quality"] = $row["quality"];
$arr["length"] = $row["length"];
@ -120,13 +123,27 @@ class Video extends RequestBase {
$arr['tags'] = array();
$query = "SELECT t.tag_name FROM video_tags
INNER JOIN tags t on video_tags.tag_id = t.tag_id
WHERE video_tags.video_id=" . $_POST['movieid'] . "
WHERE video_tags.video_id=$video_id
GROUP BY t.tag_name";
$result = $this->conn->query($query);
while ($r = mysqli_fetch_assoc($result)) {
array_push($arr['tags'], $r);
}
// get the random predict tags
$arr['suggesttag'] = array();
// select 5 random tags which are not selected for current video
$query = "SELECT * FROM tags
WHERE tag_id NOT IN (
SELECT video_tags.tag_id FROM video_tags
WHERE video_id=$video_id)
ORDER BY rand()
LIMIT 5";
$result = $this->conn->query($query);
while ($r = mysqli_fetch_assoc($result)) {
array_push($arr['suggesttag'], $r);
}
$this->commitMessage(json_encode($arr));
});

View File

@ -18,6 +18,11 @@ class Tag extends React.Component {
* click handling for a Tag
*/
TagClick() {
if (this.props.onclick) {
this.props.onclick();
return;
}
const tag = this.props.children.toString().toLowerCase();
// call callback functin to switch to category page with specified tag

View File

@ -31,4 +31,17 @@ describe('<Tag/>', function () {
expect(func).toBeCalledTimes(1);
});
it('test custom onclick function', function () {
const func = jest.fn();
const wrapper = shallow(<Tag
onclick={() => {func()}}>test</Tag>);
expect(func).toBeCalledTimes(0);
wrapper.simulate("click");
expect(func).toBeCalledTimes(1);
});
});

View File

@ -41,6 +41,7 @@ class Player extends React.Component {
quality: null,
length: null,
tags: [],
suggesttag: [],
popupvisible: false
};
}
@ -49,6 +50,79 @@ class Player extends React.Component {
this.fetchMovieData();
}
/**
* quick add callback to add tag to db and change gui correctly
* @param tag_id id of tag to add
* @param tag_name name of tag to add
*/
quickAddTag(tag_id, tag_name) {
// save the tag
const updateRequest = new FormData();
updateRequest.append('action', 'addTag');
updateRequest.append('id', tag_id);
updateRequest.append('movieid', this.props.movie_id);
fetch('/api/tags.php', {method: 'POST', body: updateRequest})
.then((response) => response.json()
.then((result) => {
if (result.result !== "success") {
console.error("error occured while writing to db -- todo error handling");
console.error(result.result);
} else {
// update tags if successful
let array = [...this.state.suggesttag]; // make a separate copy of the array
const index = array.map(function (e) {
return e.tag_id;
}).indexOf(tag_id);
if (index !== -1) {
array.splice(index, 1);
this.setState({
tags: [...this.state.tags, {tag_name: tag_name}],
suggesttag: array
});
}
}
}));
}
/**
* generate sidebar with all items
*/
assembleSideBar() {
return (
<SideBar>
<SideBarTitle>Infos:</SideBarTitle>
<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}
<Line/>
<SideBarTitle>Tags:</SideBarTitle>
{this.state.tags.map((m) => (
<Tag
key={m.tag_name}
viewbinding={this.props.viewbinding}>{m.tag_name}</Tag>
))}
<Line/>
<SideBarTitle>Tag Quickadd:</SideBarTitle>
{this.state.suggesttag.map((m) => (
<Tag
key={m.tag_name}
onclick={() => {
this.quickAddTag(m.tag_id, m.tag_name);
}}>
{m.tag_name}
</Tag>
))}
</SideBar>
);
}
render() {
return (
<div id='videocontainer'>
@ -56,23 +130,7 @@ class Player extends React.Component {
title='Watch'
subtitle={this.state.movie_name}/>
<SideBar>
<SideBarTitle>Infos:</SideBarTitle>
<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}
<Line/>
<SideBarTitle>Tags:</SideBarTitle>
{this.state.tags.map((m) => (
<Tag
key={m.tag_name}
viewbinding={this.props.viewbinding}>{m.tag_name}</Tag>
))}
</SideBar>
{this.assembleSideBar()}
<div className={style.videowrapper}>
{/* video component is added here */}
@ -131,8 +189,10 @@ class Player extends React.Component {
likes: result.likes,
quality: result.quality,
length: result.length,
tags: result.tags
tags: result.tags,
suggesttag: result.suggesttag
});
console.log(this.state);
});
}
@ -149,10 +209,11 @@ class Player extends React.Component {
.then((response) => response.json()
.then((result) => {
if (result.result === "success") {
this.fetchMovieData();
// likes +1 --> avoid reload of all data
this.setState({likes: this.state.likes + 1})
} else {
console.log("an error occured while liking");
console.log(result);
console.error("an error occured while liking");
console.error(result);
}
}));
}

View File

@ -23,17 +23,8 @@ describe('<Player/>', function () {
expect(wrapper.find("r")).toHaveLength(1);
});
it('likebtn click', done => {
global.fetch = global.prepareFetchApi({result: 'success'});
const func = jest.fn();
function simulateLikeButtonClick(){
const wrapper = shallow(<Player/>);
wrapper.setProps({
onHide: () => {
func()
}
});
// initial fetch for getting movie data
expect(global.fetch).toHaveBeenCalledTimes(1);
@ -41,9 +32,19 @@ describe('<Player/>', function () {
// fetch for liking
expect(global.fetch).toHaveBeenCalledTimes(2);
return wrapper;
}
it('likebtn click', done => {
global.fetch = global.prepareFetchApi({result: 'success'});
global.console.error = jest.fn();
simulateLikeButtonClick();
process.nextTick(() => {
// refetch is called so fetch called 3 times
expect(global.fetch).toHaveBeenCalledTimes(3);
expect(global.fetch).toHaveBeenCalledTimes(2);
expect(global.console.error).toHaveBeenCalledTimes(0);
global.fetch.mockClear();
done();
@ -52,24 +53,14 @@ describe('<Player/>', function () {
it('errored likebtn click', done => {
global.fetch = global.prepareFetchApi({result: 'nosuccess'});
const func = jest.fn();
global.console.error = jest.fn();
const wrapper = shallow(<Player/>);
wrapper.setProps({
onHide: () => {
func()
}
});
// initial fetch for getting movie data
expect(global.fetch).toHaveBeenCalledTimes(1);
wrapper.find('.videoactions').find("button").first().simulate('click');
// fetch for liking
expect(global.fetch).toHaveBeenCalledTimes(2);
simulateLikeButtonClick();
process.nextTick(() => {
// refetch is called so fetch called 3 times
expect(global.fetch).toHaveBeenCalledTimes(2);
expect(global.console.error).toHaveBeenCalledTimes(2);
global.fetch.mockClear();
done();
@ -117,4 +108,59 @@ describe('<Player/>', function () {
expect(wrapper.find("Tag")).toHaveLength(2);
});
it('inserts tag quickadd correctly', function () {
generatetag();
});
it('test click of quickadd tag btn', done => {
const wrapper = generatetag();
global.fetch = prepareFetchApi({result: 'success'});
// render tag subcomponent
const tag = wrapper.find("Tag").first().dive();
tag.simulate('click');
process.nextTick(() => {
expect(global.fetch).toHaveBeenCalledTimes(1);
global.fetch.mockClear();
done();
});
});
it('test failing quickadd', done => {
const wrapper = generatetag();
global.fetch = prepareFetchApi({result: 'nonsuccess'});
global.console.error = jest.fn();
// render tag subcomponent
const tag = wrapper.find("Tag").first().dive();
tag.simulate('click');
process.nextTick(() => {
expect(global.console.error).toHaveBeenCalledTimes(2);
global.fetch.mockClear();
done();
});
});
function generatetag(){
const wrapper = shallow(<Player/>);
expect(wrapper.find("Tag")).toHaveLength(0);
wrapper.setState({
suggesttag: [
{tag_name: 'first', tag_id: 1},
]
});
expect(wrapper.find("Tag")).toHaveLength(1);
return wrapper;
}
});