diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8b8f1c5..4250c65 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -108,18 +108,13 @@ Debian_Server: - Minimize_Frontend - Build_Backend -Test_Server: +.Test_Server_Common: stage: deploy image: luki42/ssh:latest needs: - Frontend_Tests - Backend_Tests - Debian_Server - rules: - - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH # run this always on default branch - - if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH # allow triggering this manually - when: manual - allow_failure: true script: - eval $(ssh-agent -s) - echo "$SSH_PRIVATE_KEY" | ssh-add - @@ -129,18 +124,23 @@ Test_Server: - ssh root@192.168.0.42 "DEBIAN_FRONTEND=noninteractive apt-get --reinstall -y -qq install /tmp/OpenMediaCenter-*.deb && rm /tmp/OpenMediaCenter-*.deb" allow_failure: true -Test_Server_2: +Test_Server_CD: + extends: .Test_Server_Common + only: + refs: + - master + +Test_Server_MANUAL: + extends: .Test_Server_Common + when: manual + +.Test_Server_2_Common: stage: deploy image: luki42/ssh:latest needs: - Frontend_Tests - Backend_Tests - Debian_Server - rules: - - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH # run this always on default branch - - if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH # allow triggering this manually - when: manual - allow_failure: true script: - eval $(ssh-agent -s) - echo "$SSH_PRIVATE_KEY_2" | ssh-add - @@ -150,3 +150,12 @@ Test_Server_2: - ssh root@192.168.0.209 "DEBIAN_FRONTEND=noninteractive apt-get --reinstall -y -qq install /tmp/OpenMediaCenter-*.deb && rm /tmp/OpenMediaCenter-*.deb" allow_failure: true +Test_Server_2_CD: + extends: .Test_Server_2_Common + only: + refs: + - master + +Test_Server_2_MANUAL: + extends: .Test_Server_2_Common + when: manual \ No newline at end of file diff --git a/apiGo/api/Video.go b/apiGo/api/Video.go index 69a25fa..c9c2d2e 100644 --- a/apiGo/api/Video.go +++ b/apiGo/api/Video.go @@ -1,6 +1,7 @@ package api import ( + "encoding/json" "fmt" "net/url" "openmediacenter/apiGo/api/api" @@ -9,6 +10,7 @@ import ( "openmediacenter/apiGo/database" "os" "strconv" + "strings" ) func addVideoHandlers() { @@ -162,7 +164,8 @@ func getVideoHandlers() { */ api.AddHandler("getRandomMovies", api.VideoNode, api.PermUser, func(context api.Context) { var args struct { - Number int + Number int + TagFilter []uint32 } if api.DecodeRequest(context.GetRequest(), &args) != nil { context.Text("unable to decode request") @@ -174,34 +177,52 @@ func getVideoHandlers() { Videos []types.VideoUnloadedType } - query := fmt.Sprintf("SELECT movie_id,movie_name FROM videos ORDER BY RAND() LIMIT %d", args.Number) - result.Videos = readVideosFromResultset(database.Query(query)) + whereclause := "WHERE 1" + if len(args.TagFilter) > 0 { + d, _ := json.Marshal(args.TagFilter) + vals := strings.Trim(string(d), "[]") - var ids string - for i := range result.Videos { - ids += "video_tags.video_id=" + strconv.Itoa(result.Videos[i].MovieId) - - if i < len(result.Videos)-1 { - ids += " OR " - } + whereclause = fmt.Sprintf("WHERE tag_id IN (%s)", vals) } - // add the corresponding tags - query = fmt.Sprintf(`SELECT t.tag_name,t.tag_id FROM video_tags + query := fmt.Sprintf(` +SELECT video_tags.video_id,v.movie_name FROM video_tags join videos v on v.movie_id = video_tags.video_id + %s + group by video_id + ORDER BY RAND() + LIMIT %d`, whereclause, args.Number) + result.Videos = readVideosFromResultset(database.Query(query)) + + if len(result.Videos) > 0 { + var ids string + for i := range result.Videos { + ids += "video_tags.video_id=" + strconv.Itoa(result.Videos[i].MovieId) + + if i < len(result.Videos)-1 { + ids += " OR " + } + } + + // add the corresponding tags + query = fmt.Sprintf(`SELECT t.tag_name,t.tag_id FROM video_tags INNER JOIN tags t on video_tags.tag_id = t.tag_id WHERE %s GROUP BY t.tag_id`, ids) - rows := database.Query(query) - - for rows.Next() { - var tag types.Tag - err := rows.Scan(&tag.TagName, &tag.TagId) - if err != nil { - panic(err.Error()) // proper Error handling instead of panic in your app + rows := database.Query(query) + if rows != nil { + for rows.Next() { + var tag types.Tag + err := rows.Scan(&tag.TagName, &tag.TagId) + if err != nil { + panic(err.Error()) // proper Error handling instead of panic in your app + } + // append to final array + result.Tags = append(result.Tags, tag) + } } - // append to final array - result.Tags = append(result.Tags, tag) + } else { + result.Tags = []types.Tag{} } context.Json(result) diff --git a/src/pages/RandomPage/RandomPage.tsx b/src/pages/RandomPage/RandomPage.tsx index baa7b0a..50e9161 100644 --- a/src/pages/RandomPage/RandomPage.tsx +++ b/src/pages/RandomPage/RandomPage.tsx @@ -2,16 +2,21 @@ import React from 'react'; import style from './RandomPage.module.css'; import SideBar, {SideBarTitle} from '../../elements/SideBar/SideBar'; import Tag from '../../elements/Tag/Tag'; -import PageTitle from '../../elements/PageTitle/PageTitle'; +import PageTitle, {Line} from '../../elements/PageTitle/PageTitle'; import VideoContainer from '../../elements/VideoContainer/VideoContainer'; import {APINode, callAPI} from '../../utils/Api'; import {TagType} from '../../types/VideoTypes'; import {VideoTypes} from '../../types/ApiTypes'; import {addKeyHandler, removeKeyHandler} from '../../utils/ShortkeyHandler'; +import {IconButton} from '../../elements/GPElements/Button'; +import {faPlusCircle} from '@fortawesome/free-solid-svg-icons'; +import AddTagPopup from '../../elements/Popups/AddTagPopup/AddTagPopup'; interface state { videos: VideoTypes.VideoUnloadedType[]; tags: TagType[]; + filterTags: TagType[]; + addTagPopup: boolean; } interface GetRandomMoviesType { @@ -29,8 +34,10 @@ class RandomPage extends React.Component<{}, state> { super(props); this.state = { + addTagPopup: false, videos: [], - tags: [] + tags: [], + filterTags: [] }; this.keypress = this.keypress.bind(this); @@ -56,42 +63,56 @@ class RandomPage extends React.Component<{}, state> { {this.state.tags.map((m) => ( ))} + + Filter Tags: + {this.state.filterTags.map((m) => ( + + ))} + { + this.setState({addTagPopup: true}); + }} + /> - {this.state.videos.length !== 0 ? ( - -
- -
-
- ) : ( -
No Data found!
- )} + {this.state.videos.length !== 0 ? :
No Data found!
} +
+ +
+ {this.state.addTagPopup ? ( + this.setState({addTagPopup: false})} + submit={(tagId: number, tagName: string): void => { + this.setState({filterTags: [...this.state.filterTags, {TagId: tagId, TagName: tagName}]}, (): void => { + this.loadShuffledvideos(this.LoadNR); + }); + }} + /> + ) : null} ); } - /** - * click handler for shuffle btn - */ - shuffleclick(): void { - this.loadShuffledvideos(this.LoadNR); - } - /** * load random videos from backend * @param nr number of videos to load */ loadShuffledvideos(nr: number): void { - callAPI(APINode.Video, {action: 'getRandomMovies', Number: nr}, (result) => { - this.setState({videos: []}); // needed to trigger rerender of main videoview - this.setState({ - videos: result.Videos, - tags: result.Tags - }); - }); + callAPI( + APINode.Video, + {action: 'getRandomMovies', Number: nr, TagFilter: this.state.filterTags.map((t) => t.TagId)}, + (result) => { + this.setState({videos: []}); // needed to trigger rerender of main videoview + this.setState({ + videos: result.Videos, + tags: result.Tags + }); + } + ); } /**