Compare commits

...

2 Commits

Author SHA1 Message Date
9b23666fe6 remember a shuffle seed to remain page reload 2022-03-06 16:01:04 +01:00
1adafef4e1 remember sortby selection with localstorage 2022-03-01 13:20:39 +01:00
4 changed files with 83 additions and 22 deletions

View File

@ -2,6 +2,7 @@ package api
import (
"fmt"
"math/rand"
"net/url"
"openmediacenter/apiGo/api/api"
"openmediacenter/apiGo/api/types"
@ -163,18 +164,25 @@ func getVideoHandlers() {
api.AddHandler("getRandomMovies", api.VideoNode, api.PermUser, func(context api.Context) {
var args struct {
Number int
Seed *int
}
if api.DecodeRequest(context.GetRequest(), &args) != nil {
context.Text("unable to decode request")
return
}
// if Seed argument not passed generate random seed
if args.Seed == nil {
r := rand.Int()
args.Seed = &r
}
var result struct {
Tags []types.Tag
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))
var ids string

View File

@ -90,14 +90,12 @@ describe('<HomePage/>', function () {
const wrapper = shallow(<HomePage/>);
// expect those default values
expect(wrapper.state().sortby).toBe('Date Added');
expect(wrapper.instance().sortState).toBe(SortBy.date);
expect(wrapper.state().sortby).toBe(0);
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.instance().sortState).toBe(SortBy.name);
expect(wrapper.state().sortby).toBe(SortBy.name);
});
});

View File

@ -29,7 +29,7 @@ interface state {
subtitle: string;
data: VideoTypes.VideoUnloadedType[];
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 = '';
/**
* 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) {
super(props);
// get previously stored location from localstorage
const storedSelection = global.localStorage.getItem('sortby');
this.state = {
sideinfo: {
VideoNr: 0,
@ -54,11 +78,10 @@ export class HomePage extends React.Component<Props, state> {
subtitle: 'All Videos',
data: [],
selectionnr: 0,
sortby: 'Date Added'
sortby: storedSelection == null ? SortBy.date : parseInt(storedSelection, 10)
};
}
sortState = SortBy.date;
tagState = DefaultTags.all;
componentDidMount(): void {
@ -87,7 +110,7 @@ export class HomePage extends React.Component<Props, state> {
fetchVideoData(): void {
callAPI(
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}) => {
this.setState({
data: result.Videos,
@ -190,15 +213,25 @@ export class HomePage extends React.Component<Props, state> {
<span className={style.sortbyLabel}>Sort By: </span>
<div className={style.dropdown}>
<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' />
</span>
<div className={style.dropdownContent}>
<span onClick={(): void => this.onDropDownItemClick(SortBy.date, 'Date Added')}>Date Added</span>
<span onClick={(): void => this.onDropDownItemClick(SortBy.likes, 'Most likes')}>Most likes</span>
<span onClick={(): void => this.onDropDownItemClick(SortBy.random, 'Random')}>Random</span>
<span onClick={(): void => this.onDropDownItemClick(SortBy.name, 'Name')}>Name</span>
<span onClick={(): void => this.onDropDownItemClick(SortBy.length, 'Length')}>Length</span>
<span onClick={(): void => this.onDropDownItemClick(SortBy.date)}>
{this.getLabelFromSortType(SortBy.date)}
</span>
<span onClick={(): void => this.onDropDownItemClick(SortBy.likes)}>
{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>
@ -214,10 +247,12 @@ export class HomePage extends React.Component<Props, state> {
* @param type type of sort action
* @param name new header title
*/
onDropDownItemClick(type: SortBy, name: string): void {
this.sortState = type;
this.setState({sortby: name});
this.fetchVideoData();
onDropDownItemClick(type: SortBy): void {
this.setState({sortby: type}, (): void => {
global.localStorage.setItem('sortby', type.toString());
this.fetchVideoData();
});
}
}

View File

@ -25,9 +25,18 @@ interface GetRandomMoviesType {
class RandomPage extends React.Component<{}, state> {
readonly LoadNR = 3;
// random seed to load videos, remains page reload.
seed = this.genRandInt();
constructor(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 = {
videos: [],
tags: []
@ -36,6 +45,10 @@ class RandomPage extends React.Component<{}, state> {
this.keypress = this.keypress.bind(this);
}
genRandInt(): number {
return Math.floor(Math.random() * 2147483647) + 1;
}
componentDidMount(): void {
addKeyHandler(this.keypress);
@ -77,15 +90,21 @@ class RandomPage extends React.Component<{}, state> {
* click handler for shuffle btn
*/
shuffleclick(): void {
this.genSeed();
this.loadShuffledvideos(this.LoadNR);
}
genSeed(): void {
this.seed = this.genRandInt();
global.localStorage.setItem('randpageseed', this.seed.toString());
}
/**
* 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) => {
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: result.Videos,
@ -101,7 +120,8 @@ class RandomPage extends React.Component<{}, state> {
private keypress(event: KeyboardEvent): void {
// bind s to shuffle
if (event.key === 's') {
this.loadShuffledvideos(4);
this.genSeed();
this.loadShuffledvideos(this.LoadNR);
}
}
}