From 43a0e75acfa2db113d8e0c4cad760fcdce86aca0 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 30 Jul 2023 16:23:41 +0300 Subject: [PATCH] Convert store selectors to Typescript (cherry picked from commit a57b35a1966266b49d1241474fe3b69523f70474) --- frontend/src/App/State/AppState.ts | 14 ++++++--- frontend/src/App/State/CommandAppState.ts | 6 ++++ .../src/App/State/MovieCollectionAppState.ts | 6 ++++ frontend/src/App/State/SettingsAppState.ts | 7 +++-- frontend/src/App/State/SystemAppState.ts | 10 ++++++ frontend/src/App/State/TagsAppState.ts | 22 ++++++++++++- .../Index/Overview/MovieIndexOverviewInfo.tsx | 8 ++--- .../Movie/Index/Posters/MovieIndexPoster.tsx | 2 +- .../Index/Posters/MovieIndexPosterInfo.tsx | 8 +++-- .../src/Movie/Index/Table/MovieIndexRow.tsx | 2 +- frontend/src/Movie/Movie.ts | 2 +- ...Selector.js => createAllMoviesSelector.ts} | 3 +- ...r.js => createCommandExecutingSelector.ts} | 11 +++---- .../Store/Selectors/createCommandSelector.js | 14 --------- .../Store/Selectors/createCommandSelector.ts | 11 +++++++ ...sSelector.js => createCommandsSelector.ts} | 3 +- .../Selectors/createDeepEqualSelector.js | 9 ------ .../Selectors/createDeepEqualSelector.ts | 6 ++++ ....js => createExecutingCommandsSelector.ts} | 3 +- ...ctor.js => createExistingMovieSelector.ts} | 7 +++-- .../Selectors/createLanguagesSelector.js | 27 ---------------- .../Selectors/createLanguagesSelector.ts | 25 +++++++++++++++ ...elector.js => createMovieCountSelector.ts} | 9 +++--- ...Selector.js => createMovieFileSelector.ts} | 5 +-- .../createMovieQualityProfileSelector.js | 16 ---------- .../createMovieQualityProfileSelector.ts | 18 +++++++++++ .../Selectors/createProfileInUseSelector.js | 25 --------------- .../Selectors/createProfileInUseSelector.ts | 31 +++++++++++++++++++ .../Selectors/createQualityProfileSelector.js | 26 ---------------- .../Selectors/createQualityProfileSelector.ts | 24 ++++++++++++++ ...Selector.js => createQueueItemSelector.ts} | 9 +++--- ...ector.js => createSystemStatusSelector.ts} | 3 +- ...elector.js => createTagDetailsSelector.ts} | 5 +-- ...eTagsSelector.js => createTagsSelector.ts} | 3 +- ...elector.js => createUISettingsSelector.ts} | 3 +- frontend/src/typings/MovieCollection.ts | 17 ++++++++++ frontend/src/typings/SystemStatus.ts | 31 +++++++++++++++++++ frontend/src/typings/UiSettings.ts | 1 + 38 files changed, 268 insertions(+), 164 deletions(-) create mode 100644 frontend/src/App/State/CommandAppState.ts create mode 100644 frontend/src/App/State/MovieCollectionAppState.ts create mode 100644 frontend/src/App/State/SystemAppState.ts rename frontend/src/Store/Selectors/{createAllMoviesSelector.js => createAllMoviesSelector.ts} (71%) rename frontend/src/Store/Selectors/{createCommandExecutingSelector.js => createCommandExecutingSelector.ts} (50%) delete mode 100644 frontend/src/Store/Selectors/createCommandSelector.js create mode 100644 frontend/src/Store/Selectors/createCommandSelector.ts rename frontend/src/Store/Selectors/{createCommandsSelector.js => createCommandsSelector.ts} (71%) delete mode 100644 frontend/src/Store/Selectors/createDeepEqualSelector.js create mode 100644 frontend/src/Store/Selectors/createDeepEqualSelector.ts rename frontend/src/Store/Selectors/{createExecutingCommandsSelector.js => createExecutingCommandsSelector.ts} (78%) rename frontend/src/Store/Selectors/{createExistingMovieSelector.js => createExistingMovieSelector.ts} (62%) delete mode 100644 frontend/src/Store/Selectors/createLanguagesSelector.js create mode 100644 frontend/src/Store/Selectors/createLanguagesSelector.ts rename frontend/src/Store/Selectors/{createMovieCountSelector.js => createMovieCountSelector.ts} (65%) rename frontend/src/Store/Selectors/{createMovieFileSelector.js => createMovieFileSelector.ts} (66%) delete mode 100644 frontend/src/Store/Selectors/createMovieQualityProfileSelector.js create mode 100644 frontend/src/Store/Selectors/createMovieQualityProfileSelector.ts delete mode 100644 frontend/src/Store/Selectors/createProfileInUseSelector.js create mode 100644 frontend/src/Store/Selectors/createProfileInUseSelector.ts delete mode 100644 frontend/src/Store/Selectors/createQualityProfileSelector.js create mode 100644 frontend/src/Store/Selectors/createQualityProfileSelector.ts rename frontend/src/Store/Selectors/{createQueueItemSelector.js => createQueueItemSelector.ts} (53%) rename frontend/src/Store/Selectors/{createSystemStatusSelector.js => createSystemStatusSelector.ts} (70%) rename frontend/src/Store/Selectors/{createTagDetailsSelector.js => createTagDetailsSelector.ts} (62%) rename frontend/src/Store/Selectors/{createTagsSelector.js => createTagsSelector.ts} (68%) rename frontend/src/Store/Selectors/{createUISettingsSelector.js => createUISettingsSelector.ts} (69%) create mode 100644 frontend/src/typings/MovieCollection.ts create mode 100644 frontend/src/typings/SystemStatus.ts diff --git a/frontend/src/App/State/AppState.ts b/frontend/src/App/State/AppState.ts index 15d8451b4c..a72690680b 100644 --- a/frontend/src/App/State/AppState.ts +++ b/frontend/src/App/State/AppState.ts @@ -1,9 +1,12 @@ import InteractiveImportAppState from 'App/State/InteractiveImportAppState'; +import CommandAppState from './CommandAppState'; +import MovieCollectionAppState from './MovieCollectionAppState'; import MovieFilesAppState from './MovieFilesAppState'; import MoviesAppState, { MovieIndexAppState } from './MoviesAppState'; import ParseAppState from './ParseAppState'; import QueueAppState from './QueueAppState'; import SettingsAppState from './SettingsAppState'; +import SystemAppState from './SystemAppState'; import TagsAppState from './TagsAppState'; interface FilterBuilderPropOption { @@ -39,14 +42,17 @@ export interface CustomFilter { } interface AppState { - movieFiles: MovieFilesAppState; + commands: CommandAppState; interactiveImport: InteractiveImportAppState; + movieCollections: MovieCollectionAppState; + movieFiles: MovieFilesAppState; movieIndex: MovieIndexAppState; - parse: ParseAppState; - settings: SettingsAppState; movies: MoviesAppState; - tags: TagsAppState; + parse: ParseAppState; queue: QueueAppState; + settings: SettingsAppState; + system: SystemAppState; + tags: TagsAppState; } export default AppState; diff --git a/frontend/src/App/State/CommandAppState.ts b/frontend/src/App/State/CommandAppState.ts new file mode 100644 index 0000000000..1bde373715 --- /dev/null +++ b/frontend/src/App/State/CommandAppState.ts @@ -0,0 +1,6 @@ +import AppSectionState from 'App/State/AppSectionState'; +import Command from 'Commands/Command'; + +export type CommandAppState = AppSectionState; + +export default CommandAppState; diff --git a/frontend/src/App/State/MovieCollectionAppState.ts b/frontend/src/App/State/MovieCollectionAppState.ts new file mode 100644 index 0000000000..aee45245f9 --- /dev/null +++ b/frontend/src/App/State/MovieCollectionAppState.ts @@ -0,0 +1,6 @@ +import AppSectionState from 'App/State/AppSectionState'; +import MovieCollection from 'typings/MovieCollection'; + +type MovieCollectionAppState = AppSectionState; + +export default MovieCollectionAppState; diff --git a/frontend/src/App/State/SettingsAppState.ts b/frontend/src/App/State/SettingsAppState.ts index 7630ad2d7c..aeb1cbf68f 100644 --- a/frontend/src/App/State/SettingsAppState.ts +++ b/frontend/src/App/State/SettingsAppState.ts @@ -1,5 +1,6 @@ import AppSectionState, { AppSectionDeleteState, + AppSectionItemState, AppSectionSaveState, AppSectionSchemaState, } from 'App/State/AppSectionState'; @@ -41,17 +42,17 @@ export interface RootFolderAppState AppSectionSaveState {} export type LanguageSettingsAppState = AppSectionState; -export type UiSettingsAppState = AppSectionState; +export type UiSettingsAppState = AppSectionItemState; interface SettingsAppState { downloadClients: DownloadClientAppState; importLists: ImportListAppState; indexers: IndexerAppState; - language: LanguageSettingsAppState; + languages: LanguageSettingsAppState; notifications: NotificationAppState; qualityProfiles: QualityProfilesAppState; rootFolders: RootFolderAppState; - uiSettings: UiSettingsAppState; + ui: UiSettingsAppState; } export default SettingsAppState; diff --git a/frontend/src/App/State/SystemAppState.ts b/frontend/src/App/State/SystemAppState.ts new file mode 100644 index 0000000000..d43c1d0ee4 --- /dev/null +++ b/frontend/src/App/State/SystemAppState.ts @@ -0,0 +1,10 @@ +import SystemStatus from 'typings/SystemStatus'; +import { AppSectionItemState } from './AppSectionState'; + +export type SystemStatusAppState = AppSectionItemState; + +interface SystemAppState { + status: SystemStatusAppState; +} + +export default SystemAppState; diff --git a/frontend/src/App/State/TagsAppState.ts b/frontend/src/App/State/TagsAppState.ts index d1f1d5a2fb..f22873606b 100644 --- a/frontend/src/App/State/TagsAppState.ts +++ b/frontend/src/App/State/TagsAppState.ts @@ -1,12 +1,32 @@ import ModelBase from 'App/ModelBase'; import AppSectionState, { AppSectionDeleteState, + AppSectionSaveState, } from 'App/State/AppSectionState'; export interface Tag extends ModelBase { label: string; } -interface TagsAppState extends AppSectionState, AppSectionDeleteState {} +export interface TagDetail extends ModelBase { + label: string; + autoTagIds: number[]; + delayProfileIds: number[]; + downloadClientIds: number[]; + importListIds: number[]; + indexerIds: number[]; + movieIds: number[]; + notificationIds: number[]; + restrictionIds: number[]; +} + +export interface TagDetailAppState + extends AppSectionState, + AppSectionDeleteState, + AppSectionSaveState {} + +interface TagsAppState extends AppSectionState, AppSectionDeleteState { + details: TagDetailAppState; +} export default TagsAppState; diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.tsx b/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.tsx index 9d8b9a9bc9..b237dd92b5 100644 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.tsx +++ b/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.tsx @@ -4,6 +4,7 @@ import { useSelector } from 'react-redux'; import { icons } from 'Helpers/Props'; import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; import dimensions from 'Styles/Variables/dimensions'; +import QualityProfile from 'typings/QualityProfile'; import { UiSettings } from 'typings/UiSettings'; import formatDateTime from 'Utilities/Date/formatDateTime'; import getRelativeDate from 'Utilities/Date/getRelativeDate'; @@ -33,7 +34,7 @@ interface MovieIndexOverviewInfoProps { showSizeOnDisk: boolean; monitored: boolean; studio?: string; - qualityProfile: object; + qualityProfile?: QualityProfile; added?: string; path: string; sizeOnDisk?: number; @@ -100,13 +101,10 @@ function getInfoRowProps( }; } - if (name === 'qualityProfileId') { + if (name === 'qualityProfileId' && !!props.qualityProfile?.name) { return { title: 'Quality Profile', iconName: icons.PROFILE, - // TODO: Type QualityProfile - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore ts(2339) label: props.qualityProfile.name, }; } diff --git a/frontend/src/Movie/Index/Posters/MovieIndexPoster.tsx b/frontend/src/Movie/Index/Posters/MovieIndexPoster.tsx index 2ea560e367..e64c272f1a 100644 --- a/frontend/src/Movie/Index/Posters/MovieIndexPoster.tsx +++ b/frontend/src/Movie/Index/Posters/MovieIndexPoster.tsx @@ -229,7 +229,7 @@ function MovieIndexPoster(props: MovieIndexPosterProps) { ) : null} - {showQualityProfile ? ( + {showQualityProfile && !!qualityProfile?.name ? (
{qualityProfile.name}
diff --git a/frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.tsx b/frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.tsx index ccbd61cb68..859504e2e4 100644 --- a/frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.tsx +++ b/frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.tsx @@ -14,7 +14,7 @@ import styles from './MovieIndexPosterInfo.css'; interface MovieIndexPosterInfoProps { studio?: string; showQualityProfile: boolean; - qualityProfile: QualityProfile; + qualityProfile?: QualityProfile; added?: string; year: number; inCinemas?: string; @@ -68,7 +68,11 @@ function MovieIndexPosterInfo(props: MovieIndexPosterInfoProps) { ); } - if (sortKey === 'qualityProfileId' && !showQualityProfile) { + if ( + sortKey === 'qualityProfileId' && + !showQualityProfile && + !!qualityProfile?.name + ) { return (
{qualityProfile.name} diff --git a/frontend/src/Movie/Index/Table/MovieIndexRow.tsx b/frontend/src/Movie/Index/Table/MovieIndexRow.tsx index 56fe0d5103..6cecac3e9d 100644 --- a/frontend/src/Movie/Index/Table/MovieIndexRow.tsx +++ b/frontend/src/Movie/Index/Table/MovieIndexRow.tsx @@ -210,7 +210,7 @@ function MovieIndexRow(props: MovieIndexRowProps) { if (name === 'qualityProfileId') { return ( - {qualityProfile.name} + {qualityProfile?.name ?? ''} ); } diff --git a/frontend/src/Movie/Movie.ts b/frontend/src/Movie/Movie.ts index 7160497b7b..b819170323 100644 --- a/frontend/src/Movie/Movie.ts +++ b/frontend/src/Movie/Movie.ts @@ -35,7 +35,7 @@ interface Movie extends ModelBase { titleSlug: string; collection: Collection; studio: string; - qualityProfile: object; + qualityProfileId: number; added: string; year: number; inCinemas: string; diff --git a/frontend/src/Store/Selectors/createAllMoviesSelector.js b/frontend/src/Store/Selectors/createAllMoviesSelector.ts similarity index 71% rename from frontend/src/Store/Selectors/createAllMoviesSelector.js rename to frontend/src/Store/Selectors/createAllMoviesSelector.ts index a6bad0991d..67f276ff8a 100644 --- a/frontend/src/Store/Selectors/createAllMoviesSelector.js +++ b/frontend/src/Store/Selectors/createAllMoviesSelector.ts @@ -1,8 +1,9 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; function createAllMoviesSelector() { return createSelector( - (state) => state.movies, + (state: AppState) => state.movies, (movies) => { return movies.items; } diff --git a/frontend/src/Store/Selectors/createCommandExecutingSelector.js b/frontend/src/Store/Selectors/createCommandExecutingSelector.ts similarity index 50% rename from frontend/src/Store/Selectors/createCommandExecutingSelector.js rename to frontend/src/Store/Selectors/createCommandExecutingSelector.ts index 6037d5820e..6a80e172b3 100644 --- a/frontend/src/Store/Selectors/createCommandExecutingSelector.js +++ b/frontend/src/Store/Selectors/createCommandExecutingSelector.ts @@ -2,13 +2,10 @@ import { createSelector } from 'reselect'; import { isCommandExecuting } from 'Utilities/Command'; import createCommandSelector from './createCommandSelector'; -function createCommandExecutingSelector(name, contraints = {}) { - return createSelector( - createCommandSelector(name, contraints), - (command) => { - return isCommandExecuting(command); - } - ); +function createCommandExecutingSelector(name: string, contraints = {}) { + return createSelector(createCommandSelector(name, contraints), (command) => { + return isCommandExecuting(command); + }); } export default createCommandExecutingSelector; diff --git a/frontend/src/Store/Selectors/createCommandSelector.js b/frontend/src/Store/Selectors/createCommandSelector.js deleted file mode 100644 index 709dfebaf0..0000000000 --- a/frontend/src/Store/Selectors/createCommandSelector.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createSelector } from 'reselect'; -import { findCommand } from 'Utilities/Command'; -import createCommandsSelector from './createCommandsSelector'; - -function createCommandSelector(name, contraints = {}) { - return createSelector( - createCommandsSelector(), - (commands) => { - return findCommand(commands, { name, ...contraints }); - } - ); -} - -export default createCommandSelector; diff --git a/frontend/src/Store/Selectors/createCommandSelector.ts b/frontend/src/Store/Selectors/createCommandSelector.ts new file mode 100644 index 0000000000..cced7b1864 --- /dev/null +++ b/frontend/src/Store/Selectors/createCommandSelector.ts @@ -0,0 +1,11 @@ +import { createSelector } from 'reselect'; +import { findCommand } from 'Utilities/Command'; +import createCommandsSelector from './createCommandsSelector'; + +function createCommandSelector(name: string, contraints = {}) { + return createSelector(createCommandsSelector(), (commands) => { + return findCommand(commands, { name, ...contraints }); + }); +} + +export default createCommandSelector; diff --git a/frontend/src/Store/Selectors/createCommandsSelector.js b/frontend/src/Store/Selectors/createCommandsSelector.ts similarity index 71% rename from frontend/src/Store/Selectors/createCommandsSelector.js rename to frontend/src/Store/Selectors/createCommandsSelector.ts index 7b9edffd92..2dd5d24a25 100644 --- a/frontend/src/Store/Selectors/createCommandsSelector.js +++ b/frontend/src/Store/Selectors/createCommandsSelector.ts @@ -1,8 +1,9 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; function createCommandsSelector() { return createSelector( - (state) => state.commands, + (state: AppState) => state.commands, (commands) => { return commands.items; } diff --git a/frontend/src/Store/Selectors/createDeepEqualSelector.js b/frontend/src/Store/Selectors/createDeepEqualSelector.js deleted file mode 100644 index 85562f28ba..0000000000 --- a/frontend/src/Store/Selectors/createDeepEqualSelector.js +++ /dev/null @@ -1,9 +0,0 @@ -import _ from 'lodash'; -import { createSelectorCreator, defaultMemoize } from 'reselect'; - -const createDeepEqualSelector = createSelectorCreator( - defaultMemoize, - _.isEqual -); - -export default createDeepEqualSelector; diff --git a/frontend/src/Store/Selectors/createDeepEqualSelector.ts b/frontend/src/Store/Selectors/createDeepEqualSelector.ts new file mode 100644 index 0000000000..9d4a63d2e4 --- /dev/null +++ b/frontend/src/Store/Selectors/createDeepEqualSelector.ts @@ -0,0 +1,6 @@ +import { isEqual } from 'lodash'; +import { createSelectorCreator, defaultMemoize } from 'reselect'; + +const createDeepEqualSelector = createSelectorCreator(defaultMemoize, isEqual); + +export default createDeepEqualSelector; diff --git a/frontend/src/Store/Selectors/createExecutingCommandsSelector.js b/frontend/src/Store/Selectors/createExecutingCommandsSelector.ts similarity index 78% rename from frontend/src/Store/Selectors/createExecutingCommandsSelector.js rename to frontend/src/Store/Selectors/createExecutingCommandsSelector.ts index 266865a8a0..dd16571fcb 100644 --- a/frontend/src/Store/Selectors/createExecutingCommandsSelector.js +++ b/frontend/src/Store/Selectors/createExecutingCommandsSelector.ts @@ -1,9 +1,10 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; import { isCommandExecuting } from 'Utilities/Command'; function createExecutingCommandsSelector() { return createSelector( - (state) => state.commands.items, + (state: AppState) => state.commands.items, (commands) => { return commands.filter((command) => isCommandExecuting(command)); } diff --git a/frontend/src/Store/Selectors/createExistingMovieSelector.js b/frontend/src/Store/Selectors/createExistingMovieSelector.ts similarity index 62% rename from frontend/src/Store/Selectors/createExistingMovieSelector.js rename to frontend/src/Store/Selectors/createExistingMovieSelector.ts index 94bb63687f..dba8f4d0a2 100644 --- a/frontend/src/Store/Selectors/createExistingMovieSelector.js +++ b/frontend/src/Store/Selectors/createExistingMovieSelector.ts @@ -1,13 +1,14 @@ -import _ from 'lodash'; +import { some } from 'lodash'; import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; import createAllMoviesSelector from './createAllMoviesSelector'; function createExistingMovieSelector() { return createSelector( - (state, { tmdbId }) => tmdbId, + (_: AppState, { tmdbId }: { tmdbId: number }) => tmdbId, createAllMoviesSelector(), (tmdbId, movies) => { - return _.some(movies, { tmdbId }); + return some(movies, { tmdbId }); } ); } diff --git a/frontend/src/Store/Selectors/createLanguagesSelector.js b/frontend/src/Store/Selectors/createLanguagesSelector.js deleted file mode 100644 index 47840933c1..0000000000 --- a/frontend/src/Store/Selectors/createLanguagesSelector.js +++ /dev/null @@ -1,27 +0,0 @@ -import { createSelector } from 'reselect'; - -function createLanguagesSelector() { - return createSelector( - (state) => state.settings.languages, - (languages) => { - const { - isFetching, - isPopulated, - error, - items - } = languages; - - const filterItems = ['Any']; - const filteredLanguages = items.filter((lang) => !filterItems.includes(lang.name)); - - return { - isFetching, - isPopulated, - error, - items: filteredLanguages - }; - } - ); -} - -export default createLanguagesSelector; diff --git a/frontend/src/Store/Selectors/createLanguagesSelector.ts b/frontend/src/Store/Selectors/createLanguagesSelector.ts new file mode 100644 index 0000000000..8319221037 --- /dev/null +++ b/frontend/src/Store/Selectors/createLanguagesSelector.ts @@ -0,0 +1,25 @@ +import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; + +function createLanguagesSelector() { + return createSelector( + (state: AppState) => state.settings.languages, + (languages) => { + const { isFetching, isPopulated, error, items } = languages; + + const filterItems = ['Any']; + const filteredLanguages = items.filter( + (lang) => !filterItems.includes(lang.name) + ); + + return { + isFetching, + isPopulated, + error, + items: filteredLanguages, + }; + } + ); +} + +export default createLanguagesSelector; diff --git a/frontend/src/Store/Selectors/createMovieCountSelector.js b/frontend/src/Store/Selectors/createMovieCountSelector.ts similarity index 65% rename from frontend/src/Store/Selectors/createMovieCountSelector.js rename to frontend/src/Store/Selectors/createMovieCountSelector.ts index 17d04afa28..668f25282b 100644 --- a/frontend/src/Store/Selectors/createMovieCountSelector.js +++ b/frontend/src/Store/Selectors/createMovieCountSelector.ts @@ -1,18 +1,19 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; import createAllMoviesSelector from './createAllMoviesSelector'; function createMovieCountSelector() { return createSelector( createAllMoviesSelector(), - (state) => state.movies.error, - (state) => state.movies.isFetching, - (state) => state.movies.isPopulated, + (state: AppState) => state.movies.error, + (state: AppState) => state.movies.isFetching, + (state: AppState) => state.movies.isPopulated, (movies, error, isFetching, isPopulated) => { return { count: movies.length, error, isFetching, - isPopulated + isPopulated, }; } ); diff --git a/frontend/src/Store/Selectors/createMovieFileSelector.js b/frontend/src/Store/Selectors/createMovieFileSelector.ts similarity index 66% rename from frontend/src/Store/Selectors/createMovieFileSelector.js rename to frontend/src/Store/Selectors/createMovieFileSelector.ts index d9b4230adb..411e6029cd 100644 --- a/frontend/src/Store/Selectors/createMovieFileSelector.js +++ b/frontend/src/Store/Selectors/createMovieFileSelector.ts @@ -1,9 +1,10 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; function createMovieFileSelector() { return createSelector( - (state, { movieFileId }) => movieFileId, - (state) => state.movieFiles, + (_: AppState, { movieFileId }: { movieFileId: number }) => movieFileId, + (state: AppState) => state.movieFiles, (movieFileId, movieFiles) => { if (!movieFileId) { return; diff --git a/frontend/src/Store/Selectors/createMovieQualityProfileSelector.js b/frontend/src/Store/Selectors/createMovieQualityProfileSelector.js deleted file mode 100644 index 376691ad65..0000000000 --- a/frontend/src/Store/Selectors/createMovieQualityProfileSelector.js +++ /dev/null @@ -1,16 +0,0 @@ -import { createSelector } from 'reselect'; -import { createMovieSelectorForHook } from './createMovieSelector'; - -function createMovieQualityProfileSelector(movieId) { - return createSelector( - (state) => state.settings.qualityProfiles.items, - createMovieSelectorForHook(movieId), - (qualityProfiles, movie = {}) => { - return qualityProfiles.find((profile) => { - return profile.id === movie.qualityProfileId; - }); - } - ); -} - -export default createMovieQualityProfileSelector; diff --git a/frontend/src/Store/Selectors/createMovieQualityProfileSelector.ts b/frontend/src/Store/Selectors/createMovieQualityProfileSelector.ts new file mode 100644 index 0000000000..45c1366e14 --- /dev/null +++ b/frontend/src/Store/Selectors/createMovieQualityProfileSelector.ts @@ -0,0 +1,18 @@ +import { createSelector } from 'reselect'; +import appState from 'App/State/AppState'; +import Movie from 'Movie/Movie'; +import { createMovieSelectorForHook } from './createMovieSelector'; + +function createMovieQualityProfileSelector(movieId: number) { + return createSelector( + (state: appState) => state.settings.qualityProfiles.items, + createMovieSelectorForHook(movieId), + (qualityProfiles, movie = {} as Movie) => { + return qualityProfiles.find( + (profile) => profile.id === movie.qualityProfileId + ); + } + ); +} + +export default createMovieQualityProfileSelector; diff --git a/frontend/src/Store/Selectors/createProfileInUseSelector.js b/frontend/src/Store/Selectors/createProfileInUseSelector.js deleted file mode 100644 index a486facbac..0000000000 --- a/frontend/src/Store/Selectors/createProfileInUseSelector.js +++ /dev/null @@ -1,25 +0,0 @@ -import _ from 'lodash'; -import { createSelector } from 'reselect'; -import createAllMoviesSelector from './createAllMoviesSelector'; - -function createProfileInUseSelector(profileProp) { - return createSelector( - (state, { id }) => id, - createAllMoviesSelector(), - (state) => state.settings.importLists.items, - (state) => state.movieCollections.items, - (id, movies, lists, collections) => { - if (!id) { - return false; - } - - if (_.some(movies, { [profileProp]: id }) || _.some(lists, { [profileProp]: id }) || _.some(collections, { [profileProp]: id })) { - return true; - } - - return false; - } - ); -} - -export default createProfileInUseSelector; diff --git a/frontend/src/Store/Selectors/createProfileInUseSelector.ts b/frontend/src/Store/Selectors/createProfileInUseSelector.ts new file mode 100644 index 0000000000..9535106c9a --- /dev/null +++ b/frontend/src/Store/Selectors/createProfileInUseSelector.ts @@ -0,0 +1,31 @@ +import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; +import Movie from 'Movie/Movie'; +import ImportList from 'typings/ImportList'; +import MovieCollection from 'typings/MovieCollection'; +import createAllMoviesSelector from './createAllMoviesSelector'; + +function createProfileInUseSelector(profileProp: string) { + return createSelector( + (_: AppState, { id }: { id: number }) => id, + createAllMoviesSelector(), + (state: AppState) => state.settings.importLists.items, + (state: AppState) => state.movieCollections.items, + (id, movies, lists, collections) => { + if (!id) { + return false; + } + + return ( + movies.some((m) => m[profileProp as keyof Movie] === id) || + lists.some((list) => list[profileProp as keyof ImportList] === id) || + collections.some( + (collection) => + collection[profileProp as keyof MovieCollection] === id + ) + ); + } + ); +} + +export default createProfileInUseSelector; diff --git a/frontend/src/Store/Selectors/createQualityProfileSelector.js b/frontend/src/Store/Selectors/createQualityProfileSelector.js deleted file mode 100644 index 611dfc9039..0000000000 --- a/frontend/src/Store/Selectors/createQualityProfileSelector.js +++ /dev/null @@ -1,26 +0,0 @@ -import { createSelector } from 'reselect'; - -export function createQualityProfileSelectorForHook(qualityProfileId) { - return createSelector( - (state) => state.settings.qualityProfiles.items, - (qualityProfiles) => { - return qualityProfiles.find((profile) => { - return profile.id === qualityProfileId; - }); - } - ); -} - -function createQualityProfileSelector() { - return createSelector( - (state, { qualityProfileId }) => qualityProfileId, - (state) => state.settings.qualityProfiles.items, - (qualityProfileId, qualityProfiles) => { - return qualityProfiles.find((profile) => { - return profile.id === qualityProfileId; - }); - } - ); -} - -export default createQualityProfileSelector; diff --git a/frontend/src/Store/Selectors/createQualityProfileSelector.ts b/frontend/src/Store/Selectors/createQualityProfileSelector.ts new file mode 100644 index 0000000000..b913e0c468 --- /dev/null +++ b/frontend/src/Store/Selectors/createQualityProfileSelector.ts @@ -0,0 +1,24 @@ +import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; + +export function createQualityProfileSelectorForHook(qualityProfileId: number) { + return createSelector( + (state: AppState) => state.settings.qualityProfiles.items, + (qualityProfiles) => { + return qualityProfiles.find((profile) => profile.id === qualityProfileId); + } + ); +} + +function createQualityProfileSelector() { + return createSelector( + (_: AppState, { qualityProfileId }: { qualityProfileId: number }) => + qualityProfileId, + (state: AppState) => state.settings.qualityProfiles.items, + (qualityProfileId, qualityProfiles) => { + return qualityProfiles.find((profile) => profile.id === qualityProfileId); + } + ); +} + +export default createQualityProfileSelector; diff --git a/frontend/src/Store/Selectors/createQueueItemSelector.js b/frontend/src/Store/Selectors/createQueueItemSelector.ts similarity index 53% rename from frontend/src/Store/Selectors/createQueueItemSelector.js rename to frontend/src/Store/Selectors/createQueueItemSelector.ts index 50bec0d0f7..ab161f5ee2 100644 --- a/frontend/src/Store/Selectors/createQueueItemSelector.js +++ b/frontend/src/Store/Selectors/createQueueItemSelector.ts @@ -1,17 +1,16 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; function createQueueItemSelector() { return createSelector( - (state, { movieId }) => movieId, - (state) => state.queue.details.items, + (_: AppState, { movieId }: { movieId: number }) => movieId, + (state: AppState) => state.queue.details.items, (movieId, details) => { if (!movieId || !details) { return null; } - return details.find((item) => { - return item.movieId === movieId; - }); + return details.find((item) => item.movieId === movieId); } ); } diff --git a/frontend/src/Store/Selectors/createSystemStatusSelector.js b/frontend/src/Store/Selectors/createSystemStatusSelector.ts similarity index 70% rename from frontend/src/Store/Selectors/createSystemStatusSelector.js rename to frontend/src/Store/Selectors/createSystemStatusSelector.ts index df586bbb97..f5e276069d 100644 --- a/frontend/src/Store/Selectors/createSystemStatusSelector.js +++ b/frontend/src/Store/Selectors/createSystemStatusSelector.ts @@ -1,8 +1,9 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; function createSystemStatusSelector() { return createSelector( - (state) => state.system.status, + (state: AppState) => state.system.status, (status) => { return status.item; } diff --git a/frontend/src/Store/Selectors/createTagDetailsSelector.js b/frontend/src/Store/Selectors/createTagDetailsSelector.ts similarity index 62% rename from frontend/src/Store/Selectors/createTagDetailsSelector.js rename to frontend/src/Store/Selectors/createTagDetailsSelector.ts index dd178944cd..2a271cafe7 100644 --- a/frontend/src/Store/Selectors/createTagDetailsSelector.js +++ b/frontend/src/Store/Selectors/createTagDetailsSelector.ts @@ -1,9 +1,10 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; function createTagDetailsSelector() { return createSelector( - (state, { id }) => id, - (state) => state.tags.details.items, + (_: AppState, { id }: { id: number }) => id, + (state: AppState) => state.tags.details.items, (id, tagDetails) => { return tagDetails.find((t) => t.id === id); } diff --git a/frontend/src/Store/Selectors/createTagsSelector.js b/frontend/src/Store/Selectors/createTagsSelector.ts similarity index 68% rename from frontend/src/Store/Selectors/createTagsSelector.js rename to frontend/src/Store/Selectors/createTagsSelector.ts index fbfd91cdbb..f653ff6e36 100644 --- a/frontend/src/Store/Selectors/createTagsSelector.js +++ b/frontend/src/Store/Selectors/createTagsSelector.ts @@ -1,8 +1,9 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; function createTagsSelector() { return createSelector( - (state) => state.tags.items, + (state: AppState) => state.tags.items, (tags) => { return tags; } diff --git a/frontend/src/Store/Selectors/createUISettingsSelector.js b/frontend/src/Store/Selectors/createUISettingsSelector.ts similarity index 69% rename from frontend/src/Store/Selectors/createUISettingsSelector.js rename to frontend/src/Store/Selectors/createUISettingsSelector.ts index b256d0e98b..ff539679b1 100644 --- a/frontend/src/Store/Selectors/createUISettingsSelector.js +++ b/frontend/src/Store/Selectors/createUISettingsSelector.ts @@ -1,8 +1,9 @@ import { createSelector } from 'reselect'; +import AppState from 'App/State/AppState'; function createUISettingsSelector() { return createSelector( - (state) => state.settings.ui, + (state: AppState) => state.settings.ui, (ui) => { return ui.item; } diff --git a/frontend/src/typings/MovieCollection.ts b/frontend/src/typings/MovieCollection.ts new file mode 100644 index 0000000000..6b194abbda --- /dev/null +++ b/frontend/src/typings/MovieCollection.ts @@ -0,0 +1,17 @@ +import ModelBase from 'App/ModelBase'; +import Movie from 'Movie/Movie'; + +interface MovieCollection extends ModelBase { + title: string; + sortTitle: string; + tmdbId: number; + overview: string; + monitored: boolean; + rootFolderPath: string; + qualityProfileId: number; + movies: Movie[]; + missingMovies: number; + tags: number[]; +} + +export default MovieCollection; diff --git a/frontend/src/typings/SystemStatus.ts b/frontend/src/typings/SystemStatus.ts new file mode 100644 index 0000000000..e72be2c5cd --- /dev/null +++ b/frontend/src/typings/SystemStatus.ts @@ -0,0 +1,31 @@ +interface SystemStatus { + appData: string; + appName: string; + authentication: string; + branch: string; + buildTime: string; + instanceName: string; + isAdmin: boolean; + isDebug: boolean; + isDocker: boolean; + isLinux: boolean; + isNetCore: boolean; + isOsx: boolean; + isProduction: boolean; + isUserInteractive: boolean; + isWindows: boolean; + migrationVersion: number; + mode: string; + osName: string; + osVersion: string; + packageUpdateMechanism: string; + runtimeName: string; + runtimeVersion: string; + sqliteVersion: string; + startTime: string; + startupPath: string; + urlBase: string; + version: string; +} + +export default SystemStatus; diff --git a/frontend/src/typings/UiSettings.ts b/frontend/src/typings/UiSettings.ts index 79cb0f3334..b35e641977 100644 --- a/frontend/src/typings/UiSettings.ts +++ b/frontend/src/typings/UiSettings.ts @@ -3,4 +3,5 @@ export interface UiSettings { shortDateFormat: string; longDateFormat: string; timeFormat: string; + movieRuntimeFormat: string; }