mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-14 00:53:57 -07:00
New: Optional Search Button on Artist Index views
This commit is contained in:
parent
88c58e2529
commit
0c1f9e6c8d
18 changed files with 310 additions and 24 deletions
|
@ -13,14 +13,42 @@ import createMetadataProfileSelector from 'Store/Selectors/createMetadataProfile
|
||||||
import { executeCommand } from 'Store/Actions/commandActions';
|
import { executeCommand } from 'Store/Actions/commandActions';
|
||||||
import * as commandNames from 'Commands/commandNames';
|
import * as commandNames from 'Commands/commandNames';
|
||||||
|
|
||||||
|
function selectShowSearchAction() {
|
||||||
|
return createSelector(
|
||||||
|
(state) => state.artistIndex,
|
||||||
|
(artistIndex) => {
|
||||||
|
const view = artistIndex.view;
|
||||||
|
|
||||||
|
switch (view) {
|
||||||
|
case 'posters':
|
||||||
|
return artistIndex.posterOptions.showSearchAction;
|
||||||
|
case 'banners':
|
||||||
|
return artistIndex.bannerOptions.showSearchAction;
|
||||||
|
case 'overview':
|
||||||
|
return artistIndex.overviewOptions.showSearchAction;
|
||||||
|
default:
|
||||||
|
return artistIndex.tableOptions.showSearchAction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
return createSelector(
|
return createSelector(
|
||||||
createArtistSelector(),
|
createArtistSelector(),
|
||||||
createQualityProfileSelector(),
|
createQualityProfileSelector(),
|
||||||
createLanguageProfileSelector(),
|
createLanguageProfileSelector(),
|
||||||
createMetadataProfileSelector(),
|
createMetadataProfileSelector(),
|
||||||
|
selectShowSearchAction(),
|
||||||
createCommandsSelector(),
|
createCommandsSelector(),
|
||||||
(artist, qualityProfile, languageProfile, metadataProfile, commands) => {
|
(
|
||||||
|
artist,
|
||||||
|
qualityProfile,
|
||||||
|
languageProfile,
|
||||||
|
metadataProfile,
|
||||||
|
showSearchAction,
|
||||||
|
commands
|
||||||
|
) => {
|
||||||
const isRefreshingArtist = commands.some((command) => {
|
const isRefreshingArtist = commands.some((command) => {
|
||||||
return (
|
return (
|
||||||
command.name === commandNames.REFRESH_ARTIST &&
|
command.name === commandNames.REFRESH_ARTIST &&
|
||||||
|
@ -29,6 +57,14 @@ function createMapStateToProps() {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isSearchingArtist = commands.some((command) => {
|
||||||
|
return (
|
||||||
|
command.name === commandNames.ARTIST_SEARCH &&
|
||||||
|
command.body.artistId === artist.id &&
|
||||||
|
isCommandExecuting(command)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const latestAlbum = _.maxBy(artist.albums, (album) => album.releaseDate);
|
const latestAlbum = _.maxBy(artist.albums, (album) => album.releaseDate);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -37,7 +73,9 @@ function createMapStateToProps() {
|
||||||
languageProfile,
|
languageProfile,
|
||||||
metadataProfile,
|
metadataProfile,
|
||||||
latestAlbum,
|
latestAlbum,
|
||||||
isRefreshingArtist
|
showSearchAction,
|
||||||
|
isRefreshingArtist,
|
||||||
|
isSearchingArtist
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -59,6 +97,13 @@ class ArtistIndexItemConnector extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSearchPress = () => {
|
||||||
|
this.props.executeCommand({
|
||||||
|
name: commandNames.ARTIST_SEARCH,
|
||||||
|
artistId: this.props.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Render
|
// Render
|
||||||
|
|
||||||
|
@ -72,6 +117,7 @@ class ArtistIndexItemConnector extends Component {
|
||||||
<ItemComponent
|
<ItemComponent
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
onRefreshArtistPress={this.onRefreshArtistPress}
|
onRefreshArtistPress={this.onRefreshArtistPress}
|
||||||
|
onSearchPress={this.onSearchPress}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ $hoverScale: 1.05;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
|
z-index: 3;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background-color: #216044;
|
background-color: #216044;
|
||||||
color: $white;
|
color: $white;
|
||||||
|
|
|
@ -69,12 +69,15 @@ class ArtistIndexBanner extends Component {
|
||||||
showTitle,
|
showTitle,
|
||||||
showMonitored,
|
showMonitored,
|
||||||
showQualityProfile,
|
showQualityProfile,
|
||||||
|
showSearchAction,
|
||||||
qualityProfile,
|
qualityProfile,
|
||||||
showRelativeDates,
|
showRelativeDates,
|
||||||
shortDateFormat,
|
shortDateFormat,
|
||||||
timeFormat,
|
timeFormat,
|
||||||
isRefreshingArtist,
|
isRefreshingArtist,
|
||||||
|
isSearchingArtist,
|
||||||
onRefreshArtistPress,
|
onRefreshArtistPress,
|
||||||
|
onSearchPress,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -111,6 +114,17 @@ class ArtistIndexBanner extends Component {
|
||||||
onPress={onRefreshArtistPress}
|
onPress={onRefreshArtistPress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{
|
||||||
|
showSearchAction &&
|
||||||
|
<SpinnerIconButton
|
||||||
|
className={styles.action}
|
||||||
|
name={icons.SEARCH}
|
||||||
|
title="Search for monitored albums"
|
||||||
|
isSpinning={isSearchingArtist}
|
||||||
|
onPress={onSearchPress}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
className={styles.action}
|
className={styles.action}
|
||||||
name={icons.EDIT}
|
name={icons.EDIT}
|
||||||
|
@ -236,11 +250,14 @@ ArtistIndexBanner.propTypes = {
|
||||||
showMonitored: PropTypes.bool.isRequired,
|
showMonitored: PropTypes.bool.isRequired,
|
||||||
showQualityProfile: PropTypes.bool.isRequired,
|
showQualityProfile: PropTypes.bool.isRequired,
|
||||||
qualityProfile: PropTypes.object.isRequired,
|
qualityProfile: PropTypes.object.isRequired,
|
||||||
|
showSearchAction: PropTypes.bool.isRequired,
|
||||||
showRelativeDates: PropTypes.bool.isRequired,
|
showRelativeDates: PropTypes.bool.isRequired,
|
||||||
shortDateFormat: PropTypes.string.isRequired,
|
shortDateFormat: PropTypes.string.isRequired,
|
||||||
timeFormat: PropTypes.string.isRequired,
|
timeFormat: PropTypes.string.isRequired,
|
||||||
isRefreshingArtist: PropTypes.bool.isRequired,
|
isRefreshingArtist: PropTypes.bool.isRequired,
|
||||||
onRefreshArtistPress: PropTypes.func.isRequired
|
isSearchingArtist: PropTypes.bool.isRequired,
|
||||||
|
onRefreshArtistPress: PropTypes.func.isRequired,
|
||||||
|
onSearchPress: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
ArtistIndexBanner.defaultProps = {
|
ArtistIndexBanner.defaultProps = {
|
||||||
|
|
|
@ -31,7 +31,8 @@ class ArtistIndexBannerOptionsModalContent extends Component {
|
||||||
size: props.size,
|
size: props.size,
|
||||||
showTitle: props.showTitle,
|
showTitle: props.showTitle,
|
||||||
showMonitored: props.showMonitored,
|
showMonitored: props.showMonitored,
|
||||||
showQualityProfile: props.showQualityProfile
|
showQualityProfile: props.showQualityProfile,
|
||||||
|
showSearchAction: props.showSearchAction
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +42,8 @@ class ArtistIndexBannerOptionsModalContent extends Component {
|
||||||
size,
|
size,
|
||||||
showTitle,
|
showTitle,
|
||||||
showMonitored,
|
showMonitored,
|
||||||
showQualityProfile
|
showQualityProfile,
|
||||||
|
showSearchAction
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const state = {};
|
const state = {};
|
||||||
|
@ -66,6 +68,10 @@ class ArtistIndexBannerOptionsModalContent extends Component {
|
||||||
state.showQualityProfile = showQualityProfile;
|
state.showQualityProfile = showQualityProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showSearchAction !== prevProps.showSearchAction) {
|
||||||
|
state.showSearchAction = showSearchAction;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_.isEmpty(state)) {
|
if (!_.isEmpty(state)) {
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +101,8 @@ class ArtistIndexBannerOptionsModalContent extends Component {
|
||||||
size,
|
size,
|
||||||
showTitle,
|
showTitle,
|
||||||
showMonitored,
|
showMonitored,
|
||||||
showQualityProfile
|
showQualityProfile,
|
||||||
|
showSearchAction
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -165,6 +172,18 @@ class ArtistIndexBannerOptionsModalContent extends Component {
|
||||||
onChange={this.onChangeBannerOption}
|
onChange={this.onChangeBannerOption}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>Show Search</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.CHECK}
|
||||||
|
name="showSearchAction"
|
||||||
|
value={showSearchAction}
|
||||||
|
helpText="Show search button on hover"
|
||||||
|
onChange={this.onChangeBannerOption}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
</Form>
|
</Form>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
|
@ -185,6 +204,7 @@ ArtistIndexBannerOptionsModalContent.propTypes = {
|
||||||
showTitle: PropTypes.bool.isRequired,
|
showTitle: PropTypes.bool.isRequired,
|
||||||
showQualityProfile: PropTypes.bool.isRequired,
|
showQualityProfile: PropTypes.bool.isRequired,
|
||||||
detailedProgressBar: PropTypes.bool.isRequired,
|
detailedProgressBar: PropTypes.bool.isRequired,
|
||||||
|
showSearchAction: PropTypes.bool.isRequired,
|
||||||
onChangeBannerOption: PropTypes.func.isRequired,
|
onChangeBannerOption: PropTypes.func.isRequired,
|
||||||
showMonitored: PropTypes.bool.isRequired,
|
showMonitored: PropTypes.bool.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
|
|
|
@ -84,6 +84,7 @@ class ArtistIndexOverview extends Component {
|
||||||
posterHeight,
|
posterHeight,
|
||||||
qualityProfile,
|
qualityProfile,
|
||||||
overviewOptions,
|
overviewOptions,
|
||||||
|
showSearchAction,
|
||||||
showRelativeDates,
|
showRelativeDates,
|
||||||
shortDateFormat,
|
shortDateFormat,
|
||||||
longDateFormat,
|
longDateFormat,
|
||||||
|
@ -91,7 +92,9 @@ class ArtistIndexOverview extends Component {
|
||||||
rowHeight,
|
rowHeight,
|
||||||
isSmallScreen,
|
isSmallScreen,
|
||||||
isRefreshingArtist,
|
isRefreshingArtist,
|
||||||
|
isSearchingArtist,
|
||||||
onRefreshArtistPress,
|
onRefreshArtistPress,
|
||||||
|
onSearchPress,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -175,6 +178,17 @@ class ArtistIndexOverview extends Component {
|
||||||
onPress={onRefreshArtistPress}
|
onPress={onRefreshArtistPress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{
|
||||||
|
showSearchAction &&
|
||||||
|
<SpinnerIconButton
|
||||||
|
className={styles.action}
|
||||||
|
name={icons.SEARCH}
|
||||||
|
title="Search for monitored albums"
|
||||||
|
isSpinning={isSearchingArtist}
|
||||||
|
onPress={onSearchPress}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
name={icons.EDIT}
|
name={icons.EDIT}
|
||||||
title="Edit Artist"
|
title="Edit Artist"
|
||||||
|
@ -246,12 +260,14 @@ ArtistIndexOverview.propTypes = {
|
||||||
rowHeight: PropTypes.number.isRequired,
|
rowHeight: PropTypes.number.isRequired,
|
||||||
qualityProfile: PropTypes.object.isRequired,
|
qualityProfile: PropTypes.object.isRequired,
|
||||||
overviewOptions: PropTypes.object.isRequired,
|
overviewOptions: PropTypes.object.isRequired,
|
||||||
|
showSearchAction: PropTypes.bool.isRequired,
|
||||||
showRelativeDates: PropTypes.bool.isRequired,
|
showRelativeDates: PropTypes.bool.isRequired,
|
||||||
shortDateFormat: PropTypes.string.isRequired,
|
shortDateFormat: PropTypes.string.isRequired,
|
||||||
longDateFormat: PropTypes.string.isRequired,
|
longDateFormat: PropTypes.string.isRequired,
|
||||||
timeFormat: PropTypes.string.isRequired,
|
timeFormat: PropTypes.string.isRequired,
|
||||||
isSmallScreen: PropTypes.bool.isRequired,
|
isSmallScreen: PropTypes.bool.isRequired,
|
||||||
isRefreshingArtist: PropTypes.bool.isRequired,
|
isRefreshingArtist: PropTypes.bool.isRequired,
|
||||||
|
isSearchingArtist: PropTypes.bool.isRequired,
|
||||||
onRefreshArtistPress: PropTypes.func.isRequired
|
onRefreshArtistPress: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,8 @@ class ArtistIndexOverviewOptionsModalContent extends Component {
|
||||||
showAdded: props.showAdded,
|
showAdded: props.showAdded,
|
||||||
showAlbumCount: props.showAlbumCount,
|
showAlbumCount: props.showAlbumCount,
|
||||||
showPath: props.showPath,
|
showPath: props.showPath,
|
||||||
showSizeOnDisk: props.showSizeOnDisk
|
showSizeOnDisk: props.showSizeOnDisk,
|
||||||
|
showSearchAction: props.showSearchAction
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +50,8 @@ class ArtistIndexOverviewOptionsModalContent extends Component {
|
||||||
showAdded,
|
showAdded,
|
||||||
showAlbumCount,
|
showAlbumCount,
|
||||||
showPath,
|
showPath,
|
||||||
showSizeOnDisk
|
showSizeOnDisk,
|
||||||
|
showSearchAction
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const state = {};
|
const state = {};
|
||||||
|
@ -90,6 +92,10 @@ class ArtistIndexOverviewOptionsModalContent extends Component {
|
||||||
state.showSizeOnDisk = showSizeOnDisk;
|
state.showSizeOnDisk = showSizeOnDisk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showSearchAction !== prevProps.showSearchAction) {
|
||||||
|
state.showSearchAction = showSearchAction;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_.isEmpty(state)) {
|
if (!_.isEmpty(state)) {
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
}
|
}
|
||||||
|
@ -123,7 +129,8 @@ class ArtistIndexOverviewOptionsModalContent extends Component {
|
||||||
showAdded,
|
showAdded,
|
||||||
showAlbumCount,
|
showAlbumCount,
|
||||||
showPath,
|
showPath,
|
||||||
showSizeOnDisk
|
showSizeOnDisk,
|
||||||
|
showSearchAction
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -235,6 +242,18 @@ class ArtistIndexOverviewOptionsModalContent extends Component {
|
||||||
onChange={this.onChangeOverviewOption}
|
onChange={this.onChangeOverviewOption}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>Show Search</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.CHECK}
|
||||||
|
name="showSearchAction"
|
||||||
|
value={showSearchAction}
|
||||||
|
helpText="Show search button"
|
||||||
|
onChange={this.onChangeOverviewOption}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
</Form>
|
</Form>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
|
@ -252,6 +271,7 @@ class ArtistIndexOverviewOptionsModalContent extends Component {
|
||||||
|
|
||||||
ArtistIndexOverviewOptionsModalContent.propTypes = {
|
ArtistIndexOverviewOptionsModalContent.propTypes = {
|
||||||
size: PropTypes.string.isRequired,
|
size: PropTypes.string.isRequired,
|
||||||
|
detailedProgressBar: PropTypes.bool.isRequired,
|
||||||
showMonitored: PropTypes.bool.isRequired,
|
showMonitored: PropTypes.bool.isRequired,
|
||||||
showQualityProfile: PropTypes.bool.isRequired,
|
showQualityProfile: PropTypes.bool.isRequired,
|
||||||
showLastAlbum: PropTypes.bool.isRequired,
|
showLastAlbum: PropTypes.bool.isRequired,
|
||||||
|
@ -259,7 +279,7 @@ ArtistIndexOverviewOptionsModalContent.propTypes = {
|
||||||
showAlbumCount: PropTypes.bool.isRequired,
|
showAlbumCount: PropTypes.bool.isRequired,
|
||||||
showPath: PropTypes.bool.isRequired,
|
showPath: PropTypes.bool.isRequired,
|
||||||
showSizeOnDisk: PropTypes.bool.isRequired,
|
showSizeOnDisk: PropTypes.bool.isRequired,
|
||||||
detailedProgressBar: PropTypes.bool.isRequired,
|
showSearchAction: PropTypes.bool.isRequired,
|
||||||
onChangeOverviewOption: PropTypes.func.isRequired,
|
onChangeOverviewOption: PropTypes.func.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,6 +61,7 @@ $hoverScale: 1.05;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
|
z-index: 3;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background-color: #216044;
|
background-color: #216044;
|
||||||
color: $white;
|
color: $white;
|
||||||
|
|
|
@ -70,11 +70,14 @@ class ArtistIndexPoster extends Component {
|
||||||
showMonitored,
|
showMonitored,
|
||||||
showQualityProfile,
|
showQualityProfile,
|
||||||
qualityProfile,
|
qualityProfile,
|
||||||
|
showSearchAction,
|
||||||
showRelativeDates,
|
showRelativeDates,
|
||||||
shortDateFormat,
|
shortDateFormat,
|
||||||
timeFormat,
|
timeFormat,
|
||||||
isRefreshingArtist,
|
isRefreshingArtist,
|
||||||
|
isSearchingArtist,
|
||||||
onRefreshArtistPress,
|
onRefreshArtistPress,
|
||||||
|
onSearchPress,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -111,6 +114,17 @@ class ArtistIndexPoster extends Component {
|
||||||
onPress={onRefreshArtistPress}
|
onPress={onRefreshArtistPress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{
|
||||||
|
showSearchAction &&
|
||||||
|
<SpinnerIconButton
|
||||||
|
className={styles.action}
|
||||||
|
name={icons.SEARCH}
|
||||||
|
title="Search for monitored albums"
|
||||||
|
isSpinning={isSearchingArtist}
|
||||||
|
onPress={onSearchPress}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
className={styles.action}
|
className={styles.action}
|
||||||
name={icons.EDIT}
|
name={icons.EDIT}
|
||||||
|
@ -235,11 +249,14 @@ ArtistIndexPoster.propTypes = {
|
||||||
showMonitored: PropTypes.bool.isRequired,
|
showMonitored: PropTypes.bool.isRequired,
|
||||||
showQualityProfile: PropTypes.bool.isRequired,
|
showQualityProfile: PropTypes.bool.isRequired,
|
||||||
qualityProfile: PropTypes.object.isRequired,
|
qualityProfile: PropTypes.object.isRequired,
|
||||||
|
showSearchAction: PropTypes.bool.isRequired,
|
||||||
showRelativeDates: PropTypes.bool.isRequired,
|
showRelativeDates: PropTypes.bool.isRequired,
|
||||||
shortDateFormat: PropTypes.string.isRequired,
|
shortDateFormat: PropTypes.string.isRequired,
|
||||||
timeFormat: PropTypes.string.isRequired,
|
timeFormat: PropTypes.string.isRequired,
|
||||||
isRefreshingArtist: PropTypes.bool.isRequired,
|
isRefreshingArtist: PropTypes.bool.isRequired,
|
||||||
onRefreshArtistPress: PropTypes.func.isRequired
|
isSearchingArtist: PropTypes.bool.isRequired,
|
||||||
|
onRefreshArtistPress: PropTypes.func.isRequired,
|
||||||
|
onSearchPress: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
ArtistIndexPoster.defaultProps = {
|
ArtistIndexPoster.defaultProps = {
|
||||||
|
|
|
@ -31,7 +31,8 @@ class ArtistIndexPosterOptionsModalContent extends Component {
|
||||||
size: props.size,
|
size: props.size,
|
||||||
showTitle: props.showTitle,
|
showTitle: props.showTitle,
|
||||||
showMonitored: props.showMonitored,
|
showMonitored: props.showMonitored,
|
||||||
showQualityProfile: props.showQualityProfile
|
showQualityProfile: props.showQualityProfile,
|
||||||
|
showSearchAction: props.showSearchAction
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +42,8 @@ class ArtistIndexPosterOptionsModalContent extends Component {
|
||||||
size,
|
size,
|
||||||
showTitle,
|
showTitle,
|
||||||
showMonitored,
|
showMonitored,
|
||||||
showQualityProfile
|
showQualityProfile,
|
||||||
|
showSearchAction
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const state = {};
|
const state = {};
|
||||||
|
@ -66,6 +68,10 @@ class ArtistIndexPosterOptionsModalContent extends Component {
|
||||||
state.showQualityProfile = showQualityProfile;
|
state.showQualityProfile = showQualityProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showSearchAction !== prevProps.showSearchAction) {
|
||||||
|
state.showSearchAction = showSearchAction;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_.isEmpty(state)) {
|
if (!_.isEmpty(state)) {
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +101,8 @@ class ArtistIndexPosterOptionsModalContent extends Component {
|
||||||
size,
|
size,
|
||||||
showTitle,
|
showTitle,
|
||||||
showMonitored,
|
showMonitored,
|
||||||
showQualityProfile
|
showQualityProfile,
|
||||||
|
showSearchAction
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -165,6 +172,18 @@ class ArtistIndexPosterOptionsModalContent extends Component {
|
||||||
onChange={this.onChangePosterOption}
|
onChange={this.onChangePosterOption}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>Show Search</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.CHECK}
|
||||||
|
name="showSearchAction"
|
||||||
|
value={showSearchAction}
|
||||||
|
helpText="Show search button on hover"
|
||||||
|
onChange={this.onChangePosterOption}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
</Form>
|
</Form>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
|
@ -186,6 +205,7 @@ ArtistIndexPosterOptionsModalContent.propTypes = {
|
||||||
showMonitored: PropTypes.bool.isRequired,
|
showMonitored: PropTypes.bool.isRequired,
|
||||||
showQualityProfile: PropTypes.bool.isRequired,
|
showQualityProfile: PropTypes.bool.isRequired,
|
||||||
detailedProgressBar: PropTypes.bool.isRequired,
|
detailedProgressBar: PropTypes.bool.isRequired,
|
||||||
|
showSearchAction: PropTypes.bool.isRequired,
|
||||||
onChangePosterOption: PropTypes.func.isRequired,
|
onChangePosterOption: PropTypes.func.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
|
@ -80,5 +80,5 @@
|
||||||
.actions {
|
.actions {
|
||||||
composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css';
|
composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css';
|
||||||
|
|
||||||
flex: 0 0 70px;
|
flex: 0 1 90px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import IconButton from 'Components/Link/IconButton';
|
||||||
import VirtualTableHeader from 'Components/Table/VirtualTableHeader';
|
import VirtualTableHeader from 'Components/Table/VirtualTableHeader';
|
||||||
import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell';
|
import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell';
|
||||||
import TableOptionsModal from 'Components/Table/TableOptions/TableOptionsModal';
|
import TableOptionsModal from 'Components/Table/TableOptions/TableOptionsModal';
|
||||||
|
import ArtistIndexTableOptionsConnector from './ArtistIndexTableOptionsConnector';
|
||||||
import styles from './ArtistIndexHeader.css';
|
import styles from './ArtistIndexHeader.css';
|
||||||
|
|
||||||
class ArtistIndexHeader extends Component {
|
class ArtistIndexHeader extends Component {
|
||||||
|
@ -36,6 +37,7 @@ class ArtistIndexHeader extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
showSearchAction,
|
||||||
columns,
|
columns,
|
||||||
onTableOptionChange,
|
onTableOptionChange,
|
||||||
...otherProps
|
...otherProps
|
||||||
|
@ -90,6 +92,7 @@ class ArtistIndexHeader extends Component {
|
||||||
<TableOptionsModal
|
<TableOptionsModal
|
||||||
isOpen={this.state.isTableOptionsModalOpen}
|
isOpen={this.state.isTableOptionsModalOpen}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
|
optionsComponent={ArtistIndexTableOptionsConnector}
|
||||||
onTableOptionChange={onTableOptionChange}
|
onTableOptionChange={onTableOptionChange}
|
||||||
onModalClose={this.onTableOptionsModalClose}
|
onModalClose={this.onTableOptionsModalClose}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
.actions {
|
.actions {
|
||||||
composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css';
|
composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css';
|
||||||
|
|
||||||
flex: 0 0 70px;
|
flex: 0 1 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkInput {
|
.checkInput {
|
||||||
|
|
|
@ -80,9 +80,12 @@ class ArtistIndexRow extends Component {
|
||||||
ratings,
|
ratings,
|
||||||
path,
|
path,
|
||||||
tags,
|
tags,
|
||||||
|
showSearchAction,
|
||||||
columns,
|
columns,
|
||||||
isRefreshingArtist,
|
isRefreshingArtist,
|
||||||
onRefreshArtistPress
|
isSearchingArtist,
|
||||||
|
onRefreshArtistPress,
|
||||||
|
onSearchPress
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -360,6 +363,17 @@ class ArtistIndexRow extends Component {
|
||||||
onPress={onRefreshArtistPress}
|
onPress={onRefreshArtistPress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{
|
||||||
|
showSearchAction &&
|
||||||
|
<SpinnerIconButton
|
||||||
|
className={styles.action}
|
||||||
|
name={icons.SEARCH}
|
||||||
|
title="Search for monitored albums"
|
||||||
|
isSpinning={isSearchingArtist}
|
||||||
|
onPress={onSearchPress}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
name={icons.EDIT}
|
name={icons.EDIT}
|
||||||
title="Edit Artist"
|
title="Edit Artist"
|
||||||
|
@ -410,9 +424,12 @@ ArtistIndexRow.propTypes = {
|
||||||
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
|
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
ratings: PropTypes.object.isRequired,
|
ratings: PropTypes.object.isRequired,
|
||||||
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
|
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||||
|
showSearchAction: PropTypes.bool.isRequired,
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
isRefreshingArtist: PropTypes.bool.isRequired,
|
isRefreshingArtist: PropTypes.bool.isRequired,
|
||||||
onRefreshArtistPress: PropTypes.func.isRequired
|
isSearchingArtist: PropTypes.bool.isRequired,
|
||||||
|
onRefreshArtistPress: PropTypes.func.isRequired,
|
||||||
|
onSearchPress: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
ArtistIndexRow.defaultProps = {
|
ArtistIndexRow.defaultProps = {
|
||||||
|
|
76
frontend/src/Artist/Index/Table/ArtistIndexTableOptions.js
Normal file
76
frontend/src/Artist/Index/Table/ArtistIndexTableOptions.js
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { inputTypes } from 'Helpers/Props';
|
||||||
|
import FormGroup from 'Components/Form/FormGroup';
|
||||||
|
import FormLabel from 'Components/Form/FormLabel';
|
||||||
|
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||||
|
|
||||||
|
class ArtistIndexTableOptions extends Component {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Lifecycle
|
||||||
|
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props, context);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
showSearchAction: props.showSearchAction
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
const { showSearchAction } = this.props;
|
||||||
|
|
||||||
|
if (showSearchAction !== prevProps.showSearchAction) {
|
||||||
|
this.setState({
|
||||||
|
showSearchAction
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Listeners
|
||||||
|
|
||||||
|
onTableOptionChange = ({ name, value }) => {
|
||||||
|
this.setState({
|
||||||
|
[name]: value
|
||||||
|
}, () => {
|
||||||
|
this.props.onTableOptionChange({
|
||||||
|
tableOptions: {
|
||||||
|
...this.state,
|
||||||
|
[name]: value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
showSearchAction
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>Show Search</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.CHECK}
|
||||||
|
name="showSearchAction"
|
||||||
|
value={showSearchAction}
|
||||||
|
helpText="Show search button"
|
||||||
|
onChange={this.onTableOptionChange}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArtistIndexTableOptions.propTypes = {
|
||||||
|
showSearchAction: PropTypes.bool.isRequired,
|
||||||
|
onTableOptionChange: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ArtistIndexTableOptions;
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
import ArtistIndexTableOptions from './ArtistIndexTableOptions';
|
||||||
|
|
||||||
|
function createMapStateToProps() {
|
||||||
|
return createSelector(
|
||||||
|
(state) => state.artistIndex.tableOptions,
|
||||||
|
(tableOptions) => {
|
||||||
|
return tableOptions;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(createMapStateToProps)(ArtistIndexTableOptions);
|
|
@ -109,6 +109,8 @@ class TableOptionsModal extends Component {
|
||||||
isOpen,
|
isOpen,
|
||||||
columns,
|
columns,
|
||||||
canModifyColumns,
|
canModifyColumns,
|
||||||
|
optionsComponent: OptionsComponent,
|
||||||
|
onTableOptionChange,
|
||||||
onModalClose
|
onModalClose
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -152,6 +154,13 @@ class TableOptionsModal extends Component {
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
!!OptionsComponent &&
|
||||||
|
<OptionsComponent
|
||||||
|
onTableOptionChange={onTableOptionChange}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
canModifyColumns &&
|
canModifyColumns &&
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
|
@ -231,6 +240,7 @@ TableOptionsModal.propTypes = {
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
pageSize: PropTypes.number,
|
pageSize: PropTypes.number,
|
||||||
canModifyColumns: PropTypes.bool.isRequired,
|
canModifyColumns: PropTypes.bool.isRequired,
|
||||||
|
optionsComponent: PropTypes.func.isRequired,
|
||||||
onTableOptionChange: PropTypes.func.isRequired,
|
onTableOptionChange: PropTypes.func.isRequired,
|
||||||
onModalClose: PropTypes.func.isRequired
|
onModalClose: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,8 @@ import updateSectionState from 'Utilities/State/updateSectionState';
|
||||||
|
|
||||||
const whitelistedProperties = [
|
const whitelistedProperties = [
|
||||||
'pageSize',
|
'pageSize',
|
||||||
'columns'
|
'columns',
|
||||||
|
'tableOptions'
|
||||||
];
|
];
|
||||||
|
|
||||||
function createSetTableOptionReducer(section) {
|
function createSetTableOptionReducer(section) {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import moment from 'moment';
|
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import sortByName from 'Utilities/Array/sortByName';
|
import sortByName from 'Utilities/Array/sortByName';
|
||||||
import { filterBuilderTypes, filterBuilderValueTypes, sortDirections } from 'Helpers/Props';
|
import { filterBuilderTypes, filterBuilderValueTypes, sortDirections } from 'Helpers/Props';
|
||||||
|
@ -28,7 +27,8 @@ export const defaultState = {
|
||||||
size: 'large',
|
size: 'large',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
showMonitored: true,
|
showMonitored: true,
|
||||||
showQualityProfile: true
|
showQualityProfile: true,
|
||||||
|
showSearchAction: false
|
||||||
},
|
},
|
||||||
|
|
||||||
bannerOptions: {
|
bannerOptions: {
|
||||||
|
@ -36,7 +36,8 @@ export const defaultState = {
|
||||||
size: 'large',
|
size: 'large',
|
||||||
showTitle: false,
|
showTitle: false,
|
||||||
showMonitored: true,
|
showMonitored: true,
|
||||||
showQualityProfile: true
|
showQualityProfile: true,
|
||||||
|
showSearchAction: false
|
||||||
},
|
},
|
||||||
|
|
||||||
overviewOptions: {
|
overviewOptions: {
|
||||||
|
@ -48,7 +49,12 @@ export const defaultState = {
|
||||||
showAdded: false,
|
showAdded: false,
|
||||||
showAlbumCount: true,
|
showAlbumCount: true,
|
||||||
showPath: false,
|
showPath: false,
|
||||||
showSizeOnDisk: false
|
showSizeOnDisk: false,
|
||||||
|
showSearchAction: false
|
||||||
|
},
|
||||||
|
|
||||||
|
tableOptions: {
|
||||||
|
showSearchAction: false
|
||||||
},
|
},
|
||||||
|
|
||||||
columns: [
|
columns: [
|
||||||
|
@ -337,7 +343,8 @@ export const persistState = [
|
||||||
'artistIndex.columns',
|
'artistIndex.columns',
|
||||||
'artistIndex.posterOptions',
|
'artistIndex.posterOptions',
|
||||||
'artistIndex.bannerOptions',
|
'artistIndex.bannerOptions',
|
||||||
'artistIndex.overviewOptions'
|
'artistIndex.overviewOptions',
|
||||||
|
'artistIndex.tableOptions'
|
||||||
];
|
];
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue