From 5a5e896eb4c7a264deb09471a031ae15f5adee95 Mon Sep 17 00:00:00 2001 From: Qstick Date: Sun, 1 Mar 2020 17:13:45 -0500 Subject: [PATCH] Fixed: Misc Calendar Improvements --- frontend/src/Calendar/Agenda/AgendaEvent.css | 35 +-- .../src/Calendar/Events/CalendarEvent.css | 10 +- frontend/src/Calendar/Events/CalendarEvent.js | 12 -- .../Calendar/Events/CalendarEventConnector.js | 5 +- .../Calendar/Events/CalendarEventGroup.css | 87 -------- .../src/Calendar/Events/CalendarEventGroup.js | 200 ------------------ .../Events/CalendarEventGroupConnector.js | 37 ---- frontend/src/Calendar/Legend/Legend.js | 45 +--- frontend/src/Calendar/Legend/LegendItem.css | 12 +- .../Options/CalendarOptionsModalContent.js | 2 - frontend/src/Calendar/getStatusStyle.js | 2 +- .../Calendar/iCal/CalendarLinkModalContent.js | 19 -- src/Radarr.Api.V3/Calendar/CalendarModule.cs | 10 +- 13 files changed, 17 insertions(+), 459 deletions(-) delete mode 100644 frontend/src/Calendar/Events/CalendarEventGroup.css delete mode 100644 frontend/src/Calendar/Events/CalendarEventGroup.js delete mode 100644 frontend/src/Calendar/Events/CalendarEventGroupConnector.js diff --git a/frontend/src/Calendar/Agenda/AgendaEvent.css b/frontend/src/Calendar/Agenda/AgendaEvent.css index 996de36d4..ffd5762e2 100644 --- a/frontend/src/Calendar/Agenda/AgendaEvent.css +++ b/frontend/src/Calendar/Agenda/AgendaEvent.css @@ -37,22 +37,6 @@ margin-right: 10px; } -.episodeTitle { - flex: 1 1 1px; -} - -.seasonEpisodeNumber { - flex: 0 0 100px; -} - -.episodeSeparator { - display: none; -} - -.absoluteEpisodeNumber { - margin-left: 3px; -} - .statusIcon { margin-left: 3px; } @@ -73,18 +57,10 @@ composes: unmonitored from '~Calendar/Events/CalendarEvent.css'; } -.onAir { - composes: onAir from '~Calendar/Events/CalendarEvent.css'; -} - .missing { composes: missing from '~Calendar/Events/CalendarEvent.css'; } -.premiere { - composes: premiere from '~Calendar/Events/CalendarEvent.css'; -} - @media only screen and (max-width: $breakpointSmall) { .event { flex-direction: column; @@ -101,16 +77,7 @@ .date, .time, - .seriesTitle { + .movieTitle { flex: 0 0 100%; } - - .seasonEpisodeNumber { - flex: 0 0 auto; - } - - .episodeSeparator { - display: inline-block; - margin: 0 5px; - } } diff --git a/frontend/src/Calendar/Events/CalendarEvent.css b/frontend/src/Calendar/Events/CalendarEvent.css index ffd12dd17..1e962f17c 100644 --- a/frontend/src/Calendar/Events/CalendarEvent.css +++ b/frontend/src/Calendar/Events/CalendarEvent.css @@ -44,18 +44,10 @@ font-size: $defaultFontSize; } -.absoluteEpisodeNumber { - margin-left: 3px; -} - .statusIcon { margin-left: 3px; } -.airTime { - color: $calendarTextDim; -} - /* * Status */ @@ -97,7 +89,7 @@ } } -.unaired { +.unreleased { border-left-color: $primaryColor !important; &:global(.colorImpaired) { diff --git a/frontend/src/Calendar/Events/CalendarEvent.js b/frontend/src/Calendar/Events/CalendarEvent.js index e6de190b7..67ea8dd91 100644 --- a/frontend/src/Calendar/Events/CalendarEvent.js +++ b/frontend/src/Calendar/Events/CalendarEvent.js @@ -11,17 +11,6 @@ import styles from './CalendarEvent.css'; class CalendarEvent extends Component { - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - // isDetailsModalOpen: false - }; - } - // // Render @@ -138,7 +127,6 @@ CalendarEvent.propTypes = { timeFormat: PropTypes.string.isRequired, colorImpairedMode: PropTypes.bool.isRequired, date: PropTypes.string.isRequired - // onEventModalOpenToggle: PropTypes.func.isRequired }; CalendarEvent.defaultProps = { diff --git a/frontend/src/Calendar/Events/CalendarEventConnector.js b/frontend/src/Calendar/Events/CalendarEventConnector.js index 1ee8d0bc5..0a38db775 100644 --- a/frontend/src/Calendar/Events/CalendarEventConnector.js +++ b/frontend/src/Calendar/Events/CalendarEventConnector.js @@ -1,6 +1,5 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; -import createMovieFileSelector from 'Store/Selectors/createMovieFileSelector'; import createMovieSelector from 'Store/Selectors/createMovieSelector'; import createQueueItemSelector from 'Store/Selectors/createQueueItemSelector'; import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; @@ -10,13 +9,11 @@ function createMapStateToProps() { return createSelector( (state) => state.calendar.options, createMovieSelector(), - createMovieFileSelector(), createQueueItemSelector(), createUISettingsSelector(), - (calendarOptions, movie, movieFile, queueItem, uiSettings) => { + (calendarOptions, movie, queueItem, uiSettings) => { return { movie, - movieFile, queueItem, ...calendarOptions, timeFormat: uiSettings.timeFormat, diff --git a/frontend/src/Calendar/Events/CalendarEventGroup.css b/frontend/src/Calendar/Events/CalendarEventGroup.css deleted file mode 100644 index e5be0fd92..000000000 --- a/frontend/src/Calendar/Events/CalendarEventGroup.css +++ /dev/null @@ -1,87 +0,0 @@ -.eventGroup { - overflow-x: hidden; - margin: 4px 2px; - padding: 5px; - border-bottom: 1px solid $borderColor; - border-left: 4px solid $borderColor; - font-size: 12px; -} - -.info, -.airingInfo { - display: flex; -} - -.seriesTitle { - @add-mixin truncate; - flex: 1 0 1px; - margin-right: 10px; - color: #3a3f51; - font-size: $defaultFontSize; -} - -.airTime { - flex: 1 0 1px; - color: $calendarTextDim; -} - -.episodeInfo { - margin-left: 10px; - color: $calendarTextDim; -} - -.absoluteEpisodeNumber { - margin-left: 3px; -} - -.expandContainerInline { - display: flex; - justify-content: flex-end; - flex: 1 0 20px; -} - -.expandContainer, -.collapseContainer { - display: flex; - justify-content: center; -} - -.collapseContainer { - margin-bottom: 5px; -} - -.statusIcon { - margin-left: 3px; -} - -/* - * Status - */ - -.downloaded { - composes: downloaded from '~Calendar/Events/CalendarEvent.css'; -} - -.downloading { - composes: downloading from '~Calendar/Events/CalendarEvent.css'; -} - -.unmonitored { - composes: unmonitored from '~Calendar/Events/CalendarEvent.css'; -} - -.onAir { - composes: onAir from '~Calendar/Events/CalendarEvent.css'; -} - -.missing { - composes: missing from '~Calendar/Events/CalendarEvent.css'; -} - -.premiere { - composes: premiere from '~Calendar/Events/CalendarEvent.css'; -} - -.unaired { - composes: unaired from '~Calendar/Events/CalendarEvent.css'; -} diff --git a/frontend/src/Calendar/Events/CalendarEventGroup.js b/frontend/src/Calendar/Events/CalendarEventGroup.js deleted file mode 100644 index 186085c52..000000000 --- a/frontend/src/Calendar/Events/CalendarEventGroup.js +++ /dev/null @@ -1,200 +0,0 @@ -import moment from 'moment'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import classNames from 'classnames'; -import { icons, kinds } from 'Helpers/Props'; -import Icon from 'Components/Icon'; -import Link from 'Components/Link/Link'; -import getStatusStyle from 'Calendar/getStatusStyle'; -import CalendarEventConnector from 'Calendar/Events/CalendarEventConnector'; -import styles from './CalendarEventGroup.css'; - -function getEventsInfo(events) { - let files = 0; - let queued = 0; - let monitored = 0; - let absoluteEpisodeNumbers = 0; - - events.forEach((event) => { - if (event.episodeFileId) { - files++; - } - - if (event.queued) { - queued++; - } - - if (event.monitored) { - monitored++; - } - - if (event.absoluteEpisodeNumber) { - absoluteEpisodeNumbers++; - } - }); - - return { - allDownloaded: files === events.length, - anyQueued: queued > 0, - anyMonitored: monitored > 0, - allAbsoluteEpisodeNumbers: absoluteEpisodeNumbers === events.length - }; -} - -class CalendarEventGroup extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isExpanded: false - }; - } - - // - // Listeners - - onExpandPress = () => { - this.setState({ isExpanded: !this.state.isExpanded }); - } - - // - // Render - - render() { - const { - series, - events, - isDownloading, - showEpisodeInformation, - showFinaleIcon, - colorImpairedMode, - onEventModalOpenToggle - } = this.props; - - const { isExpanded } = this.state; - const { - allDownloaded, - anyQueued, - anyMonitored - } = getEventsInfo(events); - const anyDownloading = isDownloading || anyQueued; - const firstEpisode = events[0]; - const lastEpisode = events[events.length -1]; - const airDateUtc = firstEpisode.airDateUtc; - const startTime = moment(airDateUtc); - const endTime = moment(lastEpisode.airDateUtc).add(series.runtime, 'minutes'); - const seasonNumber = firstEpisode.seasonNumber; - const statusStyle = getStatusStyle(allDownloaded, anyDownloading, startTime, endTime, anyMonitored); - - if (isExpanded) { - return ( -
- { - events.map((event) => { - if (event.isGroup) { - return null; - } - - return ( - - ); - }) - } - - - - -
- ); - } - - return ( -
-
-
- {series.title} -
- - { - anyDownloading && - - } - - { - firstEpisode.episodeNumber === 1 && seasonNumber > 0 && - - } - - { - showFinaleIcon && - lastEpisode.episodeNumber !== 1 && - seasonNumber > 0 && - lastEpisode.episodeNumber === series.seasons.find((season) => season.seasonNumber === seasonNumber).statistics.totalEpisodeCount && - - } -
- - { - showEpisodeInformation && - - - - } -
- ); - } -} - -CalendarEventGroup.propTypes = { - series: PropTypes.object.isRequired, - events: PropTypes.arrayOf(PropTypes.object).isRequired, - isDownloading: PropTypes.bool.isRequired, - showEpisodeInformation: PropTypes.bool.isRequired, - showFinaleIcon: PropTypes.bool.isRequired, - timeFormat: PropTypes.string.isRequired, - colorImpairedMode: PropTypes.bool.isRequired, - onEventModalOpenToggle: PropTypes.func.isRequired -}; - -export default CalendarEventGroup; diff --git a/frontend/src/Calendar/Events/CalendarEventGroupConnector.js b/frontend/src/Calendar/Events/CalendarEventGroupConnector.js deleted file mode 100644 index 483b25467..000000000 --- a/frontend/src/Calendar/Events/CalendarEventGroupConnector.js +++ /dev/null @@ -1,37 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createMovieSelector from 'Store/Selectors/createMovieSelector'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import CalendarEventGroup from './CalendarEventGroup'; - -function createIsDownloadingSelector() { - return createSelector( - (state, { movieIds }) => movieIds, - (state) => state.queue.details, - (movieIds, details) => { - return details.items.some((item) => { - return item.movie && movieIds.includes(item.movie.id); - }); - } - ); -} - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar.options, - createMovieSelector(), - createIsDownloadingSelector(), - createUISettingsSelector(), - (calendarOptions, movie, isDownloading, uiSettings) => { - return { - movie, - isDownloading, - ...calendarOptions, - timeFormat: uiSettings.timeFormat, - colorImpairedMode: uiSettings.enableColorImpairedMode - }; - } - ); -} - -export default connect(createMapStateToProps)(CalendarEventGroup); diff --git a/frontend/src/Calendar/Legend/Legend.js b/frontend/src/Calendar/Legend/Legend.js index 10293ff1b..e5bf0c6b8 100644 --- a/frontend/src/Calendar/Legend/Legend.js +++ b/frontend/src/Calendar/Legend/Legend.js @@ -7,34 +7,11 @@ import styles from './Legend.css'; function Legend(props) { const { - showFinaleIcon, - showSpecialIcon, showCutoffUnmetIcon, colorImpairedMode } = props; const iconsToShow = []; - if (showFinaleIcon) { - iconsToShow.push( - - ); - } - - if (showSpecialIcon) { - iconsToShow.push( - - ); - } if (showCutoffUnmetIcon) { iconsToShow.push( @@ -51,8 +28,8 @@ function Legend(props) {
@@ -77,22 +54,10 @@ function Legend(props) { />
-
- - - {iconsToShow[0]} -
- { - iconsToShow.length > 1 && + iconsToShow.length > 0 &&
- {iconsToShow[1]} - {iconsToShow[2]} + {iconsToShow[0]}
}
@@ -100,8 +65,6 @@ function Legend(props) { } Legend.propTypes = { - showFinaleIcon: PropTypes.bool.isRequired, - showSpecialIcon: PropTypes.bool.isRequired, showCutoffUnmetIcon: PropTypes.bool.isRequired, colorImpairedMode: PropTypes.bool.isRequired }; diff --git a/frontend/src/Calendar/Legend/LegendItem.css b/frontend/src/Calendar/Legend/LegendItem.css index c71a6d916..ddf3e6a61 100644 --- a/frontend/src/Calendar/Legend/LegendItem.css +++ b/frontend/src/Calendar/Legend/LegendItem.css @@ -24,18 +24,10 @@ composes: unmonitored from '~Calendar/Events/CalendarEvent.css'; } -.onAir { - composes: onAir from '~Calendar/Events/CalendarEvent.css'; -} - .missing { composes: missing from '~Calendar/Events/CalendarEvent.css'; } -.premiere { - composes: premiere from '~Calendar/Events/CalendarEvent.css'; -} - -.unaired { - composes: unaired from '~Calendar/Events/CalendarEvent.css'; +.unreleased { + composes: unreleased from '~Calendar/Events/CalendarEvent.css'; } diff --git a/frontend/src/Calendar/Options/CalendarOptionsModalContent.js b/frontend/src/Calendar/Options/CalendarOptionsModalContent.js index 486b78d5d..b137865d7 100644 --- a/frontend/src/Calendar/Options/CalendarOptionsModalContent.js +++ b/frontend/src/Calendar/Options/CalendarOptionsModalContent.js @@ -203,8 +203,6 @@ class CalendarOptionsModalContent extends Component { CalendarOptionsModalContent.propTypes = { showMovieInformation: PropTypes.bool.isRequired, - showFinaleIcon: PropTypes.bool.isRequired, - showSpecialIcon: PropTypes.bool.isRequired, showCutoffUnmetIcon: PropTypes.bool.isRequired, firstDayOfWeek: PropTypes.number.isRequired, calendarWeekColumnHeader: PropTypes.string.isRequired, diff --git a/frontend/src/Calendar/getStatusStyle.js b/frontend/src/Calendar/getStatusStyle.js index 871cccd5b..5cf1ec577 100644 --- a/frontend/src/Calendar/getStatusStyle.js +++ b/frontend/src/Calendar/getStatusStyle.js @@ -20,7 +20,7 @@ function getStatusStyle(hasFile, downloading, startTime, isMonitored) { return 'missing'; } - return 'unaired'; + return 'unreleased'; } export default getStatusStyle; diff --git a/frontend/src/Calendar/iCal/CalendarLinkModalContent.js b/frontend/src/Calendar/iCal/CalendarLinkModalContent.js index 6233f2839..ea51f37cf 100644 --- a/frontend/src/Calendar/iCal/CalendarLinkModalContent.js +++ b/frontend/src/Calendar/iCal/CalendarLinkModalContent.js @@ -17,7 +17,6 @@ import ModalFooter from 'Components/Modal/ModalFooter'; function getUrls(state) { const { unmonitored, - premieresOnly, asAllDay, tags } = state; @@ -28,10 +27,6 @@ function getUrls(state) { icalUrl += 'unmonitored=true&'; } - if (premieresOnly) { - icalUrl += 'premieresOnly=true&'; - } - if (asAllDay) { icalUrl += 'asAllDay=true&'; } @@ -61,7 +56,6 @@ class CalendarLinkModalContent extends Component { const defaultState = { unmonitored: false, - premieresOnly: false, asAllDay: false, tags: [] }; @@ -105,7 +99,6 @@ class CalendarLinkModalContent extends Component { const { unmonitored, - premieresOnly, asAllDay, tags, iCalHttpUrl, @@ -132,18 +125,6 @@ class CalendarLinkModalContent extends Component { /> - - Season Premieres Only - - - - Show as All-Day Events diff --git a/src/Radarr.Api.V3/Calendar/CalendarModule.cs b/src/Radarr.Api.V3/Calendar/CalendarModule.cs index 2a43afaa2..c27f50b60 100644 --- a/src/Radarr.Api.V3/Calendar/CalendarModule.cs +++ b/src/Radarr.Api.V3/Calendar/CalendarModule.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Nancy; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Movies; using NzbDrone.SignalR; using Radarr.Api.V3.Movies; @@ -11,13 +12,16 @@ namespace Radarr.Api.V3.Calendar { public class CalendarModule : RadarrRestModuleWithSignalR { - protected readonly IMovieService _moviesService; + private readonly IMovieService _moviesService; + private readonly IUpgradableSpecification _qualityUpgradableSpecification; public CalendarModule(IBroadcastSignalRMessage signalR, - IMovieService moviesService) + IMovieService moviesService, + IUpgradableSpecification qualityUpgradableSpecification) : base(signalR, "calendar") { _moviesService = moviesService; + _qualityUpgradableSpecification = qualityUpgradableSpecification; GetResourceAll = GetCalendar; } @@ -59,7 +63,7 @@ namespace Radarr.Api.V3.Calendar return null; } - var resource = movie.ToResource(); + var resource = movie.ToResource(_qualityUpgradableSpecification); return resource; }