Merge branch 'randompage_filter_tags' into 'master'
make tags on random page filterable See merge request lukas/openmediacenter!61
This commit is contained in:
commit
3d845aaf04
@ -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
|
@ -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)
|
||||
|
@ -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) => (
|
||||
<Tag key={m.TagId} tagInfo={m} />
|
||||
))}
|
||||
<Line />
|
||||
<SideBarTitle>Filter Tags:</SideBarTitle>
|
||||
{this.state.filterTags.map((m) => (
|
||||
<Tag key={m.TagId} tagInfo={m} />
|
||||
))}
|
||||
<IconButton
|
||||
title='Add'
|
||||
icon={faPlusCircle}
|
||||
onClick={(): void => {
|
||||
this.setState({addTagPopup: true});
|
||||
}}
|
||||
/>
|
||||
</SideBar>
|
||||
|
||||
{this.state.videos.length !== 0 ? (
|
||||
<VideoContainer data={this.state.videos}>
|
||||
<div className={style.Shufflebutton}>
|
||||
<button onClick={(): void => this.shuffleclick()} className={style.btnshuffle}>
|
||||
Shuffle
|
||||
</button>
|
||||
</div>
|
||||
</VideoContainer>
|
||||
) : (
|
||||
<div>No Data found!</div>
|
||||
)}
|
||||
{this.state.videos.length !== 0 ? <VideoContainer data={this.state.videos} /> : <div>No Data found!</div>}
|
||||
<div className={style.Shufflebutton}>
|
||||
<button onClick={(): void => this.loadShuffledvideos(this.LoadNR)} className={style.btnshuffle}>
|
||||
Shuffle
|
||||
</button>
|
||||
</div>
|
||||
{this.state.addTagPopup ? (
|
||||
<AddTagPopup
|
||||
onHide={(): void => 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}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<GetRandomMoviesType>(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<GetRandomMoviesType>(
|
||||
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
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user