JSX component for api requests
This commit is contained in:
		
							
								
								
									
										48
									
								
								src/elements/APIComponent.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/elements/APIComponent.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import {APINode, callAPI} from '../utils/Api';
 | 
			
		||||
 | 
			
		||||
interface Props<T> {
 | 
			
		||||
    onLoad?: JSX.Element;
 | 
			
		||||
    render: (data: T, actions: {refresh: () => void}) => JSX.Element;
 | 
			
		||||
    node: APINode;
 | 
			
		||||
    action: string;
 | 
			
		||||
    params?: {[_: string]: string | number | boolean | object};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface State {
 | 
			
		||||
    loaded: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default class APIComponent<T> extends React.Component<Props<T>, State> {
 | 
			
		||||
    state = {
 | 
			
		||||
        loaded: false
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    data: T | undefined;
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        if (this.state.loaded && this.data !== undefined) {
 | 
			
		||||
            return this.props.render(this.data, {refresh: () => this.loadData()});
 | 
			
		||||
        } else {
 | 
			
		||||
            return this.props.onLoad ? this.props.onLoad : <></>;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        this.loadData();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidUpdate(prevProps: Readonly<Props<T>>): void {
 | 
			
		||||
        if (prevProps.params !== this.props.params) {
 | 
			
		||||
            this.loadData();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private loadData(): void {
 | 
			
		||||
        this.setState({loaded: false});
 | 
			
		||||
        callAPI(this.props.node, {action: this.props.action, ...this.props.params}, (result: T) => {
 | 
			
		||||
            this.data = result;
 | 
			
		||||
            this.setState({loaded: true});
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								src/elements/KeyComponent.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/elements/KeyComponent.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
    listenKey: string;
 | 
			
		||||
    onKey: () => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default class KeyComponent extends React.Component<Props> {
 | 
			
		||||
    constructor(props: Props) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.handler = this.handler.bind(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        return <>{this.props.children}</>;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        document.addEventListener('keyup', this.handler);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentWillUnmount(): void {
 | 
			
		||||
        document.removeEventListener('keyup', this.handler);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private handler(e: KeyboardEvent): void {
 | 
			
		||||
        if (e.key === this.props.listenKey) {
 | 
			
		||||
            this.props.onKey();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -5,7 +5,7 @@ import VideoContainer from '../../elements/VideoContainer/VideoContainer';
 | 
			
		||||
 | 
			
		||||
import style from './HomePage.module.css';
 | 
			
		||||
import PageTitle, {Line} from '../../elements/PageTitle/PageTitle';
 | 
			
		||||
import {APINode, callAPI} from '../../utils/Api';
 | 
			
		||||
import {APINode} from '../../utils/Api';
 | 
			
		||||
import {Route, Switch, withRouter} from 'react-router-dom';
 | 
			
		||||
import {RouteComponentProps} from 'react-router';
 | 
			
		||||
import SearchHandling from './SearchHandling';
 | 
			
		||||
@@ -13,6 +13,8 @@ import {VideoTypes} from '../../types/ApiTypes';
 | 
			
		||||
import {DefaultTags} from '../../types/GeneralTypes';
 | 
			
		||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
 | 
			
		||||
import {faSortDown} from '@fortawesome/free-solid-svg-icons';
 | 
			
		||||
import APIComponent from '../../elements/APIComponent';
 | 
			
		||||
import {TagType} from '../../types/VideoTypes';
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line no-shadow
 | 
			
		||||
export enum SortBy {
 | 
			
		||||
@@ -26,11 +28,10 @@ export enum SortBy {
 | 
			
		||||
interface Props extends RouteComponentProps {}
 | 
			
		||||
 | 
			
		||||
interface state {
 | 
			
		||||
    sideinfo: VideoTypes.startDataType;
 | 
			
		||||
    subtitle: string;
 | 
			
		||||
    data: VideoTypes.VideoUnloadedType[];
 | 
			
		||||
    selectionnr: number;
 | 
			
		||||
    sortby: string;
 | 
			
		||||
    sortState: SortBy;
 | 
			
		||||
    tagState: TagType;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -40,166 +41,130 @@ export class HomePage extends React.Component<Props, state> {
 | 
			
		||||
    /** keyword variable needed temporary store search keyword */
 | 
			
		||||
    keyword = '';
 | 
			
		||||
 | 
			
		||||
    constructor(props: Props) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            sideinfo: {
 | 
			
		||||
                VideoNr: 0,
 | 
			
		||||
                FullHdNr: 0,
 | 
			
		||||
                HDNr: 0,
 | 
			
		||||
                SDNr: 0,
 | 
			
		||||
                DifferentTags: 0,
 | 
			
		||||
                Tagged: 0
 | 
			
		||||
            },
 | 
			
		||||
            subtitle: 'All Videos',
 | 
			
		||||
            data: [],
 | 
			
		||||
            selectionnr: 0,
 | 
			
		||||
            sortby: 'Date Added'
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sortState = SortBy.date;
 | 
			
		||||
    tagState = DefaultTags.all;
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        // initial get of all videos
 | 
			
		||||
        this.fetchVideoData();
 | 
			
		||||
        this.fetchStartData();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * fetch available videos for specified tag
 | 
			
		||||
     * this function clears all preview elements an reloads gravity with tag
 | 
			
		||||
     *
 | 
			
		||||
     * @param tag tag to fetch videos
 | 
			
		||||
     */
 | 
			
		||||
    fetchVideoData(): void {
 | 
			
		||||
        callAPI(
 | 
			
		||||
            APINode.Video,
 | 
			
		||||
            {action: 'getMovies', Tag: this.tagState.TagId, Sort: this.sortState},
 | 
			
		||||
            (result: {Videos: VideoTypes.VideoUnloadedType[]; TagName: string}) => {
 | 
			
		||||
                this.setState({
 | 
			
		||||
                    data: result.Videos,
 | 
			
		||||
                    selectionnr: result.Videos.length
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * fetch the necessary data for left info box
 | 
			
		||||
     */
 | 
			
		||||
    fetchStartData(): void {
 | 
			
		||||
        callAPI(APINode.Video, {action: 'getStartData'}, (result: VideoTypes.startDataType) => {
 | 
			
		||||
            this.setState({sideinfo: result});
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    state = {
 | 
			
		||||
        subtitle: 'All Videos',
 | 
			
		||||
        sortby: 'Date Added',
 | 
			
		||||
        sortState: SortBy.date,
 | 
			
		||||
        tagState: DefaultTags.all
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        return (
 | 
			
		||||
            <>
 | 
			
		||||
                <Switch>
 | 
			
		||||
                    <Route path='/search/:name'>
 | 
			
		||||
                        <SearchHandling />
 | 
			
		||||
                    </Route>
 | 
			
		||||
                    <Route path='/'>
 | 
			
		||||
                        <PageTitle title='Home Page' subtitle={this.state.subtitle + ' - ' + this.state.selectionnr}>
 | 
			
		||||
                            <form
 | 
			
		||||
                                className={'form-inline ' + style.searchform}
 | 
			
		||||
                                onSubmit={(e): void => {
 | 
			
		||||
                                    e.preventDefault();
 | 
			
		||||
                                    this.props.history.push('/search/' + this.keyword);
 | 
			
		||||
                                }}>
 | 
			
		||||
                                <input
 | 
			
		||||
                                    data-testid='searchtextfield'
 | 
			
		||||
                                    className='form-control mr-sm-2'
 | 
			
		||||
                                    type='text'
 | 
			
		||||
                                    placeholder='Search'
 | 
			
		||||
                                    onChange={(e): void => {
 | 
			
		||||
                                        this.keyword = e.target.value;
 | 
			
		||||
                                    }}
 | 
			
		||||
                                />
 | 
			
		||||
                                <button data-testid='searchbtnsubmit' className='btn btn-success' type='submit'>
 | 
			
		||||
                                    Search
 | 
			
		||||
                                </button>
 | 
			
		||||
                            </form>
 | 
			
		||||
                        </PageTitle>
 | 
			
		||||
                        <SideBar>
 | 
			
		||||
                            <SideBarTitle>Infos:</SideBarTitle>
 | 
			
		||||
                            <Line />
 | 
			
		||||
                            <SideBarItem>
 | 
			
		||||
                                <b>{this.state.sideinfo.VideoNr}</b> Videos Total!
 | 
			
		||||
                            </SideBarItem>
 | 
			
		||||
                            <SideBarItem>
 | 
			
		||||
                                <b>{this.state.sideinfo.FullHdNr}</b> FULL-HD Videos!
 | 
			
		||||
                            </SideBarItem>
 | 
			
		||||
                            <SideBarItem>
 | 
			
		||||
                                <b>{this.state.sideinfo.HDNr}</b> HD Videos!
 | 
			
		||||
                            </SideBarItem>
 | 
			
		||||
                            <SideBarItem>
 | 
			
		||||
                                <b>{this.state.sideinfo.SDNr}</b> SD Videos!
 | 
			
		||||
                            </SideBarItem>
 | 
			
		||||
                            <SideBarItem>
 | 
			
		||||
                                <b>{this.state.sideinfo.DifferentTags}</b> different Tags!
 | 
			
		||||
                            </SideBarItem>
 | 
			
		||||
                            <Line />
 | 
			
		||||
                            <SideBarTitle>Default Tags:</SideBarTitle>
 | 
			
		||||
                            <Tag
 | 
			
		||||
                                tagInfo={{TagName: 'All', TagId: DefaultTags.all.TagId}}
 | 
			
		||||
                                onclick={(): void => {
 | 
			
		||||
                                    this.tagState = DefaultTags.all;
 | 
			
		||||
                                    this.fetchVideoData();
 | 
			
		||||
                                    this.setState({subtitle: 'All Videos'});
 | 
			
		||||
                                }}
 | 
			
		||||
                            />
 | 
			
		||||
                            <Tag
 | 
			
		||||
                                tagInfo={{TagName: 'Full Hd', TagId: DefaultTags.fullhd.TagId}}
 | 
			
		||||
                                onclick={(): void => {
 | 
			
		||||
                                    this.tagState = DefaultTags.fullhd;
 | 
			
		||||
                                    this.fetchVideoData();
 | 
			
		||||
                                    this.setState({subtitle: 'Full Hd Videos'});
 | 
			
		||||
                                }}
 | 
			
		||||
                            />
 | 
			
		||||
                            <Tag
 | 
			
		||||
                                tagInfo={{TagName: 'Low Quality', TagId: DefaultTags.lowq.TagId}}
 | 
			
		||||
                                onclick={(): void => {
 | 
			
		||||
                                    this.tagState = DefaultTags.lowq;
 | 
			
		||||
                                    this.fetchVideoData();
 | 
			
		||||
                                    this.setState({subtitle: 'Low Quality Videos'});
 | 
			
		||||
                                }}
 | 
			
		||||
                            />
 | 
			
		||||
                            <Tag
 | 
			
		||||
                                tagInfo={{TagName: 'HD', TagId: DefaultTags.hd.TagId}}
 | 
			
		||||
                                onclick={(): void => {
 | 
			
		||||
                                    this.tagState = DefaultTags.hd;
 | 
			
		||||
                                    this.fetchVideoData();
 | 
			
		||||
                                    this.setState({subtitle: 'HD Videos'});
 | 
			
		||||
                                }}
 | 
			
		||||
                            />
 | 
			
		||||
                        </SideBar>
 | 
			
		||||
                        <div>
 | 
			
		||||
                            <span className={style.sortbyLabel}>Sort By: </span>
 | 
			
		||||
                            <div className={style.dropdown}>
 | 
			
		||||
                                <span className={style.dropbtn}>
 | 
			
		||||
                                    <span>{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>
 | 
			
		||||
            <Switch>
 | 
			
		||||
                <Route path='/search/:name'>
 | 
			
		||||
                    <SearchHandling />
 | 
			
		||||
                </Route>
 | 
			
		||||
                <Route path='/'>
 | 
			
		||||
                    <APIComponent
 | 
			
		||||
                        render={(data: {Videos: VideoTypes.VideoUnloadedType[]; TagName: string}): JSX.Element => (
 | 
			
		||||
                            <>
 | 
			
		||||
                                <PageTitle title='Home Page' subtitle={this.state.subtitle + ' - ' + data.Videos.length}>
 | 
			
		||||
                                    <form
 | 
			
		||||
                                        className={'form-inline ' + style.searchform}
 | 
			
		||||
                                        onSubmit={(e): void => {
 | 
			
		||||
                                            e.preventDefault();
 | 
			
		||||
                                            this.props.history.push('/search/' + this.keyword);
 | 
			
		||||
                                        }}>
 | 
			
		||||
                                        <input
 | 
			
		||||
                                            data-testid='searchtextfield'
 | 
			
		||||
                                            className='form-control mr-sm-2'
 | 
			
		||||
                                            type='text'
 | 
			
		||||
                                            placeholder='Search'
 | 
			
		||||
                                            onChange={(e): void => {
 | 
			
		||||
                                                this.keyword = e.target.value;
 | 
			
		||||
                                            }}
 | 
			
		||||
                                        />
 | 
			
		||||
                                        <button data-testid='searchbtnsubmit' className='btn btn-success' type='submit'>
 | 
			
		||||
                                            Search
 | 
			
		||||
                                        </button>
 | 
			
		||||
                                    </form>
 | 
			
		||||
                                </PageTitle>
 | 
			
		||||
                                <SideBar>
 | 
			
		||||
                                    <APIComponent
 | 
			
		||||
                                        render={(sidebardata: VideoTypes.startDataType): JSX.Element => (
 | 
			
		||||
                                            <>
 | 
			
		||||
                                                <SideBarTitle>Infos:</SideBarTitle>
 | 
			
		||||
                                                <Line />
 | 
			
		||||
                                                <SideBarItem>
 | 
			
		||||
                                                    <b>{sidebardata.VideoNr}</b> Videos Total!
 | 
			
		||||
                                                </SideBarItem>
 | 
			
		||||
                                                <SideBarItem>
 | 
			
		||||
                                                    <b>{sidebardata.FullHdNr}</b> FULL-HD Videos!
 | 
			
		||||
                                                </SideBarItem>
 | 
			
		||||
                                                <SideBarItem>
 | 
			
		||||
                                                    <b>{sidebardata.HDNr}</b> HD Videos!
 | 
			
		||||
                                                </SideBarItem>
 | 
			
		||||
                                                <SideBarItem>
 | 
			
		||||
                                                    <b>{sidebardata.SDNr}</b> SD Videos!
 | 
			
		||||
                                                </SideBarItem>
 | 
			
		||||
                                                <SideBarItem>
 | 
			
		||||
                                                    <b>{sidebardata.DifferentTags}</b> different Tags!
 | 
			
		||||
                                                </SideBarItem>
 | 
			
		||||
                                                <Line />
 | 
			
		||||
                                                <SideBarTitle>Default Tags:</SideBarTitle>
 | 
			
		||||
                                                <Tag
 | 
			
		||||
                                                    tagInfo={{TagName: 'All', TagId: DefaultTags.all.TagId}}
 | 
			
		||||
                                                    onclick={(): void => {
 | 
			
		||||
                                                        this.setState({tagState: DefaultTags.all, subtitle: 'All Videos'});
 | 
			
		||||
                                                    }}
 | 
			
		||||
                                                />
 | 
			
		||||
                                                <Tag
 | 
			
		||||
                                                    tagInfo={{TagName: 'Full Hd', TagId: DefaultTags.fullhd.TagId}}
 | 
			
		||||
                                                    onclick={(): void => {
 | 
			
		||||
                                                        this.setState({tagState: DefaultTags.fullhd, subtitle: 'Full Hd Videos'});
 | 
			
		||||
                                                    }}
 | 
			
		||||
                                                />
 | 
			
		||||
                                                <Tag
 | 
			
		||||
                                                    tagInfo={{TagName: 'Low Quality', TagId: DefaultTags.lowq.TagId}}
 | 
			
		||||
                                                    onclick={(): void => {
 | 
			
		||||
                                                        this.setState({
 | 
			
		||||
                                                            tagState: DefaultTags.lowq,
 | 
			
		||||
                                                            subtitle: 'Low Quality Videos'
 | 
			
		||||
                                                        });
 | 
			
		||||
                                                    }}
 | 
			
		||||
                                                />
 | 
			
		||||
                                                <Tag
 | 
			
		||||
                                                    tagInfo={{TagName: 'HD', TagId: DefaultTags.hd.TagId}}
 | 
			
		||||
                                                    onclick={(): void => {
 | 
			
		||||
                                                        this.setState({tagState: DefaultTags.hd, subtitle: 'HD Videos'});
 | 
			
		||||
                                                    }}
 | 
			
		||||
                                                />
 | 
			
		||||
                                            </>
 | 
			
		||||
                                        )}
 | 
			
		||||
                                        node={APINode.Video}
 | 
			
		||||
                                        action='getStartData'
 | 
			
		||||
                                    />
 | 
			
		||||
                                </SideBar>
 | 
			
		||||
                                <div>
 | 
			
		||||
                                    <span className={style.sortbyLabel}>Sort By: </span>
 | 
			
		||||
                                    <div className={style.dropdown}>
 | 
			
		||||
                                        <span className={style.dropbtn}>
 | 
			
		||||
                                            <span>{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>
 | 
			
		||||
                                        </div>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
 | 
			
		||||
                        <VideoContainer data={this.state.data} />
 | 
			
		||||
                        <div className={style.rightinfo} />
 | 
			
		||||
                    </Route>
 | 
			
		||||
                </Switch>
 | 
			
		||||
            </>
 | 
			
		||||
                                <VideoContainer data={data.Videos} />
 | 
			
		||||
                                <div className={style.rightinfo} />
 | 
			
		||||
                            </>
 | 
			
		||||
                        )}
 | 
			
		||||
                        node={APINode.Video}
 | 
			
		||||
                        action='getMovies'
 | 
			
		||||
                        params={{Tag: this.state.tagState.TagId, Sort: this.state.sortState}}
 | 
			
		||||
                    />
 | 
			
		||||
                </Route>
 | 
			
		||||
            </Switch>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -209,9 +174,7 @@ export class HomePage extends React.Component<Props, state> {
 | 
			
		||||
     * @param name new header title
 | 
			
		||||
     */
 | 
			
		||||
    onDropDownItemClick(type: SortBy, name: string): void {
 | 
			
		||||
        this.sortState = type;
 | 
			
		||||
        this.setState({sortby: name});
 | 
			
		||||
        this.fetchVideoData();
 | 
			
		||||
        this.setState({sortby: name, sortState: type});
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,15 +4,11 @@ import SideBar, {SideBarTitle} from '../../elements/SideBar/SideBar';
 | 
			
		||||
import Tag from '../../elements/Tag/Tag';
 | 
			
		||||
import PageTitle from '../../elements/PageTitle/PageTitle';
 | 
			
		||||
import VideoContainer from '../../elements/VideoContainer/VideoContainer';
 | 
			
		||||
import {APINode, callAPI} from '../../utils/Api';
 | 
			
		||||
import {APINode} from '../../utils/Api';
 | 
			
		||||
import {TagType} from '../../types/VideoTypes';
 | 
			
		||||
import {VideoTypes} from '../../types/ApiTypes';
 | 
			
		||||
import {addKeyHandler, removeKeyHandler} from '../../utils/ShortkeyHandler';
 | 
			
		||||
 | 
			
		||||
interface state {
 | 
			
		||||
    videos: VideoTypes.VideoUnloadedType[];
 | 
			
		||||
    tags: TagType[];
 | 
			
		||||
}
 | 
			
		||||
import APIComponent from '../../elements/APIComponent';
 | 
			
		||||
import KeyComponent from '../../elements/KeyComponent';
 | 
			
		||||
 | 
			
		||||
interface GetRandomMoviesType {
 | 
			
		||||
    Videos: VideoTypes.VideoUnloadedType[];
 | 
			
		||||
@@ -22,88 +18,43 @@ interface GetRandomMoviesType {
 | 
			
		||||
/**
 | 
			
		||||
 * Randompage shuffles random viedeopreviews and provides a shuffle btn
 | 
			
		||||
 */
 | 
			
		||||
class RandomPage extends React.Component<{}, state> {
 | 
			
		||||
class RandomPage extends React.Component {
 | 
			
		||||
    readonly LoadNR = 3;
 | 
			
		||||
 | 
			
		||||
    constructor(props: {}) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            videos: [],
 | 
			
		||||
            tags: []
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.keypress = this.keypress.bind(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        addKeyHandler(this.keypress);
 | 
			
		||||
 | 
			
		||||
        this.loadShuffledvideos(this.LoadNR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentWillUnmount(): void {
 | 
			
		||||
        removeKeyHandler(this.keypress);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        return (
 | 
			
		||||
            <div>
 | 
			
		||||
                <PageTitle title='Random Videos' subtitle='4pc' />
 | 
			
		||||
                <PageTitle title='Random Videos' subtitle={this.LoadNR + 'pcs'} />
 | 
			
		||||
                <APIComponent
 | 
			
		||||
                    render={(data: GetRandomMoviesType, actions): JSX.Element => (
 | 
			
		||||
                        <KeyComponent listenKey='s' onKey={actions.refresh}>
 | 
			
		||||
                            <SideBar>
 | 
			
		||||
                                <SideBarTitle>Visible Tags:</SideBarTitle>
 | 
			
		||||
                                {data.Tags.map((m) => (
 | 
			
		||||
                                    <Tag key={m.TagId} tagInfo={m} />
 | 
			
		||||
                                ))}
 | 
			
		||||
                            </SideBar>
 | 
			
		||||
 | 
			
		||||
                <SideBar>
 | 
			
		||||
                    <SideBarTitle>Visible Tags:</SideBarTitle>
 | 
			
		||||
                    {this.state.tags.map((m) => (
 | 
			
		||||
                        <Tag key={m.TagId} tagInfo={m} />
 | 
			
		||||
                    ))}
 | 
			
		||||
                </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>
 | 
			
		||||
                )}
 | 
			
		||||
                            {data.Videos.length !== 0 ? (
 | 
			
		||||
                                <VideoContainer data={data.Videos}>
 | 
			
		||||
                                    <div className={style.Shufflebutton}>
 | 
			
		||||
                                        <button onClick={actions.refresh} className={style.btnshuffle}>
 | 
			
		||||
                                            Shuffle
 | 
			
		||||
                                        </button>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </VideoContainer>
 | 
			
		||||
                            ) : (
 | 
			
		||||
                                <div>No Data found!</div>
 | 
			
		||||
                            )}
 | 
			
		||||
                        </KeyComponent>
 | 
			
		||||
                    )}
 | 
			
		||||
                    node={APINode.Video}
 | 
			
		||||
                    action='getRandomMovies'
 | 
			
		||||
                    params={{Number: this.LoadNR}}
 | 
			
		||||
                />
 | 
			
		||||
            </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
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * key event handling
 | 
			
		||||
     * @param event keyevent
 | 
			
		||||
     */
 | 
			
		||||
    private keypress(event: KeyboardEvent): void {
 | 
			
		||||
        // bind s to shuffle
 | 
			
		||||
        if (event.key === 's') {
 | 
			
		||||
            this.loadShuffledvideos(4);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default RandomPage;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user