Created generic Hinted EnhancedSelectInput components and use it instead of SelectInput

This commit is contained in:
Taloth Saldono 2019-06-16 15:36:11 +02:00 committed by Taloth
parent d3662f2302
commit 1af3e0bd93
11 changed files with 175 additions and 22 deletions

View File

@ -6,7 +6,7 @@ import classNames from 'classnames';
import getUniqueElememtId from 'Utilities/getUniqueElementId'; import getUniqueElememtId from 'Utilities/getUniqueElementId';
import isMobileUtil from 'Utilities/isMobile'; import isMobileUtil from 'Utilities/isMobile';
import * as keyCodes from 'Utilities/Constants/keyCodes'; import * as keyCodes from 'Utilities/Constants/keyCodes';
import { icons, scrollDirections } from 'Helpers/Props'; import { icons, sizes, scrollDirections } from 'Helpers/Props';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import Portal from 'Components/Portal'; import Portal from 'Components/Portal';
import Link from 'Components/Link/Link'; import Link from 'Components/Link/Link';
@ -14,8 +14,8 @@ import Measure from 'Components/Measure';
import Modal from 'Components/Modal/Modal'; import Modal from 'Components/Modal/Modal';
import ModalBody from 'Components/Modal/ModalBody'; import ModalBody from 'Components/Modal/ModalBody';
import Scroller from 'Components/Scroller/Scroller'; import Scroller from 'Components/Scroller/Scroller';
import EnhancedSelectInputSelectedValue from './EnhancedSelectInputSelectedValue'; import HintedSelectInputSelectedValue from './HintedSelectInputSelectedValue';
import EnhancedSelectInputOption from './EnhancedSelectInputOption'; import HintedSelectInputOption from './HintedSelectInputOption';
import styles from './EnhancedSelectInput.css'; import styles from './EnhancedSelectInput.css';
function isArrowKey(keyCode) { function isArrowKey(keyCode) {
@ -150,9 +150,11 @@ class EnhancedSelectInput extends Component {
} }
onBlur = () => { onBlur = () => {
this.setState({ // Calling setState without this check prevents the click event from being properly handled on Chrome (it is on firefox)
selectedIndex: getSelectedIndex(this.props) const origIndex = getSelectedIndex(this.props);
}); if (origIndex !== this.state.selectedIndex) {
this.setState({ selectedIndex: origIndex });
}
} }
onKeyDown = (event) => { onKeyDown = (event) => {
@ -385,6 +387,7 @@ class EnhancedSelectInput extends Component {
isMobile && isMobile &&
<Modal <Modal
className={styles.optionsModal} className={styles.optionsModal}
size={sizes.EXTRA_SMALL}
isOpen={isOpen} isOpen={isOpen}
onModalClose={this.onOptionsModalClose} onModalClose={this.onOptionsModalClose}
> >
@ -439,8 +442,8 @@ EnhancedSelectInput.defaultProps = {
disabledClassName: styles.isDisabled, disabledClassName: styles.isDisabled,
isDisabled: false, isDisabled: false,
selectedValueOptions: {}, selectedValueOptions: {},
selectedValueComponent: EnhancedSelectInputSelectedValue, selectedValueComponent: HintedSelectInputSelectedValue,
optionComponent: EnhancedSelectInputOption optionComponent: HintedSelectInputOption
}; };
export default EnhancedSelectInput; export default EnhancedSelectInput;

View File

@ -7,13 +7,17 @@
cursor: default; cursor: default;
&:hover { &:hover {
background-color: #f9f9f9; background-color: #f8f8f8;
} }
} }
.isSelected { .isSelected {
background-color: #e2e2e2; background-color: #e2e2e2;
&:hover {
background-color: #e2e2e2;
}
&.isMobile { &.isMobile {
background-color: inherit; background-color: inherit;

View File

@ -1,5 +1,6 @@
.inputGroupContainer { .inputGroupContainer {
flex: 1 1 auto; flex: 1 1 auto;
min-width: 0;
} }
.inputGroup { .inputGroup {
@ -11,6 +12,7 @@
.inputContainer { .inputContainer {
position: relative; position: relative;
flex: 1 1 auto; flex: 1 1 auto;
min-width: 0;
} }
.inputUnit { .inputUnit {

View File

@ -16,7 +16,7 @@ import QualityProfileSelectInputConnector from './QualityProfileSelectInputConne
import LanguageProfileSelectInputConnector from './LanguageProfileSelectInputConnector'; import LanguageProfileSelectInputConnector from './LanguageProfileSelectInputConnector';
import RootFolderSelectInputConnector from './RootFolderSelectInputConnector'; import RootFolderSelectInputConnector from './RootFolderSelectInputConnector';
import SeriesTypeSelectInput from './SeriesTypeSelectInput'; import SeriesTypeSelectInput from './SeriesTypeSelectInput';
import SelectInput from './SelectInput'; import EnhancedSelectInput from './EnhancedSelectInput';
import TagInputConnector from './TagInputConnector'; import TagInputConnector from './TagInputConnector';
import TextTagInputConnector from './TextTagInputConnector'; import TextTagInputConnector from './TextTagInputConnector';
import TextInput from './TextInput'; import TextInput from './TextInput';
@ -65,7 +65,7 @@ function getComponent(type) {
return RootFolderSelectInputConnector; return RootFolderSelectInputConnector;
case inputTypes.SELECT: case inputTypes.SELECT:
return SelectInput; return EnhancedSelectInput;
case inputTypes.SERIES_TYPE_SELECT: case inputTypes.SERIES_TYPE_SELECT:
return SeriesTypeSelectInput; return SeriesTypeSelectInput;

View File

@ -0,0 +1,23 @@
.optionText {
display: flex;
align-items: center;
justify-content: space-between;
flex: 1 0 0;
min-width: 0;
&.isMobile {
display: block;
.hintText {
margin-left: 0;
}
}
}
.hintText {
@add-mixin truncate;
margin-left: 15px;
color: $darkGray;
font-size: $smallFontSize;
}

View File

@ -0,0 +1,44 @@
import PropTypes from 'prop-types';
import React from 'react';
import classNames from 'classnames';
import EnhancedSelectInputOption from './EnhancedSelectInputOption';
import styles from './HintedSelectInputOption.css';
function HintedSelectInputOption(props) {
const {
value,
hint,
isMobile,
...otherProps
} = props;
return (
<EnhancedSelectInputOption
isMobile={isMobile}
{...otherProps}
>
<div className={classNames(
styles.optionText,
isMobile && styles.isMobile
)}
>
<div>{value}</div>
{
hint != null &&
<div className={styles.hintText}>
{hint}
</div>
}
</div>
</EnhancedSelectInputOption>
);
}
HintedSelectInputOption.propTypes = {
value: PropTypes.string.isRequired,
hint: PropTypes.node,
isMobile: PropTypes.bool.isRequired
};
export default HintedSelectInputOption;

View File

@ -0,0 +1,24 @@
.selectedValue {
composes: selectedValue from '~./EnhancedSelectInputSelectedValue.css';
display: flex;
align-items: center;
justify-content: space-between;
overflow: hidden;
}
.valueText {
@add-mixin truncate;
flex: 0 0 auto;
}
.hintText {
@add-mixin truncate;
flex: 1 10 0;
margin-left: 15px;
color: $gray;
text-align: right;
font-size: $smallFontSize;
}

View File

@ -0,0 +1,43 @@
import PropTypes from 'prop-types';
import React from 'react';
import EnhancedSelectInputSelectedValue from './EnhancedSelectInputSelectedValue';
import styles from './HintedSelectInputSelectedValue.css';
function HintedSelectInputSelectedValue(props) {
const {
value,
hint,
includeHint,
...otherProps
} = props;
return (
<EnhancedSelectInputSelectedValue
className={styles.selectedValue}
{...otherProps}
>
<div className={styles.valueText}>
{value}
</div>
{
hint != null && includeHint &&
<div className={styles.hintText}>
{hint}
</div>
}
</EnhancedSelectInputSelectedValue>
);
}
HintedSelectInputSelectedValue.propTypes = {
value: PropTypes.string,
hint: PropTypes.string,
includeHint: PropTypes.bool.isRequired
};
HintedSelectInputSelectedValue.defaultProps = {
includeHint: true
};
export default HintedSelectInputSelectedValue;

View File

@ -61,7 +61,7 @@ function EditRemotePathMappingModalContent(props) {
<FormLabel>Host</FormLabel> <FormLabel>Host</FormLabel>
<FormInputGroup <FormInputGroup
type={inputTypes.AUTO_COMPLETE} type={inputTypes.SELECT}
name="host" name="host"
helpText="The same host you specified for the remote Download Client" helpText="The same host you specified for the remote Download Client"
{...host} {...host}

View File

@ -16,17 +16,27 @@ const newRemotePathMapping = {
const selectDownloadClientHosts = createSelector( const selectDownloadClientHosts = createSelector(
(state) => state.settings.downloadClients.items, (state) => state.settings.downloadClients.items,
(downloadClients) => { (downloadClients) => {
return downloadClients.reduce((acc, downloadClient) => { const hosts = downloadClients.reduce((acc, downloadClient) => {
const name = downloadClient.name;
const host = downloadClient.fields.find((field) => { const host = downloadClient.fields.find((field) => {
return field.name === 'host'; return field.name === 'host';
}); });
if (host && !acc.includes(host.value)) { if (host) {
acc.push(host.value); const group = acc[host.value] = acc[host.value] || [];
group.push(name);
} }
return acc; return acc;
}, []); }, {});
return Object.keys(hosts).map((host) => {
return {
key: host,
value: host,
hint: `${hosts[host].join(', ')}`
};
});
} }
); );

View File

@ -122,12 +122,12 @@ class Naming extends Component {
const renameEpisodes = hasSettings && settings.renameEpisodes.value; const renameEpisodes = hasSettings && settings.renameEpisodes.value;
const multiEpisodeStyleOptions = [ const multiEpisodeStyleOptions = [
{ key: 0, value: 'Extend' }, { key: 0, value: 'Extend', hint: 'S01E01-02-03' },
{ key: 1, value: 'Duplicate' }, { key: 1, value: 'Duplicate', hint: 'S01E01.S01E02' },
{ key: 2, value: 'Repeat' }, { key: 2, value: 'Repeat', hint: 'S01E01E02E03' },
{ key: 3, value: 'Scene' }, { key: 3, value: 'Scene', hint: 'S01E01-E02-E03' },
{ key: 4, value: 'Range' }, { key: 4, value: 'Range', hint: 'S01E01-03' },
{ key: 5, value: 'Prefixed Range' } { key: 5, value: 'Prefixed Range', hint: 'S01E01-E03' }
]; ];
const standardEpisodeFormatHelpTexts = []; const standardEpisodeFormatHelpTexts = [];