Added custom languages to the top

This commit is contained in:
JohnBednarczyk 2020-12-20 09:21:51 -06:00 committed by Qstick
parent a31ca4e80b
commit c2a21cd238
25 changed files with 133 additions and 41 deletions

View File

@ -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}

View File

@ -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;

View File

@ -21,3 +21,8 @@
color: $darkGray;
font-size: $smallFontSize;
}
.divider {
border: none;
border-bottom: 1px solid $lightGray;
}

View File

@ -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
};

View 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);

View File

@ -49,6 +49,7 @@ function getSelectValues(selectOptions) {
result.push({
key: option.value,
value: option.name,
dividerAfter: option.dividerAfter,
hint: option.hint
});

View File

@ -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,

View File

@ -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}

View File

@ -254,7 +254,7 @@ class EditQualityProfileModalContent extends Component {
</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
type={inputTypes.LANGUAGE_SELECT}
name="language"
values={languages}
value={languageId}

View File

@ -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')}

View File

@ -10,6 +10,9 @@ namespace NzbDrone.Core.Test.Languages
{
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 @@ namespace NzbDrone.Core.Test.Languages
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 },

View File

@ -6,5 +6,6 @@ namespace NzbDrone.Core.Annotations
public string Name { get; set; }
public int Order { get; set; }
public string Hint { get; set; }
public bool DividerAfter { get; set; }
}
}

View File

@ -45,7 +45,7 @@ namespace NzbDrone.Core.Indexers.FileList
[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.")]

View File

@ -37,7 +37,7 @@ namespace NzbDrone.Core.Indexers.HDBits
[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)]

View File

@ -40,7 +40,7 @@ namespace NzbDrone.Core.Indexers.IPTorrents
[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)]

View File

@ -69,7 +69,7 @@ namespace NzbDrone.Core.Indexers.Newznab
[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)]

View File

@ -35,7 +35,7 @@ namespace NzbDrone.Core.Indexers.Nyaa
[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.")]

View File

@ -38,7 +38,7 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs
[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()

View File

@ -40,7 +40,7 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
[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)]

View File

@ -54,7 +54,7 @@ namespace NzbDrone.Core.Indexers.Rarbg
[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)]

View File

@ -38,7 +38,7 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
[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)]

View File

@ -39,7 +39,7 @@ namespace NzbDrone.Core.Indexers.TorrentRss
[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)]

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.Annotations;
namespace NzbDrone.Core.Languages
@ -7,7 +8,10 @@ namespace NzbDrone.Core.Languages
{
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 });
}
}
}

View File

@ -10,8 +10,9 @@ namespace NzbDrone.Core.Languages
{
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 });
}
}
}

View File

@ -26,13 +26,15 @@ namespace Radarr.Api.V3.Profiles.Languages
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;
}
}
}