From 8f88aa3c022f914e9ac15a93a7fe655918ce972d Mon Sep 17 00:00:00 2001 From: Lukas Heiligenbrunner Date: Sat, 26 Sep 2020 18:43:30 +0000 Subject: [PATCH] only load non assigned tags fix custom onClick events --- api/src/handlers/Video.php | 23 ++++++- src/elements/Tag/Tag.js | 5 ++ src/elements/Tag/Tag.test.js | 13 ++++ src/pages/Player/Player.js | 103 +++++++++++++++++++++++++------- src/pages/Player/Player.test.js | 96 +++++++++++++++++++++-------- 5 files changed, 191 insertions(+), 49 deletions(-) diff --git a/api/src/handlers/Video.php b/api/src/handlers/Video.php index 4d2ecfe..9b37724 100755 --- a/api/src/handlers/Video.php +++ b/api/src/handlers/Video.php @@ -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)); }); diff --git a/src/elements/Tag/Tag.js b/src/elements/Tag/Tag.js index 45e5f43..21c73ce 100644 --- a/src/elements/Tag/Tag.js +++ b/src/elements/Tag/Tag.js @@ -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 diff --git a/src/elements/Tag/Tag.test.js b/src/elements/Tag/Tag.test.js index f53bfbc..7d9ec59 100644 --- a/src/elements/Tag/Tag.test.js +++ b/src/elements/Tag/Tag.test.js @@ -31,4 +31,17 @@ describe('', function () { expect(func).toBeCalledTimes(1); }); + + it('test custom onclick function', function () { + const func = jest.fn(); + + const wrapper = shallow( {func()}}>test); + + expect(func).toBeCalledTimes(0); + + wrapper.simulate("click"); + + expect(func).toBeCalledTimes(1); + }); }); diff --git a/src/pages/Player/Player.js b/src/pages/Player/Player.js index 18d3801..5b593a2 100644 --- a/src/pages/Player/Player.js +++ b/src/pages/Player/Player.js @@ -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 ( + + Infos: + + {this.state.likes} Likes! + {this.state.quality !== 0 ? + {this.state.quality}p Quality! : null} + {this.state.length !== 0 ? + {Math.round(this.state.length / 60)} Minutes of + length! : null} + + Tags: + {this.state.tags.map((m) => ( + {m.tag_name} + ))} + + Tag Quickadd: + {this.state.suggesttag.map((m) => ( + { + this.quickAddTag(m.tag_id, m.tag_name); + }}> + {m.tag_name} + + ))} + + ); + } + render() { return (
@@ -56,23 +130,7 @@ class Player extends React.Component { title='Watch' subtitle={this.state.movie_name}/> - - Infos: - - {this.state.likes} Likes! - {this.state.quality !== 0 ? - {this.state.quality}p Quality! : null} - {this.state.length !== 0 ? - {Math.round(this.state.length / 60)} Minutes of - length! : null} - - Tags: - {this.state.tags.map((m) => ( - {m.tag_name} - ))} - + {this.assembleSideBar()}
{/* 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); } })); } diff --git a/src/pages/Player/Player.test.js b/src/pages/Player/Player.test.js index 67b5bab..b2da6a1 100644 --- a/src/pages/Player/Player.test.js +++ b/src/pages/Player/Player.test.js @@ -23,17 +23,8 @@ describe('', 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(); - wrapper.setProps({ - onHide: () => { - func() - } - }); // initial fetch for getting movie data expect(global.fetch).toHaveBeenCalledTimes(1); @@ -41,9 +32,19 @@ describe('', 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('', function () { it('errored likebtn click', done => { global.fetch = global.prepareFetchApi({result: 'nosuccess'}); - const func = jest.fn(); + global.console.error = jest.fn(); - const wrapper = shallow(); - 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('', 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(); + + expect(wrapper.find("Tag")).toHaveLength(0); + + wrapper.setState({ + suggesttag: [ + {tag_name: 'first', tag_id: 1}, + ] + }); + + expect(wrapper.find("Tag")).toHaveLength(1); + + return wrapper; + } });