Compare commits
5 Commits
newdeploy
...
rememberLo
Author | SHA1 | Date | |
---|---|---|---|
9b23666fe6 | |||
1adafef4e1 | |||
43091ff7ed | |||
12dc8427aa | |||
23d91973d7 |
@ -2,6 +2,7 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
"openmediacenter/apiGo/api/api"
|
"openmediacenter/apiGo/api/api"
|
||||||
"openmediacenter/apiGo/api/types"
|
"openmediacenter/apiGo/api/types"
|
||||||
@ -163,18 +164,25 @@ func getVideoHandlers() {
|
|||||||
api.AddHandler("getRandomMovies", api.VideoNode, api.PermUser, func(context api.Context) {
|
api.AddHandler("getRandomMovies", api.VideoNode, api.PermUser, func(context api.Context) {
|
||||||
var args struct {
|
var args struct {
|
||||||
Number int
|
Number int
|
||||||
|
Seed *int
|
||||||
}
|
}
|
||||||
if api.DecodeRequest(context.GetRequest(), &args) != nil {
|
if api.DecodeRequest(context.GetRequest(), &args) != nil {
|
||||||
context.Text("unable to decode request")
|
context.Text("unable to decode request")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if Seed argument not passed generate random seed
|
||||||
|
if args.Seed == nil {
|
||||||
|
r := rand.Int()
|
||||||
|
args.Seed = &r
|
||||||
|
}
|
||||||
|
|
||||||
var result struct {
|
var result struct {
|
||||||
Tags []types.Tag
|
Tags []types.Tag
|
||||||
Videos []types.VideoUnloadedType
|
Videos []types.VideoUnloadedType
|
||||||
}
|
}
|
||||||
|
|
||||||
query := fmt.Sprintf("SELECT movie_id,movie_name FROM videos ORDER BY RAND() LIMIT %d", args.Number)
|
query := fmt.Sprintf("SELECT movie_id,movie_name FROM videos ORDER BY RAND(%d) LIMIT %d", *args.Seed, args.Number)
|
||||||
result.Videos = readVideosFromResultset(database.Query(query))
|
result.Videos = readVideosFromResultset(database.Query(query))
|
||||||
|
|
||||||
var ids string
|
var ids string
|
||||||
|
@ -19,7 +19,7 @@ describe('<App/>', function () {
|
|||||||
it('are navlinks correct', function () {
|
it('are navlinks correct', function () {
|
||||||
const wrapper = shallow(<App/>);
|
const wrapper = shallow(<App/>);
|
||||||
wrapper.setState({password: false});
|
wrapper.setState({password: false});
|
||||||
expect(wrapper.find('.navitem')).toHaveLength(4);
|
expect(wrapper.find('.navitem')).toHaveLength(5);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('test render of password page', function () {
|
it('test render of password page', function () {
|
||||||
|
@ -88,6 +88,13 @@ class App extends React.Component<{}, state> {
|
|||||||
Categories
|
Categories
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|
||||||
|
<NavLink
|
||||||
|
className={[style.navitem, themeStyle.navitem].join(' ')}
|
||||||
|
to={'/media/actors'}
|
||||||
|
activeStyle={{opacity: '0.85'}}>
|
||||||
|
Actors
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
{this.context.TVShowEnabled ? (
|
{this.context.TVShowEnabled ? (
|
||||||
<NavLink
|
<NavLink
|
||||||
className={[style.navitem, themeStyle.navitem].join(' ')}
|
className={[style.navitem, themeStyle.navitem].join(' ')}
|
||||||
|
@ -17,7 +17,7 @@ class Tag extends React.Component<props> {
|
|||||||
if (this.props.onclick) {
|
if (this.props.onclick) {
|
||||||
return this.renderButton();
|
return this.renderButton();
|
||||||
} else {
|
} else {
|
||||||
return <Link to={'/categories/' + this.props.tagInfo.TagId}>{this.renderButton()}</Link>;
|
return <Link to={'/media/categories/' + this.props.tagInfo.TagId}>{this.renderButton()}</Link>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ export class ActorPage extends React.Component<Props, state> {
|
|||||||
<>
|
<>
|
||||||
<PageTitle title={this.state.actor.Name} subtitle={this.state.data ? this.state.data.length + ' videos' : null}>
|
<PageTitle title={this.state.actor.Name} subtitle={this.state.data ? this.state.data.length + ' videos' : null}>
|
||||||
<span className={style.overviewbutton}>
|
<span className={style.overviewbutton}>
|
||||||
<Link to='/actors'>
|
<Link to='/media/actors'>
|
||||||
<Button onClick={(): void => {}} title='Go to Actor overview' />
|
<Button onClick={(): void => {}} title='Go to Actor overview' />
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
|
@ -90,14 +90,12 @@ describe('<HomePage/>', function () {
|
|||||||
const wrapper = shallow(<HomePage/>);
|
const wrapper = shallow(<HomePage/>);
|
||||||
|
|
||||||
// expect those default values
|
// expect those default values
|
||||||
expect(wrapper.state().sortby).toBe('Date Added');
|
expect(wrapper.state().sortby).toBe(0);
|
||||||
expect(wrapper.instance().sortState).toBe(SortBy.date);
|
|
||||||
expect(wrapper.instance().tagState).toBe(DefaultTags.all);
|
expect(wrapper.instance().tagState).toBe(DefaultTags.all);
|
||||||
|
|
||||||
wrapper.instance().onDropDownItemClick(SortBy.name, 'namesort');
|
wrapper.instance().onDropDownItemClick(SortBy.name);
|
||||||
|
|
||||||
expect(wrapper.state().sortby).toBe('namesort');
|
expect(wrapper.state().sortby).toBe(SortBy.name);
|
||||||
expect(wrapper.instance().sortState).toBe(SortBy.name);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ interface state {
|
|||||||
subtitle: string;
|
subtitle: string;
|
||||||
data: VideoTypes.VideoUnloadedType[];
|
data: VideoTypes.VideoUnloadedType[];
|
||||||
selectionnr: number;
|
selectionnr: number;
|
||||||
sortby: string;
|
sortby: SortBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,9 +39,33 @@ export class HomePage extends React.Component<Props, state> {
|
|||||||
/** keyword variable needed temporary store search keyword */
|
/** keyword variable needed temporary store search keyword */
|
||||||
keyword = '';
|
keyword = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get text label from sort type
|
||||||
|
* @param type SortBy type
|
||||||
|
*/
|
||||||
|
getLabelFromSortType(type: SortBy): String {
|
||||||
|
switch (type) {
|
||||||
|
case SortBy.date:
|
||||||
|
return 'Date Added';
|
||||||
|
case SortBy.length:
|
||||||
|
return 'Length';
|
||||||
|
case SortBy.likes:
|
||||||
|
return 'Most likes';
|
||||||
|
case SortBy.name:
|
||||||
|
return 'Name';
|
||||||
|
case SortBy.random:
|
||||||
|
return 'Random';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
// get previously stored location from localstorage
|
||||||
|
const storedSelection = global.localStorage.getItem('sortby');
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
sideinfo: {
|
sideinfo: {
|
||||||
VideoNr: 0,
|
VideoNr: 0,
|
||||||
@ -54,11 +78,10 @@ export class HomePage extends React.Component<Props, state> {
|
|||||||
subtitle: 'All Videos',
|
subtitle: 'All Videos',
|
||||||
data: [],
|
data: [],
|
||||||
selectionnr: 0,
|
selectionnr: 0,
|
||||||
sortby: 'Date Added'
|
sortby: storedSelection == null ? SortBy.date : parseInt(storedSelection, 10)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
sortState = SortBy.date;
|
|
||||||
tagState = DefaultTags.all;
|
tagState = DefaultTags.all;
|
||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
@ -87,7 +110,7 @@ export class HomePage extends React.Component<Props, state> {
|
|||||||
fetchVideoData(): void {
|
fetchVideoData(): void {
|
||||||
callAPI(
|
callAPI(
|
||||||
APINode.Video,
|
APINode.Video,
|
||||||
{action: 'getMovies', Tag: this.tagState.TagId, Sort: this.sortState},
|
{action: 'getMovies', Tag: this.tagState.TagId, Sort: this.state.sortby},
|
||||||
(result: {Videos: VideoTypes.VideoUnloadedType[]; TagName: string}) => {
|
(result: {Videos: VideoTypes.VideoUnloadedType[]; TagName: string}) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
data: result.Videos,
|
data: result.Videos,
|
||||||
@ -190,15 +213,25 @@ export class HomePage extends React.Component<Props, state> {
|
|||||||
<span className={style.sortbyLabel}>Sort By: </span>
|
<span className={style.sortbyLabel}>Sort By: </span>
|
||||||
<div className={style.dropdown}>
|
<div className={style.dropdown}>
|
||||||
<span className={style.dropbtn}>
|
<span className={style.dropbtn}>
|
||||||
<span>{this.state.sortby}</span>
|
<span>{this.getLabelFromSortType(this.state.sortby)}</span>
|
||||||
<FontAwesomeIcon style={{marginLeft: 3, paddingBottom: 3}} icon={faSortDown} size='1x' />
|
<FontAwesomeIcon style={{marginLeft: 3, paddingBottom: 3}} icon={faSortDown} size='1x' />
|
||||||
</span>
|
</span>
|
||||||
<div className={style.dropdownContent}>
|
<div className={style.dropdownContent}>
|
||||||
<span onClick={(): void => this.onDropDownItemClick(SortBy.date, 'Date Added')}>Date Added</span>
|
<span onClick={(): void => this.onDropDownItemClick(SortBy.date)}>
|
||||||
<span onClick={(): void => this.onDropDownItemClick(SortBy.likes, 'Most likes')}>Most likes</span>
|
{this.getLabelFromSortType(SortBy.date)}
|
||||||
<span onClick={(): void => this.onDropDownItemClick(SortBy.random, 'Random')}>Random</span>
|
</span>
|
||||||
<span onClick={(): void => this.onDropDownItemClick(SortBy.name, 'Name')}>Name</span>
|
<span onClick={(): void => this.onDropDownItemClick(SortBy.likes)}>
|
||||||
<span onClick={(): void => this.onDropDownItemClick(SortBy.length, 'Length')}>Length</span>
|
{this.getLabelFromSortType(SortBy.likes)}
|
||||||
|
</span>
|
||||||
|
<span onClick={(): void => this.onDropDownItemClick(SortBy.random)}>
|
||||||
|
{this.getLabelFromSortType(SortBy.random)}
|
||||||
|
</span>
|
||||||
|
<span onClick={(): void => this.onDropDownItemClick(SortBy.name)}>
|
||||||
|
{this.getLabelFromSortType(SortBy.name)}
|
||||||
|
</span>
|
||||||
|
<span onClick={(): void => this.onDropDownItemClick(SortBy.length)}>
|
||||||
|
{this.getLabelFromSortType(SortBy.length)}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -214,10 +247,12 @@ export class HomePage extends React.Component<Props, state> {
|
|||||||
* @param type type of sort action
|
* @param type type of sort action
|
||||||
* @param name new header title
|
* @param name new header title
|
||||||
*/
|
*/
|
||||||
onDropDownItemClick(type: SortBy, name: string): void {
|
onDropDownItemClick(type: SortBy): void {
|
||||||
this.sortState = type;
|
this.setState({sortby: type}, (): void => {
|
||||||
this.setState({sortby: name});
|
global.localStorage.setItem('sortby', type.toString());
|
||||||
|
|
||||||
this.fetchVideoData();
|
this.fetchVideoData();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,18 @@ interface GetRandomMoviesType {
|
|||||||
class RandomPage extends React.Component<{}, state> {
|
class RandomPage extends React.Component<{}, state> {
|
||||||
readonly LoadNR = 3;
|
readonly LoadNR = 3;
|
||||||
|
|
||||||
|
// random seed to load videos, remains page reload.
|
||||||
|
seed = this.genRandInt();
|
||||||
|
|
||||||
constructor(props: {}) {
|
constructor(props: {}) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
// get previously stored location from localstorage
|
||||||
|
const storedseed = global.localStorage.getItem('randpageseed');
|
||||||
|
if (storedseed != null) {
|
||||||
|
this.seed = parseInt(storedseed, 10);
|
||||||
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
videos: [],
|
videos: [],
|
||||||
tags: []
|
tags: []
|
||||||
@ -36,6 +45,10 @@ class RandomPage extends React.Component<{}, state> {
|
|||||||
this.keypress = this.keypress.bind(this);
|
this.keypress = this.keypress.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
genRandInt(): number {
|
||||||
|
return Math.floor(Math.random() * 2147483647) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
addKeyHandler(this.keypress);
|
addKeyHandler(this.keypress);
|
||||||
|
|
||||||
@ -77,15 +90,21 @@ class RandomPage extends React.Component<{}, state> {
|
|||||||
* click handler for shuffle btn
|
* click handler for shuffle btn
|
||||||
*/
|
*/
|
||||||
shuffleclick(): void {
|
shuffleclick(): void {
|
||||||
|
this.genSeed();
|
||||||
this.loadShuffledvideos(this.LoadNR);
|
this.loadShuffledvideos(this.LoadNR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
genSeed(): void {
|
||||||
|
this.seed = this.genRandInt();
|
||||||
|
global.localStorage.setItem('randpageseed', this.seed.toString());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* load random videos from backend
|
* load random videos from backend
|
||||||
* @param nr number of videos to load
|
* @param nr number of videos to load
|
||||||
*/
|
*/
|
||||||
loadShuffledvideos(nr: number): void {
|
loadShuffledvideos(nr: number): void {
|
||||||
callAPI<GetRandomMoviesType>(APINode.Video, {action: 'getRandomMovies', Number: nr}, (result) => {
|
callAPI<GetRandomMoviesType>(APINode.Video, {action: 'getRandomMovies', Number: nr, Seed: this.seed}, (result) => {
|
||||||
this.setState({videos: []}); // needed to trigger rerender of main videoview
|
this.setState({videos: []}); // needed to trigger rerender of main videoview
|
||||||
this.setState({
|
this.setState({
|
||||||
videos: result.Videos,
|
videos: result.Videos,
|
||||||
@ -101,7 +120,8 @@ class RandomPage extends React.Component<{}, state> {
|
|||||||
private keypress(event: KeyboardEvent): void {
|
private keypress(event: KeyboardEvent): void {
|
||||||
// bind s to shuffle
|
// bind s to shuffle
|
||||||
if (event.key === 's') {
|
if (event.key === 's') {
|
||||||
this.loadShuffledvideos(4);
|
this.genSeed();
|
||||||
|
this.loadShuffledvideos(this.LoadNR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,5 +103,5 @@ export enum APINode {
|
|||||||
Tags = 'tags',
|
Tags = 'tags',
|
||||||
Actor = 'actor',
|
Actor = 'actor',
|
||||||
Video = 'video',
|
Video = 'video',
|
||||||
TVShow = 'tvshow'
|
TVShow = 'tv'
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user