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() { private function loadVideos() {
$this->addActionHandler("loadVideo", function () { $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); $result = $this->conn->query($query);
$row = $result->fetch_assoc(); $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 // todo drop video url from db -- maybe one with and one without extension
// extension hardcoded here!!! // extension hardcoded here!!!
$arr["movie_url"] = str_replace("?", "%3F", $this->videopath . $row["movie_name"] . ".mp4"); $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["quality"] = $row["quality"];
$arr["length"] = $row["length"]; $arr["length"] = $row["length"];
@ -120,13 +123,27 @@ class Video extends RequestBase {
$arr['tags'] = array(); $arr['tags'] = array();
$query = "SELECT t.tag_name FROM video_tags $query = "SELECT t.tag_name FROM video_tags
INNER JOIN tags t on video_tags.tag_id = t.tag_id 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"; GROUP BY t.tag_name";
$result = $this->conn->query($query); $result = $this->conn->query($query);
while ($r = mysqli_fetch_assoc($result)) { while ($r = mysqli_fetch_assoc($result)) {
array_push($arr['tags'], $r); 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)); $this->commitMessage(json_encode($arr));
}); });

View File

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

View File

@ -31,4 +31,17 @@ describe('<Tag/>', function () {
expect(func).toBeCalledTimes(1); 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, quality: null,
length: null, length: null,
tags: [], tags: [],
suggesttag: [],
popupvisible: false popupvisible: false
}; };
} }
@ -49,6 +50,79 @@ class Player extends React.Component {
this.fetchMovieData(); 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() { render() {
return ( return (
<div id='videocontainer'> <div id='videocontainer'>
@ -56,23 +130,7 @@ class Player extends React.Component {
title='Watch' title='Watch'
subtitle={this.state.movie_name}/> subtitle={this.state.movie_name}/>
<SideBar> {this.assembleSideBar()}
<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>
<div className={style.videowrapper}> <div className={style.videowrapper}>
{/* video component is added here */} {/* video component is added here */}
@ -131,8 +189,10 @@ class Player extends React.Component {
likes: result.likes, likes: result.likes,
quality: result.quality, quality: result.quality,
length: result.length, 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((response) => response.json()
.then((result) => { .then((result) => {
if (result.result === "success") { if (result.result === "success") {
this.fetchMovieData(); // likes +1 --> avoid reload of all data
this.setState({likes: this.state.likes + 1})
} else { } else {
console.log("an error occured while liking"); console.error("an error occured while liking");
console.log(result); console.error(result);
} }
})); }));
} }

View File

@ -23,17 +23,8 @@ describe('<Player/>', function () {
expect(wrapper.find("r")).toHaveLength(1); expect(wrapper.find("r")).toHaveLength(1);
}); });
it('likebtn click', done => { function simulateLikeButtonClick(){
global.fetch = global.prepareFetchApi({result: 'success'});
const func = jest.fn();
const wrapper = shallow(<Player/>); const wrapper = shallow(<Player/>);
wrapper.setProps({
onHide: () => {
func()
}
});
// initial fetch for getting movie data // initial fetch for getting movie data
expect(global.fetch).toHaveBeenCalledTimes(1); expect(global.fetch).toHaveBeenCalledTimes(1);
@ -41,9 +32,19 @@ describe('<Player/>', function () {
// fetch for liking // fetch for liking
expect(global.fetch).toHaveBeenCalledTimes(2); 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(() => { process.nextTick(() => {
// refetch is called so fetch called 3 times expect(global.fetch).toHaveBeenCalledTimes(2);
expect(global.fetch).toHaveBeenCalledTimes(3); expect(global.console.error).toHaveBeenCalledTimes(0);
global.fetch.mockClear(); global.fetch.mockClear();
done(); done();
@ -52,24 +53,14 @@ describe('<Player/>', function () {
it('errored likebtn click', done => { it('errored likebtn click', done => {
global.fetch = global.prepareFetchApi({result: 'nosuccess'}); global.fetch = global.prepareFetchApi({result: 'nosuccess'});
const func = jest.fn(); global.console.error = jest.fn();
const wrapper = shallow(<Player/>); simulateLikeButtonClick();
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);
process.nextTick(() => { process.nextTick(() => {
// refetch is called so fetch called 3 times // refetch is called so fetch called 3 times
expect(global.fetch).toHaveBeenCalledTimes(2); expect(global.fetch).toHaveBeenCalledTimes(2);
expect(global.console.error).toHaveBeenCalledTimes(2);
global.fetch.mockClear(); global.fetch.mockClear();
done(); done();
@ -117,4 +108,59 @@ describe('<Player/>', function () {
expect(wrapper.find("Tag")).toHaveLength(2); 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;
}
}); });