bind enter events as a submit to Popups
add s as key to submit a reshuffle in shuffled videos
This commit is contained in:
		@@ -28,11 +28,9 @@ class ActorTile extends React.Component<props> {
 | 
			
		||||
                </Link>
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    renderActorTile(customclickhandler: (actor: ActorType) => void): JSX.Element {
 | 
			
		||||
        console.log(this.props.actor);
 | 
			
		||||
        return (
 | 
			
		||||
            <div className={style.actortile} onClick={(): void => customclickhandler(this.props.actor)}>
 | 
			
		||||
                <div className={style.actortile_thumbnail}>
 | 
			
		||||
 
 | 
			
		||||
@@ -74,4 +74,16 @@ describe('<AddActorPopup/>', function () {
 | 
			
		||||
 | 
			
		||||
        expect(wrapper.find('PopupBase').find('ActorTile')).toHaveLength(0);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('test Enter submit if only one element left', function () {
 | 
			
		||||
        const wrapper = shallow(<AddActorPopup/>);
 | 
			
		||||
 | 
			
		||||
        callAPIMock({});
 | 
			
		||||
 | 
			
		||||
        wrapper.setState({actors: [{name: 'test', actor_id: 1}]});
 | 
			
		||||
 | 
			
		||||
        wrapper.find('PopupBase').props().ParentSubmit();
 | 
			
		||||
 | 
			
		||||
        expect(callAPI).toHaveBeenCalledTimes(1);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ import {GeneralSuccess} from '../../../types/GeneralTypes';
 | 
			
		||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
 | 
			
		||||
import {faFilter, faTimes} from '@fortawesome/free-solid-svg-icons';
 | 
			
		||||
import {Button} from '../../GPElements/Button';
 | 
			
		||||
import {addKeyHandler, removeKeyHandler} from '../../../utils/ShortkeyHandler';
 | 
			
		||||
 | 
			
		||||
interface props {
 | 
			
		||||
    onHide: () => void;
 | 
			
		||||
@@ -41,6 +42,19 @@ class AddActorPopup extends React.Component<props, state> {
 | 
			
		||||
 | 
			
		||||
        this.tileClickHandler = this.tileClickHandler.bind(this);
 | 
			
		||||
        this.filterSearch = this.filterSearch.bind(this);
 | 
			
		||||
        this.parentSubmit = this.parentSubmit.bind(this);
 | 
			
		||||
        this.keypress = this.keypress.bind(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentWillUnmount(): void {
 | 
			
		||||
        removeKeyHandler(this.keypress);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        addKeyHandler(this.keypress);
 | 
			
		||||
 | 
			
		||||
        // fetch the available actors
 | 
			
		||||
        this.loadActors();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
@@ -52,18 +66,13 @@ class AddActorPopup extends React.Component<props, state> {
 | 
			
		||||
                        className={style.newactorbutton}
 | 
			
		||||
                        onClick={(): void => {
 | 
			
		||||
                            this.setState({contentDefault: false});
 | 
			
		||||
                        }}>Create new Actor</button>}>
 | 
			
		||||
                        }}>Create new Actor</button>} ParentSubmit={this.parentSubmit}>
 | 
			
		||||
                    {this.resolvePage()}
 | 
			
		||||
                </PopupBase>
 | 
			
		||||
            </>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        // fetch the available actors
 | 
			
		||||
        this.loadActors();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * selector for current showing popup page
 | 
			
		||||
     * @returns {JSX.Element}
 | 
			
		||||
@@ -101,15 +110,13 @@ class AddActorPopup extends React.Component<props, state> {
 | 
			
		||||
                                        this.setState({filter: '', filtervisible: false});
 | 
			
		||||
                                    }}/>
 | 
			
		||||
                                </> :
 | 
			
		||||
                                <Button title={<span>Filter <FontAwesomeIcon style={{
 | 
			
		||||
                                    verticalAlign: 'middle',
 | 
			
		||||
                                    lineHeight: '130px'
 | 
			
		||||
                                }} icon={faFilter} size='1x'/></span>} color={{backgroundColor: 'cornflowerblue', color: 'white'}} onClick={(): void => {
 | 
			
		||||
                                    this.setState({filtervisible: true}, () => {
 | 
			
		||||
                                        // focus filterfield after state update
 | 
			
		||||
                                        this.filterfield?.focus();
 | 
			
		||||
                                    });
 | 
			
		||||
                                }}/>
 | 
			
		||||
                                <Button
 | 
			
		||||
                                    title={<span>Filter <FontAwesomeIcon style={{
 | 
			
		||||
                                        verticalAlign: 'middle',
 | 
			
		||||
                                        lineHeight: '130px'
 | 
			
		||||
                                    }} icon={faFilter} size='1x'/></span>}
 | 
			
		||||
                                    color={{backgroundColor: 'cornflowerblue', color: 'white'}}
 | 
			
		||||
                                    onClick={(): void => this.enableFilterField()}/>
 | 
			
		||||
                        }
 | 
			
		||||
                    </div>
 | 
			
		||||
                    {this.state.actors.filter(this.filterSearch).map((el) => (<ActorTile actor={el} onClick={this.tileClickHandler}/>))}
 | 
			
		||||
@@ -120,6 +127,16 @@ class AddActorPopup extends React.Component<props, state> {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * enable filterfield and focus into searchbar
 | 
			
		||||
     */
 | 
			
		||||
    private enableFilterField(): void {
 | 
			
		||||
        this.setState({filtervisible: true}, () => {
 | 
			
		||||
            // focus filterfield after state update
 | 
			
		||||
            this.filterfield?.focus();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * event handling for ActorTile Click
 | 
			
		||||
     */
 | 
			
		||||
@@ -155,6 +172,30 @@ class AddActorPopup extends React.Component<props, state> {
 | 
			
		||||
    private filterSearch(actor: ActorType): boolean {
 | 
			
		||||
        return actor.name.toLowerCase().includes(this.state.filter.toLowerCase());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * handle a Popupbase parent submit action
 | 
			
		||||
     */
 | 
			
		||||
    private parentSubmit(): void {
 | 
			
		||||
        // allow submit only if one item is left in selection
 | 
			
		||||
        const filteredList = this.state.actors.filter(this.filterSearch);
 | 
			
		||||
 | 
			
		||||
        if (filteredList.length === 1) {
 | 
			
		||||
            // simulate click if parent submit
 | 
			
		||||
            this.tileClickHandler(filteredList[0]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * key event handling
 | 
			
		||||
     * @param event keyevent
 | 
			
		||||
     */
 | 
			
		||||
    private keypress(event: KeyboardEvent): void {
 | 
			
		||||
        // hide if escape is pressed
 | 
			
		||||
        if (event.key === 'f') {
 | 
			
		||||
            this.enableFilterField();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default AddActorPopup;
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,6 @@ class AddTagPopup extends React.Component<props, state> {
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        callAPI('tags.php', {action: 'getAllTags'}, (result: TagType[]) => {
 | 
			
		||||
            console.log(result);
 | 
			
		||||
            this.setState({
 | 
			
		||||
                items: result
 | 
			
		||||
            });
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ class NewTagPopup extends React.Component<props> {
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        return (
 | 
			
		||||
            <PopupBase title='Add new Tag' onHide={this.props.onHide} height='200px' width='400px'>
 | 
			
		||||
            <PopupBase title='Add new Tag' onHide={this.props.onHide} height='200px' width='400px' ParentSubmit={(): void => this.storeselection()}>
 | 
			
		||||
                <div><input type='text' placeholder='Tagname' onChange={(v): void => {
 | 
			
		||||
                    this.value = v.target.value;
 | 
			
		||||
                }}/></div>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,16 @@ describe('<PopupBase/>', function () {
 | 
			
		||||
        wrapper.unmount();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('simulate keypress', function () {
 | 
			
		||||
        let events = [];
 | 
			
		||||
    let events;
 | 
			
		||||
    function mockKeyPress(){
 | 
			
		||||
        events = [];
 | 
			
		||||
        document.addEventListener = jest.fn((event, cb) => {
 | 
			
		||||
            events[event] = cb;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    it('simulate keypress', function () {
 | 
			
		||||
        mockKeyPress();
 | 
			
		||||
        const func = jest.fn();
 | 
			
		||||
        shallow(<PopupBase onHide={() => func()}/>);
 | 
			
		||||
 | 
			
		||||
@@ -23,4 +27,14 @@ describe('<PopupBase/>', function () {
 | 
			
		||||
        expect(func).toBeCalledTimes(1);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('test an Enter sumit', function () {
 | 
			
		||||
        mockKeyPress();
 | 
			
		||||
        const func = jest.fn();
 | 
			
		||||
        shallow(<PopupBase ParentSubmit={() => func()}/>);
 | 
			
		||||
 | 
			
		||||
        // trigger the keypress event
 | 
			
		||||
        events.keyup({key: 'Enter'});
 | 
			
		||||
 | 
			
		||||
        expect(func).toBeCalledTimes(1);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,15 @@ import GlobalInfos from '../../utils/GlobalInfos';
 | 
			
		||||
import style from './PopupBase.module.css';
 | 
			
		||||
import {Line} from '../PageTitle/PageTitle';
 | 
			
		||||
import React, {RefObject} from 'react';
 | 
			
		||||
import {addKeyHandler, removeKeyHandler} from '../../utils/ShortkeyHandler';
 | 
			
		||||
 | 
			
		||||
interface props {
 | 
			
		||||
    width?: string;
 | 
			
		||||
    height?: string;
 | 
			
		||||
    banner?: JSX.Element;
 | 
			
		||||
    title: string;
 | 
			
		||||
    onHide: () => void
 | 
			
		||||
    onHide: () => void;
 | 
			
		||||
    ParentSubmit?: () => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -38,7 +40,7 @@ class PopupBase extends React.Component<props> {
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        document.addEventListener('mousedown', this.handleClickOutside);
 | 
			
		||||
        document.addEventListener('keyup', this.keypress);
 | 
			
		||||
        addKeyHandler(this.keypress);
 | 
			
		||||
 | 
			
		||||
        // add element drag drop events
 | 
			
		||||
        if (this.wrapperRef != null) {
 | 
			
		||||
@@ -49,7 +51,7 @@ class PopupBase extends React.Component<props> {
 | 
			
		||||
    componentWillUnmount(): void {
 | 
			
		||||
        // remove the appended listeners
 | 
			
		||||
        document.removeEventListener('mousedown', this.handleClickOutside);
 | 
			
		||||
        document.removeEventListener('keyup', this.keypress);
 | 
			
		||||
        removeKeyHandler(this.keypress);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
@@ -86,6 +88,9 @@ class PopupBase extends React.Component<props> {
 | 
			
		||||
        // hide if escape is pressed
 | 
			
		||||
        if (event.key === 'Escape') {
 | 
			
		||||
            this.props.onHide();
 | 
			
		||||
        } else if (event.key === 'Enter') {
 | 
			
		||||
            // call a parentsubmit if defined
 | 
			
		||||
            if (this.props.ParentSubmit) this.props.ParentSubmit();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
import {shallow} from 'enzyme';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import RandomPage from './RandomPage';
 | 
			
		||||
import {callAPI} from '../../utils/Api';
 | 
			
		||||
import PopupBase from '../../elements/Popups/PopupBase';
 | 
			
		||||
 | 
			
		||||
describe('<RandomPage/>', function () {
 | 
			
		||||
    it('renders without crashing ', function () {
 | 
			
		||||
@@ -45,4 +47,20 @@ describe('<RandomPage/>', function () {
 | 
			
		||||
 | 
			
		||||
        expect(wrapper.find('Tag')).toHaveLength(2);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('test shortkey press', function () {
 | 
			
		||||
        let events = [];
 | 
			
		||||
        document.addEventListener = jest.fn((event, cb) => {
 | 
			
		||||
            events[event] = cb;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        shallow(<RandomPage/>);
 | 
			
		||||
 | 
			
		||||
        callAPIMock({rows: [], tags: []});
 | 
			
		||||
 | 
			
		||||
        // trigger the keypress event
 | 
			
		||||
        events.keyup({key: 's'});
 | 
			
		||||
 | 
			
		||||
        expect(callAPI).toBeCalledTimes(1);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ import VideoContainer from '../../elements/VideoContainer/VideoContainer';
 | 
			
		||||
import {callAPI} from '../../utils/Api';
 | 
			
		||||
import {TagType} from '../../types/VideoTypes';
 | 
			
		||||
import {VideoTypes} from '../../types/ApiTypes';
 | 
			
		||||
import {addKeyHandler, removeKeyHandler} from '../../utils/ShortkeyHandler';
 | 
			
		||||
 | 
			
		||||
interface state {
 | 
			
		||||
    videos: VideoTypes.VideoUnloadedType[];
 | 
			
		||||
@@ -29,12 +30,20 @@ class RandomPage extends React.Component<{}, state> {
 | 
			
		||||
            videos: [],
 | 
			
		||||
            tags: []
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.keypress = this.keypress.bind(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        addKeyHandler(this.keypress);
 | 
			
		||||
 | 
			
		||||
        this.loadShuffledvideos(4);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentWillUnmount(): void {
 | 
			
		||||
        removeKeyHandler(this.keypress);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        return (
 | 
			
		||||
            <div>
 | 
			
		||||
@@ -75,8 +84,6 @@ class RandomPage extends React.Component<{}, state> {
 | 
			
		||||
     */
 | 
			
		||||
    loadShuffledvideos(nr: number): void {
 | 
			
		||||
        callAPI<GetRandomMoviesType>('video.php', {action: 'getRandomMovies', number: nr}, result => {
 | 
			
		||||
            console.log(result);
 | 
			
		||||
 | 
			
		||||
            this.setState({videos: []}); // needed to trigger rerender of main videoview
 | 
			
		||||
            this.setState({
 | 
			
		||||
                videos: result.rows,
 | 
			
		||||
@@ -84,6 +91,17 @@ class RandomPage extends React.Component<{}, state> {
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								src/utils/ShortkeyHandler.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/utils/ShortkeyHandler.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
/**
 | 
			
		||||
 * add a new keyhandler
 | 
			
		||||
 * @param handler function to be called onkeyup
 | 
			
		||||
 */
 | 
			
		||||
export const addKeyHandler = (handler: (event: KeyboardEvent) => void): void => {
 | 
			
		||||
    document.addEventListener('keyup', handler);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * delete keyhandler
 | 
			
		||||
 * @param handler handler to be removed
 | 
			
		||||
 */
 | 
			
		||||
export const removeKeyHandler = (handler: (event: KeyboardEvent) => void): void => {
 | 
			
		||||
    document.removeEventListener('keyup', handler);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user