From ad04d0d261386d89d9816eb86b867f9e6c32b251 Mon Sep 17 00:00:00 2001 From: Qstick Date: Mon, 19 Oct 2020 01:07:21 -0400 Subject: [PATCH] More Cleanup --- .gitchangelog.rc | 305 ---------- .gitchangelog.rc.release | 311 ----------- .gitignore | 6 +- README.md | 2 +- azure-pipelines.yml | 59 +- build.sh | 6 +- frontend/src/Activity/Blacklist/Blacklist.js | 235 -------- .../Activity/Blacklist/BlacklistConnector.js | 160 ------ .../Blacklist/BlacklistDetailsModal.js | 90 --- .../src/Activity/Blacklist/BlacklistRow.css | 18 - .../src/Activity/Blacklist/BlacklistRow.js | 213 ------- .../Blacklist/BlacklistRowConnector.js | 26 - frontend/src/Activity/Queue/ProtocolLabel.css | 13 - frontend/src/Activity/Queue/ProtocolLabel.js | 20 - frontend/src/Activity/Queue/Queue.js | 292 ---------- frontend/src/Activity/Queue/QueueConnector.js | 170 ------ frontend/src/Activity/Queue/QueueDetails.js | 128 ----- frontend/src/Activity/Queue/QueueOptions.js | 78 --- .../Activity/Queue/QueueOptionsConnector.js | 19 - frontend/src/Activity/Queue/QueueRow.css | 23 - frontend/src/Activity/Queue/QueueRow.js | 370 ------------- .../src/Activity/Queue/QueueRowConnector.js | 67 --- .../src/Activity/Queue/QueueStatusCell.css | 5 - .../src/Activity/Queue/QueueStatusCell.js | 157 ------ .../Activity/Queue/RemoveQueueItemModal.js | 144 ----- .../Activity/Queue/RemoveQueueItemsModal.css | 3 - .../Activity/Queue/RemoveQueueItemsModal.js | 148 ----- .../Queue/Status/QueueStatusConnector.js | 76 --- frontend/src/Activity/Queue/TimeleftCell.css | 5 - frontend/src/Activity/Queue/TimeleftCell.js | 83 --- .../src/AddMovie/AddNewMovie/AddNewMovie.css | 60 -- .../src/AddMovie/AddNewMovie/AddNewMovie.js | 219 -------- .../AddNewMovie/AddNewMovieConnector.js | 104 ---- .../AddMovie/AddNewMovie/AddNewMovieModal.js | 31 -- .../AddNewMovie/AddNewMovieModalContent.css | 68 --- .../AddNewMovie/AddNewMovieModalContent.js | 217 -------- .../AddNewMovieModalContentConnector.js | 103 ---- .../AddNewMovie/AddNewMovieSearchResult.css | 94 ---- .../AddNewMovie/AddNewMovieSearchResult.js | 218 -------- .../AddNewMovieSearchResultConnector.js | 23 - .../ImportMovie/Import/ImportMovie.js | 177 ------ .../Import/ImportMovieConnector.js | 153 ----- .../ImportMovie/Import/ImportMovieFooter.css | 37 -- .../ImportMovie/Import/ImportMovieFooter.js | 267 --------- .../Import/ImportMovieFooterConnector.js | 59 -- .../ImportMovie/Import/ImportMovieHeader.css | 31 -- .../ImportMovie/Import/ImportMovieHeader.js | 68 --- .../ImportMovie/Import/ImportMovieRow.css | 32 -- .../ImportMovie/Import/ImportMovieRow.js | 92 --- .../Import/ImportMovieRowConnector.js | 87 --- .../Import/ImportMovieSelected.css | 3 - .../ImportMovie/Import/ImportMovieTable.js | 185 ------- .../Import/ImportMovieTableConnector.js | 42 -- .../SelectMovie/ImportMovieSearchResult.css | 8 - .../SelectMovie/ImportMovieSearchResult.js | 52 -- .../ImportMovieSearchResultConnector.js | 17 - .../SelectMovie/ImportMovieSelectMovie.css | 66 --- .../SelectMovie/ImportMovieSelectMovie.js | 303 ---------- .../ImportMovieSelectMovieConnector.js | 76 --- .../Import/SelectMovie/ImportMovieTitle.css | 17 - .../Import/SelectMovie/ImportMovieTitle.js | 51 -- .../src/AddMovie/ImportMovie/ImportMovies.js | 30 - .../SelectFolder/ImportMovieRootFolderRow.css | 18 - .../SelectFolder/ImportMovieRootFolderRow.js | 66 --- .../ImportMovieRootFolderRowConnector.js | 48 -- .../SelectFolder/ImportMovieSelectFolder.css | 32 -- .../SelectFolder/ImportMovieSelectFolder.js | 187 ------- .../ImportMovieSelectFolderConnector.js | 91 --- frontend/src/App/AppRoutes.js | 32 +- .../src/Components/CircularProgressBar.js | 2 +- .../Filter/Builder/FilterBuilderRow.js | 8 - .../QualityFilterBuilderRowValueConnector.js | 75 --- ...tyProfileFilterBuilderRowValueConnector.js | 28 - .../src/Components/Form/FormInputGroup.js | 8 - .../QualityProfileSelectInputConnector.js | 99 ---- .../Components/Form/RootFolderSelectInput.js | 109 ---- .../Form/RootFolderSelectInputConnector.js | 157 ------ .../Form/RootFolderSelectInputOption.css | 31 -- .../Form/RootFolderSelectInputOption.js | 65 --- .../RootFolderSelectInputSelectedValue.css | 32 -- .../RootFolderSelectInputSelectedValue.js | 61 -- .../Page/Header/MovieSearchResult.js | 2 +- .../src/Components/Page/Header/PageHeader.css | 5 + .../src/Components/Page/Header/PageHeader.js | 9 +- frontend/src/Components/Page/PageConnector.js | 2 +- .../Components/Page/Sidebar/PageSidebar.js | 34 +- frontend/src/Components/SignalRConnector.js | 56 +- .../Helpers/Props/filterBuilderValueTypes.js | 3 - frontend/src/Helpers/Props/inputTypes.js | 4 - .../History/Details/HistoryDetails.css | 0 .../History/Details/HistoryDetails.js | 0 .../Details/HistoryDetailsConnector.js | 0 .../History/Details/HistoryDetailsModal.css | 0 .../History/Details/HistoryDetailsModal.js | 0 .../src/{Activity => }/History/History.js | 0 .../History/HistoryConnector.js | 0 .../History/HistoryEventTypeCell.css | 0 .../History/HistoryEventTypeCell.js | 0 .../src/{Activity => }/History/HistoryRow.css | 0 .../src/{Activity => }/History/HistoryRow.js | 8 +- .../History/HistoryRowConnector.js | 0 .../Delete/DeleteMovieModal.js | 0 .../Delete/DeleteMovieModalContent.css | 0 .../Delete/DeleteMovieModalContent.js | 0 .../DeleteMovieModalContentConnector.js | 0 .../{Movie => Indexer}/Edit/EditMovieModal.js | 0 .../Edit/EditMovieModalConnector.js | 0 .../Edit/EditMovieModalContent.css | 0 .../Edit/EditMovieModalContent.js | 15 - .../Edit/EditMovieModalContentConnector.js | 0 .../Editor/Delete/DeleteMovieModal.js | 0 .../Editor/Delete/DeleteMovieModalContent.css | 0 .../Editor/Delete/DeleteMovieModalContent.js | 0 .../DeleteMovieModalContentConnector.js | 0 .../Editor/MovieEditorFooter.css | 0 .../Editor/MovieEditorFooter.js | 47 +- .../Editor/MovieEditorFooterLabel.css | 0 .../Editor/MovieEditorFooterLabel.js | 0 .../Editor/Organize/OrganizeMovieModal.js | 0 .../Organize/OrganizeMovieModalContent.css | 0 .../Organize/OrganizeMovieModalContent.js | 0 .../OrganizeMovieModalContentConnector.js | 0 .../Editor/Tags/TagsModal.js | 0 .../Editor/Tags/TagsModalContent.css | 0 .../Editor/Tags/TagsModalContent.js | 0 .../Editor/Tags/TagsModalContentConnector.js | 0 .../History/MovieHistoryRow.css | 0 .../History/MovieHistoryRow.js | 10 +- .../History/MovieHistoryRowConnector.js | 0 .../History/MovieHistoryTable.js | 0 .../History/MovieHistoryTableContent.css | 0 .../History/MovieHistoryTableContent.js | 0 .../MovieHistoryTableContentConnector.js | 0 .../Index/Menus/MovieIndexFilterMenu.js | 2 +- .../Index/Menus/MovieIndexSearchMenu.js | 0 .../Index/Menus/MovieIndexSortMenu.js | 0 .../{Movie => Indexer}/Index/MovieIndex.css | 0 .../{Movie => Indexer}/Index/MovieIndex.js | 91 +-- .../Index/MovieIndexConnector.js | 27 - .../Index/MovieIndexFilterModalConnector.js | 0 .../Index/MovieIndexFooter.css | 0 .../Index/MovieIndexFooter.js | 0 .../Index/MovieIndexFooterConnector.js | 0 .../Index/MovieIndexItemConnector.js | 25 +- .../ProgressBar/MovieIndexProgressBar.css | 0 .../ProgressBar/MovieIndexProgressBar.js | 0 .../Index/Table/MovieIndexActionsCell.js | 4 +- .../Index/Table/MovieIndexHeader.css | 0 .../Index/Table/MovieIndexHeader.js | 0 .../Index/Table/MovieIndexHeaderConnector.js | 0 .../Index/Table/MovieIndexRow.css | 0 .../Index/Table/MovieIndexRow.js | 8 +- .../Index/Table/MovieIndexTable.css | 0 .../Index/Table/MovieIndexTable.js | 2 +- .../Index/Table/MovieIndexTableConnector.js | 0 .../Index/Table/MovieIndexTableOptions.js | 0 .../Table/MovieIndexTableOptionsConnector.js | 0 .../Index/Table/MovieStatusCell.css | 0 .../Index/Table/MovieStatusCell.js | 2 +- .../src/{Movie => Indexer}/MovieBanner.js | 0 .../{Movie => Indexer}/MovieCollection.css | 0 .../src/{Movie => Indexer}/MovieCollection.js | 0 .../MovieCollectionConnector.js | 0 .../{Movie => Indexer}/MovieFileStatus.css | 0 .../src/{Movie => Indexer}/MovieFileStatus.js | 2 +- .../MovieFileStatusConnector.js | 0 .../src/{Movie => Indexer}/MovieFormats.js | 0 .../src/{Movie => Indexer}/MovieHeadshot.js | 0 frontend/src/{Movie => Indexer}/MovieImage.js | 0 .../src/{Movie => Indexer}/MovieLanguage.js | 0 .../src/{Movie => Indexer}/MoviePoster.js | 0 .../src/{Movie => Indexer}/MovieQuality.js | 0 .../src/{Movie => Indexer}/MovieStatus.js | 0 .../src/{Movie => Indexer}/MovieTitleLink.js | 0 frontend/src/{Movie => Indexer}/NoMovie.css | 0 frontend/src/{Movie => Indexer}/NoMovie.js | 0 .../src/{Movie => Indexer}/movieEntities.js | 0 ...eractiveImportSelectFolderModalContent.css | 24 - ...teractiveImportSelectFolderModalContent.js | 169 ------ ...ImportSelectFolderModalContentConnector.js | 80 --- .../Folder/RecentFolderRow.css | 5 - .../Folder/RecentFolderRow.js | 65 --- .../InteractiveImportModalContent.css | 65 --- .../InteractiveImportModalContent.js | 409 -------------- .../InteractiveImportModalContentConnector.js | 195 ------- .../Interactive/InteractiveImportRow.css | 23 - .../Interactive/InteractiveImportRow.js | 307 ---------- .../InteractiveImportRowCellPlaceholder.css | 7 - .../InteractiveImportRowCellPlaceholder.js | 10 - .../InteractiveImportModal.js | 79 --- .../Language/SelectLanguageModal.js | 39 -- .../Language/SelectLanguageModalContent.css | 4 - .../Language/SelectLanguageModalContent.js | 153 ----- .../SelectLanguageModalContentConnector.js | 97 ---- .../Movie/SelectMovieModal.js | 37 -- .../Movie/SelectMovieModalContent.css | 52 -- .../Movie/SelectMovieModalContent.js | 237 -------- .../Movie/SelectMovieModalContentConnector.js | 115 ---- .../Movie/SelectMovieRow.css | 5 - .../InteractiveImport/Movie/SelectMovieRow.js | 38 -- .../Quality/SelectQualityModal.js | 37 -- .../Quality/SelectQualityModalContent.js | 169 ------ .../SelectQualityModalContentConnector.js | 95 ---- .../InteractiveSearch/InteractiveSearchRow.js | 8 +- .../Movie/Index/Menus/MovieIndexViewMenu.js | 56 -- .../Index/Overview/MovieIndexOverview.css | 104 ---- .../Index/Overview/MovieIndexOverview.js | 310 ----------- .../Index/Overview/MovieIndexOverviewInfo.css | 12 - .../Index/Overview/MovieIndexOverviewInfo.js | 192 ------- .../Overview/MovieIndexOverviewInfoRow.css | 10 - .../Overview/MovieIndexOverviewInfoRow.js | 35 -- .../Index/Overview/MovieIndexOverviews.css | 11 - .../Index/Overview/MovieIndexOverviews.js | 276 --------- .../Overview/MovieIndexOverviewsConnector.js | 25 - .../Options/MovieIndexOverviewOptionsModal.js | 25 - .../MovieIndexOverviewOptionsModalContent.js | 268 --------- ...dexOverviewOptionsModalContentConnector.js | 23 - .../Movie/Index/Posters/MovieIndexPoster.css | 114 ---- .../Movie/Index/Posters/MovieIndexPoster.js | 317 ----------- .../Index/Posters/MovieIndexPosterInfo.css | 5 - .../Index/Posters/MovieIndexPosterInfo.js | 158 ------ .../Movie/Index/Posters/MovieIndexPosters.css | 3 - .../Movie/Index/Posters/MovieIndexPosters.js | 336 ----------- .../Posters/MovieIndexPostersConnector.js | 24 - .../Options/MovieIndexPosterOptionsModal.js | 25 - .../MovieIndexPosterOptionsModalContent.js | 214 ------- ...IndexPosterOptionsModalContentConnector.js | 23 - .../src/Movie/MoveMovie/MoveMovieModal.css | 5 - .../src/Movie/MoveMovie/MoveMovieModal.js | 90 --- frontend/src/MovieFile/Edit/FileEditModal.js | 37 -- .../MovieFile/Edit/FileEditModalContent.js | 237 -------- .../Edit/FileEditModalContentConnector.js | 139 ----- .../src/MovieFile/Editor/MediaInfoPopover.js | 33 -- .../MovieFile/Editor/MovieFileEditorRow.css | 35 -- .../MovieFile/Editor/MovieFileEditorRow.js | 224 -------- .../MovieFile/Editor/MovieFileEditorTable.css | 10 - .../MovieFile/Editor/MovieFileEditorTable.js | 24 - .../Editor/MovieFileEditorTableContent.css | 14 - .../Editor/MovieFileEditorTableContent.js | 104 ---- .../MovieFileEditorTableContentConnector.js | 103 ---- .../Editor/MovieFileRowCellPlaceholder.css | 7 - .../Editor/MovieFileRowCellPlaceholder.js | 10 - .../src/MovieFile/Extras/ExtraFileRow.css | 10 - frontend/src/MovieFile/Extras/ExtraFileRow.js | 63 --- .../src/MovieFile/Extras/ExtraFileTable.css | 10 - .../src/MovieFile/Extras/ExtraFileTable.js | 25 - .../Extras/ExtraFileTableContent.css | 10 - .../MovieFile/Extras/ExtraFileTableContent.js | 81 --- .../Extras/ExtraFileTableContentConnector.js | 56 -- frontend/src/MovieFile/FileDetailsModal.js | 53 -- .../MovieFile/Language/SelectLanguageModal.js | 37 -- .../SelectLanguageModalContentConnector.js | 97 ---- frontend/src/MovieFile/MediaInfo.js | 52 -- frontend/src/MovieFile/MediaInfoConnector.js | 21 - .../MovieFile/MovieFileLanguageConnector.js | 17 - .../MovieFile/Quality/SelectQualityModal.js | 37 -- .../Quality/SelectQualityModalContent.js | 169 ------ .../SelectQualityModalContentConnector.js | 97 ---- frontend/src/MovieFile/mediaInfoTypes.js | 2 - frontend/src/Organize/OrganizePreviewModal.js | 34 -- .../Organize/OrganizePreviewModalConnector.js | 39 -- .../Organize/OrganizePreviewModalContent.css | 24 - .../Organize/OrganizePreviewModalContent.js | 203 ------- .../OrganizePreviewModalContentConnector.js | 88 --- frontend/src/Organize/OrganizePreviewRow.css | 20 - frontend/src/Organize/OrganizePreviewRow.js | 90 --- frontend/src/RootFolder/RootFolderRow.css | 27 - frontend/src/RootFolder/RootFolderRow.js | 82 --- .../src/RootFolder/RootFolderRowConnector.js | 13 - frontend/src/RootFolder/RootFolders.js | 84 --- .../src/RootFolder/RootFoldersConnector.js | 46 -- .../CustomFormatSettingsConnector.js | 33 -- .../CustomFormats/CustomFormat.css | 38 -- .../CustomFormats/CustomFormat.js | 180 ------ .../CustomFormats/CustomFormats.css | 21 - .../CustomFormats/CustomFormats.js | 116 ---- .../CustomFormats/CustomFormatsConnector.js | 63 --- .../CustomFormats/EditCustomFormatModal.js | 61 -- .../EditCustomFormatModalConnector.js | 43 -- .../EditCustomFormatModalContent.css | 22 - .../EditCustomFormatModalContent.js | 258 --------- .../EditCustomFormatModalContentConnector.js | 102 ---- .../CustomFormats/ExportCustomFormatModal.js | 61 -- .../ExportCustomFormatModalContent.css | 5 - .../ExportCustomFormatModalContent.js | 85 --- ...ExportCustomFormatModalContentConnector.js | 83 --- .../CustomFormats/ImportCustomFormatModal.js | 61 -- .../ImportCustomFormatModalContent.css | 5 - .../ImportCustomFormatModalContent.js | 152 ----- ...ImportCustomFormatModalContentConnector.js | 146 ----- .../Specifications/AddSpecificationItem.css | 44 -- .../Specifications/AddSpecificationItem.js | 111 ---- .../Specifications/AddSpecificationModal.js | 25 - .../AddSpecificationModalContent.css | 5 - .../AddSpecificationModalContent.js | 102 ---- .../AddSpecificationModalContentConnector.js | 70 --- .../AddSpecificationPresetMenuItem.js | 49 -- .../Specifications/EditSpecificationModal.js | 27 - .../EditSpecificationModalConnector.js | 50 -- .../EditSpecificationModalContent.css | 5 - .../EditSpecificationModalContent.js | 161 ------ .../EditSpecificationModalContentConnector.js | 78 --- .../Specifications/Specification.css | 38 -- .../Specifications/Specification.js | 146 ----- .../DownloadClients/DownloadClientSettings.js | 101 ---- .../DownloadClientSettingsConnector.js | 21 - .../DownloadClients/AddDownloadClientItem.css | 44 -- .../DownloadClients/AddDownloadClientItem.js | 111 ---- .../DownloadClients/AddDownloadClientModal.js | 25 - .../AddDownloadClientModalContent.css | 5 - .../AddDownloadClientModalContent.js | 122 ---- .../AddDownloadClientModalContentConnector.js | 75 --- .../AddDownloadClientPresetMenuItem.js | 49 -- .../DownloadClients/DownloadClient.css | 19 - .../DownloadClients/DownloadClient.js | 126 ----- .../DownloadClients/DownloadClients.css | 20 - .../DownloadClients/DownloadClients.js | 115 ---- .../DownloadClientsConnector.js | 56 -- .../EditDownloadClientModal.js | 27 - .../EditDownloadClientModalConnector.js | 65 --- .../EditDownloadClientModalContent.css | 11 - .../EditDownloadClientModalContent.js | 197 ------- ...EditDownloadClientModalContentConnector.js | 88 --- .../Options/DownloadClientOptions.js | 138 ----- .../Options/DownloadClientOptionsConnector.js | 101 ---- .../EditRemotePathMappingModal.js | 27 - .../EditRemotePathMappingModalConnector.js | 43 -- .../EditRemotePathMappingModalContent.css | 11 - .../EditRemotePathMappingModalContent.js | 153 ----- ...tRemotePathMappingModalContentConnector.js | 148 ----- .../RemotePathMappings/RemotePathMapping.css | 23 - .../RemotePathMappings/RemotePathMapping.js | 115 ---- .../RemotePathMappings/RemotePathMappings.css | 23 - .../RemotePathMappings/RemotePathMappings.js | 101 ---- .../RemotePathMappingsConnector.js | 59 -- .../src/Settings/General/GeneralSettings.js | 2 +- .../src/Settings/Indexers/IndexerSettings.js | 3 - .../Indexers/AddIndexerModalContent.js | 2 +- .../Restrictions/EditRestrictionModal.js | 27 - .../EditRestrictionModalConnector.js | 39 -- .../EditRestrictionModalContent.css | 5 - .../EditRestrictionModalContent.js | 127 ----- .../EditRestrictionModalContentConnector.js | 111 ---- .../Indexers/Restrictions/Restriction.css | 11 - .../Indexers/Restrictions/Restriction.js | 149 ----- .../Indexers/Restrictions/Restrictions.css | 20 - .../Indexers/Restrictions/Restrictions.js | 99 ---- .../Restrictions/RestrictionsConnector.js | 61 -- .../MediaManagement/MediaManagement.js | 407 -------------- .../MediaManagementConnector.js | 86 --- .../MediaManagement/Naming/Naming.css | 5 - .../Settings/MediaManagement/Naming/Naming.js | 227 -------- .../MediaManagement/Naming/NamingConnector.js | 97 ---- .../MediaManagement/Naming/NamingModal.css | 18 - .../MediaManagement/Naming/NamingModal.js | 440 --------------- .../MediaManagement/Naming/NamingOption.css | 69 --- .../MediaManagement/Naming/NamingOption.js | 84 --- .../RootFolder/AddRootFolder.css | 7 - .../RootFolder/AddRootFolder.js | 71 --- .../RootFolder/AddRootFolderConnector.js | 13 - .../Metadata/Metadata/EditMetadataModal.js | 27 - .../Metadata/EditMetadataModalConnector.js | 44 -- .../Metadata/EditMetadataModalContent.js | 105 ---- .../EditMetadataModalContentConnector.js | 95 ---- .../Settings/Metadata/Metadata/Metadata.css | 15 - .../Settings/Metadata/Metadata/Metadata.js | 149 ----- .../Settings/Metadata/Metadata/Metadatas.css | 4 - .../Settings/Metadata/Metadata/Metadatas.js | 44 -- .../Metadata/Metadata/MetadatasConnector.js | 47 -- .../src/Settings/Metadata/MetadataSettings.js | 72 --- .../Metadata/Options/MetadataOptions.js | 69 --- .../Options/MetadataOptionsConnector.js | 101 ---- .../Settings/Profiles/Delay/DelayProfile.css | 40 -- .../Settings/Profiles/Delay/DelayProfile.js | 173 ------ .../Delay/DelayProfileDragPreview.css | 3 - .../Profiles/Delay/DelayProfileDragPreview.js | 78 --- .../Profiles/Delay/DelayProfileDragSource.css | 17 - .../Profiles/Delay/DelayProfileDragSource.js | 148 ----- .../Settings/Profiles/Delay/DelayProfiles.css | 27 - .../Settings/Profiles/Delay/DelayProfiles.js | 149 ----- .../Profiles/Delay/DelayProfilesConnector.js | 105 ---- .../Profiles/Delay/EditDelayProfileModal.js | 27 - .../Delay/EditDelayProfileModalConnector.js | 43 -- .../Delay/EditDelayProfileModalContent.css | 5 - .../Delay/EditDelayProfileModalContent.js | 189 ------- .../EditDelayProfileModalContentConnector.js | 178 ------ frontend/src/Settings/Profiles/Profiles.css | 6 - frontend/src/Settings/Profiles/Profiles.js | 43 -- .../Quality/EditQualityProfileModal.js | 61 -- .../EditQualityProfileModalConnector.js | 43 -- .../EditQualityProfileModalContent.css | 31 -- .../Quality/EditQualityProfileModalContent.js | 359 ------------ ...EditQualityProfileModalContentConnector.js | 523 ------------------ .../Profiles/Quality/QualityProfile.css | 38 -- .../Profiles/Quality/QualityProfile.js | 187 ------- .../Quality/QualityProfileFormatItem.css | 45 -- .../Quality/QualityProfileFormatItem.js | 68 --- .../Quality/QualityProfileFormatItems.css | 31 -- .../Quality/QualityProfileFormatItems.js | 160 ------ .../Profiles/Quality/QualityProfileItem.css | 86 --- .../Profiles/Quality/QualityProfileItem.js | 132 ----- .../Quality/QualityProfileItemDragPreview.css | 4 - .../Quality/QualityProfileItemDragPreview.js | 92 --- .../Quality/QualityProfileItemDragSource.css | 18 - .../Quality/QualityProfileItemDragSource.js | 241 -------- .../Quality/QualityProfileItemGroup.css | 106 ---- .../Quality/QualityProfileItemGroup.js | 201 ------- .../Profiles/Quality/QualityProfileItems.css | 15 - .../Profiles/Quality/QualityProfileItems.js | 181 ------ .../Quality/QualityProfileNameConnector.js | 31 -- .../Profiles/Quality/QualityProfiles.css | 21 - .../Profiles/Quality/QualityProfiles.js | 107 ---- .../Quality/QualityProfilesConnector.js | 63 --- frontend/src/Settings/Tags/TagsConnector.js | 16 +- .../Settings/customFormatSpecifications.js | 193 ------- .../Store/Actions/Settings/customFormats.js | 108 ---- .../Store/Actions/Settings/delayProfiles.js | 103 ---- .../Actions/Settings/downloadClientOptions.js | 64 --- .../Store/Actions/Settings/downloadClients.js | 117 ---- .../Store/Actions/Settings/mediaManagement.js | 64 --- .../src/Store/Actions/Settings/metadata.js | 75 --- .../Store/Actions/Settings/metadataOptions.js | 64 --- frontend/src/Store/Actions/Settings/naming.js | 64 --- .../Store/Actions/Settings/namingExamples.js | 79 --- .../Actions/Settings/qualityDefinitions.js | 135 ----- .../Store/Actions/Settings/qualityProfiles.js | 97 ---- .../Actions/Settings/remotePathMappings.js | 69 --- .../Store/Actions/Settings/restrictions.js | 71 --- frontend/src/Store/Actions/addMovieActions.js | 178 ------ .../src/Store/Actions/blacklistActions.js | 205 ------- .../src/Store/Actions/extraFileActions.js | 49 -- .../src/Store/Actions/importMovieActions.js | 312 ----------- frontend/src/Store/Actions/index.js | 24 - .../Store/Actions/interactiveImportActions.js | 272 --------- .../Store/Actions/movieBlacklistActions.js | 82 --- .../src/Store/Actions/movieCreditsActions.js | 81 --- .../src/Store/Actions/movieFileActions.js | 238 -------- .../src/Store/Actions/movieHistoryActions.js | 103 ---- .../src/Store/Actions/movieIndexActions.js | 22 - .../Store/Actions/organizePreviewActions.js | 51 -- frontend/src/Store/Actions/queueActions.js | 456 --------------- .../src/Store/Actions/rootFolderActions.js | 97 ---- frontend/src/Store/Actions/settingsActions.js | 70 --- ...rMovieClientSideCollectionItemsSelector.js | 36 -- .../Selectors/createDiscoverMovieSelector.js | 13 - .../Selectors/createMovieFileSelector.js | 17 - .../createMovieQualityProfileSelector.js | 16 - .../Selectors/createProfileInUseSelector.js | 23 - .../Selectors/createQualityProfileSelector.js | 15 - .../Selectors/createQueueItemSelector.js | 19 - frontend/src/Styles/Variables/colors.js | 6 +- .../src/System/Status/DiskSpace/DiskSpace.css | 5 - .../src/System/Status/DiskSpace/DiskSpace.js | 125 ----- .../Status/DiskSpace/DiskSpaceConnector.js | 57 -- frontend/src/System/Status/Health/Health.js | 30 - .../System/Status/Health/HealthConnector.js | 7 +- frontend/src/System/Status/Status.js | 2 - setup/radarr.iss | 2 +- src/Directory.Build.props | 46 +- .../PathExtensionFixture.cs | 8 +- .../Cloud/ProwlarrCloudRequestBuilder.cs | 19 +- src/NzbDrone.Common/Disk/DiskProviderBase.cs | 2 +- .../EnvironmentInfo/AppFolderFactory.cs | 6 +- .../EnvironmentInfo/RuntimeInfo.cs | 4 +- .../Exceptions/ProwlarrStartupException.cs | 14 +- .../Extensions/PathExtensions.cs | 6 +- .../Processes/PidFileProvider.cs | 2 +- .../Processes/ProcessProvider.cs | 4 +- src/NzbDrone.Console/ConsoleApp.cs | 2 +- src/NzbDrone.Core.Test/Framework/CoreTest.cs | 2 +- .../Checks/SystemTimeCheckFixture.cs | 2 +- .../Housekeepers/CleanupUnusedTagsFixture.cs | 23 +- .../IndexerTests/TestIndexer.cs | 2 +- src/NzbDrone.Core/Backup/BackupService.cs | 6 +- .../Datastore/CorruptDatabaseException.cs | 2 +- src/NzbDrone.Core/Datastore/DbFactory.cs | 4 +- .../Datastore/Migration/001_initial_setup.cs | 6 + src/NzbDrone.Core/Datastore/TableMapping.cs | 2 - .../HealthCheck/Checks/ProxyCheck.cs | 2 +- .../HealthCheck/Checks/SystemTimeCheck.cs | 2 +- .../Housekeepers/CleanupUnusedTags.cs | 2 +- .../Indexers/AwesomeHD/AwesomeHD.cs | 2 +- .../Indexers/FileList/FileList.cs | 2 +- src/NzbDrone.Core/Indexers/HDBits/HDBits.cs | 2 +- src/NzbDrone.Core/Indexers/HttpIndexerBase.cs | 4 +- .../Indexers/IPTorrents/IPTorrents.cs | 2 +- src/NzbDrone.Core/Indexers/Newznab/Newznab.cs | 2 +- src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs | 2 +- .../Indexers/Omgwtfnzbs/Omgwtfnzbs.cs | 2 +- .../Indexers/PassThePopcorn/PassThePopcorn.cs | 2 +- src/NzbDrone.Core/Indexers/Rarbg/Rarbg.cs | 2 +- .../Indexers/TorrentPotato/TorrentPotato.cs | 2 +- .../Indexers/TorrentRss/TorrentRssIndexer.cs | 2 +- src/NzbDrone.Core/Indexers/Torznab/Torznab.cs | 2 +- src/NzbDrone.Core/Localization/Core/de.json | 20 +- src/NzbDrone.Core/Localization/Core/en.json | 14 +- src/NzbDrone.Core/Localization/Core/es.json | 14 +- src/NzbDrone.Core/Localization/Core/fr.json | 14 +- src/NzbDrone.Core/Localization/Core/hu.json | 16 +- src/NzbDrone.Core/Localization/Core/it.json | 14 +- src/NzbDrone.Core/Localization/Core/nl.json | 14 +- src/NzbDrone.Core/Localization/Core/pt.json | 14 +- .../CustomScript/CustomScript.cs | 12 +- .../DiscordNotifier/DiscordNotifier.cs | 10 +- .../DiscordNotifier/DiscordNotifierProxy.cs | 2 +- .../Restrictions/PerlRegexFactory.cs | 68 --- src/NzbDrone.Core/Restrictions/Restriction.cs | 18 - .../Restrictions/RestrictionRepository.cs | 17 - .../Restrictions/RestrictionService.cs | 65 --- src/NzbDrone.Core/Restrictions/TermMatcher.cs | 59 -- src/NzbDrone.Core/Tags/TagDetails.cs | 6 +- src/NzbDrone.Core/Tags/TagService.cs | 14 +- .../Update/UpdatePackageProvider.cs | 2 +- .../NzbDroneProcessServiceFixture.cs | 8 +- src/NzbDrone.Host/Bootstrap.cs | 2 +- src/NzbDrone.Host/MainAppContainerBuilder.cs | 2 +- src/NzbDrone.Host/SingleInstancePolicy.cs | 4 +- .../WebHost/WebHostController.cs | 4 +- src/NzbDrone.Test.Common/LoggingTest.cs | 2 +- src/NzbDrone.Test.Common/NzbDroneRunner.cs | 10 +- .../UpdateEngine/DetectApplicationType.cs | 2 +- .../UpdateEngine/InstallUpdateService.cs | 10 +- .../UpdateEngine/TerminateNzbDrone.cs | 8 +- src/Prowlarr.Api.V1/Commands/CommandModule.cs | 2 +- .../Config/DownloadClientConfigModule.cs | 2 +- .../Config/IndexerConfigModule.cs | 2 +- .../Config/MediaManagementConfigModule.cs | 2 +- .../Config/ProwlarrConfigModule.cs | 6 +- src/Prowlarr.Api.V1/Config/UiConfigModule.cs | 2 +- .../FileSystem/FileSystemModule.cs | 2 +- src/Prowlarr.Api.V1/Health/HealthModule.cs | 2 +- src/Prowlarr.Api.V1/ProwlarrV1FeedModule.cs | 4 +- src/Prowlarr.Api.V1/ProwlarrV1Module.cs | 4 +- .../Restrictions/RestrictionModule.cs | 57 -- .../Restrictions/RestrictionResource.cs | 64 --- .../System/Backup/BackupModule.cs | 2 +- src/Prowlarr.Api.V1/System/SystemModule.cs | 2 +- .../System/Tasks/TaskModule.cs | 2 +- .../Tags/TagDetailsResource.cs | 10 +- src/Prowlarr.Api.V1/Tags/TagModule.cs | 2 +- .../Authentication/EnableAuthInNancy.cs | 2 +- .../ErrorManagement/ProwlarrErrorPipeline.cs | 4 +- .../Pipelines/ProwlarrVersionPipeline.cs | 2 +- .../Pipelines/RequestLoggingPipeline.cs | 4 +- src/Prowlarr.Http/ProwlarrBootstrapper.cs | 6 +- src/Prowlarr.Http/ProwlarrModule.cs | 4 +- .../ProwlarrRestModuleWithSignalR.cs | 6 +- .../ServiceInstall/ServiceHelper.cs | 6 +- .../ServiceUninstall/ServiceHelper.cs | 6 +- test.sh | 2 +- 550 files changed, 326 insertions(+), 31626 deletions(-) delete mode 100644 .gitchangelog.rc delete mode 100644 .gitchangelog.rc.release delete mode 100644 frontend/src/Activity/Blacklist/Blacklist.js delete mode 100644 frontend/src/Activity/Blacklist/BlacklistConnector.js delete mode 100644 frontend/src/Activity/Blacklist/BlacklistDetailsModal.js delete mode 100644 frontend/src/Activity/Blacklist/BlacklistRow.css delete mode 100644 frontend/src/Activity/Blacklist/BlacklistRow.js delete mode 100644 frontend/src/Activity/Blacklist/BlacklistRowConnector.js delete mode 100644 frontend/src/Activity/Queue/ProtocolLabel.css delete mode 100644 frontend/src/Activity/Queue/ProtocolLabel.js delete mode 100644 frontend/src/Activity/Queue/Queue.js delete mode 100644 frontend/src/Activity/Queue/QueueConnector.js delete mode 100644 frontend/src/Activity/Queue/QueueDetails.js delete mode 100644 frontend/src/Activity/Queue/QueueOptions.js delete mode 100644 frontend/src/Activity/Queue/QueueOptionsConnector.js delete mode 100644 frontend/src/Activity/Queue/QueueRow.css delete mode 100644 frontend/src/Activity/Queue/QueueRow.js delete mode 100644 frontend/src/Activity/Queue/QueueRowConnector.js delete mode 100644 frontend/src/Activity/Queue/QueueStatusCell.css delete mode 100644 frontend/src/Activity/Queue/QueueStatusCell.js delete mode 100644 frontend/src/Activity/Queue/RemoveQueueItemModal.js delete mode 100644 frontend/src/Activity/Queue/RemoveQueueItemsModal.css delete mode 100644 frontend/src/Activity/Queue/RemoveQueueItemsModal.js delete mode 100644 frontend/src/Activity/Queue/Status/QueueStatusConnector.js delete mode 100644 frontend/src/Activity/Queue/TimeleftCell.css delete mode 100644 frontend/src/Activity/Queue/TimeleftCell.js delete mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovie.css delete mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovie.js delete mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js delete mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieModal.js delete mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.css delete mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.js delete mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContentConnector.js delete mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.css delete mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js delete mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResultConnector.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovie.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieConnector.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.css delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooterConnector.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.css delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.css delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieRowConnector.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieSelected.css delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieTable.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.css delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResultConnector.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.css delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovieConnector.js delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.css delete mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.js delete mode 100644 frontend/src/AddMovie/ImportMovie/ImportMovies.js delete mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.css delete mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.js delete mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRowConnector.js delete mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.css delete mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.js delete mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector.js delete mode 100644 frontend/src/Components/Filter/Builder/QualityFilterBuilderRowValueConnector.js delete mode 100644 frontend/src/Components/Filter/Builder/QualityProfileFilterBuilderRowValueConnector.js delete mode 100644 frontend/src/Components/Form/QualityProfileSelectInputConnector.js delete mode 100644 frontend/src/Components/Form/RootFolderSelectInput.js delete mode 100644 frontend/src/Components/Form/RootFolderSelectInputConnector.js delete mode 100644 frontend/src/Components/Form/RootFolderSelectInputOption.css delete mode 100644 frontend/src/Components/Form/RootFolderSelectInputOption.js delete mode 100644 frontend/src/Components/Form/RootFolderSelectInputSelectedValue.css delete mode 100644 frontend/src/Components/Form/RootFolderSelectInputSelectedValue.js rename frontend/src/{Activity => }/History/Details/HistoryDetails.css (100%) rename frontend/src/{Activity => }/History/Details/HistoryDetails.js (100%) rename frontend/src/{Activity => }/History/Details/HistoryDetailsConnector.js (100%) rename frontend/src/{Activity => }/History/Details/HistoryDetailsModal.css (100%) rename frontend/src/{Activity => }/History/Details/HistoryDetailsModal.js (100%) rename frontend/src/{Activity => }/History/History.js (100%) rename frontend/src/{Activity => }/History/HistoryConnector.js (100%) rename frontend/src/{Activity => }/History/HistoryEventTypeCell.css (100%) rename frontend/src/{Activity => }/History/HistoryEventTypeCell.js (100%) rename frontend/src/{Activity => }/History/HistoryRow.css (100%) rename frontend/src/{Activity => }/History/HistoryRow.js (96%) rename frontend/src/{Activity => }/History/HistoryRowConnector.js (100%) rename frontend/src/{Movie => Indexer}/Delete/DeleteMovieModal.js (100%) rename frontend/src/{Movie => Indexer}/Delete/DeleteMovieModalContent.css (100%) rename frontend/src/{Movie => Indexer}/Delete/DeleteMovieModalContent.js (100%) rename frontend/src/{Movie => Indexer}/Delete/DeleteMovieModalContentConnector.js (100%) rename frontend/src/{Movie => Indexer}/Edit/EditMovieModal.js (100%) rename frontend/src/{Movie => Indexer}/Edit/EditMovieModalConnector.js (100%) rename frontend/src/{Movie => Indexer}/Edit/EditMovieModalContent.css (100%) rename frontend/src/{Movie => Indexer}/Edit/EditMovieModalContent.js (91%) rename frontend/src/{Movie => Indexer}/Edit/EditMovieModalContentConnector.js (100%) rename frontend/src/{Movie => Indexer}/Editor/Delete/DeleteMovieModal.js (100%) rename frontend/src/{Movie => Indexer}/Editor/Delete/DeleteMovieModalContent.css (100%) rename frontend/src/{Movie => Indexer}/Editor/Delete/DeleteMovieModalContent.js (100%) rename frontend/src/{Movie => Indexer}/Editor/Delete/DeleteMovieModalContentConnector.js (100%) rename frontend/src/{Movie => Indexer}/Editor/MovieEditorFooter.css (100%) rename frontend/src/{Movie => Indexer}/Editor/MovieEditorFooter.js (82%) rename frontend/src/{Movie => Indexer}/Editor/MovieEditorFooterLabel.css (100%) rename frontend/src/{Movie => Indexer}/Editor/MovieEditorFooterLabel.js (100%) rename frontend/src/{Movie => Indexer}/Editor/Organize/OrganizeMovieModal.js (100%) rename frontend/src/{Movie => Indexer}/Editor/Organize/OrganizeMovieModalContent.css (100%) rename frontend/src/{Movie => Indexer}/Editor/Organize/OrganizeMovieModalContent.js (100%) rename frontend/src/{Movie => Indexer}/Editor/Organize/OrganizeMovieModalContentConnector.js (100%) rename frontend/src/{Movie => Indexer}/Editor/Tags/TagsModal.js (100%) rename frontend/src/{Movie => Indexer}/Editor/Tags/TagsModalContent.css (100%) rename frontend/src/{Movie => Indexer}/Editor/Tags/TagsModalContent.js (100%) rename frontend/src/{Movie => Indexer}/Editor/Tags/TagsModalContentConnector.js (100%) rename frontend/src/{Movie => Indexer}/History/MovieHistoryRow.css (100%) rename frontend/src/{Movie => Indexer}/History/MovieHistoryRow.js (96%) rename frontend/src/{Movie => Indexer}/History/MovieHistoryRowConnector.js (100%) rename frontend/src/{Movie => Indexer}/History/MovieHistoryTable.js (100%) rename frontend/src/{Movie => Indexer}/History/MovieHistoryTableContent.css (100%) rename frontend/src/{Movie => Indexer}/History/MovieHistoryTableContent.js (100%) rename frontend/src/{Movie => Indexer}/History/MovieHistoryTableContentConnector.js (100%) rename frontend/src/{Movie => Indexer}/Index/Menus/MovieIndexFilterMenu.js (92%) rename frontend/src/{Movie => Indexer}/Index/Menus/MovieIndexSearchMenu.js (100%) rename frontend/src/{Movie => Indexer}/Index/Menus/MovieIndexSortMenu.js (100%) rename frontend/src/{Movie => Indexer}/Index/MovieIndex.css (100%) rename frontend/src/{Movie => Indexer}/Index/MovieIndex.js (84%) rename frontend/src/{Movie => Indexer}/Index/MovieIndexConnector.js (81%) rename frontend/src/{Movie => Indexer}/Index/MovieIndexFilterModalConnector.js (100%) rename frontend/src/{Movie => Indexer}/Index/MovieIndexFooter.css (100%) rename frontend/src/{Movie => Indexer}/Index/MovieIndexFooter.js (100%) rename frontend/src/{Movie => Indexer}/Index/MovieIndexFooterConnector.js (100%) rename frontend/src/{Movie => Indexer}/Index/MovieIndexItemConnector.js (76%) rename frontend/src/{Movie => Indexer}/Index/ProgressBar/MovieIndexProgressBar.css (100%) rename frontend/src/{Movie => Indexer}/Index/ProgressBar/MovieIndexProgressBar.js (100%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexActionsCell.js (94%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexHeader.css (100%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexHeader.js (100%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexHeaderConnector.js (100%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexRow.css (100%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexRow.js (98%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexTable.css (100%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexTable.js (98%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexTableConnector.js (100%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexTableOptions.js (100%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieIndexTableOptionsConnector.js (100%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieStatusCell.css (100%) rename frontend/src/{Movie => Indexer}/Index/Table/MovieStatusCell.js (95%) rename frontend/src/{Movie => Indexer}/MovieBanner.js (100%) rename frontend/src/{Movie => Indexer}/MovieCollection.css (100%) rename frontend/src/{Movie => Indexer}/MovieCollection.js (100%) rename frontend/src/{Movie => Indexer}/MovieCollectionConnector.js (100%) rename frontend/src/{Movie => Indexer}/MovieFileStatus.css (100%) rename frontend/src/{Movie => Indexer}/MovieFileStatus.js (97%) rename frontend/src/{Movie => Indexer}/MovieFileStatusConnector.js (100%) rename frontend/src/{Movie => Indexer}/MovieFormats.js (100%) rename frontend/src/{Movie => Indexer}/MovieHeadshot.js (100%) rename frontend/src/{Movie => Indexer}/MovieImage.js (100%) rename frontend/src/{Movie => Indexer}/MovieLanguage.js (100%) rename frontend/src/{Movie => Indexer}/MoviePoster.js (100%) rename frontend/src/{Movie => Indexer}/MovieQuality.js (100%) rename frontend/src/{Movie => Indexer}/MovieStatus.js (100%) rename frontend/src/{Movie => Indexer}/MovieTitleLink.js (100%) rename frontend/src/{Movie => Indexer}/NoMovie.css (100%) rename frontend/src/{Movie => Indexer}/NoMovie.js (100%) rename frontend/src/{Movie => Indexer}/movieEntities.js (100%) delete mode 100644 frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.css delete mode 100644 frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.js delete mode 100644 frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContentConnector.js delete mode 100644 frontend/src/InteractiveImport/Folder/RecentFolderRow.css delete mode 100644 frontend/src/InteractiveImport/Folder/RecentFolderRow.js delete mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.css delete mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js delete mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js delete mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportRow.css delete mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js delete mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportRowCellPlaceholder.css delete mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportRowCellPlaceholder.js delete mode 100644 frontend/src/InteractiveImport/InteractiveImportModal.js delete mode 100644 frontend/src/InteractiveImport/Language/SelectLanguageModal.js delete mode 100644 frontend/src/InteractiveImport/Language/SelectLanguageModalContent.css delete mode 100644 frontend/src/InteractiveImport/Language/SelectLanguageModalContent.js delete mode 100644 frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js delete mode 100644 frontend/src/InteractiveImport/Movie/SelectMovieModal.js delete mode 100644 frontend/src/InteractiveImport/Movie/SelectMovieModalContent.css delete mode 100644 frontend/src/InteractiveImport/Movie/SelectMovieModalContent.js delete mode 100644 frontend/src/InteractiveImport/Movie/SelectMovieModalContentConnector.js delete mode 100644 frontend/src/InteractiveImport/Movie/SelectMovieRow.css delete mode 100644 frontend/src/InteractiveImport/Movie/SelectMovieRow.js delete mode 100644 frontend/src/InteractiveImport/Quality/SelectQualityModal.js delete mode 100644 frontend/src/InteractiveImport/Quality/SelectQualityModalContent.js delete mode 100644 frontend/src/InteractiveImport/Quality/SelectQualityModalContentConnector.js delete mode 100644 frontend/src/Movie/Index/Menus/MovieIndexViewMenu.js delete mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverview.css delete mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverview.js delete mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.css delete mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.js delete mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviewInfoRow.css delete mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviewInfoRow.js delete mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviews.css delete mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviews.js delete mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviewsConnector.js delete mode 100644 frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModal.js delete mode 100644 frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModalContent.js delete mode 100644 frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModalContentConnector.js delete mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPoster.css delete mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPoster.js delete mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.css delete mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.js delete mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPosters.css delete mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPosters.js delete mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPostersConnector.js delete mode 100644 frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModal.js delete mode 100644 frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModalContent.js delete mode 100644 frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModalContentConnector.js delete mode 100644 frontend/src/Movie/MoveMovie/MoveMovieModal.css delete mode 100644 frontend/src/Movie/MoveMovie/MoveMovieModal.js delete mode 100644 frontend/src/MovieFile/Edit/FileEditModal.js delete mode 100644 frontend/src/MovieFile/Edit/FileEditModalContent.js delete mode 100644 frontend/src/MovieFile/Edit/FileEditModalContentConnector.js delete mode 100644 frontend/src/MovieFile/Editor/MediaInfoPopover.js delete mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorRow.css delete mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorRow.js delete mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorTable.css delete mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorTable.js delete mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorTableContent.css delete mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorTableContent.js delete mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorTableContentConnector.js delete mode 100644 frontend/src/MovieFile/Editor/MovieFileRowCellPlaceholder.css delete mode 100644 frontend/src/MovieFile/Editor/MovieFileRowCellPlaceholder.js delete mode 100644 frontend/src/MovieFile/Extras/ExtraFileRow.css delete mode 100644 frontend/src/MovieFile/Extras/ExtraFileRow.js delete mode 100644 frontend/src/MovieFile/Extras/ExtraFileTable.css delete mode 100644 frontend/src/MovieFile/Extras/ExtraFileTable.js delete mode 100644 frontend/src/MovieFile/Extras/ExtraFileTableContent.css delete mode 100644 frontend/src/MovieFile/Extras/ExtraFileTableContent.js delete mode 100644 frontend/src/MovieFile/Extras/ExtraFileTableContentConnector.js delete mode 100644 frontend/src/MovieFile/FileDetailsModal.js delete mode 100644 frontend/src/MovieFile/Language/SelectLanguageModal.js delete mode 100644 frontend/src/MovieFile/Language/SelectLanguageModalContentConnector.js delete mode 100644 frontend/src/MovieFile/MediaInfo.js delete mode 100644 frontend/src/MovieFile/MediaInfoConnector.js delete mode 100644 frontend/src/MovieFile/MovieFileLanguageConnector.js delete mode 100644 frontend/src/MovieFile/Quality/SelectQualityModal.js delete mode 100644 frontend/src/MovieFile/Quality/SelectQualityModalContent.js delete mode 100644 frontend/src/MovieFile/Quality/SelectQualityModalContentConnector.js delete mode 100644 frontend/src/MovieFile/mediaInfoTypes.js delete mode 100644 frontend/src/Organize/OrganizePreviewModal.js delete mode 100644 frontend/src/Organize/OrganizePreviewModalConnector.js delete mode 100644 frontend/src/Organize/OrganizePreviewModalContent.css delete mode 100644 frontend/src/Organize/OrganizePreviewModalContent.js delete mode 100644 frontend/src/Organize/OrganizePreviewModalContentConnector.js delete mode 100644 frontend/src/Organize/OrganizePreviewRow.css delete mode 100644 frontend/src/Organize/OrganizePreviewRow.js delete mode 100644 frontend/src/RootFolder/RootFolderRow.css delete mode 100644 frontend/src/RootFolder/RootFolderRow.js delete mode 100644 frontend/src/RootFolder/RootFolderRowConnector.js delete mode 100644 frontend/src/RootFolder/RootFolders.js delete mode 100644 frontend/src/RootFolder/RootFoldersConnector.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormatSettingsConnector.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.css delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/CustomFormats.css delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/CustomFormats.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/CustomFormatsConnector.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModal.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalConnector.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContent.css delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContent.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContentConnector.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModal.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContent.css delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContent.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContentConnector.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModal.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContent.css delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContent.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContentConnector.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationItem.css delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationItem.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModal.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.css delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContentConnector.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationPresetMenuItem.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModal.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalConnector.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.css delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContentConnector.js delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.css delete mode 100644 frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClientSettings.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClientSettingsConnector.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientItem.css delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientItem.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModal.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContent.css delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContent.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContentConnector.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientPresetMenuItem.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.css delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/DownloadClients.css delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/DownloadClients.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/DownloadClientsConnector.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModal.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalConnector.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.css delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.js delete mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContentConnector.js delete mode 100644 frontend/src/Settings/DownloadClients/Options/DownloadClientOptions.js delete mode 100644 frontend/src/Settings/DownloadClients/Options/DownloadClientOptionsConnector.js delete mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModal.js delete mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalConnector.js delete mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContent.css delete mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContent.js delete mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContentConnector.js delete mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMapping.css delete mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMapping.js delete mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappings.css delete mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappings.js delete mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappingsConnector.js delete mode 100644 frontend/src/Settings/Indexers/Restrictions/EditRestrictionModal.js delete mode 100644 frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalConnector.js delete mode 100644 frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContent.css delete mode 100644 frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContent.js delete mode 100644 frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContentConnector.js delete mode 100644 frontend/src/Settings/Indexers/Restrictions/Restriction.css delete mode 100644 frontend/src/Settings/Indexers/Restrictions/Restriction.js delete mode 100644 frontend/src/Settings/Indexers/Restrictions/Restrictions.css delete mode 100644 frontend/src/Settings/Indexers/Restrictions/Restrictions.js delete mode 100644 frontend/src/Settings/Indexers/Restrictions/RestrictionsConnector.js delete mode 100644 frontend/src/Settings/MediaManagement/MediaManagement.js delete mode 100644 frontend/src/Settings/MediaManagement/MediaManagementConnector.js delete mode 100644 frontend/src/Settings/MediaManagement/Naming/Naming.css delete mode 100644 frontend/src/Settings/MediaManagement/Naming/Naming.js delete mode 100644 frontend/src/Settings/MediaManagement/Naming/NamingConnector.js delete mode 100644 frontend/src/Settings/MediaManagement/Naming/NamingModal.css delete mode 100644 frontend/src/Settings/MediaManagement/Naming/NamingModal.js delete mode 100644 frontend/src/Settings/MediaManagement/Naming/NamingOption.css delete mode 100644 frontend/src/Settings/MediaManagement/Naming/NamingOption.js delete mode 100644 frontend/src/Settings/MediaManagement/RootFolder/AddRootFolder.css delete mode 100644 frontend/src/Settings/MediaManagement/RootFolder/AddRootFolder.js delete mode 100644 frontend/src/Settings/MediaManagement/RootFolder/AddRootFolderConnector.js delete mode 100644 frontend/src/Settings/Metadata/Metadata/EditMetadataModal.js delete mode 100644 frontend/src/Settings/Metadata/Metadata/EditMetadataModalConnector.js delete mode 100644 frontend/src/Settings/Metadata/Metadata/EditMetadataModalContent.js delete mode 100644 frontend/src/Settings/Metadata/Metadata/EditMetadataModalContentConnector.js delete mode 100644 frontend/src/Settings/Metadata/Metadata/Metadata.css delete mode 100644 frontend/src/Settings/Metadata/Metadata/Metadata.js delete mode 100644 frontend/src/Settings/Metadata/Metadata/Metadatas.css delete mode 100644 frontend/src/Settings/Metadata/Metadata/Metadatas.js delete mode 100644 frontend/src/Settings/Metadata/Metadata/MetadatasConnector.js delete mode 100644 frontend/src/Settings/Metadata/MetadataSettings.js delete mode 100644 frontend/src/Settings/Metadata/Options/MetadataOptions.js delete mode 100644 frontend/src/Settings/Metadata/Options/MetadataOptionsConnector.js delete mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfile.css delete mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfile.js delete mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css delete mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.js delete mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css delete mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.js delete mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfiles.css delete mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfiles.js delete mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfilesConnector.js delete mode 100644 frontend/src/Settings/Profiles/Delay/EditDelayProfileModal.js delete mode 100644 frontend/src/Settings/Profiles/Delay/EditDelayProfileModalConnector.js delete mode 100644 frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css delete mode 100644 frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js delete mode 100644 frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContentConnector.js delete mode 100644 frontend/src/Settings/Profiles/Profiles.css delete mode 100644 frontend/src/Settings/Profiles/Profiles.js delete mode 100644 frontend/src/Settings/Profiles/Quality/EditQualityProfileModal.js delete mode 100644 frontend/src/Settings/Profiles/Quality/EditQualityProfileModalConnector.js delete mode 100644 frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css delete mode 100644 frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.js delete mode 100644 frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContentConnector.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfile.css delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfile.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.css delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.css delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItem.css delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItem.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItems.css delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItems.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileNameConnector.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfiles.css delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfiles.js delete mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfilesConnector.js delete mode 100644 frontend/src/Store/Actions/Settings/customFormatSpecifications.js delete mode 100644 frontend/src/Store/Actions/Settings/customFormats.js delete mode 100644 frontend/src/Store/Actions/Settings/delayProfiles.js delete mode 100644 frontend/src/Store/Actions/Settings/downloadClientOptions.js delete mode 100644 frontend/src/Store/Actions/Settings/downloadClients.js delete mode 100644 frontend/src/Store/Actions/Settings/mediaManagement.js delete mode 100644 frontend/src/Store/Actions/Settings/metadata.js delete mode 100644 frontend/src/Store/Actions/Settings/metadataOptions.js delete mode 100644 frontend/src/Store/Actions/Settings/naming.js delete mode 100644 frontend/src/Store/Actions/Settings/namingExamples.js delete mode 100644 frontend/src/Store/Actions/Settings/qualityDefinitions.js delete mode 100644 frontend/src/Store/Actions/Settings/qualityProfiles.js delete mode 100644 frontend/src/Store/Actions/Settings/remotePathMappings.js delete mode 100644 frontend/src/Store/Actions/Settings/restrictions.js delete mode 100644 frontend/src/Store/Actions/addMovieActions.js delete mode 100644 frontend/src/Store/Actions/blacklistActions.js delete mode 100644 frontend/src/Store/Actions/extraFileActions.js delete mode 100644 frontend/src/Store/Actions/importMovieActions.js delete mode 100644 frontend/src/Store/Actions/interactiveImportActions.js delete mode 100644 frontend/src/Store/Actions/movieBlacklistActions.js delete mode 100644 frontend/src/Store/Actions/movieCreditsActions.js delete mode 100644 frontend/src/Store/Actions/movieFileActions.js delete mode 100644 frontend/src/Store/Actions/movieHistoryActions.js delete mode 100644 frontend/src/Store/Actions/organizePreviewActions.js delete mode 100644 frontend/src/Store/Actions/queueActions.js delete mode 100644 frontend/src/Store/Actions/rootFolderActions.js delete mode 100644 frontend/src/Store/Selectors/createDiscoverMovieClientSideCollectionItemsSelector.js delete mode 100644 frontend/src/Store/Selectors/createDiscoverMovieSelector.js delete mode 100644 frontend/src/Store/Selectors/createMovieFileSelector.js delete mode 100644 frontend/src/Store/Selectors/createMovieQualityProfileSelector.js delete mode 100644 frontend/src/Store/Selectors/createProfileInUseSelector.js delete mode 100644 frontend/src/Store/Selectors/createQualityProfileSelector.js delete mode 100644 frontend/src/Store/Selectors/createQueueItemSelector.js delete mode 100644 frontend/src/System/Status/DiskSpace/DiskSpace.css delete mode 100644 frontend/src/System/Status/DiskSpace/DiskSpace.js delete mode 100644 frontend/src/System/Status/DiskSpace/DiskSpaceConnector.js delete mode 100644 src/NzbDrone.Core/Restrictions/PerlRegexFactory.cs delete mode 100644 src/NzbDrone.Core/Restrictions/Restriction.cs delete mode 100644 src/NzbDrone.Core/Restrictions/RestrictionRepository.cs delete mode 100644 src/NzbDrone.Core/Restrictions/RestrictionService.cs delete mode 100644 src/NzbDrone.Core/Restrictions/TermMatcher.cs delete mode 100644 src/Prowlarr.Api.V1/Restrictions/RestrictionModule.cs delete mode 100644 src/Prowlarr.Api.V1/Restrictions/RestrictionResource.cs diff --git a/.gitchangelog.rc b/.gitchangelog.rc deleted file mode 100644 index aee317954..000000000 --- a/.gitchangelog.rc +++ /dev/null @@ -1,305 +0,0 @@ -# -*- coding: utf-8; mode: python -*- -## -## Format -## -## ACTION: [AUDIENCE:] COMMIT_MSG [!TAG ...] -## -## Description -## -## ACTION is one of 'chg', 'fix', 'new' -## -## Is WHAT the change is about. -## -## 'chg' is for refactor, small improvement, cosmetic changes... -## 'fix' is for bug fixes -## 'new' is for new features, big improvement -## -## AUDIENCE is optional and one of 'dev', 'usr', 'pkg', 'test', 'doc' -## -## Is WHO is concerned by the change. -## -## 'dev' is for developpers (API changes, refactors...) -## 'usr' is for final users (UI changes) -## 'pkg' is for packagers (packaging changes) -## 'test' is for testers (test only related changes) -## 'doc' is for doc guys (doc only changes) -## -## COMMIT_MSG is ... well ... the commit message itself. -## -## TAGs are additionnal adjective as 'refactor' 'minor' 'cosmetic' -## -## They are preceded with a '!' or a '@' (prefer the former, as the -## latter is wrongly interpreted in github.) Commonly used tags are: -## -## 'refactor' is obviously for refactoring code only -## 'minor' is for a very meaningless change (a typo, adding a comment) -## 'cosmetic' is for cosmetic driven change (re-indentation, 80-col...) -## 'wip' is for partial functionality but complete subfunctionality. -## -## Example: -## -## new: usr: support of bazaar implemented -## chg: re-indentend some lines !cosmetic -## new: dev: updated code to be compatible with last version of killer lib. -## fix: pkg: updated year of licence coverage. -## new: test: added a bunch of test around user usability of feature X. -## fix: typo in spelling my name in comment. !minor -## -## Please note that multi-line commit message are supported, and only the -## first line will be considered as the "summary" of the commit message. So -## tags, and other rules only applies to the summary. The body of the commit -## message will be displayed in the changelog without reformatting. - - -## -## ``ignore_regexps`` is a line of regexps -## -## Any commit having its full commit message matching any regexp listed here -## will be ignored and won't be reported in the changelog. -## -ignore_regexps = [ - r'@minor', r'!minor', - r'@cosmetic', r'!cosmetic', - r'@refactor', r'!refactor', - r'@wip', r'!wip', - r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:', - r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:', - r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$', - r'^$', ## ignore commits with empty messages -] - - -## ``section_regexps`` is a list of 2-tuples associating a string label and a -## list of regexp -## -## Commit messages will be classified in sections thanks to this. Section -## titles are the label, and a commit is classified under this section if any -## of the regexps associated is matching. -## -## Please note that ``section_regexps`` will only classify commits and won't -## make any changes to the contents. So you'll probably want to go check -## ``subject_process`` (or ``body_process``) to do some changes to the subject, -## whenever you are tweaking this variable. -## -section_regexps = [ - ('**New features**', [ - r'^[aA]dded?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?(.*)$', - r'^[uU]pdated?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', - r'^[cC]hanged?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', - r'^[nN]ew?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', - ]), - ('**Fixes**', [ - r'^(?![mM]erge\s*)' - ] - ), - -] - - -## ``body_process`` is a callable -## -## This callable will be given the original body and result will -## be used in the changelog. -## -## Available constructs are: -## -## - any python callable that take one txt argument and return txt argument. -## -## - ReSub(pattern, replacement): will apply regexp substitution. -## -## - Indent(chars=" "): will indent the text with the prefix -## Please remember that template engines gets also to modify the text and -## will usually indent themselves the text if needed. -## -## - Wrap(regexp=r"\n\n"): re-wrap text in separate paragraph to fill 80-Columns -## -## - noop: do nothing -## -## - ucfirst: ensure the first letter is uppercase. -## (usually used in the ``subject_process`` pipeline) -## -## - final_dot: ensure text finishes with a dot -## (usually used in the ``subject_process`` pipeline) -## -## - strip: remove any spaces before or after the content of the string -## -## - SetIfEmpty(msg="No commit message."): will set the text to -## whatever given ``msg`` if the current text is empty. -## -## Additionally, you can `pipe` the provided filters, for instance: -#body_process = Wrap(regexp=r'\n(?=\w+\s*:)') | Indent(chars=" ") -#body_process = Wrap(regexp=r'\n(?=\w+\s*:)') -#body_process = noop -body_process = ReSub(r'((^|\n)[A-Z]\w+(-\w+)*: .*(\n\s+.*)*)+$', r'') | strip - - -## ``subject_process`` is a callable -## -## This callable will be given the original subject and result will -## be used in the changelog. -## subject_process = (strip | -## ReSub(r'^([aA]dd(ed?)?|[nN]ew)(\s?:?\s)(.*)$', r'![New](https://img.shields.io/badge/-- -New-brightgreen.svg?style=flat-square) \4') | -## ReSub(r'^([cC]hang(ed?)?)(\s?:?\s)(.*)$', r'![Changed](https://img.shields.io/badge/-- -Changed-orange.svg?style=flat-square) \4') | -## ReSub(r'^([fF]ix(ed?)?)(\s?:?\s)(.*)$', r'![Fixed](https://img.shields.io/badge/-- -Fixed-red.svg?style=flat-square) \4') | -## ReSub(r'^([uU]pdat(ed?)?)(\s?:?\s)(.*)$', r'![Updated](https://img.shields.io/badge/-- -Updated-blue.svg?style=flat-square) \4') | -## ReSub(r'#(\d{3,4})', r'[#\1](https://github.com/Prowlarr/Prowlarr/issues/\1)') | -## SetIfEmpty("No commit message.") | ucfirst | final_dot) - -## Available constructs are those listed in ``body_process`` doc. -subject_process = (strip | - ReSub(r'^([aA]dd(ed?)?|[nN]ew)(\s?:?\s)(.*)$', r'![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) \4') | - ReSub(r'^([cC]hang(ed?)?)(\s?:?\s)(.*)$', r'![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) \4') | - ReSub(r'^([fF]ix(ed?)?)(\s?:?\s)(.*)$', r'![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) \4') | - ReSub(r'^([uU]pdat(ed?)?)(\s?:?\s)(.*)$', r'![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) \4') | - ReSub(r'#(\d{3,4})', r'[#\1](https://github.com/Prowlarr/Prowlarr/issues/\1)') | - SetIfEmpty("No commit message.") | ucfirst | final_dot) - - -## ``tag_filter_regexp`` is a regexp -## -## Tags that will be used for the changelog must match this regexp. -## -tag_filter_regexp = r'^v[0]+\.[2-9]+\.[0-9]+\.[0-9]{3,4}$' - - -## ``unreleased_version_label`` is a string or a callable that outputs a string -## -## This label will be used as the changelog Title of the last set of changes -## between last valid tag and HEAD if any. -unreleased_version_label = "(unreleased)" - - -## ``output_engine`` is a callable -## -## This will change the output format of the generated changelog file -## -## Available choices are: -## -## - rest_py -## -## Legacy pure python engine, outputs ReSTructured text. -## This is the default. -## -## - mustache() -## -## Template name could be any of the available templates in -## ``templates/mustache/*.tpl``. -## Requires python package ``pystache``. -## Examples: -## - mustache("markdown") -## - mustache("restructuredtext") -## -## - makotemplate() -## -## Template name could be any of the available templates in -## ``templates/mako/*.tpl``. -## Requires python package ``mako``. -## Examples: -## - makotemplate("restructuredtext") -## -#output_engine = rest_py -#output_engine = mustache("restructuredtext") -output_engine = mustache("changelog.tpl") -#output_engine = makotemplate("restructuredtext") - - -## ``include_merge`` is a boolean -## -## This option tells git-log whether to include merge commits in the log. -## The default is to include them. -include_merge = False - - -## ``log_encoding`` is a string identifier -## -## This option tells gitchangelog what encoding is outputed by ``git log``. -## The default is to be clever about it: it checks ``git config`` for -## ``i18n.logOutputEncoding``, and if not found will default to git's own -## default: ``utf-8``. -#log_encoding = 'utf-8' - - -## ``publish`` is a callable -## -## Sets what ``gitchangelog`` should do with the output generated by -## the output engine. ``publish`` is a callable taking one argument -## that is an interator on lines from the output engine. -## -## Some helper callable are provided: -## -## Available choices are: -## -## - stdout -## -## Outputs directly to standard output -## (This is the default) -## -## - FileInsertAtFirstRegexMatch(file, pattern, idx=lamda m: m.start()) -## -## Creates a callable that will parse given file for the given -## regex pattern and will insert the output in the file. -## ``idx`` is a callable that receive the matching object and -## must return a integer index point where to insert the -## the output in the file. Default is to return the position of -## the start of the matched string. -## -## - FileRegexSubst(file, pattern, replace, flags) -## -## Apply a replace inplace in the given file. Your regex pattern must -## take care of everything and might be more complex. Check the README -## for a complete copy-pastable example. -## -# publish = FileInsertIntoFirstRegexMatch( -# "CHANGELOG.rst", -# r'/(?P[0-9]+\.[0-9]+(\.[0-9]+)?)\s+\([0-9]+-[0-9]{2}-[0-9]{2}\)\n--+\n/', -# idx=lambda m: m.start(1) -# ) -#publish = stdout - -def write_to_file(content): - with open("CHANGELOG.md", "w+") as f: - for chunk in content: - f.write(chunk) - -publish = write_to_file - - -## ``revs`` is a list of callable or a list of string -## -## callable will be called to resolve as strings and allow dynamical -## computation of these. The result will be used as revisions for -## gitchangelog (as if directly stated on the command line). This allows -## to filter exaclty which commits will be read by gitchangelog. -## -## To get a full documentation on the format of these strings, please -## refer to the ``git rev-list`` arguments. There are many examples. -## -## Using callables is especially useful, for instance, if you -## are using gitchangelog to generate incrementally your changelog. -## -## Some helpers are provided, you can use them:: -## -## - FileFirstRegexMatch(file, pattern): will return a callable that will -## return the first string match for the given pattern in the given file. -## If you use named sub-patterns in your regex pattern, it'll output only -## the string matching the regex pattern named "rev". -## -## - Caret(rev): will return the rev prefixed by a "^", which is a -## way to remove the given revision and all its ancestor. -## -## Please note that if you provide a rev-list on the command line, it'll -## replace this value (which will then be ignored). -## -## If empty, then ``gitchangelog`` will act as it had to generate a full -## changelog. -## -## The default is to use all commits to make the changelog. -#revs = ["^1.0.3", ] -#revs = [ -# Caret( -# FileFirstRegexMatch( -# "CHANGELOG.rst", -# r"(?P[0-9]+\.[0-9]+(\.[0-9]+)?)\s+\([0-9]+-[0-9]{2}-[0-9]{2}\)\n--+\n")), -# "HEAD" -#] -revs = ["v0.2.0.134..."] diff --git a/.gitchangelog.rc.release b/.gitchangelog.rc.release deleted file mode 100644 index 7e0071f74..000000000 --- a/.gitchangelog.rc.release +++ /dev/null @@ -1,311 +0,0 @@ -# -*- coding: utf-8; mode: python -*- -## -## Format -## -## ACTION: [AUDIENCE:] COMMIT_MSG [!TAG ...] -## -## Description -## -## ACTION is one of 'chg', 'fix', 'new' -## -## Is WHAT the change is about. -## -## 'chg' is for refactor, small improvement, cosmetic changes... -## 'fix' is for bug fixes -## 'new' is for new features, big improvement -## -## AUDIENCE is optional and one of 'dev', 'usr', 'pkg', 'test', 'doc' -## -## Is WHO is concerned by the change. -## -## 'dev' is for developpers (API changes, refactors...) -## 'usr' is for final users (UI changes) -## 'pkg' is for packagers (packaging changes) -## 'test' is for testers (test only related changes) -## 'doc' is for doc guys (doc only changes) -## -## COMMIT_MSG is ... well ... the commit message itself. -## -## TAGs are additionnal adjective as 'refactor' 'minor' 'cosmetic' -## -## They are preceded with a '!' or a '@' (prefer the former, as the -## latter is wrongly interpreted in github.) Commonly used tags are: -## -## 'refactor' is obviously for refactoring code only -## 'minor' is for a very meaningless change (a typo, adding a comment) -## 'cosmetic' is for cosmetic driven change (re-indentation, 80-col...) -## 'wip' is for partial functionality but complete subfunctionality. -## -## Example: -## -## new: usr: support of bazaar implemented -## chg: re-indentend some lines !cosmetic -## new: dev: updated code to be compatible with last version of killer lib. -## fix: pkg: updated year of licence coverage. -## new: test: added a bunch of test around user usability of feature X. -## fix: typo in spelling my name in comment. !minor -## -## Please note that multi-line commit message are supported, and only the -## first line will be considered as the "summary" of the commit message. So -## tags, and other rules only applies to the summary. The body of the commit -## message will be displayed in the changelog without reformatting. - - -## -## ``ignore_regexps`` is a line of regexps -## -## Any commit having its full commit message matching any regexp listed here -## will be ignored and won't be reported in the changelog. -## -ignore_regexps = [ - r'@minor', r'!minor', - r'@cosmetic', r'!cosmetic', - r'@refactor', r'!refactor', - r'@wip', r'!wip', - r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:', - r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:', - r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$', - r'^$', ## ignore commits with empty messages -] - - -## ``section_regexps`` is a list of 2-tuples associating a string label and a -## list of regexp -## -## Commit messages will be classified in sections thanks to this. Section -## titles are the label, and a commit is classified under this section if any -## of the regexps associated is matching. -## -## Please note that ``section_regexps`` will only classify commits and won't -## make any changes to the contents. So you'll probably want to go check -## ``subject_process`` (or ``body_process``) to do some changes to the subject, -## whenever you are tweaking this variable. -## -section_regexps = [ - ('**New features:**', [ - r'^[aA]dded?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', - r'^[uU]pdated?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', - r'^[cC]hanged?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', - r'^[nN]ew?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$', - ]), - ('**Fixes:**', [ - r'^(?![mM]erge\s*)' - ] - ), - -] - - -## ``body_process`` is a callable -## -## This callable will be given the original body and result will -## be used in the changelog. -## -## Available constructs are: -## -## - any python callable that take one txt argument and return txt argument. -## -## - ReSub(pattern, replacement): will apply regexp substitution. -## -## - Indent(chars=" "): will indent the text with the prefix -## Please remember that template engines gets also to modify the text and -## will usually indent themselves the text if needed. -## -## - Wrap(regexp=r"\n\n"): re-wrap text in separate paragraph to fill 80-Columns -## -## - noop: do nothing -## -## - ucfirst: ensure the first letter is uppercase. -## (usually used in the ``subject_process`` pipeline) -## -## - final_dot: ensure text finishes with a dot -## (usually used in the ``subject_process`` pipeline) -## -## - strip: remove any spaces before or after the content of the string -## -## - SetIfEmpty(msg="No commit message."): will set the text to -## whatever given ``msg`` if the current text is empty. -## -## Additionally, you can `pipe` the provided filters, for instance: -#body_process = Wrap(regexp=r'\n(?=\w+\s*:)') | Indent(chars=" ") -#body_process = Wrap(regexp=r'\n(?=\w+\s*:)') -#body_process = noop -body_process = ReSub(r'((^|\n)[A-Z]\w+(-\w+)*: .*(\n\s+.*)*)+$', r'') | strip - - -## ``subject_process`` is a callable -## -## This callable will be given the original subject and result will -## be used in the changelog. -## subject_process = (strip | -## ReSub(r'^([aA]dd(ed?)?|[nN]ew)(\s?:?\s)(.*)$', r'![New](https://img.shields.io/badge/-- -New-brightgreen.svg?style=flat-square) \4') | -## ReSub(r'^([cC]hang(ed?)?)(\s?:?\s)(.*)$', r'![Changed](https://img.shields.io/badge/-- -Changed-orange.svg?style=flat-square) \4') | -## ReSub(r'^([fF]ix(ed?)?)(\s?:?\s)(.*)$', r'![Fixed](https://img.shields.io/badge/-- -Fixed-red.svg?style=flat-square) \4') | -## ReSub(r'^([uU]pdat(ed?)?)(\s?:?\s)(.*)$', r'![Updated](https://img.shields.io/badge/-- -Updated-blue.svg?style=flat-square) \4') | -## ReSub(r'#(\d{3,4})', r'[#\1](https://github.com/Prowlarr/Prowlarr/issues/\1)') | -## SetIfEmpty("No commit message.") | ucfirst | final_dot) - -## Available constructs are those listed in ``body_process`` doc. -subject_process = (strip | - ReSub(r'^([aA]dd(ed?)?|[nN]ew)(\s?:?\s)(.*)$', r'\4') | - ReSub(r'^([cC]hang(ed?)?)(\s?:?\s)(.*)$', r'\4') | - ReSub(r'^([fF]ix(ed?)?)(\s?:?\s)(.*)$', r'\4') | - ReSub(r'^([uU]pdat(ed?)?)(\s?:?\s)(.*)$', r'\4') | - ReSub(r'#(\d{3,4})', r'Issue #\1') | - SetIfEmpty("No commit message.") | ucfirst | final_dot) - - -## ``tag_filter_regexp`` is a regexp -## -## Tags that will be used for the changelog must match this regexp. -## -tag_filter_regexp = r'^v[0]+\.[2-9]+\.[0-9]+\.[0-9]+$' - - -## ``unreleased_version_label`` is a string or a callable that outputs a string -## -## This label will be used as the changelog Title of the last set of changes -## between last valid tag and HEAD if any. -unreleased_version_label = "(unreleased)" - - -## ``output_engine`` is a callable -## -## This will change the output format of the generated changelog file -## -## Available choices are: -## -## - rest_py -## -## Legacy pure python engine, outputs ReSTructured text. -## This is the default. -## -## - mustache() -## -## Template name could be any of the available templates in -## ``templates/mustache/*.tpl``. -## Requires python package ``pystache``. -## Examples: -## - mustache("markdown") -## - mustache("restructuredtext") -## -## - makotemplate() -## -## Template name could be any of the available templates in -## ``templates/mako/*.tpl``. -## Requires python package ``mako``. -## Examples: -## - makotemplate("restructuredtext") -## -#output_engine = rest_py -#output_engine = mustache("restructuredtext") -output_engine = mustache("changelog_release.tpl") -#output_engine = makotemplate("restructuredtext") - - -## ``include_merge`` is a boolean -## -## This option tells git-log whether to include merge commits in the log. -## The default is to include them. -include_merge = False - - -## ``log_encoding`` is a string identifier -## -## This option tells gitchangelog what encoding is outputed by ``git log``. -## The default is to be clever about it: it checks ``git config`` for -## ``i18n.logOutputEncoding``, and if not found will default to git's own -## default: ``utf-8``. -#log_encoding = 'utf-8' - - -## ``publish`` is a callable -## -## Sets what ``gitchangelog`` should do with the output generated by -## the output engine. ``publish`` is a callable taking one argument -## that is an interator on lines from the output engine. -## -## Some helper callable are provided: -## -## Available choices are: -## -## - stdout -## -## Outputs directly to standard output -## (This is the default) -## -## - FileInsertAtFirstRegexMatch(file, pattern, idx=lamda m: m.start()) -## -## Creates a callable that will parse given file for the given -## regex pattern and will insert the output in the file. -## ``idx`` is a callable that receive the matching object and -## must return a integer index point where to insert the -## the output in the file. Default is to return the position of -## the start of the matched string. -## -## - FileRegexSubst(file, pattern, replace, flags) -## -## Apply a replace inplace in the given file. Your regex pattern must -## take care of everything and might be more complex. Check the README -## for a complete copy-pastable example. -## -# publish = FileInsertIntoFirstRegexMatch( -# "CHANGELOG.rst", -# r'/(?P[0-9]+\.[0-9]+(\.[0-9]+)?)\s+\([0-9]+-[0-9]{2}-[0-9]{2}\)\n--+\n/', -# idx=lambda m: m.start(1) -# ) -publish = stdout - -#def write_to_file(content): -# with open("CHANGELOG.md", "w+") as f: -# for chunk in content: -# f.write(chunk) - -#publish = write_to_file - - -## ``revs`` is a list of callable or a list of string -## -## callable will be called to resolve as strings and allow dynamical -## computation of these. The result will be used as revisions for -## gitchangelog (as if directly stated on the command line). This allows -## to filter exaclty which commits will be read by gitchangelog. -## -## To get a full documentation on the format of these strings, please -## refer to the ``git rev-list`` arguments. There are many examples. -## -## Using callables is especially useful, for instance, if you -## are using gitchangelog to generate incrementally your changelog. -## -## Some helpers are provided, you can use them:: -## -## - FileFirstRegexMatch(file, pattern): will return a callable that will -## return the first string match for the given pattern in the given file. -## If you use named sub-patterns in your regex pattern, it'll output only -## the string matching the regex pattern named "rev". -## -## - Caret(rev): will return the rev prefixed by a "^", which is a -## way to remove the given revision and all its ancestor. -## -## Please note that if you provide a rev-list on the command line, it'll -## replace this value (which will then be ignored). -## -## If empty, then ``gitchangelog`` will act as it had to generate a full -## changelog. -## -## The default is to use all commits to make the changelog. -#revs = ["^1.0.3", ] -#revs = [ -# Caret( -# FileFirstRegexMatch( -# "CHANGELOG.rst", -# r"(?P[0-9]+\.[0-9]+(\.[0-9]+)?)\s+\([0-9]+-[0-9]{2}-[0-9]{2}\)\n--+\n")), -# "HEAD" -#] -# Gets the latest annoted tag and uses that as a base for new changes. - -import subprocess - -proc = subprocess.Popen(["git", "describe", "--abbrev=0", "--tags"], stdout=subprocess.PIPE) -out = str(proc.communicate()[0].strip(), "utf-8") -revs = [out+"..."] diff --git a/.gitignore b/.gitignore index abccf45c9..11a1b4059 100644 --- a/.gitignore +++ b/.gitignore @@ -139,9 +139,9 @@ artifacts/ **/Properties/launchSettings.json # Packages -Radarr_*/ -Radarr_*.zip -Radarr_*.gz +Prowlarr_*/ +Prowlarr_*.zip +Prowlarr_*.gz gecko.zip geckodriver.exe diff --git a/README.md b/README.md index c5cd4adac..e8d4c73ed 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # Prowlarr -Prowlarr is a indexer manager/proxy built on the popular arr .net base stack to integrate with your various PVR apps. Prowlarr supports both Torrent and Usenet indexers and integrates seamlessly with Sonarr, Radarr, Lidarr, Readarr offering complete management of your indexers with no per app Indexer setup required (we do it all). +Prowlarr is a indexer manager/proxy built on the popular arr .net base stack to integrate with your various PVR apps. Prowlarr supports both Torrent and Usenet indexers and integrates seamlessly with Sonarr, Prowlarr, Lidarr, Readarr offering complete management of your indexers with no per app Indexer setup required (we do it all). diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 807cfeeeb..5c4476851 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -7,13 +7,13 @@ variables: outputFolder: './_output' artifactsFolder: './_artifacts' testsFolder: './_tests' - majorVersion: '3.0.0' - minorVersion: $[counter('minorVersion', 2000)] - radarrVersion: '$(majorVersion).$(minorVersion)' - buildName: '$(Build.SourceBranchName).$(radarrVersion)' + majorVersion: '0.1.0' + minorVersion: $[counter('minorVersion', 1)] + prowlarrVersion: '$(majorVersion).$(minorVersion)' + buildName: '$(Build.SourceBranchName).$(prowlarrVersion)' sentryOrg: 'servarr' sentryUrl: 'https://sentry.servarr.com' - dotnetVersion: '3.1.401' + dotnetVersion: '3.1.403' yarnCacheFolder: $(Pipeline.Workspace)/.yarn trigger: @@ -35,7 +35,7 @@ stages: vmImage: 'ubuntu-18.04' steps: # Set the build name properly. The 'name' property won't recursively expand so hack here: - - bash: echo "##vso[build.updatebuildnumber]$RADARRVERSION" + - bash: echo "##vso[build.updatebuildnumber]$PROWLARRVERSION" displayName: Set Build Name - bash: | if [[ $BUILD_REASON == "PullRequest" ]]; then @@ -297,7 +297,7 @@ stages: - bash: | echo "Uploading source maps to sentry" curl -sL https://sentry.io/get-cli/ | bash - RELEASENAME="${RADARRVERSION}-${BUILD_SOURCEBRANCHNAME}" + RELEASENAME="${PROWLARRVERSION}-${BUILD_SOURCEBRANCHNAME}" sentry-cli releases new --finalize -p prowlarr -p prowlarr-ui -p prowlarr-update "${RELEASENAME}" sentry-cli releases -p prowlarr-ui files "${RELEASENAME}" upload-sourcemaps _output/UI/ --rewrite sentry-cli releases set-commits --auto "${RELEASENAME}" @@ -376,13 +376,6 @@ stages: buildType: 'current' artifactName: '$(testName)Tests' targetPath: $(testsFolder) - - bash: | - wget https://mediaarea.net/repo/deb/repo-mediaarea_1.0-11_all.deb - sudo dpkg -i repo-mediaarea_1.0-11_all.deb - sudo apt-get update - sudo apt-get install -y --allow-unauthenticated libmediainfo-dev libmediainfo0v5 mediainfo - displayName: Install mediainfo - condition: and(succeeded(), eq(variables['osName'], 'Linux')) - powershell: Set-Service SCardSvr -StartupType Manual displayName: Enable Windows Test Service condition: and(succeeded(), eq(variables['osName'], 'Windows')) @@ -764,27 +757,6 @@ stages: FORCE_COLOR: 0 YARN_CACHE_FOLDER: $(yarnCacheFolder) - - job: Analyze_Frontend - displayName: Frontend - condition: eq(variables['System.PullRequest.IsFork'], 'False') - pool: - vmImage: windows-2019 - steps: - - checkout: self # Need history for Sonar analysis - - task: SonarCloudPrepare@1 - env: - SONAR_SCANNER_OPTS: '' - inputs: - SonarCloud: 'SonarCloud' - organization: 'prowlarr' - scannerMode: 'CLI' - configMode: 'manual' - cliProjectKey: 'Radarr_Radarr.UI' - cliProjectName: 'RadarrUI' - cliProjectVersion: '$(radarrVersion)' - cliSources: './frontend' - - task: SonarCloudAnalyze@1 - - job: Analyze_Backend displayName: Backend dependsOn: Prepare @@ -805,27 +777,10 @@ stages: submodules: true - powershell: Set-Service SCardSvr -StartupType Manual displayName: Enable Windows Test Service - - task: SonarCloudPrepare@1 - condition: eq(variables['System.PullRequest.IsFork'], 'False') - inputs: - SonarCloud: 'SonarCloud' - organization: 'prowlarr' - scannerMode: 'MSBuild' - projectKey: 'Radarr_Radarr' - projectName: 'Prowlarr' - projectVersion: '$(radarrVersion)' - extraProperties: | - sonar.exclusions=**/obj/**,**/*.dll,**/NzbDrone.Core.Test/Files/**/*,./frontend/**,**/ExternalModules/**,./src/Libraries/** - sonar.coverage.exclusions=**/Prowlarr.Api.V1/**/*,**/NzbDrone.Api/**/*,**/MonoTorrent/**/*,**/Marr.Data/**/* - sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml - sonar.cs.nunit.reportsPaths=$(Build.SourcesDirectory)/TestResult.xml - bash: | ./build.sh --backend -f netcoreapp3.1 -r win-x64 TEST_DIR=_tests/netcoreapp3.1/win-x64/publish/ ./test.sh Windows Unit Coverage displayName: Coverage Unit Tests - - task: SonarCloudAnalyze@1 - condition: eq(variables['System.PullRequest.IsFork'], 'False') - displayName: Publish SonarCloud Results - task: reportgenerator@4 displayName: Generate Coverage Report inputs: diff --git a/build.sh b/build.sh index 329e66707..c27bc4c61 100755 --- a/build.sh +++ b/build.sh @@ -17,11 +17,11 @@ ProgressEnd() UpdateVersionNumber() { - if [ "$RADARRVERSION" != "" ]; then + if [ "$PROWLARRVERSION" != "" ]; then echo "Updating Version Info" - sed -i'' -e "s/[0-9.*]\+<\/AssemblyVersion>/$RADARRVERSION<\/AssemblyVersion>/g" src/Directory.Build.props + sed -i'' -e "s/[0-9.*]\+<\/AssemblyVersion>/$PROWLARRVERSION<\/AssemblyVersion>/g" src/Directory.Build.props sed -i'' -e "s/[\$()A-Za-z-]\+<\/AssemblyConfiguration>/${BUILD_SOURCEBRANCHNAME}<\/AssemblyConfiguration>/g" src/Directory.Build.props - sed -i'' -e "s/10.0.0.0<\/string>/$RADARRVERSION<\/string>/g" macOS/Prowlarr.app/Contents/Info.plist + sed -i'' -e "s/10.0.0.0<\/string>/$PROWLARRVERSION<\/string>/g" macOS/Prowlarr.app/Contents/Info.plist fi } diff --git a/frontend/src/Activity/Blacklist/Blacklist.js b/frontend/src/Activity/Blacklist/Blacklist.js deleted file mode 100644 index 34b274a29..000000000 --- a/frontend/src/Activity/Blacklist/Blacklist.js +++ /dev/null @@ -1,235 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import PageToolbar from 'Components/Page/Toolbar/PageToolbar'; -import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton'; -import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection'; -import Table from 'Components/Table/Table'; -import TableBody from 'Components/Table/TableBody'; -import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper'; -import TablePager from 'Components/Table/TablePager'; -import { align, icons, kinds } from 'Helpers/Props'; -import getRemovedItems from 'Utilities/Object/getRemovedItems'; -import hasDifferentItems from 'Utilities/Object/hasDifferentItems'; -import translate from 'Utilities/String/translate'; -import getSelectedIds from 'Utilities/Table/getSelectedIds'; -import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState'; -import selectAll from 'Utilities/Table/selectAll'; -import toggleSelected from 'Utilities/Table/toggleSelected'; -import BlacklistRowConnector from './BlacklistRowConnector'; - -class Blacklist extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - allSelected: false, - allUnselected: false, - lastToggled: null, - selectedState: {}, - isConfirmRemoveModalOpen: false, - items: props.items - }; - } - - componentDidUpdate(prevProps) { - const { - items - } = this.props; - - if (hasDifferentItems(prevProps.items, items)) { - this.setState((state) => { - return { - ...removeOldSelectedState(state, getRemovedItems(prevProps.items, items)), - items - }; - }); - - return; - } - } - - // - // Control - - getSelectedIds = () => { - return getSelectedIds(this.state.selectedState); - } - - // - // Listeners - - onSelectAllChange = ({ value }) => { - this.setState(selectAll(this.state.selectedState, value)); - } - - onSelectedChange = ({ id, value, shiftKey = false }) => { - this.setState((state) => { - return toggleSelected(state, this.props.items, id, value, shiftKey); - }); - } - - onRemoveSelectedPress = () => { - this.setState({ isConfirmRemoveModalOpen: true }); - } - - onRemoveSelectedConfirmed = () => { - this.props.onRemoveSelected(this.getSelectedIds()); - this.setState({ isConfirmRemoveModalOpen: false }); - } - - onConfirmRemoveModalClose = () => { - this.setState({ isConfirmRemoveModalOpen: false }); - } - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - items, - columns, - totalRecords, - isRemoving, - isClearingBlacklistExecuting, - onClearBlacklistPress, - ...otherProps - } = this.props; - - const { - allSelected, - allUnselected, - selectedState, - isConfirmRemoveModalOpen - } = this.state; - - const selectedIds = this.getSelectedIds(); - - return ( - - - - - - - - - - - - - - - - - { - isFetching && !isPopulated && - - } - - { - !isFetching && !!error && -
- {translate('UnableToLoadBlacklist')} -
- } - - { - isPopulated && !error && !items.length && -
- {translate('NoHistory')} -
- } - - { - isPopulated && !error && !!items.length && -
- - - { - items.map((item) => { - return ( - - ); - }) - } - -
- - -
- } -
- - -
- ); - } -} - -Blacklist.propTypes = { - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - columns: PropTypes.arrayOf(PropTypes.object).isRequired, - totalRecords: PropTypes.number, - isRemoving: PropTypes.bool.isRequired, - isClearingBlacklistExecuting: PropTypes.bool.isRequired, - onRemoveSelected: PropTypes.func.isRequired, - onClearBlacklistPress: PropTypes.func.isRequired -}; - -export default Blacklist; diff --git a/frontend/src/Activity/Blacklist/BlacklistConnector.js b/frontend/src/Activity/Blacklist/BlacklistConnector.js deleted file mode 100644 index 737f4eb82..000000000 --- a/frontend/src/Activity/Blacklist/BlacklistConnector.js +++ /dev/null @@ -1,160 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import * as commandNames from 'Commands/commandNames'; -import withCurrentPage from 'Components/withCurrentPage'; -import * as blacklistActions from 'Store/Actions/blacklistActions'; -import { executeCommand } from 'Store/Actions/commandActions'; -import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector'; -import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; -import Blacklist from './Blacklist'; - -function createMapStateToProps() { - return createSelector( - (state) => state.blacklist, - createCommandExecutingSelector(commandNames.CLEAR_BLACKLIST), - (blacklist, isClearingBlacklistExecuting) => { - return { - isClearingBlacklistExecuting, - ...blacklist - }; - } - ); -} - -const mapDispatchToProps = { - ...blacklistActions, - executeCommand -}; - -class BlacklistConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - useCurrentPage, - fetchBlacklist, - gotoBlacklistFirstPage - } = this.props; - - registerPagePopulator(this.repopulate); - - if (useCurrentPage) { - fetchBlacklist(); - } else { - gotoBlacklistFirstPage(); - } - } - - componentDidUpdate(prevProps) { - if (prevProps.isClearingBlacklistExecuting && !this.props.isClearingBlacklistExecuting) { - this.props.gotoBlacklistFirstPage(); - } - } - - componentWillUnmount() { - this.props.clearBlacklist(); - unregisterPagePopulator(this.repopulate); - } - - // - // Control - - repopulate = () => { - this.props.fetchBlacklist(); - } - // - // Listeners - - onFirstPagePress = () => { - this.props.gotoBlacklistFirstPage(); - } - - onPreviousPagePress = () => { - this.props.gotoBlacklistPreviousPage(); - } - - onNextPagePress = () => { - this.props.gotoBlacklistNextPage(); - } - - onLastPagePress = () => { - this.props.gotoBlacklistLastPage(); - } - - onPageSelect = (page) => { - this.props.gotoBlacklistPage({ page }); - } - - onRemoveSelected = (ids) => { - this.props.removeBlacklistItems({ ids }); - } - - onSortPress = (sortKey) => { - this.props.setBlacklistSort({ sortKey }); - } - - onTableOptionChange = (payload) => { - this.props.setBlacklistTableOption(payload); - - if (payload.pageSize) { - this.props.gotoBlacklistFirstPage(); - } - } - - onClearBlacklistPress = () => { - this.props.executeCommand({ name: commandNames.CLEAR_BLACKLIST }); - } - - onTableOptionChange = (payload) => { - this.props.setBlacklistTableOption(payload); - - if (payload.pageSize) { - this.props.gotoBlacklistFirstPage(); - } - } - - // - // Render - - render() { - return ( - - ); - } -} - -BlacklistConnector.propTypes = { - useCurrentPage: PropTypes.bool.isRequired, - isClearingBlacklistExecuting: PropTypes.bool.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - fetchBlacklist: PropTypes.func.isRequired, - gotoBlacklistFirstPage: PropTypes.func.isRequired, - gotoBlacklistPreviousPage: PropTypes.func.isRequired, - gotoBlacklistNextPage: PropTypes.func.isRequired, - gotoBlacklistLastPage: PropTypes.func.isRequired, - gotoBlacklistPage: PropTypes.func.isRequired, - removeBlacklistItems: PropTypes.func.isRequired, - setBlacklistSort: PropTypes.func.isRequired, - setBlacklistTableOption: PropTypes.func.isRequired, - clearBlacklist: PropTypes.func.isRequired, - executeCommand: PropTypes.func.isRequired -}; - -export default withCurrentPage( - connect(createMapStateToProps, mapDispatchToProps)(BlacklistConnector) -); diff --git a/frontend/src/Activity/Blacklist/BlacklistDetailsModal.js b/frontend/src/Activity/Blacklist/BlacklistDetailsModal.js deleted file mode 100644 index 9b8cf07c8..000000000 --- a/frontend/src/Activity/Blacklist/BlacklistDetailsModal.js +++ /dev/null @@ -1,90 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import DescriptionList from 'Components/DescriptionList/DescriptionList'; -import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem'; -import Button from 'Components/Link/Button'; -import Modal from 'Components/Modal/Modal'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import translate from 'Utilities/String/translate'; - -class BlacklistDetailsModal extends Component { - - // - // Render - - render() { - const { - isOpen, - sourceTitle, - protocol, - indexer, - message, - onModalClose - } = this.props; - - return ( - - - - Details - - - - - - - - - { - !!message && - - } - - { - !!message && - - } - - - - - - - - - ); - } -} - -BlacklistDetailsModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - sourceTitle: PropTypes.string.isRequired, - protocol: PropTypes.string.isRequired, - indexer: PropTypes.string, - message: PropTypes.string, - onModalClose: PropTypes.func.isRequired -}; - -export default BlacklistDetailsModal; diff --git a/frontend/src/Activity/Blacklist/BlacklistRow.css b/frontend/src/Activity/Blacklist/BlacklistRow.css deleted file mode 100644 index c7d31a886..000000000 --- a/frontend/src/Activity/Blacklist/BlacklistRow.css +++ /dev/null @@ -1,18 +0,0 @@ -.language, -.quality { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 100px; -} - -.indexer { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 80px; -} - -.actions { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 70px; -} diff --git a/frontend/src/Activity/Blacklist/BlacklistRow.js b/frontend/src/Activity/Blacklist/BlacklistRow.js deleted file mode 100644 index 1eb45360d..000000000 --- a/frontend/src/Activity/Blacklist/BlacklistRow.js +++ /dev/null @@ -1,213 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import IconButton from 'Components/Link/IconButton'; -import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import TableSelectCell from 'Components/Table/Cells/TableSelectCell'; -import TableRow from 'Components/Table/TableRow'; -import { icons, kinds } from 'Helpers/Props'; -import MovieFormats from 'Movie/MovieFormats'; -import MovieLanguage from 'Movie/MovieLanguage'; -import MovieQuality from 'Movie/MovieQuality'; -import MovieTitleLink from 'Movie/MovieTitleLink'; -import translate from 'Utilities/String/translate'; -import BlacklistDetailsModal from './BlacklistDetailsModal'; -import styles from './BlacklistRow.css'; - -class BlacklistRow extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isDetailsModalOpen: false - }; - } - - // - // Listeners - - onDetailsPress = () => { - this.setState({ isDetailsModalOpen: true }); - } - - onDetailsModalClose = () => { - this.setState({ isDetailsModalOpen: false }); - } - - // - // Render - - render() { - const { - id, - movie, - sourceTitle, - quality, - customFormats, - languages, - date, - protocol, - indexer, - message, - isSelected, - columns, - onSelectedChange, - onRemovePress - } = this.props; - - if (!movie) { - return null; - } - - return ( - - - - { - columns.map((column) => { - const { - name, - isVisible - } = column; - - if (!isVisible) { - return null; - } - - if (name === 'movies.sortTitle') { - return ( - - - - ); - } - - if (name === 'sourceTitle') { - return ( - - {sourceTitle} - - ); - } - - if (name === 'languages') { - return ( - - - - ); - } - - if (name === 'quality') { - return ( - - - - ); - } - - if (name === 'customFormats') { - return ( - - - - ); - } - - if (name === 'date') { - return ( - - ); - } - - if (name === 'indexer') { - return ( - - {indexer} - - ); - } - - if (name === 'actions') { - return ( - - - - - - ); - } - - return null; - }) - } - - - - ); - } - -} - -BlacklistRow.propTypes = { - id: PropTypes.number.isRequired, - movie: PropTypes.object.isRequired, - sourceTitle: PropTypes.string.isRequired, - quality: PropTypes.object.isRequired, - customFormats: PropTypes.arrayOf(PropTypes.object).isRequired, - languages: PropTypes.arrayOf(PropTypes.object).isRequired, - date: PropTypes.string.isRequired, - protocol: PropTypes.string.isRequired, - indexer: PropTypes.string, - message: PropTypes.string, - isSelected: PropTypes.bool.isRequired, - columns: PropTypes.arrayOf(PropTypes.object).isRequired, - onSelectedChange: PropTypes.func.isRequired, - onRemovePress: PropTypes.func.isRequired -}; - -export default BlacklistRow; diff --git a/frontend/src/Activity/Blacklist/BlacklistRowConnector.js b/frontend/src/Activity/Blacklist/BlacklistRowConnector.js deleted file mode 100644 index 47a3ce644..000000000 --- a/frontend/src/Activity/Blacklist/BlacklistRowConnector.js +++ /dev/null @@ -1,26 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { removeBlacklistItem } from 'Store/Actions/blacklistActions'; -import createMovieSelector from 'Store/Selectors/createMovieSelector'; -import BlacklistRow from './BlacklistRow'; - -function createMapStateToProps() { - return createSelector( - createMovieSelector(), - (movie) => { - return { - movie - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - onRemovePress() { - dispatch(removeBlacklistItem({ id: props.id })); - } - }; -} - -export default connect(createMapStateToProps, createMapDispatchToProps)(BlacklistRow); diff --git a/frontend/src/Activity/Queue/ProtocolLabel.css b/frontend/src/Activity/Queue/ProtocolLabel.css deleted file mode 100644 index 259fd5c65..000000000 --- a/frontend/src/Activity/Queue/ProtocolLabel.css +++ /dev/null @@ -1,13 +0,0 @@ -.torrent { - composes: label from '~Components/Label.css'; - - border-color: $torrentColor; - background-color: $torrentColor; -} - -.usenet { - composes: label from '~Components/Label.css'; - - border-color: $usenetColor; - background-color: $usenetColor; -} diff --git a/frontend/src/Activity/Queue/ProtocolLabel.js b/frontend/src/Activity/Queue/ProtocolLabel.js deleted file mode 100644 index e8a08943c..000000000 --- a/frontend/src/Activity/Queue/ProtocolLabel.js +++ /dev/null @@ -1,20 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Label from 'Components/Label'; -import styles from './ProtocolLabel.css'; - -function ProtocolLabel({ protocol }) { - const protocolName = protocol === 'usenet' ? 'nzb' : protocol; - - return ( - - ); -} - -ProtocolLabel.propTypes = { - protocol: PropTypes.string.isRequired -}; - -export default ProtocolLabel; diff --git a/frontend/src/Activity/Queue/Queue.js b/frontend/src/Activity/Queue/Queue.js deleted file mode 100644 index c60cd4114..000000000 --- a/frontend/src/Activity/Queue/Queue.js +++ /dev/null @@ -1,292 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import PageToolbar from 'Components/Page/Toolbar/PageToolbar'; -import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton'; -import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection'; -import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator'; -import Table from 'Components/Table/Table'; -import TableBody from 'Components/Table/TableBody'; -import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper'; -import TablePager from 'Components/Table/TablePager'; -import { align, icons } from 'Helpers/Props'; -import getRemovedItems from 'Utilities/Object/getRemovedItems'; -import hasDifferentItems from 'Utilities/Object/hasDifferentItems'; -import translate from 'Utilities/String/translate'; -import getSelectedIds from 'Utilities/Table/getSelectedIds'; -import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState'; -import selectAll from 'Utilities/Table/selectAll'; -import toggleSelected from 'Utilities/Table/toggleSelected'; -import QueueOptionsConnector from './QueueOptionsConnector'; -import QueueRowConnector from './QueueRowConnector'; -import RemoveQueueItemsModal from './RemoveQueueItemsModal'; - -class Queue extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - allSelected: false, - allUnselected: false, - lastToggled: null, - selectedState: {}, - isPendingSelected: false, - isConfirmRemoveModalOpen: false, - items: props.items - }; - } - - componentDidUpdate(prevProps) { - const { - items, - isFetching, - isMoviesFetching - } = this.props; - - if ( - (!isMoviesFetching && prevProps.isMoviesFetching) || - (!isFetching && prevProps.isFetching) || - (hasDifferentItems(prevProps.items, items) && !items.some((e) => e.movieId)) - ) { - this.setState((state) => { - return { - ...removeOldSelectedState(state, getRemovedItems(prevProps.items, items)), - items - }; - }); - - return; - } - - const selectedIds = this.getSelectedIds(); - const isPendingSelected = _.some(this.props.items, (item) => { - return selectedIds.indexOf(item.id) > -1 && item.status === 'delay'; - }); - - if (isPendingSelected !== this.state.isPendingSelected) { - this.setState({ isPendingSelected }); - } - } - - // - // Control - - getSelectedIds = () => { - return getSelectedIds(this.state.selectedState); - } - - // - // Listeners - - onSelectAllChange = ({ value }) => { - this.setState(selectAll(this.state.selectedState, value)); - } - - onSelectedChange = ({ id, value, shiftKey = false }) => { - this.setState((state) => { - return toggleSelected(state, this.props.items, id, value, shiftKey); - }); - } - - onGrabSelectedPress = () => { - this.props.onGrabSelectedPress(this.getSelectedIds()); - } - - onRemoveSelectedPress = () => { - this.setState({ isConfirmRemoveModalOpen: true }); - } - - onRemoveSelectedConfirmed = (payload) => { - this.props.onRemoveSelectedPress({ ids: this.getSelectedIds(), ...payload }); - this.setState({ isConfirmRemoveModalOpen: false }); - } - - onConfirmRemoveModalClose = () => { - this.setState({ isConfirmRemoveModalOpen: false }); - } - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - isMoviesFetching, - isMoviesPopulated, - moviesError, - columns, - totalRecords, - isGrabbing, - isRemoving, - isRefreshMonitoredDownloadsExecuting, - onRefreshPress, - ...otherProps - } = this.props; - - const { - allSelected, - allUnselected, - selectedState, - isConfirmRemoveModalOpen, - isPendingSelected, - items - } = this.state; - - const isRefreshing = isFetching || isMoviesFetching || isRefreshMonitoredDownloadsExecuting; - const isAllPopulated = isPopulated && (isMoviesPopulated || !items.length || items.every((e) => !e.movieId)); - const hasError = error || moviesError; - const selectedIds = this.getSelectedIds(); - const selectedCount = selectedIds.length; - const disableSelectedActions = selectedCount === 0; - - return ( - - - - - - - - - - - - - - - - - - - - - { - isRefreshing && !isAllPopulated && - - } - - { - !isRefreshing && hasError && -
- Failed to load Queue -
- } - - { - isPopulated && !hasError && !items.length && -
- Queue is empty -
- } - - { - isAllPopulated && !hasError && !!items.length && -
- - - { - items.map((item) => { - return ( - - ); - }) - } - -
- - -
- } -
- - { - const item = items.find((i) => i.id === id); - - return !!(item && item.movieId); - }) - )} - onRemovePress={this.onRemoveSelectedConfirmed} - onModalClose={this.onConfirmRemoveModalClose} - /> -
- ); - } -} - -Queue.propTypes = { - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - isMoviesFetching: PropTypes.bool.isRequired, - isMoviesPopulated: PropTypes.bool.isRequired, - moviesError: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - columns: PropTypes.arrayOf(PropTypes.object).isRequired, - totalRecords: PropTypes.number, - isGrabbing: PropTypes.bool.isRequired, - isRemoving: PropTypes.bool.isRequired, - isRefreshMonitoredDownloadsExecuting: PropTypes.bool.isRequired, - onRefreshPress: PropTypes.func.isRequired, - onGrabSelectedPress: PropTypes.func.isRequired, - onRemoveSelectedPress: PropTypes.func.isRequired -}; - -export default Queue; diff --git a/frontend/src/Activity/Queue/QueueConnector.js b/frontend/src/Activity/Queue/QueueConnector.js deleted file mode 100644 index d892a25fd..000000000 --- a/frontend/src/Activity/Queue/QueueConnector.js +++ /dev/null @@ -1,170 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import * as commandNames from 'Commands/commandNames'; -import withCurrentPage from 'Components/withCurrentPage'; -import { executeCommand } from 'Store/Actions/commandActions'; -import * as queueActions from 'Store/Actions/queueActions'; -import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector'; -import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; -import Queue from './Queue'; - -function createMapStateToProps() { - return createSelector( - (state) => state.movies, - (state) => state.queue.options, - (state) => state.queue.paged, - createCommandExecutingSelector(commandNames.REFRESH_MONITORED_DOWNLOADS), - (movies, options, queue, isRefreshMonitoredDownloadsExecuting) => { - return { - isMoviesFetching: movies.isFetching, - isMoviesPopulated: movies.isPopulated, - moviesError: movies.error, - isRefreshMonitoredDownloadsExecuting, - ...options, - ...queue - }; - } - ); -} - -const mapDispatchToProps = { - ...queueActions, - executeCommand -}; - -class QueueConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - useCurrentPage, - fetchQueue, - gotoQueueFirstPage - } = this.props; - - registerPagePopulator(this.repopulate); - - if (useCurrentPage) { - fetchQueue(); - } else { - gotoQueueFirstPage(); - } - } - - componentDidUpdate(prevProps) { - if ( - this.props.includeUnknownMovieItems !== - prevProps.includeUnknownMovieItems - ) { - this.repopulate(); - } - } - - componentWillUnmount() { - unregisterPagePopulator(this.repopulate); - this.props.clearQueue(); - } - - // - // Control - - repopulate = () => { - this.props.fetchQueue(); - } - - // - // Listeners - - onFirstPagePress = () => { - this.props.gotoQueueFirstPage(); - } - - onPreviousPagePress = () => { - this.props.gotoQueuePreviousPage(); - } - - onNextPagePress = () => { - this.props.gotoQueueNextPage(); - } - - onLastPagePress = () => { - this.props.gotoQueueLastPage(); - } - - onPageSelect = (page) => { - this.props.gotoQueuePage({ page }); - } - - onSortPress = (sortKey) => { - this.props.setQueueSort({ sortKey }); - } - - onTableOptionChange = (payload) => { - this.props.setQueueTableOption(payload); - - if (payload.pageSize) { - this.props.gotoQueueFirstPage(); - } - } - - onRefreshPress = () => { - this.props.executeCommand({ - name: commandNames.REFRESH_MONITORED_DOWNLOADS - }); - } - - onGrabSelectedPress = (ids) => { - this.props.grabQueueItems({ ids }); - } - - onRemoveSelectedPress = (payload) => { - this.props.removeQueueItems(payload); - } - - // - // Render - - render() { - return ( - - ); - } -} - -QueueConnector.propTypes = { - includeUnknownMovieItems: PropTypes.bool.isRequired, - useCurrentPage: PropTypes.bool.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - fetchQueue: PropTypes.func.isRequired, - gotoQueueFirstPage: PropTypes.func.isRequired, - gotoQueuePreviousPage: PropTypes.func.isRequired, - gotoQueueNextPage: PropTypes.func.isRequired, - gotoQueueLastPage: PropTypes.func.isRequired, - gotoQueuePage: PropTypes.func.isRequired, - setQueueSort: PropTypes.func.isRequired, - setQueueTableOption: PropTypes.func.isRequired, - clearQueue: PropTypes.func.isRequired, - grabQueueItems: PropTypes.func.isRequired, - removeQueueItems: PropTypes.func.isRequired, - executeCommand: PropTypes.func.isRequired -}; - -export default withCurrentPage( - connect(createMapStateToProps, mapDispatchToProps)(QueueConnector) -); diff --git a/frontend/src/Activity/Queue/QueueDetails.js b/frontend/src/Activity/Queue/QueueDetails.js deleted file mode 100644 index 874b52217..000000000 --- a/frontend/src/Activity/Queue/QueueDetails.js +++ /dev/null @@ -1,128 +0,0 @@ -import moment from 'moment'; -import PropTypes from 'prop-types'; -import React from 'react'; -import Icon from 'Components/Icon'; -import { icons, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -function QueueDetails(props) { - const { - title, - size, - sizeleft, - estimatedCompletionTime, - status, - trackedDownloadState, - trackedDownloadStatus, - errorMessage, - progressBar - } = props; - - const progress = size ? (100 - sizeleft / size * 100) : 0; - - if (status === 'pending') { - return ( - - ); - } - - if (status === 'completed') { - if (errorMessage) { - return ( - - ); - } - - if (trackedDownloadStatus === 'warning') { - return ( - - ); - } - - if (trackedDownloadState === 'importPending') { - return ( - - ); - } - - if (trackedDownloadState === 'importing') { - return ( - - ); - } - } - - if (errorMessage) { - return ( - - ); - } - - if (status === 'failed') { - return ( - - ); - } - - if (status === 'warning') { - return ( - - ); - } - - if (progress < 5) { - return ( - - ); - } - - return progressBar; -} - -QueueDetails.propTypes = { - title: PropTypes.string.isRequired, - size: PropTypes.number.isRequired, - sizeleft: PropTypes.number.isRequired, - estimatedCompletionTime: PropTypes.string, - status: PropTypes.string.isRequired, - trackedDownloadState: PropTypes.string.isRequired, - trackedDownloadStatus: PropTypes.string.isRequired, - errorMessage: PropTypes.string, - progressBar: PropTypes.node.isRequired -}; - -export default QueueDetails; diff --git a/frontend/src/Activity/Queue/QueueOptions.js b/frontend/src/Activity/Queue/QueueOptions.js deleted file mode 100644 index 03c86bd75..000000000 --- a/frontend/src/Activity/Queue/QueueOptions.js +++ /dev/null @@ -1,78 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component, Fragment } from 'react'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import { inputTypes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -class QueueOptions extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - includeUnknownMovieItems: props.includeUnknownMovieItems - }; - } - - componentDidUpdate(prevProps) { - const { - includeUnknownMovieItems - } = this.props; - - if (includeUnknownMovieItems !== prevProps.includeUnknownMovieItems) { - this.setState({ - includeUnknownMovieItems - }); - } - } - - // - // Listeners - - onOptionChange = ({ name, value }) => { - this.setState({ - [name]: value - }, () => { - this.props.onOptionChange({ - [name]: value - }); - }); - } - - // - // Render - - render() { - const { - includeUnknownMovieItems - } = this.state; - - return ( - - - {translate('ShowUnknownMovieItems')} - - - - - ); - } -} - -QueueOptions.propTypes = { - includeUnknownMovieItems: PropTypes.bool.isRequired, - onOptionChange: PropTypes.func.isRequired -}; - -export default QueueOptions; diff --git a/frontend/src/Activity/Queue/QueueOptionsConnector.js b/frontend/src/Activity/Queue/QueueOptionsConnector.js deleted file mode 100644 index b2c99511c..000000000 --- a/frontend/src/Activity/Queue/QueueOptionsConnector.js +++ /dev/null @@ -1,19 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { setQueueOption } from 'Store/Actions/queueActions'; -import QueueOptions from './QueueOptions'; - -function createMapStateToProps() { - return createSelector( - (state) => state.queue.options, - (options) => { - return options; - } - ); -} - -const mapDispatchToProps = { - onOptionChange: setQueueOption -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(QueueOptions); diff --git a/frontend/src/Activity/Queue/QueueRow.css b/frontend/src/Activity/Queue/QueueRow.css deleted file mode 100644 index ee0483f96..000000000 --- a/frontend/src/Activity/Queue/QueueRow.css +++ /dev/null @@ -1,23 +0,0 @@ -.quality { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 150px; -} - -.protocol { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 100px; -} - -.progress { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 150px; -} - -.actions { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 70px; -} diff --git a/frontend/src/Activity/Queue/QueueRow.js b/frontend/src/Activity/Queue/QueueRow.js deleted file mode 100644 index 03570ac5c..000000000 --- a/frontend/src/Activity/Queue/QueueRow.js +++ /dev/null @@ -1,370 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import ProtocolLabel from 'Activity/Queue/ProtocolLabel'; -import IconButton from 'Components/Link/IconButton'; -import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; -import ProgressBar from 'Components/ProgressBar'; -// import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import TableSelectCell from 'Components/Table/Cells/TableSelectCell'; -import TableRow from 'Components/Table/TableRow'; -import { icons, kinds } from 'Helpers/Props'; -import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal'; -import MovieFormats from 'Movie/MovieFormats'; -import MovieLanguage from 'Movie/MovieLanguage'; -import MovieQuality from 'Movie/MovieQuality'; -import MovieTitleLink from 'Movie/MovieTitleLink'; -import formatBytes from 'Utilities/Number/formatBytes'; -import translate from 'Utilities/String/translate'; -import QueueStatusCell from './QueueStatusCell'; -import RemoveQueueItemModal from './RemoveQueueItemModal'; -import TimeleftCell from './TimeleftCell'; -import styles from './QueueRow.css'; - -class QueueRow extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isRemoveQueueItemModalOpen: false, - isInteractiveImportModalOpen: false - }; - } - - // - // Listeners - - onRemoveQueueItemPress = () => { - this.setState({ isRemoveQueueItemModalOpen: true }); - } - - onRemoveQueueItemModalConfirmed = (blacklist) => { - this.props.onRemoveQueueItemPress(blacklist); - this.setState({ isRemoveQueueItemModalOpen: false }); - } - - onRemoveQueueItemModalClose = () => { - this.setState({ isRemoveQueueItemModalOpen: false }); - } - - onInteractiveImportPress = () => { - this.setState({ isInteractiveImportModalOpen: true }); - } - - onInteractiveImportModalClose = () => { - this.setState({ isInteractiveImportModalOpen: false }); - } - - // - // Render - - render() { - const { - id, - downloadId, - title, - status, - trackedDownloadStatus, - trackedDownloadState, - statusMessages, - errorMessage, - movie, - quality, - customFormats, - languages, - protocol, - indexer, - outputPath, - downloadClient, - estimatedCompletionTime, - timeleft, - size, - sizeleft, - showRelativeDates, - shortDateFormat, - timeFormat, - isGrabbing, - grabError, - isRemoving, - isSelected, - columns, - onSelectedChange, - onGrabPress - } = this.props; - - const { - isRemoveQueueItemModalOpen, - isInteractiveImportModalOpen - } = this.state; - - const progress = 100 - (sizeleft / size * 100); - const showInteractiveImport = status === 'completed' && trackedDownloadStatus === 'warning'; - const isPending = status === 'delay' || status === 'downloadClientUnavailable'; - - return ( - - - - { - columns.map((column) => { - const { - name, - isVisible - } = column; - - if (!isVisible) { - return null; - } - - if (name === 'status') { - return ( - - ); - } - - if (name === 'movies.sortTitle') { - return ( - - { - movie ? - : - title - } - - ); - } - - if (name === 'languages') { - return ( - - - - ); - } - - if (name === 'quality') { - return ( - - { - quality ? - : - null - } - - ); - } - - if (name === 'customFormats') { - return ( - - - - ); - } - - if (name === 'protocol') { - return ( - - - - ); - } - - if (name === 'indexer') { - return ( - - {indexer} - - ); - } - - if (name === 'downloadClient') { - return ( - - {downloadClient} - - ); - } - - if (name === 'size') { - return ( - - {formatBytes(size)} - - ); - } - - if (name === 'title') { - return ( - - {title} - - ); - } - - if (name === 'outputPath') { - return ( - - {outputPath} - - ); - } - - if (name === 'estimatedCompletionTime') { - return ( - - ); - } - - if (name === 'progress') { - return ( - - { - !!progress && - - } - - ); - } - - if (name === 'actions') { - return ( - - { - showInteractiveImport && - - } - - { - isPending && - - } - - - - ); - } - - return null; - }) - } - - - - - - ); - } - -} - -QueueRow.propTypes = { - id: PropTypes.number.isRequired, - downloadId: PropTypes.string, - title: PropTypes.string.isRequired, - status: PropTypes.string.isRequired, - trackedDownloadStatus: PropTypes.string, - trackedDownloadState: PropTypes.string, - statusMessages: PropTypes.arrayOf(PropTypes.object), - errorMessage: PropTypes.string, - movie: PropTypes.object, - quality: PropTypes.object.isRequired, - customFormats: PropTypes.arrayOf(PropTypes.object), - languages: PropTypes.arrayOf(PropTypes.object).isRequired, - protocol: PropTypes.string.isRequired, - indexer: PropTypes.string, - outputPath: PropTypes.string, - downloadClient: PropTypes.string, - estimatedCompletionTime: PropTypes.string, - timeleft: PropTypes.string, - size: PropTypes.number, - sizeleft: PropTypes.number, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - timeFormat: PropTypes.string.isRequired, - isGrabbing: PropTypes.bool.isRequired, - grabError: PropTypes.object, - isRemoving: PropTypes.bool.isRequired, - isSelected: PropTypes.bool, - columns: PropTypes.arrayOf(PropTypes.object).isRequired, - onSelectedChange: PropTypes.func.isRequired, - onGrabPress: PropTypes.func.isRequired, - onRemoveQueueItemPress: PropTypes.func.isRequired -}; - -QueueRow.defaultProps = { - isGrabbing: false, - isRemoving: false -}; - -export default QueueRow; diff --git a/frontend/src/Activity/Queue/QueueRowConnector.js b/frontend/src/Activity/Queue/QueueRowConnector.js deleted file mode 100644 index 4a46374b3..000000000 --- a/frontend/src/Activity/Queue/QueueRowConnector.js +++ /dev/null @@ -1,67 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { grabQueueItem, removeQueueItem } from 'Store/Actions/queueActions'; -import createMovieSelector from 'Store/Selectors/createMovieSelector'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import QueueRow from './QueueRow'; - -function createMapStateToProps() { - return createSelector( - createMovieSelector(), - createUISettingsSelector(), - (movie, uiSettings) => { - const result = { - showRelativeDates: uiSettings.showRelativeDates, - shortDateFormat: uiSettings.shortDateFormat, - timeFormat: uiSettings.timeFormat - }; - - result.movie = movie; - - return result; - } - ); -} - -const mapDispatchToProps = { - grabQueueItem, - removeQueueItem -}; - -class QueueRowConnector extends Component { - - // - // Listeners - - onGrabPress = () => { - this.props.grabQueueItem({ id: this.props.id }); - } - - onRemoveQueueItemPress = (payload) => { - this.props.removeQueueItem({ id: this.props.id, ...payload }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -QueueRowConnector.propTypes = { - id: PropTypes.number.isRequired, - movie: PropTypes.object, - grabQueueItem: PropTypes.func.isRequired, - removeQueueItem: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(QueueRowConnector); diff --git a/frontend/src/Activity/Queue/QueueStatusCell.css b/frontend/src/Activity/Queue/QueueStatusCell.css deleted file mode 100644 index e1b9a23e9..000000000 --- a/frontend/src/Activity/Queue/QueueStatusCell.css +++ /dev/null @@ -1,5 +0,0 @@ -.status { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 30px; -} diff --git a/frontend/src/Activity/Queue/QueueStatusCell.js b/frontend/src/Activity/Queue/QueueStatusCell.js deleted file mode 100644 index cf6e7c879..000000000 --- a/frontend/src/Activity/Queue/QueueStatusCell.js +++ /dev/null @@ -1,157 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Icon from 'Components/Icon'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import Popover from 'Components/Tooltip/Popover'; -import { icons, kinds, tooltipPositions } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './QueueStatusCell.css'; - -function getDetailedPopoverBody(statusMessages) { - return ( -
- { - statusMessages.map(({ title, messages }) => { - return ( -
- {title} -
    - { - messages.map((message) => { - return ( -
  • - {message} -
  • - ); - }) - } -
-
- ); - }) - } -
- ); -} - -function QueueStatusCell(props) { - const { - sourceTitle, - status, - trackedDownloadStatus, - trackedDownloadState, - statusMessages, - errorMessage - } = props; - - const hasWarning = trackedDownloadStatus === 'warning'; - const hasError = trackedDownloadStatus === 'error'; - - // status === 'downloading' - let iconName = icons.DOWNLOADING; - let iconKind = kinds.DEFAULT; - let title = translate('Downloading'); - - if (status === 'paused') { - iconName = icons.PAUSED; - title = translate('Paused'); - } - - if (status === 'queued') { - iconName = icons.QUEUED; - title = translate('Queued'); - } - - if (status === 'completed') { - iconName = icons.DOWNLOADED; - title = translate('Downloaded'); - - if (trackedDownloadState === 'importPending') { - title += ` - ${translate('WaitingToImport')}`; - iconKind = kinds.PURPLE; - } - - if (trackedDownloadState === 'importing') { - title += ` - ${translate('Importing')}`; - iconKind = kinds.PURPLE; - } - - if (trackedDownloadState === 'failedPending') { - title += ` - ${translate('WaitingToProcess')}`; - iconKind = kinds.DANGER; - } - } - - if (hasWarning) { - iconKind = kinds.WARNING; - } - - if (status === 'delay') { - iconName = icons.PENDING; - title = translate('Pending'); - } - - if (status === 'DownloadClientUnavailable') { - iconName = icons.PENDING; - iconKind = kinds.WARNING; - title = `${translate('Pending')} - ${translate('DownloadClientUnavailable')}`; - } - - if (status === 'failed') { - iconName = icons.DOWNLOADING; - iconKind = kinds.DANGER; - title = translate('DownloadFailed'); - } - - if (status === 'warning') { - iconName = icons.DOWNLOADING; - iconKind = kinds.WARNING; - const warningMessage = errorMessage || translate('CheckDownloadClientForDetails'); - title = translate('DownloadWarning', [warningMessage]); - } - - if (hasError) { - if (status === 'completed') { - iconName = icons.DOWNLOAD; - iconKind = kinds.DANGER; - title = translate('ImportFailed', [sourceTitle]); - } else { - iconName = icons.DOWNLOADING; - iconKind = kinds.DANGER; - title = translate('DownloadFailed'); - } - } - - return ( - - - } - title={title} - body={hasWarning || hasError ? getDetailedPopoverBody(statusMessages) : sourceTitle} - position={tooltipPositions.RIGHT} - canFlip={false} - /> - - ); -} - -QueueStatusCell.propTypes = { - sourceTitle: PropTypes.string.isRequired, - status: PropTypes.string.isRequired, - trackedDownloadStatus: PropTypes.string.isRequired, - trackedDownloadState: PropTypes.string.isRequired, - statusMessages: PropTypes.arrayOf(PropTypes.object), - errorMessage: PropTypes.string -}; - -QueueStatusCell.defaultProps = { - trackedDownloadStatus: translate('Ok'), - trackedDownloadState: translate('Downloading') -}; - -export default QueueStatusCell; diff --git a/frontend/src/Activity/Queue/RemoveQueueItemModal.js b/frontend/src/Activity/Queue/RemoveQueueItemModal.js deleted file mode 100644 index e6840ab7e..000000000 --- a/frontend/src/Activity/Queue/RemoveQueueItemModal.js +++ /dev/null @@ -1,144 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import Modal from 'Components/Modal/Modal'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds, sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -class RemoveQueueItemModal extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - remove: true, - blacklist: false - }; - } - - // - // Control - - resetState = function() { - this.setState({ - remove: true, - blacklist: false - }); - } - - // - // Listeners - - onRemoveChange = ({ value }) => { - this.setState({ remove: value }); - } - - onBlacklistChange = ({ value }) => { - this.setState({ blacklist: value }); - } - - onRemoveConfirmed = () => { - const state = this.state; - - this.resetState(); - this.props.onRemovePress(state); - } - - onModalClose = () => { - this.resetState(); - this.props.onModalClose(); - } - - // - // Render - - render() { - const { - isOpen, - sourceTitle, - canIgnore - } = this.props; - - const { remove, blacklist } = this.state; - - return ( - - - - Remove - {sourceTitle} - - - -
- Are you sure you want to remove '{sourceTitle}' from the queue? -
- - - {translate('RemoveFromDownloadClient')} - - - - - - {translate('BlacklistRelease')} - - - -
- - - - - - -
-
- ); - } -} - -RemoveQueueItemModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - sourceTitle: PropTypes.string.isRequired, - canIgnore: PropTypes.bool.isRequired, - onRemovePress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default RemoveQueueItemModal; diff --git a/frontend/src/Activity/Queue/RemoveQueueItemsModal.css b/frontend/src/Activity/Queue/RemoveQueueItemsModal.css deleted file mode 100644 index c9ef59ec1..000000000 --- a/frontend/src/Activity/Queue/RemoveQueueItemsModal.css +++ /dev/null @@ -1,3 +0,0 @@ -.message { - margin-bottom: 30px; -} diff --git a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js b/frontend/src/Activity/Queue/RemoveQueueItemsModal.js deleted file mode 100644 index 9b52ef160..000000000 --- a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js +++ /dev/null @@ -1,148 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import Modal from 'Components/Modal/Modal'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds, sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './RemoveQueueItemsModal.css'; - -class RemoveQueueItemsModal extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - remove: true, - blacklist: false - }; - } - - // - // Control - - resetState = function() { - this.setState({ - remove: true, - blacklist: false - }); - } - - // - // Listeners - - onRemoveChange = ({ value }) => { - this.setState({ remove: value }); - } - - onBlacklistChange = ({ value }) => { - this.setState({ blacklist: value }); - } - - onRemoveConfirmed = () => { - const state = this.state; - - this.resetState(); - this.props.onRemovePress(state); - } - - onModalClose = () => { - this.resetState(); - this.props.onModalClose(); - } - - // - // Render - - render() { - const { - isOpen, - selectedCount, - canIgnore - } = this.props; - - const { remove, blacklist } = this.state; - - return ( - - - - Remove Selected Item{selectedCount > 1 ? 's' : ''} - - - -
- Are you sure you want to remove {selectedCount} item{selectedCount > 1 ? 's' : ''} from the queue? -
- - - {translate('RemoveFromDownloadClient')} - - - - - - - Blacklist Release{selectedCount > 1 ? 's' : ''} - - - - - -
- - - - - - -
-
- ); - } -} - -RemoveQueueItemsModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - selectedCount: PropTypes.number.isRequired, - canIgnore: PropTypes.bool.isRequired, - onRemovePress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default RemoveQueueItemsModal; diff --git a/frontend/src/Activity/Queue/Status/QueueStatusConnector.js b/frontend/src/Activity/Queue/Status/QueueStatusConnector.js deleted file mode 100644 index 9e3662de6..000000000 --- a/frontend/src/Activity/Queue/Status/QueueStatusConnector.js +++ /dev/null @@ -1,76 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import PageSidebarStatus from 'Components/Page/Sidebar/PageSidebarStatus'; -import { fetchQueueStatus } from 'Store/Actions/queueActions'; - -function createMapStateToProps() { - return createSelector( - (state) => state.app, - (state) => state.queue.status, - (state) => state.queue.options.includeUnknownMovieItems, - (app, status, includeUnknownMovieItems) => { - const { - errors, - warnings, - unknownErrors, - unknownWarnings, - count, - totalCount - } = status.item; - - return { - isConnected: app.isConnected, - isReconnecting: app.isReconnecting, - isPopulated: status.isPopulated, - ...status.item, - count: includeUnknownMovieItems ? totalCount : count, - errors: includeUnknownMovieItems ? errors || unknownErrors : errors, - warnings: includeUnknownMovieItems ? warnings || unknownWarnings : warnings - }; - } - ); -} - -const mapDispatchToProps = { - fetchQueueStatus -}; - -class QueueStatusConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - if (!this.props.isPopulated) { - this.props.fetchQueueStatus(); - } - } - - componentDidUpdate(prevProps) { - if (this.props.isConnected && prevProps.isReconnecting) { - this.props.fetchQueueStatus(); - } - } - - // - // Render - - render() { - return ( - - ); - } -} - -QueueStatusConnector.propTypes = { - isConnected: PropTypes.bool.isRequired, - isReconnecting: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - fetchQueueStatus: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(QueueStatusConnector); diff --git a/frontend/src/Activity/Queue/TimeleftCell.css b/frontend/src/Activity/Queue/TimeleftCell.css deleted file mode 100644 index cc6001a22..000000000 --- a/frontend/src/Activity/Queue/TimeleftCell.css +++ /dev/null @@ -1,5 +0,0 @@ -.timeleft { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 100px; -} diff --git a/frontend/src/Activity/Queue/TimeleftCell.js b/frontend/src/Activity/Queue/TimeleftCell.js deleted file mode 100644 index f2aa1390a..000000000 --- a/frontend/src/Activity/Queue/TimeleftCell.js +++ /dev/null @@ -1,83 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import formatTime from 'Utilities/Date/formatTime'; -import formatTimeSpan from 'Utilities/Date/formatTimeSpan'; -import getRelativeDate from 'Utilities/Date/getRelativeDate'; -import formatBytes from 'Utilities/Number/formatBytes'; -import translate from 'Utilities/String/translate'; -import styles from './TimeleftCell.css'; - -function TimeleftCell(props) { - const { - estimatedCompletionTime, - timeleft, - status, - size, - sizeleft, - showRelativeDates, - shortDateFormat, - timeFormat - } = props; - - if (status === 'delay') { - const date = getRelativeDate(estimatedCompletionTime, shortDateFormat, showRelativeDates); - const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true }); - - return ( - - - - - ); - } - - if (status === 'downloadClientUnavailable') { - const date = getRelativeDate(estimatedCompletionTime, shortDateFormat, showRelativeDates); - const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true }); - - return ( - - - - - ); - } - - if (!timeleft || status === 'completed' || status === 'failed') { - return ( - - - - - ); - } - - const totalSize = formatBytes(size); - const remainingSize = formatBytes(sizeleft); - - return ( - - {formatTimeSpan(timeleft)} - - ); -} - -TimeleftCell.propTypes = { - estimatedCompletionTime: PropTypes.string, - timeleft: PropTypes.string, - status: PropTypes.string.isRequired, - size: PropTypes.number.isRequired, - sizeleft: PropTypes.number.isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - timeFormat: PropTypes.string.isRequired -}; - -export default TimeleftCell; diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovie.css b/frontend/src/AddMovie/AddNewMovie/AddNewMovie.css deleted file mode 100644 index ed5a43c65..000000000 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovie.css +++ /dev/null @@ -1,60 +0,0 @@ -.searchContainer { - display: flex; - margin-bottom: 10px; -} - -.searchIconContainer { - width: 58px; - height: 46px; - border: 1px solid $inputBorderColor; - border-right: none; - border-radius: 4px; - border-top-right-radius: 0; - border-bottom-right-radius: 0; - background-color: #edf1f2; - text-align: center; - line-height: 46px; -} - -.searchInput { - composes: input from '~Components/Form/TextInput.css'; - - height: 46px; - border-radius: 0; - font-size: 18px; -} - -.clearLookupButton { - border: 1px solid $inputBorderColor; - border-left: none; - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.message { - margin-top: 30px; - text-align: center; - font-weight: 300; - font-size: $largeFontSize; -} - -.helpText { - margin-bottom: 10px; - font-size: 24px; -} - -.noMoviesText { - margin-top: 80px; - margin-bottom: 20px; -} - -.noResults { - margin-bottom: 10px; - font-weight: 300; - font-size: 30px; -} - -.searchResults { - margin-top: 30px; -} diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js deleted file mode 100644 index b387915b5..000000000 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js +++ /dev/null @@ -1,219 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import TextInput from 'Components/Form/TextInput'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import Link from 'Components/Link/Link'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import { icons, kinds } from 'Helpers/Props'; -import getErrorMessage from 'Utilities/Object/getErrorMessage'; -import translate from 'Utilities/String/translate'; -import AddNewMovieSearchResultConnector from './AddNewMovieSearchResultConnector'; -import styles from './AddNewMovie.css'; - -class AddNewMovie extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - term: props.term || '', - isFetching: false - }; - } - - componentDidMount() { - const term = this.state.term; - - if (term) { - this.props.onMovieLookupChange(term); - } - } - - componentDidUpdate(prevProps) { - const { - term, - isFetching - } = this.props; - - if (term && term !== prevProps.term) { - this.setState({ - term, - isFetching: true - }); - this.props.onMovieLookupChange(term); - } else if (isFetching !== prevProps.isFetching) { - this.setState({ - isFetching - }); - } - } - - // - // Listeners - - onSearchInputChange = ({ value }) => { - const hasValue = !!value.trim(); - - this.setState({ term: value, isFetching: hasValue }, () => { - if (hasValue) { - this.props.onMovieLookupChange(value); - } else { - this.props.onClearMovieLookup(); - } - }); - } - - onClearMovieLookupPress = () => { - this.setState({ term: '' }); - this.props.onClearMovieLookup(); - } - - // - // Render - - render() { - const { - error, - items, - hasExistingMovies - } = this.props; - - const term = this.state.term; - const isFetching = this.state.isFetching; - - return ( - - -
-
- -
- - - - -
- - { - isFetching && - - } - - { - !isFetching && !!error ? -
-
- {translate('FailedLoadingSearchResults')} -
-
{getErrorMessage(error)}
-
: null - } - - { - !isFetching && !error && !!items.length && -
- { - items.map((item) => { - return ( - - ); - }) - } -
- } - - { - !isFetching && !error && !items.length && !!term && -
-
- {translate('CouldNotFindResults', [term])} -
-
- {translate('YouCanAlsoSearch')} -
-
- - {translate('CantFindMovie')} - -
-
- } - - { - term ? - null : -
-
- {translate('AddNewMessage')} -
-
- {translate('AddNewTmdbIdMessage')} -
-
- } - - { - !term && !hasExistingMovies ? -
-
- {translate('HaveNotAddedMovies')} -
-
- -
-
: - null - } - -
- - - ); - } -} - -AddNewMovie.propTypes = { - term: PropTypes.string, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - isAdding: PropTypes.bool.isRequired, - addError: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - hasExistingMovies: PropTypes.bool.isRequired, - onMovieLookupChange: PropTypes.func.isRequired, - onClearMovieLookup: PropTypes.func.isRequired -}; - -export default AddNewMovie; diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js deleted file mode 100644 index 37f22ed18..000000000 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js +++ /dev/null @@ -1,104 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { clearAddMovie, lookupMovie } from 'Store/Actions/addMovieActions'; -import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; -import parseUrl from 'Utilities/String/parseUrl'; -import AddNewMovie from './AddNewMovie'; - -function createMapStateToProps() { - return createSelector( - (state) => state.addMovie, - (state) => state.movies.items.length, - (state) => state.router.location, - (addMovie, existingMoviesCount, location) => { - const { params } = parseUrl(location.search); - - return { - ...addMovie, - term: params.term, - hasExistingMovies: existingMoviesCount > 0 - }; - } - ); -} - -const mapDispatchToProps = { - lookupMovie, - clearAddMovie, - fetchRootFolders -}; - -class AddNewMovieConnector extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this._movieLookupTimeout = null; - } - - componentDidMount() { - this.props.fetchRootFolders(); - } - - componentWillUnmount() { - if (this._movieLookupTimeout) { - clearTimeout(this._movieLookupTimeout); - } - - this.props.clearAddMovie(); - } - - // - // Listeners - - onMovieLookupChange = (term) => { - if (this._movieLookupTimeout) { - clearTimeout(this._movieLookupTimeout); - } - - if (term.trim() === '') { - this.props.clearAddMovie(); - } else { - this._movieLookupTimeout = setTimeout(() => { - this.props.lookupMovie({ term }); - }, 300); - } - } - - onClearMovieLookup = () => { - this.props.clearAddMovie(); - } - - // - // Render - - render() { - const { - term, - ...otherProps - } = this.props; - - return ( - - ); - } -} - -AddNewMovieConnector.propTypes = { - term: PropTypes.string, - lookupMovie: PropTypes.func.isRequired, - clearAddMovie: PropTypes.func.isRequired, - fetchRootFolders: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(AddNewMovieConnector); diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieModal.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieModal.js deleted file mode 100644 index 785f758ab..000000000 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieModal.js +++ /dev/null @@ -1,31 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import AddNewMovieModalContentConnector from './AddNewMovieModalContentConnector'; - -function AddNewMovieModal(props) { - const { - isOpen, - onModalClose, - ...otherProps - } = props; - - return ( - - - - ); -} - -AddNewMovieModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default AddNewMovieModal; diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.css b/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.css deleted file mode 100644 index 9c42822be..000000000 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.css +++ /dev/null @@ -1,68 +0,0 @@ -.container { - display: flex; -} - -.year { - margin-left: 5px; - color: $disabledColor; -} - -.poster { - flex: 0 0 170px; - margin-right: 20px; - height: 250px; -} - -.info { - flex-grow: 1; -} - -.overview { - margin-bottom: 30px; -} - -.labelIcon { - margin-left: 8px; -} - -.searchForMissingMovieLabelContainer { - display: flex; - margin-top: 2px; -} - -.searchForMissingMovieLabel { - margin-right: 8px; - font-weight: normal; -} - -.searchForMissingMovieContainer { - composes: container from '~Components/Form/CheckInput.css'; - - flex: 0 1 0; -} - -.searchForMissingMovieInput { - composes: input from '~Components/Form/CheckInput.css'; - - margin-top: 0; -} - -.modalFooter { - composes: modalFooter from '~Components/Modal/ModalFooter.css'; -} - -.addButton { - @add-mixin truncate; - composes: button from '~Components/Link/SpinnerButton.css'; -} - -@media only screen and (max-width: $breakpointSmall) { - .modalFooter { - display: block; - text-align: center; - } - - .addButton { - margin-top: 10px; - } -} diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.js deleted file mode 100644 index 9f02cb2a3..000000000 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.js +++ /dev/null @@ -1,217 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import CheckInput from 'Components/Form/CheckInput'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import SpinnerButton from 'Components/Link/SpinnerButton'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds } from 'Helpers/Props'; -import MoviePoster from 'Movie/MoviePoster'; -import translate from 'Utilities/String/translate'; -import styles from './AddNewMovieModalContent.css'; - -class AddNewMovieModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - searchForMovie: false - }; - } - - // - // Listeners - - onSearchForMissingMovieChange = ({ value }) => { - this.setState({ searchForMovie: value }); - } - - onQualityProfileIdChange = ({ value }) => { - this.props.onInputChange({ name: 'qualityProfileId', value: parseInt(value) }); - } - - onAddMoviePress = () => { - this.props.onAddMoviePress(this.state.searchForMovie); - } - - // - // Render - - render() { - const { - title, - year, - overview, - images, - isAdding, - rootFolderPath, - monitor, - qualityProfileId, - minimumAvailability, - folder, - tags, - isSmallScreen, - isWindows, - onModalClose, - onInputChange - } = this.props; - - return ( - - - {title} - - { - !title.contains(year) && !!year && - ({year}) - } - - - -
- { - !isSmallScreen && -
- -
- } - -
-
- {overview} -
- -
- - {translate('RootFolder')} - - - - - - - {translate('Monitor')} - - - - - - - {translate('MinimumAvailability')} - - - - - - {translate('QualityProfile')} - - - - - - {translate('Tags')} - - - -
-
-
-
- - - - - - {translate('AddMovie')} - - -
- ); - } -} - -AddNewMovieModalContent.propTypes = { - title: PropTypes.string.isRequired, - year: PropTypes.number.isRequired, - overview: PropTypes.string, - images: PropTypes.arrayOf(PropTypes.object).isRequired, - isAdding: PropTypes.bool.isRequired, - addError: PropTypes.object, - rootFolderPath: PropTypes.object, - monitor: PropTypes.object.isRequired, - qualityProfileId: PropTypes.object, - minimumAvailability: PropTypes.object.isRequired, - folder: PropTypes.string.isRequired, - tags: PropTypes.object.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - isWindows: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired, - onInputChange: PropTypes.func.isRequired, - onAddMoviePress: PropTypes.func.isRequired -}; - -export default AddNewMovieModalContent; diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContentConnector.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContentConnector.js deleted file mode 100644 index 166bbaecf..000000000 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContentConnector.js +++ /dev/null @@ -1,103 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { addMovie, setAddMovieDefault } from 'Store/Actions/addMovieActions'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector'; -import selectSettings from 'Store/Selectors/selectSettings'; -import AddNewMovieModalContent from './AddNewMovieModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.addMovie, - createDimensionsSelector(), - createSystemStatusSelector(), - (addMovieState, dimensions, systemStatus) => { - const { - isAdding, - addError, - defaults - } = addMovieState; - - const { - settings, - validationErrors, - validationWarnings - } = selectSettings(defaults, {}, addError); - - return { - isAdding, - addError, - isSmallScreen: dimensions.isSmallScreen, - validationErrors, - validationWarnings, - isWindows: systemStatus.isWindows, - ...settings - }; - } - ); -} - -const mapDispatchToProps = { - setAddMovieDefault, - addMovie -}; - -class AddNewMovieModalContentConnector extends Component { - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setAddMovieDefault({ [name]: value }); - } - - onAddMoviePress = (searchForMovie) => { - const { - tmdbId, - rootFolderPath, - monitor, - qualityProfileId, - minimumAvailability, - tags - } = this.props; - - this.props.addMovie({ - tmdbId, - rootFolderPath: rootFolderPath.value, - monitor: monitor.value, - qualityProfileId: qualityProfileId.value, - minimumAvailability: minimumAvailability.value, - tags: tags.value, - searchForMovie - }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -AddNewMovieModalContentConnector.propTypes = { - tmdbId: PropTypes.number.isRequired, - rootFolderPath: PropTypes.object, - monitor: PropTypes.object.isRequired, - qualityProfileId: PropTypes.object, - minimumAvailability: PropTypes.object.isRequired, - tags: PropTypes.object.isRequired, - onModalClose: PropTypes.func.isRequired, - setAddMovieDefault: PropTypes.func.isRequired, - addMovie: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(AddNewMovieModalContentConnector); diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.css b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.css deleted file mode 100644 index ffa89f5e6..000000000 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.css +++ /dev/null @@ -1,94 +0,0 @@ -.searchResult { - position: relative; - margin: 20px 0; - padding: 20px; - width: 100%; - color: inherit; -} - -.underlay { - @add-mixin cover; - - background-color: $white; - transition: background 500ms; - - &:hover { - background-color: #eaf2ff; - color: inherit; - text-decoration: none; - } -} - -.overlay { - @add-mixin linkOverlay; - - position: relative; - display: flex; -} - -.poster { - flex: 0 0 170px; - margin-right: 20px; - height: 250px; -} - -.content { - flex: 0 1 100%; - overflow: hidden; -} - -.titleRow { - display: flex; -} - -.titleContainer { - display: flex; - align-items: flex-end; - flex: 0 1 auto; -} - -.title { - font-weight: 300; - font-size: 36px; -} - -.year { - margin-left: 10px; - color: $disabledColor; -} - -.icons { - display: flex; - align-items: center; - justify-content: space-between; - flex: 1 0 auto; - height: 55px; -} - -.alreadyExistsIcon { - margin-left: 10px; - color: #37bc9b; - pointer-events: all; -} - -.exclusionIcon { - margin-left: 10px; - color: $dangerColor; - pointer-events: all; -} - -.overview { - margin-top: 20px; -} - -.links { - margin-left: 8px; - pointer-events: all; -} - -@media only screen and (max-width: $breakpointMedium) { - .titleRow { - justify-content: space-between; - overflow: hidden; - } -} diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js deleted file mode 100644 index 3302a7bdb..000000000 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js +++ /dev/null @@ -1,218 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import HeartRating from 'Components/HeartRating'; -import Icon from 'Components/Icon'; -import Label from 'Components/Label'; -import Link from 'Components/Link/Link'; -import Tooltip from 'Components/Tooltip/Tooltip'; -import { icons, kinds, sizes, tooltipPositions } from 'Helpers/Props'; -import MoviePoster from 'Movie/MoviePoster'; -import translate from 'Utilities/String/translate'; -import AddNewMovieModal from './AddNewMovieModal'; -import styles from './AddNewMovieSearchResult.css'; - -class AddNewMovieSearchResult extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isNewAddMovieModalOpen: false - }; - } - - componentDidUpdate(prevProps) { - if (!prevProps.isExistingMovie && this.props.isExistingMovie) { - this.onAddMovieModalClose(); - } - } - - // - // Listeners - - onPress = () => { - this.setState({ isNewAddMovieModalOpen: true }); - } - - onAddMovieModalClose = () => { - this.setState({ isNewAddMovieModalOpen: false }); - } - - onExternalLinkPress = (event) => { - event.stopPropagation(); - } - - // - // Render - - render() { - const { - tmdbId, - title, - titleSlug, - year, - studio, - status, - overview, - ratings, - folder, - images, - isExistingMovie, - isExclusionMovie, - isSmallScreen - } = this.props; - - const { - isNewAddMovieModalOpen - } = this.state; - - const linkProps = isExistingMovie ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress }; - - return ( -
- - -
- { - isSmallScreen ? - null : - - } - -
-
-
-
- {title} - - { - !title.contains(year) && !!year ? - - ({year}) - : - null - } -
-
- -
- - { - isExistingMovie && - - } - - { - isExclusionMovie && - - } -
-
- -
- - - { - !!studio && - - } - - - - - - Links - - - } - canFlip={true} - kind={kinds.INVERSE} - position={tooltipPositions.BOTTOM} - /> - - { - status === 'ended' && - - } -
- -
- {overview} -
-
-
- - -
- ); - } -} - -AddNewMovieSearchResult.propTypes = { - tmdbId: PropTypes.number.isRequired, - imdbId: PropTypes.string, - youTubeTrailerId: PropTypes.string, - title: PropTypes.string.isRequired, - titleSlug: PropTypes.string.isRequired, - year: PropTypes.number.isRequired, - studio: PropTypes.string, - status: PropTypes.string.isRequired, - overview: PropTypes.string, - ratings: PropTypes.object.isRequired, - folder: PropTypes.string.isRequired, - images: PropTypes.arrayOf(PropTypes.object).isRequired, - isExistingMovie: PropTypes.bool.isRequired, - isExclusionMovie: PropTypes.bool.isRequired, - isSmallScreen: PropTypes.bool.isRequired -}; - -export default AddNewMovieSearchResult; diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResultConnector.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResultConnector.js deleted file mode 100644 index fb843d67f..000000000 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResultConnector.js +++ /dev/null @@ -1,23 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import createExclusionMovieSelector from 'Store/Selectors/createExclusionMovieSelector'; -import createExistingMovieSelector from 'Store/Selectors/createExistingMovieSelector'; -import AddNewMovieSearchResult from './AddNewMovieSearchResult'; - -function createMapStateToProps() { - return createSelector( - createExistingMovieSelector(), - createExclusionMovieSelector(), - createDimensionsSelector(), - (isExistingMovie, isExclusionMovie, dimensions) => { - return { - isExistingMovie, - isExclusionMovie, - isSmallScreen: dimensions.isSmallScreen - }; - } - ); -} - -export default connect(createMapStateToProps)(AddNewMovieSearchResult); diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovie.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovie.js deleted file mode 100644 index ee5f42342..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovie.js +++ /dev/null @@ -1,177 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import translate from 'Utilities/String/translate'; -import getSelectedIds from 'Utilities/Table/getSelectedIds'; -import selectAll from 'Utilities/Table/selectAll'; -import toggleSelected from 'Utilities/Table/toggleSelected'; -import ImportMovieFooterConnector from './ImportMovieFooterConnector'; -import ImportMovieTableConnector from './ImportMovieTableConnector'; - -class ImportMovie extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - allSelected: false, - allUnselected: false, - lastToggled: null, - selectedState: {}, - contentBody: null - }; - } - - // - // Control - - setScrollerRef = (ref) => { - this.setState({ scroller: ref }); - } - - // - // Listeners - - getSelectedIds = () => { - return getSelectedIds(this.state.selectedState, { parseIds: false }); - } - - onSelectAllChange = ({ value }) => { - // Only select non-dupes - this.setState(selectAll(this.state.selectedState, value)); - } - - onSelectedChange = ({ id, value, shiftKey = false }) => { - this.setState((state) => { - return toggleSelected(state, this.props.items, id, value, shiftKey); - }); - } - - onRemoveSelectedStateItem = (id) => { - this.setState((state) => { - const selectedState = Object.assign({}, state.selectedState); - delete selectedState[id]; - - return { - ...state, - selectedState - }; - }); - } - - onInputChange = ({ name, value }) => { - this.props.onInputChange(this.getSelectedIds(), name, value); - } - - onImportPress = () => { - this.props.onImportPress(this.getSelectedIds()); - } - - // - // Render - - render() { - const { - rootFolderId, - path, - rootFoldersFetching, - rootFoldersError, - rootFoldersPopulated, - unmappedFolders - } = this.props; - - const { - allSelected, - allUnselected, - selectedState, - scroller - } = this.state; - - return ( - - - { - rootFoldersFetching ? : null - } - - { - !rootFoldersFetching && !!rootFoldersError ? -
- {translate('UnableToLoadRootFolders')} -
: - null - } - - { - !rootFoldersError && - !rootFoldersFetching && - rootFoldersPopulated && - !unmappedFolders.length ? -
- All movies in {path} have been imported -
: - null - } - - { - !rootFoldersError && - !rootFoldersFetching && - rootFoldersPopulated && - !!unmappedFolders.length && - scroller ? - : - null - } -
- - { - !rootFoldersError && - !rootFoldersFetching && - !!unmappedFolders.length ? - : - null - } -
- ); - } -} - -ImportMovie.propTypes = { - rootFolderId: PropTypes.number.isRequired, - path: PropTypes.string, - rootFoldersFetching: PropTypes.bool.isRequired, - rootFoldersPopulated: PropTypes.bool.isRequired, - rootFoldersError: PropTypes.object, - unmappedFolders: PropTypes.arrayOf(PropTypes.object), - items: PropTypes.arrayOf(PropTypes.object), - onInputChange: PropTypes.func.isRequired, - onImportPress: PropTypes.func.isRequired -}; - -ImportMovie.defaultProps = { - unmappedFolders: [] -}; - -export default ImportMovie; diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieConnector.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieConnector.js deleted file mode 100644 index f6f92aea4..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieConnector.js +++ /dev/null @@ -1,153 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createRouteMatchShape from 'Helpers/Props/Shapes/createRouteMatchShape'; -import { setAddMovieDefault } from 'Store/Actions/addMovieActions'; -import { clearImportMovie, importMovie, setImportMovieValue } from 'Store/Actions/importMovieActions'; -import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; -import ImportMovie from './ImportMovie'; - -function createMapStateToProps() { - return createSelector( - (state, { match }) => match, - (state) => state.rootFolders, - (state) => state.addMovie, - (state) => state.importMovie, - (state) => state.settings.qualityProfiles, - ( - match, - rootFolders, - addMovie, - importMovieState, - qualityProfiles - ) => { - const { - isFetching: rootFoldersFetching, - isPopulated: rootFoldersPopulated, - error: rootFoldersError, - items - } = rootFolders; - - const rootFolderId = parseInt(match.params.rootFolderId); - - const result = { - rootFolderId, - rootFoldersFetching, - rootFoldersPopulated, - rootFoldersError, - qualityProfiles: qualityProfiles.items, - defaultQualityProfileId: addMovie.defaults.qualityProfileId - }; - - if (items.length) { - const rootFolder = _.find(items, { id: rootFolderId }); - - return { - ...result, - ...rootFolder, - items: importMovieState.items - }; - } - - return result; - } - ); -} - -const mapDispatchToProps = { - dispatchSetImportMovieValue: setImportMovieValue, - dispatchImportMovie: importMovie, - dispatchClearImportMovie: clearImportMovie, - dispatchFetchRootFolders: fetchRootFolders, - dispatchSetAddMovieDefault: setAddMovieDefault -}; - -class ImportMovieConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - rootFolderId, - qualityProfiles, - defaultQualityProfileId, - dispatchFetchRootFolders, - dispatchSetAddMovieDefault - } = this.props; - - dispatchFetchRootFolders({ id: rootFolderId, timeout: false }); - - let setDefaults = false; - const setDefaultPayload = {}; - - if ( - !defaultQualityProfileId || - !qualityProfiles.some((p) => p.id === defaultQualityProfileId) - ) { - setDefaults = true; - setDefaultPayload.qualityProfileId = qualityProfiles[0].id; - } - - if (setDefaults) { - dispatchSetAddMovieDefault(setDefaultPayload); - } - } - - componentWillUnmount() { - this.props.dispatchClearImportMovie(); - } - - // - // Listeners - - onInputChange = (ids, name, value) => { - this.props.dispatchSetAddMovieDefault({ [name]: value }); - - ids.forEach((id) => { - this.props.dispatchSetImportMovieValue({ - id, - [name]: value - }); - }); - } - - onImportPress = (ids) => { - this.props.dispatchImportMovie({ ids }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -const routeMatchShape = createRouteMatchShape({ - rootFolderId: PropTypes.string.isRequired -}); - -ImportMovieConnector.propTypes = { - match: routeMatchShape.isRequired, - rootFolderId: PropTypes.number.isRequired, - rootFoldersFetching: PropTypes.bool.isRequired, - rootFoldersPopulated: PropTypes.bool.isRequired, - qualityProfiles: PropTypes.arrayOf(PropTypes.object).isRequired, - defaultQualityProfileId: PropTypes.number.isRequired, - dispatchSetImportMovieValue: PropTypes.func.isRequired, - dispatchImportMovie: PropTypes.func.isRequired, - dispatchClearImportMovie: PropTypes.func.isRequired, - dispatchFetchRootFolders: PropTypes.func.isRequired, - dispatchSetAddMovieDefault: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportMovieConnector); diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.css b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.css deleted file mode 100644 index 9bfb5a493..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.css +++ /dev/null @@ -1,37 +0,0 @@ -.inputContainer { - margin-right: 20px; - min-width: 150px; -} - -.label { - margin-bottom: 3px; - font-weight: bold; -} - -.importButtonContainer { - display: flex; - align-items: center; -} - -.importButton { - composes: button from '~Components/Link/SpinnerButton.css'; - - height: 35px; -} - -.loadingButton { - composes: importButton; - - margin-left: 10px; -} - -.loading { - composes: loading from '~Components/Loading/LoadingIndicator.css'; - - margin: 0 10px 0 12px; - text-align: left; -} - -.importError { - margin-left: 10px; -} diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js deleted file mode 100644 index 0f6b4b9ca..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js +++ /dev/null @@ -1,267 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -// import CheckInput from 'Components/Form/CheckInput'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import SpinnerButton from 'Components/Link/SpinnerButton'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import PageContentFooter from 'Components/Page/PageContentFooter'; -import Popover from 'Components/Tooltip/Popover'; -import { icons, inputTypes, kinds, tooltipPositions } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './ImportMovieFooter.css'; - -const MIXED = 'mixed'; - -class ImportMovieFooter extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - const { - defaultMonitor, - defaultQualityProfileId, - defaultMinimumAvailability - } = props; - - this.state = { - monitor: defaultMonitor, - qualityProfileId: defaultQualityProfileId, - minimumAvailability: defaultMinimumAvailability - }; - } - - componentDidUpdate(prevProps, prevState) { - const { - defaultMonitor, - defaultQualityProfileId, - defaultMinimumAvailability, - isMonitorMixed, - isQualityProfileIdMixed, - isMinimumAvailabilityMixed - } = this.props; - - const { - monitor, - qualityProfileId, - minimumAvailability - } = this.state; - - const newState = {}; - - if (isMonitorMixed && monitor !== MIXED) { - newState.monitor = MIXED; - } else if (!isMonitorMixed && monitor !== defaultMonitor) { - newState.monitor = defaultMonitor; - } - - if (isQualityProfileIdMixed && qualityProfileId !== MIXED) { - newState.qualityProfileId = MIXED; - } else if (!isQualityProfileIdMixed && qualityProfileId !== defaultQualityProfileId) { - newState.qualityProfileId = defaultQualityProfileId; - } - - if (isMinimumAvailabilityMixed && minimumAvailability !== MIXED) { - newState.minimumAvailability = MIXED; - } else if (!isMinimumAvailabilityMixed && minimumAvailability !== defaultMinimumAvailability) { - newState.minimumAvailability = defaultMinimumAvailability; - } - - if (!_.isEmpty(newState)) { - this.setState(newState); - } - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.setState({ [name]: value }); - this.props.onInputChange({ name, value }); - } - - // - // Render - - render() { - const { - selectedCount, - isImporting, - isLookingUpMovie, - isMonitorMixed, - isQualityProfileIdMixed, - isMinimumAvailabilityMixed, - hasUnsearchedItems, - importError, - onImportPress, - onLookupPress, - onCancelLookupPress - } = this.props; - - const { - monitor, - qualityProfileId, - minimumAvailability - } = this.state; - - return ( - -
-
- {translate('Monitor')} -
- - -
- -
-
- {translate('MinimumAvailability')} -
- - -
- -
-
- {translate('QualityProfile')} -
- - -
- -
-
-   -
- -
- - {translate('Import')} {selectedCount} {selectedCount > 1 ? translate('Movies') : translate('Movie')} - - - { - isLookingUpMovie ? - : - null - } - - { - hasUnsearchedItems ? - : - null - } - - { - isLookingUpMovie ? - : - null - } - - { - isLookingUpMovie ? - translate('ProcessingFolders') : - null - } - - { - importError ? - - } - title={translate('ImportErrors')} - body={ -
    - { - importError.responseJSON.map((error, index) => { - return ( -
  • - {error.errorMessage} -
  • - ); - }) - } -
- } - position={tooltipPositions.RIGHT} - /> : - null - } -
-
-
- ); - } -} - -ImportMovieFooter.propTypes = { - selectedCount: PropTypes.number.isRequired, - isImporting: PropTypes.bool.isRequired, - isLookingUpMovie: PropTypes.bool.isRequired, - defaultMonitor: PropTypes.string.isRequired, - defaultQualityProfileId: PropTypes.number, - defaultMinimumAvailability: PropTypes.string, - isMonitorMixed: PropTypes.bool.isRequired, - isQualityProfileIdMixed: PropTypes.bool.isRequired, - isMinimumAvailabilityMixed: PropTypes.bool.isRequired, - hasUnsearchedItems: PropTypes.bool.isRequired, - importError: PropTypes.object, - onInputChange: PropTypes.func.isRequired, - onImportPress: PropTypes.func.isRequired, - onLookupPress: PropTypes.func.isRequired, - onCancelLookupPress: PropTypes.func.isRequired -}; - -export default ImportMovieFooter; diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooterConnector.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooterConnector.js deleted file mode 100644 index f43cfa8e4..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooterConnector.js +++ /dev/null @@ -1,59 +0,0 @@ -import _ from 'lodash'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { cancelLookupMovie, lookupUnsearchedMovies } from 'Store/Actions/importMovieActions'; -import ImportMovieFooter from './ImportMovieFooter'; - -function isMixed(items, selectedIds, defaultValue, key) { - return _.some(items, (movie) => { - return selectedIds.indexOf(movie.id) > -1 && movie[key] !== defaultValue; - }); -} - -function createMapStateToProps() { - return createSelector( - (state) => state.addMovie, - (state) => state.importMovie, - (state, { selectedIds }) => selectedIds, - (addMovie, importMovie, selectedIds) => { - const { - monitor: defaultMonitor, - qualityProfileId: defaultQualityProfileId, - minimumAvailability: defaultMinimumAvailability - } = addMovie.defaults; - - const { - isLookingUpMovie, - isImporting, - items, - importError - } = importMovie; - - const isMonitorMixed = isMixed(items, selectedIds, defaultMonitor, 'monitor'); - const isQualityProfileIdMixed = isMixed(items, selectedIds, defaultQualityProfileId, 'qualityProfileId'); - const isMinimumAvailabilityMixed = isMixed(items, selectedIds, defaultMinimumAvailability, 'minimumAvailability'); - const hasUnsearchedItems = !isLookingUpMovie && items.some((item) => !item.isPopulated); - - return { - selectedCount: selectedIds.length, - isLookingUpMovie, - isImporting, - defaultMonitor, - defaultQualityProfileId, - defaultMinimumAvailability, - isMonitorMixed, - isQualityProfileIdMixed, - isMinimumAvailabilityMixed, - importError, - hasUnsearchedItems - }; - } - ); -} - -const mapDispatchToProps = { - onLookupPress: lookupUnsearchedMovies, - onCancelLookupPress: cancelLookupMovie -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportMovieFooter); diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.css b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.css deleted file mode 100644 index dec42e592..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.css +++ /dev/null @@ -1,31 +0,0 @@ -.folder { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 1 0 200px; -} - -.monitor { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 0 1 200px; - min-width: 185px; -} - -.minimumAvailability, -.qualityProfile { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 0 1 250px; - min-width: 170px; -} - -.movie { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 0 1 400px; - min-width: 300px; -} - -.detailsIcon { - margin-left: 8px; -} diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.js deleted file mode 100644 index a6d9d7df8..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.js +++ /dev/null @@ -1,68 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import VirtualTableHeader from 'Components/Table/VirtualTableHeader'; -import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell'; -import VirtualTableSelectAllHeaderCell from 'Components/Table/VirtualTableSelectAllHeaderCell'; -import translate from 'Utilities/String/translate'; -import styles from './ImportMovieHeader.css'; - -function ImportMovieHeader(props) { - const { - allSelected, - allUnselected, - onSelectAllChange - } = props; - - return ( - - - - - {translate('Folder')} - - - - {translate('Monitor')} - - - - {translate('MinAvailability')} - - - - {translate('QualityProfile')} - - - - {translate('Movie')} - - - ); -} - -ImportMovieHeader.propTypes = { - allSelected: PropTypes.bool.isRequired, - allUnselected: PropTypes.bool.isRequired, - onSelectAllChange: PropTypes.func.isRequired -}; - -export default ImportMovieHeader; diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.css b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.css deleted file mode 100644 index e65394b67..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.css +++ /dev/null @@ -1,32 +0,0 @@ -.selectInput { - composes: input from '~Components/Form/CheckInput.css'; -} - -.folder { - composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css'; - - flex: 1 0 200px; - line-height: 36px; -} - -.monitor { - composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css'; - - flex: 0 1 200px; - min-width: 185px; -} - -.minimumAvailability, -.qualityProfile { - composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css'; - - flex: 0 1 250px; - min-width: 170px; -} - -.movie { - composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css'; - - flex: 0 1 400px; - min-width: 300px; -} diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.js deleted file mode 100644 index 96ea739e4..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.js +++ /dev/null @@ -1,92 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell'; -import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell'; -import { inputTypes } from 'Helpers/Props'; -import ImportMovieSelectMovieConnector from './SelectMovie/ImportMovieSelectMovieConnector'; -import styles from './ImportMovieRow.css'; - -function ImportMovieRow(props) { - const { - id, - monitor, - qualityProfileId, - minimumAvailability, - selectedMovie, - isExistingMovie, - isSelected, - onSelectedChange, - onInputChange - } = props; - - return ( - <> - - - - {id} - - - - - - - - - - - - - - - - - - - ); -} - -ImportMovieRow.propTypes = { - id: PropTypes.string.isRequired, - monitor: PropTypes.string.isRequired, - qualityProfileId: PropTypes.number.isRequired, - minimumAvailability: PropTypes.string.isRequired, - selectedMovie: PropTypes.object, - isExistingMovie: PropTypes.bool.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - queued: PropTypes.bool.isRequired, - isSelected: PropTypes.bool, - onSelectedChange: PropTypes.func.isRequired, - onInputChange: PropTypes.func.isRequired -}; - -ImportMovieRow.defaultsProps = { - items: [] -}; - -export default ImportMovieRow; diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRowConnector.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRowConnector.js deleted file mode 100644 index b134b8ffd..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRowConnector.js +++ /dev/null @@ -1,87 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { queueLookupMovie, setImportMovieValue } from 'Store/Actions/importMovieActions'; -import createAllMoviesSelector from 'Store/Selectors/createAllMoviesSelector'; -import ImportMovieRow from './ImportMovieRow'; - -function createImportMovieItemSelector() { - return createSelector( - (state, { id }) => id, - (state) => state.importMovie.items, - (id, items) => { - return _.find(items, { id }) || {}; - } - ); -} - -function createMapStateToProps() { - return createSelector( - createImportMovieItemSelector(), - createAllMoviesSelector(), - (item, movies) => { - const selectedMovie = item && item.selectedMovie; - const isExistingMovie = !!selectedMovie && _.some(movies, { tmdbId: selectedMovie.tmdbId }); - - return { - ...item, - isExistingMovie - }; - } - ); -} - -const mapDispatchToProps = { - queueLookupMovie, - setImportMovieValue -}; - -class ImportMovieRowConnector extends Component { - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setImportMovieValue({ - id: this.props.id, - [name]: value - }); - } - - // - // Render - - render() { - // Don't show the row until we have the information we require for it. - - const { - items, - monitor - } = this.props; - - if (!items || !monitor) { - return null; - } - - return ( - - ); - } -} - -ImportMovieRowConnector.propTypes = { - rootFolderId: PropTypes.number.isRequired, - id: PropTypes.string.isRequired, - monitor: PropTypes.string, - items: PropTypes.arrayOf(PropTypes.object), - queueLookupMovie: PropTypes.func.isRequired, - setImportMovieValue: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportMovieRowConnector); diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieSelected.css b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieSelected.css deleted file mode 100644 index 51fe4ce39..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieSelected.css +++ /dev/null @@ -1,3 +0,0 @@ -.input { - composes: input from '~Components/Form/CheckInput.css'; -} diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTable.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTable.js deleted file mode 100644 index 89665fb0a..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTable.js +++ /dev/null @@ -1,185 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import VirtualTable from 'Components/Table/VirtualTable'; -import VirtualTableRow from 'Components/Table/VirtualTableRow'; -import ImportMovieHeader from './ImportMovieHeader'; -import ImportMovieRowConnector from './ImportMovieRowConnector'; - -class ImportMovieTable extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - unmappedFolders, - defaultMonitor, - defaultQualityProfileId, - defaultMinimumAvailability, - onMovieLookup, - onSetImportMovieValue - } = this.props; - - const values = { - monitor: defaultMonitor, - qualityProfileId: defaultQualityProfileId, - minimumAvailability: defaultMinimumAvailability - }; - - unmappedFolders.forEach((unmappedFolder) => { - const id = unmappedFolder.name; - - onMovieLookup(id, unmappedFolder.path); - - onSetImportMovieValue({ - id, - ...values - }); - }); - } - - // This isn't great, but it's the most reliable way to ensure the items - // are checked off even if they aren't actually visible since the cells - // are virtualized. - - componentDidUpdate(prevProps) { - const { - items, - selectedState, - onSelectedChange, - onRemoveSelectedStateItem - } = this.props; - - prevProps.items.forEach((prevItem) => { - const { - id - } = prevItem; - - const item = _.find(items, { id }); - - if (!item) { - onRemoveSelectedStateItem(id); - return; - } - - const selectedMovie = item.selectedMovie; - const isSelected = selectedState[id]; - - const isExistingMovie = !!selectedMovie && - _.some(prevProps.allMovies, { tmdbId: selectedMovie.tmdbId }); - - // Props doesn't have a selected movie or - // the selected movie is an existing movie. - if ((!selectedMovie && prevItem.selectedMovie) || (isExistingMovie && !prevItem.selectedMovie)) { - onSelectedChange({ id, value: false }); - - return; - } - - // State is selected, but a movie isn't selected or - // the selected movie is an existing movie. - if (isSelected && (!selectedMovie || isExistingMovie)) { - onSelectedChange({ id, value: false }); - - return; - } - - // A movie is being selected that wasn't previously selected. - if (selectedMovie && selectedMovie !== prevItem.selectedMovie) { - onSelectedChange({ id, value: true }); - - return; - } - }); - } - - // - // Control - - rowRenderer = ({ key, rowIndex, style }) => { - const { - rootFolderId, - items, - selectedState, - onSelectedChange - } = this.props; - - const item = items[rowIndex]; - - return ( - - - - ); - } - - // - // Render - - render() { - const { - items, - allSelected, - allUnselected, - isSmallScreen, - scroller, - selectedState, - onSelectAllChange - } = this.props; - - if (!items.length) { - return null; - } - - return ( - - } - selectedState={selectedState} - /> - ); - } -} - -ImportMovieTable.propTypes = { - rootFolderId: PropTypes.number.isRequired, - items: PropTypes.arrayOf(PropTypes.object), - unmappedFolders: PropTypes.arrayOf(PropTypes.object), - defaultMonitor: PropTypes.string.isRequired, - defaultQualityProfileId: PropTypes.number, - defaultMinimumAvailability: PropTypes.string, - allSelected: PropTypes.bool.isRequired, - allUnselected: PropTypes.bool.isRequired, - selectedState: PropTypes.object.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - allMovies: PropTypes.arrayOf(PropTypes.object), - scroller: PropTypes.instanceOf(Element).isRequired, - onSelectAllChange: PropTypes.func.isRequired, - onSelectedChange: PropTypes.func.isRequired, - onRemoveSelectedStateItem: PropTypes.func.isRequired, - onMovieLookup: PropTypes.func.isRequired, - onSetImportMovieValue: PropTypes.func.isRequired -}; - -export default ImportMovieTable; diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js deleted file mode 100644 index 2717336c9..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js +++ /dev/null @@ -1,42 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { queueLookupMovie, setImportMovieValue } from 'Store/Actions/importMovieActions'; -import createAllMoviesSelector from 'Store/Selectors/createAllMoviesSelector'; -import ImportMovieTable from './ImportMovieTable'; - -function createMapStateToProps() { - return createSelector( - (state) => state.addMovie, - (state) => state.importMovie, - (state) => state.app.dimensions, - createAllMoviesSelector(), - (addMovie, importMovie, dimensions, allMovies) => { - return { - defaultMonitor: addMovie.defaults.monitor, - defaultQualityProfileId: addMovie.defaults.qualityProfileId, - defaultMinimumAvailability: addMovie.defaults.minimumAvailability, - items: importMovie.items, - isSmallScreen: dimensions.isSmallScreen, - allMovies - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - onMovieLookup(name, path) { - dispatch(queueLookupMovie({ - name, - path, - term: name - })); - }, - - onSetImportMovieValue(values) { - dispatch(setImportMovieValue(values)); - } - }; -} - -export default connect(createMapStateToProps, createMapDispatchToProps)(ImportMovieTable); diff --git a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.css b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.css deleted file mode 100644 index 2e556c521..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.css +++ /dev/null @@ -1,8 +0,0 @@ -.movie { - padding: 10px 20px; - width: 100%; - - &:hover { - background-color: $menuItemHoverBackgroundColor; - } -} diff --git a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.js b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.js deleted file mode 100644 index a36e8d0d2..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.js +++ /dev/null @@ -1,52 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Link from 'Components/Link/Link'; -import ImportMovieTitle from './ImportMovieTitle'; -import styles from './ImportMovieSearchResult.css'; - -class ImportMovieSearchResult extends Component { - - // - // Listeners - - onPress = () => { - this.props.onPress(this.props.tmdbId); - } - - // - // Render - - render() { - const { - title, - year, - studio, - isExistingMovie - } = this.props; - - return ( - - - - ); - } -} - -ImportMovieSearchResult.propTypes = { - tmdbId: PropTypes.number.isRequired, - title: PropTypes.string.isRequired, - year: PropTypes.number.isRequired, - studio: PropTypes.string, - isExistingMovie: PropTypes.bool.isRequired, - onPress: PropTypes.func.isRequired -}; - -export default ImportMovieSearchResult; diff --git a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResultConnector.js b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResultConnector.js deleted file mode 100644 index da5608403..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResultConnector.js +++ /dev/null @@ -1,17 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createExistingMovieSelector from 'Store/Selectors/createExistingMovieSelector'; -import ImportMovieSearchResult from './ImportMovieSearchResult'; - -function createMapStateToProps() { - return createSelector( - createExistingMovieSelector(), - (isExistingMovie) => { - return { - isExistingMovie - }; - } - ); -} - -export default connect(createMapStateToProps)(ImportMovieSearchResult); diff --git a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.css b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.css deleted file mode 100644 index 2b9cef136..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.css +++ /dev/null @@ -1,66 +0,0 @@ -.button { - composes: link from '~Components/Link/Link.css'; - - display: flex; - align-items: center; - justify-content: space-between; - padding: 6px 16px; - width: 100%; - height: 35px; - border: 1px solid $inputBorderColor; - border-radius: 4px; - background-color: $white; - box-shadow: inset 0 1px 1px $inputBoxShadowColor; -} - -.loading { - display: inline-block; -} - -.warningIcon { - margin-right: 8px; -} - -.existing { - margin-left: 5px; -} - -.dropdownArrowContainer { - right: 16px; -} - -.contentContainer { - z-index: $popperZIndex; - margin-top: 4px; - /* 400px container witdh with 8px padding on each side */ - width: 384px; -} - -.content { - padding: 4px; - border: 1px solid $inputBorderColor; - border-radius: 4px; - background-color: $white; -} - -.searchContainer { - display: flex; -} - -.searchIconContainer { - width: 58px; - border: 1px solid $inputBorderColor; - border-right: none; - border-radius: 4px; - border-top-right-radius: 0; - border-bottom-right-radius: 0; - background-color: #edf1f2; - text-align: center; - line-height: 33px; -} - -.searchInput { - composes: input from '~Components/Form/TextInput.css'; - - border-radius: 0; -} diff --git a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.js b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.js deleted file mode 100644 index e3241cebf..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.js +++ /dev/null @@ -1,303 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { Manager, Popper, Reference } from 'react-popper'; -import FormInputButton from 'Components/Form/FormInputButton'; -import TextInput from 'Components/Form/TextInput'; -import Icon from 'Components/Icon'; -import Link from 'Components/Link/Link'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import Portal from 'Components/Portal'; -import { icons, kinds } from 'Helpers/Props'; -import getUniqueElememtId from 'Utilities/getUniqueElementId'; -import translate from 'Utilities/String/translate'; -import ImportMovieSearchResultConnector from './ImportMovieSearchResultConnector'; -import ImportMovieTitle from './ImportMovieTitle'; -import styles from './ImportMovieSelectMovie.css'; - -class ImportMovieSelectMovie extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this._movieLookupTimeout = null; - this._scheduleUpdate = null; - this._buttonId = getUniqueElememtId(); - this._contentId = getUniqueElememtId(); - - this.state = { - term: props.id, - isOpen: false - }; - } - - componentDidUpdate() { - if (this._scheduleUpdate) { - this._scheduleUpdate(); - } - } - - // - // Control - - _addListener() { - window.addEventListener('click', this.onWindowClick); - } - - _removeListener() { - window.removeEventListener('click', this.onWindowClick); - } - - // - // Listeners - - onWindowClick = (event) => { - const button = document.getElementById(this._buttonId); - const content = document.getElementById(this._contentId); - - if (!button || !content) { - return; - } - - if ( - !button.contains(event.target) && - !content.contains(event.target) && - this.state.isOpen - ) { - this.setState({ isOpen: false }); - this._removeListener(); - } - } - - onPress = () => { - if (this.state.isOpen) { - this._removeListener(); - } else { - this._addListener(); - } - - this.setState({ isOpen: !this.state.isOpen }); - } - - onSearchInputChange = ({ value }) => { - if (this._movieLookupTimeout) { - clearTimeout(this._movieLookupTimeout); - } - - this.setState({ term: value }, () => { - this._movieLookupTimeout = setTimeout(() => { - this.props.onSearchInputChange(value); - }, 200); - }); - } - - onRefreshPress = () => { - this.props.onSearchInputChange(this.state.term); - } - - onMovieSelect = (tmdbId) => { - this.setState({ isOpen: false }); - - this.props.onMovieSelect(tmdbId); - } - - // - // Render - - render() { - const { - selectedMovie, - isExistingMovie, - isFetching, - isPopulated, - error, - items, - isQueued, - isLookingUpMovie - } = this.props; - - const errorMessage = error && - error.responseJSON && - error.responseJSON.message; - - return ( - - - {({ ref }) => ( -
- - { - isLookingUpMovie && isQueued && !isPopulated ? - : - null - } - - { - isPopulated && selectedMovie && isExistingMovie ? - : - null - } - - { - isPopulated && selectedMovie ? - : - null - } - - { - isPopulated && !selectedMovie ? -
- - - {translate('NoMatchFound')} -
: - null - } - - { - !isFetching && !!error ? -
- - - {translate('SearchFailedPleaseTryAgainLater')} -
: - null - } - -
- -
- -
- )} -
- - - - {({ ref, style, scheduleUpdate }) => { - this._scheduleUpdate = scheduleUpdate; - - return ( -
- { - this.state.isOpen ? -
-
-
- -
- - - - - - -
- -
- { - items.map((item) => { - return ( - - ); - }) - } -
-
: - null - } -
- ); - }} -
-
-
- ); - } -} - -ImportMovieSelectMovie.propTypes = { - id: PropTypes.string.isRequired, - selectedMovie: PropTypes.object, - isExistingMovie: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - isQueued: PropTypes.bool.isRequired, - isLookingUpMovie: PropTypes.bool.isRequired, - onSearchInputChange: PropTypes.func.isRequired, - onMovieSelect: PropTypes.func.isRequired -}; - -ImportMovieSelectMovie.defaultProps = { - isFetching: true, - isPopulated: false, - items: [], - isQueued: true -}; - -export default ImportMovieSelectMovie; diff --git a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovieConnector.js b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovieConnector.js deleted file mode 100644 index 31c94f294..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovieConnector.js +++ /dev/null @@ -1,76 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { queueLookupMovie, setImportMovieValue } from 'Store/Actions/importMovieActions'; -import createImportMovieItemSelector from 'Store/Selectors/createImportMovieItemSelector'; -import ImportMovieSelectMovie from './ImportMovieSelectMovie'; - -function createMapStateToProps() { - return createSelector( - (state) => state.importMovie.isLookingUpMovie, - createImportMovieItemSelector(), - (isLookingUpMovie, item) => { - return { - isLookingUpMovie, - ...item - }; - } - ); -} - -const mapDispatchToProps = { - queueLookupMovie, - setImportMovieValue -}; - -class ImportMovieSelectMovieConnector extends Component { - - // - // Listeners - - onSearchInputChange = (term) => { - this.props.queueLookupMovie({ - name: this.props.id, - term, - topOfQueue: true - }); - } - - onMovieSelect = (tmdbId) => { - const { - id, - items - } = this.props; - - this.props.setImportMovieValue({ - id, - selectedMovie: _.find(items, { tmdbId }) - }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -ImportMovieSelectMovieConnector.propTypes = { - id: PropTypes.string.isRequired, - items: PropTypes.arrayOf(PropTypes.object), - selectedMovie: PropTypes.object, - isSelected: PropTypes.bool, - queueLookupMovie: PropTypes.func.isRequired, - setImportMovieValue: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportMovieSelectMovieConnector); diff --git a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.css b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.css deleted file mode 100644 index f6ae0f4e6..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.css +++ /dev/null @@ -1,17 +0,0 @@ -.titleContainer { - display: flex; - align-items: center; -} - -.title { - margin-right: 5px; -} - -.year { - margin-left: 5px; - color: $disabledColor; -} - -.existing { - margin-left: 5px; -} diff --git a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.js b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.js deleted file mode 100644 index c6597f1e3..000000000 --- a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.js +++ /dev/null @@ -1,51 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Label from 'Components/Label'; -import { kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './ImportMovieTitle.css'; - -function ImportMovieTitle(props) { - const { - title, - year, - studio, - isExistingMovie - } = props; - - return ( -
-
- {title} - - { - !title.contains(year) && - ({year}) - } -
- - { - !!studio && - - } - - { - isExistingMovie && - - } -
- ); -} - -ImportMovieTitle.propTypes = { - title: PropTypes.string.isRequired, - year: PropTypes.number.isRequired, - studio: PropTypes.string, - isExistingMovie: PropTypes.bool.isRequired -}; - -export default ImportMovieTitle; diff --git a/frontend/src/AddMovie/ImportMovie/ImportMovies.js b/frontend/src/AddMovie/ImportMovie/ImportMovies.js deleted file mode 100644 index c6ae6f9d7..000000000 --- a/frontend/src/AddMovie/ImportMovie/ImportMovies.js +++ /dev/null @@ -1,30 +0,0 @@ -import React, { Component } from 'react'; -import { Route } from 'react-router-dom'; -import ImportMovieConnector from 'AddMovie/ImportMovie/Import/ImportMovieConnector'; -import ImportMovieSelectFolderConnector from 'AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector'; -import Switch from 'Components/Router/Switch'; - -class ImportMovies extends Component { - - // - // Render - - render() { - return ( - - - - - - ); - } -} - -export default ImportMovies; diff --git a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.css b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.css deleted file mode 100644 index 124c9e449..000000000 --- a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.css +++ /dev/null @@ -1,18 +0,0 @@ -.link { - composes: link from '~Components/Link/Link.css'; - - display: block; -} - -.freeSpace, -.unmappedFolders { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 150px; -} - -.actions { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 45px; -} diff --git a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.js b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.js deleted file mode 100644 index 3255a766c..000000000 --- a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.js +++ /dev/null @@ -1,66 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import IconButton from 'Components/Link/IconButton'; -import Link from 'Components/Link/Link'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import TableRow from 'Components/Table/TableRow'; -import { icons } from 'Helpers/Props'; -import formatBytes from 'Utilities/Number/formatBytes'; -import translate from 'Utilities/String/translate'; -import styles from './ImportMovieRootFolderRow.css'; - -function ImportMovieRootFolderRow(props) { - const { - id, - path, - freeSpace, - unmappedFolders, - onDeletePress - } = props; - - const unmappedFoldersCount = unmappedFolders.length || '-'; - - return ( - - - - {path} - - - - - {formatBytes(freeSpace) || '-'} - - - - {unmappedFoldersCount} - - - - - - - ); -} - -ImportMovieRootFolderRow.propTypes = { - id: PropTypes.number.isRequired, - path: PropTypes.string.isRequired, - freeSpace: PropTypes.number.isRequired, - unmappedFolders: PropTypes.arrayOf(PropTypes.object).isRequired, - onDeletePress: PropTypes.func.isRequired -}; - -ImportMovieRootFolderRow.defaultProps = { - freeSpace: 0, - unmappedFolders: [] -}; - -export default ImportMovieRootFolderRow; diff --git a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRowConnector.js b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRowConnector.js deleted file mode 100644 index e25637472..000000000 --- a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRowConnector.js +++ /dev/null @@ -1,48 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { deleteRootFolder } from 'Store/Actions/rootFolderActions'; -import ImportMovieRootFolderRow from './ImportMovieRootFolderRow'; - -function createMapStateToProps() { - return createSelector( - () => { - return { - }; - } - ); -} - -const mapDispatchToProps = { - deleteRootFolder -}; - -class ImportMovieRootFolderRowConnector extends Component { - - // - // Listeners - - onDeletePress = () => { - this.props.deleteRootFolder({ id: this.props.id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -ImportMovieRootFolderRowConnector.propTypes = { - id: PropTypes.number.isRequired, - deleteRootFolder: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportMovieRootFolderRowConnector); diff --git a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.css b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.css deleted file mode 100644 index 030da96fb..000000000 --- a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.css +++ /dev/null @@ -1,32 +0,0 @@ -.header { - margin-bottom: 40px; - text-align: center; - font-weight: 300; - font-size: 36px; -} - -.tips { - font-size: 20px; -} - -.tip { - font-size: $defaultFontSize; -} - -.code { - font-size: 12px; - font-family: $monoSpaceFontFamily; -} - -.recentFolders { - margin-top: 40px; -} - -.startImport { - margin-top: 40px; - text-align: center; -} - -.importButtonIcon { - margin-right: 8px; -} diff --git a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.js b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.js deleted file mode 100644 index d4fa7c048..000000000 --- a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.js +++ /dev/null @@ -1,187 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FieldSet from 'Components/FieldSet'; -import FileBrowserModal from 'Components/FileBrowser/FileBrowserModal'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import Table from 'Components/Table/Table'; -import TableBody from 'Components/Table/TableBody'; -import { icons, kinds, sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import ImportMovieRootFolderRowConnector from './ImportMovieRootFolderRowConnector'; -import styles from './ImportMovieSelectFolder.css'; - -const rootFolderColumns = [ - { - name: 'path', - label: translate('Path'), - isVisible: true - }, - { - name: 'freeSpace', - label: translate('FreeSpace'), - isVisible: true - }, - { - name: 'unmappedFolders', - label: translate('UnmappedFolders'), - isVisible: true - }, - { - name: 'actions', - isVisible: true - } -]; - -class ImportMovieSelectFolder extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isAddNewRootFolderModalOpen: false - }; - } - - // - // Lifecycle - - onAddNewRootFolderPress = () => { - this.setState({ isAddNewRootFolderModalOpen: true }); - } - - onNewRootFolderSelect = ({ value }) => { - this.props.onNewRootFolderSelect(value); - } - - onAddRootFolderModalClose = () => { - this.setState({ isAddNewRootFolderModalOpen: false }); - } - - // - // Render - - render() { - const { - isWindows, - isFetching, - isPopulated, - error, - items - } = this.props; - - return ( - - - { - isFetching && !isPopulated && - - } - - { - !isFetching && !!error && -
- {translate('UnableToLoadRootFolders')} -
- } - - { - !error && isPopulated && -
-
- {translate('ImportHeader')} -
- -
- {translate('ImportTipsMessage')} -
    -
  • movie.2008.bluray.mkv']) }} /> -
  • ${isWindows ? 'C:\\movies' : '/movies'}`, `${isWindows ? 'C:\\movies\\the matrix' : '/movies/the matrix'}`]) }} /> -
-
- - { - items.length > 0 ? -
-
- - - { - items.map((rootFolder) => { - return ( - - ); - }) - } - -
-
- - -
: - -
- -
- } - - -
- } -
-
- ); - } -} - -ImportMovieSelectFolder.propTypes = { - isWindows: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onNewRootFolderSelect: PropTypes.func.isRequired, - onDeleteRootFolderPress: PropTypes.func.isRequired -}; - -export default ImportMovieSelectFolder; diff --git a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector.js b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector.js deleted file mode 100644 index f874cec87..000000000 --- a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector.js +++ /dev/null @@ -1,91 +0,0 @@ -import { push } from 'connected-react-router'; -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { addRootFolder, deleteRootFolder, fetchRootFolders } from 'Store/Actions/rootFolderActions'; -import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector'; -import ImportMovieSelectFolder from './ImportMovieSelectFolder'; - -function createMapStateToProps() { - return createSelector( - (state) => state.rootFolders, - createSystemStatusSelector(), - (rootFolders, systemStatus) => { - return { - ...rootFolders, - isWindows: systemStatus.isWindows - }; - } - ); -} - -const mapDispatchToProps = { - fetchRootFolders, - addRootFolder, - deleteRootFolder, - push -}; - -class ImportMovieSelectFolderConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchRootFolders(); - } - - componentDidUpdate(prevProps) { - const { - items, - isSaving, - saveError - } = this.props; - - if (prevProps.isSaving && !isSaving && !saveError) { - const newRootFolders = _.differenceBy(items, prevProps.items, (item) => item.id); - - if (newRootFolders.length === 1) { - this.props.push(`${window.Prowlarr.urlBase}/add/import/${newRootFolders[0].id}`); - } - } - } - - // - // Listeners - - onNewRootFolderSelect = (path) => { - this.props.addRootFolder({ path }); - } - - onDeleteRootFolderPress = (id) => { - this.props.deleteRootFolder({ id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -ImportMovieSelectFolderConnector.propTypes = { - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - fetchRootFolders: PropTypes.func.isRequired, - addRootFolder: PropTypes.func.isRequired, - deleteRootFolder: PropTypes.func.isRequired, - push: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportMovieSelectFolderConnector); diff --git a/frontend/src/App/AppRoutes.js b/frontend/src/App/AppRoutes.js index 4db8a940a..f61d87e18 100644 --- a/frontend/src/App/AppRoutes.js +++ b/frontend/src/App/AppRoutes.js @@ -1,14 +1,10 @@ import PropTypes from 'prop-types'; import React from 'react'; import { Redirect, Route } from 'react-router-dom'; -import BlacklistConnector from 'Activity/Blacklist/BlacklistConnector'; -import HistoryConnector from 'Activity/History/HistoryConnector'; -import QueueConnector from 'Activity/Queue/QueueConnector'; -import AddNewMovieConnector from 'AddMovie/AddNewMovie/AddNewMovieConnector'; -import ImportMovies from 'AddMovie/ImportMovie/ImportMovies'; import NotFound from 'Components/NotFound'; import Switch from 'Components/Router/Switch'; -import MovieIndexConnector from 'Movie/Index/MovieIndexConnector'; +import HistoryConnector from 'History/HistoryConnector'; +import MovieIndexConnector from 'Indexer/Index/MovieIndexConnector'; import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector'; import IndexerSettingsConnector from 'Settings/Indexers/IndexerSettingsConnector'; import NotificationSettings from 'Settings/Notifications/NotificationSettings'; @@ -58,13 +54,17 @@ function AppRoutes(props) { } + {/* + Search + */} + {/* @@ -72,20 +72,10 @@ function AppRoutes(props) { */} - - - - {/* Settings */} diff --git a/frontend/src/Components/CircularProgressBar.js b/frontend/src/Components/CircularProgressBar.js index b526eef3b..9663503dc 100644 --- a/frontend/src/Components/CircularProgressBar.js +++ b/frontend/src/Components/CircularProgressBar.js @@ -132,7 +132,7 @@ CircularProgressBar.defaultProps = { containerClassName: styles.circularProgressBarContainer, size: 60, strokeWidth: 5, - strokeColor: colors.radarrYellow, + strokeColor: colors.prowlarrYellow, showProgressText: false }; diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRow.js b/frontend/src/Components/Filter/Builder/FilterBuilderRow.js index 9cc6d0360..6938a6162 100644 --- a/frontend/src/Components/Filter/Builder/FilterBuilderRow.js +++ b/frontend/src/Components/Filter/Builder/FilterBuilderRow.js @@ -9,8 +9,6 @@ import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector'; import IndexerFilterBuilderRowValueConnector from './IndexerFilterBuilderRowValueConnector'; import MovieStatusFilterBuilderRowValue from './MovieStatusFilterBuilderRowValue'; import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue'; -import QualityFilterBuilderRowValueConnector from './QualityFilterBuilderRowValueConnector'; -import QualityProfileFilterBuilderRowValueConnector from './QualityProfileFilterBuilderRowValueConnector'; import TagFilterBuilderRowValueConnector from './TagFilterBuilderRowValueConnector'; import styles from './FilterBuilderRow.css'; @@ -62,12 +60,6 @@ function getRowValueConnector(selectedFilterBuilderProp) { case filterBuilderValueTypes.PROTOCOL: return ProtocolFilterBuilderRowValue; - case filterBuilderValueTypes.QUALITY: - return QualityFilterBuilderRowValueConnector; - - case filterBuilderValueTypes.QUALITY_PROFILE: - return QualityProfileFilterBuilderRowValueConnector; - case filterBuilderValueTypes.MOVIE_STATUS: return MovieStatusFilterBuilderRowValue; diff --git a/frontend/src/Components/Filter/Builder/QualityFilterBuilderRowValueConnector.js b/frontend/src/Components/Filter/Builder/QualityFilterBuilderRowValueConnector.js deleted file mode 100644 index bc868cfb0..000000000 --- a/frontend/src/Components/Filter/Builder/QualityFilterBuilderRowValueConnector.js +++ /dev/null @@ -1,75 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import tagShape from 'Helpers/Props/Shapes/tagShape'; -import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions'; -import getQualities from 'Utilities/Quality/getQualities'; -import FilterBuilderRowValue from './FilterBuilderRowValue'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.qualityProfiles, - (qualityProfiles) => { - const { - isSchemaFetching: isFetching, - isSchemaPopulated: isPopulated, - schemaError: error, - schema - } = qualityProfiles; - - const tagList = getQualities(schema.items); - - return { - isFetching, - isPopulated, - error, - tagList - }; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchQualityProfileSchema: fetchQualityProfileSchema -}; - -class QualityFilterBuilderRowValueConnector extends Component { - - // - // Lifecycle - - componentDidMount = () => { - if (!this.props.isPopulated) { - this.props.dispatchFetchQualityProfileSchema(); - } - } - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - ...otherProps - } = this.props; - - return ( - - ); - } -} - -QualityFilterBuilderRowValueConnector.propTypes = { - tagList: PropTypes.arrayOf(PropTypes.shape(tagShape)).isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - dispatchFetchQualityProfileSchema: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(QualityFilterBuilderRowValueConnector); diff --git a/frontend/src/Components/Filter/Builder/QualityProfileFilterBuilderRowValueConnector.js b/frontend/src/Components/Filter/Builder/QualityProfileFilterBuilderRowValueConnector.js deleted file mode 100644 index 4a8b82283..000000000 --- a/frontend/src/Components/Filter/Builder/QualityProfileFilterBuilderRowValueConnector.js +++ /dev/null @@ -1,28 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import FilterBuilderRowValue from './FilterBuilderRowValue'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.qualityProfiles, - (qualityProfiles) => { - const tagList = qualityProfiles.items.map((qualityProfile) => { - const { - id, - name - } = qualityProfile; - - return { - id, - name - }; - }); - - return { - tagList - }; - } - ); -} - -export default connect(createMapStateToProps)(FilterBuilderRowValue); diff --git a/frontend/src/Components/Form/FormInputGroup.js b/frontend/src/Components/Form/FormInputGroup.js index 269117513..0fd434b79 100644 --- a/frontend/src/Components/Form/FormInputGroup.js +++ b/frontend/src/Components/Form/FormInputGroup.js @@ -17,8 +17,6 @@ import NumberInput from './NumberInput'; import OAuthInputConnector from './OAuthInputConnector'; import PasswordInput from './PasswordInput'; import PathInputConnector from './PathInputConnector'; -import QualityProfileSelectInputConnector from './QualityProfileSelectInputConnector'; -import RootFolderSelectInputConnector from './RootFolderSelectInputConnector'; import TagInputConnector from './TagInputConnector'; import TagSelectInputConnector from './TagSelectInputConnector'; import TextArea from './TextArea'; @@ -58,15 +56,9 @@ function getComponent(type) { case inputTypes.PATH: return PathInputConnector; - case inputTypes.QUALITY_PROFILE_SELECT: - return QualityProfileSelectInputConnector; - case inputTypes.MOVIE_MONITORED_SELECT: return MovieMonitoredSelectInput; - case inputTypes.ROOT_FOLDER_SELECT: - return RootFolderSelectInputConnector; - case inputTypes.INDEXER_FLAGS_SELECT: return IndexerFlagsSelectInputConnector; diff --git a/frontend/src/Components/Form/QualityProfileSelectInputConnector.js b/frontend/src/Components/Form/QualityProfileSelectInputConnector.js deleted file mode 100644 index ec0d9ba50..000000000 --- a/frontend/src/Components/Form/QualityProfileSelectInputConnector.js +++ /dev/null @@ -1,99 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector'; -import sortByName from 'Utilities/Array/sortByName'; -import SelectInput from './SelectInput'; - -function createMapStateToProps() { - return createSelector( - createSortedSectionSelector('settings.qualityProfiles', sortByName), - (state, { includeNoChange }) => includeNoChange, - (state, { includeMixed }) => includeMixed, - (qualityProfiles, includeNoChange, includeMixed) => { - const values = _.map(qualityProfiles.items, (qualityProfile) => { - return { - key: qualityProfile.id, - value: qualityProfile.name - }; - }); - - if (includeNoChange) { - values.unshift({ - key: 'noChange', - value: 'No Change', - disabled: true - }); - } - - if (includeMixed) { - values.unshift({ - key: 'mixed', - value: '(Mixed)', - disabled: true - }); - } - - return { - values - }; - } - ); -} - -class QualityProfileSelectInputConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - name, - value, - values - } = this.props; - - if (!value || !values.some((v) => v.key === value) ) { - const firstValue = _.find(values, (option) => !isNaN(parseInt(option.key))); - - if (firstValue) { - this.onChange({ name, value: firstValue.key }); - } - } - } - - // - // Listeners - - onChange = ({ name, value }) => { - this.props.onChange({ name, value: parseInt(value) }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -QualityProfileSelectInputConnector.propTypes = { - name: PropTypes.string.isRequired, - value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - values: PropTypes.arrayOf(PropTypes.object).isRequired, - includeNoChange: PropTypes.bool.isRequired, - onChange: PropTypes.func.isRequired -}; - -QualityProfileSelectInputConnector.defaultProps = { - includeNoChange: false -}; - -export default connect(createMapStateToProps)(QualityProfileSelectInputConnector); diff --git a/frontend/src/Components/Form/RootFolderSelectInput.js b/frontend/src/Components/Form/RootFolderSelectInput.js deleted file mode 100644 index 08d88e5f1..000000000 --- a/frontend/src/Components/Form/RootFolderSelectInput.js +++ /dev/null @@ -1,109 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FileBrowserModal from 'Components/FileBrowser/FileBrowserModal'; -import EnhancedSelectInput from './EnhancedSelectInput'; -import RootFolderSelectInputOption from './RootFolderSelectInputOption'; -import RootFolderSelectInputSelectedValue from './RootFolderSelectInputSelectedValue'; - -class RootFolderSelectInput extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isAddNewRootFolderModalOpen: false, - newRootFolderPath: '' - }; - } - - componentDidUpdate(prevProps) { - const { - name, - isSaving, - saveError, - onChange - } = this.props; - - const newRootFolderPath = this.state.newRootFolderPath; - - if ( - prevProps.isSaving && - !isSaving && - !saveError && - newRootFolderPath - ) { - onChange({ name, value: newRootFolderPath }); - this.setState({ newRootFolderPath: '' }); - } - } - - // - // Listeners - - onChange = ({ name, value }) => { - if (value === 'addNew') { - this.setState({ isAddNewRootFolderModalOpen: true }); - } else { - this.props.onChange({ name, value }); - } - } - - onNewRootFolderSelect = ({ value }) => { - this.setState({ newRootFolderPath: value }, () => { - this.props.onNewRootFolderSelect(value); - }); - } - - onAddRootFolderModalClose = () => { - this.setState({ isAddNewRootFolderModalOpen: false }); - } - - // - // Render - - render() { - const { - includeNoChange, - onNewRootFolderSelect, - ...otherProps - } = this.props; - - return ( -
- - - -
- ); - } -} - -RootFolderSelectInput.propTypes = { - name: PropTypes.string.isRequired, - values: PropTypes.arrayOf(PropTypes.object).isRequired, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - includeNoChange: PropTypes.bool.isRequired, - onChange: PropTypes.func.isRequired, - onNewRootFolderSelect: PropTypes.func.isRequired -}; - -RootFolderSelectInput.defaultProps = { - includeNoChange: false -}; - -export default RootFolderSelectInput; diff --git a/frontend/src/Components/Form/RootFolderSelectInputConnector.js b/frontend/src/Components/Form/RootFolderSelectInputConnector.js deleted file mode 100644 index 0b192d0d3..000000000 --- a/frontend/src/Components/Form/RootFolderSelectInputConnector.js +++ /dev/null @@ -1,157 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { addRootFolder } from 'Store/Actions/rootFolderActions'; -import RootFolderSelectInput from './RootFolderSelectInput'; - -const ADD_NEW_KEY = 'addNew'; - -function createMapStateToProps() { - return createSelector( - (state) => state.rootFolders, - (state, { includeNoChange }) => includeNoChange, - (rootFolders, includeNoChange) => { - const values = rootFolders.items.map((rootFolder) => { - return { - key: rootFolder.path, - value: rootFolder.path, - freeSpace: rootFolder.freeSpace - }; - }); - - if (includeNoChange) { - values.unshift({ - key: 'noChange', - value: 'No Change', - isDisabled: true - }); - } - - if (!values.length) { - values.push({ - key: '', - value: '', - isDisabled: true, - isHidden: true - }); - } - - values.push({ - key: ADD_NEW_KEY, - value: 'Add a new path' - }); - - return { - values, - isSaving: rootFolders.isSaving, - saveError: rootFolders.saveError - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - dispatchAddRootFolder(path) { - dispatch(addRootFolder({ path })); - } - }; -} - -class RootFolderSelectInputConnector extends Component { - - // - // Lifecycle - - UNSAFE_componentWillMount() { - const { - value, - values, - onChange - } = this.props; - - if (value == null && values[0].key === '') { - onChange({ name, value: '' }); - } - } - - componentDidMount() { - const { - name, - value, - values, - onChange - } = this.props; - - if (!value || !values.some((v) => v.key === value) || value === ADD_NEW_KEY) { - const defaultValue = values[0]; - - if (defaultValue.key === ADD_NEW_KEY) { - onChange({ name, value: '' }); - } else { - onChange({ name, value: defaultValue.key }); - } - } - } - - componentDidUpdate(prevProps) { - const { - name, - value, - values, - onChange - } = this.props; - - if (prevProps.values === values) { - return; - } - - if (!value && values.length && values.some((v) => !!v.key && v.key !== ADD_NEW_KEY)) { - const defaultValue = values[0]; - - if (defaultValue.key !== ADD_NEW_KEY) { - onChange({ name, value: defaultValue.key }); - } - } - } - - // - // Listeners - - onNewRootFolderSelect = (path) => { - this.props.dispatchAddRootFolder(path); - } - - // - // Render - - render() { - const { - dispatchAddRootFolder, - ...otherProps - } = this.props; - - return ( - - ); - } -} - -RootFolderSelectInputConnector.propTypes = { - name: PropTypes.string.isRequired, - value: PropTypes.string, - values: PropTypes.arrayOf(PropTypes.object).isRequired, - includeNoChange: PropTypes.bool.isRequired, - onChange: PropTypes.func.isRequired, - dispatchAddRootFolder: PropTypes.func.isRequired -}; - -RootFolderSelectInputConnector.defaultProps = { - includeNoChange: false -}; - -export default connect(createMapStateToProps, createMapDispatchToProps)(RootFolderSelectInputConnector); diff --git a/frontend/src/Components/Form/RootFolderSelectInputOption.css b/frontend/src/Components/Form/RootFolderSelectInputOption.css deleted file mode 100644 index 86cba74bf..000000000 --- a/frontend/src/Components/Form/RootFolderSelectInputOption.css +++ /dev/null @@ -1,31 +0,0 @@ -.optionText { - display: flex; - align-items: center; - justify-content: space-between; - flex: 1 0 0; - - &.isMobile { - display: block; - - .freeSpace { - margin-left: 0; - } - } -} - -.value { - display: flex; - max-width: 500px; -} - -.movieFolder { - @add-mixin truncate; - - color: $disabledColor; -} - -.freeSpace { - margin-left: 15px; - color: $darkGray; - font-size: $smallFontSize; -} diff --git a/frontend/src/Components/Form/RootFolderSelectInputOption.js b/frontend/src/Components/Form/RootFolderSelectInputOption.js deleted file mode 100644 index 58d0c0a28..000000000 --- a/frontend/src/Components/Form/RootFolderSelectInputOption.js +++ /dev/null @@ -1,65 +0,0 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React from 'react'; -import formatBytes from 'Utilities/Number/formatBytes'; -import EnhancedSelectInputOption from './EnhancedSelectInputOption'; -import styles from './RootFolderSelectInputOption.css'; - -function RootFolderSelectInputOption(props) { - const { - id, - value, - freeSpace, - movieFolder, - isMobile, - isWindows, - ...otherProps - } = props; - - const slashCharacter = isWindows ? '\\' : '/'; - - return ( - -
-
- {value} - - { - movieFolder && id !== 'addNew' ? -
- {slashCharacter} - {movieFolder} -
: - null - } -
- - { - freeSpace != null && -
- {formatBytes(freeSpace)} Free -
- } -
-
- ); -} - -RootFolderSelectInputOption.propTypes = { - id: PropTypes.string.isRequired, - value: PropTypes.string.isRequired, - freeSpace: PropTypes.number, - movieFolder: PropTypes.string, - isMobile: PropTypes.bool.isRequired, - isWindows: PropTypes.bool -}; - -export default RootFolderSelectInputOption; diff --git a/frontend/src/Components/Form/RootFolderSelectInputSelectedValue.css b/frontend/src/Components/Form/RootFolderSelectInputSelectedValue.css deleted file mode 100644 index 3ed598bf3..000000000 --- a/frontend/src/Components/Form/RootFolderSelectInputSelectedValue.css +++ /dev/null @@ -1,32 +0,0 @@ -.selectedValue { - composes: selectedValue from '~./EnhancedSelectInputSelectedValue.css'; - - display: flex; - align-items: center; - justify-content: space-between; - overflow: hidden; -} - -.pathContainer { - @add-mixin truncate; - display: flex; - flex: 1 0 0; -} - -.path { - flex: 0 1 auto; -} - -.movieFolder { - @add-mixin truncate; - flex: 0 1 auto; - color: $disabledColor; -} - -.freeSpace { - flex: 0 0 auto; - margin-left: 15px; - color: $gray; - text-align: right; - font-size: $smallFontSize; -} diff --git a/frontend/src/Components/Form/RootFolderSelectInputSelectedValue.js b/frontend/src/Components/Form/RootFolderSelectInputSelectedValue.js deleted file mode 100644 index 803b8bee9..000000000 --- a/frontend/src/Components/Form/RootFolderSelectInputSelectedValue.js +++ /dev/null @@ -1,61 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import formatBytes from 'Utilities/Number/formatBytes'; -import EnhancedSelectInputSelectedValue from './EnhancedSelectInputSelectedValue'; -import styles from './RootFolderSelectInputSelectedValue.css'; - -function RootFolderSelectInputSelectedValue(props) { - const { - value, - freeSpace, - movieFolder, - includeFreeSpace, - isWindows, - ...otherProps - } = props; - - const slashCharacter = isWindows ? '\\' : '/'; - - return ( - -
-
- {value} -
- - { - movieFolder ? -
- {slashCharacter} - {movieFolder} -
: - null - } -
- - { - freeSpace != null && includeFreeSpace && -
- {formatBytes(freeSpace)} Free -
- } -
- ); -} - -RootFolderSelectInputSelectedValue.propTypes = { - value: PropTypes.string, - freeSpace: PropTypes.number, - movieFolder: PropTypes.string, - isWindows: PropTypes.bool, - includeFreeSpace: PropTypes.bool.isRequired -}; - -RootFolderSelectInputSelectedValue.defaultProps = { - includeFreeSpace: true -}; - -export default RootFolderSelectInputSelectedValue; diff --git a/frontend/src/Components/Page/Header/MovieSearchResult.js b/frontend/src/Components/Page/Header/MovieSearchResult.js index 099a0a69e..c0eaa568d 100644 --- a/frontend/src/Components/Page/Header/MovieSearchResult.js +++ b/frontend/src/Components/Page/Header/MovieSearchResult.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import Label from 'Components/Label'; import { kinds } from 'Helpers/Props'; -import MoviePoster from 'Movie/MoviePoster'; +import MoviePoster from 'Indexer/MoviePoster'; import styles from './MovieSearchResult.css'; function MovieSearchResult(props) { diff --git a/frontend/src/Components/Page/Header/PageHeader.css b/frontend/src/Components/Page/Header/PageHeader.css index 53f0b4322..f14f885a0 100644 --- a/frontend/src/Components/Page/Header/PageHeader.css +++ b/frontend/src/Components/Page/Header/PageHeader.css @@ -15,6 +15,11 @@ padding-left: 20px; } +.appTitle { + font-size: 30px; + color: #fff +} + .logoFull, .logo { vertical-align: middle; diff --git a/frontend/src/Components/Page/Header/PageHeader.js b/frontend/src/Components/Page/Header/PageHeader.js index 0054d99b5..0acfc55f4 100644 --- a/frontend/src/Components/Page/Header/PageHeader.js +++ b/frontend/src/Components/Page/Header/PageHeader.js @@ -46,18 +46,14 @@ class PageHeader extends Component { render() { const { - onSidebarToggle, - isSmallScreen + onSidebarToggle } = this.props; return (
- + Prowlarr
@@ -101,7 +97,6 @@ class PageHeader extends Component { PageHeader.propTypes = { onSidebarToggle: PropTypes.func.isRequired, - isSmallScreen: PropTypes.bool.isRequired, bindShortcut: PropTypes.func.isRequired }; diff --git a/frontend/src/Components/Page/PageConnector.js b/frontend/src/Components/Page/PageConnector.js index 9b9adfebe..67dd70538 100644 --- a/frontend/src/Components/Page/PageConnector.js +++ b/frontend/src/Components/Page/PageConnector.js @@ -14,7 +14,7 @@ import LoadingPage from './LoadingPage'; import Page from './Page'; function testLocalStorage() { - const key = 'radarrTest'; + const key = 'prowlarrTest'; try { localStorage.setItem(key, key); diff --git a/frontend/src/Components/Page/Sidebar/PageSidebar.js b/frontend/src/Components/Page/Sidebar/PageSidebar.js index d38f77a5c..7cf67e0d1 100644 --- a/frontend/src/Components/Page/Sidebar/PageSidebar.js +++ b/frontend/src/Components/Page/Sidebar/PageSidebar.js @@ -3,7 +3,6 @@ import _ from 'lodash'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; import ReactDOM from 'react-dom'; -import QueueStatusConnector from 'Activity/Queue/Status/QueueStatusConnector'; import OverlayScroller from 'Components/Scroller/OverlayScroller'; import Scroller from 'Components/Scroller/Scroller'; import { icons } from 'Helpers/Props'; @@ -26,35 +25,22 @@ const links = [ alias: '/movies', children: [ { - title: translate('AddNew'), - to: '/add/new' - }, - { - title: translate('Import'), - to: '/add/import' + title: translate('Stats'), + to: '/indexer/stats' } ] }, { - iconName: icons.ACTIVITY, + iconName: icons.SEARCH, title: 'Search', - to: '/activity/queue', - children: [ - { - title: translate('Queue'), - to: '/activity/queue', - statusComponent: QueueStatusConnector - }, - { - title: translate('History'), - to: '/activity/history' - }, - { - title: translate('Blacklist'), - to: '/activity/blacklist' - } - ] + to: '/search' + }, + + { + iconName: icons.ACTIVITY, + title: 'History', + to: '/history' }, { diff --git a/frontend/src/Components/SignalRConnector.js b/frontend/src/Components/SignalRConnector.js index 74b005460..195e99e39 100644 --- a/frontend/src/Components/SignalRConnector.js +++ b/frontend/src/Components/SignalRConnector.js @@ -7,8 +7,6 @@ import { setAppValue, setVersion } from 'Store/Actions/appActions'; import { removeItem, update, updateItem } from 'Store/Actions/baseActions'; import { fetchCommands, finishCommand, updateCommand } from 'Store/Actions/commandActions'; import { fetchMovies } from 'Store/Actions/movieActions'; -import { fetchQueue, fetchQueueDetails } from 'Store/Actions/queueActions'; -import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; import { fetchHealth } from 'Store/Actions/systemActions'; import { fetchTagDetails, fetchTags } from 'Store/Actions/tagActions'; import { repopulatePage } from 'Utilities/pagePopulator'; @@ -25,12 +23,10 @@ function createMapStateToProps() { return createSelector( (state) => state.app.isReconnecting, (state) => state.app.isDisconnected, - (state) => state.queue.paged.isPopulated, - (isReconnecting, isDisconnected, isQueuePopulated) => { + (isReconnecting, isDisconnected) => { return { isReconnecting, - isDisconnected, - isQueuePopulated + isDisconnected }; } ); @@ -46,9 +42,6 @@ const mapDispatchToProps = { dispatchUpdateItem: updateItem, dispatchRemoveItem: removeItem, dispatchFetchHealth: fetchHealth, - dispatchFetchQueue: fetchQueue, - dispatchFetchQueueDetails: fetchQueueDetails, - dispatchFetchRootFolders: fetchRootFolders, dispatchFetchMovies: fetchMovies, dispatchFetchTags: fetchTags, dispatchFetchTagDetails: fetchTagDetails @@ -146,16 +139,6 @@ class SignalRConnector extends Component { console.error(`signalR: Unable to find handler for ${name}`); } - handleCalendar = (body) => { - if (body.action === 'updated') { - this.props.dispatchUpdateItem({ - section: 'calendar', - updateOnly: true, - ...body.resource - }); - } - } - handleCommand = (body) => { if (body.action === 'sync') { this.props.dispatchFetchCommands(); @@ -175,19 +158,6 @@ class SignalRConnector extends Component { } } - handleMoviefile = (body) => { - const section = 'movieFiles'; - - if (body.action === 'updated') { - this.props.dispatchUpdateItem({ section, ...body.resource }); - - // Repopulate the page to handle recently imported file - repopulatePage('movieFileUpdated'); - } else if (body.action === 'deleted') { - this.props.dispatchRemoveItem({ section, id: body.resource.id }); - } - } - handleHealth = () => { this.props.dispatchFetchHealth(); } @@ -203,20 +173,6 @@ class SignalRConnector extends Component { } } - handleQueue = () => { - if (this.props.isQueuePopulated) { - this.props.dispatchFetchQueue(); - } - } - - handleQueueDetails = () => { - this.props.dispatchFetchQueueDetails(); - } - - handleQueueStatus = (body) => { - this.props.dispatchUpdate({ section: 'queue.status', data: body.resource }); - } - handleVersion = (body) => { const version = body.version; @@ -227,10 +183,6 @@ class SignalRConnector extends Component { this.props.dispatchFetchCommands(); } - handleRootfolder = () => { - this.props.dispatchFetchRootFolders(); - } - handleTag = (body) => { if (body.action === 'sync') { this.props.dispatchFetchTags(); @@ -312,7 +264,6 @@ class SignalRConnector extends Component { SignalRConnector.propTypes = { isReconnecting: PropTypes.bool.isRequired, isDisconnected: PropTypes.bool.isRequired, - isQueuePopulated: PropTypes.bool.isRequired, dispatchFetchCommands: PropTypes.func.isRequired, dispatchUpdateCommand: PropTypes.func.isRequired, dispatchFinishCommand: PropTypes.func.isRequired, @@ -322,9 +273,6 @@ SignalRConnector.propTypes = { dispatchUpdateItem: PropTypes.func.isRequired, dispatchRemoveItem: PropTypes.func.isRequired, dispatchFetchHealth: PropTypes.func.isRequired, - dispatchFetchQueue: PropTypes.func.isRequired, - dispatchFetchQueueDetails: PropTypes.func.isRequired, - dispatchFetchRootFolders: PropTypes.func.isRequired, dispatchFetchMovies: PropTypes.func.isRequired, dispatchFetchTags: PropTypes.func.isRequired, dispatchFetchTagDetails: PropTypes.func.isRequired diff --git a/frontend/src/Helpers/Props/filterBuilderValueTypes.js b/frontend/src/Helpers/Props/filterBuilderValueTypes.js index db340d046..06ea326a3 100644 --- a/frontend/src/Helpers/Props/filterBuilderValueTypes.js +++ b/frontend/src/Helpers/Props/filterBuilderValueTypes.js @@ -4,8 +4,5 @@ export const DATE = 'date'; export const DEFAULT = 'default'; export const INDEXER = 'indexer'; export const PROTOCOL = 'protocol'; -export const QUALITY = 'quality'; -export const QUALITY_PROFILE = 'qualityProfile'; export const MOVIE_STATUS = 'movieStatus'; export const TAG = 'tag'; -export const IMPORTLIST = 'importList'; diff --git a/frontend/src/Helpers/Props/inputTypes.js b/frontend/src/Helpers/Props/inputTypes.js index 46f4c1b84..bc0379858 100644 --- a/frontend/src/Helpers/Props/inputTypes.js +++ b/frontend/src/Helpers/Props/inputTypes.js @@ -8,8 +8,6 @@ export const NUMBER = 'number'; export const OAUTH = 'oauth'; export const PASSWORD = 'password'; export const PATH = 'path'; -export const QUALITY_PROFILE_SELECT = 'qualityProfileSelect'; -export const ROOT_FOLDER_SELECT = 'rootFolderSelect'; export const INDEXER_FLAGS_SELECT = 'indexerFlagsSelect'; export const SELECT = 'select'; export const TAG = 'tag'; @@ -29,8 +27,6 @@ export const all = [ OAUTH, PASSWORD, PATH, - QUALITY_PROFILE_SELECT, - ROOT_FOLDER_SELECT, INDEXER_FLAGS_SELECT, SELECT, TAG, diff --git a/frontend/src/Activity/History/Details/HistoryDetails.css b/frontend/src/History/Details/HistoryDetails.css similarity index 100% rename from frontend/src/Activity/History/Details/HistoryDetails.css rename to frontend/src/History/Details/HistoryDetails.css diff --git a/frontend/src/Activity/History/Details/HistoryDetails.js b/frontend/src/History/Details/HistoryDetails.js similarity index 100% rename from frontend/src/Activity/History/Details/HistoryDetails.js rename to frontend/src/History/Details/HistoryDetails.js diff --git a/frontend/src/Activity/History/Details/HistoryDetailsConnector.js b/frontend/src/History/Details/HistoryDetailsConnector.js similarity index 100% rename from frontend/src/Activity/History/Details/HistoryDetailsConnector.js rename to frontend/src/History/Details/HistoryDetailsConnector.js diff --git a/frontend/src/Activity/History/Details/HistoryDetailsModal.css b/frontend/src/History/Details/HistoryDetailsModal.css similarity index 100% rename from frontend/src/Activity/History/Details/HistoryDetailsModal.css rename to frontend/src/History/Details/HistoryDetailsModal.css diff --git a/frontend/src/Activity/History/Details/HistoryDetailsModal.js b/frontend/src/History/Details/HistoryDetailsModal.js similarity index 100% rename from frontend/src/Activity/History/Details/HistoryDetailsModal.js rename to frontend/src/History/Details/HistoryDetailsModal.js diff --git a/frontend/src/Activity/History/History.js b/frontend/src/History/History.js similarity index 100% rename from frontend/src/Activity/History/History.js rename to frontend/src/History/History.js diff --git a/frontend/src/Activity/History/HistoryConnector.js b/frontend/src/History/HistoryConnector.js similarity index 100% rename from frontend/src/Activity/History/HistoryConnector.js rename to frontend/src/History/HistoryConnector.js diff --git a/frontend/src/Activity/History/HistoryEventTypeCell.css b/frontend/src/History/HistoryEventTypeCell.css similarity index 100% rename from frontend/src/Activity/History/HistoryEventTypeCell.css rename to frontend/src/History/HistoryEventTypeCell.css diff --git a/frontend/src/Activity/History/HistoryEventTypeCell.js b/frontend/src/History/HistoryEventTypeCell.js similarity index 100% rename from frontend/src/Activity/History/HistoryEventTypeCell.js rename to frontend/src/History/HistoryEventTypeCell.js diff --git a/frontend/src/Activity/History/HistoryRow.css b/frontend/src/History/HistoryRow.css similarity index 100% rename from frontend/src/Activity/History/HistoryRow.css rename to frontend/src/History/HistoryRow.css diff --git a/frontend/src/Activity/History/HistoryRow.js b/frontend/src/History/HistoryRow.js similarity index 96% rename from frontend/src/Activity/History/HistoryRow.js rename to frontend/src/History/HistoryRow.js index a605e1435..072a49c6d 100644 --- a/frontend/src/Activity/History/HistoryRow.js +++ b/frontend/src/History/HistoryRow.js @@ -5,10 +5,10 @@ import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellCo import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRow from 'Components/Table/TableRow'; import { icons } from 'Helpers/Props'; -import MovieFormats from 'Movie/MovieFormats'; -import MovieLanguage from 'Movie/MovieLanguage'; -import MovieQuality from 'Movie/MovieQuality'; -import MovieTitleLink from 'Movie/MovieTitleLink'; +import MovieFormats from 'Indexer/MovieFormats'; +import MovieLanguage from 'Indexer/MovieLanguage'; +import MovieQuality from 'Indexer/MovieQuality'; +import MovieTitleLink from 'Indexer/MovieTitleLink'; import HistoryDetailsModal from './Details/HistoryDetailsModal'; import HistoryEventTypeCell from './HistoryEventTypeCell'; import styles from './HistoryRow.css'; diff --git a/frontend/src/Activity/History/HistoryRowConnector.js b/frontend/src/History/HistoryRowConnector.js similarity index 100% rename from frontend/src/Activity/History/HistoryRowConnector.js rename to frontend/src/History/HistoryRowConnector.js diff --git a/frontend/src/Movie/Delete/DeleteMovieModal.js b/frontend/src/Indexer/Delete/DeleteMovieModal.js similarity index 100% rename from frontend/src/Movie/Delete/DeleteMovieModal.js rename to frontend/src/Indexer/Delete/DeleteMovieModal.js diff --git a/frontend/src/Movie/Delete/DeleteMovieModalContent.css b/frontend/src/Indexer/Delete/DeleteMovieModalContent.css similarity index 100% rename from frontend/src/Movie/Delete/DeleteMovieModalContent.css rename to frontend/src/Indexer/Delete/DeleteMovieModalContent.css diff --git a/frontend/src/Movie/Delete/DeleteMovieModalContent.js b/frontend/src/Indexer/Delete/DeleteMovieModalContent.js similarity index 100% rename from frontend/src/Movie/Delete/DeleteMovieModalContent.js rename to frontend/src/Indexer/Delete/DeleteMovieModalContent.js diff --git a/frontend/src/Movie/Delete/DeleteMovieModalContentConnector.js b/frontend/src/Indexer/Delete/DeleteMovieModalContentConnector.js similarity index 100% rename from frontend/src/Movie/Delete/DeleteMovieModalContentConnector.js rename to frontend/src/Indexer/Delete/DeleteMovieModalContentConnector.js diff --git a/frontend/src/Movie/Edit/EditMovieModal.js b/frontend/src/Indexer/Edit/EditMovieModal.js similarity index 100% rename from frontend/src/Movie/Edit/EditMovieModal.js rename to frontend/src/Indexer/Edit/EditMovieModal.js diff --git a/frontend/src/Movie/Edit/EditMovieModalConnector.js b/frontend/src/Indexer/Edit/EditMovieModalConnector.js similarity index 100% rename from frontend/src/Movie/Edit/EditMovieModalConnector.js rename to frontend/src/Indexer/Edit/EditMovieModalConnector.js diff --git a/frontend/src/Movie/Edit/EditMovieModalContent.css b/frontend/src/Indexer/Edit/EditMovieModalContent.css similarity index 100% rename from frontend/src/Movie/Edit/EditMovieModalContent.css rename to frontend/src/Indexer/Edit/EditMovieModalContent.css diff --git a/frontend/src/Movie/Edit/EditMovieModalContent.js b/frontend/src/Indexer/Edit/EditMovieModalContent.js similarity index 91% rename from frontend/src/Movie/Edit/EditMovieModalContent.js rename to frontend/src/Indexer/Edit/EditMovieModalContent.js index f356ee213..a76d40bad 100644 --- a/frontend/src/Movie/Edit/EditMovieModalContent.js +++ b/frontend/src/Indexer/Edit/EditMovieModalContent.js @@ -11,7 +11,6 @@ import ModalContent from 'Components/Modal/ModalContent'; import ModalFooter from 'Components/Modal/ModalFooter'; import ModalHeader from 'Components/Modal/ModalHeader'; import { inputTypes, kinds } from 'Helpers/Props'; -import MoveMovieModal from 'Movie/MoveMovie/MoveMovieModal'; import translate from 'Utilities/String/translate'; import styles from './EditMovieModalContent.css'; @@ -46,12 +45,6 @@ class EditMovieModalContent extends Component { } } - onMoveMoviePress = () => { - this.setState({ isConfirmMoveModalOpen: false }); - - this.props.onSavePress(true); - } - // // Render @@ -166,14 +159,6 @@ class EditMovieModalContent extends Component { {translate('Save')} - - ); } diff --git a/frontend/src/Movie/Edit/EditMovieModalContentConnector.js b/frontend/src/Indexer/Edit/EditMovieModalContentConnector.js similarity index 100% rename from frontend/src/Movie/Edit/EditMovieModalContentConnector.js rename to frontend/src/Indexer/Edit/EditMovieModalContentConnector.js diff --git a/frontend/src/Movie/Editor/Delete/DeleteMovieModal.js b/frontend/src/Indexer/Editor/Delete/DeleteMovieModal.js similarity index 100% rename from frontend/src/Movie/Editor/Delete/DeleteMovieModal.js rename to frontend/src/Indexer/Editor/Delete/DeleteMovieModal.js diff --git a/frontend/src/Movie/Editor/Delete/DeleteMovieModalContent.css b/frontend/src/Indexer/Editor/Delete/DeleteMovieModalContent.css similarity index 100% rename from frontend/src/Movie/Editor/Delete/DeleteMovieModalContent.css rename to frontend/src/Indexer/Editor/Delete/DeleteMovieModalContent.css diff --git a/frontend/src/Movie/Editor/Delete/DeleteMovieModalContent.js b/frontend/src/Indexer/Editor/Delete/DeleteMovieModalContent.js similarity index 100% rename from frontend/src/Movie/Editor/Delete/DeleteMovieModalContent.js rename to frontend/src/Indexer/Editor/Delete/DeleteMovieModalContent.js diff --git a/frontend/src/Movie/Editor/Delete/DeleteMovieModalContentConnector.js b/frontend/src/Indexer/Editor/Delete/DeleteMovieModalContentConnector.js similarity index 100% rename from frontend/src/Movie/Editor/Delete/DeleteMovieModalContentConnector.js rename to frontend/src/Indexer/Editor/Delete/DeleteMovieModalContentConnector.js diff --git a/frontend/src/Movie/Editor/MovieEditorFooter.css b/frontend/src/Indexer/Editor/MovieEditorFooter.css similarity index 100% rename from frontend/src/Movie/Editor/MovieEditorFooter.css rename to frontend/src/Indexer/Editor/MovieEditorFooter.css diff --git a/frontend/src/Movie/Editor/MovieEditorFooter.js b/frontend/src/Indexer/Editor/MovieEditorFooter.js similarity index 82% rename from frontend/src/Movie/Editor/MovieEditorFooter.js rename to frontend/src/Indexer/Editor/MovieEditorFooter.js index 8135fac35..d009d83ab 100644 --- a/frontend/src/Movie/Editor/MovieEditorFooter.js +++ b/frontend/src/Indexer/Editor/MovieEditorFooter.js @@ -1,13 +1,10 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import AvailabilitySelectInput from 'Components/Form/AvailabilitySelectInput'; -import QualityProfileSelectInputConnector from 'Components/Form/QualityProfileSelectInputConnector'; -import RootFolderSelectInputConnector from 'Components/Form/RootFolderSelectInputConnector'; import SelectInput from 'Components/Form/SelectInput'; import SpinnerButton from 'Components/Link/SpinnerButton'; import PageContentFooter from 'Components/Page/PageContentFooter'; import { kinds } from 'Helpers/Props'; -import MoveMovieModal from 'Movie/MoveMovie/MoveMovieModal'; import translate from 'Utilities/String/translate'; import DeleteMovieModal from './Delete/DeleteMovieModal'; import MovieEditorFooterLabel from './MovieEditorFooterLabel'; @@ -31,9 +28,7 @@ class MovieEditorFooter extends Component { rootFolderPath: NO_CHANGE, savingTags: false, isDeleteMovieModalOpen: false, - isTagsModalOpen: false, - isConfirmMoveModalOpen: false, - destinationRootFolder: null + isTagsModalOpen: false }; } @@ -116,18 +111,6 @@ class MovieEditorFooter extends Component { this.props.onSaveSelected({ rootFolderPath: this.state.destinationRootFolder }); } - onMoveMoviePress = () => { - this.setState({ - isConfirmMoveModalOpen: false, - destinationRootFolder: null - }); - - this.props.onSaveSelected({ - rootFolderPath: this.state.destinationRootFolder, - moveFiles: true - }); - } - // // Render @@ -148,9 +131,7 @@ class MovieEditorFooter extends Component { rootFolderPath, savingTags, isTagsModalOpen, - isDeleteMovieModalOpen, - isConfirmMoveModalOpen, - destinationRootFolder + isDeleteMovieModalOpen } = this.state; const monitoredOptions = [ @@ -181,14 +162,6 @@ class MovieEditorFooter extends Component { label={translate('QualityProfile')} isSaving={isSaving && qualityProfileId !== NO_CHANGE} /> - -
@@ -211,15 +184,6 @@ class MovieEditorFooter extends Component { label={translate('RootFolder')} isSaving={isSaving && rootFolderPath !== NO_CHANGE} /> - -
@@ -276,13 +240,6 @@ class MovieEditorFooter extends Component { movieIds={movieIds} onModalClose={this.onDeleteMovieModalClose} /> - - ); } diff --git a/frontend/src/Movie/Editor/MovieEditorFooterLabel.css b/frontend/src/Indexer/Editor/MovieEditorFooterLabel.css similarity index 100% rename from frontend/src/Movie/Editor/MovieEditorFooterLabel.css rename to frontend/src/Indexer/Editor/MovieEditorFooterLabel.css diff --git a/frontend/src/Movie/Editor/MovieEditorFooterLabel.js b/frontend/src/Indexer/Editor/MovieEditorFooterLabel.js similarity index 100% rename from frontend/src/Movie/Editor/MovieEditorFooterLabel.js rename to frontend/src/Indexer/Editor/MovieEditorFooterLabel.js diff --git a/frontend/src/Movie/Editor/Organize/OrganizeMovieModal.js b/frontend/src/Indexer/Editor/Organize/OrganizeMovieModal.js similarity index 100% rename from frontend/src/Movie/Editor/Organize/OrganizeMovieModal.js rename to frontend/src/Indexer/Editor/Organize/OrganizeMovieModal.js diff --git a/frontend/src/Movie/Editor/Organize/OrganizeMovieModalContent.css b/frontend/src/Indexer/Editor/Organize/OrganizeMovieModalContent.css similarity index 100% rename from frontend/src/Movie/Editor/Organize/OrganizeMovieModalContent.css rename to frontend/src/Indexer/Editor/Organize/OrganizeMovieModalContent.css diff --git a/frontend/src/Movie/Editor/Organize/OrganizeMovieModalContent.js b/frontend/src/Indexer/Editor/Organize/OrganizeMovieModalContent.js similarity index 100% rename from frontend/src/Movie/Editor/Organize/OrganizeMovieModalContent.js rename to frontend/src/Indexer/Editor/Organize/OrganizeMovieModalContent.js diff --git a/frontend/src/Movie/Editor/Organize/OrganizeMovieModalContentConnector.js b/frontend/src/Indexer/Editor/Organize/OrganizeMovieModalContentConnector.js similarity index 100% rename from frontend/src/Movie/Editor/Organize/OrganizeMovieModalContentConnector.js rename to frontend/src/Indexer/Editor/Organize/OrganizeMovieModalContentConnector.js diff --git a/frontend/src/Movie/Editor/Tags/TagsModal.js b/frontend/src/Indexer/Editor/Tags/TagsModal.js similarity index 100% rename from frontend/src/Movie/Editor/Tags/TagsModal.js rename to frontend/src/Indexer/Editor/Tags/TagsModal.js diff --git a/frontend/src/Movie/Editor/Tags/TagsModalContent.css b/frontend/src/Indexer/Editor/Tags/TagsModalContent.css similarity index 100% rename from frontend/src/Movie/Editor/Tags/TagsModalContent.css rename to frontend/src/Indexer/Editor/Tags/TagsModalContent.css diff --git a/frontend/src/Movie/Editor/Tags/TagsModalContent.js b/frontend/src/Indexer/Editor/Tags/TagsModalContent.js similarity index 100% rename from frontend/src/Movie/Editor/Tags/TagsModalContent.js rename to frontend/src/Indexer/Editor/Tags/TagsModalContent.js diff --git a/frontend/src/Movie/Editor/Tags/TagsModalContentConnector.js b/frontend/src/Indexer/Editor/Tags/TagsModalContentConnector.js similarity index 100% rename from frontend/src/Movie/Editor/Tags/TagsModalContentConnector.js rename to frontend/src/Indexer/Editor/Tags/TagsModalContentConnector.js diff --git a/frontend/src/Movie/History/MovieHistoryRow.css b/frontend/src/Indexer/History/MovieHistoryRow.css similarity index 100% rename from frontend/src/Movie/History/MovieHistoryRow.css rename to frontend/src/Indexer/History/MovieHistoryRow.css diff --git a/frontend/src/Movie/History/MovieHistoryRow.js b/frontend/src/Indexer/History/MovieHistoryRow.js similarity index 96% rename from frontend/src/Movie/History/MovieHistoryRow.js rename to frontend/src/Indexer/History/MovieHistoryRow.js index 6dac1bdd5..0bbe18fbd 100644 --- a/frontend/src/Movie/History/MovieHistoryRow.js +++ b/frontend/src/Indexer/History/MovieHistoryRow.js @@ -1,16 +1,16 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; import HistoryDetailsModal from 'Activity/History/Details/HistoryDetailsModal'; import HistoryEventTypeCell from 'Activity/History/HistoryEventTypeCell'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; import IconButton from 'Components/Link/IconButton'; import ConfirmModal from 'Components/Modal/ConfirmModal'; import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRow from 'Components/Table/TableRow'; import { icons, kinds } from 'Helpers/Props'; -import MovieFormats from 'Movie/MovieFormats'; -import MovieLanguage from 'Movie/MovieLanguage'; -import MovieQuality from 'Movie/MovieQuality'; +import MovieFormats from 'Indexer/MovieFormats'; +import MovieLanguage from 'Indexer/MovieLanguage'; +import MovieQuality from 'Indexer/MovieQuality'; import translate from 'Utilities/String/translate'; import styles from './MovieHistoryRow.css'; diff --git a/frontend/src/Movie/History/MovieHistoryRowConnector.js b/frontend/src/Indexer/History/MovieHistoryRowConnector.js similarity index 100% rename from frontend/src/Movie/History/MovieHistoryRowConnector.js rename to frontend/src/Indexer/History/MovieHistoryRowConnector.js diff --git a/frontend/src/Movie/History/MovieHistoryTable.js b/frontend/src/Indexer/History/MovieHistoryTable.js similarity index 100% rename from frontend/src/Movie/History/MovieHistoryTable.js rename to frontend/src/Indexer/History/MovieHistoryTable.js diff --git a/frontend/src/Movie/History/MovieHistoryTableContent.css b/frontend/src/Indexer/History/MovieHistoryTableContent.css similarity index 100% rename from frontend/src/Movie/History/MovieHistoryTableContent.css rename to frontend/src/Indexer/History/MovieHistoryTableContent.css diff --git a/frontend/src/Movie/History/MovieHistoryTableContent.js b/frontend/src/Indexer/History/MovieHistoryTableContent.js similarity index 100% rename from frontend/src/Movie/History/MovieHistoryTableContent.js rename to frontend/src/Indexer/History/MovieHistoryTableContent.js diff --git a/frontend/src/Movie/History/MovieHistoryTableContentConnector.js b/frontend/src/Indexer/History/MovieHistoryTableContentConnector.js similarity index 100% rename from frontend/src/Movie/History/MovieHistoryTableContentConnector.js rename to frontend/src/Indexer/History/MovieHistoryTableContentConnector.js diff --git a/frontend/src/Movie/Index/Menus/MovieIndexFilterMenu.js b/frontend/src/Indexer/Index/Menus/MovieIndexFilterMenu.js similarity index 92% rename from frontend/src/Movie/Index/Menus/MovieIndexFilterMenu.js rename to frontend/src/Indexer/Index/Menus/MovieIndexFilterMenu.js index a34f310a9..a2846512c 100644 --- a/frontend/src/Movie/Index/Menus/MovieIndexFilterMenu.js +++ b/frontend/src/Indexer/Index/Menus/MovieIndexFilterMenu.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import FilterMenu from 'Components/Menu/FilterMenu'; import { align } from 'Helpers/Props'; -import MovieIndexFilterModalConnector from 'Movie/Index/MovieIndexFilterModalConnector'; +import MovieIndexFilterModalConnector from 'Indexer/Index/MovieIndexFilterModalConnector'; function MovieIndexFilterMenu(props) { const { diff --git a/frontend/src/Movie/Index/Menus/MovieIndexSearchMenu.js b/frontend/src/Indexer/Index/Menus/MovieIndexSearchMenu.js similarity index 100% rename from frontend/src/Movie/Index/Menus/MovieIndexSearchMenu.js rename to frontend/src/Indexer/Index/Menus/MovieIndexSearchMenu.js diff --git a/frontend/src/Movie/Index/Menus/MovieIndexSortMenu.js b/frontend/src/Indexer/Index/Menus/MovieIndexSortMenu.js similarity index 100% rename from frontend/src/Movie/Index/Menus/MovieIndexSortMenu.js rename to frontend/src/Indexer/Index/Menus/MovieIndexSortMenu.js diff --git a/frontend/src/Movie/Index/MovieIndex.css b/frontend/src/Indexer/Index/MovieIndex.css similarity index 100% rename from frontend/src/Movie/Index/MovieIndex.css rename to frontend/src/Indexer/Index/MovieIndex.css diff --git a/frontend/src/Movie/Index/MovieIndex.js b/frontend/src/Indexer/Index/MovieIndex.js similarity index 84% rename from frontend/src/Movie/Index/MovieIndex.js rename to frontend/src/Indexer/Index/MovieIndex.js index c176eda73..4f7ba06dc 100644 --- a/frontend/src/Movie/Index/MovieIndex.js +++ b/frontend/src/Indexer/Index/MovieIndex.js @@ -12,10 +12,9 @@ import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection'; import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator'; import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper'; import { align, icons, kinds, sortDirections } from 'Helpers/Props'; -import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal'; -import MovieEditorFooter from 'Movie/Editor/MovieEditorFooter.js'; -import OrganizeMovieModal from 'Movie/Editor/Organize/OrganizeMovieModal'; -import NoMovie from 'Movie/NoMovie'; +import MovieEditorFooter from 'Indexer/Editor/MovieEditorFooter.js'; +import OrganizeMovieModal from 'Indexer/Editor/Organize/OrganizeMovieModal'; +import NoMovie from 'Indexer/NoMovie'; import * as keyCodes from 'Utilities/Constants/keyCodes'; import getErrorMessage from 'Utilities/Object/getErrorMessage'; import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder'; @@ -25,25 +24,12 @@ import selectAll from 'Utilities/Table/selectAll'; import toggleSelected from 'Utilities/Table/toggleSelected'; import MovieIndexFilterMenu from './Menus/MovieIndexFilterMenu'; import MovieIndexSortMenu from './Menus/MovieIndexSortMenu'; -import MovieIndexViewMenu from './Menus/MovieIndexViewMenu'; import MovieIndexFooterConnector from './MovieIndexFooterConnector'; -import MovieIndexOverviewsConnector from './Overview/MovieIndexOverviewsConnector'; -import MovieIndexOverviewOptionsModal from './Overview/Options/MovieIndexOverviewOptionsModal'; -import MovieIndexPostersConnector from './Posters/MovieIndexPostersConnector'; -import MovieIndexPosterOptionsModal from './Posters/Options/MovieIndexPosterOptionsModal'; import MovieIndexTableConnector from './Table/MovieIndexTableConnector'; import MovieIndexTableOptionsConnector from './Table/MovieIndexTableOptionsConnector'; import styles from './MovieIndex.css'; function getViewComponent(view) { - if (view === 'posters') { - return MovieIndexPostersConnector; - } - - if (view === 'overview') { - return MovieIndexOverviewsConnector; - } - return MovieIndexTableConnector; } @@ -61,7 +47,6 @@ class MovieIndex extends Component { jumpToCharacter: null, isPosterOptionsModalOpen: false, isOverviewOptionsModalOpen: false, - isInteractiveImportModalOpen: false, isMovieEditorActive: false, isOrganizingMovieModalOpen: false, isConfirmSearchModalOpen: false, @@ -222,14 +207,6 @@ class MovieIndex extends Component { this.setState({ isOverviewOptionsModalOpen: false }); } - onInteractiveImportPress = () => { - this.setState({ isInteractiveImportModalOpen: true }); - } - - onInteractiveImportModalClose = () => { - this.setState({ isInteractiveImportModalOpen: false }); - } - onMovieEditorTogglePress = () => { if (this.state.isMovieEditorActive) { this.setState({ isMovieEditorActive: false }); @@ -351,9 +328,6 @@ class MovieIndex extends Component { scroller, jumpBarItems, jumpToCharacter, - isPosterOptionsModalOpen, - isOverviewOptionsModalOpen, - isInteractiveImportModalOpen, isConfirmSearchModalOpen, isMovieEditorActive, selectedState, @@ -367,44 +341,26 @@ class MovieIndex extends Component { const isLoaded = !!(!error && isPopulated && items.length && scroller); const hasNoMovie = !totalItems; - const searchIndexLabel = selectedFilterKey === 'all' ? translate('SearchAll') : translate('SearchFiltered'); - const searchEditorLabel = selectedMovieIds.length > 0 ? translate('SearchSelected') : translate('SearchAll'); - return ( 0 ? translate('UpdateSelected') : translate('UpdateAll')} - iconName={icons.REFRESH} - spinningName={icons.REFRESH} + label={'Add Indexer'} + iconName={icons.ADD} + spinningName={icons.ADD} isSpinning={isRefreshingMovie} isDisabled={hasNoMovie} onPress={this.onRefreshMoviePress} /> - - - - - - @@ -412,13 +368,13 @@ class MovieIndex extends Component { { isMovieEditorActive ? : - - } - - - - - - state.movieIndex, (movieIndex) => { - const view = movieIndex.view; - - switch (view) { - case 'posters': - return movieIndex.posterOptions.showSearchAction; - case 'overview': - return movieIndex.overviewOptions.showSearchAction; - default: - return movieIndex.tableOptions.showSearchAction; - } + return movieIndex.tableOptions.showSearchAction; } ); } @@ -29,16 +19,12 @@ function selectShowSearchAction() { function createMapStateToProps() { return createSelector( createMovieSelector(), - createMovieQualityProfileSelector(), selectShowSearchAction(), createExecutingCommandsSelector(), - (state) => state.queue.details.items, ( movie, - qualityProfile, showSearchAction, - executingCommands, - queueItems + executingCommands ) => { // If a movie is deleted this selector may fire before the parent @@ -64,16 +50,11 @@ function createMapStateToProps() { ); }); - const firstQueueItem = queueItems.find((q) => q.movieId === movie.id); - return { ...movie, - qualityProfile, showSearchAction, isRefreshingMovie, - isSearchingMovie, - queueStatus: firstQueueItem ? firstQueueItem.status : null, - queueState: firstQueueItem ? firstQueueItem.trackedDownloadState : null + isSearchingMovie }; } ); diff --git a/frontend/src/Movie/Index/ProgressBar/MovieIndexProgressBar.css b/frontend/src/Indexer/Index/ProgressBar/MovieIndexProgressBar.css similarity index 100% rename from frontend/src/Movie/Index/ProgressBar/MovieIndexProgressBar.css rename to frontend/src/Indexer/Index/ProgressBar/MovieIndexProgressBar.css diff --git a/frontend/src/Movie/Index/ProgressBar/MovieIndexProgressBar.js b/frontend/src/Indexer/Index/ProgressBar/MovieIndexProgressBar.js similarity index 100% rename from frontend/src/Movie/Index/ProgressBar/MovieIndexProgressBar.js rename to frontend/src/Indexer/Index/ProgressBar/MovieIndexProgressBar.js diff --git a/frontend/src/Movie/Index/Table/MovieIndexActionsCell.js b/frontend/src/Indexer/Index/Table/MovieIndexActionsCell.js similarity index 94% rename from frontend/src/Movie/Index/Table/MovieIndexActionsCell.js rename to frontend/src/Indexer/Index/Table/MovieIndexActionsCell.js index 47c937536..554ec54d3 100644 --- a/frontend/src/Movie/Index/Table/MovieIndexActionsCell.js +++ b/frontend/src/Indexer/Index/Table/MovieIndexActionsCell.js @@ -4,8 +4,8 @@ import IconButton from 'Components/Link/IconButton'; import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell'; import { icons } from 'Helpers/Props'; -import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal'; -import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector'; +import DeleteMovieModal from 'Indexer/Delete/DeleteMovieModal'; +import EditMovieModalConnector from 'Indexer/Edit/EditMovieModalConnector'; import translate from 'Utilities/String/translate'; class MovieIndexActionsCell extends Component { diff --git a/frontend/src/Movie/Index/Table/MovieIndexHeader.css b/frontend/src/Indexer/Index/Table/MovieIndexHeader.css similarity index 100% rename from frontend/src/Movie/Index/Table/MovieIndexHeader.css rename to frontend/src/Indexer/Index/Table/MovieIndexHeader.css diff --git a/frontend/src/Movie/Index/Table/MovieIndexHeader.js b/frontend/src/Indexer/Index/Table/MovieIndexHeader.js similarity index 100% rename from frontend/src/Movie/Index/Table/MovieIndexHeader.js rename to frontend/src/Indexer/Index/Table/MovieIndexHeader.js diff --git a/frontend/src/Movie/Index/Table/MovieIndexHeaderConnector.js b/frontend/src/Indexer/Index/Table/MovieIndexHeaderConnector.js similarity index 100% rename from frontend/src/Movie/Index/Table/MovieIndexHeaderConnector.js rename to frontend/src/Indexer/Index/Table/MovieIndexHeaderConnector.js diff --git a/frontend/src/Movie/Index/Table/MovieIndexRow.css b/frontend/src/Indexer/Index/Table/MovieIndexRow.css similarity index 100% rename from frontend/src/Movie/Index/Table/MovieIndexRow.css rename to frontend/src/Indexer/Index/Table/MovieIndexRow.css diff --git a/frontend/src/Movie/Index/Table/MovieIndexRow.js b/frontend/src/Indexer/Index/Table/MovieIndexRow.js similarity index 98% rename from frontend/src/Movie/Index/Table/MovieIndexRow.js rename to frontend/src/Indexer/Index/Table/MovieIndexRow.js index 4b2d1090e..c8c0a60c7 100644 --- a/frontend/src/Movie/Index/Table/MovieIndexRow.js +++ b/frontend/src/Indexer/Index/Table/MovieIndexRow.js @@ -10,10 +10,10 @@ import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCel import TagListConnector from 'Components/TagListConnector'; import Tooltip from 'Components/Tooltip/Tooltip'; import { icons, kinds } from 'Helpers/Props'; -import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal'; -import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector'; -import MovieFileStatusConnector from 'Movie/MovieFileStatusConnector'; -import MovieTitleLink from 'Movie/MovieTitleLink'; +import DeleteMovieModal from 'Indexer/Delete/DeleteMovieModal'; +import EditMovieModalConnector from 'Indexer/Edit/EditMovieModalConnector'; +import MovieFileStatusConnector from 'Indexer/MovieFileStatusConnector'; +import MovieTitleLink from 'Indexer/MovieTitleLink'; import formatRuntime from 'Utilities/Date/formatRuntime'; import formatBytes from 'Utilities/Number/formatBytes'; import titleCase from 'Utilities/String/titleCase'; diff --git a/frontend/src/Movie/Index/Table/MovieIndexTable.css b/frontend/src/Indexer/Index/Table/MovieIndexTable.css similarity index 100% rename from frontend/src/Movie/Index/Table/MovieIndexTable.css rename to frontend/src/Indexer/Index/Table/MovieIndexTable.css diff --git a/frontend/src/Movie/Index/Table/MovieIndexTable.js b/frontend/src/Indexer/Index/Table/MovieIndexTable.js similarity index 98% rename from frontend/src/Movie/Index/Table/MovieIndexTable.js rename to frontend/src/Indexer/Index/Table/MovieIndexTable.js index 9c2f6542c..b32213c10 100644 --- a/frontend/src/Movie/Index/Table/MovieIndexTable.js +++ b/frontend/src/Indexer/Index/Table/MovieIndexTable.js @@ -3,7 +3,7 @@ import React, { Component } from 'react'; import VirtualTable from 'Components/Table/VirtualTable'; import VirtualTableRow from 'Components/Table/VirtualTableRow'; import { sortDirections } from 'Helpers/Props'; -import MovieIndexItemConnector from 'Movie/Index/MovieIndexItemConnector'; +import MovieIndexItemConnector from 'Indexer/Index/MovieIndexItemConnector'; import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter'; import MovieIndexHeaderConnector from './MovieIndexHeaderConnector'; import MovieIndexRow from './MovieIndexRow'; diff --git a/frontend/src/Movie/Index/Table/MovieIndexTableConnector.js b/frontend/src/Indexer/Index/Table/MovieIndexTableConnector.js similarity index 100% rename from frontend/src/Movie/Index/Table/MovieIndexTableConnector.js rename to frontend/src/Indexer/Index/Table/MovieIndexTableConnector.js diff --git a/frontend/src/Movie/Index/Table/MovieIndexTableOptions.js b/frontend/src/Indexer/Index/Table/MovieIndexTableOptions.js similarity index 100% rename from frontend/src/Movie/Index/Table/MovieIndexTableOptions.js rename to frontend/src/Indexer/Index/Table/MovieIndexTableOptions.js diff --git a/frontend/src/Movie/Index/Table/MovieIndexTableOptionsConnector.js b/frontend/src/Indexer/Index/Table/MovieIndexTableOptionsConnector.js similarity index 100% rename from frontend/src/Movie/Index/Table/MovieIndexTableOptionsConnector.js rename to frontend/src/Indexer/Index/Table/MovieIndexTableOptionsConnector.js diff --git a/frontend/src/Movie/Index/Table/MovieStatusCell.css b/frontend/src/Indexer/Index/Table/MovieStatusCell.css similarity index 100% rename from frontend/src/Movie/Index/Table/MovieStatusCell.css rename to frontend/src/Indexer/Index/Table/MovieStatusCell.css diff --git a/frontend/src/Movie/Index/Table/MovieStatusCell.js b/frontend/src/Indexer/Index/Table/MovieStatusCell.js similarity index 95% rename from frontend/src/Movie/Index/Table/MovieStatusCell.js rename to frontend/src/Indexer/Index/Table/MovieStatusCell.js index d8f129573..24595ac60 100644 --- a/frontend/src/Movie/Index/Table/MovieStatusCell.js +++ b/frontend/src/Indexer/Index/Table/MovieStatusCell.js @@ -3,7 +3,7 @@ import React from 'react'; import Icon from 'Components/Icon'; import VirtualTableRowCell from 'Components/Table/Cells/TableRowCell'; import { icons } from 'Helpers/Props'; -import { getMovieStatusDetails } from 'Movie/MovieStatus'; +import { getMovieStatusDetails } from 'Indexer/MovieStatus'; import translate from 'Utilities/String/translate'; import styles from './MovieStatusCell.css'; diff --git a/frontend/src/Movie/MovieBanner.js b/frontend/src/Indexer/MovieBanner.js similarity index 100% rename from frontend/src/Movie/MovieBanner.js rename to frontend/src/Indexer/MovieBanner.js diff --git a/frontend/src/Movie/MovieCollection.css b/frontend/src/Indexer/MovieCollection.css similarity index 100% rename from frontend/src/Movie/MovieCollection.css rename to frontend/src/Indexer/MovieCollection.css diff --git a/frontend/src/Movie/MovieCollection.js b/frontend/src/Indexer/MovieCollection.js similarity index 100% rename from frontend/src/Movie/MovieCollection.js rename to frontend/src/Indexer/MovieCollection.js diff --git a/frontend/src/Movie/MovieCollectionConnector.js b/frontend/src/Indexer/MovieCollectionConnector.js similarity index 100% rename from frontend/src/Movie/MovieCollectionConnector.js rename to frontend/src/Indexer/MovieCollectionConnector.js diff --git a/frontend/src/Movie/MovieFileStatus.css b/frontend/src/Indexer/MovieFileStatus.css similarity index 100% rename from frontend/src/Movie/MovieFileStatus.css rename to frontend/src/Indexer/MovieFileStatus.css diff --git a/frontend/src/Movie/MovieFileStatus.js b/frontend/src/Indexer/MovieFileStatus.js similarity index 97% rename from frontend/src/Movie/MovieFileStatus.js rename to frontend/src/Indexer/MovieFileStatus.js index 7c6be4825..14f4200e7 100644 --- a/frontend/src/Movie/MovieFileStatus.js +++ b/frontend/src/Indexer/MovieFileStatus.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import Label from 'Components/Label'; import { kinds } from 'Helpers/Props'; -import MovieQuality from 'Movie/MovieQuality'; +import MovieQuality from 'Indexer/MovieQuality'; import getQueueStatusText from 'Utilities/Movie/getQueueStatusText'; import translate from 'Utilities/String/translate'; import styles from './MovieFileStatus.css'; diff --git a/frontend/src/Movie/MovieFileStatusConnector.js b/frontend/src/Indexer/MovieFileStatusConnector.js similarity index 100% rename from frontend/src/Movie/MovieFileStatusConnector.js rename to frontend/src/Indexer/MovieFileStatusConnector.js diff --git a/frontend/src/Movie/MovieFormats.js b/frontend/src/Indexer/MovieFormats.js similarity index 100% rename from frontend/src/Movie/MovieFormats.js rename to frontend/src/Indexer/MovieFormats.js diff --git a/frontend/src/Movie/MovieHeadshot.js b/frontend/src/Indexer/MovieHeadshot.js similarity index 100% rename from frontend/src/Movie/MovieHeadshot.js rename to frontend/src/Indexer/MovieHeadshot.js diff --git a/frontend/src/Movie/MovieImage.js b/frontend/src/Indexer/MovieImage.js similarity index 100% rename from frontend/src/Movie/MovieImage.js rename to frontend/src/Indexer/MovieImage.js diff --git a/frontend/src/Movie/MovieLanguage.js b/frontend/src/Indexer/MovieLanguage.js similarity index 100% rename from frontend/src/Movie/MovieLanguage.js rename to frontend/src/Indexer/MovieLanguage.js diff --git a/frontend/src/Movie/MoviePoster.js b/frontend/src/Indexer/MoviePoster.js similarity index 100% rename from frontend/src/Movie/MoviePoster.js rename to frontend/src/Indexer/MoviePoster.js diff --git a/frontend/src/Movie/MovieQuality.js b/frontend/src/Indexer/MovieQuality.js similarity index 100% rename from frontend/src/Movie/MovieQuality.js rename to frontend/src/Indexer/MovieQuality.js diff --git a/frontend/src/Movie/MovieStatus.js b/frontend/src/Indexer/MovieStatus.js similarity index 100% rename from frontend/src/Movie/MovieStatus.js rename to frontend/src/Indexer/MovieStatus.js diff --git a/frontend/src/Movie/MovieTitleLink.js b/frontend/src/Indexer/MovieTitleLink.js similarity index 100% rename from frontend/src/Movie/MovieTitleLink.js rename to frontend/src/Indexer/MovieTitleLink.js diff --git a/frontend/src/Movie/NoMovie.css b/frontend/src/Indexer/NoMovie.css similarity index 100% rename from frontend/src/Movie/NoMovie.css rename to frontend/src/Indexer/NoMovie.css diff --git a/frontend/src/Movie/NoMovie.js b/frontend/src/Indexer/NoMovie.js similarity index 100% rename from frontend/src/Movie/NoMovie.js rename to frontend/src/Indexer/NoMovie.js diff --git a/frontend/src/Movie/movieEntities.js b/frontend/src/Indexer/movieEntities.js similarity index 100% rename from frontend/src/Movie/movieEntities.js rename to frontend/src/Indexer/movieEntities.js diff --git a/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.css b/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.css deleted file mode 100644 index 5f9033a18..000000000 --- a/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.css +++ /dev/null @@ -1,24 +0,0 @@ -.recentFoldersContainer { - margin-top: 15px; -} - -.buttonsContainer { - margin-top: 30px; -} - -.buttonContainer { - display: flex; - justify-content: center; - - margin-top: 10px; -} - -.button { - composes: button from '~Components/Link/Button.css'; - - width: 300px; -} - -.buttonIcon { - margin-right: 5px; -} diff --git a/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.js b/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.js deleted file mode 100644 index c99f4e33a..000000000 --- a/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.js +++ /dev/null @@ -1,169 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import PathInputConnector from 'Components/Form/PathInputConnector'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import Table from 'Components/Table/Table'; -import TableBody from 'Components/Table/TableBody'; -import { icons, kinds, sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import RecentFolderRow from './RecentFolderRow'; -import styles from './InteractiveImportSelectFolderModalContent.css'; - -const recentFoldersColumns = [ - { - name: 'folder', - label: 'Folder' - }, - { - name: 'lastUsed', - label: 'Last Used' - }, - { - name: 'actions', - label: '' - } -]; - -class InteractiveImportSelectFolderModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - folder: '' - }; - } - - // - // Listeners - - onPathChange = ({ value }) => { - this.setState({ folder: value }); - } - - onRecentPathPress = (folder) => { - this.setState({ folder }); - } - - onQuickImportPress = () => { - this.props.onQuickImportPress(this.state.folder); - } - - onInteractiveImportPress = () => { - this.props.onInteractiveImportPress(this.state.folder); - } - - // - // Render - - render() { - const { - recentFolders, - onRemoveRecentFolderPress, - onModalClose - } = this.props; - - const folder = this.state.folder; - - return ( - - - {translate('ManualImport')} - {translate('SelectFolder')} - - - - - - { - !!recentFolders.length && -
- - - { - recentFolders.slice(0).reverse().map((recentFolder) => { - return ( - - ); - }) - } - -
-
- } - -
-
- -
- -
- -
-
-
- - - - -
- ); - } -} - -InteractiveImportSelectFolderModalContent.propTypes = { - recentFolders: PropTypes.arrayOf(PropTypes.object).isRequired, - onQuickImportPress: PropTypes.func.isRequired, - onInteractiveImportPress: PropTypes.func.isRequired, - onRemoveRecentFolderPress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default InteractiveImportSelectFolderModalContent; diff --git a/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContentConnector.js b/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContentConnector.js deleted file mode 100644 index b0aced65c..000000000 --- a/frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContentConnector.js +++ /dev/null @@ -1,80 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import * as commandNames from 'Commands/commandNames'; -import { executeCommand } from 'Store/Actions/commandActions'; -import { addRecentFolder, removeRecentFolder } from 'Store/Actions/interactiveImportActions'; -import InteractiveImportSelectFolderModalContent from './InteractiveImportSelectFolderModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.interactiveImport.recentFolders, - (recentFolders) => { - return { - recentFolders - }; - } - ); -} - -const mapDispatchToProps = { - addRecentFolder, - removeRecentFolder, - executeCommand -}; - -class InteractiveImportSelectFolderModalContentConnector extends Component { - - // - // Listeners - - onQuickImportPress = (folder) => { - this.props.addRecentFolder({ folder }); - - this.props.executeCommand({ - name: commandNames.DOWNLOADED_MOVIES_SCAN, - path: folder - }); - - this.props.onModalClose(); - } - - onInteractiveImportPress = (folder) => { - this.props.addRecentFolder({ folder }); - this.props.onFolderSelect(folder); - } - - onRemoveRecentFolderPress = (folder) => { - this.props.removeRecentFolder({ folder }); - } - - // - // Render - - render() { - if (this.path) { - return null; - } - - return ( - - ); - } -} - -InteractiveImportSelectFolderModalContentConnector.propTypes = { - path: PropTypes.string, - onFolderSelect: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired, - addRecentFolder: PropTypes.func.isRequired, - removeRecentFolder: PropTypes.func.isRequired, - executeCommand: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(InteractiveImportSelectFolderModalContentConnector); diff --git a/frontend/src/InteractiveImport/Folder/RecentFolderRow.css b/frontend/src/InteractiveImport/Folder/RecentFolderRow.css deleted file mode 100644 index 58eb9a8e4..000000000 --- a/frontend/src/InteractiveImport/Folder/RecentFolderRow.css +++ /dev/null @@ -1,5 +0,0 @@ -.actions { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 40px; -} diff --git a/frontend/src/InteractiveImport/Folder/RecentFolderRow.js b/frontend/src/InteractiveImport/Folder/RecentFolderRow.js deleted file mode 100644 index 6e3185cd5..000000000 --- a/frontend/src/InteractiveImport/Folder/RecentFolderRow.js +++ /dev/null @@ -1,65 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import IconButton from 'Components/Link/IconButton'; -import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import TableRowButton from 'Components/Table/TableRowButton'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './RecentFolderRow.css'; - -class RecentFolderRow extends Component { - - // - // Listeners - - onPress = () => { - this.props.onPress(this.props.folder); - } - - onRemovePress = (event) => { - event.stopPropagation(); - - const { - folder, - onRemoveRecentFolderPress - } = this.props; - - onRemoveRecentFolderPress(folder); - } - - // - // Render - - render() { - const { - folder, - lastUsed - } = this.props; - - return ( - - {folder} - - - - - - - - ); - } -} - -RecentFolderRow.propTypes = { - folder: PropTypes.string.isRequired, - lastUsed: PropTypes.string.isRequired, - onPress: PropTypes.func.isRequired, - onRemoveRecentFolderPress: PropTypes.func.isRequired -}; - -export default RecentFolderRow; diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.css b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.css deleted file mode 100644 index d50f3a261..000000000 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.css +++ /dev/null @@ -1,65 +0,0 @@ -.filterContainer { - display: flex; - justify-content: flex-end; - margin-bottom: 10px; -} - -.filterText { - margin-left: 5px; -} - -.footer { - composes: modalFooter from '~Components/Modal/ModalFooter.css'; - - justify-content: space-between; - padding: 15px; -} - -.leftButtons, -.rightButtons { - display: flex; - flex: 1 0 50%; - flex-wrap: wrap; -} - -.rightButtons { - justify-content: flex-end; -} - -.importMode, -.bulkSelect { - composes: select from '~Components/Form/SelectInput.css'; - - margin-right: 10px; - width: auto; -} - -.errorMessage { - color: $dangerColor; -} - -@media only screen and (max-width: $breakpointSmall) { - .footer { - .leftButtons, - .rightButtons { - flex-direction: column; - } - - .leftButtons { - align-items: flex-start; - } - - .rightButtons { - align-items: flex-end; - } - - a, - button { - margin-left: 0; - - &:first-child { - margin-bottom: 5px; - } - } - } -} diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js deleted file mode 100644 index 1aab8f6dc..000000000 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js +++ /dev/null @@ -1,409 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import SelectInput from 'Components/Form/SelectInput'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import Menu from 'Components/Menu/Menu'; -import MenuButton from 'Components/Menu/MenuButton'; -import MenuContent from 'Components/Menu/MenuContent'; -import SelectedMenuItem from 'Components/Menu/SelectedMenuItem'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import Table from 'Components/Table/Table'; -import TableBody from 'Components/Table/TableBody'; -import { align, icons, kinds, scrollDirections } from 'Helpers/Props'; -import SelectLanguageModal from 'InteractiveImport/Language/SelectLanguageModal'; -import SelectMovieModal from 'InteractiveImport/Movie/SelectMovieModal'; -import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal'; -import getErrorMessage from 'Utilities/Object/getErrorMessage'; -import translate from 'Utilities/String/translate'; -import getSelectedIds from 'Utilities/Table/getSelectedIds'; -import selectAll from 'Utilities/Table/selectAll'; -import toggleSelected from 'Utilities/Table/toggleSelected'; -import InteractiveImportRow from './InteractiveImportRow'; -import styles from './InteractiveImportModalContent.css'; - -const columns = [ - { - name: 'relativePath', - label: translate('RelativePath'), - isSortable: true, - isVisible: true - }, - { - name: 'movie', - label: translate('Movie'), - isSortable: true, - isVisible: true - }, - { - name: 'quality', - label: translate('Quality'), - isSortable: true, - isVisible: true - }, - { - name: 'languages', - label: translate('Languages'), - isSortable: true, - isVisible: true - }, - { - name: 'size', - label: translate('Size'), - isSortable: true, - isVisible: true - }, - { - name: 'rejections', - label: React.createElement(Icon, { - name: icons.DANGER, - kind: kinds.DANGER - }), - isVisible: true - } -]; - -const filterExistingFilesOptions = { - ALL: 'all', - NEW: 'new' -}; - -const importModeOptions = [ - { key: 'move', value: translate('MoveFiles') }, - { key: 'copy', value: translate('HardlinkCopyFiles') } -]; - -const SELECT = 'select'; -const MOVIE = 'movie'; -const LANGUAGE = 'language'; -const QUALITY = 'quality'; - -class InteractiveImportModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - allSelected: false, - allUnselected: false, - lastToggled: null, - selectedState: {}, - invalidRowsSelected: [], - selectModalOpen: null - }; - } - - // - // Control - - getSelectedIds = () => { - return getSelectedIds(this.state.selectedState); - } - - // - // Listeners - - onSelectAllChange = ({ value }) => { - this.setState(selectAll(this.state.selectedState, value)); - } - - onSelectedChange = ({ id, value, shiftKey = false }) => { - this.setState((state) => { - return toggleSelected(state, this.props.items, id, value, shiftKey); - }); - } - - onValidRowChange = (id, isValid) => { - this.setState((state) => { - if (isValid) { - return { - invalidRowsSelected: _.without(state.invalidRowsSelected, id) - }; - } - - return { - invalidRowsSelected: [...state.invalidRowsSelected, id] - }; - }); - } - - onImportSelectedPress = () => { - const { - downloadId, - showImportMode, - importMode, - onImportSelectedPress - } = this.props; - - const selected = this.getSelectedIds(); - const finalImportMode = downloadId || !showImportMode ? 'auto' : importMode; - - onImportSelectedPress(selected, finalImportMode); - } - - onFilterExistingFilesChange = (value) => { - this.props.onFilterExistingFilesChange(value !== filterExistingFilesOptions.ALL); - } - - onImportModeChange = ({ value }) => { - this.props.onImportModeChange(value); - } - - onSelectModalSelect = ({ value }) => { - this.setState({ selectModalOpen: value }); - } - - onSelectModalClose = () => { - this.setState({ selectModalOpen: null }); - } - - // - // Render - - render() { - const { - downloadId, - allowMovieChange, - showFilterExistingFiles, - showImportMode, - filterExistingFiles, - title, - folder, - isFetching, - isPopulated, - error, - items, - sortKey, - sortDirection, - importMode, - interactiveImportErrorMessage, - onSortPress, - onModalClose - } = this.props; - - const { - allSelected, - allUnselected, - selectedState, - invalidRowsSelected, - selectModalOpen - } = this.state; - - const selectedIds = this.getSelectedIds(); - const errorMessage = getErrorMessage(error, 'Unable to load manual import items'); - - const bulkSelectOptions = [ - { key: SELECT, value: 'Select...', disabled: true }, - { key: LANGUAGE, value: 'Select Language' }, - { key: QUALITY, value: 'Select Quality' } - ]; - - if (allowMovieChange) { - bulkSelectOptions.splice(1, 0, { - key: MOVIE, - value: 'Select Movie' - }); - } - - return ( - - - Manual Import - {title || folder} - - - - { - showFilterExistingFiles && -
- - - - -
- { - filterExistingFiles ? 'Unmapped Files Only' : 'All Files' - } -
-
- - - - All Files - - - - Unmapped Files Only - - -
-
- } - - { - isFetching && - - } - - { - error && -
{errorMessage}
- } - - { - isPopulated && !!items.length && !isFetching && !isFetching && - - - { - items.map((item) => { - return ( - - ); - }) - } - -
- } - - { - isPopulated && !items.length && !isFetching && - 'No video files were found in the selected folder' - } -
- - -
- { - !downloadId && showImportMode ? - : - null - } - - -
- -
- - - { - interactiveImportErrorMessage && - {interactiveImportErrorMessage} - } - - -
-
- - - - - - -
- ); - } -} - -InteractiveImportModalContent.propTypes = { - downloadId: PropTypes.string, - allowMovieChange: PropTypes.bool.isRequired, - showImportMode: PropTypes.bool.isRequired, - showFilterExistingFiles: PropTypes.bool.isRequired, - filterExistingFiles: PropTypes.bool.isRequired, - importMode: PropTypes.string.isRequired, - title: PropTypes.string, - folder: PropTypes.string, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - sortKey: PropTypes.string, - sortDirection: PropTypes.string, - interactiveImportErrorMessage: PropTypes.string, - onSortPress: PropTypes.func.isRequired, - onFilterExistingFilesChange: PropTypes.func.isRequired, - onImportModeChange: PropTypes.func.isRequired, - onImportSelectedPress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -InteractiveImportModalContent.defaultProps = { - allowMovieChange: true, - showFilterExistingFiles: false, - showImportMode: true, - importMode: 'move' -}; - -export default InteractiveImportModalContent; diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js deleted file mode 100644 index d1544c79c..000000000 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js +++ /dev/null @@ -1,195 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import * as commandNames from 'Commands/commandNames'; -import { executeCommand } from 'Store/Actions/commandActions'; -import { clearInteractiveImport, fetchInteractiveImportItems, setInteractiveImportMode, setInteractiveImportSort } from 'Store/Actions/interactiveImportActions'; -import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector'; -import InteractiveImportModalContent from './InteractiveImportModalContent'; - -function createMapStateToProps() { - return createSelector( - createClientSideCollectionSelector('interactiveImport'), - (interactiveImport) => { - return interactiveImport; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchInteractiveImportItems: fetchInteractiveImportItems, - dispatchSetInteractiveImportSort: setInteractiveImportSort, - dispatchSetInteractiveImportMode: setInteractiveImportMode, - dispatchClearInteractiveImport: clearInteractiveImport, - dispatchExecuteCommand: executeCommand -}; - -class InteractiveImportModalContentConnector extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - interactiveImportErrorMessage: null, - filterExistingFiles: true - }; - } - - componentDidMount() { - const { - downloadId, - movieId, - folder - } = this.props; - - const { - filterExistingFiles - } = this.state; - - this.props.dispatchFetchInteractiveImportItems({ - downloadId, - movieId, - folder, - filterExistingFiles - }); - } - - componentDidUpdate(prevProps, prevState) { - const { - filterExistingFiles - } = this.state; - - if (prevState.filterExistingFiles !== filterExistingFiles) { - const { - downloadId, - movieId, - folder - } = this.props; - - this.props.dispatchFetchInteractiveImportItems({ - downloadId, - movieId, - folder, - filterExistingFiles - }); - } - } - - componentWillUnmount() { - this.props.dispatchClearInteractiveImport(); - } - - // - // Listeners - - onSortPress = (sortKey, sortDirection) => { - this.props.dispatchSetInteractiveImportSort({ sortKey, sortDirection }); - } - - onFilterExistingFilesChange = (filterExistingFiles) => { - this.setState({ filterExistingFiles }); - } - - onImportModeChange = (importMode) => { - this.props.dispatchSetInteractiveImportMode({ importMode }); - } - - onImportSelectedPress = (selected, importMode) => { - const files = []; - - _.forEach(this.props.items, (item) => { - const isSelected = selected.indexOf(item.id) > -1; - - if (isSelected) { - const { - movie, - quality, - languages - } = item; - - if (!movie) { - this.setState({ interactiveImportErrorMessage: 'Movie must be chosen for each selected file' }); - return false; - } - - if (!quality) { - this.setState({ interactiveImportErrorMessage: 'Quality must be chosen for each selected file' }); - return false; - } - - if (!languages) { - this.setState({ interactiveImportErrorMessage: 'Language must be chosen for each selected file' }); - return false; - } - - files.push({ - path: item.path, - folderName: item.folderName, - movieId: movie.id, - quality, - languages, - downloadId: this.props.downloadId - }); - } - }); - - if (!files.length) { - return; - } - - this.props.dispatchExecuteCommand({ - name: commandNames.INTERACTIVE_IMPORT, - files, - importMode - }); - - this.props.onModalClose(); - } - - // - // Render - - render() { - const { - interactiveImportErrorMessage, - filterExistingFiles - } = this.state; - - return ( - - ); - } -} - -InteractiveImportModalContentConnector.propTypes = { - downloadId: PropTypes.string, - movieId: PropTypes.number, - folder: PropTypes.string, - filterExistingFiles: PropTypes.bool.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - dispatchFetchInteractiveImportItems: PropTypes.func.isRequired, - dispatchSetInteractiveImportSort: PropTypes.func.isRequired, - dispatchSetInteractiveImportMode: PropTypes.func.isRequired, - dispatchClearInteractiveImport: PropTypes.func.isRequired, - dispatchExecuteCommand: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -InteractiveImportModalContentConnector.defaultProps = { - filterExistingFiles: true -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(InteractiveImportModalContentConnector); diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.css b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.css deleted file mode 100644 index f1b7b44e7..000000000 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.css +++ /dev/null @@ -1,23 +0,0 @@ -.relativePath { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - word-break: break-all; -} - -.quality, -.language { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; -} - -.label { - composes: label from '~Components/Label.css'; - - cursor: pointer; -} - -.reprocessing { - composes: loading from '~Components/Loading/LoadingIndicator.css'; - - margin-top: 0; - text-align: start; -} diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js deleted file mode 100644 index 19a340893..000000000 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js +++ /dev/null @@ -1,307 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Icon from 'Components/Icon'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import TableRowCellButton from 'Components/Table/Cells/TableRowCellButton'; -import TableSelectCell from 'Components/Table/Cells/TableSelectCell'; -import TableRow from 'Components/Table/TableRow'; -import Popover from 'Components/Tooltip/Popover'; -import { icons, kinds, tooltipPositions } from 'Helpers/Props'; -import SelectLanguageModal from 'InteractiveImport/Language/SelectLanguageModal'; -import SelectMovieModal from 'InteractiveImport/Movie/SelectMovieModal'; -import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal'; -import MovieLanguage from 'Movie/MovieLanguage'; -import MovieQuality from 'Movie/MovieQuality'; -import formatBytes from 'Utilities/Number/formatBytes'; -import translate from 'Utilities/String/translate'; -import InteractiveImportRowCellPlaceholder from './InteractiveImportRowCellPlaceholder'; -import styles from './InteractiveImportRow.css'; - -class InteractiveImportRow extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isSelectMovieModalOpen: false, - isSelectQualityModalOpen: false, - isSelectLanguageModalOpen: false - }; - } - - componentDidMount() { - const { - id, - movie, - quality, - languages - } = this.props; - - if ( - movie && - quality && - languages - ) { - this.props.onSelectedChange({ id, value: true }); - } - } - - componentDidUpdate(prevProps) { - const { - id, - movie, - quality, - languages, - isSelected, - onValidRowChange - } = this.props; - - if ( - prevProps.movie === movie && - prevProps.quality === quality && - prevProps.languages === languages && - prevProps.isSelected === isSelected - ) { - return; - } - - const isValid = !!( - movie && - quality && - languages - ); - - if (isSelected && !isValid) { - onValidRowChange(id, false); - } else { - onValidRowChange(id, true); - } - } - - // - // Control - - selectRowAfterChange = (value) => { - const { - id, - isSelected - } = this.props; - - if (!isSelected && value === true) { - this.props.onSelectedChange({ id, value }); - } - } - - // - // Listeners - - onSelectMoviePress = () => { - this.setState({ isSelectMovieModalOpen: true }); - } - - onSelectQualityPress = () => { - this.setState({ isSelectQualityModalOpen: true }); - } - - onSelectLanguagePress = () => { - this.setState({ isSelectLanguageModalOpen: true }); - } - - onSelectMovieModalClose = (changed) => { - this.setState({ isSelectMovieModalOpen: false }); - this.selectRowAfterChange(changed); - } - - onSelectQualityModalClose = (changed) => { - this.setState({ isSelectQualityModalOpen: false }); - this.selectRowAfterChange(changed); - } - - onSelectLanguageModalClose = (changed) => { - this.setState({ isSelectLanguageModalOpen: false }); - this.selectRowAfterChange(changed); - } - - // - // Render - - render() { - const { - id, - allowMovieChange, - relativePath, - movie, - quality, - languages, - size, - rejections, - isReprocessing, - isSelected, - onSelectedChange - } = this.props; - - const { - isSelectMovieModalOpen, - isSelectQualityModalOpen, - isSelectLanguageModalOpen - } = this.state; - - const movieTitle = movie ? movie.title + ( movie.year > 0 ? ` (${movie.year})` : '') : ''; - - const showMoviePlaceholder = isSelected && !movie; - const showQualityPlaceholder = isSelected && !quality; - const showLanguagePlaceholder = isSelected && !languages && !isReprocessing; - - return ( - - - - - {relativePath} - - - - { - showMoviePlaceholder ? : movieTitle - } - - - - { - showQualityPlaceholder && - - } - - { - !showQualityPlaceholder && !!quality && - - } - - - - { - showLanguagePlaceholder && - - } - - { - !showLanguagePlaceholder && !!languages && !isReprocessing ? - : - null - } - - { - isReprocessing ? - : null - } - - - - {formatBytes(size)} - - - - { - !!rejections.length && - - } - title={translate('ReleaseRejected')} - body={ -
    - { - rejections.map((rejection, index) => { - return ( -
  • - {rejection.reason} -
  • - ); - }) - } -
- } - position={tooltipPositions.LEFT} - /> - } -
- - - - 1 : false} - real={quality ? quality.revision.real > 0 : false} - onModalClose={this.onSelectQualityModalClose} - /> - - l.id) : []} - onModalClose={this.onSelectLanguageModalClose} - /> -
- ); - } - -} - -InteractiveImportRow.propTypes = { - id: PropTypes.number.isRequired, - allowMovieChange: PropTypes.bool.isRequired, - relativePath: PropTypes.string.isRequired, - movie: PropTypes.object, - quality: PropTypes.object, - languages: PropTypes.arrayOf(PropTypes.object), - size: PropTypes.number.isRequired, - rejections: PropTypes.arrayOf(PropTypes.object).isRequired, - isReprocessing: PropTypes.bool, - isSelected: PropTypes.bool, - onSelectedChange: PropTypes.func.isRequired, - onValidRowChange: PropTypes.func.isRequired -}; - -export default InteractiveImportRow; diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportRowCellPlaceholder.css b/frontend/src/InteractiveImport/Interactive/InteractiveImportRowCellPlaceholder.css deleted file mode 100644 index 941988144..000000000 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportRowCellPlaceholder.css +++ /dev/null @@ -1,7 +0,0 @@ -.placeholder { - display: inline-block; - margin: -8px 0; - width: 100%; - height: 25px; - border: 2px dashed $dangerColor; -} diff --git a/frontend/src/InteractiveImport/Interactive/InteractiveImportRowCellPlaceholder.js b/frontend/src/InteractiveImport/Interactive/InteractiveImportRowCellPlaceholder.js deleted file mode 100644 index b6744d156..000000000 --- a/frontend/src/InteractiveImport/Interactive/InteractiveImportRowCellPlaceholder.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import styles from './InteractiveImportRowCellPlaceholder.css'; - -function InteractiveImportRowCellPlaceholder() { - return ( - - ); -} - -export default InteractiveImportRowCellPlaceholder; diff --git a/frontend/src/InteractiveImport/InteractiveImportModal.js b/frontend/src/InteractiveImport/InteractiveImportModal.js deleted file mode 100644 index 0a2248bc8..000000000 --- a/frontend/src/InteractiveImport/InteractiveImportModal.js +++ /dev/null @@ -1,79 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import InteractiveImportSelectFolderModalContentConnector from './Folder/InteractiveImportSelectFolderModalContentConnector'; -import InteractiveImportModalContentConnector from './Interactive/InteractiveImportModalContentConnector'; - -class InteractiveImportModal extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - folder: null - }; - } - - componentDidUpdate(prevProps) { - if (prevProps.isOpen && !this.props.isOpen) { - this.setState({ folder: null }); - } - } - - // - // Listeners - - onFolderSelect = (folder) => { - this.setState({ folder }); - } - - // - // Render - - render() { - const { - isOpen, - folder, - downloadId, - onModalClose, - ...otherProps - } = this.props; - - const folderPath = folder || this.state.folder; - - return ( - - { - folderPath || downloadId ? - : - - } - - ); - } -} - -InteractiveImportModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - folder: PropTypes.string, - downloadId: PropTypes.string, - onModalClose: PropTypes.func.isRequired -}; - -export default InteractiveImportModal; diff --git a/frontend/src/InteractiveImport/Language/SelectLanguageModal.js b/frontend/src/InteractiveImport/Language/SelectLanguageModal.js deleted file mode 100644 index f0164358e..000000000 --- a/frontend/src/InteractiveImport/Language/SelectLanguageModal.js +++ /dev/null @@ -1,39 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import SelectLanguageModalContentConnector from './SelectLanguageModalContentConnector'; - -class SelectLanguageModal extends Component { - - // - // Render - - render() { - const { - isOpen, - onModalClose, - ...otherProps - } = this.props; - - return ( - - - - ); - } -} - -SelectLanguageModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default SelectLanguageModal; diff --git a/frontend/src/InteractiveImport/Language/SelectLanguageModalContent.css b/frontend/src/InteractiveImport/Language/SelectLanguageModalContent.css deleted file mode 100644 index d80a7e734..000000000 --- a/frontend/src/InteractiveImport/Language/SelectLanguageModalContent.css +++ /dev/null @@ -1,4 +0,0 @@ -.languageInput { - display: flex; - margin-bottom: 0; -} diff --git a/frontend/src/InteractiveImport/Language/SelectLanguageModalContent.js b/frontend/src/InteractiveImport/Language/SelectLanguageModalContent.js deleted file mode 100644 index 67f182ad7..000000000 --- a/frontend/src/InteractiveImport/Language/SelectLanguageModalContent.js +++ /dev/null @@ -1,153 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds, sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './SelectLanguageModalContent.css'; - -class SelectLanguageModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - const { - languageIds - } = props; - - this.state = { - languageIds - }; - } - - // - // Listeners - - onLanguageChange = ({ value, name }) => { - const { - languageIds - } = this.state; - - const changedId = parseInt(name); - - let newLanguages = languageIds; - - if (value) { - newLanguages.push(changedId); - } - - if (!value) { - newLanguages = languageIds.filter((i) => i !== changedId); - } - - this.setState({ languageIds: newLanguages }); - } - - onLanguageSelect = () => { - this.props.onLanguageSelect(this.state); - } - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - items, - onModalClose - } = this.props; - - const { - languageIds - } = this.state; - - return ( - - - Manual Import - Select Language - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToLoadLanguages')} -
- } - - { - isPopulated && !error && -
- { - items.map(( language ) => { - return ( - - {language.name} - - - ); - }) - } -
- } -
- - - - - - -
- ); - } -} - -SelectLanguageModalContent.propTypes = { - languageIds: PropTypes.arrayOf(PropTypes.number).isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onLanguageSelect: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -SelectLanguageModalContent.defaultProps = { - languages: [] -}; - -export default SelectLanguageModalContent; diff --git a/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js b/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js deleted file mode 100644 index e1b30f9ea..000000000 --- a/frontend/src/InteractiveImport/Language/SelectLanguageModalContentConnector.js +++ /dev/null @@ -1,97 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { updateInteractiveImportItems } from 'Store/Actions/interactiveImportActions'; -import { fetchLanguages } from 'Store/Actions/settingsActions'; -import SelectLanguageModalContent from './SelectLanguageModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.languages, - (languages) => { - const { - isFetching, - isPopulated, - error, - items - } = languages; - - const filterItems = ['Any', 'Original']; - const filteredLanguages = items.filter((lang) => !filterItems.includes(lang.name)); - - return { - isFetching, - isPopulated, - error, - items: filteredLanguages - }; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchLanguages: fetchLanguages, - dispatchUpdateInteractiveImportItems: updateInteractiveImportItems -}; - -class SelectLanguageModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount = () => { - if (!this.props.isPopulated) { - this.props.dispatchFetchLanguages(); - } - } - - // - // Listeners - - onLanguageSelect = ({ languageIds }) => { - const languages = []; - - languageIds.forEach((languageId) => { - const language = _.find(this.props.items, - (item) => item.id === parseInt(languageId)); - - if (language !== undefined) { - languages.push(language); - } - }); - - this.props.dispatchUpdateInteractiveImportItems({ - ids: this.props.ids, - languages - }); - - this.props.onModalClose(true); - } - - // - // Render - - render() { - return ( - - ); - } -} - -SelectLanguageModalContentConnector.propTypes = { - ids: PropTypes.arrayOf(PropTypes.number).isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - dispatchFetchLanguages: PropTypes.func.isRequired, - dispatchUpdateInteractiveImportItems: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(SelectLanguageModalContentConnector); diff --git a/frontend/src/InteractiveImport/Movie/SelectMovieModal.js b/frontend/src/InteractiveImport/Movie/SelectMovieModal.js deleted file mode 100644 index a2ef71718..000000000 --- a/frontend/src/InteractiveImport/Movie/SelectMovieModal.js +++ /dev/null @@ -1,37 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import SelectMovieModalContentConnector from './SelectMovieModalContentConnector'; - -class SelectMovieModal extends Component { - - // - // Render - - render() { - const { - isOpen, - onModalClose, - ...otherProps - } = this.props; - - return ( - - - - ); - } -} - -SelectMovieModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default SelectMovieModal; diff --git a/frontend/src/InteractiveImport/Movie/SelectMovieModalContent.css b/frontend/src/InteractiveImport/Movie/SelectMovieModalContent.css deleted file mode 100644 index 70e697bb3..000000000 --- a/frontend/src/InteractiveImport/Movie/SelectMovieModalContent.css +++ /dev/null @@ -1,52 +0,0 @@ -.modalBody { - composes: modalBody from '~Components/Modal/ModalBody.css'; - - display: flex; - flex: 1 1 auto; - flex-direction: column; -} - -.filterInput { - composes: input from '~Components/Form/TextInput.css'; - - flex: 0 0 auto; - margin-bottom: 20px; -} - -.scroller { - min-height: 1px; -} - -.footer { - composes: modalFooter from '~Components/Modal/ModalFooter.css'; - - display: flex; - justify-content: space-between; - overflow: hidden; -} - -.path { - margin-right: 20px; - color: $dimColor; - word-break: break-word; -} - -.buttons { - display: flex; -} - -@media only screen and (max-width: $breakpointSmall) { - .footer { - display: block; - } - - .path { - margin-right: 0; - margin-bottom: 10px; - } - - .buttons { - justify-content: space-between; - flex-grow: 1; - } -} diff --git a/frontend/src/InteractiveImport/Movie/SelectMovieModalContent.js b/frontend/src/InteractiveImport/Movie/SelectMovieModalContent.js deleted file mode 100644 index a35c30ecd..000000000 --- a/frontend/src/InteractiveImport/Movie/SelectMovieModalContent.js +++ /dev/null @@ -1,237 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import TextInput from 'Components/Form/TextInput'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import FuseWorker from 'Components/Page/Header/fuse.worker'; -import Scroller from 'Components/Scroller/Scroller'; -import VirtualTable from 'Components/Table/VirtualTable'; -import VirtualTableRow from 'Components/Table/VirtualTableRow'; -import { scrollDirections } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import SelectMovieRow from './SelectMovieRow'; -import styles from './SelectMovieModalContent.css'; - -class SelectMovieModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this._worker = null; - - this.state = { - scroller: null, - filter: '', - loading: false, - suggestions: props.items - }; - } - - componentWillUnmount() { - if (this._worker) { - this._worker.removeEventListener('message', this.onSuggestionsReceived, false); - this._worker.terminate(); - this._worker = null; - } - } - - getWorker() { - if (!this._worker) { - this._worker = new FuseWorker(); - this._worker.addEventListener('message', this.onSuggestionsReceived, false); - } - - return this._worker; - } - - // - // Control - - setScrollerRef = (ref) => { - this.setState({ scroller: ref }); - } - - rowRenderer = ({ key, rowIndex, style }) => { - const item = this.state.suggestions[rowIndex]; - - return ( - - - - ); - } - - // - // Listeners - - onFilterChange = ({ value }) => { - if (value) { - this.setState({ - loading: true, - filter: value.toLowerCase() - }); - this.requestSuggestions(value); - } else { - this.setState({ - loading: false, - filter: '', - suggestions: this.props.items - }); - this.requestSuggestions.cancel(); - } - } - - requestSuggestions = _.debounce((value) => { - if (!this.state.loading) { - return; - } - - const requestLoading = this.state.requestLoading; - - this.setState({ - requestValue: value, - requestLoading: true - }); - - if (!requestLoading) { - const payload = { - value, - movies: this.props.items - }; - - this.getWorker().postMessage(payload); - } - }, 250); - - onSuggestionsReceived = (message) => { - const { - value, - suggestions - } = message.data; - - if (!this.state.loading) { - this.setState({ - requestValue: null, - requestLoading: false - }); - } else if (value === this.state.requestValue) { - this.setState({ - suggestions: suggestions.map((suggestion) => suggestion.item), - requestValue: null, - requestLoading: false, - loading: false - }); - } else { - this.setState({ - suggestions: suggestions.map((suggestion) => suggestion.item), - requestLoading: true - }); - - const payload = { - value: this.state.requestValue, - movies: this.props.items - }; - - this.getWorker().postMessage(payload); - } - } - - // - // Render - - render() { - const { - relativePath, - onModalClose - } = this.props; - - const { - scroller, - filter, - loading, - suggestions - } = this.state; - - return ( - - -
- Manual Import - Select Movie -
-
- - - - - -
- { - loading || !scroller ? - : - - } - items={suggestions} - isSmallScreen={false} - scroller={scroller} - focusScroller={false} - rowRenderer={this.rowRenderer} - /> - } -
-
-
- - -
{relativePath}
-
- -
-
-
- ); - } -} - -SelectMovieModalContent.propTypes = { - items: PropTypes.arrayOf(PropTypes.object).isRequired, - relativePath: PropTypes.string.isRequired, - onMovieSelect: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default SelectMovieModalContent; diff --git a/frontend/src/InteractiveImport/Movie/SelectMovieModalContentConnector.js b/frontend/src/InteractiveImport/Movie/SelectMovieModalContentConnector.js deleted file mode 100644 index 4115a59da..000000000 --- a/frontend/src/InteractiveImport/Movie/SelectMovieModalContentConnector.js +++ /dev/null @@ -1,115 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { reprocessInteractiveImportItems, updateInteractiveImportItem } from 'Store/Actions/interactiveImportActions'; -import createAllMoviesSelector from 'Store/Selectors/createAllMoviesSelector'; -import createDeepEqualSelector from 'Store/Selectors/createDeepEqualSelector'; -import SelectMovieModalContent from './SelectMovieModalContent'; - -function createCleanMovieSelector() { - return createSelector( - createAllMoviesSelector(), - (items) => { - return items.map((movie) => { - const { - id, - title, - titleSlug, - sortTitle, - year, - images, - alternateTitles = [] - } = movie; - - return { - id, - title, - titleSlug, - sortTitle, - year, - images, - alternateTitles, - firstCharacter: title.charAt(0).toLowerCase() - }; - }).sort((a, b) => { - if (a.sortTitle < b.sortTitle) { - return -1; - } - - if (a.sortTitle > b.sortTitle) { - return 1; - } - - return 0; - }); - } - ); -} - -function createMapStateToProps() { - return createDeepEqualSelector( - createCleanMovieSelector(), - (movies) => { - return { - items: movies - }; - } - ); -} - -const mapDispatchToProps = { - dispatchReprocessInteractiveImportItems: reprocessInteractiveImportItems, - dispatchUpdateInteractiveImportItem: updateInteractiveImportItem -}; - -class SelectMovieModalContentConnector extends Component { - - // - // Listeners - - onMovieSelect = (movieId) => { - const { - ids, - items, - dispatchUpdateInteractiveImportItem, - dispatchReprocessInteractiveImportItems, - onModalClose - } = this.props; - - const movie = items.find((s) => s.id === movieId); - - ids.forEach((id) => { - dispatchUpdateInteractiveImportItem({ - id, - movie - }); - }); - - dispatchReprocessInteractiveImportItems({ ids }); - - onModalClose(true); - } - - // - // Render - - render() { - return ( - - ); - } -} - -SelectMovieModalContentConnector.propTypes = { - ids: PropTypes.arrayOf(PropTypes.number).isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - dispatchReprocessInteractiveImportItems: PropTypes.func.isRequired, - dispatchUpdateInteractiveImportItem: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(SelectMovieModalContentConnector); diff --git a/frontend/src/InteractiveImport/Movie/SelectMovieRow.css b/frontend/src/InteractiveImport/Movie/SelectMovieRow.css deleted file mode 100644 index 6ebc63656..000000000 --- a/frontend/src/InteractiveImport/Movie/SelectMovieRow.css +++ /dev/null @@ -1,5 +0,0 @@ -.movie { - padding: 8px; - width: 100%; - border-bottom: 1px solid $borderColor; -} diff --git a/frontend/src/InteractiveImport/Movie/SelectMovieRow.js b/frontend/src/InteractiveImport/Movie/SelectMovieRow.js deleted file mode 100644 index e7fc4b9ad..000000000 --- a/frontend/src/InteractiveImport/Movie/SelectMovieRow.js +++ /dev/null @@ -1,38 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Link from 'Components/Link/Link'; -import styles from './SelectMovieRow.css'; - -class SelectMovieRow extends Component { - - // - // Listeners - - onPress = () => { - this.props.onMovieSelect(this.props.id); - } - - // - // Render - - render() { - return ( - - {this.props.title} ({this.props.year}) - - ); - } -} - -SelectMovieRow.propTypes = { - id: PropTypes.number.isRequired, - title: PropTypes.string.isRequired, - year: PropTypes.number.isRequired, - onMovieSelect: PropTypes.func.isRequired -}; - -export default SelectMovieRow; diff --git a/frontend/src/InteractiveImport/Quality/SelectQualityModal.js b/frontend/src/InteractiveImport/Quality/SelectQualityModal.js deleted file mode 100644 index d3e31d2dd..000000000 --- a/frontend/src/InteractiveImport/Quality/SelectQualityModal.js +++ /dev/null @@ -1,37 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import SelectQualityModalContentConnector from './SelectQualityModalContentConnector'; - -class SelectQualityModal extends Component { - - // - // Render - - render() { - const { - isOpen, - onModalClose, - ...otherProps - } = this.props; - - return ( - - - - ); - } -} - -SelectQualityModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default SelectQualityModal; diff --git a/frontend/src/InteractiveImport/Quality/SelectQualityModalContent.js b/frontend/src/InteractiveImport/Quality/SelectQualityModalContent.js deleted file mode 100644 index dd22b9889..000000000 --- a/frontend/src/InteractiveImport/Quality/SelectQualityModalContent.js +++ /dev/null @@ -1,169 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -class SelectQualityModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - const { - qualityId, - proper, - real - } = props; - - this.state = { - qualityId, - proper, - real - }; - } - - // - // Listeners - - onQualityChange = ({ value }) => { - this.setState({ qualityId: parseInt(value) }); - } - - onProperChange = ({ value }) => { - this.setState({ proper: value }); - } - - onRealChange = ({ value }) => { - this.setState({ real: value }); - } - - onQualitySelect = () => { - this.props.onQualitySelect(this.state); - } - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - items, - onModalClose - } = this.props; - - const { - qualityId, - proper, - real - } = this.state; - - const qualityOptions = items.map(({ id, name }) => { - return { - key: id, - value: name - }; - }); - - return ( - - - Manual Import - Select Quality - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToLoadQualities')} -
- } - - { - isPopulated && !error && -
- - {translate('Quality')} - - - - - - {translate('Proper')} - - - - - - {translate('Real')} - - - -
- } -
- - - - - - -
- ); - } -} - -SelectQualityModalContent.propTypes = { - qualityId: PropTypes.number.isRequired, - proper: PropTypes.bool.isRequired, - real: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onQualitySelect: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default SelectQualityModalContent; diff --git a/frontend/src/InteractiveImport/Quality/SelectQualityModalContentConnector.js b/frontend/src/InteractiveImport/Quality/SelectQualityModalContentConnector.js deleted file mode 100644 index 149d2536a..000000000 --- a/frontend/src/InteractiveImport/Quality/SelectQualityModalContentConnector.js +++ /dev/null @@ -1,95 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { updateInteractiveImportItems } from 'Store/Actions/interactiveImportActions'; -import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions'; -import getQualities from 'Utilities/Quality/getQualities'; -import SelectQualityModalContent from './SelectQualityModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.qualityProfiles, - (qualityProfiles) => { - const { - isSchemaFetching: isFetching, - isSchemaPopulated: isPopulated, - schemaError: error, - schema - } = qualityProfiles; - - return { - isFetching, - isPopulated, - error, - items: getQualities(schema.items) - }; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchQualityProfileSchema: fetchQualityProfileSchema, - dispatchUpdateInteractiveImportItems: updateInteractiveImportItems -}; - -class SelectQualityModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount = () => { - if (!this.props.isPopulated) { - this.props.dispatchFetchQualityProfileSchema(); - } - } - - // - // Listeners - - onQualitySelect = ({ qualityId, proper, real }) => { - const quality = _.find(this.props.items, - (item) => item.id === qualityId); - - const revision = { - version: proper ? 2 : 1, - real: real ? 1 : 0 - }; - - this.props.dispatchUpdateInteractiveImportItems({ - ids: this.props.ids, - quality: { - quality, - revision - } - }); - - this.props.onModalClose(true); - } - - // - // Render - - render() { - return ( - - ); - } -} - -SelectQualityModalContentConnector.propTypes = { - ids: PropTypes.arrayOf(PropTypes.number).isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - dispatchFetchQualityProfileSchema: PropTypes.func.isRequired, - dispatchUpdateInteractiveImportItems: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(SelectQualityModalContentConnector); diff --git a/frontend/src/InteractiveSearch/InteractiveSearchRow.js b/frontend/src/InteractiveSearch/InteractiveSearchRow.js index 5c7ce20de..35f9ebb66 100644 --- a/frontend/src/InteractiveSearch/InteractiveSearchRow.js +++ b/frontend/src/InteractiveSearch/InteractiveSearchRow.js @@ -1,6 +1,6 @@ +import ProtocolLabel from 'Activity/Queue/ProtocolLabel'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import ProtocolLabel from 'Activity/Queue/ProtocolLabel'; import Icon from 'Components/Icon'; import Link from 'Components/Link/Link'; import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; @@ -9,9 +9,9 @@ import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRow from 'Components/Table/TableRow'; import Popover from 'Components/Tooltip/Popover'; import { icons, kinds, tooltipPositions } from 'Helpers/Props'; -import MovieFormats from 'Movie/MovieFormats'; -import MovieLanguage from 'Movie/MovieLanguage'; -import MovieQuality from 'Movie/MovieQuality'; +import MovieFormats from 'Indexer/MovieFormats'; +import MovieLanguage from 'Indexer/MovieLanguage'; +import MovieQuality from 'Indexer/MovieQuality'; import formatDateTime from 'Utilities/Date/formatDateTime'; import formatAge from 'Utilities/Number/formatAge'; import formatBytes from 'Utilities/Number/formatBytes'; diff --git a/frontend/src/Movie/Index/Menus/MovieIndexViewMenu.js b/frontend/src/Movie/Index/Menus/MovieIndexViewMenu.js deleted file mode 100644 index 76507cd76..000000000 --- a/frontend/src/Movie/Index/Menus/MovieIndexViewMenu.js +++ /dev/null @@ -1,56 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import MenuContent from 'Components/Menu/MenuContent'; -import ViewMenu from 'Components/Menu/ViewMenu'; -import ViewMenuItem from 'Components/Menu/ViewMenuItem'; -import { align } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -function MovieIndexViewMenu(props) { - const { - view, - isDisabled, - onViewSelect - } = props; - - return ( - - - - {translate('Table')} - - - - {translate('Posters')} - - - - {translate('Overview')} - - - - ); -} - -MovieIndexViewMenu.propTypes = { - view: PropTypes.string.isRequired, - isDisabled: PropTypes.bool.isRequired, - onViewSelect: PropTypes.func.isRequired -}; - -export default MovieIndexViewMenu; diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverview.css b/frontend/src/Movie/Index/Overview/MovieIndexOverview.css deleted file mode 100644 index 4e59d1739..000000000 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverview.css +++ /dev/null @@ -1,104 +0,0 @@ -$hoverScale: 1.05; - -.content { - display: flex; - flex-grow: 1; -} - -.poster { - position: relative; -} - -.editorSelect { - position: absolute; - top: 0; - left: 5px; - z-index: 3; -} - -.posterContainer { - position: relative; -} - -.link { - composes: link from '~Components/Link/Link.css'; - - display: block; - color: $defaultColor; - - &:hover { - color: $defaultColor; - text-decoration: none; - } -} - -.ended { - position: absolute; - top: 0; - right: 0; - z-index: 1; - width: 0; - height: 0; - border-width: 0 25px 25px 0; - border-style: solid; - border-color: transparent $dangerColor transparent transparent; - color: $white; -} - -.info { - display: flex; - flex: 1 0 1px; - flex-direction: column; - overflow: hidden; - padding-left: 10px; -} - -.titleRow { - display: flex; - justify-content: space-between; - flex: 0 0 auto; - margin-bottom: 10px; - line-height: 32px; -} - -.title { - @add-mixin truncate; - composes: link; - - flex: 1 0 1px; - font-weight: 300; - font-size: 30px; -} - -.actions { - white-space: nowrap; -} - -.details { - display: flex; - justify-content: space-between; - flex: 1 0 auto; -} - -.overview { - composes: link; - - flex: 0 1 1000px; - overflow: hidden; - min-height: 0; -} - -@media only screen and (max-width: $breakpointSmall) { - .overview { - display: none; - } -} - -.externalLinks { - margin-right: 0.5em; -} - -.queue { - padding-left: 2px; - border-left: 4px solid $queueColor; -} diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverview.js b/frontend/src/Movie/Index/Overview/MovieIndexOverview.js deleted file mode 100644 index 63579c0da..000000000 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverview.js +++ /dev/null @@ -1,310 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import TextTruncate from 'react-text-truncate'; -import CheckInput from 'Components/Form/CheckInput'; -import Icon from 'Components/Icon'; -import IconButton from 'Components/Link/IconButton'; -import Link from 'Components/Link/Link'; -import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; -import Popover from 'Components/Tooltip/Popover'; -import { icons } from 'Helpers/Props'; -import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal'; -import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector'; -import MovieIndexProgressBar from 'Movie/Index/ProgressBar/MovieIndexProgressBar'; -import MoviePoster from 'Movie/MoviePoster'; -import dimensions from 'Styles/Variables/dimensions'; -import fonts from 'Styles/Variables/fonts'; -import translate from 'Utilities/String/translate'; -import MovieIndexOverviewInfo from './MovieIndexOverviewInfo'; -import styles from './MovieIndexOverview.css'; - -const columnPadding = parseInt(dimensions.movieIndexColumnPadding); -const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen); -const defaultFontSize = parseInt(fonts.defaultFontSize); -const lineHeight = parseFloat(fonts.lineHeight); - -// Hardcoded height beased on line-height of 32 + bottom margin of 10. -// Less side-effecty than using react-measure. -const titleRowHeight = 42; - -function getContentHeight(rowHeight, isSmallScreen) { - const padding = isSmallScreen ? columnPaddingSmallScreen : columnPadding; - - return rowHeight - padding; -} - -class MovieIndexOverview extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditMovieModalOpen: false, - isDeleteMovieModalOpen: false - }; - } - - // - // Listeners - - onEditMoviePress = () => { - this.setState({ isEditMovieModalOpen: true }); - } - - onEditMovieModalClose = () => { - this.setState({ isEditMovieModalOpen: false }); - } - - onDeleteMoviePress = () => { - this.setState({ - isEditMovieModalOpen: false, - isDeleteMovieModalOpen: true - }); - } - - onDeleteMovieModalClose = () => { - this.setState({ isDeleteMovieModalOpen: false }); - } - - onChange = ({ value, shiftKey }) => { - const { - id, - onSelectedChange - } = this.props; - - onSelectedChange({ id, value, shiftKey }); - } - - // - // Render - - render() { - const { - id, - tmdbId, - imdbId, - youTubeTrailerId, - title, - overview, - monitored, - hasFile, - isAvailable, - status, - titleSlug, - images, - posterWidth, - posterHeight, - qualityProfile, - overviewOptions, - showSearchAction, - showRelativeDates, - shortDateFormat, - longDateFormat, - timeFormat, - rowHeight, - isSmallScreen, - isRefreshingMovie, - isSearchingMovie, - onRefreshMoviePress, - onSearchPress, - isMovieEditorActive, - isSelected, - onSelectedChange, - queueStatus, - queueState, - ...otherProps - } = this.props; - - const { - isEditMovieModalOpen, - isDeleteMovieModalOpen - } = this.state; - - const link = `/movie/${titleSlug}`; - - const elementStyle = { - width: `${posterWidth}px`, - height: `${posterHeight}px` - }; - - const contentHeight = getContentHeight(rowHeight, isSmallScreen); - const overviewHeight = contentHeight - titleRowHeight; - - return ( -
-
-
-
- { - isMovieEditorActive && -
- -
- } - - - - -
- - -
- -
-
- - {title} - - -
- - - } - title={translate('Links')} - body={ - 'place' - } - /> - - - - - { - showSearchAction && - - } - - -
-
- -
- - - - - -
-
-
- - - - -
- ); - } -} - -MovieIndexOverview.propTypes = { - id: PropTypes.number.isRequired, - title: PropTypes.string.isRequired, - overview: PropTypes.string.isRequired, - monitored: PropTypes.bool.isRequired, - hasFile: PropTypes.bool.isRequired, - isAvailable: PropTypes.bool.isRequired, - status: PropTypes.string.isRequired, - titleSlug: PropTypes.string.isRequired, - images: PropTypes.arrayOf(PropTypes.object).isRequired, - posterWidth: PropTypes.number.isRequired, - posterHeight: PropTypes.number.isRequired, - rowHeight: PropTypes.number.isRequired, - qualityProfile: PropTypes.object.isRequired, - overviewOptions: PropTypes.object.isRequired, - showSearchAction: PropTypes.bool.isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - longDateFormat: PropTypes.string.isRequired, - timeFormat: PropTypes.string.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - isRefreshingMovie: PropTypes.bool.isRequired, - isSearchingMovie: PropTypes.bool.isRequired, - onRefreshMoviePress: PropTypes.func.isRequired, - onSearchPress: PropTypes.func.isRequired, - isMovieEditorActive: PropTypes.bool.isRequired, - isSelected: PropTypes.bool, - onSelectedChange: PropTypes.func.isRequired, - tmdbId: PropTypes.number.isRequired, - imdbId: PropTypes.string, - youTubeTrailerId: PropTypes.string, - queueStatus: PropTypes.string, - queueState: PropTypes.string -}; - -export default MovieIndexOverview; diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.css b/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.css deleted file mode 100644 index 5dc53762f..000000000 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.css +++ /dev/null @@ -1,12 +0,0 @@ -.infos { - display: flex; - flex: 0 0 250px; - flex-direction: column; - margin-left: 10px; -} - -@media only screen and (max-width: $breakpointSmall) { - .infos { - margin-left: 0; - } -} diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.js b/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.js deleted file mode 100644 index 1135a1f69..000000000 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.js +++ /dev/null @@ -1,192 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { icons } from 'Helpers/Props'; -import dimensions from 'Styles/Variables/dimensions'; -import formatDateTime from 'Utilities/Date/formatDateTime'; -import getRelativeDate from 'Utilities/Date/getRelativeDate'; -import formatBytes from 'Utilities/Number/formatBytes'; -import MovieIndexOverviewInfoRow from './MovieIndexOverviewInfoRow'; -import styles from './MovieIndexOverviewInfo.css'; - -const infoRowHeight = parseInt(dimensions.movieIndexOverviewInfoRowHeight); - -const rows = [ - { - name: 'monitored', - showProp: 'showMonitored', - valueProp: 'monitored' - - }, - { - name: 'studio', - showProp: 'showStudio', - valueProp: 'studio' - }, - { - name: 'qualityProfileId', - showProp: 'showQualityProfile', - valueProp: 'qualityProfileId' - }, - { - name: 'added', - showProp: 'showAdded', - valueProp: 'added' - }, - { - 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 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 === 'studio') { - return { - title: 'Studio', - iconName: icons.STUDIO, - label: props.studio - }; - } - - if (name === 'qualityProfileId') { - return { - title: 'Quality Profile', - iconName: icons.PROFILE, - label: props.qualityProfile.name - }; - } - - if (name === 'added') { - const { - added, - showRelativeDates, - shortDateFormat, - longDateFormat, - timeFormat - } = props; - - return { - title: `Added: ${formatDateTime(added, longDateFormat, timeFormat)}`, - iconName: icons.ADD, - label: getRelativeDate( - added, - shortDateFormat, - showRelativeDates, - { - timeFormat, - timeForToday: true - } - ) - }; - } - - 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 MovieIndexOverviewInfo(props) { - const { - height - // showRelativeDates, - // shortDateFormat, - // longDateFormat, - // timeFormat - } = props; - - let shownRows = 1; - const maxRows = Math.floor(height / (infoRowHeight + 4)); - - return ( -
- { - rows.map((row) => { - if (!isVisible(row, props)) { - return null; - } - - if (shownRows >= maxRows) { - return null; - } - - shownRows++; - - const infoRowProps = getInfoRowProps(row, props); - - return ( - - ); - }) - } -
- ); -} - -MovieIndexOverviewInfo.propTypes = { - height: PropTypes.number.isRequired, - showStudio: PropTypes.bool.isRequired, - showMonitored: PropTypes.bool.isRequired, - showQualityProfile: PropTypes.bool.isRequired, - showAdded: PropTypes.bool.isRequired, - showPath: PropTypes.bool.isRequired, - showSizeOnDisk: PropTypes.bool.isRequired, - monitored: PropTypes.bool.isRequired, - studio: PropTypes.string, - qualityProfile: PropTypes.object.isRequired, - added: PropTypes.string, - path: PropTypes.string.isRequired, - sizeOnDisk: PropTypes.number, - sortKey: PropTypes.string.isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - longDateFormat: PropTypes.string.isRequired, - timeFormat: PropTypes.string.isRequired -}; - -export default MovieIndexOverviewInfo; diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfoRow.css b/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfoRow.css deleted file mode 100644 index ea94e2ef6..000000000 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfoRow.css +++ /dev/null @@ -1,10 +0,0 @@ -.infoRow { - flex: 0 0 $movieIndexOverviewInfoRowHeight; - margin: 2px 0; -} - -.icon { - margin-right: 5px; - width: 25px !important; - text-align: center; -} diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfoRow.js b/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfoRow.js deleted file mode 100644 index 15e77426d..000000000 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverviewInfoRow.js +++ /dev/null @@ -1,35 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Icon from 'Components/Icon'; -import styles from './MovieIndexOverviewInfoRow.css'; - -function MovieIndexOverviewInfoRow(props) { - const { - title, - iconName, - label - } = props; - - return ( -
- - - {label} -
- ); -} - -MovieIndexOverviewInfoRow.propTypes = { - title: PropTypes.string, - iconName: PropTypes.object.isRequired, - label: PropTypes.string.isRequired -}; - -export default MovieIndexOverviewInfoRow; diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverviews.css b/frontend/src/Movie/Index/Overview/MovieIndexOverviews.css deleted file mode 100644 index 5f8ca5baf..000000000 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverviews.css +++ /dev/null @@ -1,11 +0,0 @@ -.grid { - flex: 1 0 auto; -} - -.container { - &:hover { - .content { - background-color: $tableRowHoverBackgroundColor; - } - } -} diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverviews.js b/frontend/src/Movie/Index/Overview/MovieIndexOverviews.js deleted file mode 100644 index 4dd40bc55..000000000 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverviews.js +++ /dev/null @@ -1,276 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { Grid, WindowScroller } from 'react-virtualized'; -import Measure from 'Components/Measure'; -import MovieIndexItemConnector from 'Movie/Index/MovieIndexItemConnector'; -import dimensions from 'Styles/Variables/dimensions'; -import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter'; -import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder'; -import MovieIndexOverview from './MovieIndexOverview'; -import styles from './MovieIndexOverviews.css'; - -// Poster container dimensions -const columnPadding = parseInt(dimensions.movieIndexColumnPadding); -const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen); -const progressBarHeight = parseInt(dimensions.progressBarSmallHeight); -const detailedProgressBarHeight = parseInt(dimensions.progressBarMediumHeight); - -function calculatePosterWidth(posterSize, isSmallScreen) { - const maxiumPosterWidth = isSmallScreen ? 152 : 162; - - if (posterSize === 'large') { - return maxiumPosterWidth; - } - - if (posterSize === 'medium') { - return Math.floor(maxiumPosterWidth * 0.75); - } - - return Math.floor(maxiumPosterWidth * 0.5); -} - -function calculateRowHeight(posterHeight, sortKey, isSmallScreen, overviewOptions) { - const { - detailedProgressBar - } = overviewOptions; - - const heights = [ - posterHeight, - detailedProgressBar ? detailedProgressBarHeight : progressBarHeight, - isSmallScreen ? columnPaddingSmallScreen : columnPadding - ]; - - return heights.reduce((acc, height) => acc + height, 0); -} - -function calculatePosterHeight(posterWidth) { - return Math.ceil((250 / 170) * posterWidth); -} - -class MovieIndexOverviews extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - width: 0, - columnCount: 1, - posterWidth: 162, - posterHeight: 238, - rowHeight: calculateRowHeight(238, null, props.isSmallScreen, {}) - }; - - this._grid = null; - } - - componentDidUpdate(prevProps, prevState) { - const { - items, - sortKey, - overviewOptions, - jumpToCharacter, - isMovieEditorActive, - isSmallScreen - } = this.props; - - const { - width, - rowHeight - } = this.state; - - if (prevProps.sortKey !== sortKey || - prevProps.overviewOptions !== overviewOptions) { - this.calculateGrid(this.state.width, isSmallScreen); - } - - if ( - this._grid && - (prevState.width !== width || - prevState.rowHeight !== rowHeight || - hasDifferentItemsOrOrder(prevProps.items, items) || - prevProps.overviewOptions !== overviewOptions || - prevProps.isMovieEditorActive !== isMovieEditorActive)) { - // recomputeGridSize also forces Grid to discard its cache of rendered cells - this._grid.recomputeGridSize(); - } - - if (jumpToCharacter != null && jumpToCharacter !== prevProps.jumpToCharacter) { - const index = getIndexOfFirstCharacter(items, jumpToCharacter); - - if (this._grid && index != null) { - - this._grid.scrollToCell({ - rowIndex: index, - columnIndex: 0 - }); - } - } - } - - // - // Control - - setGridRef = (ref) => { - this._grid = ref; - } - - calculateGrid = (width = this.state.width, isSmallScreen) => { - const { - sortKey, - overviewOptions - } = this.props; - - const posterWidth = calculatePosterWidth(overviewOptions.size, isSmallScreen); - const posterHeight = calculatePosterHeight(posterWidth); - const rowHeight = calculateRowHeight(posterHeight, sortKey, isSmallScreen, overviewOptions); - - this.setState({ - width, - posterWidth, - posterHeight, - rowHeight - }); - } - - cellRenderer = ({ key, rowIndex, style }) => { - const { - items, - sortKey, - overviewOptions, - showRelativeDates, - shortDateFormat, - longDateFormat, - timeFormat, - isSmallScreen, - selectedState, - isMovieEditorActive, - onSelectedChange - } = this.props; - - const { - posterWidth, - posterHeight, - rowHeight - } = this.state; - - const movie = items[rowIndex]; - - if (!movie) { - return null; - } - - return ( -
- -
- ); - } - - // - // Listeners - - onMeasure = ({ width }) => { - this.calculateGrid(width, this.props.isSmallScreen); - } - - // - // Render - - render() { - const { - isSmallScreen, - scroller, - items, - selectedState - } = this.props; - - const { - width, - rowHeight - } = this.state; - - return ( - - - {({ height, registerChild, onChildScroll, scrollTop }) => { - if (!height) { - return
; - } - - return ( -
- -
- ); - } - } - - - ); - } -} - -MovieIndexOverviews.propTypes = { - items: PropTypes.arrayOf(PropTypes.object).isRequired, - sortKey: PropTypes.string, - overviewOptions: PropTypes.object.isRequired, - jumpToCharacter: PropTypes.string, - scroller: PropTypes.instanceOf(Element).isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - longDateFormat: PropTypes.string.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - timeFormat: PropTypes.string.isRequired, - selectedState: PropTypes.object.isRequired, - onSelectedChange: PropTypes.func.isRequired, - isMovieEditorActive: PropTypes.bool.isRequired -}; - -export default MovieIndexOverviews; diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverviewsConnector.js b/frontend/src/Movie/Index/Overview/MovieIndexOverviewsConnector.js deleted file mode 100644 index 4a46dc1c1..000000000 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverviewsConnector.js +++ /dev/null @@ -1,25 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import MovieIndexOverviews from './MovieIndexOverviews'; - -function createMapStateToProps() { - return createSelector( - (state) => state.movieIndex.overviewOptions, - createUISettingsSelector(), - createDimensionsSelector(), - (overviewOptions, uiSettings, dimensions) => { - return { - overviewOptions, - showRelativeDates: uiSettings.showRelativeDates, - shortDateFormat: uiSettings.shortDateFormat, - longDateFormat: uiSettings.longDateFormat, - timeFormat: uiSettings.timeFormat, - isSmallScreen: dimensions.isSmallScreen - }; - } - ); -} - -export default connect(createMapStateToProps)(MovieIndexOverviews); diff --git a/frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModal.js b/frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModal.js deleted file mode 100644 index 75b38e228..000000000 --- a/frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModal.js +++ /dev/null @@ -1,25 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import MovieIndexOverviewOptionsModalContentConnector from './MovieIndexOverviewOptionsModalContentConnector'; - -function MovieIndexOverviewOptionsModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -MovieIndexOverviewOptionsModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default MovieIndexOverviewOptionsModal; diff --git a/frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModalContent.js b/frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModalContent.js deleted file mode 100644 index 216d21cd5..000000000 --- a/frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModalContent.js +++ /dev/null @@ -1,268 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -const posterSizeOptions = [ - { key: 'small', value: 'Small' }, - { key: 'medium', value: 'Medium' }, - { key: 'large', value: 'Large' } -]; - -class MovieIndexOverviewOptionsModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - detailedProgressBar: props.detailedProgressBar, - size: props.size, - showMonitored: props.showMonitored, - showStudio: props.showStudio, - showQualityProfile: props.showQualityProfile, - showAdded: props.showAdded, - showPath: props.showPath, - showSizeOnDisk: props.showSizeOnDisk, - showSearchAction: props.showSearchAction - }; - } - - componentDidUpdate(prevProps) { - const { - detailedProgressBar, - size, - showMonitored, - showStudio, - showQualityProfile, - showAdded, - showPath, - showSizeOnDisk, - showSearchAction - } = this.props; - - const state = {}; - - if (detailedProgressBar !== prevProps.detailedProgressBar) { - state.detailedProgressBar = detailedProgressBar; - } - - if (size !== prevProps.size) { - state.size = size; - } - - if (showMonitored !== prevProps.showMonitored) { - state.showMonitored = showMonitored; - } - - if (showStudio !== prevProps.showStudio) { - state.showStudio = showStudio; - } - - if (showQualityProfile !== prevProps.showQualityProfile) { - state.showQualityProfile = showQualityProfile; - } - - if (showAdded !== prevProps.showAdded) { - state.showAdded = showAdded; - } - - if (showPath !== prevProps.showPath) { - state.showPath = showPath; - } - - if (showSizeOnDisk !== prevProps.showSizeOnDisk) { - state.showSizeOnDisk = showSizeOnDisk; - } - - if (showSearchAction !== prevProps.showSearchAction) { - state.showSearchAction = showSearchAction; - } - - if (!_.isEmpty(state)) { - this.setState(state); - } - } - - // - // Listeners - - onChangeOverviewOption = ({ name, value }) => { - this.setState({ - [name]: value - }, () => { - this.props.onChangeOverviewOption({ [name]: value }); - }); - } - - // - // Render - - render() { - const { - onModalClose - } = this.props; - - const { - detailedProgressBar, - size, - showMonitored, - showStudio, - showQualityProfile, - showAdded, - showPath, - showSizeOnDisk, - showSearchAction - } = this.state; - - return ( - - - {translate('OverviewOptions')} - - - -
- - {translate('PosterSize')} - - - - - - {translate('DetailedProgressBar')} - - - - - - {translate('ShowMonitored')} - - - - - - {translate('ShowStudio')} - - - - - - {translate('ShowQualityProfile')} - - - - - - {translate('ShowDateAdded')} - - - - - - {translate('ShowPath')} - - - - - - {translate('ShowSizeOnDisk')} - - - - - - {translate('ShowSearch')} - - - -
-
- - - - -
- ); - } -} - -MovieIndexOverviewOptionsModalContent.propTypes = { - size: PropTypes.string.isRequired, - detailedProgressBar: PropTypes.bool.isRequired, - showMonitored: PropTypes.bool.isRequired, - showStudio: PropTypes.bool.isRequired, - showQualityProfile: PropTypes.bool.isRequired, - showAdded: PropTypes.bool.isRequired, - showPath: PropTypes.bool.isRequired, - showSizeOnDisk: PropTypes.bool.isRequired, - showSearchAction: PropTypes.bool.isRequired, - onChangeOverviewOption: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default MovieIndexOverviewOptionsModalContent; diff --git a/frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModalContentConnector.js b/frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModalContentConnector.js deleted file mode 100644 index 06e3d7eb8..000000000 --- a/frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModalContentConnector.js +++ /dev/null @@ -1,23 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { setMovieOverviewOption } from 'Store/Actions/movieIndexActions'; -import MovieIndexOverviewOptionsModalContent from './MovieIndexOverviewOptionsModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.movieIndex, - (movieIndex) => { - return movieIndex.overviewOptions; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - onChangeOverviewOption(payload) { - dispatch(setMovieOverviewOption(payload)); - } - }; -} - -export default connect(createMapStateToProps, createMapDispatchToProps)(MovieIndexOverviewOptionsModalContent); diff --git a/frontend/src/Movie/Index/Posters/MovieIndexPoster.css b/frontend/src/Movie/Index/Posters/MovieIndexPoster.css deleted file mode 100644 index 8bba6a1d2..000000000 --- a/frontend/src/Movie/Index/Posters/MovieIndexPoster.css +++ /dev/null @@ -1,114 +0,0 @@ -$hoverScale: 1.05; - -.content { - transition: all 200ms ease-in; - - &:hover { - z-index: 2; - box-shadow: 0 0 12px $black; - transition: all 200ms ease-in; - - .controls { - opacity: 0.9; - transition: opacity 200ms linear 150ms; - } - } -} - -.posterContainer { - position: relative; -} - -.poster { - position: relative; - display: block; - background-color: $defaultColor; -} - -.overlayTitle { - position: absolute; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; - padding: 5px; - width: 100%; - height: 100%; - color: $offWhite; - text-align: center; - font-size: 20px; -} - -.title { - @add-mixin truncate; - - background-color: #fafbfc; - text-align: center; - font-size: $smallFontSize; -} - -.controls { - position: absolute; - bottom: 10px; - left: 10px; - z-index: 3; - border-radius: 4px; - background-color: #707070; - color: $white; - font-size: $smallFontSize; - opacity: 0; - transition: opacity 0; -} - -.action { - composes: button from '~Components/Link/IconButton.css'; - - &:hover { - color: $radarrYellow; - } -} - -@media only screen and (max-width: $breakpointSmall) { - .container { - padding: 5px; - } -} - -.ended { - position: absolute; - top: 0; - right: 0; - z-index: 1; - width: 0; - height: 0; - border-width: 0 25px 25px 0; - border-style: solid; - border-color: transparent $dangerColor transparent transparent; - color: $white; -} - -.editorSelect { - position: absolute; - top: 10px; - left: 10px; - z-index: 3; -} - -.externalLinks { - margin-left: 0.5em; -} - -.link { - composes: link from '~Components/Link/Link.css'; - - position: relative; - display: block; - background-color: $defaultColor; -} - -.nextAiring { - background-color: #fafbfc; - text-align: center; - font-size: $smallFontSize; -} diff --git a/frontend/src/Movie/Index/Posters/MovieIndexPoster.js b/frontend/src/Movie/Index/Posters/MovieIndexPoster.js deleted file mode 100644 index ada3c7fd8..000000000 --- a/frontend/src/Movie/Index/Posters/MovieIndexPoster.js +++ /dev/null @@ -1,317 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import CheckInput from 'Components/Form/CheckInput'; -import Icon from 'Components/Icon'; -import Label from 'Components/Label'; -import IconButton from 'Components/Link/IconButton'; -import Link from 'Components/Link/Link'; -import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; -import Popover from 'Components/Tooltip/Popover'; -import { icons } from 'Helpers/Props'; -import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal'; -import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector'; -import MovieIndexProgressBar from 'Movie/Index/ProgressBar/MovieIndexProgressBar'; -import MoviePoster from 'Movie/MoviePoster'; -import translate from 'Utilities/String/translate'; -import MovieIndexPosterInfo from './MovieIndexPosterInfo'; -import styles from './MovieIndexPoster.css'; - -class MovieIndexPoster extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - hasPosterError: false, - isEditMovieModalOpen: false, - isDeleteMovieModalOpen: false - }; - } - - // - // Listeners - - onEditMoviePress = () => { - this.setState({ isEditMovieModalOpen: true }); - } - - onEditMovieModalClose = () => { - this.setState({ isEditMovieModalOpen: false }); - } - - onDeleteMoviePress = () => { - this.setState({ - isEditMovieModalOpen: false, - isDeleteMovieModalOpen: true - }); - } - - onDeleteMovieModalClose = () => { - this.setState({ isDeleteMovieModalOpen: false }); - } - - onPosterLoad = () => { - if (this.state.hasPosterError) { - this.setState({ hasPosterError: false }); - } - } - - onPosterLoadError = () => { - if (!this.state.hasPosterError) { - this.setState({ hasPosterError: true }); - } - } - - onChange = ({ value, shiftKey }) => { - const { - id, - onSelectedChange - } = this.props; - - onSelectedChange({ id, value, shiftKey }); - } - - // - // Render - - render() { - const { - id, - tmdbId, - imdbId, - youTubeTrailerId, - title, - monitored, - hasFile, - isAvailable, - status, - titleSlug, - images, - posterWidth, - posterHeight, - detailedProgressBar, - showTitle, - showMonitored, - showQualityProfile, - qualityProfile, - showSearchAction, - showRelativeDates, - shortDateFormat, - timeFormat, - isRefreshingMovie, - isSearchingMovie, - onRefreshMoviePress, - onSearchPress, - isMovieEditorActive, - isSelected, - onSelectedChange, - queueStatus, - queueState, - ...otherProps - } = this.props; - - const { - hasPosterError, - isEditMovieModalOpen, - isDeleteMovieModalOpen - } = this.state; - - const link = `/movie/${titleSlug}`; - - const elementStyle = { - width: `${posterWidth}px`, - height: `${posterHeight}px` - }; - - return ( -
-
- { - isMovieEditorActive && -
- -
- } - - - { - status === 'ended' && -
- } - - - - - { - hasPosterError && -
- {title} -
- } - -
- - - - { - showTitle && -
- {title} -
- } - - { - showMonitored && -
- {monitored ? 'Monitored' : 'Unmonitored'} -
- } - - { - showQualityProfile && -
- {qualityProfile.name} -
- } - - - - - - -
- ); - } -} - -MovieIndexPoster.propTypes = { - id: PropTypes.number.isRequired, - title: PropTypes.string.isRequired, - monitored: PropTypes.bool.isRequired, - hasFile: PropTypes.bool.isRequired, - isAvailable: PropTypes.bool.isRequired, - status: PropTypes.string.isRequired, - titleSlug: PropTypes.string.isRequired, - images: PropTypes.arrayOf(PropTypes.object).isRequired, - posterWidth: PropTypes.number.isRequired, - posterHeight: PropTypes.number.isRequired, - detailedProgressBar: PropTypes.bool.isRequired, - showTitle: PropTypes.bool.isRequired, - showMonitored: PropTypes.bool.isRequired, - showQualityProfile: PropTypes.bool.isRequired, - qualityProfile: PropTypes.object.isRequired, - showSearchAction: PropTypes.bool.isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - timeFormat: PropTypes.string.isRequired, - isRefreshingMovie: PropTypes.bool.isRequired, - isSearchingMovie: PropTypes.bool.isRequired, - onRefreshMoviePress: PropTypes.func.isRequired, - onSearchPress: PropTypes.func.isRequired, - isMovieEditorActive: PropTypes.bool.isRequired, - isSelected: PropTypes.bool, - onSelectedChange: PropTypes.func.isRequired, - tmdbId: PropTypes.number.isRequired, - imdbId: PropTypes.string, - youTubeTrailerId: PropTypes.string, - queueStatus: PropTypes.string, - queueState: PropTypes.string -}; - -MovieIndexPoster.defaultProps = { - statistics: { - movieFileCount: 0 - } -}; - -export default MovieIndexPoster; diff --git a/frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.css b/frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.css deleted file mode 100644 index aab27d827..000000000 --- a/frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.css +++ /dev/null @@ -1,5 +0,0 @@ -.info { - background-color: #fafbfc; - text-align: center; - font-size: $smallFontSize; -} diff --git a/frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.js b/frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.js deleted file mode 100644 index 7871f2b2b..000000000 --- a/frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.js +++ /dev/null @@ -1,158 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import getRelativeDate from 'Utilities/Date/getRelativeDate'; -import formatBytes from 'Utilities/Number/formatBytes'; -import translate from 'Utilities/String/translate'; -import styles from './MovieIndexPosterInfo.css'; - -function MovieIndexPosterInfo(props) { - const { - studio, - qualityProfile, - showQualityProfile, - added, - inCinemas, - digitalRelease, - physicalRelease, - certification, - path, - sizeOnDisk, - sortKey, - showRelativeDates, - shortDateFormat, - timeFormat - } = props; - - if (sortKey === 'studio' && studio) { - return ( -
- {studio} -
- ); - } - - if (sortKey === 'qualityProfileId' && !showQualityProfile) { - return ( -
- {qualityProfile.name} -
- ); - } - - if (sortKey === 'added' && added) { - const addedDate = getRelativeDate( - added, - shortDateFormat, - showRelativeDates, - { - timeFormat, - timeForToday: false - } - ); - - return ( -
- {translate('Added')}: {addedDate} -
- ); - } - - if (sortKey === 'inCinemas' && inCinemas) { - const inCinemasDate = getRelativeDate( - inCinemas, - shortDateFormat, - showRelativeDates, - { - timeFormat, - timeForToday: false - } - ); - - return ( -
- {translate('InCinemas')}: {inCinemasDate} -
- ); - } - - if (sortKey === 'digitalRelease' && digitalRelease) { - const digitalReleaseDate = getRelativeDate( - digitalRelease, - shortDateFormat, - showRelativeDates, - { - timeFormat, - timeForToday: false - } - ); - - return ( -
- {translate('Digital')}: {digitalReleaseDate} -
- ); - } - - if (sortKey === 'physicalRelease' && physicalRelease) { - const physicalReleaseDate = getRelativeDate( - physicalRelease, - shortDateFormat, - showRelativeDates, - { - timeFormat, - timeForToday: false - } - ); - - return ( -
- {translate('Released')}: {physicalReleaseDate} -
- ); - } - - if (sortKey === 'path') { - return ( -
- {path} -
- ); - } - - if (sortKey === 'sizeOnDisk') { - return ( -
- {formatBytes(sizeOnDisk)} -
- ); - } - - if (sortKey === 'certification') { - return ( -
- {certification} -
- ); - } - - return null; -} - -MovieIndexPosterInfo.propTypes = { - studio: PropTypes.string, - showQualityProfile: PropTypes.bool.isRequired, - qualityProfile: PropTypes.object.isRequired, - added: PropTypes.string, - inCinemas: PropTypes.string, - certification: PropTypes.string, - digitalRelease: PropTypes.string, - physicalRelease: PropTypes.string, - path: PropTypes.string.isRequired, - sizeOnDisk: PropTypes.number, - sortKey: PropTypes.string.isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - timeFormat: PropTypes.string.isRequired -}; - -export default MovieIndexPosterInfo; diff --git a/frontend/src/Movie/Index/Posters/MovieIndexPosters.css b/frontend/src/Movie/Index/Posters/MovieIndexPosters.css deleted file mode 100644 index 9c6520fb5..000000000 --- a/frontend/src/Movie/Index/Posters/MovieIndexPosters.css +++ /dev/null @@ -1,3 +0,0 @@ -.grid { - flex: 1 0 auto; -} diff --git a/frontend/src/Movie/Index/Posters/MovieIndexPosters.js b/frontend/src/Movie/Index/Posters/MovieIndexPosters.js deleted file mode 100644 index 68463b39c..000000000 --- a/frontend/src/Movie/Index/Posters/MovieIndexPosters.js +++ /dev/null @@ -1,336 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { Grid, WindowScroller } from 'react-virtualized'; -import Measure from 'Components/Measure'; -import MovieIndexItemConnector from 'Movie/Index/MovieIndexItemConnector'; -import dimensions from 'Styles/Variables/dimensions'; -import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter'; -import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder'; -import MovieIndexPoster from './MovieIndexPoster'; -import styles from './MovieIndexPosters.css'; - -// Poster container dimensions -const columnPadding = parseInt(dimensions.movieIndexColumnPadding); -const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen); -const progressBarHeight = parseInt(dimensions.progressBarSmallHeight); -const detailedProgressBarHeight = parseInt(dimensions.progressBarMediumHeight); - -const additionalColumnCount = { - small: 3, - medium: 2, - large: 1 -}; - -function calculateColumnWidth(width, posterSize, isSmallScreen) { - const maxiumColumnWidth = isSmallScreen ? 172 : 182; - const columns = Math.floor(width / maxiumColumnWidth); - const remainder = width % maxiumColumnWidth; - - if (remainder === 0 && posterSize === 'large') { - return maxiumColumnWidth; - } - - return Math.floor(width / (columns + additionalColumnCount[posterSize])); -} - -function calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions) { - const { - detailedProgressBar, - showTitle, - showMonitored, - showQualityProfile - } = posterOptions; - - const nextAiringHeight = 19; - - const heights = [ - posterHeight, - detailedProgressBar ? detailedProgressBarHeight : progressBarHeight, - nextAiringHeight, - isSmallScreen ? columnPaddingSmallScreen : columnPadding - ]; - - if (showTitle) { - heights.push(19); - } - - if (showMonitored) { - heights.push(19); - } - - if (showQualityProfile) { - heights.push(19); - } - - switch (sortKey) { - case 'studio': - case 'added': - case 'path': - case 'sizeOnDisk': - heights.push(19); - break; - case 'qualityProfileId': - if (!showQualityProfile) { - heights.push(19); - } - break; - default: - // No need to add a height of 0 - } - - return heights.reduce((acc, height) => acc + height, 0); -} - -function calculatePosterHeight(posterWidth) { - return Math.ceil((250 / 170) * posterWidth); -} - -class MovieIndexPosters extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - width: 0, - columnWidth: 182, - columnCount: 1, - posterWidth: 162, - posterHeight: 238, - rowHeight: calculateRowHeight(238, null, props.isSmallScreen, {}) - }; - - this._isInitialized = false; - this._grid = null; - this._padding = props.isSmallScreen ? columnPaddingSmallScreen : columnPadding; - } - - componentDidUpdate(prevProps, prevState) { - const { - items, - sortKey, - posterOptions, - jumpToCharacter, - isSmallScreen, - isMovieEditorActive - } = this.props; - - const { - width, - columnWidth, - columnCount, - rowHeight - } = this.state; - - if (prevProps.sortKey !== sortKey || - prevProps.posterOptions !== posterOptions) { - this.calculateGrid(width, isSmallScreen); - } - - if (this._grid && - (prevState.width !== width || - prevState.columnWidth !== columnWidth || - prevState.columnCount !== columnCount || - prevState.rowHeight !== rowHeight || - hasDifferentItemsOrOrder(prevProps.items, items) || - prevState.isMovieEditorActive !== isMovieEditorActive)) { - // recomputeGridSize also forces Grid to discard its cache of rendered cells - this._grid.recomputeGridSize(); - } - - if (jumpToCharacter != null && jumpToCharacter !== prevProps.jumpToCharacter) { - const index = getIndexOfFirstCharacter(items, jumpToCharacter); - - if (this._grid && index != null) { - const row = Math.floor(index / columnCount); - - this._grid.scrollToCell({ - rowIndex: row, - columnIndex: 0 - }); - } - } - } - - // - // Control - - setGridRef = (ref) => { - this._grid = ref; - } - - calculateGrid = (width = this.state.width, isSmallScreen) => { - const { - sortKey, - posterOptions - } = this.props; - - const columnWidth = calculateColumnWidth(width, posterOptions.size, isSmallScreen); - const columnCount = Math.max(Math.floor(width / columnWidth), 1); - const posterWidth = columnWidth - this._padding * 2; - const posterHeight = calculatePosterHeight(posterWidth); - const rowHeight = calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions); - - this.setState({ - width, - columnWidth, - columnCount, - posterWidth, - posterHeight, - rowHeight - }); - } - - cellRenderer = ({ key, rowIndex, columnIndex, style }) => { - const { - items, - sortKey, - posterOptions, - showRelativeDates, - shortDateFormat, - timeFormat, - selectedState, - isMovieEditorActive, - onSelectedChange - } = this.props; - - const { - posterWidth, - posterHeight, - columnCount - } = this.state; - - const { - detailedProgressBar, - showTitle, - showMonitored, - showQualityProfile - } = posterOptions; - - const movieIdx = rowIndex * columnCount + columnIndex; - const movie = items[movieIdx]; - - if (!movie) { - return null; - } - - return ( -
- -
- ); - } - - // - // Listeners - - onMeasure = ({ width }) => { - this.calculateGrid(width, this.props.isSmallScreen); - } - - // - // Render - - render() { - const { - isSmallScreen, - scroller, - items, - selectedState - } = this.props; - - const { - width, - columnWidth, - columnCount, - rowHeight - } = this.state; - - const rowCount = Math.ceil(items.length / columnCount); - - return ( - - - {({ height, registerChild, onChildScroll, scrollTop }) => { - if (!height) { - return
; - } - - return ( -
- -
- ); - } - } - - - ); - } -} - -MovieIndexPosters.propTypes = { - items: PropTypes.arrayOf(PropTypes.object).isRequired, - sortKey: PropTypes.string, - posterOptions: PropTypes.object.isRequired, - jumpToCharacter: PropTypes.string, - scroller: PropTypes.instanceOf(Element).isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - timeFormat: PropTypes.string.isRequired, - selectedState: PropTypes.object.isRequired, - onSelectedChange: PropTypes.func.isRequired, - isMovieEditorActive: PropTypes.bool.isRequired -}; - -export default MovieIndexPosters; diff --git a/frontend/src/Movie/Index/Posters/MovieIndexPostersConnector.js b/frontend/src/Movie/Index/Posters/MovieIndexPostersConnector.js deleted file mode 100644 index c54804957..000000000 --- a/frontend/src/Movie/Index/Posters/MovieIndexPostersConnector.js +++ /dev/null @@ -1,24 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import MovieIndexPosters from './MovieIndexPosters'; - -function createMapStateToProps() { - return createSelector( - (state) => state.movieIndex.posterOptions, - createUISettingsSelector(), - createDimensionsSelector(), - (posterOptions, uiSettings, dimensions) => { - return { - posterOptions, - showRelativeDates: uiSettings.showRelativeDates, - shortDateFormat: uiSettings.shortDateFormat, - timeFormat: uiSettings.timeFormat, - isSmallScreen: dimensions.isSmallScreen - }; - } - ); -} - -export default connect(createMapStateToProps)(MovieIndexPosters); diff --git a/frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModal.js b/frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModal.js deleted file mode 100644 index a9aeaaed7..000000000 --- a/frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModal.js +++ /dev/null @@ -1,25 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import MovieIndexPosterOptionsModalContentConnector from './MovieIndexPosterOptionsModalContentConnector'; - -function MovieIndexPosterOptionsModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -MovieIndexPosterOptionsModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default MovieIndexPosterOptionsModal; diff --git a/frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModalContent.js b/frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModalContent.js deleted file mode 100644 index d673e493d..000000000 --- a/frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModalContent.js +++ /dev/null @@ -1,214 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -const posterSizeOptions = [ - { key: 'small', value: 'Small' }, - { key: 'medium', value: 'Medium' }, - { key: 'large', value: 'Large' } -]; - -class MovieIndexPosterOptionsModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - detailedProgressBar: props.detailedProgressBar, - size: props.size, - showTitle: props.showTitle, - showMonitored: props.showMonitored, - showQualityProfile: props.showQualityProfile, - showSearchAction: props.showSearchAction - }; - } - - componentDidUpdate(prevProps) { - const { - detailedProgressBar, - size, - showTitle, - showMonitored, - showQualityProfile, - showSearchAction - } = this.props; - - const state = {}; - - if (detailedProgressBar !== prevProps.detailedProgressBar) { - state.detailedProgressBar = detailedProgressBar; - } - - if (size !== prevProps.size) { - state.size = size; - } - - if (showTitle !== prevProps.showTitle) { - state.showTitle = showTitle; - } - - if (showMonitored !== prevProps.showMonitored) { - state.showMonitored = showMonitored; - } - - if (showQualityProfile !== prevProps.showQualityProfile) { - state.showQualityProfile = showQualityProfile; - } - - if (showSearchAction !== prevProps.showSearchAction) { - state.showSearchAction = showSearchAction; - } - - if (!_.isEmpty(state)) { - this.setState(state); - } - } - - // - // Listeners - - onChangePosterOption = ({ name, value }) => { - this.setState({ - [name]: value - }, () => { - this.props.onChangePosterOption({ [name]: value }); - }); - } - - // - // Render - - render() { - const { - onModalClose - } = this.props; - - const { - detailedProgressBar, - size, - showTitle, - showMonitored, - showQualityProfile, - showSearchAction - } = this.state; - - return ( - - - {translate('PosterOptions')} - - - -
- - {translate('PosterSize')} - - - - - - {translate('DetailedProgressBar')} - - - - - - {translate('ShowTitle')} - - - - - - {translate('ShowMonitored')} - - - - - - {translate('ShowQualityProfile')} - - - - - - {translate('ShowSearch')} - - - -
-
- - - - -
- ); - } -} - -MovieIndexPosterOptionsModalContent.propTypes = { - size: PropTypes.string.isRequired, - showTitle: PropTypes.bool.isRequired, - showMonitored: PropTypes.bool.isRequired, - showQualityProfile: PropTypes.bool.isRequired, - detailedProgressBar: PropTypes.bool.isRequired, - showSearchAction: PropTypes.bool.isRequired, - onChangePosterOption: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default MovieIndexPosterOptionsModalContent; diff --git a/frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModalContentConnector.js b/frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModalContentConnector.js deleted file mode 100644 index c8b9a2a88..000000000 --- a/frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModalContentConnector.js +++ /dev/null @@ -1,23 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { setMoviePosterOption } from 'Store/Actions/movieIndexActions'; -import MovieIndexPosterOptionsModalContent from './MovieIndexPosterOptionsModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.movieIndex, - (movieIndex) => { - return movieIndex.posterOptions; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - onChangePosterOption(payload) { - dispatch(setMoviePosterOption(payload)); - } - }; -} - -export default connect(createMapStateToProps, createMapDispatchToProps)(MovieIndexPosterOptionsModalContent); diff --git a/frontend/src/Movie/MoveMovie/MoveMovieModal.css b/frontend/src/Movie/MoveMovie/MoveMovieModal.css deleted file mode 100644 index c1e247a50..000000000 --- a/frontend/src/Movie/MoveMovie/MoveMovieModal.css +++ /dev/null @@ -1,5 +0,0 @@ -.doNotMoveButton { - composes: button from '~Components/Link/Button.css'; - - margin-right: auto; -} diff --git a/frontend/src/Movie/MoveMovie/MoveMovieModal.js b/frontend/src/Movie/MoveMovie/MoveMovieModal.js deleted file mode 100644 index c1117fa10..000000000 --- a/frontend/src/Movie/MoveMovie/MoveMovieModal.js +++ /dev/null @@ -1,90 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Button from 'Components/Link/Button'; -import Modal from 'Components/Modal/Modal'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { kinds, sizes } from 'Helpers/Props'; -import styles from './MoveMovieModal.css'; - -function MoveMovieModal(props) { - const { - originalPath, - destinationPath, - destinationRootFolder, - isOpen, - onSavePress, - onMoveMoviePress - } = props; - - if ( - isOpen && - !originalPath && - !destinationPath && - !destinationRootFolder - ) { - console.error('orginalPath and destinationPath OR destinationRootFolder must be provided'); - } - - return ( - - - - Move Files - - - - { - destinationRootFolder ? - `Would you like to move the movie folders to '${destinationRootFolder}'?` : - `Would you like to move the movie files from '${originalPath}' to '${destinationPath}'?` - } - { - destinationRootFolder ? -
- This will also rename the movie folder per the movie folder format in settings. -
: - null - } -
- - - - - - -
-
- ); -} - -MoveMovieModal.propTypes = { - originalPath: PropTypes.string, - destinationPath: PropTypes.string, - destinationRootFolder: PropTypes.string, - isOpen: PropTypes.bool.isRequired, - onSavePress: PropTypes.func.isRequired, - onMoveMoviePress: PropTypes.func.isRequired -}; - -export default MoveMovieModal; diff --git a/frontend/src/MovieFile/Edit/FileEditModal.js b/frontend/src/MovieFile/Edit/FileEditModal.js deleted file mode 100644 index f12665726..000000000 --- a/frontend/src/MovieFile/Edit/FileEditModal.js +++ /dev/null @@ -1,37 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import FileEditModalContentConnector from './FileEditModalContentConnector'; - -class FileEditModal extends Component { - - // - // Render - - render() { - const { - isOpen, - onModalClose, - ...otherProps - } = this.props; - - return ( - - - - ); - } -} - -FileEditModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default FileEditModal; diff --git a/frontend/src/MovieFile/Edit/FileEditModalContent.js b/frontend/src/MovieFile/Edit/FileEditModalContent.js deleted file mode 100644 index 02bb6ba84..000000000 --- a/frontend/src/MovieFile/Edit/FileEditModalContent.js +++ /dev/null @@ -1,237 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -class FileEditModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - const { - qualityId, - languageIds, - indexerFlags, - proper, - real, - edition, - releaseGroup - } = props; - - this.state = { - qualityId, - languageIds, - indexerFlags, - proper, - real, - edition, - releaseGroup - }; - } - - // - // Listeners - - onQualityChange = ({ value }) => { - this.setState({ qualityId: parseInt(value) }); - } - - onInputChange = ({ name, value }) => { - this.setState({ [name]: value }); - } - - onSaveInputs = () => { - this.props.onSaveInputs(this.state); - } - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - qualities, - languages, - relativePath, - onModalClose - } = this.props; - - const { - qualityId, - languageIds, - indexerFlags, - proper, - real, - edition, - releaseGroup - } = this.state; - - const qualityOptions = qualities.map(({ id, name }) => { - return { - key: id, - value: name - }; - }); - - const languageOptions = languages.map(({ id, name }) => { - return { - key: id, - value: name - }; - }); - - return ( - - - {translate('EditMovieFile')} - {relativePath} - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToLoadQualities')} -
- } - - { - isPopulated && !error && -
- - {translate('Quality')} - - - - - - {translate('Proper')} - - - - - - {translate('Real')} - - - - - - {translate('Languages')} - - - - - - {translate('IndexerFlags')} - - - - - - {translate('Edition')} - - - - - - {translate('ReleaseGroup')} - - - -
- } -
- - - - - - -
- ); - } -} - -FileEditModalContent.propTypes = { - qualityId: PropTypes.number.isRequired, - proper: PropTypes.bool.isRequired, - real: PropTypes.bool.isRequired, - relativePath: PropTypes.string.isRequired, - edition: PropTypes.string.isRequired, - releaseGroup: PropTypes.string.isRequired, - languageIds: PropTypes.arrayOf(PropTypes.number).isRequired, - languages: PropTypes.arrayOf(PropTypes.object).isRequired, - indexerFlags: PropTypes.number.isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - qualities: PropTypes.arrayOf(PropTypes.object).isRequired, - onSaveInputs: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default FileEditModalContent; diff --git a/frontend/src/MovieFile/Edit/FileEditModalContentConnector.js b/frontend/src/MovieFile/Edit/FileEditModalContentConnector.js deleted file mode 100644 index 942e4a22b..000000000 --- a/frontend/src/MovieFile/Edit/FileEditModalContentConnector.js +++ /dev/null @@ -1,139 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { updateMovieFiles } from 'Store/Actions/movieFileActions'; -import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions'; -import createMovieFileSelector from 'Store/Selectors/createMovieFileSelector'; -import getQualities from 'Utilities/Quality/getQualities'; -import FileEditModalContent from './FileEditModalContent'; - -function createMapStateToProps() { - return createSelector( - createMovieFileSelector(), - (state) => state.settings.qualityProfiles, - (state) => state.settings.languages, - (movieFile, qualityProfiles, languages) => { - - const filterItems = ['Any', 'Original']; - const filteredLanguages = languages.items.filter((lang) => !filterItems.includes(lang.name)); - - const quality = movieFile.quality; - - return { - isFetching: qualityProfiles.isSchemaFetching || languages.isFetching, - isPopulated: qualityProfiles.isSchemaPopulated && languages.isPopulated, - error: qualityProfiles.error || languages.error, - qualityId: quality ? quality.quality.id : 0, - real: quality ? quality.revision.real > 0 : false, - proper: quality ? quality.revision.version > 1 : false, - qualities: getQualities(qualityProfiles.schema.items), - languageIds: movieFile.languages ? movieFile.languages.map((l) => l.id) : [], - languages: filteredLanguages, - indexerFlags: movieFile.indexerFlags, - edition: movieFile.edition, - releaseGroup: movieFile.releaseGroup, - relativePath: movieFile.relativePath - }; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchQualityProfileSchema: fetchQualityProfileSchema, - dispatchUpdateMovieFiles: updateMovieFiles -}; - -class FileEditModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount = () => { - if (!this.props.isPopulated) { - this.props.dispatchFetchQualityProfileSchema(); - } - } - - // - // Listeners - - onSaveInputs = ( payload ) => { - const { - qualityId, - real, - proper, - languageIds, - edition, - releaseGroup, - indexerFlags - } = payload; - - const quality = this.props.qualities.find((item) => item.id === qualityId); - - const languages = []; - - languageIds.forEach((languageId) => { - const language = this.props.languages.find((item) => item.id === parseInt(languageId)); - - if (language !== undefined) { - languages.push(language); - } - }); - - const revision = { - version: proper ? 2 : 1, - real: real ? 1 : 0 - }; - - const movieFileIds = [this.props.movieFileId]; - - this.props.dispatchUpdateMovieFiles({ - movieFileIds, - languages, - indexerFlags, - edition, - releaseGroup, - quality: { - quality, - revision - } - }); - - this.props.onModalClose(true); - } - - // - // Render - - render() { - return ( - - ); - } -} - -FileEditModalContentConnector.propTypes = { - movieFileId: PropTypes.number.isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - qualities: PropTypes.arrayOf(PropTypes.object).isRequired, - languages: PropTypes.arrayOf(PropTypes.object).isRequired, - languageIds: PropTypes.arrayOf(PropTypes.number).isRequired, - indexerFlags: PropTypes.number.isRequired, - qualityId: PropTypes.number.isRequired, - real: PropTypes.bool.isRequired, - edition: PropTypes.string.isRequired, - releaseGroup: PropTypes.string.isRequired, - relativePath: PropTypes.string.isRequired, - proper: PropTypes.bool.isRequired, - dispatchFetchQualityProfileSchema: PropTypes.func.isRequired, - dispatchUpdateMovieFiles: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(FileEditModalContentConnector); diff --git a/frontend/src/MovieFile/Editor/MediaInfoPopover.js b/frontend/src/MovieFile/Editor/MediaInfoPopover.js deleted file mode 100644 index a3d0d2403..000000000 --- a/frontend/src/MovieFile/Editor/MediaInfoPopover.js +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; -import DescriptionList from 'Components/DescriptionList/DescriptionList'; -import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem'; - -function MediaInfoPopover(props) { - return ( - - { - Object.keys(props).map((key) => { - const title = key - .replace(/([A-Z])/g, ' $1') - .replace(/^./, (str) => str.toUpperCase()); - - const value = props[key]; - - if (!value) { - return null; - } - - return ( - - ); - }) - } - - ); -} - -export default MediaInfoPopover; diff --git a/frontend/src/MovieFile/Editor/MovieFileEditorRow.css b/frontend/src/MovieFile/Editor/MovieFileEditorRow.css deleted file mode 100644 index b75a60a77..000000000 --- a/frontend/src/MovieFile/Editor/MovieFileEditorRow.css +++ /dev/null @@ -1,35 +0,0 @@ -.relativePath { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - word-break: break-all; -} - -.quality, -.formats, -.language { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; -} - -.language { - width: 100px; -} - -.rejected, -.download { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 50px; -} - -.age, -.size { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - white-space: nowrap; -} - -.actions { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 100px; -} diff --git a/frontend/src/MovieFile/Editor/MovieFileEditorRow.js b/frontend/src/MovieFile/Editor/MovieFileEditorRow.js deleted file mode 100644 index 80f171789..000000000 --- a/frontend/src/MovieFile/Editor/MovieFileEditorRow.js +++ /dev/null @@ -1,224 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import IconButton from 'Components/Link/IconButton'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import TableRow from 'Components/Table/TableRow'; -import { icons, kinds } from 'Helpers/Props'; -import MovieFormats from 'Movie/MovieFormats'; -import MovieLanguage from 'Movie/MovieLanguage'; -import MovieQuality from 'Movie/MovieQuality'; -import FileEditModal from 'MovieFile/Edit/FileEditModal'; -import MediaInfoConnector from 'MovieFile/MediaInfoConnector'; -import * as mediaInfoTypes from 'MovieFile/mediaInfoTypes'; -import formatBytes from 'Utilities/Number/formatBytes'; -import translate from 'Utilities/String/translate'; -import FileDetailsModal from '../FileDetailsModal'; -import MovieFileRowCellPlaceholder from './MovieFileRowCellPlaceholder'; -import styles from './MovieFileEditorRow.css'; - -class MovieFileEditorRow extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isConfirmDeleteModalOpen: false, - isFileDetailsModalOpen: false, - isFileEditModalOpen: false - }; - } - - // - // Listeners - - onDeletePress = () => { - this.setState({ isConfirmDeleteModalOpen: true }); - } - - onConfirmDelete = () => { - this.setState({ isConfirmDeleteModalOpen: false }); - - this.props.onDeletePress(this.props.id); - } - - onConfirmDeleteModalClose = () => { - this.setState({ isConfirmDeleteModalOpen: false }); - } - - onFileDetailsPress = () => { - this.setState({ isFileDetailsModalOpen: true }); - } - - onFileDetailsModalClose = () => { - this.setState({ isFileDetailsModalOpen: false }); - } - - onFileEditPress = () => { - this.setState({ isFileEditModalOpen: true }); - } - - onFileEditModalClose = () => { - this.setState({ isFileEditModalOpen: false }); - } - - // - // Render - - render() { - const { - id, - mediaInfo, - relativePath, - size, - quality, - qualityCutoffNotMet, - customFormats, - languages - } = this.props; - - const { - isFileDetailsModalOpen, - isFileEditModalOpen, - isConfirmDeleteModalOpen - } = this.state; - - const showQualityPlaceholder = !quality; - - const showLanguagePlaceholder = !languages; - - return ( - - - {relativePath} - - - - - - - - - - - - {formatBytes(size)} - - - - { - showLanguagePlaceholder && - - } - - { - !showLanguagePlaceholder && !!languages && - - } - - - - { - showQualityPlaceholder && - - } - - { - !showQualityPlaceholder && !!quality && - - } - - - - - - - - - - - - - - - - - - - - - ); - } - -} - -MovieFileEditorRow.propTypes = { - id: PropTypes.number.isRequired, - size: PropTypes.number.isRequired, - relativePath: PropTypes.string.isRequired, - quality: PropTypes.object.isRequired, - customFormats: PropTypes.arrayOf(PropTypes.object).isRequired, - qualityCutoffNotMet: PropTypes.bool.isRequired, - languages: PropTypes.arrayOf(PropTypes.object).isRequired, - mediaInfo: PropTypes.object, - onDeletePress: PropTypes.func.isRequired -}; - -export default MovieFileEditorRow; diff --git a/frontend/src/MovieFile/Editor/MovieFileEditorTable.css b/frontend/src/MovieFile/Editor/MovieFileEditorTable.css deleted file mode 100644 index 50d1a9e93..000000000 --- a/frontend/src/MovieFile/Editor/MovieFileEditorTable.css +++ /dev/null @@ -1,10 +0,0 @@ -.container { - margin-top: 20px; - border: 1px solid $borderColor; - border-radius: 4px; - background-color: $white; - - &:last-of-type { - margin-bottom: 0; - } -} diff --git a/frontend/src/MovieFile/Editor/MovieFileEditorTable.js b/frontend/src/MovieFile/Editor/MovieFileEditorTable.js deleted file mode 100644 index 5c71c631a..000000000 --- a/frontend/src/MovieFile/Editor/MovieFileEditorTable.js +++ /dev/null @@ -1,24 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import MovieFileEditorTableContentConnector from './MovieFileEditorTableContentConnector'; -import styles from './MovieFileEditorTable.css'; - -function MovieFileEditorTable(props) { - const { - movieId - } = props; - - return ( -
- -
- ); -} - -MovieFileEditorTable.propTypes = { - movieId: PropTypes.number.isRequired -}; - -export default MovieFileEditorTable; diff --git a/frontend/src/MovieFile/Editor/MovieFileEditorTableContent.css b/frontend/src/MovieFile/Editor/MovieFileEditorTableContent.css deleted file mode 100644 index 4176a45be..000000000 --- a/frontend/src/MovieFile/Editor/MovieFileEditorTableContent.css +++ /dev/null @@ -1,14 +0,0 @@ -.actions { - display: flex; - margin-right: auto; -} - -.selectInput { - margin-left: 10px; -} - -.blankpad { - padding-top: 10px; - padding-bottom: 10px; - padding-left: 2em; -} diff --git a/frontend/src/MovieFile/Editor/MovieFileEditorTableContent.js b/frontend/src/MovieFile/Editor/MovieFileEditorTableContent.js deleted file mode 100644 index 98c29482e..000000000 --- a/frontend/src/MovieFile/Editor/MovieFileEditorTableContent.js +++ /dev/null @@ -1,104 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import IconButton from 'Components/Link/IconButton'; -import Table from 'Components/Table/Table'; -import TableBody from 'Components/Table/TableBody'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import MovieFileEditorRow from './MovieFileEditorRow'; -import styles from './MovieFileEditorTableContent.css'; - -const columns = [ - { - name: 'title', - label: 'Relative Path', - isVisible: true - }, - { - name: 'videoCodec', - label: translate('VideoCodec'), - isVisible: true - }, - { - name: 'audioInfo', - label: translate('AudioInfo'), - isVisible: true - }, - { - name: 'size', - label: translate('Size'), - isVisible: true - }, - { - name: 'languages', - label: translate('Languages'), - isVisible: true - }, - { - name: 'quality', - label: translate('Quality'), - isVisible: true - }, - { - name: 'quality.customFormats', - label: translate('Formats'), - isVisible: true - }, - { - name: 'action', - label: React.createElement(IconButton, { name: icons.ADVANCED_SETTINGS }), - isVisible: true - } -]; - -class MovieFileEditorTableContent extends Component { - - // - // Render - - render() { - const { - items - } = this.props; - - return ( -
- { - !items.length && -
- No movie files to manage. -
- } - - { - !!items.length && - - - { - items.map((item) => { - return ( - - ); - }) - } - -
- } - -
- ); - } -} - -MovieFileEditorTableContent.propTypes = { - movieId: PropTypes.number, - isDeleting: PropTypes.bool.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onDeletePress: PropTypes.func.isRequired -}; - -export default MovieFileEditorTableContent; diff --git a/frontend/src/MovieFile/Editor/MovieFileEditorTableContentConnector.js b/frontend/src/MovieFile/Editor/MovieFileEditorTableContentConnector.js deleted file mode 100644 index 7597741fe..000000000 --- a/frontend/src/MovieFile/Editor/MovieFileEditorTableContentConnector.js +++ /dev/null @@ -1,103 +0,0 @@ -/* eslint max-params: 0 */ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { deleteMovieFile, updateMovieFiles } from 'Store/Actions/movieFileActions'; -import { fetchLanguages, fetchQualityProfileSchema } from 'Store/Actions/settingsActions'; -import createMovieSelector from 'Store/Selectors/createMovieSelector'; -import getQualities from 'Utilities/Quality/getQualities'; -import MovieFileEditorTableContent from './MovieFileEditorTableContent'; - -function createMapStateToProps() { - return createSelector( - (state, { movieId }) => movieId, - (state) => state.movieFiles, - (state) => state.settings.languages, - (state) => state.settings.qualityProfiles, - createMovieSelector(), - ( - movieId, - movieFiles, - languageProfiles, - qualityProfiles - ) => { - const languages = languageProfiles.items; - const qualities = getQualities(qualityProfiles.schema.items); - const filesForMovie = movieFiles.items.filter((obj) => { - return obj.movieId === movieId; - }); - - return { - items: filesForMovie, - isDeleting: movieFiles.isDeleting, - isSaving: movieFiles.isSaving, - error: null, - languages, - qualities - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - dispatchFetchQualityProfileSchema(name, path) { - dispatch(fetchQualityProfileSchema()); - }, - - dispatchFetchLanguages(name, path) { - dispatch(fetchLanguages()); - }, - - dispatchUpdateMovieFiles(updateProps) { - dispatch(updateMovieFiles(updateProps)); - }, - - onDeletePress(movieFileId) { - dispatch(deleteMovieFile({ - id: movieFileId - })); - } - }; -} - -class MovieFileEditorTableContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.dispatchFetchLanguages(); - this.props.dispatchFetchQualityProfileSchema(); - } - - // - // Render - - render() { - const { - dispatchFetchLanguages, - dispatchFetchQualityProfileSchema, - dispatchUpdateMovieFiles, - ...otherProps - } = this.props; - - return ( - - ); - } -} - -MovieFileEditorTableContentConnector.propTypes = { - movieId: PropTypes.number.isRequired, - languages: PropTypes.arrayOf(PropTypes.object).isRequired, - qualities: PropTypes.arrayOf(PropTypes.object).isRequired, - dispatchFetchLanguages: PropTypes.func.isRequired, - dispatchFetchQualityProfileSchema: PropTypes.func.isRequired, - dispatchUpdateMovieFiles: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, createMapDispatchToProps)(MovieFileEditorTableContentConnector); diff --git a/frontend/src/MovieFile/Editor/MovieFileRowCellPlaceholder.css b/frontend/src/MovieFile/Editor/MovieFileRowCellPlaceholder.css deleted file mode 100644 index 941988144..000000000 --- a/frontend/src/MovieFile/Editor/MovieFileRowCellPlaceholder.css +++ /dev/null @@ -1,7 +0,0 @@ -.placeholder { - display: inline-block; - margin: -8px 0; - width: 100%; - height: 25px; - border: 2px dashed $dangerColor; -} diff --git a/frontend/src/MovieFile/Editor/MovieFileRowCellPlaceholder.js b/frontend/src/MovieFile/Editor/MovieFileRowCellPlaceholder.js deleted file mode 100644 index e2956a5ed..000000000 --- a/frontend/src/MovieFile/Editor/MovieFileRowCellPlaceholder.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import styles from './MovieFileRowCellPlaceholder.css'; - -function MovieFileRowCellPlaceholder() { - return ( - - ); -} - -export default MovieFileRowCellPlaceholder; diff --git a/frontend/src/MovieFile/Extras/ExtraFileRow.css b/frontend/src/MovieFile/Extras/ExtraFileRow.css deleted file mode 100644 index fcf05d5a5..000000000 --- a/frontend/src/MovieFile/Extras/ExtraFileRow.css +++ /dev/null @@ -1,10 +0,0 @@ -.relativePath { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - word-break: break-all; -} - -.extension, -.type { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; -} diff --git a/frontend/src/MovieFile/Extras/ExtraFileRow.js b/frontend/src/MovieFile/Extras/ExtraFileRow.js deleted file mode 100644 index d0888db2c..000000000 --- a/frontend/src/MovieFile/Extras/ExtraFileRow.js +++ /dev/null @@ -1,63 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import IconButton from 'Components/Link/IconButton'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import TableRow from 'Components/Table/TableRow'; -import { icons } from 'Helpers/Props'; -import titleCase from 'Utilities/String/titleCase'; -import styles from './ExtraFileRow.css'; - -class ExtraFileRow extends Component { - - // - // Render - - render() { - const { - relativePath, - extension, - type - } = this.props; - - return ( - - - {relativePath} - - - - {extension} - - - - {titleCase(type)} - - - - - - - ); - } - -} - -ExtraFileRow.propTypes = { - id: PropTypes.number.isRequired, - extension: PropTypes.string.isRequired, - type: PropTypes.string.isRequired, - relativePath: PropTypes.string.isRequired -}; - -export default ExtraFileRow; diff --git a/frontend/src/MovieFile/Extras/ExtraFileTable.css b/frontend/src/MovieFile/Extras/ExtraFileTable.css deleted file mode 100644 index 50d1a9e93..000000000 --- a/frontend/src/MovieFile/Extras/ExtraFileTable.css +++ /dev/null @@ -1,10 +0,0 @@ -.container { - margin-top: 20px; - border: 1px solid $borderColor; - border-radius: 4px; - background-color: $white; - - &:last-of-type { - margin-bottom: 0; - } -} diff --git a/frontend/src/MovieFile/Extras/ExtraFileTable.js b/frontend/src/MovieFile/Extras/ExtraFileTable.js deleted file mode 100644 index 46381c26f..000000000 --- a/frontend/src/MovieFile/Extras/ExtraFileTable.js +++ /dev/null @@ -1,25 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import ExtraFileTableContentConnector from './ExtraFileTableContentConnector'; -import styles from './ExtraFileTable.css'; - -function ExtraFileTable(props) { - const { - movieId - } = props; - - return ( -
- -
- - ); -} - -ExtraFileTable.propTypes = { - movieId: PropTypes.number.isRequired -}; - -export default ExtraFileTable; diff --git a/frontend/src/MovieFile/Extras/ExtraFileTableContent.css b/frontend/src/MovieFile/Extras/ExtraFileTableContent.css deleted file mode 100644 index 2bb243f27..000000000 --- a/frontend/src/MovieFile/Extras/ExtraFileTableContent.css +++ /dev/null @@ -1,10 +0,0 @@ -.actions { - display: flex; - margin-right: auto; -} - -.blankpad { - padding-top: 10px; - padding-bottom: 10px; - padding-left: 2em; -} diff --git a/frontend/src/MovieFile/Extras/ExtraFileTableContent.js b/frontend/src/MovieFile/Extras/ExtraFileTableContent.js deleted file mode 100644 index 829c0323d..000000000 --- a/frontend/src/MovieFile/Extras/ExtraFileTableContent.js +++ /dev/null @@ -1,81 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import IconButton from 'Components/Link/IconButton'; -import Table from 'Components/Table/Table'; -import TableBody from 'Components/Table/TableBody'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import ExtraFileRow from './ExtraFileRow'; -import styles from './ExtraFileTableContent.css'; - -const columns = [ - { - name: 'relativePath', - label: translate('RelativePath'), - isVisible: true - }, - { - name: 'extension', - label: translate('Extension'), - isVisible: true - }, - { - name: 'type', - label: translate('Type'), - isVisible: true - }, - { - name: 'action', - label: React.createElement(IconButton, { name: icons.ADVANCED_SETTINGS }), - isVisible: true - } -]; - -class ExtraFileTableContent extends Component { - - // - // Render - - render() { - const { - items - } = this.props; - - return ( -
- { - !items.length && -
- No extra files to manage. -
- } - - { - !!items.length && - - - { - items.map((item) => { - return ( - - ); - }) - } - -
- } - -
- ); - } -} - -ExtraFileTableContent.propTypes = { - movieId: PropTypes.number, - items: PropTypes.arrayOf(PropTypes.object).isRequired -}; - -export default ExtraFileTableContent; diff --git a/frontend/src/MovieFile/Extras/ExtraFileTableContentConnector.js b/frontend/src/MovieFile/Extras/ExtraFileTableContentConnector.js deleted file mode 100644 index 0454bb3f5..000000000 --- a/frontend/src/MovieFile/Extras/ExtraFileTableContentConnector.js +++ /dev/null @@ -1,56 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createMovieSelector from 'Store/Selectors/createMovieSelector'; -import ExtraFileTableContent from './ExtraFileTableContent'; - -function createMapStateToProps() { - return createSelector( - (state, { movieId }) => movieId, - (state) => state.extraFiles, - createMovieSelector(), - ( - movieId, - extraFiles - ) => { - const filesForMovie = extraFiles.items.filter((obj) => { - return obj.movieId === movieId; - }); - - return { - items: filesForMovie, - error: null - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - }; -} - -class ExtraFileTableContentConnector extends Component { - - // - // Render - - render() { - const { - ...otherProps - } = this.props; - - return ( - - ); - } -} - -ExtraFileTableContentConnector.propTypes = { - movieId: PropTypes.number.isRequired -}; - -export default connect(createMapStateToProps, createMapDispatchToProps)(ExtraFileTableContentConnector); diff --git a/frontend/src/MovieFile/FileDetailsModal.js b/frontend/src/MovieFile/FileDetailsModal.js deleted file mode 100644 index dd19b3137..000000000 --- a/frontend/src/MovieFile/FileDetailsModal.js +++ /dev/null @@ -1,53 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Button from 'Components/Link/Button'; -import Modal from 'Components/Modal/Modal'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import MediaInfoPopover from './Editor/MediaInfoPopover'; - -function FileDetailsModal(props) { - const { - isOpen, - onModalClose, - mediaInfo - } = props; - - return ( - - - - {translate('Details')} - - - - - - - - - - - - ); -} - -FileDetailsModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired, - mediaInfo: PropTypes.object -}; - -export default FileDetailsModal; diff --git a/frontend/src/MovieFile/Language/SelectLanguageModal.js b/frontend/src/MovieFile/Language/SelectLanguageModal.js deleted file mode 100644 index 938d26a6d..000000000 --- a/frontend/src/MovieFile/Language/SelectLanguageModal.js +++ /dev/null @@ -1,37 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import SelectLanguageModalContentConnector from './SelectLanguageModalContentConnector'; - -class SelectLanguageModal extends Component { - - // - // Render - - render() { - const { - isOpen, - onModalClose, - ...otherProps - } = this.props; - - return ( - - - - ); - } -} - -SelectLanguageModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default SelectLanguageModal; diff --git a/frontend/src/MovieFile/Language/SelectLanguageModalContentConnector.js b/frontend/src/MovieFile/Language/SelectLanguageModalContentConnector.js deleted file mode 100644 index 1eacde068..000000000 --- a/frontend/src/MovieFile/Language/SelectLanguageModalContentConnector.js +++ /dev/null @@ -1,97 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import SelectLanguageModalContent from 'InteractiveImport/Language/SelectLanguageModalContent'; -import { updateMovieFiles } from 'Store/Actions/movieFileActions'; -import { fetchLanguages } from 'Store/Actions/settingsActions'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.languages, - (languages) => { - const { - isFetching, - isPopulated, - error, - items - } = languages; - - const filterItems = ['Any', 'Original']; - const filteredLanguages = items.filter((lang) => !filterItems.includes(lang.name)); - - return { - isFetching, - isPopulated, - error, - items: filteredLanguages - }; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchLanguages: fetchLanguages, - dispatchupdateMovieFiles: updateMovieFiles -}; - -class SelectLanguageModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount = () => { - if (!this.props.isPopulated) { - this.props.dispatchFetchLanguages(); - } - } - - // - // Listeners - - onLanguageSelect = ({ languageIds }) => { - const languages = []; - - languageIds.forEach((languageId) => { - const language = _.find(this.props.items, - (item) => item.id === parseInt(languageId)); - - if (language !== undefined) { - languages.push(language); - } - }); - - this.props.dispatchupdateMovieFiles({ - movieFileIds: this.props.ids, - languages - }); - - this.props.onModalClose(true); - } - - // - // Render - - render() { - return ( - - ); - } -} - -SelectLanguageModalContentConnector.propTypes = { - ids: PropTypes.arrayOf(PropTypes.number).isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - dispatchFetchLanguages: PropTypes.func.isRequired, - dispatchupdateMovieFiles: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(SelectLanguageModalContentConnector); diff --git a/frontend/src/MovieFile/MediaInfo.js b/frontend/src/MovieFile/MediaInfo.js deleted file mode 100644 index 75b264d58..000000000 --- a/frontend/src/MovieFile/MediaInfo.js +++ /dev/null @@ -1,52 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import * as mediaInfoTypes from './mediaInfoTypes'; - -function MediaInfo(props) { - const { - type, - audioChannels, - audioCodec, - videoCodec - } = props; - - if (type === mediaInfoTypes.AUDIO) { - return ( - - { - !!audioCodec && - audioCodec - } - - { - !!audioCodec && !!audioChannels && - ' - ' - } - - { - !!audioChannels && - audioChannels.toFixed(1) - } - - ); - } - - if (type === mediaInfoTypes.VIDEO) { - return ( - - {videoCodec} - - ); - } - - return null; -} - -MediaInfo.propTypes = { - type: PropTypes.string.isRequired, - audioChannels: PropTypes.number, - audioCodec: PropTypes.string, - videoCodec: PropTypes.string -}; - -export default MediaInfo; diff --git a/frontend/src/MovieFile/MediaInfoConnector.js b/frontend/src/MovieFile/MediaInfoConnector.js deleted file mode 100644 index ce955c8aa..000000000 --- a/frontend/src/MovieFile/MediaInfoConnector.js +++ /dev/null @@ -1,21 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createMovieFileSelector from 'Store/Selectors/createMovieFileSelector'; -import MediaInfo from './MediaInfo'; - -function createMapStateToProps() { - return createSelector( - createMovieFileSelector(), - (movieFile) => { - if (movieFile) { - return { - ...movieFile.mediaInfo - }; - } - - return {}; - } - ); -} - -export default connect(createMapStateToProps)(MediaInfo); diff --git a/frontend/src/MovieFile/MovieFileLanguageConnector.js b/frontend/src/MovieFile/MovieFileLanguageConnector.js deleted file mode 100644 index b7e8b8c0d..000000000 --- a/frontend/src/MovieFile/MovieFileLanguageConnector.js +++ /dev/null @@ -1,17 +0,0 @@ -import EpisodeLanguage from 'Episode/EpisodeLanguage'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createMovieFileSelector from 'Store/Selectors/createMovieFileSelector'; - -function createMapStateToProps() { - return createSelector( - createMovieFileSelector(), - (movieFile) => { - return { - language: movieFile ? movieFile.language : undefined - }; - } - ); -} - -export default connect(createMapStateToProps)(EpisodeLanguage); diff --git a/frontend/src/MovieFile/Quality/SelectQualityModal.js b/frontend/src/MovieFile/Quality/SelectQualityModal.js deleted file mode 100644 index d3e31d2dd..000000000 --- a/frontend/src/MovieFile/Quality/SelectQualityModal.js +++ /dev/null @@ -1,37 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import SelectQualityModalContentConnector from './SelectQualityModalContentConnector'; - -class SelectQualityModal extends Component { - - // - // Render - - render() { - const { - isOpen, - onModalClose, - ...otherProps - } = this.props; - - return ( - - - - ); - } -} - -SelectQualityModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default SelectQualityModal; diff --git a/frontend/src/MovieFile/Quality/SelectQualityModalContent.js b/frontend/src/MovieFile/Quality/SelectQualityModalContent.js deleted file mode 100644 index dd22b9889..000000000 --- a/frontend/src/MovieFile/Quality/SelectQualityModalContent.js +++ /dev/null @@ -1,169 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -class SelectQualityModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - const { - qualityId, - proper, - real - } = props; - - this.state = { - qualityId, - proper, - real - }; - } - - // - // Listeners - - onQualityChange = ({ value }) => { - this.setState({ qualityId: parseInt(value) }); - } - - onProperChange = ({ value }) => { - this.setState({ proper: value }); - } - - onRealChange = ({ value }) => { - this.setState({ real: value }); - } - - onQualitySelect = () => { - this.props.onQualitySelect(this.state); - } - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - items, - onModalClose - } = this.props; - - const { - qualityId, - proper, - real - } = this.state; - - const qualityOptions = items.map(({ id, name }) => { - return { - key: id, - value: name - }; - }); - - return ( - - - Manual Import - Select Quality - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToLoadQualities')} -
- } - - { - isPopulated && !error && -
- - {translate('Quality')} - - - - - - {translate('Proper')} - - - - - - {translate('Real')} - - - -
- } -
- - - - - - -
- ); - } -} - -SelectQualityModalContent.propTypes = { - qualityId: PropTypes.number.isRequired, - proper: PropTypes.bool.isRequired, - real: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onQualitySelect: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default SelectQualityModalContent; diff --git a/frontend/src/MovieFile/Quality/SelectQualityModalContentConnector.js b/frontend/src/MovieFile/Quality/SelectQualityModalContentConnector.js deleted file mode 100644 index 629ed8043..000000000 --- a/frontend/src/MovieFile/Quality/SelectQualityModalContentConnector.js +++ /dev/null @@ -1,97 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { updateMovieFiles } from 'Store/Actions/movieFileActions'; -import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions'; -import getQualities from 'Utilities/Quality/getQualities'; -import SelectQualityModalContent from './SelectQualityModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.qualityProfiles, - (qualityProfiles) => { - const { - isSchemaFetching: isFetching, - isSchemaPopulated: isPopulated, - schemaError: error, - schema - } = qualityProfiles; - - return { - isFetching, - isPopulated, - error, - items: getQualities(schema.items) - }; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchQualityProfileSchema: fetchQualityProfileSchema, - dispatchupdateMovieFiles: updateMovieFiles -}; - -class SelectQualityModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount = () => { - if (!this.props.isPopulated) { - this.props.dispatchFetchQualityProfileSchema(); - } - } - - // - // Listeners - - onQualitySelect = ({ qualityId, proper, real }) => { - const quality = _.find(this.props.items, - (item) => item.id === qualityId); - - const revision = { - version: proper ? 2 : 1, - real: real ? 1 : 0 - }; - - const movieFileIds = this.props.ids; - - this.props.dispatchupdateMovieFiles({ - movieFileIds, - quality: { - quality, - revision - } - }); - - this.props.onModalClose(true); - } - - // - // Render - - render() { - return ( - - ); - } -} - -SelectQualityModalContentConnector.propTypes = { - ids: PropTypes.arrayOf(PropTypes.number).isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - dispatchFetchQualityProfileSchema: PropTypes.func.isRequired, - dispatchupdateMovieFiles: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(SelectQualityModalContentConnector); diff --git a/frontend/src/MovieFile/mediaInfoTypes.js b/frontend/src/MovieFile/mediaInfoTypes.js deleted file mode 100644 index 5e5a78e64..000000000 --- a/frontend/src/MovieFile/mediaInfoTypes.js +++ /dev/null @@ -1,2 +0,0 @@ -export const AUDIO = 'audio'; -export const VIDEO = 'video'; diff --git a/frontend/src/Organize/OrganizePreviewModal.js b/frontend/src/Organize/OrganizePreviewModal.js deleted file mode 100644 index 647f4ddf8..000000000 --- a/frontend/src/Organize/OrganizePreviewModal.js +++ /dev/null @@ -1,34 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import OrganizePreviewModalContentConnector from './OrganizePreviewModalContentConnector'; - -function OrganizePreviewModal(props) { - const { - isOpen, - onModalClose, - ...otherProps - } = props; - - return ( - - { - isOpen && - - } - - ); -} - -OrganizePreviewModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default OrganizePreviewModal; diff --git a/frontend/src/Organize/OrganizePreviewModalConnector.js b/frontend/src/Organize/OrganizePreviewModalConnector.js deleted file mode 100644 index ace733c86..000000000 --- a/frontend/src/Organize/OrganizePreviewModalConnector.js +++ /dev/null @@ -1,39 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearOrganizePreview } from 'Store/Actions/organizePreviewActions'; -import OrganizePreviewModal from './OrganizePreviewModal'; - -const mapDispatchToProps = { - clearOrganizePreview -}; - -class OrganizePreviewModalConnector extends Component { - - // - // Listeners - - onModalClose = () => { - this.props.clearOrganizePreview(); - this.props.onModalClose(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -OrganizePreviewModalConnector.propTypes = { - clearOrganizePreview: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(undefined, mapDispatchToProps)(OrganizePreviewModalConnector); diff --git a/frontend/src/Organize/OrganizePreviewModalContent.css b/frontend/src/Organize/OrganizePreviewModalContent.css deleted file mode 100644 index 9623358c9..000000000 --- a/frontend/src/Organize/OrganizePreviewModalContent.css +++ /dev/null @@ -1,24 +0,0 @@ -.path { - margin-left: 5px; - font-weight: bold; -} - -.standardMovieFormat { - margin-left: 5px; - font-family: $monoSpaceFontFamily; -} - -.previews { - margin-top: 10px; -} - -.selectAllInputContainer { - margin-right: auto; - line-height: 30px; -} - -.selectAllInput { - composes: input from '~Components/Form/CheckInput.css'; - - margin: 0; -} diff --git a/frontend/src/Organize/OrganizePreviewModalContent.js b/frontend/src/Organize/OrganizePreviewModalContent.js deleted file mode 100644 index c1bd97f94..000000000 --- a/frontend/src/Organize/OrganizePreviewModalContent.js +++ /dev/null @@ -1,203 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Alert from 'Components/Alert'; -import CheckInput from 'Components/Form/CheckInput'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import getSelectedIds from 'Utilities/Table/getSelectedIds'; -import selectAll from 'Utilities/Table/selectAll'; -import toggleSelected from 'Utilities/Table/toggleSelected'; -import OrganizePreviewRow from './OrganizePreviewRow'; -import styles from './OrganizePreviewModalContent.css'; - -function getValue(allSelected, allUnselected) { - if (allSelected) { - return true; - } else if (allUnselected) { - return false; - } - - return null; -} - -class OrganizePreviewModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - allSelected: false, - allUnselected: false, - lastToggled: null, - selectedState: {} - }; - } - - // - // Control - - getSelectedIds = () => { - return getSelectedIds(this.state.selectedState); - } - - // - // Listeners - - onSelectAllChange = ({ value }) => { - this.setState(selectAll(this.state.selectedState, value)); - } - - onSelectedChange = ({ id, value, shiftKey = false }) => { - this.setState((state) => { - return toggleSelected(state, this.props.items, id, value, shiftKey); - }); - } - - onOrganizePress = () => { - this.props.onOrganizePress(this.getSelectedIds()); - } - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - items, - renameMovies, - standardMovieFormat, - path, - onModalClose - } = this.props; - - const { - allSelected, - allUnselected, - selectedState - } = this.state; - - const selectAllValue = getValue(allSelected, allUnselected); - - return ( - - - {translate('OrganizeAndRename')} - - - - { - isFetching && - - } - - { - !isFetching && error && -
- {translate('ErrorLoadingPreviews')} -
- } - - { - !isFetching && isPopulated && !items.length && -
- { - renameMovies ? -
{translate('OrganizeModalSuccess')}
: -
{translate('OrganizeModalDisabled')}
- } -
- } - - { - !isFetching && isPopulated && !!items.length && -
- -
- {translate('OrganizeModalAllPathsRelative')} - - {path} - -
- -
- {translate('OrganizeModalNamingPattern')} - - {standardMovieFormat} - -
-
- -
- { - items.map((item) => { - return ( - - ); - }) - } -
-
- } -
- - - { - isPopulated && !!items.length && - - } - - - - - -
- ); - } -} - -OrganizePreviewModalContent.propTypes = { - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - path: PropTypes.string.isRequired, - renameMovies: PropTypes.bool, - standardMovieFormat: PropTypes.string, - onOrganizePress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default OrganizePreviewModalContent; diff --git a/frontend/src/Organize/OrganizePreviewModalContentConnector.js b/frontend/src/Organize/OrganizePreviewModalContentConnector.js deleted file mode 100644 index 6a384f4b1..000000000 --- a/frontend/src/Organize/OrganizePreviewModalContentConnector.js +++ /dev/null @@ -1,88 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import * as commandNames from 'Commands/commandNames'; -import { executeCommand } from 'Store/Actions/commandActions'; -import { fetchOrganizePreview } from 'Store/Actions/organizePreviewActions'; -import { fetchNamingSettings } from 'Store/Actions/settingsActions'; -import createMovieSelector from 'Store/Selectors/createMovieSelector'; -import OrganizePreviewModalContent from './OrganizePreviewModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.organizePreview, - (state) => state.settings.naming, - createMovieSelector(), - (organizePreview, naming, movie) => { - const props = { ...organizePreview }; - props.isFetching = organizePreview.isFetching || naming.isFetching; - props.isPopulated = organizePreview.isPopulated && naming.isPopulated; - props.error = organizePreview.error || naming.error; - props.renameMovies = naming.item.renameMovies; - props.standardMovieFormat = naming.item.standardMovieFormat; - props.path = movie.path; - - return props; - } - ); -} - -const mapDispatchToProps = { - fetchOrganizePreview, - fetchNamingSettings, - executeCommand -}; - -class OrganizePreviewModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - movieId - } = this.props; - - this.props.fetchOrganizePreview({ - movieId - }); - - this.props.fetchNamingSettings(); - } - - // - // Listeners - - onOrganizePress = (files) => { - this.props.executeCommand({ - name: commandNames.RENAME_FILES, - movieId: this.props.movieId, - files - }); - - this.props.onModalClose(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -OrganizePreviewModalContentConnector.propTypes = { - movieId: PropTypes.number.isRequired, - fetchOrganizePreview: PropTypes.func.isRequired, - fetchNamingSettings: PropTypes.func.isRequired, - executeCommand: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(OrganizePreviewModalContentConnector); diff --git a/frontend/src/Organize/OrganizePreviewRow.css b/frontend/src/Organize/OrganizePreviewRow.css deleted file mode 100644 index 1b3c8ca47..000000000 --- a/frontend/src/Organize/OrganizePreviewRow.css +++ /dev/null @@ -1,20 +0,0 @@ -.row { - display: flex; - margin-bottom: 5px; - padding: 5px 0; - border-bottom: 1px solid $borderColor; - - &:last-of-type { - margin-bottom: 0; - padding-bottom: 0; - border-bottom: none; - } -} - -.selectedContainer { - margin-right: 30px; -} - -.path { - margin-left: 10px; -} diff --git a/frontend/src/Organize/OrganizePreviewRow.js b/frontend/src/Organize/OrganizePreviewRow.js deleted file mode 100644 index 7cad23a5b..000000000 --- a/frontend/src/Organize/OrganizePreviewRow.js +++ /dev/null @@ -1,90 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import CheckInput from 'Components/Form/CheckInput'; -import Icon from 'Components/Icon'; -import { icons, kinds } from 'Helpers/Props'; -import styles from './OrganizePreviewRow.css'; - -class OrganizePreviewRow extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - id, - onSelectedChange - } = this.props; - - onSelectedChange({ id, value: true }); - } - - // - // Listeners - - onSelectedChange = ({ value, shiftKey }) => { - const { - id, - onSelectedChange - } = this.props; - - onSelectedChange({ id, value, shiftKey }); - } - - // - // Render - - render() { - const { - id, - existingPath, - newPath, - isSelected - } = this.props; - - return ( -
- - -
-
- - - - {existingPath} - -
- -
- - - - {newPath} - -
-
-
- ); - } -} - -OrganizePreviewRow.propTypes = { - id: PropTypes.number.isRequired, - existingPath: PropTypes.string.isRequired, - newPath: PropTypes.string.isRequired, - isSelected: PropTypes.bool, - onSelectedChange: PropTypes.func.isRequired -}; - -export default OrganizePreviewRow; diff --git a/frontend/src/RootFolder/RootFolderRow.css b/frontend/src/RootFolder/RootFolderRow.css deleted file mode 100644 index c1ec2625e..000000000 --- a/frontend/src/RootFolder/RootFolderRow.css +++ /dev/null @@ -1,27 +0,0 @@ -.link { - composes: link from '~Components/Link/Link.css'; -} - -.unavailablePath { - display: flex; - align-items: center; -} - -.unavailableLabel { - composes: label from '~Components/Label.css'; - - margin-left: 10px; -} - -.freeSpace, -.unmappedFolders { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 150px; -} - -.actions { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 45px; -} diff --git a/frontend/src/RootFolder/RootFolderRow.js b/frontend/src/RootFolder/RootFolderRow.js deleted file mode 100644 index 3a6551955..000000000 --- a/frontend/src/RootFolder/RootFolderRow.js +++ /dev/null @@ -1,82 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Label from 'Components/Label'; -import IconButton from 'Components/Link/IconButton'; -import Link from 'Components/Link/Link'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import TableRow from 'Components/Table/TableRow'; -import { icons, kinds } from 'Helpers/Props'; -import formatBytes from 'Utilities/Number/formatBytes'; -import translate from 'Utilities/String/translate'; -import styles from './RootFolderRow.css'; - -function RootFolderRow(props) { - const { - id, - path, - accessible, - freeSpace, - unmappedFolders, - onDeletePress - } = props; - - const isUnavailable = !accessible; - - return ( - - - { - isUnavailable ? -
- {path} - - -
: - - - {path} - - } -
- - - {(isUnavailable || isNaN(freeSpace)) ? '-' : formatBytes(freeSpace)} - - - - {isUnavailable ? '-' : unmappedFolders.length} - - - - - -
- ); -} - -RootFolderRow.propTypes = { - id: PropTypes.number.isRequired, - path: PropTypes.string.isRequired, - accessible: PropTypes.bool.isRequired, - freeSpace: PropTypes.number, - unmappedFolders: PropTypes.arrayOf(PropTypes.object).isRequired, - onDeletePress: PropTypes.func.isRequired -}; - -RootFolderRow.defaultProps = { - unmappedFolders: [] -}; - -export default RootFolderRow; diff --git a/frontend/src/RootFolder/RootFolderRowConnector.js b/frontend/src/RootFolder/RootFolderRowConnector.js deleted file mode 100644 index ab0848e87..000000000 --- a/frontend/src/RootFolder/RootFolderRowConnector.js +++ /dev/null @@ -1,13 +0,0 @@ -import { connect } from 'react-redux'; -import { deleteRootFolder } from 'Store/Actions/rootFolderActions'; -import RootFolderRow from './RootFolderRow'; - -function createMapDispatchToProps(dispatch, props) { - return { - onDeletePress() { - dispatch(deleteRootFolder({ id: props.id })); - } - }; -} - -export default connect(null, createMapDispatchToProps)(RootFolderRow); diff --git a/frontend/src/RootFolder/RootFolders.js b/frontend/src/RootFolder/RootFolders.js deleted file mode 100644 index ef81f2b61..000000000 --- a/frontend/src/RootFolder/RootFolders.js +++ /dev/null @@ -1,84 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import Table from 'Components/Table/Table'; -import TableBody from 'Components/Table/TableBody'; -import translate from 'Utilities/String/translate'; -import RootFolderRowConnector from './RootFolderRowConnector'; - -const rootFolderColumns = [ - { - name: 'path', - label: translate('Path'), - isVisible: true - }, - { - name: 'freeSpace', - label: translate('FreeSpace'), - isVisible: true - }, - { - name: 'unmappedFolders', - label: translate('UnmappedFolders'), - isVisible: true - }, - { - name: 'actions', - isVisible: true - } -]; - -function RootFolders(props) { - const { - isFetching, - isPopulated, - error, - items - } = props; - - if (isFetching && !isPopulated) { - return ( - - ); - } - - if (!isFetching && !!error) { - return ( -
- {translate('UnableToLoadRootFolders')} -
- ); - } - - return ( - - - { - items.map((rootFolder) => { - return ( - - ); - }) - } - -
- ); -} - -RootFolders.propTypes = { - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired -}; - -export default RootFolders; diff --git a/frontend/src/RootFolder/RootFoldersConnector.js b/frontend/src/RootFolder/RootFoldersConnector.js deleted file mode 100644 index 39f140bcc..000000000 --- a/frontend/src/RootFolder/RootFoldersConnector.js +++ /dev/null @@ -1,46 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; -import RootFolders from './RootFolders'; - -function createMapStateToProps() { - return createSelector( - (state) => state.rootFolders, - (rootFolders) => { - return rootFolders; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchRootFolders: fetchRootFolders -}; - -class RootFoldersConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.dispatchFetchRootFolders(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -RootFoldersConnector.propTypes = { - dispatchFetchRootFolders: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(RootFoldersConnector); diff --git a/frontend/src/Settings/CustomFormats/CustomFormatSettingsConnector.js b/frontend/src/Settings/CustomFormats/CustomFormatSettingsConnector.js deleted file mode 100644 index ec823ba21..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormatSettingsConnector.js +++ /dev/null @@ -1,33 +0,0 @@ -import React, { Component } from 'react'; -import { DndProvider } from 'react-dnd'; -import { HTML5Backend } from 'react-dnd-html5-backend'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; -import translate from 'Utilities/String/translate'; -import CustomFormatsConnector from './CustomFormats/CustomFormatsConnector'; - -class CustomFormatSettingsConnector extends Component { - - // - // Render - - render() { - return ( - - - - - - - - - - ); - } -} - -export default CustomFormatSettingsConnector; - diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.css b/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.css deleted file mode 100644 index ed030aa80..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.css +++ /dev/null @@ -1,38 +0,0 @@ -.customFormat { - composes: card from '~Components/Card.css'; - - width: 300px; -} - -.nameContainer { - display: flex; - justify-content: space-between; -} - -.name { - @add-mixin truncate; - - margin-bottom: 20px; - font-weight: 300; - font-size: 24px; -} - -.cloneButton { - composes: button from '~Components/Link/IconButton.css'; - - height: 36px; -} - -.formats { - display: flex; - flex-wrap: wrap; - margin-top: 5px; - pointer-events: all; -} - -.tooltipLabel { - composes: label from '~Components/Label.css'; - - margin: 0; - border: none; -} diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.js b/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.js deleted file mode 100644 index 4dad8f517..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormat.js +++ /dev/null @@ -1,180 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import Label from 'Components/Label'; -import IconButton from 'Components/Link/IconButton'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import { icons, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditCustomFormatModalConnector from './EditCustomFormatModalConnector'; -import ExportCustomFormatModal from './ExportCustomFormatModal'; -import styles from './CustomFormat.css'; - -class CustomFormat extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditCustomFormatModalOpen: false, - isExportCustomFormatModalOpen: false, - isDeleteCustomFormatModalOpen: false - }; - } - - // - // Listeners - - onEditCustomFormatPress = () => { - this.setState({ isEditCustomFormatModalOpen: true }); - } - - onEditCustomFormatModalClose = () => { - this.setState({ isEditCustomFormatModalOpen: false }); - } - - onExportCustomFormatPress = () => { - this.setState({ isExportCustomFormatModalOpen: true }); - } - - onExportCustomFormatModalClose = () => { - this.setState({ isExportCustomFormatModalOpen: false }); - } - - onDeleteCustomFormatPress = () => { - this.setState({ - isEditCustomFormatModalOpen: false, - isDeleteCustomFormatModalOpen: true - }); - } - - onDeleteCustomFormatModalClose = () => { - this.setState({ isDeleteCustomFormatModalOpen: false }); - } - - onConfirmDeleteCustomFormat = () => { - this.props.onConfirmDeleteCustomFormat(this.props.id); - } - - onCloneCustomFormatPress = () => { - const { - id, - onCloneCustomFormatPress - } = this.props; - - onCloneCustomFormatPress(id); - } - - // - // Render - - render() { - const { - id, - name, - specifications, - isDeleting - } = this.props; - - return ( - -
-
- {name} -
- -
- - - -
-
- -
- { - specifications.map((item, index) => { - if (!item) { - return null; - } - - let kind = kinds.DEFAULT; - if (item.required) { - kind = kinds.SUCCESS; - } - if (item.negate) { - kind = kinds.DANGER; - } - - return ( - - ); - }) - } -
- - - - - - -
- Are you sure you want to delete custom format '{name}'? -
-
- } - confirmLabel={translate('Delete')} - isSpinning={isDeleting} - onConfirm={this.onConfirmDeleteCustomFormat} - onCancel={this.onDeleteCustomFormatModalClose} - /> - - ); - } -} - -CustomFormat.propTypes = { - id: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - specifications: PropTypes.arrayOf(PropTypes.object).isRequired, - isDeleting: PropTypes.bool.isRequired, - onConfirmDeleteCustomFormat: PropTypes.func.isRequired, - onCloneCustomFormatPress: PropTypes.func.isRequired -}; - -export default CustomFormat; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormats.css b/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormats.css deleted file mode 100644 index d4b3d6375..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormats.css +++ /dev/null @@ -1,21 +0,0 @@ -.customFormats { - display: flex; - flex-wrap: wrap; -} - -.addCustomFormat { - composes: customFormat from '~./CustomFormat.css'; - - background-color: $cardAlternateBackgroundColor; - color: $gray; - text-align: center; - font-size: 45px; -} - -.center { - display: inline-block; - padding: 5px 20px 0; - border: 1px solid $borderColor; - border-radius: 4px; - background-color: $white; -} diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormats.js b/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormats.js deleted file mode 100644 index 02fcb2050..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormats.js +++ /dev/null @@ -1,116 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import FieldSet from 'Components/FieldSet'; -import Icon from 'Components/Icon'; -import PageSectionContent from 'Components/Page/PageSectionContent'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import CustomFormat from './CustomFormat'; -import EditCustomFormatModalConnector from './EditCustomFormatModalConnector'; -import styles from './CustomFormats.css'; - -class CustomFormats extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isCustomFormatModalOpen: false, - tagsFromId: undefined - }; - } - - // - // Listeners - - onCloneCustomFormatPress = (id) => { - this.props.onCloneCustomFormatPress(id); - this.setState({ - isCustomFormatModalOpen: true, - tagsFromId: id - }); - } - - onEditCustomFormatPress = () => { - this.setState({ isCustomFormatModalOpen: true }); - } - - onModalClose = () => { - this.setState({ - isCustomFormatModalOpen: false, - tagsFromId: undefined - }); - } - - // - // Render - - render() { - const { - items, - isDeleting, - onConfirmDeleteCustomFormat, - onCloneCustomFormatPress, - ...otherProps - } = this.props; - - return ( -
- -
- { - items.map((item) => { - return ( - - ); - }) - } - - -
- -
-
-
- - - -
-
- ); - } -} - -CustomFormats.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - isDeleting: PropTypes.bool.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteCustomFormat: PropTypes.func.isRequired, - onCloneCustomFormatPress: PropTypes.func.isRequired -}; - -export default CustomFormats; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormatsConnector.js b/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormatsConnector.js deleted file mode 100644 index 62b0942a9..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/CustomFormatsConnector.js +++ /dev/null @@ -1,63 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { cloneCustomFormat, deleteCustomFormat, fetchCustomFormats } from 'Store/Actions/settingsActions'; -import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector'; -import sortByName from 'Utilities/Array/sortByName'; -import CustomFormats from './CustomFormats'; - -function createMapStateToProps() { - return createSelector( - createSortedSectionSelector('settings.customFormats', sortByName), - (customFormats) => customFormats - ); -} - -const mapDispatchToProps = { - dispatchFetchCustomFormats: fetchCustomFormats, - dispatchDeleteCustomFormat: deleteCustomFormat, - dispatchCloneCustomFormat: cloneCustomFormat -}; - -class CustomFormatsConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.dispatchFetchCustomFormats(); - } - - // - // Listeners - - onConfirmDeleteCustomFormat = (id) => { - this.props.dispatchDeleteCustomFormat({ id }); - } - - onCloneCustomFormatPress = (id) => { - this.props.dispatchCloneCustomFormat({ id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -CustomFormatsConnector.propTypes = { - dispatchFetchCustomFormats: PropTypes.func.isRequired, - dispatchDeleteCustomFormat: PropTypes.func.isRequired, - dispatchCloneCustomFormat: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(CustomFormatsConnector); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModal.js b/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModal.js deleted file mode 100644 index 59b302030..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModal.js +++ /dev/null @@ -1,61 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import EditCustomFormatModalContentConnector from './EditCustomFormatModalContentConnector'; - -class EditCustomFormatModal extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - height: 'auto' - }; - } - - // - // Listeners - - onContentHeightChange = (height) => { - if (this.state.height === 'auto' || height > this.state.height) { - this.setState({ height }); - } - } - - // - // Render - - render() { - const { - isOpen, - onModalClose, - ...otherProps - } = this.props; - - return ( - - - - ); - } -} - -EditCustomFormatModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditCustomFormatModal; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalConnector.js b/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalConnector.js deleted file mode 100644 index d500cfd9f..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalConnector.js +++ /dev/null @@ -1,43 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import EditCustomFormatModal from './EditCustomFormatModal'; - -function mapStateToProps() { - return {}; -} - -const mapDispatchToProps = { - clearPendingChanges -}; - -class EditCustomFormatModalConnector extends Component { - - // - // Listeners - - onModalClose = () => { - this.props.clearPendingChanges({ section: 'settings.customFormats' }); - this.props.onModalClose(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditCustomFormatModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(mapStateToProps, mapDispatchToProps)(EditCustomFormatModalConnector); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContent.css b/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContent.css deleted file mode 100644 index cdf21ca8a..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContent.css +++ /dev/null @@ -1,22 +0,0 @@ -.deleteButton { - composes: button from '~Components/Link/Button.css'; - - margin-right: auto; -} - -.addSpecification { - composes: customFormat from '~./CustomFormat.css'; - - background-color: $cardAlternateBackgroundColor; - color: $gray; - text-align: center; - font-size: 45px; -} - -.center { - display: inline-block; - padding: 5px 20px 0; - border: 1px solid $borderColor; - border-radius: 4px; - background-color: $white; -} diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContent.js b/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContent.js deleted file mode 100644 index c2d4a4804..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContent.js +++ /dev/null @@ -1,258 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import FieldSet from 'Components/FieldSet'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { icons, inputTypes, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import ImportCustomFormatModal from './ImportCustomFormatModal'; -import AddSpecificationModal from './Specifications/AddSpecificationModal'; -import EditSpecificationModalConnector from './Specifications/EditSpecificationModalConnector'; -import Specification from './Specifications/Specification'; -import styles from './EditCustomFormatModalContent.css'; - -class EditCustomFormatModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isAddSpecificationModalOpen: false, - isEditSpecificationModalOpen: false, - isImportCustomFormatModalOpen: false - }; - } - - // - // Listeners - - onAddSpecificationPress = () => { - this.setState({ isAddSpecificationModalOpen: true }); - } - - onAddSpecificationModalClose = ({ specificationSelected = false } = {}) => { - this.setState({ - isAddSpecificationModalOpen: false, - isEditSpecificationModalOpen: specificationSelected - }); - } - - onEditSpecificationModalClose = () => { - this.setState({ isEditSpecificationModalOpen: false }); - } - - onImportPress = () => { - this.setState({ isImportCustomFormatModalOpen: true }); - } - - onImportCustomFormatModalClose = () => { - this.setState({ isImportCustomFormatModalOpen: false }); - } - - // - // Render - - render() { - const { - isFetching, - error, - isSaving, - saveError, - item, - specificationsPopulated, - specifications, - onInputChange, - onSavePress, - onModalClose, - onDeleteCustomFormatPress, - onCloneSpecificationPress, - onConfirmDeleteSpecification, - ...otherProps - } = this.props; - - const { - isAddSpecificationModalOpen, - isEditSpecificationModalOpen, - isImportCustomFormatModalOpen - } = this.state; - - const { - id, - name, - includeCustomFormatWhenRenaming - } = item; - - return ( - - - - {id ? 'Edit Custom Format' : 'Add Custom Format'} - - - -
- { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToAddANewCustomFormatPleaseTryAgain')} -
- } - - { - !isFetching && !error && specificationsPopulated && -
-
- - - Name - - - - - - - {translate('IncludeCustomFormatWhenRenaming')} - - - -
- -
-
- { - specifications.map((tag) => { - return ( - - ); - }) - } - - -
- -
-
-
-
- - - - - - - -
- } -
-
- - { - id && - - } - - { - !id && - - } - - - - - {translate('Save')} - - -
- ); - } -} - -EditCustomFormatModalContent.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - specificationsPopulated: PropTypes.bool.isRequired, - specifications: PropTypes.arrayOf(PropTypes.object), - onInputChange: PropTypes.func.isRequired, - onSavePress: PropTypes.func.isRequired, - onContentHeightChange: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired, - onDeleteCustomFormatPress: PropTypes.func, - onCloneSpecificationPress: PropTypes.func.isRequired, - onConfirmDeleteSpecification: PropTypes.func.isRequired -}; - -export default EditCustomFormatModalContent; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContentConnector.js b/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContentConnector.js deleted file mode 100644 index 1168c7b2b..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/EditCustomFormatModalContentConnector.js +++ /dev/null @@ -1,102 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { cloneCustomFormatSpecification, deleteCustomFormatSpecification, fetchCustomFormatSpecifications, saveCustomFormat, setCustomFormatValue } from 'Store/Actions/settingsActions'; -import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector'; -import EditCustomFormatModalContent from './EditCustomFormatModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - createProviderSettingsSelector('customFormats'), - (state) => state.settings.customFormatSpecifications, - (advancedSettings, customFormat, specifications) => { - return { - advancedSettings, - ...customFormat, - specificationsPopulated: specifications.isPopulated, - specifications: specifications.items - }; - } - ); -} - -const mapDispatchToProps = { - setCustomFormatValue, - saveCustomFormat, - fetchCustomFormatSpecifications, - cloneCustomFormatSpecification, - deleteCustomFormatSpecification -}; - -class EditCustomFormatModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - id, - tagsFromId - } = this.props; - this.props.fetchCustomFormatSpecifications({ id: tagsFromId || id }); - } - - componentDidUpdate(prevProps, prevState) { - if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) { - this.props.onModalClose(); - } - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setCustomFormatValue({ name, value }); - } - - onSavePress = () => { - this.props.saveCustomFormat({ id: this.props.id }); - } - - onCloneSpecificationPress = (id) => { - this.props.cloneCustomFormatSpecification({ id }); - } - - onConfirmDeleteSpecification = (id) => { - this.props.deleteCustomFormatSpecification({ id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditCustomFormatModalContentConnector.propTypes = { - id: PropTypes.number, - tagsFromId: PropTypes.number, - isFetching: PropTypes.bool.isRequired, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - setCustomFormatValue: PropTypes.func.isRequired, - saveCustomFormat: PropTypes.func.isRequired, - fetchCustomFormatSpecifications: PropTypes.func.isRequired, - cloneCustomFormatSpecification: PropTypes.func.isRequired, - deleteCustomFormatSpecification: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(EditCustomFormatModalContentConnector); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModal.js b/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModal.js deleted file mode 100644 index 94cd041c6..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModal.js +++ /dev/null @@ -1,61 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import ExportCustomFormatModalContentConnector from './ExportCustomFormatModalContentConnector'; - -class ExportCustomFormatModal extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - height: 'auto' - }; - } - - // - // Listeners - - onContentHeightChange = (height) => { - if (this.state.height === 'auto' || height > this.state.height) { - this.setState({ height }); - } - } - - // - // Render - - render() { - const { - isOpen, - onModalClose, - ...otherProps - } = this.props; - - return ( - - - - ); - } -} - -ExportCustomFormatModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default ExportCustomFormatModal; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContent.css b/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContent.css deleted file mode 100644 index d7983f681..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContent.css +++ /dev/null @@ -1,5 +0,0 @@ -.button { - composes: button from '~Components/Link/Button.css'; - - position: relative; -} diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContent.js b/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContent.js deleted file mode 100644 index 41f2a36bb..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContent.js +++ /dev/null @@ -1,85 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Button from 'Components/Link/Button'; -import ClipboardButton from 'Components/Link/ClipboardButton'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './ExportCustomFormatModalContent.css'; - -class ExportCustomFormatModalContent extends Component { - - // - // Render - - render() { - const { - isFetching, - error, - json, - specificationsPopulated, - onModalClose - } = this.props; - - return ( - - - - {translate('ExportCustomFormat')} - - - -
- { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToLoadCustomFormats')} -
- } - - { - !isFetching && !error && specificationsPopulated && -
-
-                    {json}
-                  
-
- } -
-
- - - - -
- ); - } -} - -ExportCustomFormatModalContent.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - json: PropTypes.string.isRequired, - specificationsPopulated: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default ExportCustomFormatModalContent; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContentConnector.js b/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContentConnector.js deleted file mode 100644 index f762f44e7..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/ExportCustomFormatModalContentConnector.js +++ /dev/null @@ -1,83 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchCustomFormatSpecifications } from 'Store/Actions/settingsActions'; -import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector'; -import ExportCustomFormatModalContent from './ExportCustomFormatModalContent'; - -const blacklistedProperties = ['id', 'implementationName', 'infoLink']; - -function replacer(key, value) { - if (blacklistedProperties.includes(key)) { - return undefined; - } - - // provider fields - if (key === 'fields') { - return value.reduce((acc, cur) => { - acc[cur.name] = cur.value; - return acc; - }, {}); - } - - // regular setting values - if (value.hasOwnProperty('value')) { - return value.value; - } - - return value; -} - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - createProviderSettingsSelector('customFormats'), - (state) => state.settings.customFormatSpecifications, - (advancedSettings, customFormat, specifications) => { - const json = customFormat.item ? JSON.stringify(customFormat.item, replacer, 2) : ''; - return { - advancedSettings, - ...customFormat, - json, - specificationsPopulated: specifications.isPopulated, - specifications: specifications.items - }; - } - ); -} - -const mapDispatchToProps = { - fetchCustomFormatSpecifications -}; - -class ExportCustomFormatModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - id - } = this.props; - this.props.fetchCustomFormatSpecifications({ id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -ExportCustomFormatModalContentConnector.propTypes = { - id: PropTypes.number, - fetchCustomFormatSpecifications: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ExportCustomFormatModalContentConnector); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModal.js b/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModal.js deleted file mode 100644 index 2a4d9735e..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModal.js +++ /dev/null @@ -1,61 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import ImportCustomFormatModalContentConnector from './ImportCustomFormatModalContentConnector'; - -class ImportCustomFormatModal extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - height: 'auto' - }; - } - - // - // Listeners - - onContentHeightChange = (height) => { - if (this.state.height === 'auto' || height > this.state.height) { - this.setState({ height }); - } - } - - // - // Render - - render() { - const { - isOpen, - onModalClose, - ...otherProps - } = this.props; - - return ( - - - - ); - } -} - -ImportCustomFormatModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default ImportCustomFormatModal; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContent.css b/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContent.css deleted file mode 100644 index 028df2455..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContent.css +++ /dev/null @@ -1,5 +0,0 @@ -.input { - composes: input from '~Components/Form/TextArea.css'; - - font-family: $monoSpaceFontFamily; -} diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContent.js b/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContent.js deleted file mode 100644 index cfcd2d30a..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContent.js +++ /dev/null @@ -1,152 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './ImportCustomFormatModalContent.css'; - -class ImportCustomFormatModalContent extends Component { - - // - // Lifecycle - constructor(props, context) { - super(props, context); - - this._importTimeout = null; - - this.state = { - json: '', - isSpinning: false, - parseError: null - }; - } - - componentWillUnmount() { - if (this._importTimeout) { - clearTimeout(this._importTimeout); - } - } - - // - // Control - - onChange = (event) => { - this.setState({ json: event.value }); - } - - onImportPress = () => { - this.setState({ isSpinning: true }); - // this is a bodge as we need to register a isSpinning: true to get the spinner button to update - this._importTimeout = setTimeout(this.doImport, 250); - } - - doImport = () => { - const parseError = this.props.onImportPress(this.state.json); - this.setState({ - parseError, - isSpinning: false - }); - - if (!parseError) { - this.props.onModalClose(); - } - } - - // - // Render - - render() { - const { - isFetching, - error, - specificationsPopulated, - onModalClose - } = this.props; - - const { - json, - isSpinning, - parseError - } = this.state; - - return ( - - - - {translate('ImportCustomFormat')} - - - -
- { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToLoadCustomFormats')} -
- } - - { - !isFetching && !error && specificationsPopulated && -
- - - {translate('CustomFormatJSON')} - - - -
- } -
-
- - - - {translate('Import')} - - -
- ); - } -} - -ImportCustomFormatModalContent.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - specificationsPopulated: PropTypes.bool.isRequired, - onImportPress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default ImportCustomFormatModalContent; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContentConnector.js b/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContentConnector.js deleted file mode 100644 index f7b01fa95..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/ImportCustomFormatModalContentConnector.js +++ /dev/null @@ -1,146 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import { clearCustomFormatSpecificationPending, deleteAllCustomFormatSpecification, fetchCustomFormatSpecificationSchema, saveCustomFormatSpecification, selectCustomFormatSpecificationSchema, setCustomFormatSpecificationFieldValue, setCustomFormatSpecificationValue, setCustomFormatValue } from 'Store/Actions/settingsActions'; -import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector'; -import translate from 'Utilities/String/translate'; -import ImportCustomFormatModalContent from './ImportCustomFormatModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - createProviderSettingsSelector('customFormats'), - (state) => state.settings.customFormatSpecifications, - (advancedSettings, customFormat, specifications) => { - return { - advancedSettings, - ...customFormat, - specificationsPopulated: specifications.isPopulated, - specificationSchema: specifications.schema - }; - } - ); -} - -const mapDispatchToProps = { - deleteAllCustomFormatSpecification, - clearCustomFormatSpecificationPending, - clearPendingChanges, - saveCustomFormatSpecification, - selectCustomFormatSpecificationSchema, - setCustomFormatSpecificationFieldValue, - setCustomFormatSpecificationValue, - setCustomFormatValue, - fetchCustomFormatSpecificationSchema -}; - -class ImportCustomFormatModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchCustomFormatSpecificationSchema(); - } - - // - // Listeners - - clearPending = () => { - this.props.clearPendingChanges({ section: 'settings.customFormats' }); - this.props.clearCustomFormatSpecificationPending(); - this.props.deleteAllCustomFormatSpecification(); - } - - onImportPress = (payload) => { - - this.clearPending(); - - try { - const cf = JSON.parse(payload); - this.parseCf(cf); - } catch (err) { - this.clearPending(); - return { - message: err.message, - detailedMessage: err.stack - }; - } - - return null; - } - - parseCf = (cf) => { - for (const [key, value] of Object.entries(cf)) { - if (key === 'specifications') { - for (const spec of value) { - this.parseSpecification(spec); - } - } else if (key !== 'id') { - this.props.setCustomFormatValue({ name: key, value }); - } - } - } - - parseSpecification = (spec) => { - const selectedImplementation = _.find(this.props.specificationSchema, { implementation: spec.implementation }); - - if (!selectedImplementation) { - throw new Error(translate('CustomFormatUnknownCondition', [spec.implementation])); - } - - this.props.selectCustomFormatSpecificationSchema({ implementation: spec.implementation }); - - for (const [key, value] of Object.entries(spec)) { - if (key === 'fields') { - this.parseFields(value, selectedImplementation); - } else if (key !== 'id') { - this.props.setCustomFormatSpecificationValue({ name: key, value }); - } - } - - this.props.saveCustomFormatSpecification(); - } - - parseFields = (fields, schema) => { - for (const [key, value] of Object.entries(fields)) { - const field = _.find(schema.fields, { name: key }); - if (!field) { - throw new Error(translate('CustomFormatUnknownConditionOption', [key, schema.implementationName])); - } - - this.props.setCustomFormatSpecificationFieldValue({ name: key, value }); - } - } - - // - // Render - - render() { - return ( - - ); - } -} - -ImportCustomFormatModalContentConnector.propTypes = { - specificationSchema: PropTypes.arrayOf(PropTypes.object).isRequired, - clearPendingChanges: PropTypes.func.isRequired, - deleteAllCustomFormatSpecification: PropTypes.func.isRequired, - clearCustomFormatSpecificationPending: PropTypes.func.isRequired, - saveCustomFormatSpecification: PropTypes.func.isRequired, - fetchCustomFormatSpecificationSchema: PropTypes.func.isRequired, - selectCustomFormatSpecificationSchema: PropTypes.func.isRequired, - setCustomFormatSpecificationValue: PropTypes.func.isRequired, - setCustomFormatSpecificationFieldValue: PropTypes.func.isRequired, - setCustomFormatValue: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportCustomFormatModalContentConnector); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationItem.css b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationItem.css deleted file mode 100644 index eabcae750..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationItem.css +++ /dev/null @@ -1,44 +0,0 @@ -.specification { - composes: card from '~Components/Card.css'; - - position: relative; - width: 300px; - height: 100px; -} - -.underlay { - @add-mixin cover; -} - -.overlay { - @add-mixin linkOverlay; - - padding: 10px; -} - -.name { - text-align: center; - font-weight: lighter; - font-size: 24px; -} - -.actions { - margin-top: 20px; - text-align: right; -} - -.presetsMenu { - composes: menu from '~Components/Menu/Menu.css'; - - display: inline-block; - margin: 0 5px; -} - -.presetsMenuButton { - composes: button from '~Components/Link/Button.css'; - - &::after { - margin-left: 5px; - content: '\25BE'; - } -} diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationItem.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationItem.js deleted file mode 100644 index 15bba5468..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationItem.js +++ /dev/null @@ -1,111 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Button from 'Components/Link/Button'; -import Link from 'Components/Link/Link'; -import Menu from 'Components/Menu/Menu'; -import MenuContent from 'Components/Menu/MenuContent'; -import { sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import AddSpecificationPresetMenuItem from './AddSpecificationPresetMenuItem'; -import styles from './AddSpecificationItem.css'; - -class AddSpecificationItem extends Component { - - // - // Listeners - - onSpecificationSelect = () => { - const { - implementation - } = this.props; - - this.props.onSpecificationSelect({ implementation }); - } - - // - // Render - - render() { - const { - implementation, - implementationName, - infoLink, - presets, - onSpecificationSelect - } = this.props; - - const hasPresets = !!presets && !!presets.length; - - return ( -
- - -
-
- {implementationName} -
- -
- { - hasPresets && - - - - - - - - { - presets.map((preset, index) => { - return ( - - ); - }) - } - - - - } - - -
-
-
- ); - } -} - -AddSpecificationItem.propTypes = { - implementation: PropTypes.string.isRequired, - implementationName: PropTypes.string.isRequired, - infoLink: PropTypes.string.isRequired, - presets: PropTypes.arrayOf(PropTypes.object), - onSpecificationSelect: PropTypes.func.isRequired -}; - -export default AddSpecificationItem; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModal.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModal.js deleted file mode 100644 index 19d8a4335..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModal.js +++ /dev/null @@ -1,25 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import AddSpecificationModalContentConnector from './AddSpecificationModalContentConnector'; - -function AddSpecificationModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -AddSpecificationModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default AddSpecificationModal; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.css b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.css deleted file mode 100644 index d51349ea9..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.css +++ /dev/null @@ -1,5 +0,0 @@ -.specifications { - display: flex; - justify-content: center; - flex-wrap: wrap; -} diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.js deleted file mode 100644 index fda59c073..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.js +++ /dev/null @@ -1,102 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Alert from 'Components/Alert'; -import Button from 'Components/Link/Button'; -import Link from 'Components/Link/Link'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import AddSpecificationItem from './AddSpecificationItem'; -import styles from './AddSpecificationModalContent.css'; - -class AddSpecificationModalContent extends Component { - - // - // Render - - render() { - const { - isSchemaFetching, - isSchemaPopulated, - schemaError, - schema, - onSpecificationSelect, - onModalClose - } = this.props; - - return ( - - - Add Condition - - - - { - isSchemaFetching && - - } - - { - !isSchemaFetching && !!schemaError && -
- {translate('UnableToAddANewConditionPleaseTryAgain')} -
- } - - { - isSchemaPopulated && !schemaError && -
- - -
- {translate('RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow')} -
-
- {translate('VisitGithubCustomFormatsAphrodite')} - GitHub -
-
- -
- { - schema.map((specification) => { - return ( - - ); - }) - } -
- -
- } -
- - - -
- ); - } -} - -AddSpecificationModalContent.propTypes = { - isSchemaFetching: PropTypes.bool.isRequired, - isSchemaPopulated: PropTypes.bool.isRequired, - schemaError: PropTypes.object, - schema: PropTypes.arrayOf(PropTypes.object).isRequired, - onSpecificationSelect: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default AddSpecificationModalContent; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContentConnector.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContentConnector.js deleted file mode 100644 index 79c992c9a..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContentConnector.js +++ /dev/null @@ -1,70 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchCustomFormatSpecificationSchema, selectCustomFormatSpecificationSchema } from 'Store/Actions/settingsActions'; -import AddSpecificationModalContent from './AddSpecificationModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.customFormatSpecifications, - (specifications) => { - const { - isSchemaFetching, - isSchemaPopulated, - schemaError, - schema - } = specifications; - - return { - isSchemaFetching, - isSchemaPopulated, - schemaError, - schema - }; - } - ); -} - -const mapDispatchToProps = { - fetchCustomFormatSpecificationSchema, - selectCustomFormatSpecificationSchema -}; - -class AddSpecificationModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchCustomFormatSpecificationSchema(); - } - - // - // Listeners - - onSpecificationSelect = ({ implementation, name }) => { - this.props.selectCustomFormatSpecificationSchema({ implementation, presetName: name }); - this.props.onModalClose({ specificationSelected: true }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -AddSpecificationModalContentConnector.propTypes = { - fetchCustomFormatSpecificationSchema: PropTypes.func.isRequired, - selectCustomFormatSpecificationSchema: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(AddSpecificationModalContentConnector); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationPresetMenuItem.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationPresetMenuItem.js deleted file mode 100644 index e007d9e21..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationPresetMenuItem.js +++ /dev/null @@ -1,49 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import MenuItem from 'Components/Menu/MenuItem'; - -class AddSpecificationPresetMenuItem extends Component { - - // - // Listeners - - onPress = () => { - const { - name, - implementation - } = this.props; - - this.props.onPress({ - name, - implementation - }); - } - - // - // Render - - render() { - const { - name, - implementation, - ...otherProps - } = this.props; - - return ( - - {name} - - ); - } -} - -AddSpecificationPresetMenuItem.propTypes = { - name: PropTypes.string.isRequired, - implementation: PropTypes.string.isRequired, - onPress: PropTypes.func.isRequired -}; - -export default AddSpecificationPresetMenuItem; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModal.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModal.js deleted file mode 100644 index b5c287c35..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModal.js +++ /dev/null @@ -1,27 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import EditSpecificationModalContentConnector from './EditSpecificationModalContentConnector'; - -function EditSpecificationModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -EditSpecificationModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditSpecificationModal; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalConnector.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalConnector.js deleted file mode 100644 index 996c49c97..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalConnector.js +++ /dev/null @@ -1,50 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import EditSpecificationModal from './EditSpecificationModal'; - -function createMapDispatchToProps(dispatch, props) { - const section = 'settings.customFormatSpecifications'; - - return { - dispatchClearPendingChanges() { - dispatch(clearPendingChanges({ section })); - } - }; -} - -class EditSpecificationModalConnector extends Component { - - // - // Listeners - - onModalClose = () => { - this.props.dispatchClearPendingChanges(); - this.props.onModalClose(); - } - - // - // Render - - render() { - const { - dispatchClearPendingChanges, - ...otherProps - } = this.props; - - return ( - - ); - } -} - -EditSpecificationModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - dispatchClearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(null, createMapDispatchToProps)(EditSpecificationModalConnector); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.css b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.css deleted file mode 100644 index a2b6014df..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.css +++ /dev/null @@ -1,5 +0,0 @@ -.deleteButton { - composes: button from '~Components/Link/Button.css'; - - margin-right: auto; -} diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.js deleted file mode 100644 index 4ffc82386..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContent.js +++ /dev/null @@ -1,161 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Alert from 'Components/Alert'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import ProviderFieldFormGroup from 'Components/Form/ProviderFieldFormGroup'; -import Button from 'Components/Link/Button'; -import Link from 'Components/Link/Link'; -import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './EditSpecificationModalContent.css'; - -function EditSpecificationModalContent(props) { - const { - advancedSettings, - item, - onInputChange, - onFieldChange, - onCancelPress, - onSavePress, - onDeleteSpecificationPress, - ...otherProps - } = props; - - const { - id, - implementationName, - name, - negate, - required, - fields - } = item; - - return ( - - - {`${id ? 'Edit' : 'Add'} Condition - ${implementationName}`} - - - -
- { - fields && fields.some((x) => x.label === 'Regular Expression') && - -
-
\\^$.|?*+()[{', '\\']) }} /> - {translate('MoreDetails')} {translate('LinkHere')} -
-
- {translate('RegularExpressionsCanBeTested')} - {translate('LinkHere')} -
- - } - - - - Name - - - - - - { - fields && fields.map((field) => { - return ( - - ); - }) - } - - - - Negate - - - - - - - - Required - - - - - - - - { - id && - - } - - - - - {translate('Save')} - - - - ); -} - -EditSpecificationModalContent.propTypes = { - advancedSettings: PropTypes.bool.isRequired, - item: PropTypes.object.isRequired, - onInputChange: PropTypes.func.isRequired, - onFieldChange: PropTypes.func.isRequired, - onCancelPress: PropTypes.func.isRequired, - onSavePress: PropTypes.func.isRequired, - onDeleteSpecificationPress: PropTypes.func -}; - -export default EditSpecificationModalContent; diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContentConnector.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContentConnector.js deleted file mode 100644 index 786245a54..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/EditSpecificationModalContentConnector.js +++ /dev/null @@ -1,78 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { clearCustomFormatSpecificationPending, saveCustomFormatSpecification, setCustomFormatSpecificationFieldValue, setCustomFormatSpecificationValue } from 'Store/Actions/settingsActions'; -import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector'; -import EditSpecificationModalContent from './EditSpecificationModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - createProviderSettingsSelector('customFormatSpecifications'), - (advancedSettings, specification) => { - return { - advancedSettings, - ...specification - }; - } - ); -} - -const mapDispatchToProps = { - setCustomFormatSpecificationValue, - setCustomFormatSpecificationFieldValue, - saveCustomFormatSpecification, - clearCustomFormatSpecificationPending -}; - -class EditSpecificationModalContentConnector extends Component { - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setCustomFormatSpecificationValue({ name, value }); - } - - onFieldChange = ({ name, value }) => { - this.props.setCustomFormatSpecificationFieldValue({ name, value }); - } - - onCancelPress = () => { - this.props.clearCustomFormatSpecificationPending(); - this.props.onModalClose(); - } - - onSavePress = () => { - this.props.saveCustomFormatSpecification({ id: this.props.id }); - this.props.onModalClose(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditSpecificationModalContentConnector.propTypes = { - id: PropTypes.number, - item: PropTypes.object.isRequired, - setCustomFormatSpecificationValue: PropTypes.func.isRequired, - setCustomFormatSpecificationFieldValue: PropTypes.func.isRequired, - clearCustomFormatSpecificationPending: PropTypes.func.isRequired, - saveCustomFormatSpecification: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(EditSpecificationModalContentConnector); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.css b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.css deleted file mode 100644 index f05c942b0..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.css +++ /dev/null @@ -1,38 +0,0 @@ -.customFormat { - composes: card from '~Components/Card.css'; - - width: 300px; -} - -.nameContainer { - display: flex; - justify-content: space-between; -} - -.name { - @add-mixin truncate; - - margin-bottom: 20px; - font-weight: 300; - font-size: 24px; -} - -.cloneButton { - composes: button from '~Components/Link/IconButton.css'; - - height: 36px; -} - -.labels { - display: flex; - flex-wrap: wrap; - margin-top: 5px; - pointer-events: all; -} - -.tooltipLabel { - composes: label from '~Components/Label.css'; - - margin: 0; - border: none; -} diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.js deleted file mode 100644 index 41dc827c3..000000000 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/Specification.js +++ /dev/null @@ -1,146 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import Label from 'Components/Label'; -import IconButton from 'Components/Link/IconButton'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import { icons, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditSpecificationModalConnector from './EditSpecificationModal'; -import styles from './Specification.css'; - -class Specification extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditSpecificationModalOpen: false, - isDeleteSpecificationModalOpen: false - }; - } - - // - // Listeners - - onEditSpecificationPress = () => { - this.setState({ isEditSpecificationModalOpen: true }); - } - - onEditSpecificationModalClose = () => { - this.setState({ isEditSpecificationModalOpen: false }); - } - - onDeleteSpecificationPress = () => { - this.setState({ - isEditSpecificationModalOpen: false, - isDeleteSpecificationModalOpen: true - }); - } - - onDeleteSpecificationModalClose = () => { - this.setState({ isDeleteSpecificationModalOpen: false }); - } - - onCloneSpecificationPress = () => { - this.props.onCloneSpecificationPress(this.props.id); - } - - onConfirmDeleteSpecification = () => { - this.props.onConfirmDeleteSpecification(this.props.id); - } - - // - // Lifecycle - - render() { - const { - id, - implementationName, - name, - required, - negate - } = this.props; - - return ( - -
-
- {name} -
- - -
- -
- - - { - negate && - - } - - { - required && - - } -
- - - - -
- Are you sure you want to delete format tag '{name}'? -
-
- } - confirmLabel={translate('Delete')} - onConfirm={this.onConfirmDeleteSpecification} - onCancel={this.onDeleteSpecificationModalClose} - /> - - ); - } -} - -Specification.propTypes = { - id: PropTypes.number.isRequired, - implementation: PropTypes.string.isRequired, - implementationName: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - negate: PropTypes.bool.isRequired, - required: PropTypes.bool.isRequired, - fields: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteSpecification: PropTypes.func.isRequired, - onCloneSpecificationPress: PropTypes.func.isRequired -}; - -export default Specification; diff --git a/frontend/src/Settings/DownloadClients/DownloadClientSettings.js b/frontend/src/Settings/DownloadClients/DownloadClientSettings.js deleted file mode 100644 index 5df9318bb..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClientSettings.js +++ /dev/null @@ -1,101 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component, Fragment } from 'react'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton'; -import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator'; -import { icons } from 'Helpers/Props'; -import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; -import translate from 'Utilities/String/translate'; -import DownloadClientsConnector from './DownloadClients/DownloadClientsConnector'; -import DownloadClientOptionsConnector from './Options/DownloadClientOptionsConnector'; -import RemotePathMappingsConnector from './RemotePathMappings/RemotePathMappingsConnector'; - -class DownloadClientSettings extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this._saveCallback = null; - - this.state = { - isSaving: false, - hasPendingChanges: false - }; - } - - // - // Listeners - - onChildMounted = (saveCallback) => { - this._saveCallback = saveCallback; - } - - onChildStateChange = (payload) => { - this.setState(payload); - } - - onSavePress = () => { - if (this._saveCallback) { - this._saveCallback(); - } - } - - // - // Render - - render() { - const { - isTestingAll, - dispatchTestAllDownloadClients - } = this.props; - - const { - isSaving, - hasPendingChanges - } = this.state; - - return ( - - - - - - - } - onSavePress={this.onSavePress} - /> - - - - - - - - - - ); - } -} - -DownloadClientSettings.propTypes = { - isTestingAll: PropTypes.bool.isRequired, - dispatchTestAllDownloadClients: PropTypes.func.isRequired -}; - -export default DownloadClientSettings; diff --git a/frontend/src/Settings/DownloadClients/DownloadClientSettingsConnector.js b/frontend/src/Settings/DownloadClients/DownloadClientSettingsConnector.js deleted file mode 100644 index 5e1a8a1ca..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClientSettingsConnector.js +++ /dev/null @@ -1,21 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { testAllDownloadClients } from 'Store/Actions/settingsActions'; -import DownloadClientSettings from './DownloadClientSettings'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.downloadClients.isTestingAll, - (isTestingAll) => { - return { - isTestingAll - }; - } - ); -} - -const mapDispatchToProps = { - dispatchTestAllDownloadClients: testAllDownloadClients -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(DownloadClientSettings); diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientItem.css b/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientItem.css deleted file mode 100644 index a3d90cc5a..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientItem.css +++ /dev/null @@ -1,44 +0,0 @@ -.downloadClient { - composes: card from '~Components/Card.css'; - - position: relative; - width: 300px; - height: 100px; -} - -.underlay { - @add-mixin cover; -} - -.overlay { - @add-mixin linkOverlay; - - padding: 10px; -} - -.name { - text-align: center; - font-weight: lighter; - font-size: 24px; -} - -.actions { - margin-top: 20px; - text-align: right; -} - -.presetsMenu { - composes: menu from '~Components/Menu/Menu.css'; - - display: inline-block; - margin: 0 5px; -} - -.presetsMenuButton { - composes: button from '~Components/Link/Button.css'; - - &::after { - margin-left: 5px; - content: '\25BE'; - } -} diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientItem.js b/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientItem.js deleted file mode 100644 index f85201a46..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientItem.js +++ /dev/null @@ -1,111 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Button from 'Components/Link/Button'; -import Link from 'Components/Link/Link'; -import Menu from 'Components/Menu/Menu'; -import MenuContent from 'Components/Menu/MenuContent'; -import { sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import AddDownloadClientPresetMenuItem from './AddDownloadClientPresetMenuItem'; -import styles from './AddDownloadClientItem.css'; - -class AddDownloadClientItem extends Component { - - // - // Listeners - - onDownloadClientSelect = () => { - const { - implementation - } = this.props; - - this.props.onDownloadClientSelect({ implementation }); - } - - // - // Render - - render() { - const { - implementation, - implementationName, - infoLink, - presets, - onDownloadClientSelect - } = this.props; - - const hasPresets = !!presets && !!presets.length; - - return ( -
- - -
-
- {implementationName} -
- -
- { - hasPresets && - - - - - - - - { - presets.map((preset) => { - return ( - - ); - }) - } - - - - } - - -
-
-
- ); - } -} - -AddDownloadClientItem.propTypes = { - implementation: PropTypes.string.isRequired, - implementationName: PropTypes.string.isRequired, - infoLink: PropTypes.string.isRequired, - presets: PropTypes.arrayOf(PropTypes.object), - onDownloadClientSelect: PropTypes.func.isRequired -}; - -export default AddDownloadClientItem; diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModal.js b/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModal.js deleted file mode 100644 index 0c21e7dbd..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModal.js +++ /dev/null @@ -1,25 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import AddDownloadClientModalContentConnector from './AddDownloadClientModalContentConnector'; - -function AddDownloadClientModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -AddDownloadClientModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default AddDownloadClientModal; diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContent.css b/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContent.css deleted file mode 100644 index b4d5c6787..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContent.css +++ /dev/null @@ -1,5 +0,0 @@ -.downloadClients { - display: flex; - justify-content: center; - flex-wrap: wrap; -} diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContent.js b/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContent.js deleted file mode 100644 index 2fcff25bd..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContent.js +++ /dev/null @@ -1,122 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Alert from 'Components/Alert'; -import FieldSet from 'Components/FieldSet'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import AddDownloadClientItem from './AddDownloadClientItem'; -import styles from './AddDownloadClientModalContent.css'; - -class AddDownloadClientModalContent extends Component { - - // - // Render - - render() { - const { - isSchemaFetching, - isSchemaPopulated, - schemaError, - usenetDownloadClients, - torrentDownloadClients, - onDownloadClientSelect, - onModalClose - } = this.props; - - return ( - - - Add DownloadClient - - - - { - isSchemaFetching && - - } - - { - !isSchemaFetching && !!schemaError && -
- {translate('UnableToAddANewDownloadClientPleaseTryAgain')} -
- } - - { - isSchemaPopulated && !schemaError && -
- - -
- {translate('RadarrSupportsAnyDownloadClient')} -
-
- {translate('ForMoreInformationOnTheIndividualDownloadClients')} -
-
- -
-
- { - usenetDownloadClients.map((downloadClient) => { - return ( - - ); - }) - } -
-
- -
-
- { - torrentDownloadClients.map((downloadClient) => { - return ( - - ); - }) - } -
-
-
- } -
- - - -
- ); - } -} - -AddDownloadClientModalContent.propTypes = { - isSchemaFetching: PropTypes.bool.isRequired, - isSchemaPopulated: PropTypes.bool.isRequired, - schemaError: PropTypes.object, - usenetDownloadClients: PropTypes.arrayOf(PropTypes.object).isRequired, - torrentDownloadClients: PropTypes.arrayOf(PropTypes.object).isRequired, - onDownloadClientSelect: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default AddDownloadClientModalContent; diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContentConnector.js b/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContentConnector.js deleted file mode 100644 index 99d5c4f19..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContentConnector.js +++ /dev/null @@ -1,75 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchDownloadClientSchema, selectDownloadClientSchema } from 'Store/Actions/settingsActions'; -import AddDownloadClientModalContent from './AddDownloadClientModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.downloadClients, - (downloadClients) => { - const { - isSchemaFetching, - isSchemaPopulated, - schemaError, - schema - } = downloadClients; - - const usenetDownloadClients = _.filter(schema, { protocol: 'usenet' }); - const torrentDownloadClients = _.filter(schema, { protocol: 'torrent' }); - - return { - isSchemaFetching, - isSchemaPopulated, - schemaError, - usenetDownloadClients, - torrentDownloadClients - }; - } - ); -} - -const mapDispatchToProps = { - fetchDownloadClientSchema, - selectDownloadClientSchema -}; - -class AddDownloadClientModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchDownloadClientSchema(); - } - - // - // Listeners - - onDownloadClientSelect = ({ implementation }) => { - this.props.selectDownloadClientSchema({ implementation }); - this.props.onModalClose({ downloadClientSelected: true }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -AddDownloadClientModalContentConnector.propTypes = { - fetchDownloadClientSchema: PropTypes.func.isRequired, - selectDownloadClientSchema: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(AddDownloadClientModalContentConnector); diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientPresetMenuItem.js b/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientPresetMenuItem.js deleted file mode 100644 index f356f8140..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientPresetMenuItem.js +++ /dev/null @@ -1,49 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import MenuItem from 'Components/Menu/MenuItem'; - -class AddDownloadClientPresetMenuItem extends Component { - - // - // Listeners - - onPress = () => { - const { - name, - implementation - } = this.props; - - this.props.onPress({ - name, - implementation - }); - } - - // - // Render - - render() { - const { - name, - implementation, - ...otherProps - } = this.props; - - return ( - - {name} - - ); - } -} - -AddDownloadClientPresetMenuItem.propTypes = { - name: PropTypes.string.isRequired, - implementation: PropTypes.string.isRequired, - onPress: PropTypes.func.isRequired -}; - -export default AddDownloadClientPresetMenuItem; diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.css b/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.css deleted file mode 100644 index 8eea80383..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.css +++ /dev/null @@ -1,19 +0,0 @@ -.downloadClient { - composes: card from '~Components/Card.css'; - - width: 290px; -} - -.name { - @add-mixin truncate; - - margin-bottom: 20px; - font-weight: 300; - font-size: 24px; -} - -.enabled { - display: flex; - flex-wrap: wrap; - margin-top: 5px; -} diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.js b/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.js deleted file mode 100644 index 25f1ae6cf..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.js +++ /dev/null @@ -1,126 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import Label from 'Components/Label'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import { kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditDownloadClientModalConnector from './EditDownloadClientModalConnector'; -import styles from './DownloadClient.css'; - -class DownloadClient extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditDownloadClientModalOpen: false, - isDeleteDownloadClientModalOpen: false - }; - } - - // - // Listeners - - onEditDownloadClientPress = () => { - this.setState({ isEditDownloadClientModalOpen: true }); - } - - onEditDownloadClientModalClose = () => { - this.setState({ isEditDownloadClientModalOpen: false }); - } - - onDeleteDownloadClientPress = () => { - this.setState({ - isEditDownloadClientModalOpen: false, - isDeleteDownloadClientModalOpen: true - }); - } - - onDeleteDownloadClientModalClose= () => { - this.setState({ isDeleteDownloadClientModalOpen: false }); - } - - onConfirmDeleteDownloadClient = () => { - this.props.onConfirmDeleteDownloadClient(this.props.id); - } - - // - // Render - - render() { - const { - id, - name, - enable, - priority - } = this.props; - - return ( - -
- {name} -
- -
- { - enable ? - : - - } - - { - priority > 1 && - - } -
- - - - -
- ); - } -} - -DownloadClient.propTypes = { - id: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - enable: PropTypes.bool.isRequired, - priority: PropTypes.number.isRequired, - onConfirmDeleteDownloadClient: PropTypes.func.isRequired -}; - -export default DownloadClient; diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClients.css b/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClients.css deleted file mode 100644 index 81b4f1510..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClients.css +++ /dev/null @@ -1,20 +0,0 @@ -.downloadClients { - display: flex; - flex-wrap: wrap; -} - -.addDownloadClient { - composes: downloadClient from '~./DownloadClient.css'; - - background-color: $cardAlternateBackgroundColor; - color: $gray; - text-align: center; -} - -.center { - display: inline-block; - padding: 5px 20px 0; - border: 1px solid $borderColor; - border-radius: 4px; - background-color: $white; -} diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClients.js b/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClients.js deleted file mode 100644 index 52f211f4a..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClients.js +++ /dev/null @@ -1,115 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import FieldSet from 'Components/FieldSet'; -import Icon from 'Components/Icon'; -import PageSectionContent from 'Components/Page/PageSectionContent'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import AddDownloadClientModal from './AddDownloadClientModal'; -import DownloadClient from './DownloadClient'; -import EditDownloadClientModalConnector from './EditDownloadClientModalConnector'; -import styles from './DownloadClients.css'; - -class DownloadClients extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isAddDownloadClientModalOpen: false, - isEditDownloadClientModalOpen: false - }; - } - - // - // Listeners - - onAddDownloadClientPress = () => { - this.setState({ isAddDownloadClientModalOpen: true }); - } - - onAddDownloadClientModalClose = ({ downloadClientSelected = false } = {}) => { - this.setState({ - isAddDownloadClientModalOpen: false, - isEditDownloadClientModalOpen: downloadClientSelected - }); - } - - onEditDownloadClientModalClose = () => { - this.setState({ isEditDownloadClientModalOpen: false }); - } - - // - // Render - - render() { - const { - items, - onConfirmDeleteDownloadClient, - ...otherProps - } = this.props; - - const { - isAddDownloadClientModalOpen, - isEditDownloadClientModalOpen - } = this.state; - - return ( -
- -
- { - items.map((item) => { - return ( - - ); - }) - } - - -
- -
-
-
- - - - -
-
- ); - } -} - -DownloadClients.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteDownloadClient: PropTypes.func.isRequired -}; - -export default DownloadClients; diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClientsConnector.js b/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClientsConnector.js deleted file mode 100644 index ed8ddffc9..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/DownloadClientsConnector.js +++ /dev/null @@ -1,56 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { deleteDownloadClient, fetchDownloadClients } from 'Store/Actions/settingsActions'; -import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector'; -import sortByName from 'Utilities/Array/sortByName'; -import DownloadClients from './DownloadClients'; - -function createMapStateToProps() { - return createSelector( - createSortedSectionSelector('settings.downloadClients', sortByName), - (downloadClients) => downloadClients - ); -} - -const mapDispatchToProps = { - fetchDownloadClients, - deleteDownloadClient -}; - -class DownloadClientsConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchDownloadClients(); - } - - // - // Listeners - - onConfirmDeleteDownloadClient = (id) => { - this.props.deleteDownloadClient({ id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -DownloadClientsConnector.propTypes = { - fetchDownloadClients: PropTypes.func.isRequired, - deleteDownloadClient: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(DownloadClientsConnector); diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModal.js b/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModal.js deleted file mode 100644 index 4fd6b607d..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModal.js +++ /dev/null @@ -1,27 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import EditDownloadClientModalContentConnector from './EditDownloadClientModalContentConnector'; - -function EditDownloadClientModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -EditDownloadClientModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditDownloadClientModal; diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalConnector.js b/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalConnector.js deleted file mode 100644 index e6b06974d..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalConnector.js +++ /dev/null @@ -1,65 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import { cancelSaveDownloadClient, cancelTestDownloadClient } from 'Store/Actions/settingsActions'; -import EditDownloadClientModal from './EditDownloadClientModal'; - -function createMapDispatchToProps(dispatch, props) { - const section = 'settings.downloadClients'; - - return { - dispatchClearPendingChanges() { - dispatch(clearPendingChanges({ section })); - }, - - dispatchCancelTestDownloadClient() { - dispatch(cancelTestDownloadClient({ section })); - }, - - dispatchCancelSaveDownloadClient() { - dispatch(cancelSaveDownloadClient({ section })); - } - }; -} - -class EditDownloadClientModalConnector extends Component { - - // - // Listeners - - onModalClose = () => { - this.props.dispatchClearPendingChanges(); - this.props.dispatchCancelTestDownloadClient(); - this.props.dispatchCancelSaveDownloadClient(); - this.props.onModalClose(); - } - - // - // Render - - render() { - const { - dispatchClearPendingChanges, - dispatchCancelTestDownloadClient, - dispatchCancelSaveDownloadClient, - ...otherProps - } = this.props; - - return ( - - ); - } -} - -EditDownloadClientModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - dispatchClearPendingChanges: PropTypes.func.isRequired, - dispatchCancelTestDownloadClient: PropTypes.func.isRequired, - dispatchCancelSaveDownloadClient: PropTypes.func.isRequired -}; - -export default connect(null, createMapDispatchToProps)(EditDownloadClientModalConnector); diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.css b/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.css deleted file mode 100644 index 8e1c16507..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.css +++ /dev/null @@ -1,11 +0,0 @@ -.deleteButton { - composes: button from '~Components/Link/Button.css'; - - margin-right: auto; -} - -.message { - composes: alert from '~Components/Alert.css'; - - margin-bottom: 30px; -} diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.js b/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.js deleted file mode 100644 index d32301ee8..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.js +++ /dev/null @@ -1,197 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Alert from 'Components/Alert'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import ProviderFieldFormGroup from 'Components/Form/ProviderFieldFormGroup'; -import Button from 'Components/Link/Button'; -import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './EditDownloadClientModalContent.css'; - -class EditDownloadClientModalContent extends Component { - - // - // Render - - render() { - const { - advancedSettings, - isFetching, - error, - isSaving, - isTesting, - saveError, - item, - onInputChange, - onFieldChange, - onModalClose, - onSavePress, - onTestPress, - onDeleteDownloadClientPress, - ...otherProps - } = this.props; - - const { - id, - implementationName, - name, - enable, - priority, - fields, - message - } = item; - - return ( - - - {`${id ? 'Edit' : 'Add'} Download Client - ${implementationName}`} - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToAddANewDownloadClientPleaseTryAgain')} -
- } - - { - !isFetching && !error && -
- { - !!message && - - {message.value.message} - - } - - - {translate('Name')} - - - - - - {translate('Enable')} - - - - - { - fields.map((field) => { - return ( - - ); - }) - } - - - {translate('ClientPriority')} - - - - - - } -
- - { - id && - - } - - - {translate('Test')} - - - - - - {translate('Save')} - - -
- ); - } -} - -EditDownloadClientModalContent.propTypes = { - advancedSettings: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - isTesting: PropTypes.bool.isRequired, - item: PropTypes.object.isRequired, - onInputChange: PropTypes.func.isRequired, - onFieldChange: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired, - onSavePress: PropTypes.func.isRequired, - onTestPress: PropTypes.func.isRequired, - onDeleteDownloadClientPress: PropTypes.func -}; - -export default EditDownloadClientModalContent; diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContentConnector.js b/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContentConnector.js deleted file mode 100644 index 864d83cfe..000000000 --- a/frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContentConnector.js +++ /dev/null @@ -1,88 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { saveDownloadClient, setDownloadClientFieldValue, setDownloadClientValue, testDownloadClient } from 'Store/Actions/settingsActions'; -import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector'; -import EditDownloadClientModalContent from './EditDownloadClientModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - createProviderSettingsSelector('downloadClients'), - (advancedSettings, downloadClient) => { - return { - advancedSettings, - ...downloadClient - }; - } - ); -} - -const mapDispatchToProps = { - setDownloadClientValue, - setDownloadClientFieldValue, - saveDownloadClient, - testDownloadClient -}; - -class EditDownloadClientModalContentConnector extends Component { - - // - // Lifecycle - - componentDidUpdate(prevProps, prevState) { - if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) { - this.props.onModalClose(); - } - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setDownloadClientValue({ name, value }); - } - - onFieldChange = ({ name, value }) => { - this.props.setDownloadClientFieldValue({ name, value }); - } - - onSavePress = () => { - this.props.saveDownloadClient({ id: this.props.id }); - } - - onTestPress = () => { - this.props.testDownloadClient({ id: this.props.id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditDownloadClientModalContentConnector.propTypes = { - id: PropTypes.number, - isFetching: PropTypes.bool.isRequired, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - setDownloadClientValue: PropTypes.func.isRequired, - setDownloadClientFieldValue: PropTypes.func.isRequired, - saveDownloadClient: PropTypes.func.isRequired, - testDownloadClient: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(EditDownloadClientModalContentConnector); diff --git a/frontend/src/Settings/DownloadClients/Options/DownloadClientOptions.js b/frontend/src/Settings/DownloadClients/Options/DownloadClientOptions.js deleted file mode 100644 index 35252c013..000000000 --- a/frontend/src/Settings/DownloadClients/Options/DownloadClientOptions.js +++ /dev/null @@ -1,138 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import FieldSet from 'Components/FieldSet'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import { inputTypes, sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -function DownloadClientOptions(props) { - const { - advancedSettings, - isFetching, - error, - settings, - hasSettings, - onInputChange - } = props; - - return ( -
- { - isFetching && - - } - - { - !isFetching && error && -
- {translate('UnableToLoadDownloadClientOptions')} -
- } - - { - hasSettings && !isFetching && !error && -
-
-
- - {translate('Enable')} - - - - - - {translate('Remove')} - - - - - - {translate('CheckForFinishedDownloadsInterval')} - - - -
-
- -
-
- - {translate('Redownload')} - - - - - - {translate('Remove')} - - - -
-
-
- } -
- ); -} - -DownloadClientOptions.propTypes = { - advancedSettings: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - settings: PropTypes.object.isRequired, - hasSettings: PropTypes.bool.isRequired, - onInputChange: PropTypes.func.isRequired -}; - -export default DownloadClientOptions; diff --git a/frontend/src/Settings/DownloadClients/Options/DownloadClientOptionsConnector.js b/frontend/src/Settings/DownloadClients/Options/DownloadClientOptionsConnector.js deleted file mode 100644 index 34ec88253..000000000 --- a/frontend/src/Settings/DownloadClients/Options/DownloadClientOptionsConnector.js +++ /dev/null @@ -1,101 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import { fetchDownloadClientOptions, saveDownloadClientOptions, setDownloadClientOptionsValue } from 'Store/Actions/settingsActions'; -import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector'; -import DownloadClientOptions from './DownloadClientOptions'; - -const SECTION = 'downloadClientOptions'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - createSettingsSectionSelector(SECTION), - (advancedSettings, sectionSettings) => { - return { - advancedSettings, - ...sectionSettings - }; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchDownloadClientOptions: fetchDownloadClientOptions, - dispatchSetDownloadClientOptionsValue: setDownloadClientOptionsValue, - dispatchSaveDownloadClientOptions: saveDownloadClientOptions, - dispatchClearPendingChanges: clearPendingChanges -}; - -class DownloadClientOptionsConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - dispatchFetchDownloadClientOptions, - dispatchSaveDownloadClientOptions, - onChildMounted - } = this.props; - - dispatchFetchDownloadClientOptions(); - onChildMounted(dispatchSaveDownloadClientOptions); - } - - componentDidUpdate(prevProps) { - const { - hasPendingChanges, - isSaving, - onChildStateChange - } = this.props; - - if ( - prevProps.isSaving !== isSaving || - prevProps.hasPendingChanges !== hasPendingChanges - ) { - onChildStateChange({ - isSaving, - hasPendingChanges - }); - } - } - - componentWillUnmount() { - this.props.dispatchClearPendingChanges({ section: `settings.${SECTION}` }); - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.dispatchSetDownloadClientOptionsValue({ name, value }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -DownloadClientOptionsConnector.propTypes = { - isSaving: PropTypes.bool.isRequired, - hasPendingChanges: PropTypes.bool.isRequired, - dispatchFetchDownloadClientOptions: PropTypes.func.isRequired, - dispatchSetDownloadClientOptionsValue: PropTypes.func.isRequired, - dispatchSaveDownloadClientOptions: PropTypes.func.isRequired, - dispatchClearPendingChanges: PropTypes.func.isRequired, - onChildMounted: PropTypes.func.isRequired, - onChildStateChange: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(DownloadClientOptionsConnector); diff --git a/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModal.js b/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModal.js deleted file mode 100644 index 9016f14e7..000000000 --- a/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModal.js +++ /dev/null @@ -1,27 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import EditRemotePathMappingModalContentConnector from './EditRemotePathMappingModalContentConnector'; - -function EditRemotePathMappingModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -EditRemotePathMappingModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditRemotePathMappingModal; diff --git a/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalConnector.js b/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalConnector.js deleted file mode 100644 index 94172429d..000000000 --- a/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalConnector.js +++ /dev/null @@ -1,43 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import EditRemotePathMappingModal from './EditRemotePathMappingModal'; - -function mapStateToProps() { - return {}; -} - -const mapDispatchToProps = { - clearPendingChanges -}; - -class EditRemotePathMappingModalConnector extends Component { - - // - // Listeners - - onModalClose = () => { - this.props.clearPendingChanges({ section: 'settings.remotePathMappings' }); - this.props.onModalClose(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditRemotePathMappingModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(mapStateToProps, mapDispatchToProps)(EditRemotePathMappingModalConnector); diff --git a/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContent.css b/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContent.css deleted file mode 100644 index 97e132552..000000000 --- a/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContent.css +++ /dev/null @@ -1,11 +0,0 @@ -.body { - composes: modalBody from '~Components/Modal/ModalBody.css'; - - flex: 1 1 430px; -} - -.deleteButton { - composes: button from '~Components/Link/Button.css'; - - margin-right: auto; -} diff --git a/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContent.js b/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContent.js deleted file mode 100644 index 228633255..000000000 --- a/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContent.js +++ /dev/null @@ -1,153 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds } from 'Helpers/Props'; -import { stringSettingShape } from 'Helpers/Props/Shapes/settingShape'; -import translate from 'Utilities/String/translate'; -import styles from './EditRemotePathMappingModalContent.css'; - -function EditRemotePathMappingModalContent(props) { - const { - id, - isFetching, - error, - isSaving, - saveError, - item, - downloadClientHosts, - onInputChange, - onSavePress, - onModalClose, - onDeleteRemotePathMappingPress, - ...otherProps - } = props; - - const { - host, - remotePath, - localPath - } = item; - - return ( - - - {id ? translate('EditRemotePathMapping') : translate('AddRemotePathMapping')} - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToAddANewRemotePathMappingPleaseTryAgain')} -
- } - - { - !isFetching && !error && -
- - {translate('Host')} - - - - - - {translate('SettingsRemotePathMappingRemotePath')} - - - - - - {translate('SettingsRemotePathMappingLocalPath')} - - - -
- } -
- - - { - id && - - } - - - - - {translate('Save')} - - -
- ); -} - -const remotePathMappingShape = { - host: PropTypes.shape(stringSettingShape).isRequired, - remotePath: PropTypes.shape(stringSettingShape).isRequired, - localPath: PropTypes.shape(stringSettingShape).isRequired -}; - -EditRemotePathMappingModalContent.propTypes = { - id: PropTypes.number, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.shape(remotePathMappingShape).isRequired, - downloadClientHosts: PropTypes.arrayOf(PropTypes.object).isRequired, - onInputChange: PropTypes.func.isRequired, - onSavePress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired, - onDeleteRemotePathMappingPress: PropTypes.func -}; - -export default EditRemotePathMappingModalContent; diff --git a/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContentConnector.js b/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContentConnector.js deleted file mode 100644 index 5854f17b9..000000000 --- a/frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContentConnector.js +++ /dev/null @@ -1,148 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { saveRemotePathMapping, setRemotePathMappingValue } from 'Store/Actions/settingsActions'; -import selectSettings from 'Store/Selectors/selectSettings'; -import EditRemotePathMappingModalContent from './EditRemotePathMappingModalContent'; - -const newRemotePathMapping = { - host: '', - remotePath: '', - localPath: '' -}; - -const selectDownloadClientHosts = createSelector( - (state) => state.settings.downloadClients.items, - (downloadClients) => { - const hosts = downloadClients.reduce((acc, downloadClient) => { - const name = downloadClient.name; - const host = downloadClient.fields.find((field) => { - return field.name === 'host'; - }); - - if (host) { - const group = acc[host.value] = acc[host.value] || []; - group.push(name); - } - - return acc; - }, {}); - - return Object.keys(hosts).map((host) => { - return { - key: host, - value: host, - hint: `${hosts[host].join(', ')}` - }; - }); - } -); - -function createRemotePathMappingSelector() { - return createSelector( - (state, { id }) => id, - (state) => state.settings.remotePathMappings, - selectDownloadClientHosts, - (id, remotePathMappings, downloadClientHosts) => { - const { - isFetching, - error, - isSaving, - saveError, - pendingChanges, - items - } = remotePathMappings; - - const mapping = id ? _.find(items, { id }) : newRemotePathMapping; - const settings = selectSettings(mapping, pendingChanges, saveError); - - return { - id, - isFetching, - error, - isSaving, - saveError, - item: settings.settings, - ...settings, - downloadClientHosts - }; - } - ); -} - -function createMapStateToProps() { - return createSelector( - createRemotePathMappingSelector(), - (remotePathMapping) => { - return { - ...remotePathMapping - }; - } - ); -} - -const mapDispatchToProps = { - dispatchSetRemotePathMappingValue: setRemotePathMappingValue, - dispatchSaveRemotePathMapping: saveRemotePathMapping -}; - -class EditRemotePathMappingModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - if (!this.props.id) { - Object.keys(newRemotePathMapping).forEach((name) => { - this.props.dispatchSetRemotePathMappingValue({ - name, - value: newRemotePathMapping[name] - }); - }); - } - } - - componentDidUpdate(prevProps, prevState) { - if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) { - this.props.onModalClose(); - } - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.dispatchSetRemotePathMappingValue({ name, value }); - } - - onSavePress = () => { - this.props.dispatchSaveRemotePathMapping({ id: this.props.id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditRemotePathMappingModalContentConnector.propTypes = { - id: PropTypes.number, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - dispatchSetRemotePathMappingValue: PropTypes.func.isRequired, - dispatchSaveRemotePathMapping: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(EditRemotePathMappingModalContentConnector); diff --git a/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMapping.css b/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMapping.css deleted file mode 100644 index a79efda26..000000000 --- a/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMapping.css +++ /dev/null @@ -1,23 +0,0 @@ -.remotePathMapping { - display: flex; - align-items: stretch; - margin-bottom: 10px; - height: 30px; - border-bottom: 1px solid $borderColor; - line-height: 30px; -} - -.host { - flex: 0 0 300px; -} - -.path { - flex: 0 0 400px; -} - -.actions { - display: flex; - justify-content: flex-end; - flex: 1 0 auto; - padding-right: 10px; -} diff --git a/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMapping.js b/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMapping.js deleted file mode 100644 index 78011dccd..000000000 --- a/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMapping.js +++ /dev/null @@ -1,115 +0,0 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Icon from 'Components/Icon'; -import Link from 'Components/Link/Link'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import { icons, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditRemotePathMappingModalConnector from './EditRemotePathMappingModalConnector'; -import styles from './RemotePathMapping.css'; - -class RemotePathMapping extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditRemotePathMappingModalOpen: false, - isDeleteRemotePathMappingModalOpen: false - }; - } - - // - // Listeners - - onEditRemotePathMappingPress = () => { - this.setState({ isEditRemotePathMappingModalOpen: true }); - } - - onEditRemotePathMappingModalClose = () => { - this.setState({ isEditRemotePathMappingModalOpen: false }); - } - - onDeleteRemotePathMappingPress = () => { - this.setState({ - isEditRemotePathMappingModalOpen: false, - isDeleteRemotePathMappingModalOpen: true - }); - } - - onDeleteRemotePathMappingModalClose = () => { - this.setState({ isDeleteRemotePathMappingModalOpen: false }); - } - - onConfirmDeleteRemotePathMapping = () => { - this.props.onConfirmDeleteRemotePathMapping(this.props.id); - } - - // - // Render - - render() { - const { - id, - host, - remotePath, - localPath - } = this.props; - - return ( -
-
{host}
-
{remotePath}
-
{localPath}
- -
- - - -
- - - - -
- ); - } -} - -RemotePathMapping.propTypes = { - id: PropTypes.number.isRequired, - host: PropTypes.string.isRequired, - remotePath: PropTypes.string.isRequired, - localPath: PropTypes.string.isRequired, - onConfirmDeleteRemotePathMapping: PropTypes.func.isRequired -}; - -RemotePathMapping.defaultProps = { - // The drag preview will not connect the drag handle. - connectDragSource: (node) => node -}; - -export default RemotePathMapping; diff --git a/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappings.css b/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappings.css deleted file mode 100644 index 4ef9dcb0f..000000000 --- a/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappings.css +++ /dev/null @@ -1,23 +0,0 @@ -.remotePathMappingsHeader { - display: flex; - margin-bottom: 10px; - font-weight: bold; -} - -.host { - flex: 0 0 300px; -} - -.path { - flex: 0 0 400px; -} - -.addRemotePathMapping { - display: flex; - justify-content: flex-end; - padding-right: 10px; -} - -.addButton { - text-align: center; -} diff --git a/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappings.js b/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappings.js deleted file mode 100644 index 2f3f7782e..000000000 --- a/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappings.js +++ /dev/null @@ -1,101 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FieldSet from 'Components/FieldSet'; -import Icon from 'Components/Icon'; -import Link from 'Components/Link/Link'; -import PageSectionContent from 'Components/Page/PageSectionContent'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditRemotePathMappingModalConnector from './EditRemotePathMappingModalConnector'; -import RemotePathMapping from './RemotePathMapping'; -import styles from './RemotePathMappings.css'; - -class RemotePathMappings extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isAddRemotePathMappingModalOpen: false - }; - } - - // - // Listeners - - onAddRemotePathMappingPress = () => { - this.setState({ isAddRemotePathMappingModalOpen: true }); - } - - onModalClose = () => { - this.setState({ isAddRemotePathMappingModalOpen: false }); - } - - // - // Render - - render() { - const { - items, - onConfirmDeleteRemotePathMapping, - ...otherProps - } = this.props; - - return ( -
- -
-
Host
-
Remote Path
-
Local Path
-
- -
- { - items.map((item, index) => { - return ( - - ); - }) - } -
- -
- - - -
- - -
-
- ); - } -} - -RemotePathMappings.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteRemotePathMapping: PropTypes.func.isRequired -}; - -export default RemotePathMappings; diff --git a/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappingsConnector.js b/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappingsConnector.js deleted file mode 100644 index eabdae228..000000000 --- a/frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappingsConnector.js +++ /dev/null @@ -1,59 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { deleteRemotePathMapping, fetchRemotePathMappings } from 'Store/Actions/settingsActions'; -import RemotePathMappings from './RemotePathMappings'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.remotePathMappings, - (remotePathMappings) => { - return { - ...remotePathMappings - }; - } - ); -} - -const mapDispatchToProps = { - fetchRemotePathMappings, - deleteRemotePathMapping -}; - -class RemotePathMappingsConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchRemotePathMappings(); - } - - // - // Listeners - - onConfirmDeleteRemotePathMapping = (id) => { - this.props.deleteRemotePathMapping({ id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -RemotePathMappingsConnector.propTypes = { - fetchRemotePathMappings: PropTypes.func.isRequired, - deleteRemotePathMapping: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(RemotePathMappingsConnector); diff --git a/frontend/src/Settings/General/GeneralSettings.js b/frontend/src/Settings/General/GeneralSettings.js index 263ddef73..1c2dda024 100644 --- a/frontend/src/Settings/General/GeneralSettings.js +++ b/frontend/src/Settings/General/GeneralSettings.js @@ -187,7 +187,7 @@ class GeneralSettings extends Component { - - ); diff --git a/frontend/src/Settings/Indexers/Indexers/AddIndexerModalContent.js b/frontend/src/Settings/Indexers/Indexers/AddIndexerModalContent.js index 74873bb49..6447246d4 100644 --- a/frontend/src/Settings/Indexers/Indexers/AddIndexerModalContent.js +++ b/frontend/src/Settings/Indexers/Indexers/AddIndexerModalContent.js @@ -54,7 +54,7 @@ class AddIndexerModalContent extends Component {
- {translate('RadarrSupportsAnyIndexer')} + {translate('ProwlarrSupportsAnyIndexer')}
{translate('ForMoreInformationOnTheIndividualIndexers')} diff --git a/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModal.js b/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModal.js deleted file mode 100644 index 2b1448d8e..000000000 --- a/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModal.js +++ /dev/null @@ -1,27 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import EditRestrictionModalContentConnector from './EditRestrictionModalContentConnector'; - -function EditRestrictionModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -EditRestrictionModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditRestrictionModal; diff --git a/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalConnector.js b/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalConnector.js deleted file mode 100644 index 0089d153e..000000000 --- a/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalConnector.js +++ /dev/null @@ -1,39 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import EditRestrictionModal from './EditRestrictionModal'; - -const mapDispatchToProps = { - clearPendingChanges -}; - -class EditRestrictionModalConnector extends Component { - - // - // Listeners - - onModalClose = () => { - this.props.clearPendingChanges({ section: 'settings.restrictions' }); - this.props.onModalClose(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditRestrictionModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(null, mapDispatchToProps)(EditRestrictionModalConnector); diff --git a/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContent.css b/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContent.css deleted file mode 100644 index a2b6014df..000000000 --- a/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContent.css +++ /dev/null @@ -1,5 +0,0 @@ -.deleteButton { - composes: button from '~Components/Link/Button.css'; - - margin-right: auto; -} diff --git a/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContent.js b/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContent.js deleted file mode 100644 index 28b460b2e..000000000 --- a/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContent.js +++ /dev/null @@ -1,127 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './EditRestrictionModalContent.css'; - -function EditRestrictionModalContent(props) { - const { - isSaving, - saveError, - item, - onInputChange, - onModalClose, - onSavePress, - onDeleteRestrictionPress, - ...otherProps - } = props; - - const { - id, - required, - ignored, - tags - } = item; - - return ( - - - {id ? translate('EditRestriction') : translate('AddRestriction')} - - - -
- - {translate('MustContain')} - - - - - - {translate('MustNotContain')} - - - - - - {translate('Tags')} - - - -
-
- - { - id && - - } - - - - - {translate('Save')} - - -
- ); -} - -EditRestrictionModalContent.propTypes = { - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - onInputChange: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired, - onSavePress: PropTypes.func.isRequired, - onDeleteRestrictionPress: PropTypes.func -}; - -export default EditRestrictionModalContent; diff --git a/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContentConnector.js b/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContentConnector.js deleted file mode 100644 index 5737826e6..000000000 --- a/frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContentConnector.js +++ /dev/null @@ -1,111 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { saveRestriction, setRestrictionValue } from 'Store/Actions/settingsActions'; -import selectSettings from 'Store/Selectors/selectSettings'; -import EditRestrictionModalContent from './EditRestrictionModalContent'; - -const newRestriction = { - required: '', - ignored: '', - tags: [] -}; - -function createMapStateToProps() { - return createSelector( - (state, { id }) => id, - (state) => state.settings.restrictions, - (id, restrictions) => { - const { - isFetching, - error, - isSaving, - saveError, - pendingChanges, - items - } = restrictions; - - const profile = id ? _.find(items, { id }) : newRestriction; - const settings = selectSettings(profile, pendingChanges, saveError); - - return { - id, - isFetching, - error, - isSaving, - saveError, - item: settings.settings, - ...settings - }; - } - ); -} - -const mapDispatchToProps = { - setRestrictionValue, - saveRestriction -}; - -class EditRestrictionModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - if (!this.props.id) { - Object.keys(newRestriction).forEach((name) => { - this.props.setRestrictionValue({ - name, - value: newRestriction[name] - }); - }); - } - } - - componentDidUpdate(prevProps, prevState) { - if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) { - this.props.onModalClose(); - } - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setRestrictionValue({ name, value }); - } - - onSavePress = () => { - this.props.saveRestriction({ id: this.props.id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditRestrictionModalContentConnector.propTypes = { - id: PropTypes.number, - isFetching: PropTypes.bool.isRequired, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - setRestrictionValue: PropTypes.func.isRequired, - saveRestriction: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(EditRestrictionModalContentConnector); diff --git a/frontend/src/Settings/Indexers/Restrictions/Restriction.css b/frontend/src/Settings/Indexers/Restrictions/Restriction.css deleted file mode 100644 index ec6a01056..000000000 --- a/frontend/src/Settings/Indexers/Restrictions/Restriction.css +++ /dev/null @@ -1,11 +0,0 @@ -.restriction { - composes: card from '~Components/Card.css'; - - width: 290px; -} - -.enabled { - display: flex; - flex-wrap: wrap; - margin-top: 5px; -} diff --git a/frontend/src/Settings/Indexers/Restrictions/Restriction.js b/frontend/src/Settings/Indexers/Restrictions/Restriction.js deleted file mode 100644 index 748a700da..000000000 --- a/frontend/src/Settings/Indexers/Restrictions/Restriction.js +++ /dev/null @@ -1,149 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import Label from 'Components/Label'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import TagList from 'Components/TagList'; -import { kinds } from 'Helpers/Props'; -import split from 'Utilities/String/split'; -import translate from 'Utilities/String/translate'; -import EditRestrictionModalConnector from './EditRestrictionModalConnector'; -import styles from './Restriction.css'; - -class Restriction extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditRestrictionModalOpen: false, - isDeleteRestrictionModalOpen: false - }; - } - - // - // Listeners - - onEditRestrictionPress = () => { - this.setState({ isEditRestrictionModalOpen: true }); - } - - onEditRestrictionModalClose = () => { - this.setState({ isEditRestrictionModalOpen: false }); - } - - onDeleteRestrictionPress = () => { - this.setState({ - isEditRestrictionModalOpen: false, - isDeleteRestrictionModalOpen: true - }); - } - - onDeleteRestrictionModalClose= () => { - this.setState({ isDeleteRestrictionModalOpen: false }); - } - - onConfirmDeleteRestriction = () => { - this.props.onConfirmDeleteRestriction(this.props.id); - } - - // - // Render - - render() { - const { - id, - required, - ignored, - tags, - tagList - } = this.props; - - return ( - -
- { - split(required).map((item) => { - if (!item) { - return null; - } - - return ( - - ); - }) - } -
- -
- { - split(ignored).map((item) => { - if (!item) { - return null; - } - - return ( - - ); - }) - } -
- - - - - - -
- ); - } -} - -Restriction.propTypes = { - id: PropTypes.number.isRequired, - required: PropTypes.string.isRequired, - ignored: PropTypes.string.isRequired, - tags: PropTypes.arrayOf(PropTypes.number).isRequired, - tagList: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteRestriction: PropTypes.func.isRequired -}; - -Restriction.defaultProps = { - required: '', - ignored: '' -}; - -export default Restriction; diff --git a/frontend/src/Settings/Indexers/Restrictions/Restrictions.css b/frontend/src/Settings/Indexers/Restrictions/Restrictions.css deleted file mode 100644 index 4aa0dc107..000000000 --- a/frontend/src/Settings/Indexers/Restrictions/Restrictions.css +++ /dev/null @@ -1,20 +0,0 @@ -.restrictions { - display: flex; - flex-wrap: wrap; -} - -.addRestriction { - composes: restriction from '~./Restriction.css'; - - background-color: $cardAlternateBackgroundColor; - color: $gray; - text-align: center; -} - -.center { - display: inline-block; - padding: 5px 20px 0; - border: 1px solid $borderColor; - border-radius: 4px; - background-color: $white; -} diff --git a/frontend/src/Settings/Indexers/Restrictions/Restrictions.js b/frontend/src/Settings/Indexers/Restrictions/Restrictions.js deleted file mode 100644 index f76762f13..000000000 --- a/frontend/src/Settings/Indexers/Restrictions/Restrictions.js +++ /dev/null @@ -1,99 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import FieldSet from 'Components/FieldSet'; -import Icon from 'Components/Icon'; -import PageSectionContent from 'Components/Page/PageSectionContent'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditRestrictionModalConnector from './EditRestrictionModalConnector'; -import Restriction from './Restriction'; -import styles from './Restrictions.css'; - -class Restrictions extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isAddRestrictionModalOpen: false - }; - } - - // - // Listeners - - onAddRestrictionPress = () => { - this.setState({ isAddRestrictionModalOpen: true }); - } - - onAddRestrictionModalClose = () => { - this.setState({ isAddRestrictionModalOpen: false }); - } - - // - // Render - - render() { - const { - items, - tagList, - onConfirmDeleteRestriction, - ...otherProps - } = this.props; - - return ( -
- -
- -
- -
-
- - { - items.map((item) => { - return ( - - ); - }) - } -
- - -
-
- ); - } -} - -Restrictions.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - tagList: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteRestriction: PropTypes.func.isRequired -}; - -export default Restrictions; diff --git a/frontend/src/Settings/Indexers/Restrictions/RestrictionsConnector.js b/frontend/src/Settings/Indexers/Restrictions/RestrictionsConnector.js deleted file mode 100644 index 4cb644230..000000000 --- a/frontend/src/Settings/Indexers/Restrictions/RestrictionsConnector.js +++ /dev/null @@ -1,61 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { deleteRestriction, fetchRestrictions } from 'Store/Actions/settingsActions'; -import createTagsSelector from 'Store/Selectors/createTagsSelector'; -import Restrictions from './Restrictions'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.restrictions, - createTagsSelector(), - (restrictions, tagList) => { - return { - ...restrictions, - tagList - }; - } - ); -} - -const mapDispatchToProps = { - fetchRestrictions, - deleteRestriction -}; - -class RestrictionsConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchRestrictions(); - } - - // - // Listeners - - onConfirmDeleteRestriction = (id) => { - this.props.deleteRestriction({ id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -RestrictionsConnector.propTypes = { - fetchRestrictions: PropTypes.func.isRequired, - deleteRestriction: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(RestrictionsConnector); diff --git a/frontend/src/Settings/MediaManagement/MediaManagement.js b/frontend/src/Settings/MediaManagement/MediaManagement.js deleted file mode 100644 index 4d6247b4b..000000000 --- a/frontend/src/Settings/MediaManagement/MediaManagement.js +++ /dev/null @@ -1,407 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FieldSet from 'Components/FieldSet'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import { inputTypes, sizes } from 'Helpers/Props'; -import RootFoldersConnector from 'RootFolder/RootFoldersConnector'; -import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; -import translate from 'Utilities/String/translate'; -import NamingConnector from './Naming/NamingConnector'; -import AddRootFolderConnector from './RootFolder/AddRootFolderConnector'; - -const rescanAfterRefreshOptions = [ - { key: 'always', value: 'Always' }, - { key: 'afterManual', value: 'After Manual Refresh' }, - { key: 'never', value: 'Never' } -]; - -const downloadPropersAndRepacksOptions = [ - { key: 'preferAndUpgrade', value: 'Prefer and Upgrade' }, - { key: 'doNotUpgrade', value: 'Do not Upgrade Automatically' }, - { key: 'doNotPrefer', value: 'Do not Prefer' } -]; - -const fileDateOptions = [ - { key: 'none', value: 'None' }, - { key: 'cinemas', value: 'In Cinemas Date' }, - { key: 'release', value: 'Physical Release Date' } -]; - -class MediaManagement extends Component { - - // - // Render - - render() { - const { - advancedSettings, - isFetching, - error, - settings, - hasSettings, - isWindows, - onInputChange, - onSavePress, - ...otherProps - } = this.props; - - return ( - - - - - - - { - isFetching && -
- -
- } - - { - !isFetching && error && -
-
- {translate('UnableToLoadMediaManagementSettings')} -
-
- } - - { - hasSettings && !isFetching && !error && -
- { - advancedSettings && -
- - {translate('CreateEmptyMovieFolders')} - - - - - - {translate('DeleteEmptyFolders')} - - - -
- } - - { - advancedSettings && -
- { - !isWindows && - - {translate('SkipFreeSpaceCheck')} - - - - } - - - {translate('MinimumFreeSpace')} - - - - - - {translate('UseHardlinksInsteadOfCopy')} - - - - - - {translate('ImportExtraFiles')} - - - - - { - settings.importExtraFiles.value && - - {translate('ImportExtraFiles')} - - - - } -
- } - -
- - {translate('IgnoreDeletedMovies')} - - - - - - {translate('DownloadPropersAndRepacks')} - - - - - - {translate('AnalyseVideoFiles')} - - - - - - {translate('RescanMovieFolderAfterRefresh')} - - - - - - {translate('ChangeFileDate')} - - - - - - {translate('RecyclingBin')} - - - - - - {translate('RecyclingBinCleanup')} - - - -
- - { - advancedSettings && !isWindows && -
- - {translate('SetPermissions')} - - - - - - {translate('FileChmodMode')} - - - -
- } -
- } - -
- - -
-
-
- ); - } - -} - -MediaManagement.propTypes = { - advancedSettings: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - settings: PropTypes.object.isRequired, - hasSettings: PropTypes.bool.isRequired, - isWindows: PropTypes.bool.isRequired, - onSavePress: PropTypes.func.isRequired, - onInputChange: PropTypes.func.isRequired -}; - -export default MediaManagement; diff --git a/frontend/src/Settings/MediaManagement/MediaManagementConnector.js b/frontend/src/Settings/MediaManagement/MediaManagementConnector.js deleted file mode 100644 index 253f5a96c..000000000 --- a/frontend/src/Settings/MediaManagement/MediaManagementConnector.js +++ /dev/null @@ -1,86 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import { fetchMediaManagementSettings, saveMediaManagementSettings, saveNamingSettings, setMediaManagementSettingsValue } from 'Store/Actions/settingsActions'; -import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector'; -import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector'; -import MediaManagement from './MediaManagement'; - -const SECTION = 'mediaManagement'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - (state) => state.settings.naming, - createSettingsSectionSelector(SECTION), - createSystemStatusSelector(), - (advancedSettings, namingSettings, sectionSettings, systemStatus) => { - return { - advancedSettings, - ...sectionSettings, - hasPendingChanges: !_.isEmpty(namingSettings.pendingChanges) || sectionSettings.hasPendingChanges, - isWindows: systemStatus.isWindows - }; - } - ); -} - -const mapDispatchToProps = { - fetchMediaManagementSettings, - setMediaManagementSettingsValue, - saveMediaManagementSettings, - saveNamingSettings, - clearPendingChanges -}; - -class MediaManagementConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchMediaManagementSettings(); - } - - componentWillUnmount() { - this.props.clearPendingChanges({ section: `settings.${SECTION}` }); - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setMediaManagementSettingsValue({ name, value }); - } - - onSavePress = () => { - this.props.saveMediaManagementSettings(); - this.props.saveNamingSettings(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -MediaManagementConnector.propTypes = { - fetchMediaManagementSettings: PropTypes.func.isRequired, - setMediaManagementSettingsValue: PropTypes.func.isRequired, - saveMediaManagementSettings: PropTypes.func.isRequired, - saveNamingSettings: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(MediaManagementConnector); diff --git a/frontend/src/Settings/MediaManagement/Naming/Naming.css b/frontend/src/Settings/MediaManagement/Naming/Naming.css deleted file mode 100644 index 59d223e92..000000000 --- a/frontend/src/Settings/MediaManagement/Naming/Naming.css +++ /dev/null @@ -1,5 +0,0 @@ -.namingInput { - composes: input from '~Components/Form/TextInput.css'; - - font-family: $monoSpaceFontFamily; -} diff --git a/frontend/src/Settings/MediaManagement/Naming/Naming.js b/frontend/src/Settings/MediaManagement/Naming/Naming.js deleted file mode 100644 index aaff0e0a1..000000000 --- a/frontend/src/Settings/MediaManagement/Naming/Naming.js +++ /dev/null @@ -1,227 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FieldSet from 'Components/FieldSet'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputButton from 'Components/Form/FormInputButton'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import { inputTypes, sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import NamingModal from './NamingModal'; -import styles from './Naming.css'; - -const colonReplacementOptions = [ - { key: 'delete', value: 'Delete' }, - { key: 'dash', value: 'Replace with Dash' }, - { key: 'spaceDash', value: 'Replace with Space Dash' }, - { key: 'spaceDashSpace', value: 'Replace with Space Dash Space' } -]; - -class Naming extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isNamingModalOpen: false, - namingModalOptions: null - }; - } - - // - // Listeners - - onStandardNamingModalOpenClick = () => { - this.setState({ - isNamingModalOpen: true, - namingModalOptions: { - name: 'standardMovieFormat', - additional: true - } - }); - } - - onMovieFolderNamingModalOpenClick = () => { - this.setState({ - isNamingModalOpen: true, - namingModalOptions: { - name: 'movieFolderFormat' - } - }); - } - - onNamingModalClose = () => { - this.setState({ isNamingModalOpen: false }); - } - - // - // Render - - render() { - const { - advancedSettings, - isFetching, - error, - settings, - hasSettings, - examples, - examplesPopulated, - onInputChange - } = this.props; - - const { - isNamingModalOpen, - namingModalOptions - } = this.state; - - const renameMovies = hasSettings && settings.renameMovies.value; - const replaceIllegalCharacters = hasSettings && settings.replaceIllegalCharacters.value; - - const standardMovieFormatHelpTexts = []; - const standardMovieFormatErrors = []; - const movieFolderFormatHelpTexts = []; - const movieFolderFormatErrors = []; - - if (examplesPopulated) { - if (examples.movieExample) { - standardMovieFormatHelpTexts.push(`Movie: ${examples.movieExample}`); - } else { - standardMovieFormatErrors.push({ message: 'Movie: Invalid Format' }); - } - - if (examples.movieFolderExample) { - movieFolderFormatHelpTexts.push(`Example: ${examples.movieFolderExample}`); - } else { - movieFolderFormatErrors.push({ message: 'Invalid Format' }); - } - } - - return ( -
- { - isFetching && - - } - - { - !isFetching && error && -
- {translate('UnableToLoadNamingSettings')} -
- } - - { - hasSettings && !isFetching && !error && -
- - {translate('RenameMovies')} - - - - - - {translate('ReplaceIllegalCharacters')} - - - - - { - replaceIllegalCharacters && - - {translate('ColonReplacement')} - - - - } - - { - renameMovies && - - {translate('StandardMovieFormat')} - - ?} - onChange={onInputChange} - {...settings.standardMovieFormat} - helpTexts={standardMovieFormatHelpTexts} - errors={[...standardMovieFormatErrors, ...settings.standardMovieFormat.errors]} - /> - - } - - - {translate('MovieFolderFormat')} - - ?} - onChange={onInputChange} - {...settings.movieFolderFormat} - helpTexts={['Used when adding a new movie or moving movies via the editor', ...movieFolderFormatHelpTexts]} - errors={[...movieFolderFormatErrors, ...settings.movieFolderFormat.errors]} - /> - - - { - namingModalOptions && - - } - - } -
- ); - } - -} - -Naming.propTypes = { - advancedSettings: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - settings: PropTypes.object.isRequired, - hasSettings: PropTypes.bool.isRequired, - examples: PropTypes.object.isRequired, - examplesPopulated: PropTypes.bool.isRequired, - onInputChange: PropTypes.func.isRequired -}; - -export default Naming; diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingConnector.js b/frontend/src/Settings/MediaManagement/Naming/NamingConnector.js deleted file mode 100644 index b08cac699..000000000 --- a/frontend/src/Settings/MediaManagement/Naming/NamingConnector.js +++ /dev/null @@ -1,97 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import { fetchNamingExamples, fetchNamingSettings, setNamingSettingsValue } from 'Store/Actions/settingsActions'; -import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector'; -import Naming from './Naming'; - -const SECTION = 'naming'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - (state) => state.settings.namingExamples, - createSettingsSectionSelector(SECTION), - (advancedSettings, examples, sectionSettings) => { - return { - advancedSettings, - examples: examples.item, - examplesPopulated: !_.isEmpty(examples.item), - ...sectionSettings - }; - } - ); -} - -const mapDispatchToProps = { - fetchNamingSettings, - setNamingSettingsValue, - fetchNamingExamples, - clearPendingChanges -}; - -class NamingConnector extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this._namingExampleTimeout = null; - } - - componentDidMount() { - this.props.fetchNamingSettings(); - this.props.fetchNamingExamples(); - } - - componentWillUnmount() { - this.props.clearPendingChanges({ section: `settings.${SECTION}` }); - } - - // - // Control - - _fetchNamingExamples = () => { - this.props.fetchNamingExamples(); - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setNamingSettingsValue({ name, value }); - - if (this._namingExampleTimeout) { - clearTimeout(this._namingExampleTimeout); - } - - this._namingExampleTimeout = setTimeout(this._fetchNamingExamples, 1000); - } - - // - // Render - - render() { - return ( - - ); - } -} - -NamingConnector.propTypes = { - fetchNamingSettings: PropTypes.func.isRequired, - setNamingSettingsValue: PropTypes.func.isRequired, - fetchNamingExamples: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(NamingConnector); diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingModal.css b/frontend/src/Settings/MediaManagement/Naming/NamingModal.css deleted file mode 100644 index c178d82cb..000000000 --- a/frontend/src/Settings/MediaManagement/Naming/NamingModal.css +++ /dev/null @@ -1,18 +0,0 @@ -.groups { - display: flex; - justify-content: space-between; - flex-wrap: wrap; - margin-bottom: 20px; -} - -.namingSelectContainer { - display: flex; - justify-content: flex-end; -} - -.namingSelect { - composes: select from '~Components/Form/SelectInput.css'; - - margin-left: 10px; - width: 200px; -} diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingModal.js b/frontend/src/Settings/MediaManagement/Naming/NamingModal.js deleted file mode 100644 index a2a59469c..000000000 --- a/frontend/src/Settings/MediaManagement/Naming/NamingModal.js +++ /dev/null @@ -1,440 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FieldSet from 'Components/FieldSet'; -import SelectInput from 'Components/Form/SelectInput'; -import TextInput from 'Components/Form/TextInput'; -import Button from 'Components/Link/Button'; -import Modal from 'Components/Modal/Modal'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import NamingOption from './NamingOption'; -import styles from './NamingModal.css'; - -class NamingModal extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this._selectionStart = null; - this._selectionEnd = null; - - this.state = { - separator: ' ', - case: 'title' - }; - } - - // - // Listeners - - onTokenSeparatorChange = (event) => { - this.setState({ separator: event.value }); - } - - onTokenCaseChange = (event) => { - this.setState({ case: event.value }); - } - - onInputSelectionChange = (selectionStart, selectionEnd) => { - this._selectionStart = selectionStart; - this._selectionEnd = selectionEnd; - } - - onOptionPress = ({ isFullFilename, tokenValue }) => { - const { - name, - value, - onInputChange - } = this.props; - - const selectionStart = this._selectionStart; - const selectionEnd = this._selectionEnd; - - if (isFullFilename) { - onInputChange({ name, value: tokenValue }); - } else if (selectionStart == null) { - onInputChange({ - name, - value: `${value}${tokenValue}` - }); - } else { - const start = value.substring(0, selectionStart); - const end = value.substring(selectionEnd); - const newValue = `${start}${tokenValue}${end}`; - - onInputChange({ name, value: newValue }); - this._selectionStart = newValue.length - 1; - this._selectionEnd = newValue.length - 1; - } - } - - // - // Render - - render() { - const { - name, - value, - isOpen, - advancedSettings, - additional, - onInputChange, - onModalClose - } = this.props; - - const { - separator: tokenSeparator, - case: tokenCase - } = this.state; - - const separatorOptions = [ - { key: ' ', value: 'Space ( )' }, - { key: '.', value: 'Period (.)' }, - { key: '_', value: 'Underscore (_)' }, - { key: '-', value: 'Dash (-)' } - ]; - - const caseOptions = [ - { key: 'title', value: 'Default Case' }, - { key: 'lower', value: 'Lower Case' }, - { key: 'upper', value: 'Upper Case' } - ]; - - const fileNameTokens = [ - { - token: '{Movie Title} - {Quality Full}', - example: 'Movie Title (2010) - HDTV-720p Proper' - } - ]; - - const movieTokens = [ - { token: '{Movie Title}', example: 'Movie Title!' }, - { token: '{Movie Title:DE}', example: 'Filetitle' }, - { token: '{Movie CleanTitle}', example: 'Movie Title' }, - { token: '{Movie TitleThe}', example: 'Movie Title, The' }, - { token: '{Movie OriginalTitle}', example: 'Τίτλος ταινίας' }, - { token: '{Movie TitleFirstCharacter}', example: 'M' }, - { token: '{Movie Collection}', example: 'The Movie Collection' }, - { token: '{Movie Certification}', example: 'R' }, - { token: '{Release Year}', example: '2009' } - ]; - - const movieIdTokens = [ - { token: '{ImdbId}', example: 'tt12345' }, - { token: '{TmdbId}', example: '123456' } - ]; - - const qualityTokens = [ - { token: '{Quality Full}', example: 'HDTV 720p Proper' }, - { token: '{Quality Title}', example: 'HDTV 720p' } - ]; - - const mediaInfoTokens = [ - { token: '{MediaInfo Simple}', example: 'x264 DTS' }, - { token: '{MediaInfo Full}', example: 'x264 DTS [EN+DE]' }, - { token: '{MediaInfo VideoCodec}', example: 'x264' }, - { token: '{MediaInfo AudioCodec}', example: 'DTS' }, - { token: '{MediaInfo AudioChannels}', example: '5.1' }, - { token: '{MediaInfo AudioLanguages}', example: '[EN+DE]' }, - { token: '{MediaInfo SubtitleLanguages}', example: '[DE]' }, - - { token: '{MediaInfo VideoCodec}', example: 'x264' }, - { token: '{MediaInfo VideoBitDepth}', example: '10' }, - { token: '{MediaInfo VideoDynamicRange}', example: 'HDR' } - ]; - - const releaseGroupTokens = [ - { token: '{Release Group}', example: 'Rls Grp' } - ]; - - const editionTokens = [ - { token: '{Edition Tags}', example: 'IMAX' } - ]; - - const customFormatTokens = [ - { token: '{Custom Formats}', example: 'Surround Sound x264' } - ]; - - const originalTokens = [ - { token: '{Original Title}', example: 'Movie.Title.HDTV.x264-EVOLVE' }, - { token: '{Original Filename}', example: 'Movie.title.hdtv.x264-EVOLVE' } - ]; - - return ( - - - - File Name Tokens - - - -
- - - -
- - { - !advancedSettings && -
-
- { - fileNameTokens.map(({ token, example }) => { - return ( - - ); - } - ) - } -
-
- } - -
-
- { - movieTokens.map(({ token, example }) => { - return ( - - ); - } - ) - } -
-
- -
-
- { - movieIdTokens.map(({ token, example }) => { - return ( - - ); - } - ) - } -
-
- - { - additional && -
-
-
- { - qualityTokens.map(({ token, example }) => { - return ( - - ); - } - ) - } -
-
- -
-
- { - mediaInfoTokens.map(({ token, example }) => { - return ( - - ); - } - ) - } -
-
- -
-
- { - releaseGroupTokens.map(({ token, example }) => { - return ( - - ); - } - ) - } -
-
- -
-
- { - editionTokens.map(({ token, example }) => { - return ( - - ); - } - ) - } -
-
- -
-
- { - customFormatTokens.map(({ token, example }) => { - return ( - - ); - } - ) - } -
-
- -
-
- { - originalTokens.map(({ token, example }) => { - return ( - - ); - } - ) - } -
-
-
- } -
- - - - - -
-
- ); - } -} - -NamingModal.propTypes = { - name: PropTypes.string.isRequired, - value: PropTypes.string.isRequired, - isOpen: PropTypes.bool.isRequired, - advancedSettings: PropTypes.bool.isRequired, - additional: PropTypes.bool.isRequired, - onInputChange: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -NamingModal.defaultProps = { - additional: false -}; - -export default NamingModal; diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingOption.css b/frontend/src/Settings/MediaManagement/Naming/NamingOption.css deleted file mode 100644 index c895cb6bc..000000000 --- a/frontend/src/Settings/MediaManagement/Naming/NamingOption.css +++ /dev/null @@ -1,69 +0,0 @@ -.option { - display: flex; - align-items: stretch; - flex-wrap: wrap; - margin: 3px; - border: 1px solid $borderColor; - - &:hover { - .token { - background-color: #ddd; - } - - .example { - background-color: #ccc; - } - } -} - -.small { - width: 480px; -} - -.large { - width: 100%; -} - -.token { - flex: 0 0 50%; - padding: 6px 16px; - background-color: #eee; - font-family: $monoSpaceFontFamily; -} - -.example { - display: flex; - align-items: center; - align-self: stretch; - flex: 0 0 50%; - padding: 6px 16px; - background-color: #ddd; -} - -.lower { - text-transform: lowercase; -} - -.upper { - text-transform: uppercase; -} - -.isFullFilename { - .token, - .example { - flex: 1 0 auto; - } -} - -@media only screen and (max-width: $breakpointSmall) { - .option.small { - width: 100%; - } -} - -@media only screen and (max-width: $breakpointExtraSmall) { - .token, - .example { - flex: 1 0 auto; - } -} diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingOption.js b/frontend/src/Settings/MediaManagement/Naming/NamingOption.js deleted file mode 100644 index 0eb9456ef..000000000 --- a/frontend/src/Settings/MediaManagement/Naming/NamingOption.js +++ /dev/null @@ -1,84 +0,0 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Link from 'Components/Link/Link'; -import { sizes } from 'Helpers/Props'; -import styles from './NamingOption.css'; - -class NamingOption extends Component { - - // - // Listeners - - onPress = () => { - const { - token, - tokenSeparator, - tokenCase, - isFullFilename, - onPress - } = this.props; - - let tokenValue = token; - - tokenValue = tokenValue.replace(/ /g, tokenSeparator); - - if (tokenCase === 'lower') { - tokenValue = token.toLowerCase(); - } else if (tokenCase === 'upper') { - tokenValue = token.toUpperCase(); - } - - onPress({ isFullFilename, tokenValue }); - } - - // - // Render - render() { - const { - token, - tokenSeparator, - example, - tokenCase, - isFullFilename, - size - } = this.props; - - return ( - -
- {token.replace(/ /g, tokenSeparator)} -
- -
- {example.replace(/ /g, tokenSeparator)} -
- - ); - } -} - -NamingOption.propTypes = { - token: PropTypes.string.isRequired, - example: PropTypes.string.isRequired, - tokenSeparator: PropTypes.string.isRequired, - tokenCase: PropTypes.string.isRequired, - isFullFilename: PropTypes.bool.isRequired, - size: PropTypes.oneOf([sizes.SMALL, sizes.LARGE]), - onPress: PropTypes.func.isRequired -}; - -NamingOption.defaultProps = { - size: sizes.SMALL, - isFullFilename: false -}; - -export default NamingOption; diff --git a/frontend/src/Settings/MediaManagement/RootFolder/AddRootFolder.css b/frontend/src/Settings/MediaManagement/RootFolder/AddRootFolder.css deleted file mode 100644 index 19b1880be..000000000 --- a/frontend/src/Settings/MediaManagement/RootFolder/AddRootFolder.css +++ /dev/null @@ -1,7 +0,0 @@ -.addRootFolderButtonContainer { - margin-top: 20px; -} - -.importButtonIcon { - margin-right: 8px; -} diff --git a/frontend/src/Settings/MediaManagement/RootFolder/AddRootFolder.js b/frontend/src/Settings/MediaManagement/RootFolder/AddRootFolder.js deleted file mode 100644 index 91278b6f5..000000000 --- a/frontend/src/Settings/MediaManagement/RootFolder/AddRootFolder.js +++ /dev/null @@ -1,71 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FileBrowserModal from 'Components/FileBrowser/FileBrowserModal'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import { icons, kinds, sizes } from 'Helpers/Props'; -import styles from './AddRootFolder.css'; - -class AddRootFolder extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isAddNewRootFolderModalOpen: false - }; - } - - // - // Lifecycle - - onAddNewRootFolderPress = () => { - this.setState({ isAddNewRootFolderModalOpen: true }); - } - - onNewRootFolderSelect = ({ value }) => { - this.props.onNewRootFolderSelect(value); - } - - onAddRootFolderModalClose = () => { - this.setState({ isAddNewRootFolderModalOpen: false }); - } - - // - // Render - - render() { - return ( -
- - - -
- ); - } -} - -AddRootFolder.propTypes = { - onNewRootFolderSelect: PropTypes.func.isRequired -}; - -export default AddRootFolder; diff --git a/frontend/src/Settings/MediaManagement/RootFolder/AddRootFolderConnector.js b/frontend/src/Settings/MediaManagement/RootFolder/AddRootFolderConnector.js deleted file mode 100644 index f32a1aec0..000000000 --- a/frontend/src/Settings/MediaManagement/RootFolder/AddRootFolderConnector.js +++ /dev/null @@ -1,13 +0,0 @@ -import { connect } from 'react-redux'; -import { addRootFolder } from 'Store/Actions/rootFolderActions'; -import AddRootFolder from './AddRootFolder'; - -function createMapDispatchToProps(dispatch) { - return { - onNewRootFolderSelect(path) { - dispatch(addRootFolder({ path })); - } - }; -} - -export default connect(null, createMapDispatchToProps)(AddRootFolder); diff --git a/frontend/src/Settings/Metadata/Metadata/EditMetadataModal.js b/frontend/src/Settings/Metadata/Metadata/EditMetadataModal.js deleted file mode 100644 index 4b33df528..000000000 --- a/frontend/src/Settings/Metadata/Metadata/EditMetadataModal.js +++ /dev/null @@ -1,27 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import EditMetadataModalContentConnector from './EditMetadataModalContentConnector'; - -function EditMetadataModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -EditMetadataModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditMetadataModal; diff --git a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalConnector.js b/frontend/src/Settings/Metadata/Metadata/EditMetadataModalConnector.js deleted file mode 100644 index 1a38beb4a..000000000 --- a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalConnector.js +++ /dev/null @@ -1,44 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import EditMetadataModal from './EditMetadataModal'; - -function createMapDispatchToProps(dispatch, props) { - const section = 'settings.metadata'; - - return { - dispatchClearPendingChanges() { - dispatch(clearPendingChanges({ section })); - } - }; -} - -class EditMetadataModalConnector extends Component { - // - // Listeners - - onModalClose = () => { - this.props.dispatchClearPendingChanges({ section: 'metadata' }); - this.props.onModalClose(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditMetadataModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - dispatchClearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(null, createMapDispatchToProps)(EditMetadataModalConnector); diff --git a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContent.js b/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContent.js deleted file mode 100644 index 3f9087ada..000000000 --- a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContent.js +++ /dev/null @@ -1,105 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import ProviderFieldFormGroup from 'Components/Form/ProviderFieldFormGroup'; -import Button from 'Components/Link/Button'; -import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -function EditMetadataModalContent(props) { - const { - advancedSettings, - isSaving, - saveError, - item, - onInputChange, - onFieldChange, - onModalClose, - onSavePress, - ...otherProps - } = props; - - const { - name, - enable, - fields - } = item; - - return ( - - - Edit {name.value} Metadata - - - -
- - {translate('Enable')} - - - - - { - fields.map((field) => { - return ( - - ); - }) - } - - -
- - - - - - {translate('Save')} - - -
- ); -} - -EditMetadataModalContent.propTypes = { - advancedSettings: PropTypes.bool.isRequired, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - onInputChange: PropTypes.func.isRequired, - onFieldChange: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired, - onSavePress: PropTypes.func.isRequired, - onDeleteMetadataPress: PropTypes.func -}; - -export default EditMetadataModalContent; diff --git a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContentConnector.js b/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContentConnector.js deleted file mode 100644 index 6ebeb7907..000000000 --- a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContentConnector.js +++ /dev/null @@ -1,95 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { saveMetadata, setMetadataFieldValue, setMetadataValue } from 'Store/Actions/settingsActions'; -import selectSettings from 'Store/Selectors/selectSettings'; -import EditMetadataModalContent from './EditMetadataModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - (state, { id }) => id, - (state) => state.settings.metadata, - (advancedSettings, id, metadata) => { - const { - isSaving, - saveError, - pendingChanges, - items - } = metadata; - - const settings = selectSettings(_.find(items, { id }), pendingChanges, saveError); - - return { - advancedSettings, - id, - isSaving, - saveError, - item: settings.settings, - ...settings - }; - } - ); -} - -const mapDispatchToProps = { - setMetadataValue, - setMetadataFieldValue, - saveMetadata -}; - -class EditMetadataModalContentConnector extends Component { - - // - // Lifecycle - - componentDidUpdate(prevProps, prevState) { - if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) { - this.props.onModalClose(); - } - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setMetadataValue({ name, value }); - } - - onFieldChange = ({ name, value }) => { - this.props.setMetadataFieldValue({ name, value }); - } - - onSavePress = () => { - this.props.saveMetadata({ id: this.props.id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditMetadataModalContentConnector.propTypes = { - id: PropTypes.number, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - setMetadataValue: PropTypes.func.isRequired, - setMetadataFieldValue: PropTypes.func.isRequired, - saveMetadata: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(EditMetadataModalContentConnector); diff --git a/frontend/src/Settings/Metadata/Metadata/Metadata.css b/frontend/src/Settings/Metadata/Metadata/Metadata.css deleted file mode 100644 index f87b92a81..000000000 --- a/frontend/src/Settings/Metadata/Metadata/Metadata.css +++ /dev/null @@ -1,15 +0,0 @@ -.metadata { - composes: card from '~Components/Card.css'; - - width: 290px; -} - -.name { - margin-bottom: 20px; - font-weight: 300; - font-size: 24px; -} - -.section { - margin-top: 10px; -} diff --git a/frontend/src/Settings/Metadata/Metadata/Metadata.js b/frontend/src/Settings/Metadata/Metadata/Metadata.js deleted file mode 100644 index a004912d1..000000000 --- a/frontend/src/Settings/Metadata/Metadata/Metadata.js +++ /dev/null @@ -1,149 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import Label from 'Components/Label'; -import { kinds } from 'Helpers/Props'; -import EditMetadataModalConnector from './EditMetadataModalConnector'; -import styles from './Metadata.css'; - -class Metadata extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditMetadataModalOpen: false - }; - } - - // - // Listeners - - onEditMetadataPress = () => { - this.setState({ isEditMetadataModalOpen: true }); - } - - onEditMetadataModalClose = () => { - this.setState({ isEditMetadataModalOpen: false }); - } - - // - // Render - - render() { - const { - id, - name, - enable, - fields - } = this.props; - - const metadataFields = []; - const imageFields = []; - - fields.forEach((field) => { - if (field.section === 'metadata') { - metadataFields.push(field); - } else { - imageFields.push(field); - } - }); - - return ( - -
- {name} -
- -
- { - enable ? - : - - } -
- - { - enable && !!metadataFields.length && -
-
- Metadata -
- - { - metadataFields.map((field) => { - if (!field.value) { - return null; - } - - return ( - - ); - }) - } -
- } - - { - enable && !!imageFields.length && -
-
- Images -
- - { - imageFields.map((field) => { - if (!field.value) { - return null; - } - - return ( - - ); - }) - } -
- } - - -
- ); - } -} - -Metadata.propTypes = { - id: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - enable: PropTypes.bool.isRequired, - fields: PropTypes.arrayOf(PropTypes.object).isRequired -}; - -export default Metadata; diff --git a/frontend/src/Settings/Metadata/Metadata/Metadatas.css b/frontend/src/Settings/Metadata/Metadata/Metadatas.css deleted file mode 100644 index fb1bd6080..000000000 --- a/frontend/src/Settings/Metadata/Metadata/Metadatas.css +++ /dev/null @@ -1,4 +0,0 @@ -.metadatas { - display: flex; - flex-wrap: wrap; -} diff --git a/frontend/src/Settings/Metadata/Metadata/Metadatas.js b/frontend/src/Settings/Metadata/Metadata/Metadatas.js deleted file mode 100644 index 91c570a7b..000000000 --- a/frontend/src/Settings/Metadata/Metadata/Metadatas.js +++ /dev/null @@ -1,44 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import FieldSet from 'Components/FieldSet'; -import PageSectionContent from 'Components/Page/PageSectionContent'; -import translate from 'Utilities/String/translate'; -import Metadata from './Metadata'; -import styles from './Metadatas.css'; - -function Metadatas(props) { - const { - items, - ...otherProps - } = props; - - return ( -
- -
- { - items.map((item) => { - return ( - - ); - }) - } -
-
-
- ); -} - -Metadatas.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired -}; - -export default Metadatas; diff --git a/frontend/src/Settings/Metadata/Metadata/MetadatasConnector.js b/frontend/src/Settings/Metadata/Metadata/MetadatasConnector.js deleted file mode 100644 index fb52ac33b..000000000 --- a/frontend/src/Settings/Metadata/Metadata/MetadatasConnector.js +++ /dev/null @@ -1,47 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchMetadata } from 'Store/Actions/settingsActions'; -import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector'; -import sortByName from 'Utilities/Array/sortByName'; -import Metadatas from './Metadatas'; - -function createMapStateToProps() { - return createSelector( - createSortedSectionSelector('settings.metadata', sortByName), - (metadata) => metadata - ); -} - -const mapDispatchToProps = { - fetchMetadata -}; - -class MetadatasConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchMetadata(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -MetadatasConnector.propTypes = { - fetchMetadata: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(MetadatasConnector); diff --git a/frontend/src/Settings/Metadata/MetadataSettings.js b/frontend/src/Settings/Metadata/MetadataSettings.js deleted file mode 100644 index 665813f8b..000000000 --- a/frontend/src/Settings/Metadata/MetadataSettings.js +++ /dev/null @@ -1,72 +0,0 @@ -import React, { Component } from 'react'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; -import translate from 'Utilities/String/translate'; -import MetadatasConnector from './Metadata/MetadatasConnector'; -import MetadataOptionsConnector from './Options/MetadataOptionsConnector'; - -class MetadataSettings extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this._saveCallback = null; - - this.state = { - isSaving: false, - hasPendingChanges: false - }; - } - - // - // Listeners - - onChildMounted = (saveCallback) => { - this._saveCallback = saveCallback; - } - - onChildStateChange = (payload) => { - this.setState(payload); - } - - onSavePress = () => { - if (this._saveCallback) { - this._saveCallback(); - } - } - - // - // Render - - render() { - const { - isSaving, - hasPendingChanges - } = this.state; - - return ( - - - - - - - - - - ); - } -} - -export default MetadataSettings; diff --git a/frontend/src/Settings/Metadata/Options/MetadataOptions.js b/frontend/src/Settings/Metadata/Options/MetadataOptions.js deleted file mode 100644 index b6d061809..000000000 --- a/frontend/src/Settings/Metadata/Options/MetadataOptions.js +++ /dev/null @@ -1,69 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import FieldSet from 'Components/FieldSet'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import { inputTypes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -export const certificationCountryOptions = [ - { key: 'us', value: 'United States' }, - { key: 'gb', value: 'Great Britain' } -]; - -function MetadataOptions(props) { - const { - isFetching, - error, - settings, - hasSettings, - onInputChange - } = props; - - return ( -
- { - isFetching && - - } - - { - !isFetching && error && -
- {translate('UnableToLoadIndexerOptions')} -
- } - - { - hasSettings && !isFetching && !error && -
- - {translate('CertificationCountry')} - - - -
- } -
- ); -} - -MetadataOptions.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - settings: PropTypes.object.isRequired, - hasSettings: PropTypes.bool.isRequired, - onInputChange: PropTypes.func.isRequired -}; - -export default MetadataOptions; diff --git a/frontend/src/Settings/Metadata/Options/MetadataOptionsConnector.js b/frontend/src/Settings/Metadata/Options/MetadataOptionsConnector.js deleted file mode 100644 index 23fa9ae5f..000000000 --- a/frontend/src/Settings/Metadata/Options/MetadataOptionsConnector.js +++ /dev/null @@ -1,101 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import { fetchMetadataOptions, saveMetadataOptions, setMetadataOptionsValue } from 'Store/Actions/settingsActions'; -import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector'; -import MetadataOptions from './MetadataOptions'; - -const SECTION = 'metadataOptions'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - createSettingsSectionSelector(SECTION), - (advancedSettings, sectionSettings) => { - return { - advancedSettings, - ...sectionSettings - }; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchMetadataOptions: fetchMetadataOptions, - dispatchSetMetadataOptionsValue: setMetadataOptionsValue, - dispatchSaveMetadataOptions: saveMetadataOptions, - dispatchClearPendingChanges: clearPendingChanges -}; - -class MetadataOptionsConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - dispatchFetchMetadataOptions, - dispatchSaveMetadataOptions, - onChildMounted - } = this.props; - - dispatchFetchMetadataOptions(); - onChildMounted(dispatchSaveMetadataOptions); - } - - componentDidUpdate(prevProps) { - const { - hasPendingChanges, - isSaving, - onChildStateChange - } = this.props; - - if ( - prevProps.isSaving !== isSaving || - prevProps.hasPendingChanges !== hasPendingChanges - ) { - onChildStateChange({ - isSaving, - hasPendingChanges - }); - } - } - - componentWillUnmount() { - this.props.dispatchClearPendingChanges({ section: SECTION }); - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.dispatchSetMetadataOptionsValue({ name, value }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -MetadataOptionsConnector.propTypes = { - isSaving: PropTypes.bool.isRequired, - hasPendingChanges: PropTypes.bool.isRequired, - dispatchFetchMetadataOptions: PropTypes.func.isRequired, - dispatchSetMetadataOptionsValue: PropTypes.func.isRequired, - dispatchSaveMetadataOptions: PropTypes.func.isRequired, - dispatchClearPendingChanges: PropTypes.func.isRequired, - onChildMounted: PropTypes.func.isRequired, - onChildStateChange: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(MetadataOptionsConnector); diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfile.css b/frontend/src/Settings/Profiles/Delay/DelayProfile.css deleted file mode 100644 index 238742efd..000000000 --- a/frontend/src/Settings/Profiles/Delay/DelayProfile.css +++ /dev/null @@ -1,40 +0,0 @@ -.delayProfile { - display: flex; - align-items: stretch; - margin-bottom: 10px; - height: 30px; - border-bottom: 1px solid $borderColor; - line-height: 30px; -} - -.column { - flex: 0 0 200px; -} - -.actions { - display: flex; -} - -.dragHandle { - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - margin-left: auto; - width: $dragHandleWidth; - text-align: center; - cursor: grab; -} - -.dragIcon { - top: 0; -} - -.isDragging { - opacity: 0.25; -} - -.editButton { - width: $dragHandleWidth; - text-align: center; -} diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfile.js b/frontend/src/Settings/Profiles/Delay/DelayProfile.js deleted file mode 100644 index 65f160813..000000000 --- a/frontend/src/Settings/Profiles/Delay/DelayProfile.js +++ /dev/null @@ -1,173 +0,0 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Icon from 'Components/Icon'; -import Link from 'Components/Link/Link'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import TagList from 'Components/TagList'; -import { icons, kinds } from 'Helpers/Props'; -import titleCase from 'Utilities/String/titleCase'; -import translate from 'Utilities/String/translate'; -import EditDelayProfileModalConnector from './EditDelayProfileModalConnector'; -import styles from './DelayProfile.css'; - -function getDelay(enabled, delay) { - if (!enabled) { - return '-'; - } - - if (!delay) { - return 'No Delay'; - } - - if (delay === 1) { - return '1 Minute'; - } - - // TODO: use better units of time than just minutes - return `${delay} Minutes`; -} - -class DelayProfile extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditDelayProfileModalOpen: false, - isDeleteDelayProfileModalOpen: false - }; - } - - // - // Listeners - - onEditDelayProfilePress = () => { - this.setState({ isEditDelayProfileModalOpen: true }); - } - - onEditDelayProfileModalClose = () => { - this.setState({ isEditDelayProfileModalOpen: false }); - } - - onDeleteDelayProfilePress = () => { - this.setState({ - isEditDelayProfileModalOpen: false, - isDeleteDelayProfileModalOpen: true - }); - } - - onDeleteDelayProfileModalClose = () => { - this.setState({ isDeleteDelayProfileModalOpen: false }); - } - - onConfirmDeleteDelayProfile = () => { - this.props.onConfirmDeleteDelayProfile(this.props.id); - } - - // - // Render - - render() { - const { - id, - enableUsenet, - enableTorrent, - preferredProtocol, - usenetDelay, - torrentDelay, - tags, - tagList, - isDragging, - connectDragSource - } = this.props; - - let preferred = titleCase(preferredProtocol); - - if (!enableUsenet) { - preferred = 'Only Torrent'; - } else if (!enableTorrent) { - preferred = 'Only Usenet'; - } - - return ( -
-
{preferred}
-
{getDelay(enableUsenet, usenetDelay)}
-
{getDelay(enableTorrent, torrentDelay)}
- - - -
- - - - - { - id !== 1 && - connectDragSource( -
- -
- ) - } -
- - - - -
- ); - } -} - -DelayProfile.propTypes = { - id: PropTypes.number.isRequired, - enableUsenet: PropTypes.bool.isRequired, - enableTorrent: PropTypes.bool.isRequired, - preferredProtocol: PropTypes.string.isRequired, - usenetDelay: PropTypes.number.isRequired, - torrentDelay: PropTypes.number.isRequired, - tags: PropTypes.arrayOf(PropTypes.number).isRequired, - tagList: PropTypes.arrayOf(PropTypes.object).isRequired, - isDragging: PropTypes.bool.isRequired, - connectDragSource: PropTypes.func, - onConfirmDeleteDelayProfile: PropTypes.func.isRequired -}; - -DelayProfile.defaultProps = { - // The drag preview will not connect the drag handle. - connectDragSource: (node) => node -}; - -export default DelayProfile; diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css b/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css deleted file mode 100644 index cc5a92830..000000000 --- a/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css +++ /dev/null @@ -1,3 +0,0 @@ -.dragPreview { - opacity: 0.75; -} diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.js b/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.js deleted file mode 100644 index 1ebb32a95..000000000 --- a/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.js +++ /dev/null @@ -1,78 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { DragLayer } from 'react-dnd'; -import DragPreviewLayer from 'Components/DragPreviewLayer'; -import { DELAY_PROFILE } from 'Helpers/dragTypes'; -import dimensions from 'Styles/Variables/dimensions.js'; -import DelayProfile from './DelayProfile'; -import styles from './DelayProfileDragPreview.css'; - -const dragHandleWidth = parseInt(dimensions.dragHandleWidth); - -function collectDragLayer(monitor) { - return { - item: monitor.getItem(), - itemType: monitor.getItemType(), - currentOffset: monitor.getSourceClientOffset() - }; -} - -class DelayProfileDragPreview extends Component { - - // - // Render - - render() { - const { - width, - item, - itemType, - currentOffset - } = this.props; - - if (!currentOffset || itemType !== DELAY_PROFILE) { - return null; - } - - // The offset is shifted because the drag handle is on the right edge of the - // list item and the preview is wider than the drag handle. - - const { x, y } = currentOffset; - const handleOffset = width - dragHandleWidth; - const transform = `translate3d(${x - handleOffset}px, ${y}px, 0)`; - - const style = { - width, - position: 'absolute', - WebkitTransform: transform, - msTransform: transform, - transform - }; - - return ( - -
- -
-
- ); - } -} - -DelayProfileDragPreview.propTypes = { - width: PropTypes.number.isRequired, - item: PropTypes.object, - itemType: PropTypes.string, - currentOffset: PropTypes.shape({ - x: PropTypes.number.isRequired, - y: PropTypes.number.isRequired - }) -}; - -export default DragLayer(collectDragLayer)(DelayProfileDragPreview); diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css b/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css deleted file mode 100644 index 835250678..000000000 --- a/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css +++ /dev/null @@ -1,17 +0,0 @@ -.delayProfileDragSource { - padding: 4px 0; -} - -.delayProfilePlaceholder { - width: 100%; - height: 30px; - border-bottom: 1px dotted #aaa; -} - -.delayProfilePlaceholderBefore { - margin-bottom: 8px; -} - -.delayProfilePlaceholderAfter { - margin-top: 8px; -} diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.js b/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.js deleted file mode 100644 index 8bf739ceb..000000000 --- a/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.js +++ /dev/null @@ -1,148 +0,0 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { DragSource, DropTarget } from 'react-dnd'; -import { findDOMNode } from 'react-dom'; -import { DELAY_PROFILE } from 'Helpers/dragTypes'; -import DelayProfile from './DelayProfile'; -import styles from './DelayProfileDragSource.css'; - -const delayProfileDragSource = { - beginDrag(item) { - return item; - }, - - endDrag(props, monitor, component) { - props.onDelayProfileDragEnd(monitor.getItem(), monitor.didDrop()); - } -}; - -const delayProfileDropTarget = { - hover(props, monitor, component) { - const dragIndex = monitor.getItem().order; - const hoverIndex = props.order; - - const hoverBoundingRect = findDOMNode(component).getBoundingClientRect(); - const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2; - const clientOffset = monitor.getClientOffset(); - const hoverClientY = clientOffset.y - hoverBoundingRect.top; - - if (dragIndex === hoverIndex) { - return; - } - - // When moving up, only trigger if drag position is above 50% and - // when moving down, only trigger if drag position is below 50%. - // If we're moving down the hoverIndex needs to be increased - // by one so it's ordered properly. Otherwise the hoverIndex will work. - - if (dragIndex < hoverIndex && hoverClientY > hoverMiddleY) { - props.onDelayProfileDragMove(dragIndex, hoverIndex + 1); - } else if (dragIndex > hoverIndex && hoverClientY < hoverMiddleY) { - props.onDelayProfileDragMove(dragIndex, hoverIndex); - } - } -}; - -function collectDragSource(connect, monitor) { - return { - connectDragSource: connect.dragSource(), - isDragging: monitor.isDragging() - }; -} - -function collectDropTarget(connect, monitor) { - return { - connectDropTarget: connect.dropTarget(), - isOver: monitor.isOver() - }; -} - -class DelayProfileDragSource extends Component { - - // - // Render - - render() { - const { - id, - order, - isDragging, - isDraggingUp, - isDraggingDown, - isOver, - connectDragSource, - connectDropTarget, - ...otherProps - } = this.props; - - const isBefore = !isDragging && isDraggingUp && isOver; - const isAfter = !isDragging && isDraggingDown && isOver; - - // if (isDragging && !isOver) { - // return null; - // } - - return connectDropTarget( -
- { - isBefore && -
- } - - - - { - isAfter && -
- } -
- ); - } -} - -DelayProfileDragSource.propTypes = { - id: PropTypes.number.isRequired, - order: PropTypes.number.isRequired, - isDragging: PropTypes.bool, - isDraggingUp: PropTypes.bool, - isDraggingDown: PropTypes.bool, - isOver: PropTypes.bool, - connectDragSource: PropTypes.func, - connectDropTarget: PropTypes.func, - onDelayProfileDragMove: PropTypes.func.isRequired, - onDelayProfileDragEnd: PropTypes.func.isRequired -}; - -export default DropTarget( - DELAY_PROFILE, - delayProfileDropTarget, - collectDropTarget -)(DragSource( - DELAY_PROFILE, - delayProfileDragSource, - collectDragSource -)(DelayProfileDragSource)); diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfiles.css b/frontend/src/Settings/Profiles/Delay/DelayProfiles.css deleted file mode 100644 index 3cf3e9020..000000000 --- a/frontend/src/Settings/Profiles/Delay/DelayProfiles.css +++ /dev/null @@ -1,27 +0,0 @@ -.delayProfiles { - user-select: none; -} - -.delayProfilesHeader { - display: flex; - margin-bottom: 10px; - font-weight: bold; -} - -.column { - flex: 0 0 200px; -} - -.tags { - flex: 1 0 auto; -} - -.addDelayProfile { - display: flex; - justify-content: flex-end; -} - -.addButton { - width: $dragHandleWidth; - text-align: center; -} diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfiles.js b/frontend/src/Settings/Profiles/Delay/DelayProfiles.js deleted file mode 100644 index 70465dd64..000000000 --- a/frontend/src/Settings/Profiles/Delay/DelayProfiles.js +++ /dev/null @@ -1,149 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FieldSet from 'Components/FieldSet'; -import Icon from 'Components/Icon'; -import Link from 'Components/Link/Link'; -import Measure from 'Components/Measure'; -import PageSectionContent from 'Components/Page/PageSectionContent'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import DelayProfile from './DelayProfile'; -import DelayProfileDragPreview from './DelayProfileDragPreview'; -import DelayProfileDragSource from './DelayProfileDragSource'; -import EditDelayProfileModalConnector from './EditDelayProfileModalConnector'; -import styles from './DelayProfiles.css'; - -class DelayProfiles extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isAddDelayProfileModalOpen: false, - width: 0 - }; - } - - // - // Listeners - - onAddDelayProfilePress = () => { - this.setState({ isAddDelayProfileModalOpen: true }); - } - - onModalClose = () => { - this.setState({ isAddDelayProfileModalOpen: false }); - } - - onMeasure = ({ width }) => { - this.setState({ width }); - } - - // - // Render - - render() { - const { - defaultProfile, - items, - tagList, - dragIndex, - dropIndex, - onConfirmDeleteDelayProfile, - ...otherProps - } = this.props; - - const { - isAddDelayProfileModalOpen, - width - } = this.state; - - const isDragging = dropIndex !== null; - const isDraggingUp = isDragging && dropIndex < dragIndex; - const isDraggingDown = isDragging && dropIndex > dragIndex; - - return ( - -
- -
-
Protocol
-
Usenet Delay
-
Torrent Delay
-
Tags
-
- -
- { - items.map((item, index) => { - return ( - - ); - }) - } - - -
- - { - defaultProfile && -
- -
- } - -
- - - -
- - -
-
-
- ); - } -} - -DelayProfiles.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - defaultProfile: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - tagList: PropTypes.arrayOf(PropTypes.object).isRequired, - dragIndex: PropTypes.number, - dropIndex: PropTypes.number, - onConfirmDeleteDelayProfile: PropTypes.func.isRequired -}; - -export default DelayProfiles; diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfilesConnector.js b/frontend/src/Settings/Profiles/Delay/DelayProfilesConnector.js deleted file mode 100644 index f8621d4a0..000000000 --- a/frontend/src/Settings/Profiles/Delay/DelayProfilesConnector.js +++ /dev/null @@ -1,105 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { deleteDelayProfile, fetchDelayProfiles, reorderDelayProfile } from 'Store/Actions/settingsActions'; -import createTagsSelector from 'Store/Selectors/createTagsSelector'; -import DelayProfiles from './DelayProfiles'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.delayProfiles, - createTagsSelector(), - (delayProfiles, tagList) => { - const defaultProfile = _.find(delayProfiles.items, { id: 1 }); - const items = _.sortBy(_.reject(delayProfiles.items, { id: 1 }), ['order']); - - return { - defaultProfile, - ...delayProfiles, - items, - tagList - }; - } - ); -} - -const mapDispatchToProps = { - fetchDelayProfiles, - deleteDelayProfile, - reorderDelayProfile -}; - -class DelayProfilesConnector extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - dragIndex: null, - dropIndex: null - }; - } - - componentDidMount() { - this.props.fetchDelayProfiles(); - } - - // - // Listeners - - onConfirmDeleteDelayProfile = (id) => { - this.props.deleteDelayProfile({ id }); - } - - onDelayProfileDragMove = (dragIndex, dropIndex) => { - if (this.state.dragIndex !== dragIndex || this.state.dropIndex !== dropIndex) { - this.setState({ - dragIndex, - dropIndex - }); - } - } - - onDelayProfileDragEnd = ({ id }, didDrop) => { - const { - dropIndex - } = this.state; - - if (didDrop && dropIndex !== null) { - this.props.reorderDelayProfile({ id, moveIndex: dropIndex - 1 }); - } - - this.setState({ - dragIndex: null, - dropIndex: null - }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -DelayProfilesConnector.propTypes = { - fetchDelayProfiles: PropTypes.func.isRequired, - deleteDelayProfile: PropTypes.func.isRequired, - reorderDelayProfile: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(DelayProfilesConnector); diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModal.js b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModal.js deleted file mode 100644 index ddcd8cf7f..000000000 --- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModal.js +++ /dev/null @@ -1,27 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import EditDelayProfileModalContentConnector from './EditDelayProfileModalContentConnector'; - -function EditDelayProfileModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -EditDelayProfileModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditDelayProfileModal; diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalConnector.js b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalConnector.js deleted file mode 100644 index a1e8d2dcd..000000000 --- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalConnector.js +++ /dev/null @@ -1,43 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import EditDelayProfileModal from './EditDelayProfileModal'; - -function mapStateToProps() { - return {}; -} - -const mapDispatchToProps = { - clearPendingChanges -}; - -class EditDelayProfileModalConnector extends Component { - - // - // Listeners - - onModalClose = () => { - this.props.clearPendingChanges({ section: 'settings.delayProfiles' }); - this.props.onModalClose(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditDelayProfileModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(mapStateToProps, mapDispatchToProps)(EditDelayProfileModalConnector); diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css deleted file mode 100644 index a2b6014df..000000000 --- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css +++ /dev/null @@ -1,5 +0,0 @@ -.deleteButton { - composes: button from '~Components/Link/Button.css'; - - margin-right: auto; -} diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js deleted file mode 100644 index 78d101144..000000000 --- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js +++ /dev/null @@ -1,189 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Alert from 'Components/Alert'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds } from 'Helpers/Props'; -import { boolSettingShape, numberSettingShape, tagSettingShape } from 'Helpers/Props/Shapes/settingShape'; -import translate from 'Utilities/String/translate'; -import styles from './EditDelayProfileModalContent.css'; - -function EditDelayProfileModalContent(props) { - const { - id, - isFetching, - error, - isSaving, - saveError, - item, - protocol, - protocolOptions, - onInputChange, - onProtocolChange, - onSavePress, - onModalClose, - onDeleteDelayProfilePress, - ...otherProps - } = props; - - const { - enableUsenet, - enableTorrent, - usenetDelay, - torrentDelay, - tags - } = item; - - return ( - - - {id ? 'Edit Delay Profile' : 'Add Delay Profile'} - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToAddANewQualityProfilePleaseTryAgain')} -
- } - - { - !isFetching && !error && -
- - {translate('Protocol')} - - - - - { - enableUsenet.value && - - {translate('UsenetDelay')} - - - - } - - { - enableTorrent.value && - - {translate('TorrentDelay')} - - - - } - - { - id === 1 ? - - This is the default profile. It applies to all movies that don't have an explicit profile. - : - - - {translate('Tags')} - - - - } -
- } -
- - { - id && id > 1 && - - } - - - - - {translate('Save')} - - -
- ); -} - -const delayProfileShape = { - enableUsenet: PropTypes.shape(boolSettingShape).isRequired, - enableTorrent: PropTypes.shape(boolSettingShape).isRequired, - usenetDelay: PropTypes.shape(numberSettingShape).isRequired, - torrentDelay: PropTypes.shape(numberSettingShape).isRequired, - order: PropTypes.shape(numberSettingShape), - tags: PropTypes.shape(tagSettingShape).isRequired -}; - -EditDelayProfileModalContent.propTypes = { - id: PropTypes.number, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.shape(delayProfileShape).isRequired, - protocol: PropTypes.string.isRequired, - protocolOptions: PropTypes.arrayOf(PropTypes.object).isRequired, - onInputChange: PropTypes.func.isRequired, - onProtocolChange: PropTypes.func.isRequired, - onSavePress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired, - onDeleteDelayProfilePress: PropTypes.func -}; - -export default EditDelayProfileModalContent; diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContentConnector.js b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContentConnector.js deleted file mode 100644 index 370966cb7..000000000 --- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContentConnector.js +++ /dev/null @@ -1,178 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { saveDelayProfile, setDelayProfileValue } from 'Store/Actions/settingsActions'; -import selectSettings from 'Store/Selectors/selectSettings'; -import EditDelayProfileModalContent from './EditDelayProfileModalContent'; - -const newDelayProfile = { - enableUsenet: true, - enableTorrent: true, - preferredProtocol: 'usenet', - usenetDelay: 0, - torrentDelay: 0, - tags: [] -}; - -const protocolOptions = [ - { key: 'preferUsenet', value: 'Prefer Usenet' }, - { key: 'preferTorrent', value: 'Prefer Torrent' }, - { key: 'onlyUsenet', value: 'Only Usenet' }, - { key: 'onlyTorrent', value: 'Only Torrent' } -]; - -function createDelayProfileSelector() { - return createSelector( - (state, { id }) => id, - (state) => state.settings.delayProfiles, - (id, delayProfiles) => { - const { - isFetching, - error, - isSaving, - saveError, - pendingChanges, - items - } = delayProfiles; - - const profile = id ? _.find(items, { id }) : newDelayProfile; - const settings = selectSettings(profile, pendingChanges, saveError); - - return { - id, - isFetching, - error, - isSaving, - saveError, - item: settings.settings, - ...settings - }; - } - ); -} - -function createMapStateToProps() { - return createSelector( - createDelayProfileSelector(), - (delayProfile) => { - const enableUsenet = delayProfile.item.enableUsenet.value; - const enableTorrent = delayProfile.item.enableTorrent.value; - const preferredProtocol = delayProfile.item.preferredProtocol.value; - let protocol = 'preferUsenet'; - - if (preferredProtocol === 'usenet') { - protocol = 'preferUsenet'; - } else { - protocol = 'preferTorrent'; - } - - if (!enableUsenet) { - protocol = 'onlyTorrent'; - } - - if (!enableTorrent) { - protocol = 'onlyUsenet'; - } - - return { - protocol, - protocolOptions, - ...delayProfile - }; - } - ); -} - -const mapDispatchToProps = { - setDelayProfileValue, - saveDelayProfile -}; - -class EditDelayProfileModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - if (!this.props.id) { - Object.keys(newDelayProfile).forEach((name) => { - this.props.setDelayProfileValue({ - name, - value: newDelayProfile[name] - }); - }); - } - } - - componentDidUpdate(prevProps, prevState) { - if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) { - this.props.onModalClose(); - } - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setDelayProfileValue({ name, value }); - } - - onProtocolChange = ({ value }) => { - switch (value) { - case 'preferUsenet': - this.props.setDelayProfileValue({ name: 'enableUsenet', value: true }); - this.props.setDelayProfileValue({ name: 'enableTorrent', value: true }); - this.props.setDelayProfileValue({ name: 'preferredProtocol', value: 'usenet' }); - break; - case 'preferTorrent': - this.props.setDelayProfileValue({ name: 'enableUsenet', value: true }); - this.props.setDelayProfileValue({ name: 'enableTorrent', value: true }); - this.props.setDelayProfileValue({ name: 'preferredProtocol', value: 'torrent' }); - break; - case 'onlyUsenet': - this.props.setDelayProfileValue({ name: 'enableUsenet', value: true }); - this.props.setDelayProfileValue({ name: 'enableTorrent', value: false }); - this.props.setDelayProfileValue({ name: 'preferredProtocol', value: 'usenet' }); - break; - case 'onlyTorrent': - this.props.setDelayProfileValue({ name: 'enableUsenet', value: false }); - this.props.setDelayProfileValue({ name: 'enableTorrent', value: true }); - this.props.setDelayProfileValue({ name: 'preferredProtocol', value: 'torrent' }); - break; - default: - throw Error(`Unknown protocol option: ${value}`); - } - } - - onSavePress = () => { - this.props.saveDelayProfile({ id: this.props.id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditDelayProfileModalContentConnector.propTypes = { - id: PropTypes.number, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - setDelayProfileValue: PropTypes.func.isRequired, - saveDelayProfile: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(EditDelayProfileModalContentConnector); diff --git a/frontend/src/Settings/Profiles/Profiles.css b/frontend/src/Settings/Profiles/Profiles.css deleted file mode 100644 index 9198cf815..000000000 --- a/frontend/src/Settings/Profiles/Profiles.css +++ /dev/null @@ -1,6 +0,0 @@ -.addCustomFormatMessage { - color: $helpTextColor; - text-align: center; - font-weight: 300; - font-size: 20px; -} diff --git a/frontend/src/Settings/Profiles/Profiles.js b/frontend/src/Settings/Profiles/Profiles.js deleted file mode 100644 index 2dcdbed0a..000000000 --- a/frontend/src/Settings/Profiles/Profiles.js +++ /dev/null @@ -1,43 +0,0 @@ -import React, { Component } from 'react'; -import { DndProvider } from 'react-dnd'; -import { HTML5Backend } from 'react-dnd-html5-backend'; -import Link from 'Components/Link/Link'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; -import translate from 'Utilities/String/translate'; -import DelayProfilesConnector from './Delay/DelayProfilesConnector'; -import QualityProfilesConnector from './Quality/QualityProfilesConnector'; -import styles from './Profiles.css'; -// Only a single DragDrop Context can exist so it's done here to allow editing -// quality profiles and reordering delay profiles to work. - -class Profiles extends Component { - - // - // Render - - render() { - return ( - - - - - - - -
- Looking for Release Profiles? Try - Custom Formats - instead. -
-
-
-
- ); - } -} - -export default Profiles; diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModal.js b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModal.js deleted file mode 100644 index 261e03262..000000000 --- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModal.js +++ /dev/null @@ -1,61 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import EditQualityProfileModalContentConnector from './EditQualityProfileModalContentConnector'; - -class EditQualityProfileModal extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - height: 'auto' - }; - } - - // - // Listeners - - onContentHeightChange = (height) => { - if (this.state.height === 'auto' || height > this.state.height) { - this.setState({ height }); - } - } - - // - // Render - - render() { - const { - isOpen, - onModalClose, - ...otherProps - } = this.props; - - return ( - - - - ); - } -} - -EditQualityProfileModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditQualityProfileModal; diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalConnector.js b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalConnector.js deleted file mode 100644 index 942949cac..000000000 --- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalConnector.js +++ /dev/null @@ -1,43 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import EditQualityProfileModal from './EditQualityProfileModal'; - -function mapStateToProps() { - return {}; -} - -const mapDispatchToProps = { - clearPendingChanges -}; - -class EditQualityProfileModalConnector extends Component { - - // - // Listeners - - onModalClose = () => { - this.props.clearPendingChanges({ section: 'settings.qualityProfiles' }); - this.props.onModalClose(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditQualityProfileModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(mapStateToProps, mapDispatchToProps)(EditQualityProfileModalConnector); diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css deleted file mode 100644 index 586f99e70..000000000 --- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css +++ /dev/null @@ -1,31 +0,0 @@ -.formGroupsContainer { - display: flex; - flex-wrap: wrap; -} - -.formGroupWrapper, -.formatItemLarge { - flex: 0 0 calc($formGroupSmallWidth - 100px); -} - -.deleteButtonContainer { - margin-right: auto; -} - -.formatItemSmall { - display: none; -} - -@media only screen and (max-width: calc($breakpointLarge + 100px)) { - .formGroupsContainer { - display: block; - } - - .formatItemSmall { - display: block; - } - - .formatItemLarge { - display: none; - } -} diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.js b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.js deleted file mode 100644 index 0b70552e4..000000000 --- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.js +++ /dev/null @@ -1,359 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Button from 'Components/Link/Button'; -import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import Measure from 'Components/Measure'; -import ModalBody from 'Components/Modal/ModalBody'; -import ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes, kinds, sizes } from 'Helpers/Props'; -import dimensions from 'Styles/Variables/dimensions'; -import translate from 'Utilities/String/translate'; -import QualityProfileFormatItems from './QualityProfileFormatItems'; -import QualityProfileItems from './QualityProfileItems'; -import styles from './EditQualityProfileModalContent.css'; - -const MODAL_BODY_PADDING = parseInt(dimensions.modalBodyPadding); - -function getCustomFormatRender(formatItems, otherProps) { - return ( - - ); -} - -class EditQualityProfileModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - headerHeight: 0, - bodyHeight: 0, - footerHeight: 0 - }; - } - - componentDidUpdate(prevProps, prevState) { - const { - headerHeight, - bodyHeight, - footerHeight - } = this.state; - - if ( - headerHeight > 0 && - bodyHeight > 0 && - footerHeight > 0 && - ( - headerHeight !== prevState.headerHeight || - bodyHeight !== prevState.bodyHeight || - footerHeight !== prevState.footerHeight - ) - ) { - const padding = MODAL_BODY_PADDING * 2; - - this.props.onContentHeightChange( - headerHeight + bodyHeight + footerHeight + padding - ); - } - } - - // - // Listeners - - onHeaderMeasure = ({ height }) => { - if (height > this.state.headerHeight) { - this.setState({ headerHeight: height }); - } - } - - onBodyMeasure = ({ height }) => { - - if (height > this.state.bodyHeight) { - this.setState({ bodyHeight: height }); - } - } - - onFooterMeasure = ({ height }) => { - if (height > this.state.footerHeight) { - this.setState({ footerHeight: height }); - } - } - - // - // Render - - render() { - const { - editGroups, - isFetching, - error, - isSaving, - saveError, - qualities, - customFormats, - languages, - item, - isInUse, - onInputChange, - onCutoffChange, - onLanguageChange, - onSavePress, - onModalClose, - onDeleteQualityProfilePress, - ...otherProps - } = this.props; - - const { - id, - name, - upgradeAllowed, - cutoff, - minFormatScore, - cutoffFormatScore, - language, - items, - formatItems - } = item; - - const languageId = language ? language.value.id : 0; - - return ( - - - - {id ? 'Edit Quality Profile' : 'Add Quality Profile'} - - - - - -
- { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToAddANewQualityProfilePleaseTryAgain')} -
- } - - { - !isFetching && !error && -
-
-
- - - Name - - - - - - - - Upgrades Allowed - - - - - - { - upgradeAllowed.value && - - - Upgrade Until Quality - - - - - } - - { - formatItems.value.length > 0 && - - - Minimum Custom Format Score - - - - - } - - { - upgradeAllowed.value && formatItems.value.length > 0 && - - - Upgrade Until Custom Format Score - - - - - } - - - - Language - - - - - -
- {getCustomFormatRender(formatItems, ...otherProps)} -
-
- -
- -
- -
- {getCustomFormatRender(formatItems, otherProps)} -
-
-
- - } -
-
-
- - - - { - id ? -
- -
: - null - } - - - - - {translate('Save')} - -
-
-
- ); - } -} - -EditQualityProfileModalContent.propTypes = { - editGroups: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - qualities: PropTypes.arrayOf(PropTypes.object).isRequired, - customFormats: PropTypes.arrayOf(PropTypes.object).isRequired, - languages: PropTypes.arrayOf(PropTypes.object).isRequired, - item: PropTypes.object.isRequired, - isInUse: PropTypes.bool.isRequired, - onInputChange: PropTypes.func.isRequired, - onCutoffChange: PropTypes.func.isRequired, - onLanguageChange: PropTypes.func.isRequired, - onSavePress: PropTypes.func.isRequired, - onContentHeightChange: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired, - onDeleteQualityProfilePress: PropTypes.func -}; - -export default EditQualityProfileModalContent; diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContentConnector.js b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContentConnector.js deleted file mode 100644 index 8dbf83fa6..000000000 --- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContentConnector.js +++ /dev/null @@ -1,523 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchQualityProfileSchema, saveQualityProfile, setQualityProfileValue } from 'Store/Actions/settingsActions'; -import createProfileInUseSelector from 'Store/Selectors/createProfileInUseSelector'; -import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector'; -import EditQualityProfileModalContent from './EditQualityProfileModalContent'; - -function getQualityItemGroupId(qualityProfile) { - // Get items with an `id` and filter out null/undefined values - const ids = _.filter(_.map(qualityProfile.items.value, 'id'), (i) => i != null); - - return Math.max(1000, ...ids) + 1; -} - -function parseIndex(index) { - const split = index.split('.'); - - if (split.length === 1) { - return [ - null, - parseInt(split[0]) - 1 - ]; - } - - return [ - parseInt(split[0]) - 1, - parseInt(split[1]) - 1 - ]; -} - -function createQualitiesSelector() { - return createSelector( - createProviderSettingsSelector('qualityProfiles'), - (qualityProfile) => { - const items = qualityProfile.item.items; - if (!items || !items.value) { - return []; - } - - return _.reduceRight(items.value, (result, { allowed, id, name, quality }) => { - if (allowed) { - if (id) { - result.push({ - key: id, - value: name - }); - } else { - result.push({ - key: quality.id, - value: quality.name - }); - } - } - - return result; - }, []); - } - ); -} - -function createFormatsSelector() { - return createSelector( - createProviderSettingsSelector('qualityProfiles'), - (customFormat) => { - const items = customFormat.item.formatItems; - if (!items || !items.value) { - return []; - } - - return _.reduceRight(items.value, (result, { id, name, format, score }) => { - if (id) { - result.push({ - key: id, - value: name, - score - }); - } else { - result.push({ - key: format, - value: name, - score - }); - } - - return result; - }, []); - } - ); -} - -function createLanguagesSelector() { - return createSelector( - (state) => state.settings.languages, - (languages) => { - const items = languages.items; - - if (!items) { - return []; - } - - const newItems = items.map((item) => { - return { - key: item.id, - value: item.name - }; - }); - - return newItems; - } - ); -} - -function createMapStateToProps() { - return createSelector( - createProviderSettingsSelector('qualityProfiles'), - createQualitiesSelector(), - createFormatsSelector(), - createLanguagesSelector(), - createProfileInUseSelector('qualityProfileId'), - (qualityProfile, qualities, customFormats, languages, isInUse) => { - return { - qualities, - customFormats, - languages, - ...qualityProfile, - isInUse - }; - } - ); -} - -const mapDispatchToProps = { - fetchQualityProfileSchema, - setQualityProfileValue, - saveQualityProfile -}; - -class EditQualityProfileModalContentConnector extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - dragQualityIndex: null, - dropQualityIndex: null, - dropPosition: null, - editGroups: false - }; - } - - componentDidMount() { - if (!this.props.id && !this.props.isPopulated) { - this.props.fetchQualityProfileSchema(); - } - } - - componentDidUpdate(prevProps, prevState) { - if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) { - this.props.onModalClose(); - } - } - - // - // Control - - ensureCutoff = (qualityProfile) => { - const cutoff = qualityProfile.cutoff.value; - - const cutoffItem = _.find(qualityProfile.items.value, (i) => { - if (!cutoff) { - return false; - } - - return i.id === cutoff || (i.quality && i.quality.id === cutoff); - }); - - // If the cutoff isn't allowed anymore or there isn't a cutoff set one - if (!cutoff || !cutoffItem || !cutoffItem.allowed) { - const firstAllowed = _.find(qualityProfile.items.value, { allowed: true }); - let cutoffId = null; - - if (firstAllowed) { - cutoffId = firstAllowed.quality ? firstAllowed.quality.id : firstAllowed.id; - } - - this.props.setQualityProfileValue({ name: 'cutoff', value: cutoffId }); - } - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setQualityProfileValue({ name, value }); - } - - onCutoffChange = ({ name, value }) => { - const id = parseInt(value); - const item = _.find(this.props.item.items.value, (i) => { - if (i.quality) { - return i.quality.id === id; - } - - return i.id === id; - }); - - const cutoffId = item.quality ? item.quality.id : item.id; - - this.props.setQualityProfileValue({ name, value: cutoffId }); - } - - onLanguageChange = ({ name, value }) => { - - const id = parseInt(value); - - const language = _.find(this.props.languages, (item) => item.key === id); - - this.props.setQualityProfileValue({ name, value: { id: language.key, Name: language.value } }); - } - - onSavePress = () => { - this.props.saveQualityProfile({ id: this.props.id }); - } - - onQualityProfileItemAllowedChange = (id, allowed) => { - const qualityProfile = _.cloneDeep(this.props.item); - const items = qualityProfile.items.value; - const item = _.find(qualityProfile.items.value, (i) => i.quality && i.quality.id === id); - - item.allowed = allowed; - - this.props.setQualityProfileValue({ - name: 'items', - value: items - }); - - this.ensureCutoff(qualityProfile); - } - - onQualityProfileFormatItemScoreChange = (id, score) => { - const qualityProfile = _.cloneDeep(this.props.item); - const formatItems = qualityProfile.formatItems.value; - const item = _.find(qualityProfile.formatItems.value, (i) => i.format === id); - - item.score = score; - - this.props.setQualityProfileValue({ - name: 'formatItems', - value: formatItems - }); - } - - onItemGroupAllowedChange = (id, allowed) => { - const qualityProfile = _.cloneDeep(this.props.item); - const items = qualityProfile.items.value; - const item = _.find(qualityProfile.items.value, (i) => i.id === id); - - item.allowed = allowed; - - // Update each item in the group (for consistency only) - item.items.forEach((i) => { - i.allowed = allowed; - }); - - this.props.setQualityProfileValue({ - name: 'items', - value: items - }); - - this.ensureCutoff(qualityProfile); - } - - onItemGroupNameChange = (id, name) => { - const qualityProfile = _.cloneDeep(this.props.item); - const items = qualityProfile.items.value; - const group = _.find(items, (i) => i.id === id); - - group.name = name; - - this.props.setQualityProfileValue({ - name: 'items', - value: items - }); - } - - onCreateGroupPress = (id) => { - const qualityProfile = _.cloneDeep(this.props.item); - const items = qualityProfile.items.value; - const item = _.find(items, (i) => i.quality && i.quality.id === id); - const index = items.indexOf(item); - const groupId = getQualityItemGroupId(qualityProfile); - - const group = { - id: groupId, - name: item.quality.name, - allowed: item.allowed, - items: [ - item - ] - }; - - // Add the group in the same location the quality item was in. - items.splice(index, 1, group); - - this.props.setQualityProfileValue({ - name: 'items', - value: items - }); - - this.ensureCutoff(qualityProfile); - } - - onDeleteGroupPress = (id) => { - const qualityProfile = _.cloneDeep(this.props.item); - const items = qualityProfile.items.value; - const group = _.find(items, (i) => i.id === id); - const index = items.indexOf(group); - - // Add the items in the same location the group was in - items.splice(index, 1, ...group.items); - - this.props.setQualityProfileValue({ - name: 'items', - value: items - }); - - this.ensureCutoff(qualityProfile); - } - - onQualityProfileItemDragMove = (options) => { - const { - dragQualityIndex, - dropQualityIndex, - dropPosition - } = options; - - const [dragGroupIndex, dragItemIndex] = parseIndex(dragQualityIndex); - const [dropGroupIndex, dropItemIndex] = parseIndex(dropQualityIndex); - - if ( - (dropPosition === 'below' && dropItemIndex - 1 === dragItemIndex) || - (dropPosition === 'above' && dropItemIndex + 1 === dragItemIndex) - ) { - if ( - this.state.dragQualityIndex != null && - this.state.dropQualityIndex != null && - this.state.dropPosition != null - ) { - this.setState({ - dragQualityIndex: null, - dropQualityIndex: null, - dropPosition: null - }); - } - - return; - } - - let adjustedDropQualityIndex = dropQualityIndex; - - // Correct dragging out of a group to the position above - if ( - dropPosition === 'above' && - dragGroupIndex !== dropGroupIndex && - dropGroupIndex != null - ) { - // Add 1 to the group index and 2 to the item index so it's inserted above in the correct group - adjustedDropQualityIndex = `${dropGroupIndex + 1}.${dropItemIndex + 2}`; - } - - // Correct inserting above outside a group - if ( - dropPosition === 'above' && - dragGroupIndex !== dropGroupIndex && - dropGroupIndex == null - ) { - // Add 2 to the item index so it's entered in the correct place - adjustedDropQualityIndex = `${dropItemIndex + 2}`; - } - - // Correct inserting below a quality within the same group (when moving a lower item) - if ( - dropPosition === 'below' && - dragGroupIndex === dropGroupIndex && - dropGroupIndex != null && - dragItemIndex < dropItemIndex - ) { - // Add 1 to the group index leave the item index - adjustedDropQualityIndex = `${dropGroupIndex + 1}.${dropItemIndex}`; - } - - // Correct inserting below a quality outside a group (when moving a lower item) - if ( - dropPosition === 'below' && - dragGroupIndex === dropGroupIndex && - dropGroupIndex == null && - dragItemIndex < dropItemIndex - ) { - // Leave the item index so it's inserted below the item - adjustedDropQualityIndex = `${dropItemIndex}`; - } - - if ( - dragQualityIndex !== this.state.dragQualityIndex || - adjustedDropQualityIndex !== this.state.dropQualityIndex || - dropPosition !== this.state.dropPosition - ) { - this.setState({ - dragQualityIndex, - dropQualityIndex: adjustedDropQualityIndex, - dropPosition - }); - } - } - - onQualityProfileItemDragEnd = (didDrop) => { - const { - dragQualityIndex, - dropQualityIndex - } = this.state; - - if (didDrop && dropQualityIndex != null) { - const qualityProfile = _.cloneDeep(this.props.item); - const items = qualityProfile.items.value; - const [dragGroupIndex, dragItemIndex] = parseIndex(dragQualityIndex); - const [dropGroupIndex, dropItemIndex] = parseIndex(dropQualityIndex); - - let item = null; - let dropGroup = null; - - // Get the group before moving anything so we know the correct place to drop it. - if (dropGroupIndex != null) { - dropGroup = items[dropGroupIndex]; - } - - if (dragGroupIndex == null) { - item = items.splice(dragItemIndex, 1)[0]; - } else { - const group = items[dragGroupIndex]; - item = group.items.splice(dragItemIndex, 1)[0]; - - // If the group is now empty, destroy it. - if (!group.items.length) { - items.splice(dragGroupIndex, 1); - } - } - - if (dropGroupIndex == null) { - items.splice(dropItemIndex, 0, item); - } else { - dropGroup.items.splice(dropItemIndex, 0, item); - } - - this.props.setQualityProfileValue({ - name: 'items', - value: items - }); - - this.ensureCutoff(qualityProfile); - } - - this.setState({ - dragQualityIndex: null, - dropQualityIndex: null, - dropPosition: null - }); - } - - onToggleEditGroupsMode = () => { - this.setState({ editGroups: !this.state.editGroups }); - } - - // - // Render - - render() { - if (_.isEmpty(this.props.item.items) && !this.props.isFetching) { - return null; - } - - return ( - - ); - } -} - -EditQualityProfileModalContentConnector.propTypes = { - id: PropTypes.number, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - languages: PropTypes.arrayOf(PropTypes.object).isRequired, - setQualityProfileValue: PropTypes.func.isRequired, - fetchQualityProfileSchema: PropTypes.func.isRequired, - saveQualityProfile: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(EditQualityProfileModalContentConnector); diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfile.css b/frontend/src/Settings/Profiles/Quality/QualityProfile.css deleted file mode 100644 index 2513577a1..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfile.css +++ /dev/null @@ -1,38 +0,0 @@ -.qualityProfile { - composes: card from '~Components/Card.css'; - - width: 300px; -} - -.nameContainer { - display: flex; - justify-content: space-between; -} - -.name { - @add-mixin truncate; - - margin-bottom: 20px; - font-weight: 300; - font-size: 24px; -} - -.cloneButton { - composes: button from '~Components/Link/IconButton.css'; - - height: 36px; -} - -.qualities { - display: flex; - flex-wrap: wrap; - margin-top: 5px; - pointer-events: all; -} - -.tooltipLabel { - composes: label from '~Components/Label.css'; - - margin: 0; - border: none; -} diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfile.js b/frontend/src/Settings/Profiles/Quality/QualityProfile.js deleted file mode 100644 index 75b860e62..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfile.js +++ /dev/null @@ -1,187 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import Label from 'Components/Label'; -import IconButton from 'Components/Link/IconButton'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import Tooltip from 'Components/Tooltip/Tooltip'; -import { icons, kinds, tooltipPositions } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditQualityProfileModalConnector from './EditQualityProfileModalConnector'; -import styles from './QualityProfile.css'; - -class QualityProfile extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditQualityProfileModalOpen: false, - isDeleteQualityProfileModalOpen: false - }; - } - - // - // Listeners - - onEditQualityProfilePress = () => { - this.setState({ isEditQualityProfileModalOpen: true }); - } - - onEditQualityProfileModalClose = () => { - this.setState({ isEditQualityProfileModalOpen: false }); - } - - onDeleteQualityProfilePress = () => { - this.setState({ - isEditQualityProfileModalOpen: false, - isDeleteQualityProfileModalOpen: true - }); - } - - onDeleteQualityProfileModalClose = () => { - this.setState({ isDeleteQualityProfileModalOpen: false }); - } - - onConfirmDeleteQualityProfile = () => { - this.props.onConfirmDeleteQualityProfile(this.props.id); - } - - onCloneQualityProfilePress = () => { - const { - id, - onCloneQualityProfilePress - } = this.props; - - onCloneQualityProfilePress(id); - } - - // - // Render - - render() { - const { - id, - name, - upgradeAllowed, - cutoff, - items, - isDeleting - } = this.props; - - return ( - -
-
- {name} -
- - -
- -
- { - items.map((item) => { - if (!item.allowed) { - return null; - } - - if (item.quality) { - const isCutoff = upgradeAllowed && item.quality.id === cutoff; - - return ( - - ); - } - - const isCutoff = upgradeAllowed && item.id === cutoff; - - return ( - - {item.name} - - } - tooltip={ -
- { - item.items.map((groupItem) => { - return ( - - ); - }) - } -
- } - kind={kinds.INVERSE} - position={tooltipPositions.TOP} - /> - ); - }) - } -
- - - - -
- ); - } -} - -QualityProfile.propTypes = { - id: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - upgradeAllowed: PropTypes.bool.isRequired, - cutoff: PropTypes.number.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - isDeleting: PropTypes.bool.isRequired, - onConfirmDeleteQualityProfile: PropTypes.func.isRequired, - onCloneQualityProfilePress: PropTypes.func.isRequired -}; - -export default QualityProfile; diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.css b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.css deleted file mode 100644 index e3035773e..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.css +++ /dev/null @@ -1,45 +0,0 @@ -.qualityProfileFormatItemContainer { - display: flex; - padding: $qualityProfileItemDragSourcePadding 0; - width: 100%; -} - -.qualityProfileFormatItem { - display: flex; - align-items: stretch; - width: 100%; - border: 1px solid #aaa; - border-radius: 4px; - background: #fafafa; -} - -.formatNameContainer { - display: flex; - flex-grow: 1; - margin-bottom: 0; - margin-left: 14px; - width: 100%; - font-weight: normal; - line-height: $qualityProfileItemHeight; - cursor: text; -} - -.formatName { - display: flex; - flex-grow: 1; -} - -.scoreContainer { - display: flex; - flex-grow: 0; -} - -.scoreInput { - composes: input from '~Components/Form/Input.css'; - - width: 100px; - height: 30px; - border: unset; - border-radius: unset; - background-color: unset; -} diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.js b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.js deleted file mode 100644 index 18d7444ba..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.js +++ /dev/null @@ -1,68 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import NumberInput from 'Components/Form/NumberInput'; -import styles from './QualityProfileFormatItem.css'; - -class QualityProfileFormatItem extends Component { - - // - // Listeners - - onScoreChange = ({ value }) => { - const { - formatId - } = this.props; - - this.props.onScoreChange(formatId, value); - } - - // - // Render - - render() { - const { - name, - score - } = this.props; - - return ( -
-
- - -
-
- ); - } -} - -QualityProfileFormatItem.propTypes = { - formatId: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - score: PropTypes.number.isRequired, - onScoreChange: PropTypes.func -}; - -QualityProfileFormatItem.defaultProps = { - // To handle the case score is deleted during edit - score: 0 -}; - -export default QualityProfileFormatItem; diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.css b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.css deleted file mode 100644 index 6963c8401..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.css +++ /dev/null @@ -1,31 +0,0 @@ -.formats { - margin-top: 10px; - /* TODO: This should consider the number of languages in the list */ - user-select: none; -} - -.headerContainer { - display: flex; - font-weight: bold; - line-height: 35px; -} - -.headerTitle { - display: flex; - flex-grow: 1; -} - -.headerScore { - display: flex; - flex-grow: 0; - padding-left: 16px; - width: 100px; -} - -.addCustomFormatMessage { - max-width: $formGroupExtraSmallWidth; - color: $helpTextColor; - text-align: center; - font-weight: 300; - font-size: 20px; -} diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js deleted file mode 100644 index 21e8152ab..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js +++ /dev/null @@ -1,160 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputHelpText from 'Components/Form/FormInputHelpText'; -import FormLabel from 'Components/Form/FormLabel'; -import Link from 'Components/Link/Link'; -import { sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import QualityProfileFormatItem from './QualityProfileFormatItem'; -import styles from './QualityProfileFormatItems.css'; - -function calcOrder(profileFormatItems) { - const items = profileFormatItems.reduce((acc, cur, index) => { - acc[cur.format] = index; - return acc; - }, {}); - - return [...profileFormatItems].sort((a, b) => { - if (b.score !== a.score) { - return b.score - a.score; - } - return a.name > b.name ? 1 : -1; - }).map((x) => items[x.format]); -} - -class QualityProfileFormatItems extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - order: calcOrder(this.props.profileFormatItems) - }; - } - - // - // Listeners - - onScoreChange = (formatId, value) => { - const { - onQualityProfileFormatItemScoreChange - } = this.props; - - onQualityProfileFormatItemScoreChange(formatId, value); - this.reorderItems(); - } - - reorderItems = _.debounce(() => this.setState({ order: calcOrder(this.props.profileFormatItems) }), 1000); - - // - // Render - - render() { - const { - profileFormatItems, - errors, - warnings - } = this.props; - - const { - order - } = this.state; - - if (profileFormatItems.length < 1) { - return ( -
- Want more control over which downloads are preferred? Add a - Custom Format -
- ); - } - - return ( - - - {translate('CustomFormats')} - - -
- - - { - errors.map((error, index) => { - return ( - - ); - }) - } - - { - warnings.map((warning, index) => { - return ( - - ); - }) - } - -
-
-
- Custom Format -
-
- Score -
-
- { - order.map((index) => { - const { - format, - name, - score - } = profileFormatItems[index]; - return ( - - ); - }) - } -
-
-
- ); - } -} - -QualityProfileFormatItems.propTypes = { - profileFormatItems: PropTypes.arrayOf(PropTypes.object).isRequired, - errors: PropTypes.arrayOf(PropTypes.object), - warnings: PropTypes.arrayOf(PropTypes.object), - onQualityProfileFormatItemScoreChange: PropTypes.func -}; - -QualityProfileFormatItems.defaultProps = { - errors: [], - warnings: [] -}; - -export default QualityProfileFormatItems; diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.css b/frontend/src/Settings/Profiles/Quality/QualityProfileItem.css deleted file mode 100644 index bf54fedc2..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.css +++ /dev/null @@ -1,86 +0,0 @@ -.qualityProfileItem { - display: flex; - align-items: stretch; - width: 100%; - border: 1px solid #aaa; - border-radius: 4px; - background: #fafafa; - - &.isInGroup { - border-style: dashed; - } -} - -.checkInputContainer { - position: relative; - margin-right: 4px; - margin-bottom: 5px; - margin-left: 8px; -} - -.checkInput { - composes: input from '~Components/Form/CheckInput.css'; - - margin-top: 5px; -} - -.qualityNameContainer { - display: flex; - flex-grow: 1; - margin-bottom: 0; - margin-left: 2px; - font-weight: normal; - line-height: $qualityProfileItemHeight; - cursor: pointer; -} - -.qualityName { - &.isInGroup { - margin-left: 14px; - } - - &.notAllowed { - color: #c6c6c6; - } -} - -.createGroupButton { - composes: buton from '~Components/Link/IconButton.css'; - - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - margin-right: 5px; - margin-left: 8px; - width: 20px; -} - -.dragHandle { - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - margin-left: auto; - width: $dragHandleWidth; - text-align: center; - cursor: grab; -} - -.dragIcon { - top: 0; -} - -.isDragging { - opacity: 0.25; -} - -.isPreview { - .qualityName { - margin-left: 14px; - - &.isInGroup { - margin-left: 28px; - } - } -} diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.js b/frontend/src/Settings/Profiles/Quality/QualityProfileItem.js deleted file mode 100644 index 63128da92..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.js +++ /dev/null @@ -1,132 +0,0 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import CheckInput from 'Components/Form/CheckInput'; -import Icon from 'Components/Icon'; -import IconButton from 'Components/Link/IconButton'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './QualityProfileItem.css'; - -class QualityProfileItem extends Component { - - // - // Listeners - - onAllowedChange = ({ value }) => { - const { - qualityId, - onQualityProfileItemAllowedChange - } = this.props; - - onQualityProfileItemAllowedChange(qualityId, value); - } - - onCreateGroupPress = () => { - const { - qualityId, - onCreateGroupPress - } = this.props; - - onCreateGroupPress(qualityId); - } - - // - // Render - - render() { - const { - editGroups, - isPreview, - groupId, - name, - allowed, - isDragging, - isOverCurrent, - connectDragSource - } = this.props; - - return ( -
- - - { - connectDragSource( -
- -
- ) - } -
- ); - } -} - -QualityProfileItem.propTypes = { - editGroups: PropTypes.bool, - isPreview: PropTypes.bool, - groupId: PropTypes.number, - qualityId: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - allowed: PropTypes.bool.isRequired, - isDragging: PropTypes.bool.isRequired, - isOverCurrent: PropTypes.bool.isRequired, - isInGroup: PropTypes.bool, - connectDragSource: PropTypes.func, - onCreateGroupPress: PropTypes.func, - onQualityProfileItemAllowedChange: PropTypes.func -}; - -QualityProfileItem.defaultProps = { - isPreview: false, - isOverCurrent: false, - // The drag preview will not connect the drag handle. - connectDragSource: (node) => node -}; - -export default QualityProfileItem; diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css b/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css deleted file mode 100644 index b927d9bce..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css +++ /dev/null @@ -1,4 +0,0 @@ -.dragPreview { - width: 380px; - opacity: 0.75; -} diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.js b/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.js deleted file mode 100644 index 31290baa9..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.js +++ /dev/null @@ -1,92 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { DragLayer } from 'react-dnd'; -import DragPreviewLayer from 'Components/DragPreviewLayer'; -import { QUALITY_PROFILE_ITEM } from 'Helpers/dragTypes'; -import dimensions from 'Styles/Variables/dimensions.js'; -import QualityProfileItem from './QualityProfileItem'; -import styles from './QualityProfileItemDragPreview.css'; - -const formGroupExtraSmallWidth = parseInt(dimensions.formGroupExtraSmallWidth); -const formLabelSmallWidth = parseInt(dimensions.formLabelSmallWidth); -const formLabelRightMarginWidth = parseInt(dimensions.formLabelRightMarginWidth); -const dragHandleWidth = parseInt(dimensions.dragHandleWidth); - -function collectDragLayer(monitor) { - return { - item: monitor.getItem(), - itemType: monitor.getItemType(), - currentOffset: monitor.getSourceClientOffset() - }; -} - -class QualityProfileItemDragPreview extends Component { - - // - // Render - - render() { - const { - item, - itemType, - currentOffset - } = this.props; - - if (!currentOffset || itemType !== QUALITY_PROFILE_ITEM) { - return null; - } - - // The offset is shifted because the drag handle is on the right edge of the - // list item and the preview is wider than the drag handle. - - const { x, y } = currentOffset; - const handleOffset = formGroupExtraSmallWidth - formLabelSmallWidth - formLabelRightMarginWidth - dragHandleWidth; - const transform = `translate3d(${x - handleOffset}px, ${y}px, 0)`; - - const style = { - position: 'absolute', - WebkitTransform: transform, - msTransform: transform, - transform - }; - - const { - editGroups, - groupId, - qualityId, - name, - allowed - } = item; - - // TODO: Show a different preview for groups - - return ( - -
- -
-
- ); - } -} - -QualityProfileItemDragPreview.propTypes = { - item: PropTypes.object, - itemType: PropTypes.string, - currentOffset: PropTypes.shape({ - x: PropTypes.number.isRequired, - y: PropTypes.number.isRequired - }) -}; - -export default DragLayer(collectDragLayer)(QualityProfileItemDragPreview); diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css b/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css deleted file mode 100644 index d5061cc95..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css +++ /dev/null @@ -1,18 +0,0 @@ -.qualityProfileItemDragSource { - padding: $qualityProfileItemDragSourcePadding 0; -} - -.qualityProfileItemPlaceholder { - width: 100%; - height: $qualityProfileItemHeight; - border: 1px dotted #aaa; - border-radius: 4px; -} - -.qualityProfileItemPlaceholderBefore { - margin-bottom: 8px; -} - -.qualityProfileItemPlaceholderAfter { - margin-top: 8px; -} diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.js b/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.js deleted file mode 100644 index b47470171..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.js +++ /dev/null @@ -1,241 +0,0 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { DragSource, DropTarget } from 'react-dnd'; -import { findDOMNode } from 'react-dom'; -import { QUALITY_PROFILE_ITEM } from 'Helpers/dragTypes'; -import QualityProfileItem from './QualityProfileItem'; -import QualityProfileItemGroup from './QualityProfileItemGroup'; -import styles from './QualityProfileItemDragSource.css'; - -const qualityProfileItemDragSource = { - beginDrag(props) { - const { - editGroups, - qualityIndex, - groupId, - qualityId, - name, - allowed - } = props; - - return { - editGroups, - qualityIndex, - groupId, - qualityId, - isGroup: !qualityId, - name, - allowed - }; - }, - - endDrag(props, monitor, component) { - props.onQualityProfileItemDragEnd(monitor.didDrop()); - } -}; - -const qualityProfileItemDropTarget = { - hover(props, monitor, component) { - const { - qualityIndex: dragQualityIndex, - isGroup: isDragGroup - } = monitor.getItem(); - - const dropQualityIndex = props.qualityIndex; - const isDropGroupItem = !!(props.qualityId && props.groupId); - - // Use childNodeIndex to select the correct node to get the middle of so - // we don't bounce between above and below causing rapid setState calls. - const childNodeIndex = component.props.isOverCurrent && component.props.isDraggingUp ? 1 :0; - const componentDOMNode = findDOMNode(component).children[childNodeIndex]; - const hoverBoundingRect = componentDOMNode.getBoundingClientRect(); - const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2; - const clientOffset = monitor.getClientOffset(); - const hoverClientY = clientOffset.y - hoverBoundingRect.top; - - // If we're hovering over a child don't trigger on the parent - if (!monitor.isOver({ shallow: true })) { - return; - } - - // Don't show targets for dropping on self - if (dragQualityIndex === dropQualityIndex) { - return; - } - - // Don't allow a group to be dropped inside a group - if (isDragGroup && isDropGroupItem) { - return; - } - - let dropPosition = null; - - // Determine drop position based on position over target - if (hoverClientY > hoverMiddleY) { - dropPosition = 'below'; - } else if (hoverClientY < hoverMiddleY) { - dropPosition = 'above'; - } else { - return; - } - - props.onQualityProfileItemDragMove({ - dragQualityIndex, - dropQualityIndex, - dropPosition - }); - } -}; - -function collectDragSource(connect, monitor) { - return { - connectDragSource: connect.dragSource(), - isDragging: monitor.isDragging() - }; -} - -function collectDropTarget(connect, monitor) { - return { - connectDropTarget: connect.dropTarget(), - isOver: monitor.isOver(), - isOverCurrent: monitor.isOver({ shallow: true }) - }; -} - -class QualityProfileItemDragSource extends Component { - - // - // Render - - render() { - const { - editGroups, - groupId, - qualityId, - name, - allowed, - items, - qualityIndex, - isDragging, - isDraggingUp, - isDraggingDown, - isOverCurrent, - connectDragSource, - connectDropTarget, - onCreateGroupPress, - onDeleteGroupPress, - onQualityProfileItemAllowedChange, - onItemGroupAllowedChange, - onItemGroupNameChange, - onQualityProfileItemDragMove, - onQualityProfileItemDragEnd - } = this.props; - - const isBefore = !isDragging && isDraggingUp && isOverCurrent; - const isAfter = !isDragging && isDraggingDown && isOverCurrent; - - return connectDropTarget( -
- { - isBefore && -
- } - - { - !!groupId && qualityId == null && - - } - - { - qualityId != null && - - } - - { - isAfter && -
- } -
- ); - } -} - -QualityProfileItemDragSource.propTypes = { - editGroups: PropTypes.bool.isRequired, - groupId: PropTypes.number, - qualityId: PropTypes.number, - name: PropTypes.string.isRequired, - allowed: PropTypes.bool.isRequired, - items: PropTypes.arrayOf(PropTypes.object), - qualityIndex: PropTypes.string.isRequired, - isDragging: PropTypes.bool, - isDraggingUp: PropTypes.bool, - isDraggingDown: PropTypes.bool, - isOverCurrent: PropTypes.bool, - isInGroup: PropTypes.bool, - connectDragSource: PropTypes.func, - connectDropTarget: PropTypes.func, - onCreateGroupPress: PropTypes.func, - onDeleteGroupPress: PropTypes.func, - onQualityProfileItemAllowedChange: PropTypes.func.isRequired, - onItemGroupAllowedChange: PropTypes.func, - onItemGroupNameChange: PropTypes.func, - onQualityProfileItemDragMove: PropTypes.func.isRequired, - onQualityProfileItemDragEnd: PropTypes.func.isRequired -}; - -export default DropTarget( - QUALITY_PROFILE_ITEM, - qualityProfileItemDropTarget, - collectDropTarget -)(DragSource( - QUALITY_PROFILE_ITEM, - qualityProfileItemDragSource, - collectDragSource -)(QualityProfileItemDragSource)); diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css b/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css deleted file mode 100644 index dad463b28..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css +++ /dev/null @@ -1,106 +0,0 @@ -.qualityProfileItemGroup { - width: 100%; - border: 1px solid #aaa; - border-radius: 4px; - background: #fafafa; - - &.editGroups { - background: #fcfcfc; - } -} - -.qualityProfileItemGroupInfo { - display: flex; - align-items: stretch; - width: 100%; -} - -.checkInputContainer { - composes: checkInputContainer from '~./QualityProfileItem.css'; - - display: flex; - align-items: center; -} - -.checkInput { - composes: checkInput from '~./QualityProfileItem.css'; -} - -.nameInput { - composes: input from '~Components/Form/TextInput.css'; - - margin-top: 4px; - margin-right: 10px; -} - -.nameContainer { - display: flex; - align-items: center; - flex-grow: 1; -} - -.name { - flex-shrink: 0; - - &.notAllowed { - color: #c6c6c6; - } -} - -.groupQualities { - display: flex; - justify-content: flex-end; - flex-grow: 1; - flex-wrap: wrap; - margin: 2px 0 2px 10px; -} - -.qualityNameContainer { - display: flex; - align-items: stretch; - flex-grow: 1; - margin-bottom: 0; - margin-left: 2px; - font-weight: normal; -} - -.qualityNameLabel { - composes: qualityNameContainer; - - cursor: pointer; -} - -.deleteGroupButton { - composes: buton from '~Components/Link/IconButton.css'; - - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - margin-right: 5px; - margin-left: 8px; - width: 20px; -} - -.dragHandle { - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - margin-left: auto; - width: $dragHandleWidth; - text-align: center; - cursor: grab; -} - -.dragIcon { - top: 0; -} - -.isDragging { - opacity: 0.25; -} - -.items { - margin: 0 50px 0 35px; -} diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.js b/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.js deleted file mode 100644 index 2ca323916..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.js +++ /dev/null @@ -1,201 +0,0 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import CheckInput from 'Components/Form/CheckInput'; -import TextInput from 'Components/Form/TextInput'; -import Icon from 'Components/Icon'; -import Label from 'Components/Label'; -import IconButton from 'Components/Link/IconButton'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import QualityProfileItemDragSource from './QualityProfileItemDragSource'; -import styles from './QualityProfileItemGroup.css'; - -class QualityProfileItemGroup extends Component { - - // - // Listeners - - onAllowedChange = ({ value }) => { - const { - groupId, - onItemGroupAllowedChange - } = this.props; - - onItemGroupAllowedChange(groupId, value); - } - - onNameChange = ({ value }) => { - const { - groupId, - onItemGroupNameChange - } = this.props; - - onItemGroupNameChange(groupId, value); - } - - onDeleteGroupPress = ({ value }) => { - const { - groupId, - onDeleteGroupPress - } = this.props; - - onDeleteGroupPress(groupId, value); - } - - // - // Render - - render() { - const { - editGroups, - groupId, - name, - allowed, - items, - qualityIndex, - isDragging, - isDraggingUp, - isDraggingDown, - connectDragSource, - onQualityProfileItemAllowedChange, - onQualityProfileItemDragMove, - onQualityProfileItemDragEnd - } = this.props; - - return ( -
-
- { - editGroups && -
- - - -
- } - - { - !editGroups && - - } - - { - connectDragSource( -
- -
- ) - } -
- - { - editGroups && -
- { - items.map(({ quality }, index) => { - return ( - - ); - }).reverse() - } -
- } -
- ); - } -} - -QualityProfileItemGroup.propTypes = { - editGroups: PropTypes.bool, - groupId: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - allowed: PropTypes.bool.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - qualityIndex: PropTypes.string.isRequired, - isDragging: PropTypes.bool.isRequired, - isDraggingUp: PropTypes.bool.isRequired, - isDraggingDown: PropTypes.bool.isRequired, - connectDragSource: PropTypes.func, - onItemGroupAllowedChange: PropTypes.func.isRequired, - onQualityProfileItemAllowedChange: PropTypes.func.isRequired, - onItemGroupNameChange: PropTypes.func.isRequired, - onDeleteGroupPress: PropTypes.func.isRequired, - onQualityProfileItemDragMove: PropTypes.func.isRequired, - onQualityProfileItemDragEnd: PropTypes.func.isRequired -}; - -QualityProfileItemGroup.defaultProps = { - // The drag preview will not connect the drag handle. - connectDragSource: (node) => node -}; - -export default QualityProfileItemGroup; diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItems.css b/frontend/src/Settings/Profiles/Quality/QualityProfileItems.css deleted file mode 100644 index 002e555a7..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItems.css +++ /dev/null @@ -1,15 +0,0 @@ -.editGroupsButton { - composes: button from '~Components/Link/Button.css'; - - margin-top: 10px; -} - -.editGroupsButtonIcon { - margin-right: 8px; -} - -.qualities { - margin-top: 10px; - transition: min-height 200ms; - user-select: none; -} diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItems.js b/frontend/src/Settings/Profiles/Quality/QualityProfileItems.js deleted file mode 100644 index 2dc40cf4b..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileItems.js +++ /dev/null @@ -1,181 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputHelpText from 'Components/Form/FormInputHelpText'; -import FormLabel from 'Components/Form/FormLabel'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import Measure from 'Components/Measure'; -import { icons, kinds, sizes } from 'Helpers/Props'; -import QualityProfileItemDragPreview from './QualityProfileItemDragPreview'; -import QualityProfileItemDragSource from './QualityProfileItemDragSource'; -import styles from './QualityProfileItems.css'; - -class QualityProfileItems extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - qualitiesHeight: 0, - qualitiesHeightEditGroups: 0 - }; - } - - // - // Listeners - - onMeasure = ({ height }) => { - if (this.props.editGroups) { - this.setState({ - qualitiesHeightEditGroups: height - }); - } else { - this.setState({ qualitiesHeight: height }); - } - } - - onToggleEditGroupsMode = () => { - this.props.onToggleEditGroupsMode(); - } - - // - // Render - - render() { - const { - editGroups, - dropQualityIndex, - dropPosition, - qualityProfileItems, - errors, - warnings, - ...otherProps - } = this.props; - - const { - qualitiesHeight, - qualitiesHeightEditGroups - } = this.state; - - const isDragging = dropQualityIndex !== null; - const isDraggingUp = isDragging && dropPosition === 'above'; - const isDraggingDown = isDragging && dropPosition === 'below'; - const minHeight = editGroups ? qualitiesHeightEditGroups : qualitiesHeight; - - return ( - - - Qualities - - -
- - - { - errors.map((error, index) => { - return ( - - ); - }) - } - - { - warnings.map((warning, index) => { - return ( - - ); - }) - } - - - - -
- { - qualityProfileItems.map(({ id, name, allowed, quality, items }, index) => { - const identifier = quality ? quality.id : id; - - return ( - - ); - }).reverse() - } - - -
-
-
-
- ); - } -} - -QualityProfileItems.propTypes = { - editGroups: PropTypes.bool.isRequired, - dragQualityIndex: PropTypes.string, - dropQualityIndex: PropTypes.string, - dropPosition: PropTypes.string, - qualityProfileItems: PropTypes.arrayOf(PropTypes.object).isRequired, - errors: PropTypes.arrayOf(PropTypes.object), - warnings: PropTypes.arrayOf(PropTypes.object), - onToggleEditGroupsMode: PropTypes.func.isRequired -}; - -QualityProfileItems.defaultProps = { - errors: [], - warnings: [] -}; - -export default QualityProfileItems; diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileNameConnector.js b/frontend/src/Settings/Profiles/Quality/QualityProfileNameConnector.js deleted file mode 100644 index bf13815ff..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileNameConnector.js +++ /dev/null @@ -1,31 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createQualityProfileSelector from 'Store/Selectors/createQualityProfileSelector'; - -function createMapStateToProps() { - return createSelector( - createQualityProfileSelector(), - (qualityProfile) => { - return { - name: qualityProfile.name - }; - } - ); -} - -function QualityProfileNameConnector({ name, ...otherProps }) { - return ( - - {name} - - ); -} - -QualityProfileNameConnector.propTypes = { - qualityProfileId: PropTypes.number.isRequired, - name: PropTypes.string.isRequired -}; - -export default connect(createMapStateToProps)(QualityProfileNameConnector); diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfiles.css b/frontend/src/Settings/Profiles/Quality/QualityProfiles.css deleted file mode 100644 index 437d152d2..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfiles.css +++ /dev/null @@ -1,21 +0,0 @@ -.qualityProfiles { - display: flex; - flex-wrap: wrap; -} - -.addQualityProfile { - composes: qualityProfile from '~./QualityProfile.css'; - - background-color: $cardAlternateBackgroundColor; - color: $gray; - text-align: center; - font-size: 45px; -} - -.center { - display: inline-block; - padding: 5px 20px 0; - border: 1px solid $borderColor; - border-radius: 4px; - background-color: $white; -} diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfiles.js b/frontend/src/Settings/Profiles/Quality/QualityProfiles.js deleted file mode 100644 index c6074f007..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfiles.js +++ /dev/null @@ -1,107 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import FieldSet from 'Components/FieldSet'; -import Icon from 'Components/Icon'; -import PageSectionContent from 'Components/Page/PageSectionContent'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditQualityProfileModalConnector from './EditQualityProfileModalConnector'; -import QualityProfile from './QualityProfile'; -import styles from './QualityProfiles.css'; - -class QualityProfiles extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isQualityProfileModalOpen: false - }; - } - - // - // Listeners - - onCloneQualityProfilePress = (id) => { - this.props.onCloneQualityProfilePress(id); - this.setState({ isQualityProfileModalOpen: true }); - } - - onEditQualityProfilePress = () => { - this.setState({ isQualityProfileModalOpen: true }); - } - - onModalClose = () => { - this.setState({ isQualityProfileModalOpen: false }); - } - - // - // Render - - render() { - const { - items, - isDeleting, - onConfirmDeleteQualityProfile, - onCloneQualityProfilePress, - ...otherProps - } = this.props; - - return ( -
- -
- { - items.map((item) => { - return ( - - ); - }) - } - - -
- -
-
-
- - -
-
- ); - } -} - -QualityProfiles.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - isDeleting: PropTypes.bool.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteQualityProfile: PropTypes.func.isRequired, - onCloneQualityProfilePress: PropTypes.func.isRequired -}; - -export default QualityProfiles; diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfilesConnector.js b/frontend/src/Settings/Profiles/Quality/QualityProfilesConnector.js deleted file mode 100644 index cc6295e4c..000000000 --- a/frontend/src/Settings/Profiles/Quality/QualityProfilesConnector.js +++ /dev/null @@ -1,63 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { cloneQualityProfile, deleteQualityProfile, fetchQualityProfiles } from 'Store/Actions/settingsActions'; -import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector'; -import sortByName from 'Utilities/Array/sortByName'; -import QualityProfiles from './QualityProfiles'; - -function createMapStateToProps() { - return createSelector( - createSortedSectionSelector('settings.qualityProfiles', sortByName), - (qualityProfiles) => qualityProfiles - ); -} - -const mapDispatchToProps = { - dispatchFetchQualityProfiles: fetchQualityProfiles, - dispatchDeleteQualityProfile: deleteQualityProfile, - dispatchCloneQualityProfile: cloneQualityProfile -}; - -class QualityProfilesConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.dispatchFetchQualityProfiles(); - } - - // - // Listeners - - onConfirmDeleteQualityProfile = (id) => { - this.props.dispatchDeleteQualityProfile({ id }); - } - - onCloneQualityProfilePress = (id) => { - this.props.dispatchCloneQualityProfile({ id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -QualityProfilesConnector.propTypes = { - dispatchFetchQualityProfiles: PropTypes.func.isRequired, - dispatchDeleteQualityProfile: PropTypes.func.isRequired, - dispatchCloneQualityProfile: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(QualityProfilesConnector); diff --git a/frontend/src/Settings/Tags/TagsConnector.js b/frontend/src/Settings/Tags/TagsConnector.js index c75bc0c7b..edcfa4918 100644 --- a/frontend/src/Settings/Tags/TagsConnector.js +++ b/frontend/src/Settings/Tags/TagsConnector.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; -import { fetchDelayProfiles, fetchNotifications, fetchRestrictions } from 'Store/Actions/settingsActions'; +import { fetchNotifications } from 'Store/Actions/settingsActions'; import { fetchTagDetails } from 'Store/Actions/tagActions'; import Tags from './Tags'; @@ -26,9 +26,7 @@ function createMapStateToProps() { const mapDispatchToProps = { dispatchFetchTagDetails: fetchTagDetails, - dispatchFetchDelayProfiles: fetchDelayProfiles, - dispatchFetchNotifications: fetchNotifications, - dispatchFetchRestrictions: fetchRestrictions + dispatchFetchNotifications: fetchNotifications }; class MetadatasConnector extends Component { @@ -39,15 +37,11 @@ class MetadatasConnector extends Component { componentDidMount() { const { dispatchFetchTagDetails, - dispatchFetchDelayProfiles, - dispatchFetchNotifications, - dispatchFetchRestrictions + dispatchFetchNotifications } = this.props; dispatchFetchTagDetails(); - dispatchFetchDelayProfiles(); dispatchFetchNotifications(); - dispatchFetchRestrictions(); } // @@ -64,9 +58,7 @@ class MetadatasConnector extends Component { MetadatasConnector.propTypes = { dispatchFetchTagDetails: PropTypes.func.isRequired, - dispatchFetchDelayProfiles: PropTypes.func.isRequired, - dispatchFetchNotifications: PropTypes.func.isRequired, - dispatchFetchRestrictions: PropTypes.func.isRequired + dispatchFetchNotifications: PropTypes.func.isRequired }; export default connect(createMapStateToProps, mapDispatchToProps)(MetadatasConnector); diff --git a/frontend/src/Store/Actions/Settings/customFormatSpecifications.js b/frontend/src/Store/Actions/Settings/customFormatSpecifications.js deleted file mode 100644 index d74898d3e..000000000 --- a/frontend/src/Store/Actions/Settings/customFormatSpecifications.js +++ /dev/null @@ -1,193 +0,0 @@ -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler'; -import createClearReducer from 'Store/Actions/Creators/Reducers/createClearReducer'; -import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; -import getNextId from 'Utilities/State/getNextId'; -import getProviderState from 'Utilities/State/getProviderState'; -import getSectionState from 'Utilities/State/getSectionState'; -import selectProviderSchema from 'Utilities/State/selectProviderSchema'; -import updateSectionState from 'Utilities/State/updateSectionState'; -import { removeItem, set, update, updateItem } from '../baseActions'; - -// -// Variables - -const section = 'settings.customFormatSpecifications'; - -// -// Actions Types - -export const FETCH_CUSTOM_FORMAT_SPECIFICATIONS = 'settings/customFormatSpecifications/fetchCustomFormatSpecifications'; -export const FETCH_CUSTOM_FORMAT_SPECIFICATION_SCHEMA = 'settings/customFormatSpecifications/fetchCustomFormatSpecificationSchema'; -export const SELECT_CUSTOM_FORMAT_SPECIFICATION_SCHEMA = 'settings/customFormatSpecifications/selectCustomFormatSpecificationSchema'; -export const SET_CUSTOM_FORMAT_SPECIFICATION_VALUE = 'settings/customFormatSpecifications/setCustomFormatSpecificationValue'; -export const SET_CUSTOM_FORMAT_SPECIFICATION_FIELD_VALUE = 'settings/customFormatSpecifications/setCustomFormatSpecificationFieldValue'; -export const SAVE_CUSTOM_FORMAT_SPECIFICATION = 'settings/customFormatSpecifications/saveCustomFormatSpecification'; -export const DELETE_CUSTOM_FORMAT_SPECIFICATION = 'settings/customFormatSpecifications/deleteCustomFormatSpecification'; -export const DELETE_ALL_CUSTOM_FORMAT_SPECIFICATION = 'settings/customFormatSpecifications/deleteAllCustomFormatSpecification'; -export const CLONE_CUSTOM_FORMAT_SPECIFICATION = 'settings/customFormatSpecifications/cloneCustomFormatSpecification'; -export const CLEAR_CUSTOM_FORMAT_SPECIFICATIONS = 'settings/customFormatSpecifications/clearCustomFormatSpecifications'; -export const CLEAR_CUSTOM_FORMAT_SPECIFICATION_PENDING = 'settings/customFormatSpecifications/clearCustomFormatSpecificationPending'; -// -// Action Creators - -export const fetchCustomFormatSpecifications = createThunk(FETCH_CUSTOM_FORMAT_SPECIFICATIONS); -export const fetchCustomFormatSpecificationSchema = createThunk(FETCH_CUSTOM_FORMAT_SPECIFICATION_SCHEMA); -export const selectCustomFormatSpecificationSchema = createAction(SELECT_CUSTOM_FORMAT_SPECIFICATION_SCHEMA); - -export const saveCustomFormatSpecification = createThunk(SAVE_CUSTOM_FORMAT_SPECIFICATION); -export const deleteCustomFormatSpecification = createThunk(DELETE_CUSTOM_FORMAT_SPECIFICATION); -export const deleteAllCustomFormatSpecification = createThunk(DELETE_ALL_CUSTOM_FORMAT_SPECIFICATION); - -export const setCustomFormatSpecificationValue = createAction(SET_CUSTOM_FORMAT_SPECIFICATION_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -export const setCustomFormatSpecificationFieldValue = createAction(SET_CUSTOM_FORMAT_SPECIFICATION_FIELD_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -export const cloneCustomFormatSpecification = createAction(CLONE_CUSTOM_FORMAT_SPECIFICATION); - -export const clearCustomFormatSpecification = createAction(CLEAR_CUSTOM_FORMAT_SPECIFICATIONS); - -export const clearCustomFormatSpecificationPending = createThunk(CLEAR_CUSTOM_FORMAT_SPECIFICATION_PENDING); - -// -// Details - -export default { - - // - // State - - defaultState: { - isPopulated: false, - error: null, - isSchemaFetching: false, - isSchemaPopulated: false, - schemaError: null, - schema: [], - selectedSchema: {}, - isSaving: false, - saveError: null, - items: [], - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_CUSTOM_FORMAT_SPECIFICATION_SCHEMA]: createFetchSchemaHandler(section, '/customformat/schema'), - - [FETCH_CUSTOM_FORMAT_SPECIFICATIONS]: (getState, payload, dispatch) => { - let tags = []; - if (payload.id) { - const cfState = getSectionState(getState(), 'settings.customFormats', true); - const cf = cfState.items[cfState.itemMap[payload.id]]; - tags = cf.specifications.map((tag, i) => { - return { - id: i + 1, - ...tag - }; - }); - } - - dispatch(batchActions([ - update({ section, data: tags }), - set({ - section, - isPopulated: true - }) - ])); - }, - - [SAVE_CUSTOM_FORMAT_SPECIFICATION]: (getState, payload, dispatch) => { - const { - id, - ...otherPayload - } = payload; - - const saveData = getProviderState({ id, ...otherPayload }, getState, section, false); - - // we have to set id since not actually posting to server yet - if (!saveData.id) { - saveData.id = getNextId(getState().settings.customFormatSpecifications.items); - } - - dispatch(batchActions([ - updateItem({ section, ...saveData }), - set({ - section, - pendingChanges: {} - }) - ])); - }, - - [DELETE_CUSTOM_FORMAT_SPECIFICATION]: (getState, payload, dispatch) => { - const id = payload.id; - return dispatch(removeItem({ section, id })); - }, - - [DELETE_ALL_CUSTOM_FORMAT_SPECIFICATION]: (getState, payload, dispatch) => { - return dispatch(set({ - section, - items: [] - })); - }, - - [CLEAR_CUSTOM_FORMAT_SPECIFICATION_PENDING]: (getState, payload, dispatch) => { - return dispatch(set({ - section, - pendingChanges: {} - })); - } - }, - - // - // Reducers - - reducers: { - [SET_CUSTOM_FORMAT_SPECIFICATION_VALUE]: createSetSettingValueReducer(section), - [SET_CUSTOM_FORMAT_SPECIFICATION_FIELD_VALUE]: createSetProviderFieldValueReducer(section), - - [SELECT_CUSTOM_FORMAT_SPECIFICATION_SCHEMA]: (state, { payload }) => { - return selectProviderSchema(state, section, payload, (selectedSchema) => { - return selectedSchema; - }); - }, - - [CLONE_CUSTOM_FORMAT_SPECIFICATION]: function(state, { payload }) { - const id = payload.id; - const newState = getSectionState(state, section); - const items = newState.items; - const item = items.find((i) => i.id === id); - const newId = getNextId(newState.items); - const newItem = { - ...item, - id: newId, - name: `${item.name} - Copy` - }; - newState.items = [...items, newItem]; - newState.itemMap[newId] = newState.items.length - 1; - - return updateSectionState(state, section, newState); - }, - - [CLEAR_CUSTOM_FORMAT_SPECIFICATIONS]: createClearReducer(section, { - isPopulated: false, - error: null, - items: [] - }) - } -}; diff --git a/frontend/src/Store/Actions/Settings/customFormats.js b/frontend/src/Store/Actions/Settings/customFormats.js deleted file mode 100644 index 4a175abea..000000000 --- a/frontend/src/Store/Actions/Settings/customFormats.js +++ /dev/null @@ -1,108 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; -import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; -import getSectionState from 'Utilities/State/getSectionState'; -import updateSectionState from 'Utilities/State/updateSectionState'; -import { set } from '../baseActions'; - -// -// Variables - -const section = 'settings.customFormats'; - -// -// Actions Types - -export const FETCH_CUSTOM_FORMATS = 'settings/customFormats/fetchCustomFormats'; -export const SAVE_CUSTOM_FORMAT = 'settings/customFormats/saveCustomFormat'; -export const DELETE_CUSTOM_FORMAT = 'settings/customFormats/deleteCustomFormat'; -export const SET_CUSTOM_FORMAT_VALUE = 'settings/customFormats/setCustomFormatValue'; -export const CLONE_CUSTOM_FORMAT = 'settings/customFormats/cloneCustomFormat'; - -// -// Action Creators - -export const fetchCustomFormats = createThunk(FETCH_CUSTOM_FORMATS); -export const saveCustomFormat = createThunk(SAVE_CUSTOM_FORMAT); -export const deleteCustomFormat = createThunk(DELETE_CUSTOM_FORMAT); - -export const setCustomFormatValue = createAction(SET_CUSTOM_FORMAT_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -export const cloneCustomFormat = createAction(CLONE_CUSTOM_FORMAT); - -// -// Details - -export default { - - // - // State - - defaultState: { - isSchemaFetching: false, - isSchemaPopulated: false, - isFetching: false, - isPopulated: false, - schema: { - includeCustomFormatWhenRenaming: false - }, - error: null, - isDeleting: false, - deleteError: null, - isSaving: false, - saveError: null, - items: [], - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_CUSTOM_FORMATS]: createFetchHandler(section, '/customformat'), - - [DELETE_CUSTOM_FORMAT]: createRemoveItemHandler(section, '/customformat'), - - [SAVE_CUSTOM_FORMAT]: (getState, payload, dispatch) => { - // move the format tags in as a pending change - const state = getState(); - const pendingChanges = state.settings.customFormats.pendingChanges; - pendingChanges.specifications = state.settings.customFormatSpecifications.items; - dispatch(set({ - section, - pendingChanges - })); - - createSaveProviderHandler(section, '/customformat')(getState, payload, dispatch); - } - }, - - // - // Reducers - - reducers: { - [SET_CUSTOM_FORMAT_VALUE]: createSetSettingValueReducer(section), - - [CLONE_CUSTOM_FORMAT]: function(state, { payload }) { - const id = payload.id; - const newState = getSectionState(state, section); - const item = newState.items.find((i) => i.id === id); - const pendingChanges = { ...item, id: 0 }; - delete pendingChanges.id; - - pendingChanges.name = `${pendingChanges.name} - Copy`; - newState.pendingChanges = pendingChanges; - - return updateSectionState(state, section, newState); - } - } - -}; diff --git a/frontend/src/Store/Actions/Settings/delayProfiles.js b/frontend/src/Store/Actions/Settings/delayProfiles.js deleted file mode 100644 index 38abc5841..000000000 --- a/frontend/src/Store/Actions/Settings/delayProfiles.js +++ /dev/null @@ -1,103 +0,0 @@ -import _ from 'lodash'; -import { createAction } from 'redux-actions'; -import { update } from 'Store/Actions/baseActions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler'; -import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; -import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; - -// -// Variables - -const section = 'settings.delayProfiles'; - -// -// Actions Types - -export const FETCH_DELAY_PROFILES = 'settings/delayProfiles/fetchDelayProfiles'; -export const FETCH_DELAY_PROFILE_SCHEMA = 'settings/delayProfiles/fetchDelayProfileSchema'; -export const SAVE_DELAY_PROFILE = 'settings/delayProfiles/saveDelayProfile'; -export const DELETE_DELAY_PROFILE = 'settings/delayProfiles/deleteDelayProfile'; -export const REORDER_DELAY_PROFILE = 'settings/delayProfiles/reorderDelayProfile'; -export const SET_DELAY_PROFILE_VALUE = 'settings/delayProfiles/setDelayProfileValue'; - -// -// Action Creators - -export const fetchDelayProfiles = createThunk(FETCH_DELAY_PROFILES); -export const fetchDelayProfileSchema = createThunk(FETCH_DELAY_PROFILE_SCHEMA); -export const saveDelayProfile = createThunk(SAVE_DELAY_PROFILE); -export const deleteDelayProfile = createThunk(DELETE_DELAY_PROFILE); -export const reorderDelayProfile = createThunk(REORDER_DELAY_PROFILE); - -export const setDelayProfileValue = createAction(SET_DELAY_PROFILE_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - items: [], - isSaving: false, - saveError: null, - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_DELAY_PROFILES]: createFetchHandler(section, '/delayprofile'), - [FETCH_DELAY_PROFILE_SCHEMA]: createFetchSchemaHandler(section, '/delayprofile/schema'), - - [SAVE_DELAY_PROFILE]: createSaveProviderHandler(section, '/delayprofile'), - [DELETE_DELAY_PROFILE]: createRemoveItemHandler(section, '/delayprofile'), - - [REORDER_DELAY_PROFILE]: (getState, payload, dispatch) => { - const { id, moveIndex } = payload; - const moveOrder = moveIndex + 1; - const delayProfiles = getState().settings.delayProfiles.items; - const moving = _.find(delayProfiles, { id }); - - // Don't move if the order hasn't changed - if (moving.order === moveOrder) { - return; - } - - const after = moveIndex > 0 ? _.find(delayProfiles, { order: moveIndex }) : null; - const afterQueryParam = after ? `after=${after.id}` : ''; - - const promise = createAjaxRequest({ - method: 'PUT', - url: `/delayprofile/reorder/${id}?${afterQueryParam}` - }).request; - - promise.done((data) => { - dispatch(update({ section, data })); - }); - } - }, - - // - // Reducers - - reducers: { - [SET_DELAY_PROFILE_VALUE]: createSetSettingValueReducer(section) - } - -}; diff --git a/frontend/src/Store/Actions/Settings/downloadClientOptions.js b/frontend/src/Store/Actions/Settings/downloadClientOptions.js deleted file mode 100644 index 0cd7b285e..000000000 --- a/frontend/src/Store/Actions/Settings/downloadClientOptions.js +++ /dev/null @@ -1,64 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createSaveHandler from 'Store/Actions/Creators/createSaveHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; - -// -// Variables - -const section = 'settings.downloadClientOptions'; - -// -// Actions Types - -export const FETCH_DOWNLOAD_CLIENT_OPTIONS = 'FETCH_DOWNLOAD_CLIENT_OPTIONS'; -export const SET_DOWNLOAD_CLIENT_OPTIONS_VALUE = 'SET_DOWNLOAD_CLIENT_OPTIONS_VALUE'; -export const SAVE_DOWNLOAD_CLIENT_OPTIONS = 'SAVE_DOWNLOAD_CLIENT_OPTIONS'; - -// -// Action Creators - -export const fetchDownloadClientOptions = createThunk(FETCH_DOWNLOAD_CLIENT_OPTIONS); -export const saveDownloadClientOptions = createThunk(SAVE_DOWNLOAD_CLIENT_OPTIONS); -export const setDownloadClientOptionsValue = createAction(SET_DOWNLOAD_CLIENT_OPTIONS_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - pendingChanges: {}, - isSaving: false, - saveError: null, - item: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_DOWNLOAD_CLIENT_OPTIONS]: createFetchHandler(section, '/config/downloadclient'), - [SAVE_DOWNLOAD_CLIENT_OPTIONS]: createSaveHandler(section, '/config/downloadclient') - }, - - // - // Reducers - - reducers: { - [SET_DOWNLOAD_CLIENT_OPTIONS_VALUE]: createSetSettingValueReducer(section) - } - -}; diff --git a/frontend/src/Store/Actions/Settings/downloadClients.js b/frontend/src/Store/Actions/Settings/downloadClients.js deleted file mode 100644 index c18b4db76..000000000 --- a/frontend/src/Store/Actions/Settings/downloadClients.js +++ /dev/null @@ -1,117 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler'; -import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; -import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler'; -import createTestAllProvidersHandler from 'Store/Actions/Creators/createTestAllProvidersHandler'; -import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler'; -import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; -import selectProviderSchema from 'Utilities/State/selectProviderSchema'; - -// -// Variables - -const section = 'settings.downloadClients'; - -// -// Actions Types - -export const FETCH_DOWNLOAD_CLIENTS = 'settings/downloadClients/fetchDownloadClients'; -export const FETCH_DOWNLOAD_CLIENT_SCHEMA = 'settings/downloadClients/fetchDownloadClientSchema'; -export const SELECT_DOWNLOAD_CLIENT_SCHEMA = 'settings/downloadClients/selectDownloadClientSchema'; -export const SET_DOWNLOAD_CLIENT_VALUE = 'settings/downloadClients/setDownloadClientValue'; -export const SET_DOWNLOAD_CLIENT_FIELD_VALUE = 'settings/downloadClients/setDownloadClientFieldValue'; -export const SAVE_DOWNLOAD_CLIENT = 'settings/downloadClients/saveDownloadClient'; -export const CANCEL_SAVE_DOWNLOAD_CLIENT = 'settings/downloadClients/cancelSaveDownloadClient'; -export const DELETE_DOWNLOAD_CLIENT = 'settings/downloadClients/deleteDownloadClient'; -export const TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/testDownloadClient'; -export const CANCEL_TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/cancelTestDownloadClient'; -export const TEST_ALL_DOWNLOAD_CLIENTS = 'settings/downloadClients/testAllDownloadClients'; - -// -// Action Creators - -export const fetchDownloadClients = createThunk(FETCH_DOWNLOAD_CLIENTS); -export const fetchDownloadClientSchema = createThunk(FETCH_DOWNLOAD_CLIENT_SCHEMA); -export const selectDownloadClientSchema = createAction(SELECT_DOWNLOAD_CLIENT_SCHEMA); - -export const saveDownloadClient = createThunk(SAVE_DOWNLOAD_CLIENT); -export const cancelSaveDownloadClient = createThunk(CANCEL_SAVE_DOWNLOAD_CLIENT); -export const deleteDownloadClient = createThunk(DELETE_DOWNLOAD_CLIENT); -export const testDownloadClient = createThunk(TEST_DOWNLOAD_CLIENT); -export const cancelTestDownloadClient = createThunk(CANCEL_TEST_DOWNLOAD_CLIENT); -export const testAllDownloadClients = createThunk(TEST_ALL_DOWNLOAD_CLIENTS); - -export const setDownloadClientValue = createAction(SET_DOWNLOAD_CLIENT_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -export const setDownloadClientFieldValue = createAction(SET_DOWNLOAD_CLIENT_FIELD_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - isSchemaFetching: false, - isSchemaPopulated: false, - schemaError: null, - schema: [], - selectedSchema: {}, - isSaving: false, - saveError: null, - isTesting: false, - isTestingAll: false, - items: [], - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_DOWNLOAD_CLIENTS]: createFetchHandler(section, '/downloadclient'), - [FETCH_DOWNLOAD_CLIENT_SCHEMA]: createFetchSchemaHandler(section, '/downloadclient/schema'), - - [SAVE_DOWNLOAD_CLIENT]: createSaveProviderHandler(section, '/downloadclient'), - [CANCEL_SAVE_DOWNLOAD_CLIENT]: createCancelSaveProviderHandler(section), - [DELETE_DOWNLOAD_CLIENT]: createRemoveItemHandler(section, '/downloadclient'), - [TEST_DOWNLOAD_CLIENT]: createTestProviderHandler(section, '/downloadclient'), - [CANCEL_TEST_DOWNLOAD_CLIENT]: createCancelTestProviderHandler(section), - [TEST_ALL_DOWNLOAD_CLIENTS]: createTestAllProvidersHandler(section, '/downloadclient') - }, - - // - // Reducers - - reducers: { - [SET_DOWNLOAD_CLIENT_VALUE]: createSetSettingValueReducer(section), - [SET_DOWNLOAD_CLIENT_FIELD_VALUE]: createSetProviderFieldValueReducer(section), - - [SELECT_DOWNLOAD_CLIENT_SCHEMA]: (state, { payload }) => { - return selectProviderSchema(state, section, payload, (selectedSchema) => { - selectedSchema.enable = true; - - return selectedSchema; - }); - } - } - -}; diff --git a/frontend/src/Store/Actions/Settings/mediaManagement.js b/frontend/src/Store/Actions/Settings/mediaManagement.js deleted file mode 100644 index b1ace08b0..000000000 --- a/frontend/src/Store/Actions/Settings/mediaManagement.js +++ /dev/null @@ -1,64 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createSaveHandler from 'Store/Actions/Creators/createSaveHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; - -// -// Variables - -const section = 'settings.mediaManagement'; - -// -// Actions Types - -export const FETCH_MEDIA_MANAGEMENT_SETTINGS = 'settings/mediaManagement/fetchMediaManagementSettings'; -export const SAVE_MEDIA_MANAGEMENT_SETTINGS = 'settings/mediaManagement/saveMediaManagementSettings'; -export const SET_MEDIA_MANAGEMENT_SETTINGS_VALUE = 'settings/mediaManagement/setMediaManagementSettingsValue'; - -// -// Action Creators - -export const fetchMediaManagementSettings = createThunk(FETCH_MEDIA_MANAGEMENT_SETTINGS); -export const saveMediaManagementSettings = createThunk(SAVE_MEDIA_MANAGEMENT_SETTINGS); -export const setMediaManagementSettingsValue = createAction(SET_MEDIA_MANAGEMENT_SETTINGS_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - pendingChanges: {}, - isSaving: false, - saveError: null, - item: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_MEDIA_MANAGEMENT_SETTINGS]: createFetchHandler(section, '/config/mediamanagement'), - [SAVE_MEDIA_MANAGEMENT_SETTINGS]: createSaveHandler(section, '/config/mediamanagement') - }, - - // - // Reducers - - reducers: { - [SET_MEDIA_MANAGEMENT_SETTINGS_VALUE]: createSetSettingValueReducer(section) - } - -}; diff --git a/frontend/src/Store/Actions/Settings/metadata.js b/frontend/src/Store/Actions/Settings/metadata.js deleted file mode 100644 index e3a661f6d..000000000 --- a/frontend/src/Store/Actions/Settings/metadata.js +++ /dev/null @@ -1,75 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler'; -import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; - -// -// Variables - -const section = 'settings.metadata'; - -// -// Actions Types - -export const FETCH_METADATA = 'settings/metadata/fetchMetadata'; -export const SET_METADATA_VALUE = 'settings/metadata/setMetadataValue'; -export const SET_METADATA_FIELD_VALUE = 'settings/metadata/setMetadataFieldValue'; -export const SAVE_METADATA = 'settings/metadata/saveMetadata'; - -// -// Action Creators - -export const fetchMetadata = createThunk(FETCH_METADATA); -export const saveMetadata = createThunk(SAVE_METADATA); - -export const setMetadataValue = createAction(SET_METADATA_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -export const setMetadataFieldValue = createAction(SET_METADATA_FIELD_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - isSaving: false, - saveError: null, - items: [], - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_METADATA]: createFetchHandler(section, '/metadata'), - [SAVE_METADATA]: createSaveProviderHandler(section, '/metadata') - }, - - // - // Reducers - - reducers: { - [SET_METADATA_VALUE]: createSetSettingValueReducer(section), - [SET_METADATA_FIELD_VALUE]: createSetProviderFieldValueReducer(section) - } - -}; diff --git a/frontend/src/Store/Actions/Settings/metadataOptions.js b/frontend/src/Store/Actions/Settings/metadataOptions.js deleted file mode 100644 index 395924edf..000000000 --- a/frontend/src/Store/Actions/Settings/metadataOptions.js +++ /dev/null @@ -1,64 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createSaveHandler from 'Store/Actions/Creators/createSaveHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; - -// -// Variables - -const section = 'settings.metadataOptions'; - -// -// Actions Types - -export const FETCH_METADATA_OPTIONS = 'settings/metadataOptions/fetchMetadataOptions'; -export const SAVE_METADATA_OPTIONS = 'settings/metadataOptions/saveMetadataOptions'; -export const SET_METADATA_OPTIONS_VALUE = 'settings/metadataOptions/setMetadataOptionsValue'; - -// -// Action Creators - -export const fetchMetadataOptions = createThunk(FETCH_METADATA_OPTIONS); -export const saveMetadataOptions = createThunk(SAVE_METADATA_OPTIONS); -export const setMetadataOptionsValue = createAction(SET_METADATA_OPTIONS_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - pendingChanges: {}, - isSaving: false, - saveError: null, - item: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_METADATA_OPTIONS]: createFetchHandler(section, '/config/metadata'), - [SAVE_METADATA_OPTIONS]: createSaveHandler(section, '/config/metadata') - }, - - // - // Reducers - - reducers: { - [SET_METADATA_OPTIONS_VALUE]: createSetSettingValueReducer(section) - } - -}; diff --git a/frontend/src/Store/Actions/Settings/naming.js b/frontend/src/Store/Actions/Settings/naming.js deleted file mode 100644 index cf5a6818a..000000000 --- a/frontend/src/Store/Actions/Settings/naming.js +++ /dev/null @@ -1,64 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createSaveHandler from 'Store/Actions/Creators/createSaveHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; - -// -// Variables - -const section = 'settings.naming'; - -// -// Actions Types - -export const FETCH_NAMING_SETTINGS = 'settings/naming/fetchNamingSettings'; -export const SAVE_NAMING_SETTINGS = 'settings/naming/saveNamingSettings'; -export const SET_NAMING_SETTINGS_VALUE = 'settings/naming/setNamingSettingsValue'; - -// -// Action Creators - -export const fetchNamingSettings = createThunk(FETCH_NAMING_SETTINGS); -export const saveNamingSettings = createThunk(SAVE_NAMING_SETTINGS); -export const setNamingSettingsValue = createAction(SET_NAMING_SETTINGS_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - pendingChanges: {}, - isSaving: false, - saveError: null, - item: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_NAMING_SETTINGS]: createFetchHandler(section, '/config/naming'), - [SAVE_NAMING_SETTINGS]: createSaveHandler(section, '/config/naming') - }, - - // - // Reducers - - reducers: { - [SET_NAMING_SETTINGS_VALUE]: createSetSettingValueReducer(section) - } - -}; diff --git a/frontend/src/Store/Actions/Settings/namingExamples.js b/frontend/src/Store/Actions/Settings/namingExamples.js deleted file mode 100644 index 0fef90ce2..000000000 --- a/frontend/src/Store/Actions/Settings/namingExamples.js +++ /dev/null @@ -1,79 +0,0 @@ -import { batchActions } from 'redux-batched-actions'; -import { set, update } from 'Store/Actions/baseActions'; -import { createThunk } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; - -// -// Variables - -const section = 'settings.namingExamples'; - -// -// Actions Types - -export const FETCH_NAMING_EXAMPLES = 'settings/namingExamples/fetchNamingExamples'; - -// -// Action Creators - -export const fetchNamingExamples = createThunk(FETCH_NAMING_EXAMPLES); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - item: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_NAMING_EXAMPLES]: function(getState, payload, dispatch) { - dispatch(set({ section, isFetching: true })); - - const naming = getState().settings.naming; - - const promise = createAjaxRequest({ - url: '/config/naming/examples', - data: Object.assign({}, naming.item, naming.pendingChanges) - }).request; - - promise.done((data) => { - dispatch(batchActions([ - update({ section, data }), - - set({ - section, - isFetching: false, - isPopulated: true, - error: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isFetching: false, - isPopulated: false, - error: xhr - })); - }); - } - }, - - // - // Reducers - - reducers: {} - -}; diff --git a/frontend/src/Store/Actions/Settings/qualityDefinitions.js b/frontend/src/Store/Actions/Settings/qualityDefinitions.js deleted file mode 100644 index b17ec01de..000000000 --- a/frontend/src/Store/Actions/Settings/qualityDefinitions.js +++ /dev/null @@ -1,135 +0,0 @@ -import _ from 'lodash'; -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import { clearPendingChanges, set, update } from 'Store/Actions/baseActions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createSaveHandler from 'Store/Actions/Creators/createSaveHandler'; -import { createThunk } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import getSectionState from 'Utilities/State/getSectionState'; -import updateSectionState from 'Utilities/State/updateSectionState'; - -// -// Variables - -const section = 'settings.qualityDefinitions'; - -// -// Actions Types - -export const FETCH_QUALITY_DEFINITIONS = 'settings/qualityDefinitions/fetchQualityDefinitions'; -export const SAVE_QUALITY_DEFINITIONS = 'settings/qualityDefinitions/saveQualityDefinitions'; -export const SET_QUALITY_DEFINITION_VALUE = 'settings/qualityDefinitions/setQualityDefinitionValue'; - -// -// Action Creators - -export const fetchQualityDefinitions = createThunk(FETCH_QUALITY_DEFINITIONS); -export const saveQualityDefinitions = createThunk(SAVE_QUALITY_DEFINITIONS); - -export const setQualityDefinitionValue = createAction(SET_QUALITY_DEFINITION_VALUE); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - items: [], - isSaving: false, - saveError: null, - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_QUALITY_DEFINITIONS]: createFetchHandler(section, '/qualitydefinition'), - [SAVE_QUALITY_DEFINITIONS]: createSaveHandler(section, '/qualitydefinition'), - - [SAVE_QUALITY_DEFINITIONS]: function(getState, payload, dispatch) { - const qualityDefinitions = getState().settings.qualityDefinitions; - - const upatedDefinitions = Object.keys(qualityDefinitions.pendingChanges).map((key) => { - const id = parseInt(key); - const pendingChanges = qualityDefinitions.pendingChanges[id] || {}; - const item = _.find(qualityDefinitions.items, { id }); - - return Object.assign({}, item, pendingChanges); - }); - - // If there is nothing to save don't bother isSaving - if (!upatedDefinitions || !upatedDefinitions.length) { - return; - } - - dispatch(set({ - section, - isSaving: true - })); - - const promise = createAjaxRequest({ - method: 'PUT', - url: '/qualityDefinition/update', - data: JSON.stringify(upatedDefinitions) - }).request; - - promise.done((data) => { - dispatch(batchActions([ - set({ - section, - isSaving: false, - saveError: null - }), - - update({ section, data }), - clearPendingChanges({ section }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isSaving: false, - saveError: xhr - })); - }); - } - }, - - // - // Reducers - - reducers: { - [SET_QUALITY_DEFINITION_VALUE]: function(state, { payload }) { - const { id, name, value } = payload; - const newState = getSectionState(state, section); - newState.pendingChanges = _.cloneDeep(newState.pendingChanges); - - const pendingState = newState.pendingChanges[id] || {}; - const currentValue = _.find(newState.items, { id })[name]; - - if (currentValue === value) { - delete pendingState[name]; - } else { - pendingState[name] = value; - } - - if (_.isEmpty(pendingState)) { - delete newState.pendingChanges[id]; - } else { - newState.pendingChanges[id] = pendingState; - } - - return updateSectionState(state, section, newState); - } - } - -}; diff --git a/frontend/src/Store/Actions/Settings/qualityProfiles.js b/frontend/src/Store/Actions/Settings/qualityProfiles.js deleted file mode 100644 index 8e6036073..000000000 --- a/frontend/src/Store/Actions/Settings/qualityProfiles.js +++ /dev/null @@ -1,97 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler'; -import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; -import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; -import getSectionState from 'Utilities/State/getSectionState'; -import updateSectionState from 'Utilities/State/updateSectionState'; - -// -// Variables - -const section = 'settings.qualityProfiles'; - -// -// Actions Types - -export const FETCH_QUALITY_PROFILES = 'settings/qualityProfiles/fetchQualityProfiles'; -export const FETCH_QUALITY_PROFILE_SCHEMA = 'settings/qualityProfiles/fetchQualityProfileSchema'; -export const SAVE_QUALITY_PROFILE = 'settings/qualityProfiles/saveQualityProfile'; -export const DELETE_QUALITY_PROFILE = 'settings/qualityProfiles/deleteQualityProfile'; -export const SET_QUALITY_PROFILE_VALUE = 'settings/qualityProfiles/setQualityProfileValue'; -export const CLONE_QUALITY_PROFILE = 'settings/qualityProfiles/cloneQualityProfile'; - -// -// Action Creators - -export const fetchQualityProfiles = createThunk(FETCH_QUALITY_PROFILES); -export const fetchQualityProfileSchema = createThunk(FETCH_QUALITY_PROFILE_SCHEMA); -export const saveQualityProfile = createThunk(SAVE_QUALITY_PROFILE); -export const deleteQualityProfile = createThunk(DELETE_QUALITY_PROFILE); - -export const setQualityProfileValue = createAction(SET_QUALITY_PROFILE_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -export const cloneQualityProfile = createAction(CLONE_QUALITY_PROFILE); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - isDeleting: false, - deleteError: null, - isSchemaFetching: false, - isSchemaPopulated: false, - schemaError: null, - schema: {}, - isSaving: false, - saveError: null, - items: [], - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_QUALITY_PROFILES]: createFetchHandler(section, '/qualityprofile'), - [FETCH_QUALITY_PROFILE_SCHEMA]: createFetchSchemaHandler(section, '/qualityprofile/schema'), - [SAVE_QUALITY_PROFILE]: createSaveProviderHandler(section, '/qualityprofile'), - [DELETE_QUALITY_PROFILE]: createRemoveItemHandler(section, '/qualityprofile') - }, - - // - // Reducers - - reducers: { - [SET_QUALITY_PROFILE_VALUE]: createSetSettingValueReducer(section), - - [CLONE_QUALITY_PROFILE]: function(state, { payload }) { - const id = payload.id; - const newState = getSectionState(state, section); - const item = newState.items.find((i) => i.id === id); - const pendingChanges = { ...item, id: 0 }; - delete pendingChanges.id; - - pendingChanges.name = `${pendingChanges.name} - Copy`; - newState.pendingChanges = pendingChanges; - - return updateSectionState(state, section, newState); - } - } - -}; diff --git a/frontend/src/Store/Actions/Settings/remotePathMappings.js b/frontend/src/Store/Actions/Settings/remotePathMappings.js deleted file mode 100644 index ca7955754..000000000 --- a/frontend/src/Store/Actions/Settings/remotePathMappings.js +++ /dev/null @@ -1,69 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; -import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; - -// -// Variables - -const section = 'settings.remotePathMappings'; - -// -// Actions Types - -export const FETCH_REMOTE_PATH_MAPPINGS = 'settings/remotePathMappings/fetchRemotePathMappings'; -export const SAVE_REMOTE_PATH_MAPPING = 'settings/remotePathMappings/saveRemotePathMapping'; -export const DELETE_REMOTE_PATH_MAPPING = 'settings/remotePathMappings/deleteRemotePathMapping'; -export const SET_REMOTE_PATH_MAPPING_VALUE = 'settings/remotePathMappings/setRemotePathMappingValue'; - -// -// Action Creators - -export const fetchRemotePathMappings = createThunk(FETCH_REMOTE_PATH_MAPPINGS); -export const saveRemotePathMapping = createThunk(SAVE_REMOTE_PATH_MAPPING); -export const deleteRemotePathMapping = createThunk(DELETE_REMOTE_PATH_MAPPING); - -export const setRemotePathMappingValue = createAction(SET_REMOTE_PATH_MAPPING_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - items: [], - isSaving: false, - saveError: null, - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_REMOTE_PATH_MAPPINGS]: createFetchHandler(section, '/remotepathmapping'), - [SAVE_REMOTE_PATH_MAPPING]: createSaveProviderHandler(section, '/remotepathmapping'), - [DELETE_REMOTE_PATH_MAPPING]: createRemoveItemHandler(section, '/remotepathmapping') - }, - - // - // Reducers - - reducers: { - [SET_REMOTE_PATH_MAPPING_VALUE]: createSetSettingValueReducer(section) - } - -}; diff --git a/frontend/src/Store/Actions/Settings/restrictions.js b/frontend/src/Store/Actions/Settings/restrictions.js deleted file mode 100644 index 7e0838593..000000000 --- a/frontend/src/Store/Actions/Settings/restrictions.js +++ /dev/null @@ -1,71 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; -import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; - -// -// Variables - -const section = 'settings.restrictions'; - -// -// Actions Types - -export const FETCH_RESTRICTIONS = 'settings/restrictions/fetchRestrictions'; -export const SAVE_RESTRICTION = 'settings/restrictions/saveRestriction'; -export const DELETE_RESTRICTION = 'settings/restrictions/deleteRestriction'; -export const SET_RESTRICTION_VALUE = 'settings/restrictions/setRestrictionValue'; - -// -// Action Creators - -export const fetchRestrictions = createThunk(FETCH_RESTRICTIONS); -export const saveRestriction = createThunk(SAVE_RESTRICTION); -export const deleteRestriction = createThunk(DELETE_RESTRICTION); - -export const setRestrictionValue = createAction(SET_RESTRICTION_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - isSaving: false, - saveError: null, - items: [], - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_RESTRICTIONS]: createFetchHandler(section, '/restriction'), - - [SAVE_RESTRICTION]: createSaveProviderHandler(section, '/restriction'), - - [DELETE_RESTRICTION]: createRemoveItemHandler(section, '/restriction') - }, - - // - // Reducers - - reducers: { - [SET_RESTRICTION_VALUE]: createSetSettingValueReducer(section) - } - -}; diff --git a/frontend/src/Store/Actions/addMovieActions.js b/frontend/src/Store/Actions/addMovieActions.js deleted file mode 100644 index 4d624df86..000000000 --- a/frontend/src/Store/Actions/addMovieActions.js +++ /dev/null @@ -1,178 +0,0 @@ -import _ from 'lodash'; -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import getNewMovie from 'Utilities/Movie/getNewMovie'; -import getSectionState from 'Utilities/State/getSectionState'; -import updateSectionState from 'Utilities/State/updateSectionState'; -import { set, update, updateItem } from './baseActions'; -import createHandleActions from './Creators/createHandleActions'; -import createSetSettingValueReducer from './Creators/Reducers/createSetSettingValueReducer'; - -// -// Variables - -export const section = 'addMovie'; -let abortCurrentRequest = null; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - error: null, - isAdding: false, - isAdded: false, - addError: null, - items: [], - - defaults: { - rootFolderPath: '', - monitor: 'true', - qualityProfileId: 0, - minimumAvailability: 'announced', - tags: [] - } -}; - -export const persistState = [ - 'addMovie.defaults' -]; - -// -// Actions Types - -export const LOOKUP_MOVIE = 'addMovie/lookupMovie'; -export const ADD_MOVIE = 'addMovie/addMovie'; -export const SET_ADD_MOVIE_VALUE = 'addMovie/setAddMovieValue'; -export const CLEAR_ADD_MOVIE = 'addMovie/clearAddMovie'; -export const SET_ADD_MOVIE_DEFAULT = 'addMovie/setAddMovieDefault'; - -// -// Action Creators - -export const lookupMovie = createThunk(LOOKUP_MOVIE); -export const addMovie = createThunk(ADD_MOVIE); -export const clearAddMovie = createAction(CLEAR_ADD_MOVIE); -export const setAddMovieDefault = createAction(SET_ADD_MOVIE_DEFAULT); - -export const setAddMovieValue = createAction(SET_ADD_MOVIE_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - - [LOOKUP_MOVIE]: function(getState, payload, dispatch) { - dispatch(set({ section, isFetching: true })); - - if (abortCurrentRequest) { - abortCurrentRequest(); - } - - const { request, abortRequest } = createAjaxRequest({ - url: '/movie/lookup', - data: { - term: payload.term - } - }); - - abortCurrentRequest = abortRequest; - - request.done((data) => { - dispatch(batchActions([ - update({ section, data }), - - set({ - section, - isFetching: false, - isPopulated: true, - error: null - }) - ])); - }); - - request.fail((xhr) => { - dispatch(set({ - section, - isFetching: false, - isPopulated: false, - error: xhr.aborted ? null : xhr - })); - }); - }, - - [ADD_MOVIE]: function(getState, payload, dispatch) { - dispatch(set({ section, isAdding: true })); - - const tmdbId = payload.tmdbId; - const items = getState().addMovie.items; - const newMovie = getNewMovie(_.cloneDeep(_.find(items, { tmdbId })), payload); - - const promise = createAjaxRequest({ - url: '/movie', - method: 'POST', - contentType: 'application/json', - data: JSON.stringify(newMovie) - }).request; - - promise.done((data) => { - dispatch(batchActions([ - updateItem({ section: 'movies', ...data }), - - set({ - section, - isAdding: false, - isAdded: true, - addError: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isAdding: false, - isAdded: false, - addError: xhr - })); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [SET_ADD_MOVIE_VALUE]: createSetSettingValueReducer(section), - - [SET_ADD_MOVIE_DEFAULT]: function(state, { payload }) { - const newState = getSectionState(state, section); - - newState.defaults = { - ...newState.defaults, - ...payload - }; - - return updateSectionState(state, section, newState); - }, - - [CLEAR_ADD_MOVIE]: function(state) { - const { - defaults, - view, - ...otherDefaultState - } = defaultState; - - return Object.assign({}, state, otherDefaultState); - } - -}, defaultState, section); diff --git a/frontend/src/Store/Actions/blacklistActions.js b/frontend/src/Store/Actions/blacklistActions.js deleted file mode 100644 index 51e9330e7..000000000 --- a/frontend/src/Store/Actions/blacklistActions.js +++ /dev/null @@ -1,205 +0,0 @@ -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import { sortDirections } from 'Helpers/Props'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers'; -import translate from 'Utilities/String/translate'; -import { set, updateItem } from './baseActions'; -import createHandleActions from './Creators/createHandleActions'; -import createRemoveItemHandler from './Creators/createRemoveItemHandler'; -import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers'; -import createClearReducer from './Creators/Reducers/createClearReducer'; -import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer'; - -// -// Variables - -export const section = 'blacklist'; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - pageSize: 20, - sortKey: 'date', - sortDirection: sortDirections.DESCENDING, - error: null, - items: [], - isRemoving: false, - - columns: [ - { - name: 'movies.sortTitle', - label: translate('MovieTitle'), - isSortable: true, - isVisible: true - }, - { - name: 'sourceTitle', - label: translate('SourceTitle'), - isSortable: true, - isVisible: true - }, - { - name: 'languages', - label: translate('Languages'), - isSortable: true, - isVisible: true - }, - { - name: 'quality', - label: translate('Quality'), - isSortable: true, - isVisible: true - }, - { - name: 'customFormats', - label: translate('Formats'), - isSortable: false, - isVisible: true - }, - { - name: 'date', - label: translate('Date'), - isSortable: true, - isVisible: true - }, - { - name: 'indexer', - label: translate('Indexer'), - isSortable: true, - isVisible: false - }, - { - name: 'actions', - columnLabel: translate('Actions'), - isVisible: true, - isModifiable: false - } - ] -}; - -export const persistState = [ - 'blacklist.pageSize', - 'blacklist.sortKey', - 'blacklist.sortDirection', - 'blacklist.columns' -]; - -// -// Action Types - -export const FETCH_BLACKLIST = 'blacklist/fetchBlacklist'; -export const GOTO_FIRST_BLACKLIST_PAGE = 'blacklist/gotoBlacklistFirstPage'; -export const GOTO_PREVIOUS_BLACKLIST_PAGE = 'blacklist/gotoBlacklistPreviousPage'; -export const GOTO_NEXT_BLACKLIST_PAGE = 'blacklist/gotoBlacklistNextPage'; -export const GOTO_LAST_BLACKLIST_PAGE = 'blacklist/gotoBlacklistLastPage'; -export const GOTO_BLACKLIST_PAGE = 'blacklist/gotoBlacklistPage'; -export const SET_BLACKLIST_SORT = 'blacklist/setBlacklistSort'; -export const SET_BLACKLIST_TABLE_OPTION = 'blacklist/setBlacklistTableOption'; -export const REMOVE_BLACKLIST_ITEM = 'blacklist/removeBlacklistItem'; -export const REMOVE_BLACKLIST_ITEMS = 'blacklist/removeBlacklistItems'; -export const CLEAR_BLACKLIST = 'blacklist/clearBlacklist'; - -// -// Action Creators - -export const fetchBlacklist = createThunk(FETCH_BLACKLIST); -export const gotoBlacklistFirstPage = createThunk(GOTO_FIRST_BLACKLIST_PAGE); -export const gotoBlacklistPreviousPage = createThunk(GOTO_PREVIOUS_BLACKLIST_PAGE); -export const gotoBlacklistNextPage = createThunk(GOTO_NEXT_BLACKLIST_PAGE); -export const gotoBlacklistLastPage = createThunk(GOTO_LAST_BLACKLIST_PAGE); -export const gotoBlacklistPage = createThunk(GOTO_BLACKLIST_PAGE); -export const setBlacklistSort = createThunk(SET_BLACKLIST_SORT); -export const setBlacklistTableOption = createAction(SET_BLACKLIST_TABLE_OPTION); -export const removeBlacklistItem = createThunk(REMOVE_BLACKLIST_ITEM); -export const removeBlacklistItems = createThunk(REMOVE_BLACKLIST_ITEMS); -export const clearBlacklist = createAction(CLEAR_BLACKLIST); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - ...createServerSideCollectionHandlers( - section, - '/blacklist', - fetchBlacklist, - { - [serverSideCollectionHandlers.FETCH]: FETCH_BLACKLIST, - [serverSideCollectionHandlers.FIRST_PAGE]: GOTO_FIRST_BLACKLIST_PAGE, - [serverSideCollectionHandlers.PREVIOUS_PAGE]: GOTO_PREVIOUS_BLACKLIST_PAGE, - [serverSideCollectionHandlers.NEXT_PAGE]: GOTO_NEXT_BLACKLIST_PAGE, - [serverSideCollectionHandlers.LAST_PAGE]: GOTO_LAST_BLACKLIST_PAGE, - [serverSideCollectionHandlers.EXACT_PAGE]: GOTO_BLACKLIST_PAGE, - [serverSideCollectionHandlers.SORT]: SET_BLACKLIST_SORT - }), - - [REMOVE_BLACKLIST_ITEM]: createRemoveItemHandler(section, '/blacklist'), - - [REMOVE_BLACKLIST_ITEMS]: function(getState, payload, dispatch) { - const { - ids - } = payload; - - dispatch(batchActions([ - ...ids.map((id) => { - return updateItem({ - section, - id, - isRemoving: true - }); - }), - - set({ section, isRemoving: true }) - ])); - - const promise = createAjaxRequest({ - url: '/blacklist/bulk', - method: 'DELETE', - dataType: 'json', - data: JSON.stringify({ ids }) - }).request; - - promise.done((data) => { - // Don't use batchActions with thunks - dispatch(fetchBlacklist()); - - dispatch(set({ section, isRemoving: false })); - }); - - promise.fail((xhr) => { - dispatch(batchActions([ - ...ids.map((id) => { - return updateItem({ - section, - id, - isRemoving: false - }); - }), - - set({ section, isRemoving: false }) - ])); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [SET_BLACKLIST_TABLE_OPTION]: createSetTableOptionReducer(section), - - [CLEAR_BLACKLIST]: createClearReducer(section, { - isFetching: false, - isPopulated: false, - error: null, - items: [], - totalPages: 0, - totalRecords: 0 - }) - -}, defaultState, section); diff --git a/frontend/src/Store/Actions/extraFileActions.js b/frontend/src/Store/Actions/extraFileActions.js deleted file mode 100644 index 04d2c728a..000000000 --- a/frontend/src/Store/Actions/extraFileActions.js +++ /dev/null @@ -1,49 +0,0 @@ -import { createAction } from 'redux-actions'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createFetchHandler from './Creators/createFetchHandler'; -import createHandleActions from './Creators/createHandleActions'; - -// -// Variables - -export const section = 'extraFiles'; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - error: null, - items: [] -}; - -// -// Actions Types - -export const FETCH_EXTRA_FILES = 'extraFiles/fetchExtraFiles'; -export const CLEAR_EXTRA_FILES = 'extraFiles/clearExtraFiles'; - -// -// Action Creators - -export const fetchExtraFiles = createThunk(FETCH_EXTRA_FILES); -export const clearExtraFiles = createAction(CLEAR_EXTRA_FILES); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - [FETCH_EXTRA_FILES]: createFetchHandler(section, '/extraFile') -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [CLEAR_EXTRA_FILES]: (state) => { - return Object.assign({}, state, defaultState); - } - -}, defaultState, section); diff --git a/frontend/src/Store/Actions/importMovieActions.js b/frontend/src/Store/Actions/importMovieActions.js deleted file mode 100644 index a3aa59a86..000000000 --- a/frontend/src/Store/Actions/importMovieActions.js +++ /dev/null @@ -1,312 +0,0 @@ -import _ from 'lodash'; -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import getNewMovie from 'Utilities/Movie/getNewMovie'; -import getSectionState from 'Utilities/State/getSectionState'; -import updateSectionState from 'Utilities/State/updateSectionState'; -import { removeItem, set, updateItem } from './baseActions'; -import createHandleActions from './Creators/createHandleActions'; -import { fetchRootFolders } from './rootFolderActions'; - -// -// Variables - -export const section = 'importMovie'; -let concurrentLookups = 0; -let abortCurrentLookup = null; -const queue = []; - -// -// State - -export const defaultState = { - isLookingUpMovie: false, - isImporting: false, - isImported: false, - importError: null, - items: [] -}; - -// -// Actions Types - -export const QUEUE_LOOKUP_MOVIE = 'importMovie/queueLookupMovie'; -export const START_LOOKUP_MOVIE = 'importMovie/startLookupMovie'; -export const CANCEL_LOOKUP_MOVIE = 'importMovie/cancelLookupMovie'; -export const LOOKUP_UNSEARCHED_MOVIES = 'importMovie/lookupUnsearchedMovies'; -export const CLEAR_IMPORT_MOVIE = 'importMovie/clearImportMovie'; -export const SET_IMPORT_MOVIE_VALUE = 'importMovie/setImportMovieValue'; -export const IMPORT_MOVIE = 'importMovie/importMovie'; - -// -// Action Creators - -export const queueLookupMovie = createThunk(QUEUE_LOOKUP_MOVIE); -export const startLookupMovie = createThunk(START_LOOKUP_MOVIE); -export const importMovie = createThunk(IMPORT_MOVIE); -export const lookupUnsearchedMovies = createThunk(LOOKUP_UNSEARCHED_MOVIES); -export const clearImportMovie = createAction(CLEAR_IMPORT_MOVIE); -export const cancelLookupMovie = createAction(CANCEL_LOOKUP_MOVIE); - -export const setImportMovieValue = createAction(SET_IMPORT_MOVIE_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - - [QUEUE_LOOKUP_MOVIE]: function(getState, payload, dispatch) { - const { - name, - path, - term, - topOfQueue = false - } = payload; - - const state = getState().importMovie; - const item = _.find(state.items, { id: name }) || { - id: name, - term, - path, - isFetching: false, - isPopulated: false, - error: null - }; - - dispatch(updateItem({ - section, - ...item, - term, - queued: true, - items: [] - })); - - const itemIndex = queue.indexOf(item.id); - - if (itemIndex >= 0) { - queue.splice(itemIndex, 1); - } - - if (topOfQueue) { - queue.unshift(item.id); - } else { - queue.push(item.id); - } - - if (term && term.length > 2) { - dispatch(startLookupMovie({ start: true })); - } - }, - - [START_LOOKUP_MOVIE]: function(getState, payload, dispatch) { - if (concurrentLookups >= 1) { - return; - } - - const state = getState().importMovie; - - const { - isLookingUpMovie, - items - } = state; - - const queueId = queue[0]; - - if (payload.start && !isLookingUpMovie) { - dispatch(set({ section, isLookingUpMovie: true })); - } else if (!isLookingUpMovie) { - return; - } else if (!queueId) { - dispatch(set({ section, isLookingUpMovie: false })); - return; - } - - concurrentLookups++; - queue.splice(0, 1); - - const queued = items.find((i) => i.id === queueId); - - dispatch(updateItem({ - section, - id: queued.id, - isFetching: true - })); - - const { request, abortRequest } = createAjaxRequest({ - url: '/movie/lookup', - data: { - term: queued.term - } - }); - - abortCurrentLookup = abortRequest; - - request.done((data) => { - dispatch(updateItem({ - section, - id: queued.id, - isFetching: false, - isPopulated: true, - error: null, - items: data, - queued: false, - selectedMovie: queued.selectedMovie || data[0], - updateOnly: true - })); - }); - - request.fail((xhr) => { - dispatch(updateItem({ - section, - id: queued.id, - isFetching: false, - isPopulated: false, - error: xhr, - queued: false, - updateOnly: true - })); - }); - - request.always(() => { - concurrentLookups--; - - dispatch(startLookupMovie()); - }); - }, - - [LOOKUP_UNSEARCHED_MOVIES]: function(getState, payload, dispatch) { - const state = getState().importMovie; - - if (state.isLookingUpMovie) { - return; - } - - state.items.forEach((item) => { - const id = item.id; - - if ( - !item.isPopulated && - !queue.includes(id) - ) { - queue.push(item.id); - } - }); - - if (queue.length) { - dispatch(startLookupMovie({ start: true })); - } - }, - - [IMPORT_MOVIE]: function(getState, payload, dispatch) { - dispatch(set({ section, isImporting: true })); - - const ids = payload.ids; - const items = getState().importMovie.items; - const addedIds = []; - - const allNewMovies = ids.reduce((acc, id) => { - const item = items.find((i) => i.id === id); - const selectedMovie = item.selectedMovie; - - // Make sure we have a selected movie and - // the same movie hasn't been added yet. - if (selectedMovie && !acc.some((a) => a.tmdbId === selectedMovie.tmdbId)) { - const newMovie = getNewMovie(_.cloneDeep(selectedMovie), item); - newMovie.path = item.path; - - addedIds.push(id); - acc.push(newMovie); - } - - return acc; - }, []); - - const promise = createAjaxRequest({ - url: '/movie/import', - method: 'POST', - contentType: 'application/json', - data: JSON.stringify(allNewMovies) - }).request; - - promise.done((data) => { - dispatch(batchActions([ - set({ - section, - isImporting: false, - isImported: true, - importError: null - }), - - ...data.map((movie) => updateItem({ section: 'movies', ...movie })), - - ...addedIds.map((id) => removeItem({ section, id })) - ])); - - dispatch(fetchRootFolders()); - }); - - promise.fail((xhr) => { - dispatch(batchActions([ - set({ - section, - isImporting: false, - isImported: true, - importError: xhr - }), - - ...addedIds.map((id) => updateItem({ - section, - id - })) - ])); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [CANCEL_LOOKUP_MOVIE]: function(state) { - return Object.assign({}, state, { isLookingUpMovie: false }); - }, - - [CLEAR_IMPORT_MOVIE]: function(state) { - if (abortCurrentLookup) { - abortCurrentLookup(); - - abortCurrentLookup = null; - } - - queue.splice(0, queue.length); - - return Object.assign({}, state, defaultState); - }, - - [SET_IMPORT_MOVIE_VALUE]: function(state, { payload }) { - const newState = getSectionState(state, section); - const items = newState.items; - const index = items.findIndex((item) => item.id === payload.id); - - newState.items = [...items]; - - if (index >= 0) { - const item = items[index]; - - newState.items.splice(index, 1, { ...item, ...payload }); - } else { - newState.items.push({ ...payload }); - } - - return updateSectionState(state, section, newState); - } - -}, defaultState, section); diff --git a/frontend/src/Store/Actions/index.js b/frontend/src/Store/Actions/index.js index 3de50b558..53281e985 100644 --- a/frontend/src/Store/Actions/index.js +++ b/frontend/src/Store/Actions/index.js @@ -1,54 +1,30 @@ -import * as addMovie from './addMovieActions'; import * as app from './appActions'; -import * as blacklist from './blacklistActions'; import * as captcha from './captchaActions'; import * as commands from './commandActions'; import * as customFilters from './customFilterActions'; -import * as extraFiles from './extraFileActions'; import * as history from './historyActions'; -import * as importMovie from './importMovieActions'; -import * as interactiveImportActions from './interactiveImportActions'; import * as movies from './movieActions'; -import * as movieBlacklist from './movieBlacklistActions'; -import * as movieCredits from './movieCreditsActions'; -import * as movieFiles from './movieFileActions'; -import * as movieHistory from './movieHistoryActions'; import * as movieIndex from './movieIndexActions'; import * as oAuth from './oAuthActions'; -import * as organizePreview from './organizePreviewActions'; import * as paths from './pathActions'; import * as providerOptions from './providerOptionActions'; -import * as queue from './queueActions'; import * as releases from './releaseActions'; -import * as rootFolders from './rootFolderActions'; import * as settings from './settingsActions'; import * as system from './systemActions'; import * as tags from './tagActions'; export default [ - addMovie, app, - blacklist, captcha, commands, customFilters, - movieFiles, - extraFiles, history, - importMovie, - interactiveImportActions, oAuth, - organizePreview, paths, providerOptions, - queue, releases, - rootFolders, movies, - movieBlacklist, - movieHistory, movieIndex, - movieCredits, settings, system, tags diff --git a/frontend/src/Store/Actions/interactiveImportActions.js b/frontend/src/Store/Actions/interactiveImportActions.js deleted file mode 100644 index 6f5043555..000000000 --- a/frontend/src/Store/Actions/interactiveImportActions.js +++ /dev/null @@ -1,272 +0,0 @@ -import moment from 'moment'; -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import { sortDirections } from 'Helpers/Props'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import { set, update, updateItem } from './baseActions'; -import createHandleActions from './Creators/createHandleActions'; -import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer'; - -// -// Variables - -export const section = 'interactiveImport'; - -const MAXIMUM_RECENT_FOLDERS = 10; - -let abortCurrentRequest = null; -let currentIds = []; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - isReprocessing: false, - error: null, - items: [], - sortKey: 'quality', - sortDirection: sortDirections.DESCENDING, - recentFolders: [], - importMode: 'move', - sortPredicates: { - relativePath: function(item, direction) { - const relativePath = item.relativePath; - - return relativePath.toLowerCase(); - }, - - movie: function(item, direction) { - const movie = item.movie; - - return movie ? movie.sortTitle : ''; - }, - - quality: function(item, direction) { - return item.qualityWeight || 0; - } - } -}; - -export const persistState = [ - 'interactiveImport.recentFolders', - 'interactiveImport.importMode' -]; - -// -// Actions Types - -export const FETCH_INTERACTIVE_IMPORT_ITEMS = 'interactiveImport/fetchInteractiveImportItems'; -export const REPROCESS_INTERACTIVE_IMPORT_ITEMS = 'interactiveImport/reprocessInteractiveImportItems'; -export const SET_INTERACTIVE_IMPORT_SORT = 'interactiveImport/setInteractiveImportSort'; -export const UPDATE_INTERACTIVE_IMPORT_ITEM = 'interactiveImport/updateInteractiveImportItem'; -export const UPDATE_INTERACTIVE_IMPORT_ITEMS = 'interactiveImport/updateInteractiveImportItems'; -export const CLEAR_INTERACTIVE_IMPORT = 'interactiveImport/clearInteractiveImport'; -export const ADD_RECENT_FOLDER = 'interactiveImport/addRecentFolder'; -export const REMOVE_RECENT_FOLDER = 'interactiveImport/removeRecentFolder'; -export const SET_INTERACTIVE_IMPORT_MODE = 'interactiveImport/setInteractiveImportMode'; - -// -// Action Creators - -export const fetchInteractiveImportItems = createThunk(FETCH_INTERACTIVE_IMPORT_ITEMS); -export const reprocessInteractiveImportItems = createThunk(REPROCESS_INTERACTIVE_IMPORT_ITEMS); -export const setInteractiveImportSort = createAction(SET_INTERACTIVE_IMPORT_SORT); -export const updateInteractiveImportItem = createAction(UPDATE_INTERACTIVE_IMPORT_ITEM); -export const updateInteractiveImportItems = createAction(UPDATE_INTERACTIVE_IMPORT_ITEMS); -export const clearInteractiveImport = createAction(CLEAR_INTERACTIVE_IMPORT); -export const addRecentFolder = createAction(ADD_RECENT_FOLDER); -export const removeRecentFolder = createAction(REMOVE_RECENT_FOLDER); -export const setInteractiveImportMode = createAction(SET_INTERACTIVE_IMPORT_MODE); - -// -// Action Handlers -export const actionHandlers = handleThunks({ - [FETCH_INTERACTIVE_IMPORT_ITEMS]: function(getState, payload, dispatch) { - if (!payload.downloadId && !payload.folder) { - dispatch(set({ section, error: { message: '`downloadId` or `folder` is required.' } })); - return; - } - - dispatch(set({ section, isFetching: true })); - - const promise = createAjaxRequest({ - url: '/manualimport', - data: payload - }).request; - - promise.done((data) => { - dispatch(batchActions([ - update({ section, data }), - - set({ - section, - isFetching: false, - isPopulated: true, - error: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isFetching: false, - isPopulated: false, - error: xhr - })); - }); - }, - - [REPROCESS_INTERACTIVE_IMPORT_ITEMS]: function(getState, payload, dispatch) { - if (abortCurrentRequest) { - abortCurrentRequest(); - } - - dispatch(batchActions([ - ...currentIds.map((id) => updateItem({ - section, - id, - isReprocessing: false, - updateOnly: true - })), - ...payload.ids.map((id) => updateItem({ - section, - id, - isReprocessing: true, - updateOnly: true - })) - ])); - - const items = getState()[section].items; - - const requestPayload = payload.ids.map((id) => { - const item = items.find((i) => i.id === id); - - return { - id, - path: item.path, - movieId: item.movie.id, - downloadId: item.downloadId - }; - }); - - const { request, abortRequest } = createAjaxRequest({ - method: 'POST', - url: '/manualimport', - contentType: 'application/json', - data: JSON.stringify(requestPayload) - }); - - abortCurrentRequest = abortRequest; - currentIds = payload.ids; - - request.done((data) => { - dispatch(batchActions( - data.map((item) => updateItem({ - section, - ...item, - isReprocessing: false, - updateOnly: true - })) - )); - }); - - request.fail((xhr) => { - if (xhr.aborted) { - return; - } - - dispatch(batchActions( - payload.ids.map((id) => updateItem({ - section, - id, - isReprocessing: false, - updateOnly: true - })) - )); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [UPDATE_INTERACTIVE_IMPORT_ITEM]: (state, { payload }) => { - const id = payload.id; - const newState = Object.assign({}, state); - const items = newState.items; - const index = items.findIndex((item) => item.id === id); - const item = Object.assign({}, items[index], payload); - - newState.items = [...items]; - newState.items.splice(index, 1, item); - - return newState; - }, - - [UPDATE_INTERACTIVE_IMPORT_ITEMS]: (state, { payload }) => { - const ids = payload.ids; - const newState = Object.assign({}, state); - const items = [...newState.items]; - - ids.forEach((id) => { - const index = items.findIndex((item) => item.id === id); - const item = Object.assign({}, items[index], payload); - - items.splice(index, 1, item); - }); - - newState.items = items; - - return newState; - }, - - [ADD_RECENT_FOLDER]: function(state, { payload }) { - const folder = payload.folder; - const recentFolder = { folder, lastUsed: moment().toISOString() }; - const recentFolders = [...state.recentFolders]; - const index = recentFolders.findIndex((r) => r.folder === folder); - - if (index > -1) { - recentFolders.splice(index, 1); - } - - recentFolders.push(recentFolder); - - const sliceIndex = Math.max(recentFolders.length - MAXIMUM_RECENT_FOLDERS, 0); - - return Object.assign({}, state, { recentFolders: recentFolders.slice(sliceIndex) }); - }, - - [REMOVE_RECENT_FOLDER]: function(state, { payload }) { - const folder = payload.folder; - const recentFolders = [...state.recentFolders]; - const index = recentFolders.findIndex((r) => r.folder === folder); - - recentFolders.splice(index, 1); - - return Object.assign({}, state, { recentFolders }); - }, - - [CLEAR_INTERACTIVE_IMPORT]: function(state) { - const newState = { - ...defaultState, - recentFolders: state.recentFolders, - importMode: state.importMode - }; - - return newState; - }, - - [SET_INTERACTIVE_IMPORT_SORT]: createSetClientSideCollectionSortReducer(section), - - [SET_INTERACTIVE_IMPORT_MODE]: function(state, { payload }) { - return Object.assign({}, state, { importMode: payload.importMode }); - } - -}, defaultState, section); diff --git a/frontend/src/Store/Actions/movieBlacklistActions.js b/frontend/src/Store/Actions/movieBlacklistActions.js deleted file mode 100644 index 08c3c2baf..000000000 --- a/frontend/src/Store/Actions/movieBlacklistActions.js +++ /dev/null @@ -1,82 +0,0 @@ -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import { set, update } from './baseActions'; -import createHandleActions from './Creators/createHandleActions'; - -// -// Variables - -export const section = 'movieBlacklist'; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - error: null, - items: [] -}; - -// -// Actions Types - -export const FETCH_MOVIE_BLACKLIST = 'movieBlacklist/fetchMovieBlacklist'; -export const CLEAR_MOVIE_BLACKLIST = 'movieBlacklist/clearMovieBlacklist'; - -// -// Action Creators - -export const fetchMovieBlacklist = createThunk(FETCH_MOVIE_BLACKLIST); -export const clearMovieBlacklist = createAction(CLEAR_MOVIE_BLACKLIST); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - - [FETCH_MOVIE_BLACKLIST]: function(getState, payload, dispatch) { - dispatch(set({ section, isFetching: true })); - - const promise = createAjaxRequest({ - url: '/blacklist/movie', - data: payload - }).request; - - promise.done((data) => { - dispatch(batchActions([ - update({ section, data }), - - set({ - section, - isFetching: false, - isPopulated: true, - error: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isFetching: false, - isPopulated: false, - error: xhr - })); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [CLEAR_MOVIE_BLACKLIST]: (state) => { - return Object.assign({}, state, defaultState); - } - -}, defaultState, section); - diff --git a/frontend/src/Store/Actions/movieCreditsActions.js b/frontend/src/Store/Actions/movieCreditsActions.js deleted file mode 100644 index 49f978554..000000000 --- a/frontend/src/Store/Actions/movieCreditsActions.js +++ /dev/null @@ -1,81 +0,0 @@ -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import { set, update } from './baseActions'; -import createHandleActions from './Creators/createHandleActions'; - -// -// Variables - -export const section = 'movieCredits'; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - error: null, - items: [] -}; - -// -// Actions Types - -export const FETCH_MOVIE_CREDITS = 'movieCredits/fetchMovieCredits'; -export const CLEAR_MOVIE_CREDITS = 'movieCredits/clearMovieCredits'; - -// -// Action Creators - -export const fetchMovieCredits = createThunk(FETCH_MOVIE_CREDITS); -export const clearMovieCredits = createAction(CLEAR_MOVIE_CREDITS); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - - [FETCH_MOVIE_CREDITS]: function(getState, payload, dispatch) { - dispatch(set({ section, isFetching: true })); - - const promise = createAjaxRequest({ - url: '/credit', - data: payload - }).request; - - promise.done((data) => { - dispatch(batchActions([ - update({ section, data }), - - set({ - section, - isFetching: false, - isPopulated: true, - error: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isFetching: false, - isPopulated: false, - error: xhr - })); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [CLEAR_MOVIE_CREDITS]: (state) => { - return Object.assign({}, state, defaultState); - } - -}, defaultState, section); diff --git a/frontend/src/Store/Actions/movieFileActions.js b/frontend/src/Store/Actions/movieFileActions.js deleted file mode 100644 index 9e7e99ca6..000000000 --- a/frontend/src/Store/Actions/movieFileActions.js +++ /dev/null @@ -1,238 +0,0 @@ -import _ from 'lodash'; -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import movieEntities from 'Movie/movieEntities'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import { removeItem, set, updateItem } from './baseActions'; -import createFetchHandler from './Creators/createFetchHandler'; -import createHandleActions from './Creators/createHandleActions'; -import createRemoveItemHandler from './Creators/createRemoveItemHandler'; - -// -// Variables - -export const section = 'movieFiles'; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - error: null, - isDeleting: false, - deleteError: null, - isSaving: false, - saveError: null, - items: [] -}; - -// -// Actions Types - -export const FETCH_MOVIE_FILES = 'movieFiles/fetchMovieFiles'; -export const DELETE_MOVIE_FILE = 'movieFiles/deleteMovieFile'; -export const DELETE_MOVIE_FILES = 'movieFiles/deleteMovieFiles'; -export const UPDATE_MOVIE_FILES = 'movieFiles/updateMovieFiles'; -export const CLEAR_MOVIE_FILES = 'movieFiles/clearMovieFiles'; - -// -// Action Creators - -export const fetchMovieFiles = createThunk(FETCH_MOVIE_FILES); -export const deleteMovieFile = createThunk(DELETE_MOVIE_FILE); -export const deleteMovieFiles = createThunk(DELETE_MOVIE_FILES); -export const updateMovieFiles = createThunk(UPDATE_MOVIE_FILES); -export const clearMovieFiles = createAction(CLEAR_MOVIE_FILES); - -// -// Helpers - -const deleteMovieFileHelper = createRemoveItemHandler(section, '/movieFile'); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - [FETCH_MOVIE_FILES]: createFetchHandler(section, '/movieFile'), - - [DELETE_MOVIE_FILE]: function(getState, payload, dispatch) { - const { - id: movieFileId, - movieEntity = movieEntities.MOVIES - } = payload; - - const movieSection = _.last(movieEntity.split('.')); - const deletePromise = deleteMovieFileHelper(getState, payload, dispatch); - - deletePromise.done(() => { - const movies = getState().movies.items; - const moviesWithRemovedFiles = _.filter(movies, { movieFileId }); - - dispatch(batchActions([ - ...moviesWithRemovedFiles.map((movie) => { - return updateItem({ - section: movieSection, - ...movie, - movieFileId: 0, - hasFile: false - }); - }) - ])); - }); - }, - - [DELETE_MOVIE_FILES]: function(getState, payload, dispatch) { - const { - movieFileIds - } = payload; - - dispatch(set({ section, isDeleting: true })); - - const promise = createAjaxRequest({ - url: '/movieFile/bulk', - method: 'DELETE', - dataType: 'json', - data: JSON.stringify({ movieFileIds }) - }).request; - - promise.done(() => { - const movies = getState().movies.items; - const moviesWithRemovedFiles = movieFileIds.reduce((acc, movieFileId) => { - acc.push(..._.filter(movies, { movieFileId })); - - return acc; - }, []); - - dispatch(batchActions([ - ...movieFileIds.map((id) => { - return removeItem({ section, id }); - }), - - ...moviesWithRemovedFiles.map((movie) => { - return updateItem({ - section: 'movies', - ...movie, - movieFileId: 0, - hasFile: false - }); - }), - - set({ - section, - isDeleting: false, - deleteError: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isDeleting: false, - deleteError: xhr - })); - }); - }, - - [UPDATE_MOVIE_FILES]: function(getState, payload, dispatch) { - - const { - movieFileIds, - languages, - indexerFlags, - quality, - edition, - releaseGroup - } = payload; - - dispatch(set({ section, isSaving: true })); - - const data = { - movieFileIds - }; - - if (languages) { - data.languages = languages; - } - - if (indexerFlags !== undefined) { - data.indexerFlags = indexerFlags; - } - - if (quality) { - data.quality = quality; - } - - if (releaseGroup) { - data.releaseGroup = releaseGroup; - } - - if (edition) { - data.edition = edition; - } - - const promise = createAjaxRequest({ - url: '/movieFile/editor', - method: 'PUT', - dataType: 'json', - data: JSON.stringify(data) - }).request; - - promise.done(() => { - dispatch(batchActions([ - ...movieFileIds.map((id) => { - const props = {}; - - if (languages) { - props.languages = languages; - } - - if (indexerFlags) { - props.indexerFlags = indexerFlags; - } - - if (quality) { - props.quality = quality; - } - - if (edition) { - props.edition = edition; - } - - if (releaseGroup) { - props.releaseGroup = releaseGroup; - } - - return updateItem({ section, id, ...props }); - }), - - set({ - section, - isSaving: false, - saveError: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isSaving: false, - saveError: xhr - })); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [CLEAR_MOVIE_FILES]: (state) => { - return Object.assign({}, state, defaultState); - } - -}, defaultState, section); diff --git a/frontend/src/Store/Actions/movieHistoryActions.js b/frontend/src/Store/Actions/movieHistoryActions.js deleted file mode 100644 index 02c1d7428..000000000 --- a/frontend/src/Store/Actions/movieHistoryActions.js +++ /dev/null @@ -1,103 +0,0 @@ -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import { set, update } from './baseActions'; -import createHandleActions from './Creators/createHandleActions'; - -// -// Variables - -export const section = 'movieHistory'; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - error: null, - items: [] -}; - -// -// Actions Types - -export const FETCH_MOVIE_HISTORY = 'movieHistory/fetchMovieHistory'; -export const CLEAR_MOVIE_HISTORY = 'movieHistory/clearMovieHistory'; -export const MOVIE_HISTORY_MARK_AS_FAILED = 'movieHistory/movieHistoryMarkAsFailed'; - -// -// Action Creators - -export const fetchMovieHistory = createThunk(FETCH_MOVIE_HISTORY); -export const clearMovieHistory = createAction(CLEAR_MOVIE_HISTORY); -export const movieHistoryMarkAsFailed = createThunk(MOVIE_HISTORY_MARK_AS_FAILED); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - - [FETCH_MOVIE_HISTORY]: function(getState, payload, dispatch) { - dispatch(set({ section, isFetching: true })); - - const promise = createAjaxRequest({ - url: '/history/movie', - data: payload - }).request; - - promise.done((data) => { - dispatch(batchActions([ - update({ section, data }), - - set({ - section, - isFetching: false, - isPopulated: true, - error: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isFetching: false, - isPopulated: false, - error: xhr - })); - }); - }, - - [MOVIE_HISTORY_MARK_AS_FAILED]: function(getState, payload, dispatch) { - const { - historyId, - movieId - } = payload; - - const promise = createAjaxRequest({ - url: '/history/failed', - method: 'POST', - data: { - id: historyId - } - }).request; - - promise.done(() => { - dispatch(fetchMovieHistory({ movieId })); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [CLEAR_MOVIE_HISTORY]: (state) => { - return Object.assign({}, state, defaultState); - } - -}, defaultState, section); - diff --git a/frontend/src/Store/Actions/movieIndexActions.js b/frontend/src/Store/Actions/movieIndexActions.js index d42e14afb..371f5b200 100644 --- a/frontend/src/Store/Actions/movieIndexActions.js +++ b/frontend/src/Store/Actions/movieIndexActions.js @@ -29,28 +29,6 @@ export const defaultState = { sortDirection: sortDirections.ASCENDING, secondarySortKey: 'sortTitle', secondarySortDirection: sortDirections.ASCENDING, - view: 'posters', - - posterOptions: { - detailedProgressBar: false, - size: 'large', - showTitle: false, - showMonitored: true, - showQualityProfile: true, - showSearchAction: false - }, - - overviewOptions: { - detailedProgressBar: false, - size: 'medium', - showMonitored: true, - showStudio: true, - showQualityProfile: true, - showAdded: false, - showPath: false, - showSizeOnDisk: false, - showSearchAction: false - }, tableOptions: { showSearchAction: false diff --git a/frontend/src/Store/Actions/organizePreviewActions.js b/frontend/src/Store/Actions/organizePreviewActions.js deleted file mode 100644 index 78f943f32..000000000 --- a/frontend/src/Store/Actions/organizePreviewActions.js +++ /dev/null @@ -1,51 +0,0 @@ -import { createAction } from 'redux-actions'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createFetchHandler from './Creators/createFetchHandler'; -import createHandleActions from './Creators/createHandleActions'; - -// -// Variables - -export const section = 'organizePreview'; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - error: null, - items: [] -}; - -// -// Actions Types - -export const FETCH_ORGANIZE_PREVIEW = 'organizePreview/fetchOrganizePreview'; -export const CLEAR_ORGANIZE_PREVIEW = 'organizePreview/clearOrganizePreview'; - -// -// Action Creators - -export const fetchOrganizePreview = createThunk(FETCH_ORGANIZE_PREVIEW); -export const clearOrganizePreview = createAction(CLEAR_ORGANIZE_PREVIEW); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - - [FETCH_ORGANIZE_PREVIEW]: createFetchHandler('organizePreview', '/rename') - -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [CLEAR_ORGANIZE_PREVIEW]: (state) => { - return Object.assign({}, state, defaultState); - } - -}, defaultState, section); diff --git a/frontend/src/Store/Actions/queueActions.js b/frontend/src/Store/Actions/queueActions.js deleted file mode 100644 index d8ec7679d..000000000 --- a/frontend/src/Store/Actions/queueActions.js +++ /dev/null @@ -1,456 +0,0 @@ -import _ from 'lodash'; -import moment from 'moment'; -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import { sortDirections } from 'Helpers/Props'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers'; -import translate from 'Utilities/String/translate'; -import { set, updateItem } from './baseActions'; -import createFetchHandler from './Creators/createFetchHandler'; -import createHandleActions from './Creators/createHandleActions'; -import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers'; -import createClearReducer from './Creators/Reducers/createClearReducer'; -import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer'; - -// -// Variables - -export const section = 'queue'; -const status = `${section}.status`; -const details = `${section}.details`; -const paged = `${section}.paged`; - -// -// State - -export const defaultState = { - options: { - includeUnknownMovieItems: false - }, - - status: { - isFetching: false, - isPopulated: false, - error: null, - item: {} - }, - - details: { - isFetching: false, - isPopulated: false, - error: null, - items: [], - params: {} - }, - - paged: { - isFetching: false, - isPopulated: false, - pageSize: 20, - sortKey: 'timeleft', - sortDirection: sortDirections.ASCENDING, - error: null, - items: [], - isGrabbing: false, - isRemoving: false, - - columns: [ - { - name: 'status', - columnLabel: translate('Status'), - isSortable: true, - isVisible: true, - isModifiable: false - }, - { - name: 'movies.sortTitle', - label: translate('Movie'), - isSortable: true, - isVisible: true - }, - { - name: 'languages', - label: translate('Languages'), - isSortable: true, - isVisible: true - }, - { - name: 'quality', - label: translate('Quality'), - isSortable: true, - isVisible: true - }, - { - name: 'customFormats', - label: translate('Formats'), - isSortable: false, - isVisible: true - }, - { - name: 'protocol', - label: translate('Protocol'), - isSortable: true, - isVisible: false - }, - { - name: 'indexer', - label: translate('Indexer'), - isSortable: true, - isVisible: false - }, - { - name: 'downloadClient', - label: translate('DownloadClient'), - isSortable: true, - isVisible: false - }, - { - name: 'size', - label: translate('Size'), - isSortable: true, - isVisible: false - }, - { - name: 'title', - label: translate('ReleaseTitle'), - isSortable: true, - isVisible: false - }, - { - name: 'outputPath', - label: translate('OutputPath'), - isSortable: false, - isVisible: false - }, - { - name: 'estimatedCompletionTime', - label: translate('Timeleft'), - isSortable: true, - isVisible: true - }, - { - name: 'progress', - label: translate('Progress'), - isSortable: true, - isVisible: true - }, - { - name: 'actions', - columnLabel: translate('Actions'), - isVisible: true, - isModifiable: false - } - ] - }, - sortPredicates: { - estimatedCompletionTime: function(item, direction) { - return moment.duration(item.timeleft).asMilliseconds(); - } - } -}; - -export const persistState = [ - 'queue.options', - 'queue.paged.pageSize', - 'queue.paged.sortKey', - 'queue.paged.sortDirection', - 'queue.paged.columns' -]; - -// -// Helpers - -function fetchDataAugmenter(getState, payload, data) { - data.includeUnknownMovieItems = getState().queue.options.includeUnknownMovieItems; -} - -// -// Actions Types - -export const FETCH_QUEUE_STATUS = 'queue/fetchQueueStatus'; - -export const FETCH_QUEUE_DETAILS = 'queue/fetchQueueDetails'; -export const CLEAR_QUEUE_DETAILS = 'queue/clearQueueDetails'; - -export const FETCH_QUEUE = 'queue/fetchQueue'; -export const GOTO_FIRST_QUEUE_PAGE = 'queue/gotoQueueFirstPage'; -export const GOTO_PREVIOUS_QUEUE_PAGE = 'queue/gotoQueuePreviousPage'; -export const GOTO_NEXT_QUEUE_PAGE = 'queue/gotoQueueNextPage'; -export const GOTO_LAST_QUEUE_PAGE = 'queue/gotoQueueLastPage'; -export const GOTO_QUEUE_PAGE = 'queue/gotoQueuePage'; -export const SET_QUEUE_SORT = 'queue/setQueueSort'; -export const SET_QUEUE_TABLE_OPTION = 'queue/setQueueTableOption'; -export const SET_QUEUE_OPTION = 'queue/setQueueOption'; -export const CLEAR_QUEUE = 'queue/clearQueue'; - -export const GRAB_QUEUE_ITEM = 'queue/grabQueueItem'; -export const GRAB_QUEUE_ITEMS = 'queue/grabQueueItems'; -export const REMOVE_QUEUE_ITEM = 'queue/removeQueueItem'; -export const REMOVE_QUEUE_ITEMS = 'queue/removeQueueItems'; - -// -// Action Creators - -export const fetchQueueStatus = createThunk(FETCH_QUEUE_STATUS); - -export const fetchQueueDetails = createThunk(FETCH_QUEUE_DETAILS); -export const clearQueueDetails = createAction(CLEAR_QUEUE_DETAILS); - -export const fetchQueue = createThunk(FETCH_QUEUE); -export const gotoQueueFirstPage = createThunk(GOTO_FIRST_QUEUE_PAGE); -export const gotoQueuePreviousPage = createThunk(GOTO_PREVIOUS_QUEUE_PAGE); -export const gotoQueueNextPage = createThunk(GOTO_NEXT_QUEUE_PAGE); -export const gotoQueueLastPage = createThunk(GOTO_LAST_QUEUE_PAGE); -export const gotoQueuePage = createThunk(GOTO_QUEUE_PAGE); -export const setQueueSort = createThunk(SET_QUEUE_SORT); -export const setQueueTableOption = createAction(SET_QUEUE_TABLE_OPTION); -export const setQueueOption = createAction(SET_QUEUE_OPTION); -export const clearQueue = createAction(CLEAR_QUEUE); - -export const grabQueueItem = createThunk(GRAB_QUEUE_ITEM); -export const grabQueueItems = createThunk(GRAB_QUEUE_ITEMS); -export const removeQueueItem = createThunk(REMOVE_QUEUE_ITEM); -export const removeQueueItems = createThunk(REMOVE_QUEUE_ITEMS); - -// -// Helpers - -const fetchQueueDetailsHelper = createFetchHandler(details, '/queue/details'); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - - [FETCH_QUEUE_STATUS]: createFetchHandler(status, '/queue/status'), - - [FETCH_QUEUE_DETAILS]: function(getState, payload, dispatch) { - let params = payload; - - // If the payload params are empty try to get params from state. - - if (params && !_.isEmpty(params)) { - dispatch(set({ section: details, params })); - } else { - params = getState().queue.details.params; - } - - fetchQueueDetailsHelper(getState, params, dispatch); - }, - - ...createServerSideCollectionHandlers( - paged, - '/queue', - fetchQueue, - { - [serverSideCollectionHandlers.FETCH]: FETCH_QUEUE, - [serverSideCollectionHandlers.FIRST_PAGE]: GOTO_FIRST_QUEUE_PAGE, - [serverSideCollectionHandlers.PREVIOUS_PAGE]: GOTO_PREVIOUS_QUEUE_PAGE, - [serverSideCollectionHandlers.NEXT_PAGE]: GOTO_NEXT_QUEUE_PAGE, - [serverSideCollectionHandlers.LAST_PAGE]: GOTO_LAST_QUEUE_PAGE, - [serverSideCollectionHandlers.EXACT_PAGE]: GOTO_QUEUE_PAGE, - [serverSideCollectionHandlers.SORT]: SET_QUEUE_SORT - }, - fetchDataAugmenter - ), - - [GRAB_QUEUE_ITEM]: function(getState, payload, dispatch) { - const id = payload.id; - - dispatch(updateItem({ section: paged, id, isGrabbing: true })); - - const promise = createAjaxRequest({ - url: `/queue/grab/${id}`, - method: 'POST' - }).request; - - promise.done((data) => { - dispatch(batchActions([ - fetchQueue(), - - set({ - section: paged, - isGrabbing: false, - grabError: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(updateItem({ - section: paged, - id, - isGrabbing: false, - grabError: xhr - })); - }); - }, - - [GRAB_QUEUE_ITEMS]: function(getState, payload, dispatch) { - const ids = payload.ids; - - dispatch(batchActions([ - ...ids.map((id) => { - return updateItem({ - section: paged, - id, - isGrabbing: true - }); - }), - - set({ - section: paged, - isGrabbing: true - }) - ])); - - const promise = createAjaxRequest({ - url: '/queue/grab/bulk', - method: 'POST', - dataType: 'json', - data: JSON.stringify(payload) - }).request; - - promise.done((data) => { - dispatch(fetchQueue()); - - dispatch(batchActions([ - ...ids.map((id) => { - return updateItem({ - section: paged, - id, - isGrabbing: false, - grabError: null - }); - }), - - set({ - section: paged, - isGrabbing: false, - grabError: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(batchActions([ - ...ids.map((id) => { - return updateItem({ - section: paged, - id, - isGrabbing: false, - grabError: null - }); - }), - - set({ section: paged, isGrabbing: false }) - ])); - }); - }, - - [REMOVE_QUEUE_ITEM]: function(getState, payload, dispatch) { - const { - id, - remove, - blacklist - } = payload; - - dispatch(updateItem({ section: paged, id, isRemoving: true })); - - const promise = createAjaxRequest({ - url: `/queue/${id}?removeFromClient=${remove}&blacklist=${blacklist}`, - method: 'DELETE' - }).request; - - promise.done((data) => { - dispatch(fetchQueue()); - }); - - promise.fail((xhr) => { - dispatch(updateItem({ section: paged, id, isRemoving: false })); - }); - }, - - [REMOVE_QUEUE_ITEMS]: function(getState, payload, dispatch) { - const { - ids, - remove, - blacklist - } = payload; - - dispatch(batchActions([ - ...ids.map((id) => { - return updateItem({ - section: paged, - id, - isRemoving: true - }); - }), - - set({ section: paged, isRemoving: true }) - ])); - - const promise = createAjaxRequest({ - url: `/queue/bulk?removeFromClient=${remove}&blacklist=${blacklist}`, - method: 'DELETE', - dataType: 'json', - data: JSON.stringify({ ids }) - }).request; - - promise.done((data) => { - // Don't use batchActions with thunks - dispatch(fetchQueue()); - - dispatch(set({ section: paged, isRemoving: false })); - }); - - promise.fail((xhr) => { - dispatch(batchActions([ - ...ids.map((id) => { - return updateItem({ - section: paged, - id, - isRemoving: false - }); - }), - - set({ section: paged, isRemoving: false }) - ])); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [CLEAR_QUEUE_DETAILS]: createClearReducer(details, defaultState.details), - - [SET_QUEUE_TABLE_OPTION]: createSetTableOptionReducer(paged), - - [SET_QUEUE_OPTION]: function(state, { payload }) { - const queueOptions = state.options; - - return { - ...state, - options: { - ...queueOptions, - ...payload - } - }; - }, - - [CLEAR_QUEUE]: createClearReducer(paged, { - isFetching: false, - isPopulated: false, - error: null, - items: [], - totalPages: 0, - totalRecords: 0 - }) - -}, defaultState, section); - diff --git a/frontend/src/Store/Actions/rootFolderActions.js b/frontend/src/Store/Actions/rootFolderActions.js deleted file mode 100644 index 5c7cd79ae..000000000 --- a/frontend/src/Store/Actions/rootFolderActions.js +++ /dev/null @@ -1,97 +0,0 @@ -import { batchActions } from 'redux-batched-actions'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import { set, updateItem } from './baseActions'; -import createFetchHandler from './Creators/createFetchHandler'; -import createHandleActions from './Creators/createHandleActions'; -import createRemoveItemHandler from './Creators/createRemoveItemHandler'; - -// -// Variables - -export const section = 'rootFolders'; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - error: null, - isSaving: false, - saveError: null, - items: [] -}; - -// -// Actions Types - -export const FETCH_ROOT_FOLDERS = 'rootFolders/fetchRootFolders'; -export const ADD_ROOT_FOLDER = 'rootFolders/addRootFolder'; -export const DELETE_ROOT_FOLDER = 'rootFolders/deleteRootFolder'; - -// -// Action Creators - -export const fetchRootFolders = createThunk(FETCH_ROOT_FOLDERS); -export const addRootFolder = createThunk(ADD_ROOT_FOLDER); -export const deleteRootFolder = createThunk(DELETE_ROOT_FOLDER); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - - [FETCH_ROOT_FOLDERS]: createFetchHandler('rootFolders', '/rootFolder'), - - [DELETE_ROOT_FOLDER]: createRemoveItemHandler( - 'rootFolders', - '/rootFolder', - (state) => state.rootFolders - ), - - [ADD_ROOT_FOLDER]: function(getState, payload, dispatch) { - const path = payload.path; - - dispatch(set({ - section, - isSaving: true - })); - - const promise = createAjaxRequest({ - url: '/rootFolder', - method: 'POST', - data: JSON.stringify({ path }), - dataType: 'json' - }).request; - - promise.done((data) => { - dispatch(batchActions([ - updateItem({ - section, - ...data - }), - - set({ - section, - isSaving: false, - saveError: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isSaving: false, - saveError: xhr - })); - }); - } - -}); - -// -// Reducers - -export const reducers = createHandleActions({}, defaultState, section); diff --git a/frontend/src/Store/Actions/settingsActions.js b/frontend/src/Store/Actions/settingsActions.js index 3eae6ded7..f5b5cb4c1 100644 --- a/frontend/src/Store/Actions/settingsActions.js +++ b/frontend/src/Store/Actions/settingsActions.js @@ -1,48 +1,20 @@ import { createAction } from 'redux-actions'; import { handleThunks } from 'Store/thunks'; import createHandleActions from './Creators/createHandleActions'; -import customFormats from './Settings/customFormats'; -import customFormatSpecifications from './Settings/customFormatSpecifications'; -import delayProfiles from './Settings/delayProfiles'; -import downloadClientOptions from './Settings/downloadClientOptions'; -import downloadClients from './Settings/downloadClients'; import general from './Settings/general'; import indexerFlags from './Settings/indexerFlags'; import indexerOptions from './Settings/indexerOptions'; import indexers from './Settings/indexers'; import languages from './Settings/languages'; -import mediaManagement from './Settings/mediaManagement'; -import metadata from './Settings/metadata'; -import metadataOptions from './Settings/metadataOptions'; -import naming from './Settings/naming'; -import namingExamples from './Settings/namingExamples'; import notifications from './Settings/notifications'; -import qualityDefinitions from './Settings/qualityDefinitions'; -import qualityProfiles from './Settings/qualityProfiles'; -import remotePathMappings from './Settings/remotePathMappings'; -import restrictions from './Settings/restrictions'; import ui from './Settings/ui'; -export * from './Settings/customFormatSpecifications.js'; -export * from './Settings/customFormats'; -export * from './Settings/delayProfiles'; -export * from './Settings/downloadClients'; -export * from './Settings/downloadClientOptions'; export * from './Settings/general'; export * from './Settings/indexerFlags'; export * from './Settings/indexerOptions'; export * from './Settings/indexers'; export * from './Settings/languages'; -export * from './Settings/mediaManagement'; -export * from './Settings/metadata'; -export * from './Settings/metadataOptions'; -export * from './Settings/naming'; -export * from './Settings/namingExamples'; export * from './Settings/notifications'; -export * from './Settings/qualityDefinitions'; -export * from './Settings/qualityProfiles'; -export * from './Settings/remotePathMappings'; -export * from './Settings/restrictions'; export * from './Settings/ui'; // @@ -56,26 +28,12 @@ export const section = 'settings'; export const defaultState = { advancedSettings: false, - customFormatSpecifications: customFormatSpecifications.defaultState, - customFormats: customFormats.defaultState, - delayProfiles: delayProfiles.defaultState, - downloadClients: downloadClients.defaultState, - downloadClientOptions: downloadClientOptions.defaultState, general: general.defaultState, indexerFlags: indexerFlags.defaultState, indexerOptions: indexerOptions.defaultState, indexers: indexers.defaultState, languages: languages.defaultState, - mediaManagement: mediaManagement.defaultState, - metadata: metadata.defaultState, - metadataOptions: metadataOptions.defaultState, - naming: naming.defaultState, - namingExamples: namingExamples.defaultState, notifications: notifications.defaultState, - qualityDefinitions: qualityDefinitions.defaultState, - qualityProfiles: qualityProfiles.defaultState, - remotePathMappings: remotePathMappings.defaultState, - restrictions: restrictions.defaultState, ui: ui.defaultState }; @@ -97,26 +55,12 @@ export const toggleAdvancedSettings = createAction(TOGGLE_ADVANCED_SETTINGS); // Action Handlers export const actionHandlers = handleThunks({ - ...customFormatSpecifications.actionHandlers, - ...customFormats.actionHandlers, - ...delayProfiles.actionHandlers, - ...downloadClients.actionHandlers, - ...downloadClientOptions.actionHandlers, ...general.actionHandlers, ...indexerFlags.actionHandlers, ...indexerOptions.actionHandlers, ...indexers.actionHandlers, ...languages.actionHandlers, - ...mediaManagement.actionHandlers, - ...metadata.actionHandlers, - ...metadataOptions.actionHandlers, - ...naming.actionHandlers, - ...namingExamples.actionHandlers, ...notifications.actionHandlers, - ...qualityDefinitions.actionHandlers, - ...qualityProfiles.actionHandlers, - ...remotePathMappings.actionHandlers, - ...restrictions.actionHandlers, ...ui.actionHandlers }); @@ -129,26 +73,12 @@ export const reducers = createHandleActions({ return Object.assign({}, state, { advancedSettings: !state.advancedSettings }); }, - ...customFormatSpecifications.reducers, - ...customFormats.reducers, - ...delayProfiles.reducers, - ...downloadClients.reducers, - ...downloadClientOptions.reducers, ...general.reducers, ...indexerFlags.reducers, ...indexerOptions.reducers, ...indexers.reducers, ...languages.reducers, - ...mediaManagement.reducers, - ...metadata.reducers, - ...metadataOptions.reducers, - ...naming.reducers, - ...namingExamples.reducers, ...notifications.reducers, - ...qualityDefinitions.reducers, - ...qualityProfiles.reducers, - ...remotePathMappings.reducers, - ...restrictions.reducers, ...ui.reducers }, defaultState, section); diff --git a/frontend/src/Store/Selectors/createDiscoverMovieClientSideCollectionItemsSelector.js b/frontend/src/Store/Selectors/createDiscoverMovieClientSideCollectionItemsSelector.js deleted file mode 100644 index 6ebd7fa1f..000000000 --- a/frontend/src/Store/Selectors/createDiscoverMovieClientSideCollectionItemsSelector.js +++ /dev/null @@ -1,36 +0,0 @@ -import { createSelector } from 'reselect'; -import createClientSideCollectionSelector from './createClientSideCollectionSelector'; -import createDeepEqualSelector from './createDeepEqualSelector'; - -function createUnoptimizedSelector(uiSection) { - return createSelector( - createClientSideCollectionSelector('movies', uiSection), - (movies) => { - const items = movies.items.map((s) => { - const { - tmdbId, - sortTitle - } = s; - - return { - tmdbId, - sortTitle - }; - }); - - return { - ...movies, - items - }; - } - ); -} - -function createDiscoverMovieClientSideCollectionItemsSelector(uiSection) { - return createDeepEqualSelector( - createUnoptimizedSelector(uiSection), - (movies) => movies - ); -} - -export default createDiscoverMovieClientSideCollectionItemsSelector; diff --git a/frontend/src/Store/Selectors/createDiscoverMovieSelector.js b/frontend/src/Store/Selectors/createDiscoverMovieSelector.js deleted file mode 100644 index da5bc282a..000000000 --- a/frontend/src/Store/Selectors/createDiscoverMovieSelector.js +++ /dev/null @@ -1,13 +0,0 @@ -import { createSelector } from 'reselect'; - -function createDiscoverMovieSelector() { - return createSelector( - (state, { movieId }) => movieId, - (state) => state.discoverMovie, - (movieId, allMovies) => { - return allMovies.items.find((movie) => movie.tmdbId === movieId); - } - ); -} - -export default createDiscoverMovieSelector; diff --git a/frontend/src/Store/Selectors/createMovieFileSelector.js b/frontend/src/Store/Selectors/createMovieFileSelector.js deleted file mode 100644 index d9b4230ad..000000000 --- a/frontend/src/Store/Selectors/createMovieFileSelector.js +++ /dev/null @@ -1,17 +0,0 @@ -import { createSelector } from 'reselect'; - -function createMovieFileSelector() { - return createSelector( - (state, { movieFileId }) => movieFileId, - (state) => state.movieFiles, - (movieFileId, movieFiles) => { - if (!movieFileId) { - return; - } - - return movieFiles.items.find((movieFile) => movieFile.id === movieFileId); - } - ); -} - -export default createMovieFileSelector; diff --git a/frontend/src/Store/Selectors/createMovieQualityProfileSelector.js b/frontend/src/Store/Selectors/createMovieQualityProfileSelector.js deleted file mode 100644 index 3b804bcb4..000000000 --- a/frontend/src/Store/Selectors/createMovieQualityProfileSelector.js +++ /dev/null @@ -1,16 +0,0 @@ -import { createSelector } from 'reselect'; -import createMovieSelector from './createMovieSelector'; - -function createMovieQualityProfileSelector() { - return createSelector( - (state) => state.settings.qualityProfiles.items, - createMovieSelector(), - (qualityProfiles, movie = {}) => { - return qualityProfiles.find((profile) => { - return 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 e9b1c5113..000000000 --- a/frontend/src/Store/Selectors/createProfileInUseSelector.js +++ /dev/null @@ -1,23 +0,0 @@ -import _ from 'lodash'; -import { createSelector } from 'reselect'; -import createAllMoviesSelector from './createAllMoviesSelector'; - -function createProfileInUseSelector(profileProp) { - return createSelector( - (state, { id }) => id, - createAllMoviesSelector(), - (id, movies) => { - if (!id) { - return false; - } - - if (_.some(movies, { [profileProp]: id })) { - return true; - } - - return false; - } - ); -} - -export default createProfileInUseSelector; diff --git a/frontend/src/Store/Selectors/createQualityProfileSelector.js b/frontend/src/Store/Selectors/createQualityProfileSelector.js deleted file mode 100644 index 451aacfd4..000000000 --- a/frontend/src/Store/Selectors/createQualityProfileSelector.js +++ /dev/null @@ -1,15 +0,0 @@ -import { createSelector } from 'reselect'; - -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/createQueueItemSelector.js b/frontend/src/Store/Selectors/createQueueItemSelector.js deleted file mode 100644 index 50bec0d0f..000000000 --- a/frontend/src/Store/Selectors/createQueueItemSelector.js +++ /dev/null @@ -1,19 +0,0 @@ -import { createSelector } from 'reselect'; - -function createQueueItemSelector() { - return createSelector( - (state, { movieId }) => movieId, - (state) => state.queue.details.items, - (movieId, details) => { - if (!movieId || !details) { - return null; - } - - return details.find((item) => { - return item.movieId === movieId; - }); - } - ); -} - -export default createQueueItemSelector; diff --git a/frontend/src/Styles/Variables/colors.js b/frontend/src/Styles/Variables/colors.js index 24e83f557..9a7ac68cd 100644 --- a/frontend/src/Styles/Variables/colors.js +++ b/frontend/src/Styles/Variables/colors.js @@ -1,4 +1,4 @@ -const radarrYellow = '#ffc230'; +const prowlarrYellow = '#aaa'; module.exports = { textColor: '#515253', @@ -17,7 +17,7 @@ module.exports = { queueColor: '#7a43b6', purple: '#7a43b6', pink: '#ff69b4', - radarrYellow, + prowlarrYellow, helpTextColor: '#909293', darkGray: '#888', gray: '#adadad', @@ -26,7 +26,7 @@ module.exports = { // Theme Colors - themeBlue: radarrYellow, + themeBlue: prowlarrYellow, themeRed: '#c4273c', themeDarkColor: '#595959', themeLightColor: '#707070', diff --git a/frontend/src/System/Status/DiskSpace/DiskSpace.css b/frontend/src/System/Status/DiskSpace/DiskSpace.css deleted file mode 100644 index dd92926d4..000000000 --- a/frontend/src/System/Status/DiskSpace/DiskSpace.css +++ /dev/null @@ -1,5 +0,0 @@ -.space { - composes: cell from '~Components/Table/Cells/TableRowCell.css'; - - width: 150px; -} diff --git a/frontend/src/System/Status/DiskSpace/DiskSpace.js b/frontend/src/System/Status/DiskSpace/DiskSpace.js deleted file mode 100644 index cd9fd643c..000000000 --- a/frontend/src/System/Status/DiskSpace/DiskSpace.js +++ /dev/null @@ -1,125 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FieldSet from 'Components/FieldSet'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import ProgressBar from 'Components/ProgressBar'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import Table from 'Components/Table/Table'; -import TableBody from 'Components/Table/TableBody'; -import TableRow from 'Components/Table/TableRow'; -import { kinds, sizes } from 'Helpers/Props'; -import formatBytes from 'Utilities/Number/formatBytes'; -import translate from 'Utilities/String/translate'; -import styles from './DiskSpace.css'; - -const columns = [ - { - name: 'path', - label: translate('Location'), - isVisible: true - }, - { - name: 'freeSpace', - label: translate('FreeSpace'), - isVisible: true - }, - { - name: 'totalSpace', - label: translate('TotalSpace'), - isVisible: true - }, - { - name: 'progress', - isVisible: true - } -]; - -class DiskSpace extends Component { - - // - // Render - - render() { - const { - isFetching, - items, - isSmallScreen - } = this.props; - - return ( -
- { - isFetching && - - } - - { - !isFetching && - - - { - items.map((item) => { - const { - freeSpace, - totalSpace - } = item; - - const diskUsage = Math.round(100 - freeSpace / totalSpace * 100); - let diskUsageKind = kinds.PRIMARY; - - if (diskUsage > 90) { - diskUsageKind = kinds.DANGER; - } else if (diskUsage > 80) { - diskUsageKind = kinds.WARNING; - } - - return ( - - - {item.path} - - { - item.label && - ` (${item.label})` - } - - - - {formatBytes(freeSpace)} - - - - {formatBytes(totalSpace)} - - - - = 12) || (isSmallScreen && diskUsage >= 45))} - text={`${diskUsage}%`} - /> - - - ); - }) - } - -
- } -
- ); - } - -} - -DiskSpace.propTypes = { - isFetching: PropTypes.bool.isRequired, - items: PropTypes.array.isRequired, - isSmallScreen: PropTypes.bool.isRequired -}; - -export default DiskSpace; diff --git a/frontend/src/System/Status/DiskSpace/DiskSpaceConnector.js b/frontend/src/System/Status/DiskSpace/DiskSpaceConnector.js deleted file mode 100644 index 873494a1a..000000000 --- a/frontend/src/System/Status/DiskSpace/DiskSpaceConnector.js +++ /dev/null @@ -1,57 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchDiskSpace } from 'Store/Actions/systemActions'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import DiskSpace from './DiskSpace'; - -function createMapStateToProps() { - return createSelector( - (state) => state.system.diskSpace, - createDimensionsSelector(), - (diskSpace, dimensions) => { - const { - isFetching, - items - } = diskSpace; - - return { - isFetching, - items, - isSmallScreen: dimensions.isSmallScreen - }; - } - ); -} - -const mapDispatchToProps = { - fetchDiskSpace -}; - -class DiskSpaceConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchDiskSpace(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -DiskSpaceConnector.propTypes = { - fetchDiskSpace: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(DiskSpaceConnector); diff --git a/frontend/src/System/Status/Health/Health.js b/frontend/src/System/Status/Health/Health.js index 01b53d1dc..614d95fe0 100644 --- a/frontend/src/System/Status/Health/Health.js +++ b/frontend/src/System/Status/Health/Health.js @@ -27,24 +27,6 @@ function getInternalLink(source) { to="/settings/indexers" /> ); - case 'DownloadClientCheck': - case 'DownloadClientStatusCheck': - case 'ImportMechanismCheck': - return ( - - ); - case 'RootFolderCheck': - return ( - - ); case 'UpdateCheck': return ( ); - case 'DownloadClientCheck': - case 'DownloadClientStatusCheck': - return ( - - ); default: break; @@ -215,9 +187,7 @@ Health.propTypes = { isFetching: PropTypes.bool.isRequired, isPopulated: PropTypes.bool.isRequired, items: PropTypes.array.isRequired, - isTestingAllDownloadClients: PropTypes.bool.isRequired, isTestingAllIndexers: PropTypes.bool.isRequired, - dispatchTestAllDownloadClients: PropTypes.func.isRequired, dispatchTestAllIndexers: PropTypes.func.isRequired }; diff --git a/frontend/src/System/Status/Health/HealthConnector.js b/frontend/src/System/Status/Health/HealthConnector.js index dd13b0a9c..2aa6fba9b 100644 --- a/frontend/src/System/Status/Health/HealthConnector.js +++ b/frontend/src/System/Status/Health/HealthConnector.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; -import { testAllDownloadClients, testAllIndexers } from 'Store/Actions/settingsActions'; +import { testAllIndexers } from 'Store/Actions/settingsActions'; import { fetchHealth } from 'Store/Actions/systemActions'; import createHealthCheckSelector from 'Store/Selectors/createHealthCheckSelector'; import Health from './Health'; @@ -11,9 +11,8 @@ function createMapStateToProps() { return createSelector( createHealthCheckSelector(), (state) => state.system.health, - (state) => state.settings.downloadClients.isTestingAll, (state) => state.settings.indexers.isTestingAll, - (items, health, isTestingAllDownloadClients, isTestingAllIndexers) => { + (items, health, isTestingAllIndexers) => { const { isFetching, isPopulated @@ -23,7 +22,6 @@ function createMapStateToProps() { isFetching, isPopulated, items, - isTestingAllDownloadClients, isTestingAllIndexers }; } @@ -32,7 +30,6 @@ function createMapStateToProps() { const mapDispatchToProps = { dispatchFetchHealth: fetchHealth, - dispatchTestAllDownloadClients: testAllDownloadClients, dispatchTestAllIndexers: testAllIndexers }; diff --git a/frontend/src/System/Status/Status.js b/frontend/src/System/Status/Status.js index 429a149ee..5ebb5d6c5 100644 --- a/frontend/src/System/Status/Status.js +++ b/frontend/src/System/Status/Status.js @@ -3,7 +3,6 @@ import PageContent from 'Components/Page/PageContent'; import PageContentBody from 'Components/Page/PageContentBody'; import translate from 'Utilities/String/translate'; import AboutConnector from './About/AboutConnector'; -import DiskSpaceConnector from './DiskSpace/DiskSpaceConnector'; import HealthConnector from './Health/HealthConnector'; import MoreInfo from './MoreInfo/MoreInfo'; @@ -17,7 +16,6 @@ class Status extends Component { - diff --git a/setup/radarr.iss b/setup/radarr.iss index 858efb280..c5f33cf94 100644 --- a/setup/radarr.iss +++ b/setup/radarr.iss @@ -8,7 +8,7 @@ #define AppExeName "Prowlarr.exe" #define BaseVersion GetEnv('MAJORVERSION') #define BuildNumber GetEnv('MINORVERSION') -#define BuildVersion GetEnv('RADARRVERSION') +#define BuildVersion GetEnv('PROWLARRVERSION') #define BranchName GetEnv('BUILD_SOURCEBRANCHNAME') [Setup] diff --git a/src/Directory.Build.props b/src/Directory.Build.props index ef72c7e17..ee0f27c8e 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -8,35 +8,35 @@ win-x64;osx-x64;linux-x64;linux-musl-x64;linux-arm;linux-arm64;linux-musl-arm64 win-x64:net462;osx-x64:net462;linux-arm:net462;linux-arm64:net462;linux-musl-x64:net462;linux-musl-arm64:net462 - $(MSBuildThisFileDirectory)..\ + $(MSBuildThisFileDirectory)..\ - Library - Test - Exe - Exe - Exe - Exe - Update + Library + Test + Exe + Exe + Exe + Exe + Update - false - true - true - true + false + true + true + true Release - $(RadarrRootDir)_temp\obj\$(MSBuildProjectName)\ - $(RadarrRootDir)_temp\obj\$(MSBuildProjectName)\$(Configuration)\ - $(RadarrRootDir)_temp\bin\$(Configuration)\$(MSBuildProjectName)\ + $(ProwlarrRootDir)_temp\obj\$(MSBuildProjectName)\ + $(ProwlarrRootDir)_temp\obj\$(MSBuildProjectName)\$(Configuration)\ + $(ProwlarrRootDir)_temp\bin\$(Configuration)\$(MSBuildProjectName)\ - $(RadarrRootDir)_output\ - $(RadarrRootDir)_tests\ - $(RadarrRootDir)_output\Prowlarr.Update\ + $(ProwlarrRootDir)_output\ + $(ProwlarrRootDir)_tests\ + $(ProwlarrRootDir)_output\Prowlarr.Update\ $([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)', '$(BaseIntermediateOutputPath)')) @@ -47,14 +47,14 @@ - + true true false - + Prowlarr prowlarr.video Copyright 2014-$([System.DateTime]::Now.ToString('yyyy')) prowlarr.video (GNU General Public v3) @@ -71,7 +71,7 @@ - + <_Parameter1>$(AssemblyConfiguration) @@ -79,7 +79,7 @@ - $(MSBuildProjectName.Replace('Prowlarr','NzbDrone')) + $(MSBuildProjectName.Replace('Prowlarr','NzbDrone')) @@ -91,7 +91,7 @@ - + all diff --git a/src/NzbDrone.Common.Test/PathExtensionFixture.cs b/src/NzbDrone.Common.Test/PathExtensionFixture.cs index a46ac961b..2e522eb60 100644 --- a/src/NzbDrone.Common.Test/PathExtensionFixture.cs +++ b/src/NzbDrone.Common.Test/PathExtensionFixture.cs @@ -260,25 +260,25 @@ namespace NzbDrone.Common.Test [Test] public void Sandbox() { - GetIAppDirectoryInfo().GetUpdateSandboxFolder().Should().BeEquivalentTo(@"C:\Temp\radarr_update\".AsOsAgnostic()); + GetIAppDirectoryInfo().GetUpdateSandboxFolder().Should().BeEquivalentTo(@"C:\Temp\prowlarr_update\".AsOsAgnostic()); } [Test] public void GetUpdatePackageFolder() { - GetIAppDirectoryInfo().GetUpdatePackageFolder().Should().BeEquivalentTo(@"C:\Temp\radarr_update\Prowlarr\".AsOsAgnostic()); + GetIAppDirectoryInfo().GetUpdatePackageFolder().Should().BeEquivalentTo(@"C:\Temp\prowlarr_update\Prowlarr\".AsOsAgnostic()); } [Test] public void GetUpdateClientFolder() { - GetIAppDirectoryInfo().GetUpdateClientFolder().Should().BeEquivalentTo(@"C:\Temp\radarr_update\Prowlarr\Prowlarr.Update\".AsOsAgnostic()); + GetIAppDirectoryInfo().GetUpdateClientFolder().Should().BeEquivalentTo(@"C:\Temp\prowlarr_update\Prowlarr\Prowlarr.Update\".AsOsAgnostic()); } [Test] public void GetUpdateClientExePath() { - GetIAppDirectoryInfo().GetUpdateClientExePath(PlatformType.DotNet).Should().BeEquivalentTo(@"C:\Temp\radarr_update\Prowlarr.Update.exe".AsOsAgnostic()); + GetIAppDirectoryInfo().GetUpdateClientExePath(PlatformType.DotNet).Should().BeEquivalentTo(@"C:\Temp\prowlarr_update\Prowlarr.Update.exe".AsOsAgnostic()); } [Test] diff --git a/src/NzbDrone.Common/Cloud/ProwlarrCloudRequestBuilder.cs b/src/NzbDrone.Common/Cloud/ProwlarrCloudRequestBuilder.cs index a86116f6c..86ced4c84 100644 --- a/src/NzbDrone.Common/Cloud/ProwlarrCloudRequestBuilder.cs +++ b/src/NzbDrone.Common/Cloud/ProwlarrCloudRequestBuilder.cs @@ -2,32 +2,19 @@ using NzbDrone.Common.Http; namespace NzbDrone.Common.Cloud { - public interface IRadarrCloudRequestBuilder + public interface IProwlarrCloudRequestBuilder { IHttpRequestBuilderFactory Services { get; } - IHttpRequestBuilderFactory TMDB { get; } - IHttpRequestBuilderFactory RadarrMetadata { get; } } - public class RadarrCloudRequestBuilder : IRadarrCloudRequestBuilder + public class ProwlarrCloudRequestBuilder : IProwlarrCloudRequestBuilder { - public RadarrCloudRequestBuilder() + public ProwlarrCloudRequestBuilder() { Services = new HttpRequestBuilder("https://prowlarr.servarr.com/v1/") .CreateFactory(); - - TMDB = new HttpRequestBuilder("https://api.themoviedb.org/{api}/{route}/{id}{secondaryRoute}") - .SetHeader("Authorization", $"Bearer {AuthToken}") - .CreateFactory(); - - RadarrMetadata = new HttpRequestBuilder("https://radarrapi.servarr.com/v1/{route}") - .CreateFactory(); } public IHttpRequestBuilderFactory Services { get; private set; } - public IHttpRequestBuilderFactory TMDB { get; private set; } - public IHttpRequestBuilderFactory RadarrMetadata { get; private set; } - - public string AuthToken => "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxYTczNzMzMDE5NjFkMDNmOTdmODUzYTg3NmRkMTIxMiIsInN1YiI6IjU4NjRmNTkyYzNhMzY4MGFiNjAxNzUzNCIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.gh1BwogCCKOda6xj9FRMgAAj_RYKMMPC3oNlcBtlmwk"; } } diff --git a/src/NzbDrone.Common/Disk/DiskProviderBase.cs b/src/NzbDrone.Common/Disk/DiskProviderBase.cs index 32b046b58..084e515c2 100644 --- a/src/NzbDrone.Common/Disk/DiskProviderBase.cs +++ b/src/NzbDrone.Common/Disk/DiskProviderBase.cs @@ -128,7 +128,7 @@ namespace NzbDrone.Common.Disk try { - var testPath = Path.Combine(path, "radarr_write_test.txt"); + var testPath = Path.Combine(path, "prowlarr_write_test.txt"); var testContent = string.Format("This file was created to verify if '{0}' is writable. It should've been automatically deleted. Feel free to delete it.", path); File.WriteAllText(testPath, testContent); File.Delete(testPath); diff --git a/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs b/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs index b5f09d799..5f0730d09 100644 --- a/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs +++ b/src/NzbDrone.Common/EnvironmentInfo/AppFolderFactory.cs @@ -45,7 +45,7 @@ namespace NzbDrone.Common.EnvironmentInfo } catch (UnauthorizedAccessException) { - throw new RadarrStartupException("Cannot create AppFolder, Access to the path {0} is denied", _appFolderInfo.AppDataFolder); + throw new ProwlarrStartupException("Cannot create AppFolder, Access to the path {0} is denied", _appFolderInfo.AppDataFolder); } if (OsInfo.IsWindows) @@ -55,7 +55,7 @@ namespace NzbDrone.Common.EnvironmentInfo if (!_diskProvider.FolderWritable(_appFolderInfo.AppDataFolder)) { - throw new RadarrStartupException("AppFolder {0} is not writable", _appFolderInfo.AppDataFolder); + throw new ProwlarrStartupException("AppFolder {0} is not writable", _appFolderInfo.AppDataFolder); } InitializeMonoApplicationData(); @@ -117,7 +117,7 @@ namespace NzbDrone.Common.EnvironmentInfo catch (Exception ex) { _logger.Debug(ex, ex.Message); - throw new RadarrStartupException("Unable to migrate DB from nzbdrone.db to {0}. Migrate manually", _appFolderInfo.GetDatabase()); + throw new ProwlarrStartupException("Unable to migrate DB from nzbdrone.db to {0}. Migrate manually", _appFolderInfo.GetDatabase()); } } diff --git a/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs b/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs index 51141ddec..79c096380 100644 --- a/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs +++ b/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs @@ -33,7 +33,7 @@ namespace NzbDrone.Common.EnvironmentInfo if (entry != null) { ExecutingApplication = entry.Location; - IsWindowsTray = OsInfo.IsWindows && entry.ManifestModule.Name == $"{ProcessProvider.RADARR_PROCESS_NAME}.exe"; + IsWindowsTray = OsInfo.IsWindows && entry.ManifestModule.Name == $"{ProcessProvider.PROWLARR_PROCESS_NAME}.exe"; } } @@ -99,7 +99,7 @@ namespace NzbDrone.Common.EnvironmentInfo { if (OsInfo.IsWindows) { - return IsUserInteractive && Process.GetCurrentProcess().ProcessName.Equals(ProcessProvider.RADARR_PROCESS_NAME, StringComparison.InvariantCultureIgnoreCase); + return IsUserInteractive && Process.GetCurrentProcess().ProcessName.Equals(ProcessProvider.PROWLARR_PROCESS_NAME, StringComparison.InvariantCultureIgnoreCase); } return false; diff --git a/src/NzbDrone.Common/Exceptions/ProwlarrStartupException.cs b/src/NzbDrone.Common/Exceptions/ProwlarrStartupException.cs index e71bede8e..cb223c1eb 100644 --- a/src/NzbDrone.Common/Exceptions/ProwlarrStartupException.cs +++ b/src/NzbDrone.Common/Exceptions/ProwlarrStartupException.cs @@ -2,34 +2,34 @@ using System; namespace NzbDrone.Common.Exceptions { - public class RadarrStartupException : NzbDroneException + public class ProwlarrStartupException : NzbDroneException { - public RadarrStartupException(string message, params object[] args) + public ProwlarrStartupException(string message, params object[] args) : base("Prowlarr failed to start: " + string.Format(message, args)) { } - public RadarrStartupException(string message) + public ProwlarrStartupException(string message) : base("Prowlarr failed to start: " + message) { } - public RadarrStartupException() + public ProwlarrStartupException() : base("Prowlarr failed to start") { } - public RadarrStartupException(Exception innerException, string message, params object[] args) + public ProwlarrStartupException(Exception innerException, string message, params object[] args) : base("Prowlarr failed to start: " + string.Format(message, args), innerException) { } - public RadarrStartupException(Exception innerException, string message) + public ProwlarrStartupException(Exception innerException, string message) : base("Prowlarr failed to start: " + message, innerException) { } - public RadarrStartupException(Exception innerException) + public ProwlarrStartupException(Exception innerException) : base("Prowlarr failed to start: " + innerException.Message) { } diff --git a/src/NzbDrone.Common/Extensions/PathExtensions.cs b/src/NzbDrone.Common/Extensions/PathExtensions.cs index a21cc1ed5..80a54ac7d 100644 --- a/src/NzbDrone.Common/Extensions/PathExtensions.cs +++ b/src/NzbDrone.Common/Extensions/PathExtensions.cs @@ -17,10 +17,10 @@ namespace NzbDrone.Common.Extensions private const string NLOG_CONFIG_FILE = "nlog.config"; private const string UPDATE_CLIENT_EXE_NAME = "Prowlarr.Update"; - private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "radarr_update" + Path.DirectorySeparatorChar; + private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "prowlarr_update" + Path.DirectorySeparatorChar; private static readonly string UPDATE_PACKAGE_FOLDER_NAME = "Prowlarr" + Path.DirectorySeparatorChar; - private static readonly string UPDATE_BACKUP_FOLDER_NAME = "radarr_backup" + Path.DirectorySeparatorChar; - private static readonly string UPDATE_BACKUP_APPDATA_FOLDER_NAME = "radarr_appdata_backup" + Path.DirectorySeparatorChar; + private static readonly string UPDATE_BACKUP_FOLDER_NAME = "prowlarr_backup" + Path.DirectorySeparatorChar; + private static readonly string UPDATE_BACKUP_APPDATA_FOLDER_NAME = "prowlarr_appdata_backup" + Path.DirectorySeparatorChar; private static readonly string UPDATE_CLIENT_FOLDER_NAME = "Prowlarr.Update" + Path.DirectorySeparatorChar; private static readonly string UPDATE_LOG_FOLDER_NAME = "UpdateLogs" + Path.DirectorySeparatorChar; diff --git a/src/NzbDrone.Common/Processes/PidFileProvider.cs b/src/NzbDrone.Common/Processes/PidFileProvider.cs index 4769abc4b..970663284 100644 --- a/src/NzbDrone.Common/Processes/PidFileProvider.cs +++ b/src/NzbDrone.Common/Processes/PidFileProvider.cs @@ -39,7 +39,7 @@ namespace NzbDrone.Common.Processes catch (Exception ex) { _logger.Error(ex, "Unable to write PID file: " + filename); - throw new RadarrStartupException(ex, "Unable to write PID file {0}", filename); + throw new ProwlarrStartupException(ex, "Unable to write PID file {0}", filename); } } } diff --git a/src/NzbDrone.Common/Processes/ProcessProvider.cs b/src/NzbDrone.Common/Processes/ProcessProvider.cs index 3ec8c8c5f..6e6a0edb4 100644 --- a/src/NzbDrone.Common/Processes/ProcessProvider.cs +++ b/src/NzbDrone.Common/Processes/ProcessProvider.cs @@ -35,8 +35,8 @@ namespace NzbDrone.Common.Processes { private readonly Logger _logger; - public const string RADARR_PROCESS_NAME = "Prowlarr"; - public const string RADARR_CONSOLE_PROCESS_NAME = "Prowlarr.Console"; + public const string PROWLARR_PROCESS_NAME = "Prowlarr"; + public const string PROWLARR_CONSOLE_PROCESS_NAME = "Prowlarr.Console"; public ProcessProvider(Logger logger) { diff --git a/src/NzbDrone.Console/ConsoleApp.cs b/src/NzbDrone.Console/ConsoleApp.cs index bd8471e65..630d4b288 100644 --- a/src/NzbDrone.Console/ConsoleApp.cs +++ b/src/NzbDrone.Console/ConsoleApp.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Console Bootstrap.Start(startupArgs, new ConsoleAlerts()); } - catch (RadarrStartupException ex) + catch (ProwlarrStartupException ex) { System.Console.WriteLine(""); System.Console.WriteLine(""); diff --git a/src/NzbDrone.Core.Test/Framework/CoreTest.cs b/src/NzbDrone.Core.Test/Framework/CoreTest.cs index 056234eec..9da38329f 100644 --- a/src/NzbDrone.Core.Test/Framework/CoreTest.cs +++ b/src/NzbDrone.Core.Test/Framework/CoreTest.cs @@ -27,7 +27,7 @@ namespace NzbDrone.Core.Test.Framework Mocker.SetConstant(new ManagedWebProxyFactory(Mocker.Resolve())); Mocker.SetConstant(new ManagedHttpDispatcher(Mocker.Resolve(), Mocker.Resolve(), Mocker.Resolve(), Mocker.Resolve(), TestLogger)); Mocker.SetConstant(new HttpClient(Array.Empty(), Mocker.Resolve(), Mocker.Resolve(), Mocker.Resolve(), TestLogger)); - Mocker.SetConstant(new RadarrCloudRequestBuilder()); + Mocker.SetConstant(new ProwlarrCloudRequestBuilder()); } } diff --git a/src/NzbDrone.Core.Test/HealthCheck/Checks/SystemTimeCheckFixture.cs b/src/NzbDrone.Core.Test/HealthCheck/Checks/SystemTimeCheckFixture.cs index 8cf7f53dc..74cf3a0b4 100644 --- a/src/NzbDrone.Core.Test/HealthCheck/Checks/SystemTimeCheckFixture.cs +++ b/src/NzbDrone.Core.Test/HealthCheck/Checks/SystemTimeCheckFixture.cs @@ -18,7 +18,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks [SetUp] public void Setup() { - Mocker.SetConstant(new RadarrCloudRequestBuilder()); + Mocker.SetConstant(new ProwlarrCloudRequestBuilder()); } private void GivenServerTime(DateTime dateTime) diff --git a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupUnusedTagsFixture.cs b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupUnusedTagsFixture.cs index d32e16e63..05e2b58df 100644 --- a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupUnusedTagsFixture.cs +++ b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupUnusedTagsFixture.cs @@ -1,8 +1,7 @@ -using FizzWare.NBuilder; +using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Housekeeping.Housekeepers; -using NzbDrone.Core.Restrictions; using NzbDrone.Core.Tags; using NzbDrone.Core.Test.Framework; @@ -23,25 +22,5 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers Subject.Clean(); AllStoredModels.Should().BeEmpty(); } - - [Test] - public void should_not_delete_used_tags() - { - var tags = Builder.CreateListOfSize(2) - .All() - .With(x => x.Id = 0) - .BuildList(); - Db.InsertMany(tags); - - var restrictions = Builder.CreateListOfSize(2) - .All() - .With(v => v.Id = 0) - .With(v => v.Tags.Add(tags[0].Id)) - .BuildList(); - Db.InsertMany(restrictions); - - Subject.Clean(); - AllStoredModels.Should().HaveCount(1); - } } } diff --git a/src/NzbDrone.Core.Test/IndexerTests/TestIndexer.cs b/src/NzbDrone.Core.Test/IndexerTests/TestIndexer.cs index c0a0c887d..0e231deac 100644 --- a/src/NzbDrone.Core.Test/IndexerTests/TestIndexer.cs +++ b/src/NzbDrone.Core.Test/IndexerTests/TestIndexer.cs @@ -6,7 +6,7 @@ using NzbDrone.Core.Parser; namespace NzbDrone.Core.Test.IndexerTests { - public class TestIndexer : HttpIndexerBase + public class TestIndexer : HttpApplicationBase { public override string Name => "Test Indexer"; diff --git a/src/NzbDrone.Core/Backup/BackupService.cs b/src/NzbDrone.Core/Backup/BackupService.cs index a641008be..300461f80 100644 --- a/src/NzbDrone.Core/Backup/BackupService.cs +++ b/src/NzbDrone.Core/Backup/BackupService.cs @@ -59,7 +59,7 @@ namespace NzbDrone.Core.Backup _configService = configService; _logger = logger; - _backupTempFolder = Path.Combine(_appFolderInfo.TempFolder, "radarr_backup"); + _backupTempFolder = Path.Combine(_appFolderInfo.TempFolder, "prowlarr_backup"); } public void Backup(BackupType backupType) @@ -69,7 +69,7 @@ namespace NzbDrone.Core.Backup _diskProvider.EnsureFolder(_backupTempFolder); _diskProvider.EnsureFolder(GetBackupFolder(backupType)); - var backupFilename = string.Format("radarr_backup_v{0}_{1:yyyy.MM.dd_HH.mm.ss}.zip", BuildInfo.Version, DateTime.Now); + var backupFilename = string.Format("prowlarr_backup_v{0}_{1:yyyy.MM.dd_HH.mm.ss}.zip", BuildInfo.Version, DateTime.Now); var backupPath = Path.Combine(GetBackupFolder(backupType), backupFilename); Cleanup(); @@ -120,7 +120,7 @@ namespace NzbDrone.Core.Backup if (backupFileName.EndsWith(".zip")) { var restoredFile = false; - var temporaryPath = Path.Combine(_appFolderInfo.TempFolder, "radarr_backup_restore"); + var temporaryPath = Path.Combine(_appFolderInfo.TempFolder, "prowlarr_backup_restore"); _archiveService.Extract(backupFileName, temporaryPath); diff --git a/src/NzbDrone.Core/Datastore/CorruptDatabaseException.cs b/src/NzbDrone.Core/Datastore/CorruptDatabaseException.cs index c6763a774..82b4065f7 100644 --- a/src/NzbDrone.Core/Datastore/CorruptDatabaseException.cs +++ b/src/NzbDrone.Core/Datastore/CorruptDatabaseException.cs @@ -3,7 +3,7 @@ using NzbDrone.Common.Exceptions; namespace NzbDrone.Core.Datastore { - public class CorruptDatabaseException : RadarrStartupException + public class CorruptDatabaseException : ProwlarrStartupException { public CorruptDatabaseException(string message, params object[] args) : base(message, args) diff --git a/src/NzbDrone.Core/Datastore/DbFactory.cs b/src/NzbDrone.Core/Datastore/DbFactory.cs index 1f327b748..9dc0e3ff3 100644 --- a/src/NzbDrone.Core/Datastore/DbFactory.cs +++ b/src/NzbDrone.Core/Datastore/DbFactory.cs @@ -127,7 +127,7 @@ namespace NzbDrone.Core.Datastore } catch (Exception e) { - throw new RadarrStartupException(e, "Error creating main database"); + throw new ProwlarrStartupException(e, "Error creating main database"); } } @@ -159,7 +159,7 @@ namespace NzbDrone.Core.Datastore } catch (Exception e) { - throw new RadarrStartupException(e, "Error creating log database"); + throw new ProwlarrStartupException(e, "Error creating log database"); } } } diff --git a/src/NzbDrone.Core/Datastore/Migration/001_initial_setup.cs b/src/NzbDrone.Core/Datastore/Migration/001_initial_setup.cs index d0db8428d..e144aebea 100644 --- a/src/NzbDrone.Core/Datastore/Migration/001_initial_setup.cs +++ b/src/NzbDrone.Core/Datastore/Migration/001_initial_setup.cs @@ -46,6 +46,12 @@ namespace NzbDrone.Core.Datastore.Migration .WithColumn("EnableRss").AsBoolean().Nullable() .WithColumn("EnableSearch").AsBoolean().Nullable(); + Create.TableForModel("Applications") + .WithColumn("Name").AsString().Unique() + .WithColumn("Implementation").AsString() + .WithColumn("Settings").AsString().Nullable() + .WithColumn("ConfigContract").AsString().Nullable(); + Create.TableForModel("Tags") .WithColumn("Label").AsString().Unique(); diff --git a/src/NzbDrone.Core/Datastore/TableMapping.cs b/src/NzbDrone.Core/Datastore/TableMapping.cs index 8e72c19a6..da8cf6bf9 100644 --- a/src/NzbDrone.Core/Datastore/TableMapping.cs +++ b/src/NzbDrone.Core/Datastore/TableMapping.cs @@ -15,7 +15,6 @@ using NzbDrone.Core.Languages; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Notifications; using NzbDrone.Core.Parser.Model; -using NzbDrone.Core.Restrictions; using NzbDrone.Core.Tags; using NzbDrone.Core.ThingiProvider; using static Dapper.SqlMapper; @@ -56,7 +55,6 @@ namespace NzbDrone.Core.Datastore Mapper.Entity("Logs").RegisterModel(); Mapper.Entity("Tags").RegisterModel(); - Mapper.Entity("Restrictions").RegisterModel(); Mapper.Entity("Users").RegisterModel(); Mapper.Entity("Commands").RegisterModel() diff --git a/src/NzbDrone.Core/HealthCheck/Checks/ProxyCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/ProxyCheck.cs index 7ac940c16..f8f7df340 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/ProxyCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/ProxyCheck.cs @@ -19,7 +19,7 @@ namespace NzbDrone.Core.HealthCheck.Checks private readonly IHttpRequestBuilderFactory _cloudRequestBuilder; - public ProxyCheck(IRadarrCloudRequestBuilder cloudRequestBuilder, IConfigService configService, IHttpClient client, ILocalizationService localizationService, Logger logger) + public ProxyCheck(IProwlarrCloudRequestBuilder cloudRequestBuilder, IConfigService configService, IHttpClient client, ILocalizationService localizationService, Logger logger) : base(localizationService) { _configService = configService; diff --git a/src/NzbDrone.Core/HealthCheck/Checks/SystemTimeCheck.cs b/src/NzbDrone.Core/HealthCheck/Checks/SystemTimeCheck.cs index 36e913e69..a761f90df 100644 --- a/src/NzbDrone.Core/HealthCheck/Checks/SystemTimeCheck.cs +++ b/src/NzbDrone.Core/HealthCheck/Checks/SystemTimeCheck.cs @@ -13,7 +13,7 @@ namespace NzbDrone.Core.HealthCheck.Checks private readonly IHttpRequestBuilderFactory _cloudRequestBuilder; private readonly Logger _logger; - public SystemTimeCheck(IHttpClient client, IRadarrCloudRequestBuilder cloudRequestBuilder, ILocalizationService localizationService, Logger logger) + public SystemTimeCheck(IHttpClient client, IProwlarrCloudRequestBuilder cloudRequestBuilder, ILocalizationService localizationService, Logger logger) : base(localizationService) { _client = client; diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupUnusedTags.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupUnusedTags.cs index caab4d5d3..f23773660 100644 --- a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupUnusedTags.cs +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupUnusedTags.cs @@ -19,7 +19,7 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers { using (var mapper = _database.OpenConnection()) { - var usedTags = new[] { "Movies", "Notifications", "DelayProfiles", "Restrictions", "ImportLists" } + var usedTags = new[] { "Notifications" } .SelectMany(v => GetUsedTags(v, mapper)) .Distinct() .ToArray(); diff --git a/src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHD.cs b/src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHD.cs index e87c2692e..1603d5227 100644 --- a/src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHD.cs +++ b/src/NzbDrone.Core/Indexers/AwesomeHD/AwesomeHD.cs @@ -4,7 +4,7 @@ using NzbDrone.Core.Configuration; namespace NzbDrone.Core.Indexers.AwesomeHD { - public class AwesomeHD : HttpIndexerBase + public class AwesomeHD : HttpApplicationBase { public override string Name => "AwesomeHD"; public override DownloadProtocol Protocol => DownloadProtocol.Torrent; diff --git a/src/NzbDrone.Core/Indexers/FileList/FileList.cs b/src/NzbDrone.Core/Indexers/FileList/FileList.cs index 3121e1788..1df00b0af 100644 --- a/src/NzbDrone.Core/Indexers/FileList/FileList.cs +++ b/src/NzbDrone.Core/Indexers/FileList/FileList.cs @@ -4,7 +4,7 @@ using NzbDrone.Core.Configuration; namespace NzbDrone.Core.Indexers.FileList { - public class FileList : HttpIndexerBase + public class FileList : HttpApplicationBase { public override string Name => "FileList.io"; public override DownloadProtocol Protocol => DownloadProtocol.Torrent; diff --git a/src/NzbDrone.Core/Indexers/HDBits/HDBits.cs b/src/NzbDrone.Core/Indexers/HDBits/HDBits.cs index 959d4cc5c..2f70aa083 100644 --- a/src/NzbDrone.Core/Indexers/HDBits/HDBits.cs +++ b/src/NzbDrone.Core/Indexers/HDBits/HDBits.cs @@ -4,7 +4,7 @@ using NzbDrone.Core.Configuration; namespace NzbDrone.Core.Indexers.HDBits { - public class HDBits : HttpIndexerBase + public class HDBits : HttpApplicationBase { public override string Name => "HDBits"; public override DownloadProtocol Protocol => DownloadProtocol.Torrent; diff --git a/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs b/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs index 8f0a11842..fa02f1079 100644 --- a/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs +++ b/src/NzbDrone.Core/Indexers/HttpIndexerBase.cs @@ -14,7 +14,7 @@ using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.Indexers { - public abstract class HttpIndexerBase : IndexerBase + public abstract class HttpApplicationBase : IndexerBase where TSettings : IIndexerSettings, new() { protected const int MaxNumResultsPerQuery = 1000; @@ -31,7 +31,7 @@ namespace NzbDrone.Core.Indexers public abstract IIndexerRequestGenerator GetRequestGenerator(); public abstract IParseIndexerResponse GetParser(); - public HttpIndexerBase(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) + public HttpApplicationBase(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger) : base(indexerStatusService, configService, logger) { _httpClient = httpClient; diff --git a/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrents.cs b/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrents.cs index d052aed75..5f5f93249 100644 --- a/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrents.cs +++ b/src/NzbDrone.Core/Indexers/IPTorrents/IPTorrents.cs @@ -4,7 +4,7 @@ using NzbDrone.Core.Configuration; namespace NzbDrone.Core.Indexers.IPTorrents { - public class IPTorrents : HttpIndexerBase + public class IPTorrents : HttpApplicationBase { public override string Name => "IP Torrents"; diff --git a/src/NzbDrone.Core/Indexers/Newznab/Newznab.cs b/src/NzbDrone.Core/Indexers/Newznab/Newznab.cs index bada7594a..d05b3f189 100644 --- a/src/NzbDrone.Core/Indexers/Newznab/Newznab.cs +++ b/src/NzbDrone.Core/Indexers/Newznab/Newznab.cs @@ -11,7 +11,7 @@ using NzbDrone.Core.Validation; namespace NzbDrone.Core.Indexers.Newznab { - public class Newznab : HttpIndexerBase + public class Newznab : HttpApplicationBase { private readonly INewznabCapabilitiesProvider _capabilitiesProvider; diff --git a/src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs b/src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs index c8037a538..5b3ba8e8b 100644 --- a/src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs +++ b/src/NzbDrone.Core/Indexers/Nyaa/Nyaa.cs @@ -4,7 +4,7 @@ using NzbDrone.Core.Configuration; namespace NzbDrone.Core.Indexers.Nyaa { - public class Nyaa : HttpIndexerBase + public class Nyaa : HttpApplicationBase { public override string Name => "Nyaa"; diff --git a/src/NzbDrone.Core/Indexers/Omgwtfnzbs/Omgwtfnzbs.cs b/src/NzbDrone.Core/Indexers/Omgwtfnzbs/Omgwtfnzbs.cs index efad3812d..1ad38160d 100644 --- a/src/NzbDrone.Core/Indexers/Omgwtfnzbs/Omgwtfnzbs.cs +++ b/src/NzbDrone.Core/Indexers/Omgwtfnzbs/Omgwtfnzbs.cs @@ -4,7 +4,7 @@ using NzbDrone.Core.Configuration; namespace NzbDrone.Core.Indexers.Omgwtfnzbs { - public class Omgwtfnzbs : HttpIndexerBase + public class Omgwtfnzbs : HttpApplicationBase { public override string Name => "omgwtfnzbs"; diff --git a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcorn.cs b/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcorn.cs index 1c9f9b7aa..83a1084cf 100644 --- a/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcorn.cs +++ b/src/NzbDrone.Core/Indexers/PassThePopcorn/PassThePopcorn.cs @@ -5,7 +5,7 @@ using NzbDrone.Core.Configuration; namespace NzbDrone.Core.Indexers.PassThePopcorn { - public class PassThePopcorn : HttpIndexerBase + public class PassThePopcorn : HttpApplicationBase { public override string Name => "PassThePopcorn"; public override DownloadProtocol Protocol => DownloadProtocol.Torrent; diff --git a/src/NzbDrone.Core/Indexers/Rarbg/Rarbg.cs b/src/NzbDrone.Core/Indexers/Rarbg/Rarbg.cs index 67fdd4ffd..1e596ab85 100644 --- a/src/NzbDrone.Core/Indexers/Rarbg/Rarbg.cs +++ b/src/NzbDrone.Core/Indexers/Rarbg/Rarbg.cs @@ -10,7 +10,7 @@ using NzbDrone.Core.Validation; namespace NzbDrone.Core.Indexers.Rarbg { - public class Rarbg : HttpIndexerBase + public class Rarbg : HttpApplicationBase { private readonly IRarbgTokenProvider _tokenProvider; diff --git a/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotato.cs b/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotato.cs index 80ee70c03..cde5bc081 100644 --- a/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotato.cs +++ b/src/NzbDrone.Core/Indexers/TorrentPotato/TorrentPotato.cs @@ -5,7 +5,7 @@ using NzbDrone.Core.Configuration; namespace NzbDrone.Core.Indexers.TorrentPotato { - public class TorrentPotato : HttpIndexerBase + public class TorrentPotato : HttpApplicationBase { public override string Name => "TorrentPotato"; diff --git a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexer.cs b/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexer.cs index 6e3d6214c..94b47c1ea 100644 --- a/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexer.cs +++ b/src/NzbDrone.Core/Indexers/TorrentRss/TorrentRssIndexer.cs @@ -4,7 +4,7 @@ using NzbDrone.Core.Configuration; namespace NzbDrone.Core.Indexers.TorrentRss { - public class TorrentRssIndexer : HttpIndexerBase + public class TorrentRssIndexer : HttpApplicationBase { public override string Name => "Torrent RSS Feed"; diff --git a/src/NzbDrone.Core/Indexers/Torznab/Torznab.cs b/src/NzbDrone.Core/Indexers/Torznab/Torznab.cs index 5fdb1a5a8..4533d0b6f 100644 --- a/src/NzbDrone.Core/Indexers/Torznab/Torznab.cs +++ b/src/NzbDrone.Core/Indexers/Torznab/Torznab.cs @@ -12,7 +12,7 @@ using NzbDrone.Core.Validation; namespace NzbDrone.Core.Indexers.Torznab { - public class Torznab : HttpIndexerBase + public class Torznab : HttpApplicationBase { private readonly INewznabCapabilitiesProvider _capabilitiesProvider; diff --git a/src/NzbDrone.Core/Localization/Core/de.json b/src/NzbDrone.Core/Localization/Core/de.json index 28fd00e87..a436de777 100644 --- a/src/NzbDrone.Core/Localization/Core/de.json +++ b/src/NzbDrone.Core/Localization/Core/de.json @@ -496,7 +496,7 @@ "QualityCutoffHasNotBeenMet": "Qualitätsschwelle wurde noch nicht erreicht", "QualitySettings": "Qualitäts Einstellungen", "Prowlarr": "Prowlarr", - "RadarrTags": "Prowlarr Tags", + "ProwlarrTags": "Prowlarr Tags", "Real": "Echt", "Reason": "Grund", "RecycleBinCleanupDaysHelpText": "Auf 0 setzen um das automatische leeren des Papierkorbs zu deaktivieren", @@ -524,7 +524,7 @@ "Reset": "Zurücksetzen", "ResetAPIKey": "API-Schlüssel zurücksetzen", "RestartNow": "Jetzt neustarten", - "RestartRadarr": "Prowlarr Neustarten", + "RestartProwlarr": "Prowlarr Neustarten", "Result": "Ergebnis", "Retention": "Aufbewahrung ( Retention )", "RetentionHelpText": "Nur Usenet: Für eine umbegrenzte Aufbewahrung auf 0 setzen", @@ -619,7 +619,7 @@ "RssSyncIntervalHelpTextWarning": "Dies betrifft alle Indexer. Bitte beachte dessen API Regeln", "AreYouSureYouWantToResetYourAPIKey": "Bist du sicher, dass du den API-Schlüssel zurücksetzen willst?", "CopyUsingHardlinksHelpText": "Hardlinks erstellen wenn Torrents die noch geseeded werden kopiert werden sollen", - "IncludeUnknownMovieItemsHelpText": "Einträge ohne eine Zuordnung in der Warteschlange anzeigen. Dies könnten gelöschte Filme oder alles andere mit Radarrs Downloadkategorie sein", + "IncludeUnknownMovieItemsHelpText": "Einträge ohne eine Zuordnung in der Warteschlange anzeigen. Dies könnten gelöschte Filme oder alles andere mit Prowlarrs Downloadkategorie sein", "PriorityHelpText": "Priorisiere mehrere Downloader. Rundlauf-Verfahren wird für Downloader mit der gleichen Priorität verwendet.", "SearchForMovie": "Film suchen", "AuthenticationMethodHelpText": "Für den Zugriff auf Prowlarr sind Benutzername und Passwort erforderlich", @@ -632,7 +632,7 @@ "LaunchBrowserHelpText": " Öffne die Startseite von Prowlarr im Webbrowser nach dem Start.", "ReadTheWikiForMoreInformation": "Lese das Wiki für mehr Informationen", "SetPermissionsLinuxHelpText": "Soll CHMOD ausgeführt werden wenn Datien importiert/umbenannt werden?", - "BackupFolderHelpText": "Relative Pfade befinden sich unter Radarrs AppData Ordner", + "BackupFolderHelpText": "Relative Pfade befinden sich unter Prowlarrs AppData Ordner", "DelayProfile": "Verzögerungs Profil", "MaximumLimits": "Maximale Grenzen", "RecycleBinCleanupDaysHelpTextWarning": "Datien im Papierkorb die älter sind als der gewählte Wert, werden endgültig gelöscht", @@ -686,8 +686,8 @@ "Manual": "Manuell", "LogLevelTraceHelpTextWarning": "Trace logging sollte nur kurzzeitig aktiviert werden", "LastDuration": "Letzte Laufzeit", - "IncludeRecommendationsHelpText": "Radarrs Empfehlungen in der Entdeckungsansicht mit einbeziehen", - "IncludeRadarrRecommendations": "Prowlarr Empfehlungen einbeziehen", + "IncludeRecommendationsHelpText": "Prowlarrs Empfehlungen in der Entdeckungsansicht mit einbeziehen", + "IncludeProwlarrRecommendations": "Prowlarr Empfehlungen einbeziehen", "ImportFailedInterp": "Import fehlgeschlagen: {0}", "ImportFailed": "Import fehlgeschlagen: {0}", "HiddenClickToShow": "Versteckt, klicken zum anzeigen", @@ -755,10 +755,10 @@ "Restore": "Wiederherstellen", "RequiredPlaceHolder": "Neue Beschränkung hinzufügen", "RegularExpressionsCanBeTested": "Reguläre Ausdrücke können getestet werden ", - "RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Benutzerdefinierte Bedingungen gegen die unten aufgeführten Release-Eigenschaften werden unterstützt.", - "RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "RSS Film Listen sowie unten aufgelistete werden untertützt.", - "RadarrSupportsAnyIndexer": "Jeder Indexer der den Newznab-Standard verwendet oder unten aufgelistet ist wird untertützt.", - "RadarrSupportsAnyDownloadClient": "Jeder Downloader der den Newznab-Standard verwendet oder unten aufgelistet ist wird untertützt.", + "ProwlarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Benutzerdefinierte Bedingungen gegen die unten aufgeführten Release-Eigenschaften werden unterstützt.", + "ProwlarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "RSS Film Listen sowie unten aufgelistete werden untertützt.", + "ProwlarrSupportsAnyIndexer": "Jeder Indexer der den Newznab-Standard verwendet oder unten aufgelistet ist wird untertützt.", + "ProwlarrSupportsAnyDownloadClient": "Jeder Downloader der den Newznab-Standard verwendet oder unten aufgelistet ist wird untertützt.", "OnDeleteHelpText": "Löschen", "NoUpdatesAreAvailable": "Es sind keine Updates verfügbar", "NoTagsHaveBeenAddedYet": "Es wurden noch keine Tags erstellt", diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index a044dfa46..c9f2d9546 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -326,7 +326,7 @@ "IncludeCustomFormatWhenRenaming": "Include Custom Format when Renaming", "IncludeCustomFormatWhenRenamingHelpText": "Include in {Custom Formats} renaming format", "IncludeHealthWarningsHelpText": "Include Health Warnings", - "IncludeRadarrRecommendations": "Include Prowlarr Recommendations", + "IncludeProwlarrRecommendations": "Include Prowlarr Recommendations", "IncludeRecommendationsHelpText": "Include Prowlarr recommended movies in discovery view", "IncludeUnknownMovieItemsHelpText": "Show items without a movie in the queue. This could include removed movies or anything else in Prowlarr's category", "IncludeUnmonitored": "Include Unmonitored", @@ -552,11 +552,11 @@ "Queued": "Queued", "QuickImport": "Quick Import", "Prowlarr": "Prowlarr", - "RadarrSupportsAnyDownloadClient": "Prowlarr supports any download client that uses the Newznab standard, as well as other download clients listed below.", - "RadarrSupportsAnyIndexer": "Prowlarr supports any indexer that uses the Newznab standard, as well as other indexers listed below.", - "RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "Prowlarr supports any RSS movie lists as well as the one stated below.", - "RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Prowlarr supports custom conditions against the release properties below.", - "RadarrTags": "Prowlarr Tags", + "ProwlarrSupportsAnyDownloadClient": "Prowlarr supports any download client that uses the Newznab standard, as well as other download clients listed below.", + "ProwlarrSupportsAnyIndexer": "Prowlarr supports any indexer that uses the Newznab standard, as well as other indexers listed below.", + "ProwlarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "Prowlarr supports any RSS movie lists as well as the one stated below.", + "ProwlarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Prowlarr supports custom conditions against the release properties below.", + "ProwlarrTags": "Prowlarr Tags", "Ratings": "Ratings", "ReadTheWikiForMoreInformation": "Read the Wiki for more information", "Real": "Real", @@ -617,7 +617,7 @@ "ResetAPIKey": "Reset API Key", "Restart": "Restart", "RestartNow": "Restart Now", - "RestartRadarr": "Restart Prowlarr", + "RestartProwlarr": "Restart Prowlarr", "RestartRequiredHelpTextWarning": "Requires restart to take effect", "Restore": "Restore", "RestoreBackup": "Restore Backup", diff --git a/src/NzbDrone.Core/Localization/Core/es.json b/src/NzbDrone.Core/Localization/Core/es.json index 1a27de751..9c01651c2 100644 --- a/src/NzbDrone.Core/Localization/Core/es.json +++ b/src/NzbDrone.Core/Localization/Core/es.json @@ -499,7 +499,7 @@ "Retention": "Retención", "Result": "Resultado", "RestartRequiredHelpTextWarning": "Requiere reiniciar para que surta efecto", - "RestartRadarr": "Reiniciar Prowlarr", + "RestartProwlarr": "Reiniciar Prowlarr", "RestartNow": "Reiniciar Ahora", "ResetAPIKey": "Reajustar API", "Reset": "Reajustar", @@ -534,7 +534,7 @@ "Reason": "Razón", "Real": "Real", "ReadTheWikiForMoreInformation": "Lee la Wiki para más información", - "RadarrTags": "Etiquetas de Prowlarr", + "ProwlarrTags": "Etiquetas de Prowlarr", "Prowlarr": "Prowlarr", "QualitySettings": "Ajustes de Calidad", "QualityCutoffHasNotBeenMet": "Corte de calidad no ha sido alcanzado", @@ -687,7 +687,7 @@ "LogLevelTraceHelpTextWarning": "El registro de seguimiento se ha de habilitar solo temporalmente", "LastDuration": "Duración", "IncludeRecommendationsHelpText": "Incluir las películas recomendadas por Prowlarr en la vista de descubrir", - "IncludeRadarrRecommendations": "Incluir Recomendaciones de Prowlarr", + "IncludeProwlarrRecommendations": "Incluir Recomendaciones de Prowlarr", "ImportFailedInterp": "la importación ha fallado: {0}", "ImportFailed": "Importación fallida: {0}", "HiddenClickToShow": "Oculto, clic para mostrar", @@ -722,7 +722,7 @@ "BeforeUpdate": "Antes de actualizar", "AllowMovieChangeClickToChangeMovie": "Clic para cambiar la película", "AddingTag": "Añadiendo etiqueta", - "RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Prowlarr soporta condiciones personalizadas contra las propiedades de estrenos abajo.", + "ProwlarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Prowlarr soporta condiciones personalizadas contra las propiedades de estrenos abajo.", "ThisConditionMatchesUsingRegularExpressions": "Esta condición coincide con el uso de Expresiones Regulares. Tenga en cuenta que los caracteres {0} tienen significados especiales y necesitan escapar con un {1}", "YouCanAlsoSearch": "También puedes buscar usando la ID de TMDb o la ID de IMDb de una película. ej. tmdb:71663", "VisitGithubCustomFormatsAphrodite": "Visita Github para más detalles: ", @@ -756,9 +756,9 @@ "Restore": "Restaurar", "RequiredPlaceHolder": "Añadir nueva restricción", "RegularExpressionsCanBeTested": "Las expresiones regulares se pueden testear ", - "RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "Prowlarr soporta cualquier lista RSS de películas, como también la listada debajo.", - "RadarrSupportsAnyIndexer": "Prowlarr soporta cualquier indexer que utilice el estandar Newznab, como también cualquiera de los indexers listados debajo.", - "RadarrSupportsAnyDownloadClient": "Raddar soporta cualquier gestor de descargas que utilice el estandar Newznab, como también los clientes indicados debajo.", + "ProwlarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "Prowlarr soporta cualquier lista RSS de películas, como también la listada debajo.", + "ProwlarrSupportsAnyIndexer": "Prowlarr soporta cualquier indexer que utilice el estandar Newznab, como también cualquiera de los indexers listados debajo.", + "ProwlarrSupportsAnyDownloadClient": "Raddar soporta cualquier gestor de descargas que utilice el estandar Newznab, como también los clientes indicados debajo.", "OnDeleteHelpText": "Al Borrar", "NoUpdatesAreAvailable": "No hay actualizaciones disponibles", "NoTagsHaveBeenAddedYet": "No se han añadido etiquetas todavía", diff --git a/src/NzbDrone.Core/Localization/Core/fr.json b/src/NzbDrone.Core/Localization/Core/fr.json index 4be82f2e0..fc7fc34b7 100644 --- a/src/NzbDrone.Core/Localization/Core/fr.json +++ b/src/NzbDrone.Core/Localization/Core/fr.json @@ -506,7 +506,7 @@ "IndexerPriority": "Priorité de l'indexeur", "IncludeUnmonitored": "Inclure non surveillé", "IncludeRecommendationsHelpText": "Inclure les films recommandés par Prowlarr dans la vue découverte", - "IncludeRadarrRecommendations": "Inclure les recommandations de Prowlarr", + "IncludeProwlarrRecommendations": "Inclure les recommandations de Prowlarr", "ImportMovies": "Importer Films", "ImportListSyncIntervalHelpText": "À quelle fréquence Prowlarr se synchronise avec vos listes.", "Importing": "Importation", @@ -721,7 +721,7 @@ "Result": "Résultat", "Restore": "Restaurer", "RestartRequiredHelpTextWarning": "Nécessite un redémarrage pour prendre effet", - "RestartRadarr": "Redémarrer Prowlarr", + "RestartProwlarr": "Redémarrer Prowlarr", "RestartNow": "Redémarrer maintenant", "ResetAPIKey": "Réinitialiser la clé API", "Reset": "Réinitialiser", @@ -734,7 +734,7 @@ "Reorder": "Réorganiser", "RenameMoviesHelpText": "Prowlarr utilisera le nom de fichier existant si le changement de nom est désactivé", "RemovingTag": "Suppression du tag", - "RadarrTags": "Prowlarr Tags", + "ProwlarrTags": "Prowlarr Tags", "QualityProfileDeleteConfirm": "Voulez-vous vraiment supprimer le profil de qualité {0}", "Paused": "En pause", "MarkAsFailedMessageText": "Voulez-vous vraiment marquer '{0}' comme échoué ?", @@ -767,10 +767,10 @@ "Reason": "Raison", "Real": "Réel", "ReadTheWikiForMoreInformation": "Consultez le Wiki pour plus d'informations", - "RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Prowlarr prend en charge les conditions personnalisées par rapport aux propriétés de publication ci-dessous.", - "RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "Prowlarr prend en charge toutes les listes de films RSS ainsi que celle indiquée ci-dessous.", - "RadarrSupportsAnyIndexer": "Prowlarr prend en charge tout indexeur qui utilise le standard Newznab, ainsi que d'autres indexeurs répertoriés ci-dessous.", - "RadarrSupportsAnyDownloadClient": "Prowlarr prend en charge tout client de téléchargement qui utilise le standard Newznab, ainsi que d'autres clients de téléchargement répertoriés ci-dessous.", + "ProwlarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Prowlarr prend en charge les conditions personnalisées par rapport aux propriétés de publication ci-dessous.", + "ProwlarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "Prowlarr prend en charge toutes les listes de films RSS ainsi que celle indiquée ci-dessous.", + "ProwlarrSupportsAnyIndexer": "Prowlarr prend en charge tout indexeur qui utilise le standard Newznab, ainsi que d'autres indexeurs répertoriés ci-dessous.", + "ProwlarrSupportsAnyDownloadClient": "Prowlarr prend en charge tout client de téléchargement qui utilise le standard Newznab, ainsi que d'autres clients de téléchargement répertoriés ci-dessous.", "Prowlarr": "Prowlarr", "Queued": "En file d'attente", "QualitySettings": "Paramètres Qualité", diff --git a/src/NzbDrone.Core/Localization/Core/hu.json b/src/NzbDrone.Core/Localization/Core/hu.json index 28a46e5cb..e71deeb38 100644 --- a/src/NzbDrone.Core/Localization/Core/hu.json +++ b/src/NzbDrone.Core/Localization/Core/hu.json @@ -357,7 +357,7 @@ "Seeders": "Seederek", "Security": "Biztonság", "SearchSelected": "Kiválasztottak keresése", - "SearchOnAddHelpText": "Keresse meg a listán található filmeket, ha hozzá van adva a Radarrhoz", + "SearchOnAddHelpText": "Keresse meg a listán található filmeket, ha hozzá van adva a Prowlarrhoz", "SearchOnAdd": "Keresés hozzáadáskor", "SearchMovie": "Film keresés", "SearchForMovie": "Film keresés", @@ -388,7 +388,7 @@ "RestoreBackup": "Biztonsági mentés visszaállítása", "Restore": "Visszaállítás", "RestartRequiredHelpTextWarning": "Újraindítás szükséges a hatálybalépéshez", - "RestartRadarr": "Prowlarr Újraindítása", + "RestartProwlarr": "Prowlarr Újraindítása", "RestartNow": "Újraindítás Most", "Restart": "Újraindítás", "ResetAPIKey": "API Kulcs visszaállítása", @@ -448,11 +448,11 @@ "Real": "Valódi", "ReadTheWikiForMoreInformation": "Olvasd el a Wiki-t további információkért", "Ratings": "Értékelések", - "RadarrTags": "Prowlarr Címkék", - "RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "A Prowlarr támogatja az egyéni feltételeket az alábbi kiadási tulajdonságokkal szemben.", - "RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "A Prowlarr támogatja az RSS filmlistákat, valamint az alábbiakban felsoroltakat.", - "RadarrSupportsAnyIndexer": "A Prowlarr minden indexert támogat, amely a Newznab szabványt használja, valamint az alább felsorolt egyéb indexereket.", - "RadarrSupportsAnyDownloadClient": "A Prowlarr minden olyan letöltési klienst támogat, amely a Newznab szabványt használja, valamint az alább felsorolt letöltési klienseket.", + "ProwlarrTags": "Prowlarr Címkék", + "ProwlarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "A Prowlarr támogatja az egyéni feltételeket az alábbi kiadási tulajdonságokkal szemben.", + "ProwlarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "A Prowlarr támogatja az RSS filmlistákat, valamint az alábbiakban felsoroltakat.", + "ProwlarrSupportsAnyIndexer": "A Prowlarr minden indexert támogat, amely a Newznab szabványt használja, valamint az alább felsorolt egyéb indexereket.", + "ProwlarrSupportsAnyDownloadClient": "A Prowlarr minden olyan letöltési klienst támogat, amely a Newznab szabványt használja, valamint az alább felsorolt letöltési klienseket.", "Prowlarr": "Prowlarr", "QuickImport": "Gyors Importálás", "Queued": "Sorban", @@ -735,7 +735,7 @@ "IncludeUnmonitored": "Figyelmen Kívül hagyott Filmeket is Tartalmazza", "IncludeUnknownMovieItemsHelpText": "Mutasson tételeket film nélkül a sorban. Ez tartalmazhat eltávolított filmeket vagy bármi mást a Prowlarr kategóriájából", "IncludeRecommendationsHelpText": "Helyezze be a Prowlarr ajánlásait a felfedező nézetbe", - "IncludeRadarrRecommendations": "Tartalmazza a Prowlarr Ajánlásait", + "IncludeProwlarrRecommendations": "Tartalmazza a Prowlarr Ajánlásait", "IncludeHealthWarningsHelpText": "Tartalmazza a Állapot Figyelmeztetéseket", "IncludeCustomFormatWhenRenamingHelpText": "Tartalmazza a(z) {Custom Formats} átnevezési formátumot", "IncludeCustomFormatWhenRenaming": "Az átnevezéskor vegye fel az egyéni formátumot", diff --git a/src/NzbDrone.Core/Localization/Core/it.json b/src/NzbDrone.Core/Localization/Core/it.json index 145cceb11..357b951b3 100644 --- a/src/NzbDrone.Core/Localization/Core/it.json +++ b/src/NzbDrone.Core/Localization/Core/it.json @@ -380,7 +380,7 @@ "AllowMovieChangeClickToChangeMovie": "Clicca per cambiare film", "AddingTag": "Aggiungi tag", "AddImportExclusionHelpText": "Impedire che il film venga aggiunto a Prowlarr da liste", - "RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Prowlarr supporta condizioni personalizzate verso le seguenti release.", + "ProwlarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Prowlarr supporta condizioni personalizzate verso le seguenti release.", "Prowlarr": "Prowlarr", "Proper": "Proper", "Posters": "Locandine", @@ -433,7 +433,7 @@ "Result": "Risultato", "Restore": "Ripristina", "RestartRequiredHelpTextWarning": "Richiede il riavvio per avere effetti", - "RestartRadarr": "Riavvia Prowlarr", + "RestartProwlarr": "Riavvia Prowlarr", "RestartNow": "Riavvia adesso", "ResetAPIKey": "Resetta la Chiave API", "Reset": "Resetta", @@ -474,9 +474,9 @@ "Reason": "Ragione", "Real": "Reale", "ReadTheWikiForMoreInformation": "Leggi le Wiki per maggiori informazioni", - "RadarrSupportsAnyIndexer": "Prowlarr supporta qualunque indexer che usi gli standard Newznab, cosi come gli altri Indexer sotto.", - "RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "Prowlarr supporta qualunque Lista di film RSS, cosi come le altre sotto.", - "RadarrSupportsAnyDownloadClient": "Prowlarr supporta qualunque client di download che usi gli standard Newznab, cosi come gli altri client sotto.", + "ProwlarrSupportsAnyIndexer": "Prowlarr supporta qualunque indexer che usi gli standard Newznab, cosi come gli altri Indexer sotto.", + "ProwlarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "Prowlarr supporta qualunque Lista di film RSS, cosi come le altre sotto.", + "ProwlarrSupportsAnyDownloadClient": "Prowlarr supporta qualunque client di download che usi gli standard Newznab, cosi come gli altri client sotto.", "QuickImport": "Importazione veloce", "Queued": "Messo in coda", "QualitySettings": "Impostazione di Qualità", @@ -587,7 +587,7 @@ "IncludeUnmonitored": "Includi non Monitorati", "IncludeUnknownMovieItemsHelpText": "Mostra le voci senza un film nella coda. Ciò potrebbe include film spostati o altro nelle categorie di Prowlarr", "IncludeRecommendationsHelpText": "Includi le raccomandazioni di Prowlarr nella vista scoperta", - "IncludeRadarrRecommendations": "Includi le raccomandazioni di Prowlarr", + "IncludeProwlarrRecommendations": "Includi le raccomandazioni di Prowlarr", "IncludeHealthWarningsHelpText": "Includi gli avvisi di salute", "IncludeCustomFormatWhenRenaming": "Includi formati personalizzati quando rinomini", "ImportMovies": "Importa Film", @@ -802,7 +802,7 @@ "SettingsRemotePathMappingLocalPath": "Percorso locale", "SettingsRemotePathMappingHostHelpText": "Lo stesso host specificato per il client di download remoto", "SettingsEnableColorImpairedModeHelpText": "Stile alterato per permettere agli utenti daltonici di distinguere meglio le informazioni con colori codificati", - "RadarrTags": "Tag di Prowlarr", + "ProwlarrTags": "Tag di Prowlarr", "DownloadPropersAndRepacksHelpTextWarning": "Usa le parole preferite per aggiornare automaticamente a proper/repack", "DownloadPropersAndRepacksHelpText2": "Usa \"Preferisco di no\" per ordinare i punteggi della parola preferita più di proper/repack", "DownloadPropersAndRepacksHelpText1": "Aggiornare o meno automaticamente a Proper/Repack", diff --git a/src/NzbDrone.Core/Localization/Core/nl.json b/src/NzbDrone.Core/Localization/Core/nl.json index 222ff5427..67eaa60e4 100644 --- a/src/NzbDrone.Core/Localization/Core/nl.json +++ b/src/NzbDrone.Core/Localization/Core/nl.json @@ -569,7 +569,7 @@ "Proper": "PROPER", "ProxyBypassFilterHelpText": "Gebruik ',' als scheidingsteken en '*' als wildcard voor subdomeinen", "Prowlarr": "Prowlarr", - "RadarrTags": "Prowlarr Tags", + "ProwlarrTags": "Prowlarr Tags", "ReleaseDates": "Uitgave Datums", "ReleaseRejected": "Uitgave Afgekeurd", "Remove": "Verwijder", @@ -588,7 +588,7 @@ "RescanMovieFolderAfterRefresh": "De film map herscannen na vernieuwen", "Reset": "Reset", "RestartNow": "Herstart Nu", - "RestartRadarr": "Herstart Prowlarr", + "RestartProwlarr": "Herstart Prowlarr", "RestartRequiredHelpTextWarning": "Herstarten vereist om in werking te treden", "Result": "Resultaat", "Retention": "Retentie", @@ -687,7 +687,7 @@ "LogLevelTraceHelpTextWarning": "Trace log niveau moet enkel tijdelijk worden gebruikt", "LastDuration": "Laatste Looptijd", "IncludeRecommendationsHelpText": "Voeg Prowlarr aanbevolen films toe aan ontdekken weergave", - "IncludeRadarrRecommendations": "Voeg Prowlarr Aanbevelingen Toe", + "IncludeProwlarrRecommendations": "Voeg Prowlarr Aanbevelingen Toe", "ImportFailedInterp": "Importeren mislukt: {0}", "ImportFailed": "Importeren mislukt: {0}", "HiddenClickToShow": "Verborgen, klik om te tonen", @@ -747,10 +747,10 @@ "UnableToAddANewConditionPleaseTryAgain": "Kon geen nieuwe conditie toevoegen, gelieve opnieuw te proberen.", "ThisConditionMatchesUsingRegularExpressions": "Deze conditie toont een overeenkomst vanwege Reguliere Expressie. Merk op dat de karakters {0} een speciale betekenis hebben en met {1} moeten worden voorgegaan om hun oorspronkelijke betekenis te krijgen", "RegularExpressionsCanBeTested": "Reguliere expressies kunnen worden getest ", - "RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Prowlarr ondersteunt aangepaste condities tegenover de uitgave eigenschappen hieronder.", - "RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "Prowlarr ondersteunt elke RSS filmlijst, tevens ook de ander hieronder weergegeven lijsten.", - "RadarrSupportsAnyIndexer": "Prowlarr ondersteund elke indexeerder die gebruik maakt van de Newznab standaard, tevens ook de ander hieronder weergegeven indexeerders.", - "RadarrSupportsAnyDownloadClient": "Prowlarr ondersteund elke downloader die gebruik maakt van de Newznab standaard, tevens ook de ander hieronder weergegeven downloaders.", + "ProwlarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "Prowlarr ondersteunt aangepaste condities tegenover de uitgave eigenschappen hieronder.", + "ProwlarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "Prowlarr ondersteunt elke RSS filmlijst, tevens ook de ander hieronder weergegeven lijsten.", + "ProwlarrSupportsAnyIndexer": "Prowlarr ondersteund elke indexeerder die gebruik maakt van de Newznab standaard, tevens ook de ander hieronder weergegeven indexeerders.", + "ProwlarrSupportsAnyDownloadClient": "Prowlarr ondersteund elke downloader die gebruik maakt van de Newznab standaard, tevens ook de ander hieronder weergegeven downloaders.", "NoTagsHaveBeenAddedYet": "Er zijn nog geen tags toegevoegd", "MissingMonitoredAndConsideredAvailable": "Ontbrekend, Bewaakt en beschouwd als Beschikbaar", "HaveNotAddedMovies": "U heeft nog geen films toegevoegd, wilt u eerst enkele of al uw films importeren?", diff --git a/src/NzbDrone.Core/Localization/Core/pt.json b/src/NzbDrone.Core/Localization/Core/pt.json index 1b7e4981e..b727bf97b 100644 --- a/src/NzbDrone.Core/Localization/Core/pt.json +++ b/src/NzbDrone.Core/Localization/Core/pt.json @@ -559,7 +559,7 @@ "TestAllIndexers": "Testar Todos os Indexadores", "RSSSyncIntervalHelpTextWarning": "Isto se aplicará a todos os indexadores, siga as regras estabelecidas por eles", "RSSIsNotSupportedWithThisIndexer": "RSS não é suportado por esse indexador", - "RadarrSupportsAnyIndexer": "O Prowlarr suporta qualquer indexador que use o padrão Newznab, bem como outros indexadores listados abaixo.", + "ProwlarrSupportsAnyIndexer": "O Prowlarr suporta qualquer indexador que use o padrão Newznab, bem como outros indexadores listados abaixo.", "IndexerPriorityHelpText": "Prioridade do Indexador de 1 (mais alta) a 50 (mais baixa). Padrão: 25.", "IndexerPriority": "Prioridade do Indexador", "ForMoreInformationOnTheIndividualIndexers": "Para mais informações sobre cada indexador, clique nos botões de informação.", @@ -576,7 +576,7 @@ "Retention": "Retenção", "Result": "Resultado", "Restore": "Restaurar", - "RestartRadarr": "Reiniciar Prowlarr", + "RestartProwlarr": "Reiniciar Prowlarr", "RestartNow": "Reiniciar Agora", "ResetAPIKey": "Redefinir Chave API", "Reset": "Redefinir", @@ -598,7 +598,7 @@ "Reason": "Razão", "Real": "Real", "ReadTheWikiForMoreInformation": "Leia a Wiki para mais informações", - "RadarrTags": "Tags do Prowlarr", + "ProwlarrTags": "Tags do Prowlarr", "Prowlarr": "Prowlarr", "Queued": "Em Fila", "Priority": "Prioridade", @@ -625,7 +625,7 @@ "LinkHere": "aqui", "LastDuration": "Duração", "InteractiveSearch": "Busca Interativa", - "IncludeRadarrRecommendations": "Incluir recomendações do Prowlarr", + "IncludeProwlarrRecommendations": "Incluir recomendações do Prowlarr", "ImportListSyncIntervalHelpText": "Frequência com que o Prowlarr sincroniza suas listas.", "ImportListStatusCheckSingleClientMessage": "Listas indisponíveis devido a erros: {0}", "ImportListStatusCheckAllClientMessage": "Todas as listas estão indisponíveis devido a erros", @@ -739,9 +739,9 @@ "RemoveFailedDownloadsHelpText": "Remover downloads falhados do histórico do gerenciador de downloads", "RemoveCompletedDownloadsHelpText": "Remover downloads importados do histórico do gerenciador de downloads", "RecycleBinCleanupDaysHelpText": "Ajuste para 0 para desabilitar a limpeza automática", - "RadarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "O Radar suporta condições personalizadas em relação às propriedades das versões abaixo.", - "RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "O Prowlarr suporta qualquer lista RSS de filmes, bem como os demais listados abaixo.", - "RadarrSupportsAnyDownloadClient": "O Prowlarr suporta qualquer gerenciador de download que utilize o padrão Newznab, bem como os demais listados abaixo.", + "ProwlarrSupportsCustomConditionsAgainstTheReleasePropertiesBelow": "O Radar suporta condições personalizadas em relação às propriedades das versões abaixo.", + "ProwlarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow": "O Prowlarr suporta qualquer lista RSS de filmes, bem como os demais listados abaixo.", + "ProwlarrSupportsAnyDownloadClient": "O Prowlarr suporta qualquer gerenciador de download que utilize o padrão Newznab, bem como os demais listados abaixo.", "QualityProfileDeleteConfirm": "Tem certeza que quer deletar o perfil de qualidade {0}", "ProxyUsernameHelpText": "Apenas insira usuário e senha caso seja requerido. Caso contrário, deixe em branco.", "ProxyPasswordHelpText": "Apenas insira usuário e senha caso seja requerido. Caso contrário, deixe em branco.", diff --git a/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs b/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs index 8d0232de8..98ced05c4 100755 --- a/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs +++ b/src/NzbDrone.Core/Notifications/CustomScript/CustomScript.cs @@ -34,11 +34,11 @@ namespace NzbDrone.Core.Notifications.CustomScript { var environmentVariables = new StringDictionary(); - environmentVariables.Add("Radarr_EventType", "HealthIssue"); - environmentVariables.Add("Radarr_Health_Issue_Level", nameof(healthCheck.Type)); - environmentVariables.Add("Radarr_Health_Issue_Message", healthCheck.Message); - environmentVariables.Add("Radarr_Health_Issue_Type", healthCheck.Source.Name); - environmentVariables.Add("Radarr_Health_Issue_Wiki", healthCheck.WikiUrl.ToString() ?? string.Empty); + environmentVariables.Add("Prowlarr_EventType", "HealthIssue"); + environmentVariables.Add("Prowlarr_Health_Issue_Level", nameof(healthCheck.Type)); + environmentVariables.Add("Prowlarr_Health_Issue_Message", healthCheck.Message); + environmentVariables.Add("Prowlarr_Health_Issue_Type", healthCheck.Source.Name); + environmentVariables.Add("Prowlarr_Health_Issue_Wiki", healthCheck.WikiUrl.ToString() ?? string.Empty); ExecuteScript(environmentVariables); } @@ -65,7 +65,7 @@ namespace NzbDrone.Core.Notifications.CustomScript try { var environmentVariables = new StringDictionary(); - environmentVariables.Add("Radarr_EventType", "Test"); + environmentVariables.Add("Prowlarr_EventType", "Test"); var processOutput = ExecuteScript(environmentVariables); diff --git a/src/NzbDrone.Core/Notifications/DiscordNotifier/DiscordNotifier.cs b/src/NzbDrone.Core/Notifications/DiscordNotifier/DiscordNotifier.cs index a890d72d5..338cd3b7e 100644 --- a/src/NzbDrone.Core/Notifications/DiscordNotifier/DiscordNotifier.cs +++ b/src/NzbDrone.Core/Notifications/DiscordNotifier/DiscordNotifier.cs @@ -20,11 +20,11 @@ namespace NzbDrone.Core.Notifications.DiscordNotifier { var variables = new StringDictionary(); - variables.Add("Radarr_EventType", "HealthIssue"); - variables.Add("Radarr_Health_Issue_Level", nameof(healthCheck.Type)); - variables.Add("Radarr_Health_Issue_Message", healthCheck.Message); - variables.Add("Radarr_Health_Issue_Type", healthCheck.Source.Name); - variables.Add("Radarr_Health_Issue_Wiki", healthCheck.WikiUrl.ToString() ?? string.Empty); + variables.Add("Prowlarr_EventType", "HealthIssue"); + variables.Add("Prowlarr_Health_Issue_Level", nameof(healthCheck.Type)); + variables.Add("Prowlarr_Health_Issue_Message", healthCheck.Message); + variables.Add("Prowlarr_Health_Issue_Type", healthCheck.Source.Name); + variables.Add("Prowlarr_Health_Issue_Wiki", healthCheck.WikiUrl.ToString() ?? string.Empty); _proxy.SendNotification(variables, Settings); } diff --git a/src/NzbDrone.Core/Notifications/DiscordNotifier/DiscordNotifierProxy.cs b/src/NzbDrone.Core/Notifications/DiscordNotifier/DiscordNotifierProxy.cs index 1d1f98169..3eef6d551 100644 --- a/src/NzbDrone.Core/Notifications/DiscordNotifier/DiscordNotifierProxy.cs +++ b/src/NzbDrone.Core/Notifications/DiscordNotifier/DiscordNotifierProxy.cs @@ -43,7 +43,7 @@ namespace NzbDrone.Core.Notifications.DiscordNotifier try { var variables = new StringDictionary(); - variables.Add("Radarr_EventType", "Test"); + variables.Add("Prowlarr_EventType", "Test"); SendNotification(variables, settings); return null; diff --git a/src/NzbDrone.Core/Restrictions/PerlRegexFactory.cs b/src/NzbDrone.Core/Restrictions/PerlRegexFactory.cs deleted file mode 100644 index 52806c80d..000000000 --- a/src/NzbDrone.Core/Restrictions/PerlRegexFactory.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Text.RegularExpressions; - -namespace NzbDrone.Core.Restrictions -{ - public static class PerlRegexFactory - { - private static Regex _perlRegexFormat = new Regex(@"/(?.*)/(?[a-z]*)", RegexOptions.Compiled); - - public static bool TryCreateRegex(string pattern, out Regex regex) - { - var match = _perlRegexFormat.Match(pattern); - - if (!match.Success) - { - regex = null; - return false; - } - - regex = CreateRegex(match.Groups["pattern"].Value, match.Groups["modifiers"].Value); - return true; - } - - public static Regex CreateRegex(string pattern, string modifiers) - { - var options = GetOptions(modifiers); - - // For now we simply expect the pattern to be .net compliant. We should probably check and reject perl-specific constructs. - return new Regex(pattern, options | RegexOptions.Compiled); - } - - private static RegexOptions GetOptions(string modifiers) - { - var options = RegexOptions.None; - - foreach (var modifier in modifiers) - { - switch (modifier) - { - case 'm': - options |= RegexOptions.Multiline; - break; - - case 's': - options |= RegexOptions.Singleline; - break; - - case 'i': - options |= RegexOptions.IgnoreCase; - break; - - case 'x': - options |= RegexOptions.IgnorePatternWhitespace; - break; - - case 'n': - options |= RegexOptions.ExplicitCapture; - break; - - default: - throw new ArgumentException("Unknown or unsupported perl regex modifier: " + modifier); - } - } - - return options; - } - } -} diff --git a/src/NzbDrone.Core/Restrictions/Restriction.cs b/src/NzbDrone.Core/Restrictions/Restriction.cs deleted file mode 100644 index 9be667d81..000000000 --- a/src/NzbDrone.Core/Restrictions/Restriction.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using NzbDrone.Core.Datastore; - -namespace NzbDrone.Core.Restrictions -{ - public class Restriction : ModelBase - { - public string Required { get; set; } - public string Preferred { get; set; } - public string Ignored { get; set; } - public HashSet Tags { get; set; } - - public Restriction() - { - Tags = new HashSet(); - } - } -} diff --git a/src/NzbDrone.Core/Restrictions/RestrictionRepository.cs b/src/NzbDrone.Core/Restrictions/RestrictionRepository.cs deleted file mode 100644 index a88b0e67f..000000000 --- a/src/NzbDrone.Core/Restrictions/RestrictionRepository.cs +++ /dev/null @@ -1,17 +0,0 @@ -using NzbDrone.Core.Datastore; -using NzbDrone.Core.Messaging.Events; - -namespace NzbDrone.Core.Restrictions -{ - public interface IRestrictionRepository : IBasicRepository - { - } - - public class RestrictionRepository : BasicRepository, IRestrictionRepository - { - public RestrictionRepository(IMainDatabase database, IEventAggregator eventAggregator) - : base(database, eventAggregator) - { - } - } -} diff --git a/src/NzbDrone.Core/Restrictions/RestrictionService.cs b/src/NzbDrone.Core/Restrictions/RestrictionService.cs deleted file mode 100644 index 561add650..000000000 --- a/src/NzbDrone.Core/Restrictions/RestrictionService.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using NLog; -using NzbDrone.Common.Extensions; - -namespace NzbDrone.Core.Restrictions -{ - public interface IRestrictionService - { - List All(); - List AllForTag(int tagId); - List AllForTags(HashSet tagIds); - Restriction Get(int id); - void Delete(int id); - Restriction Add(Restriction restriction); - Restriction Update(Restriction restriction); - } - - public class RestrictionService : IRestrictionService - { - private readonly IRestrictionRepository _repo; - private readonly Logger _logger; - - public RestrictionService(IRestrictionRepository repo, Logger logger) - { - _repo = repo; - _logger = logger; - } - - public List All() - { - return _repo.All().ToList(); - } - - public List AllForTag(int tagId) - { - return _repo.All().Where(r => r.Tags.Contains(tagId)).ToList(); - } - - public List AllForTags(HashSet tagIds) - { - return _repo.All().Where(r => r.Tags.Intersect(tagIds).Any() || r.Tags.Empty()).ToList(); - } - - public Restriction Get(int id) - { - return _repo.Get(id); - } - - public void Delete(int id) - { - _repo.Delete(id); - } - - public Restriction Add(Restriction restriction) - { - return _repo.Insert(restriction); - } - - public Restriction Update(Restriction restriction) - { - return _repo.Update(restriction); - } - } -} diff --git a/src/NzbDrone.Core/Restrictions/TermMatcher.cs b/src/NzbDrone.Core/Restrictions/TermMatcher.cs deleted file mode 100644 index ceb5d66a9..000000000 --- a/src/NzbDrone.Core/Restrictions/TermMatcher.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Text.RegularExpressions; -using NzbDrone.Common.Cache; - -namespace NzbDrone.Core.Restrictions -{ - public interface ITermMatcher - { - bool IsMatch(string term, string value); - } - - public class TermMatcher : ITermMatcher - { - private ICached> _matcherCache; - - public TermMatcher(ICacheManager cacheManager) - { - _matcherCache = cacheManager.GetCache>(GetType()); - } - - public bool IsMatch(string term, string value) - { - return GetMatcher(term)(value); - } - - public Predicate GetMatcher(string term) - { - return _matcherCache.Get(term, () => CreateMatcherInternal(term), TimeSpan.FromHours(24)); - } - - private Predicate CreateMatcherInternal(string term) - { - Regex regex; - if (PerlRegexFactory.TryCreateRegex(term, out regex)) - { - return regex.IsMatch; - } - else - { - return new CaseInsensitiveTermMatcher(term).IsMatch; - } - } - - private sealed class CaseInsensitiveTermMatcher - { - private readonly string _term; - - public CaseInsensitiveTermMatcher(string term) - { - _term = term.ToLowerInvariant(); - } - - public bool IsMatch(string value) - { - return value.ToLowerInvariant().Contains(_term); - } - } - } -} diff --git a/src/NzbDrone.Core/Tags/TagDetails.cs b/src/NzbDrone.Core/Tags/TagDetails.cs index 16c262176..d538b7771 100644 --- a/src/NzbDrone.Core/Tags/TagDetails.cs +++ b/src/NzbDrone.Core/Tags/TagDetails.cs @@ -7,17 +7,13 @@ namespace NzbDrone.Core.Tags public class TagDetails : ModelBase { public string Label { get; set; } - public List MovieIds { get; set; } public List NotificationIds { get; set; } - public List RestrictionIds { get; set; } - public List ImportListIds { get; set; } - public List DelayProfileIds { get; set; } public bool InUse { get { - return MovieIds.Any() || NotificationIds.Any() || RestrictionIds.Any() || DelayProfileIds.Any(); + return NotificationIds.Any(); } } } diff --git a/src/NzbDrone.Core/Tags/TagService.cs b/src/NzbDrone.Core/Tags/TagService.cs index 63a93ee8e..b8994d127 100644 --- a/src/NzbDrone.Core/Tags/TagService.cs +++ b/src/NzbDrone.Core/Tags/TagService.cs @@ -3,7 +3,6 @@ using System.Linq; using NzbDrone.Core.Datastore; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Notifications; -using NzbDrone.Core.Restrictions; namespace NzbDrone.Core.Tags { @@ -25,17 +24,14 @@ namespace NzbDrone.Core.Tags private readonly ITagRepository _repo; private readonly IEventAggregator _eventAggregator; private readonly INotificationFactory _notificationFactory; - private readonly IRestrictionService _restrictionService; public TagService(ITagRepository repo, IEventAggregator eventAggregator, - INotificationFactory notificationFactory, - IRestrictionService restrictionService) + INotificationFactory notificationFactory) { _repo = repo; _eventAggregator = eventAggregator; _notificationFactory = notificationFactory; - _restrictionService = restrictionService; } public Tag GetTag(int tagId) @@ -64,14 +60,12 @@ namespace NzbDrone.Core.Tags { var tag = GetTag(tagId); var notifications = _notificationFactory.AllForTag(tagId); - var restrictions = _restrictionService.AllForTag(tagId); return new TagDetails { Id = tagId, Label = tag.Label, - NotificationIds = notifications.Select(c => c.Id).ToList(), - RestrictionIds = restrictions.Select(c => c.Id).ToList() + NotificationIds = notifications.Select(c => c.Id).ToList() }; } @@ -79,7 +73,6 @@ namespace NzbDrone.Core.Tags { var tags = All(); var notifications = _notificationFactory.All(); - var restrictions = _restrictionService.All(); var details = new List(); @@ -89,8 +82,7 @@ namespace NzbDrone.Core.Tags { Id = tag.Id, Label = tag.Label, - NotificationIds = notifications.Where(c => c.Tags.Contains(tag.Id)).Select(c => c.Id).ToList(), - RestrictionIds = restrictions.Where(c => c.Tags.Contains(tag.Id)).Select(c => c.Id).ToList() + NotificationIds = notifications.Where(c => c.Tags.Contains(tag.Id)).Select(c => c.Id).ToList() }); } diff --git a/src/NzbDrone.Core/Update/UpdatePackageProvider.cs b/src/NzbDrone.Core/Update/UpdatePackageProvider.cs index 91c8eff34..ee0a275e8 100644 --- a/src/NzbDrone.Core/Update/UpdatePackageProvider.cs +++ b/src/NzbDrone.Core/Update/UpdatePackageProvider.cs @@ -21,7 +21,7 @@ namespace NzbDrone.Core.Update private readonly IPlatformInfo _platformInfo; private readonly IAnalyticsService _analyticsService; - public UpdatePackageProvider(IHttpClient httpClient, IRadarrCloudRequestBuilder requestBuilder, IAnalyticsService analyticsService, IPlatformInfo platformInfo) + public UpdatePackageProvider(IHttpClient httpClient, IProwlarrCloudRequestBuilder requestBuilder, IAnalyticsService analyticsService, IPlatformInfo platformInfo) { _platformInfo = platformInfo; _analyticsService = analyticsService; diff --git a/src/NzbDrone.Host.Test/NzbDroneProcessServiceFixture.cs b/src/NzbDrone.Host.Test/NzbDroneProcessServiceFixture.cs index 6294608b9..5cc591b39 100644 --- a/src/NzbDrone.Host.Test/NzbDroneProcessServiceFixture.cs +++ b/src/NzbDrone.Host.Test/NzbDroneProcessServiceFixture.cs @@ -20,11 +20,11 @@ namespace NzbDrone.App.Test .Returns(new ProcessInfo() { Id = CURRENT_PROCESS_ID }); Mocker.GetMock() - .Setup(s => s.FindProcessByName(ProcessProvider.RADARR_CONSOLE_PROCESS_NAME)) + .Setup(s => s.FindProcessByName(ProcessProvider.PROWLARR_CONSOLE_PROCESS_NAME)) .Returns(new List()); Mocker.GetMock() - .Setup(s => s.FindProcessByName(ProcessProvider.RADARR_PROCESS_NAME)) + .Setup(s => s.FindProcessByName(ProcessProvider.PROWLARR_PROCESS_NAME)) .Returns(new List()); } @@ -47,7 +47,7 @@ namespace NzbDrone.App.Test public void should_enforce_if_another_console_is_running() { Mocker.GetMock() - .Setup(c => c.FindProcessByName(ProcessProvider.RADARR_CONSOLE_PROCESS_NAME)) + .Setup(c => c.FindProcessByName(ProcessProvider.PROWLARR_CONSOLE_PROCESS_NAME)) .Returns(new List { new ProcessInfo { Id = 10 }, @@ -63,7 +63,7 @@ namespace NzbDrone.App.Test public void should_return_false_if_another_gui_is_running() { Mocker.GetMock() - .Setup(c => c.FindProcessByName(ProcessProvider.RADARR_PROCESS_NAME)) + .Setup(c => c.FindProcessByName(ProcessProvider.PROWLARR_PROCESS_NAME)) .Returns(new List { new ProcessInfo { Id = CURRENT_PROCESS_ID }, diff --git a/src/NzbDrone.Host/Bootstrap.cs b/src/NzbDrone.Host/Bootstrap.cs index 03a5d7902..e62617be1 100644 --- a/src/NzbDrone.Host/Bootstrap.cs +++ b/src/NzbDrone.Host/Bootstrap.cs @@ -50,7 +50,7 @@ namespace Prowlarr.Host } catch (InvalidConfigFileException ex) { - throw new RadarrStartupException(ex); + throw new ProwlarrStartupException(ex); } catch (TerminateApplicationException e) { diff --git a/src/NzbDrone.Host/MainAppContainerBuilder.cs b/src/NzbDrone.Host/MainAppContainerBuilder.cs index 941271c85..78831d23e 100644 --- a/src/NzbDrone.Host/MainAppContainerBuilder.cs +++ b/src/NzbDrone.Host/MainAppContainerBuilder.cs @@ -28,7 +28,7 @@ namespace Prowlarr.Host { AutoRegisterImplementations(); - Container.Register(); + Container.Register(); if (OsInfo.IsWindows) { diff --git a/src/NzbDrone.Host/SingleInstancePolicy.cs b/src/NzbDrone.Host/SingleInstancePolicy.cs index a365efe6a..79a5f9c05 100644 --- a/src/NzbDrone.Host/SingleInstancePolicy.cs +++ b/src/NzbDrone.Host/SingleInstancePolicy.cs @@ -65,8 +65,8 @@ namespace Prowlarr.Host { var currentId = _processProvider.GetCurrentProcess().Id; - var otherProcesses = _processProvider.FindProcessByName(ProcessProvider.RADARR_CONSOLE_PROCESS_NAME) - .Union(_processProvider.FindProcessByName(ProcessProvider.RADARR_PROCESS_NAME)) + var otherProcesses = _processProvider.FindProcessByName(ProcessProvider.PROWLARR_CONSOLE_PROCESS_NAME) + .Union(_processProvider.FindProcessByName(ProcessProvider.PROWLARR_PROCESS_NAME)) .Select(c => c.Id) .Except(new[] { currentId }) .ToList(); diff --git a/src/NzbDrone.Host/WebHost/WebHostController.cs b/src/NzbDrone.Host/WebHost/WebHostController.cs index d6b90b554..18460363e 100644 --- a/src/NzbDrone.Host/WebHost/WebHostController.cs +++ b/src/NzbDrone.Host/WebHost/WebHostController.cs @@ -84,10 +84,10 @@ namespace Prowlarr.Host { if (ex.HResult == 0x2 || ex.HResult == 0x2006D080) { - throw new RadarrStartupException(ex, $"The SSL certificate file {sslCertPath} does not exist"); + throw new ProwlarrStartupException(ex, $"The SSL certificate file {sslCertPath} does not exist"); } - throw new RadarrStartupException(ex); + throw new ProwlarrStartupException(ex); } configureOptions.ServerCertificate = certificate; diff --git a/src/NzbDrone.Test.Common/LoggingTest.cs b/src/NzbDrone.Test.Common/LoggingTest.cs index f08d3aa4b..396581f55 100644 --- a/src/NzbDrone.Test.Common/LoggingTest.cs +++ b/src/NzbDrone.Test.Common/LoggingTest.cs @@ -24,7 +24,7 @@ namespace NzbDrone.Test.Common LogManager.Configuration = new LoggingConfiguration(); var logOutput = TestLogOutput.Console; - Enum.TryParse(Environment.GetEnvironmentVariable("RADARR_TESTS_LOG_OUTPUT"), out logOutput); + Enum.TryParse(Environment.GetEnvironmentVariable("PROWLARR_TESTS_LOG_OUTPUT"), out logOutput); RegisterSentryLogger(); diff --git a/src/NzbDrone.Test.Common/NzbDroneRunner.cs b/src/NzbDrone.Test.Common/NzbDroneRunner.cs index 2a083d5a7..45a9ab88d 100644 --- a/src/NzbDrone.Test.Common/NzbDroneRunner.cs +++ b/src/NzbDrone.Test.Common/NzbDroneRunner.cs @@ -124,8 +124,8 @@ namespace NzbDrone.Test.Common _processProvider.Kill(_nzbDroneProcess.Id); } - _processProvider.KillAll(ProcessProvider.RADARR_CONSOLE_PROCESS_NAME); - _processProvider.KillAll(ProcessProvider.RADARR_PROCESS_NAME); + _processProvider.KillAll(ProcessProvider.PROWLARR_CONSOLE_PROCESS_NAME); + _processProvider.KillAll(ProcessProvider.PROWLARR_PROCESS_NAME); } catch (InvalidOperationException) { @@ -135,11 +135,11 @@ namespace NzbDrone.Test.Common TestBase.DeleteTempFolder(AppData); } - private void Start(string outputRadarrConsoleExe) + private void Start(string outputProwlarrConsoleExe) { - TestContext.Progress.WriteLine("Starting instance from {0} on port {1}", outputRadarrConsoleExe, Port); + TestContext.Progress.WriteLine("Starting instance from {0} on port {1}", outputProwlarrConsoleExe, Port); var args = "-nobrowser -nosingleinstancecheck -data=\"" + AppData + "\""; - _nzbDroneProcess = _processProvider.Start(outputRadarrConsoleExe, args, null, OnOutputDataReceived, OnOutputDataReceived); + _nzbDroneProcess = _processProvider.Start(outputProwlarrConsoleExe, args, null, OnOutputDataReceived, OnOutputDataReceived); } private void OnOutputDataReceived(string data) diff --git a/src/NzbDrone.Update/UpdateEngine/DetectApplicationType.cs b/src/NzbDrone.Update/UpdateEngine/DetectApplicationType.cs index 06bcdbfef..461c26b7d 100644 --- a/src/NzbDrone.Update/UpdateEngine/DetectApplicationType.cs +++ b/src/NzbDrone.Update/UpdateEngine/DetectApplicationType.cs @@ -34,7 +34,7 @@ namespace NzbDrone.Update.UpdateEngine return AppType.Service; } - if (_processProvider.Exists(ProcessProvider.RADARR_CONSOLE_PROCESS_NAME)) + if (_processProvider.Exists(ProcessProvider.PROWLARR_CONSOLE_PROCESS_NAME)) { return AppType.Console; } diff --git a/src/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs b/src/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs index aaf72ceaf..c44820c50 100644 --- a/src/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs +++ b/src/NzbDrone.Update/UpdateEngine/InstallUpdateService.cs @@ -92,8 +92,8 @@ namespace NzbDrone.Update.UpdateEngine var appType = _detectApplicationType.GetAppType(); - _processProvider.FindProcessByName(ProcessProvider.RADARR_CONSOLE_PROCESS_NAME); - _processProvider.FindProcessByName(ProcessProvider.RADARR_PROCESS_NAME); + _processProvider.FindProcessByName(ProcessProvider.PROWLARR_CONSOLE_PROCESS_NAME); + _processProvider.FindProcessByName(ProcessProvider.PROWLARR_PROCESS_NAME); if (OsInfo.IsWindows) { @@ -107,7 +107,7 @@ namespace NzbDrone.Update.UpdateEngine if (OsInfo.IsWindows) { - if (_processProvider.Exists(ProcessProvider.RADARR_CONSOLE_PROCESS_NAME) || _processProvider.Exists(ProcessProvider.RADARR_PROCESS_NAME)) + if (_processProvider.Exists(ProcessProvider.PROWLARR_CONSOLE_PROCESS_NAME) || _processProvider.Exists(ProcessProvider.PROWLARR_PROCESS_NAME)) { _logger.Error("Prowlarr was restarted prematurely by external process."); return; @@ -150,14 +150,14 @@ namespace NzbDrone.Update.UpdateEngine { System.Threading.Thread.Sleep(1000); - if (_processProvider.Exists(ProcessProvider.RADARR_PROCESS_NAME)) + if (_processProvider.Exists(ProcessProvider.PROWLARR_PROCESS_NAME)) { _logger.Info("Prowlarr was restarted by external process."); break; } } - if (!_processProvider.Exists(ProcessProvider.RADARR_PROCESS_NAME)) + if (!_processProvider.Exists(ProcessProvider.PROWLARR_PROCESS_NAME)) { _startNzbDrone.Start(appType, installationFolder); } diff --git a/src/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs b/src/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs index 80af99e08..a6b7a68ec 100644 --- a/src/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs +++ b/src/NzbDrone.Update/UpdateEngine/TerminateNzbDrone.cs @@ -47,15 +47,15 @@ namespace NzbDrone.Update.UpdateEngine _logger.Info("Killing all running processes"); - _processProvider.KillAll(ProcessProvider.RADARR_CONSOLE_PROCESS_NAME); - _processProvider.KillAll(ProcessProvider.RADARR_PROCESS_NAME); + _processProvider.KillAll(ProcessProvider.PROWLARR_CONSOLE_PROCESS_NAME); + _processProvider.KillAll(ProcessProvider.PROWLARR_PROCESS_NAME); } else { _logger.Info("Killing all running processes"); - _processProvider.KillAll(ProcessProvider.RADARR_CONSOLE_PROCESS_NAME); - _processProvider.KillAll(ProcessProvider.RADARR_PROCESS_NAME); + _processProvider.KillAll(ProcessProvider.PROWLARR_CONSOLE_PROCESS_NAME); + _processProvider.KillAll(ProcessProvider.PROWLARR_PROCESS_NAME); _processProvider.Kill(processId); } diff --git a/src/Prowlarr.Api.V1/Commands/CommandModule.cs b/src/Prowlarr.Api.V1/Commands/CommandModule.cs index e6cada9b0..da1cfbf8f 100644 --- a/src/Prowlarr.Api.V1/Commands/CommandModule.cs +++ b/src/Prowlarr.Api.V1/Commands/CommandModule.cs @@ -14,7 +14,7 @@ using Prowlarr.Http.Validation; namespace Prowlarr.Api.V1.Commands { - public class CommandModule : RadarrRestModuleWithSignalR, IHandle + public class CommandModule : ProwlarrRestModuleWithSignalR, IHandle { private readonly IManageCommandQueue _commandQueueManager; private readonly IServiceFactory _serviceFactory; diff --git a/src/Prowlarr.Api.V1/Config/DownloadClientConfigModule.cs b/src/Prowlarr.Api.V1/Config/DownloadClientConfigModule.cs index 400e47f2d..5db97ef82 100644 --- a/src/Prowlarr.Api.V1/Config/DownloadClientConfigModule.cs +++ b/src/Prowlarr.Api.V1/Config/DownloadClientConfigModule.cs @@ -2,7 +2,7 @@ using NzbDrone.Core.Configuration; namespace Prowlarr.Api.V1.Config { - public class DownloadClientConfigModule : RadarrConfigModule + public class DownloadClientConfigModule : ProwlarrConfigModule { public DownloadClientConfigModule(IConfigService configService) : base(configService) diff --git a/src/Prowlarr.Api.V1/Config/IndexerConfigModule.cs b/src/Prowlarr.Api.V1/Config/IndexerConfigModule.cs index e17bfefe1..384fe97ec 100644 --- a/src/Prowlarr.Api.V1/Config/IndexerConfigModule.cs +++ b/src/Prowlarr.Api.V1/Config/IndexerConfigModule.cs @@ -4,7 +4,7 @@ using Prowlarr.Http.Validation; namespace Prowlarr.Api.V1.Config { - public class IndexerConfigModule : RadarrConfigModule + public class IndexerConfigModule : ProwlarrConfigModule { public IndexerConfigModule(IConfigService configService) : base(configService) diff --git a/src/Prowlarr.Api.V1/Config/MediaManagementConfigModule.cs b/src/Prowlarr.Api.V1/Config/MediaManagementConfigModule.cs index 60165e7e1..9f63461b2 100644 --- a/src/Prowlarr.Api.V1/Config/MediaManagementConfigModule.cs +++ b/src/Prowlarr.Api.V1/Config/MediaManagementConfigModule.cs @@ -6,7 +6,7 @@ using NzbDrone.Core.Validation.Paths; namespace Prowlarr.Api.V1.Config { - public class MediaManagementConfigModule : RadarrConfigModule + public class MediaManagementConfigModule : ProwlarrConfigModule { public MediaManagementConfigModule(IConfigService configService, PathExistsValidator pathExistsValidator, FileChmodValidator fileChmodValidator) : base(configService) diff --git a/src/Prowlarr.Api.V1/Config/ProwlarrConfigModule.cs b/src/Prowlarr.Api.V1/Config/ProwlarrConfigModule.cs index d0e5f73d2..8ed822ada 100644 --- a/src/Prowlarr.Api.V1/Config/ProwlarrConfigModule.cs +++ b/src/Prowlarr.Api.V1/Config/ProwlarrConfigModule.cs @@ -6,17 +6,17 @@ using Prowlarr.Http.REST; namespace Prowlarr.Api.V1.Config { - public abstract class RadarrConfigModule : ProwlarrRestModule + public abstract class ProwlarrConfigModule : ProwlarrRestModule where TResource : RestResource, new() { private readonly IConfigService _configService; - protected RadarrConfigModule(IConfigService configService) + protected ProwlarrConfigModule(IConfigService configService) : this(new TResource().ResourceName.Replace("config", ""), configService) { } - protected RadarrConfigModule(string resource, IConfigService configService) + protected ProwlarrConfigModule(string resource, IConfigService configService) : base("config/" + resource.Trim('/')) { _configService = configService; diff --git a/src/Prowlarr.Api.V1/Config/UiConfigModule.cs b/src/Prowlarr.Api.V1/Config/UiConfigModule.cs index d280b5a5a..df322e9d3 100644 --- a/src/Prowlarr.Api.V1/Config/UiConfigModule.cs +++ b/src/Prowlarr.Api.V1/Config/UiConfigModule.cs @@ -2,7 +2,7 @@ using NzbDrone.Core.Configuration; namespace Prowlarr.Api.V1.Config { - public class UiConfigModule : RadarrConfigModule + public class UiConfigModule : ProwlarrConfigModule { public UiConfigModule(IConfigService configService) : base(configService) diff --git a/src/Prowlarr.Api.V1/FileSystem/FileSystemModule.cs b/src/Prowlarr.Api.V1/FileSystem/FileSystemModule.cs index c24be31c6..695bdff4d 100644 --- a/src/Prowlarr.Api.V1/FileSystem/FileSystemModule.cs +++ b/src/Prowlarr.Api.V1/FileSystem/FileSystemModule.cs @@ -8,7 +8,7 @@ using Prowlarr.Http.Extensions; namespace Prowlarr.Api.V1.FileSystem { - public class FileSystemModule : RadarrV3Module + public class FileSystemModule : ProwlarrV3Module { private readonly IFileSystemLookupService _fileSystemLookupService; private readonly IDiskProvider _diskProvider; diff --git a/src/Prowlarr.Api.V1/Health/HealthModule.cs b/src/Prowlarr.Api.V1/Health/HealthModule.cs index cdadc590e..c0aee6f24 100644 --- a/src/Prowlarr.Api.V1/Health/HealthModule.cs +++ b/src/Prowlarr.Api.V1/Health/HealthModule.cs @@ -7,7 +7,7 @@ using Prowlarr.Http; namespace Prowlarr.Api.V1.Health { - public class HealthModule : RadarrRestModuleWithSignalR, + public class HealthModule : ProwlarrRestModuleWithSignalR, IHandle { private readonly IHealthCheckService _healthCheckService; diff --git a/src/Prowlarr.Api.V1/ProwlarrV1FeedModule.cs b/src/Prowlarr.Api.V1/ProwlarrV1FeedModule.cs index acc4d4725..ef927ccfe 100644 --- a/src/Prowlarr.Api.V1/ProwlarrV1FeedModule.cs +++ b/src/Prowlarr.Api.V1/ProwlarrV1FeedModule.cs @@ -2,9 +2,9 @@ using Prowlarr.Http; namespace Prowlarr.Api.V1 { - public abstract class RadarrV3FeedModule : RadarrModule + public abstract class ProwlarrV3FeedModule : ProwlarrModule { - protected RadarrV3FeedModule(string resource) + protected ProwlarrV3FeedModule(string resource) : base("/feed/v1/" + resource.Trim('/')) { } diff --git a/src/Prowlarr.Api.V1/ProwlarrV1Module.cs b/src/Prowlarr.Api.V1/ProwlarrV1Module.cs index ecf9bc455..b9eb66001 100644 --- a/src/Prowlarr.Api.V1/ProwlarrV1Module.cs +++ b/src/Prowlarr.Api.V1/ProwlarrV1Module.cs @@ -2,9 +2,9 @@ using Prowlarr.Http; namespace Prowlarr.Api.V1 { - public abstract class RadarrV3Module : RadarrModule + public abstract class ProwlarrV3Module : ProwlarrModule { - protected RadarrV3Module(string resource) + protected ProwlarrV3Module(string resource) : base("/api/v1/" + resource.Trim('/')) { } diff --git a/src/Prowlarr.Api.V1/Restrictions/RestrictionModule.cs b/src/Prowlarr.Api.V1/Restrictions/RestrictionModule.cs deleted file mode 100644 index f7d299936..000000000 --- a/src/Prowlarr.Api.V1/Restrictions/RestrictionModule.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Collections.Generic; -using FluentValidation; -using NzbDrone.Common.Extensions; -using NzbDrone.Core.Restrictions; -using Prowlarr.Http; - -namespace Prowlarr.Api.V1.Restrictions -{ - public class RestrictionModule : ProwlarrRestModule - { - private readonly IRestrictionService _restrictionService; - - public RestrictionModule(IRestrictionService restrictionService) - { - _restrictionService = restrictionService; - - GetResourceById = GetById; - GetResourceAll = GetAll; - CreateResource = Create; - UpdateResource = Update; - DeleteResource = DeleteRestriction; - - SharedValidator.RuleFor(d => d).Custom((restriction, context) => - { - if (restriction.Ignored.IsNullOrWhiteSpace() && restriction.Required.IsNullOrWhiteSpace()) - { - context.AddFailure("Either 'Must contain' or 'Must not contain' is required"); - } - }); - } - - private RestrictionResource GetById(int id) - { - return _restrictionService.Get(id).ToResource(); - } - - private List GetAll() - { - return _restrictionService.All().ToResource(); - } - - private int Create(RestrictionResource resource) - { - return _restrictionService.Add(resource.ToModel()).Id; - } - - private void Update(RestrictionResource resource) - { - _restrictionService.Update(resource.ToModel()); - } - - private void DeleteRestriction(int id) - { - _restrictionService.Delete(id); - } - } -} diff --git a/src/Prowlarr.Api.V1/Restrictions/RestrictionResource.cs b/src/Prowlarr.Api.V1/Restrictions/RestrictionResource.cs deleted file mode 100644 index abded300e..000000000 --- a/src/Prowlarr.Api.V1/Restrictions/RestrictionResource.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using NzbDrone.Core.Restrictions; -using Prowlarr.Http.REST; - -namespace Prowlarr.Api.V1.Restrictions -{ - public class RestrictionResource : RestResource - { - public string Required { get; set; } - public string Preferred { get; set; } - public string Ignored { get; set; } - public HashSet Tags { get; set; } - - public RestrictionResource() - { - Tags = new HashSet(); - } - } - - public static class RestrictionResourceMapper - { - public static RestrictionResource ToResource(this Restriction model) - { - if (model == null) - { - return null; - } - - return new RestrictionResource - { - Id = model.Id, - - Required = model.Required, - Preferred = model.Preferred, - Ignored = model.Ignored, - Tags = new HashSet(model.Tags) - }; - } - - public static Restriction ToModel(this RestrictionResource resource) - { - if (resource == null) - { - return null; - } - - return new Restriction - { - Id = resource.Id, - - Required = resource.Required, - Preferred = resource.Preferred, - Ignored = resource.Ignored, - Tags = new HashSet(resource.Tags) - }; - } - - public static List ToResource(this IEnumerable models) - { - return models.Select(ToResource).ToList(); - } - } -} diff --git a/src/Prowlarr.Api.V1/System/Backup/BackupModule.cs b/src/Prowlarr.Api.V1/System/Backup/BackupModule.cs index e0bcb55e4..1ef5a1027 100644 --- a/src/Prowlarr.Api.V1/System/Backup/BackupModule.cs +++ b/src/Prowlarr.Api.V1/System/Backup/BackupModule.cs @@ -99,7 +99,7 @@ namespace Prowlarr.Api.V1.System.Backup throw new UnsupportedMediaTypeException($"Invalid extension, must be one of: {ValidExtensions.Join(", ")}"); } - var path = Path.Combine(_appFolderInfo.TempFolder, $"radarr_backup_restore{extension}"); + var path = Path.Combine(_appFolderInfo.TempFolder, $"prowlarr_backup_restore{extension}"); _diskProvider.SaveStream(file.Value, path); _backupService.Restore(path); diff --git a/src/Prowlarr.Api.V1/System/SystemModule.cs b/src/Prowlarr.Api.V1/System/SystemModule.cs index 8af185fcc..750b0417f 100644 --- a/src/Prowlarr.Api.V1/System/SystemModule.cs +++ b/src/Prowlarr.Api.V1/System/SystemModule.cs @@ -8,7 +8,7 @@ using NzbDrone.Core.Lifecycle; namespace Prowlarr.Api.V1.System { - public class SystemModule : RadarrV3Module + public class SystemModule : ProwlarrV3Module { private readonly IAppFolderInfo _appFolderInfo; private readonly IRuntimeInfo _runtimeInfo; diff --git a/src/Prowlarr.Api.V1/System/Tasks/TaskModule.cs b/src/Prowlarr.Api.V1/System/Tasks/TaskModule.cs index 1d12949b5..cbc0f3273 100644 --- a/src/Prowlarr.Api.V1/System/Tasks/TaskModule.cs +++ b/src/Prowlarr.Api.V1/System/Tasks/TaskModule.cs @@ -9,7 +9,7 @@ using Prowlarr.Http; namespace Prowlarr.Api.V1.System.Tasks { - public class TaskModule : RadarrRestModuleWithSignalR, IHandle + public class TaskModule : ProwlarrRestModuleWithSignalR, IHandle { private readonly ITaskManager _taskManager; diff --git a/src/Prowlarr.Api.V1/Tags/TagDetailsResource.cs b/src/Prowlarr.Api.V1/Tags/TagDetailsResource.cs index db0d32700..41ef94c94 100644 --- a/src/Prowlarr.Api.V1/Tags/TagDetailsResource.cs +++ b/src/Prowlarr.Api.V1/Tags/TagDetailsResource.cs @@ -8,11 +8,7 @@ namespace Prowlarr.Api.V1.Tags public class TagDetailsResource : RestResource { public string Label { get; set; } - public List DelayProfileIds { get; set; } public List NotificationIds { get; set; } - public List RestrictionIds { get; set; } - public List ImportListIds { get; set; } - public List MovieIds { get; set; } } public static class TagDetailsResourceMapper @@ -28,11 +24,7 @@ namespace Prowlarr.Api.V1.Tags { Id = model.Id, Label = model.Label, - DelayProfileIds = model.DelayProfileIds, - NotificationIds = model.NotificationIds, - RestrictionIds = model.RestrictionIds, - ImportListIds = model.ImportListIds, - MovieIds = model.MovieIds + NotificationIds = model.NotificationIds }; } diff --git a/src/Prowlarr.Api.V1/Tags/TagModule.cs b/src/Prowlarr.Api.V1/Tags/TagModule.cs index cd1b2721d..44d1db688 100644 --- a/src/Prowlarr.Api.V1/Tags/TagModule.cs +++ b/src/Prowlarr.Api.V1/Tags/TagModule.cs @@ -7,7 +7,7 @@ using Prowlarr.Http; namespace Prowlarr.Api.V1.Tags { - public class TagModule : RadarrRestModuleWithSignalR, IHandle + public class TagModule : ProwlarrRestModuleWithSignalR, IHandle { private readonly ITagService _tagService; diff --git a/src/Prowlarr.Http/Authentication/EnableAuthInNancy.cs b/src/Prowlarr.Http/Authentication/EnableAuthInNancy.cs index 9e0b74973..97e56d408 100644 --- a/src/Prowlarr.Http/Authentication/EnableAuthInNancy.cs +++ b/src/Prowlarr.Http/Authentication/EnableAuthInNancy.cs @@ -71,7 +71,7 @@ namespace Prowlarr.Http.Authentication private void RegisterFormsAuth(IPipelines pipelines) { - FormsAuthentication.FormsAuthenticationCookieName = "RadarrAuth"; + FormsAuthentication.FormsAuthenticationCookieName = "ProwlarrAuth"; var cryptographyConfiguration = new CryptographyConfiguration( new AesEncryptionProvider(new PassphraseKeyGenerator(_configService.RijndaelPassphrase, Encoding.ASCII.GetBytes(_configService.RijndaelSalt))), diff --git a/src/Prowlarr.Http/ErrorManagement/ProwlarrErrorPipeline.cs b/src/Prowlarr.Http/ErrorManagement/ProwlarrErrorPipeline.cs index dbbfe1fd2..c524f1140 100644 --- a/src/Prowlarr.Http/ErrorManagement/ProwlarrErrorPipeline.cs +++ b/src/Prowlarr.Http/ErrorManagement/ProwlarrErrorPipeline.cs @@ -11,11 +11,11 @@ using HttpStatusCode = Nancy.HttpStatusCode; namespace Prowlarr.Http.ErrorManagement { - public class RadarrErrorPipeline + public class ProwlarrErrorPipeline { private readonly Logger _logger; - public RadarrErrorPipeline(Logger logger) + public ProwlarrErrorPipeline(Logger logger) { _logger = logger; } diff --git a/src/Prowlarr.Http/Extensions/Pipelines/ProwlarrVersionPipeline.cs b/src/Prowlarr.Http/Extensions/Pipelines/ProwlarrVersionPipeline.cs index 3a1cb737d..74e9b4fe7 100644 --- a/src/Prowlarr.Http/Extensions/Pipelines/ProwlarrVersionPipeline.cs +++ b/src/Prowlarr.Http/Extensions/Pipelines/ProwlarrVersionPipeline.cs @@ -5,7 +5,7 @@ using NzbDrone.Common.EnvironmentInfo; namespace Prowlarr.Http.Extensions.Pipelines { - public class RadarrVersionPipeline : IRegisterNancyPipeline + public class ProwlarrVersionPipeline : IRegisterNancyPipeline { public int Order => 0; diff --git a/src/Prowlarr.Http/Extensions/Pipelines/RequestLoggingPipeline.cs b/src/Prowlarr.Http/Extensions/Pipelines/RequestLoggingPipeline.cs index 38efe8292..300a4a578 100644 --- a/src/Prowlarr.Http/Extensions/Pipelines/RequestLoggingPipeline.cs +++ b/src/Prowlarr.Http/Extensions/Pipelines/RequestLoggingPipeline.cs @@ -17,9 +17,9 @@ namespace NzbDrone.Api.Extensions.Pipelines private static int _requestSequenceID; - private readonly RadarrErrorPipeline _errorPipeline; + private readonly ProwlarrErrorPipeline _errorPipeline; - public RequestLoggingPipeline(RadarrErrorPipeline errorPipeline) + public RequestLoggingPipeline(ProwlarrErrorPipeline errorPipeline) { _errorPipeline = errorPipeline; } diff --git a/src/Prowlarr.Http/ProwlarrBootstrapper.cs b/src/Prowlarr.Http/ProwlarrBootstrapper.cs index c0d8792ee..58d836b80 100644 --- a/src/Prowlarr.Http/ProwlarrBootstrapper.cs +++ b/src/Prowlarr.Http/ProwlarrBootstrapper.cs @@ -13,12 +13,12 @@ using TinyIoC; namespace Prowlarr.Http { - public class RadarrBootstrapper : TinyIoCNancyBootstrapper + public class ProwlarrBootstrapper : TinyIoCNancyBootstrapper { private readonly TinyIoCContainer _tinyIoCContainer; - private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(RadarrBootstrapper)); + private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(ProwlarrBootstrapper)); - public RadarrBootstrapper(TinyIoCContainer tinyIoCContainer) + public ProwlarrBootstrapper(TinyIoCContainer tinyIoCContainer) { _tinyIoCContainer = tinyIoCContainer; } diff --git a/src/Prowlarr.Http/ProwlarrModule.cs b/src/Prowlarr.Http/ProwlarrModule.cs index 71fcc8cbd..81583d4eb 100644 --- a/src/Prowlarr.Http/ProwlarrModule.cs +++ b/src/Prowlarr.Http/ProwlarrModule.cs @@ -3,9 +3,9 @@ using Nancy.Responses.Negotiation; namespace Prowlarr.Http { - public abstract class RadarrModule : NancyModule + public abstract class ProwlarrModule : NancyModule { - protected RadarrModule(string resource) + protected ProwlarrModule(string resource) : base(resource) { } diff --git a/src/Prowlarr.Http/ProwlarrRestModuleWithSignalR.cs b/src/Prowlarr.Http/ProwlarrRestModuleWithSignalR.cs index 59431d46c..2101e4267 100644 --- a/src/Prowlarr.Http/ProwlarrRestModuleWithSignalR.cs +++ b/src/Prowlarr.Http/ProwlarrRestModuleWithSignalR.cs @@ -6,18 +6,18 @@ using Prowlarr.Http.REST; namespace Prowlarr.Http { - public abstract class RadarrRestModuleWithSignalR : ProwlarrRestModule, IHandle> + public abstract class ProwlarrRestModuleWithSignalR : ProwlarrRestModule, IHandle> where TResource : RestResource, new() where TModel : ModelBase, new() { private readonly IBroadcastSignalRMessage _signalRBroadcaster; - protected RadarrRestModuleWithSignalR(IBroadcastSignalRMessage signalRBroadcaster) + protected ProwlarrRestModuleWithSignalR(IBroadcastSignalRMessage signalRBroadcaster) { _signalRBroadcaster = signalRBroadcaster; } - protected RadarrRestModuleWithSignalR(IBroadcastSignalRMessage signalRBroadcaster, string resource) + protected ProwlarrRestModuleWithSignalR(IBroadcastSignalRMessage signalRBroadcaster, string resource) : base(resource) { _signalRBroadcaster = signalRBroadcaster; diff --git a/src/ServiceHelpers/ServiceInstall/ServiceHelper.cs b/src/ServiceHelpers/ServiceInstall/ServiceHelper.cs index 83232306a..4c4901bc9 100644 --- a/src/ServiceHelpers/ServiceInstall/ServiceHelper.cs +++ b/src/ServiceHelpers/ServiceInstall/ServiceHelper.cs @@ -8,7 +8,7 @@ namespace ServiceInstall { public static class ServiceHelper { - private static string RadarrExe => Path.Combine(new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName, "Prowlarr.Console.exe"); + private static string ProwlarrExe => Path.Combine(new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName, "Prowlarr.Console.exe"); private static bool IsAnAdministrator() { @@ -18,7 +18,7 @@ namespace ServiceInstall public static void Run(string arg) { - if (!File.Exists(RadarrExe)) + if (!File.Exists(ProwlarrExe)) { Console.WriteLine("Unable to find Prowlarr.Console.exe in the current directory."); return; @@ -32,7 +32,7 @@ namespace ServiceInstall var startInfo = new ProcessStartInfo { - FileName = RadarrExe, + FileName = ProwlarrExe, Arguments = arg, UseShellExecute = false, RedirectStandardOutput = true, diff --git a/src/ServiceHelpers/ServiceUninstall/ServiceHelper.cs b/src/ServiceHelpers/ServiceUninstall/ServiceHelper.cs index a142d2e12..01bb06d2b 100644 --- a/src/ServiceHelpers/ServiceUninstall/ServiceHelper.cs +++ b/src/ServiceHelpers/ServiceUninstall/ServiceHelper.cs @@ -8,7 +8,7 @@ namespace ServiceUninstall { public static class ServiceHelper { - private static string RadarrExe => Path.Combine(new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName, "Prowlarr.Console.exe"); + private static string ProwlarrExe => Path.Combine(new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName, "Prowlarr.Console.exe"); private static bool IsAnAdministrator() { @@ -18,7 +18,7 @@ namespace ServiceUninstall public static void Run(string arg) { - if (!File.Exists(RadarrExe)) + if (!File.Exists(ProwlarrExe)) { Console.WriteLine("Unable to find Prowlarr.exe in the current directory."); return; @@ -32,7 +32,7 @@ namespace ServiceUninstall var startInfo = new ProcessStartInfo { - FileName = RadarrExe, + FileName = ProwlarrExe, Arguments = arg, UseShellExecute = false, RedirectStandardOutput = true, diff --git a/test.sh b/test.sh index a1932b6b6..4e6bf7ad7 100755 --- a/test.sh +++ b/test.sh @@ -20,7 +20,7 @@ fi rm -f "$TEST_LOG_FILE" # Uncomment to log test output to a file instead of the console -export RADARR_TESTS_LOG_OUTPUT="File" +export PROWLARR_TESTS_LOG_OUTPUT="File" VSTEST_PARAMS="--logger:nunit;LogFilePath=TestResult.xml"