From 51f99a2e7b0ba472ca0c0f1180c64c2823ceffaf Mon Sep 17 00:00:00 2001 From: sct Date: Sat, 19 Dec 2020 01:24:50 +0900 Subject: [PATCH 01/14] ci: add missing build-args back into ci workflow --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03a03c2f1..8f96b3b34 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,6 +52,8 @@ jobs: context: . file: ./Dockerfile push: true + build-args: | + COMMIT_TAG=${{ github.sha }} tags: | sctx/overseerr:develop sctx/overseerr:${{ github.sha }} From 549567a7e9db01933546d9970fc06f17218dfab1 Mon Sep 17 00:00:00 2001 From: Brandon Cohen Date: Fri, 18 Dec 2020 11:55:11 -0500 Subject: [PATCH 02/14] fix(frontend): changed request block for slideover on mobile UI (#387) --- src/components/RequestBlock/index.tsx | 63 ++++++++++++++++----------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/src/components/RequestBlock/index.tsx b/src/components/RequestBlock/index.tsx index b10909eb3..06122ae3f 100644 --- a/src/components/RequestBlock/index.tsx +++ b/src/components/RequestBlock/index.tsx @@ -43,26 +43,30 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => { return (
-
+
-
- - - - {request.requestedBy.username} +
+
+ + + + + {request.requestedBy.username} + +
{request.modifiedBy && ( - <> +
= ({ request, onUpdate }) => { clipRule="evenodd" /> - {request.modifiedBy?.username} - + + {request.modifiedBy?.username} + +
)}
@@ -189,13 +195,18 @@ const RequestBlock: React.FC = ({ request, onUpdate }) => {
{(request.seasons ?? []).length > 0 && ( -
- {intl.formatMessage(messages.seasons)} - {request.seasons.map((season) => ( - - {season.seasonNumber} - - ))} +
+
{intl.formatMessage(messages.seasons)}
+
+ {request.seasons.map((season) => ( + + {season.seasonNumber} + + ))} +
)}
From ed49e7c28e138988221d727d2e77289edfbedf4a Mon Sep 17 00:00:00 2001 From: sct Date: Sat, 19 Dec 2020 01:55:23 +0900 Subject: [PATCH 03/14] docs: add FUNDING.yml --- .github/FUNDING.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..9d966899f --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: [sct] +patreon: overseerr From 8408e19568b2f239c57e11e2946c75f193d1c22e Mon Sep 17 00:00:00 2001 From: "Weblate (bot)" Date: Fri, 18 Dec 2020 18:01:47 +0100 Subject: [PATCH 04/14] feat(lang): translations update from Weblate (#380) * feat(lang): translated using Weblate (Italian) Currently translated at 2.0% (7 of 350 strings) feat(lang): added translation using Weblate (Italian) Co-authored-by: Hosted Weblate Co-authored-by: Simone Chiavaccini Co-authored-by: sct Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/it/ Translation: Overseerr/Overseerr Frontend * feat(lang): translated using Weblate (Spanish) Currently translated at 100.0% (340 of 340 strings) Co-authored-by: Hosted Weblate Co-authored-by: Shutruk Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/es/ Translation: Overseerr/Overseerr Frontend * feat(lang): translated using Weblate (German) Currently translated at 100.0% (340 of 340 strings) Co-authored-by: Hosted Weblate Co-authored-by: J. Lavoie Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/de/ Translation: Overseerr/Overseerr Frontend * feat(lang): translated using Weblate (French) Currently translated at 100.0% (340 of 340 strings) Co-authored-by: Hosted Weblate Co-authored-by: J. Lavoie Translate-URL: https://hosted.weblate.org/projects/overseerr/overseerr-frontend/fr/ Translation: Overseerr/Overseerr Frontend Co-authored-by: Simone Chiavaccini Co-authored-by: sct Co-authored-by: Shutruk Co-authored-by: J. Lavoie --- src/i18n/locale/de.json | 19 ++++++++++++++++++- src/i18n/locale/es.json | 19 ++++++++++++++++++- src/i18n/locale/fr.json | 19 ++++++++++++++++++- src/i18n/locale/it.json | 9 +++++++++ 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 src/i18n/locale/it.json diff --git a/src/i18n/locale/de.json b/src/i18n/locale/de.json index bd662375c..52f2318a4 100644 --- a/src/i18n/locale/de.json +++ b/src/i18n/locale/de.json @@ -321,5 +321,22 @@ "components.Settings.SettingsAbout.clickheretojoindiscord": "Klicken Sie hier, um unserem Discord-Server beizutreten.", "components.Settings.RadarrModal.validationNameRequired": "Sie müssen einen Servernamen angeben", "components.Setup.tip": "Tipp", - "components.Setup.syncingbackground": "Die Synchronisierung wird im Hintergrund ausgeführt. Sie können die Konfiguration in der Zwischenzeit fortsetzen." + "components.Setup.syncingbackground": "Die Synchronisierung wird im Hintergrund ausgeführt. Sie können die Konfiguration in der Zwischenzeit fortsetzen.", + "i18n.deleting": "Löschen …", + "components.UserList.userdeleteerror": "Beim Löschen des Benutzers ist ein Fehler aufgetreten", + "components.UserList.userdeleted": "Benutzer gelöscht", + "components.UserList.deleteuser": "Benutzer löschen", + "components.UserList.deleteconfirm": "Wollen Sie diesen Benutzer wirklich löschen? Alle vorhandenen Anforderungsdaten dieses Benutzers werden entfernt.", + "components.Settings.nodefaultdescription": "Mindestens ein Server muss als Standard markiert sein, bevor Anforderungen an Ihre Dienste weitergeleitet werden.", + "components.Settings.nodefault": "Kein Standardserver ausgewählt!", + "components.Settings.no4kimplemented": "(Standard-4K-Server sind derzeit nicht implementiert.)", + "components.Settings.SonarrModal.testFirstRootFolders": "Testen Sie Ihre Verbindung, um Stammordner zu laden", + "components.Settings.SonarrModal.testFirstQualityProfiles": "Testen Sie Ihre Verbindung, um Qualitätsprofile zu laden", + "components.Settings.SonarrModal.loadingrootfolders": "Laden von Stammordnern…", + "components.Settings.SonarrModal.loadingprofiles": "Qualitätsprofile werden geladen…", + "components.Settings.RadarrModal.validationMinimumAvailabilityRequired": "Sie müssen die Mindestverfügbarkeit auswählen", + "components.Settings.RadarrModal.testFirstRootFolders": "Testen Sie Ihre Verbindung, um Stammordner zu laden", + "components.Settings.RadarrModal.testFirstQualityProfiles": "Testen Sie Ihre Verbindung zu Lastqualitätsprofilen", + "components.Settings.RadarrModal.loadingrootfolders": "Laden von Stammordnern…", + "components.Settings.RadarrModal.loadingprofiles": "Qualitätsprofile werden geladen…" } diff --git a/src/i18n/locale/es.json b/src/i18n/locale/es.json index c76732702..7ed562040 100644 --- a/src/i18n/locale/es.json +++ b/src/i18n/locale/es.json @@ -321,5 +321,22 @@ "components.Settings.applicationurl": "URL de la aplicación", "components.Settings.apikey": "Clave API", "components.Setup.tip": "Consejo", - "components.Setup.syncingbackground": "La sincronización se ejecutará en segundo plano. Mientras tanto, puede continuar con el proceso de configuración." + "components.Setup.syncingbackground": "La sincronización se ejecutará en segundo plano. Mientras tanto, puede continuar con el proceso de configuración.", + "i18n.deleting": "Eliminando…", + "components.UserList.userdeleteerror": "Algo salió mal al eliminar al usuario", + "components.UserList.userdeleted": "Usuario eliminado", + "components.UserList.deleteuser": "Eliminar usuario", + "components.UserList.deleteconfirm": "¿Está seguro de que desea eliminar este usuario? Se eliminarán todas las solicitudes existentes de este usuario.", + "components.Settings.nodefaultdescription": "Al menos un servidor debe estar marcado como predeterminado antes de que cualquier solicitud llegue a sus servicios.", + "components.Settings.nodefault": "¡Ningún servidor predeterminado seleccionado!", + "components.Settings.no4kimplemented": "(Los servidores 4K predeterminados no están implementados actualmente)", + "components.Settings.SonarrModal.testFirstRootFolders": "Prueba la conexión para cargar carpetas raíz", + "components.Settings.SonarrModal.testFirstQualityProfiles": "Prueba la conexión para cargar perfiles de calidad", + "components.Settings.SonarrModal.loadingrootfolders": "Cargando carpetas raíz…", + "components.Settings.SonarrModal.loadingprofiles": "Cargando perfiles de calidad…", + "components.Settings.RadarrModal.validationMinimumAvailabilityRequired": "Debes seleccionar disponibilidad mínima", + "components.Settings.RadarrModal.testFirstRootFolders": "Prueba la conexión para cargar carpetas raíz", + "components.Settings.RadarrModal.testFirstQualityProfiles": "Prueba la conexión para cargar perfiles de calidad", + "components.Settings.RadarrModal.loadingrootfolders": "Cargando carpetas raíz…", + "components.Settings.RadarrModal.loadingprofiles": "Cargando perfiles de calidad…" } diff --git a/src/i18n/locale/fr.json b/src/i18n/locale/fr.json index 266bb8830..8295831f5 100644 --- a/src/i18n/locale/fr.json +++ b/src/i18n/locale/fr.json @@ -321,5 +321,22 @@ "components.Settings.SettingsAbout.clickheretojoindiscord": "Cliquez ici pour rejoindre notre serveur Discord.", "components.Settings.RadarrModal.validationNameRequired": "Vous devez fournir un nom de serveur", "components.Setup.tip": "Astuce", - "components.Setup.syncingbackground": "La synchronisation s'exécutera en arrière-plan. Vous pouvez continuer le processus de configuration en attendant." + "components.Setup.syncingbackground": "La synchronisation s'exécutera en arrière-plan. Vous pouvez continuer le processus de configuration en attendant.", + "i18n.deleting": "Suppression…", + "components.UserList.userdeleteerror": "Une erreur s'est produite lors de la suppression de l'utilisateur", + "components.UserList.userdeleted": "Utilisateur supprimé", + "components.UserList.deleteuser": "Supprimer l'utilisateur", + "components.UserList.deleteconfirm": "Voulez-vous vraiment supprimer cet utilisateur ? Toutes les données de demande existantes de cet utilisateur seront supprimées.", + "components.Settings.nodefaultdescription": "Au moins un serveur doit être marqué par défaut avant que toute demande parvienne à vos services.", + "components.Settings.nodefault": "Aucun serveur par défaut sélectionné !", + "components.Settings.no4kimplemented": "(Les serveurs 4K par défaut ne sont actuellement pas implémentés)", + "components.Settings.SonarrModal.testFirstRootFolders": "Testez votre connexion pour charger les dossiers racine", + "components.Settings.SonarrModal.testFirstQualityProfiles": "Testez votre connexion pour charger des profils qualité", + "components.Settings.SonarrModal.loadingrootfolders": "Chargement des dossiers racine…", + "components.Settings.SonarrModal.loadingprofiles": "Chargement des profils qualité…", + "components.Settings.RadarrModal.validationMinimumAvailabilityRequired": "Vous devez sélectionner une disponibilité minimale", + "components.Settings.RadarrModal.testFirstRootFolders": "Testez votre connexion pour charger les dossiers racine", + "components.Settings.RadarrModal.testFirstQualityProfiles": "Testez votre connexion pour charger des profils qualité", + "components.Settings.RadarrModal.loadingrootfolders": "Chargement des dossiers racine…", + "components.Settings.RadarrModal.loadingprofiles": "Chargement des profils qualité…" } diff --git a/src/i18n/locale/it.json b/src/i18n/locale/it.json new file mode 100644 index 000000000..aafa03028 --- /dev/null +++ b/src/i18n/locale/it.json @@ -0,0 +1,9 @@ +{ + "components.Discover.recentrequests": "Richieste Recenti", + "components.Discover.recentlyAdded": "Aggiunti di Recente", + "components.Discover.populartv": "Serie Popolari", + "components.Discover.popularmovies": "Film Popolari", + "components.Discover.nopending": "Nessuna richiesta in sospeso", + "components.Discover.discovertv": "Serie Popolari", + "components.Discover.discovermovies": "Film Popolari" +} From a0024a0cbe717d78f53413bb78644c829f143c4d Mon Sep 17 00:00:00 2001 From: sct Date: Sat, 19 Dec 2020 02:46:32 +0900 Subject: [PATCH 05/14] feat(frontend): add external links to movie and tv detail pages --- src/assets/services/imdb.svg | 3 ++ src/assets/services/rt.svg | 1 + src/assets/services/tmdb.svg | 1 + src/components/ExternalLinkBlock/index.tsx | 55 ++++++++++++++++++++++ src/components/MovieDetails/index.tsx | 9 ++++ src/components/TvDetails/index.tsx | 9 ++++ tailwind.config.js | 2 +- 7 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/assets/services/imdb.svg create mode 100644 src/assets/services/rt.svg create mode 100644 src/assets/services/tmdb.svg create mode 100644 src/components/ExternalLinkBlock/index.tsx diff --git a/src/assets/services/imdb.svg b/src/assets/services/imdb.svg new file mode 100644 index 000000000..b99f43a1a --- /dev/null +++ b/src/assets/services/imdb.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/services/rt.svg b/src/assets/services/rt.svg new file mode 100644 index 000000000..6783b157b --- /dev/null +++ b/src/assets/services/rt.svg @@ -0,0 +1 @@ + diff --git a/src/assets/services/tmdb.svg b/src/assets/services/tmdb.svg new file mode 100644 index 000000000..62a660554 --- /dev/null +++ b/src/assets/services/tmdb.svg @@ -0,0 +1 @@ +Asset 4 \ No newline at end of file diff --git a/src/components/ExternalLinkBlock/index.tsx b/src/components/ExternalLinkBlock/index.tsx new file mode 100644 index 000000000..cc042fef9 --- /dev/null +++ b/src/components/ExternalLinkBlock/index.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import TmdbLogo from '../../assets/services/tmdb.svg'; +import ImdbLogo from '../../assets/services/imdb.svg'; +import RTLogo from '../../assets/services/rt.svg'; + +interface ExternalLinkBlockProps { + mediaType: 'movie' | 'tv'; + imdbId?: string; + tmdbId?: number; + rtUrl?: string; +} + +const ExternalLinkBlock: React.FC = ({ + imdbId, + tmdbId, + rtUrl, + mediaType, +}) => { + return ( +
+ {tmdbId && ( + + + + )} + {imdbId && ( + + + + )} + {rtUrl && ( + + + + )} +
+ ); +}; + +export default ExternalLinkBlock; diff --git a/src/components/MovieDetails/index.tsx b/src/components/MovieDetails/index.tsx index f11fb2b7a..9e2f967e8 100644 --- a/src/components/MovieDetails/index.tsx +++ b/src/components/MovieDetails/index.tsx @@ -37,6 +37,7 @@ import type { RTRating } from '../../../server/api/rottentomatoes'; import Error from '../../pages/_error'; import Head from 'next/head'; import globalMessages from '../../i18n/globalMessages'; +import ExternalLinkBlock from '../ExternalLinkBlock'; const messages = defineMessages({ releasedate: 'Release Date', @@ -512,6 +513,14 @@ const MovieDetails: React.FC = ({ movie }) => {
)}
+
+ +
diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index d0f8d8844..c75029ce4 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -29,6 +29,7 @@ import type { RTRating } from '../../../server/api/rottentomatoes'; import Head from 'next/head'; import globalMessages from '../../i18n/globalMessages'; import { ANIME_KEYWORD_ID } from '../../../server/api/themoviedb'; +import ExternalLinkBlock from '../ExternalLinkBlock'; const messages = defineMessages({ userrating: 'User Rating', @@ -482,6 +483,14 @@ const TvDetails: React.FC = ({ tv }) => {
)} +
+ +
diff --git a/tailwind.config.js b/tailwind.config.js index 0f721fc75..9793abc8d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -15,7 +15,7 @@ module.exports = { borderWidth: ['first', 'last'], margin: ['first', 'last', 'responsive'], boxShadow: ['group-focus'], - opacity: ['disabled'], + opacity: ['disabled', 'hover'], }, plugins: [ require('@tailwindcss/forms'), From fe468952894e84894827d25e3fa2eefd2c039b97 Mon Sep 17 00:00:00 2001 From: sct Date: Sat, 19 Dec 2020 03:09:42 +0900 Subject: [PATCH 06/14] ci: add @semantic-release/github step to publish array --- package.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f6f3d9b3d..06702c3af 100644 --- a/package.json +++ b/package.json @@ -172,7 +172,12 @@ } ], "semantic-release-docker", - "@semantic-release/github" + [ + "@semantic-release/github", + { + "addReleases": "top" + } + ] ], "branches": [ "master" @@ -182,7 +187,8 @@ { "path": "semantic-release-docker", "name": "sctx/overseerr" - } + }, + "@semantic-release/github" ] } } From 53bede692d4f0e940dededa63015fe1908129914 Mon Sep 17 00:00:00 2001 From: sct Date: Sat, 19 Dec 2020 11:32:17 +0900 Subject: [PATCH 07/14] feat: add missing tzdata package to image re #394 --- Dockerfile | 2 ++ overseerr-api.yml | 4 ++++ server/interfaces/api/settingsInterfaces.ts | 1 + server/routes/settings.ts | 4 +++- src/components/Settings/SettingsAbout/index.tsx | 6 ++++++ 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1afedf3d9..48bd94d42 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,8 @@ FROM node:12.18-alpine ARG COMMIT_TAG ENV COMMIT_TAG=${COMMIT_TAG} +RUN apk add tzdata + COPY . /app WORKDIR /app diff --git a/overseerr-api.yml b/overseerr-api.yml index d84ac3fac..209017974 100644 --- a/overseerr-api.yml +++ b/overseerr-api.yml @@ -1542,6 +1542,10 @@ paths: totalMediaItems: type: number example: 100 + tz: + type: string + nullable: true + example: Asia/Tokyo /auth/me: get: summary: Returns the currently logged in user diff --git a/server/interfaces/api/settingsInterfaces.ts b/server/interfaces/api/settingsInterfaces.ts index bc6dcf024..2938e6967 100644 --- a/server/interfaces/api/settingsInterfaces.ts +++ b/server/interfaces/api/settingsInterfaces.ts @@ -2,4 +2,5 @@ export interface SettingsAboutResponse { version: string; totalRequests: number; totalMediaItems: number; + tz?: string; } diff --git a/server/routes/settings.ts b/server/routes/settings.ts index f90ae9b62..8f72e588a 100644 --- a/server/routes/settings.ts +++ b/server/routes/settings.ts @@ -20,6 +20,7 @@ import { merge } from 'lodash'; import Media from '../entity/Media'; import { MediaRequest } from '../entity/MediaRequest'; import { getAppVersion } from '../utils/appVersion'; +import { SettingsAboutResponse } from '../interfaces/api/settingsInterfaces'; const settingsRoutes = Router(); @@ -473,7 +474,8 @@ settingsRoutes.get('/about', async (req, res) => { version: getAppVersion(), totalMediaItems, totalRequests, - }); + tz: process.env.TZ, + } as SettingsAboutResponse); }); export default settingsRoutes; diff --git a/src/components/Settings/SettingsAbout/index.tsx b/src/components/Settings/SettingsAbout/index.tsx index 7925e1935..958951ffe 100644 --- a/src/components/Settings/SettingsAbout/index.tsx +++ b/src/components/Settings/SettingsAbout/index.tsx @@ -14,6 +14,7 @@ const messages = defineMessages({ gettingsupport: 'Getting Support', githubdiscussions: 'GitHub Discussions', clickheretojoindiscord: 'Click here to join our Discord server.', + timezone: 'Timezone', }); const SettingsAbout: React.FC = () => { @@ -47,6 +48,11 @@ const SettingsAbout: React.FC = () => { + {data.tz && ( + + {data.tz} + + )}
From 3601d442db32d3f98f7b050365c11ea8ef9bc4ae Mon Sep 17 00:00:00 2001 From: sct Date: Sat, 19 Dec 2020 12:57:17 +0900 Subject: [PATCH 08/14] fix(frontend): adjust padding of search box so placeholder text fits on mobile this only fixes English. Other languages placeholders may or may not fit into the space fixes #393 --- src/components/Layout/LanguagePicker/index.tsx | 2 +- src/components/Layout/SearchInput/index.tsx | 2 +- src/components/Layout/index.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Layout/LanguagePicker/index.tsx b/src/components/Layout/LanguagePicker/index.tsx index 13f66de8e..2c82397d6 100644 --- a/src/components/Layout/LanguagePicker/index.tsx +++ b/src/components/Layout/LanguagePicker/index.tsx @@ -58,7 +58,7 @@ const LanguagePicker: React.FC = () => { useClickOutside(dropdownRef, () => setDropdownOpen(false)); return ( -
+
{
-
+
From 2a4dd52275007e48f946c3b9e29f1d78da57bdaa Mon Sep 17 00:00:00 2001 From: sct Date: Sat, 19 Dec 2020 13:16:58 +0900 Subject: [PATCH 09/14] fix(frontend): hide Request More button if all current seasons are available fixes #343 --- server/api/rottentomatoes.ts | 12 ++- server/routes/tv.ts | 2 +- src/components/TvDetails/index.tsx | 144 +++++++++++++++-------------- 3 files changed, 86 insertions(+), 72 deletions(-) diff --git a/server/api/rottentomatoes.ts b/server/api/rottentomatoes.ts index c75f203bf..7c1c5985b 100644 --- a/server/api/rottentomatoes.ts +++ b/server/api/rottentomatoes.ts @@ -116,7 +116,7 @@ class RottenTomatoes { public async getTVRatings( name: string, - year: number + year?: number ): Promise { try { const response = await this.axios.get( @@ -126,9 +126,13 @@ class RottenTomatoes { } ); - const tvshow = response.data.tvSeries.find( - (series) => series.startYear === year - ); + let tvshow: RTTvSearchResult | undefined = response.data.tvSeries[0]; + + if (year) { + tvshow = response.data.tvSeries.find( + (series) => series.startYear === year + ); + } if (!tvshow) { return null; diff --git a/server/routes/tv.ts b/server/routes/tv.ts index 7e8b06257..be3915b03 100644 --- a/server/routes/tv.ts +++ b/server/routes/tv.ts @@ -106,7 +106,7 @@ tvRoutes.get('/:id/ratings', async (req, res, next) => { const rtratings = await rtapi.getTVRatings( tv.name, - Number(tv.first_air_date.slice(0, 4)) + tv.first_air_date ? Number(tv.first_air_date.slice(0, 4)) : undefined ); if (!rtratings) { diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index c75029ce4..7da4771c2 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -138,6 +138,14 @@ const TvDetails: React.FC = ({ tv }) => { } }; + const isComplete = + data.seasons.filter((season) => season.seasonNumber !== 0).length <= + ( + data.mediaInfo?.seasons.filter( + (season) => season.status === MediaStatus.AVAILABLE + ) ?? [] + ).length; + return (
= ({ tv }) => { )} - {data.mediaInfo && data.mediaInfo.status !== MediaStatus.UNKNOWN && ( - - - - } - text={ - <> + {data.mediaInfo && + data.mediaInfo.status !== MediaStatus.UNKNOWN && + !isComplete && ( + - - - } - onClick={() => setShowRequestModal(true)} - > - {hasPermission(Permission.MANAGE_REQUESTS) && - activeRequests && - activeRequests.length > 0 && ( + } + text={ <> - modifyRequests('approve')} + - + + + + } + onClick={() => setShowRequestModal(true)} + > + {hasPermission(Permission.MANAGE_REQUESTS) && + activeRequests && + activeRequests.length > 0 && ( + <> + modifyRequests('approve')} > - + + + - - - - modifyRequests('decline')} - > - + modifyRequests('decline')} > - + + + - - - - - )} - - )} + + + )} + + )} {hasPermission(Permission.MANAGE_REQUESTS) && (