Compare commits
	
		
			6 Commits
		
	
	
		
			rememberLo
			...
			settings_r
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7cd9cd7d89 | |||
| 11c1e25de5 | |||
| 3d845aaf04 | |||
| 7f98528fbe | |||
| 191fa5386d | |||
| 9715012685 | 
@@ -108,18 +108,13 @@ Debian_Server:
 | 
			
		||||
      - Minimize_Frontend
 | 
			
		||||
      - Build_Backend
 | 
			
		||||
 | 
			
		||||
Test_Server:
 | 
			
		||||
.Test_Server_Common:
 | 
			
		||||
  stage: deploy
 | 
			
		||||
  image: luki42/ssh:latest
 | 
			
		||||
  needs:
 | 
			
		||||
    - Frontend_Tests
 | 
			
		||||
    - Backend_Tests
 | 
			
		||||
    - Debian_Server
 | 
			
		||||
  rules:
 | 
			
		||||
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH # run this always on default branch
 | 
			
		||||
    - if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH # allow triggering this manually
 | 
			
		||||
      when: manual
 | 
			
		||||
      allow_failure: true
 | 
			
		||||
  script:
 | 
			
		||||
    - eval $(ssh-agent -s)
 | 
			
		||||
    - echo "$SSH_PRIVATE_KEY" | ssh-add -
 | 
			
		||||
@@ -129,18 +124,23 @@ Test_Server:
 | 
			
		||||
    - ssh root@192.168.0.42 "DEBIAN_FRONTEND=noninteractive apt-get --reinstall  -y -qq install /tmp/OpenMediaCenter-*.deb && rm /tmp/OpenMediaCenter-*.deb"
 | 
			
		||||
  allow_failure: true
 | 
			
		||||
 | 
			
		||||
Test_Server_2:
 | 
			
		||||
Test_Server_CD:
 | 
			
		||||
  extends: .Test_Server_Common
 | 
			
		||||
  only:
 | 
			
		||||
    refs:
 | 
			
		||||
      - master
 | 
			
		||||
 | 
			
		||||
Test_Server_MANUAL:
 | 
			
		||||
  extends: .Test_Server_Common
 | 
			
		||||
  when: manual
 | 
			
		||||
 | 
			
		||||
.Test_Server_2_Common:
 | 
			
		||||
  stage: deploy
 | 
			
		||||
  image: luki42/ssh:latest
 | 
			
		||||
  needs:
 | 
			
		||||
    - Frontend_Tests
 | 
			
		||||
    - Backend_Tests
 | 
			
		||||
    - Debian_Server
 | 
			
		||||
  rules:
 | 
			
		||||
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH # run this always on default branch
 | 
			
		||||
    - if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH # allow triggering this manually
 | 
			
		||||
      when: manual
 | 
			
		||||
      allow_failure: true
 | 
			
		||||
  script:
 | 
			
		||||
    - eval $(ssh-agent -s)
 | 
			
		||||
    - echo "$SSH_PRIVATE_KEY_2" | ssh-add -
 | 
			
		||||
@@ -150,3 +150,12 @@ Test_Server_2:
 | 
			
		||||
    - ssh root@192.168.0.209 "DEBIAN_FRONTEND=noninteractive apt-get --reinstall  -y -qq install /tmp/OpenMediaCenter-*.deb && rm /tmp/OpenMediaCenter-*.deb"
 | 
			
		||||
  allow_failure: true
 | 
			
		||||
 | 
			
		||||
Test_Server_2_CD:
 | 
			
		||||
  extends: .Test_Server_2_Common
 | 
			
		||||
  only:
 | 
			
		||||
    refs:
 | 
			
		||||
      - master
 | 
			
		||||
 | 
			
		||||
Test_Server_2_MANUAL:
 | 
			
		||||
  extends: .Test_Server_2_Common
 | 
			
		||||
  when: manual
 | 
			
		||||
@@ -74,6 +74,7 @@ func getSettingsFromDB() {
 | 
			
		||||
			TVShowPath        string
 | 
			
		||||
			TVShowEnabled     bool
 | 
			
		||||
			FullDeleteEnabled bool
 | 
			
		||||
			RandomNR          uint32
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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}")
 | 
			
		||||
@@ -90,6 +91,7 @@ func getSettingsFromDB() {
 | 
			
		||||
			TVShowPath:        serverTVShowPath,
 | 
			
		||||
			TVShowEnabled:     !config.GetConfig().Features.DisableTVSupport,
 | 
			
		||||
			FullDeleteEnabled: config.GetConfig().Features.FullyDeletableVideos,
 | 
			
		||||
			RandomNR:          sett.RandomNR,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		context.Json(res)
 | 
			
		||||
@@ -127,12 +129,13 @@ func saveSettingsToDB() {
 | 
			
		||||
                        password=?,
 | 
			
		||||
                        mediacenter_name=?,
 | 
			
		||||
                        TMDB_grabbing=?, 
 | 
			
		||||
                        DarkMode=?
 | 
			
		||||
                        DarkMode=?,
 | 
			
		||||
						random_nr=?
 | 
			
		||||
                    WHERE 1`
 | 
			
		||||
		// todo avoid conversion
 | 
			
		||||
		context.Text(string(database.SuccessQuery(query,
 | 
			
		||||
			args.VideoPath, args.EpisodePath, args.Password,
 | 
			
		||||
			args.MediacenterName, args.TMDBGrabbing, args.DarkMode)))
 | 
			
		||||
			args.MediacenterName, args.TMDBGrabbing, args.DarkMode, args.RandomNR)))
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"openmediacenter/apiGo/api/api"
 | 
			
		||||
@@ -9,6 +10,7 @@ import (
 | 
			
		||||
	"openmediacenter/apiGo/database"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func addVideoHandlers() {
 | 
			
		||||
@@ -162,7 +164,8 @@ func getVideoHandlers() {
 | 
			
		||||
	 */
 | 
			
		||||
	api.AddHandler("getRandomMovies", api.VideoNode, api.PermUser, func(context api.Context) {
 | 
			
		||||
		var args struct {
 | 
			
		||||
			Number int
 | 
			
		||||
			Number    int
 | 
			
		||||
			TagFilter []uint32
 | 
			
		||||
		}
 | 
			
		||||
		if api.DecodeRequest(context.GetRequest(), &args) != nil {
 | 
			
		||||
			context.Text("unable to decode request")
 | 
			
		||||
@@ -174,34 +177,52 @@ func getVideoHandlers() {
 | 
			
		||||
			Videos []types.VideoUnloadedType
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		query := fmt.Sprintf("SELECT movie_id,movie_name FROM videos ORDER BY RAND() LIMIT %d", args.Number)
 | 
			
		||||
		result.Videos = readVideosFromResultset(database.Query(query))
 | 
			
		||||
		whereclause := "WHERE 1"
 | 
			
		||||
		if len(args.TagFilter) > 0 {
 | 
			
		||||
			d, _ := json.Marshal(args.TagFilter)
 | 
			
		||||
			vals := strings.Trim(string(d), "[]")
 | 
			
		||||
 | 
			
		||||
		var ids string
 | 
			
		||||
		for i := range result.Videos {
 | 
			
		||||
			ids += "video_tags.video_id=" + strconv.Itoa(result.Videos[i].MovieId)
 | 
			
		||||
 | 
			
		||||
			if i < len(result.Videos)-1 {
 | 
			
		||||
				ids += " OR "
 | 
			
		||||
			}
 | 
			
		||||
			whereclause = fmt.Sprintf("WHERE tag_id IN (%s)", vals)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// add the corresponding tags
 | 
			
		||||
		query = fmt.Sprintf(`SELECT t.tag_name,t.tag_id FROM video_tags
 | 
			
		||||
		query := fmt.Sprintf(`
 | 
			
		||||
SELECT video_tags.video_id,v.movie_name FROM video_tags join videos v on v.movie_id = video_tags.video_id
 | 
			
		||||
                                        %s
 | 
			
		||||
                                        group by video_id
 | 
			
		||||
                                        ORDER BY RAND()
 | 
			
		||||
                                        LIMIT %d`, whereclause, args.Number)
 | 
			
		||||
		result.Videos = readVideosFromResultset(database.Query(query))
 | 
			
		||||
 | 
			
		||||
		if len(result.Videos) > 0 {
 | 
			
		||||
			var ids string
 | 
			
		||||
			for i := range result.Videos {
 | 
			
		||||
				ids += "video_tags.video_id=" + strconv.Itoa(result.Videos[i].MovieId)
 | 
			
		||||
 | 
			
		||||
				if i < len(result.Videos)-1 {
 | 
			
		||||
					ids += " OR "
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// add the corresponding tags
 | 
			
		||||
			query = fmt.Sprintf(`SELECT t.tag_name,t.tag_id FROM video_tags
 | 
			
		||||
									INNER JOIN tags t on video_tags.tag_id = t.tag_id
 | 
			
		||||
									WHERE %s
 | 
			
		||||
									GROUP BY t.tag_id`, ids)
 | 
			
		||||
 | 
			
		||||
		rows := database.Query(query)
 | 
			
		||||
 | 
			
		||||
		for rows.Next() {
 | 
			
		||||
			var tag types.Tag
 | 
			
		||||
			err := rows.Scan(&tag.TagName, &tag.TagId)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				panic(err.Error()) // proper Error handling instead of panic in your app
 | 
			
		||||
			rows := database.Query(query)
 | 
			
		||||
			if rows != nil {
 | 
			
		||||
				for rows.Next() {
 | 
			
		||||
					var tag types.Tag
 | 
			
		||||
					err := rows.Scan(&tag.TagName, &tag.TagId)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						panic(err.Error()) // proper Error handling instead of panic in your app
 | 
			
		||||
					}
 | 
			
		||||
					// append to final array
 | 
			
		||||
					result.Tags = append(result.Tags, tag)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			// append to final array
 | 
			
		||||
			result.Tags = append(result.Tags, tag)
 | 
			
		||||
		} else {
 | 
			
		||||
			result.Tags = []types.Tag{}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		context.Json(result)
 | 
			
		||||
 
 | 
			
		||||
@@ -48,6 +48,7 @@ type SettingsType struct {
 | 
			
		||||
	PasswordEnabled bool
 | 
			
		||||
	TMDBGrabbing    bool
 | 
			
		||||
	DarkMode        bool
 | 
			
		||||
	RandomNR        uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SettingsSizeType struct {
 | 
			
		||||
 
 | 
			
		||||
@@ -126,7 +126,7 @@ func GetSettings() (result types.SettingsType, PathPrefix string, sizes types.Se
 | 
			
		||||
                           SELECT COUNT(*)
 | 
			
		||||
                           FROM video_tags
 | 
			
		||||
                       ) AS tagsadded,
 | 
			
		||||
                       video_path, episode_path, password, mediacenter_name, TMDB_grabbing, DarkMode
 | 
			
		||||
                       video_path, episode_path, password, mediacenter_name, TMDB_grabbing, DarkMode, random_nr
 | 
			
		||||
                FROM settings
 | 
			
		||||
                LIMIT 1`, DBName)
 | 
			
		||||
 | 
			
		||||
@@ -134,7 +134,7 @@ func GetSettings() (result types.SettingsType, PathPrefix string, sizes types.Se
 | 
			
		||||
	var TMDBGrabbing int
 | 
			
		||||
 | 
			
		||||
	err := QueryRow(query).Scan(&sizes.VideoNr, &sizes.DBSize, &sizes.DifferentTags, &sizes.TagsAdded,
 | 
			
		||||
		&result.VideoPath, &result.EpisodePath, &result.Password, &result.MediacenterName, &TMDBGrabbing, &DarkMode)
 | 
			
		||||
		&result.VideoPath, &result.EpisodePath, &result.Password, &result.MediacenterName, &TMDBGrabbing, &DarkMode, &result.RandomNR)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err.Error())
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								apiGo/database/migrations/20220505195845_randomnr.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								apiGo/database/migrations/20220505195845_randomnr.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
-- +goose Up
 | 
			
		||||
-- +goose StatementBegin
 | 
			
		||||
alter table settings
 | 
			
		||||
    add random_nr int default  3 null;
 | 
			
		||||
-- +goose StatementEnd
 | 
			
		||||
 | 
			
		||||
-- +goose Down
 | 
			
		||||
-- +goose StatementBegin
 | 
			
		||||
alter table settings
 | 
			
		||||
    drop random_nr;
 | 
			
		||||
-- +goose StatementEnd
 | 
			
		||||
@@ -20,15 +20,16 @@ type SettingsType struct {
 | 
			
		||||
	MediacenterName string
 | 
			
		||||
	VideoPath       string
 | 
			
		||||
	TVShowPath      string
 | 
			
		||||
	RandomNR        uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func LoadSettings() *SettingsType {
 | 
			
		||||
	query := "SELECT DarkMode, password, mediacenter_name, video_path, episode_path from settings"
 | 
			
		||||
	query := "SELECT DarkMode, password, mediacenter_name, video_path, episode_path, random_nr from settings"
 | 
			
		||||
 | 
			
		||||
	result := SettingsType{}
 | 
			
		||||
	var darkmode uint8
 | 
			
		||||
 | 
			
		||||
	err := database.QueryRow(query).Scan(&darkmode, &result.Pasword, &result.MediacenterName, &result.VideoPath, &result.TVShowPath)
 | 
			
		||||
	err := database.QueryRow(query).Scan(&darkmode, &result.Pasword, &result.MediacenterName, &result.VideoPath, &result.TVShowPath, &result.RandomNR)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("error while parsing db data: " + err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,16 +2,22 @@ import React from 'react';
 | 
			
		||||
import style from './RandomPage.module.css';
 | 
			
		||||
import SideBar, {SideBarTitle} from '../../elements/SideBar/SideBar';
 | 
			
		||||
import Tag from '../../elements/Tag/Tag';
 | 
			
		||||
import PageTitle from '../../elements/PageTitle/PageTitle';
 | 
			
		||||
import PageTitle, {Line} from '../../elements/PageTitle/PageTitle';
 | 
			
		||||
import VideoContainer from '../../elements/VideoContainer/VideoContainer';
 | 
			
		||||
import {APINode, callAPI} from '../../utils/Api';
 | 
			
		||||
import {TagType} from '../../types/VideoTypes';
 | 
			
		||||
import {VideoTypes} from '../../types/ApiTypes';
 | 
			
		||||
import {addKeyHandler, removeKeyHandler} from '../../utils/ShortkeyHandler';
 | 
			
		||||
import {IconButton} from '../../elements/GPElements/Button';
 | 
			
		||||
import {faPlusCircle} from '@fortawesome/free-solid-svg-icons';
 | 
			
		||||
import AddTagPopup from '../../elements/Popups/AddTagPopup/AddTagPopup';
 | 
			
		||||
import GlobalInfos from '../../utils/GlobalInfos';
 | 
			
		||||
 | 
			
		||||
interface state {
 | 
			
		||||
    videos: VideoTypes.VideoUnloadedType[];
 | 
			
		||||
    tags: TagType[];
 | 
			
		||||
    filterTags: TagType[];
 | 
			
		||||
    addTagPopup: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface GetRandomMoviesType {
 | 
			
		||||
@@ -23,14 +29,14 @@ interface GetRandomMoviesType {
 | 
			
		||||
 * Randompage shuffles random viedeopreviews and provides a shuffle btn
 | 
			
		||||
 */
 | 
			
		||||
class RandomPage extends React.Component<{}, state> {
 | 
			
		||||
    readonly LoadNR = 3;
 | 
			
		||||
 | 
			
		||||
    constructor(props: {}) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.state = {
 | 
			
		||||
            addTagPopup: false,
 | 
			
		||||
            videos: [],
 | 
			
		||||
            tags: []
 | 
			
		||||
            tags: [],
 | 
			
		||||
            filterTags: []
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.keypress = this.keypress.bind(this);
 | 
			
		||||
@@ -39,7 +45,7 @@ class RandomPage extends React.Component<{}, state> {
 | 
			
		||||
    componentDidMount(): void {
 | 
			
		||||
        addKeyHandler(this.keypress);
 | 
			
		||||
 | 
			
		||||
        this.loadShuffledvideos(this.LoadNR);
 | 
			
		||||
        this.loadShuffledvideos();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    componentWillUnmount(): void {
 | 
			
		||||
@@ -49,49 +55,66 @@ class RandomPage extends React.Component<{}, state> {
 | 
			
		||||
    render(): JSX.Element {
 | 
			
		||||
        return (
 | 
			
		||||
            <div>
 | 
			
		||||
                <PageTitle title='Random Videos' subtitle='4pc' />
 | 
			
		||||
                <PageTitle title='Random Videos' subtitle={GlobalInfos.getRandomNR() + 'pc'} />
 | 
			
		||||
 | 
			
		||||
                <SideBar>
 | 
			
		||||
                    <SideBarTitle>Visible Tags:</SideBarTitle>
 | 
			
		||||
                    {this.state.tags.map((m) => (
 | 
			
		||||
                        <Tag key={m.TagId} tagInfo={m} />
 | 
			
		||||
                    ))}
 | 
			
		||||
                    <Line />
 | 
			
		||||
                    <SideBarTitle>Filter Tags:</SideBarTitle>
 | 
			
		||||
                    {this.state.filterTags.map((m) => (
 | 
			
		||||
                        <Tag key={m.TagId} tagInfo={m} />
 | 
			
		||||
                    ))}
 | 
			
		||||
                    <IconButton
 | 
			
		||||
                        title='Add'
 | 
			
		||||
                        icon={faPlusCircle}
 | 
			
		||||
                        onClick={(): void => {
 | 
			
		||||
                            this.setState({addTagPopup: true});
 | 
			
		||||
                        }}
 | 
			
		||||
                    />
 | 
			
		||||
                </SideBar>
 | 
			
		||||
 | 
			
		||||
                {this.state.videos.length !== 0 ? (
 | 
			
		||||
                    <VideoContainer data={this.state.videos}>
 | 
			
		||||
                        <div className={style.Shufflebutton}>
 | 
			
		||||
                            <button onClick={(): void => this.shuffleclick()} className={style.btnshuffle}>
 | 
			
		||||
                                Shuffle
 | 
			
		||||
                            </button>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </VideoContainer>
 | 
			
		||||
                ) : (
 | 
			
		||||
                    <div>No Data found!</div>
 | 
			
		||||
                )}
 | 
			
		||||
                {this.state.videos.length !== 0 ? <VideoContainer data={this.state.videos} /> : <div>No Data found!</div>}
 | 
			
		||||
                <div className={style.Shufflebutton}>
 | 
			
		||||
                    <button onClick={(): void => this.loadShuffledvideos()} className={style.btnshuffle}>
 | 
			
		||||
                        Shuffle
 | 
			
		||||
                    </button>
 | 
			
		||||
                </div>
 | 
			
		||||
                {this.state.addTagPopup ? (
 | 
			
		||||
                    <AddTagPopup
 | 
			
		||||
                        onHide={(): void => this.setState({addTagPopup: false})}
 | 
			
		||||
                        submit={(tagId: number, tagName: string): void => {
 | 
			
		||||
                            this.setState({filterTags: [...this.state.filterTags, {TagId: tagId, TagName: tagName}]}, (): void => {
 | 
			
		||||
                                this.loadShuffledvideos();
 | 
			
		||||
                            });
 | 
			
		||||
                        }}
 | 
			
		||||
                    />
 | 
			
		||||
                ) : null}
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * click handler for shuffle btn
 | 
			
		||||
     */
 | 
			
		||||
    shuffleclick(): void {
 | 
			
		||||
        this.loadShuffledvideos(this.LoadNR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * load random videos from backend
 | 
			
		||||
     * @param nr number of videos to load
 | 
			
		||||
     */
 | 
			
		||||
    loadShuffledvideos(nr: number): void {
 | 
			
		||||
        callAPI<GetRandomMoviesType>(APINode.Video, {action: 'getRandomMovies', Number: nr}, (result) => {
 | 
			
		||||
            this.setState({videos: []}); // needed to trigger rerender of main videoview
 | 
			
		||||
            this.setState({
 | 
			
		||||
                videos: result.Videos,
 | 
			
		||||
                tags: result.Tags
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    loadShuffledvideos(): void {
 | 
			
		||||
        callAPI<GetRandomMoviesType>(
 | 
			
		||||
            APINode.Video,
 | 
			
		||||
            {
 | 
			
		||||
                action: 'getRandomMovies',
 | 
			
		||||
                Number: GlobalInfos.getRandomNR(),
 | 
			
		||||
                TagFilter: this.state.filterTags.map((t) => t.TagId)
 | 
			
		||||
            },
 | 
			
		||||
            (result) => {
 | 
			
		||||
                this.setState({videos: []}); // needed to trigger rerender of main videoview
 | 
			
		||||
                this.setState({
 | 
			
		||||
                    videos: result.Videos,
 | 
			
		||||
                    tags: result.Tags
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -101,7 +124,7 @@ class RandomPage extends React.Component<{}, state> {
 | 
			
		||||
    private keypress(event: KeyboardEvent): void {
 | 
			
		||||
        // bind s to shuffle
 | 
			
		||||
        if (event.key === 's') {
 | 
			
		||||
            this.loadShuffledvideos(4);
 | 
			
		||||
            this.loadShuffledvideos();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,8 @@ class GeneralSettings extends React.Component<Props, state> {
 | 
			
		||||
                Password: '',
 | 
			
		||||
                PasswordEnabled: false,
 | 
			
		||||
                TMDBGrabbing: false,
 | 
			
		||||
                VideoPath: ''
 | 
			
		||||
                VideoPath: '',
 | 
			
		||||
                RandomNR: 3
 | 
			
		||||
            },
 | 
			
		||||
            sizes: {
 | 
			
		||||
                DBSize: 0,
 | 
			
		||||
@@ -199,6 +200,23 @@ class GeneralSettings extends React.Component<Props, state> {
 | 
			
		||||
                            />
 | 
			
		||||
                        </Form.Group>
 | 
			
		||||
 | 
			
		||||
                        <Form.Group className={style.mediacenternameform} data-testid='randnrform'>
 | 
			
		||||
                            <Form.Label>Number of random videos on Random page</Form.Label>
 | 
			
		||||
                            <Form.Control
 | 
			
		||||
                                type='number'
 | 
			
		||||
                                placeholder='2'
 | 
			
		||||
                                value={this.state.generalSettings.RandomNR}
 | 
			
		||||
                                onChange={(e): void =>
 | 
			
		||||
                                    this.setState({
 | 
			
		||||
                                        generalSettings: {
 | 
			
		||||
                                            ...this.state.generalSettings,
 | 
			
		||||
                                            RandomNR: parseInt(e.target.value, 10)
 | 
			
		||||
                                        }
 | 
			
		||||
                                    })
 | 
			
		||||
                                }
 | 
			
		||||
                            />
 | 
			
		||||
                        </Form.Group>
 | 
			
		||||
 | 
			
		||||
                        <Button variant='primary' type='submit'>
 | 
			
		||||
                            Submit
 | 
			
		||||
                        </Button>
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@ export namespace SettingsTypes {
 | 
			
		||||
        TVShowPath: string;
 | 
			
		||||
        TVShowEnabled: boolean;
 | 
			
		||||
        FullDeleteEnabled: boolean;
 | 
			
		||||
        RandomNR: number;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export interface SettingsType {
 | 
			
		||||
@@ -50,6 +51,7 @@ export namespace SettingsTypes {
 | 
			
		||||
        PasswordEnabled: boolean;
 | 
			
		||||
        TMDBGrabbing: boolean;
 | 
			
		||||
        DarkMode: boolean;
 | 
			
		||||
        RandomNR: number;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    export interface SizesType {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@ class StaticInfos {
 | 
			
		||||
    private tvshowpath: string = '';
 | 
			
		||||
    private TVShowsEnabled: boolean = false;
 | 
			
		||||
    private fullDeleteable: boolean = false;
 | 
			
		||||
    private RandomNR: number = 3;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * check if the current theme is the dark theme
 | 
			
		||||
@@ -44,6 +45,7 @@ class StaticInfos {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handlers: (() => void)[] = [];
 | 
			
		||||
 | 
			
		||||
    onThemeChange(func: () => void): void {
 | 
			
		||||
        this.handlers.push(func);
 | 
			
		||||
    }
 | 
			
		||||
@@ -71,6 +73,14 @@ class StaticInfos {
 | 
			
		||||
    getTVShowPath(): string {
 | 
			
		||||
        return this.tvshowpath;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setRandomNR(nr: number): void {
 | 
			
		||||
        this.RandomNR = nr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getRandomNR(): number {
 | 
			
		||||
        return this.RandomNR;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default new StaticInfos();
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@ export const LoginContextProvider: FunctionComponent = (props): JSX.Element => {
 | 
			
		||||
                GlobalInfos.enableDarkTheme(result.DarkMode);
 | 
			
		||||
 | 
			
		||||
                GlobalInfos.setVideoPaths(result.VideoPath, result.TVShowPath);
 | 
			
		||||
                GlobalInfos.setRandomNR(result.RandomNR);
 | 
			
		||||
 | 
			
		||||
                features.setTVShowEnabled(result.TVShowEnabled);
 | 
			
		||||
                features.setVideosFullyDeleteable(result.FullDeleteEnabled);
 | 
			
		||||
 
 | 
			
		||||
@@ -3538,9 +3538,9 @@ caniuse-api@^3.0.0:
 | 
			
		||||
    lodash.uniq "^4.5.0"
 | 
			
		||||
 | 
			
		||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001219:
 | 
			
		||||
  version "1.0.30001236"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001236.tgz#0a80de4cdf62e1770bb46a30d884fc8d633e3958"
 | 
			
		||||
  integrity sha512-o0PRQSrSCGJKCPZcgMzl5fUaj5xHe8qA2m4QRvnyY4e1lITqoNkr7q/Oh1NcpGSy0Th97UZ35yoKcINPoq7YOQ==
 | 
			
		||||
  version "1.0.30001336"
 | 
			
		||||
  resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001336.tgz"
 | 
			
		||||
  integrity sha512-/YxSlBmL7iKXTbIJ48IQTnAOBk7XmWsxhBF1PZLOko5Dt9qc4Pl+84lfqG3Tc4EuavurRn1QLoVJGxY2iSycfw==
 | 
			
		||||
 | 
			
		||||
capture-exit@^2.0.0:
 | 
			
		||||
  version "2.0.0"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user