Merge branch 'fullydeleable' into 'master'
Fully Deletable Videos Closes #74 See merge request lukas/openmediacenter!52
This commit is contained in:
		| @@ -15,7 +15,8 @@ func readVideosFromResultset(rows *sql.Rows) []types.VideoUnloadedType { | |||||||
| 		var vid types.VideoUnloadedType | 		var vid types.VideoUnloadedType | ||||||
| 		err := rows.Scan(&vid.MovieId, &vid.MovieName) | 		err := rows.Scan(&vid.MovieId, &vid.MovieName) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			panic(err.Error()) // proper error handling instead of panic in your app | 			fmt.Println(err.Error()) | ||||||
|  | 			return nil | ||||||
| 		} | 		} | ||||||
| 		result = append(result, vid) | 		result = append(result, vid) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -73,6 +73,7 @@ func getSettingsFromDB() { | |||||||
| 			VideoPath         string | 			VideoPath         string | ||||||
| 			TVShowPath        string | 			TVShowPath        string | ||||||
| 			TVShowEnabled     bool | 			TVShowEnabled     bool | ||||||
|  | 			FullDeleteEnabled bool | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		regexMatchUrl := regexp.MustCompile("^http(|s)://([0-9]){1,3}\\.([0-9]){1,3}\\.([0-9]){1,3}\\.([0-9]){1,3}:[0-9]{1,5}") | 		regexMatchUrl := regexp.MustCompile("^http(|s)://([0-9]){1,3}\\.([0-9]){1,3}\\.([0-9]){1,3}\\.([0-9]){1,3}:[0-9]{1,5}") | ||||||
| @@ -88,6 +89,7 @@ func getSettingsFromDB() { | |||||||
| 			VideoPath:         serverVideoPath, | 			VideoPath:         serverVideoPath, | ||||||
| 			TVShowPath:        serverTVShowPath, | 			TVShowPath:        serverTVShowPath, | ||||||
| 			TVShowEnabled:     settings.TVShowsEnabled(), | 			TVShowEnabled:     settings.TVShowsEnabled(), | ||||||
|  | 			FullDeleteEnabled: settings.VideosDeletable(), | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		str, _ := json.Marshal(res) | 		str, _ := json.Marshal(res) | ||||||
|   | |||||||
| @@ -6,6 +6,8 @@ import ( | |||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"openmediacenter/apiGo/api/types" | 	"openmediacenter/apiGo/api/types" | ||||||
| 	"openmediacenter/apiGo/database" | 	"openmediacenter/apiGo/database" | ||||||
|  | 	"openmediacenter/apiGo/database/settings" | ||||||
|  | 	"os" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -418,12 +420,14 @@ func addToVideoHandlers() { | |||||||
| 	 * @apiGroup video | 	 * @apiGroup video | ||||||
| 	 * | 	 * | ||||||
| 	 * @apiParam {int} MovieId ID of video | 	 * @apiParam {int} MovieId ID of video | ||||||
|  | 	 * @apiParam {bool} FullyDelete Delete video from disk? | ||||||
| 	 * | 	 * | ||||||
| 	 * @apiSuccess {string} result 'success' if successfully or error message if not | 	 * @apiSuccess {string} result 'success' if successfully or error message if not | ||||||
| 	 */ | 	 */ | ||||||
| 	AddHandler("deleteVideo", VideoNode, func(info *HandlerInfo) []byte { | 	AddHandler("deleteVideo", VideoNode, func(info *HandlerInfo) []byte { | ||||||
| 		var args struct { | 		var args struct { | ||||||
| 			MovieId     int | 			MovieId     int | ||||||
|  | 			FullyDelete bool | ||||||
| 		} | 		} | ||||||
| 		if err := FillStruct(&args, info.Data); err != nil { | 		if err := FillStruct(&args, info.Data); err != nil { | ||||||
| 			fmt.Println(err.Error()) | 			fmt.Println(err.Error()) | ||||||
| @@ -443,6 +447,26 @@ func addToVideoHandlers() { | |||||||
| 			return database.ManualSuccessResponse(err) | 			return database.ManualSuccessResponse(err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		// only allow deletion of video if cli flag is set, independent of passed api arg | ||||||
|  | 		if settings.VideosDeletable() && args.FullyDelete { | ||||||
|  | 			// get physical path of video to delete | ||||||
|  | 			query = fmt.Sprintf("SELECT movie_url FROM videos WHERE movie_id=%d", args.MovieId) | ||||||
|  | 			var vidpath string | ||||||
|  | 			err := database.QueryRow(query).Scan(&vidpath) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return database.ManualSuccessResponse(err) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			assembledPath := database.SettingsVideoPrefix + "/" + vidpath | ||||||
|  |  | ||||||
|  | 			err = os.Remove(assembledPath) | ||||||
|  | 			if err != nil { | ||||||
|  | 				fmt.Printf("unable to delete file: %s -- %s\n", assembledPath, err.Error()) | ||||||
|  | 				return database.ManualSuccessResponse(err) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// delete video row from db | ||||||
| 		query = fmt.Sprintf("DELETE FROM videos WHERE movie_id=%d", args.MovieId) | 		query = fmt.Sprintf("DELETE FROM videos WHERE movie_id=%d", args.MovieId) | ||||||
| 		return database.SuccessQuery(query) | 		return database.SuccessQuery(query) | ||||||
| 	}) | 	}) | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package settings | package settings | ||||||
|  |  | ||||||
| var tvShowEnabled bool | var tvShowEnabled bool | ||||||
|  | var videosDeletable bool | ||||||
|  |  | ||||||
| func TVShowsEnabled() bool { | func TVShowsEnabled() bool { | ||||||
| 	return tvShowEnabled | 	return tvShowEnabled | ||||||
| @@ -9,3 +10,11 @@ func TVShowsEnabled() bool { | |||||||
| func SetTVShowEnabled(enabled bool) { | func SetTVShowEnabled(enabled bool) { | ||||||
| 	tvShowEnabled = enabled | 	tvShowEnabled = enabled | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func VideosDeletable() bool { | ||||||
|  | 	return videosDeletable | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func SetVideosDeletable(deletable bool) { | ||||||
|  | 	videosDeletable = deletable | ||||||
|  | } | ||||||
|   | |||||||
| @@ -57,10 +57,12 @@ func handleCommandLineArguments() (*database.DatabaseConfig, bool, *string) { | |||||||
| 	pathPrefix := flag.String("ReindexPrefix", "/var/www/openmediacenter", "Prefix path for videos to reindex") | 	pathPrefix := flag.String("ReindexPrefix", "/var/www/openmediacenter", "Prefix path for videos to reindex") | ||||||
|  |  | ||||||
| 	disableTVShowSupport := flag.Bool("DisableTVSupport", false, "Disable the TVShow support and pages") | 	disableTVShowSupport := flag.Bool("DisableTVSupport", false, "Disable the TVShow support and pages") | ||||||
|  | 	videosFullyDeletable := flag.Bool("FullyDeletableVideos", false, "Allow deletion from harddisk") | ||||||
|  |  | ||||||
| 	flag.Parse() | 	flag.Parse() | ||||||
|  |  | ||||||
| 	settings2.SetTVShowEnabled(!*disableTVShowSupport) | 	settings2.SetTVShowEnabled(!*disableTVShowSupport) | ||||||
|  | 	settings2.SetVideosDeletable(*videosFullyDeletable) | ||||||
|  |  | ||||||
| 	return &database.DatabaseConfig{ | 	return &database.DatabaseConfig{ | ||||||
| 		DBHost:     *dbhostPtr, | 		DBHost:     *dbhostPtr, | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ | |||||||
|     "build": "CI=false react-scripts build", |     "build": "CI=false react-scripts build", | ||||||
|     "test": "CI=true react-scripts test --reporters=jest-junit --verbose --silent --coverage --reporters=default", |     "test": "CI=true react-scripts test --reporters=jest-junit --verbose --silent --coverage --reporters=default", | ||||||
|     "lint": "eslint --format gitlab src/", |     "lint": "eslint --format gitlab src/", | ||||||
|     "apidoc": "apidoc -i apiGo/ -o doc/" |     "apidoc": "apidoc --single -i apiGo/ -o doc/" | ||||||
|   }, |   }, | ||||||
|   "jest": { |   "jest": { | ||||||
|     "collectCoverageFrom": [ |     "collectCoverageFrom": [ | ||||||
|   | |||||||
| @@ -87,6 +87,7 @@ class App extends React.Component<{}, state> { | |||||||
|             GlobalInfos.setVideoPaths(result.VideoPath, result.TVShowPath); |             GlobalInfos.setVideoPaths(result.VideoPath, result.TVShowPath); | ||||||
|  |  | ||||||
|             GlobalInfos.setTVShowsEnabled(result.TVShowEnabled); |             GlobalInfos.setTVShowsEnabled(result.TVShowEnabled); | ||||||
|  |             GlobalInfos.setFullDeleteEnabled(result.FullDeleteEnabled); | ||||||
|  |  | ||||||
|             this.setState({ |             this.setState({ | ||||||
|                 mediacentername: result.MediacenterName |                 mediacentername: result.MediacenterName | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								src/elements/Popups/ButtonPopup/ButtonPopup.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/elements/Popups/ButtonPopup/ButtonPopup.test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | import {shallow} from 'enzyme'; | ||||||
|  | import React from 'react'; | ||||||
|  | import {ButtonPopup} from './ButtonPopup'; | ||||||
|  | import exp from "constants"; | ||||||
|  |  | ||||||
|  | describe('<ButtonPopup/>', function () { | ||||||
|  |     it('renders without crashing ', function () { | ||||||
|  |         const wrapper = shallow(<ButtonPopup/>); | ||||||
|  |         wrapper.unmount(); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('renders two buttons', function () { | ||||||
|  |         const wrapper = shallow(<ButtonPopup/>); | ||||||
|  |         expect(wrapper.find('Button')).toHaveLength(2); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('renders three buttons if alternative defined', function () { | ||||||
|  |         const wrapper = shallow(<ButtonPopup AlternativeButtonTitle='alt'/>); | ||||||
|  |         expect(wrapper.find('Button')).toHaveLength(3); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('test click handlings', function () { | ||||||
|  |         const althandler = jest.fn(); | ||||||
|  |         const denyhandler = jest.fn(); | ||||||
|  |         const submithandler = jest.fn(); | ||||||
|  |  | ||||||
|  |         const wrapper = shallow(<ButtonPopup DenyButtonTitle='deny' onDeny={denyhandler} SubmitButtonTitle='submit' | ||||||
|  |                                              onSubmit={submithandler} AlternativeButtonTitle='alt' | ||||||
|  |                                              onAlternativeButton={althandler}/>); | ||||||
|  |         wrapper.find('Button').findWhere(e => e.props().title === "deny").simulate('click'); | ||||||
|  |         expect(denyhandler).toHaveBeenCalledTimes(1); | ||||||
|  |  | ||||||
|  |         wrapper.find('Button').findWhere(e => e.props().title === "alt").simulate('click'); | ||||||
|  |         expect(althandler).toHaveBeenCalledTimes(1); | ||||||
|  |  | ||||||
|  |         wrapper.find('Button').findWhere(e => e.props().title === "submit").simulate('click'); | ||||||
|  |         expect(submithandler).toHaveBeenCalledTimes(1); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('test Parentsubmit and parenthide callbacks', function () { | ||||||
|  |         const ondeny = jest.fn(); | ||||||
|  |         const onsubmit = jest.fn(); | ||||||
|  |  | ||||||
|  |         const wrapper = shallow(<ButtonPopup DenyButtonTitle='deny' SubmitButtonTitle='submit' onDeny={ondeny} onSubmit={onsubmit} AlternativeButtonTitle='alt'/>); | ||||||
|  |         wrapper.find('PopupBase').props().onHide(); | ||||||
|  |         expect(ondeny).toHaveBeenCalledTimes(1); | ||||||
|  |  | ||||||
|  |         wrapper.find('PopupBase').props().ParentSubmit(); | ||||||
|  |         expect(onsubmit).toHaveBeenCalledTimes(1); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
							
								
								
									
										58
									
								
								src/elements/Popups/ButtonPopup/ButtonPopup.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/elements/Popups/ButtonPopup/ButtonPopup.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | import React from 'react'; | ||||||
|  | import PopupBase from '../PopupBase'; | ||||||
|  | import {Button} from '../../GPElements/Button'; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Delete Video popup | ||||||
|  |  * can only be rendered once! | ||||||
|  |  * @constructor | ||||||
|  |  */ | ||||||
|  | export const ButtonPopup = (props: { | ||||||
|  |     onSubmit: () => void; | ||||||
|  |     onDeny: () => void; | ||||||
|  |     onAlternativeButton?: () => void; | ||||||
|  |     SubmitButtonTitle: string; | ||||||
|  |     DenyButtonTitle: string; | ||||||
|  |     AlternativeButtonTitle?: string; | ||||||
|  |     Title: string; | ||||||
|  | }): JSX.Element => { | ||||||
|  |     return ( | ||||||
|  |         <> | ||||||
|  |             <PopupBase | ||||||
|  |                 title={props.Title} | ||||||
|  |                 onHide={(): void => props.onDeny()} | ||||||
|  |                 height='200px' | ||||||
|  |                 width='400px' | ||||||
|  |                 ParentSubmit={(): void => { | ||||||
|  |                     props.onSubmit(); | ||||||
|  |                 }}> | ||||||
|  |                 <Button | ||||||
|  |                     onClick={(): void => { | ||||||
|  |                         props.onSubmit(); | ||||||
|  |                     }} | ||||||
|  |                     title={props.SubmitButtonTitle} | ||||||
|  |                 /> | ||||||
|  |  | ||||||
|  |                 {props.AlternativeButtonTitle ? ( | ||||||
|  |                     <Button | ||||||
|  |                         color={{backgroundColor: 'darkorange'}} | ||||||
|  |                         onClick={(): void => { | ||||||
|  |                             props.onAlternativeButton ? props.onAlternativeButton() : null; | ||||||
|  |                         }} | ||||||
|  |                         title={props.AlternativeButtonTitle} | ||||||
|  |                     /> | ||||||
|  |                 ) : ( | ||||||
|  |                     <></> | ||||||
|  |                 )} | ||||||
|  |  | ||||||
|  |                 <Button | ||||||
|  |                     color={{backgroundColor: 'red'}} | ||||||
|  |                     onClick={(): void => { | ||||||
|  |                         props.onDeny(); | ||||||
|  |                     }} | ||||||
|  |                     title={props.DenyButtonTitle} | ||||||
|  |                 /> | ||||||
|  |             </PopupBase> | ||||||
|  |         </> | ||||||
|  |     ); | ||||||
|  | }; | ||||||
| @@ -2,6 +2,7 @@ import {shallow} from 'enzyme'; | |||||||
| import React from 'react'; | import React from 'react'; | ||||||
| import {Player} from './Player'; | import {Player} from './Player'; | ||||||
| import {callAPI} from '../../utils/Api'; | import {callAPI} from '../../utils/Api'; | ||||||
|  | import GlobalInfos from "../../utils/GlobalInfos"; | ||||||
|  |  | ||||||
| describe('<Player/>', function () { | describe('<Player/>', function () { | ||||||
|  |  | ||||||
| @@ -84,23 +85,54 @@ describe('<Player/>', function () { | |||||||
|         expect(wrapper.find('AddTagPopup')).toHaveLength(1); |         expect(wrapper.find('AddTagPopup')).toHaveLength(1); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     it('test delete button', done => { |     it('test fully delete popup rendering', function () { | ||||||
|         const wrapper = instance(); |         const wrapper = instance(); | ||||||
|  |  | ||||||
|  |         // allow videos to be fully deletable | ||||||
|  |         GlobalInfos.setFullDeleteEnabled(true); | ||||||
|  |  | ||||||
|         wrapper.setProps({history: {goBack: jest.fn()}}); |         wrapper.setState({deletepopupvisible: true}); | ||||||
|  |  | ||||||
|         global.fetch = prepareFetchApi({result: 'success'}); |         expect(wrapper.find('ButtonPopup')).toHaveLength(1) | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('test delete popup rendering', function () { | ||||||
|  |         const wrapper = instance(); | ||||||
|  |  | ||||||
|  |         GlobalInfos.setFullDeleteEnabled(false); | ||||||
|  |         wrapper.setState({deletepopupvisible: true}); | ||||||
|  |  | ||||||
|  |         expect(wrapper.find('ButtonPopup')).toHaveLength(1) | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     it('test delete button', () => { | ||||||
|  |         const wrapper = instance(); | ||||||
|  |         const callback = jest.fn(); | ||||||
|  |  | ||||||
|  |         wrapper.setProps({history: {goBack: callback}}); | ||||||
|  |  | ||||||
|  |         callAPIMock({result: 'success'}) | ||||||
|  |         GlobalInfos.setFullDeleteEnabled(false); | ||||||
|  |  | ||||||
|  |         // request the popup to pop | ||||||
|         wrapper.find('.videoactions').find('Button').at(2).simulate('click'); |         wrapper.find('.videoactions').find('Button').at(2).simulate('click'); | ||||||
|  |  | ||||||
|         process.nextTick(() => { |         // click the first submit button | ||||||
|             // refetch is called so fetch called 3 times |         wrapper.find('ButtonPopup').dive().find('Button').at(0).simulate('click') | ||||||
|             expect(global.fetch).toHaveBeenCalledTimes(1); |  | ||||||
|             expect(wrapper.instance().props.history.goBack).toHaveBeenCalledTimes(1); |  | ||||||
|  |  | ||||||
|             global.fetch.mockClear(); |         // refetch is called so fetch called 3 times | ||||||
|             done(); |         expect(callAPI).toHaveBeenCalledTimes(1); | ||||||
|  |         expect(callback).toHaveBeenCalledTimes(1); | ||||||
|  |  | ||||||
|  |         // now lets test if this works also with the fullydeletepopup | ||||||
|  |         GlobalInfos.setFullDeleteEnabled(true); | ||||||
|  |         // request the popup to pop | ||||||
|  |         wrapper.setState({deletepopupvisible: true}, () => { | ||||||
|  |             // click the first submit button | ||||||
|  |             wrapper.find('ButtonPopup').dive().find('Button').at(0).simulate('click') | ||||||
|  |  | ||||||
|  |             expect(callAPI).toHaveBeenCalledTimes(2); | ||||||
|  |             expect(callback).toHaveBeenCalledTimes(2); | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
| @@ -152,16 +184,14 @@ describe('<Player/>', function () { | |||||||
|     it('test click of quickadd tag btn', done => { |     it('test click of quickadd tag btn', done => { | ||||||
|         const wrapper = generatetag(); |         const wrapper = generatetag(); | ||||||
|  |  | ||||||
|         global.fetch = prepareFetchApi({result: 'success'}); |         callAPIMock({result: 'success'}) | ||||||
|  |  | ||||||
|         // render tag subcomponent |         // render tag subcomponent | ||||||
|         const tag = wrapper.find('Tag').first().dive(); |         const tag = wrapper.find('Tag').first().dive(); | ||||||
|         tag.simulate('click'); |         tag.simulate('click'); | ||||||
|  |  | ||||||
|         process.nextTick(() => { |         process.nextTick(() => { | ||||||
|             expect(global.fetch).toHaveBeenCalledTimes(1); |             expect(callAPI).toHaveBeenCalledTimes(1); | ||||||
|  |  | ||||||
|             global.fetch.mockClear(); |  | ||||||
|             done(); |             done(); | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
| @@ -169,7 +199,7 @@ describe('<Player/>', function () { | |||||||
|     it('test failing quickadd', done => { |     it('test failing quickadd', done => { | ||||||
|         const wrapper = generatetag(); |         const wrapper = generatetag(); | ||||||
|  |  | ||||||
|         global.fetch = prepareFetchApi({result: 'nonsuccess'}); |         callAPIMock({result: 'nonsuccess'}); | ||||||
|         global.console.error = jest.fn(); |         global.console.error = jest.fn(); | ||||||
|  |  | ||||||
|         // render tag subcomponent |         // render tag subcomponent | ||||||
| @@ -178,8 +208,6 @@ describe('<Player/>', function () { | |||||||
|  |  | ||||||
|         process.nextTick(() => { |         process.nextTick(() => { | ||||||
|             expect(global.console.error).toHaveBeenCalledTimes(2); |             expect(global.console.error).toHaveBeenCalledTimes(2); | ||||||
|  |  | ||||||
|             global.fetch.mockClear(); |  | ||||||
|             done(); |             done(); | ||||||
|         }); |         }); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ import PlyrJS from 'plyr'; | |||||||
| import {Button} from '../../elements/GPElements/Button'; | import {Button} from '../../elements/GPElements/Button'; | ||||||
| import {VideoTypes} from '../../types/ApiTypes'; | import {VideoTypes} from '../../types/ApiTypes'; | ||||||
| import GlobalInfos from '../../utils/GlobalInfos'; | import GlobalInfos from '../../utils/GlobalInfos'; | ||||||
|  | import {ButtonPopup} from '../../elements/Popups/ButtonPopup/ButtonPopup'; | ||||||
|  |  | ||||||
| interface Props extends RouteComponentProps<{id: string}> {} | interface Props extends RouteComponentProps<{id: string}> {} | ||||||
|  |  | ||||||
| @@ -35,6 +36,7 @@ interface mystate { | |||||||
|     suggesttag: TagType[]; |     suggesttag: TagType[]; | ||||||
|     popupvisible: boolean; |     popupvisible: boolean; | ||||||
|     actorpopupvisible: boolean; |     actorpopupvisible: boolean; | ||||||
|  |     deletepopupvisible: boolean; | ||||||
|     actors: ActorType[]; |     actors: ActorType[]; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -56,6 +58,7 @@ export class Player extends React.Component<Props, mystate> { | |||||||
|             suggesttag: [], |             suggesttag: [], | ||||||
|             popupvisible: false, |             popupvisible: false, | ||||||
|             actorpopupvisible: false, |             actorpopupvisible: false, | ||||||
|  |             deletepopupvisible: false, | ||||||
|             actors: [] |             actors: [] | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
| @@ -91,7 +94,7 @@ export class Player extends React.Component<Props, mystate> { | |||||||
|                         <Button |                         <Button | ||||||
|                             title='Delete Video' |                             title='Delete Video' | ||||||
|                             onClick={(): void => { |                             onClick={(): void => { | ||||||
|                                 this.deleteVideo(); |                                 this.setState({deletepopupvisible: true}); | ||||||
|                             }} |                             }} | ||||||
|                             color={{backgroundColor: 'red'}} |                             color={{backgroundColor: 'red'}} | ||||||
|                         /> |                         /> | ||||||
| @@ -196,10 +199,46 @@ export class Player extends React.Component<Props, mystate> { | |||||||
|                         movieId={this.state.movieId} |                         movieId={this.state.movieId} | ||||||
|                     /> |                     /> | ||||||
|                 ) : null} |                 ) : null} | ||||||
|  |                 {this.state.deletepopupvisible ? this.renderDeletePopup() : null} | ||||||
|             </> |             </> | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     renderDeletePopup(): JSX.Element { | ||||||
|  |         if (GlobalInfos.isVideoFulldeleteable()) { | ||||||
|  |             return ( | ||||||
|  |                 <ButtonPopup | ||||||
|  |                     onDeny={(): void => this.setState({deletepopupvisible: false})} | ||||||
|  |                     onSubmit={(): void => { | ||||||
|  |                         this.setState({deletepopupvisible: false}); | ||||||
|  |                         this.deleteVideo(true); | ||||||
|  |                     }} | ||||||
|  |                     onAlternativeButton={(): void => { | ||||||
|  |                         this.setState({deletepopupvisible: false}); | ||||||
|  |                         this.deleteVideo(false); | ||||||
|  |                     }} | ||||||
|  |                     DenyButtonTitle='Cancel' | ||||||
|  |                     SubmitButtonTitle='Fully Delete!' | ||||||
|  |                     Title='Fully Delete Video?' | ||||||
|  |                     AlternativeButtonTitle='Reference Only' | ||||||
|  |                 /> | ||||||
|  |             ); | ||||||
|  |         } else { | ||||||
|  |             return ( | ||||||
|  |                 <ButtonPopup | ||||||
|  |                     onDeny={(): void => this.setState({deletepopupvisible: false})} | ||||||
|  |                     onSubmit={(): void => { | ||||||
|  |                         this.setState({deletepopupvisible: false}); | ||||||
|  |                         this.deleteVideo(false); | ||||||
|  |                     }} | ||||||
|  |                     DenyButtonTitle='Cancel' | ||||||
|  |                     SubmitButtonTitle='Delete Video Reference!' | ||||||
|  |                     Title='Delete Video?' | ||||||
|  |                 /> | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * quick add callback to add tag to db and change gui correctly |      * quick add callback to add tag to db and change gui correctly | ||||||
|      * @param tagId id of tag to add |      * @param tagId id of tag to add | ||||||
| @@ -325,17 +364,16 @@ export class Player extends React.Component<Props, mystate> { | |||||||
|     /** |     /** | ||||||
|      * delete the current video and return to last page |      * delete the current video and return to last page | ||||||
|      */ |      */ | ||||||
|     deleteVideo(): void { |     deleteVideo(fullyDelete: boolean): void { | ||||||
|         callAPI( |         callAPI( | ||||||
|             APINode.Video, |             APINode.Video, | ||||||
|             {action: 'deleteVideo', MovieId: parseInt(this.props.match.params.id, 10)}, |             {action: 'deleteVideo', MovieId: parseInt(this.props.match.params.id, 10), FullyDelete: fullyDelete}, | ||||||
|             (result: GeneralSuccess) => { |             (result: GeneralSuccess) => { | ||||||
|                 if (result.result === 'success') { |                 if (result.result === 'success') { | ||||||
|                     // return to last element if successful |                     // return to last element if successful | ||||||
|                     this.props.history.goBack(); |                     this.props.history.goBack(); | ||||||
|                 } else { |                 } else { | ||||||
|                     console.error('an error occured while liking'); |                     console.error('an error occured while deleting the video: ' + JSON.stringify(result)); | ||||||
|                     console.error(result); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|   | |||||||
| @@ -37,6 +37,7 @@ export namespace SettingsTypes { | |||||||
|         VideoPath: string; |         VideoPath: string; | ||||||
|         TVShowPath: string; |         TVShowPath: string; | ||||||
|         TVShowEnabled: boolean; |         TVShowEnabled: boolean; | ||||||
|  |         FullDeleteEnabled: boolean; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     export interface SettingsType { |     export interface SettingsType { | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ class StaticInfos { | |||||||
|     private videopath: string = ''; |     private videopath: string = ''; | ||||||
|     private tvshowpath: string = ''; |     private tvshowpath: string = ''; | ||||||
|     private TVShowsEnabled: boolean = false; |     private TVShowsEnabled: boolean = false; | ||||||
|  |     private fullDeleteable: boolean = false; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * check if the current theme is the dark theme |      * check if the current theme is the dark theme | ||||||
| @@ -80,6 +81,14 @@ class StaticInfos { | |||||||
|     isTVShowEnabled(): boolean { |     isTVShowEnabled(): boolean { | ||||||
|         return this.TVShowsEnabled; |         return this.TVShowsEnabled; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     setFullDeleteEnabled(FullDeleteEnabled: boolean): void { | ||||||
|  |         this.fullDeleteable = FullDeleteEnabled; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     isVideoFulldeleteable(): boolean { | ||||||
|  |         return this.fullDeleteable; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| export default new StaticInfos(); | export default new StaticInfos(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user