typescriptify Popupbase
focus textfield on filterclick
This commit is contained in:
@ -3,7 +3,7 @@ import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||
import {faUser} from '@fortawesome/free-solid-svg-icons';
|
||||
import React from 'react';
|
||||
import {Link} from 'react-router-dom';
|
||||
import {ActorType} from '../../api/VideoTypes';
|
||||
import {ActorType} from '../../types/VideoTypes';
|
||||
|
||||
interface props {
|
||||
actor: ActorType;
|
||||
|
@ -2,14 +2,23 @@ import React from 'react';
|
||||
import style from './InfoHeaderItem.module.css';
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||
import {Spinner} from 'react-bootstrap';
|
||||
import {IconDefinition} from '@fortawesome/fontawesome-common-types';
|
||||
|
||||
interface props {
|
||||
onClick?: () => void
|
||||
backColor: string
|
||||
icon: IconDefinition
|
||||
text: string | number
|
||||
subtext: string | number
|
||||
}
|
||||
|
||||
/**
|
||||
* a component to display one of the short quickinfo tiles on dashboard
|
||||
*/
|
||||
class InfoHeaderItem extends React.Component {
|
||||
render() {
|
||||
class InfoHeaderItem extends React.Component<props> {
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<div onClick={() => {
|
||||
<div onClick={(): void => {
|
||||
// call clicklistener if defined
|
||||
if (this.props.onClick != null) this.props.onClick();
|
||||
}} className={style.infoheaderitem} style={{backgroundColor: this.props.backColor}}>
|
@ -4,8 +4,8 @@ import ActorTile from '../../ActorTile/ActorTile';
|
||||
import style from './AddActorPopup.module.css';
|
||||
import {NewActorPopupContent} from '../NewActorPopup/NewActorPopup';
|
||||
import {callAPI} from '../../../utils/Api';
|
||||
import {ActorType} from '../../../api/VideoTypes';
|
||||
import {GeneralSuccess} from '../../../api/GeneralTypes';
|
||||
import {ActorType} from '../../../types/VideoTypes';
|
||||
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';
|
||||
@ -26,6 +26,9 @@ interface state {
|
||||
* Popup for Adding a new Actor to a Video
|
||||
*/
|
||||
class AddActorPopup extends React.Component<props, state> {
|
||||
// filterfield anchor, needed to focus after filter btn click
|
||||
private filterfield: HTMLInputElement | null | undefined;
|
||||
|
||||
constructor(props: props) {
|
||||
super(props);
|
||||
|
||||
@ -89,7 +92,8 @@ class AddActorPopup extends React.Component<props, state> {
|
||||
type='text' placeholder='Filter' value={this.state.filter}
|
||||
onChange={(e): void => {
|
||||
this.setState({filter: e.target.value});
|
||||
}}/>
|
||||
}}
|
||||
ref={(input): void => {this.filterfield = input;}}/>
|
||||
<Button title={<FontAwesomeIcon style={{
|
||||
verticalAlign: 'middle',
|
||||
lineHeight: '130px'
|
||||
@ -101,7 +105,10 @@ class AddActorPopup extends React.Component<props, state> {
|
||||
verticalAlign: 'middle',
|
||||
lineHeight: '130px'
|
||||
}} icon={faFilter} size='1x'/></span>} color={{backgroundColor: 'cornflowerblue', color: 'white'}} onClick={(): void => {
|
||||
this.setState({filtervisible: true});
|
||||
this.setState({filtervisible: true}, () => {
|
||||
// focus filterfield after state update
|
||||
this.filterfield?.focus();
|
||||
});
|
||||
}}/>
|
||||
}
|
||||
</div>
|
||||
|
@ -2,19 +2,31 @@ import React from 'react';
|
||||
import Tag from '../../Tag/Tag';
|
||||
import PopupBase from '../PopupBase';
|
||||
import {callAPI} from '../../../utils/Api';
|
||||
import {TagType} from '../../../types/VideoTypes';
|
||||
import {GeneralSuccess} from '../../../types/GeneralTypes';
|
||||
|
||||
interface props {
|
||||
onHide: () => void;
|
||||
submit: (tagId: number, tagName: string) => void;
|
||||
movie_id: number;
|
||||
}
|
||||
|
||||
interface state {
|
||||
items: TagType[];
|
||||
}
|
||||
|
||||
/**
|
||||
* component creates overlay to add a new tag to a video
|
||||
*/
|
||||
class AddTagPopup extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
class AddTagPopup extends React.Component<props, state> {
|
||||
constructor(props: props) {
|
||||
super(props);
|
||||
|
||||
this.state = {items: []};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
callAPI('tags.php', {action: 'getAllTags'}, (result) => {
|
||||
componentDidMount(): void {
|
||||
callAPI('tags.php', {action: 'getAllTags'}, (result: TagType[]) => {
|
||||
console.log(result);
|
||||
this.setState({
|
||||
items: result
|
||||
@ -22,13 +34,13 @@ class AddTagPopup extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<PopupBase title='Add a Tag to this Video:' onHide={this.props.onHide}>
|
||||
{this.state.items ?
|
||||
this.state.items.map((i) => (
|
||||
<Tag tagInfo={i}
|
||||
onclick={() => {
|
||||
onclick={(): void => {
|
||||
this.addTag(i.tag_id, i.tag_name);
|
||||
}}/>
|
||||
)) : null}
|
||||
@ -41,8 +53,8 @@ class AddTagPopup extends React.Component {
|
||||
* @param tagid tag id to add
|
||||
* @param tagname tag name to add
|
||||
*/
|
||||
addTag(tagid, tagname) {
|
||||
callAPI('tags.php', {action: 'addTag', id: tagid, movieid: this.props.movie_id}, result => {
|
||||
addTag(tagid: number, tagname: string): void {
|
||||
callAPI('tags.php', {action: 'addTag', id: tagid, movieid: this.props.movie_id}, (result: GeneralSuccess) => {
|
||||
if (result.result !== 'success') {
|
||||
console.log('error occured while writing to db -- todo error handling');
|
||||
console.log(result.result);
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PopupBase from '../PopupBase';
|
||||
import style from './NewActorPopup.module.css';
|
||||
import {callAPI} from '../../../utils/Api';
|
||||
import {GeneralSuccess} from '../../../api/GeneralTypes';
|
||||
import {GeneralSuccess} from '../../../types/GeneralTypes';
|
||||
|
||||
interface NewActorPopupProps {
|
||||
onHide: () => void;
|
||||
|
@ -2,24 +2,25 @@ import React from 'react';
|
||||
import PopupBase from '../PopupBase';
|
||||
import style from './NewTagPopup.module.css';
|
||||
import {callAPI} from '../../../utils/Api';
|
||||
import {GeneralSuccess} from '../../../types/GeneralTypes';
|
||||
|
||||
interface props {
|
||||
onHide: () => void
|
||||
}
|
||||
|
||||
/**
|
||||
* creates modal overlay to define a new Tag
|
||||
*/
|
||||
class NewTagPopup extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
class NewTagPopup extends React.Component<props> {
|
||||
private value: string = '';
|
||||
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
render() {
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<PopupBase title='Add new Tag' onHide={this.props.onHide} height='200px' width='400px'>
|
||||
<div><input type='text' placeholder='Tagname' onChange={(v) => {
|
||||
<div><input type='text' placeholder='Tagname' onChange={(v): void => {
|
||||
this.value = v.target.value;
|
||||
}}/></div>
|
||||
<button className={style.savebtn} onClick={() => this.storeselection()}>Save</button>
|
||||
<button className={style.savebtn} onClick={(): void => this.storeselection()}>Save</button>
|
||||
</PopupBase>
|
||||
);
|
||||
}
|
||||
@ -27,8 +28,8 @@ class NewTagPopup extends React.Component {
|
||||
/**
|
||||
* store the filled in form to the backend
|
||||
*/
|
||||
storeselection() {
|
||||
callAPI('tags.php', {action: 'createTag', tagname: this.value}, result => {
|
||||
storeselection(): void {
|
||||
callAPI('tags.php', {action: 'createTag', tagname: this.value}, (result: GeneralSuccess) => {
|
||||
if (result.result !== 'success') {
|
||||
console.log('error occured while writing to db -- todo error handling');
|
||||
console.log(result.result);
|
@ -1,13 +1,24 @@
|
||||
import GlobalInfos from '../../utils/GlobalInfos';
|
||||
import style from './PopupBase.module.css';
|
||||
import {Line} from '../PageTitle/PageTitle';
|
||||
import React from 'react';
|
||||
import React, {RefObject} from 'react';
|
||||
|
||||
interface props {
|
||||
width?: string;
|
||||
height?: string;
|
||||
banner?: JSX.Element;
|
||||
title: string;
|
||||
onHide: () => void
|
||||
}
|
||||
|
||||
/**
|
||||
* wrapper class for generic types of popups
|
||||
*/
|
||||
class PopupBase extends React.Component {
|
||||
constructor(props) {
|
||||
class PopupBase extends React.Component<props> {
|
||||
private wrapperRef: RefObject<HTMLDivElement>;
|
||||
private framedimensions: { minHeight: string | undefined; width: string | undefined; height: string | undefined };
|
||||
|
||||
constructor(props: props) {
|
||||
super(props);
|
||||
|
||||
this.state = {items: []};
|
||||
@ -25,7 +36,7 @@ class PopupBase extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
componentDidMount(): void {
|
||||
document.addEventListener('mousedown', this.handleClickOutside);
|
||||
document.addEventListener('keyup', this.keypress);
|
||||
|
||||
@ -35,13 +46,13 @@ class PopupBase extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
componentWillUnmount(): void {
|
||||
// remove the appended listeners
|
||||
document.removeEventListener('mousedown', this.handleClickOutside);
|
||||
document.removeEventListener('keyup', this.keypress);
|
||||
}
|
||||
|
||||
render() {
|
||||
render(): JSX.Element {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<div style={this.framedimensions} className={[style.popup, themeStyle.thirdbackground].join(' ')} ref={this.wrapperRef}>
|
||||
@ -61,8 +72,8 @@ class PopupBase extends React.Component {
|
||||
/**
|
||||
* Alert if clicked on outside of element
|
||||
*/
|
||||
handleClickOutside(event) {
|
||||
if (this.wrapperRef && !this.wrapperRef.current.contains(event.target)) {
|
||||
handleClickOutside(event: MouseEvent): void {
|
||||
if (this.wrapperRef && this.wrapperRef.current && !this.wrapperRef.current.contains(event.target as Node)) {
|
||||
this.props.onHide();
|
||||
}
|
||||
}
|
||||
@ -71,7 +82,7 @@ class PopupBase extends React.Component {
|
||||
* key event handling
|
||||
* @param event keyevent
|
||||
*/
|
||||
keypress(event) {
|
||||
keypress(event: KeyboardEvent): void {
|
||||
// hide if escape is pressed
|
||||
if (event.key === 'Escape') {
|
||||
this.props.onHide();
|
||||
@ -81,16 +92,17 @@ class PopupBase extends React.Component {
|
||||
/**
|
||||
* make the element drag and droppable
|
||||
*/
|
||||
dragElement() {
|
||||
dragElement(): void {
|
||||
let xOld = 0, yOld = 0;
|
||||
|
||||
const elmnt = this.wrapperRef.current;
|
||||
if (elmnt === null) return;
|
||||
if (elmnt.firstChild === null) return;
|
||||
|
||||
elmnt.firstChild.onmousedown = dragMouseDown;
|
||||
(elmnt.firstChild as HTMLDivElement).onmousedown = dragMouseDown;
|
||||
|
||||
|
||||
function dragMouseDown(e) {
|
||||
function dragMouseDown(e: MouseEvent): void {
|
||||
e.preventDefault();
|
||||
// get the mouse cursor position at startup:
|
||||
xOld = e.clientX;
|
||||
@ -100,7 +112,7 @@ class PopupBase extends React.Component {
|
||||
document.onmousemove = elementDrag;
|
||||
}
|
||||
|
||||
function elementDrag(e) {
|
||||
function elementDrag(e: MouseEvent): void {
|
||||
e.preventDefault();
|
||||
// calculate the new cursor position:
|
||||
const dx = xOld - e.clientX;
|
||||
@ -108,11 +120,12 @@ class PopupBase extends React.Component {
|
||||
xOld = e.clientX;
|
||||
yOld = e.clientY;
|
||||
// set the element's new position:
|
||||
if (elmnt === null) return;
|
||||
elmnt.style.top = (elmnt.offsetTop - dy) + 'px';
|
||||
elmnt.style.left = (elmnt.offsetLeft - dx) + 'px';
|
||||
}
|
||||
|
||||
function closeDragElement() {
|
||||
function closeDragElement(): void {
|
||||
// stop moving when mouse button is released:
|
||||
document.onmouseup = null;
|
||||
document.onmousemove = null;
|
@ -5,35 +5,42 @@ import {Link} from 'react-router-dom';
|
||||
import GlobalInfos from '../../utils/GlobalInfos';
|
||||
import {callAPIPlain} from '../../utils/Api';
|
||||
|
||||
interface PreviewProps{
|
||||
name: string;
|
||||
movie_id: number;
|
||||
}
|
||||
|
||||
interface PreviewState {
|
||||
previewpicture: string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component for single preview tile
|
||||
* floating side by side
|
||||
*/
|
||||
class Preview extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
class Preview extends React.Component<PreviewProps, PreviewState> {
|
||||
constructor(props: PreviewProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
previewpicture: null,
|
||||
name: null
|
||||
previewpicture: null
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
componentDidMount(): void {
|
||||
callAPIPlain('video.php', {action: 'readThumbnail', movieid: this.props.movie_id}, (result) => {
|
||||
this.setState({
|
||||
previewpicture: result,
|
||||
name: this.props.name
|
||||
previewpicture: result
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
render(): JSX.Element {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<Link to={'/player/' + this.props.movie_id}>
|
||||
<div className={style.videopreview + ' ' + themeStyle.secbackground + ' ' + themeStyle.preview}>
|
||||
<div className={style.previewtitle + ' ' + themeStyle.lighttextcolor}>{this.state.name}</div>
|
||||
<div className={style.previewtitle + ' ' + themeStyle.lighttextcolor}>{this.props.name}</div>
|
||||
<div className={style.previewpic}>
|
||||
{this.state.previewpicture !== null ?
|
||||
<img className={style.previewimage}
|
||||
@ -55,8 +62,8 @@ class Preview extends React.Component {
|
||||
/**
|
||||
* Component for a Tag-name tile (used in category page)
|
||||
*/
|
||||
export class TagPreview extends React.Component {
|
||||
render() {
|
||||
export class TagPreview extends React.Component<{name: string}> {
|
||||
render(): JSX.Element {
|
||||
const themeStyle = GlobalInfos.getThemeStyle();
|
||||
return (
|
||||
<div
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
|
||||
import styles from './Tag.module.css';
|
||||
import {Link} from 'react-router-dom';
|
||||
import {TagType} from '../../api/VideoTypes';
|
||||
import {TagType} from '../../types/VideoTypes';
|
||||
|
||||
interface props {
|
||||
onclick?: (_: string) => void
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React from 'react';
|
||||
import Preview from '../Preview/Preview';
|
||||
import style from './VideoContainer.module.css';
|
||||
import {VideoUnloadedType} from '../../api/VideoTypes';
|
||||
import {VideoTypes} from '../../types/ApiTypes';
|
||||
|
||||
interface props {
|
||||
data: VideoUnloadedType[]
|
||||
data: VideoTypes.VideoUnloadedType[]
|
||||
}
|
||||
|
||||
interface state {
|
||||
loadeditems: VideoUnloadedType[];
|
||||
loadeditems: VideoTypes.VideoUnloadedType[];
|
||||
selectionnr: number;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user