From 9ad6b3a61159b84b56dc80d97e085d8af75793d6 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Thu, 15 Aug 2024 23:34:56 +0300 Subject: [PATCH] New: Improve status label and progress bar style for deleted movies Closes #7127 --- .../AddNewMovie/AddNewMovieSearchResult.js | 1 + frontend/src/Calendar/Agenda/AgendaEvent.js | 4 +- frontend/src/Calendar/Events/CalendarEvent.js | 4 +- frontend/src/Calendar/getStatusStyle.js | 25 ++++++++++++ .../Overview/CollectionMovieLabel.js | 4 +- frontend/src/Components/InfoLabel.css | 2 +- frontend/src/Components/InfoLabel.css.d.ts | 2 +- frontend/src/Components/InfoLabel.js | 8 ++-- frontend/src/Components/ProgressBar.css | 12 ++++++ frontend/src/Components/ProgressBar.css.d.ts | 1 + frontend/src/Components/ProgressBar.js | 3 +- frontend/src/Movie/Details/MovieDetails.js | 22 +++++++---- .../src/Movie/Details/MovieStatusLabel.css | 6 +++ .../Movie/Details/MovieStatusLabel.css.d.ts | 1 + .../src/Movie/Details/MovieStatusLabel.js | 38 ++++++++++++------- .../ProgressBar/MovieIndexProgressBar.tsx | 22 ++++------- .../src/Utilities/Movie/getProgressBarKind.ts | 38 +++++++++++++++++++ .../src/Utilities/Movie/getStatusStyle.js | 27 ------------- src/NzbDrone.Core/Localization/Core/en.json | 1 + 19 files changed, 146 insertions(+), 75 deletions(-) create mode 100644 frontend/src/Calendar/getStatusStyle.js create mode 100644 frontend/src/Utilities/Movie/getProgressBarKind.ts delete mode 100644 frontend/src/Utilities/Movie/getStatusStyle.js diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js index e41df3dba..f07a55173 100644 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js @@ -285,6 +285,7 @@ class AddNewMovieSearchResult extends Component { { isExistingMovie && isSmallScreen && { diff --git a/frontend/src/Components/InfoLabel.css b/frontend/src/Components/InfoLabel.css index 6a2f5601b..7edc667c8 100644 --- a/frontend/src/Components/InfoLabel.css +++ b/frontend/src/Components/InfoLabel.css @@ -8,7 +8,7 @@ cursor: default; } -.title { +.name { margin-bottom: 2px; color: var(--helpTextColor); font-size: 10px; diff --git a/frontend/src/Components/InfoLabel.css.d.ts b/frontend/src/Components/InfoLabel.css.d.ts index d3c8040e8..b5664ee83 100644 --- a/frontend/src/Components/InfoLabel.css.d.ts +++ b/frontend/src/Components/InfoLabel.css.d.ts @@ -4,9 +4,9 @@ interface CssExports { 'label': string; 'large': string; 'medium': string; + 'name': string; 'outline': string; 'small': string; - 'title': string; } export const cssExports: CssExports; export default cssExports; diff --git a/frontend/src/Components/InfoLabel.js b/frontend/src/Components/InfoLabel.js index c2d0bbf9c..cdcdff377 100644 --- a/frontend/src/Components/InfoLabel.js +++ b/frontend/src/Components/InfoLabel.js @@ -7,7 +7,7 @@ import styles from './InfoLabel.css'; function InfoLabel(props) { const { className, - title, + name, kind, size, outline, @@ -25,8 +25,8 @@ function InfoLabel(props) { )} {...otherProps} > -
- {title} +
+ {name}
{children} @@ -37,7 +37,7 @@ function InfoLabel(props) { InfoLabel.propTypes = { className: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, kind: PropTypes.oneOf(kinds.all).isRequired, size: PropTypes.oneOf(sizes.all).isRequired, outline: PropTypes.bool.isRequired, diff --git a/frontend/src/Components/ProgressBar.css b/frontend/src/Components/ProgressBar.css index 716421fa9..a34628e71 100644 --- a/frontend/src/Components/ProgressBar.css +++ b/frontend/src/Components/ProgressBar.css @@ -21,6 +21,10 @@ background-color: var(--darkGray); } + &.inverse { + background-color: var(--inverseLabelColor); + } + &.primary { background-color: var(--primaryColor); } @@ -61,10 +65,18 @@ .frontTextContainer { z-index: 1; color: var(--progressBarFrontTextColor); + + &.inverse { + color: var(--inverseLabelTextColor); + } } .backTextContainer { color: var(--progressBarBackTextColor); + + &.inverse { + color: var(--inverseLabelTextColor); + } } .backTextContainer, diff --git a/frontend/src/Components/ProgressBar.css.d.ts b/frontend/src/Components/ProgressBar.css.d.ts index c63ee42e1..571e862f0 100644 --- a/frontend/src/Components/ProgressBar.css.d.ts +++ b/frontend/src/Components/ProgressBar.css.d.ts @@ -9,6 +9,7 @@ interface CssExports { 'frontText': string; 'frontTextContainer': string; 'info': string; + 'inverse': string; 'large': string; 'medium': string; 'primary': string; diff --git a/frontend/src/Components/ProgressBar.js b/frontend/src/Components/ProgressBar.js index 0cf04da46..171b4c0fa 100644 --- a/frontend/src/Components/ProgressBar.js +++ b/frontend/src/Components/ProgressBar.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { ColorImpairedConsumer } from 'App/ColorImpairedContext'; import { kinds, sizes } from 'Helpers/Props'; +import translate from 'Utilities/String/translate'; import styles from './ProgressBar.css'; function ProgressBar(props) { @@ -57,7 +58,7 @@ function ProgressBar(props) { enableColorImpairedMode && 'colorImpaired' )} role="meter" - aria-label={`Progress Bar at ${progress.toFixed(0)}%`} + aria-label={translate('ProgressBarProgress', { progress: progress.toFixed(0) })} aria-valuenow={progress.toFixed(0)} aria-valuemin="0" aria-valuemax="100" diff --git a/frontend/src/Movie/Details/MovieDetails.js b/frontend/src/Movie/Details/MovieDetails.js index 57e1fcc47..aa0134ad3 100644 --- a/frontend/src/Movie/Details/MovieDetails.js +++ b/frontend/src/Movie/Details/MovieDetails.js @@ -24,6 +24,7 @@ import { icons, kinds, sizes, tooltipPositions } from 'Helpers/Props'; import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal'; import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal'; import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector'; +import getMovieStatusDetails from 'Movie/getMovieStatusDetails'; import MovieHistoryModal from 'Movie/History/MovieHistoryModal'; import MoviePoster from 'Movie/MoviePoster'; import MovieInteractiveSearchModalConnector from 'Movie/Search/MovieInteractiveSearchModalConnector'; @@ -246,6 +247,7 @@ class MovieDetails extends Component { genres, collection, overview, + status, youTubeTrailerId, isAvailable, images, @@ -283,6 +285,8 @@ class MovieDetails extends Component { titleWidth } = this.state; + const statusDetails = getMovieStatusDetails(status); + const fanartUrl = getFanartUrl(images); const marqueeWidth = isSmallScreen ? titleWidth : (titleWidth - 150); @@ -524,7 +528,7 @@ class MovieDetails extends Component {
@@ -534,12 +538,14 @@ class MovieDetails extends Component { @@ -564,7 +570,7 @@ class MovieDetails extends Component { @@ -576,7 +582,7 @@ class MovieDetails extends Component { collection ?
@@ -592,7 +598,7 @@ class MovieDetails extends Component { originalLanguage?.name && !isSmallScreen ? @@ -606,7 +612,7 @@ class MovieDetails extends Component { studio && !isSmallScreen ? @@ -620,7 +626,7 @@ class MovieDetails extends Component { genres.length && !isSmallScreen ? diff --git a/frontend/src/Movie/Details/MovieStatusLabel.css b/frontend/src/Movie/Details/MovieStatusLabel.css index b4a4f8891..d22bdcdba 100644 --- a/frontend/src/Movie/Details/MovieStatusLabel.css +++ b/frontend/src/Movie/Details/MovieStatusLabel.css @@ -27,3 +27,9 @@ padding-left: 2px; border-left: 4px solid var(--warningColor); } + +.deleted { + padding-left: 2px; + border-left: 4px solid var(--inverseLabelColor); + color: var(--dangerColor); +} diff --git a/frontend/src/Movie/Details/MovieStatusLabel.css.d.ts b/frontend/src/Movie/Details/MovieStatusLabel.css.d.ts index 170e0aa1d..36aa5e7d6 100644 --- a/frontend/src/Movie/Details/MovieStatusLabel.css.d.ts +++ b/frontend/src/Movie/Details/MovieStatusLabel.css.d.ts @@ -3,6 +3,7 @@ interface CssExports { 'availNotMonitored': string; 'continuing': string; + 'deleted': string; 'ended': string; 'missingMonitored': string; 'missingUnmonitored': string; diff --git a/frontend/src/Movie/Details/MovieStatusLabel.js b/frontend/src/Movie/Details/MovieStatusLabel.js index 5534c5603..cde6f1a77 100644 --- a/frontend/src/Movie/Details/MovieStatusLabel.js +++ b/frontend/src/Movie/Details/MovieStatusLabel.js @@ -7,7 +7,7 @@ import firstCharToUpper from 'Utilities/String/firstCharToUpper'; import translate from 'Utilities/String/translate'; import styles from './MovieStatusLabel.css'; -function getMovieStatus(hasFile, isMonitored, isAvailable, queueItem = false) { +function getMovieStatus(status, hasFile, isMonitored, isAvailable, queueItem = false) { if (queueItem) { const queueStatus = queueItem.status; const queueState = queueItem.trackedDownloadStatus; @@ -26,6 +26,10 @@ function getMovieStatus(hasFile, isMonitored, isAvailable, queueItem = false) { return 'ended'; } + if (status === 'deleted') { + return 'deleted'; + } + if (isAvailable && !isMonitored && !hasFile) { return 'missingUnmonitored'; } @@ -39,6 +43,7 @@ function getMovieStatus(hasFile, isMonitored, isAvailable, queueItem = false) { function MovieStatusLabel(props) { const { + status, hasMovieFiles, monitored, isAvailable, @@ -47,17 +52,15 @@ function MovieStatusLabel(props) { colorImpairedMode } = props; - let status = getMovieStatus(hasMovieFiles, monitored, isAvailable, queueItem); - let statusClass = status; + let movieStatus = getMovieStatus(status, hasMovieFiles, monitored, isAvailable, queueItem); + let statusClass = movieStatus; - if (status === 'availNotMonitored' || status === 'ended') { - status = 'downloaded'; - } - if (status === 'missingMonitored' || status === 'missingUnmonitored') { - status = 'missing'; - } - if (status === 'continuing') { - status = 'notAvailable'; + if (movieStatus === 'availNotMonitored' || movieStatus === 'ended') { + movieStatus = 'downloaded'; + } else if (movieStatus === 'missingMonitored' || movieStatus === 'missingUnmonitored') { + movieStatus = 'missing'; + } else if (movieStatus === 'continuing') { + movieStatus = 'notAvailable'; } if (queueItem) { @@ -83,6 +86,9 @@ function MovieStatusLabel(props) { case 'missingUnmonitored': kind = kinds.WARNING; break; + case 'deleted': + kind = kinds.INVERSE; + break; default: } @@ -92,7 +98,7 @@ function MovieStatusLabel(props) { size={sizes.LARGE} colorImpairedMode={colorImpairedMode} > - {translate(firstCharToUpper(status))} + {translate(firstCharToUpper(movieStatus))} ); } @@ -101,12 +107,13 @@ function MovieStatusLabel(props) { - {translate(firstCharToUpper(status))} + {translate(firstCharToUpper(movieStatus))} ); } MovieStatusLabel.propTypes = { + status: PropTypes.string.isRequired, hasMovieFiles: PropTypes.bool.isRequired, monitored: PropTypes.bool.isRequired, isAvailable: PropTypes.bool.isRequired, @@ -115,4 +122,9 @@ MovieStatusLabel.propTypes = { colorImpairedMode: PropTypes.bool }; +MovieStatusLabel.defaultProps = { + useLabel: false, + colorImpairedMode: false +}; + export default MovieStatusLabel; diff --git a/frontend/src/Movie/Index/ProgressBar/MovieIndexProgressBar.tsx b/frontend/src/Movie/Index/ProgressBar/MovieIndexProgressBar.tsx index d22ed8ed0..a3af8040f 100644 --- a/frontend/src/Movie/Index/ProgressBar/MovieIndexProgressBar.tsx +++ b/frontend/src/Movie/Index/ProgressBar/MovieIndexProgressBar.tsx @@ -5,8 +5,9 @@ import { sizes } from 'Helpers/Props'; import createMovieQueueItemsDetailsSelector, { MovieQueueDetails, } from 'Movie/Index/createMovieQueueDetailsSelector'; +import { MovieStatus } from 'Movie/Movie'; import { MovieFile } from 'MovieFile/MovieFile'; -import getStatusStyle from 'Utilities/Movie/getStatusStyle'; +import getProgressBarKind from 'Utilities/Movie/getProgressBarKind'; import translate from 'Utilities/String/translate'; import styles from './MovieIndexProgressBar.css'; @@ -14,7 +15,7 @@ interface MovieIndexProgressBarProps { movieId: number; movieFile: MovieFile; monitored: boolean; - status: string; + status: MovieStatus; hasFile: boolean; isAvailable: boolean; width: number; @@ -44,20 +45,14 @@ function MovieIndexProgressBar(props: MovieIndexProgressBarProps) { const progress = 100; const queueStatusText = queueDetails.count > 0 ? translate('Downloading') : null; - let movieStatus = status === 'released' && hasFile ? 'downloaded' : status; - if (movieStatus === 'deleted') { - movieStatus = translate('Missing'); - - if (hasFile) { - movieStatus = movieFile?.quality?.quality.name ?? translate('Downloaded'); - } - } else if (hasFile) { + let movieStatus = translate('NotAvailable'); + if (hasFile) { movieStatus = movieFile?.quality?.quality.name ?? translate('Downloaded'); + } else if (status === 'deleted') { + movieStatus = translate('Deleted'); } else if (isAvailable && !hasFile) { movieStatus = translate('Missing'); - } else { - movieStatus = translate('NotAvailable'); } const attachedClassName = bottomRadius @@ -70,12 +65,11 @@ function MovieIndexProgressBar(props: MovieIndexProgressBarProps) { className={styles.progressBar} containerClassName={containerClassName} progress={progress} - kind={getStatusStyle( + kind={getProgressBarKind( status, monitored, hasFile, isAvailable, - 'kinds', queueDetails.count > 0 )} size={detailedProgressBar ? sizes.MEDIUM : sizes.SMALL} diff --git a/frontend/src/Utilities/Movie/getProgressBarKind.ts b/frontend/src/Utilities/Movie/getProgressBarKind.ts new file mode 100644 index 000000000..819c119d4 --- /dev/null +++ b/frontend/src/Utilities/Movie/getProgressBarKind.ts @@ -0,0 +1,38 @@ +import { kinds } from 'Helpers/Props'; +import { MovieStatus } from 'Movie/Movie'; + +function getProgressBarKind( + status: MovieStatus, + monitored: boolean, + hasFile: boolean, + isAvailable: boolean, + isDownloading: boolean = false +) { + if (isDownloading) { + return kinds.PURPLE; + } + + if (hasFile && monitored) { + return kinds.SUCCESS; + } + + if (hasFile && !monitored) { + return kinds.DEFAULT; + } + + if (status === 'deleted') { + return kinds.INVERSE; + } + + if (isAvailable && monitored) { + return kinds.DANGER; + } + + if (!monitored) { + return kinds.WARNING; + } + + return kinds.PRIMARY; +} + +export default getProgressBarKind; diff --git a/frontend/src/Utilities/Movie/getStatusStyle.js b/frontend/src/Utilities/Movie/getStatusStyle.js deleted file mode 100644 index 7a92c4e87..000000000 --- a/frontend/src/Utilities/Movie/getStatusStyle.js +++ /dev/null @@ -1,27 +0,0 @@ -import { kinds } from 'Helpers/Props'; - -function getStatusStyle(status, monitored, hasFile, isAvailable, returnType, queue = false) { - if (queue) { - return returnType === 'kinds' ? kinds.QUEUE : 'queue'; - } - - if (hasFile && monitored) { - return returnType === 'kinds' ? kinds.SUCCESS : 'downloaded'; - } - - if (hasFile && !monitored) { - return returnType === 'kinds' ? kinds.DEFAULT : 'unmonitored'; - } - - if (isAvailable && monitored) { - return returnType === 'kinds' ? kinds.DANGER : 'missingMonitored'; - } - - if (!monitored) { - return returnType === 'kinds' ? kinds.WARNING : 'missingUnmonitored'; - } - - return returnType === 'kinds' ? kinds.PRIMARY : 'continuing'; -} - -export default getStatusStyle; diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index a9634b1a4..584de3460 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -1306,6 +1306,7 @@ "Profiles": "Profiles", "ProfilesSettingsSummary": "Quality, Language, Delay and Release profiles", "Progress": "Progress", + "ProgressBarProgress": "Progress Bar at {progress}%", "Proper": "Proper", "Protocol": "Protocol", "ProtocolHelpText": "Choose which protocol(s) to use and which one is preferred when choosing between otherwise equal releases",