mirror of
https://github.com/Radarr/Radarr.git
synced 2024-10-26 22:52:40 +02:00
Added custom languages to the top
This commit is contained in:
parent
a31ca4e80b
commit
c2a21cd238
@ -479,6 +479,7 @@ class EnhancedSelectInput extends Component {
|
||||
<OptionComponent
|
||||
key={v.key}
|
||||
id={v.key}
|
||||
dividerAfter={v.dividerAfter}
|
||||
depth={depth}
|
||||
isSelected={isSelectedItem(index, this.props)}
|
||||
isDisabled={parentSelected}
|
||||
@ -539,6 +540,7 @@ class EnhancedSelectInput extends Component {
|
||||
<OptionComponent
|
||||
key={v.key}
|
||||
id={v.key}
|
||||
dividerAfter={v.dividerAfter}
|
||||
depth={depth}
|
||||
isSelected={isSelectedItem(index, this.props)}
|
||||
isMultiSelect={isMultiSelect}
|
||||
|
@ -13,6 +13,7 @@ import EnhancedSelectInputConnector from './EnhancedSelectInputConnector';
|
||||
import FormInputHelpText from './FormInputHelpText';
|
||||
import IndexerFlagsSelectInputConnector from './IndexerFlagsSelectInputConnector';
|
||||
import KeyValueListInput from './KeyValueListInput';
|
||||
import LanguageSelectInputConnector from './LanguageSelectInputConnector';
|
||||
import MovieMonitoredSelectInput from './MovieMonitoredSelectInput';
|
||||
import NumberInput from './NumberInput';
|
||||
import OAuthInputConnector from './OAuthInputConnector';
|
||||
@ -72,6 +73,9 @@ function getComponent(type) {
|
||||
case inputTypes.INDEXER_FLAGS_SELECT:
|
||||
return IndexerFlagsSelectInputConnector;
|
||||
|
||||
case inputTypes.LANGUAGE_SELECT:
|
||||
return LanguageSelectInputConnector;
|
||||
|
||||
case inputTypes.SELECT:
|
||||
return EnhancedSelectInput;
|
||||
|
||||
|
@ -21,3 +21,8 @@
|
||||
color: $darkGray;
|
||||
font-size: $smallFontSize;
|
||||
}
|
||||
|
||||
.divider {
|
||||
border: none;
|
||||
border-bottom: 1px solid $lightGray;
|
||||
}
|
||||
|
@ -12,37 +12,46 @@ function HintedSelectInputOption(props) {
|
||||
depth,
|
||||
isSelected,
|
||||
isDisabled,
|
||||
dividerAfter,
|
||||
isMultiSelect,
|
||||
isMobile,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<EnhancedSelectInputOption
|
||||
id={id}
|
||||
depth={depth}
|
||||
isSelected={isSelected}
|
||||
isDisabled={isDisabled}
|
||||
isHidden={isDisabled}
|
||||
isMultiSelect={isMultiSelect}
|
||||
isMobile={isMobile}
|
||||
{...otherProps}
|
||||
>
|
||||
<div className={classNames(
|
||||
styles.optionText,
|
||||
isMobile && styles.isMobile
|
||||
)}
|
||||
<div>
|
||||
<EnhancedSelectInputOption
|
||||
id={id}
|
||||
depth={depth}
|
||||
isSelected={isSelected}
|
||||
isDisabled={isDisabled}
|
||||
isHidden={isDisabled}
|
||||
isMultiSelect={isMultiSelect}
|
||||
isMobile={isMobile}
|
||||
{...otherProps}
|
||||
>
|
||||
<div>{value}</div>
|
||||
<div className={classNames(
|
||||
styles.optionText,
|
||||
isMobile && styles.isMobile
|
||||
)}
|
||||
>
|
||||
<div>{value}</div>
|
||||
|
||||
{
|
||||
hint != null &&
|
||||
<div className={styles.hintText}>
|
||||
{hint}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</EnhancedSelectInputOption>
|
||||
{
|
||||
hint != null &&
|
||||
<div className={styles.hintText}>
|
||||
{hint}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</EnhancedSelectInputOption>
|
||||
|
||||
{
|
||||
dividerAfter ?
|
||||
<div className={styles.divider} /> :
|
||||
null
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -50,15 +59,18 @@ HintedSelectInputOption.propTypes = {
|
||||
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
hint: PropTypes.node,
|
||||
name: PropTypes.string,
|
||||
depth: PropTypes.number,
|
||||
isSelected: PropTypes.bool.isRequired,
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
dividerAfter: PropTypes.bool.isRequired,
|
||||
isMultiSelect: PropTypes.bool.isRequired,
|
||||
isMobile: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
HintedSelectInputOption.defaultProps = {
|
||||
isDisabled: false,
|
||||
dividerAfter: false,
|
||||
isHidden: false,
|
||||
isMultiSelect: false
|
||||
};
|
||||
|
52
frontend/src/Components/Form/LanguageSelectInputConnector.js
Normal file
52
frontend/src/Components/Form/LanguageSelectInputConnector.js
Normal file
@ -0,0 +1,52 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import EnhancedSelectInput from './EnhancedSelectInput';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state, { values }) => values,
|
||||
( languages ) => {
|
||||
|
||||
const minId = languages.reduce((min, v) => (v.key < 1 ? v.key : min), languages[0].key);
|
||||
|
||||
const values = languages.map(({ key, value }) => {
|
||||
return {
|
||||
key,
|
||||
value,
|
||||
dividerAfter: minId < 1 ? key === minId : false
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
values
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
class LanguageSelectInputConnector extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<EnhancedSelectInput
|
||||
{...this.props}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LanguageSelectInputConnector.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]).isRequired,
|
||||
values: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps)(LanguageSelectInputConnector);
|
@ -49,6 +49,7 @@ function getSelectValues(selectOptions) {
|
||||
result.push({
|
||||
key: option.value,
|
||||
value: option.name,
|
||||
dividerAfter: option.dividerAfter,
|
||||
hint: option.hint
|
||||
});
|
||||
|
||||
|
@ -12,6 +12,7 @@ export const PATH = 'path';
|
||||
export const QUALITY_PROFILE_SELECT = 'qualityProfileSelect';
|
||||
export const ROOT_FOLDER_SELECT = 'rootFolderSelect';
|
||||
export const INDEXER_FLAGS_SELECT = 'indexerFlagsSelect';
|
||||
export const LANGUAGE_SELECT = 'languageSelect';
|
||||
export const SELECT = 'select';
|
||||
export const DYNAMIC_SELECT = 'dynamicSelect';
|
||||
export const TAG = 'tag';
|
||||
@ -36,6 +37,7 @@ export const all = [
|
||||
QUALITY_PROFILE_SELECT,
|
||||
ROOT_FOLDER_SELECT,
|
||||
INDEXER_FLAGS_SELECT,
|
||||
LANGUAGE_SELECT,
|
||||
SELECT,
|
||||
DYNAMIC_SELECT,
|
||||
TAG,
|
||||
|
@ -155,7 +155,7 @@ class FileEditModalContent extends Component {
|
||||
<FormLabel>{translate('Languages')}</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
type={inputTypes.LANGUAGE_SELECT}
|
||||
name="languageIds"
|
||||
value={languageIds}
|
||||
values={languageOptions}
|
||||
|
@ -254,7 +254,7 @@ class EditQualityProfileModalContent extends Component {
|
||||
</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
type={inputTypes.LANGUAGE_SELECT}
|
||||
name="language"
|
||||
values={languages}
|
||||
value={languageId}
|
||||
|
@ -200,7 +200,7 @@ class UISettings extends Component {
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('MovieInfoLanguage')}</FormLabel>
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
type={inputTypes.LANGUAGE_SELECT}
|
||||
name="movieInfoLanguage"
|
||||
values={languages}
|
||||
helpText={translate('MovieInfoLanguageHelpText')}
|
||||
@ -213,7 +213,7 @@ class UISettings extends Component {
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('UILanguage')}</FormLabel>
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
type={inputTypes.LANGUAGE_SELECT}
|
||||
name="uiLanguage"
|
||||
values={uiLanguages}
|
||||
helpText={translate('UILanguageHelpText')}
|
||||
|
@ -10,6 +10,9 @@ public class LanguageFixture : CoreTest
|
||||
{
|
||||
public static object[] FromIntCases =
|
||||
{
|
||||
new object[] { -2, Language.Original },
|
||||
new object[] { -1, Language.Any },
|
||||
new object[] { 0, Language.Unknown },
|
||||
new object[] { 1, Language.English },
|
||||
new object[] { 2, Language.French },
|
||||
new object[] { 3, Language.Spanish },
|
||||
@ -45,6 +48,9 @@ public class LanguageFixture : CoreTest
|
||||
|
||||
public static object[] ToIntCases =
|
||||
{
|
||||
new object[] { Language.Original, -2 },
|
||||
new object[] { Language.Any, -1 },
|
||||
new object[] { Language.Unknown, 0 },
|
||||
new object[] { Language.English, 1 },
|
||||
new object[] { Language.French, 2 },
|
||||
new object[] { Language.Spanish, 3 },
|
||||
|
@ -6,5 +6,6 @@ public class SelectOption
|
||||
public string Name { get; set; }
|
||||
public int Order { get; set; }
|
||||
public string Hint { get; set; }
|
||||
public bool DividerAfter { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public FileListSettings()
|
||||
[FieldDefinition(1, Label = "Passkey", Privacy = PrivacyLevel.ApiKey)]
|
||||
public string Passkey { get; set; }
|
||||
|
||||
[FieldDefinition(2, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
[FieldDefinition(2, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since your API key will be sent to that host.")]
|
||||
|
@ -37,7 +37,7 @@ public HDBitsSettings()
|
||||
[FieldDefinition(0, Label = "Username", Privacy = PrivacyLevel.UserName)]
|
||||
public string Username { get; set; }
|
||||
|
||||
[FieldDefinition(1, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
[FieldDefinition(1, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey)]
|
||||
|
@ -40,7 +40,7 @@ public IPTorrentsSettings()
|
||||
[FieldDefinition(0, Label = "Feed URL", HelpText = "The full RSS feed url generated by IPTorrents, using only the categories you selected (HD, SD, x264, etc ...)")]
|
||||
public string BaseUrl { get; set; }
|
||||
|
||||
[FieldDefinition(1, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
[FieldDefinition(1, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(2, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
|
@ -69,7 +69,7 @@ public NewznabSettings()
|
||||
[FieldDefinition(1, Label = "API Path", HelpText = "Path to the api, usually /api", Advanced = true)]
|
||||
public string ApiPath { get; set; }
|
||||
|
||||
[FieldDefinition(1, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
[FieldDefinition(1, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey)]
|
||||
|
@ -35,7 +35,7 @@ public NyaaSettings()
|
||||
[FieldDefinition(0, Label = "Website URL")]
|
||||
public string BaseUrl { get; set; }
|
||||
|
||||
[FieldDefinition(1, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
[FieldDefinition(1, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "Additional Parameters", Advanced = true, HelpText = "Please note if you change the category you will have to add required/restricted rules about the subgroups to avoid foreign language releases.")]
|
||||
|
@ -38,7 +38,7 @@ public OmgwtfnzbsSettings()
|
||||
[FieldDefinition(2, Label = "Delay", HelpText = "Time in minutes to delay new nzbs before they appear on the RSS feed", Advanced = true)]
|
||||
public int Delay { get; set; }
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
[FieldDefinition(3, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
|
@ -40,7 +40,7 @@ public PassThePopcornSettings()
|
||||
[FieldDefinition(2, Label = "APIKey", Type = FieldType.Password, Privacy = PrivacyLevel.Password)]
|
||||
public string APIKey { get; set; }
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
[FieldDefinition(3, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(4, Type = FieldType.Textbox, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
|
@ -54,7 +54,7 @@ public RarbgSettings()
|
||||
[FieldDefinition(2, Type = FieldType.Captcha, Label = "CAPTCHA Token", HelpText = "CAPTCHA Clearance token used to handle CloudFlare Anti-DDOS measures on shared-ip VPNs.")]
|
||||
public string CaptchaToken { get; set; }
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
[FieldDefinition(3, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(4, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
|
@ -38,7 +38,7 @@ public TorrentPotatoSettings()
|
||||
[FieldDefinition(2, Label = "Passkey", HelpText = "The password you use at your Indexer.", Privacy = PrivacyLevel.Password)]
|
||||
public string Passkey { get; set; }
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
[FieldDefinition(3, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(4, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
|
@ -39,7 +39,7 @@ public TorrentRssIndexerSettings()
|
||||
[FieldDefinition(2, Type = FieldType.Checkbox, Label = "Allow Zero Size", HelpText = "Enabling this will allow you to use feeds that don't specify release size, but be careful, size related checks will not be performed.")]
|
||||
public bool AllowZeroSize { get; set; }
|
||||
|
||||
[FieldDefinition(3, Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
[FieldDefinition(3, Type = FieldType.Select, SelectOptions = typeof(RealLanguageFieldConverter), Label = "Multi Languages", HelpText = "What languages are normally in a multi release on this indexer?", Advanced = true)]
|
||||
public IEnumerable<int> MultiLanguages { get; set; }
|
||||
|
||||
[FieldDefinition(4, Type = FieldType.Number, Label = "Minimum Seeders", HelpText = "Minimum number of seeders required.", Advanced = true)]
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Annotations;
|
||||
|
||||
namespace NzbDrone.Core.Languages
|
||||
@ -7,7 +8,10 @@ public class LanguageFieldConverter : ISelectOptionsConverter
|
||||
{
|
||||
public List<SelectOption> GetSelectOptions()
|
||||
{
|
||||
return Language.All.ConvertAll(v => new SelectOption { Value = v.Id, Name = v.Name });
|
||||
return Language.All
|
||||
.OrderBy(l => l.Id > 0).ThenBy(l => l.Name)
|
||||
.ToList()
|
||||
.ConvertAll(v => new SelectOption { Value = v.Id, Name = v.Name, DividerAfter = v.Id == Language.Unknown.Id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,9 @@ public List<SelectOption> GetSelectOptions()
|
||||
{
|
||||
return Language.All
|
||||
.Where(l => l != Language.Unknown && l != Language.Any)
|
||||
.OrderBy(l => l.Id > 0).ThenBy(l => l.Name)
|
||||
.ToList()
|
||||
.ConvertAll(v => new SelectOption { Value = v.Id, Name = v.Name });
|
||||
.ConvertAll(v => new SelectOption { Value = v.Id, Name = v.Name, DividerAfter = v.Id == Language.Original.Id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,13 +26,15 @@ private LanguageResource GetById(int id)
|
||||
|
||||
private List<LanguageResource> GetAll()
|
||||
{
|
||||
return Language.All.Select(l => new LanguageResource
|
||||
var languageResources = Language.All.Select(l => new LanguageResource
|
||||
{
|
||||
Id = (int)l,
|
||||
Name = l.ToString()
|
||||
})
|
||||
.OrderBy(l => l.Name)
|
||||
.OrderBy(l => l.Id > 0).ThenBy(l => l.Name)
|
||||
.ToList();
|
||||
|
||||
return languageResources;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user