diff --git a/frontend/src/Activity/History/HistoryRow.js b/frontend/src/Activity/History/HistoryRow.js index 8f29fee8f..f2f0cb732 100644 --- a/frontend/src/Activity/History/HistoryRow.js +++ b/frontend/src/Activity/History/HistoryRow.js @@ -119,6 +119,7 @@ class HistoryRow extends Component { artistId={artist.id} albumTitle={album.title} showOpenArtistButton={true} + showOpenAlbumButton={true} /> ); diff --git a/frontend/src/Activity/Queue/QueueRow.js b/frontend/src/Activity/Queue/QueueRow.js index 90622873c..266a4a836 100644 --- a/frontend/src/Activity/Queue/QueueRow.js +++ b/frontend/src/Activity/Queue/QueueRow.js @@ -161,6 +161,7 @@ class QueueRow extends Component { trackFileId={album.trackFileId} albumTitle={album.title} showOpenArtistButton={true} + showOpenAlbumButton={true} /> ); diff --git a/frontend/src/AddArtist/AddNewArtist/AddNewArtistSearchResult.js b/frontend/src/AddArtist/AddNewArtist/AddNewArtistSearchResult.js index 8399b8df1..a5f9ecadc 100644 --- a/frontend/src/AddArtist/AddNewArtist/AddNewArtistSearchResult.js +++ b/frontend/src/AddArtist/AddNewArtist/AddNewArtistSearchResult.js @@ -78,6 +78,10 @@ class AddNewArtistSearchResult extends Component { isSmallScreen } = this.props; + const { + isNewAddArtistModalOpen + } = this.state; + const linkProps = isExistingArtist ? { to: `/artist/${foreignArtistId}` } : { onPress: this.onPress }; let albums = '1 Album'; @@ -88,78 +92,78 @@ class AddNewArtistSearchResult extends Component { const height = calculateHeight(230, isSmallScreen); return ( - - { - !isSmallScreen && +
+ + { + !isSmallScreen && - } + } -
-
- {artistName} +
+
+ {artistName} - { - !name.contains(year) && !!year && + { + !name.contains(year) && !!year && ({year}) - } + } - { - !!disambiguation && + { + !!disambiguation && ({disambiguation}) - } - - { - isExistingArtist && - - } -
+ } + + { + isExistingArtist && + + } +
-
- - - { - !!artistType && - - } - - { - !!albumCount && - - } - - { - status === 'ended' && - - } -
+
+ + + { + !!artistType && + + } + + { + !!albumCount && + + } + + { + status === 'ended' && + + } +
-
-
+ - +
); } } diff --git a/frontend/src/AddArtist/ImportArtist/Import/SelectArtist/ImportArtistSelectArtist.js b/frontend/src/AddArtist/ImportArtist/Import/SelectArtist/ImportArtistSelectArtist.js index 533a0bc46..189c73aa6 100644 --- a/frontend/src/AddArtist/ImportArtist/Import/SelectArtist/ImportArtistSelectArtist.js +++ b/frontend/src/AddArtist/ImportArtist/Import/SelectArtist/ImportArtistSelectArtist.js @@ -4,7 +4,6 @@ import ReactDOM from 'react-dom'; import TetherComponent from 'react-tether'; import { icons, kinds } from 'Helpers/Props'; import Icon from 'Components/Icon'; -import SpinnerIcon from 'Components/SpinnerIcon'; import FormInputButton from 'Components/Form/FormInputButton'; import Link from 'Components/Link/Link'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; diff --git a/frontend/src/AddArtist/ImportArtist/SelectFolder/ImportArtistSelectFolderConnector.js b/frontend/src/AddArtist/ImportArtist/SelectFolder/ImportArtistSelectFolderConnector.js index da95019cb..10d010903 100644 --- a/frontend/src/AddArtist/ImportArtist/SelectFolder/ImportArtistSelectFolderConnector.js +++ b/frontend/src/AddArtist/ImportArtist/SelectFolder/ImportArtistSelectFolderConnector.js @@ -43,7 +43,7 @@ class ImportArtistSelectFolderConnector extends Component { const newRootFolders = _.differenceBy(items, prevProps.items, (item) => item.id); if (newRootFolders.length === 1) { - this.props.push(`${window.Sonarr.urlBase}/add/import/${newRootFolders[0].id}`); + this.props.push(`${window.Lidarr.urlBase}/add/import/${newRootFolders[0].id}`); } } } diff --git a/frontend/src/Album/AlbumDetailsModalContent.css b/frontend/src/Album/AlbumDetailsModalContent.css index b80b14cb9..b9edb1d33 100644 --- a/frontend/src/Album/AlbumDetailsModalContent.css +++ b/frontend/src/Album/AlbumDetailsModalContent.css @@ -42,3 +42,7 @@ margin-right: auto; } + +.openButtons { + margin-right: auto; +} diff --git a/frontend/src/Album/AlbumDetailsModalContent.js b/frontend/src/Album/AlbumDetailsModalContent.js index 178be8086..675a567e7 100644 --- a/frontend/src/Album/AlbumDetailsModalContent.js +++ b/frontend/src/Album/AlbumDetailsModalContent.js @@ -45,17 +45,20 @@ class AlbumDetailsModalContent extends Component { albumId, artistName, foreignArtistId, + foreignAlbumId, artistMonitored, albumTitle, monitored, isSaving, showOpenArtistButton, + showOpenAlbumButton, startInteractiveSearch, onMonitorAlbumPress, onModalClose } = this.props; const artistLink = `/artist/${foreignArtistId}`; + const albumLink = `/album/${foreignAlbumId}`; return ( - - { - showOpenArtistButton && - - } - + +
+ { + showOpenArtistButton && + + } + + { + showOpenAlbumButton && + + } +
diff --git a/frontend/src/Components/Page/Header/ArtistSearchInputConnector.js b/frontend/src/Components/Page/Header/ArtistSearchInputConnector.js index f1c3cfeeb..2ab4c667d 100644 --- a/frontend/src/Components/Page/Header/ArtistSearchInputConnector.js +++ b/frontend/src/Components/Page/Header/ArtistSearchInputConnector.js @@ -19,11 +19,11 @@ function createMapStateToProps() { function createMapDispatchToProps(dispatch, props) { return { onGoToArtist(foreignArtistId) { - dispatch(push(`${window.Sonarr.urlBase}/artist/${foreignArtistId}`)); + dispatch(push(`${window.Lidarr.urlBase}/artist/${foreignArtistId}`)); }, onGoToAddNewArtist(query) { - dispatch(push(`${window.Sonarr.urlBase}/add/new?term=${encodeURIComponent(query)}`)); + dispatch(push(`${window.Lidarr.urlBase}/add/new?term=${encodeURIComponent(query)}`)); } }; } diff --git a/frontend/src/Components/Page/Header/PageHeader.js b/frontend/src/Components/Page/Header/PageHeader.js index e53436657..95bc2d771 100644 --- a/frontend/src/Components/Page/Header/PageHeader.js +++ b/frontend/src/Components/Page/Header/PageHeader.js @@ -51,10 +51,10 @@ class PageHeader extends Component { return (
- +
@@ -74,6 +74,7 @@ class PageHeader extends Component { className={styles.donate} name={icons.HEART} to="https://www.paypal.me/Lidarr" + size={14} /> { + const section = 'trackFiles'; + if (body.action === 'updated') { - this.props.updateItem({ - section: 'trackFiles', - ...body.resource - }); + this.props.updateItem({ section, ...body.resource }); + } else if (body.action === 'deleted') { + this.props.removeItem({ section, id: body.resource.id }); } } @@ -335,7 +336,7 @@ class SignalRConnector extends Component { } onReconnecting = () => { - if (window.Sonarr.unloading) { + if (window.Lidarr.unloading) { return; } @@ -349,7 +350,7 @@ class SignalRConnector extends Component { } onDisconnected = () => { - if (window.Sonarr.unloading) { + if (window.Lidarr.unloading) { return; } diff --git a/frontend/src/Components/SpinnerIcon.js b/frontend/src/Components/SpinnerIcon.js index f45f6937d..d21674d9e 100644 --- a/frontend/src/Components/SpinnerIcon.js +++ b/frontend/src/Components/SpinnerIcon.js @@ -14,14 +14,15 @@ function SpinnerIcon(props) { return ( ); } SpinnerIcon.propTypes = { - name: PropTypes.string.isRequired, - spinningName: PropTypes.string.isRequired, + name: PropTypes.object.isRequired, + spinningName: PropTypes.object.isRequired, isSpinning: PropTypes.bool.isRequired }; diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsColumn.js b/frontend/src/Components/Table/TableOptions/TableOptionsColumn.js index 6a8e345f8..a986be615 100644 --- a/frontend/src/Components/Table/TableOptions/TableOptionsColumn.js +++ b/frontend/src/Components/Table/TableOptions/TableOptionsColumn.js @@ -18,7 +18,7 @@ function TableOptionsColumn(props) { } = props; return ( -
+
+ + + + + + + + +
+
+ {advancedSettings ? 'Hide Advanced' : 'Show Advanced'} +
+
+ + ); +} + +AdvancedSettingsButton.propTypes = { + advancedSettings: PropTypes.bool.isRequired, + onAdvancedSettingsPress: PropTypes.func.isRequired +}; + +export default AdvancedSettingsButton; diff --git a/frontend/src/Settings/DownloadClients/DownloadClientSettings.js b/frontend/src/Settings/DownloadClients/DownloadClientSettings.js index 414887fd5..8a7abd5c2 100644 --- a/frontend/src/Settings/DownloadClients/DownloadClientSettings.js +++ b/frontend/src/Settings/DownloadClients/DownloadClientSettings.js @@ -14,7 +14,10 @@ class DownloadClientSettings extends Component { constructor(props, context) { super(props, context); + this._saveCallback = null; + this.state = { + isSaving: false, hasPendingChanges: false }; } @@ -22,28 +25,34 @@ class DownloadClientSettings extends Component { // // Listeners - setDownloadClientOptionsRef = (ref) => { - this._downloadClientOptions = ref; + onChildMounted = (saveCallback) => { + this._saveCallback = saveCallback; } - onHasPendingChange = (hasPendingChanges) => { - this.setState({ - hasPendingChanges - }); + onChildStateChange = (payload) => { + this.setState(payload); } onSavePress = () => { - this._downloadClientOptions.getWrappedInstance().save(); + if (this._saveCallback) { + this._saveCallback(); + } } // // Render render() { + const { + isSaving, + hasPendingChanges + } = this.state; + return ( @@ -51,8 +60,8 @@ class DownloadClientSettings extends Component { diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.js b/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.js index b4a725303..b8fde8bcc 100644 --- a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.js +++ b/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.js @@ -60,6 +60,7 @@ class DownloadClient extends Component { return (
diff --git a/frontend/src/Settings/DownloadClients/Options/DownloadClientOptionsConnector.js b/frontend/src/Settings/DownloadClients/Options/DownloadClientOptionsConnector.js index 2c5c78c7e..4dd67f356 100644 --- a/frontend/src/Settings/DownloadClients/Options/DownloadClientOptionsConnector.js +++ b/frontend/src/Settings/DownloadClients/Options/DownloadClientOptionsConnector.js @@ -21,10 +21,10 @@ function createMapStateToProps() { } const mapDispatchToProps = { - fetchDownloadClientOptions, - setDownloadClientOptionsValue, - saveDownloadClientOptions, - clearPendingChanges + dispatchFetchDownloadClientOptions: fetchDownloadClientOptions, + dispatchSetDownloadClientOptionsValue: setDownloadClientOptionsValue, + dispatchSaveDownloadClientOptions: saveDownloadClientOptions, + dispatchClearPendingChanges: clearPendingChanges }; class DownloadClientOptionsConnector extends Component { @@ -33,31 +33,43 @@ class DownloadClientOptionsConnector extends Component { // Lifecycle componentDidMount() { - this.props.fetchDownloadClientOptions(); + const { + dispatchFetchDownloadClientOptions, + dispatchSaveDownloadClientOptions, + onChildMounted + } = this.props; + + dispatchFetchDownloadClientOptions(); + onChildMounted(dispatchSaveDownloadClientOptions); } componentDidUpdate(prevProps) { - if (this.props.hasPendingChanges !== prevProps.hasPendingChanges) { - this.props.onHasPendingChange(this.props.hasPendingChanges); + const { + hasPendingChanges, + isSaving, + onChildStateChange + } = this.props; + + if ( + prevProps.isSaving !== isSaving || + prevProps.hasPendingChanges !== hasPendingChanges + ) { + onChildStateChange({ + isSaving, + hasPendingChanges + }); } } componentWillUnmount() { - this.props.clearPendingChanges({ section: this.props.section }); - } - - // - // Control - - save = () => { - this.props.saveDownloadClientOptions(); + this.props.dispatchClearPendingChanges({ section: this.props.section }); } // // Listeners onInputChange = ({ name, value }) => { - this.props.setDownloadClientOptionsValue({ name, value }); + this.props.dispatchSetDownloadClientOptionsValue({ name, value }); } // @@ -75,18 +87,20 @@ class DownloadClientOptionsConnector extends Component { DownloadClientOptionsConnector.propTypes = { section: PropTypes.string.isRequired, + isSaving: PropTypes.bool.isRequired, hasPendingChanges: PropTypes.bool.isRequired, - fetchDownloadClientOptions: PropTypes.func.isRequired, - setDownloadClientOptionsValue: PropTypes.func.isRequired, - saveDownloadClientOptions: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired, - onHasPendingChange: PropTypes.func.isRequired + dispatchFetchDownloadClientOptions: PropTypes.func.isRequired, + dispatchSetDownloadClientOptionsValue: PropTypes.func.isRequired, + dispatchSaveDownloadClientOptions: PropTypes.func.isRequired, + dispatchClearPendingChanges: PropTypes.func.isRequired, + onChildMounted: PropTypes.func.isRequired, + onChildStateChange: PropTypes.func.isRequired }; export default connectSection( createMapStateToProps, mapDispatchToProps, undefined, - { withRef: true }, + undefined, { section: 'settings.downloadClientOptions' } )(DownloadClientOptionsConnector); diff --git a/frontend/src/Settings/General/HostSettings.js b/frontend/src/Settings/General/HostSettings.js index 0c91d5e67..3e8941555 100644 --- a/frontend/src/Settings/General/HostSettings.js +++ b/frontend/src/Settings/General/HostSettings.js @@ -49,6 +49,8 @@ function HostSettings(props) { diff --git a/frontend/src/Settings/Indexers/IndexerSettings.js b/frontend/src/Settings/Indexers/IndexerSettings.js index 2e526c080..3b42dc2e5 100644 --- a/frontend/src/Settings/Indexers/IndexerSettings.js +++ b/frontend/src/Settings/Indexers/IndexerSettings.js @@ -14,7 +14,10 @@ class IndexerSettings extends Component { constructor(props, context) { super(props, context); + this._saveCallback = null; + this.state = { + isSaving: false, hasPendingChanges: false }; } @@ -22,28 +25,34 @@ class IndexerSettings extends Component { // // Listeners - setIndexerOptionsRef = (ref) => { - this._indexerOptions = ref; + onChildMounted = (saveCallback) => { + this._saveCallback = saveCallback; } - onHasPendingChange = (hasPendingChanges) => { - this.setState({ - hasPendingChanges - }); + onChildStateChange = (payload) => { + this.setState(payload); } onSavePress = () => { - this._indexerOptions.getWrappedInstance().save(); + if (this._saveCallback) { + this._saveCallback(); + } } // // Render render() { + const { + isSaving, + hasPendingChanges + } = this.state; + return ( @@ -51,8 +60,8 @@ class IndexerSettings extends Component { diff --git a/frontend/src/Settings/Indexers/Indexers/Indexer.js b/frontend/src/Settings/Indexers/Indexers/Indexer.js index 379e818b8..27ce30f44 100644 --- a/frontend/src/Settings/Indexers/Indexers/Indexer.js +++ b/frontend/src/Settings/Indexers/Indexers/Indexer.js @@ -76,6 +76,7 @@ class Indexer extends Component { return (
diff --git a/frontend/src/Settings/Indexers/Options/IndexerOptions.js b/frontend/src/Settings/Indexers/Options/IndexerOptions.js index d47a3ca3c..b4b0de2b7 100644 --- a/frontend/src/Settings/Indexers/Options/IndexerOptions.js +++ b/frontend/src/Settings/Indexers/Options/IndexerOptions.js @@ -41,6 +41,7 @@ function IndexerOptions(props) { { - this.props.saveIndexerOptions(); + this.props.dispatchClearPendingChanges({ section: this.props.section }); } // // Listeners onInputChange = ({ name, value }) => { - this.props.setIndexerOptionsValue({ name, value }); + this.props.dispatchSetIndexerOptionsValue({ name, value }); } // @@ -75,18 +87,20 @@ class IndexerOptionsConnector extends Component { IndexerOptionsConnector.propTypes = { section: PropTypes.string.isRequired, + isSaving: PropTypes.bool.isRequired, hasPendingChanges: PropTypes.bool.isRequired, - fetchIndexerOptions: PropTypes.func.isRequired, - setIndexerOptionsValue: PropTypes.func.isRequired, - saveIndexerOptions: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired, - onHasPendingChange: PropTypes.func.isRequired + dispatchFetchIndexerOptions: PropTypes.func.isRequired, + dispatchSetIndexerOptionsValue: PropTypes.func.isRequired, + dispatchSaveIndexerOptions: PropTypes.func.isRequired, + dispatchClearPendingChanges: PropTypes.func.isRequired, + onChildMounted: PropTypes.func.isRequired, + onChildStateChange: PropTypes.func.isRequired }; export default connectSection( createMapStateToProps, mapDispatchToProps, undefined, - { withRef: true }, + undefined, { section: 'settings.indexerOptions' } )(IndexerOptionsConnector); diff --git a/frontend/src/Settings/Indexers/Restrictions/Restriction.js b/frontend/src/Settings/Indexers/Restrictions/Restriction.js index bdd457aca..07b7feece 100644 --- a/frontend/src/Settings/Indexers/Restrictions/Restriction.js +++ b/frontend/src/Settings/Indexers/Restrictions/Restriction.js @@ -64,6 +64,7 @@ class Restriction extends Component { return (
diff --git a/frontend/src/Settings/Metadata/Metadata/Metadata.js b/frontend/src/Settings/Metadata/Metadata/Metadata.js index fb6495f7c..392b4838f 100644 --- a/frontend/src/Settings/Metadata/Metadata/Metadata.js +++ b/frontend/src/Settings/Metadata/Metadata/Metadata.js @@ -52,6 +52,7 @@ class Metadata extends Component { return (
diff --git a/frontend/src/Settings/Notifications/Notifications/Notification.js b/frontend/src/Settings/Notifications/Notifications/Notification.js index cca3761fc..08017f6c5 100644 --- a/frontend/src/Settings/Notifications/Notifications/Notification.js +++ b/frontend/src/Settings/Notifications/Notifications/Notification.js @@ -79,6 +79,7 @@ class Notification extends Component { return (
diff --git a/frontend/src/Settings/Profiles/Language/EditLanguageProfileModalContent.js b/frontend/src/Settings/Profiles/Language/EditLanguageProfileModalContent.js index 947bd62ed..f6affee99 100644 --- a/frontend/src/Settings/Profiles/Language/EditLanguageProfileModalContent.js +++ b/frontend/src/Settings/Profiles/Language/EditLanguageProfileModalContent.js @@ -101,7 +101,7 @@ function EditLanguageProfileModalContent(props) { id &&