Compare commits
	
		
			9 Commits
		
	
	
		
			hls_on_the
			...
			threedotso
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 20f29d9df6 | |||
| c13e758301 | |||
| 219124c843 | |||
| 4de39ab471 | |||
| b5220634a2 | |||
| d59980460f | |||
| 4e52688ff9 | |||
| 009f21390e | |||
| 62d3e02645 | 
							
								
								
									
										84
									
								
								api/src/handlers/Tags.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								api/src/handlers/Tags.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
<?php
 | 
			
		||||
require_once 'RequestBase.php';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class Tags
 | 
			
		||||
 * backend to handle Tag database interactions
 | 
			
		||||
 */
 | 
			
		||||
class Tags extends RequestBase {
 | 
			
		||||
    function initHandlers() {
 | 
			
		||||
        $this->addToDB();
 | 
			
		||||
        $this->getFromDB();
 | 
			
		||||
        $this->delete();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function addToDB() {
 | 
			
		||||
        /**
 | 
			
		||||
         * creates a new tag
 | 
			
		||||
         * query requirements:
 | 
			
		||||
         * * tagname -- name of the new tag
 | 
			
		||||
         */
 | 
			
		||||
        $this->addActionHandler("createTag", function () {
 | 
			
		||||
            // skip tag create if already existing
 | 
			
		||||
            $query = "INSERT IGNORE INTO tags (tag_name) VALUES ('" . $_POST['tagname'] . "')";
 | 
			
		||||
 | 
			
		||||
            if ($this->conn->query($query) === TRUE) {
 | 
			
		||||
                $this->commitMessage('{"result":"success"}');
 | 
			
		||||
            } else {
 | 
			
		||||
                $this->commitMessage('{"result":"' . $this->conn->error . '"}');
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * adds a new tag to an existing video
 | 
			
		||||
         *
 | 
			
		||||
         * query requirements:
 | 
			
		||||
         * * movieid  -- the id of the video to add the tag to
 | 
			
		||||
         * * id -- the tag id which tag to add
 | 
			
		||||
         */
 | 
			
		||||
        $this->addActionHandler("addTag", function () {
 | 
			
		||||
            $movieid = $_POST['movieid'];
 | 
			
		||||
            $tagid = $_POST['id'];
 | 
			
		||||
 | 
			
		||||
            // skip tag add if already assigned
 | 
			
		||||
            $query = "INSERT IGNORE INTO video_tags(tag_id, video_id) VALUES ('$tagid','$movieid')";
 | 
			
		||||
 | 
			
		||||
            if ($this->conn->query($query) === TRUE) {
 | 
			
		||||
                $this->commitMessage('{"result":"success"}');
 | 
			
		||||
            } else {
 | 
			
		||||
                $this->commitMessage('{"result":"' . $this->conn->error . '"}');
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getFromDB() {
 | 
			
		||||
        /**
 | 
			
		||||
         * returns all available tags from database
 | 
			
		||||
         */
 | 
			
		||||
        $this->addActionHandler("getAllTags", function () {
 | 
			
		||||
            $query = "SELECT tag_name,tag_id from tags";
 | 
			
		||||
            $result = $this->conn->query($query);
 | 
			
		||||
 | 
			
		||||
            $rows = array();
 | 
			
		||||
            while ($r = mysqli_fetch_assoc($result)) {
 | 
			
		||||
                array_push($rows, $r);
 | 
			
		||||
            }
 | 
			
		||||
            $this->commitMessage(json_encode($rows));
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function delete() {
 | 
			
		||||
        /**
 | 
			
		||||
         * delete a Tag from a video
 | 
			
		||||
         */
 | 
			
		||||
        $this->addActionHandler("deleteVideoTag", function () {
 | 
			
		||||
            $movieid = $_POST['video_id'];
 | 
			
		||||
            $tagid = $_POST['tag_id'];
 | 
			
		||||
 | 
			
		||||
            // skip tag add if already assigned
 | 
			
		||||
            $query = "DELETE FROM video_tags WHERE tag_id=$tagid AND video_id=$movieid";
 | 
			
		||||
 | 
			
		||||
            $this->commitMessage($this->conn->query($query) ? '{"result":"success"}' : '{"result":"' . $this->conn->error . '"}');
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -25,7 +25,11 @@ class ActorTile extends React.Component<Props> {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    renderActorTile(customclickhandler: (actor: ActorType) => void): JSX.Element {
 | 
			
		||||
    /**
 | 
			
		||||
     * render the Actor Tile with its pic
 | 
			
		||||
     * @param customclickhandler a custom click handler to be called onclick instead of Link
 | 
			
		||||
     */
 | 
			
		||||
    private renderActorTile(customclickhandler: (actor: ActorType) => void): JSX.Element {
 | 
			
		||||
        return (
 | 
			
		||||
            <div className={style.actortile} onClick={(): void => customclickhandler(this.props.actor)}>
 | 
			
		||||
                <div className={style.actortile_thumbnail}>
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,7 @@ class PopupBase extends React.Component<Props> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Alert if clicked on outside of element
 | 
			
		||||
     * handle click on outside of element
 | 
			
		||||
     */
 | 
			
		||||
    handleClickOutside(event: MouseEvent): void {
 | 
			
		||||
        if (this.wrapperRef && this.wrapperRef.current && !this.wrapperRef.current.contains(event.target as Node)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,29 @@
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.videopreview:hover .quickactions {
 | 
			
		||||
    background-color: rgba(0, 0, 0, 0.8);
 | 
			
		||||
    border-radius: 50%;
 | 
			
		||||
 | 
			
		||||
    color: lightgrey;
 | 
			
		||||
    display: block;
 | 
			
		||||
 | 
			
		||||
    height: 35px;
 | 
			
		||||
    opacity: 0.7;
 | 
			
		||||
    padding-top: 5px;
 | 
			
		||||
 | 
			
		||||
    position: absolute;
 | 
			
		||||
 | 
			
		||||
    right: 5px;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    top: 5px;
 | 
			
		||||
    width: 35px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.quickactions {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.previewpic {
 | 
			
		||||
    height: 80%;
 | 
			
		||||
    min-height: 150px;
 | 
			
		||||
@@ -38,6 +61,7 @@
 | 
			
		||||
    margin-left: 25px;
 | 
			
		||||
    margin-top: 25px;
 | 
			
		||||
    opacity: 0.85;
 | 
			
		||||
    position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.videopreview:hover {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,8 @@ import {Link} from 'react-router-dom';
 | 
			
		||||
import GlobalInfos from '../../utils/GlobalInfos';
 | 
			
		||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
 | 
			
		||||
import {faPhotoVideo} from '@fortawesome/free-solid-svg-icons';
 | 
			
		||||
import {faEllipsisV} from '@fortawesome/free-solid-svg-icons';
 | 
			
		||||
import QuickActionPop, {ContextItem} from '../QuickActionPop/QuickActionPop';
 | 
			
		||||
 | 
			
		||||
interface PreviewProps {
 | 
			
		||||
    name: string;
 | 
			
		||||
@@ -15,6 +17,7 @@ interface PreviewProps {
 | 
			
		||||
 | 
			
		||||
interface PreviewState {
 | 
			
		||||
    picLoaded: boolean | null;
 | 
			
		||||
    optionsvisible: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -29,7 +32,8 @@ class Preview extends React.Component<PreviewProps, PreviewState> {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            picLoaded: null
 | 
			
		||||
            picLoaded: null,
 | 
			
		||||
            optionsvisible: false
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -56,6 +60,23 @@ class Preview extends React.Component<PreviewProps, PreviewState> {
 | 
			
		||||
            <div
 | 
			
		||||
                className={style.videopreview + ' ' + themeStyle.secbackground + ' ' + themeStyle.preview}
 | 
			
		||||
                onClick={this.props.onClick}>
 | 
			
		||||
                <div
 | 
			
		||||
                    className={style.quickactions}
 | 
			
		||||
                    onClick={(e): void => {
 | 
			
		||||
                        this.setState({optionsvisible: true});
 | 
			
		||||
                        e.stopPropagation();
 | 
			
		||||
                        e.preventDefault();
 | 
			
		||||
                    }}>
 | 
			
		||||
                    <FontAwesomeIcon
 | 
			
		||||
                        style={{
 | 
			
		||||
                            verticalAlign: 'middle',
 | 
			
		||||
                            fontSize: '25px'
 | 
			
		||||
                        }}
 | 
			
		||||
                        icon={faEllipsisV}
 | 
			
		||||
                        size='1x'
 | 
			
		||||
                    />
 | 
			
		||||
                </div>
 | 
			
		||||
                {this.popupvisible()}
 | 
			
		||||
                <div className={style.previewtitle + ' ' + themeStyle.lighttextcolor}>{this.props.name}</div>
 | 
			
		||||
                <div className={style.previewpic}>
 | 
			
		||||
                    {this.state.picLoaded === false ? (
 | 
			
		||||
@@ -79,6 +100,19 @@ class Preview extends React.Component<PreviewProps, PreviewState> {
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    popupvisible(): JSX.Element {
 | 
			
		||||
        if (this.state.optionsvisible) {
 | 
			
		||||
            return (
 | 
			
		||||
                <QuickActionPop position={{x: 350, y: 45}} onHide={(): void => this.setState({optionsvisible: false})}>
 | 
			
		||||
                    <ContextItem title='Delete' onClick={(): void => {}} />
 | 
			
		||||
                    <ContextItem title='Delete' onClick={(): void => {}} />
 | 
			
		||||
                </QuickActionPop>
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            return <></>;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										65
									
								
								src/elements/QuickActionPop/QuickActionPop.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/elements/QuickActionPop/QuickActionPop.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
import React, {RefObject} from 'react';
 | 
			
		||||
import style from './QuickActionPopup.module.css';
 | 
			
		||||
 | 
			
		||||
interface props {
 | 
			
		||||
    position: {
 | 
			
		||||
        x: number;
 | 
			
		||||
        y: number;
 | 
			
		||||
    };
 | 
			
		||||
    onHide: () => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class QuickActionPop extends React.Component<props> {
 | 
			
		||||
    private readonly wrapperRef: RefObject<HTMLDivElement>;
 | 
			
		||||
 | 
			
		||||
    constructor(props: props) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.wrapperRef = React.createRef();
 | 
			
		||||
 | 
			
		||||
        this.handleClickOutside = this.handleClickOutside.bind(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        document.addEventListener('mousedown', this.handleClickOutside);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentWillUnmount(): void {
 | 
			
		||||
        document.removeEventListener('mousedown', this.handleClickOutside);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        return (
 | 
			
		||||
            <div ref={this.wrapperRef} className={style.quickaction} style={{top: this.props.position.y, left: this.props.position.x}}>
 | 
			
		||||
                {this.props.children}
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * trigger hide if we click outside the div
 | 
			
		||||
     */
 | 
			
		||||
    handleClickOutside(event: MouseEvent): void {
 | 
			
		||||
        if (this.wrapperRef && this.wrapperRef.current && !this.wrapperRef.current.contains(event.target as Node)) {
 | 
			
		||||
            this.props.onHide();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface Itemprops {
 | 
			
		||||
    title: string;
 | 
			
		||||
    onClick: () => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const ContextItem = (props: Itemprops): JSX.Element => (
 | 
			
		||||
    <div
 | 
			
		||||
        onClick={(e): void => {
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
            props.onClick();
 | 
			
		||||
        }}
 | 
			
		||||
        className={style.ContextItem}>
 | 
			
		||||
        {props.title}
 | 
			
		||||
    </div>
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
export default QuickActionPop;
 | 
			
		||||
							
								
								
									
										17
									
								
								src/elements/QuickActionPop/QuickActionPopup.module.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/elements/QuickActionPop/QuickActionPopup.module.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
.quickaction {
 | 
			
		||||
    background-color: white;
 | 
			
		||||
    height: 120px;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    width: 90px;
 | 
			
		||||
    z-index: 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ContextItem {
 | 
			
		||||
    height: 40px;
 | 
			
		||||
    padding-top: 10px;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ContextItem:hover {
 | 
			
		||||
    background-color: lightgray;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import React, {SyntheticEvent, PointerEvent} from 'react';
 | 
			
		||||
 | 
			
		||||
import styles from './Tag.module.css';
 | 
			
		||||
import {Link} from 'react-router-dom';
 | 
			
		||||
@@ -7,12 +7,27 @@ import {TagType} from '../../types/VideoTypes';
 | 
			
		||||
interface props {
 | 
			
		||||
    onclick?: (_: string) => void;
 | 
			
		||||
    tagInfo: TagType;
 | 
			
		||||
    onContextMenu?: (pos: {x: number; y: number}) => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface state {
 | 
			
		||||
    contextVisible: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A Component representing a single Category tag
 | 
			
		||||
 */
 | 
			
		||||
class Tag extends React.Component<props> {
 | 
			
		||||
class Tag extends React.Component<props, state> {
 | 
			
		||||
    constructor(props: Readonly<props> | props) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            contextVisible: false
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.contextmenu = this.contextmenu.bind(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        if (this.props.onclick) {
 | 
			
		||||
            return this.renderButton();
 | 
			
		||||
@@ -23,7 +38,11 @@ class Tag extends React.Component<props> {
 | 
			
		||||
 | 
			
		||||
    renderButton(): JSX.Element {
 | 
			
		||||
        return (
 | 
			
		||||
            <button className={styles.tagbtn} onClick={(): void => this.TagClick()} data-testid='Test-Tag'>
 | 
			
		||||
            <button
 | 
			
		||||
                className={styles.tagbtn}
 | 
			
		||||
                onClick={(): void => this.TagClick()}
 | 
			
		||||
                data-testid='Test-Tag'
 | 
			
		||||
                onContextMenu={this.contextmenu}>
 | 
			
		||||
                {this.props.tagInfo.TagName}
 | 
			
		||||
            </button>
 | 
			
		||||
        );
 | 
			
		||||
@@ -39,6 +58,22 @@ class Tag extends React.Component<props> {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * handle a custom contextmenu for this item
 | 
			
		||||
     * @param e
 | 
			
		||||
     * @private
 | 
			
		||||
     */
 | 
			
		||||
    private contextmenu(e: SyntheticEvent): void {
 | 
			
		||||
        if (!this.props.onContextMenu) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const event = e as unknown as PointerEvent;
 | 
			
		||||
        event.preventDefault();
 | 
			
		||||
        this.props.onContextMenu({x: event.clientX, y: event.clientY});
 | 
			
		||||
        // this.setState({contextVisible: true});
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default Tag;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ import {ActorType, TagType} from '../../types/VideoTypes';
 | 
			
		||||
import PlyrJS from 'plyr';
 | 
			
		||||
import {Button} from '../../elements/GPElements/Button';
 | 
			
		||||
import {VideoTypes} from '../../types/ApiTypes';
 | 
			
		||||
import QuickActionPop, {ContextItem} from '../../elements/QuickActionPop/QuickActionPop';
 | 
			
		||||
import GlobalInfos from '../../utils/GlobalInfos';
 | 
			
		||||
 | 
			
		||||
interface Props extends RouteComponentProps<{id: string}> {}
 | 
			
		||||
@@ -36,6 +37,7 @@ interface mystate {
 | 
			
		||||
    popupvisible: boolean;
 | 
			
		||||
    actorpopupvisible: boolean;
 | 
			
		||||
    actors: ActorType[];
 | 
			
		||||
    tagContextMenu: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -43,12 +45,15 @@ interface mystate {
 | 
			
		||||
 * and actions such as tag adding and liking
 | 
			
		||||
 */
 | 
			
		||||
export class Player extends React.Component<Props, mystate> {
 | 
			
		||||
    private contextpos = {x: 0, y: 0, tagid: -1};
 | 
			
		||||
 | 
			
		||||
    constructor(props: Props) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            movieId: -1,
 | 
			
		||||
            movieName: '',
 | 
			
		||||
            tagContextMenu: false,
 | 
			
		||||
            likes: 0,
 | 
			
		||||
            quality: 0,
 | 
			
		||||
            length: 0,
 | 
			
		||||
@@ -60,6 +65,7 @@ export class Player extends React.Component<Props, mystate> {
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.quickAddTag = this.quickAddTag.bind(this);
 | 
			
		||||
        this.deleteTag = this.deleteTag.bind(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
@@ -133,7 +139,14 @@ export class Player extends React.Component<Props, mystate> {
 | 
			
		||||
                <Line />
 | 
			
		||||
                <SideBarTitle>Tags:</SideBarTitle>
 | 
			
		||||
                {this.state.tags.map((m: TagType) => (
 | 
			
		||||
                    <Tag key={m.TagId} tagInfo={m} />
 | 
			
		||||
                    <Tag
 | 
			
		||||
                        key={m.TagId}
 | 
			
		||||
                        tagInfo={m}
 | 
			
		||||
                        onContextMenu={(pos): void => {
 | 
			
		||||
                            this.setState({tagContextMenu: true});
 | 
			
		||||
                            this.contextpos = {...pos, tagid: m.TagId};
 | 
			
		||||
                        }}
 | 
			
		||||
                    />
 | 
			
		||||
                ))}
 | 
			
		||||
                <Line />
 | 
			
		||||
                <SideBarTitle>Tag Quickadd:</SideBarTitle>
 | 
			
		||||
@@ -196,6 +209,7 @@ export class Player extends React.Component<Props, mystate> {
 | 
			
		||||
                        movieId={this.state.movieId}
 | 
			
		||||
                    />
 | 
			
		||||
                ) : null}
 | 
			
		||||
                {this.renderContextMenu()}
 | 
			
		||||
            </>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
@@ -355,6 +369,51 @@ export class Player extends React.Component<Props, mystate> {
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * render the Tag context menu
 | 
			
		||||
     */
 | 
			
		||||
    private renderContextMenu(): JSX.Element {
 | 
			
		||||
        if (this.state.tagContextMenu) {
 | 
			
		||||
            return (
 | 
			
		||||
                <QuickActionPop onHide={(): void => this.setState({tagContextMenu: false})} position={this.contextpos}>
 | 
			
		||||
                    <ContextItem title='Delete' onClick={(): void => this.deleteTag(this.contextpos.tagid)} />
 | 
			
		||||
                </QuickActionPop>
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            return <></>;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * delete a tag from the current video
 | 
			
		||||
     */
 | 
			
		||||
    private deleteTag(tag_id: number): void {
 | 
			
		||||
        callAPI<GeneralSuccess>(
 | 
			
		||||
            APINode.Tags,
 | 
			
		||||
            {action: 'deleteVideoTag', video_id: this.props.match.params.id, tag_id: tag_id},
 | 
			
		||||
            (res) => {
 | 
			
		||||
                if (res.result !== 'success') {
 | 
			
		||||
                    console.log('deletion errored!');
 | 
			
		||||
 | 
			
		||||
                    this.setState({tagContextMenu: false});
 | 
			
		||||
                } else {
 | 
			
		||||
                    // check if tag has already been added
 | 
			
		||||
                    const tagIndex = this.state.tags
 | 
			
		||||
                        .map(function (e: TagType) {
 | 
			
		||||
                            return e.TagId;
 | 
			
		||||
                        })
 | 
			
		||||
                        .indexOf(tag_id);
 | 
			
		||||
 | 
			
		||||
                    // delete tag from array
 | 
			
		||||
                    const newTagArray = this.state.tags;
 | 
			
		||||
                    newTagArray.splice(tagIndex, 1);
 | 
			
		||||
 | 
			
		||||
                    this.setState({tags: newTagArray, tagContextMenu: false});
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default withRouter(Player);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user