- All results are hidden by {filters.length > 1 ? 'filters' : 'a filter'}.
-
+ isFetching &&
+
+ Unable to load results for this album search. Try again later.
+
+ }
+
+ {
+ !isFetching && isPopulated && !totalReleasesCount &&
+
+ All results are hidden by {filters.length > 1 ? 'filters' : 'a filter'}.
+
}
{
diff --git a/frontend/src/Artist/Index/Banners/ArtistIndexBanner.js b/frontend/src/Artist/Index/Banners/ArtistIndexBanner.js
index 95291e5dc..144995632 100644
--- a/frontend/src/Artist/Index/Banners/ArtistIndexBanner.js
+++ b/frontend/src/Artist/Index/Banners/ArtistIndexBanner.js
@@ -79,6 +79,8 @@ class ArtistIndexBanner extends Component {
} = this.props;
const {
+ albumCount,
+ sizeOnDisk,
trackCount,
trackFileCount,
totalTrackCount
@@ -189,12 +191,13 @@ class ArtistIndexBanner extends Component {
}
@@ -107,8 +103,9 @@ ArtistIndexBannerInfo.propTypes = {
showQualityProfile: PropTypes.bool.isRequired,
previousAiring: PropTypes.string,
added: PropTypes.string,
- statistics: PropTypes.object.isRequired,
+ albumCount: PropTypes.number.isRequired,
path: PropTypes.string.isRequired,
+ sizeOnDisk: PropTypes.number,
sortKey: PropTypes.string.isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
diff --git a/frontend/src/Artist/Index/Overview/ArtistIndexOverview.js b/frontend/src/Artist/Index/Overview/ArtistIndexOverview.js
index 01cfe1598..af3cc11a0 100644
--- a/frontend/src/Artist/Index/Overview/ArtistIndexOverview.js
+++ b/frontend/src/Artist/Index/Overview/ArtistIndexOverview.js
@@ -95,6 +95,8 @@ class ArtistIndexOverview extends Component {
} = this.props;
const {
+ albumCount,
+ sizeOnDisk,
trackCount,
trackFileCount,
totalTrackCount
@@ -196,11 +198,12 @@ class ArtistIndexOverview extends Component {
height={overviewHeight}
monitored={monitored}
nextAiring={nextAiring}
+ albumCount={albumCount}
+ sizeOnDisk={sizeOnDisk}
qualityProfile={qualityProfile}
showRelativeDates={showRelativeDates}
shortDateFormat={shortDateFormat}
timeFormat={timeFormat}
- statistics={statistics}
{...overviewOptions}
{...otherProps}
/>
@@ -251,8 +254,7 @@ ArtistIndexOverview.propTypes = {
ArtistIndexOverview.defaultProps = {
trackCount: 0,
- trackFileCount: 0,
- albumCount: 0
+ trackFileCount: 0
};
export default ArtistIndexOverview;
diff --git a/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfo.css b/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfo.css
index aa25a676c..5dc53762f 100644
--- a/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfo.css
+++ b/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfo.css
@@ -5,17 +5,6 @@
margin-left: 10px;
}
-.info {
- flex: 0 0 $artistIndexOverviewInfoRowHeight;
- margin: 2px 0;
-}
-
-.icon {
- margin-right: 5px;
- width: 25px;
- text-align: center;
-}
-
@media only screen and (max-width: $breakpointSmall) {
.infos {
margin-left: 0;
diff --git a/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfo.js b/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfo.js
index 004a48a51..1922f7041 100644
--- a/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfo.js
+++ b/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfo.js
@@ -5,190 +5,191 @@ import getRelativeDate from 'Utilities/Date/getRelativeDate';
import formatBytes from 'Utilities/Number/formatBytes';
import { icons } from 'Helpers/Props';
import dimensions from 'Styles/Variables/dimensions';
-import Icon from 'Components/Icon';
+import ArtistIndexOverviewInfoRow from './ArtistIndexOverviewInfoRow';
import styles from './ArtistIndexOverviewInfo.css';
const infoRowHeight = parseInt(dimensions.artistIndexOverviewInfoRowHeight);
-function isVisible(name, show, value, sortKey, index) {
- if (value == null) {
+const rows = [
+ {
+ name: 'monitored',
+ showProp: 'showMonitored',
+ valueProp: 'monitored'
+
+ },
+ {
+ name: 'qualityProfileId',
+ showProp: 'showQualityProfile',
+ valueProp: 'qualityProfileId'
+ },
+ {
+ name: 'added',
+ showProp: 'showAdded',
+ valueProp: 'added'
+ },
+ {
+ name: 'albumCount',
+ showProp: 'showAlbumCount',
+ valueProp: 'albumCount'
+ },
+ {
+ name: 'path',
+ showProp: 'showPath',
+ valueProp: 'path'
+ },
+ {
+ name: 'sizeOnDisk',
+ showProp: 'showSizeOnDisk',
+ valueProp: 'sizeOnDisk'
+ }
+];
+
+function isVisible(row, props) {
+ const {
+ name,
+ showProp,
+ valueProp
+ } = row;
+
+ if (props[valueProp] == null) {
return false;
}
- return show || sortKey === name;
+ return props[showProp] || props.sortKey === name;
+}
+
+function getInfoRowProps(row, props) {
+ const { name } = row;
+
+ if (name === 'monitored') {
+ const monitoredText = props.monitored ? 'Monitored' : 'Unmonitored';
+
+ return {
+ title: monitoredText,
+ iconName: props.monitored ? icons.MONITORED : icons.UNMONITORED,
+ label: monitoredText
+ };
+ }
+
+ if (name === 'qualityProfileId') {
+ return {
+ title: 'Quality PROFILE',
+ iconName: icons.PROFILE,
+ label: props.qualityProfile.name
+ };
+ }
+
+ if (name === 'added') {
+ const {
+ added,
+ shortDateFormat,
+ showRelativeDates,
+ timeFormat
+ } = props;
+
+ return {
+ title: 'Added',
+ iconName: icons.ADD,
+ label: getRelativeDate(
+ added,
+ shortDateFormat,
+ showRelativeDates,
+ {
+ timeFormat,
+ timeForToday: true
+ }
+ )
+ };
+ }
+
+ if (name === 'albumCount') {
+ const { albumCount } = props;
+ let albums = '1 album';
+
+ if (albumCount === 0) {
+ albums = 'No albums';
+ } else if (albumCount > 1) {
+ albums = `${albumCount} albums`;
+ }
+
+ return {
+ title: 'Album Count',
+ iconName: icons.CIRCLE,
+ label: albums
+ };
+ }
+
+ if (name === 'path') {
+ return {
+ title: 'Path',
+ iconName: icons.FOLDER,
+ label: props.path
+ };
+ }
+
+ if (name === 'sizeOnDisk') {
+ return {
+ title: 'Size on Disk',
+ iconName: icons.DRIVE,
+ label: formatBytes(props.sizeOnDisk)
+ };
+ }
}
function ArtistIndexOverviewInfo(props) {
const {
height,
- showMonitored,
- showQualityProfile,
- showAdded,
- showAlbumCount,
- showPath,
- showSizeOnDisk,
- monitored,
nextAiring,
- qualityProfile,
- added,
- statistics,
- path,
- sortKey,
showRelativeDates,
shortDateFormat,
timeFormat
} = props;
- const {
- albumCount,
- sizeOnDisk
- } = statistics;
-
- let albums = '1 album';
-
- if (albumCount === 0) {
- albums = 'No albums';
- } else if (albumCount > 1) {
- albums = `${albumCount} albums`;
- }
+ let shownRows = 1;
const maxRows = Math.floor(height / (infoRowHeight + 4));
- const monitoredText = monitored ? 'Monitored' : 'Unmonitored';
return (
{
!!nextAiring &&
-
-
-
+
+ )}
+ />
}
{
- isVisible('monitored', showMonitored, monitored, sortKey) && maxRows > 1 &&
-
-
+ rows.map((row) => {
+ if (!isVisible(row, props)) {
+ return null;
+ }
- {monitoredText}
-
- }
+ if (shownRows >= maxRows) {
+ return null;
+ }
- {
- isVisible('qualityProfileId', showQualityProfile, qualityProfile, sortKey) && maxRows > 2 &&
-
-
+ shownRows++;
- {qualityProfile.name}
-
- }
+ const infoRowProps = getInfoRowProps(row, props);
- {
- isVisible('added', showAdded, added, sortKey) && maxRows > 3 &&
-
-
-
- {
- getRelativeDate(
- added,
- shortDateFormat,
- showRelativeDates,
- {
- timeFormat,
- timeForToday: true
- }
- )
- }
-
+ );
+ })
}
-
- {
- isVisible('albumCount', showAlbumCount, albumCount, sortKey) && maxRows > 4 &&
-
-
-
- {albums}
-
- }
-
- {
- isVisible('path', showPath, path, sortKey) && maxRows > 5 &&
-
-
-
- {path}
-
- }
-
- {
- isVisible('sizeOnDisk', showSizeOnDisk, sizeOnDisk, sortKey) && maxRows > 6 &&
-
-
-
- {formatBytes(sizeOnDisk)}
-
- }
-
);
}
@@ -207,8 +208,9 @@ ArtistIndexOverviewInfo.propTypes = {
qualityProfile: PropTypes.object.isRequired,
previousAiring: PropTypes.string,
added: PropTypes.string,
- statistics: PropTypes.object.isRequired,
+ albumCount: PropTypes.number.isRequired,
path: PropTypes.string.isRequired,
+ sizeOnDisk: PropTypes.number,
sortKey: PropTypes.string.isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
diff --git a/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfoRow.css b/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfoRow.css
new file mode 100644
index 000000000..1fcd432a3
--- /dev/null
+++ b/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfoRow.css
@@ -0,0 +1,10 @@
+.infoRow {
+ flex: 0 0 $artistIndexOverviewInfoRowHeight;
+ margin: 2px 0;
+}
+
+.icon {
+ margin-right: 5px;
+ width: 25px !important;
+ text-align: center;
+}
diff --git a/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfoRow.js b/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfoRow.js
new file mode 100644
index 000000000..b04029b88
--- /dev/null
+++ b/frontend/src/Artist/Index/Overview/ArtistIndexOverviewInfoRow.js
@@ -0,0 +1,35 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import Icon from 'Components/Icon';
+import styles from './ArtistIndexOverviewInfoRow.css';
+
+function ArtistIndexOverviewInfoRow(props) {
+ const {
+ title,
+ iconName,
+ label
+ } = props;
+
+ return (
+
+
+
+ {label}
+
+ );
+}
+
+ArtistIndexOverviewInfoRow.propTypes = {
+ title: PropTypes.string,
+ iconName: PropTypes.object.isRequired,
+ label: PropTypes.string.isRequired
+};
+
+export default ArtistIndexOverviewInfoRow;
diff --git a/frontend/src/Artist/Index/Posters/ArtistIndexPoster.js b/frontend/src/Artist/Index/Posters/ArtistIndexPoster.js
index fe079a24c..d05bd4e4d 100644
--- a/frontend/src/Artist/Index/Posters/ArtistIndexPoster.js
+++ b/frontend/src/Artist/Index/Posters/ArtistIndexPoster.js
@@ -79,6 +79,8 @@ class ArtistIndexPoster extends Component {
} = this.props;
const {
+ albumCount,
+ sizeOnDisk,
trackCount,
trackFileCount,
totalTrackCount
@@ -188,11 +190,12 @@ class ArtistIndexPoster extends Component {
}
@@ -241,8 +244,7 @@ ArtistIndexPoster.propTypes = {
ArtistIndexPoster.defaultProps = {
trackCount: 0,
- trackFileCount: 0,
- albumCount: 0
+ trackFileCount: 0
};
export default ArtistIndexPoster;
diff --git a/frontend/src/Artist/Index/Posters/ArtistIndexPosterInfo.js b/frontend/src/Artist/Index/Posters/ArtistIndexPosterInfo.js
index 432faf68e..591961605 100644
--- a/frontend/src/Artist/Index/Posters/ArtistIndexPosterInfo.js
+++ b/frontend/src/Artist/Index/Posters/ArtistIndexPosterInfo.js
@@ -10,19 +10,15 @@ function ArtistIndexPosterInfo(props) {
showQualityProfile,
previousAiring,
added,
- statistics,
+ albumCount,
path,
+ sizeOnDisk,
sortKey,
showRelativeDates,
shortDateFormat,
timeFormat
} = props;
- const {
- albumCount,
- sizeOnDisk
- } = statistics;
-
if (sortKey === 'qualityProfileId' && !showQualityProfile) {
return (
@@ -107,8 +103,9 @@ ArtistIndexPosterInfo.propTypes = {
showQualityProfile: PropTypes.bool.isRequired,
previousAiring: PropTypes.string,
added: PropTypes.string,
- statistics: PropTypes.object.isRequired,
+ albumCount: PropTypes.number.isRequired,
path: PropTypes.string.isRequired,
+ sizeOnDisk: PropTypes.number,
sortKey: PropTypes.string.isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
diff --git a/frontend/src/Artist/Index/Table/ArtistIndexHeader.css b/frontend/src/Artist/Index/Table/ArtistIndexHeader.css
index 31261d74b..299ca4855 100644
--- a/frontend/src/Artist/Index/Table/ArtistIndexHeader.css
+++ b/frontend/src/Artist/Index/Table/ArtistIndexHeader.css
@@ -43,7 +43,7 @@
.trackCount {
composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css';
- flex: 0 0 120px;
+ flex: 0 0 130px;
}
.path {
@@ -55,7 +55,7 @@
.sizeOnDisk {
composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css';
- flex: 0 0 115px;
+ flex: 0 0 120px;
}
.tags {
diff --git a/frontend/src/Artist/Index/Table/ArtistIndexRow.css b/frontend/src/Artist/Index/Table/ArtistIndexRow.css
index 0001750a8..4c869d02e 100644
--- a/frontend/src/Artist/Index/Table/ArtistIndexRow.css
+++ b/frontend/src/Artist/Index/Table/ArtistIndexRow.css
@@ -45,7 +45,7 @@
.trackCount {
composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css';
- flex: 0 0 120px;
+ flex: 0 0 130px;
}
.path {
@@ -57,7 +57,7 @@
.sizeOnDisk {
composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css';
- flex: 0 0 110px;
+ flex: 0 0 120px;
}
.tags {
diff --git a/frontend/src/Artist/Index/Table/ArtistIndexRow.js b/frontend/src/Artist/Index/Table/ArtistIndexRow.js
index a042752f5..79d923d5b 100644
--- a/frontend/src/Artist/Index/Table/ArtistIndexRow.js
+++ b/frontend/src/Artist/Index/Table/ArtistIndexRow.js
@@ -382,8 +382,7 @@ ArtistIndexRow.propTypes = {
ArtistIndexRow.defaultProps = {
trackCount: 0,
- trackFileCount: 0,
- albumCount: 0
+ trackFileCount: 0
};
export default ArtistIndexRow;
diff --git a/frontend/src/Calendar/CalendarPage.js b/frontend/src/Calendar/CalendarPage.js
index 6d235f806..bb4d125a5 100644
--- a/frontend/src/Calendar/CalendarPage.js
+++ b/frontend/src/Calendar/CalendarPage.js
@@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Measure from 'react-measure';
import { align, icons } from 'Helpers/Props';
-import getFilterValue from 'Utilities/Filter/getFilterValue';
import PageContent from 'Components/Page/PageContent';
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
@@ -41,6 +40,10 @@ class CalendarPage extends Component {
this.props.onDaysCountChange(days);
}
+ onFilterSelect = (selectedFilterKey) => {
+ this.props.onUnmonitoredChange(selectedFilterKey === 'unmonitored');
+ }
+
onGetCalendarLinkPress = () => {
this.setState({ isCalendarLinkModalOpen: true });
}
@@ -57,8 +60,7 @@ class CalendarPage extends Component {
selectedFilterKey,
filters,
hasArtist,
- colorImpairedMode,
- onFilterSelect
+ colorImpairedMode
} = this.props;
const isMeasured = this.state.width > 0;
@@ -83,10 +85,11 @@ class CalendarPage extends Component {
@@ -123,7 +126,7 @@ CalendarPage.propTypes = {
hasArtist: PropTypes.bool.isRequired,
colorImpairedMode: PropTypes.bool.isRequired,
onDaysCountChange: PropTypes.func.isRequired,
- onFilterSelect: PropTypes.func.isRequired
+ onUnmonitoredChange: PropTypes.func.isRequired
};
export default CalendarPage;
diff --git a/frontend/src/Calendar/CalendarPageConnector.js b/frontend/src/Calendar/CalendarPageConnector.js
index fbd6a17f9..859ade5c7 100644
--- a/frontend/src/Calendar/CalendarPageConnector.js
+++ b/frontend/src/Calendar/CalendarPageConnector.js
@@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
-import { setCalendarDaysCount, setCalendarFilter } from 'Store/Actions/calendarActions';
+import { setCalendarDaysCount, setCalendarIncludeUnmonitored } from 'Store/Actions/calendarActions';
import createArtistCountSelector from 'Store/Selectors/createArtistCountSelector';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import CalendarPage from './CalendarPage';
@@ -12,8 +12,8 @@ function createMapStateToProps() {
createUISettingsSelector(),
(calendar, artistCount, uiSettings) => {
return {
- filters: calendar.filters,
selectedFilterKey: calendar.selectedFilterKey,
+ filters: calendar.filters,
showUpcoming: calendar.showUpcoming,
colorImpairedMode: uiSettings.enableColorImpairedMode,
hasArtist: !!artistCount
@@ -28,8 +28,8 @@ function createMapDispatchToProps(dispatch, props) {
dispatch(setCalendarDaysCount({ dayCount }));
},
- onFilterSelect(selectedFilterKey) {
- dispatch(setCalendarFilter({ selectedFilterKey }));
+ onUnmonitoredChange(unmonitored) {
+ dispatch(setCalendarIncludeUnmonitored({ unmonitored }));
}
};
}
diff --git a/frontend/src/Store/Actions/calendarActions.js b/frontend/src/Store/Actions/calendarActions.js
index 2b2a97317..f61df1dbf 100644
--- a/frontend/src/Store/Actions/calendarActions.js
+++ b/frontend/src/Store/Actions/calendarActions.js
@@ -36,27 +36,27 @@ export const defaultState = {
error: null,
items: [],
- selectedFilterKey: 'all',
+ selectedFilterKey: 'monitored',
filters: [
{
- key: 'all',
- label: 'All',
+ key: 'monitored',
+ label: 'Monitored Only',
filters: [
{
- key: 'unmonitored',
- value: false,
+ key: 'monitored',
+ value: true,
type: filterTypes.EQUAL
}
]
},
{
key: 'unmonitored',
- label: 'Unmonitored',
+ label: 'Include Unmonitored',
filters: [
{
- key: 'unmonitored',
- value: true,
+ key: 'monitored',
+ value: false,
type: filterTypes.EQUAL
}
]
@@ -66,7 +66,7 @@ export const defaultState = {
export const persistState = [
'calendar.view',
- 'calendar.showUpcoming',
+ 'calendar.unmonitored',
'calendar.selectedFilterKey'
];
@@ -75,8 +75,8 @@ export const persistState = [
export const FETCH_CALENDAR = 'calendar/fetchCalendar';
export const SET_CALENDAR_DAYS_COUNT = 'calendar/setCalendarDaysCount';
+export const SET_CALENDAR_INCLUDE_UNMONITORED = 'calendar/setCalendarIncludeUnmonitored';
export const SET_CALENDAR_VIEW = 'calendar/setCalendarView';
-export const SET_CALENDAR_FILTER = 'calendar/setCalendarFilter';
export const GOTO_CALENDAR_TODAY = 'calendar/gotoCalendarToday';
export const GOTO_CALENDAR_PREVIOUS_RANGE = 'calendar/gotoCalendarPreviousRange';
export const GOTO_CALENDAR_NEXT_RANGE = 'calendar/gotoCalendarNextRange';
@@ -182,8 +182,8 @@ function isRangePopulated(start, end, state) {
export const fetchCalendar = createThunk(FETCH_CALENDAR);
export const setCalendarDaysCount = createThunk(SET_CALENDAR_DAYS_COUNT);
+export const setCalendarIncludeUnmonitored = createThunk(SET_CALENDAR_INCLUDE_UNMONITORED);
export const setCalendarView = createThunk(SET_CALENDAR_VIEW);
-export const setCalendarFilter = createThunk(SET_CALENDAR_FILTER);
export const gotoCalendarToday = createThunk(GOTO_CALENDAR_TODAY);
export const gotoCalendarPreviousRange = createThunk(GOTO_CALENDAR_PREVIOUS_RANGE);
export const gotoCalendarNextRange = createThunk(GOTO_CALENDAR_NEXT_RANGE);
@@ -196,8 +196,7 @@ export const actionHandlers = handleThunks({
[FETCH_CALENDAR]: function(getState, payload, dispatch) {
const state = getState();
- const selectedFilter = state.calendar.selectedFilterKey;
- const unmonitored = state.calendar.filters.find((f) => f.key === selectedFilter).filters[0].value;
+ const unmonitored = state.calendar.unmonitored;
const {
time,
@@ -274,6 +273,18 @@ export const actionHandlers = handleThunks({
dispatch(fetchCalendar({ time, view }));
},
+ [SET_CALENDAR_INCLUDE_UNMONITORED]: function(getState, payload, dispatch) {
+ dispatch(set({
+ section,
+ unmonitored: payload.unmonitored
+ }));
+
+ const state = getState();
+ const { time, view } = state.calendar;
+
+ dispatch(fetchCalendar({ time, view }));
+ },
+
[SET_CALENDAR_VIEW]: function(getState, payload, dispatch) {
const state = getState();
const view = payload.view;
@@ -317,18 +328,6 @@ export const actionHandlers = handleThunks({
const amount = view === calendarViews.FORECAST ? dayCount : 1;
const time = moment(state.calendar.time).add(amount, viewRanges[view]);
- dispatch(fetchCalendar({ time, view }));
- },
-
- [SET_CALENDAR_FILTER]: function(getState, payload, dispatch) {
- dispatch(set({
- section,
- selectedFilterKey: payload.selectedFilterKey
- }));
-
- const state = getState();
- const { time, view } = state.calendar;
-
dispatch(fetchCalendar({ time, view }));
}
});