2020-12-11 18:23:13 +00:00
|
|
|
import PopupBase from '../PopupBase';
|
|
|
|
import React from 'react';
|
|
|
|
import ActorTile from '../../ActorTile/ActorTile';
|
|
|
|
import style from './AddActorPopup.module.css';
|
|
|
|
import {NewActorPopupContent} from '../NewActorPopup/NewActorPopup';
|
2021-01-29 22:15:17 +00:00
|
|
|
import {APINode, callAPI} from '../../../utils/Api';
|
2021-01-22 21:05:21 +00:00
|
|
|
import {ActorType} from '../../../types/VideoTypes';
|
|
|
|
import {GeneralSuccess} from '../../../types/GeneralTypes';
|
2021-01-03 21:58:55 +01:00
|
|
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
|
|
|
import {faFilter, faTimes} from '@fortawesome/free-solid-svg-icons';
|
|
|
|
import {Button} from '../../GPElements/Button';
|
2021-01-28 19:50:26 +00:00
|
|
|
import {addKeyHandler, removeKeyHandler} from '../../../utils/ShortkeyHandler';
|
2020-12-29 19:39:30 +00:00
|
|
|
|
|
|
|
interface props {
|
|
|
|
onHide: () => void;
|
|
|
|
movie_id: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface state {
|
|
|
|
contentDefault: boolean;
|
|
|
|
actors: ActorType[];
|
2021-01-03 21:58:55 +01:00
|
|
|
filter: string;
|
|
|
|
filtervisible: boolean;
|
2020-12-29 19:39:30 +00:00
|
|
|
}
|
2020-12-11 18:23:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Popup for Adding a new Actor to a Video
|
|
|
|
*/
|
2020-12-29 19:39:30 +00:00
|
|
|
class AddActorPopup extends React.Component<props, state> {
|
2021-01-22 21:05:21 +00:00
|
|
|
// filterfield anchor, needed to focus after filter btn click
|
|
|
|
private filterfield: HTMLInputElement | null | undefined;
|
|
|
|
|
2020-12-29 19:39:30 +00:00
|
|
|
constructor(props: props) {
|
2020-12-11 18:23:13 +00:00
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
contentDefault: true,
|
2021-01-03 21:58:55 +01:00
|
|
|
actors: [],
|
|
|
|
filter: '',
|
|
|
|
filtervisible: false
|
2020-12-11 18:23:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
this.tileClickHandler = this.tileClickHandler.bind(this);
|
2021-01-03 21:58:55 +01:00
|
|
|
this.filterSearch = this.filterSearch.bind(this);
|
2021-01-28 19:50:26 +00:00
|
|
|
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();
|
2020-12-11 18:23:13 +00:00
|
|
|
}
|
|
|
|
|
2020-12-29 19:39:30 +00:00
|
|
|
render(): JSX.Element {
|
2020-12-11 18:23:13 +00:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{/* todo render actor tiles here and add search field*/}
|
|
|
|
<PopupBase title='Add new Actor to Video' onHide={this.props.onHide} banner={
|
|
|
|
<button
|
|
|
|
className={style.newactorbutton}
|
2020-12-29 19:39:30 +00:00
|
|
|
onClick={(): void => {
|
|
|
|
this.setState({contentDefault: false});
|
2021-01-28 19:50:26 +00:00
|
|
|
}}>Create new Actor</button>} ParentSubmit={this.parentSubmit}>
|
2020-12-11 18:23:13 +00:00
|
|
|
{this.resolvePage()}
|
|
|
|
</PopupBase>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* selector for current showing popup page
|
|
|
|
* @returns {JSX.Element}
|
|
|
|
*/
|
2020-12-29 19:39:30 +00:00
|
|
|
resolvePage(): JSX.Element {
|
2020-12-11 18:23:13 +00:00
|
|
|
if (this.state.contentDefault) return (this.getContent());
|
2020-12-29 19:39:30 +00:00
|
|
|
else return (<NewActorPopupContent onHide={(): void => {
|
2020-12-11 18:23:13 +00:00
|
|
|
this.loadActors();
|
|
|
|
this.setState({contentDefault: true});
|
|
|
|
}}/>);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* returns content for the newActor popup
|
|
|
|
* @returns {JSX.Element}
|
|
|
|
*/
|
2020-12-29 19:39:30 +00:00
|
|
|
getContent(): JSX.Element {
|
|
|
|
if (this.state.actors.length !== 0) {
|
2021-01-03 21:58:55 +01:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<div className={style.searchbar}>
|
|
|
|
{
|
|
|
|
this.state.filtervisible ?
|
|
|
|
<>
|
|
|
|
<input className={'form-control mr-sm-2 ' + style.searchinput}
|
|
|
|
type='text' placeholder='Filter' value={this.state.filter}
|
|
|
|
onChange={(e): void => {
|
|
|
|
this.setState({filter: e.target.value});
|
2021-01-22 21:05:21 +00:00
|
|
|
}}
|
2021-01-24 16:43:38 +01:00
|
|
|
ref={(input): void => {this.filterfield = input;}}/>
|
2021-01-03 21:58:55 +01:00
|
|
|
<Button title={<FontAwesomeIcon style={{
|
|
|
|
verticalAlign: 'middle',
|
|
|
|
lineHeight: '130px'
|
|
|
|
}} icon={faTimes} size='1x'/>} color={{backgroundColor: 'red'}} onClick={(): void => {
|
|
|
|
this.setState({filter: '', filtervisible: false});
|
|
|
|
}}/>
|
|
|
|
</> :
|
2021-01-28 19:50:26 +00:00
|
|
|
<Button
|
|
|
|
title={<span>Filter <FontAwesomeIcon style={{
|
|
|
|
verticalAlign: 'middle',
|
|
|
|
lineHeight: '130px'
|
|
|
|
}} icon={faFilter} size='1x'/></span>}
|
|
|
|
color={{backgroundColor: 'cornflowerblue', color: 'white'}}
|
|
|
|
onClick={(): void => this.enableFilterField()}/>
|
2021-01-03 21:58:55 +01:00
|
|
|
}
|
|
|
|
</div>
|
|
|
|
{this.state.actors.filter(this.filterSearch).map((el) => (<ActorTile actor={el} onClick={this.tileClickHandler}/>))}
|
|
|
|
</>
|
|
|
|
);
|
2020-12-11 18:23:13 +00:00
|
|
|
} else {
|
|
|
|
return (<div>somekind of loading</div>);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* event handling for ActorTile Click
|
|
|
|
*/
|
2020-12-29 19:39:30 +00:00
|
|
|
tileClickHandler(actor: ActorType): void {
|
2020-12-11 18:23:13 +00:00
|
|
|
// fetch the available actors
|
2021-01-29 22:15:17 +00:00
|
|
|
callAPI<GeneralSuccess>(APINode.Actor, {
|
2020-12-29 19:39:30 +00:00
|
|
|
action: 'addActorToVideo',
|
2021-02-23 16:01:29 +00:00
|
|
|
ActorId: actor.ActorId,
|
|
|
|
MovieId: this.props.movie_id
|
2020-12-29 19:39:30 +00:00
|
|
|
}, result => {
|
2020-12-17 20:53:22 +00:00
|
|
|
if (result.result === 'success') {
|
|
|
|
// return back to player page
|
|
|
|
this.props.onHide();
|
|
|
|
} else {
|
2021-01-03 21:58:55 +01:00
|
|
|
console.error('an error occured while fetching actors: ' + result);
|
2020-12-17 20:53:22 +00:00
|
|
|
}
|
|
|
|
});
|
2020-12-11 18:23:13 +00:00
|
|
|
}
|
|
|
|
|
2021-01-03 21:58:55 +01:00
|
|
|
/**
|
|
|
|
* load the actors from backend and set state
|
|
|
|
*/
|
2020-12-29 19:39:30 +00:00
|
|
|
loadActors(): void {
|
2021-01-29 22:15:17 +00:00
|
|
|
callAPI<ActorType[]>(APINode.Actor, {action: 'getAllActors'}, result => {
|
2020-12-17 20:53:22 +00:00
|
|
|
this.setState({actors: result});
|
|
|
|
});
|
2020-12-11 18:23:13 +00:00
|
|
|
}
|
2021-01-24 16:43:38 +01:00
|
|
|
|
2021-01-29 22:15:17 +00:00
|
|
|
/**
|
|
|
|
* enable filterfield and focus into searchbar
|
|
|
|
*/
|
|
|
|
private enableFilterField(): void {
|
|
|
|
this.setState({filtervisible: true}, () => {
|
|
|
|
// focus filterfield after state update
|
|
|
|
this.filterfield?.focus();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-01-24 16:43:38 +01:00
|
|
|
/**
|
|
|
|
* filter the actor array for search matches
|
|
|
|
* @param actor
|
|
|
|
*/
|
|
|
|
private filterSearch(actor: ActorType): boolean {
|
2021-02-23 16:01:29 +00:00
|
|
|
return actor.Name.toLowerCase().includes(this.state.filter.toLowerCase());
|
2021-01-24 16:43:38 +01:00
|
|
|
}
|
2021-01-28 19:50:26 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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();
|
|
|
|
}
|
|
|
|
}
|
2020-12-11 18:23:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export default AddActorPopup;
|