mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-17 21:25:39 -04:00
Renames in Frontend
This commit is contained in:
@@ -6,7 +6,7 @@ const protocols = [
|
||||
{ id: 'ended', name: 'Ended' }
|
||||
];
|
||||
|
||||
function ArtistStatusFilterBuilderRowValue(props) {
|
||||
function AuthorStatusFilterBuilderRowValue(props) {
|
||||
return (
|
||||
<FilterBuilderRowValue
|
||||
tagList={protocols}
|
||||
@@ -15,4 +15,4 @@ function ArtistStatusFilterBuilderRowValue(props) {
|
||||
);
|
||||
}
|
||||
|
||||
export default ArtistStatusFilterBuilderRowValue;
|
||||
export default AuthorStatusFilterBuilderRowValue;
|
||||
@@ -11,7 +11,7 @@ import MetadataProfileFilterBuilderRowValueConnector from './MetadataProfileFilt
|
||||
import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue';
|
||||
import QualityFilterBuilderRowValueConnector from './QualityFilterBuilderRowValueConnector';
|
||||
import QualityProfileFilterBuilderRowValueConnector from './QualityProfileFilterBuilderRowValueConnector';
|
||||
import ArtistStatusFilterBuilderRowValue from './ArtistStatusFilterBuilderRowValue';
|
||||
import AuthorStatusFilterBuilderRowValue from './AuthorStatusFilterBuilderRowValue';
|
||||
import TagFilterBuilderRowValueConnector from './TagFilterBuilderRowValueConnector';
|
||||
import styles from './FilterBuilderRow.css';
|
||||
|
||||
@@ -72,8 +72,8 @@ function getRowValueConnector(selectedFilterBuilderProp) {
|
||||
case filterBuilderValueTypes.QUALITY_PROFILE:
|
||||
return QualityProfileFilterBuilderRowValueConnector;
|
||||
|
||||
case filterBuilderValueTypes.ARTIST_STATUS:
|
||||
return ArtistStatusFilterBuilderRowValue;
|
||||
case filterBuilderValueTypes.AUTHOR_STATUS:
|
||||
return AuthorStatusFilterBuilderRowValue;
|
||||
|
||||
case filterBuilderValueTypes.TAG:
|
||||
return TagFilterBuilderRowValueConnector;
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import titleCase from 'Utilities/String/titleCase';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state, { albumReleases }) => albumReleases,
|
||||
(albumReleases) => {
|
||||
const values = _.map(albumReleases.value, (albumRelease) => {
|
||||
|
||||
return {
|
||||
key: albumRelease.foreignReleaseId,
|
||||
value: `${albumRelease.title}` +
|
||||
`${albumRelease.disambiguation ? ' (' : ''}${titleCase(albumRelease.disambiguation)}${albumRelease.disambiguation ? ')' : ''}` +
|
||||
`, ${albumRelease.mediumCount} med, ${albumRelease.trackCount} tracks` +
|
||||
`${albumRelease.country.length > 0 ? ', ' : ''}${albumRelease.country}` +
|
||||
`${albumRelease.format ? ', [' : ''}${albumRelease.format}${albumRelease.format ? ']' : ''}`
|
||||
};
|
||||
});
|
||||
|
||||
const sortedValues = _.orderBy(values, ['value']);
|
||||
|
||||
const value = _.find(albumReleases.value, { monitored: true }).foreignReleaseId;
|
||||
|
||||
return {
|
||||
values: sortedValues,
|
||||
value
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
class AlbumReleaseSelectInputConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onChange = ({ name, value }) => {
|
||||
const {
|
||||
albumReleases
|
||||
} = this.props;
|
||||
|
||||
const updatedReleases = _.map(albumReleases.value, (e) => ({ ...e, monitored: false }));
|
||||
_.find(updatedReleases, { foreignReleaseId: value }).monitored = true;
|
||||
|
||||
this.props.onChange({ name, value: updatedReleases });
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<SelectInput
|
||||
{...this.props}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AlbumReleaseSelectInputConnector.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
albumReleases: PropTypes.object
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps)(AlbumReleaseSelectInputConnector);
|
||||
@@ -0,0 +1,70 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import titleCase from 'Utilities/String/titleCase';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state, { bookReleases }) => bookReleases,
|
||||
(bookReleases) => {
|
||||
const values = _.map(bookReleases.value, (bookRelease) => {
|
||||
|
||||
return {
|
||||
key: bookRelease.foreignReleaseId,
|
||||
value: `${bookRelease.title}` +
|
||||
`${bookRelease.disambiguation ? ' (' : ''}${titleCase(bookRelease.disambiguation)}${bookRelease.disambiguation ? ')' : ''}` +
|
||||
`, ${bookRelease.mediumCount} med, ${bookRelease.bookCount} books` +
|
||||
`${bookRelease.country.length > 0 ? ', ' : ''}${bookRelease.country}` +
|
||||
`${bookRelease.format ? ', [' : ''}${bookRelease.format}${bookRelease.format ? ']' : ''}`
|
||||
};
|
||||
});
|
||||
|
||||
const sortedValues = _.orderBy(values, ['value']);
|
||||
|
||||
const value = _.find(bookReleases.value, { monitored: true }).foreignReleaseId;
|
||||
|
||||
return {
|
||||
values: sortedValues,
|
||||
value
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
class BookReleaseSelectInputConnector extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onChange = ({ name, value }) => {
|
||||
const {
|
||||
bookReleases
|
||||
} = this.props;
|
||||
|
||||
const updatedReleases = _.map(bookReleases.value, (e) => ({ ...e, monitored: false }));
|
||||
_.find(updatedReleases, { foreignReleaseId: value }).monitored = true;
|
||||
|
||||
this.props.onChange({ name, value: updatedReleases });
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<SelectInput
|
||||
{...this.props}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
BookReleaseSelectInputConnector.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
bookReleases: PropTypes.object
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps)(BookReleaseSelectInputConnector);
|
||||
@@ -8,14 +8,14 @@ import CheckInput from './CheckInput';
|
||||
import DeviceInputConnector from './DeviceInputConnector';
|
||||
import PlaylistInputConnector from './PlaylistInputConnector';
|
||||
import KeyValueListInput from './KeyValueListInput';
|
||||
import MonitorAlbumsSelectInput from './MonitorAlbumsSelectInput';
|
||||
import MonitorBooksSelectInput from './MonitorBooksSelectInput';
|
||||
import NumberInput from './NumberInput';
|
||||
import OAuthInputConnector from './OAuthInputConnector';
|
||||
import PasswordInput from './PasswordInput';
|
||||
import PathInputConnector from './PathInputConnector';
|
||||
import QualityProfileSelectInputConnector from './QualityProfileSelectInputConnector';
|
||||
import MetadataProfileSelectInputConnector from './MetadataProfileSelectInputConnector';
|
||||
import AlbumReleaseSelectInputConnector from './AlbumReleaseSelectInputConnector';
|
||||
import BookReleaseSelectInputConnector from './BookReleaseSelectInputConnector';
|
||||
import RootFolderSelectInputConnector from './RootFolderSelectInputConnector';
|
||||
import SeriesTypeSelectInput from './SeriesTypeSelectInput';
|
||||
import EnhancedSelectInput from './EnhancedSelectInput';
|
||||
@@ -45,8 +45,8 @@ function getComponent(type) {
|
||||
case inputTypes.KEY_VALUE_LIST:
|
||||
return KeyValueListInput;
|
||||
|
||||
case inputTypes.MONITOR_ALBUMS_SELECT:
|
||||
return MonitorAlbumsSelectInput;
|
||||
case inputTypes.MONITOR_BOOKS_SELECT:
|
||||
return MonitorBooksSelectInput;
|
||||
|
||||
case inputTypes.NUMBER:
|
||||
return NumberInput;
|
||||
@@ -66,8 +66,8 @@ function getComponent(type) {
|
||||
case inputTypes.METADATA_PROFILE_SELECT:
|
||||
return MetadataProfileSelectInputConnector;
|
||||
|
||||
case inputTypes.ALBUM_RELEASE_SELECT:
|
||||
return AlbumReleaseSelectInputConnector;
|
||||
case inputTypes.BOOK_RELEASE_SELECT:
|
||||
return BookReleaseSelectInputConnector;
|
||||
|
||||
case inputTypes.ROOT_FOLDER_SELECT:
|
||||
return RootFolderSelectInputConnector;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import monitorOptions from 'Utilities/Artist/monitorOptions';
|
||||
import monitorOptions from 'Utilities/Author/monitorOptions';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
function MonitorAlbumsSelectInput(props) {
|
||||
function MonitorBooksSelectInput(props) {
|
||||
const {
|
||||
includeNoChange,
|
||||
includeMixed,
|
||||
@@ -36,15 +36,15 @@ function MonitorAlbumsSelectInput(props) {
|
||||
);
|
||||
}
|
||||
|
||||
MonitorAlbumsSelectInput.propTypes = {
|
||||
MonitorBooksSelectInput.propTypes = {
|
||||
includeNoChange: PropTypes.bool.isRequired,
|
||||
includeMixed: PropTypes.bool.isRequired,
|
||||
onChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
MonitorAlbumsSelectInput.defaultProps = {
|
||||
MonitorBooksSelectInput.defaultProps = {
|
||||
includeNoChange: false,
|
||||
includeMixed: false
|
||||
};
|
||||
|
||||
export default MonitorAlbumsSelectInput;
|
||||
export default MonitorBooksSelectInput;
|
||||
@@ -2,14 +2,14 @@ import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
const artistTypeOptions = [
|
||||
const authorTypeOptions = [
|
||||
{ key: 'standard', value: 'Standard' },
|
||||
{ key: 'daily', value: 'Daily' },
|
||||
{ key: 'anime', value: 'Anime' }
|
||||
];
|
||||
|
||||
function SeriesTypeSelectInput(props) {
|
||||
const values = [...artistTypeOptions];
|
||||
const values = [...authorTypeOptions];
|
||||
|
||||
const {
|
||||
includeNoChange,
|
||||
|
||||
@@ -12,7 +12,7 @@ const messages = [
|
||||
'Hum something loud while others stare',
|
||||
'Loading humorous message... Please Wait',
|
||||
'I could\'ve been faster in Python',
|
||||
'Don\'t forget to rewind your tracks',
|
||||
'Don\'t forget to return your library books',
|
||||
'Congratulations! you are the 1000th visitor.',
|
||||
'HELP! I\'m being held hostage and forced to write these stupid lines!',
|
||||
'RE-calibrating the internet...',
|
||||
|
||||
@@ -7,7 +7,7 @@ import styles from './MonitorToggleButton.css';
|
||||
|
||||
function getTooltip(monitored, isDisabled) {
|
||||
if (isDisabled) {
|
||||
return 'Cannot toogle monitored state when artist is unmonitored';
|
||||
return 'Cannot toogle monitored state when author is unmonitored';
|
||||
}
|
||||
|
||||
if (monitored) {
|
||||
|
||||
@@ -7,7 +7,7 @@ function ErrorPage(props) {
|
||||
const {
|
||||
version,
|
||||
isLocalStorageSupported,
|
||||
artistError,
|
||||
authorError,
|
||||
customFiltersError,
|
||||
tagsError,
|
||||
qualityProfilesError,
|
||||
@@ -20,8 +20,8 @@ function ErrorPage(props) {
|
||||
|
||||
if (!isLocalStorageSupported) {
|
||||
errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.';
|
||||
} else if (artistError) {
|
||||
errorMessage = getErrorMessage(artistError, 'Failed to load artist from API');
|
||||
} else if (authorError) {
|
||||
errorMessage = getErrorMessage(authorError, 'Failed to load author from API');
|
||||
} else if (customFiltersError) {
|
||||
errorMessage = getErrorMessage(customFiltersError, 'Failed to load custom filters from API');
|
||||
} else if (tagsError) {
|
||||
@@ -52,7 +52,7 @@ function ErrorPage(props) {
|
||||
ErrorPage.propTypes = {
|
||||
version: PropTypes.string.isRequired,
|
||||
isLocalStorageSupported: PropTypes.bool.isRequired,
|
||||
artistError: PropTypes.object,
|
||||
authorError: PropTypes.object,
|
||||
customFiltersError: PropTypes.object,
|
||||
tagsError: PropTypes.object,
|
||||
qualityProfilesError: PropTypes.object,
|
||||
|
||||
@@ -34,14 +34,14 @@
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.artistContainer {
|
||||
.authorContainer {
|
||||
@add-mixin scrollbar;
|
||||
@add-mixin scrollbarTrack;
|
||||
@add-mixin scrollbarThumb;
|
||||
}
|
||||
|
||||
.containerOpen {
|
||||
.artistContainer {
|
||||
.authorContainer {
|
||||
position: absolute;
|
||||
top: 42px;
|
||||
z-index: 1;
|
||||
@@ -78,7 +78,7 @@
|
||||
color: $disabledColor;
|
||||
}
|
||||
|
||||
.addNewArtistSuggestion {
|
||||
.addNewAuthorSuggestion {
|
||||
padding: 0 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -5,16 +5,16 @@ import Autosuggest from 'react-autosuggest';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import Icon from 'Components/Icon';
|
||||
import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts';
|
||||
import ArtistSearchResult from './ArtistSearchResult';
|
||||
import AuthorSearchResult from './AuthorSearchResult';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import FuseWorker from './fuse.worker';
|
||||
import styles from './ArtistSearchInput.css';
|
||||
import styles from './AuthorSearchInput.css';
|
||||
|
||||
const LOADING_TYPE = 'suggestionsLoading';
|
||||
const ADD_NEW_TYPE = 'addNew';
|
||||
const workerInstance = new FuseWorker();
|
||||
|
||||
class ArtistSearchInput extends Component {
|
||||
class AuthorSearchInput extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
@@ -31,7 +31,7 @@ class ArtistSearchInput extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.bindShortcut(shortcuts.ARTIST_SEARCH_INPUT.key, this.focusInput);
|
||||
this.props.bindShortcut(shortcuts.AUTHOR_SEARCH_INPUT.key, this.focusInput);
|
||||
workerInstance.addEventListener('message', this.onSuggestionsReceived, false);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ class ArtistSearchInput extends Component {
|
||||
renderSuggestion(item, { query }) {
|
||||
if (item.type === ADD_NEW_TYPE) {
|
||||
return (
|
||||
<div className={styles.addNewArtistSuggestion}>
|
||||
<div className={styles.addNewAuthorSuggestion}>
|
||||
Search for {query}
|
||||
</div>
|
||||
);
|
||||
@@ -79,16 +79,16 @@ class ArtistSearchInput extends Component {
|
||||
}
|
||||
|
||||
return (
|
||||
<ArtistSearchResult
|
||||
<AuthorSearchResult
|
||||
{...item.item}
|
||||
match={item.matches[0]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
goToArtist(item) {
|
||||
goToAuthor(item) {
|
||||
this.setState({ value: '' });
|
||||
this.props.onGoToArtist(item.item.titleSlug);
|
||||
this.props.onGoToAuthor(item.item.titleSlug);
|
||||
}
|
||||
|
||||
reset() {
|
||||
@@ -125,20 +125,20 @@ class ArtistSearchInput extends Component {
|
||||
} = this._autosuggest.state;
|
||||
|
||||
if (!suggestions.length || suggestions[0].type === LOADING_TYPE || highlightedSectionIndex) {
|
||||
this.props.onGoToAddNewArtist(value);
|
||||
this.props.onGoToAddNewAuthor(value);
|
||||
this._autosuggest.input.blur();
|
||||
this.reset();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If an suggestion is not selected go to the first artist,
|
||||
// otherwise go to the selected artist.
|
||||
// If an suggestion is not selected go to the first author,
|
||||
// otherwise go to the selected author.
|
||||
|
||||
if (highlightedSuggestionIndex == null) {
|
||||
this.goToArtist(suggestions[0]);
|
||||
this.goToAuthor(suggestions[0]);
|
||||
} else {
|
||||
this.goToArtist(suggestions[highlightedSuggestionIndex]);
|
||||
this.goToAuthor(suggestions[highlightedSuggestionIndex]);
|
||||
}
|
||||
|
||||
this._autosuggest.input.blur();
|
||||
@@ -164,7 +164,7 @@ class ArtistSearchInput extends Component {
|
||||
requestSuggestions = _.debounce((value) => {
|
||||
const payload = {
|
||||
value,
|
||||
artists: this.props.artists
|
||||
authors: this.props.authors
|
||||
};
|
||||
|
||||
workerInstance.postMessage(payload);
|
||||
@@ -184,9 +184,9 @@ class ArtistSearchInput extends Component {
|
||||
|
||||
onSuggestionSelected = (event, { suggestion }) => {
|
||||
if (suggestion.type === ADD_NEW_TYPE) {
|
||||
this.props.onGoToAddNewArtist(this.state.value);
|
||||
this.props.onGoToAddNewAuthor(this.state.value);
|
||||
} else {
|
||||
this.goToArtist(suggestion);
|
||||
this.goToAuthor(suggestion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ class ArtistSearchInput extends Component {
|
||||
|
||||
if (suggestions.length) {
|
||||
suggestionGroups.push({
|
||||
title: 'Existing Artist',
|
||||
title: 'Existing Author',
|
||||
suggestions
|
||||
});
|
||||
}
|
||||
@@ -221,7 +221,7 @@ class ArtistSearchInput extends Component {
|
||||
const inputProps = {
|
||||
ref: this.setInputRef,
|
||||
className: styles.input,
|
||||
name: 'artistSearch',
|
||||
name: 'authorSearch',
|
||||
value,
|
||||
placeholder: 'Search',
|
||||
autoComplete: 'off',
|
||||
@@ -235,7 +235,7 @@ class ArtistSearchInput extends Component {
|
||||
const theme = {
|
||||
container: styles.container,
|
||||
containerOpen: styles.containerOpen,
|
||||
suggestionsContainer: styles.artistContainer,
|
||||
suggestionsContainer: styles.authorContainer,
|
||||
suggestionsList: styles.list,
|
||||
suggestion: styles.listItem,
|
||||
suggestionHighlighted: styles.highlighted
|
||||
@@ -266,11 +266,11 @@ class ArtistSearchInput extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
ArtistSearchInput.propTypes = {
|
||||
artists: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onGoToArtist: PropTypes.func.isRequired,
|
||||
onGoToAddNewArtist: PropTypes.func.isRequired,
|
||||
AuthorSearchInput.propTypes = {
|
||||
authors: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onGoToAuthor: PropTypes.func.isRequired,
|
||||
onGoToAddNewAuthor: PropTypes.func.isRequired,
|
||||
bindShortcut: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default keyboardShortcuts(ArtistSearchInput);
|
||||
export default keyboardShortcuts(AuthorSearchInput);
|
||||
@@ -1,27 +1,27 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { push } from 'connected-react-router';
|
||||
import { createSelector } from 'reselect';
|
||||
import createAllArtistSelector from 'Store/Selectors/createAllArtistSelector';
|
||||
import createAllAuthorSelector from 'Store/Selectors/createAllAuthorsSelector';
|
||||
import createDeepEqualSelector from 'Store/Selectors/createDeepEqualSelector';
|
||||
import createTagsSelector from 'Store/Selectors/createTagsSelector';
|
||||
import ArtistSearchInput from './ArtistSearchInput';
|
||||
import AuthorSearchInput from './AuthorSearchInput';
|
||||
|
||||
function createCleanArtistSelector() {
|
||||
function createCleanAuthorSelector() {
|
||||
return createSelector(
|
||||
createAllArtistSelector(),
|
||||
createAllAuthorSelector(),
|
||||
createTagsSelector(),
|
||||
(allArtists, allTags) => {
|
||||
return allArtists.map((artist) => {
|
||||
(allAuthors, allTags) => {
|
||||
return allAuthors.map((author) => {
|
||||
const {
|
||||
artistName,
|
||||
authorName,
|
||||
sortName,
|
||||
images,
|
||||
titleSlug,
|
||||
tags = []
|
||||
} = artist;
|
||||
} = author;
|
||||
|
||||
return {
|
||||
artistName,
|
||||
authorName,
|
||||
sortName,
|
||||
titleSlug,
|
||||
images,
|
||||
@@ -42,10 +42,10 @@ function createCleanArtistSelector() {
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createDeepEqualSelector(
|
||||
createCleanArtistSelector(),
|
||||
(artists) => {
|
||||
createCleanAuthorSelector(),
|
||||
(authors) => {
|
||||
return {
|
||||
artists
|
||||
authors
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -53,14 +53,14 @@ function createMapStateToProps() {
|
||||
|
||||
function createMapDispatchToProps(dispatch, props) {
|
||||
return {
|
||||
onGoToArtist(titleSlug) {
|
||||
onGoToAuthor(titleSlug) {
|
||||
dispatch(push(`${window.Readarr.urlBase}/author/${titleSlug}`));
|
||||
},
|
||||
|
||||
onGoToAddNewArtist(query) {
|
||||
onGoToAddNewAuthor(query) {
|
||||
dispatch(push(`${window.Readarr.urlBase}/add/search?term=${encodeURIComponent(query)}`));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps, createMapDispatchToProps)(ArtistSearchInput);
|
||||
export default connect(createMapStateToProps, createMapDispatchToProps)(AuthorSearchInput);
|
||||
@@ -2,13 +2,13 @@ import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import Label from 'Components/Label';
|
||||
import ArtistPoster from 'Artist/ArtistPoster';
|
||||
import styles from './ArtistSearchResult.css';
|
||||
import AuthorPoster from 'Author/AuthorPoster';
|
||||
import styles from './AuthorSearchResult.css';
|
||||
|
||||
function ArtistSearchResult(props) {
|
||||
function AuthorSearchResult(props) {
|
||||
const {
|
||||
match,
|
||||
artistName,
|
||||
authorName,
|
||||
images,
|
||||
tags
|
||||
} = props;
|
||||
@@ -21,7 +21,7 @@ function ArtistSearchResult(props) {
|
||||
|
||||
return (
|
||||
<div className={styles.result}>
|
||||
<ArtistPoster
|
||||
<AuthorPoster
|
||||
className={styles.poster}
|
||||
images={images}
|
||||
size={250}
|
||||
@@ -31,7 +31,7 @@ function ArtistSearchResult(props) {
|
||||
|
||||
<div className={styles.titles}>
|
||||
<div className={styles.title}>
|
||||
{artistName}
|
||||
{authorName}
|
||||
</div>
|
||||
|
||||
{
|
||||
@@ -51,11 +51,11 @@ function ArtistSearchResult(props) {
|
||||
);
|
||||
}
|
||||
|
||||
ArtistSearchResult.propTypes = {
|
||||
artistName: PropTypes.string.isRequired,
|
||||
AuthorSearchResult.propTypes = {
|
||||
authorName: PropTypes.string.isRequired,
|
||||
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
tags: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
match: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
export default ArtistSearchResult;
|
||||
export default AuthorSearchResult;
|
||||
@@ -4,7 +4,7 @@ import { icons } from 'Helpers/Props';
|
||||
import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import Link from 'Components/Link/Link';
|
||||
import ArtistSearchInputConnector from './ArtistSearchInputConnector';
|
||||
import AuthorSearchInputConnector from './AuthorSearchInputConnector';
|
||||
import PageHeaderActionsMenuConnector from './PageHeaderActionsMenuConnector';
|
||||
import KeyboardShortcutsModal from './KeyboardShortcutsModal';
|
||||
import styles from './PageHeader.css';
|
||||
@@ -70,7 +70,7 @@ class PageHeader extends Component {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<ArtistSearchInputConnector />
|
||||
<AuthorSearchInputConnector />
|
||||
|
||||
<div className={styles.right}>
|
||||
<IconButton
|
||||
|
||||
@@ -9,21 +9,21 @@ const fuseOptions = {
|
||||
maxPatternLength: 32,
|
||||
minMatchCharLength: 1,
|
||||
keys: [
|
||||
'artistName',
|
||||
'authorName',
|
||||
'tags.label'
|
||||
]
|
||||
};
|
||||
|
||||
function getSuggestions(artists, value) {
|
||||
function getSuggestions(authors, value) {
|
||||
const limit = 10;
|
||||
let suggestions = [];
|
||||
|
||||
if (value.length === 1) {
|
||||
for (let i = 0; i < artists.length; i++) {
|
||||
const s = artists[i];
|
||||
for (let i = 0; i < authors.length; i++) {
|
||||
const s = authors[i];
|
||||
if (s.firstCharacter === value.toLowerCase()) {
|
||||
suggestions.push({
|
||||
item: artists[i],
|
||||
item: authors[i],
|
||||
indices: [
|
||||
[0, 0]
|
||||
],
|
||||
@@ -41,7 +41,7 @@ function getSuggestions(artists, value) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const fuse = new Fuse(artists, fuseOptions);
|
||||
const fuse = new Fuse(authors, fuseOptions);
|
||||
suggestions = fuse.search(value, { limit });
|
||||
}
|
||||
|
||||
@@ -54,9 +54,9 @@ self.addEventListener('message', (e) => {
|
||||
}
|
||||
|
||||
const {
|
||||
artists,
|
||||
authors,
|
||||
value
|
||||
} = e.data;
|
||||
|
||||
self.postMessage(getSuggestions(artists, value));
|
||||
self.postMessage(getSuggestions(authors, value));
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import { createSelector } from 'reselect';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
|
||||
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
|
||||
import { fetchArtist } from 'Store/Actions/artistActions';
|
||||
import { fetchAuthor } from 'Store/Actions/authorActions';
|
||||
import { fetchTags } from 'Store/Actions/tagActions';
|
||||
import { fetchQualityProfiles, fetchMetadataProfiles, fetchUISettings, fetchImportLists } from 'Store/Actions/settingsActions';
|
||||
import { fetchStatus } from 'Store/Actions/systemActions';
|
||||
@@ -138,8 +138,8 @@ function createMapStateToProps() {
|
||||
|
||||
function createMapDispatchToProps(dispatch, props) {
|
||||
return {
|
||||
dispatchFetchArtist() {
|
||||
dispatch(fetchArtist());
|
||||
dispatchFetchAuthor() {
|
||||
dispatch(fetchAuthor());
|
||||
},
|
||||
dispatchFetchCustomFilters() {
|
||||
dispatch(fetchCustomFilters());
|
||||
@@ -186,7 +186,7 @@ class PageConnector extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.isPopulated) {
|
||||
this.props.dispatchFetchArtist();
|
||||
this.props.dispatchFetchAuthor();
|
||||
this.props.dispatchFetchCustomFilters();
|
||||
this.props.dispatchFetchTags();
|
||||
this.props.dispatchFetchQualityProfiles();
|
||||
@@ -211,7 +211,7 @@ class PageConnector extends Component {
|
||||
const {
|
||||
isPopulated,
|
||||
hasError,
|
||||
dispatchFetchArtist,
|
||||
dispatchFetchAuthor,
|
||||
dispatchFetchTags,
|
||||
dispatchFetchQualityProfiles,
|
||||
dispatchFetchMetadataProfiles,
|
||||
@@ -249,7 +249,7 @@ PageConnector.propTypes = {
|
||||
isPopulated: PropTypes.bool.isRequired,
|
||||
hasError: PropTypes.bool.isRequired,
|
||||
isSidebarVisible: PropTypes.bool.isRequired,
|
||||
dispatchFetchArtist: PropTypes.func.isRequired,
|
||||
dispatchFetchAuthor: PropTypes.func.isRequired,
|
||||
dispatchFetchCustomFilters: PropTypes.func.isRequired,
|
||||
dispatchFetchTags: PropTypes.func.isRequired,
|
||||
dispatchFetchQualityProfiles: PropTypes.func.isRequired,
|
||||
|
||||
@@ -13,19 +13,19 @@ function getIconName(name) {
|
||||
return icons.BACKUP;
|
||||
case 'CheckHealth':
|
||||
return icons.HEALTH;
|
||||
case 'AlbumSearch':
|
||||
case 'BookSearch':
|
||||
return icons.SEARCH;
|
||||
case 'Housekeeping':
|
||||
return icons.HOUSEKEEPING;
|
||||
case 'RescanFolders':
|
||||
return icons.RESCAN;
|
||||
case 'RefreshArtist':
|
||||
case 'RefreshAuthor':
|
||||
return icons.REFRESH;
|
||||
case 'RssSync':
|
||||
return icons.RSS;
|
||||
case 'SeasonSearch':
|
||||
return icons.SEARCH;
|
||||
case 'ArtistSearch':
|
||||
case 'AuthorSearch':
|
||||
return icons.SEARCH;
|
||||
case 'UpdateSceneMapping':
|
||||
return icons.REFRESH;
|
||||
|
||||
@@ -19,10 +19,10 @@ const SIDEBAR_WIDTH = parseInt(dimensions.sidebarWidth);
|
||||
|
||||
const links = [
|
||||
{
|
||||
iconName: icons.ARTIST_CONTINUING,
|
||||
iconName: icons.AUTHOR_CONTINUING,
|
||||
title: 'Library',
|
||||
to: '/',
|
||||
alias: '/artist',
|
||||
alias: '/author',
|
||||
children: [
|
||||
{
|
||||
title: 'Add New',
|
||||
@@ -30,11 +30,11 @@ const links = [
|
||||
},
|
||||
{
|
||||
title: 'Mass Editor',
|
||||
to: '/artisteditor'
|
||||
to: '/authoreditor'
|
||||
},
|
||||
{
|
||||
title: 'Bookshelf',
|
||||
to: '/albumstudio'
|
||||
to: '/bookshelf'
|
||||
},
|
||||
{
|
||||
title: 'Unmapped Files',
|
||||
|
||||
@@ -8,7 +8,7 @@ import titleCase from 'Utilities/String/titleCase';
|
||||
import { fetchCommands, updateCommand, finishCommand } from 'Store/Actions/commandActions';
|
||||
import { setAppValue, setVersion } from 'Store/Actions/appActions';
|
||||
import { update, updateItem, removeItem } from 'Store/Actions/baseActions';
|
||||
import { fetchArtist } from 'Store/Actions/artistActions';
|
||||
import { fetchAuthor } from 'Store/Actions/authorActions';
|
||||
import { fetchHealth } from 'Store/Actions/systemActions';
|
||||
import { fetchQueue, fetchQueueDetails } from 'Store/Actions/queueActions';
|
||||
import { fetchRootFolders } from 'Store/Actions/settingsActions';
|
||||
@@ -45,7 +45,7 @@ const mapDispatchToProps = {
|
||||
dispatchUpdate: update,
|
||||
dispatchUpdateItem: updateItem,
|
||||
dispatchRemoveItem: removeItem,
|
||||
dispatchFetchArtist: fetchArtist,
|
||||
dispatchFetchAuthor: fetchAuthor,
|
||||
dispatchFetchHealth: fetchHealth,
|
||||
dispatchFetchQueue: fetchQueue,
|
||||
dispatchFetchQueueDetails: fetchQueueDetails,
|
||||
@@ -175,9 +175,9 @@ class SignalRConnector extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleAlbum = (body) => {
|
||||
handleBook = (body) => {
|
||||
const action = body.action;
|
||||
const section = 'albums';
|
||||
const section = 'books';
|
||||
|
||||
if (action === 'updated') {
|
||||
this.props.dispatchUpdateItem({
|
||||
@@ -193,18 +193,8 @@ class SignalRConnector extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleTrack = (body) => {
|
||||
if (body.action === 'updated') {
|
||||
this.props.dispatchUpdateItem({
|
||||
section: 'tracks',
|
||||
updateOnly: true,
|
||||
...body.resource
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleTrackfile = (body) => {
|
||||
const section = 'trackFiles';
|
||||
handleBookfile = (body) => {
|
||||
const section = 'bookFiles';
|
||||
|
||||
if (body.action === 'updated') {
|
||||
this.props.dispatchUpdateItem({ section, ...body.resource });
|
||||
@@ -213,16 +203,16 @@ class SignalRConnector extends Component {
|
||||
}
|
||||
|
||||
// Repopulate the page to handle recently imported file
|
||||
repopulatePage('trackFileUpdated');
|
||||
repopulatePage('bookFileUpdated');
|
||||
}
|
||||
|
||||
handleHealth = () => {
|
||||
this.props.dispatchFetchHealth();
|
||||
}
|
||||
|
||||
handleArtist = (body) => {
|
||||
handleAuthor = (body) => {
|
||||
const action = body.action;
|
||||
const section = 'artist';
|
||||
const section = 'authors';
|
||||
|
||||
if (action === 'updated') {
|
||||
this.props.dispatchUpdateItem({ section, ...body.resource });
|
||||
@@ -315,7 +305,7 @@ class SignalRConnector extends Component {
|
||||
|
||||
const {
|
||||
dispatchFetchCommands,
|
||||
dispatchFetchArtist,
|
||||
dispatchFetchAuthor,
|
||||
dispatchSetAppValue
|
||||
} = this.props;
|
||||
|
||||
@@ -328,7 +318,7 @@ class SignalRConnector extends Component {
|
||||
|
||||
// Repopulate the page (if a repopulator is set) to ensure things
|
||||
// are in sync after reconnecting.
|
||||
dispatchFetchArtist();
|
||||
dispatchFetchAuthor();
|
||||
dispatchFetchCommands();
|
||||
repopulatePage();
|
||||
}
|
||||
@@ -363,7 +353,7 @@ SignalRConnector.propTypes = {
|
||||
dispatchUpdate: PropTypes.func.isRequired,
|
||||
dispatchUpdateItem: PropTypes.func.isRequired,
|
||||
dispatchRemoveItem: PropTypes.func.isRequired,
|
||||
dispatchFetchArtist: PropTypes.func.isRequired,
|
||||
dispatchFetchAuthor: PropTypes.func.isRequired,
|
||||
dispatchFetchHealth: PropTypes.func.isRequired,
|
||||
dispatchFetchQueue: PropTypes.func.isRequired,
|
||||
dispatchFetchQueueDetails: PropTypes.func.isRequired,
|
||||
|
||||
@@ -8,7 +8,7 @@ export const shortcuts = {
|
||||
name: 'Open This Modal'
|
||||
},
|
||||
|
||||
ARTIST_SEARCH_INPUT: {
|
||||
AUTHOR_SEARCH_INPUT: {
|
||||
key: 's',
|
||||
name: 'Focus Search Box'
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user