From 8430cb40ab64bb2fd6c8f6cebce48fe3329a0262 Mon Sep 17 00:00:00 2001 From: Qstick Date: Fri, 23 Nov 2018 02:04:42 -0500 Subject: [PATCH] New: Project Aphrodite --- frontend/.csscomb.json | 25 + frontend/.esformatter | 335 ++++++++++ frontend/.eslintignore | 1 + frontend/.eslintrc | 288 +++++++++ frontend/.jsbeautifyrc | 12 + frontend/.stylelintrc | 396 ++++++++++++ frontend/.tern-project | 7 + frontend/gulp/build.js | 15 + frontend/gulp/clean.js | 8 + frontend/gulp/copy.js | 45 ++ frontend/gulp/gulpFile.js | 8 + frontend/gulp/helpers/errorHandler.js | 6 + frontend/gulp/helpers/html-annotate-loader.js | 15 + frontend/gulp/helpers/paths.js | 23 + frontend/gulp/imageMin.js | 15 + frontend/gulp/start.js | 104 +++ frontend/gulp/stripBom.js | 13 + frontend/gulp/watch.js | 27 + frontend/gulp/webpack.js | 212 +++++++ frontend/gulp/webpack/css-variables-loader.js | 11 + frontend/postcss.config.js | 33 + frontend/src/.vscode/settings.json | 4 + frontend/src/Activity/Blacklist/Blacklist.js | 123 ++++ .../Activity/Blacklist/BlacklistConnector.js | 154 +++++ .../Blacklist/BlacklistDetailsModal.js | 89 +++ .../src/Activity/Blacklist/BlacklistRow.css | 18 + .../src/Activity/Blacklist/BlacklistRow.js | 170 +++++ .../Blacklist/BlacklistRowConnector.js | 26 + .../History/Details/HistoryDetails.css | 5 + .../History/Details/HistoryDetails.js | 244 +++++++ .../Details/HistoryDetailsConnector.js | 19 + .../History/Details/HistoryDetailsModal.css | 5 + .../History/Details/HistoryDetailsModal.js | 104 +++ frontend/src/Activity/History/History.js | 163 +++++ .../src/Activity/History/HistoryConnector.js | 134 ++++ .../Activity/History/HistoryEventTypeCell.css | 6 + .../Activity/History/HistoryEventTypeCell.js | 82 +++ frontend/src/Activity/History/HistoryRow.css | 23 + frontend/src/Activity/History/HistoryRow.js | 212 +++++++ .../Activity/History/HistoryRowConnector.js | 73 +++ frontend/src/Activity/Queue/ProtocolLabel.css | 13 + frontend/src/Activity/Queue/ProtocolLabel.js | 20 + frontend/src/Activity/Queue/Queue.js | 278 ++++++++ frontend/src/Activity/Queue/QueueConnector.js | 164 +++++ frontend/src/Activity/Queue/QueueDetails.js | 97 +++ frontend/src/Activity/Queue/QueueOptions.js | 77 +++ .../Activity/Queue/QueueOptionsConnector.js | 19 + frontend/src/Activity/Queue/QueueRow.css | 23 + frontend/src/Activity/Queue/QueueRow.js | 326 ++++++++++ .../src/Activity/Queue/QueueRowConnector.js | 68 ++ .../src/Activity/Queue/QueueStatusCell.css | 5 + .../src/Activity/Queue/QueueStatusCell.js | 132 ++++ .../Activity/Queue/RemoveQueueItemModal.css | 3 + .../Activity/Queue/RemoveQueueItemModal.js | 114 ++++ .../Activity/Queue/RemoveQueueItemsModal.css | 3 + .../Activity/Queue/RemoveQueueItemsModal.js | 114 ++++ .../Queue/Status/QueueStatusConnector.js | 70 +++ frontend/src/Activity/Queue/TimeleftCell.css | 5 + frontend/src/Activity/Queue/TimeleftCell.js | 82 +++ .../src/AddMovie/AddNewMovie/AddNewMovie.css | 54 ++ .../src/AddMovie/AddNewMovie/AddNewMovie.js | 182 ++++++ .../AddNewMovie/AddNewMovieConnector.js | 102 +++ .../AddMovie/AddNewMovie/AddNewMovieModal.js | 31 + .../AddNewMovie/AddNewMovieModalContent.css | 68 ++ .../AddNewMovie/AddNewMovieModalContent.js | 190 ++++++ .../AddNewMovieModalContentConnector.js | 97 +++ .../AddNewMovie/AddNewMovieSearchResult.css | 40 ++ .../AddNewMovie/AddNewMovieSearchResult.js | 162 +++++ .../AddNewMovieSearchResultConnector.js | 20 + .../ImportMovie/Import/ImportMovie.js | 169 +++++ .../Import/ImportMovieConnector.js | 152 +++++ .../ImportMovie/Import/ImportMovieFooter.css | 33 + .../ImportMovie/Import/ImportMovieFooter.js | 184 ++++++ .../Import/ImportMovieFooterConnector.js | 50 ++ .../ImportMovie/Import/ImportMovieHeader.css | 30 + .../ImportMovie/Import/ImportMovieHeader.js | 60 ++ .../ImportMovie/Import/ImportMovieRow.css | 31 + .../ImportMovie/Import/ImportMovieRow.js | 84 +++ .../Import/ImportMovieRowConnector.js | 87 +++ .../Import/ImportMovieSelected.css | 3 + .../ImportMovie/Import/ImportMovieTable.js | 183 ++++++ .../Import/ImportMovieTableConnector.js | 41 ++ .../SelectMovie/ImportMovieSearchResult.css | 8 + .../SelectMovie/ImportMovieSearchResult.js | 52 ++ .../ImportMovieSearchResultConnector.js | 17 + .../SelectMovie/ImportMovieSelectMovie.css | 70 +++ .../SelectMovie/ImportMovieSelectMovie.js | 280 +++++++++ .../ImportMovieSelectMovieConnector.js | 76 +++ .../Import/SelectMovie/ImportMovieTitle.css | 17 + .../Import/SelectMovie/ImportMovieTitle.js | 50 ++ .../src/AddMovie/ImportMovie/ImportMovies.js | 30 + .../SelectFolder/ImportMovieRootFolderRow.css | 18 + .../SelectFolder/ImportMovieRootFolderRow.js | 65 ++ .../ImportMovieRootFolderRowConnector.js | 48 ++ .../SelectFolder/ImportMovieSelectFolder.css | 32 + .../SelectFolder/ImportMovieSelectFolder.js | 188 ++++++ .../ImportMovieSelectFolderConnector.js | 91 +++ frontend/src/App/App.js | 28 + frontend/src/App/AppRoutes.js | 232 +++++++ frontend/src/App/AppUpdatedModal.js | 30 + frontend/src/App/AppUpdatedModalConnector.js | 12 + frontend/src/App/AppUpdatedModalContent.css | 15 + frontend/src/App/AppUpdatedModalContent.js | 98 +++ .../App/AppUpdatedModalContentConnector.js | 76 +++ frontend/src/App/ColorImpairedContext.js | 6 + frontend/src/App/ConnectionLostModal.css | 3 + frontend/src/App/ConnectionLostModal.js | 55 ++ .../src/App/ConnectionLostModalConnector.js | 12 + frontend/src/Calendar/Agenda/Agenda.css | 3 + frontend/src/Calendar/Agenda/Agenda.js | 38 ++ .../src/Calendar/Agenda/AgendaConnector.js | 14 + frontend/src/Calendar/Agenda/AgendaEvent.css | 117 ++++ frontend/src/Calendar/Agenda/AgendaEvent.js | 141 +++++ .../Calendar/Agenda/AgendaEventConnector.js | 30 + frontend/src/Calendar/Calendar.css | 8 + frontend/src/Calendar/Calendar.js | 64 ++ frontend/src/Calendar/CalendarConnector.js | 183 ++++++ frontend/src/Calendar/CalendarPage.css | 14 + frontend/src/Calendar/CalendarPage.js | 152 +++++ .../src/Calendar/CalendarPageConnector.js | 36 ++ frontend/src/Calendar/Day/CalendarDay.css | 25 + frontend/src/Calendar/Day/CalendarDay.js | 74 +++ .../src/Calendar/Day/CalendarDayConnector.js | 91 +++ frontend/src/Calendar/Day/CalendarDays.css | 14 + frontend/src/Calendar/Day/CalendarDays.js | 164 +++++ .../src/Calendar/Day/CalendarDaysConnector.js | 25 + frontend/src/Calendar/Day/DayOfWeek.css | 13 + frontend/src/Calendar/Day/DayOfWeek.js | 56 ++ frontend/src/Calendar/Day/DaysOfWeek.css | 4 + frontend/src/Calendar/Day/DaysOfWeek.js | 97 +++ .../src/Calendar/Day/DaysOfWeekConnector.js | 22 + .../src/Calendar/Events/CalendarEvent.css | 78 +++ frontend/src/Calendar/Events/CalendarEvent.js | 135 ++++ .../Calendar/Events/CalendarEventConnector.js | 29 + .../Calendar/Events/CalendarEventGroup.css | 82 +++ .../src/Calendar/Events/CalendarEventGroup.js | 200 ++++++ .../Events/CalendarEventGroupConnector.js | 37 ++ .../Events/CalendarEventQueueDetails.js | 50 ++ .../src/Calendar/Header/CalendarHeader.css | 53 ++ .../src/Calendar/Header/CalendarHeader.js | 224 +++++++ .../Header/CalendarHeaderConnector.js | 84 +++ .../Header/CalendarHeaderViewButton.js | 45 ++ frontend/src/Calendar/Legend/Legend.css | 6 + frontend/src/Calendar/Legend/Legend.js | 109 ++++ .../src/Calendar/Legend/LegendConnector.js | 19 + .../src/Calendar/Legend/LegendIconItem.css | 10 + .../src/Calendar/Legend/LegendIconItem.js | 37 ++ frontend/src/Calendar/Legend/LegendItem.css | 41 ++ frontend/src/Calendar/Legend/LegendItem.js | 36 ++ .../Calendar/Options/CalendarOptionsModal.js | 29 + .../Options/CalendarOptionsModalContent.js | 258 ++++++++ .../CalendarOptionsModalContentConnector.js | 25 + frontend/src/Calendar/calendarViews.js | 4 + frontend/src/Calendar/getStatusStyle.js | 26 + .../src/Calendar/iCal/CalendarLinkModal.js | 29 + .../Calendar/iCal/CalendarLinkModalContent.js | 221 +++++++ .../iCal/CalendarLinkModalContentConnector.js | 17 + frontend/src/Commands/commandNames.js | 18 + frontend/src/Components/Alert.css | 31 + frontend/src/Components/Alert.js | 32 + frontend/src/Components/Card.css | 19 + frontend/src/Components/Card.js | 60 ++ .../src/Components/CircularProgressBar.css | 21 + .../src/Components/CircularProgressBar.js | 139 ++++ .../DescriptionList/DescriptionList.css | 4 + .../DescriptionList/DescriptionList.js | 33 + .../DescriptionList/DescriptionListItem.js | 44 ++ .../DescriptionListItemDescription.css | 13 + .../DescriptionListItemDescription.js | 27 + .../DescriptionListItemTitle.css | 18 + .../DescriptionListItemTitle.js | 27 + frontend/src/Components/DragPreviewLayer.css | 9 + frontend/src/Components/DragPreviewLayer.js | 22 + .../src/Components/Error/ErrorBoundary.js | 62 ++ .../Components/Error/ErrorBoundaryError.css | 38 ++ .../Components/Error/ErrorBoundaryError.js | 60 ++ frontend/src/Components/FieldSet.css | 19 + frontend/src/Components/FieldSet.js | 33 + .../FileBrowser/FileBrowserModal.css | 5 + .../FileBrowser/FileBrowserModal.js | 39 ++ .../FileBrowser/FileBrowserModalContent.css | 33 + .../FileBrowser/FileBrowserModalContent.js | 253 ++++++++ .../FileBrowserModalContentConnector.js | 101 +++ .../Components/FileBrowser/FileBrowserRow.css | 5 + .../Components/FileBrowser/FileBrowserRow.js | 62 ++ .../Builder/BoolFilterBuilderRowValue.js | 18 + .../Builder/DateFilterBuilderRowValue.css | 15 + .../Builder/DateFilterBuilderRowValue.js | 171 +++++ .../Builder/FilterBuilderModalContent.css | 16 + .../Builder/FilterBuilderModalContent.js | 226 +++++++ .../FilterBuilderModalContentConnector.js | 42 ++ .../Filter/Builder/FilterBuilderRow.css | 32 + .../Filter/Builder/FilterBuilderRow.js | 282 +++++++++ .../Filter/Builder/FilterBuilderRowValue.js | 159 +++++ .../Builder/FilterBuilderRowValueConnector.js | 55 ++ .../Builder/FilterBuilderRowValueTag.css | 19 + .../Builder/FilterBuilderRowValueTag.js | 31 + .../IndexerFilterBuilderRowValueConnector.js | 79 +++ .../Builder/ProtocolFilterBuilderRowValue.js | 18 + .../QualityFilterBuilderRowValueConnector.js | 75 +++ ...tyProfileFilterBuilderRowValueConnector.js | 28 + .../SeriesStatusFilterBuilderRowValue.js | 18 + .../TagFilterBuilderRowValueConnector.js | 27 + .../Filter/CustomFilters/CustomFilter.css | 17 + .../Filter/CustomFilters/CustomFilter.js | 114 ++++ .../CustomFiltersModalContent.css | 3 + .../CustomFiltersModalContent.js | 80 +++ .../CustomFiltersModalContentConnector.js | 23 + frontend/src/Components/Filter/FilterModal.js | 90 +++ .../src/Components/Form/AutoCompleteInput.css | 58 ++ .../src/Components/Form/AutoCompleteInput.js | 162 +++++ frontend/src/Components/Form/CaptchaInput.css | 23 + frontend/src/Components/Form/CaptchaInput.js | 84 +++ .../Components/Form/CaptchaInputConnector.js | 98 +++ frontend/src/Components/Form/CheckInput.css | 105 ++++ frontend/src/Components/Form/CheckInput.js | 191 ++++++ frontend/src/Components/Form/DeviceInput.css | 8 + frontend/src/Components/Form/DeviceInput.js | 103 +++ .../Components/Form/DeviceInputConnector.js | 99 +++ .../Components/Form/EnhancedSelectInput.css | 79 +++ .../Components/Form/EnhancedSelectInput.js | 411 ++++++++++++ .../Form/EnhancedSelectInputOption.css | 41 ++ .../Form/EnhancedSelectInputOption.js | 81 +++ .../Form/EnhancedSelectInputSelectedValue.css | 7 + .../Form/EnhancedSelectInputSelectedValue.js | 35 ++ frontend/src/Components/Form/Form.css | 3 + frontend/src/Components/Form/Form.js | 58 ++ frontend/src/Components/Form/FormGroup.css | 28 + frontend/src/Components/Form/FormGroup.js | 56 ++ .../src/Components/Form/FormInputButton.css | 12 + .../src/Components/Form/FormInputButton.js | 54 ++ .../src/Components/Form/FormInputGroup.css | 49 ++ .../src/Components/Form/FormInputGroup.js | 249 ++++++++ .../src/Components/Form/FormInputHelpText.css | 39 ++ .../src/Components/Form/FormInputHelpText.js | 63 ++ frontend/src/Components/Form/FormLabel.css | 29 + frontend/src/Components/Form/FormLabel.js | 50 ++ frontend/src/Components/Form/Input.css | 30 + .../Form/MovieMonitoredSelectInput.js | 52 ++ frontend/src/Components/Form/NumberInput.js | 126 ++++ frontend/src/Components/Form/OAuthInput.js | 39 ++ .../Components/Form/OAuthInputConnector.js | 89 +++ .../src/Components/Form/PasswordInput.css | 5 + frontend/src/Components/Form/PasswordInput.js | 22 + frontend/src/Components/Form/PathInput.css | 68 ++ frontend/src/Components/Form/PathInput.js | 206 ++++++ .../src/Components/Form/PathInputConnector.js | 67 ++ .../Components/Form/ProviderFieldFormGroup.js | 120 ++++ .../QualityProfileSelectInputConnector.js | 98 +++ .../Components/Form/RootFolderSelectInput.js | 109 ++++ .../Form/RootFolderSelectInputConnector.js | 137 ++++ .../Form/RootFolderSelectInputOption.css | 20 + .../Form/RootFolderSelectInputOption.js | 45 ++ .../RootFolderSelectInputSelectedValue.css | 22 + .../RootFolderSelectInputSelectedValue.js | 44 ++ frontend/src/Components/Form/SelectInput.css | 18 + frontend/src/Components/Form/SelectInput.js | 95 +++ frontend/src/Components/Form/TagInput.css | 78 +++ frontend/src/Components/Form/TagInput.js | 303 +++++++++ .../src/Components/Form/TagInputConnector.js | 156 +++++ .../src/Components/Form/TagInputInput.css | 6 + frontend/src/Components/Form/TagInputInput.js | 76 +++ frontend/src/Components/Form/TagInputTag.js | 55 ++ frontend/src/Components/Form/TextInput.css | 19 + frontend/src/Components/Form/TextInput.js | 188 ++++++ .../Components/Form/TextTagInputConnector.js | 95 +++ frontend/src/Components/HeartRating.css | 4 + frontend/src/Components/HeartRating.js | 30 + frontend/src/Components/Icon.css | 27 + frontend/src/Components/Icon.js | 69 ++ frontend/src/Components/Label.css | 111 ++++ frontend/src/Components/Label.js | 47 ++ frontend/src/Components/Link/Button.css | 119 ++++ frontend/src/Components/Link/Button.js | 54 ++ .../src/Components/Link/ClipboardButton.css | 33 + .../src/Components/Link/ClipboardButton.js | 127 ++++ frontend/src/Components/Link/IconButton.css | 21 + frontend/src/Components/Link/IconButton.js | 55 ++ frontend/src/Components/Link/Link.css | 24 + frontend/src/Components/Link/Link.js | 101 +++ .../src/Components/Link/SpinnerButton.css | 37 ++ frontend/src/Components/Link/SpinnerButton.js | 57 ++ .../Components/Link/SpinnerErrorButton.css | 23 + .../src/Components/Link/SpinnerErrorButton.js | 162 +++++ .../src/Components/Link/SpinnerIconButton.js | 38 ++ .../Components/Loading/LoadingIndicator.css | 49 ++ .../Components/Loading/LoadingIndicator.js | 48 ++ .../src/Components/Loading/LoadingMessage.css | 6 + .../src/Components/Loading/LoadingMessage.js | 20 + frontend/src/Components/Measure.js | 38 ++ frontend/src/Components/Menu/FilterMenu.css | 9 + frontend/src/Components/Menu/FilterMenu.js | 110 ++++ .../src/Components/Menu/FilterMenuContent.js | 85 +++ .../src/Components/Menu/FilterMenuItem.js | 45 ++ frontend/src/Components/Menu/Menu.css | 7 + frontend/src/Components/Menu/Menu.js | 207 ++++++ frontend/src/Components/Menu/MenuButton.css | 21 + frontend/src/Components/Menu/MenuButton.js | 49 ++ frontend/src/Components/Menu/MenuContent.css | 11 + frontend/src/Components/Menu/MenuContent.js | 43 ++ frontend/src/Components/Menu/MenuItem.css | 19 + frontend/src/Components/Menu/MenuItem.js | 38 ++ .../src/Components/Menu/MenuItemSeparator.css | 5 + .../src/Components/Menu/MenuItemSeparator.js | 10 + .../src/Components/Menu/PageMenuButton.css | 11 + .../src/Components/Menu/PageMenuButton.js | 36 ++ .../src/Components/Menu/SelectedMenuItem.css | 15 + .../src/Components/Menu/SelectedMenuItem.js | 63 ++ frontend/src/Components/Menu/SortMenu.js | 40 ++ frontend/src/Components/Menu/SortMenuItem.js | 37 ++ .../src/Components/Menu/ToolbarMenuButton.css | 11 + .../src/Components/Menu/ToolbarMenuButton.js | 38 ++ frontend/src/Components/Menu/ViewMenu.js | 37 ++ frontend/src/Components/Menu/ViewMenuItem.js | 28 + frontend/src/Components/Modal/ConfirmModal.js | 88 +++ frontend/src/Components/Modal/Modal.css | 92 +++ frontend/src/Components/Modal/Modal.js | 215 +++++++ frontend/src/Components/Modal/ModalBody.css | 12 + frontend/src/Components/Modal/ModalBody.js | 59 ++ .../src/Components/Modal/ModalContent.css | 23 + frontend/src/Components/Modal/ModalContent.js | 52 ++ frontend/src/Components/Modal/ModalError.css | 15 + frontend/src/Components/Modal/ModalError.js | 46 ++ frontend/src/Components/Modal/ModalFooter.css | 23 + frontend/src/Components/Modal/ModalFooter.js | 32 + frontend/src/Components/Modal/ModalHeader.css | 8 + frontend/src/Components/Modal/ModalHeader.js | 32 + .../src/Components/MonitorToggleButton.css | 11 + .../src/Components/MonitorToggleButton.js | 79 +++ frontend/src/Components/NotFound.css | 14 + frontend/src/Components/NotFound.js | 31 + frontend/src/Components/Page/ErrorPage.css | 12 + frontend/src/Components/Page/ErrorPage.js | 56 ++ .../Page/Header/KeyboardShortcutsModal.js | 31 + .../Header/KeyboardShortcutsModalContent.css | 15 + .../Header/KeyboardShortcutsModalContent.js | 90 +++ .../KeyboardShortcutsModalContentConnector.js | 17 + .../Page/Header/MovieSearchInput.css | 96 +++ .../Page/Header/MovieSearchInput.js | 264 ++++++++ .../Page/Header/MovieSearchInputConnector.js | 98 +++ .../Page/Header/MovieSearchResult.css | 38 ++ .../Page/Header/MovieSearchResult.js | 89 +++ .../src/Components/Page/Header/PageHeader.css | 65 ++ .../src/Components/Page/Header/PageHeader.js | 100 +++ .../Page/Header/PageHeaderActionsMenu.css | 21 + .../Page/Header/PageHeaderActionsMenu.js | 88 +++ .../Header/PageHeaderActionsMenuConnector.js | 56 ++ frontend/src/Components/Page/LoadingPage.css | 3 + frontend/src/Components/Page/LoadingPage.js | 15 + frontend/src/Components/Page/Page.css | 18 + frontend/src/Components/Page/Page.js | 136 ++++ frontend/src/Components/Page/PageConnector.js | 197 ++++++ frontend/src/Components/Page/PageContent.css | 8 + frontend/src/Components/Page/PageContent.js | 36 ++ .../src/Components/Page/PageContentBody.css | 19 + .../src/Components/Page/PageContentBody.js | 52 ++ .../Page/PageContentBodyConnector.js | 17 + .../src/Components/Page/PageContentError.css | 3 + .../src/Components/Page/PageContentError.js | 19 + .../src/Components/Page/PageContentFooter.css | 26 + .../src/Components/Page/PageContentFooter.js | 33 + frontend/src/Components/Page/PageJumpBar.css | 22 + frontend/src/Components/Page/PageJumpBar.js | 140 +++++ .../src/Components/Page/PageJumpBarItem.css | 14 + .../src/Components/Page/PageJumpBarItem.js | 40 ++ .../src/Components/Page/PageSectionContent.js | 39 ++ .../Page/Sidebar/Messages/Message.css | 42 ++ .../Page/Sidebar/Messages/Message.js | 70 +++ .../Page/Sidebar/Messages/MessageConnector.js | 67 ++ .../Page/Sidebar/Messages/Messages.css | 11 + .../Page/Sidebar/Messages/Messages.js | 27 + .../Sidebar/Messages/MessagesConnector.js | 16 + .../Components/Page/Sidebar/PageSidebar.css | 34 + .../Components/Page/Sidebar/PageSidebar.js | 513 +++++++++++++++ .../Page/Sidebar/PageSidebarItem.css | 50 ++ .../Page/Sidebar/PageSidebarItem.js | 106 ++++ .../Page/Sidebar/PageSidebarStatus.css | 3 + .../Page/Sidebar/PageSidebarStatus.js | 35 ++ .../Components/Page/Toolbar/PageToolbar.css | 16 + .../Components/Page/Toolbar/PageToolbar.js | 33 + .../Page/Toolbar/PageToolbarButton.css | 32 + .../Page/Toolbar/PageToolbarButton.js | 57 ++ .../Page/Toolbar/PageToolbarSection.css | 40 ++ .../Page/Toolbar/PageToolbarSection.js | 221 +++++++ .../Page/Toolbar/PageToolbarSeparator.css | 12 + .../Page/Toolbar/PageToolbarSeparator.js | 17 + frontend/src/Components/ProgressBar.css | 93 +++ frontend/src/Components/ProgressBar.js | 100 +++ frontend/src/Components/Router/Switch.js | 44 ++ .../Components/Scroller/OverlayScroller.css | 15 + .../Components/Scroller/OverlayScroller.js | 127 ++++ frontend/src/Components/Scroller/Scroller.css | 28 + frontend/src/Components/Scroller/Scroller.js | 81 +++ frontend/src/Components/SignalRConnector.js | 351 +++++++++++ frontend/src/Components/SpinnerIcon.js | 33 + .../Table/Cells/RelativeDateCell.css | 5 + .../Table/Cells/RelativeDateCell.js | 60 ++ .../Table/Cells/RelativeDateCellConnector.js | 21 + .../Components/Table/Cells/TableRowCell.css | 11 + .../Components/Table/Cells/TableRowCell.js | 37 ++ .../Table/Cells/TableRowCellButton.css | 4 + .../Table/Cells/TableRowCellButton.js | 25 + .../Table/Cells/TableSelectCell.css | 11 + .../Components/Table/Cells/TableSelectCell.js | 80 +++ .../Table/Cells/VirtualTableRowCell.css | 14 + .../Table/Cells/VirtualTableRowCell.js | 29 + .../Table/Cells/VirtualTableSelectCell.css | 11 + .../Table/Cells/VirtualTableSelectCell.js | 82 +++ frontend/src/Components/Table/Table.css | 16 + frontend/src/Components/Table/Table.js | 129 ++++ frontend/src/Components/Table/TableBody.js | 25 + frontend/src/Components/Table/TableHeader.js | 28 + .../src/Components/Table/TableHeaderCell.css | 16 + .../src/Components/Table/TableHeaderCell.js | 96 +++ .../Table/TableOptions/TableOptionsColumn.css | 48 ++ .../Table/TableOptions/TableOptionsColumn.js | 68 ++ .../TableOptionsColumnDragPreview.css | 4 + .../TableOptionsColumnDragPreview.js | 78 +++ .../TableOptionsColumnDragSource.css | 18 + .../TableOptionsColumnDragSource.js | 164 +++++ .../Table/TableOptions/TableOptionsModal.css | 5 + .../Table/TableOptions/TableOptionsModal.js | 252 ++++++++ .../TableOptions/TableOptionsModalWrapper.js | 61 ++ frontend/src/Components/Table/TablePager.css | 77 +++ frontend/src/Components/Table/TablePager.js | 180 ++++++ frontend/src/Components/Table/TableRow.css | 7 + frontend/src/Components/Table/TableRow.js | 33 + .../src/Components/Table/TableRowButton.css | 4 + .../src/Components/Table/TableRowButton.js | 16 + .../Table/TableSelectAllHeaderCell.css | 11 + .../Table/TableSelectAllHeaderCell.js | 47 ++ .../src/Components/Table/VirtualTable.css | 3 + frontend/src/Components/Table/VirtualTable.js | 167 +++++ .../src/Components/Table/VirtualTableBody.css | 3 + .../src/Components/Table/VirtualTableBody.js | 40 ++ .../Components/Table/VirtualTableHeader.css | 3 + .../Components/Table/VirtualTableHeader.js | 17 + .../Table/VirtualTableHeaderCell.css | 16 + .../Table/VirtualTableHeaderCell.js | 107 ++++ .../src/Components/Table/VirtualTableRow.css | 14 + .../src/Components/Table/VirtualTableRow.js | 34 + .../Table/VirtualTableSelectAllHeaderCell.css | 11 + .../Table/VirtualTableSelectAllHeaderCell.js | 47 ++ frontend/src/Components/TagList.css | 3 + frontend/src/Components/TagList.js | 38 ++ frontend/src/Components/TagListConnector.js | 17 + frontend/src/Components/Tooltip/Popover.css | 105 ++++ frontend/src/Components/Tooltip/Popover.js | 160 +++++ frontend/src/Components/Tooltip/Tooltip.css | 161 +++++ frontend/src/Components/Tooltip/Tooltip.js | 163 +++++ frontend/src/Components/keyboardShortcuts.js | 102 +++ frontend/src/Components/withCurrentPage.js | 25 + frontend/src/Components/withScrollPosition.js | 30 + frontend/src/Content/Fonts/Roboto-Light.ttf | Bin 0 -> 162420 bytes frontend/src/Content/Fonts/Roboto-Light.woff | Bin 0 -> 89300 bytes frontend/src/Content/Fonts/Roboto-Light.woff2 | Bin 0 -> 62832 bytes frontend/src/Content/Fonts/Roboto-Regular.ttf | Bin 0 -> 162876 bytes .../src/Content/Fonts/Roboto-Regular.woff | Bin 0 -> 89732 bytes .../src/Content/Fonts/Roboto-Regular.woff2 | Bin 0 -> 63412 bytes .../src/Content/Fonts/UbuntuMono-Regular.eot | Bin 0 -> 23691 bytes .../src/Content/Fonts/UbuntuMono-Regular.ttf | Bin 0 -> 205748 bytes .../src/Content/Fonts/UbuntuMono-Regular.woff | Bin 0 -> 27392 bytes frontend/src/Content/Fonts/fonts.css | 38 ++ .../src/Content/Fonts/text-security-disc.ttf | Bin 0 -> 12392 bytes .../src/Content/Fonts/text-security-disc.woff | Bin 0 -> 2988 bytes frontend/src/Content/Images/404.png | Bin 0 -> 103643 bytes .../Images/Icons/android-chrome-192x192.png | Bin 0 -> 16597 bytes .../Images/Icons/android-chrome-512x512.png | Bin 0 -> 51650 bytes .../Content/Images/Icons/apple-touch-icon.png | Bin 0 -> 8449 bytes .../Content/Images/Icons/browserconfig.xml | 9 + .../Content/Images/Icons/favicon-16x16.png | Bin 0 -> 1392 bytes .../Content/Images/Icons/favicon-32x32.png | Bin 0 -> 2670 bytes frontend/src/Content/Images/Icons/favicon.ico | Bin 0 -> 15086 bytes .../src/Content/Images/Icons/manifest.json | 18 + .../Content/Images/Icons/mstile-144x144.png | Bin 0 -> 10299 bytes .../Content/Images/Icons/mstile-150x150.png | Bin 0 -> 9680 bytes .../Content/Images/Icons/mstile-310x150.png | Bin 0 -> 10338 bytes .../Content/Images/Icons/mstile-310x310.png | Bin 0 -> 22034 bytes .../src/Content/Images/Icons/mstile-70x70.png | Bin 0 -> 6852 bytes .../Images/Icons/safari-pinned-tab.svg | 29 + frontend/src/Content/Images/error.png | Bin 0 -> 163647 bytes frontend/src/Content/Images/logo-full.png | Bin 0 -> 67146 bytes frontend/src/Content/Images/logo.png | Bin 0 -> 27298 bytes frontend/src/Content/Images/logo.svg | 9 + frontend/src/Content/Images/poster-dark.png | Bin 0 -> 2553 bytes .../Props/Shapes/createRouteMatchShape.js | 11 + .../src/Helpers/Props/Shapes/locationShape.js | 11 + .../src/Helpers/Props/Shapes/settingShape.js | 34 + frontend/src/Helpers/Props/align.js | 5 + .../src/Helpers/Props/filterBuilderTypes.js | 50 ++ .../Helpers/Props/filterBuilderValueTypes.js | 10 + .../src/Helpers/Props/filterTypePredicates.js | 45 ++ frontend/src/Helpers/Props/filterTypes.js | 21 + frontend/src/Helpers/Props/icons.js | 205 ++++++ frontend/src/Helpers/Props/index.js | 29 + frontend/src/Helpers/Props/inputTypes.js | 33 + frontend/src/Helpers/Props/kinds.js | 23 + frontend/src/Helpers/Props/messageTypes.js | 11 + .../src/Helpers/Props/scrollDirections.js | 5 + frontend/src/Helpers/Props/sizes.js | 7 + frontend/src/Helpers/Props/sortDirections.js | 4 + .../src/Helpers/Props/tooltipPositions.js | 11 + frontend/src/Helpers/dragTypes.js | 3 + frontend/src/Helpers/elementChildren.js | 149 +++++ frontend/src/Helpers/getDisplayName.js | 3 + ...eractiveImportSelectFolderModalContent.css | 24 + ...teractiveImportSelectFolderModalContent.js | 168 +++++ ...ImportSelectFolderModalContentConnector.js | 80 +++ .../Folder/RecentFolderRow.css | 5 + .../Folder/RecentFolderRow.js | 64 ++ .../InteractiveImportModalContent.css | 73 +++ .../InteractiveImportModalContent.js | 361 +++++++++++ .../InteractiveImportModalContentConnector.js | 203 ++++++ .../Interactive/InteractiveImportRow.css | 18 + .../Interactive/InteractiveImportRow.js | 251 ++++++++ .../InteractiveImportRowCellPlaceholder.css | 7 + .../InteractiveImportRowCellPlaceholder.js | 10 + .../InteractiveImportModal.js | 78 +++ .../Quality/SelectQualityModal.js | 37 ++ .../Quality/SelectQualityModalContent.js | 166 +++++ .../SelectQualityModalContentConnector.js | 95 +++ .../Series/SelectSeriesModal.js | 37 ++ .../Series/SelectSeriesModalContent.css | 18 + .../Series/SelectSeriesModalContent.js | 99 +++ .../SelectSeriesModalContentConnector.js | 75 +++ .../Series/SelectSeriesRow.css | 4 + .../Series/SelectSeriesRow.js | 37 ++ .../InteractiveSearch/InteractiveSearch.css | 9 + .../InteractiveSearch/InteractiveSearch.js | 192 ++++++ .../InteractiveSearchConnector.js | 94 +++ .../InteractiveSearchFilterModalConnector.js | 32 + .../InteractiveSearchRow.css | 25 + .../InteractiveSearch/InteractiveSearchRow.js | 253 ++++++++ frontend/src/InteractiveSearch/Peers.js | 57 ++ frontend/src/Movie/Delete/DeleteMovieModal.js | 33 + .../Movie/Delete/DeleteMovieModalContent.css | 12 + .../Movie/Delete/DeleteMovieModalContent.js | 144 +++++ .../DeleteMovieModalContentConnector.js | 55 ++ .../Movie/Details/MovieAlternateTitles.css | 3 + .../src/Movie/Details/MovieAlternateTitles.js | 28 + frontend/src/Movie/Details/MovieDetails.css | 155 +++++ frontend/src/Movie/Details/MovieDetails.js | 593 ++++++++++++++++++ .../Movie/Details/MovieDetailsConnector.js | 229 +++++++ .../src/Movie/Details/MovieDetailsLinks.css | 13 + .../src/Movie/Details/MovieDetailsLinks.js | 66 ++ .../Details/MovieDetailsPageConnector.js | 76 +++ frontend/src/Movie/Details/MovieTags.js | 30 + .../src/Movie/Details/MovieTagsConnector.js | 30 + frontend/src/Movie/Edit/EditMovieModal.js | 25 + .../src/Movie/Edit/EditMovieModalConnector.js | 39 ++ .../src/Movie/Edit/EditMovieModalContent.css | 5 + .../src/Movie/Edit/EditMovieModalContent.js | 182 ++++++ .../Edit/EditMovieModalContentConnector.js | 115 ++++ .../Movie/Editor/Delete/DeleteMovieModal.js | 31 + .../Editor/Delete/DeleteMovieModalContent.css | 13 + .../Editor/Delete/DeleteMovieModalContent.js | 123 ++++ .../DeleteMovieModalContentConnector.js | 45 ++ .../Editor/Organize/OrganizeSeriesModal.js | 31 + .../Organize/OrganizeSeriesModalContent.css | 8 + .../Organize/OrganizeSeriesModalContent.js | 74 +++ .../OrganizeSeriesModalContentConnector.js | 67 ++ frontend/src/Movie/Editor/SeriesEditor.js | 268 ++++++++ .../src/Movie/Editor/SeriesEditorConnector.js | 88 +++ .../SeriesEditorFilterModalConnector.js | 24 + .../src/Movie/Editor/SeriesEditorFooter.css | 57 ++ .../src/Movie/Editor/SeriesEditorFooter.js | 283 +++++++++ .../Movie/Editor/SeriesEditorFooterLabel.css | 8 + .../Movie/Editor/SeriesEditorFooterLabel.js | 40 ++ frontend/src/Movie/Editor/SeriesEditorRow.js | 97 +++ .../Movie/Editor/SeriesEditorRowConnector.js | 31 + frontend/src/Movie/Editor/Tags/TagsModal.js | 31 + .../Movie/Editor/Tags/TagsModalContent.css | 12 + .../src/Movie/Editor/Tags/TagsModalContent.js | 187 ++++++ .../Editor/Tags/TagsModalContentConnector.js | 36 ++ .../src/Movie/History/MovieHistoryModal.js | 31 + .../Movie/History/MovieHistoryModalContent.js | 136 ++++ .../MovieHistoryModalContentConnector.js | 81 +++ .../src/Movie/History/MovieHistoryRow.css | 6 + frontend/src/Movie/History/MovieHistoryRow.js | 156 +++++ .../Movie/History/MovieHistoryRowConnector.js | 23 + .../Movie/Index/Menus/MovieIndexFilterMenu.js | 41 ++ .../Movie/Index/Menus/MovieIndexSortMenu.js | 105 ++++ .../Movie/Index/Menus/MovieIndexViewMenu.js | 55 ++ frontend/src/Movie/Index/MovieIndex.css | 51 ++ frontend/src/Movie/Index/MovieIndex.js | 369 +++++++++++ .../src/Movie/Index/MovieIndexConnector.js | 164 +++++ .../Index/MovieIndexFilterModalConnector.js | 24 + frontend/src/Movie/Index/MovieIndexFooter.css | 72 +++ frontend/src/Movie/Index/MovieIndexFooter.js | 114 ++++ .../Movie/Index/MovieIndexItemConnector.js | 117 ++++ .../Index/Overview/MovieIndexOverview.css | 96 +++ .../Index/Overview/MovieIndexOverview.js | 258 ++++++++ .../Index/Overview/MovieIndexOverviewInfo.css | 12 + .../Index/Overview/MovieIndexOverviewInfo.js | 192 ++++++ .../Overview/MovieIndexOverviewInfoRow.css | 10 + .../Overview/MovieIndexOverviewInfoRow.js | 35 ++ .../Index/Overview/MovieIndexOverviews.css | 3 + .../Index/Overview/MovieIndexOverviews.js | 288 +++++++++ .../Overview/MovieIndexOverviewsConnector.js | 28 + .../Options/MovieIndexOverviewOptionsModal.js | 25 + .../MovieIndexOverviewOptionsModalContent.js | 267 ++++++++ ...dexOverviewOptionsModalContentConnector.js | 23 + .../Movie/Index/Posters/MovieIndexPoster.css | 100 +++ .../Movie/Index/Posters/MovieIndexPoster.js | 264 ++++++++ .../Index/Posters/MovieIndexPosterInfo.css | 5 + .../Index/Posters/MovieIndexPosterInfo.js | 87 +++ .../Movie/Index/Posters/MovieIndexPosters.css | 3 + .../Movie/Index/Posters/MovieIndexPosters.js | 324 ++++++++++ .../Posters/MovieIndexPostersConnector.js | 27 + .../Options/MovieIndexPosterOptionsModal.js | 25 + .../MovieIndexPosterOptionsModalContent.js | 213 +++++++ ...IndexPosterOptionsModalContentConnector.js | 23 + .../ProgressBar/MovieIndexProgressBar.css | 14 + .../ProgressBar/MovieIndexProgressBar.js | 40 ++ .../Index/Table/MovieIndexActionsCell.js | 102 +++ .../Movie/Index/Table/MovieIndexHeader.css | 67 ++ .../src/Movie/Index/Table/MovieIndexHeader.js | 109 ++++ .../Index/Table/MovieIndexHeaderConnector.js | 13 + .../src/Movie/Index/Table/MovieIndexRow.css | 73 +++ .../src/Movie/Index/Table/MovieIndexRow.js | 333 ++++++++++ .../src/Movie/Index/Table/MovieIndexTable.css | 5 + .../src/Movie/Index/Table/MovieIndexTable.js | 126 ++++ .../Index/Table/MovieIndexTableConnector.js | 28 + .../Index/Table/MovieIndexTableOptions.js | 76 +++ .../Table/MovieIndexTableOptionsConnector.js | 14 + .../src/Movie/Index/Table/MovieStatusCell.css | 9 + .../src/Movie/Index/Table/MovieStatusCell.js | 50 ++ .../src/Movie/MoveSeries/MoveSeriesModal.css | 5 + .../src/Movie/MoveSeries/MoveSeriesModal.js | 83 +++ frontend/src/Movie/MoviePoster.js | 195 ++++++ frontend/src/Movie/MovieQuality.js | 57 ++ frontend/src/Movie/MovieTitleLink.js | 28 + frontend/src/Movie/NoMovie.css | 11 + frontend/src/Movie/NoMovie.js | 51 ++ .../Search/SeasonInteractiveSearchModal.js | 36 ++ .../SeasonInteractiveSearchModalConnector.js | 15 + .../SeasonInteractiveSearchModalContent.js | 48 ++ frontend/src/Movie/movieEntities.js | 9 + .../MovieFile/Editor/MovieFileEditorModal.js | 34 + .../Editor/MovieFileEditorModalContent.css | 8 + .../Editor/MovieFileEditorModalContent.js | 280 +++++++++ .../MovieFileEditorModalContentConnector.js | 102 +++ .../MovieFile/Editor/MovieFileEditorRow.js | 62 ++ frontend/src/MovieFile/MediaInfo.js | 52 ++ frontend/src/MovieFile/MediaInfoConnector.js | 21 + .../MovieFile/MovieFileLanguageConnector.js | 17 + frontend/src/MovieFile/mediaInfoTypes.js | 2 + frontend/src/Organize/OrganizePreviewModal.js | 34 + .../Organize/OrganizePreviewModalConnector.js | 39 ++ .../Organize/OrganizePreviewModalContent.css | 24 + .../Organize/OrganizePreviewModalContent.js | 201 ++++++ .../OrganizePreviewModalContentConnector.js | 91 +++ frontend/src/Organize/OrganizePreviewRow.css | 20 + frontend/src/Organize/OrganizePreviewRow.js | 90 +++ frontend/src/RootFolder/RootFolderRow.css | 18 + frontend/src/RootFolder/RootFolderRow.js | 65 ++ .../src/RootFolder/RootFolderRowConnector.js | 13 + frontend/src/RootFolder/RootFolders.js | 80 +++ .../src/RootFolder/RootFoldersConnector.js | 46 ++ .../src/Settings/AdvancedSettingsButton.css | 31 + .../src/Settings/AdvancedSettingsButton.js | 59 ++ .../DownloadClients/DownloadClientSettings.js | 100 +++ .../DownloadClientSettingsConnector.js | 21 + .../DownloadClients/AddDownloadClientItem.css | 44 ++ .../DownloadClients/AddDownloadClientItem.js | 110 ++++ .../DownloadClients/AddDownloadClientModal.js | 25 + .../AddDownloadClientModalContent.css | 5 + .../AddDownloadClientModalContent.js | 115 ++++ .../AddDownloadClientModalContentConnector.js | 75 +++ .../AddDownloadClientPresetMenuItem.js | 49 ++ .../DownloadClients/DownloadClient.css | 19 + .../DownloadClients/DownloadClient.js | 113 ++++ .../DownloadClients/DownloadClients.css | 20 + .../DownloadClients/DownloadClients.js | 115 ++++ .../DownloadClientsConnector.js | 58 ++ .../EditDownloadClientModal.js | 27 + .../EditDownloadClientModalConnector.js | 65 ++ .../EditDownloadClientModalContent.css | 11 + .../EditDownloadClientModalContent.js | 178 ++++++ ...EditDownloadClientModalContentConnector.js | 88 +++ .../Options/DownloadClientOptions.js | 135 ++++ .../Options/DownloadClientOptionsConnector.js | 101 +++ .../EditRemotePathMappingModal.js | 27 + .../EditRemotePathMappingModalConnector.js | 43 ++ .../EditRemotePathMappingModalContent.css | 12 + .../EditRemotePathMappingModalContent.js | 149 +++++ ...tRemotePathMappingModalContentConnector.js | 119 ++++ .../RemotePathMappings/RemotePathMapping.css | 23 + .../RemotePathMappings/RemotePathMapping.js | 114 ++++ .../RemotePathMappings/RemotePathMappings.css | 23 + .../RemotePathMappings/RemotePathMappings.js | 100 +++ .../RemotePathMappingsConnector.js | 59 ++ .../src/Settings/General/AnalyticSettings.js | 42 ++ .../src/Settings/General/BackupSettings.js | 82 +++ .../src/Settings/General/GeneralSettings.js | 210 +++++++ .../General/GeneralSettingsConnector.js | 109 ++++ frontend/src/Settings/General/HostSettings.js | 154 +++++ .../src/Settings/General/LoggingSettings.js | 48 ++ .../src/Settings/General/ProxySettings.js | 142 +++++ .../src/Settings/General/SecuritySettings.js | 170 +++++ .../src/Settings/General/UpdateSettings.js | 117 ++++ .../src/Settings/Indexers/IndexerSettings.js | 100 +++ .../Indexers/IndexerSettingsConnector.js | 21 + .../Indexers/Indexers/AddIndexerItem.css | 44 ++ .../Indexers/Indexers/AddIndexerItem.js | 110 ++++ .../Indexers/Indexers/AddIndexerModal.js | 25 + .../Indexers/AddIndexerModalContent.css | 5 + .../Indexers/AddIndexerModalContent.js | 115 ++++ .../AddIndexerModalContentConnector.js | 75 +++ .../Indexers/AddIndexerPresetMenuItem.js | 49 ++ .../Indexers/Indexers/EditIndexerModal.js | 27 + .../Indexers/EditIndexerModalConnector.js | 65 ++ .../Indexers/EditIndexerModalContent.css | 5 + .../Indexers/EditIndexerModalContent.js | 179 ++++++ .../EditIndexerModalContentConnector.js | 88 +++ .../Settings/Indexers/Indexers/Indexer.css | 19 + .../src/Settings/Indexers/Indexers/Indexer.js | 131 ++++ .../Settings/Indexers/Indexers/Indexers.css | 20 + .../Settings/Indexers/Indexers/Indexers.js | 115 ++++ .../Indexers/Indexers/IndexersConnector.js | 58 ++ .../Indexers/Options/IndexerOptions.js | 112 ++++ .../Options/IndexerOptionsConnector.js | 101 +++ .../Restrictions/EditRestrictionModal.js | 27 + .../EditRestrictionModalConnector.js | 39 ++ .../EditRestrictionModalContent.css | 5 + .../EditRestrictionModalContent.js | 126 ++++ .../EditRestrictionModalContentConnector.js | 111 ++++ .../Indexers/Restrictions/Restriction.css | 11 + .../Indexers/Restrictions/Restriction.js | 148 +++++ .../Indexers/Restrictions/Restrictions.css | 20 + .../Indexers/Restrictions/Restrictions.js | 98 +++ .../Restrictions/RestrictionsConnector.js | 61 ++ .../MediaManagement/MediaManagement.js | 393 ++++++++++++ .../MediaManagementConnector.js | 86 +++ .../MediaManagement/Naming/Naming.css | 5 + .../Settings/MediaManagement/Naming/Naming.js | 202 ++++++ .../MediaManagement/Naming/NamingConnector.js | 97 +++ .../MediaManagement/Naming/NamingModal.css | 18 + .../MediaManagement/Naming/NamingModal.js | 549 ++++++++++++++++ .../MediaManagement/Naming/NamingOption.css | 66 ++ .../MediaManagement/Naming/NamingOption.js | 84 +++ .../Metadata/Metadata/EditMetadataModal.js | 27 + .../Metadata/EditMetadataModalConnector.js | 44 ++ .../Metadata/EditMetadataModalContent.js | 101 +++ .../EditMetadataModalContentConnector.js | 93 +++ .../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 | 49 ++ .../src/Settings/Metadata/MetadataSettings.js | 21 + .../NetImport/NetImport/AddNetImportItem.css | 44 ++ .../NetImport/NetImport/AddNetImportItem.js | 110 ++++ .../NetImport/NetImport/AddNetImportModal.js | 25 + .../NetImport/AddNetImportModalContent.css | 5 + .../NetImport/AddNetImportModalContent.js | 96 +++ .../AddNetImportModalContentConnector.js | 70 +++ .../NetImport/AddNetImportPresetMenuItem.js | 49 ++ .../NetImport/NetImport/EditNetImportModal.js | 27 + .../NetImport/EditNetImportModalConnector.js | 65 ++ .../NetImport/EditNetImportModalContent.css | 5 + .../NetImport/EditNetImportModalContent.js | 211 +++++++ .../EditNetImportModalContentConnector.js | 88 +++ .../NetImport/NetImport/NetImport.css | 19 + .../Settings/NetImport/NetImport/NetImport.js | 127 ++++ .../NetImport/NetImport/NetImports.css | 20 + .../NetImport/NetImport/NetImports.js | 115 ++++ .../NetImport/NetImportsConnector.js | 62 ++ .../Settings/NetImport/NetImportSettings.js | 99 +++ .../NetImport/NetImportSettingsConnector.js | 21 + .../NetImport/Options/NetImportOptions.js | 84 +++ .../Options/NetImportOptionsConnector.js | 101 +++ .../Notifications/NotificationSettings.js | 21 + .../Notifications/AddNotificationItem.css | 44 ++ .../Notifications/AddNotificationItem.js | 110 ++++ .../Notifications/AddNotificationModal.js | 25 + .../AddNotificationModalContent.css | 5 + .../AddNotificationModalContent.js | 85 +++ .../AddNotificationModalContentConnector.js | 70 +++ .../AddNotificationPresetMenuItem.js | 49 ++ .../Notifications/EditNotificationModal.js | 27 + .../EditNotificationModalConnector.js | 65 ++ .../EditNotificationModalContent.css | 11 + .../EditNotificationModalContent.js | 235 +++++++ .../EditNotificationModalContentConnector.js | 88 +++ .../Notifications/Notification.css | 19 + .../Notifications/Notification.js | 150 +++++ .../Notifications/Notifications.css | 20 + .../Notifications/Notifications.js | 115 ++++ .../Notifications/NotificationsConnector.js | 58 ++ frontend/src/Settings/PendingChangesModal.js | 62 ++ .../Settings/Profiles/Delay/DelayProfile.css | 40 ++ .../Settings/Profiles/Delay/DelayProfile.js | 172 +++++ .../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 | 148 +++++ .../Profiles/Delay/DelayProfilesConnector.js | 105 ++++ .../Profiles/Delay/EditDelayProfileModal.js | 27 + .../Delay/EditDelayProfileModalConnector.js | 43 ++ .../Delay/EditDelayProfileModalContent.css | 5 + .../Delay/EditDelayProfileModalContent.js | 186 ++++++ .../EditDelayProfileModalContentConnector.js | 178 ++++++ frontend/src/Settings/Profiles/Profiles.js | 34 + .../Quality/EditQualityProfileModal.js | 61 ++ .../EditQualityProfileModalConnector.js | 43 ++ .../EditQualityProfileModalContent.css | 18 + .../Quality/EditQualityProfileModalContent.js | 252 ++++++++ ...EditQualityProfileModalContentConnector.js | 442 +++++++++++++ .../Profiles/Quality/QualityProfile.css | 38 ++ .../Profiles/Quality/QualityProfile.js | 184 ++++++ .../Profiles/Quality/QualityProfileItem.css | 85 +++ .../Profiles/Quality/QualityProfileItem.js | 131 ++++ .../Quality/QualityProfileItemDragPreview.css | 4 + .../Quality/QualityProfileItemDragPreview.js | 92 +++ .../Quality/QualityProfileItemDragSource.css | 18 + .../Quality/QualityProfileItemDragSource.js | 241 +++++++ .../Quality/QualityProfileItemGroup.css | 105 ++++ .../Quality/QualityProfileItemGroup.js | 200 ++++++ .../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 | 65 ++ .../Quality/Definition/QualityDefinition.css | 93 +++ .../Quality/Definition/QualityDefinition.js | 242 +++++++ .../Definition/QualityDefinitionConnector.js | 64 ++ .../Quality/Definition/QualityDefinitions.css | 41 ++ .../Quality/Definition/QualityDefinitions.js | 73 +++ .../Definition/QualityDefinitionsConnector.js | 92 +++ frontend/src/Settings/Quality/Quality.js | 68 ++ frontend/src/Settings/Settings.css | 18 + frontend/src/Settings/Settings.js | 144 +++++ frontend/src/Settings/SettingsToolbar.js | 105 ++++ .../src/Settings/SettingsToolbarConnector.js | 147 +++++ .../Tags/Details/TagDetailsDelayProfile.js | 47 ++ .../Settings/Tags/Details/TagDetailsModal.js | 33 + .../Tags/Details/TagDetailsModalContent.css | 26 + .../Tags/Details/TagDetailsModalContent.js | 178 ++++++ .../TagDetailsModalContentConnector.js | 61 ++ frontend/src/Settings/Tags/Tag.css | 11 + frontend/src/Settings/Tags/Tag.js | 166 +++++ frontend/src/Settings/Tags/TagConnector.js | 22 + frontend/src/Settings/Tags/TagSettings.js | 21 + frontend/src/Settings/Tags/Tags.css | 4 + frontend/src/Settings/Tags/Tags.js | 49 ++ frontend/src/Settings/Tags/TagsConnector.js | 72 +++ frontend/src/Settings/UI/UISettings.js | 195 ++++++ .../src/Settings/UI/UISettingsConnector.js | 77 +++ frontend/src/Shared/piwikCheck.js | 11 + frontend/src/Shims/jquery.js | 10 + .../Creators/Reducers/createClearReducer.js | 12 + ...ateSetClientSideCollectionFilterReducer.js | 14 + ...reateSetClientSideCollectionSortReducer.js | 29 + .../createSetProviderFieldValueReducer.js | 23 + .../Reducers/createSetSettingValueReducer.js | 36 ++ .../Reducers/createSetTableOptionReducer.js | 21 + ...reateBatchToggleEpisodeMonitoredHandler.js | 42 ++ .../Actions/Creators/createFetchHandler.js | 44 ++ .../Creators/createFetchSchemaHandler.js | 33 + .../createFetchServerSideCollectionHandler.js | 67 ++ .../Actions/Creators/createHandleActions.js | 143 +++++ .../Creators/createRemoveItemHandler.js | 45 ++ .../Actions/Creators/createSaveHandler.js | 43 ++ .../Creators/createSaveProviderHandler.js | 70 +++ .../createServerSideCollectionHandlers.js | 52 ++ ...ateSetServerSideCollectionFilterHandler.js | 10 + ...reateSetServerSideCollectionPageHandler.js | 35 ++ ...reateSetServerSideCollectionSortHandler.js | 26 + .../Creators/createTestAllProvidersHandler.js | 34 + .../Creators/createTestProviderHandler.js | 52 ++ .../Store/Actions/Settings/delayProfiles.js | 103 +++ .../Actions/Settings/downloadClientOptions.js | 64 ++ .../Store/Actions/Settings/downloadClients.js | 117 ++++ .../src/Store/Actions/Settings/general.js | 64 ++ .../Store/Actions/Settings/indexerOptions.js | 64 ++ .../src/Store/Actions/Settings/indexers.js | 118 ++++ .../Store/Actions/Settings/mediaManagement.js | 64 ++ .../src/Store/Actions/Settings/metadata.js | 75 +++ frontend/src/Store/Actions/Settings/naming.js | 64 ++ .../Store/Actions/Settings/namingExamples.js | 79 +++ .../Actions/Settings/netImportOptions.js | 64 ++ .../src/Store/Actions/Settings/netImports.js | 116 ++++ .../Store/Actions/Settings/notifications.js | 115 ++++ .../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/Settings/ui.js | 64 ++ frontend/src/Store/Actions/actionTypes.js | 21 + frontend/src/Store/Actions/addMovieActions.js | 177 ++++++ frontend/src/Store/Actions/appActions.js | 135 ++++ frontend/src/Store/Actions/baseActions.js | 29 + .../src/Store/Actions/blacklistActions.js | 139 ++++ frontend/src/Store/Actions/calendarActions.js | 389 ++++++++++++ frontend/src/Store/Actions/captchaActions.js | 119 ++++ frontend/src/Store/Actions/commandActions.js | 215 +++++++ .../src/Store/Actions/customFilterActions.js | 55 ++ frontend/src/Store/Actions/deviceActions.js | 83 +++ frontend/src/Store/Actions/historyActions.js | 257 ++++++++ .../src/Store/Actions/importMovieActions.js | 287 +++++++++ frontend/src/Store/Actions/index.js | 53 ++ .../Store/Actions/interactiveImportActions.js | 204 ++++++ frontend/src/Store/Actions/movieActions.js | 255 ++++++++ .../src/Store/Actions/movieEditorActions.js | 179 ++++++ .../src/Store/Actions/movieFileActions.js | 210 +++++++ .../src/Store/Actions/movieHistoryActions.js | 104 +++ .../src/Store/Actions/movieIndexActions.js | 320 ++++++++++ frontend/src/Store/Actions/oAuthActions.js | 205 ++++++ .../Store/Actions/organizePreviewActions.js | 51 ++ frontend/src/Store/Actions/pathActions.js | 110 ++++ frontend/src/Store/Actions/queueActions.js | 439 +++++++++++++ frontend/src/Store/Actions/reducers.js | 20 + frontend/src/Store/Actions/releaseActions.js | 280 +++++++++ .../src/Store/Actions/rootFolderActions.js | 97 +++ frontend/src/Store/Actions/settingsActions.js | 139 ++++ frontend/src/Store/Actions/systemActions.js | 392 ++++++++++++ frontend/src/Store/Actions/tagActions.js | 75 +++ .../Store/Middleware/createPersistState.js | 99 +++ .../Middleware/createSentryMiddleware.js | 93 +++ frontend/src/Store/Middleware/middlewares.js | 25 + .../Selectors/createAllMoviesSelector.js | 12 + .../createClientSideCollectionSelector.js | 137 ++++ .../createCommandExecutingSelector.js | 14 + .../Store/Selectors/createCommandSelector.js | 14 + .../Store/Selectors/createCommandsSelector.js | 12 + .../Selectors/createDimensionsSelector.js | 12 + .../Selectors/createExistingMovieSelector.js | 15 + .../createImportMovieItemSelector.js | 26 + .../Selectors/createMovieCountSelector.js | 13 + .../Selectors/createMovieFileSelector.js | 17 + .../Store/Selectors/createMovieSelector.js | 15 + .../Selectors/createProfileInUseSelector.js | 19 + .../createProviderSettingsSelector.js | 63 ++ .../Selectors/createQualityProfileSelector.js | 14 + .../Selectors/createQueueItemSelector.js | 23 + .../createSettingsSectionSelector.js | 32 + .../Selectors/createSystemStatusSelector.js | 12 + .../Selectors/createTagDetailsSelector.js | 13 + .../src/Store/Selectors/createTagsSelector.js | 12 + .../Selectors/createUISettingsSelector.js | 12 + .../src/Store/Selectors/selectSettings.js | 104 +++ frontend/src/Store/createAppStore.js | 15 + frontend/src/Store/scrollPositions.js | 5 + frontend/src/Store/thunks.js | 28 + frontend/src/Styles/Mixins/cover.css | 8 + frontend/src/Styles/Mixins/linkOverlay.css | 11 + frontend/src/Styles/Mixins/scroller.css | 26 + frontend/src/Styles/Mixins/truncate.css | 18 + frontend/src/Styles/Variables/animations.js | 8 + frontend/src/Styles/Variables/colors.js | 180 ++++++ frontend/src/Styles/Variables/dimensions.js | 53 ++ frontend/src/Styles/Variables/fonts.js | 15 + frontend/src/Styles/globals.css | 7 + frontend/src/Styles/scaffolding.css | 54 ++ frontend/src/System/Backup/BackupRow.css | 12 + frontend/src/System/Backup/BackupRow.js | 153 +++++ frontend/src/System/Backup/Backups.js | 166 +++++ .../src/System/Backup/BackupsConnector.js | 84 +++ .../src/System/Backup/RestoreBackupModal.js | 31 + .../Backup/RestoreBackupModalConnector.js | 15 + .../Backup/RestoreBackupModalContent.css | 24 + .../Backup/RestoreBackupModalContent.js | 232 +++++++ .../RestoreBackupModalContentConnector.js | 37 ++ frontend/src/System/Events/LogsTable.js | 139 ++++ .../src/System/Events/LogsTableConnector.js | 141 +++++ .../System/Events/LogsTableDetailsModal.css | 17 + .../System/Events/LogsTableDetailsModal.js | 74 +++ frontend/src/System/Events/LogsTableRow.css | 35 ++ frontend/src/System/Events/LogsTableRow.js | 158 +++++ frontend/src/System/Logs/Files/LogFiles.js | 139 ++++ .../System/Logs/Files/LogFilesConnector.js | 90 +++ .../System/Logs/Files/LogFilesTableRow.css | 5 + .../src/System/Logs/Files/LogFilesTableRow.js | 50 ++ frontend/src/System/Logs/Logs.js | 30 + frontend/src/System/Logs/LogsNavMenu.js | 71 +++ .../Logs/Updates/UpdateLogFilesConnector.js | 90 +++ frontend/src/System/Status/About/About.css | 5 + frontend/src/System/Status/About/About.js | 88 +++ .../src/System/Status/About/AboutConnector.js | 52 ++ frontend/src/System/Status/About/StartTime.js | 93 +++ .../src/System/Status/DiskSpace/DiskSpace.css | 5 + .../src/System/Status/DiskSpace/DiskSpace.js | 120 ++++ .../Status/DiskSpace/DiskSpaceConnector.js | 54 ++ frontend/src/System/Status/Health/Health.css | 21 + frontend/src/System/Status/Health/Health.js | 206 ++++++ .../System/Status/Health/HealthConnector.js | 68 ++ .../Status/Health/HealthStatusConnector.js | 79 +++ .../src/System/Status/MoreInfo/MoreInfo.js | 52 ++ frontend/src/System/Status/Status.js | 29 + .../src/System/Tasks/Queued/QueuedTaskRow.css | 31 + .../src/System/Tasks/Queued/QueuedTaskRow.js | 265 ++++++++ .../Tasks/Queued/QueuedTaskRowConnector.js | 31 + .../src/System/Tasks/Queued/QueuedTasks.js | 89 +++ .../Tasks/Queued/QueuedTasksConnector.js | 46 ++ .../Tasks/Scheduled/ScheduledTaskRow.css | 18 + .../Tasks/Scheduled/ScheduledTaskRow.js | 182 ++++++ .../Scheduled/ScheduledTaskRowConnector.js | 92 +++ .../System/Tasks/Scheduled/ScheduledTasks.js | 79 +++ .../Scheduled/ScheduledTasksConnector.js | 46 ++ frontend/src/System/Tasks/Tasks.js | 18 + frontend/src/System/Updates/UpdateChanges.css | 4 + frontend/src/System/Updates/UpdateChanges.js | 45 ++ frontend/src/System/Updates/Updates.css | 57 ++ frontend/src/System/Updates/Updates.js | 169 +++++ .../src/System/Updates/UpdatesConnector.js | 76 +++ .../Array/getIndexOfFirstCharacter.js | 13 + frontend/src/Utilities/Array/sortByName.js | 5 + frontend/src/Utilities/Command/findCommand.js | 10 + frontend/src/Utilities/Command/index.js | 5 + .../Utilities/Command/isCommandComplete.js | 9 + .../Utilities/Command/isCommandExecuting.js | 9 + .../src/Utilities/Command/isCommandFailed.js | 12 + .../src/Utilities/Command/isSameCommand.js | 24 + frontend/src/Utilities/Constants/keyCodes.js | 7 + .../src/Utilities/Date/dateFilterPredicate.js | 33 + frontend/src/Utilities/Date/formatDate.js | 11 + frontend/src/Utilities/Date/formatDateTime.js | 39 ++ frontend/src/Utilities/Date/formatTime.js | 19 + frontend/src/Utilities/Date/formatTimeSpan.js | 24 + .../src/Utilities/Date/getRelativeDate.js | 42 ++ frontend/src/Utilities/Date/isAfter.js | 17 + frontend/src/Utilities/Date/isBefore.js | 17 + frontend/src/Utilities/Date/isInNextWeek.js | 11 + frontend/src/Utilities/Date/isSameWeek.js | 11 + frontend/src/Utilities/Date/isToday.js | 11 + frontend/src/Utilities/Date/isTomorrow.js | 11 + frontend/src/Utilities/Date/isYesterday.js | 11 + .../src/Utilities/Episode/updateEpisodes.js | 21 + .../Utilities/Filter/findSelectedFilters.js | 19 + .../src/Utilities/Filter/getFilterValue.js | 11 + frontend/src/Utilities/Movie/getNewMovie.js | 18 + .../src/Utilities/Movie/getProgressBarKind.js | 23 + .../src/Utilities/Number/convertToBytes.js | 16 + frontend/src/Utilities/Number/formatAge.js | 17 + frontend/src/Utilities/Number/formatBytes.js | 16 + frontend/src/Utilities/Number/padNumber.js | 10 + frontend/src/Utilities/Number/roundNumber.js | 5 + .../src/Utilities/Object/getErrorMessage.js | 11 + .../src/Utilities/Object/hasDifferentItems.js | 10 + .../src/Utilities/Object/selectUniqueIds.js | 15 + .../src/Utilities/Quality/getQualities.js | 16 + frontend/src/Utilities/ResolutionUtility.js | 26 + .../src/Utilities/State/getProviderState.js | 42 ++ .../src/Utilities/State/getSectionState.js | 22 + .../Utilities/State/selectProviderSchema.js | 34 + .../src/Utilities/State/updateSectionState.js | 16 + frontend/src/Utilities/String/combinePath.js | 5 + .../src/Utilities/String/generateUUIDv4.js | 6 + frontend/src/Utilities/String/isString.js | 3 + frontend/src/Utilities/String/parseUrl.js | 36 ++ frontend/src/Utilities/String/split.js | 17 + frontend/src/Utilities/String/titleCase.js | 11 + .../src/Utilities/Table/areAllSelected.js | 17 + .../src/Utilities/Table/getSelectedIds.js | 15 + .../src/Utilities/Table/getToggledRange.js | 23 + .../Utilities/Table/removeOldSelectedState.js | 16 + frontend/src/Utilities/Table/selectAll.js | 17 + .../src/Utilities/Table/toggleSelected.js | 30 + frontend/src/Utilities/createAjaxRequest.js | 30 + frontend/src/Utilities/getPathWithUrlBase.js | 3 + frontend/src/Utilities/getUniqueElementId.js | 7 + frontend/src/Utilities/isMobile.js | 7 + frontend/src/Utilities/pagePopulator.js | 28 + frontend/src/Utilities/pages.js | 9 + frontend/src/Utilities/requestAction.js | 40 ++ frontend/src/Utilities/sectionTypes.js | 6 + .../Utilities/serverSideCollectionHandlers.js | 12 + frontend/src/index.css | 15 + frontend/src/index.html | 61 ++ frontend/src/index.js | 18 + frontend/src/jQuery/jquery.ajax.js | 47 ++ frontend/src/login.html | 232 +++++++ frontend/src/oauth.html | 13 + frontend/src/polyfills.js | 41 ++ frontend/src/preload.js | 4 + frontend/src/vendor.js | 5 + 1080 files changed, 73015 insertions(+) create mode 100644 frontend/.csscomb.json create mode 100644 frontend/.esformatter create mode 100644 frontend/.eslintignore create mode 100644 frontend/.eslintrc create mode 100644 frontend/.jsbeautifyrc create mode 100644 frontend/.stylelintrc create mode 100644 frontend/.tern-project create mode 100644 frontend/gulp/build.js create mode 100644 frontend/gulp/clean.js create mode 100644 frontend/gulp/copy.js create mode 100644 frontend/gulp/gulpFile.js create mode 100644 frontend/gulp/helpers/errorHandler.js create mode 100644 frontend/gulp/helpers/html-annotate-loader.js create mode 100644 frontend/gulp/helpers/paths.js create mode 100644 frontend/gulp/imageMin.js create mode 100644 frontend/gulp/start.js create mode 100644 frontend/gulp/stripBom.js create mode 100644 frontend/gulp/watch.js create mode 100644 frontend/gulp/webpack.js create mode 100644 frontend/gulp/webpack/css-variables-loader.js create mode 100644 frontend/postcss.config.js create mode 100644 frontend/src/.vscode/settings.json create mode 100644 frontend/src/Activity/Blacklist/Blacklist.js create mode 100644 frontend/src/Activity/Blacklist/BlacklistConnector.js create mode 100644 frontend/src/Activity/Blacklist/BlacklistDetailsModal.js create mode 100644 frontend/src/Activity/Blacklist/BlacklistRow.css create mode 100644 frontend/src/Activity/Blacklist/BlacklistRow.js create mode 100644 frontend/src/Activity/Blacklist/BlacklistRowConnector.js create mode 100644 frontend/src/Activity/History/Details/HistoryDetails.css create mode 100644 frontend/src/Activity/History/Details/HistoryDetails.js create mode 100644 frontend/src/Activity/History/Details/HistoryDetailsConnector.js create mode 100644 frontend/src/Activity/History/Details/HistoryDetailsModal.css create mode 100644 frontend/src/Activity/History/Details/HistoryDetailsModal.js create mode 100644 frontend/src/Activity/History/History.js create mode 100644 frontend/src/Activity/History/HistoryConnector.js create mode 100644 frontend/src/Activity/History/HistoryEventTypeCell.css create mode 100644 frontend/src/Activity/History/HistoryEventTypeCell.js create mode 100644 frontend/src/Activity/History/HistoryRow.css create mode 100644 frontend/src/Activity/History/HistoryRow.js create mode 100644 frontend/src/Activity/History/HistoryRowConnector.js create mode 100644 frontend/src/Activity/Queue/ProtocolLabel.css create mode 100644 frontend/src/Activity/Queue/ProtocolLabel.js create mode 100644 frontend/src/Activity/Queue/Queue.js create mode 100644 frontend/src/Activity/Queue/QueueConnector.js create mode 100644 frontend/src/Activity/Queue/QueueDetails.js create mode 100644 frontend/src/Activity/Queue/QueueOptions.js create mode 100644 frontend/src/Activity/Queue/QueueOptionsConnector.js create mode 100644 frontend/src/Activity/Queue/QueueRow.css create mode 100644 frontend/src/Activity/Queue/QueueRow.js create mode 100644 frontend/src/Activity/Queue/QueueRowConnector.js create mode 100644 frontend/src/Activity/Queue/QueueStatusCell.css create mode 100644 frontend/src/Activity/Queue/QueueStatusCell.js create mode 100644 frontend/src/Activity/Queue/RemoveQueueItemModal.css create mode 100644 frontend/src/Activity/Queue/RemoveQueueItemModal.js create mode 100644 frontend/src/Activity/Queue/RemoveQueueItemsModal.css create mode 100644 frontend/src/Activity/Queue/RemoveQueueItemsModal.js create mode 100644 frontend/src/Activity/Queue/Status/QueueStatusConnector.js create mode 100644 frontend/src/Activity/Queue/TimeleftCell.css create mode 100644 frontend/src/Activity/Queue/TimeleftCell.js create mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovie.css create mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovie.js create mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js create mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieModal.js create mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.css create mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.js create mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContentConnector.js create mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.css create mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js create mode 100644 frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResultConnector.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovie.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieConnector.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.css create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooterConnector.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.css create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.css create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieRowConnector.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieSelected.css create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieTable.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.css create mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResultConnector.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.css create mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovieConnector.js create mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.css create mode 100644 frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.js create mode 100644 frontend/src/AddMovie/ImportMovie/ImportMovies.js create mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.css create mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.js create mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRowConnector.js create mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.css create mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.js create mode 100644 frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector.js create mode 100644 frontend/src/App/App.js create mode 100644 frontend/src/App/AppRoutes.js create mode 100644 frontend/src/App/AppUpdatedModal.js create mode 100644 frontend/src/App/AppUpdatedModalConnector.js create mode 100644 frontend/src/App/AppUpdatedModalContent.css create mode 100644 frontend/src/App/AppUpdatedModalContent.js create mode 100644 frontend/src/App/AppUpdatedModalContentConnector.js create mode 100644 frontend/src/App/ColorImpairedContext.js create mode 100644 frontend/src/App/ConnectionLostModal.css create mode 100644 frontend/src/App/ConnectionLostModal.js create mode 100644 frontend/src/App/ConnectionLostModalConnector.js create mode 100644 frontend/src/Calendar/Agenda/Agenda.css create mode 100644 frontend/src/Calendar/Agenda/Agenda.js create mode 100644 frontend/src/Calendar/Agenda/AgendaConnector.js create mode 100644 frontend/src/Calendar/Agenda/AgendaEvent.css create mode 100644 frontend/src/Calendar/Agenda/AgendaEvent.js create mode 100644 frontend/src/Calendar/Agenda/AgendaEventConnector.js create mode 100644 frontend/src/Calendar/Calendar.css create mode 100644 frontend/src/Calendar/Calendar.js create mode 100644 frontend/src/Calendar/CalendarConnector.js create mode 100644 frontend/src/Calendar/CalendarPage.css create mode 100644 frontend/src/Calendar/CalendarPage.js create mode 100644 frontend/src/Calendar/CalendarPageConnector.js create mode 100644 frontend/src/Calendar/Day/CalendarDay.css create mode 100644 frontend/src/Calendar/Day/CalendarDay.js create mode 100644 frontend/src/Calendar/Day/CalendarDayConnector.js create mode 100644 frontend/src/Calendar/Day/CalendarDays.css create mode 100644 frontend/src/Calendar/Day/CalendarDays.js create mode 100644 frontend/src/Calendar/Day/CalendarDaysConnector.js create mode 100644 frontend/src/Calendar/Day/DayOfWeek.css create mode 100644 frontend/src/Calendar/Day/DayOfWeek.js create mode 100644 frontend/src/Calendar/Day/DaysOfWeek.css create mode 100644 frontend/src/Calendar/Day/DaysOfWeek.js create mode 100644 frontend/src/Calendar/Day/DaysOfWeekConnector.js create mode 100644 frontend/src/Calendar/Events/CalendarEvent.css create mode 100644 frontend/src/Calendar/Events/CalendarEvent.js create mode 100644 frontend/src/Calendar/Events/CalendarEventConnector.js create mode 100644 frontend/src/Calendar/Events/CalendarEventGroup.css create mode 100644 frontend/src/Calendar/Events/CalendarEventGroup.js create mode 100644 frontend/src/Calendar/Events/CalendarEventGroupConnector.js create mode 100644 frontend/src/Calendar/Events/CalendarEventQueueDetails.js create mode 100644 frontend/src/Calendar/Header/CalendarHeader.css create mode 100644 frontend/src/Calendar/Header/CalendarHeader.js create mode 100644 frontend/src/Calendar/Header/CalendarHeaderConnector.js create mode 100644 frontend/src/Calendar/Header/CalendarHeaderViewButton.js create mode 100644 frontend/src/Calendar/Legend/Legend.css create mode 100644 frontend/src/Calendar/Legend/Legend.js create mode 100644 frontend/src/Calendar/Legend/LegendConnector.js create mode 100644 frontend/src/Calendar/Legend/LegendIconItem.css create mode 100644 frontend/src/Calendar/Legend/LegendIconItem.js create mode 100644 frontend/src/Calendar/Legend/LegendItem.css create mode 100644 frontend/src/Calendar/Legend/LegendItem.js create mode 100644 frontend/src/Calendar/Options/CalendarOptionsModal.js create mode 100644 frontend/src/Calendar/Options/CalendarOptionsModalContent.js create mode 100644 frontend/src/Calendar/Options/CalendarOptionsModalContentConnector.js create mode 100644 frontend/src/Calendar/calendarViews.js create mode 100644 frontend/src/Calendar/getStatusStyle.js create mode 100644 frontend/src/Calendar/iCal/CalendarLinkModal.js create mode 100644 frontend/src/Calendar/iCal/CalendarLinkModalContent.js create mode 100644 frontend/src/Calendar/iCal/CalendarLinkModalContentConnector.js create mode 100644 frontend/src/Commands/commandNames.js create mode 100644 frontend/src/Components/Alert.css create mode 100644 frontend/src/Components/Alert.js create mode 100644 frontend/src/Components/Card.css create mode 100644 frontend/src/Components/Card.js create mode 100644 frontend/src/Components/CircularProgressBar.css create mode 100644 frontend/src/Components/CircularProgressBar.js create mode 100644 frontend/src/Components/DescriptionList/DescriptionList.css create mode 100644 frontend/src/Components/DescriptionList/DescriptionList.js create mode 100644 frontend/src/Components/DescriptionList/DescriptionListItem.js create mode 100644 frontend/src/Components/DescriptionList/DescriptionListItemDescription.css create mode 100644 frontend/src/Components/DescriptionList/DescriptionListItemDescription.js create mode 100644 frontend/src/Components/DescriptionList/DescriptionListItemTitle.css create mode 100644 frontend/src/Components/DescriptionList/DescriptionListItemTitle.js create mode 100644 frontend/src/Components/DragPreviewLayer.css create mode 100644 frontend/src/Components/DragPreviewLayer.js create mode 100644 frontend/src/Components/Error/ErrorBoundary.js create mode 100644 frontend/src/Components/Error/ErrorBoundaryError.css create mode 100644 frontend/src/Components/Error/ErrorBoundaryError.js create mode 100644 frontend/src/Components/FieldSet.css create mode 100644 frontend/src/Components/FieldSet.js create mode 100644 frontend/src/Components/FileBrowser/FileBrowserModal.css create mode 100644 frontend/src/Components/FileBrowser/FileBrowserModal.js create mode 100644 frontend/src/Components/FileBrowser/FileBrowserModalContent.css create mode 100644 frontend/src/Components/FileBrowser/FileBrowserModalContent.js create mode 100644 frontend/src/Components/FileBrowser/FileBrowserModalContentConnector.js create mode 100644 frontend/src/Components/FileBrowser/FileBrowserRow.css create mode 100644 frontend/src/Components/FileBrowser/FileBrowserRow.js create mode 100644 frontend/src/Components/Filter/Builder/BoolFilterBuilderRowValue.js create mode 100644 frontend/src/Components/Filter/Builder/DateFilterBuilderRowValue.css create mode 100644 frontend/src/Components/Filter/Builder/DateFilterBuilderRowValue.js create mode 100644 frontend/src/Components/Filter/Builder/FilterBuilderModalContent.css create mode 100644 frontend/src/Components/Filter/Builder/FilterBuilderModalContent.js create mode 100644 frontend/src/Components/Filter/Builder/FilterBuilderModalContentConnector.js create mode 100644 frontend/src/Components/Filter/Builder/FilterBuilderRow.css create mode 100644 frontend/src/Components/Filter/Builder/FilterBuilderRow.js create mode 100644 frontend/src/Components/Filter/Builder/FilterBuilderRowValue.js create mode 100644 frontend/src/Components/Filter/Builder/FilterBuilderRowValueConnector.js create mode 100644 frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.css create mode 100644 frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.js create mode 100644 frontend/src/Components/Filter/Builder/IndexerFilterBuilderRowValueConnector.js create mode 100644 frontend/src/Components/Filter/Builder/ProtocolFilterBuilderRowValue.js create mode 100644 frontend/src/Components/Filter/Builder/QualityFilterBuilderRowValueConnector.js create mode 100644 frontend/src/Components/Filter/Builder/QualityProfileFilterBuilderRowValueConnector.js create mode 100644 frontend/src/Components/Filter/Builder/SeriesStatusFilterBuilderRowValue.js create mode 100644 frontend/src/Components/Filter/Builder/TagFilterBuilderRowValueConnector.js create mode 100644 frontend/src/Components/Filter/CustomFilters/CustomFilter.css create mode 100644 frontend/src/Components/Filter/CustomFilters/CustomFilter.js create mode 100644 frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.css create mode 100644 frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.js create mode 100644 frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContentConnector.js create mode 100644 frontend/src/Components/Filter/FilterModal.js create mode 100644 frontend/src/Components/Form/AutoCompleteInput.css create mode 100644 frontend/src/Components/Form/AutoCompleteInput.js create mode 100644 frontend/src/Components/Form/CaptchaInput.css create mode 100644 frontend/src/Components/Form/CaptchaInput.js create mode 100644 frontend/src/Components/Form/CaptchaInputConnector.js create mode 100644 frontend/src/Components/Form/CheckInput.css create mode 100644 frontend/src/Components/Form/CheckInput.js create mode 100644 frontend/src/Components/Form/DeviceInput.css create mode 100644 frontend/src/Components/Form/DeviceInput.js create mode 100644 frontend/src/Components/Form/DeviceInputConnector.js create mode 100644 frontend/src/Components/Form/EnhancedSelectInput.css create mode 100644 frontend/src/Components/Form/EnhancedSelectInput.js create mode 100644 frontend/src/Components/Form/EnhancedSelectInputOption.css create mode 100644 frontend/src/Components/Form/EnhancedSelectInputOption.js create mode 100644 frontend/src/Components/Form/EnhancedSelectInputSelectedValue.css create mode 100644 frontend/src/Components/Form/EnhancedSelectInputSelectedValue.js create mode 100644 frontend/src/Components/Form/Form.css create mode 100644 frontend/src/Components/Form/Form.js create mode 100644 frontend/src/Components/Form/FormGroup.css create mode 100644 frontend/src/Components/Form/FormGroup.js create mode 100644 frontend/src/Components/Form/FormInputButton.css create mode 100644 frontend/src/Components/Form/FormInputButton.js create mode 100644 frontend/src/Components/Form/FormInputGroup.css create mode 100644 frontend/src/Components/Form/FormInputGroup.js create mode 100644 frontend/src/Components/Form/FormInputHelpText.css create mode 100644 frontend/src/Components/Form/FormInputHelpText.js create mode 100644 frontend/src/Components/Form/FormLabel.css create mode 100644 frontend/src/Components/Form/FormLabel.js create mode 100644 frontend/src/Components/Form/Input.css create mode 100644 frontend/src/Components/Form/MovieMonitoredSelectInput.js create mode 100644 frontend/src/Components/Form/NumberInput.js create mode 100644 frontend/src/Components/Form/OAuthInput.js create mode 100644 frontend/src/Components/Form/OAuthInputConnector.js create mode 100644 frontend/src/Components/Form/PasswordInput.css create mode 100644 frontend/src/Components/Form/PasswordInput.js create mode 100644 frontend/src/Components/Form/PathInput.css create mode 100644 frontend/src/Components/Form/PathInput.js create mode 100644 frontend/src/Components/Form/PathInputConnector.js create mode 100644 frontend/src/Components/Form/ProviderFieldFormGroup.js create mode 100644 frontend/src/Components/Form/QualityProfileSelectInputConnector.js create mode 100644 frontend/src/Components/Form/RootFolderSelectInput.js create mode 100644 frontend/src/Components/Form/RootFolderSelectInputConnector.js create mode 100644 frontend/src/Components/Form/RootFolderSelectInputOption.css create mode 100644 frontend/src/Components/Form/RootFolderSelectInputOption.js create mode 100644 frontend/src/Components/Form/RootFolderSelectInputSelectedValue.css create mode 100644 frontend/src/Components/Form/RootFolderSelectInputSelectedValue.js create mode 100644 frontend/src/Components/Form/SelectInput.css create mode 100644 frontend/src/Components/Form/SelectInput.js create mode 100644 frontend/src/Components/Form/TagInput.css create mode 100644 frontend/src/Components/Form/TagInput.js create mode 100644 frontend/src/Components/Form/TagInputConnector.js create mode 100644 frontend/src/Components/Form/TagInputInput.css create mode 100644 frontend/src/Components/Form/TagInputInput.js create mode 100644 frontend/src/Components/Form/TagInputTag.js create mode 100644 frontend/src/Components/Form/TextInput.css create mode 100644 frontend/src/Components/Form/TextInput.js create mode 100644 frontend/src/Components/Form/TextTagInputConnector.js create mode 100644 frontend/src/Components/HeartRating.css create mode 100644 frontend/src/Components/HeartRating.js create mode 100644 frontend/src/Components/Icon.css create mode 100644 frontend/src/Components/Icon.js create mode 100644 frontend/src/Components/Label.css create mode 100644 frontend/src/Components/Label.js create mode 100644 frontend/src/Components/Link/Button.css create mode 100644 frontend/src/Components/Link/Button.js create mode 100644 frontend/src/Components/Link/ClipboardButton.css create mode 100644 frontend/src/Components/Link/ClipboardButton.js create mode 100644 frontend/src/Components/Link/IconButton.css create mode 100644 frontend/src/Components/Link/IconButton.js create mode 100644 frontend/src/Components/Link/Link.css create mode 100644 frontend/src/Components/Link/Link.js create mode 100644 frontend/src/Components/Link/SpinnerButton.css create mode 100644 frontend/src/Components/Link/SpinnerButton.js create mode 100644 frontend/src/Components/Link/SpinnerErrorButton.css create mode 100644 frontend/src/Components/Link/SpinnerErrorButton.js create mode 100644 frontend/src/Components/Link/SpinnerIconButton.js create mode 100644 frontend/src/Components/Loading/LoadingIndicator.css create mode 100644 frontend/src/Components/Loading/LoadingIndicator.js create mode 100644 frontend/src/Components/Loading/LoadingMessage.css create mode 100644 frontend/src/Components/Loading/LoadingMessage.js create mode 100644 frontend/src/Components/Measure.js create mode 100644 frontend/src/Components/Menu/FilterMenu.css create mode 100644 frontend/src/Components/Menu/FilterMenu.js create mode 100644 frontend/src/Components/Menu/FilterMenuContent.js create mode 100644 frontend/src/Components/Menu/FilterMenuItem.js create mode 100644 frontend/src/Components/Menu/Menu.css create mode 100644 frontend/src/Components/Menu/Menu.js create mode 100644 frontend/src/Components/Menu/MenuButton.css create mode 100644 frontend/src/Components/Menu/MenuButton.js create mode 100644 frontend/src/Components/Menu/MenuContent.css create mode 100644 frontend/src/Components/Menu/MenuContent.js create mode 100644 frontend/src/Components/Menu/MenuItem.css create mode 100644 frontend/src/Components/Menu/MenuItem.js create mode 100644 frontend/src/Components/Menu/MenuItemSeparator.css create mode 100644 frontend/src/Components/Menu/MenuItemSeparator.js create mode 100644 frontend/src/Components/Menu/PageMenuButton.css create mode 100644 frontend/src/Components/Menu/PageMenuButton.js create mode 100644 frontend/src/Components/Menu/SelectedMenuItem.css create mode 100644 frontend/src/Components/Menu/SelectedMenuItem.js create mode 100644 frontend/src/Components/Menu/SortMenu.js create mode 100644 frontend/src/Components/Menu/SortMenuItem.js create mode 100644 frontend/src/Components/Menu/ToolbarMenuButton.css create mode 100644 frontend/src/Components/Menu/ToolbarMenuButton.js create mode 100644 frontend/src/Components/Menu/ViewMenu.js create mode 100644 frontend/src/Components/Menu/ViewMenuItem.js create mode 100644 frontend/src/Components/Modal/ConfirmModal.js create mode 100644 frontend/src/Components/Modal/Modal.css create mode 100644 frontend/src/Components/Modal/Modal.js create mode 100644 frontend/src/Components/Modal/ModalBody.css create mode 100644 frontend/src/Components/Modal/ModalBody.js create mode 100644 frontend/src/Components/Modal/ModalContent.css create mode 100644 frontend/src/Components/Modal/ModalContent.js create mode 100644 frontend/src/Components/Modal/ModalError.css create mode 100644 frontend/src/Components/Modal/ModalError.js create mode 100644 frontend/src/Components/Modal/ModalFooter.css create mode 100644 frontend/src/Components/Modal/ModalFooter.js create mode 100644 frontend/src/Components/Modal/ModalHeader.css create mode 100644 frontend/src/Components/Modal/ModalHeader.js create mode 100644 frontend/src/Components/MonitorToggleButton.css create mode 100644 frontend/src/Components/MonitorToggleButton.js create mode 100644 frontend/src/Components/NotFound.css create mode 100644 frontend/src/Components/NotFound.js create mode 100644 frontend/src/Components/Page/ErrorPage.css create mode 100644 frontend/src/Components/Page/ErrorPage.js create mode 100644 frontend/src/Components/Page/Header/KeyboardShortcutsModal.js create mode 100644 frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.css create mode 100644 frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.js create mode 100644 frontend/src/Components/Page/Header/KeyboardShortcutsModalContentConnector.js create mode 100644 frontend/src/Components/Page/Header/MovieSearchInput.css create mode 100644 frontend/src/Components/Page/Header/MovieSearchInput.js create mode 100644 frontend/src/Components/Page/Header/MovieSearchInputConnector.js create mode 100644 frontend/src/Components/Page/Header/MovieSearchResult.css create mode 100644 frontend/src/Components/Page/Header/MovieSearchResult.js create mode 100644 frontend/src/Components/Page/Header/PageHeader.css create mode 100644 frontend/src/Components/Page/Header/PageHeader.js create mode 100644 frontend/src/Components/Page/Header/PageHeaderActionsMenu.css create mode 100644 frontend/src/Components/Page/Header/PageHeaderActionsMenu.js create mode 100644 frontend/src/Components/Page/Header/PageHeaderActionsMenuConnector.js create mode 100644 frontend/src/Components/Page/LoadingPage.css create mode 100644 frontend/src/Components/Page/LoadingPage.js create mode 100644 frontend/src/Components/Page/Page.css create mode 100644 frontend/src/Components/Page/Page.js create mode 100644 frontend/src/Components/Page/PageConnector.js create mode 100644 frontend/src/Components/Page/PageContent.css create mode 100644 frontend/src/Components/Page/PageContent.js create mode 100644 frontend/src/Components/Page/PageContentBody.css create mode 100644 frontend/src/Components/Page/PageContentBody.js create mode 100644 frontend/src/Components/Page/PageContentBodyConnector.js create mode 100644 frontend/src/Components/Page/PageContentError.css create mode 100644 frontend/src/Components/Page/PageContentError.js create mode 100644 frontend/src/Components/Page/PageContentFooter.css create mode 100644 frontend/src/Components/Page/PageContentFooter.js create mode 100644 frontend/src/Components/Page/PageJumpBar.css create mode 100644 frontend/src/Components/Page/PageJumpBar.js create mode 100644 frontend/src/Components/Page/PageJumpBarItem.css create mode 100644 frontend/src/Components/Page/PageJumpBarItem.js create mode 100644 frontend/src/Components/Page/PageSectionContent.js create mode 100644 frontend/src/Components/Page/Sidebar/Messages/Message.css create mode 100644 frontend/src/Components/Page/Sidebar/Messages/Message.js create mode 100644 frontend/src/Components/Page/Sidebar/Messages/MessageConnector.js create mode 100644 frontend/src/Components/Page/Sidebar/Messages/Messages.css create mode 100644 frontend/src/Components/Page/Sidebar/Messages/Messages.js create mode 100644 frontend/src/Components/Page/Sidebar/Messages/MessagesConnector.js create mode 100644 frontend/src/Components/Page/Sidebar/PageSidebar.css create mode 100644 frontend/src/Components/Page/Sidebar/PageSidebar.js create mode 100644 frontend/src/Components/Page/Sidebar/PageSidebarItem.css create mode 100644 frontend/src/Components/Page/Sidebar/PageSidebarItem.js create mode 100644 frontend/src/Components/Page/Sidebar/PageSidebarStatus.css create mode 100644 frontend/src/Components/Page/Sidebar/PageSidebarStatus.js create mode 100644 frontend/src/Components/Page/Toolbar/PageToolbar.css create mode 100644 frontend/src/Components/Page/Toolbar/PageToolbar.js create mode 100644 frontend/src/Components/Page/Toolbar/PageToolbarButton.css create mode 100644 frontend/src/Components/Page/Toolbar/PageToolbarButton.js create mode 100644 frontend/src/Components/Page/Toolbar/PageToolbarSection.css create mode 100644 frontend/src/Components/Page/Toolbar/PageToolbarSection.js create mode 100644 frontend/src/Components/Page/Toolbar/PageToolbarSeparator.css create mode 100644 frontend/src/Components/Page/Toolbar/PageToolbarSeparator.js create mode 100644 frontend/src/Components/ProgressBar.css create mode 100644 frontend/src/Components/ProgressBar.js create mode 100644 frontend/src/Components/Router/Switch.js create mode 100644 frontend/src/Components/Scroller/OverlayScroller.css create mode 100644 frontend/src/Components/Scroller/OverlayScroller.js create mode 100644 frontend/src/Components/Scroller/Scroller.css create mode 100644 frontend/src/Components/Scroller/Scroller.js create mode 100644 frontend/src/Components/SignalRConnector.js create mode 100644 frontend/src/Components/SpinnerIcon.js create mode 100644 frontend/src/Components/Table/Cells/RelativeDateCell.css create mode 100644 frontend/src/Components/Table/Cells/RelativeDateCell.js create mode 100644 frontend/src/Components/Table/Cells/RelativeDateCellConnector.js create mode 100644 frontend/src/Components/Table/Cells/TableRowCell.css create mode 100644 frontend/src/Components/Table/Cells/TableRowCell.js create mode 100644 frontend/src/Components/Table/Cells/TableRowCellButton.css create mode 100644 frontend/src/Components/Table/Cells/TableRowCellButton.js create mode 100644 frontend/src/Components/Table/Cells/TableSelectCell.css create mode 100644 frontend/src/Components/Table/Cells/TableSelectCell.js create mode 100644 frontend/src/Components/Table/Cells/VirtualTableRowCell.css create mode 100644 frontend/src/Components/Table/Cells/VirtualTableRowCell.js create mode 100644 frontend/src/Components/Table/Cells/VirtualTableSelectCell.css create mode 100644 frontend/src/Components/Table/Cells/VirtualTableSelectCell.js create mode 100644 frontend/src/Components/Table/Table.css create mode 100644 frontend/src/Components/Table/Table.js create mode 100644 frontend/src/Components/Table/TableBody.js create mode 100644 frontend/src/Components/Table/TableHeader.js create mode 100644 frontend/src/Components/Table/TableHeaderCell.css create mode 100644 frontend/src/Components/Table/TableHeaderCell.js create mode 100644 frontend/src/Components/Table/TableOptions/TableOptionsColumn.css create mode 100644 frontend/src/Components/Table/TableOptions/TableOptionsColumn.js create mode 100644 frontend/src/Components/Table/TableOptions/TableOptionsColumnDragPreview.css create mode 100644 frontend/src/Components/Table/TableOptions/TableOptionsColumnDragPreview.js create mode 100644 frontend/src/Components/Table/TableOptions/TableOptionsColumnDragSource.css create mode 100644 frontend/src/Components/Table/TableOptions/TableOptionsColumnDragSource.js create mode 100644 frontend/src/Components/Table/TableOptions/TableOptionsModal.css create mode 100644 frontend/src/Components/Table/TableOptions/TableOptionsModal.js create mode 100644 frontend/src/Components/Table/TableOptions/TableOptionsModalWrapper.js create mode 100644 frontend/src/Components/Table/TablePager.css create mode 100644 frontend/src/Components/Table/TablePager.js create mode 100644 frontend/src/Components/Table/TableRow.css create mode 100644 frontend/src/Components/Table/TableRow.js create mode 100644 frontend/src/Components/Table/TableRowButton.css create mode 100644 frontend/src/Components/Table/TableRowButton.js create mode 100644 frontend/src/Components/Table/TableSelectAllHeaderCell.css create mode 100644 frontend/src/Components/Table/TableSelectAllHeaderCell.js create mode 100644 frontend/src/Components/Table/VirtualTable.css create mode 100644 frontend/src/Components/Table/VirtualTable.js create mode 100644 frontend/src/Components/Table/VirtualTableBody.css create mode 100644 frontend/src/Components/Table/VirtualTableBody.js create mode 100644 frontend/src/Components/Table/VirtualTableHeader.css create mode 100644 frontend/src/Components/Table/VirtualTableHeader.js create mode 100644 frontend/src/Components/Table/VirtualTableHeaderCell.css create mode 100644 frontend/src/Components/Table/VirtualTableHeaderCell.js create mode 100644 frontend/src/Components/Table/VirtualTableRow.css create mode 100644 frontend/src/Components/Table/VirtualTableRow.js create mode 100644 frontend/src/Components/Table/VirtualTableSelectAllHeaderCell.css create mode 100644 frontend/src/Components/Table/VirtualTableSelectAllHeaderCell.js create mode 100644 frontend/src/Components/TagList.css create mode 100644 frontend/src/Components/TagList.js create mode 100644 frontend/src/Components/TagListConnector.js create mode 100644 frontend/src/Components/Tooltip/Popover.css create mode 100644 frontend/src/Components/Tooltip/Popover.js create mode 100644 frontend/src/Components/Tooltip/Tooltip.css create mode 100644 frontend/src/Components/Tooltip/Tooltip.js create mode 100644 frontend/src/Components/keyboardShortcuts.js create mode 100644 frontend/src/Components/withCurrentPage.js create mode 100644 frontend/src/Components/withScrollPosition.js create mode 100644 frontend/src/Content/Fonts/Roboto-Light.ttf create mode 100644 frontend/src/Content/Fonts/Roboto-Light.woff create mode 100644 frontend/src/Content/Fonts/Roboto-Light.woff2 create mode 100644 frontend/src/Content/Fonts/Roboto-Regular.ttf create mode 100644 frontend/src/Content/Fonts/Roboto-Regular.woff create mode 100644 frontend/src/Content/Fonts/Roboto-Regular.woff2 create mode 100644 frontend/src/Content/Fonts/UbuntuMono-Regular.eot create mode 100644 frontend/src/Content/Fonts/UbuntuMono-Regular.ttf create mode 100644 frontend/src/Content/Fonts/UbuntuMono-Regular.woff create mode 100644 frontend/src/Content/Fonts/fonts.css create mode 100644 frontend/src/Content/Fonts/text-security-disc.ttf create mode 100644 frontend/src/Content/Fonts/text-security-disc.woff create mode 100644 frontend/src/Content/Images/404.png create mode 100644 frontend/src/Content/Images/Icons/android-chrome-192x192.png create mode 100644 frontend/src/Content/Images/Icons/android-chrome-512x512.png create mode 100644 frontend/src/Content/Images/Icons/apple-touch-icon.png create mode 100644 frontend/src/Content/Images/Icons/browserconfig.xml create mode 100644 frontend/src/Content/Images/Icons/favicon-16x16.png create mode 100644 frontend/src/Content/Images/Icons/favicon-32x32.png create mode 100644 frontend/src/Content/Images/Icons/favicon.ico create mode 100644 frontend/src/Content/Images/Icons/manifest.json create mode 100644 frontend/src/Content/Images/Icons/mstile-144x144.png create mode 100644 frontend/src/Content/Images/Icons/mstile-150x150.png create mode 100644 frontend/src/Content/Images/Icons/mstile-310x150.png create mode 100644 frontend/src/Content/Images/Icons/mstile-310x310.png create mode 100644 frontend/src/Content/Images/Icons/mstile-70x70.png create mode 100644 frontend/src/Content/Images/Icons/safari-pinned-tab.svg create mode 100644 frontend/src/Content/Images/error.png create mode 100644 frontend/src/Content/Images/logo-full.png create mode 100644 frontend/src/Content/Images/logo.png create mode 100644 frontend/src/Content/Images/logo.svg create mode 100644 frontend/src/Content/Images/poster-dark.png create mode 100644 frontend/src/Helpers/Props/Shapes/createRouteMatchShape.js create mode 100644 frontend/src/Helpers/Props/Shapes/locationShape.js create mode 100644 frontend/src/Helpers/Props/Shapes/settingShape.js create mode 100644 frontend/src/Helpers/Props/align.js create mode 100644 frontend/src/Helpers/Props/filterBuilderTypes.js create mode 100644 frontend/src/Helpers/Props/filterBuilderValueTypes.js create mode 100644 frontend/src/Helpers/Props/filterTypePredicates.js create mode 100644 frontend/src/Helpers/Props/filterTypes.js create mode 100644 frontend/src/Helpers/Props/icons.js create mode 100644 frontend/src/Helpers/Props/index.js create mode 100644 frontend/src/Helpers/Props/inputTypes.js create mode 100644 frontend/src/Helpers/Props/kinds.js create mode 100644 frontend/src/Helpers/Props/messageTypes.js create mode 100644 frontend/src/Helpers/Props/scrollDirections.js create mode 100644 frontend/src/Helpers/Props/sizes.js create mode 100644 frontend/src/Helpers/Props/sortDirections.js create mode 100644 frontend/src/Helpers/Props/tooltipPositions.js create mode 100644 frontend/src/Helpers/dragTypes.js create mode 100644 frontend/src/Helpers/elementChildren.js create mode 100644 frontend/src/Helpers/getDisplayName.js create mode 100644 frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.css create mode 100644 frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContent.js create mode 100644 frontend/src/InteractiveImport/Folder/InteractiveImportSelectFolderModalContentConnector.js create mode 100644 frontend/src/InteractiveImport/Folder/RecentFolderRow.css create mode 100644 frontend/src/InteractiveImport/Folder/RecentFolderRow.js create mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.css create mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportModalContent.js create mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportModalContentConnector.js create mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportRow.css create mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportRow.js create mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportRowCellPlaceholder.css create mode 100644 frontend/src/InteractiveImport/Interactive/InteractiveImportRowCellPlaceholder.js create mode 100644 frontend/src/InteractiveImport/InteractiveImportModal.js create mode 100644 frontend/src/InteractiveImport/Quality/SelectQualityModal.js create mode 100644 frontend/src/InteractiveImport/Quality/SelectQualityModalContent.js create mode 100644 frontend/src/InteractiveImport/Quality/SelectQualityModalContentConnector.js create mode 100644 frontend/src/InteractiveImport/Series/SelectSeriesModal.js create mode 100644 frontend/src/InteractiveImport/Series/SelectSeriesModalContent.css create mode 100644 frontend/src/InteractiveImport/Series/SelectSeriesModalContent.js create mode 100644 frontend/src/InteractiveImport/Series/SelectSeriesModalContentConnector.js create mode 100644 frontend/src/InteractiveImport/Series/SelectSeriesRow.css create mode 100644 frontend/src/InteractiveImport/Series/SelectSeriesRow.js create mode 100644 frontend/src/InteractiveSearch/InteractiveSearch.css create mode 100644 frontend/src/InteractiveSearch/InteractiveSearch.js create mode 100644 frontend/src/InteractiveSearch/InteractiveSearchConnector.js create mode 100644 frontend/src/InteractiveSearch/InteractiveSearchFilterModalConnector.js create mode 100644 frontend/src/InteractiveSearch/InteractiveSearchRow.css create mode 100644 frontend/src/InteractiveSearch/InteractiveSearchRow.js create mode 100644 frontend/src/InteractiveSearch/Peers.js create mode 100644 frontend/src/Movie/Delete/DeleteMovieModal.js create mode 100644 frontend/src/Movie/Delete/DeleteMovieModalContent.css create mode 100644 frontend/src/Movie/Delete/DeleteMovieModalContent.js create mode 100644 frontend/src/Movie/Delete/DeleteMovieModalContentConnector.js create mode 100644 frontend/src/Movie/Details/MovieAlternateTitles.css create mode 100644 frontend/src/Movie/Details/MovieAlternateTitles.js create mode 100644 frontend/src/Movie/Details/MovieDetails.css create mode 100644 frontend/src/Movie/Details/MovieDetails.js create mode 100644 frontend/src/Movie/Details/MovieDetailsConnector.js create mode 100644 frontend/src/Movie/Details/MovieDetailsLinks.css create mode 100644 frontend/src/Movie/Details/MovieDetailsLinks.js create mode 100644 frontend/src/Movie/Details/MovieDetailsPageConnector.js create mode 100644 frontend/src/Movie/Details/MovieTags.js create mode 100644 frontend/src/Movie/Details/MovieTagsConnector.js create mode 100644 frontend/src/Movie/Edit/EditMovieModal.js create mode 100644 frontend/src/Movie/Edit/EditMovieModalConnector.js create mode 100644 frontend/src/Movie/Edit/EditMovieModalContent.css create mode 100644 frontend/src/Movie/Edit/EditMovieModalContent.js create mode 100644 frontend/src/Movie/Edit/EditMovieModalContentConnector.js create mode 100644 frontend/src/Movie/Editor/Delete/DeleteMovieModal.js create mode 100644 frontend/src/Movie/Editor/Delete/DeleteMovieModalContent.css create mode 100644 frontend/src/Movie/Editor/Delete/DeleteMovieModalContent.js create mode 100644 frontend/src/Movie/Editor/Delete/DeleteMovieModalContentConnector.js create mode 100644 frontend/src/Movie/Editor/Organize/OrganizeSeriesModal.js create mode 100644 frontend/src/Movie/Editor/Organize/OrganizeSeriesModalContent.css create mode 100644 frontend/src/Movie/Editor/Organize/OrganizeSeriesModalContent.js create mode 100644 frontend/src/Movie/Editor/Organize/OrganizeSeriesModalContentConnector.js create mode 100644 frontend/src/Movie/Editor/SeriesEditor.js create mode 100644 frontend/src/Movie/Editor/SeriesEditorConnector.js create mode 100644 frontend/src/Movie/Editor/SeriesEditorFilterModalConnector.js create mode 100644 frontend/src/Movie/Editor/SeriesEditorFooter.css create mode 100644 frontend/src/Movie/Editor/SeriesEditorFooter.js create mode 100644 frontend/src/Movie/Editor/SeriesEditorFooterLabel.css create mode 100644 frontend/src/Movie/Editor/SeriesEditorFooterLabel.js create mode 100644 frontend/src/Movie/Editor/SeriesEditorRow.js create mode 100644 frontend/src/Movie/Editor/SeriesEditorRowConnector.js create mode 100644 frontend/src/Movie/Editor/Tags/TagsModal.js create mode 100644 frontend/src/Movie/Editor/Tags/TagsModalContent.css create mode 100644 frontend/src/Movie/Editor/Tags/TagsModalContent.js create mode 100644 frontend/src/Movie/Editor/Tags/TagsModalContentConnector.js create mode 100644 frontend/src/Movie/History/MovieHistoryModal.js create mode 100644 frontend/src/Movie/History/MovieHistoryModalContent.js create mode 100644 frontend/src/Movie/History/MovieHistoryModalContentConnector.js create mode 100644 frontend/src/Movie/History/MovieHistoryRow.css create mode 100644 frontend/src/Movie/History/MovieHistoryRow.js create mode 100644 frontend/src/Movie/History/MovieHistoryRowConnector.js create mode 100644 frontend/src/Movie/Index/Menus/MovieIndexFilterMenu.js create mode 100644 frontend/src/Movie/Index/Menus/MovieIndexSortMenu.js create mode 100644 frontend/src/Movie/Index/Menus/MovieIndexViewMenu.js create mode 100644 frontend/src/Movie/Index/MovieIndex.css create mode 100644 frontend/src/Movie/Index/MovieIndex.js create mode 100644 frontend/src/Movie/Index/MovieIndexConnector.js create mode 100644 frontend/src/Movie/Index/MovieIndexFilterModalConnector.js create mode 100644 frontend/src/Movie/Index/MovieIndexFooter.css create mode 100644 frontend/src/Movie/Index/MovieIndexFooter.js create mode 100644 frontend/src/Movie/Index/MovieIndexItemConnector.js create mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverview.css create mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverview.js create mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.css create mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviewInfo.js create mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviewInfoRow.css create mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviewInfoRow.js create mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviews.css create mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviews.js create mode 100644 frontend/src/Movie/Index/Overview/MovieIndexOverviewsConnector.js create mode 100644 frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModal.js create mode 100644 frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModalContent.js create mode 100644 frontend/src/Movie/Index/Overview/Options/MovieIndexOverviewOptionsModalContentConnector.js create mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPoster.css create mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPoster.js create mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.css create mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPosterInfo.js create mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPosters.css create mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPosters.js create mode 100644 frontend/src/Movie/Index/Posters/MovieIndexPostersConnector.js create mode 100644 frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModal.js create mode 100644 frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModalContent.js create mode 100644 frontend/src/Movie/Index/Posters/Options/MovieIndexPosterOptionsModalContentConnector.js create mode 100644 frontend/src/Movie/Index/ProgressBar/MovieIndexProgressBar.css create mode 100644 frontend/src/Movie/Index/ProgressBar/MovieIndexProgressBar.js create mode 100644 frontend/src/Movie/Index/Table/MovieIndexActionsCell.js create mode 100644 frontend/src/Movie/Index/Table/MovieIndexHeader.css create mode 100644 frontend/src/Movie/Index/Table/MovieIndexHeader.js create mode 100644 frontend/src/Movie/Index/Table/MovieIndexHeaderConnector.js create mode 100644 frontend/src/Movie/Index/Table/MovieIndexRow.css create mode 100644 frontend/src/Movie/Index/Table/MovieIndexRow.js create mode 100644 frontend/src/Movie/Index/Table/MovieIndexTable.css create mode 100644 frontend/src/Movie/Index/Table/MovieIndexTable.js create mode 100644 frontend/src/Movie/Index/Table/MovieIndexTableConnector.js create mode 100644 frontend/src/Movie/Index/Table/MovieIndexTableOptions.js create mode 100644 frontend/src/Movie/Index/Table/MovieIndexTableOptionsConnector.js create mode 100644 frontend/src/Movie/Index/Table/MovieStatusCell.css create mode 100644 frontend/src/Movie/Index/Table/MovieStatusCell.js create mode 100644 frontend/src/Movie/MoveSeries/MoveSeriesModal.css create mode 100644 frontend/src/Movie/MoveSeries/MoveSeriesModal.js create mode 100644 frontend/src/Movie/MoviePoster.js create mode 100644 frontend/src/Movie/MovieQuality.js create mode 100644 frontend/src/Movie/MovieTitleLink.js create mode 100644 frontend/src/Movie/NoMovie.css create mode 100644 frontend/src/Movie/NoMovie.js create mode 100644 frontend/src/Movie/Search/SeasonInteractiveSearchModal.js create mode 100644 frontend/src/Movie/Search/SeasonInteractiveSearchModalConnector.js create mode 100644 frontend/src/Movie/Search/SeasonInteractiveSearchModalContent.js create mode 100644 frontend/src/Movie/movieEntities.js create mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorModal.js create mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorModalContent.css create mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorModalContent.js create mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorModalContentConnector.js create mode 100644 frontend/src/MovieFile/Editor/MovieFileEditorRow.js create mode 100644 frontend/src/MovieFile/MediaInfo.js create mode 100644 frontend/src/MovieFile/MediaInfoConnector.js create mode 100644 frontend/src/MovieFile/MovieFileLanguageConnector.js create mode 100644 frontend/src/MovieFile/mediaInfoTypes.js create mode 100644 frontend/src/Organize/OrganizePreviewModal.js create mode 100644 frontend/src/Organize/OrganizePreviewModalConnector.js create mode 100644 frontend/src/Organize/OrganizePreviewModalContent.css create mode 100644 frontend/src/Organize/OrganizePreviewModalContent.js create mode 100644 frontend/src/Organize/OrganizePreviewModalContentConnector.js create mode 100644 frontend/src/Organize/OrganizePreviewRow.css create mode 100644 frontend/src/Organize/OrganizePreviewRow.js create mode 100644 frontend/src/RootFolder/RootFolderRow.css create mode 100644 frontend/src/RootFolder/RootFolderRow.js create mode 100644 frontend/src/RootFolder/RootFolderRowConnector.js create mode 100644 frontend/src/RootFolder/RootFolders.js create mode 100644 frontend/src/RootFolder/RootFoldersConnector.js create mode 100644 frontend/src/Settings/AdvancedSettingsButton.css create mode 100644 frontend/src/Settings/AdvancedSettingsButton.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClientSettings.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClientSettingsConnector.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientItem.css create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientItem.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModal.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContent.css create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContent.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientModalContentConnector.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/AddDownloadClientPresetMenuItem.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.css create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/DownloadClient.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/DownloadClients.css create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/DownloadClients.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/DownloadClientsConnector.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModal.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalConnector.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.css create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContent.js create mode 100644 frontend/src/Settings/DownloadClients/DownloadClients/EditDownloadClientModalContentConnector.js create mode 100644 frontend/src/Settings/DownloadClients/Options/DownloadClientOptions.js create mode 100644 frontend/src/Settings/DownloadClients/Options/DownloadClientOptionsConnector.js create mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModal.js create mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalConnector.js create mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContent.css create mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContent.js create mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/EditRemotePathMappingModalContentConnector.js create mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMapping.css create mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMapping.js create mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappings.css create mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappings.js create mode 100644 frontend/src/Settings/DownloadClients/RemotePathMappings/RemotePathMappingsConnector.js create mode 100644 frontend/src/Settings/General/AnalyticSettings.js create mode 100644 frontend/src/Settings/General/BackupSettings.js create mode 100644 frontend/src/Settings/General/GeneralSettings.js create mode 100644 frontend/src/Settings/General/GeneralSettingsConnector.js create mode 100644 frontend/src/Settings/General/HostSettings.js create mode 100644 frontend/src/Settings/General/LoggingSettings.js create mode 100644 frontend/src/Settings/General/ProxySettings.js create mode 100644 frontend/src/Settings/General/SecuritySettings.js create mode 100644 frontend/src/Settings/General/UpdateSettings.js create mode 100644 frontend/src/Settings/Indexers/IndexerSettings.js create mode 100644 frontend/src/Settings/Indexers/IndexerSettingsConnector.js create mode 100644 frontend/src/Settings/Indexers/Indexers/AddIndexerItem.css create mode 100644 frontend/src/Settings/Indexers/Indexers/AddIndexerItem.js create mode 100644 frontend/src/Settings/Indexers/Indexers/AddIndexerModal.js create mode 100644 frontend/src/Settings/Indexers/Indexers/AddIndexerModalContent.css create mode 100644 frontend/src/Settings/Indexers/Indexers/AddIndexerModalContent.js create mode 100644 frontend/src/Settings/Indexers/Indexers/AddIndexerModalContentConnector.js create mode 100644 frontend/src/Settings/Indexers/Indexers/AddIndexerPresetMenuItem.js create mode 100644 frontend/src/Settings/Indexers/Indexers/EditIndexerModal.js create mode 100644 frontend/src/Settings/Indexers/Indexers/EditIndexerModalConnector.js create mode 100644 frontend/src/Settings/Indexers/Indexers/EditIndexerModalContent.css create mode 100644 frontend/src/Settings/Indexers/Indexers/EditIndexerModalContent.js create mode 100644 frontend/src/Settings/Indexers/Indexers/EditIndexerModalContentConnector.js create mode 100644 frontend/src/Settings/Indexers/Indexers/Indexer.css create mode 100644 frontend/src/Settings/Indexers/Indexers/Indexer.js create mode 100644 frontend/src/Settings/Indexers/Indexers/Indexers.css create mode 100644 frontend/src/Settings/Indexers/Indexers/Indexers.js create mode 100644 frontend/src/Settings/Indexers/Indexers/IndexersConnector.js create mode 100644 frontend/src/Settings/Indexers/Options/IndexerOptions.js create mode 100644 frontend/src/Settings/Indexers/Options/IndexerOptionsConnector.js create mode 100644 frontend/src/Settings/Indexers/Restrictions/EditRestrictionModal.js create mode 100644 frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalConnector.js create mode 100644 frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContent.css create mode 100644 frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContent.js create mode 100644 frontend/src/Settings/Indexers/Restrictions/EditRestrictionModalContentConnector.js create mode 100644 frontend/src/Settings/Indexers/Restrictions/Restriction.css create mode 100644 frontend/src/Settings/Indexers/Restrictions/Restriction.js create mode 100644 frontend/src/Settings/Indexers/Restrictions/Restrictions.css create mode 100644 frontend/src/Settings/Indexers/Restrictions/Restrictions.js create mode 100644 frontend/src/Settings/Indexers/Restrictions/RestrictionsConnector.js create mode 100644 frontend/src/Settings/MediaManagement/MediaManagement.js create mode 100644 frontend/src/Settings/MediaManagement/MediaManagementConnector.js create mode 100644 frontend/src/Settings/MediaManagement/Naming/Naming.css create mode 100644 frontend/src/Settings/MediaManagement/Naming/Naming.js create mode 100644 frontend/src/Settings/MediaManagement/Naming/NamingConnector.js create mode 100644 frontend/src/Settings/MediaManagement/Naming/NamingModal.css create mode 100644 frontend/src/Settings/MediaManagement/Naming/NamingModal.js create mode 100644 frontend/src/Settings/MediaManagement/Naming/NamingOption.css create mode 100644 frontend/src/Settings/MediaManagement/Naming/NamingOption.js create mode 100644 frontend/src/Settings/Metadata/Metadata/EditMetadataModal.js create mode 100644 frontend/src/Settings/Metadata/Metadata/EditMetadataModalConnector.js create mode 100644 frontend/src/Settings/Metadata/Metadata/EditMetadataModalContent.js create mode 100644 frontend/src/Settings/Metadata/Metadata/EditMetadataModalContentConnector.js create mode 100644 frontend/src/Settings/Metadata/Metadata/Metadata.css create mode 100644 frontend/src/Settings/Metadata/Metadata/Metadata.js create mode 100644 frontend/src/Settings/Metadata/Metadata/Metadatas.css create mode 100644 frontend/src/Settings/Metadata/Metadata/Metadatas.js create mode 100644 frontend/src/Settings/Metadata/Metadata/MetadatasConnector.js create mode 100644 frontend/src/Settings/Metadata/MetadataSettings.js create mode 100644 frontend/src/Settings/NetImport/NetImport/AddNetImportItem.css create mode 100644 frontend/src/Settings/NetImport/NetImport/AddNetImportItem.js create mode 100644 frontend/src/Settings/NetImport/NetImport/AddNetImportModal.js create mode 100644 frontend/src/Settings/NetImport/NetImport/AddNetImportModalContent.css create mode 100644 frontend/src/Settings/NetImport/NetImport/AddNetImportModalContent.js create mode 100644 frontend/src/Settings/NetImport/NetImport/AddNetImportModalContentConnector.js create mode 100644 frontend/src/Settings/NetImport/NetImport/AddNetImportPresetMenuItem.js create mode 100644 frontend/src/Settings/NetImport/NetImport/EditNetImportModal.js create mode 100644 frontend/src/Settings/NetImport/NetImport/EditNetImportModalConnector.js create mode 100644 frontend/src/Settings/NetImport/NetImport/EditNetImportModalContent.css create mode 100644 frontend/src/Settings/NetImport/NetImport/EditNetImportModalContent.js create mode 100644 frontend/src/Settings/NetImport/NetImport/EditNetImportModalContentConnector.js create mode 100644 frontend/src/Settings/NetImport/NetImport/NetImport.css create mode 100644 frontend/src/Settings/NetImport/NetImport/NetImport.js create mode 100644 frontend/src/Settings/NetImport/NetImport/NetImports.css create mode 100644 frontend/src/Settings/NetImport/NetImport/NetImports.js create mode 100644 frontend/src/Settings/NetImport/NetImport/NetImportsConnector.js create mode 100644 frontend/src/Settings/NetImport/NetImportSettings.js create mode 100644 frontend/src/Settings/NetImport/NetImportSettingsConnector.js create mode 100644 frontend/src/Settings/NetImport/Options/NetImportOptions.js create mode 100644 frontend/src/Settings/NetImport/Options/NetImportOptionsConnector.js create mode 100644 frontend/src/Settings/Notifications/NotificationSettings.js create mode 100644 frontend/src/Settings/Notifications/Notifications/AddNotificationItem.css create mode 100644 frontend/src/Settings/Notifications/Notifications/AddNotificationItem.js create mode 100644 frontend/src/Settings/Notifications/Notifications/AddNotificationModal.js create mode 100644 frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.css create mode 100644 frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.js create mode 100644 frontend/src/Settings/Notifications/Notifications/AddNotificationModalContentConnector.js create mode 100644 frontend/src/Settings/Notifications/Notifications/AddNotificationPresetMenuItem.js create mode 100644 frontend/src/Settings/Notifications/Notifications/EditNotificationModal.js create mode 100644 frontend/src/Settings/Notifications/Notifications/EditNotificationModalConnector.js create mode 100644 frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.css create mode 100644 frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.js create mode 100644 frontend/src/Settings/Notifications/Notifications/EditNotificationModalContentConnector.js create mode 100644 frontend/src/Settings/Notifications/Notifications/Notification.css create mode 100644 frontend/src/Settings/Notifications/Notifications/Notification.js create mode 100644 frontend/src/Settings/Notifications/Notifications/Notifications.css create mode 100644 frontend/src/Settings/Notifications/Notifications/Notifications.js create mode 100644 frontend/src/Settings/Notifications/Notifications/NotificationsConnector.js create mode 100644 frontend/src/Settings/PendingChangesModal.js create mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfile.css create mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfile.js create mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css create mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.js create mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css create mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.js create mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfiles.css create mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfiles.js create mode 100644 frontend/src/Settings/Profiles/Delay/DelayProfilesConnector.js create mode 100644 frontend/src/Settings/Profiles/Delay/EditDelayProfileModal.js create mode 100644 frontend/src/Settings/Profiles/Delay/EditDelayProfileModalConnector.js create mode 100644 frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css create mode 100644 frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js create mode 100644 frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContentConnector.js create mode 100644 frontend/src/Settings/Profiles/Profiles.js create mode 100644 frontend/src/Settings/Profiles/Quality/EditQualityProfileModal.js create mode 100644 frontend/src/Settings/Profiles/Quality/EditQualityProfileModalConnector.js create mode 100644 frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css create mode 100644 frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.js create mode 100644 frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContentConnector.js create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfile.css create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfile.js create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItem.css create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItem.js create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.js create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.js create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.js create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItems.css create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileItems.js create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfileNameConnector.js create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfiles.css create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfiles.js create mode 100644 frontend/src/Settings/Profiles/Quality/QualityProfilesConnector.js create mode 100644 frontend/src/Settings/Quality/Definition/QualityDefinition.css create mode 100644 frontend/src/Settings/Quality/Definition/QualityDefinition.js create mode 100644 frontend/src/Settings/Quality/Definition/QualityDefinitionConnector.js create mode 100644 frontend/src/Settings/Quality/Definition/QualityDefinitions.css create mode 100644 frontend/src/Settings/Quality/Definition/QualityDefinitions.js create mode 100644 frontend/src/Settings/Quality/Definition/QualityDefinitionsConnector.js create mode 100644 frontend/src/Settings/Quality/Quality.js create mode 100644 frontend/src/Settings/Settings.css create mode 100644 frontend/src/Settings/Settings.js create mode 100644 frontend/src/Settings/SettingsToolbar.js create mode 100644 frontend/src/Settings/SettingsToolbarConnector.js create mode 100644 frontend/src/Settings/Tags/Details/TagDetailsDelayProfile.js create mode 100644 frontend/src/Settings/Tags/Details/TagDetailsModal.js create mode 100644 frontend/src/Settings/Tags/Details/TagDetailsModalContent.css create mode 100644 frontend/src/Settings/Tags/Details/TagDetailsModalContent.js create mode 100644 frontend/src/Settings/Tags/Details/TagDetailsModalContentConnector.js create mode 100644 frontend/src/Settings/Tags/Tag.css create mode 100644 frontend/src/Settings/Tags/Tag.js create mode 100644 frontend/src/Settings/Tags/TagConnector.js create mode 100644 frontend/src/Settings/Tags/TagSettings.js create mode 100644 frontend/src/Settings/Tags/Tags.css create mode 100644 frontend/src/Settings/Tags/Tags.js create mode 100644 frontend/src/Settings/Tags/TagsConnector.js create mode 100644 frontend/src/Settings/UI/UISettings.js create mode 100644 frontend/src/Settings/UI/UISettingsConnector.js create mode 100644 frontend/src/Shared/piwikCheck.js create mode 100644 frontend/src/Shims/jquery.js create mode 100644 frontend/src/Store/Actions/Creators/Reducers/createClearReducer.js create mode 100644 frontend/src/Store/Actions/Creators/Reducers/createSetClientSideCollectionFilterReducer.js create mode 100644 frontend/src/Store/Actions/Creators/Reducers/createSetClientSideCollectionSortReducer.js create mode 100644 frontend/src/Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer.js create mode 100644 frontend/src/Store/Actions/Creators/Reducers/createSetSettingValueReducer.js create mode 100644 frontend/src/Store/Actions/Creators/Reducers/createSetTableOptionReducer.js create mode 100644 frontend/src/Store/Actions/Creators/createBatchToggleEpisodeMonitoredHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createFetchHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createFetchSchemaHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createFetchServerSideCollectionHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createHandleActions.js create mode 100644 frontend/src/Store/Actions/Creators/createRemoveItemHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createSaveHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createSaveProviderHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createServerSideCollectionHandlers.js create mode 100644 frontend/src/Store/Actions/Creators/createSetServerSideCollectionFilterHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createSetServerSideCollectionPageHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createSetServerSideCollectionSortHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createTestAllProvidersHandler.js create mode 100644 frontend/src/Store/Actions/Creators/createTestProviderHandler.js create mode 100644 frontend/src/Store/Actions/Settings/delayProfiles.js create mode 100644 frontend/src/Store/Actions/Settings/downloadClientOptions.js create mode 100644 frontend/src/Store/Actions/Settings/downloadClients.js create mode 100644 frontend/src/Store/Actions/Settings/general.js create mode 100644 frontend/src/Store/Actions/Settings/indexerOptions.js create mode 100644 frontend/src/Store/Actions/Settings/indexers.js create mode 100644 frontend/src/Store/Actions/Settings/mediaManagement.js create mode 100644 frontend/src/Store/Actions/Settings/metadata.js create mode 100644 frontend/src/Store/Actions/Settings/naming.js create mode 100644 frontend/src/Store/Actions/Settings/namingExamples.js create mode 100644 frontend/src/Store/Actions/Settings/netImportOptions.js create mode 100644 frontend/src/Store/Actions/Settings/netImports.js create mode 100644 frontend/src/Store/Actions/Settings/notifications.js create mode 100644 frontend/src/Store/Actions/Settings/qualityDefinitions.js create mode 100644 frontend/src/Store/Actions/Settings/qualityProfiles.js create mode 100644 frontend/src/Store/Actions/Settings/remotePathMappings.js create mode 100644 frontend/src/Store/Actions/Settings/restrictions.js create mode 100644 frontend/src/Store/Actions/Settings/ui.js create mode 100644 frontend/src/Store/Actions/actionTypes.js create mode 100644 frontend/src/Store/Actions/addMovieActions.js create mode 100644 frontend/src/Store/Actions/appActions.js create mode 100644 frontend/src/Store/Actions/baseActions.js create mode 100644 frontend/src/Store/Actions/blacklistActions.js create mode 100644 frontend/src/Store/Actions/calendarActions.js create mode 100644 frontend/src/Store/Actions/captchaActions.js create mode 100644 frontend/src/Store/Actions/commandActions.js create mode 100644 frontend/src/Store/Actions/customFilterActions.js create mode 100644 frontend/src/Store/Actions/deviceActions.js create mode 100644 frontend/src/Store/Actions/historyActions.js create mode 100644 frontend/src/Store/Actions/importMovieActions.js create mode 100644 frontend/src/Store/Actions/index.js create mode 100644 frontend/src/Store/Actions/interactiveImportActions.js create mode 100644 frontend/src/Store/Actions/movieActions.js create mode 100644 frontend/src/Store/Actions/movieEditorActions.js create mode 100644 frontend/src/Store/Actions/movieFileActions.js create mode 100644 frontend/src/Store/Actions/movieHistoryActions.js create mode 100644 frontend/src/Store/Actions/movieIndexActions.js create mode 100644 frontend/src/Store/Actions/oAuthActions.js create mode 100644 frontend/src/Store/Actions/organizePreviewActions.js create mode 100644 frontend/src/Store/Actions/pathActions.js create mode 100644 frontend/src/Store/Actions/queueActions.js create mode 100644 frontend/src/Store/Actions/reducers.js create mode 100644 frontend/src/Store/Actions/releaseActions.js create mode 100644 frontend/src/Store/Actions/rootFolderActions.js create mode 100644 frontend/src/Store/Actions/settingsActions.js create mode 100644 frontend/src/Store/Actions/systemActions.js create mode 100644 frontend/src/Store/Actions/tagActions.js create mode 100644 frontend/src/Store/Middleware/createPersistState.js create mode 100644 frontend/src/Store/Middleware/createSentryMiddleware.js create mode 100644 frontend/src/Store/Middleware/middlewares.js create mode 100644 frontend/src/Store/Selectors/createAllMoviesSelector.js create mode 100644 frontend/src/Store/Selectors/createClientSideCollectionSelector.js create mode 100644 frontend/src/Store/Selectors/createCommandExecutingSelector.js create mode 100644 frontend/src/Store/Selectors/createCommandSelector.js create mode 100644 frontend/src/Store/Selectors/createCommandsSelector.js create mode 100644 frontend/src/Store/Selectors/createDimensionsSelector.js create mode 100644 frontend/src/Store/Selectors/createExistingMovieSelector.js create mode 100644 frontend/src/Store/Selectors/createImportMovieItemSelector.js create mode 100644 frontend/src/Store/Selectors/createMovieCountSelector.js create mode 100644 frontend/src/Store/Selectors/createMovieFileSelector.js create mode 100644 frontend/src/Store/Selectors/createMovieSelector.js create mode 100644 frontend/src/Store/Selectors/createProfileInUseSelector.js create mode 100644 frontend/src/Store/Selectors/createProviderSettingsSelector.js create mode 100644 frontend/src/Store/Selectors/createQualityProfileSelector.js create mode 100644 frontend/src/Store/Selectors/createQueueItemSelector.js create mode 100644 frontend/src/Store/Selectors/createSettingsSectionSelector.js create mode 100644 frontend/src/Store/Selectors/createSystemStatusSelector.js create mode 100644 frontend/src/Store/Selectors/createTagDetailsSelector.js create mode 100644 frontend/src/Store/Selectors/createTagsSelector.js create mode 100644 frontend/src/Store/Selectors/createUISettingsSelector.js create mode 100644 frontend/src/Store/Selectors/selectSettings.js create mode 100644 frontend/src/Store/createAppStore.js create mode 100644 frontend/src/Store/scrollPositions.js create mode 100644 frontend/src/Store/thunks.js create mode 100644 frontend/src/Styles/Mixins/cover.css create mode 100644 frontend/src/Styles/Mixins/linkOverlay.css create mode 100644 frontend/src/Styles/Mixins/scroller.css create mode 100644 frontend/src/Styles/Mixins/truncate.css create mode 100644 frontend/src/Styles/Variables/animations.js create mode 100644 frontend/src/Styles/Variables/colors.js create mode 100644 frontend/src/Styles/Variables/dimensions.js create mode 100644 frontend/src/Styles/Variables/fonts.js create mode 100644 frontend/src/Styles/globals.css create mode 100644 frontend/src/Styles/scaffolding.css create mode 100644 frontend/src/System/Backup/BackupRow.css create mode 100644 frontend/src/System/Backup/BackupRow.js create mode 100644 frontend/src/System/Backup/Backups.js create mode 100644 frontend/src/System/Backup/BackupsConnector.js create mode 100644 frontend/src/System/Backup/RestoreBackupModal.js create mode 100644 frontend/src/System/Backup/RestoreBackupModalConnector.js create mode 100644 frontend/src/System/Backup/RestoreBackupModalContent.css create mode 100644 frontend/src/System/Backup/RestoreBackupModalContent.js create mode 100644 frontend/src/System/Backup/RestoreBackupModalContentConnector.js create mode 100644 frontend/src/System/Events/LogsTable.js create mode 100644 frontend/src/System/Events/LogsTableConnector.js create mode 100644 frontend/src/System/Events/LogsTableDetailsModal.css create mode 100644 frontend/src/System/Events/LogsTableDetailsModal.js create mode 100644 frontend/src/System/Events/LogsTableRow.css create mode 100644 frontend/src/System/Events/LogsTableRow.js create mode 100644 frontend/src/System/Logs/Files/LogFiles.js create mode 100644 frontend/src/System/Logs/Files/LogFilesConnector.js create mode 100644 frontend/src/System/Logs/Files/LogFilesTableRow.css create mode 100644 frontend/src/System/Logs/Files/LogFilesTableRow.js create mode 100644 frontend/src/System/Logs/Logs.js create mode 100644 frontend/src/System/Logs/LogsNavMenu.js create mode 100644 frontend/src/System/Logs/Updates/UpdateLogFilesConnector.js create mode 100644 frontend/src/System/Status/About/About.css create mode 100644 frontend/src/System/Status/About/About.js create mode 100644 frontend/src/System/Status/About/AboutConnector.js create mode 100644 frontend/src/System/Status/About/StartTime.js create mode 100644 frontend/src/System/Status/DiskSpace/DiskSpace.css create mode 100644 frontend/src/System/Status/DiskSpace/DiskSpace.js create mode 100644 frontend/src/System/Status/DiskSpace/DiskSpaceConnector.js create mode 100644 frontend/src/System/Status/Health/Health.css create mode 100644 frontend/src/System/Status/Health/Health.js create mode 100644 frontend/src/System/Status/Health/HealthConnector.js create mode 100644 frontend/src/System/Status/Health/HealthStatusConnector.js create mode 100644 frontend/src/System/Status/MoreInfo/MoreInfo.js create mode 100644 frontend/src/System/Status/Status.js create mode 100644 frontend/src/System/Tasks/Queued/QueuedTaskRow.css create mode 100644 frontend/src/System/Tasks/Queued/QueuedTaskRow.js create mode 100644 frontend/src/System/Tasks/Queued/QueuedTaskRowConnector.js create mode 100644 frontend/src/System/Tasks/Queued/QueuedTasks.js create mode 100644 frontend/src/System/Tasks/Queued/QueuedTasksConnector.js create mode 100644 frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.css create mode 100644 frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.js create mode 100644 frontend/src/System/Tasks/Scheduled/ScheduledTaskRowConnector.js create mode 100644 frontend/src/System/Tasks/Scheduled/ScheduledTasks.js create mode 100644 frontend/src/System/Tasks/Scheduled/ScheduledTasksConnector.js create mode 100644 frontend/src/System/Tasks/Tasks.js create mode 100644 frontend/src/System/Updates/UpdateChanges.css create mode 100644 frontend/src/System/Updates/UpdateChanges.js create mode 100644 frontend/src/System/Updates/Updates.css create mode 100644 frontend/src/System/Updates/Updates.js create mode 100644 frontend/src/System/Updates/UpdatesConnector.js create mode 100644 frontend/src/Utilities/Array/getIndexOfFirstCharacter.js create mode 100644 frontend/src/Utilities/Array/sortByName.js create mode 100644 frontend/src/Utilities/Command/findCommand.js create mode 100644 frontend/src/Utilities/Command/index.js create mode 100644 frontend/src/Utilities/Command/isCommandComplete.js create mode 100644 frontend/src/Utilities/Command/isCommandExecuting.js create mode 100644 frontend/src/Utilities/Command/isCommandFailed.js create mode 100644 frontend/src/Utilities/Command/isSameCommand.js create mode 100644 frontend/src/Utilities/Constants/keyCodes.js create mode 100644 frontend/src/Utilities/Date/dateFilterPredicate.js create mode 100644 frontend/src/Utilities/Date/formatDate.js create mode 100644 frontend/src/Utilities/Date/formatDateTime.js create mode 100644 frontend/src/Utilities/Date/formatTime.js create mode 100644 frontend/src/Utilities/Date/formatTimeSpan.js create mode 100644 frontend/src/Utilities/Date/getRelativeDate.js create mode 100644 frontend/src/Utilities/Date/isAfter.js create mode 100644 frontend/src/Utilities/Date/isBefore.js create mode 100644 frontend/src/Utilities/Date/isInNextWeek.js create mode 100644 frontend/src/Utilities/Date/isSameWeek.js create mode 100644 frontend/src/Utilities/Date/isToday.js create mode 100644 frontend/src/Utilities/Date/isTomorrow.js create mode 100644 frontend/src/Utilities/Date/isYesterday.js create mode 100644 frontend/src/Utilities/Episode/updateEpisodes.js create mode 100644 frontend/src/Utilities/Filter/findSelectedFilters.js create mode 100644 frontend/src/Utilities/Filter/getFilterValue.js create mode 100644 frontend/src/Utilities/Movie/getNewMovie.js create mode 100644 frontend/src/Utilities/Movie/getProgressBarKind.js create mode 100644 frontend/src/Utilities/Number/convertToBytes.js create mode 100644 frontend/src/Utilities/Number/formatAge.js create mode 100644 frontend/src/Utilities/Number/formatBytes.js create mode 100644 frontend/src/Utilities/Number/padNumber.js create mode 100644 frontend/src/Utilities/Number/roundNumber.js create mode 100644 frontend/src/Utilities/Object/getErrorMessage.js create mode 100644 frontend/src/Utilities/Object/hasDifferentItems.js create mode 100644 frontend/src/Utilities/Object/selectUniqueIds.js create mode 100644 frontend/src/Utilities/Quality/getQualities.js create mode 100644 frontend/src/Utilities/ResolutionUtility.js create mode 100644 frontend/src/Utilities/State/getProviderState.js create mode 100644 frontend/src/Utilities/State/getSectionState.js create mode 100644 frontend/src/Utilities/State/selectProviderSchema.js create mode 100644 frontend/src/Utilities/State/updateSectionState.js create mode 100644 frontend/src/Utilities/String/combinePath.js create mode 100644 frontend/src/Utilities/String/generateUUIDv4.js create mode 100644 frontend/src/Utilities/String/isString.js create mode 100644 frontend/src/Utilities/String/parseUrl.js create mode 100644 frontend/src/Utilities/String/split.js create mode 100644 frontend/src/Utilities/String/titleCase.js create mode 100644 frontend/src/Utilities/Table/areAllSelected.js create mode 100644 frontend/src/Utilities/Table/getSelectedIds.js create mode 100644 frontend/src/Utilities/Table/getToggledRange.js create mode 100644 frontend/src/Utilities/Table/removeOldSelectedState.js create mode 100644 frontend/src/Utilities/Table/selectAll.js create mode 100644 frontend/src/Utilities/Table/toggleSelected.js create mode 100644 frontend/src/Utilities/createAjaxRequest.js create mode 100644 frontend/src/Utilities/getPathWithUrlBase.js create mode 100644 frontend/src/Utilities/getUniqueElementId.js create mode 100644 frontend/src/Utilities/isMobile.js create mode 100644 frontend/src/Utilities/pagePopulator.js create mode 100644 frontend/src/Utilities/pages.js create mode 100644 frontend/src/Utilities/requestAction.js create mode 100644 frontend/src/Utilities/sectionTypes.js create mode 100644 frontend/src/Utilities/serverSideCollectionHandlers.js create mode 100644 frontend/src/index.css create mode 100644 frontend/src/index.html create mode 100644 frontend/src/index.js create mode 100644 frontend/src/jQuery/jquery.ajax.js create mode 100644 frontend/src/login.html create mode 100644 frontend/src/oauth.html create mode 100644 frontend/src/polyfills.js create mode 100644 frontend/src/preload.js create mode 100644 frontend/src/vendor.js diff --git a/frontend/.csscomb.json b/frontend/.csscomb.json new file mode 100644 index 000000000..a82e49732 --- /dev/null +++ b/frontend/.csscomb.json @@ -0,0 +1,25 @@ +{ + "remove-empty-rulesets": true, + "always-semicolon": true, + "color-case": "lower", + "block-indent": " ", + "color-shorthand": false, + "element-case": "lower", + "eof-newline": true, + "leading-zero": true, + "quotes": "double", + "sort-order-fallback": "abc", + "space-before-colon": "", + "space-after-colon": " ", + "space-before-combinator": " ", + "space-after-combinator": " ", + "space-between-declarations": "\n", + "space-before-opening-brace": " ", + "space-after-opening-brace": "\n", + "space-after-selector-delimiter": " ", + "space-before-selector-delimiter": "", + "space-before-closing-brace": "\n", + "strip-spaces": true, + "tab-size": true, + "unitless-zero": false +} diff --git a/frontend/.esformatter b/frontend/.esformatter new file mode 100644 index 000000000..600bb0751 --- /dev/null +++ b/frontend/.esformatter @@ -0,0 +1,335 @@ +{ + "indent": { + "value": " ", + "FunctionExpression": 1, + "ArrayExpression": 1, + "ObjectExpression": 1 + }, + "lineBreak": { + "value": "\n", + + "before": { + "ArrayPatternClosing": 0, + "ArrayPatternComma": 0, + "ArrayPatternOpening": 0, + "ArrowFunctionExpressionArrow": 0, + "ArrowFunctionExpressionClosingBrace": ">=1", + "ArrowFunctionExpressionOpeningBrace": 0, + "AssignmentExpression": ">=1", + "AssignmentOperator": 0, + "BlockStatement": 0, + "BreakKeyword": ">=1", + "CallExpression": -1, + "CallExpressionClosingParentheses": -1, + "CallExpressionOpeningParentheses": 0, + "CatchClosingBrace": ">=1", + "CatchKeyword": 0, + "CatchOpeningBrace": 0, + "ClassDeclaration": ">=1", + "ClassDeclarationClosingBrace": ">=1", + "ClassDeclarationOpeningBrace": 0, + "ConditionalExpression": ">=1", + "DeleteOperator": ">=1", + "DoWhileStatement": ">=1", + "DoWhileStatementClosingBrace": ">=1", + "DoWhileStatementOpeningBrace": 0, + "ElseIfStatement": 0, + "ElseIfStatementClosingBrace": ">=1", + "ElseIfStatementOpeningBrace": 0, + "ElseStatement": 0, + "ElseStatementClosingBrace": ">=1", + "ElseStatementOpeningBrace": 0, + "EmptyStatement": -1, + "EndOfFile": -1, + "FinallyClosingBrace": ">=1", + "FinallyKeyword": -1, + "FinallyOpeningBrace": 0, + "ForInStatement": ">=1", + "ForInStatementClosingBrace": ">=1", + "ForInStatementExpressionClosing": 0, + "ForInStatementExpressionOpening": 0, + "ForInStatementOpeningBrace": 0, + "ForStatement": ">=1", + "ForStatementClosingBrace": ">=1", + "ForStatementExpressionClosing": "<2", + "ForStatementExpressionOpening": 0, + "ForStatementOpeningBrace": 0, + "FunctionDeclaration": ">=1", + "FunctionDeclarationClosingBrace": ">=1", + "FunctionDeclarationOpeningBrace": 0, + "FunctionExpression": 0, + "FunctionExpressionClosingBrace": 1, + "FunctionExpressionOpeningBrace":0, + "IIFEClosingParentheses": 0, + "IfStatement": ">=1", + "IfStatementClosingBrace": ">=1", + "IfStatementOpeningBrace": 0, + "LogicalExpression": -1, + "MemberExpressionClosing": 0, + "MemberExpressionOpening": 0, + "MemberExpressionPeriod": -1, + "MethodDefinition": ">=1", + "ObjectExpressionClosingBrace": "<=1", + "ObjectPatternClosingBrace": 0, + "ObjectPatternComma": 0, + "ObjectPatternOpeningBrace": 0, + "ParameterDefault": 0, + "Property": "<=2", + "PropertyValue": 0, + "ReturnStatement": -1, + "SwitchClosingBrace": ">=1", + "SwitchOpeningBrace": 0, + "ThisExpression": -1, + "ThrowStatement": ">=1", + "TryClosingBrace": ">=1", + "TryKeyword": -1, + "TryOpeningBrace": 0, + "VariableDeclaration": ">=1", + "VariableDeclarationSemiColon": 0, + "VariableDeclarationWithoutInit": ">=1", + "VariableName": ">=1", + "VariableValue": 0, + "WhileStatement": ">=1", + "WhileStatementClosingBrace": ">=1", + "WhileStatementOpeningBrace": 0 + }, + + "after": { + "ArrayPatternClosing": 0, + "ArrayPatternComma": 0, + "ArrayPatternOpening": 0, + "ArrowFunctionExpressionArrow": 0, + "ArrowFunctionExpressionClosingBrace": -1, + "ArrowFunctionExpressionOpeningBrace": ">=1", + "AssignmentExpression": ">=1", + "AssignmentOperator": 0, + "BlockStatement": 0, + "BreakKeyword": -1, + "CallExpression": -1, + "CallExpressionClosingParentheses": -1, + "CallExpressionOpeningParentheses": -1, + "CatchClosingBrace": ">=0", + "CatchKeyword": 0, + "CatchOpeningBrace": ">=1", + "ClassDeclaration": ">=1", + "ClassDeclarationClosingBrace": ">=1", + "ClassDeclarationOpeningBrace": ">=1", + "ConditionalExpression": ">=1", + "DeleteOperator": ">=1", + "DoWhileStatement": ">=1", + "DoWhileStatementClosingBrace": 0, + "DoWhileStatementOpeningBrace": ">=1", + "ElseIfStatement": ">=1", + "ElseIfStatementClosingBrace": ">=1", + "ElseIfStatementOpeningBrace": ">=1", + "ElseStatement": ">=1", + "ElseStatementClosingBrace": ">=1", + "ElseStatementOpeningBrace": ">=1", + "EmptyStatement": -1, + "FinallyClosingBrace": ">=1", + "FinallyKeyword": -1, + "FinallyOpeningBrace": ">=1", + "ForInStatement": ">=1", + "ForInStatementClosingBrace": ">=1", + "ForInStatementExpressionClosing": -1, + "ForInStatementExpressionOpening": "<2", + "ForInStatementOpeningBrace": ">=1", + "ForStatement": ">=1", + "ForStatementClosingBrace": ">=1", + "ForStatementExpressionClosing": -1, + "ForStatementExpressionOpening": "<2", + "ForStatementOpeningBrace": ">=1", + "FunctionDeclaration": ">=1", + "FunctionDeclarationClosingBrace": ">=1", + "FunctionDeclarationOpeningBrace": ">=1", + "FunctionExpression": 0, + "FunctionExpressionClosingBrace": -1, + "FunctionExpressionOpeningBrace": 1, + "IIFEOpeningParentheses": 0, + "IfStatement": ">=1", + "IfStatementClosingBrace": ">=1", + "IfStatementOpeningBrace": ">=1", + "LogicalExpression": -1, + "MemberExpressionClosing": 0, + "MemberExpressionOpening": 0, + "MemberExpressionPeriod": 0, + "MethodDefinition": ">=1", + "ObjectExpressionOpeningBrace": "<=1", + "ObjectPatternClosingBrace": 0, + "ObjectPatternComma": 0, + "ObjectPatternOpeningBrace": 0, + "ParameterDefault": 0, + "Property": -1, + "PropertyName": 0, + "ReturnStatement": -1, + "SwitchCaseColon": ">=1", + "SwitchClosingBrace": ">=1", + "SwitchOpeningBrace": ">=1", + "ThisExpression": 0, + "ThrowStatement": ">=1", + "TryClosingBrace": 0, + "TryKeyword": -1, + "TryOpeningBrace": ">=1", + "VariableDeclaration": ">=1", + "VariableDeclarationSemiColon": ">=1", + "VariableValue": -1, + "WhileStatement": ">=1", + "WhileStatementClosingBrace": ">=1", + "WhileStatementOpeningBrace": ">=1" + } + }, + "whiteSpace": { + "value": " ", + "removeTrailing": 1, + "before": { + "ArgumentComma": 0, + "ArgumentList": 0, + "ArgumentListArrayExpression": 0, + "ArgumentListFunctionExpression": 1, + "ArgumentListObjectExpression": 0, + "ArrayExpressionClosing": 0, + "ArrayExpressionComma": 0, + "ArrayExpressionOpening": 1, + "AssignmentOperator": 1, + "BinaryExpression": 0, + "BinaryExpressionOperator": 1, + "BlockComment": 1, + "CallExpression": 1, + "CatchClosingBrace": 1, + "CatchKeyword": 1, + "CatchOpeningBrace": 1, + "CatchParameterList": 0, + "CommaOperator": 0, + "ConditionalExpressionAlternate": 1, + "ConditionalExpressionConsequent": 1, + "DoWhileStatementClosingBrace": 1, + "DoWhileStatementConditional": 1, + "DoWhileStatementOpeningBrace": 1, + "ElseIfStatementClosingBrace": 1, + "ElseIfStatementOpeningBrace": 1, + "ElseStatementClosingBrace": 1, + "ElseStatementOpeningBrace": 1, + "EmptyStatement": 0, + "ExpressionClosingParentheses": 0, + "FinallyClosingBrace": 1, + "FinallyKeyword": -1, + "FinallyOpeningBrace": 1, + "ForInStatement": 1, + "ForInStatementClosingBrace": 1, + "ForInStatementExpressionClosing": 0, + "ForInStatementExpressionOpening": 1, + "ForInStatementOpeningBrace": 1, + "ForStatement": 1, + "ForStatementClosingBrace": 1, + "ForStatementExpressionClosing": 0, + "ForStatementExpressionOpening": 1, + "ForStatementOpeningBrace": 1, + "ForStatementSemicolon": 0, + "FunctionDeclarationClosingBrace": 1, + "FunctionDeclarationOpeningBrace": 1, + "FunctionExpressionClosingBrace": 1, + "FunctionExpressionOpeningBrace": 1, + "IfStatementClosingBrace": 1, + "IfStatementConditionalClosing": 0, + "IfStatementConditionalOpening": 1, + "IfStatementOpeningBrace": 1, + "LineComment": 1, + "LogicalExpressionOperator": 1, + "MemberExpressionClosing": 0, + "ObjectExpressionClosingBrace": 1, + "ParameterComma": 0, + "ParameterList": 0, + "Property": 1, + "PropertyName": 1, + "PropertyValue": 1, + "SwitchDiscriminantClosing": 0, + "SwitchDiscriminantOpening": 1, + "ThrowKeyword": 1, + "TryClosingBrace": 1, + "TryKeyword": -1, + "TryOpeningBrace": 1, + "UnaryExpressionOperator": 0, + "VariableName": 1, + "VariableValue": 1, + "WhileStatementClosingBrace": 1, + "WhileStatementConditionalClosing": 0, + "WhileStatementConditionalOpening": 1, + "WhileStatementOpeningBrace": 1 + }, + "after": { + "ArgumentComma": 1, + "ArgumentList": 0, + "ArgumentListArrayExpression": 1, + "ArgumentListFunctionExpression": 1, + "ArgumentListObjectExpression": 0, + "ArrayExpressionClosing": 0, + "ArrayExpressionComma": 1, + "ArrayExpressionOpening": 0, + "AssignmentOperator": 1, + "BinaryExpression": 0, + "BinaryExpressionOperator": 1, + "BlockComment": 1, + "CallExpression": 0, + "CatchClosingBrace": 1, + "CatchKeyword": 1, + "CatchOpeningBrace": 1, + "CatchParameterList": 0, + "CommaOperator": 1, + "ConditionalExpressionConsequent": 1, + "ConditionalExpressionTest": 1, + "DoWhileStatementBody": 1, + "DoWhileStatementClosingBrace": 1, + "DoWhileStatementOpeningBrace": 1, + "ElseIfStatementClosingBrace": 1, + "ElseIfStatementOpeningBrace": 1, + "ElseStatementClosingBrace": 1, + "ElseStatementOpeningBrace": 1, + "EmptyStatement": 0, + "ExpressionOpeningParentheses": 0, + "FinallyClosingBrace": 1, + "FinallyKeyword": -1, + "FinallyOpeningBrace": 1, + "ForInStatement": 1, + "ForInStatementClosingBrace": 1, + "ForInStatementExpressionClosing": 1, + "ForInStatementExpressionOpening": 0, + "ForInStatementOpeningBrace": 1, + "ForStatement": 1, + "ForStatementClosingBrace": 1, + "ForStatementExpressionClosing": 1, + "ForStatementExpressionOpening": 0, + "ForStatementOpeningBrace": 1, + "ForStatementSemicolon": 1, + "FunctionDeclarationClosingBrace": 0, + "FunctionDeclarationOpeningBrace": 0, + "FunctionExpressionClosingBrace": 0, + "FunctionExpressionOpeningBrace": 0, + "FunctionName": 0, + "FunctionReservedWord": 0, + "IfStatementClosingBrace": 1, + "IfStatementConditionalClosing": 0, + "IfStatementConditionalOpening": 0, + "IfStatementOpeningBrace": 1, + "LogicalExpressionOperator": 1, + "MemberExpressionOpening": 0, + "ObjectExpressionClosingBrace": 0, + "ObjectExpressionOpeningBrace": 1, + "ParameterComma": 1, + "ParameterList": 0, + "PropertyName": 0, + "PropertyValue": 0, + "SwitchDiscriminantClosing": 1, + "SwitchDiscriminantOpening": 0, + "ThrowKeyword": 1, + "TryClosingBrace": 1, + "TryKeyword": -1, + "TryOpeningBrace": 1, + "UnaryExpressionOperator": 0, + "VariableName": 1, + "WhileStatementClosingBrace": 1, + "WhileStatementConditionalClosing": 1, + "WhileStatementConditionalOpening": 0, + "WhileStatementOpeningBrace": 1 + } + } +} diff --git a/frontend/.eslintignore b/frontend/.eslintignore new file mode 100644 index 000000000..d4b43f836 --- /dev/null +++ b/frontend/.eslintignore @@ -0,0 +1 @@ +**/JsLibraries/** diff --git a/frontend/.eslintrc b/frontend/.eslintrc new file mode 100644 index 000000000..31b1173ec --- /dev/null +++ b/frontend/.eslintrc @@ -0,0 +1,288 @@ +{ + "parser": "babel-eslint", + + "env": { + "browser": true, + "commonjs": true, + "node": true, + "es6": true + }, + + "globals": { + "expect": false, + "chai": false, + "sinon": false + }, + + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module", + "ecmaFeatures": { + "modules": true, + "impliedStrict": true + } + }, + + "plugins": [ + "filenames", + "react" + ], + + "rules": { + "filenames/match-exported": ["error"], + + # ECMAScript 6 + + "arrow-body-style": [0], + "arrow-parens": ["error", "always"], + "arrow-spacing": ["error", { "before": true, "after": true }], + "constructor-super": "error", + "generator-star-spacing": "off", + "no-class-assign": "error", + "no-confusing-arrow": "error", + "no-const-assign": "error", + "no-dupe-class-members": "error", + "no-duplicate-imports": "error", + "no-new-symbol": "error", + "no-this-before-super": "error", + "no-useless-escape": "error", + "no-useless-computed-key": "error", + "no-useless-constructor": "error", + "no-var": "warn", + "object-shorthand": ["error", "properties"], + "prefer-arrow-callback": "error", + "prefer-const": "warn", + "prefer-reflect": "off", + "prefer-rest-params": "off", + "prefer-spread": "warn", + "prefer-template": "error", + "require-yield": "off", + "template-curly-spacing": ["error", "never"], + "yield-star-spacing": "off", + + # Possible Errors + + "comma-dangle": "error", + "no-cond-assign": "error", + "no-console": "off", + "no-constant-condition": "warn", + "no-control-regex": "error", + "no-debugger": "off", + "no-dupe-args": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-empty": "warn", + "no-empty-character-class": "error", + "no-ex-assign": "error", + "no-extra-boolean-cast": "error", + "no-extra-parens": ["error", "functions"], + "no-extra-semi": "error", + "no-func-assign": "error", + "no-inner-declarations": "error", + "no-invalid-regexp": "error", + "no-irregular-whitespace": "error", + "no-negated-in-lhs": "error", + "no-obj-calls": "error", + "no-regex-spaces": "error", + "no-sparse-arrays": "error", + "no-unexpected-multiline": "error", + "no-unreachable": "warn", + "no-unsafe-finally": "error", + "use-isnan": "error", + "valid-jsdoc": "off", + "valid-typeof": "error", + + # Best Practices + + "accessor-pairs": "off", + "array-callback-return": "warn", + "block-scoped-var": "warn", + "consistent-return": "off", + "curly": "error", + "default-case": "error", + "dot-location": ["error", "property"], + "dot-notation": "error", + "eqeqeq": ["error", "smart"], + "guard-for-in": "error", + "no-alert": "warn", + "no-caller": "error", + "no-case-declarations": "error", + "no-div-regex": "error", + "no-else-return": "error", + "no-empty-function": ["error", {"allow": ["arrowFunctions"]}], + "no-empty-pattern": "error", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-fallthrough": "error", + "no-floating-decimal": "error", + "no-implicit-coercion": ["error", { + "boolean": false, + "number": true, + "string": true, + "allow": [/* "!!", "~", "*", "+" */] + }], + "no-implicit-globals": "error", + "no-implied-eval": "error", + "no-invalid-this": "off", + "no-iterator": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-magic-numbers": ["off", {"ignoreArrayIndexes": true, "ignore": [0, 1] }], + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-native-reassign": ["error", {"exceptions": ["console"]}], + "no-new": "off", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-octal": "error", + "no-octal-escape": "error", + "no-param-reassign": "off", + "no-process-env": "off", + "no-proto": "error", + "no-redeclare": "error", + "no-return-assign": "warn", + "no-script-url": "error", + "no-self-assign": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-throw-literal": "error", + "no-unmodified-loop-condition": "error", + "no-unused-expressions": "error", + "no-unused-labels": "error", + "no-useless-call": "error", + "no-useless-concat": "error", + "no-void": "error", + "no-warning-comments": "off", + "no-with": "error", + "radix": ["error", "as-needed"], + "vars-on-top": "off", + "wrap-iife": ["error", "inside"], + "yoda": "error", + + # Strict Mode + + "strict": ["error", "never"], + + # Variables + + "init-declarations": ["error", "always"], + "no-catch-shadow": "error", + "no-delete-var": "error", + "no-label-var": "error", + "no-restricted-globals": "off", + "no-shadow": "error", + "no-shadow-restricted-names": "error", + "no-undef": "error", + "no-undef-init": "off", + "no-undefined": "off", + "no-unused-vars": ["error", { "args": "none", "ignoreRestSiblings": true }], + "no-use-before-define": "error", + + # Node.js and CommonJS + + "callback-return": "warn", + "global-require": "error", + "handle-callback-err": "warn", + "no-mixed-requires": "error", + "no-new-require": "error", + "no-path-concat": "error", + "no-process-exit": "error", + + # Stylistic Issues + + "array-bracket-spacing": ["error", "never"], + "block-spacing": ["error", "always"], + "brace-style": ["error", "1tbs", { "allowSingleLine": false }], + "camelcase": "off", + "comma-spacing": ["error", {"before": false, "after": true}], + "comma-style": ["error", "last"], + "computed-property-spacing": ["error", "never"], + "consistent-this": ["error", "self"], + "eol-last": "error", + "func-names": "off", + "func-style": ["error", "declaration"], + "indent": ["error", 2, {"SwitchCase": 1}], + "key-spacing": ["error", {"beforeColon": false, "afterColon": true}], + "keyword-spacing": ["error", { "before": true, "after": true}], + "lines-around-comment": ["error", { "beforeBlockComment": true, "afterBlockComment": false }], + "max-depth": ["error", {"maximum": 5}], + "max-nested-callbacks": ["error", 4], + "max-params": ["error", 6], + "max-statements": "off", + "max-statements-per-line": ["error", { "max": 1 }], + "new-cap": ["error", {"capIsNewExceptions": ["$.Deferred", "DragDropContext", "DragLayer", "DragSource", "DropTarget"]}], + "new-parens": "error", + "newline-after-var": "off", + "newline-before-return": "off", + "newline-per-chained-call": "off", + "no-array-constructor": "error", + "no-bitwise": "error", + "no-continue": "error", + "no-inline-comments": "off", + "no-lonely-if": "warn", + "no-mixed-spaces-and-tabs": "error", + "no-multiple-empty-lines": ["error", { "max": 1 }], + "no-negated-condition": "warn", + "no-nested-ternary": "error", + "no-new-object": "error", + "no-plusplus": "off", + "no-restricted-syntax": "off", + "no-spaced-func": "error", + "no-ternary": "off", + "no-trailing-spaces": "error", + "no-underscore-dangle": ["error", { "allowAfterThis": true }], + "no-unneeded-ternary": "error", + "no-whitespace-before-property": "error", + "object-curly-spacing": ["error", "always"], + "one-var": ["error", "never"], + "one-var-declaration-per-line": ["error", "always"], + "operator-assignment": ["off", "never"], + "operator-linebreak": ["error", "after"], + "quote-props": ["error", "as-needed"], + "quotes": ["error", "single"], + "require-jsdoc": "off", + "semi": "error", + "semi-spacing": ["error", { "before": false, "after": true }], + "sort-vars": "off", + "space-before-blocks": ["error", "always"], + "space-before-function-paren": ["error", "never"], + "space-in-parens": "off", + "space-infix-ops": "off", + "space-unary-ops": "off", + "spaced-comment": "error", + "wrap-regex": "error", + + # React + + "react/jsx-boolean-value": [2, "always"], + "react/jsx-uses-vars": 2, + "react/jsx-closing-bracket-location": 2, + "react/jsx-tag-spacing": ["error"], + "react/jsx-curly-spacing": [2, "never"], + "react/jsx-equals-spacing": [2, "never"], + "react/jsx-indent-props": [2, 2], + "react/jsx-indent": [2, 2], + "react/jsx-key": 2, + "react/jsx-no-bind": [2, { "allowArrowFunctions": true }], + "react/jsx-no-duplicate-props": [2, { "ignoreCase": true }], + "react/jsx-max-props-per-line": [2, { "maximum": 2 }], + "react/jsx-handler-names": [2, { "eventHandlerPrefix": "(on|dispatch)", "eventHandlerPropPrefix": "on" }], + "react/jsx-no-undef": 2, + "react/jsx-pascal-case": 2, + "react/jsx-uses-react": 2, + // Explicitly disabled in case we want to enable them again + "react/no-did-mount-set-state": 0, + "react/no-did-update-set-state": 0, + "react/no-direct-mutation-state": 2, + "react/no-multi-comp": [2, { "ignoreStateless": true }], + "react/no-unknown-property": 2, + "react/prefer-es6-class": 2, + "react/prop-types": 2, + "react/react-in-jsx-scope": 2, + "react/self-closing-comp": 2, + "react/sort-comp": 2, + "react/jsx-wrap-multilines": 2 + } +} diff --git a/frontend/.jsbeautifyrc b/frontend/.jsbeautifyrc new file mode 100644 index 000000000..50aa6aa29 --- /dev/null +++ b/frontend/.jsbeautifyrc @@ -0,0 +1,12 @@ +{ + "js": { + "indent_size": 2, + "indent_char": " ", + "indent_level": 2, + "indent_with_tabs": false, + "preserve_newlines": true, + "brace_style": "collapse", + "max_preserve_newlines": 2, + "jslint_happy": true + } +} \ No newline at end of file diff --git a/frontend/.stylelintrc b/frontend/.stylelintrc new file mode 100644 index 000000000..5587e5d4d --- /dev/null +++ b/frontend/.stylelintrc @@ -0,0 +1,396 @@ +{ +"plugins": [ + "stylelint-order" +], +"ignoreFiles": [ + "frontend/src/Styles/scaffolding.css", + "**/*.js" +], +"rules": { + "at-rule-empty-line-before": [ + "always", + { + "except": [ + "inside-block" + ] + } + ], + "at-rule-name-case": "lower", + "at-rule-name-newline-after": "always-multi-line", + "at-rule-name-space-after": "always", + "at-rule-no-unknown": [ + true, + { + "ignoreAtRules": [ + "/^add\\-mixin$/", + "/^define\\-mixin$/" + ] + } + ], + "at-rule-no-vendor-prefix": true, + "at-rule-semicolon-newline-after": "always", + "at-rule-semicolon-space-before": "never", + "block-closing-brace-empty-line-before": "never", + "block-closing-brace-newline-after": "always", + "block-closing-brace-newline-before": "always", + "block-closing-brace-space-after": "always-single-line", + "block-closing-brace-space-before": "always-single-line", + "block-no-empty": true, + "block-opening-brace-newline-after": "always", + "block-opening-brace-newline-before": "never-single-line", + "block-opening-brace-space-after": "always-single-line", + "block-opening-brace-space-before": "always", + "color-hex-case": "lower", + "color-hex-length": "short", + "color-named": "never", + "color-no-invalid-hex": true, + "comment-whitespace-inside": "always", + "declaration-bang-space-after": "never", + "declaration-bang-space-before": "always", + "declaration-block-no-duplicate-properties": [ + true, + { + "ignoreProperties": [ + "composes" + ] + } + ], + "declaration-block-no-redundant-longhand-properties": true, + "declaration-block-no-shorthand-property-overrides": true, + "declaration-block-semicolon-newline-after": "always", + "declaration-block-semicolon-newline-before": "never-multi-line", + "declaration-block-semicolon-space-before": "never", + "declaration-block-single-line-max-declarations": 1, + "declaration-block-trailing-semicolon": "always", + "declaration-colon-space-after": "always", + "declaration-colon-space-before": "never", + "font-family-name-quotes": "always-unless-keyword", + "function-calc-no-unspaced-operator": true, + "function-comma-newline-after": "never-multi-line", + "function-comma-newline-before": "never-multi-line", + "function-comma-space-after": "always", + "function-comma-space-before": "never", + "function-linear-gradient-no-nonstandard-direction": true, + "function-name-case": "lower", + "function-parentheses-newline-inside": "never-multi-line", + "function-parentheses-space-inside": "never", + "function-url-quotes": "always", + "function-url-scheme-blacklist": [ + "data" + ], + "function-whitespace-after": "always", + "indentation": 2, + "keyframe-declaration-no-important": true, + "length-zero-no-unit": true, + "max-empty-lines": 1, + "max-line-length": [ + 100, + { + "ignore": [ + "non-comments" + ] + } + ], + "max-nesting-depth": 2, + "media-feature-colon-space-after": "always", + "media-feature-colon-space-before": "never", + "media-feature-name-case": "lower", + "media-feature-name-no-vendor-prefix": true, + "media-feature-range-operator-space-after": "always", + "media-feature-range-operator-space-before": "always", + "no-empty-source": true, + "no-eol-whitespace": true, + "no-extra-semicolons": true, + "no-invalid-double-slash-comments": true, + "no-missing-end-of-source-newline": true, + "number-leading-zero": "always", + "number-no-trailing-zeros": true, + "order/order": [ + "custom-properties", + "dollar-variables", + { + "hasBlock": false, + "name": "add-mixin", + "type": "at-rule" + }, + "declarations", + "rules", + "at-rules" + ], + "order/properties-order": [ + { + "emptyLineBefore": "always", + "properties": [ + "composes" + ] + }, + { + "emptyLineBefore": "always", + "properties": [ + "position", + "top", + "right", + "bottom", + "left", + "z-index", + "display", + "visibility", + "align-content", + "align-items", + "align-self", + "justify-content", + "flex", + "flex-direction", + "flex-order", + "flex-pack", + "flex-align", + "flex-grow", + "flex-shrink", + "flex-basis", + "flex-wrap", + "flex-flow", + "float", + "clear", + "overflow", + "overflow-x", + "overflow-y", + "-webkit-overflow-scrolling", + "clip", + "box-sizing", + "margin", + "margin-top", + "margin-right", + "margin-bottom", + "margin-left", + "padding", + "padding-top", + "padding-right", + "padding-bottom", + "padding-left", + "min-width", + "min-height", + "max-width", + "max-height", + "width", + "height", + "outline", + "outline-width", + "outline-style", + "outline-color", + "outline-offset", + "border", + "border-spacing", + "border-collapse", + "border-width", + "border-style", + "border-color", + "border-top", + "border-top-width", + "border-top-style", + "border-top-color", + "border-right", + "border-right-width", + "border-right-style", + "border-right-color", + "border-bottom", + "border-bottom-width", + "border-bottom-style", + "border-bottom-color", + "border-left", + "border-left-width", + "border-left-style", + "border-left-color", + "border-radius", + "border-top-left-radius", + "border-top-right-radius", + "border-bottom-right-radius", + "border-bottom-left-radius", + "border-image", + "border-image-source", + "border-image-slice", + "border-image-width", + "border-image-outset", + "border-image-repeat", + "border-top-image", + "border-right-image", + "border-bottom-image", + "border-left-image", + "border-corner-image", + "border-top-left-image", + "border-top-right-image", + "border-bottom-right-image", + "border-bottom-left-image", + "background", + "background-color", + "background-image", + "background-attachment", + "background-position", + "background-position-x", + "background-position-y", + "background-clip", + "background-origin", + "background-size", + "background-repeat", + "box-decoration-break", + "box-shadow", + "color", + "table-layout", + "caption-side", + "empty-cells", + "list-style", + "list-style-position", + "list-style-type", + "list-style-image", + "quotes", + "content", + "counter-increment", + "counter-reset", + "-ms-writing-mode", + "vertical-align", + "text-align", + "text-align-last", + "text-decoration", + "text-emphasis", + "text-emphasis-position", + "text-emphasis-style", + "text-emphasis-color", + "text-indent", + "text-justify", + "text-outline", + "text-transform", + "text-wrap", + "text-overflow", + "text-overflow-ellipsis", + "text-overflow-mode", + "text-shadow", + "white-space", + "word-spacing", + "word-wrap", + "word-break", + "tab-size", + "hyphens", + "letter-spacing", + "font", + "font-weight", + "font-style", + "font-variant", + "font-size-adjust", + "font-stretch", + "font-size", + "font-family", + "font-smoothing", + "-moz-osx-font-smoothing", + "-webkit-font-smoothing", + "src", + "line-height", + "opacity", + "filter", + "resize", + "cursor", + "appearance", + "nav-index", + "nav-up", + "nav-right", + "nav-down", + "nav-left", + "transition", + "transition-delay", + "transition-timing-function", + "transition-duration", + "transition-property", + "transform", + "transform-origin", + "transform-style", + "backface-visibility", + "animation", + "animation-name", + "animation-duration", + "animation-play-state", + "animation-timing-function", + "animation-delay", + "animation-iteration-count", + "animation-direction", + "animation-fill-mode", + "pointer-events", + "user-select", + "touch-action", + "-webkit-tap-highlight-color", + "unicode-bidi", + "direction", + "columns", + "column-span", + "column-width", + "column-count", + "column-fill", + "column-gap", + "column-rule", + "column-rule-width", + "column-rule-style", + "column-rule-color", + "break-before", + "break-inside", + "break-after", + "page-break-before", + "page-break-inside", + "page-break-after", + "orphans", + "widows", + "zoom", + "max-zoom", + "min-zoom", + "user-zoom", + "orientation" + ] + } + ], + "property-case": "lower", + "property-no-vendor-prefix": true, + "rule-empty-line-before": [ + "always", + { + "except": [ + "first-nested" + ], + "ignore": [ + "after-comment" + ] + } + ], + "selector-attribute-brackets-space-inside": "never", + "selector-attribute-operator-space-after": "never", + "selector-attribute-operator-space-before": "never", + "selector-attribute-quotes": "never", + "selector-class-pattern": "^[A-Za-z0-9]+$", + "selector-combinator-space-after": "always", + "selector-combinator-space-before": "always", + "selector-descendant-combinator-no-non-space": true, + "selector-list-comma-newline-after": "always", + "selector-list-comma-newline-before": "never-multi-line", + "selector-list-comma-space-before": "never", + "selector-max-attribute": 0, + "selector-max-class": 3, + "selector-max-compound-selectors": 3, + "selector-max-empty-lines": 0, + "selector-max-id": 0, + "selector-max-universal": 0, + "selector-pseudo-class-case": "lower", + "selector-pseudo-class-parentheses-space-inside": "never", + "selector-pseudo-element-case": "lower", + "selector-pseudo-element-colon-notation": "double", + "selector-pseudo-element-no-unknown": true, + "selector-type-case": "lower", + "selector-type-no-unknown": true, + "shorthand-property-no-redundant-values": true, + "string-no-newline": true, + "string-quotes": "single", + "time-min-milliseconds": 100, + "unit-case": "lower", + "unit-no-unknown": true, + "value-list-comma-newline-after": "never-multi-line", + "value-list-comma-newline-before": "never-multi-line", + "value-list-comma-space-after": "always", + "value-list-comma-space-before": "never", + "value-list-max-empty-lines": 0, + "value-no-vendor-prefix": true + } +} diff --git a/frontend/.tern-project b/frontend/.tern-project new file mode 100644 index 000000000..aa9d76407 --- /dev/null +++ b/frontend/.tern-project @@ -0,0 +1,7 @@ +{ + "ecmaVersion": 6, + "libs": [ + "browser", + "jquery" + ] +} diff --git a/frontend/gulp/build.js b/frontend/gulp/build.js new file mode 100644 index 000000000..cfeb5d138 --- /dev/null +++ b/frontend/gulp/build.js @@ -0,0 +1,15 @@ +const gulp = require('gulp'); +const runSequence = require('run-sequence'); + +require('./clean'); +require('./copy'); + +gulp.task('build', () => { + return runSequence('clean', [ + 'webpack', + 'copyHtml', + 'copyFonts', + 'copyImages', + 'copyJs' + ]); +}); diff --git a/frontend/gulp/clean.js b/frontend/gulp/clean.js new file mode 100644 index 000000000..ac2e4026f --- /dev/null +++ b/frontend/gulp/clean.js @@ -0,0 +1,8 @@ +const gulp = require('gulp'); +const del = require('del'); + +const paths = require('./helpers/paths'); + +gulp.task('clean', () => { + return del([paths.dest.root]); +}); diff --git a/frontend/gulp/copy.js b/frontend/gulp/copy.js new file mode 100644 index 000000000..5b48eb755 --- /dev/null +++ b/frontend/gulp/copy.js @@ -0,0 +1,45 @@ +var path = require('path'); +var gulp = require('gulp'); +var print = require('gulp-print').default; +var cache = require('gulp-cached'); +var livereload = require('gulp-livereload'); +var paths = require('./helpers/paths.js'); + +gulp.task('copyJs', () => { + return gulp.src( + [ + path.join(paths.src.root, 'polyfills.js') + ]) + .pipe(cache('copyJs')) + .pipe(print()) + .pipe(gulp.dest(paths.dest.root)) + .pipe(livereload()); +}); + +gulp.task('copyHtml', () => { + return gulp.src(paths.src.html) + .pipe(cache('copyHtml')) + .pipe(print()) + .pipe(gulp.dest(paths.dest.root)) + .pipe(livereload()); +}); + +gulp.task('copyFonts', () => { + return gulp.src( + path.join(paths.src.fonts, '**', '*.*') + ) + .pipe(cache('copyFonts')) + .pipe(print()) + .pipe(gulp.dest(paths.dest.fonts)) + .pipe(livereload()); +}); + +gulp.task('copyImages', () => { + return gulp.src( + path.join(paths.src.images, '**', '*.*') + ) + .pipe(cache('copyImages')) + .pipe(print()) + .pipe(gulp.dest(paths.dest.images)) + .pipe(livereload()); +}); diff --git a/frontend/gulp/gulpFile.js b/frontend/gulp/gulpFile.js new file mode 100644 index 000000000..744dd8d7e --- /dev/null +++ b/frontend/gulp/gulpFile.js @@ -0,0 +1,8 @@ +require('./build.js'); +require('./clean.js'); +require('./copy.js'); +require('./imageMin.js'); +require('./start.js'); +require('./stripBom.js'); +require('./watch.js'); +require('./webpack.js'); diff --git a/frontend/gulp/helpers/errorHandler.js b/frontend/gulp/helpers/errorHandler.js new file mode 100644 index 000000000..f3e1c113b --- /dev/null +++ b/frontend/gulp/helpers/errorHandler.js @@ -0,0 +1,6 @@ +const gulpUtil = require('gulp-util'); + +module.exports = function errorHandler(error) { + gulpUtil.log(gulpUtil.colors.red(`Error (${error.plugin}): ${error.message}`)); + this.emit('end'); +}; diff --git a/frontend/gulp/helpers/html-annotate-loader.js b/frontend/gulp/helpers/html-annotate-loader.js new file mode 100644 index 000000000..6c7ce10b8 --- /dev/null +++ b/frontend/gulp/helpers/html-annotate-loader.js @@ -0,0 +1,15 @@ +const path = require('path'); +const rootPath = path.resolve(__dirname + '/../../src/'); +module.exports = function(source) { + if (this.cacheable) { + this.cacheable(); + } + + const resourcePath = this.resourcePath.replace(rootPath, ''); + const wrappedSource =` + + ${source} + `; + + return wrappedSource; +}; diff --git a/frontend/gulp/helpers/paths.js b/frontend/gulp/helpers/paths.js new file mode 100644 index 000000000..b96b5aaeb --- /dev/null +++ b/frontend/gulp/helpers/paths.js @@ -0,0 +1,23 @@ +const root = './frontend/src/'; + +const paths = { + src: { + root, + html: root + '*.html', + scripts: root + '**/*.js', + content: root + 'Content/', + fonts: root + 'Content/Fonts/', + images: root + 'Content/Images/', + exclude: { + libs: `!${root}JsLibraries/**` + } + }, + dest: { + root: './_output/UI/', + content: './_output/UI/Content/', + fonts: './_output/UI/Content/Fonts/', + images: './_output/UI/Content/Images/' + } +}; + +module.exports = paths; diff --git a/frontend/gulp/imageMin.js b/frontend/gulp/imageMin.js new file mode 100644 index 000000000..8988c7ad4 --- /dev/null +++ b/frontend/gulp/imageMin.js @@ -0,0 +1,15 @@ +var gulp = require('gulp'); +var print = require('gulp-print').default; +var paths = require('./helpers/paths.js'); + +gulp.task('imageMin', () => { + var imagemin = require('gulp-imagemin'); + return gulp.src(paths.src.images) + .pipe(imagemin({ + progressive: false, + optimizationLevel: 4, + svgoPlugins: [{ removeViewBox: false }] + })) + .pipe(print()) + .pipe(gulp.dest(paths.src.content + 'Images/')); +}); diff --git a/frontend/gulp/start.js b/frontend/gulp/start.js new file mode 100644 index 000000000..013250194 --- /dev/null +++ b/frontend/gulp/start.js @@ -0,0 +1,104 @@ +// will download and run radarr (server) in a non-windows enviroment +// you can use this if you don't care about the server code and just want to work +// with the web code. + +var http = require('http'); +var gulp = require('gulp'); +var fs = require('fs'); +var targz = require('tar.gz'); +var del = require('del'); +var spawn = require('child_process').spawn; + +function download(url, dest, cb) { + console.log('Downloading ' + url + ' to ' + dest); + var file = fs.createWriteStream(dest); + http.get(url, function(response) { + response.pipe(file); + file.on('finish', function() { + console.log('Download completed'); + file.close(cb); + }); + }); +} + +function getLatest(cb) { + var branch = 'develop'; + process.argv.forEach(function(val) { + var branchMatch = /branch=([\S]*)/.exec(val); + if (branchMatch && branchMatch.length > 1) { + branch = branchMatch[1]; + } + }); + + var url = 'http://radarr.aeonlucid.com/v1/update/' + branch + '?os=osx'; + + console.log('Checking for latest version:', url); + + http.get(url, function(res) { + var data = ''; + + res.on('data', function(chunk) { + data += chunk; + }); + + res.on('end', function() { + var updatePackage = JSON.parse(data).updatePackage; + console.log('Latest version available: ' + updatePackage.version + ' Release Date: ' + updatePackage.releaseDate); + cb(updatePackage); + }); + }).on('error', function(e) { + console.log('problem with request: ' + e.message); + }); +} + +function extract(source, dest, cb) { + console.log('extracting download page to ' + dest); + new targz().extract(source, dest, function(err) { + if (err) { + console.log(err); + } + console.log('Update package extracted.'); + cb(); + }); +} + +gulp.task('getSonarr', function() { + try { + fs.mkdirSync('./_start/'); + } catch (e) { + if (e.code !== 'EEXIST') { + throw e; + } + } + + getLatest(function(updatePackage) { + var packagePath = './_start/' + updatePackage.filename; + var dirName = './_start/' + updatePackage.version; + download(updatePackage.url, packagePath, function() { + extract(packagePath, dirName, function() { + // clean old binaries + console.log('Cleaning old binaries'); + del.sync(['./_output/*', '!./_output/UI/']); + console.log('copying binaries to target'); + gulp.src(dirName + '/NzbDrone/*.*') + .pipe(gulp.dest('./_output/')); + }); + }); + }); +}); + +gulp.task('startSonarr', function() { + var ls = spawn('mono', ['--debug', './_output/Radarr.exe']); + + ls.stdout.on('data', function(data) { + process.stdout.write(data); + }); + + ls.stderr.on('data', function(data) { + process.stdout.write(data); + }); + + ls.on('close', function(code) { + console.log('child process exited with code ' + code); + }); +}); diff --git a/frontend/gulp/stripBom.js b/frontend/gulp/stripBom.js new file mode 100644 index 000000000..080b86dfe --- /dev/null +++ b/frontend/gulp/stripBom.js @@ -0,0 +1,13 @@ +const gulp = require('gulp'); +const paths = require('./helpers/paths.js'); +const stripbom = require('gulp-stripbom'); + +function stripBom(dest) { + gulp.src([paths.src.scripts, paths.src.exclude.libs]) + .pipe(stripbom({ showLog: false })) + .pipe(gulp.dest(dest)); +} + +gulp.task('stripBom', () => { + stripBom(paths.src.root); +}); diff --git a/frontend/gulp/watch.js b/frontend/gulp/watch.js new file mode 100644 index 000000000..ba1a47b66 --- /dev/null +++ b/frontend/gulp/watch.js @@ -0,0 +1,27 @@ +const gulp = require('gulp'); +const livereload = require('gulp-livereload'); +const watch = require('gulp-watch'); +const paths = require('./helpers/paths.js'); + +require('./copy.js'); +require('./webpack.js'); + +function watchTask(glob, task) { + const options = { + name: `watch: ${task}`, + verbose: true + }; + return watch(glob, options, () => { + gulp.start(task); + }); +} + +gulp.task('watch', ['copyHtml', 'copyFonts', 'copyImages', 'copyJs'], () => { + livereload.listen({ start: true }); + + gulp.start('webpackWatch'); + + watchTask(paths.src.html, 'copyHtml'); + watchTask(`${paths.src.fonts}**/*.*`, 'copyFonts'); + watchTask(`${paths.src.images}**/*.*`, 'copyImages'); +}); diff --git a/frontend/gulp/webpack.js b/frontend/gulp/webpack.js new file mode 100644 index 000000000..50aefcc1a --- /dev/null +++ b/frontend/gulp/webpack.js @@ -0,0 +1,212 @@ +const gulp = require('gulp'); +const webpackStream = require('webpack-stream'); +const livereload = require('gulp-livereload'); +const path = require('path'); +const webpack = require('webpack'); +const errorHandler = require('./helpers/errorHandler'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); + +const uiFolder = 'UI'; +const root = path.join(__dirname, '..', 'src'); +const isProduction = process.argv.indexOf('--production') > -1; + +console.log('ROOT:', root); +console.log('isProduction:', isProduction); + +const cssVarsFiles = [ + '../src/Styles/Variables/colors', + '../src/Styles/Variables/dimensions', + '../src/Styles/Variables/fonts', + '../src/Styles/Variables/animations' +].map(require.resolve); + +const extractCSSPlugin = new ExtractTextPlugin({ + filename: path.join('_output', uiFolder, 'Content', 'styles.css'), + allChunks: true, + disable: false, + ignoreOrder: true +}); + +const plugins = [ + extractCSSPlugin, + + new webpack.optimize.CommonsChunkPlugin({ + name: 'vendor' + }), + + new webpack.DefinePlugin({ + __DEV__: !isProduction, + 'process.env.NODE_ENV': isProduction ? JSON.stringify('production') : JSON.stringify('development') + }) +]; + +if (isProduction) { + plugins.push(new UglifyJSPlugin({ + sourceMap: true, + uglifyOptions: { + mangle: false, + output: { + comments: false, + beautify: true + } + } + })); +} + +const config = { + devtool: '#source-map', + + stats: { + children: false + }, + + watchOptions: { + ignored: /node_modules/ + }, + + entry: { + preload: 'preload.js', + vendor: 'vendor.js', + index: 'index.js' + }, + + resolve: { + modules: [ + root, + path.join(root, 'Shims'), + 'node_modules' + ], + alias: { + jquery: 'jquery/src/jquery' + } + }, + + output: { + filename: path.join('_output', uiFolder, '[name].js'), + sourceMapFilename: '[file].map' + }, + + plugins, + + resolveLoader: { + modules: [ + 'node_modules', + 'frontend/gulp/webpack/' + ] + }, + + module: { + rules: [ + { + test: /\.js?$/, + exclude: /(node_modules|JsLibraries)/, + loader: 'babel-loader', + query: { + plugins: ['transform-class-properties'], + presets: ['es2015', 'decorators-legacy', 'react', 'stage-2'], + env: { + development: { + plugins: ['transform-react-jsx-source'] + } + } + } + }, + + // CSS Modules + { + test: /\.css$/, + exclude: /(node_modules|globals.css)/, + use: extractCSSPlugin.extract({ + fallback: 'style-loader', + use: [ + { + loader: 'css-variables-loader', + options: { + cssVarsFiles + } + }, + { + loader: 'css-loader', + options: { + modules: true, + importLoaders: 1, + localIdentName: '[name]-[local]-[hash:base64:5]', + sourceMap: true + } + }, + { + loader: 'postcss-loader', + options: { + config: { + ctx: { + cssVarsFiles + }, + path: 'frontend/postcss.config.js' + } + } + } + ] + }) + }, + + // Global styles + { + test: /\.css$/, + include: /(node_modules|globals.css)/, + use: [ + 'style-loader', + { + loader: 'css-loader' + } + ] + }, + + // Fonts + { + test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, + use: [ + { + loader: 'url-loader', + options: { + limit: 10240, + mimetype: 'application/font-woff', + emitFile: false, + name: 'Content/Fonts/[name].[ext]' + } + } + ] + }, + + { + test: /\.(ttf|eot|eot?#iefix|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, + use: [ + { + loader: 'file-loader', + options: { + emitFile: false, + name: 'Content/Fonts/[name].[ext]' + } + } + ] + } + ] + } +}; + +gulp.task('webpack', () => { + return gulp.src('index.js') + .pipe(webpackStream(config)) + .pipe(gulp.dest('')); +}); + +gulp.task('webpackWatch', () => { + config.watch = true; + return gulp.src('') + .pipe(webpackStream(config)) + .on('error', errorHandler) + .pipe(gulp.dest('')) + .on('error', errorHandler) + .pipe(livereload()) + .on('error', errorHandler); +}); diff --git a/frontend/gulp/webpack/css-variables-loader.js b/frontend/gulp/webpack/css-variables-loader.js new file mode 100644 index 000000000..5683c98be --- /dev/null +++ b/frontend/gulp/webpack/css-variables-loader.js @@ -0,0 +1,11 @@ +const loaderUtils = require('loader-utils'); + +module.exports = function cssVariablesLoader(source) { + const options = loaderUtils.getOptions(this); + + options.cssVarsFiles.forEach((cssVarsFile) => { + this.addDependency(cssVarsFile); + }); + + return source; +}; diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js new file mode 100644 index 000000000..f82554ba8 --- /dev/null +++ b/frontend/postcss.config.js @@ -0,0 +1,33 @@ +const reload = require('require-nocache')(module); + +module.exports = (ctx, configPath, options) => { + const config = { + plugins: { + 'postcss-mixins': { + mixinsDir: [ + 'frontend/src/Styles/Mixins' + ] + }, + 'postcss-simple-vars': { + variables: () => + ctx.options.cssVarsFiles.reduce((acc, vars) => { + return Object.assign(acc, reload(vars)); + }, {}) + }, + 'postcss-nested': {}, + autoprefixer: { + browsers: [ + 'Chrome >= 30', + 'Firefox >= 30', + 'Safari >= 6', + 'Edge >= 12', + 'Explorer >= 11', + 'iOS >= 7', + 'Android >= 4.4' + ] + } + } + }; + + return config; +}; diff --git a/frontend/src/.vscode/settings.json b/frontend/src/.vscode/settings.json new file mode 100644 index 000000000..0fb2bf460 --- /dev/null +++ b/frontend/src/.vscode/settings.json @@ -0,0 +1,4 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.insertFinalNewline": true +} \ No newline at end of file diff --git a/frontend/src/Activity/Blacklist/Blacklist.js b/frontend/src/Activity/Blacklist/Blacklist.js new file mode 100644 index 000000000..d93bec0bf --- /dev/null +++ b/frontend/src/Activity/Blacklist/Blacklist.js @@ -0,0 +1,123 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { align, icons } from 'Helpers/Props'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +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 PageContent from 'Components/Page/PageContent'; +import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector'; +import PageToolbar from 'Components/Page/Toolbar/PageToolbar'; +import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection'; +import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton'; +import BlacklistRowConnector from './BlacklistRowConnector'; + +class Blacklist extends Component { + + // + // Render + + render() { + const { + isFetching, + isPopulated, + error, + items, + columns, + totalRecords, + isClearingBlacklistExecuting, + onClearBlacklistPress, + ...otherProps + } = this.props; + + return ( + + + + + + + + + + + + + + + { + isFetching && !isPopulated && + + } + + { + !isFetching && !!error && +
Unable to load blacklist
+ } + + { + isPopulated && !error && !items.length && +
+ No history blacklist +
+ } + + { + 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, + isClearingBlacklistExecuting: PropTypes.bool.isRequired, + onClearBlacklistPress: PropTypes.func.isRequired +}; + +export default Blacklist; diff --git a/frontend/src/Activity/Blacklist/BlacklistConnector.js b/frontend/src/Activity/Blacklist/BlacklistConnector.js new file mode 100644 index 000000000..b182e7bb2 --- /dev/null +++ b/frontend/src/Activity/Blacklist/BlacklistConnector.js @@ -0,0 +1,154 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; +import withCurrentPage from 'Components/withCurrentPage'; +import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector'; +import * as blacklistActions from 'Store/Actions/blacklistActions'; +import { executeCommand } from 'Store/Actions/commandActions'; +import * as commandNames from 'Commands/commandNames'; +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 }); + } + + 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, + 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 new file mode 100644 index 000000000..356512a9d --- /dev/null +++ b/frontend/src/Activity/Blacklist/BlacklistDetailsModal.js @@ -0,0 +1,89 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Button from 'Components/Link/Button'; +import DescriptionList from 'Components/DescriptionList/DescriptionList'; +import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem'; +import Modal from 'Components/Modal/Modal'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; + +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 new file mode 100644 index 000000000..b62d1e750 --- /dev/null +++ b/frontend/src/Activity/Blacklist/BlacklistRow.css @@ -0,0 +1,18 @@ +.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 new file mode 100644 index 000000000..39d4dbd0a --- /dev/null +++ b/frontend/src/Activity/Blacklist/BlacklistRow.js @@ -0,0 +1,170 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons, kinds } from 'Helpers/Props'; +import IconButton from 'Components/Link/IconButton'; +import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; +import TableRow from 'Components/Table/TableRow'; +import TableRowCell from 'Components/Table/Cells/TableRowCell'; +import MovieQuality from 'Movie/MovieQuality'; +import MovieTitleLink from 'Movie/MovieTitleLink'; +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 { + movie, + sourceTitle, + quality, + date, + protocol, + indexer, + message, + columns, + onRemovePress + } = this.props; + + return ( + + { + columns.map((column) => { + const { + name, + isVisible + } = column; + + if (!isVisible) { + return null; + } + + if (name === 'movie.sortTitle') { + return ( + + + + ); + } + + if (name === 'sourceTitle') { + return ( + + {sourceTitle} + + ); + } + + if (name === 'quality') { + 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, + date: PropTypes.string.isRequired, + protocol: PropTypes.string.isRequired, + indexer: PropTypes.string, + message: PropTypes.string, + columns: PropTypes.arrayOf(PropTypes.object).isRequired, + onRemovePress: PropTypes.func.isRequired +}; + +export default BlacklistRow; diff --git a/frontend/src/Activity/Blacklist/BlacklistRowConnector.js b/frontend/src/Activity/Blacklist/BlacklistRowConnector.js new file mode 100644 index 000000000..275a02464 --- /dev/null +++ b/frontend/src/Activity/Blacklist/BlacklistRowConnector.js @@ -0,0 +1,26 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { removeFromBlacklist } 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(removeFromBlacklist({ id: props.id })); + } + }; +} + +export default connect(createMapStateToProps, createMapDispatchToProps)(BlacklistRow); diff --git a/frontend/src/Activity/History/Details/HistoryDetails.css b/frontend/src/Activity/History/Details/HistoryDetails.css new file mode 100644 index 000000000..03f8fd3ce --- /dev/null +++ b/frontend/src/Activity/History/Details/HistoryDetails.css @@ -0,0 +1,5 @@ +.description { + composes: title from 'Components/DescriptionList/DescriptionListItemDescription.css'; + + overflow-wrap: break-word; +} diff --git a/frontend/src/Activity/History/Details/HistoryDetails.js b/frontend/src/Activity/History/Details/HistoryDetails.js new file mode 100644 index 000000000..6214eeb7e --- /dev/null +++ b/frontend/src/Activity/History/Details/HistoryDetails.js @@ -0,0 +1,244 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import formatDateTime from 'Utilities/Date/formatDateTime'; +import formatAge from 'Utilities/Number/formatAge'; +import Link from 'Components/Link/Link'; +import DescriptionList from 'Components/DescriptionList/DescriptionList'; +import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem'; +import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionListItemTitle'; +import DescriptionListItemDescription from 'Components/DescriptionList/DescriptionListItemDescription'; +import styles from './HistoryDetails.css'; + +function HistoryDetails(props) { + const { + eventType, + sourceTitle, + data, + shortDateFormat, + timeFormat + } = props; + + if (eventType === 'grabbed') { + const { + indexer, + releaseGroup, + nzbInfoUrl, + downloadClient, + downloadId, + age, + ageHours, + ageMinutes, + publishedDate + } = data; + + return ( + + + + { + !!indexer && + + } + + { + !!releaseGroup && + + } + + { + !!nzbInfoUrl && + + + Info URL + + + + {nzbInfoUrl} + + + } + + { + !!downloadClient && + + } + + { + !!downloadId && + + } + + { + !!indexer && + + } + + { + !!publishedDate && + + } + + ); + } + + if (eventType === 'downloadFailed') { + const { + message + } = data; + + return ( + + + + { + !!message && + + } + + ); + } + + if (eventType === 'downloadFolderImported') { + const { + droppedPath, + importedPath + } = data; + + return ( + + + + { + !!droppedPath && + + } + + { + !!importedPath && + + } + + ); + } + + if (eventType === 'episodeFileDeleted') { + const { + reason + } = data; + + let reasonMessage = ''; + + switch (reason) { + case 'Manual': + reasonMessage = 'File was deleted by via UI'; + break; + case 'MissingFromDisk': + reasonMessage = 'Radarr was unable to find the file on disk so it was removed'; + break; + case 'Upgrade': + reasonMessage = 'File was deleted to import an upgrade'; + break; + default: + reasonMessage = ''; + } + + return ( + + + + + + ); + } + + if (eventType === 'episodeFileRenamed') { + const { + sourcePath, + sourceRelativePath, + path, + relativePath + } = data; + + return ( + + + + + + + + + + ); + } +} + +HistoryDetails.propTypes = { + eventType: PropTypes.string.isRequired, + sourceTitle: PropTypes.string.isRequired, + data: PropTypes.object.isRequired, + shortDateFormat: PropTypes.string.isRequired, + timeFormat: PropTypes.string.isRequired +}; + +export default HistoryDetails; diff --git a/frontend/src/Activity/History/Details/HistoryDetailsConnector.js b/frontend/src/Activity/History/Details/HistoryDetailsConnector.js new file mode 100644 index 000000000..0848c7905 --- /dev/null +++ b/frontend/src/Activity/History/Details/HistoryDetailsConnector.js @@ -0,0 +1,19 @@ +import _ from 'lodash'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; +import HistoryDetails from './HistoryDetails'; + +function createMapStateToProps() { + return createSelector( + createUISettingsSelector(), + (uiSettings) => { + return _.pick(uiSettings, [ + 'shortDateFormat', + 'timeFormat' + ]); + } + ); +} + +export default connect(createMapStateToProps)(HistoryDetails); diff --git a/frontend/src/Activity/History/Details/HistoryDetailsModal.css b/frontend/src/Activity/History/Details/HistoryDetailsModal.css new file mode 100644 index 000000000..bdcb7f918 --- /dev/null +++ b/frontend/src/Activity/History/Details/HistoryDetailsModal.css @@ -0,0 +1,5 @@ +.markAsFailedButton { + composes: button from 'Components/Link/Button.css'; + + margin-right: auto; +} diff --git a/frontend/src/Activity/History/Details/HistoryDetailsModal.js b/frontend/src/Activity/History/Details/HistoryDetailsModal.js new file mode 100644 index 000000000..2cf9294f6 --- /dev/null +++ b/frontend/src/Activity/History/Details/HistoryDetailsModal.js @@ -0,0 +1,104 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { kinds } from 'Helpers/Props'; +import Button from 'Components/Link/Button'; +import SpinnerButton from 'Components/Link/SpinnerButton'; +import Modal from 'Components/Modal/Modal'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import HistoryDetails from './HistoryDetails'; +import styles from './HistoryDetailsModal.css'; + +function getHeaderTitle(eventType) { + switch (eventType) { + case 'grabbed': + return 'Grabbed'; + case 'downloadFailed': + return 'Download Failed'; + case 'downloadFolderImported': + return 'Episode Imported'; + case 'episodeFileDeleted': + return 'Episode File Deleted'; + case 'episodeFileRenamed': + return 'Episode File Renamed'; + default: + return 'Unknown'; + } +} + +function HistoryDetailsModal(props) { + const { + isOpen, + eventType, + sourceTitle, + data, + isMarkingAsFailed, + shortDateFormat, + timeFormat, + onMarkAsFailedPress, + onModalClose + } = props; + + return ( + + + + {getHeaderTitle(eventType)} + + + + + + + + { + eventType === 'grabbed' && + + Mark as Failed + + } + + + + + + ); +} + +HistoryDetailsModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + eventType: PropTypes.string.isRequired, + sourceTitle: PropTypes.string.isRequired, + data: PropTypes.object.isRequired, + isMarkingAsFailed: PropTypes.bool.isRequired, + shortDateFormat: PropTypes.string.isRequired, + timeFormat: PropTypes.string.isRequired, + onMarkAsFailedPress: PropTypes.func.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +HistoryDetailsModal.defaultProps = { + isMarkingAsFailed: false +}; + +export default HistoryDetailsModal; diff --git a/frontend/src/Activity/History/History.js b/frontend/src/Activity/History/History.js new file mode 100644 index 000000000..2d18a5e6a --- /dev/null +++ b/frontend/src/Activity/History/History.js @@ -0,0 +1,163 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { align, icons } from 'Helpers/Props'; +import hasDifferentItems from 'Utilities/Object/hasDifferentItems'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +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 PageContent from 'Components/Page/PageContent'; +import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector'; +import PageToolbar from 'Components/Page/Toolbar/PageToolbar'; +import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection'; +import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton'; +import FilterMenu from 'Components/Menu/FilterMenu'; +import HistoryRowConnector from './HistoryRowConnector'; + +class History extends Component { + + // + // Lifecycle + + shouldComponentUpdate(nextProps) { + // Don't update when fetching has completed if items have changed, + // before episodes start fetching or when episodes start fetching. + + if ( + ( + this.props.isFetching && + nextProps.isPopulated && + hasDifferentItems(this.props.items, nextProps.items) + ) + ) { + return false; + } + + return true; + } + + // + // Render + + render() { + const { + isFetching, + isPopulated, + error, + items, + columns, + selectedFilterKey, + filters, + totalRecords, + onFilterSelect, + onFirstPagePress, + ...otherProps + } = this.props; + + const hasError = error; + + return ( + + + + + + + + + + + + + + + + + { + isFetching && !isPopulated && + + } + + { + !isFetching && hasError && +
Unable to load history
+ } + + { + // If history isPopulated and it's empty show no history found and don't + // wait for the episodes to populate because they are never coming. + + isPopulated && !hasError && !items.length && +
+ No history found +
+ } + + { + isPopulated && !hasError && !!items.length && +
+ + + { + items.map((item) => { + return ( + + ); + }) + } + +
+ + +
+ } +
+
+ ); + } +} + +History.propTypes = { + isFetching: PropTypes.bool.isRequired, + isPopulated: PropTypes.bool.isRequired, + error: PropTypes.object, + items: PropTypes.arrayOf(PropTypes.object).isRequired, + columns: PropTypes.arrayOf(PropTypes.object).isRequired, + selectedFilterKey: PropTypes.string.isRequired, + filters: PropTypes.arrayOf(PropTypes.object).isRequired, + totalRecords: PropTypes.number, + onFilterSelect: PropTypes.func.isRequired, + onFirstPagePress: PropTypes.func.isRequired +}; + +export default History; diff --git a/frontend/src/Activity/History/HistoryConnector.js b/frontend/src/Activity/History/HistoryConnector.js new file mode 100644 index 000000000..df780c1ed --- /dev/null +++ b/frontend/src/Activity/History/HistoryConnector.js @@ -0,0 +1,134 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; +import withCurrentPage from 'Components/withCurrentPage'; +import * as historyActions from 'Store/Actions/historyActions'; +import History from './History'; + +function createMapStateToProps() { + return createSelector( + (state) => state.history, + (history) => { + return { + ...history + }; + } + ); +} + +const mapDispatchToProps = { + ...historyActions +}; + +class HistoryConnector extends Component { + + // + // Lifecycle + + componentDidMount() { + const { + useCurrentPage, + fetchHistory, + gotoHistoryFirstPage + } = this.props; + + registerPagePopulator(this.repopulate); + + if (useCurrentPage) { + fetchHistory(); + } else { + gotoHistoryFirstPage(); + } + } + + componentWillUnmount() { + unregisterPagePopulator(this.repopulate); + this.props.clearHistory(); + } + + // + // Control + + repopulate = () => { + this.props.fetchHistory(); + } + + // + // Listeners + + onFirstPagePress = () => { + this.props.gotoHistoryFirstPage(); + } + + onPreviousPagePress = () => { + this.props.gotoHistoryPreviousPage(); + } + + onNextPagePress = () => { + this.props.gotoHistoryNextPage(); + } + + onLastPagePress = () => { + this.props.gotoHistoryLastPage(); + } + + onPageSelect = (page) => { + this.props.gotoHistoryPage({ page }); + } + + onSortPress = (sortKey) => { + this.props.setHistorySort({ sortKey }); + } + + onFilterSelect = (selectedFilterKey) => { + this.props.setHistoryFilter({ selectedFilterKey }); + } + + onTableOptionChange = (payload) => { + this.props.setHistoryTableOption(payload); + + if (payload.pageSize) { + this.props.gotoHistoryFirstPage(); + } + } + + // + // Render + + render() { + return ( + + ); + } +} + +HistoryConnector.propTypes = { + useCurrentPage: PropTypes.bool.isRequired, + items: PropTypes.arrayOf(PropTypes.object).isRequired, + fetchHistory: PropTypes.func.isRequired, + gotoHistoryFirstPage: PropTypes.func.isRequired, + gotoHistoryPreviousPage: PropTypes.func.isRequired, + gotoHistoryNextPage: PropTypes.func.isRequired, + gotoHistoryLastPage: PropTypes.func.isRequired, + gotoHistoryPage: PropTypes.func.isRequired, + setHistorySort: PropTypes.func.isRequired, + setHistoryFilter: PropTypes.func.isRequired, + setHistoryTableOption: PropTypes.func.isRequired, + clearHistory: PropTypes.func.isRequired +}; + +export default withCurrentPage( + connect(createMapStateToProps, mapDispatchToProps)(HistoryConnector) +); diff --git a/frontend/src/Activity/History/HistoryEventTypeCell.css b/frontend/src/Activity/History/HistoryEventTypeCell.css new file mode 100644 index 000000000..fac97a6c7 --- /dev/null +++ b/frontend/src/Activity/History/HistoryEventTypeCell.css @@ -0,0 +1,6 @@ +.cell { + composes: cell from 'Components/Table/Cells/TableRowCell.css'; + + width: 35px; + text-align: center; +} diff --git a/frontend/src/Activity/History/HistoryEventTypeCell.js b/frontend/src/Activity/History/HistoryEventTypeCell.js new file mode 100644 index 000000000..f013b3f55 --- /dev/null +++ b/frontend/src/Activity/History/HistoryEventTypeCell.js @@ -0,0 +1,82 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons, kinds } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import TableRowCell from 'Components/Table/Cells/TableRowCell'; +import styles from './HistoryEventTypeCell.css'; + +function getIconName(eventType) { + switch (eventType) { + case 'grabbed': + return icons.DOWNLOADING; + case 'seriesFolderImported': + return icons.DRIVE; + case 'downloadFolderImported': + return icons.DOWNLOADED; + case 'downloadFailed': + return icons.DOWNLOADING; + case 'episodeFileDeleted': + return icons.DELETE; + case 'episodeFileRenamed': + return icons.ORGANIZE; + default: + return icons.UNKNOWN; + } +} + +function getIconKind(eventType) { + switch (eventType) { + case 'downloadFailed': + return kinds.DANGER; + default: + return kinds.DEFAULT; + } +} + +function getTooltip(eventType, data) { + switch (eventType) { + case 'grabbed': + return `Episode grabbed from ${data.indexer} and sent to ${data.downloadClient}`; + case 'seriesFolderImported': + return 'Episode imported from series folder'; + case 'downloadFolderImported': + return 'Episode downloaded successfully and picked up from download client'; + case 'downloadFailed': + return 'Episode download failed'; + case 'episodeFileDeleted': + return 'Episode file deleted'; + case 'episodeFileRenamed': + return 'Episode file renamed'; + default: + return 'Unknown event'; + } +} + +function HistoryEventTypeCell({ eventType, data }) { + const iconName = getIconName(eventType); + const iconKind = getIconKind(eventType); + const tooltip = getTooltip(eventType, data); + + return ( + + + + ); +} + +HistoryEventTypeCell.propTypes = { + eventType: PropTypes.string.isRequired, + data: PropTypes.object +}; + +HistoryEventTypeCell.defaultProps = { + data: {} +}; + +export default HistoryEventTypeCell; diff --git a/frontend/src/Activity/History/HistoryRow.css b/frontend/src/Activity/History/HistoryRow.css new file mode 100644 index 000000000..83586af58 --- /dev/null +++ b/frontend/src/Activity/History/HistoryRow.css @@ -0,0 +1,23 @@ +.downloadClient { + composes: cell from 'Components/Table/Cells/TableRowCell.css'; + + width: 120px; +} + +.indexer { + composes: cell from 'Components/Table/Cells/TableRowCell.css'; + + width: 80px; +} + +.releaseGroup { + composes: cell from 'Components/Table/Cells/TableRowCell.css'; + + width: 110px; +} + +.details { + composes: cell from 'Components/Table/Cells/TableRowCell.css'; + + width: 30px; +} diff --git a/frontend/src/Activity/History/HistoryRow.js b/frontend/src/Activity/History/HistoryRow.js new file mode 100644 index 000000000..3c9fba4f3 --- /dev/null +++ b/frontend/src/Activity/History/HistoryRow.js @@ -0,0 +1,212 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons } from 'Helpers/Props'; +import IconButton from 'Components/Link/IconButton'; +import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; +import TableRow from 'Components/Table/TableRow'; +import TableRowCell from 'Components/Table/Cells/TableRowCell'; +import MovieQuality from 'Movie/MovieQuality'; +import MovieTitleLink from 'Movie/MovieTitleLink'; +import HistoryEventTypeCell from './HistoryEventTypeCell'; +import HistoryDetailsModal from './Details/HistoryDetailsModal'; +import styles from './HistoryRow.css'; + +class HistoryRow extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isDetailsModalOpen: false + }; + } + + componentDidUpdate(prevProps) { + if ( + prevProps.isMarkingAsFailed && + !this.props.isMarkingAsFailed && + !this.props.markAsFailedError + ) { + this.setState({ isDetailsModalOpen: false }); + } + } + + // + // Listeners + + onDetailsPress = () => { + this.setState({ isDetailsModalOpen: true }); + } + + onDetailsModalClose = () => { + this.setState({ isDetailsModalOpen: false }); + } + + // + // Render + + render() { + const { + movie, + quality, + qualityCutoffNotMet, + eventType, + sourceTitle, + date, + data, + isMarkingAsFailed, + columns, + shortDateFormat, + timeFormat, + onMarkAsFailedPress + } = this.props; + + if (!movie) { + return null; + } + + return ( + + { + columns.map((column) => { + const { + name, + isVisible + } = column; + + if (!isVisible) { + return null; + } + + if (name === 'eventType') { + return ( + + ); + } + + if (name === 'movie.sortTitle') { + return ( + + + + ); + } + + if (name === 'quality') { + return ( + + + + ); + } + + if (name === 'date') { + return ( + + ); + } + + if (name === 'downloadClient') { + return ( + + {data.downloadClient} + + ); + } + + if (name === 'indexer') { + return ( + + {data.indexer} + + ); + } + + if (name === 'releaseGroup') { + return ( + + {data.releaseGroup} + + ); + } + + if (name === 'details') { + return ( + + + + ); + } + + return null; + }) + } + + + + ); + } + +} + +HistoryRow.propTypes = { + movieId: PropTypes.number, + movie: PropTypes.object.isRequired, + language: PropTypes.object.isRequired, + languageCutoffNotMet: PropTypes.bool.isRequired, + quality: PropTypes.object.isRequired, + qualityCutoffNotMet: PropTypes.bool.isRequired, + eventType: PropTypes.string.isRequired, + sourceTitle: PropTypes.string.isRequired, + date: PropTypes.string.isRequired, + data: PropTypes.object.isRequired, + isMarkingAsFailed: PropTypes.bool, + markAsFailedError: PropTypes.object, + columns: PropTypes.arrayOf(PropTypes.object).isRequired, + shortDateFormat: PropTypes.string.isRequired, + timeFormat: PropTypes.string.isRequired, + onMarkAsFailedPress: PropTypes.func.isRequired +}; + +export default HistoryRow; diff --git a/frontend/src/Activity/History/HistoryRowConnector.js b/frontend/src/Activity/History/HistoryRowConnector.js new file mode 100644 index 000000000..b68c0ba4c --- /dev/null +++ b/frontend/src/Activity/History/HistoryRowConnector.js @@ -0,0 +1,73 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { fetchHistory, markAsFailed } from 'Store/Actions/historyActions'; +import createMovieSelector from 'Store/Selectors/createMovieSelector'; +import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; +import HistoryRow from './HistoryRow'; + +function createMapStateToProps() { + return createSelector( + createMovieSelector(), + createUISettingsSelector(), + (movie, uiSettings) => { + return { + movie, + shortDateFormat: uiSettings.shortDateFormat, + timeFormat: uiSettings.timeFormat + }; + } + ); +} + +const mapDispatchToProps = { + fetchHistory, + markAsFailed +}; + +class HistoryRowConnector extends Component { + + // + // Lifecycle + + componentDidUpdate(prevProps) { + if ( + prevProps.isMarkingAsFailed && + !this.props.isMarkingAsFailed && + !this.props.markAsFailedError + ) { + this.props.fetchHistory(); + } + } + + // + // Listeners + + onMarkAsFailedPress = () => { + this.props.markAsFailed({ id: this.props.id }); + } + + // + // Render + + render() { + return ( + + ); + } + +} + +HistoryRowConnector.propTypes = { + id: PropTypes.number.isRequired, + isMarkingAsFailed: PropTypes.bool, + markAsFailedError: PropTypes.object, + fetchHistory: PropTypes.func.isRequired, + markAsFailed: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(HistoryRowConnector); diff --git a/frontend/src/Activity/Queue/ProtocolLabel.css b/frontend/src/Activity/Queue/ProtocolLabel.css new file mode 100644 index 000000000..15e8e4fc6 --- /dev/null +++ b/frontend/src/Activity/Queue/ProtocolLabel.css @@ -0,0 +1,13 @@ +.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 new file mode 100644 index 000000000..e8a08943c --- /dev/null +++ b/frontend/src/Activity/Queue/ProtocolLabel.js @@ -0,0 +1,20 @@ +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 new file mode 100644 index 000000000..b65cc8a0c --- /dev/null +++ b/frontend/src/Activity/Queue/Queue.js @@ -0,0 +1,278 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import hasDifferentItems from 'Utilities/Object/hasDifferentItems'; +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 { align, icons } from 'Helpers/Props'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import Table from 'Components/Table/Table'; +import TableBody from 'Components/Table/TableBody'; +import TablePager from 'Components/Table/TablePager'; +import PageContent from 'Components/Page/PageContent'; +import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector'; +import PageToolbar from 'Components/Page/Toolbar/PageToolbar'; +import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection'; +import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton'; +import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator'; +import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper'; +import RemoveQueueItemsModal from './RemoveQueueItemsModal'; +import QueueOptionsConnector from './QueueOptionsConnector'; +import QueueRowConnector from './QueueRowConnector'; + +class Queue extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + allSelected: false, + allUnselected: false, + lastToggled: null, + selectedState: {}, + isPendingSelected: false, + isConfirmRemoveModalOpen: false + }; + } + + shouldComponentUpdate(nextProps) { + // Don't update when fetching has completed if items have changed, + // before episodes start fetching or when episodes start fetching. + + if ( + this.props.isFetching && + nextProps.isPopulated && + hasDifferentItems(this.props.items, nextProps.items) && + nextProps.items.some((e) => e.episodeId) + ) { + return false; + } + + return true; + } + + componentDidUpdate(prevProps) { + if (hasDifferentItems(prevProps.items, this.props.items)) { + this.setState((state) => { + return removeOldSelectedState(state, prevProps.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 = (blacklist) => { + this.props.onRemoveSelectedPress(this.getSelectedIds(), blacklist); + this.setState({ isConfirmRemoveModalOpen: false }); + } + + onConfirmRemoveModalClose = () => { + this.setState({ isConfirmRemoveModalOpen: false }); + } + + // + // Render + + render() { + const { + isFetching, + isPopulated, + error, + items, + columns, + totalRecords, + isGrabbing, + isRemoving, + isCheckForFinishedDownloadExecuting, + onRefreshPress, + ...otherProps + } = this.props; + + const { + allSelected, + allUnselected, + selectedState, + isConfirmRemoveModalOpen, + isPendingSelected + } = this.state; + + const isRefreshing = isFetching || isCheckForFinishedDownloadExecuting; + const isAllPopulated = isPopulated && !items.length; + const hasError = error; + const selectedCount = this.getSelectedIds().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 ( + + ); + }) + } + +
+ + +
+ } +
+ + +
+ ); + } +} + +Queue.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, + isGrabbing: PropTypes.bool.isRequired, + isRemoving: PropTypes.bool.isRequired, + isCheckForFinishedDownloadExecuting: 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 new file mode 100644 index 000000000..59bce00c3 --- /dev/null +++ b/frontend/src/Activity/Queue/QueueConnector.js @@ -0,0 +1,164 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; +import withCurrentPage from 'Components/withCurrentPage'; +import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector'; +import { executeCommand } from 'Store/Actions/commandActions'; +import * as queueActions from 'Store/Actions/queueActions'; +import * as commandNames from 'Commands/commandNames'; +import Queue from './Queue'; + +function createMapStateToProps() { + return createSelector( + (state) => state.queue.options, + (state) => state.queue.paged, + createCommandExecutingSelector(commandNames.CHECK_FOR_FINISHED_DOWNLOAD), + (options, queue, isCheckForFinishedDownloadExecuting) => { + return { + isCheckForFinishedDownloadExecuting, + ...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.CHECK_FOR_FINISHED_DOWNLOAD + }); + } + + onGrabSelectedPress = (ids) => { + this.props.grabQueueItems({ ids }); + } + + onRemoveSelectedPress = (ids, blacklist) => { + this.props.removeQueueItems({ ids, blacklist }); + } + + // + // Render + + render() { + return ( + + ); + } +} + +QueueConnector.propTypes = { + 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 new file mode 100644 index 000000000..f6e360c0a --- /dev/null +++ b/frontend/src/Activity/Queue/QueueDetails.js @@ -0,0 +1,97 @@ +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons, kinds } from 'Helpers/Props'; +import Icon from 'Components/Icon'; + +function QueueDetails(props) { + const { + title, + size, + sizeleft, + estimatedCompletionTime, + status: queueStatus, + errorMessage, + progressBar + } = props; + + const status = queueStatus.toLowerCase(); + + const progress = (100 - sizeleft / size * 100); + + if (status === 'pending') { + return ( + + ); + } + + if (status === 'completed') { + if (errorMessage) { + return ( + + ); + } + + // TODO: show an icon when download is complete, but not imported yet? + } + + 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, + 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 new file mode 100644 index 000000000..900cf85cb --- /dev/null +++ b/frontend/src/Activity/Queue/QueueOptions.js @@ -0,0 +1,77 @@ +import PropTypes from 'prop-types'; +import React, { Component, Fragment } from 'react'; +import { inputTypes } from 'Helpers/Props'; +import FormGroup from 'Components/Form/FormGroup'; +import FormLabel from 'Components/Form/FormLabel'; +import FormInputGroup from 'Components/Form/FormInputGroup'; + +class QueueOptions extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + includeUnknownSeriesItems: props.includeUnknownSeriesItems + }; + } + + componentDidUpdate(prevProps) { + const { + includeUnknownSeriesItems + } = this.props; + + if (includeUnknownSeriesItems !== prevProps.includeUnknownSeriesItems) { + this.setState({ + includeUnknownSeriesItems + }); + } + } + + // + // Listeners + + onOptionChange = ({ name, value }) => { + this.setState({ + [name]: value + }, () => { + this.props.onOptionChange({ + [name]: value + }); + }); + } + + // + // Render + + render() { + const { + includeUnknownSeriesItems + } = this.state; + + return ( + + + Show Unknown Series Items + + + + + ); + } +} + +QueueOptions.propTypes = { + includeUnknownSeriesItems: 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 new file mode 100644 index 000000000..b2c99511c --- /dev/null +++ b/frontend/src/Activity/Queue/QueueOptionsConnector.js @@ -0,0 +1,19 @@ +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 new file mode 100644 index 000000000..6aa4a1622 --- /dev/null +++ b/frontend/src/Activity/Queue/QueueRow.css @@ -0,0 +1,23 @@ +.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 new file mode 100644 index 000000000..8cc834fbe --- /dev/null +++ b/frontend/src/Activity/Queue/QueueRow.js @@ -0,0 +1,326 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons, kinds } from 'Helpers/Props'; +import IconButton from 'Components/Link/IconButton'; +import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; +import ProgressBar from 'Components/ProgressBar'; +import TableRow from 'Components/Table/TableRow'; +import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector'; +import TableRowCell from 'Components/Table/Cells/TableRowCell'; +import TableSelectCell from 'Components/Table/Cells/TableSelectCell'; +import ProtocolLabel from 'Activity/Queue/ProtocolLabel'; +import MovieQuality from 'Movie/MovieQuality'; +import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal'; +import MovieTitleLink from 'Movie/MovieTitleLink'; +import QueueStatusCell from './QueueStatusCell'; +import TimeleftCell from './TimeleftCell'; +import RemoveQueueItemModal from './RemoveQueueItemModal'; +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, + statusMessages, + errorMessage, + series, + episode, + quality, + protocol, + indexer, + 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 === 'series.sortTitle') { + return ( + + + + ); + } + + if (name === 'series') { + return ( + + + + ); + } + + if (name === 'episode.airDateUtc') { + return ( + + ); + } + + if (name === 'quality') { + return ( + + + + ); + } + + if (name === 'protocol') { + return ( + + + + ); + } + + if (name === 'indexer') { + return ( + + {indexer} + + ); + } + + if (name === 'downloadClient') { + return ( + + {downloadClient} + + ); + } + + 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, + statusMessages: PropTypes.arrayOf(PropTypes.object), + errorMessage: PropTypes.string, + series: PropTypes.object.isRequired, + episode: PropTypes.object.isRequired, + quality: PropTypes.object.isRequired, + protocol: PropTypes.string.isRequired, + indexer: 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 new file mode 100644 index 000000000..3fdeb2b22 --- /dev/null +++ b/frontend/src/Activity/Queue/QueueRowConnector.js @@ -0,0 +1,68 @@ +import _ from 'lodash'; +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(), + (series, uiSettings) => { + const result = _.pick(uiSettings, [ + 'showRelativeDates', + 'shortDateFormat', + 'timeFormat' + ]); + + result.series = series; + + return result; + } + ); +} + +const mapDispatchToProps = { + grabQueueItem, + removeQueueItem +}; + +class QueueRowConnector extends Component { + + // + // Listeners + + onGrabPress = () => { + this.props.grabQueueItem({ id: this.props.id }); + } + + onRemoveQueueItemPress = (blacklist) => { + this.props.removeQueueItem({ id: this.props.id, blacklist }); + } + + // + // Render + + render() { + return ( + + ); + } +} + +QueueRowConnector.propTypes = { + id: PropTypes.number.isRequired, + episode: 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 new file mode 100644 index 000000000..6291ec949 --- /dev/null +++ b/frontend/src/Activity/Queue/QueueStatusCell.css @@ -0,0 +1,5 @@ +.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 new file mode 100644 index 000000000..f8cbc65ff --- /dev/null +++ b/frontend/src/Activity/Queue/QueueStatusCell.js @@ -0,0 +1,132 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons, kinds, tooltipPositions } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import TableRowCell from 'Components/Table/Cells/TableRowCell'; +import Popover from 'Components/Tooltip/Popover'; +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 = 'Ok', + statusMessages, + errorMessage + } = props; + + const hasWarning = trackedDownloadStatus === 'Warning'; + const hasError = trackedDownloadStatus === 'Error'; + + // status === 'downloading' + let iconName = icons.DOWNLOADING; + let iconKind = kinds.DEFAULT; + let title = 'Downloading'; + + if (hasWarning) { + iconKind = kinds.WARNING; + } + + if (status === 'Paused') { + iconName = icons.PAUSED; + title = 'Paused'; + } + + if (status === 'Queued') { + iconName = icons.QUEUED; + title = 'Queued'; + } + + if (status === 'Completed') { + iconName = icons.DOWNLOADED; + title = 'Downloaded'; + } + + if (status === 'Delay') { + iconName = icons.PENDING; + title = 'Pending'; + } + + if (status === 'DownloadClientUnavailable') { + iconName = icons.PENDING; + iconKind = kinds.WARNING; + title = 'Pending - Download client is unavailable'; + } + + if (status === 'Failed') { + iconName = icons.DOWNLOADING; + iconKind = kinds.DANGER; + title = 'Download failed'; + } + + if (status === 'Warning') { + iconName = icons.DOWNLOADING; + iconKind = kinds.WARNING; + title = `Download warning: ${errorMessage || 'check download client for more details'}`; + } + + if (hasError) { + if (status === 'Completed') { + iconName = icons.DOWNLOAD; + iconKind = kinds.DANGER; + title = `Import failed: ${sourceTitle}`; + } else { + iconName = icons.DOWNLOADING; + iconKind = kinds.DANGER; + title = 'Download failed'; + } + } + + return ( + + + } + title={title} + body={hasWarning || hasError ? getDetailedPopoverBody(statusMessages) : sourceTitle} + position={tooltipPositions.RIGHT} + /> + + ); +} + +QueueStatusCell.propTypes = { + sourceTitle: PropTypes.string.isRequired, + status: PropTypes.string.isRequired, + trackedDownloadStatus: PropTypes.string, + statusMessages: PropTypes.arrayOf(PropTypes.object), + errorMessage: PropTypes.string +}; + +export default QueueStatusCell; diff --git a/frontend/src/Activity/Queue/RemoveQueueItemModal.css b/frontend/src/Activity/Queue/RemoveQueueItemModal.css new file mode 100644 index 000000000..c9ef59ec1 --- /dev/null +++ b/frontend/src/Activity/Queue/RemoveQueueItemModal.css @@ -0,0 +1,3 @@ +.message { + margin-bottom: 30px; +} diff --git a/frontend/src/Activity/Queue/RemoveQueueItemModal.js b/frontend/src/Activity/Queue/RemoveQueueItemModal.js new file mode 100644 index 000000000..6c208ebbb --- /dev/null +++ b/frontend/src/Activity/Queue/RemoveQueueItemModal.js @@ -0,0 +1,114 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { inputTypes, kinds, sizes } from 'Helpers/Props'; +import Button from 'Components/Link/Button'; +import Modal from 'Components/Modal/Modal'; +import FormGroup from 'Components/Form/FormGroup'; +import FormLabel from 'Components/Form/FormLabel'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import styles from './RemoveQueueItemModal.css'; + +class RemoveQueueItemModal extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + blacklist: false + }; + } + + // + // Listeners + + onBlacklistChange = ({ value }) => { + this.setState({ blacklist: value }); + } + + onRemoveQueueItemConfirmed = () => { + const blacklist = this.state.blacklist; + + this.setState({ blacklist: false }); + this.props.onRemovePress(blacklist); + } + + onModalClose = () => { + this.setState({ blacklist: false }); + this.props.onModalClose(); + } + + // + // Render + + render() { + const { + isOpen, + sourceTitle + } = this.props; + + const blacklist = this.state.blacklist; + + return ( + + + + Remove - {sourceTitle} + + + +
+ Are you sure you want to remove '{sourceTitle}' from the queue? +
+ + + Blacklist Release + + + +
+ + + + + + +
+
+ ); + } +} + +RemoveQueueItemModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + sourceTitle: PropTypes.string.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 new file mode 100644 index 000000000..c9ef59ec1 --- /dev/null +++ b/frontend/src/Activity/Queue/RemoveQueueItemsModal.css @@ -0,0 +1,3 @@ +.message { + margin-bottom: 30px; +} diff --git a/frontend/src/Activity/Queue/RemoveQueueItemsModal.js b/frontend/src/Activity/Queue/RemoveQueueItemsModal.js new file mode 100644 index 000000000..d56472efb --- /dev/null +++ b/frontend/src/Activity/Queue/RemoveQueueItemsModal.js @@ -0,0 +1,114 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { inputTypes, kinds, sizes } from 'Helpers/Props'; +import Button from 'Components/Link/Button'; +import Modal from 'Components/Modal/Modal'; +import FormGroup from 'Components/Form/FormGroup'; +import FormLabel from 'Components/Form/FormLabel'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import styles from './RemoveQueueItemsModal.css'; + +class RemoveQueueItemsModal extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + blacklist: false + }; + } + + // + // Listeners + + onBlacklistChange = ({ value }) => { + this.setState({ blacklist: value }); + } + + onRemoveQueueItemConfirmed = () => { + const blacklist = this.state.blacklist; + + this.setState({ blacklist: false }); + this.props.onRemovePress(blacklist); + } + + onModalClose = () => { + this.setState({ blacklist: false }); + this.props.onModalClose(); + } + + // + // Render + + render() { + const { + isOpen, + selectedCount + } = this.props; + + const blacklist = this.state.blacklist; + + return ( + + + + Remove Selected Item{selectedCount > 1 ? 's' : ''} + + + +
+ Are you sure you want to remove {selectedCount} item{selectedCount > 1 ? 's' : ''} from the queue? +
+ + + Blacklist Release + + + +
+ + + + + + +
+
+ ); + } +} + +RemoveQueueItemsModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + selectedCount: PropTypes.number.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 new file mode 100644 index 000000000..ead2bfcfa --- /dev/null +++ b/frontend/src/Activity/Queue/Status/QueueStatusConnector.js @@ -0,0 +1,70 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { fetchQueueStatus } from 'Store/Actions/queueActions'; +import PageSidebarStatus from 'Components/Page/Sidebar/PageSidebarStatus'; + +function createMapStateToProps() { + return createSelector( + (state) => state.app, + (state) => state.queue.status, + (state) => state.queue.options.includeUnknownMovieItems, + (app, status, includeUnknownMovieItems) => { + const { + count, + unknownCount + } = status.item; + + return { + isConnected: app.isConnected, + isReconnecting: app.isReconnecting, + isPopulated: status.isPopulated, + ...status.item, + count: includeUnknownMovieItems ? count : count - unknownCount + }; + } + ); +} + +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 new file mode 100644 index 000000000..eb58cf297 --- /dev/null +++ b/frontend/src/Activity/Queue/TimeleftCell.css @@ -0,0 +1,5 @@ +.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 new file mode 100644 index 000000000..c9515f172 --- /dev/null +++ b/frontend/src/Activity/Queue/TimeleftCell.js @@ -0,0 +1,82 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +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 TableRowCell from 'Components/Table/Cells/TableRowCell'; +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) { + 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 new file mode 100644 index 000000000..0bf8b0e15 --- /dev/null +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovie.css @@ -0,0 +1,54 @@ +.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; +} + +.helpText { + margin-bottom: 10px; + font-weight: 300; + font-size: 24px; +} + +.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 new file mode 100644 index 000000000..e08ad2f0d --- /dev/null +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js @@ -0,0 +1,182 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons } from 'Helpers/Props'; +import Button from 'Components/Link/Button'; +import Link from 'Components/Link/Link'; +import Icon from 'Components/Icon'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import TextInput from 'Components/Form/TextInput'; +import PageContent from 'Components/Page/PageContent'; +import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector'; +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 + } = this.props; + + const term = this.state.term; + const isFetching = this.state.isFetching; + + return ( + + +
+
+ +
+ + + + +
+ + { + isFetching && + + } + + { + !isFetching && !!error && +
Failed to load search results, please try again.
+ } + + { + !isFetching && !error && !!items.length && +
+ { + items.map((item) => { + return ( + + ); + }) + } +
+ } + + { + !isFetching && !error && !items.length && !!term && +
+
Couldn't find any results for '{term}'
+
You can also search using TMDB ID or IMDB ID of a movie. eg. tmdb:71663
+
+ + Why can't I find my movie? + +
+
+ } + + { + !term && +
+
It's easy to add a new movie, just start typing the name the movie you want to add.
+
You can also search using TMDB ID of a movie. eg. tmdb:71663
+
+ } + +
+ + + ); + } +} + +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, + 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 new file mode 100644 index 000000000..e4116a653 --- /dev/null +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js @@ -0,0 +1,102 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import parseUrl from 'Utilities/String/parseUrl'; +import { lookupMovie, clearAddMovie } from 'Store/Actions/addMovieActions'; +import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; +import AddNewMovie from './AddNewMovie'; + +function createMapStateToProps() { + return createSelector( + (state) => state.addMovie, + (state) => state.routing.location, + (addMovie, location) => { + const { params } = parseUrl(location.search); + + return { + term: params.term, + ...addMovie + }; + } + ); +} + +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 new file mode 100644 index 000000000..785f758ab --- /dev/null +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieModal.js @@ -0,0 +1,31 @@ +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 new file mode 100644 index 000000000..d1cffc210 --- /dev/null +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.css @@ -0,0 +1,68 @@ +.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; +} + +.searchForMissingEpisodesLabelContainer { + display: flex; + margin-top: 2px; +} + +.searchForMissingEpisodesLabel { + margin-right: 8px; + font-weight: normal; +} + +.searchForMissingEpisodesContainer { + composes: container from 'Components/Form/CheckInput.css'; + + flex: 0 1 0; +} + +.searchForMissingEpisodesInput { + 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 new file mode 100644 index 000000000..8e981bfe5 --- /dev/null +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContent.js @@ -0,0 +1,190 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { kinds, inputTypes } from 'Helpers/Props'; +import SpinnerButton from 'Components/Link/SpinnerButton'; +import Form from 'Components/Form/Form'; +import FormGroup from 'Components/Form/FormGroup'; +import FormLabel from 'Components/Form/FormLabel'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import CheckInput from 'Components/Form/CheckInput'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import MoviePoster from 'Movie/MoviePoster'; +import styles from './AddNewMovieModalContent.css'; + +class AddNewMovieModalContent extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + searchForMissingEpisodes: false + }; + } + + // + // Listeners + + onSearchForMissingEpisodesChange = ({ value }) => { + this.setState({ searchForMissingEpisodes: value }); + } + + onQualityProfileIdChange = ({ value }) => { + this.props.onInputChange({ name: 'qualityProfileId', value: parseInt(value) }); + } + + onAddMoviePress = () => { + this.props.onAddMoviePress(this.state.searchForMissingEpisodes); + } + + // + // Render + + render() { + const { + title, + year, + overview, + images, + isAdding, + rootFolderPath, + monitor, + qualityProfileId, + tags, + isSmallScreen, + onModalClose, + onInputChange + } = this.props; + + return ( + + + {title} + + { + !title.contains(year) && !!year && + ({year}) + } + + + +
+ { + !isSmallScreen && +
+ +
+ } + +
+
+ {overview} +
+ +
+ + Root Folder + + + + + + + Monitor + + + + + + + Quality Profile + + + + + + Tags + + + +
+
+
+
+ + + + + + Add {title} + + +
+ ); + } +} + +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, + tags: PropTypes.object.isRequired, + isSmallScreen: 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 new file mode 100644 index 000000000..5f97abbda --- /dev/null +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieModalContentConnector.js @@ -0,0 +1,97 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { setAddMovieDefault, addMovie } from 'Store/Actions/addMovieActions'; +import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; +import selectSettings from 'Store/Selectors/selectSettings'; +import AddNewMovieModalContent from './AddNewMovieModalContent'; + +function createMapStateToProps() { + return createSelector( + (state) => state.addMovie, + createDimensionsSelector(), + (addMovieState, dimensions) => { + const { + isAdding, + addError, + defaults + } = addMovieState; + + const { + settings, + validationErrors, + validationWarnings + } = selectSettings(defaults, {}, addError); + + return { + isAdding, + addError, + isSmallScreen: dimensions.isSmallScreen, + validationErrors, + validationWarnings, + ...settings + }; + } + ); +} + +const mapDispatchToProps = { + setAddMovieDefault, + addMovie +}; + +class AddNewMovieModalContentConnector extends Component { + + // + // Listeners + + onInputChange = ({ name, value }) => { + this.props.setAddMovieDefault({ [name]: value }); + } + + onAddMoviePress = (searchForMissingEpisodes) => { + const { + tmdbId, + rootFolderPath, + monitor, + qualityProfileId, + tags + } = this.props; + + this.props.addMovie({ + tmdbId, + rootFolderPath: rootFolderPath.value, + monitor: monitor.value, + qualityProfileId: qualityProfileId.value, + tags: tags.value, + searchForMissingEpisodes + }); + } + + // + // Render + + render() { + return ( + + ); + } +} + +AddNewMovieModalContentConnector.propTypes = { + tmdbId: PropTypes.number.isRequired, + rootFolderPath: PropTypes.object, + monitor: PropTypes.object.isRequired, + qualityProfileId: PropTypes.object, + 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 new file mode 100644 index 000000000..38ccffb4d --- /dev/null +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.css @@ -0,0 +1,40 @@ +.searchResult { + display: flex; + margin: 20px 0; + padding: 20px; + width: 100%; + background-color: $white; + color: inherit; + transition: background 500ms; + + &:hover { + background-color: #eaf2ff; + color: inherit; + text-decoration: none; + } +} + +.poster { + flex: 0 0 170px; + margin-right: 20px; + height: 250px; +} + +.title { + font-weight: 300; + font-size: 36px; +} + +.year { + margin-left: 10px; + color: $disabledColor; +} + +.alreadyExistsIcon { + margin-left: 10px; + color: #37bc9b; +} + +.overview { + margin-top: 20px; +} diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js new file mode 100644 index 000000000..186459e95 --- /dev/null +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js @@ -0,0 +1,162 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons, kinds, sizes } from 'Helpers/Props'; +import HeartRating from 'Components/HeartRating'; +import Icon from 'Components/Icon'; +import Label from 'Components/Label'; +import Link from 'Components/Link/Link'; +import MoviePoster from 'Movie/MoviePoster'; +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.onAddSerisModalClose(); + } + } + + // + // Listeners + + onPress = () => { + this.setState({ isNewAddMovieModalOpen: true }); + } + + onAddSerisModalClose = () => { + this.setState({ isNewAddMovieModalOpen: false }); + } + + // + // Render + + render() { + const { + tmdbId, + title, + titleSlug, + year, + studio, + status, + overview, + ratings, + images, + isExistingMovie, + 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}) + } + + { + isExistingMovie && + + } +
+ +
+ + + { + !!studio && + + } + + { + status === 'ended' && + + } +
+ +
+ {overview} +
+
+ + + +
+ ); + } +} + +AddNewMovieSearchResult.propTypes = { + tmdbId: PropTypes.number.isRequired, + 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, + images: PropTypes.arrayOf(PropTypes.object).isRequired, + isExistingMovie: 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 new file mode 100644 index 000000000..fccbe6120 --- /dev/null +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResultConnector.js @@ -0,0 +1,20 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createExistingMovieSelector from 'Store/Selectors/createExistingMovieSelector'; +import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; +import AddNewMovieSearchResult from './AddNewMovieSearchResult'; + +function createMapStateToProps() { + return createSelector( + createExistingMovieSelector(), + createDimensionsSelector(), + (isExistingMovie, dimensions) => { + return { + isExistingMovie, + 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 new file mode 100644 index 000000000..b4617604b --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovie.js @@ -0,0 +1,169 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import getSelectedIds from 'Utilities/Table/getSelectedIds'; +import selectAll from 'Utilities/Table/selectAll'; +import toggleSelected from 'Utilities/Table/toggleSelected'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import PageContent from 'Components/Page/PageContent'; +import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector'; +import ImportMovieTableConnector from './ImportMovieTableConnector'; +import ImportMovieFooterConnector from './ImportMovieFooterConnector'; + +class ImportMovie extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + allSelected: false, + allUnselected: false, + lastToggled: null, + selectedState: {}, + contentBody: null, + scrollTop: 0 + }; + } + + // + // Control + + setContentBodyRef = (ref) => { + this.setState({ contentBody: 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()); + } + + onScroll = ({ scrollTop }) => { + this.setState({ scrollTop }); + } + + // + // Render + + render() { + const { + rootFolderId, + path, + rootFoldersFetching, + rootFoldersPopulated, + rootFoldersError, + unmappedFolders + } = this.props; + + const { + allSelected, + allUnselected, + selectedState, + contentBody + } = this.state; + + return ( + + + { + rootFoldersFetching && !rootFoldersPopulated && + + } + + { + !rootFoldersFetching && !!rootFoldersError && +
Unable to load root folders
+ } + + { + !rootFoldersError && rootFoldersPopulated && !unmappedFolders.length && +
+ All series in {path} have been imported +
+ } + + { + !rootFoldersError && rootFoldersPopulated && !!unmappedFolders.length && contentBody && + + } +
+ + { + !rootFoldersError && rootFoldersPopulated && !!unmappedFolders.length && + + } +
+ ); + } +} + +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 new file mode 100644 index 000000000..5b2000cc1 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieConnector.js @@ -0,0 +1,152 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { setImportMovieValue, importMovie, clearImportMovie } from 'Store/Actions/importMovieActions'; +import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; +import { setAddMovieDefault } from 'Store/Actions/addMovieActions'; +import createRouteMatchShape from 'Helpers/Props/Shapes/createRouteMatchShape'; +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, + dispatchSetAddSeriesDefault: setAddMovieDefault +}; + +class ImportMovieConnector extends Component { + + // + // Lifecycle + + componentDidMount() { + const { + qualityProfiles, + defaultQualityProfileId, + dispatchFetchRootFolders, + dispatchSetAddSeriesDefault + } = this.props; + + if (!this.props.rootFoldersPopulated) { + dispatchFetchRootFolders(); + } + + let setDefaults = false; + const setDefaultPayload = {}; + + if ( + !defaultQualityProfileId || + !qualityProfiles.some((p) => p.id === defaultQualityProfileId) + ) { + setDefaults = true; + setDefaultPayload.qualityProfileId = qualityProfiles[0].id; + } + + if (setDefaults) { + dispatchSetAddSeriesDefault(setDefaultPayload); + } + } + + componentWillUnmount() { + this.props.dispatchClearImportMovie(); + } + + // + // Listeners + + onInputChange = (ids, name, value) => { + this.props.dispatchSetAddSeriesDefault({ [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, + 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, + dispatchSetAddSeriesDefault: 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 new file mode 100644 index 000000000..0a61ca509 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.css @@ -0,0 +1,33 @@ +.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; +} diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js new file mode 100644 index 000000000..4c7eb7352 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooter.js @@ -0,0 +1,184 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { inputTypes, kinds } from 'Helpers/Props'; +import Button from 'Components/Link/Button'; +import SpinnerButton from 'Components/Link/SpinnerButton'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +// import CheckInput from 'Components/Form/CheckInput'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import PageContentFooter from 'Components/Page/PageContentFooter'; +import styles from './ImportMovieFooter.css'; + +const MIXED = 'mixed'; + +class ImportMovieFooter extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + const { + defaultMonitor, + defaultQualityProfileId + } = props; + + this.state = { + monitor: defaultMonitor, + qualityProfileId: defaultQualityProfileId + }; + } + + componentDidUpdate(prevProps, prevState) { + const { + defaultMonitor, + defaultQualityProfileId, + isMonitorMixed, + isQualityProfileIdMixed + } = this.props; + + const { + monitor, + qualityProfileId + } = 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 (!_.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, + onImportPress, + onCancelLookupPress + } = this.props; + + const { + monitor, + qualityProfileId + } = this.state; + + return ( + +
+
+ Monitor +
+ + +
+ +
+
+ Quality Profile +
+ + +
+ +
+
+   +
+ +
+ + Import {selectedCount} {selectedCount > 1 ? 'Movies' : 'Movie'} + + + { + isLookingUpMovie && + + } + + { + isLookingUpMovie && + + } + + { + isLookingUpMovie && + 'Processing Folders' + } +
+
+
+ ); + } +} + +ImportMovieFooter.propTypes = { + selectedCount: PropTypes.number.isRequired, + isImporting: PropTypes.bool.isRequired, + isLookingUpMovie: PropTypes.bool.isRequired, + defaultMonitor: PropTypes.string.isRequired, + defaultQualityProfileId: PropTypes.number, + isMonitorMixed: PropTypes.bool.isRequired, + isQualityProfileIdMixed: PropTypes.bool.isRequired, + onInputChange: PropTypes.func.isRequired, + onImportPress: 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 new file mode 100644 index 000000000..28cb4ea59 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieFooterConnector.js @@ -0,0 +1,50 @@ +import _ from 'lodash'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { cancelLookupMovie } from 'Store/Actions/importMovieActions'; +import ImportMovieFooter from './ImportMovieFooter'; + +function isMixed(items, selectedIds, defaultValue, key) { + return _.some(items, (series) => { + return selectedIds.indexOf(series.id) > -1 && series[key] !== defaultValue; + }); +} + +function createMapStateToProps() { + return createSelector( + (state) => state.addMovie, + (state) => state.importMovie, + (state, { selectedIds }) => selectedIds, + (addMovie, importMovie, selectedIds) => { + const { + monitor: defaultMonitor, + qualityProfileId: defaultQualityProfileId + } = addMovie.defaults; + + const { + isLookingUpMovie, + isImporting, + items + } = importMovie; + + const isMonitorMixed = isMixed(items, selectedIds, defaultMonitor, 'monitor'); + const isQualityProfileIdMixed = isMixed(items, selectedIds, defaultQualityProfileId, 'qualityProfileId'); + + return { + selectedCount: selectedIds.length, + isLookingUpMovie, + isImporting, + defaultMonitor, + defaultQualityProfileId, + isMonitorMixed, + isQualityProfileIdMixed + }; + } + ); +} + +const mapDispatchToProps = { + 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 new file mode 100644 index 000000000..a80a35890 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.css @@ -0,0 +1,30 @@ +.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; +} + +.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 new file mode 100644 index 000000000..7b59b409f --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieHeader.js @@ -0,0 +1,60 @@ +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 styles from './ImportMovieHeader.css'; + +function ImportMovieHeader(props) { + const { + allSelected, + allUnselected, + onSelectAllChange + } = props; + + return ( + + + + + Folder + + + + Monitor + + + + Quality Profile + + + + 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 new file mode 100644 index 000000000..5dd1c9fef --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.css @@ -0,0 +1,31 @@ +.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; +} + +.qualityProfile { + composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css'; + + flex: 0 1 250px; + min-width: 170px; +} + +.series { + 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 new file mode 100644 index 000000000..0839432ff --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRow.js @@ -0,0 +1,84 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { inputTypes } from 'Helpers/Props'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import VirtualTableRow from 'Components/Table/VirtualTableRow'; +import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell'; +import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell'; +import ImportMovieSelectMovieConnector from './SelectMovie/ImportMovieSelectMovieConnector'; +import styles from './ImportMovieRow.css'; + +function ImportMovieRow(props) { + const { + style, + id, + monitor, + qualityProfileId, + selectedMovie, + isExistingMovie, + isSelected, + onSelectedChange, + onInputChange + } = props; + + return ( + + + + + {id} + + + + + + + + + + + + + + + ); +} + +ImportMovieRow.propTypes = { + style: PropTypes.object.isRequired, + id: PropTypes.string.isRequired, + monitor: PropTypes.string.isRequired, + qualityProfileId: PropTypes.number.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 new file mode 100644 index 000000000..b134b8ffd --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieRowConnector.js @@ -0,0 +1,87 @@ +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 new file mode 100644 index 000000000..efc6dccb3 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieSelected.css @@ -0,0 +1,3 @@ +.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 new file mode 100644 index 000000000..eb886d0e4 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTable.js @@ -0,0 +1,183 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import VirtualTable from 'Components/Table/VirtualTable'; +import ImportMovieHeader from './ImportMovieHeader'; +import ImportMovieRowConnector from './ImportMovieRowConnector'; + +class ImportMovieTable extends Component { + + // + // Lifecycle + + componentDidMount() { + const { + unmappedFolders, + defaultMonitor, + defaultQualityProfileId, + onMovieLookup, + onSetImportMovieValue + } = this.props; + + const values = { + monitor: defaultMonitor, + qualityProfileId: defaultQualityProfileId + }; + + 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 series or + // the selected series is an existing series. + if ((!selectedMovie && prevItem.selectedMovie) || (isExistingMovie && !prevItem.selectedMovie)) { + onSelectedChange({ id, value: false }); + + return; + } + + // State is selected, but a series isn't selected or + // the selected series is an existing series. + if (isSelected && (!selectedMovie || isExistingMovie)) { + onSelectedChange({ id, value: false }); + + return; + } + + // A series 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, + contentBody, + scrollTop, + selectedState, + onSelectAllChange, + onScroll + } = this.props; + + if (!items.length) { + return null; + } + + return ( + + } + selectedState={selectedState} + onScroll={onScroll} + /> + ); + } +} + +ImportMovieTable.propTypes = { + rootFolderId: PropTypes.number.isRequired, + items: PropTypes.arrayOf(PropTypes.object), + unmappedFolders: PropTypes.arrayOf(PropTypes.object), + defaultMonitor: PropTypes.string.isRequired, + defaultQualityProfileId: PropTypes.number, + allSelected: PropTypes.bool.isRequired, + allUnselected: PropTypes.bool.isRequired, + selectedState: PropTypes.object.isRequired, + isSmallScreen: PropTypes.bool.isRequired, + allMovies: PropTypes.arrayOf(PropTypes.object), + contentBody: PropTypes.object.isRequired, + scrollTop: PropTypes.number.isRequired, + onSelectAllChange: PropTypes.func.isRequired, + onSelectedChange: PropTypes.func.isRequired, + onRemoveSelectedStateItem: PropTypes.func.isRequired, + onMovieLookup: PropTypes.func.isRequired, + onSetImportMovieValue: PropTypes.func.isRequired, + onScroll: PropTypes.func.isRequired +}; + +export default ImportMovieTable; diff --git a/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js new file mode 100644 index 000000000..42499c703 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/ImportMovieTableConnector.js @@ -0,0 +1,41 @@ +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, + 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 new file mode 100644 index 000000000..a862c117c --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.css @@ -0,0 +1,8 @@ +.series { + 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 new file mode 100644 index 000000000..0545df7cc --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResult.js @@ -0,0 +1,52 @@ +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 new file mode 100644 index 000000000..da5608403 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSearchResultConnector.js @@ -0,0 +1,17 @@ +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 new file mode 100644 index 000000000..1a7f4836e --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.css @@ -0,0 +1,70 @@ +.tether { + z-index: 2000; +} + +.button { + composes: link from 'Components/Link/Link.css'; + + position: relative; + display: flex; + align-items: center; + 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 { + position: absolute; + right: 16px; +} + +.contentContainer { + margin-top: 4px; + padding: 0 8px; + width: 400px; +} + +.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 new file mode 100644 index 000000000..c74e4126c --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovie.js @@ -0,0 +1,280 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import ReactDOM from 'react-dom'; +import TetherComponent from 'react-tether'; +import { icons, kinds } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import FormInputButton from 'Components/Form/FormInputButton'; +import Link from 'Components/Link/Link'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import TextInput from 'Components/Form/TextInput'; +import ImportMovieSearchResultConnector from './ImportMovieSearchResultConnector'; +import ImportMovieTitle from './ImportMovieTitle'; +import styles from './ImportMovieSelectMovie.css'; + +const tetherOptions = { + skipMoveElement: true, + constraints: [ + { + to: 'window', + attachment: 'together', + pin: true + } + ], + attachment: 'top center', + targetAttachment: 'bottom center' +}; + +class ImportMovieSelectMovie extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._movieLookupTimeout = null; + + this.state = { + term: props.id, + isOpen: false + }; + } + + // + // Control + + _setButtonRef = (ref) => { + this._buttonRef = ref; + } + + _setContentRef = (ref) => { + this._contentRef = ref; + } + + _addListener() { + window.addEventListener('click', this.onWindowClick); + } + + _removeListener() { + window.removeEventListener('click', this.onWindowClick); + } + + // + // Listeners + + onWindowClick = (event) => { + const button = ReactDOM.findDOMNode(this._buttonRef); + const content = ReactDOM.findDOMNode(this._contentRef); + + if (!button) { + return; + } + + if (!button.contains(event.target) && content && !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, + queued, + isLookingUpMovie + } = this.props; + + const errorMessage = error && + error.responseJSON && + error.responseJSON.message; + + return ( + + + { + isLookingUpMovie && queued && !isPopulated && + + } + + { + isPopulated && selectedMovie && isExistingMovie && + + } + + { + isPopulated && selectedMovie && + + } + + { + isPopulated && !selectedMovie && +
+ + + No match found! +
+ } + + { + !isFetching && !!error && +
+ + + Search failed, please try again later. +
+ } + +
+ +
+ + + { + this.state.isOpen && +
+
+
+
+ +
+ + + + + + +
+ +
+ { + items.map((item) => { + return ( + + ); + }) + } +
+
+
+ } +
+ ); + } +} + +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, + queued: PropTypes.bool.isRequired, + isLookingUpMovie: PropTypes.bool.isRequired, + onSearchInputChange: PropTypes.func.isRequired, + onMovieSelect: PropTypes.func.isRequired +}; + +ImportMovieSelectMovie.defaultProps = { + isFetching: true, + isPopulated: false, + items: [], + queued: true +}; + +export default ImportMovieSelectMovie; diff --git a/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovieConnector.js b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovieConnector.js new file mode 100644 index 000000000..31c94f294 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieSelectMovieConnector.js @@ -0,0 +1,76 @@ +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 new file mode 100644 index 000000000..f6ae0f4e6 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.css @@ -0,0 +1,17 @@ +.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 new file mode 100644 index 000000000..fc5ba5b75 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/Import/SelectMovie/ImportMovieTitle.js @@ -0,0 +1,50 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { kinds } from 'Helpers/Props'; +import Label from 'Components/Label'; +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 new file mode 100644 index 000000000..b8d1a923f --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/ImportMovies.js @@ -0,0 +1,30 @@ +import React, { Component } from 'react'; +import { Route } from 'react-router-dom'; +import Switch from 'Components/Router/Switch'; +import ImportMovieSelectFolderConnector from 'AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector'; +import ImportMovieConnector from 'AddMovie/ImportMovie/Import/ImportMovieConnector'; + +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 new file mode 100644 index 000000000..d9c5ccb01 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.css @@ -0,0 +1,18 @@ +.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 new file mode 100644 index 000000000..7730e3b43 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRow.js @@ -0,0 +1,65 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import formatBytes from 'Utilities/Number/formatBytes'; +import { icons } from 'Helpers/Props'; +import IconButton from 'Components/Link/IconButton'; +import Link from 'Components/Link/Link'; +import TableRow from 'Components/Table/TableRow'; +import TableRowCell from 'Components/Table/Cells/TableRowCell'; +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 new file mode 100644 index 000000000..e25637472 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieRootFolderRowConnector.js @@ -0,0 +1,48 @@ +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 new file mode 100644 index 000000000..030da96fb --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.css @@ -0,0 +1,32 @@ +.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 new file mode 100644 index 000000000..32211ed19 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolder.js @@ -0,0 +1,188 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons, kinds, sizes } from 'Helpers/Props'; +import Button from 'Components/Link/Button'; +import FieldSet from 'Components/FieldSet'; +import Icon from 'Components/Icon'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import FileBrowserModal from 'Components/FileBrowser/FileBrowserModal'; +import PageContent from 'Components/Page/PageContent'; +import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector'; +import Table from 'Components/Table/Table'; +import TableBody from 'Components/Table/TableBody'; +import ImportMovieRootFolderRowConnector from './ImportMovieRootFolderRowConnector'; +import styles from './ImportMovieSelectFolder.css'; + +const rootFolderColumns = [ + { + name: 'path', + label: 'Path', + isVisible: true + }, + { + name: 'freeSpace', + label: 'Free Space', + isVisible: true + }, + { + name: 'unmappedFolders', + label: 'Unmapped Folders', + 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 && +
Unable to load root folders
+ } + + { + !error && isPopulated && +
+
+ Import movies you already have +
+ +
+ Some tips to ensure the import goes smoothly: +
    +
  • + Make sure your files include the quality in the name. eg. episode.s02e15.bluray.mkv +
  • +
  • + Point Radarr to the folder containing all of your movies not a specific one. eg. "{isWindows ? 'C:\\movies' : '/movies'}" and not "{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 new file mode 100644 index 000000000..a3d5b54d6 --- /dev/null +++ b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector.js @@ -0,0 +1,91 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { push } from 'react-router-redux'; +import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector'; +import { fetchRootFolders, addRootFolder, deleteRootFolder } from 'Store/Actions/rootFolderActions'; +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.Radarr.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/App.js b/frontend/src/App/App.js new file mode 100644 index 000000000..d87c62827 --- /dev/null +++ b/frontend/src/App/App.js @@ -0,0 +1,28 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import DocumentTitle from 'react-document-title'; +import { Provider } from 'react-redux'; +import { ConnectedRouter } from 'react-router-redux'; +import PageConnector from 'Components/Page/PageConnector'; +import AppRoutes from './AppRoutes'; + +function App({ store, history }) { + return ( + + + + + + + + + + ); +} + +App.propTypes = { + store: PropTypes.object.isRequired, + history: PropTypes.object.isRequired +}; + +export default App; diff --git a/frontend/src/App/AppRoutes.js b/frontend/src/App/AppRoutes.js new file mode 100644 index 000000000..dd6bfbae1 --- /dev/null +++ b/frontend/src/App/AppRoutes.js @@ -0,0 +1,232 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { Route, Redirect } from 'react-router-dom'; +import getPathWithUrlBase from 'Utilities/getPathWithUrlBase'; +import NotFound from 'Components/NotFound'; +import Switch from 'Components/Router/Switch'; +import MovieIndexConnector from 'Movie/Index/MovieIndexConnector'; +import AddNewMovieConnector from 'AddMovie/AddNewMovie/AddNewMovieConnector'; +import ImportMovies from 'AddMovie/ImportMovie/ImportMovies'; +import SeriesEditorConnector from 'Movie/Editor/SeriesEditorConnector'; +import MovieDetailsPageConnector from 'Movie/Details/MovieDetailsPageConnector'; +import CalendarPageConnector from 'Calendar/CalendarPageConnector'; +import HistoryConnector from 'Activity/History/HistoryConnector'; +import QueueConnector from 'Activity/Queue/QueueConnector'; +import BlacklistConnector from 'Activity/Blacklist/BlacklistConnector'; +import Settings from 'Settings/Settings'; +import MediaManagementConnector from 'Settings/MediaManagement/MediaManagementConnector'; +import Profiles from 'Settings/Profiles/Profiles'; +import Quality from 'Settings/Quality/Quality'; +import IndexerSettingsConnector from 'Settings/Indexers/IndexerSettingsConnector'; +import DownloadClientSettingsConnector from 'Settings/DownloadClients/DownloadClientSettingsConnector'; +import NetImportSettingsConnector from 'Settings/NetImport/NetImportSettingsConnector'; +import NotificationSettings from 'Settings/Notifications/NotificationSettings'; +import MetadataSettings from 'Settings/Metadata/MetadataSettings'; +import TagSettings from 'Settings/Tags/TagSettings'; +import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector'; +import UISettingsConnector from 'Settings/UI/UISettingsConnector'; +import Status from 'System/Status/Status'; +import Tasks from 'System/Tasks/Tasks'; +import BackupsConnector from 'System/Backup/BackupsConnector'; +import UpdatesConnector from 'System/Updates/UpdatesConnector'; +import LogsTableConnector from 'System/Events/LogsTableConnector'; +import Logs from 'System/Logs/Logs'; + +function AppRoutes(props) { + const { + app + } = props; + + return ( + + {/* + Movies + */} + + + + { + window.Radarr.urlBase && + { + return ( + + ); + }} + /> + } + + + + + + + + + + {/* + Calendar + */} + + + + {/* + Activity + */} + + + + + + + + {/* + Settings + */} + + + + + + + + + + + + + + + + + + + + + + + + + + {/* + System + */} + + + + + + + + + + + + + + {/* + Not Found + */} + + + + ); +} + +AppRoutes.propTypes = { + app: PropTypes.func.isRequired +}; + +export default AppRoutes; diff --git a/frontend/src/App/AppUpdatedModal.js b/frontend/src/App/AppUpdatedModal.js new file mode 100644 index 000000000..abc7f8832 --- /dev/null +++ b/frontend/src/App/AppUpdatedModal.js @@ -0,0 +1,30 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Modal from 'Components/Modal/Modal'; +import AppUpdatedModalContentConnector from './AppUpdatedModalContentConnector'; + +function AppUpdatedModal(props) { + const { + isOpen, + onModalClose + } = props; + + return ( + + + + ); +} + +AppUpdatedModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default AppUpdatedModal; diff --git a/frontend/src/App/AppUpdatedModalConnector.js b/frontend/src/App/AppUpdatedModalConnector.js new file mode 100644 index 000000000..a21afbc5a --- /dev/null +++ b/frontend/src/App/AppUpdatedModalConnector.js @@ -0,0 +1,12 @@ +import { connect } from 'react-redux'; +import AppUpdatedModal from './AppUpdatedModal'; + +function createMapDispatchToProps(dispatch, props) { + return { + onModalClose() { + location.reload(); + } + }; +} + +export default connect(null, createMapDispatchToProps)(AppUpdatedModal); diff --git a/frontend/src/App/AppUpdatedModalContent.css b/frontend/src/App/AppUpdatedModalContent.css new file mode 100644 index 000000000..37b89c9be --- /dev/null +++ b/frontend/src/App/AppUpdatedModalContent.css @@ -0,0 +1,15 @@ +.version { + margin: 0 3px; + font-weight: bold; +} + +.maintenance { + margin-top: 20px; +} + +.changes { + margin-top: 20px; + padding-bottom: 5px; + border-bottom: 1px solid #e5e5e5; + font-size: 18px; +} diff --git a/frontend/src/App/AppUpdatedModalContent.js b/frontend/src/App/AppUpdatedModalContent.js new file mode 100644 index 000000000..d22eb98b5 --- /dev/null +++ b/frontend/src/App/AppUpdatedModalContent.js @@ -0,0 +1,98 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { kinds } from 'Helpers/Props'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import Button from 'Components/Link/Button'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import UpdateChanges from 'System/Updates/UpdateChanges'; +import styles from './AppUpdatedModalContent.css'; + +function AppUpdatedModalContent(props) { + const { + version, + isPopulated, + error, + items, + onSeeChangesPress, + onModalClose + } = props; + + const update = items[0]; + + return ( + + + Radarr Updated + + + +
+ Version {version} of Radarr has been installed, in order to get the latest changes you'll need to reload Radarr. +
+ + { + isPopulated && !error && !!update && +
+ { + !update.changes && +
Maintenance release
+ } + + { + !!update.changes && +
+
+ What's new? +
+ + + + +
+ } +
+ } + + { + !isPopulated && !error && + + } +
+ + + + + + +
+ ); +} + +AppUpdatedModalContent.propTypes = { + version: PropTypes.string.isRequired, + isPopulated: PropTypes.bool.isRequired, + error: PropTypes.object, + items: PropTypes.arrayOf(PropTypes.object).isRequired, + onSeeChangesPress: PropTypes.func.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default AppUpdatedModalContent; diff --git a/frontend/src/App/AppUpdatedModalContentConnector.js b/frontend/src/App/AppUpdatedModalContentConnector.js new file mode 100644 index 000000000..325a1aa95 --- /dev/null +++ b/frontend/src/App/AppUpdatedModalContentConnector.js @@ -0,0 +1,76 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { fetchUpdates } from 'Store/Actions/systemActions'; +import AppUpdatedModalContent from './AppUpdatedModalContent'; + +function createMapStateToProps() { + return createSelector( + (state) => state.app.version, + (state) => state.system.updates, + (version, updates) => { + const { + isPopulated, + error, + items + } = updates; + + return { + version, + isPopulated, + error, + items + }; + } + ); +} + +function createMapDispatchToProps(dispatch, props) { + return { + dispatchFetchUpdates() { + dispatch(fetchUpdates()); + }, + + onSeeChangesPress() { + window.location = `${window.Radarr.urlBase}/system/updates`; + } + }; +} + +class AppUpdatedModalContentConnector extends Component { + + // + // Lifecycle + + componentDidMount() { + this.props.dispatchFetchUpdates(); + } + + componentDidUpdate(prevProps) { + if (prevProps.version !== this.props.version) { + this.props.dispatchFetchUpdates(); + } + } + + // + // Render + + render() { + const { + dispatchFetchUpdates, + ...otherProps + } = this.props; + + return ( + + ); + } +} + +AppUpdatedModalContentConnector.propTypes = { + version: PropTypes.string.isRequired, + dispatchFetchUpdates: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, createMapDispatchToProps)(AppUpdatedModalContentConnector); diff --git a/frontend/src/App/ColorImpairedContext.js b/frontend/src/App/ColorImpairedContext.js new file mode 100644 index 000000000..de98ac8fb --- /dev/null +++ b/frontend/src/App/ColorImpairedContext.js @@ -0,0 +1,6 @@ +import React from 'react'; + +const ColorImpairedContext = React.createContext(false); +export const ColorImpairedConsumer = ColorImpairedContext.Consumer; + +export default ColorImpairedContext; diff --git a/frontend/src/App/ConnectionLostModal.css b/frontend/src/App/ConnectionLostModal.css new file mode 100644 index 000000000..f0a9d220f --- /dev/null +++ b/frontend/src/App/ConnectionLostModal.css @@ -0,0 +1,3 @@ +.automatic { + margin-top: 20px; +} diff --git a/frontend/src/App/ConnectionLostModal.js b/frontend/src/App/ConnectionLostModal.js new file mode 100644 index 000000000..063b3f47f --- /dev/null +++ b/frontend/src/App/ConnectionLostModal.js @@ -0,0 +1,55 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { kinds } from 'Helpers/Props'; +import Button from 'Components/Link/Button'; +import Modal from 'Components/Modal/Modal'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import styles from './ConnectionLostModal.css'; + +function ConnectionLostModal(props) { + const { + isOpen, + onModalClose + } = props; + + return ( + + + + Connnection Lost + + + +
+ Radarr has lost it's connection to the backend and will need to be reloaded to restore functionality. +
+ +
+ Radarr will try to connect automatically, or you can click reload below. +
+
+ + + +
+
+ ); +} + +ConnectionLostModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default ConnectionLostModal; diff --git a/frontend/src/App/ConnectionLostModalConnector.js b/frontend/src/App/ConnectionLostModalConnector.js new file mode 100644 index 000000000..8ab8e3cd0 --- /dev/null +++ b/frontend/src/App/ConnectionLostModalConnector.js @@ -0,0 +1,12 @@ +import { connect } from 'react-redux'; +import ConnectionLostModal from './ConnectionLostModal'; + +function createMapDispatchToProps(dispatch, props) { + return { + onModalClose() { + location.reload(); + } + }; +} + +export default connect(undefined, createMapDispatchToProps)(ConnectionLostModal); diff --git a/frontend/src/Calendar/Agenda/Agenda.css b/frontend/src/Calendar/Agenda/Agenda.css new file mode 100644 index 000000000..0304d9db5 --- /dev/null +++ b/frontend/src/Calendar/Agenda/Agenda.css @@ -0,0 +1,3 @@ +.agenda { + margin-top: 10px; +} diff --git a/frontend/src/Calendar/Agenda/Agenda.js b/frontend/src/Calendar/Agenda/Agenda.js new file mode 100644 index 000000000..89472301d --- /dev/null +++ b/frontend/src/Calendar/Agenda/Agenda.js @@ -0,0 +1,38 @@ +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React from 'react'; +import AgendaEventConnector from './AgendaEventConnector'; +import styles from './Agenda.css'; + +function Agenda(props) { + const { + items + } = props; + + return ( +
+ { + items.map((item, index) => { + const momentDate = moment(item.airDateUtc); + const showDate = index === 0 || + !moment(items[index - 1].airDateUtc).isSame(momentDate, 'day'); + + return ( + + ); + }) + } +
+ ); +} + +Agenda.propTypes = { + items: PropTypes.arrayOf(PropTypes.object).isRequired +}; + +export default Agenda; diff --git a/frontend/src/Calendar/Agenda/AgendaConnector.js b/frontend/src/Calendar/Agenda/AgendaConnector.js new file mode 100644 index 000000000..b6f238873 --- /dev/null +++ b/frontend/src/Calendar/Agenda/AgendaConnector.js @@ -0,0 +1,14 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import Agenda from './Agenda'; + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar, + (calendar) => { + return calendar; + } + ); +} + +export default connect(createMapStateToProps)(Agenda); diff --git a/frontend/src/Calendar/Agenda/AgendaEvent.css b/frontend/src/Calendar/Agenda/AgendaEvent.css new file mode 100644 index 000000000..bf0df3f2c --- /dev/null +++ b/frontend/src/Calendar/Agenda/AgendaEvent.css @@ -0,0 +1,117 @@ +.event { + display: flex; + overflow-x: hidden; + padding: 5px; + border-bottom: 1px solid $borderColor; + font-size: 14px; + + &:hover { + background-color: $tableRowHoverBackgroundColor; + } +} + +.eventWrapper { + display: flex; + flex: 1 0 1px; + overflow-x: hidden; + padding-left: 6px; + border-left-width: 4px; + border-left-style: solid; +} + +.date { + flex: 0 0 250px; + font-weight: bold; +} + +.time { + flex: 0 0 120px; + margin-right: 10px; + border: none !important; +} + +.seriesTitle, +.episodeTitle { + @add-mixin truncate; + + flex: 0 1 300px; + margin-right: 10px; +} + +.episodeTitle { + flex: 1 1 1px; +} + +.seasonEpisodeNumber { + flex: 0 0 100px; +} + +.episodeSeparator { + display: none; +} + +.absoluteEpisodeNumber { + margin-left: 3px; +} + +.statusIcon { + margin-left: 3px; +} + +/* + * Status + */ + +.downloaded { + composes: downloaded from 'Calendar/Events/CalendarEvent.css'; +} + +.downloading { + composes: downloading from 'Calendar/Events/CalendarEvent.css'; +} + +.unmonitored { + composes: unmonitored from 'Calendar/Events/CalendarEvent.css'; +} + +.onAir { + composes: onAir from 'Calendar/Events/CalendarEvent.css'; +} + +.missing { + composes: missing from 'Calendar/Events/CalendarEvent.css'; +} + +.premiere { + composes: premiere from 'Calendar/Events/CalendarEvent.css'; +} + +@media only screen and (max-width: $breakpointSmall) { + .event { + flex-direction: column; + } + + .eventWrapper { + display: block; + flex: 0 0 auto; + } + + .date { + margin-left: 10px; + } + + .date, + .time, + .seriesTitle { + flex: 0 0 100%; + } + + .seasonEpisodeNumber { + flex: 0 0 auto; + } + + .episodeSeparator { + display: inline-block; + margin: 0 5px; + } +} diff --git a/frontend/src/Calendar/Agenda/AgendaEvent.js b/frontend/src/Calendar/Agenda/AgendaEvent.js new file mode 100644 index 000000000..22b33532e --- /dev/null +++ b/frontend/src/Calendar/Agenda/AgendaEvent.js @@ -0,0 +1,141 @@ +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { icons, kinds } from 'Helpers/Props'; +import getStatusStyle from 'Calendar/getStatusStyle'; +import Icon from 'Components/Icon'; +import Link from 'Components/Link/Link'; +import CalendarEventQueueDetails from 'Calendar/Events/CalendarEventQueueDetails'; +import MovieTitleLink from 'Movie/MovieTitleLink'; +import styles from './AgendaEvent.css'; + +class AgendaEvent extends Component { + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isDetailsModalOpen: false + }; + } + + // + // Listeners + + onPress = () => { + this.setState({ isDetailsModalOpen: true }); + } + + onDetailsModalClose = () => { + this.setState({ isDetailsModalOpen: false }); + } + + // + // Render + + render() { + const { + movieFile, + title, + titleSlug, + inCinemas, + monitored, + hasFile, + grabbed, + queueItem, + showDate, + showCutoffUnmetIcon, + longDateFormat, + colorImpairedMode + } = this.props; + + const startTime = moment(inCinemas); + const downloading = !!(queueItem || grabbed); + const isMonitored = monitored; + const statusStyle = getStatusStyle(hasFile, downloading, startTime, isMonitored); + + return ( +
+ +
+ { + showDate && + startTime.format(longDateFormat) + } +
+ +
+
+ +
+ + { + !!queueItem && + + + + } + + { + !queueItem && grabbed && + + } + + { + showCutoffUnmetIcon && + !!movieFile && + movieFile.qualityCutoffNotMet && + + } +
+ +
+ ); + } +} + +AgendaEvent.propTypes = { + id: PropTypes.number.isRequired, + episodeFile: PropTypes.object, + title: PropTypes.string.isRequired, + titleSlug: PropTypes.string.isRequired, + inCinemas: PropTypes.string.isRequired, + monitored: PropTypes.bool.isRequired, + hasFile: PropTypes.bool.isRequired, + grabbed: PropTypes.bool, + queueItem: PropTypes.object, + showDate: PropTypes.bool.isRequired, + showCutoffUnmetIcon: PropTypes.bool.isRequired, + timeFormat: PropTypes.string.isRequired, + longDateFormat: PropTypes.string.isRequired, + colorImpairedMode: PropTypes.bool.isRequired +}; + +export default AgendaEvent; diff --git a/frontend/src/Calendar/Agenda/AgendaEventConnector.js b/frontend/src/Calendar/Agenda/AgendaEventConnector.js new file mode 100644 index 000000000..ec6cae394 --- /dev/null +++ b/frontend/src/Calendar/Agenda/AgendaEventConnector.js @@ -0,0 +1,30 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createMovieFileSelector from 'Store/Selectors/createMovieFileSelector'; +import createMovieSelector from 'Store/Selectors/createMovieSelector'; +import createQueueItemSelector from 'Store/Selectors/createQueueItemSelector'; +import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; +import AgendaEvent from './AgendaEvent'; + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar.options, + createMovieSelector(), + createMovieFileSelector(), + createQueueItemSelector(), + createUISettingsSelector(), + (calendarOptions, series, episodeFile, queueItem, uiSettings) => { + return { + series, + episodeFile, + queueItem, + ...calendarOptions, + timeFormat: uiSettings.timeFormat, + longDateFormat: uiSettings.longDateFormat, + colorImpairedMode: uiSettings.enableColorImpairedMode + }; + } + ); +} + +export default connect(createMapStateToProps)(AgendaEvent); diff --git a/frontend/src/Calendar/Calendar.css b/frontend/src/Calendar/Calendar.css new file mode 100644 index 000000000..37e6ff618 --- /dev/null +++ b/frontend/src/Calendar/Calendar.css @@ -0,0 +1,8 @@ +.calendar { + flex-grow: 1; + width: 100%; +} + +.calendarContent { + width: 100%; +} diff --git a/frontend/src/Calendar/Calendar.js b/frontend/src/Calendar/Calendar.js new file mode 100644 index 000000000..6ceb1f3bb --- /dev/null +++ b/frontend/src/Calendar/Calendar.js @@ -0,0 +1,64 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import * as calendarViews from './calendarViews'; +import CalendarHeaderConnector from './Header/CalendarHeaderConnector'; +import DaysOfWeekConnector from './Day/DaysOfWeekConnector'; +import CalendarDaysConnector from './Day/CalendarDaysConnector'; +import AgendaConnector from './Agenda/AgendaConnector'; +import styles from './Calendar.css'; + +class Calendar extends Component { + + // + // Render + + render() { + const { + isFetching, + isPopulated, + error, + view + } = this.props; + + return ( +
+ { + isFetching && !isPopulated && + + } + + { + !isFetching && !!error && +
Unable to load the calendar
+ } + + { + !error && isPopulated && view === calendarViews.AGENDA && +
+ + +
+ } + + { + !error && isPopulated && view !== calendarViews.AGENDA && +
+ + + +
+ } +
+ ); + } +} + +Calendar.propTypes = { + isFetching: PropTypes.bool.isRequired, + isPopulated: PropTypes.bool.isRequired, + error: PropTypes.object, + view: PropTypes.string.isRequired +}; + +export default Calendar; diff --git a/frontend/src/Calendar/CalendarConnector.js b/frontend/src/Calendar/CalendarConnector.js new file mode 100644 index 000000000..ef0f40b86 --- /dev/null +++ b/frontend/src/Calendar/CalendarConnector.js @@ -0,0 +1,183 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; +import hasDifferentItems from 'Utilities/Object/hasDifferentItems'; +import selectUniqueIds from 'Utilities/Object/selectUniqueIds'; +import * as calendarActions from 'Store/Actions/calendarActions'; +import { fetchMovieFiles, clearMovieFiles } from 'Store/Actions/movieFileActions'; +import { fetchQueueDetails, clearQueueDetails } from 'Store/Actions/queueActions'; +import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector'; +import * as commandNames from 'Commands/commandNames'; +import Calendar from './Calendar'; + +const UPDATE_DELAY = 3600000; // 1 hour + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar, + (state) => state.settings.ui.item.firstDayOfWeek, + createCommandExecutingSelector(commandNames.REFRESH_MOVIE), + (calendar, firstDayOfWeek, isRefreshingMovie) => { + return { + ...calendar, + isRefreshingMovie, + firstDayOfWeek + }; + } + ); +} + +const mapDispatchToProps = { + ...calendarActions, + fetchMovieFiles, + clearMovieFiles, + fetchQueueDetails, + clearQueueDetails +}; + +class CalendarConnector extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.updateTimeoutId = null; + } + + componentDidMount() { + registerPagePopulator(this.repopulate); + this.props.gotoCalendarToday(); + this.scheduleUpdate(); + } + + componentDidUpdate(prevProps) { + const { + items, + time, + view, + isRefreshingMovie, + firstDayOfWeek + } = this.props; + + if (hasDifferentItems(prevProps.items, items)) { + const episodeIds = selectUniqueIds(items, 'id'); + const episodeFileIds = selectUniqueIds(items, 'episodeFileId'); + + if (items.length) { + this.props.fetchQueueDetails({ episodeIds }); + } + + if (episodeFileIds.length) { + this.props.fetchMovieFiles({ episodeFileIds }); + } + } + + if (prevProps.time !== time) { + this.scheduleUpdate(); + } + + if (prevProps.firstDayOfWeek !== firstDayOfWeek) { + this.props.fetchCalendar({ time, view }); + } + + if (prevProps.isRefreshingMovie && !isRefreshingMovie) { + this.props.fetchCalendar({ time, view }); + } + } + + componentWillUnmount() { + unregisterPagePopulator(this.repopulate); + this.props.clearCalendar(); + this.props.clearQueueDetails(); + this.props.clearMovieFiles(); + this.clearUpdateTimeout(); + } + + // + // Control + + repopulate = () => { + const { + time, + view + } = this.props; + + this.props.fetchQueueDetails({ time, view }); + this.props.fetchCalendar({ time, view }); + } + + scheduleUpdate = () => { + this.clearUpdateTimeout(); + + this.updateTimeoutId = setTimeout(this.updateCalendar, UPDATE_DELAY); + } + + clearUpdateTimeout = () => { + if (this.updateTimeoutId) { + clearTimeout(this.updateTimeoutId); + } + } + + updateCalendar = () => { + this.props.gotoCalendarToday(); + this.scheduleUpdate(); + } + + // + // Listeners + + onCalendarViewChange = (view) => { + this.props.setCalendarView({ view }); + } + + onTodayPress = () => { + this.props.gotoCalendarToday(); + } + + onPreviousPress = () => { + this.props.gotoCalendarPreviousRange(); + } + + onNextPress = () => { + this.props.gotoCalendarNextRange(); + } + + // + // Render + + render() { + return ( + + ); + } +} + +CalendarConnector.propTypes = { + time: PropTypes.string, + view: PropTypes.string.isRequired, + firstDayOfWeek: PropTypes.number.isRequired, + items: PropTypes.arrayOf(PropTypes.object).isRequired, + isRefreshingMovie: PropTypes.bool.isRequired, + setCalendarView: PropTypes.func.isRequired, + gotoCalendarToday: PropTypes.func.isRequired, + gotoCalendarPreviousRange: PropTypes.func.isRequired, + gotoCalendarNextRange: PropTypes.func.isRequired, + clearCalendar: PropTypes.func.isRequired, + fetchCalendar: PropTypes.func.isRequired, + fetchMovieFiles: PropTypes.func.isRequired, + clearMovieFiles: PropTypes.func.isRequired, + fetchQueueDetails: PropTypes.func.isRequired, + clearQueueDetails: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(CalendarConnector); diff --git a/frontend/src/Calendar/CalendarPage.css b/frontend/src/Calendar/CalendarPage.css new file mode 100644 index 000000000..776f3100f --- /dev/null +++ b/frontend/src/Calendar/CalendarPage.css @@ -0,0 +1,14 @@ +.calendarPageBody { + composes: contentBody from 'Components/Page/PageContentBody.css'; + + display: flex; +} + +.calendarInnerPageBody { + composes: innerContentBody from 'Components/Page/PageContentBody.css'; + + display: flex; + flex-direction: column; + flex-grow: 1; + width: 100%; +} diff --git a/frontend/src/Calendar/CalendarPage.js b/frontend/src/Calendar/CalendarPage.js new file mode 100644 index 000000000..7cb12da2a --- /dev/null +++ b/frontend/src/Calendar/CalendarPage.js @@ -0,0 +1,152 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { align, icons } from 'Helpers/Props'; +import PageContent from 'Components/Page/PageContent'; +import Measure from 'Components/Measure'; +import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector'; +import PageToolbar from 'Components/Page/Toolbar/PageToolbar'; +import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection'; +import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton'; +import FilterMenu from 'Components/Menu/FilterMenu'; +import NoMovie from 'Movie/NoMovie'; +import CalendarLinkModal from './iCal/CalendarLinkModal'; +import CalendarOptionsModal from './Options/CalendarOptionsModal'; +import LegendConnector from './Legend/LegendConnector'; +import CalendarConnector from './CalendarConnector'; +import styles from './CalendarPage.css'; + +const MINIMUM_DAY_WIDTH = 120; + +class CalendarPage extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isCalendarLinkModalOpen: false, + isOptionsModalOpen: false, + width: 0 + }; + } + + // + // Listeners + + onMeasure = ({ width }) => { + this.setState({ width }); + const days = Math.max(3, Math.min(7, Math.floor(width / MINIMUM_DAY_WIDTH))); + + this.props.onDaysCountChange(days); + } + + onGetCalendarLinkPress = () => { + this.setState({ isCalendarLinkModalOpen: true }); + } + + onGetCalendarLinkModalClose = () => { + this.setState({ isCalendarLinkModalOpen: false }); + } + + onOptionsPress = () => { + this.setState({ isOptionsModalOpen: true }); + } + + onOptionsModalClose = () => { + this.setState({ isOptionsModalOpen: false }); + } + + // + // Render + + render() { + const { + selectedFilterKey, + filters, + hasSeries, + onFilterSelect + } = this.props; + + const { + isCalendarLinkModalOpen, + isOptionsModalOpen + } = this.state; + + const isMeasured = this.state.width > 0; + let PageComponent = 'div'; + + if (isMeasured) { + PageComponent = hasSeries ? CalendarConnector : NoMovie; + } + + return ( + + + + + + + + + + + + + + + + + + + { + hasSeries && + + } + + + + + + + ); + } +} + +CalendarPage.propTypes = { + selectedFilterKey: PropTypes.string.isRequired, + filters: PropTypes.arrayOf(PropTypes.object).isRequired, + hasSeries: PropTypes.bool.isRequired, + onDaysCountChange: PropTypes.func.isRequired, + onFilterSelect: PropTypes.func.isRequired +}; + +export default CalendarPage; diff --git a/frontend/src/Calendar/CalendarPageConnector.js b/frontend/src/Calendar/CalendarPageConnector.js new file mode 100644 index 000000000..276d7a5e2 --- /dev/null +++ b/frontend/src/Calendar/CalendarPageConnector.js @@ -0,0 +1,36 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { setCalendarDaysCount, setCalendarFilter } from 'Store/Actions/calendarActions'; +import createMovieCountSelector from 'Store/Selectors/createMovieCountSelector'; +import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; +import CalendarPage from './CalendarPage'; + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar, + createMovieCountSelector(), + createUISettingsSelector(), + (calendar, seriesCount, uiSettings) => { + return { + selectedFilterKey: calendar.selectedFilterKey, + filters: calendar.filters, + colorImpairedMode: uiSettings.enableColorImpairedMode, + hasSeries: !!seriesCount + }; + } + ); +} + +function createMapDispatchToProps(dispatch, props) { + return { + onDaysCountChange(dayCount) { + dispatch(setCalendarDaysCount({ dayCount })); + }, + + onFilterSelect(selectedFilterKey) { + dispatch(setCalendarFilter({ selectedFilterKey })); + } + }; +} + +export default connect(createMapStateToProps, createMapDispatchToProps)(CalendarPage); diff --git a/frontend/src/Calendar/Day/CalendarDay.css b/frontend/src/Calendar/Day/CalendarDay.css new file mode 100644 index 000000000..1c7694f0b --- /dev/null +++ b/frontend/src/Calendar/Day/CalendarDay.css @@ -0,0 +1,25 @@ +.day { + flex: 1 0 14.28%; + overflow: hidden; + min-height: 70px; + border-bottom: 1px solid $borderColor; + border-left: 1px solid $borderColor; +} + +.isSingleDay { + width: 100%; +} + +.dayOfMonth { + padding-right: 5px; + border-bottom: 1px solid $borderColor; + text-align: right; +} + +.isToday { + background-color: $calendarTodayBackgroundColor; +} + +.isDifferentMonth { + color: $disabledColor; +} diff --git a/frontend/src/Calendar/Day/CalendarDay.js b/frontend/src/Calendar/Day/CalendarDay.js new file mode 100644 index 000000000..faa45b28b --- /dev/null +++ b/frontend/src/Calendar/Day/CalendarDay.js @@ -0,0 +1,74 @@ +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; +import * as calendarViews from 'Calendar/calendarViews'; +import CalendarEventConnector from 'Calendar/Events/CalendarEventConnector'; +import CalendarEventGroupConnector from 'Calendar/Events/CalendarEventGroupConnector'; +import styles from './CalendarDay.css'; + +function CalendarDay(props) { + const { + date, + time, + isTodaysDate, + events, + view, + onEventModalOpenToggle + } = props; + + return ( +
+ { + view === calendarViews.MONTH && +
+ {moment(date).date()} +
+ } +
+ { + events.map((event) => { + if (event.isGroup) { + return ( + + ); + } + + return ( + + ); + }) + } +
+
+ ); +} + +CalendarDay.propTypes = { + date: PropTypes.string.isRequired, + time: PropTypes.string.isRequired, + isTodaysDate: PropTypes.bool.isRequired, + events: PropTypes.arrayOf(PropTypes.object).isRequired, + view: PropTypes.string.isRequired, + onEventModalOpenToggle: PropTypes.func.isRequired +}; + +export default CalendarDay; diff --git a/frontend/src/Calendar/Day/CalendarDayConnector.js b/frontend/src/Calendar/Day/CalendarDayConnector.js new file mode 100644 index 000000000..8fd6cc5a1 --- /dev/null +++ b/frontend/src/Calendar/Day/CalendarDayConnector.js @@ -0,0 +1,91 @@ +import _ from 'lodash'; +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import CalendarDay from './CalendarDay'; + +function sort(items) { + return _.sortBy(items, (item) => { + if (item.isGroup) { + return moment(item.events[0].airDateUtc).unix(); + } + + return moment(item.airDateUtc).unix(); + }); +} + +function createCalendarEventsConnector() { + return createSelector( + (state, { date }) => date, + (state) => state.calendar.items, + (state) => state.calendar.options.collapseMultipleEpisodes, + (date, items, collapseMultipleEpisodes) => { + const filtered = _.filter(items, (item) => { + return moment(date).isSame(moment(item.airDateUtc), 'day'); + }); + + if (!collapseMultipleEpisodes) { + return sort(filtered); + } + + const groupedObject = _.groupBy(filtered, (item) => `${item.seriesId}-${item.seasonNumber}`); + const grouped = []; + + Object.keys(groupedObject).forEach((key) => { + const events = groupedObject[key]; + + if (events.length === 1) { + grouped.push(events[0]); + } else { + grouped.push({ + isGroup: true, + seriesId: events[0].seriesId, + seasonNumber: events[0].seasonNumber, + episodeIds: events.map((event) => event.id), + events: _.sortBy(events, (item) => moment(item.airDateUtc).unix()) + }); + } + }); + + const sorted = sort(grouped); + + return sorted; + } + ); +} + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar, + createCalendarEventsConnector(), + (calendar, events) => { + return { + time: calendar.time, + view: calendar.view, + events + }; + } + ); +} + +class CalendarDayConnector extends Component { + + // + // Render + + render() { + return ( + + ); + } +} + +CalendarDayConnector.propTypes = { + date: PropTypes.string.isRequired +}; + +export default connect(createMapStateToProps)(CalendarDayConnector); diff --git a/frontend/src/Calendar/Day/CalendarDays.css b/frontend/src/Calendar/Day/CalendarDays.css new file mode 100644 index 000000000..22005e3e6 --- /dev/null +++ b/frontend/src/Calendar/Day/CalendarDays.css @@ -0,0 +1,14 @@ +.days { + display: flex; + border-right: 1px solid $borderColor; +} + +.day, +.week, +.forecast { + flex-wrap: nowrap; +} + +.month { + flex-wrap: wrap; +} diff --git a/frontend/src/Calendar/Day/CalendarDays.js b/frontend/src/Calendar/Day/CalendarDays.js new file mode 100644 index 000000000..0a1a36172 --- /dev/null +++ b/frontend/src/Calendar/Day/CalendarDays.js @@ -0,0 +1,164 @@ +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import isToday from 'Utilities/Date/isToday'; +import * as calendarViews from 'Calendar/calendarViews'; +import CalendarDayConnector from './CalendarDayConnector'; +import styles from './CalendarDays.css'; + +class CalendarDays extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._touchStart = null; + + this.state = { + todaysDate: moment().startOf('day').toISOString(), + isEventModalOpen: false + }; + + this.updateTimeoutId = null; + } + + // Lifecycle + + componentDidMount() { + const view = this.props.view; + + if (view === calendarViews.MONTH) { + this.scheduleUpdate(); + } + + window.addEventListener('touchstart', this.onTouchStart); + window.addEventListener('touchend', this.onTouchEnd); + window.addEventListener('touchcancel', this.onTouchCancel); + window.addEventListener('touchmove', this.onTouchMove); + } + + componentWillUnmount() { + this.clearUpdateTimeout(); + + window.removeEventListener('touchstart', this.onTouchStart); + window.removeEventListener('touchend', this.onTouchEnd); + window.removeEventListener('touchcancel', this.onTouchCancel); + window.removeEventListener('touchmove', this.onTouchMove); + } + + // + // Control + + scheduleUpdate = () => { + this.clearUpdateTimeout(); + const todaysDate = moment().startOf('day'); + const diff = moment().diff(todaysDate.clone().add(1, 'day')); + + this.setState({ todaysDate: todaysDate.toISOString() }); + + this.updateTimeoutId = setTimeout(this.scheduleUpdate, diff); + } + + clearUpdateTimeout = () => { + if (this.updateTimeoutId) { + clearTimeout(this.updateTimeoutId); + } + } + + // + // Listeners + + onEventModalOpenToggle = (isEventModalOpen) => { + this.setState({ isEventModalOpen }); + } + + onTouchStart = (event) => { + const touches = event.touches; + const touchStart = touches[0].pageX; + + if (touches.length !== 1) { + return; + } + + if ( + touchStart < 50 || + this.props.isSidebarVisible || + this.state.isEventModalOpen + ) { + return; + } + + this._touchStart = touchStart; + } + + onTouchEnd = (event) => { + const touches = event.changedTouches; + const currentTouch = touches[0].pageX; + + if (!this._touchStart) { + return; + } + + if (currentTouch > this._touchStart && currentTouch - this._touchStart > 100) { + this.props.onNavigatePrevious(); + } else if (currentTouch < this._touchStart && this._touchStart - currentTouch > 100) { + this.props.onNavigateNext(); + } + + this._touchStart = null; + } + + onTouchCancel = (event) => { + this._touchStart = null; + } + + onTouchMove = (event) => { + if (!this._touchStart) { + return; + } + } + + // + // Render + + render() { + const { + dates, + view + } = this.props; + + return ( +
+ { + dates.map((date) => { + return ( + + ); + }) + } +
+ ); + } +} + +CalendarDays.propTypes = { + dates: PropTypes.arrayOf(PropTypes.string).isRequired, + view: PropTypes.string.isRequired, + isSidebarVisible: PropTypes.bool.isRequired, + onNavigatePrevious: PropTypes.func.isRequired, + onNavigateNext: PropTypes.func.isRequired +}; + +export default CalendarDays; diff --git a/frontend/src/Calendar/Day/CalendarDaysConnector.js b/frontend/src/Calendar/Day/CalendarDaysConnector.js new file mode 100644 index 000000000..3dea906a7 --- /dev/null +++ b/frontend/src/Calendar/Day/CalendarDaysConnector.js @@ -0,0 +1,25 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { gotoCalendarPreviousRange, gotoCalendarNextRange } from 'Store/Actions/calendarActions'; +import CalendarDays from './CalendarDays'; + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar, + (state) => state.app.isSidebarVisible, + (calendar, isSidebarVisible) => { + return { + dates: calendar.dates, + view: calendar.view, + isSidebarVisible + }; + } + ); +} + +const mapDispatchToProps = { + onNavigatePrevious: gotoCalendarPreviousRange, + onNavigateNext: gotoCalendarNextRange +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(CalendarDays); diff --git a/frontend/src/Calendar/Day/DayOfWeek.css b/frontend/src/Calendar/Day/DayOfWeek.css new file mode 100644 index 000000000..8c3552e55 --- /dev/null +++ b/frontend/src/Calendar/Day/DayOfWeek.css @@ -0,0 +1,13 @@ +.dayOfWeek { + flex: 1 0 14.28%; + background-color: #e4eaec; + text-align: center; +} + +.isSingleDay { + width: 100%; +} + +.isToday { + background-color: $calendarTodayBackgroundColor; +} diff --git a/frontend/src/Calendar/Day/DayOfWeek.js b/frontend/src/Calendar/Day/DayOfWeek.js new file mode 100644 index 000000000..d97671522 --- /dev/null +++ b/frontend/src/Calendar/Day/DayOfWeek.js @@ -0,0 +1,56 @@ +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import getRelativeDate from 'Utilities/Date/getRelativeDate'; +import * as calendarViews from 'Calendar/calendarViews'; +import styles from './DayOfWeek.css'; + +class DayOfWeek extends Component { + + // + // Render + + render() { + const { + date, + view, + isTodaysDate, + calendarWeekColumnHeader, + shortDateFormat, + showRelativeDates + } = this.props; + + const highlightToday = view !== calendarViews.MONTH && isTodaysDate; + const momentDate = moment(date); + let formatedDate = momentDate.format('dddd'); + + if (view === calendarViews.WEEK) { + formatedDate = momentDate.format(calendarWeekColumnHeader); + } else if (view === calendarViews.FORECAST) { + formatedDate = getRelativeDate(date, shortDateFormat, showRelativeDates); + } + + return ( +
+ {formatedDate} +
+ ); + } +} + +DayOfWeek.propTypes = { + date: PropTypes.string.isRequired, + view: PropTypes.string.isRequired, + isTodaysDate: PropTypes.bool.isRequired, + calendarWeekColumnHeader: PropTypes.string.isRequired, + shortDateFormat: PropTypes.string.isRequired, + showRelativeDates: PropTypes.bool.isRequired +}; + +export default DayOfWeek; diff --git a/frontend/src/Calendar/Day/DaysOfWeek.css b/frontend/src/Calendar/Day/DaysOfWeek.css new file mode 100644 index 000000000..518664633 --- /dev/null +++ b/frontend/src/Calendar/Day/DaysOfWeek.css @@ -0,0 +1,4 @@ +.daysOfWeek { + display: flex; + margin-top: 10px; +} diff --git a/frontend/src/Calendar/Day/DaysOfWeek.js b/frontend/src/Calendar/Day/DaysOfWeek.js new file mode 100644 index 000000000..a67777f7c --- /dev/null +++ b/frontend/src/Calendar/Day/DaysOfWeek.js @@ -0,0 +1,97 @@ +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import DayOfWeek from './DayOfWeek'; +import * as calendarViews from 'Calendar/calendarViews'; +import styles from './DaysOfWeek.css'; + +class DaysOfWeek extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + todaysDate: moment().startOf('day').toISOString() + }; + + this.updateTimeoutId = null; + } + + // Lifecycle + + componentDidMount() { + const view = this.props.view; + + if (view !== calendarViews.AGENDA || view !== calendarViews.MONTH) { + this.scheduleUpdate(); + } + } + + componentWillUnmount() { + this.clearUpdateTimeout(); + } + + // + // Control + + scheduleUpdate = () => { + this.clearUpdateTimeout(); + const todaysDate = moment().startOf('day'); + const diff = todaysDate.clone().add(1, 'day').diff(moment()); + + this.setState({ + todaysDate: todaysDate.toISOString() + }); + + this.updateTimeoutId = setTimeout(this.scheduleUpdate, diff); + } + + clearUpdateTimeout = () => { + if (this.updateTimeoutId) { + clearTimeout(this.updateTimeoutId); + } + } + + // + // Render + + render() { + const { + dates, + view, + ...otherProps + } = this.props; + + if (view === calendarViews.AGENDA) { + return null; + } + + return ( +
+ { + dates.map((date) => { + return ( + + ); + }) + } +
+ ); + } +} + +DaysOfWeek.propTypes = { + dates: PropTypes.arrayOf(PropTypes.string), + view: PropTypes.string.isRequired +}; + +export default DaysOfWeek; diff --git a/frontend/src/Calendar/Day/DaysOfWeekConnector.js b/frontend/src/Calendar/Day/DaysOfWeekConnector.js new file mode 100644 index 000000000..7f5cdef19 --- /dev/null +++ b/frontend/src/Calendar/Day/DaysOfWeekConnector.js @@ -0,0 +1,22 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; +import DaysOfWeek from './DaysOfWeek'; + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar, + createUISettingsSelector(), + (calendar, UiSettings) => { + return { + dates: calendar.dates.slice(0, 7), + view: calendar.view, + calendarWeekColumnHeader: UiSettings.calendarWeekColumnHeader, + shortDateFormat: UiSettings.shortDateFormat, + showRelativeDates: UiSettings.showRelativeDates + }; + } + ); +} + +export default connect(createMapStateToProps)(DaysOfWeek); diff --git a/frontend/src/Calendar/Events/CalendarEvent.css b/frontend/src/Calendar/Events/CalendarEvent.css new file mode 100644 index 000000000..3352d5127 --- /dev/null +++ b/frontend/src/Calendar/Events/CalendarEvent.css @@ -0,0 +1,78 @@ +.event { + overflow-x: hidden; + margin: 4px 2px; + padding: 5px; + border-bottom: 1px solid $borderColor; + border-left: 4px solid $borderColor; + font-size: 12px; +} + +.info, +.episodeInfo { + display: flex; +} + +.seriesTitle, +.episodeTitle { + @add-mixin truncate; + + flex: 1 0 1px; + margin-right: 10px; +} + +.seriesTitle { + color: #3a3f51; + font-size: 14px; +} + +.absoluteEpisodeNumber { + margin-left: 3px; +} + +.statusIcon { + margin-left: 3px; +} + +/* + * Status + */ + +.downloaded { + border-left-color: $successColor !important; +} + +.downloading { + border-left-color: $purple !important; +} + +.unmonitored { + border-left-color: $gray !important; + + &:global(.colorImpaired) { + background: repeating-linear-gradient(45deg, transparent, transparent 5px, $colorImpairedGradient 5px, $colorImpairedGradient 10px); + } +} + +.onAir { + border-left-color: $warningColor !important; + + &:global(.colorImpaired) { + background: repeating-linear-gradient(90deg, transparent, transparent 5px, $colorImpairedGradient 5px, $colorImpairedGradient 10px); + } +} + +.missing { + border-left-color: $dangerColor !important; + + &:global(.colorImpaired) { + background: repeating-linear-gradient(90deg, transparent, transparent 5px, $colorImpairedGradient 5px, $colorImpairedGradient 10px); + } +} + +.unaired { + border-left-color: $primaryColor !important; + + &:global(.colorImpaired) { + background: repeating-linear-gradient(90deg, transparent, transparent 5px, $colorImpairedGradient 5px, $colorImpairedGradient 10px); + } +} diff --git a/frontend/src/Calendar/Events/CalendarEvent.js b/frontend/src/Calendar/Events/CalendarEvent.js new file mode 100644 index 000000000..fbc21b8cf --- /dev/null +++ b/frontend/src/Calendar/Events/CalendarEvent.js @@ -0,0 +1,135 @@ +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { icons, kinds } from 'Helpers/Props'; +import getStatusStyle from 'Calendar/getStatusStyle'; +import Icon from 'Components/Icon'; +import Link from 'Components/Link/Link'; +import CalendarEventQueueDetails from './CalendarEventQueueDetails'; +import MovieTitleLink from 'Movie/MovieTitleLink'; +import styles from './CalendarEvent.css'; + +class CalendarEvent extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isDetailsModalOpen: false + }; + } + + // + // Listeners + + onPress = () => { + this.setState({ isDetailsModalOpen: true }, () => { + this.props.onEventModalOpenToggle(true); + }); + } + + onDetailsModalClose = () => { + this.setState({ isDetailsModalOpen: false }, () => { + this.props.onEventModalOpenToggle(false); + }); + } + + // + // Render + + render() { + const { + movieFile, + inCinemas, + title, + titleSlug, + monitored, + hasFile, + grabbed, + queueItem, + showCutoffUnmetIcon, + colorImpairedMode + } = this.props; + + const startTime = moment(inCinemas); + const isDownloading = !!(queueItem || grabbed); + const isMonitored = monitored; + const statusStyle = getStatusStyle(hasFile, isDownloading, startTime, isMonitored); + + return ( +
+ +
+
+ +
+ + { + !!queueItem && + + + + } + + { + !queueItem && grabbed && + + } + + { + showCutoffUnmetIcon && + !!movieFile && + movieFile.qualityCutoffNotMet && + + } +
+ + +
+ ); + } +} + +CalendarEvent.propTypes = { + id: PropTypes.number.isRequired, + movieFile: PropTypes.object, + title: PropTypes.string.isRequired, + titleSlug: PropTypes.string.isRequired, + inCinemas: PropTypes.string.isRequired, + monitored: PropTypes.bool.isRequired, + hasFile: PropTypes.bool.isRequired, + grabbed: PropTypes.bool, + queueItem: PropTypes.object, + showCutoffUnmetIcon: PropTypes.bool.isRequired, + timeFormat: PropTypes.string.isRequired, + colorImpairedMode: PropTypes.bool.isRequired, + onEventModalOpenToggle: PropTypes.func.isRequired +}; + +export default CalendarEvent; diff --git a/frontend/src/Calendar/Events/CalendarEventConnector.js b/frontend/src/Calendar/Events/CalendarEventConnector.js new file mode 100644 index 000000000..7da98888e --- /dev/null +++ b/frontend/src/Calendar/Events/CalendarEventConnector.js @@ -0,0 +1,29 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createMovieFileSelector from 'Store/Selectors/createMovieFileSelector'; +import createMovieSelector from 'Store/Selectors/createMovieSelector'; +import createQueueItemSelector from 'Store/Selectors/createQueueItemSelector'; +import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; +import CalendarEvent from './CalendarEvent'; + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar.options, + createMovieSelector(), + createMovieFileSelector(), + createQueueItemSelector(), + createUISettingsSelector(), + (calendarOptions, series, episodeFile, queueItem, uiSettings) => { + return { + series, + episodeFile, + queueItem, + ...calendarOptions, + timeFormat: uiSettings.timeFormat, + colorImpairedMode: uiSettings.enableColorImpairedMode + }; + } + ); +} + +export default connect(createMapStateToProps)(CalendarEvent); diff --git a/frontend/src/Calendar/Events/CalendarEventGroup.css b/frontend/src/Calendar/Events/CalendarEventGroup.css new file mode 100644 index 000000000..e16498f25 --- /dev/null +++ b/frontend/src/Calendar/Events/CalendarEventGroup.css @@ -0,0 +1,82 @@ +.eventGroup { + overflow-x: hidden; + margin: 4px 2px; + padding: 5px; + border-bottom: 1px solid $borderColor; + border-left: 4px solid $borderColor; + font-size: 12px; +} + +.info, +.airingInfo { + display: flex; +} + +.seriesTitle { + @add-mixin truncate; + + flex: 1 0 1px; + margin-right: 10px; + color: #3a3f51; + font-size: 14px; +} + +.airTime { + flex: 1 0 1px; +} + +.episodeInfo { + margin-left: 10px; +} + +.absoluteEpisodeNumber { + margin-left: 3px; +} + +.expandContainerInline { + display: flex; + justify-content: flex-end; + flex: 1 0 20px; +} + +.expandContainer, +.collapseContainer { + display: flex; + justify-content: center; +} + +.collapseContainer { + margin-bottom: 5px; +} + +.statusIcon { + margin-left: 3px; +} + +/* + * Status + */ + +.downloaded { + composes: downloaded from 'Calendar/Events/CalendarEvent.css'; +} + +.downloading { + composes: downloading from 'Calendar/Events/CalendarEvent.css'; +} + +.unmonitored { + composes: unmonitored from 'Calendar/Events/CalendarEvent.css'; +} + +.onAir { + composes: onAir from 'Calendar/Events/CalendarEvent.css'; +} + +.missing { + composes: missing from 'Calendar/Events/CalendarEvent.css'; +} + +.premiere { + composes: premiere from 'Calendar/Events/CalendarEvent.css'; +} diff --git a/frontend/src/Calendar/Events/CalendarEventGroup.js b/frontend/src/Calendar/Events/CalendarEventGroup.js new file mode 100644 index 000000000..186085c52 --- /dev/null +++ b/frontend/src/Calendar/Events/CalendarEventGroup.js @@ -0,0 +1,200 @@ +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { icons, kinds } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import Link from 'Components/Link/Link'; +import getStatusStyle from 'Calendar/getStatusStyle'; +import CalendarEventConnector from 'Calendar/Events/CalendarEventConnector'; +import styles from './CalendarEventGroup.css'; + +function getEventsInfo(events) { + let files = 0; + let queued = 0; + let monitored = 0; + let absoluteEpisodeNumbers = 0; + + events.forEach((event) => { + if (event.episodeFileId) { + files++; + } + + if (event.queued) { + queued++; + } + + if (event.monitored) { + monitored++; + } + + if (event.absoluteEpisodeNumber) { + absoluteEpisodeNumbers++; + } + }); + + return { + allDownloaded: files === events.length, + anyQueued: queued > 0, + anyMonitored: monitored > 0, + allAbsoluteEpisodeNumbers: absoluteEpisodeNumbers === events.length + }; +} + +class CalendarEventGroup extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isExpanded: false + }; + } + + // + // Listeners + + onExpandPress = () => { + this.setState({ isExpanded: !this.state.isExpanded }); + } + + // + // Render + + render() { + const { + series, + events, + isDownloading, + showEpisodeInformation, + showFinaleIcon, + colorImpairedMode, + onEventModalOpenToggle + } = this.props; + + const { isExpanded } = this.state; + const { + allDownloaded, + anyQueued, + anyMonitored + } = getEventsInfo(events); + const anyDownloading = isDownloading || anyQueued; + const firstEpisode = events[0]; + const lastEpisode = events[events.length -1]; + const airDateUtc = firstEpisode.airDateUtc; + const startTime = moment(airDateUtc); + const endTime = moment(lastEpisode.airDateUtc).add(series.runtime, 'minutes'); + const seasonNumber = firstEpisode.seasonNumber; + const statusStyle = getStatusStyle(allDownloaded, anyDownloading, startTime, endTime, anyMonitored); + + if (isExpanded) { + return ( +
+ { + events.map((event) => { + if (event.isGroup) { + return null; + } + + return ( + + ); + }) + } + + + + +
+ ); + } + + return ( +
+
+
+ {series.title} +
+ + { + anyDownloading && + + } + + { + firstEpisode.episodeNumber === 1 && seasonNumber > 0 && + + } + + { + showFinaleIcon && + lastEpisode.episodeNumber !== 1 && + seasonNumber > 0 && + lastEpisode.episodeNumber === series.seasons.find((season) => season.seasonNumber === seasonNumber).statistics.totalEpisodeCount && + + } +
+ + { + showEpisodeInformation && + + + + } +
+ ); + } +} + +CalendarEventGroup.propTypes = { + series: PropTypes.object.isRequired, + events: PropTypes.arrayOf(PropTypes.object).isRequired, + isDownloading: PropTypes.bool.isRequired, + showEpisodeInformation: PropTypes.bool.isRequired, + showFinaleIcon: PropTypes.bool.isRequired, + timeFormat: PropTypes.string.isRequired, + colorImpairedMode: PropTypes.bool.isRequired, + onEventModalOpenToggle: PropTypes.func.isRequired +}; + +export default CalendarEventGroup; diff --git a/frontend/src/Calendar/Events/CalendarEventGroupConnector.js b/frontend/src/Calendar/Events/CalendarEventGroupConnector.js new file mode 100644 index 000000000..e13e5b998 --- /dev/null +++ b/frontend/src/Calendar/Events/CalendarEventGroupConnector.js @@ -0,0 +1,37 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createMovieSelector from 'Store/Selectors/createMovieSelector'; +import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; +import CalendarEventGroup from './CalendarEventGroup'; + +function createIsDownloadingSelector() { + return createSelector( + (state, { episodeIds }) => episodeIds, + (state) => state.queue.details, + (episodeIds, details) => { + return details.items.some((item) => { + return episodeIds.includes(item.episode.id); + }); + } + ); +} + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar.options, + createMovieSelector(), + createIsDownloadingSelector(), + createUISettingsSelector(), + (calendarOptions, series, isDownloading, uiSettings) => { + return { + series, + isDownloading, + ...calendarOptions, + timeFormat: uiSettings.timeFormat, + colorImpairedMode: uiSettings.enableColorImpairedMode + }; + } + ); +} + +export default connect(createMapStateToProps)(CalendarEventGroup); diff --git a/frontend/src/Calendar/Events/CalendarEventQueueDetails.js b/frontend/src/Calendar/Events/CalendarEventQueueDetails.js new file mode 100644 index 000000000..81d81465c --- /dev/null +++ b/frontend/src/Calendar/Events/CalendarEventQueueDetails.js @@ -0,0 +1,50 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import colors from 'Styles/Variables/colors'; +import CircularProgressBar from 'Components/CircularProgressBar'; +import QueueDetails from 'Activity/Queue/QueueDetails'; + +function CalendarEventQueueDetails(props) { + const { + title, + size, + sizeleft, + estimatedCompletionTime, + status, + errorMessage + } = props; + + const progress = (100 - sizeleft / size * 100); + + return ( + + +
+ } + /> + ); +} + +CalendarEventQueueDetails.propTypes = { + title: PropTypes.string.isRequired, + size: PropTypes.number.isRequired, + sizeleft: PropTypes.number.isRequired, + estimatedCompletionTime: PropTypes.string, + status: PropTypes.string.isRequired, + errorMessage: PropTypes.string +}; + +export default CalendarEventQueueDetails; diff --git a/frontend/src/Calendar/Header/CalendarHeader.css b/frontend/src/Calendar/Header/CalendarHeader.css new file mode 100644 index 000000000..1127bb3c3 --- /dev/null +++ b/frontend/src/Calendar/Header/CalendarHeader.css @@ -0,0 +1,53 @@ +.header { + display: flex; +} + +.navigationButtons { + flex: 1 1 33%; + text-align: left; +} + +.todayButton { + composes: button from 'Components/Link/Button.css'; + + margin-left: 5px; +} + +.titleDesktop, +.titleMobile { + text-align: center; + font-size: 18px; +} + +.titleMobile { + margin-bottom: 5px; +} + +.viewButtonsContainer { + display: flex; + justify-content: flex-end; + flex: 1 1 33%; +} + +.viewMenu { + composes: menu from 'Components/Menu/Menu.css'; + + line-height: 31px; +} + +.loading { + composes: loading from 'Components/Loading/LoadingIndicator.css'; + + margin-top: 5px; + margin-right: 10px; +} + +@media only screen and (max-width: $breakpointSmall) { + .navigationButtons { + flex: 1 0 50%; + } + + .viewButtonsContainer { + flex: 0 0 100px; + } +} diff --git a/frontend/src/Calendar/Header/CalendarHeader.js b/frontend/src/Calendar/Header/CalendarHeader.js new file mode 100644 index 000000000..6736e4b8c --- /dev/null +++ b/frontend/src/Calendar/Header/CalendarHeader.js @@ -0,0 +1,224 @@ +import moment from 'moment'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { align, icons } from 'Helpers/Props'; +import Button from 'Components/Link/Button'; +import Icon from 'Components/Icon'; +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 ViewMenuItem from 'Components/Menu/ViewMenuItem'; +import * as calendarViews from 'Calendar/calendarViews'; +import CalendarHeaderViewButton from './CalendarHeaderViewButton'; +import styles from './CalendarHeader.css'; + +function getTitle(time, start, end, view, longDateFormat) { + const timeMoment = moment(time); + const startMoment = moment(start); + const endMoment = moment(end); + + if (view === 'day') { + return timeMoment.format(longDateFormat); + } else if (view === 'month') { + return timeMoment.format('MMMM YYYY'); + } else if (view === 'agenda') { + return 'Agenda'; + } + + let startFormat = 'MMM D YYYY'; + let endFormat = 'MMM D YYYY'; + + if (startMoment.isSame(endMoment, 'month')) { + startFormat = 'MMM D'; + endFormat = 'D YYYY'; + } else if (startMoment.isSame(endMoment, 'year')) { + startFormat = 'MMM D'; + endFormat = 'MMM D YYYY'; + } + + return `${startMoment.format(startFormat)} \u2014 ${endMoment.format(endFormat)}`; +} + +// TODO Convert to a stateful Component so we can track view internally when changed + +class CalendarHeader extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + view: props.view + }; + } + + componentDidUpdate(prevProps) { + const view = this.props.view; + + if (prevProps.view !== view) { + this.setState({ view }); + } + } + + // + // Listeners + + onViewChange = (view) => { + this.setState({ view }, () => { + this.props.onViewChange(view); + }); + } + + // + // Render + + render() { + const { + isFetching, + time, + start, + end, + longDateFormat, + isSmallScreen, + onTodayPress, + onPreviousPress, + onNextPress + } = this.props; + + const view = this.state.view; + + const title = getTitle(time, start, end, view, longDateFormat); + + return ( +
+ { + isSmallScreen && +
+ {title} +
+ } + +
+
+ + + + + +
+ + { + !isSmallScreen && +
+ {title} +
+ } + +
+ { + isFetching && + + } + + { + isSmallScreen ? + + + + + + + + Forecast + + + + Day + + + + Agenda + + + : + +
+ + + +
+ } +
+
+
+ ); + } +} + +CalendarHeader.propTypes = { + isFetching: PropTypes.bool.isRequired, + time: PropTypes.string.isRequired, + start: PropTypes.string.isRequired, + end: PropTypes.string.isRequired, + view: PropTypes.oneOf(calendarViews.all).isRequired, + isSmallScreen: PropTypes.bool.isRequired, + longDateFormat: PropTypes.string.isRequired, + onViewChange: PropTypes.func.isRequired, + onTodayPress: PropTypes.func.isRequired, + onPreviousPress: PropTypes.func.isRequired, + onNextPress: PropTypes.func.isRequired +}; + +export default CalendarHeader; diff --git a/frontend/src/Calendar/Header/CalendarHeaderConnector.js b/frontend/src/Calendar/Header/CalendarHeaderConnector.js new file mode 100644 index 000000000..c96cf2869 --- /dev/null +++ b/frontend/src/Calendar/Header/CalendarHeaderConnector.js @@ -0,0 +1,84 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; +import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; +import { setCalendarView, gotoCalendarToday, gotoCalendarPreviousRange, gotoCalendarNextRange } from 'Store/Actions/calendarActions'; +import CalendarHeader from './CalendarHeader'; + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar, + createDimensionsSelector(), + createUISettingsSelector(), + (calendar, dimensions, uiSettings) => { + const result = _.pick(calendar, [ + 'isFetching', + 'view', + 'time', + 'start', + 'end' + ]); + + result.isSmallScreen = dimensions.isSmallScreen; + result.longDateFormat = uiSettings.longDateFormat; + + return result; + } + ); +} + +const mapDispatchToProps = { + setCalendarView, + gotoCalendarToday, + gotoCalendarPreviousRange, + gotoCalendarNextRange +}; + +class CalendarHeaderConnector extends Component { + + // + // Listeners + + onViewChange = (view) => { + this.props.setCalendarView({ view }); + } + + onTodayPress = () => { + this.props.gotoCalendarToday(); + } + + onPreviousPress = () => { + this.props.gotoCalendarPreviousRange(); + } + + onNextPress = () => { + this.props.gotoCalendarNextRange(); + } + + // + // Render + + render() { + return ( + + ); + } +} + +CalendarHeaderConnector.propTypes = { + setCalendarView: PropTypes.func.isRequired, + gotoCalendarToday: PropTypes.func.isRequired, + gotoCalendarPreviousRange: PropTypes.func.isRequired, + gotoCalendarNextRange: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(CalendarHeaderConnector); diff --git a/frontend/src/Calendar/Header/CalendarHeaderViewButton.js b/frontend/src/Calendar/Header/CalendarHeaderViewButton.js new file mode 100644 index 000000000..8dd5ae9f0 --- /dev/null +++ b/frontend/src/Calendar/Header/CalendarHeaderViewButton.js @@ -0,0 +1,45 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import titleCase from 'Utilities/String/titleCase'; +import Button from 'Components/Link/Button'; +import * as calendarViews from 'Calendar/calendarViews'; +// import styles from './CalendarHeaderViewButton.css'; + +class CalendarHeaderViewButton extends Component { + + // + // Listeners + + onPress = () => { + this.props.onPress(this.props.view); + } + + // + // Render + + render() { + const { + view, + selectedView, + ...otherProps + } = this.props; + + return ( + + ); + } +} + +CalendarHeaderViewButton.propTypes = { + view: PropTypes.oneOf(calendarViews.all).isRequired, + selectedView: PropTypes.oneOf(calendarViews.all).isRequired, + onPress: PropTypes.func.isRequired +}; + +export default CalendarHeaderViewButton; diff --git a/frontend/src/Calendar/Legend/Legend.css b/frontend/src/Calendar/Legend/Legend.css new file mode 100644 index 000000000..296cbd9d5 --- /dev/null +++ b/frontend/src/Calendar/Legend/Legend.css @@ -0,0 +1,6 @@ +.legend { + display: flex; + flex-wrap: wrap; + margin-top: 10px; + padding: 3px 0; +} diff --git a/frontend/src/Calendar/Legend/Legend.js b/frontend/src/Calendar/Legend/Legend.js new file mode 100644 index 000000000..9bc6303f3 --- /dev/null +++ b/frontend/src/Calendar/Legend/Legend.js @@ -0,0 +1,109 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons, kinds } from 'Helpers/Props'; +import LegendItem from './LegendItem'; +import LegendIconItem from './LegendIconItem'; +import styles from './Legend.css'; + +function Legend(props) { + const { + showFinaleIcon, + showSpecialIcon, + showCutoffUnmetIcon, + colorImpairedMode + } = props; + + const iconsToShow = []; + if (showFinaleIcon) { + iconsToShow.push( + + ); + } + + if (showSpecialIcon) { + iconsToShow.push( + + ); + } + + if (showCutoffUnmetIcon) { + iconsToShow.push( + + ); + } + + return ( +
+
+ + + +
+ +
+ + + +
+ +
+ + + {iconsToShow[0]} +
+ + { + iconsToShow.length > 1 && +
+ {iconsToShow[1]} + {iconsToShow[2]} +
+ } +
+ ); +} + +Legend.propTypes = { + showFinaleIcon: PropTypes.bool.isRequired, + showSpecialIcon: PropTypes.bool.isRequired, + showCutoffUnmetIcon: PropTypes.bool.isRequired, + colorImpairedMode: PropTypes.bool.isRequired +}; + +export default Legend; diff --git a/frontend/src/Calendar/Legend/LegendConnector.js b/frontend/src/Calendar/Legend/LegendConnector.js new file mode 100644 index 000000000..30bbc4adb --- /dev/null +++ b/frontend/src/Calendar/Legend/LegendConnector.js @@ -0,0 +1,19 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; +import Legend from './Legend'; + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar.options, + createUISettingsSelector(), + (calendarOptions, uiSettings) => { + return { + ...calendarOptions, + colorImpairedMode: uiSettings.enableColorImpairedMode + }; + } + ); +} + +export default connect(createMapStateToProps)(Legend); diff --git a/frontend/src/Calendar/Legend/LegendIconItem.css b/frontend/src/Calendar/Legend/LegendIconItem.css new file mode 100644 index 000000000..01db0ba5a --- /dev/null +++ b/frontend/src/Calendar/Legend/LegendIconItem.css @@ -0,0 +1,10 @@ +.legendIconItem { + margin: 3px 0; + margin-right: 6px; + width: 150px; + cursor: default; +} + +.icon { + margin-right: 5px; +} diff --git a/frontend/src/Calendar/Legend/LegendIconItem.js b/frontend/src/Calendar/Legend/LegendIconItem.js new file mode 100644 index 000000000..13e106784 --- /dev/null +++ b/frontend/src/Calendar/Legend/LegendIconItem.js @@ -0,0 +1,37 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Icon from 'Components/Icon'; +import styles from './LegendIconItem.css'; + +function LegendIconItem(props) { + const { + name, + icon, + kind, + tooltip + } = props; + + return ( +
+ + + {name} +
+ ); +} + +LegendIconItem.propTypes = { + name: PropTypes.string.isRequired, + icon: PropTypes.object.isRequired, + kind: PropTypes.string.isRequired, + tooltip: PropTypes.string.isRequired +}; + +export default LegendIconItem; diff --git a/frontend/src/Calendar/Legend/LegendItem.css b/frontend/src/Calendar/Legend/LegendItem.css new file mode 100644 index 000000000..d146e9d68 --- /dev/null +++ b/frontend/src/Calendar/Legend/LegendItem.css @@ -0,0 +1,41 @@ +.legendItem { + margin: 3px 0; + margin-right: 6px; + padding-left: 5px; + width: 150px; + border-left-width: 4px; + border-left-style: solid; + cursor: default; +} + +/* + * Status + */ + +.downloaded { + composes: downloaded from 'Calendar/Events/CalendarEvent.css'; +} + +.downloading { + composes: downloading from 'Calendar/Events/CalendarEvent.css'; +} + +.unmonitored { + composes: unmonitored from 'Calendar/Events/CalendarEvent.css'; +} + +.onAir { + composes: onAir from 'Calendar/Events/CalendarEvent.css'; +} + +.missing { + composes: missing from 'Calendar/Events/CalendarEvent.css'; +} + +.premiere { + composes: premiere from 'Calendar/Events/CalendarEvent.css'; +} + +.unaired { + composes: unaired from 'Calendar/Events/CalendarEvent.css'; +} diff --git a/frontend/src/Calendar/Legend/LegendItem.js b/frontend/src/Calendar/Legend/LegendItem.js new file mode 100644 index 000000000..961f48b86 --- /dev/null +++ b/frontend/src/Calendar/Legend/LegendItem.js @@ -0,0 +1,36 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; +import titleCase from 'Utilities/String/titleCase'; +import styles from './LegendItem.css'; + +function LegendItem(props) { + const { + name, + status, + tooltip, + colorImpairedMode + } = props; + + return ( +
+ {name ? name : titleCase(status)} +
+ ); +} + +LegendItem.propTypes = { + name: PropTypes.string, + status: PropTypes.string.isRequired, + tooltip: PropTypes.string.isRequired, + colorImpairedMode: PropTypes.bool.isRequired +}; + +export default LegendItem; diff --git a/frontend/src/Calendar/Options/CalendarOptionsModal.js b/frontend/src/Calendar/Options/CalendarOptionsModal.js new file mode 100644 index 000000000..b68c83f30 --- /dev/null +++ b/frontend/src/Calendar/Options/CalendarOptionsModal.js @@ -0,0 +1,29 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Modal from 'Components/Modal/Modal'; +import CalendarOptionsModalContentConnector from './CalendarOptionsModalContentConnector'; + +function CalendarOptionsModal(props) { + const { + isOpen, + onModalClose + } = props; + + return ( + + + + ); +} + +CalendarOptionsModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default CalendarOptionsModal; diff --git a/frontend/src/Calendar/Options/CalendarOptionsModalContent.js b/frontend/src/Calendar/Options/CalendarOptionsModalContent.js new file mode 100644 index 000000000..9ff7b3f82 --- /dev/null +++ b/frontend/src/Calendar/Options/CalendarOptionsModalContent.js @@ -0,0 +1,258 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { inputTypes } from 'Helpers/Props'; +import FieldSet from 'Components/FieldSet'; +import Button from 'Components/Link/Button'; +import Form from 'Components/Form/Form'; +import FormGroup from 'Components/Form/FormGroup'; +import FormLabel from 'Components/Form/FormLabel'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import { firstDayOfWeekOptions, weekColumnOptions, timeFormatOptions } from 'Settings/UI/UISettings'; + +class CalendarOptionsModalContent extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + const { + firstDayOfWeek, + calendarWeekColumnHeader, + timeFormat, + enableColorImpairedMode + } = props; + + this.state = { + firstDayOfWeek, + calendarWeekColumnHeader, + timeFormat, + enableColorImpairedMode + }; + } + + componentDidUpdate(prevProps) { + const { + firstDayOfWeek, + calendarWeekColumnHeader, + timeFormat, + enableColorImpairedMode + } = this.props; + + if ( + prevProps.firstDayOfWeek !== firstDayOfWeek || + prevProps.calendarWeekColumnHeader !== calendarWeekColumnHeader || + prevProps.timeFormat !== timeFormat || + prevProps.enableColorImpairedMode !== enableColorImpairedMode + ) { + this.setState({ + firstDayOfWeek, + calendarWeekColumnHeader, + timeFormat, + enableColorImpairedMode + }); + } + } + + // + // Listeners + + onOptionInputChange = ({ name, value }) => { + const { + dispatchSetCalendarOption + } = this.props; + + dispatchSetCalendarOption({ [name]: value }); + } + + onGlobalInputChange = ({ name, value }) => { + const { + dispatchSaveUISettings + } = this.props; + + const setting = { [name]: value }; + + this.setState(setting, () => { + dispatchSaveUISettings(setting); + }); + } + + onLinkFocus = (event) => { + event.target.select(); + } + + // + // Render + + render() { + const { + collapseMultipleEpisodes, + showEpisodeInformation, + showFinaleIcon, + showSpecialIcon, + showCutoffUnmetIcon, + onModalClose + } = this.props; + + const { + firstDayOfWeek, + calendarWeekColumnHeader, + timeFormat, + enableColorImpairedMode + } = this.state; + + return ( + + + Calendar Options + + + +
+
+ + Collapse Multiple Episodes + + + + + + Show Episode Information + + + + + + Icon for Finales + + + + + + Icon for Specials + + + + + + Icon for Cutoff Unmet + + + +
+
+ +
+
+ + First Day of Week + + + + + + Week Column Header + + + + + + Time Format + + + + Enable Color-Impaired Mode + + + + +
+
+
+ + + + +
+ ); + } +} + +CalendarOptionsModalContent.propTypes = { + collapseMultipleEpisodes: PropTypes.bool.isRequired, + showEpisodeInformation: PropTypes.bool.isRequired, + showFinaleIcon: PropTypes.bool.isRequired, + showSpecialIcon: PropTypes.bool.isRequired, + showCutoffUnmetIcon: PropTypes.bool.isRequired, + firstDayOfWeek: PropTypes.number.isRequired, + calendarWeekColumnHeader: PropTypes.string.isRequired, + timeFormat: PropTypes.string.isRequired, + enableColorImpairedMode: PropTypes.bool.isRequired, + dispatchSetCalendarOption: PropTypes.func.isRequired, + dispatchSaveUISettings: PropTypes.func.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default CalendarOptionsModalContent; diff --git a/frontend/src/Calendar/Options/CalendarOptionsModalContentConnector.js b/frontend/src/Calendar/Options/CalendarOptionsModalContentConnector.js new file mode 100644 index 000000000..eb979f74e --- /dev/null +++ b/frontend/src/Calendar/Options/CalendarOptionsModalContentConnector.js @@ -0,0 +1,25 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { setCalendarOption } from 'Store/Actions/calendarActions'; +import CalendarOptionsModalContent from './CalendarOptionsModalContent'; +import { saveUISettings } from 'Store/Actions/settingsActions'; + +function createMapStateToProps() { + return createSelector( + (state) => state.calendar.options, + (state) => state.settings.ui.item, + (options, uiSettings) => { + return { + ...options, + ...uiSettings + }; + } + ); +} + +const mapDispatchToProps = { + dispatchSetCalendarOption: setCalendarOption, + dispatchSaveUISettings: saveUISettings +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(CalendarOptionsModalContent); diff --git a/frontend/src/Calendar/calendarViews.js b/frontend/src/Calendar/calendarViews.js new file mode 100644 index 000000000..627e1bb61 --- /dev/null +++ b/frontend/src/Calendar/calendarViews.js @@ -0,0 +1,4 @@ +export const MONTH = 'month'; +export const AGENDA = 'agenda'; + +export const all = [MONTH, AGENDA]; diff --git a/frontend/src/Calendar/getStatusStyle.js b/frontend/src/Calendar/getStatusStyle.js new file mode 100644 index 000000000..871cccd5b --- /dev/null +++ b/frontend/src/Calendar/getStatusStyle.js @@ -0,0 +1,26 @@ +/* eslint max-params: 0 */ +import moment from 'moment'; + +function getStatusStyle(hasFile, downloading, startTime, isMonitored) { + const currentTime = moment(); + + if (hasFile) { + return 'downloaded'; + } + + if (downloading) { + return 'downloading'; + } + + if (!isMonitored) { + return 'unmonitored'; + } + + if (startTime.isBefore(currentTime) && !hasFile) { + return 'missing'; + } + + return 'unaired'; +} + +export default getStatusStyle; diff --git a/frontend/src/Calendar/iCal/CalendarLinkModal.js b/frontend/src/Calendar/iCal/CalendarLinkModal.js new file mode 100644 index 000000000..8cc487c16 --- /dev/null +++ b/frontend/src/Calendar/iCal/CalendarLinkModal.js @@ -0,0 +1,29 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Modal from 'Components/Modal/Modal'; +import CalendarLinkModalContentConnector from './CalendarLinkModalContentConnector'; + +function CalendarLinkModal(props) { + const { + isOpen, + onModalClose + } = props; + + return ( + + + + ); +} + +CalendarLinkModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default CalendarLinkModal; diff --git a/frontend/src/Calendar/iCal/CalendarLinkModalContent.js b/frontend/src/Calendar/iCal/CalendarLinkModalContent.js new file mode 100644 index 000000000..600a4ba61 --- /dev/null +++ b/frontend/src/Calendar/iCal/CalendarLinkModalContent.js @@ -0,0 +1,221 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons, inputTypes, kinds, sizes } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import Button from 'Components/Link/Button'; +import ClipboardButton from 'Components/Link/ClipboardButton'; +import Form from 'Components/Form/Form'; +import FormGroup from 'Components/Form/FormGroup'; +import FormLabel from 'Components/Form/FormLabel'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import FormInputButton from 'Components/Form/FormInputButton'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; + +function getUrls(state) { + const { + unmonitored, + premieresOnly, + asAllDay, + tags + } = state; + + let icalUrl = `${window.location.host}${window.Radarr.urlBase}/feed/calendar/Radarr.ics?`; + + if (unmonitored) { + icalUrl += 'unmonitored=true&'; + } + + if (premieresOnly) { + icalUrl += 'premieresOnly=true&'; + } + + if (asAllDay) { + icalUrl += 'asAllDay=true&'; + } + + if (tags.length) { + icalUrl += `tags=${tags.toString()}&`; + } + + icalUrl += `apikey=${window.Radarr.apiKey}`; + + const iCalHttpUrl = `${window.location.protocol}//${icalUrl}`; + const iCalWebCalUrl = `webcal://${icalUrl}`; + + return { + iCalHttpUrl, + iCalWebCalUrl + }; +} + +class CalendarLinkModalContent extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + const defaultState = { + unmonitored: false, + premieresOnly: false, + asAllDay: false, + tags: [] + }; + + const urls = getUrls(defaultState); + + this.state = { + ...defaultState, + ...urls + }; + } + + // + // Listeners + + onInputChange = ({ name, value }) => { + const state = { + ...this.state, + [name]: value + }; + + const urls = getUrls(state); + + this.setState({ + [name]: value, + ...urls + }); + } + + onLinkFocus = (event) => { + event.target.select(); + } + + // + // Render + + render() { + const { + onModalClose + } = this.props; + + const { + unmonitored, + premieresOnly, + asAllDay, + tags, + iCalHttpUrl, + iCalWebCalUrl + } = this.state; + + return ( + + + Radarr Calendar Feed + + + +
+ + Include Unmonitored + + + + + + Season Premieres Only + + + + + + Show as All-Day Events + + + + + + Tags + + + + + + iCal Feed + + , + + + + + ]} + onChange={this.onInputChange} + onFocus={this.onLinkFocus} + /> + +
+
+ + + + +
+ ); + } +} + +CalendarLinkModalContent.propTypes = { + tagList: PropTypes.arrayOf(PropTypes.object).isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default CalendarLinkModalContent; diff --git a/frontend/src/Calendar/iCal/CalendarLinkModalContentConnector.js b/frontend/src/Calendar/iCal/CalendarLinkModalContentConnector.js new file mode 100644 index 000000000..e10c5c3f9 --- /dev/null +++ b/frontend/src/Calendar/iCal/CalendarLinkModalContentConnector.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createTagsSelector from 'Store/Selectors/createTagsSelector'; +import CalendarLinkModalContent from './CalendarLinkModalContent'; + +function createMapStateToProps() { + return createSelector( + createTagsSelector(), + (tagList) => { + return { + tagList + }; + } + ); +} + +export default connect(createMapStateToProps)(CalendarLinkModalContent); diff --git a/frontend/src/Commands/commandNames.js b/frontend/src/Commands/commandNames.js new file mode 100644 index 000000000..fc73bafdb --- /dev/null +++ b/frontend/src/Commands/commandNames.js @@ -0,0 +1,18 @@ +export const APPLICATION_UPDATE = 'ApplicationUpdate'; +export const BACKUP = 'Backup'; +export const CHECK_FOR_FINISHED_DOWNLOAD = 'CheckForFinishedDownload'; +export const CLEAR_BLACKLIST = 'ClearBlacklist'; +export const CLEAR_LOGS = 'ClearLog'; +export const CUTOFF_UNMET_EPISODE_SEARCH = 'CutoffUnmetEpisodeSearch'; +export const DELETE_LOG_FILES = 'DeleteLogFiles'; +export const DELETE_UPDATE_LOG_FILES = 'DeleteUpdateLogFiles'; +export const DOWNLOADED_EPSIODES_SCAN = 'DownloadedEpisodesScan'; +export const INTERACTIVE_IMPORT = 'ManualImport'; +export const MISSING_EPISODE_SEARCH = 'MissingEpisodeSearch'; +export const MOVE_MOVIE = 'MoveMovie'; +export const REFRESH_MOVIE = 'RefreshMovie'; +export const RENAME_FILES = 'RenameFiles'; +export const RENAME_SERIES = 'RenameSeries'; +export const RESET_API_KEY = 'ResetApiKey'; +export const RSS_SYNC = 'RssSync'; +export const MOVIE_SEARCH = 'MoviesSearch'; diff --git a/frontend/src/Components/Alert.css b/frontend/src/Components/Alert.css new file mode 100644 index 000000000..312fbb4f2 --- /dev/null +++ b/frontend/src/Components/Alert.css @@ -0,0 +1,31 @@ +.alert { + display: block; + margin: 5px; + padding: 15px; + border: 1px solid transparent; + border-radius: 4px; +} + +.danger { + border-color: $alertDangerBorderColor; + background-color: $alertDangerBackgroundColor; + color: $alertDangerColor; +} + +.info { + border-color: $alertInfoBorderColor; + background-color: $alertInfoBackgroundColor; + color: $alertInfoColor; +} + +.success { + border-color: $alertSuccessBorderColor; + background-color: $alertSuccessBackgroundColor; + color: $alertSuccessColor; +} + +.warning { + border-color: $alertWarningBorderColor; + background-color: $alertWarningBackgroundColor; + color: $alertWarningColor; +} diff --git a/frontend/src/Components/Alert.js b/frontend/src/Components/Alert.js new file mode 100644 index 000000000..dc19a418c --- /dev/null +++ b/frontend/src/Components/Alert.js @@ -0,0 +1,32 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; +import { kinds } from 'Helpers/Props'; +import styles from './Alert.css'; + +function Alert({ className, kind, children, ...otherProps }) { + return ( +
+ {children} +
+ ); +} + +Alert.propTypes = { + className: PropTypes.string.isRequired, + kind: PropTypes.oneOf(kinds.all).isRequired, + children: PropTypes.node.isRequired +}; + +Alert.defaultProps = { + className: styles.alert, + kind: kinds.INFO +}; + +export default Alert; diff --git a/frontend/src/Components/Card.css b/frontend/src/Components/Card.css new file mode 100644 index 000000000..b54bbcdf4 --- /dev/null +++ b/frontend/src/Components/Card.css @@ -0,0 +1,19 @@ +.card { + position: relative; + margin: 10px; + padding: 10px; + border-radius: 3px; + background-color: $white; + box-shadow: 0 0 10px 1px $cardShadowColor; + color: $defaultColor; +} + +.underlay { + @add-mixin cover; +} + +.overlay { + @add-mixin linkOverlay; + + position: relative; +} diff --git a/frontend/src/Components/Card.js b/frontend/src/Components/Card.js new file mode 100644 index 000000000..c5a4d164c --- /dev/null +++ b/frontend/src/Components/Card.js @@ -0,0 +1,60 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Link from 'Components/Link/Link'; +import styles from './Card.css'; + +class Card extends Component { + + // + // Render + + render() { + const { + className, + overlayClassName, + overlayContent, + children, + onPress + } = this.props; + + if (overlayContent) { + return ( +
+ + +
+ {children} +
+
+ ); + } + + return ( + + {children} + + ); + } +} + +Card.propTypes = { + className: PropTypes.string.isRequired, + overlayClassName: PropTypes.string.isRequired, + overlayContent: PropTypes.bool.isRequired, + children: PropTypes.node.isRequired, + onPress: PropTypes.func.isRequired +}; + +Card.defaultProps = { + className: styles.card, + overlayClassName: styles.overlay, + overlayContent: false +}; + +export default Card; diff --git a/frontend/src/Components/CircularProgressBar.css b/frontend/src/Components/CircularProgressBar.css new file mode 100644 index 000000000..32b349404 --- /dev/null +++ b/frontend/src/Components/CircularProgressBar.css @@ -0,0 +1,21 @@ +.circularProgressBarContainer { + position: relative; + display: inline-block; + vertical-align: top; + text-align: center; +} + +.circularProgressBar { + position: absolute; + top: 0; + left: 0; + transform: rotate(-90deg); + transform-origin: center center; +} + +.circularProgressBarText { + position: absolute; + width: 100%; + height: 100%; + font-weight: bold; +} diff --git a/frontend/src/Components/CircularProgressBar.js b/frontend/src/Components/CircularProgressBar.js new file mode 100644 index 000000000..b526eef3b --- /dev/null +++ b/frontend/src/Components/CircularProgressBar.js @@ -0,0 +1,139 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import colors from 'Styles/Variables/colors'; +import styles from './CircularProgressBar.css'; + +class CircularProgressBar extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + progress: 0 + }; + } + + componentDidMount() { + this._progressStep(); + } + + componentDidUpdate(prevProps) { + const progress = this.props.progress; + + if (prevProps.progress !== progress) { + this._cancelProgressStep(); + this._progressStep(); + } + } + + componentWillUnmount() { + this._cancelProgressStep(); + } + + // + // Control + + _progressStep() { + this.requestAnimationFrame = window.requestAnimationFrame(() => { + this.setState({ + progress: this.state.progress + 1 + }, () => { + if (this.state.progress < this.props.progress) { + this._progressStep(); + } + }); + }); + } + + _cancelProgressStep() { + if (this.requestAnimationFrame) { + window.cancelAnimationFrame(this.requestAnimationFrame); + } + } + + // + // Render + + render() { + const { + className, + containerClassName, + size, + strokeWidth, + strokeColor, + showProgressText + } = this.props; + + const progress = this.state.progress; + + const center = size / 2; + const radius = center - strokeWidth; + const circumference = Math.PI * (radius * 2); + const sizeInPixels = `${size}px`; + const strokeDashoffset = ((100 - progress) / 100) * circumference; + const progressText = `${Math.round(progress)}%`; + + return ( +
+ + + + + { + showProgressText && +
+ {progressText} +
+ } +
+ ); + } +} + +CircularProgressBar.propTypes = { + className: PropTypes.string, + containerClassName: PropTypes.string, + size: PropTypes.number, + progress: PropTypes.number.isRequired, + strokeWidth: PropTypes.number, + strokeColor: PropTypes.string, + showProgressText: PropTypes.bool +}; + +CircularProgressBar.defaultProps = { + className: styles.circularProgressBar, + containerClassName: styles.circularProgressBarContainer, + size: 60, + strokeWidth: 5, + strokeColor: colors.radarrYellow, + showProgressText: false +}; + +export default CircularProgressBar; diff --git a/frontend/src/Components/DescriptionList/DescriptionList.css b/frontend/src/Components/DescriptionList/DescriptionList.css new file mode 100644 index 000000000..230347f80 --- /dev/null +++ b/frontend/src/Components/DescriptionList/DescriptionList.css @@ -0,0 +1,4 @@ +.descriptionList { + margin-top: 0; + margin-bottom: 0; +} diff --git a/frontend/src/Components/DescriptionList/DescriptionList.js b/frontend/src/Components/DescriptionList/DescriptionList.js new file mode 100644 index 000000000..be2c87c55 --- /dev/null +++ b/frontend/src/Components/DescriptionList/DescriptionList.js @@ -0,0 +1,33 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import styles from './DescriptionList.css'; + +class DescriptionList extends Component { + + // + // Render + + render() { + const { + className, + children + } = this.props; + + return ( +
+ {children} +
+ ); + } +} + +DescriptionList.propTypes = { + className: PropTypes.string.isRequired, + children: PropTypes.node +}; + +DescriptionList.defaultProps = { + className: styles.descriptionList +}; + +export default DescriptionList; diff --git a/frontend/src/Components/DescriptionList/DescriptionListItem.js b/frontend/src/Components/DescriptionList/DescriptionListItem.js new file mode 100644 index 000000000..4ba70bf33 --- /dev/null +++ b/frontend/src/Components/DescriptionList/DescriptionListItem.js @@ -0,0 +1,44 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import DescriptionListItemTitle from './DescriptionListItemTitle'; +import DescriptionListItemDescription from './DescriptionListItemDescription'; + +class DescriptionListItem extends Component { + + // + // Render + + render() { + const { + titleClassName, + descriptionClassName, + title, + data + } = this.props; + + return ( + + + {title} + + + + {data} + + + ); + } +} + +DescriptionListItem.propTypes = { + titleClassName: PropTypes.string, + descriptionClassName: PropTypes.string, + title: PropTypes.string, + data: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.node]) +}; + +export default DescriptionListItem; diff --git a/frontend/src/Components/DescriptionList/DescriptionListItemDescription.css b/frontend/src/Components/DescriptionList/DescriptionListItemDescription.css new file mode 100644 index 000000000..b23415a76 --- /dev/null +++ b/frontend/src/Components/DescriptionList/DescriptionListItemDescription.css @@ -0,0 +1,13 @@ +.description { + line-height: $lineHeight; +} + +.description { + margin-left: 0; +} + +@media (min-width: 768px) { + .description { + margin-left: 180px; + } +} diff --git a/frontend/src/Components/DescriptionList/DescriptionListItemDescription.js b/frontend/src/Components/DescriptionList/DescriptionListItemDescription.js new file mode 100644 index 000000000..4ef3c015e --- /dev/null +++ b/frontend/src/Components/DescriptionList/DescriptionListItemDescription.js @@ -0,0 +1,27 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import styles from './DescriptionListItemDescription.css'; + +function DescriptionListItemDescription(props) { + const { + className, + children + } = props; + + return ( +
+ {children} +
+ ); +} + +DescriptionListItemDescription.propTypes = { + className: PropTypes.string.isRequired, + children: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.node]) +}; + +DescriptionListItemDescription.defaultProps = { + className: styles.description +}; + +export default DescriptionListItemDescription; diff --git a/frontend/src/Components/DescriptionList/DescriptionListItemTitle.css b/frontend/src/Components/DescriptionList/DescriptionListItemTitle.css new file mode 100644 index 000000000..e496e463d --- /dev/null +++ b/frontend/src/Components/DescriptionList/DescriptionListItemTitle.css @@ -0,0 +1,18 @@ +.title { + line-height: $lineHeight; +} + +.title { + font-weight: bold; +} + +@media (min-width: 768px) { + .title { + @add-mixin truncate; + + float: left; + clear: left; + width: 160px; + text-align: right; + } +} diff --git a/frontend/src/Components/DescriptionList/DescriptionListItemTitle.js b/frontend/src/Components/DescriptionList/DescriptionListItemTitle.js new file mode 100644 index 000000000..e1632c1cf --- /dev/null +++ b/frontend/src/Components/DescriptionList/DescriptionListItemTitle.js @@ -0,0 +1,27 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import styles from './DescriptionListItemTitle.css'; + +function DescriptionListItemTitle(props) { + const { + className, + children + } = props; + + return ( +
+ {children} +
+ ); +} + +DescriptionListItemTitle.propTypes = { + className: PropTypes.string.isRequired, + children: PropTypes.string +}; + +DescriptionListItemTitle.defaultProps = { + className: styles.title +}; + +export default DescriptionListItemTitle; diff --git a/frontend/src/Components/DragPreviewLayer.css b/frontend/src/Components/DragPreviewLayer.css new file mode 100644 index 000000000..46f721fef --- /dev/null +++ b/frontend/src/Components/DragPreviewLayer.css @@ -0,0 +1,9 @@ +.dragLayer { + position: fixed; + top: 0; + left: 0; + z-index: 9999; + width: 100%; + height: 100%; + pointer-events: none; +} diff --git a/frontend/src/Components/DragPreviewLayer.js b/frontend/src/Components/DragPreviewLayer.js new file mode 100644 index 000000000..a111df70e --- /dev/null +++ b/frontend/src/Components/DragPreviewLayer.js @@ -0,0 +1,22 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import styles from './DragPreviewLayer.css'; + +function DragPreviewLayer({ children, ...otherProps }) { + return ( +
+ {children} +
+ ); +} + +DragPreviewLayer.propTypes = { + children: PropTypes.node, + className: PropTypes.string +}; + +DragPreviewLayer.defaultProps = { + className: styles.dragLayer +}; + +export default DragPreviewLayer; diff --git a/frontend/src/Components/Error/ErrorBoundary.js b/frontend/src/Components/Error/ErrorBoundary.js new file mode 100644 index 000000000..50fcf98b5 --- /dev/null +++ b/frontend/src/Components/Error/ErrorBoundary.js @@ -0,0 +1,62 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import * as sentry from '@sentry/browser'; + +class ErrorBoundary extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + error: null, + info: null + }; + } + + componentDidCatch(error, info) { + this.setState({ + error, + info + }); + + sentry.captureException(error); + } + + // + // Render + + render() { + const { + children, + errorComponent: ErrorComponent, + ...otherProps + } = this.props; + + const { + error, + info + } = this.state; + + if (error) { + return ( + + ); + } + + return children; + } +} + +ErrorBoundary.propTypes = { + children: PropTypes.node.isRequired, + errorComponent: PropTypes.func.isRequired +}; + +export default ErrorBoundary; diff --git a/frontend/src/Components/Error/ErrorBoundaryError.css b/frontend/src/Components/Error/ErrorBoundaryError.css new file mode 100644 index 000000000..b6d1f917e --- /dev/null +++ b/frontend/src/Components/Error/ErrorBoundaryError.css @@ -0,0 +1,38 @@ +.container { + text-align: center; +} + +.message { + margin: 50px 0; + text-align: center; + font-weight: 300; + font-size: 36px; +} + +.imageContainer { + display: flex; + justify-content: center; + flex: 0 0 auto; +} + +.image { + height: 350px; +} + +.details { + margin: 20px; + text-align: left; + white-space: pre-wrap; +} + +@media only screen and (max-width: $breakpointMedium) { + .image { + height: 250px; + } +} + +@media only screen and (max-width: $breakpointSmall) { + .image { + height: 150px; + } +} diff --git a/frontend/src/Components/Error/ErrorBoundaryError.js b/frontend/src/Components/Error/ErrorBoundaryError.js new file mode 100644 index 000000000..05cf8165a --- /dev/null +++ b/frontend/src/Components/Error/ErrorBoundaryError.js @@ -0,0 +1,60 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import styles from './ErrorBoundaryError.css'; + +function ErrorBoundaryError(props) { + const { + className, + messageClassName, + detailsClassName, + message, + error, + info + } = props; + + return ( +
+
+ {message} +
+ +
+ +
+ +
+ { + error && +
+ {error.toString()} +
+ } + +
+ {info.componentStack} +
+
+
+ ); +} + +ErrorBoundaryError.propTypes = { + className: PropTypes.string.isRequired, + messageClassName: PropTypes.string.isRequired, + detailsClassName: PropTypes.string.isRequired, + message: PropTypes.string.isRequired, + error: PropTypes.object.isRequired, + info: PropTypes.object.isRequired +}; + +ErrorBoundaryError.defaultProps = { + className: styles.container, + messageClassName: styles.message, + detailsClassName: styles.details, + message: 'There was an error loading this content' +}; + +export default ErrorBoundaryError; diff --git a/frontend/src/Components/FieldSet.css b/frontend/src/Components/FieldSet.css new file mode 100644 index 000000000..daf3bdf2e --- /dev/null +++ b/frontend/src/Components/FieldSet.css @@ -0,0 +1,19 @@ +.fieldSet { + margin: 0; + margin-bottom: 20px; + padding: 0; + min-width: 0; + border: 0; +} + +.legend { + display: block; + margin-bottom: 21px; + padding: 0; + width: 100%; + border: 0; + border-bottom: 1px solid #e5e5e5; + color: #3a3f51; + font-size: 21px; + line-height: inherit; +} diff --git a/frontend/src/Components/FieldSet.js b/frontend/src/Components/FieldSet.js new file mode 100644 index 000000000..76e68a934 --- /dev/null +++ b/frontend/src/Components/FieldSet.js @@ -0,0 +1,33 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import styles from './FieldSet.css'; + +class FieldSet extends Component { + + // + // Render + + render() { + const { + legend, + children + } = this.props; + + return ( +
+ + {legend} + + {children} +
+ ); + } + +} + +FieldSet.propTypes = { + legend: PropTypes.oneOfType([PropTypes.node, PropTypes.string]), + children: PropTypes.node +}; + +export default FieldSet; diff --git a/frontend/src/Components/FileBrowser/FileBrowserModal.css b/frontend/src/Components/FileBrowser/FileBrowserModal.css new file mode 100644 index 000000000..30b936800 --- /dev/null +++ b/frontend/src/Components/FileBrowser/FileBrowserModal.css @@ -0,0 +1,5 @@ +.modal { + composes: modal from 'Components/Modal/Modal.css'; + + height: 600px; +} diff --git a/frontend/src/Components/FileBrowser/FileBrowserModal.js b/frontend/src/Components/FileBrowser/FileBrowserModal.js new file mode 100644 index 000000000..6b58dbb8c --- /dev/null +++ b/frontend/src/Components/FileBrowser/FileBrowserModal.js @@ -0,0 +1,39 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Modal from 'Components/Modal/Modal'; +import FileBrowserModalContentConnector from './FileBrowserModalContentConnector'; +import styles from './FileBrowserModal.css'; + +class FileBrowserModal extends Component { + + // + // Render + + render() { + const { + isOpen, + onModalClose, + ...otherProps + } = this.props; + + return ( + + + + ); + } +} + +FileBrowserModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default FileBrowserModal; diff --git a/frontend/src/Components/FileBrowser/FileBrowserModalContent.css b/frontend/src/Components/FileBrowser/FileBrowserModalContent.css new file mode 100644 index 000000000..9ae11f0bd --- /dev/null +++ b/frontend/src/Components/FileBrowser/FileBrowserModalContent.css @@ -0,0 +1,33 @@ +.modalBody { + composes: modalBody from 'Components/Modal/ModalBody.css'; + + display: flex; + flex-direction: column; +} + +.mappedDrivesWarning { + composes: alert from 'Components/Alert.css'; + + margin: 0; + margin-bottom: 20px; +} + +.faqLink { + color: $alertWarningColor; + font-weight: bold; +} + +.pathInput { + composes: pathInputWrapper from 'Components/Form/PathInput.css'; + + flex: 0 0 auto; +} + +.scroller { + margin-top: 20px; +} + +.loading { + display: inline-block; + margin-right: auto; +} diff --git a/frontend/src/Components/FileBrowser/FileBrowserModalContent.js b/frontend/src/Components/FileBrowser/FileBrowserModalContent.js new file mode 100644 index 000000000..cc8bc7529 --- /dev/null +++ b/frontend/src/Components/FileBrowser/FileBrowserModalContent.js @@ -0,0 +1,253 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import ReactDOM from 'react-dom'; +import { kinds, scrollDirections } from 'Helpers/Props'; +import Alert from 'Components/Alert'; +import Button from 'Components/Link/Button'; +import Link from 'Components/Link/Link'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import Scroller from 'Components/Scroller/Scroller'; +import Table from 'Components/Table/Table'; +import TableBody from 'Components/Table/TableBody'; +import PathInput from 'Components/Form/PathInput'; +import FileBrowserRow from './FileBrowserRow'; +import styles from './FileBrowserModalContent.css'; + +const columns = [ + { + name: 'type', + label: 'Type', + isVisible: true + }, + { + name: 'name', + label: 'Name', + isVisible: true + } +]; + +class FileBrowserModalContent extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._scrollerNode = null; + + this.state = { + isFileBrowserModalOpen: false, + currentPath: props.value + }; + } + + componentDidUpdate(prevProps, prevState) { + const { + currentPath + } = this.props; + + if ( + currentPath !== this.state.currentPath && + currentPath !== prevState.currentPath + ) { + this.setState({ currentPath }); + this._scrollerNode.scrollTop = 0; + } + } + + // + // Control + + setScrollerRef = (ref) => { + if (ref) { + this._scrollerNode = ReactDOM.findDOMNode(ref); + } else { + this._scrollerNode = null; + } + } + + // + // Listeners + + onPathInputChange = ({ value }) => { + this.setState({ currentPath: value }); + } + + onRowPress = (path) => { + this.props.onFetchPaths(path); + } + + onOkPress = () => { + this.props.onChange({ + name: this.props.name, + value: this.state.currentPath + }); + + this.props.onClearPaths(); + this.props.onModalClose(); + } + + // + // Render + + render() { + const { + isFetching, + isPopulated, + error, + parent, + directories, + files, + isWindowsService, + onModalClose, + ...otherProps + } = this.props; + + const emptyParent = parent === ''; + + return ( + + + File Browser + + + + { + isWindowsService && + + Mapped network drives are not available when running as a Windows Service, see the FAQ for more information. + + } + + + + + { + !!error && +
Error loading contents
+ } + + { + isPopulated && !error && + + + { + emptyParent && + + } + + { + !emptyParent && parent && + + } + + { + directories.map((directory) => { + return ( + + ); + }) + } + + { + files.map((file) => { + return ( + + ); + }) + } + +
+ } +
+
+ + + { + isFetching && + + } + + + + + +
+ ); + } +} + +FileBrowserModalContent.propTypes = { + name: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + isFetching: PropTypes.bool.isRequired, + isPopulated: PropTypes.bool.isRequired, + error: PropTypes.object, + parent: PropTypes.string, + currentPath: PropTypes.string.isRequired, + directories: PropTypes.arrayOf(PropTypes.object).isRequired, + files: PropTypes.arrayOf(PropTypes.object).isRequired, + isWindowsService: PropTypes.bool.isRequired, + onFetchPaths: PropTypes.func.isRequired, + onClearPaths: PropTypes.func.isRequired, + onChange: PropTypes.func.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default FileBrowserModalContent; diff --git a/frontend/src/Components/FileBrowser/FileBrowserModalContentConnector.js b/frontend/src/Components/FileBrowser/FileBrowserModalContentConnector.js new file mode 100644 index 000000000..fe577b896 --- /dev/null +++ b/frontend/src/Components/FileBrowser/FileBrowserModalContentConnector.js @@ -0,0 +1,101 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { fetchPaths, clearPaths } from 'Store/Actions/pathActions'; +import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector'; +import FileBrowserModalContent from './FileBrowserModalContent'; + +function createMapStateToProps() { + return createSelector( + (state) => state.paths, + createSystemStatusSelector(), + (paths, systemStatus) => { + const { + isFetching, + isPopulated, + error, + parent, + currentPath, + directories, + files + } = paths; + + const filteredPaths = _.filter([...directories, ...files], ({ path }) => { + return path.toLowerCase().startsWith(currentPath.toLowerCase()); + }); + + return { + isFetching, + isPopulated, + error, + parent, + currentPath, + directories, + files, + paths: filteredPaths, + isWindowsService: systemStatus.isWindows && systemStatus.mode === 'service' + }; + } + ); +} + +const mapDispatchToProps = { + fetchPaths, + clearPaths +}; + +class FileBrowserModalContentConnector extends Component { + + // Lifecycle + + componentDidMount() { + this.props.fetchPaths({ + path: this.props.value, + allowFoldersWithoutTrailingSlashes: true + }); + } + + // + // Listeners + + onFetchPaths = (path) => { + this.props.fetchPaths({ + path, + allowFoldersWithoutTrailingSlashes: true + }); + } + + onClearPaths = () => { + // this.props.clearPaths(); + } + + onModalClose = () => { + this.props.clearPaths(); + this.props.onModalClose(); + } + + // + // Render + + render() { + return ( + + ); + } +} + +FileBrowserModalContentConnector.propTypes = { + value: PropTypes.string, + fetchPaths: PropTypes.func.isRequired, + clearPaths: PropTypes.func.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(FileBrowserModalContentConnector); diff --git a/frontend/src/Components/FileBrowser/FileBrowserRow.css b/frontend/src/Components/FileBrowser/FileBrowserRow.css new file mode 100644 index 000000000..a9c34be6a --- /dev/null +++ b/frontend/src/Components/FileBrowser/FileBrowserRow.css @@ -0,0 +1,5 @@ +.type { + composes: cell from 'Components/Table/Cells/TableRowCell.css'; + + width: 32px; +} diff --git a/frontend/src/Components/FileBrowser/FileBrowserRow.js b/frontend/src/Components/FileBrowser/FileBrowserRow.js new file mode 100644 index 000000000..42ac30405 --- /dev/null +++ b/frontend/src/Components/FileBrowser/FileBrowserRow.js @@ -0,0 +1,62 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import TableRowButton from 'Components/Table/TableRowButton'; +import TableRowCell from 'Components/Table/Cells/TableRowCell'; +import styles from './FileBrowserRow.css'; + +function getIconName(type) { + switch (type) { + case 'computer': + return icons.COMPUTER; + case 'drive': + return icons.DRIVE; + case 'file': + return icons.FILE; + case 'parent': + return icons.PARENT; + default: + return icons.FOLDER; + } +} + +class FileBrowserRow extends Component { + + // + // Listeners + + onPress = () => { + this.props.onPress(this.props.path); + } + + // + // Render + + render() { + const { + type, + name + } = this.props; + + return ( + + + + + + {name} + + ); + } + +} + +FileBrowserRow.propTypes = { + type: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + path: PropTypes.string.isRequired, + onPress: PropTypes.func.isRequired +}; + +export default FileBrowserRow; diff --git a/frontend/src/Components/Filter/Builder/BoolFilterBuilderRowValue.js b/frontend/src/Components/Filter/Builder/BoolFilterBuilderRowValue.js new file mode 100644 index 000000000..eea574dd1 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/BoolFilterBuilderRowValue.js @@ -0,0 +1,18 @@ +import React from 'react'; +import FilterBuilderRowValue from './FilterBuilderRowValue'; + +const protocols = [ + { id: true, name: 'true' }, + { id: false, name: 'false' } +]; + +function BoolFilterBuilderRowValue(props) { + return ( + + ); +} + +export default BoolFilterBuilderRowValue; diff --git a/frontend/src/Components/Filter/Builder/DateFilterBuilderRowValue.css b/frontend/src/Components/Filter/Builder/DateFilterBuilderRowValue.css new file mode 100644 index 000000000..fd56a4917 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/DateFilterBuilderRowValue.css @@ -0,0 +1,15 @@ +.container { + display: flex; +} + +.numberInput { + composes: input from 'Components/Form/TextInput.css'; + + margin-right: 3px; +} + +.selectInput { + composes: select from 'Components/Form/SelectInput.css'; + + margin-left: 3px; +} diff --git a/frontend/src/Components/Filter/Builder/DateFilterBuilderRowValue.js b/frontend/src/Components/Filter/Builder/DateFilterBuilderRowValue.js new file mode 100644 index 000000000..f0c2d3626 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/DateFilterBuilderRowValue.js @@ -0,0 +1,171 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import isString from 'Utilities/String/isString'; +import { IN_LAST, IN_NEXT } from 'Helpers/Props/filterTypes'; +import NumberInput from 'Components/Form/NumberInput'; +import SelectInput from 'Components/Form/SelectInput'; +import TextInput from 'Components/Form/TextInput'; +import { NAME } from './FilterBuilderRowValue'; +import styles from './DateFilterBuilderRowValue.css'; + +const timeOptions = [ + { key: 'seconds', value: 'seconds' }, + { key: 'minutes', value: 'minutes' }, + { key: 'hours', value: 'hours' }, + { key: 'days', value: 'days' }, + { key: 'weeks', value: 'weeks' }, + { key: 'months', value: 'months' } +]; + +function isInFilter(filterType) { + return filterType === IN_LAST || filterType === IN_NEXT; +} + +class DateFilterBuilderRowValue extends Component { + + // + // Lifecycle + + componentDidMount() { + const { + filterType, + filterValue, + onChange + } = this.props; + + if (isInFilter(filterType) && isString(filterValue)) { + onChange({ + name: NAME, + value: { + time: timeOptions[0].key, + value: null + } + }); + } + } + + componentDidUpdate(prevProps) { + const { + filterType, + filterValue, + onChange + } = this.props; + + if (prevProps.filterType === filterType) { + return; + } + + if (isInFilter(filterType) && isString(filterValue)) { + onChange({ + name: NAME, + value: { + time: timeOptions[0].key, + value: null + } + }); + + return; + } + + if (!isInFilter(filterType) && !isString(filterValue)) { + onChange({ + name: NAME, + value: '' + }); + } + } + + // + // Listeners + + onValueChange = ({ value }) => { + const { + filterValue, + onChange + } = this.props; + + let newValue = value; + + if (!isString(value)) { + newValue = { + time: filterValue.time, + value + }; + } + + onChange({ + name: NAME, + value: newValue + }); + } + + onTimeChange = ({ value }) => { + const { + filterValue, + onChange + } = this.props; + + onChange({ + name: NAME, + value: { + time: value, + value: filterValue.value + } + }); + } + + // + // Render + + render() { + const { + filterType, + filterValue + } = this.props; + + if ( + (isInFilter(filterType) && isString(filterValue)) || + (!isInFilter(filterType) && !isString(filterValue)) + ) { + return null; + } + + if (isInFilter(filterType)) { + return ( +
+ + + +
+ ); + } + + return ( + + ); + } +} + +DateFilterBuilderRowValue.propTypes = { + filterType: PropTypes.string, + filterValue: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired, + onChange: PropTypes.func.isRequired +}; + +export default DateFilterBuilderRowValue; diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderModalContent.css b/frontend/src/Components/Filter/Builder/FilterBuilderModalContent.css new file mode 100644 index 000000000..6cc8fab67 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/FilterBuilderModalContent.css @@ -0,0 +1,16 @@ +.labelContainer { + margin-bottom: 20px; +} + +.label { + margin-bottom: 5px; + font-weight: bold; +} + +.labelInputContainer { + width: 300px; +} + +.rows { + margin-bottom: 100px; +} diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderModalContent.js b/frontend/src/Components/Filter/Builder/FilterBuilderModalContent.js new file mode 100644 index 000000000..ed3bc2409 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/FilterBuilderModalContent.js @@ -0,0 +1,226 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { inputTypes } from 'Helpers/Props'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import Button from 'Components/Link/Button'; +import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import FilterBuilderRow from './FilterBuilderRow'; +import styles from './FilterBuilderModalContent.css'; + +class FilterBuilderModalContent extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + const filters = [...props.filters]; + + // Push an empty filter if there aren't any filters. FilterBuilderRow + // will handle initializing the filter. + + if (!filters.length) { + filters.push({}); + } + + this.state = { + label: props.label, + filters, + labelErrors: [] + }; + } + + componentDidUpdate(prevProps) { + const { + id, + customFilters, + isSaving, + saveError, + dispatchSetFilter, + onModalClose + } = this.props; + + if (prevProps.isSaving && !isSaving && !saveError) { + if (id) { + dispatchSetFilter({ selectedFilterKey: id }); + } else { + const last = customFilters[customFilters.length -1]; + dispatchSetFilter({ selectedFilterKey: last.id }); + } + + onModalClose(); + } + } + + // + // Listeners + + onLabelChange = ({ value }) => { + this.setState({ label: value }); + } + + onFilterChange = (index, filter) => { + const filters = [...this.state.filters]; + filters.splice(index, 1, filter); + + this.setState({ + filters + }); + } + + onAddFilterPress = () => { + const filters = [...this.state.filters]; + filters.push({}); + + this.setState({ + filters + }); + } + + onRemoveFilterPress = (index) => { + const filters = [...this.state.filters]; + filters.splice(index, 1); + + this.setState({ + filters + }); + } + + onSaveFilterPress = () => { + const { + id, + customFilterType, + onSaveCustomFilterPress + } = this.props; + + const { + label, + filters + } = this.state; + + if (!label) { + this.setState({ + labelErrors: [ + { + message: 'Label is required' + } + ] + }); + + return; + } + + onSaveCustomFilterPress({ + id, + type: customFilterType, + label, + filters + }); + } + + // + // Render + + render() { + const { + sectionItems, + filterBuilderProps, + isSaving, + saveError, + onModalClose + } = this.props; + + const { + label, + filters, + labelErrors + } = this.state; + + return ( + + + Custom Filter + + + +
+
+ Label +
+ +
+ +
+
+ +
Filters
+ +
+ { + filters.map((filter, index) => { + return ( + + ); + }) + } +
+
+ + + + + + Save + + +
+ ); + } +} + +FilterBuilderModalContent.propTypes = { + id: PropTypes.number, + label: PropTypes.string.isRequired, + customFilterType: PropTypes.string.isRequired, + sectionItems: PropTypes.arrayOf(PropTypes.object).isRequired, + filters: PropTypes.arrayOf(PropTypes.object).isRequired, + filterBuilderProps: PropTypes.arrayOf(PropTypes.object).isRequired, + customFilters: PropTypes.arrayOf(PropTypes.object).isRequired, + isSaving: PropTypes.bool.isRequired, + saveError: PropTypes.object, + dispatchDeleteCustomFilter: PropTypes.func.isRequired, + onSaveCustomFilterPress: PropTypes.func.isRequired, + dispatchSetFilter: PropTypes.func.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default FilterBuilderModalContent; diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderModalContentConnector.js b/frontend/src/Components/Filter/Builder/FilterBuilderModalContentConnector.js new file mode 100644 index 000000000..c94db9925 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/FilterBuilderModalContentConnector.js @@ -0,0 +1,42 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { saveCustomFilter, deleteCustomFilter } from 'Store/Actions/customFilterActions'; +import FilterBuilderModalContent from './FilterBuilderModalContent'; + +function createMapStateToProps() { + return createSelector( + (state, { customFilters }) => customFilters, + (state, { id }) => id, + (state) => state.customFilters.isSaving, + (state) => state.customFilters.saveError, + (customFilters, id, isSaving, saveError) => { + if (id) { + const customFilter = customFilters.find((c) => c.id === id); + + return { + id: customFilter.id, + label: customFilter.label, + filters: customFilter.filters, + customFilters, + isSaving, + saveError + }; + } + + return { + label: '', + filters: [], + customFilters, + isSaving, + saveError + }; + } + ); +} + +const mapDispatchToProps = { + onSaveCustomFilterPress: saveCustomFilter, + dispatchDeleteCustomFilter: deleteCustomFilter +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(FilterBuilderModalContent); diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRow.css b/frontend/src/Components/Filter/Builder/FilterBuilderRow.css new file mode 100644 index 000000000..c5471b253 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/FilterBuilderRow.css @@ -0,0 +1,32 @@ +.filterRow { + display: flex; + margin-bottom: 5px; + + &:hover { + background-color: $tableRowHoverBackgroundColor; + } +} + +.inputContainer { + flex: 0 1 200px; + margin-right: 10px; +} + +.valueInputContainer { + flex: 0 1 300px; + margin-right: 10px; +} + +.actionsContainer { + display: flex; +} + +@media only screen and (max-width: $breakpointSmall) { + .filterRow { + display: block; + } + + .inputContainer { + margin-bottom: 10px; + } +} diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRow.js b/frontend/src/Components/Filter/Builder/FilterBuilderRow.js new file mode 100644 index 000000000..53f28a90e --- /dev/null +++ b/frontend/src/Components/Filter/Builder/FilterBuilderRow.js @@ -0,0 +1,282 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { filterBuilderTypes, filterBuilderValueTypes, icons } from 'Helpers/Props'; +import SelectInput from 'Components/Form/SelectInput'; +import IconButton from 'Components/Link/IconButton'; +import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue'; +import DateFilterBuilderRowValue from './DateFilterBuilderRowValue'; +import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector'; +import IndexerFilterBuilderRowValueConnector from './IndexerFilterBuilderRowValueConnector'; +import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue'; +import QualityFilterBuilderRowValueConnector from './QualityFilterBuilderRowValueConnector'; +import QualityProfileFilterBuilderRowValueConnector from './QualityProfileFilterBuilderRowValueConnector'; +import SeriesStatusFilterBuilderRowValue from './SeriesStatusFilterBuilderRowValue'; +import TagFilterBuilderRowValueConnector from './TagFilterBuilderRowValueConnector'; +import styles from './FilterBuilderRow.css'; + +function getselectedFilterBuilderProp(filterBuilderProps, name) { + return filterBuilderProps.find((a) => { + return a.name === name; + }); +} + +function getFilterTypeOptions(filterBuilderProps, filterKey) { + const selectedFilterBuilderProp = getselectedFilterBuilderProp(filterBuilderProps, filterKey); + + if (!selectedFilterBuilderProp) { + return []; + } + + return filterBuilderTypes.possibleFilterTypes[selectedFilterBuilderProp.type]; +} + +function getDefaultFilterType(selectedFilterBuilderProp) { + return filterBuilderTypes.possibleFilterTypes[selectedFilterBuilderProp.type][0].key; +} + +function getDefaultFilterValue(selectedFilterBuilderProp) { + if (selectedFilterBuilderProp.type === filterBuilderTypes.DATE) { + return ''; + } + + return []; +} + +function getRowValueConnector(selectedFilterBuilderProp) { + if (!selectedFilterBuilderProp) { + return FilterBuilderRowValueConnector; + } + + const valueType = selectedFilterBuilderProp.valueType; + + switch (valueType) { + case filterBuilderValueTypes.BOOL: + return BoolFilterBuilderRowValue; + + case filterBuilderValueTypes.DATE: + return DateFilterBuilderRowValue; + + case filterBuilderValueTypes.INDEXER: + return IndexerFilterBuilderRowValueConnector; + + case filterBuilderValueTypes.PROTOCOL: + return ProtocolFilterBuilderRowValue; + + case filterBuilderValueTypes.QUALITY: + return QualityFilterBuilderRowValueConnector; + + case filterBuilderValueTypes.QUALITY_PROFILE: + return QualityProfileFilterBuilderRowValueConnector; + + case filterBuilderValueTypes.SERIES_STATUS: + return SeriesStatusFilterBuilderRowValue; + + case filterBuilderValueTypes.TAG: + return TagFilterBuilderRowValueConnector; + + default: + return FilterBuilderRowValueConnector; + } +} + +class FilterBuilderRow extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + const { + filterKey, + filterBuilderProps + } = props; + + if (filterKey) { + const selectedFilterBuilderProp = filterBuilderProps.find((a) => a.name === filterKey); + this.selectedFilterBuilderProp = selectedFilterBuilderProp; + } + } + + componentDidMount() { + const { + index, + filterKey, + filterBuilderProps, + onFilterChange + } = this.props; + + if (filterKey) { + const selectedFilterBuilderProp = filterBuilderProps.find((a) => a.name === filterKey); + this.selectedFilterBuilderProp = selectedFilterBuilderProp; + + return; + } + + const selectedFilterBuilderProp = filterBuilderProps[0]; + + const filter = { + key: selectedFilterBuilderProp.name, + value: getDefaultFilterValue(selectedFilterBuilderProp), + type: getDefaultFilterType(selectedFilterBuilderProp) + }; + + this.selectedFilterBuilderProp = selectedFilterBuilderProp; + onFilterChange(index, filter); + } + + // + // Listeners + + onFilterKeyChange = ({ value: key }) => { + const { + index, + filterBuilderProps, + onFilterChange + } = this.props; + + const selectedFilterBuilderProp = getselectedFilterBuilderProp(filterBuilderProps, key); + const type = getDefaultFilterType(selectedFilterBuilderProp); + + const filter = { + key, + value: getDefaultFilterValue(selectedFilterBuilderProp), + type + }; + + this.selectedFilterBuilderProp = selectedFilterBuilderProp; + onFilterChange(index, filter); + } + + onFilterChange = ({ name, value }) => { + const { + index, + filterKey, + filterValue, + filterType, + onFilterChange + } = this.props; + + const filter = { + key: filterKey, + value: filterValue, + type: filterType + }; + + filter[name] = value; + + onFilterChange(index, filter); + } + + onAddPress = () => { + const { + index, + onAddPress + } = this.props; + + onAddPress(index); + } + + onRemovePress = () => { + const { + index, + onRemovePress + } = this.props; + + onRemovePress(index); + } + + // + // Render + + render() { + const { + filterKey, + filterType, + filterValue, + filterCount, + filterBuilderProps, + sectionItems + } = this.props; + + const selectedFilterBuilderProp = this.selectedFilterBuilderProp; + + const keyOptions = filterBuilderProps.map((availablePropFilter) => { + return { + key: availablePropFilter.name, + value: availablePropFilter.label + }; + }); + + const ValueComponent = getRowValueConnector(selectedFilterBuilderProp); + + return ( +
+
+ { + filterKey && + + } +
+ +
+ { + filterType && + + } +
+ +
+ { + filterValue != null && !!selectedFilterBuilderProp && + + } +
+ +
+ + + +
+
+ ); + } +} + +FilterBuilderRow.propTypes = { + index: PropTypes.number.isRequired, + filterKey: PropTypes.string, + filterValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array, PropTypes.object]), + filterType: PropTypes.string, + filterCount: PropTypes.number.isRequired, + filterBuilderProps: PropTypes.arrayOf(PropTypes.object).isRequired, + sectionItems: PropTypes.arrayOf(PropTypes.object).isRequired, + onFilterChange: PropTypes.func.isRequired, + onAddPress: PropTypes.func.isRequired, + onRemovePress: PropTypes.func.isRequired +}; + +export default FilterBuilderRow; diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRowValue.js b/frontend/src/Components/Filter/Builder/FilterBuilderRowValue.js new file mode 100644 index 000000000..70c496620 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/FilterBuilderRowValue.js @@ -0,0 +1,159 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import convertToBytes from 'Utilities/Number/convertToBytes'; +import formatBytes from 'Utilities/Number/formatBytes'; +import { kinds, filterBuilderTypes, filterBuilderValueTypes } from 'Helpers/Props'; +import TagInput, { tagShape } from 'Components/Form/TagInput'; +import FilterBuilderRowValueTag from './FilterBuilderRowValueTag'; + +export const NAME = 'value'; + +function getTagDisplayValue(value, selectedFilterBuilderProp) { + if (selectedFilterBuilderProp.valueType === filterBuilderValueTypes.BYTES) { + return formatBytes(value); + } + + return value; +} + +function getValue(input, selectedFilterBuilderProp) { + if (selectedFilterBuilderProp.valueType === filterBuilderValueTypes.BYTES) { + const match = input.match(/^(\d+)([kmgt](i?b)?)$/i); + + if (match && match.length > 1) { + const [, value, unit] = input.match(/^(\d+)([kmgt](i?b)?)$/i); + + switch (unit.toLowerCase()) { + case 'k': + return convertToBytes(value, 1, true); + case 'm': + return convertToBytes(value, 2, true); + case 'g': + return convertToBytes(value, 3, true); + case 't': + return convertToBytes(value, 4, true); + case 'kb': + return convertToBytes(value, 1, true); + case 'mb': + return convertToBytes(value, 2, true); + case 'gb': + return convertToBytes(value, 3, true); + case 'tb': + return convertToBytes(value, 4, true); + case 'kib': + return convertToBytes(value, 1, true); + case 'mib': + return convertToBytes(value, 2, true); + case 'gib': + return convertToBytes(value, 3, true); + case 'tib': + return convertToBytes(value, 4, true); + default: + return parseInt(value); + } + } + } + + if (selectedFilterBuilderProp.type === filterBuilderTypes.NUMBER) { + return parseInt(input); + } + + return input; +} + +class FilterBuilderRowValue extends Component { + + // + // Listeners + + onTagAdd = (tag) => { + const { + filterValue, + selectedFilterBuilderProp, + onChange + } = this.props; + + let value = tag.id; + + if (value == null) { + value = getValue(tag.name, selectedFilterBuilderProp); + } + + onChange({ + name: NAME, + value: [...filterValue, value] + }); + } + + onTagDelete = ({ index }) => { + const { + filterValue, + onChange + } = this.props; + + const value = filterValue.filter((v, i) => i !== index); + + onChange({ + name: NAME, + value + }); + } + + // + // Render + + render() { + const { + filterValue, + selectedFilterBuilderProp, + tagList + } = this.props; + + const hasItems = !!tagList.length; + + const tags = filterValue.map((id) => { + if (hasItems) { + const tag = tagList.find((t) => t.id === id); + + return { + id, + name: tag && tag.name + }; + } + + return { + id, + name: getTagDisplayValue(id, selectedFilterBuilderProp) + }; + }); + + return ( + + ); + } +} + +FilterBuilderRowValue.propTypes = { + filterValue: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.number])).isRequired, + selectedFilterBuilderProp: PropTypes.object.isRequired, + tagList: PropTypes.arrayOf(PropTypes.shape(tagShape)).isRequired, + onChange: PropTypes.func.isRequired +}; + +FilterBuilderRowValue.defaultProps = { + filterValue: [] +}; + +export default FilterBuilderRowValue; diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRowValueConnector.js b/frontend/src/Components/Filter/Builder/FilterBuilderRowValueConnector.js new file mode 100644 index 000000000..ac74240e4 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/FilterBuilderRowValueConnector.js @@ -0,0 +1,55 @@ +import _ from 'lodash'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import sortByName from 'Utilities/Array/sortByName'; +import { filterBuilderTypes } from 'Helpers/Props'; +import FilterBuilderRowValue from './FilterBuilderRowValue'; + +function createTagListSelector() { + return createSelector( + (state, { sectionItems }) => sectionItems, + (state, { selectedFilterBuilderProp }) => selectedFilterBuilderProp, + (sectionItems, selectedFilterBuilderProp) => { + if ( + selectedFilterBuilderProp.type === filterBuilderTypes.NUMBER || + selectedFilterBuilderProp.type === filterBuilderTypes.STRING + ) { + return []; + } + + let items = []; + + if (selectedFilterBuilderProp.optionsSelector) { + items = selectedFilterBuilderProp.optionsSelector(sectionItems); + } else { + items = sectionItems.reduce((acc, item) => { + const name = item[selectedFilterBuilderProp.name]; + + if (name) { + acc.push({ + id: name, + name + }); + } + + return acc; + }, []).sort(sortByName); + } + + return _.uniqBy(items, 'id'); + } + ); +} + +function createMapStateToProps() { + return createSelector( + createTagListSelector(), + (tagList) => { + return { + tagList + }; + } + ); +} + +export default connect(createMapStateToProps)(FilterBuilderRowValue); diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.css b/frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.css new file mode 100644 index 000000000..1c4c5acf1 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.css @@ -0,0 +1,19 @@ +.tag { + &.isLastTag { + .or { + display: none; + } + } +} + +.label { + composes: label from 'Components/Label.css'; + + border-style: none; + font-size: 13px; +} + +.or { + margin: 0 3px; + color: $themeDarkColor; +} diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.js b/frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.js new file mode 100644 index 000000000..573e05759 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/FilterBuilderRowValueTag.js @@ -0,0 +1,31 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { kinds } from 'Helpers/Props'; +import TagInputTag from 'Components/Form/TagInputTag'; +import styles from './FilterBuilderRowValueTag.css'; + +function FilterBuilderRowValueTag(props) { + return ( + + + + { + !props.isLastTag && + + or + + } + + ); +} + +FilterBuilderRowValueTag.propTypes = { + isLastTag: PropTypes.bool.isRequired +}; + +export default FilterBuilderRowValueTag; diff --git a/frontend/src/Components/Filter/Builder/IndexerFilterBuilderRowValueConnector.js b/frontend/src/Components/Filter/Builder/IndexerFilterBuilderRowValueConnector.js new file mode 100644 index 000000000..968b26d2c --- /dev/null +++ b/frontend/src/Components/Filter/Builder/IndexerFilterBuilderRowValueConnector.js @@ -0,0 +1,79 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { fetchIndexers } from 'Store/Actions/settingsActions'; +import { tagShape } from 'Components/Form/TagInput'; +import FilterBuilderRowValue from './FilterBuilderRowValue'; + +function createMapStateToProps() { + return createSelector( + (state) => state.settings.indexers, + (qualityProfiles) => { + const { + isFetching, + isPopulated, + error, + items + } = qualityProfiles; + + const tagList = items.map((item) => { + return { + id: item.id, + name: item.name + }; + }); + + return { + isFetching, + isPopulated, + error, + tagList + }; + } + ); +} + +const mapDispatchToProps = { + dispatchFetchIndexers: fetchIndexers +}; + +class IndexerFilterBuilderRowValueConnector extends Component { + + // + // Lifecycle + + componentDidMount = () => { + if (!this.props.isPopulated) { + this.props.dispatchFetchIndexers(); + } + } + + // + // Render + + render() { + const { + isFetching, + isPopulated, + error, + ...otherProps + } = this.props; + + return ( + + ); + } +} + +IndexerFilterBuilderRowValueConnector.propTypes = { + tagList: PropTypes.arrayOf(PropTypes.shape(tagShape)).isRequired, + isFetching: PropTypes.bool.isRequired, + isPopulated: PropTypes.bool.isRequired, + error: PropTypes.object, + dispatchFetchIndexers: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(IndexerFilterBuilderRowValueConnector); diff --git a/frontend/src/Components/Filter/Builder/ProtocolFilterBuilderRowValue.js b/frontend/src/Components/Filter/Builder/ProtocolFilterBuilderRowValue.js new file mode 100644 index 000000000..ae63ae0eb --- /dev/null +++ b/frontend/src/Components/Filter/Builder/ProtocolFilterBuilderRowValue.js @@ -0,0 +1,18 @@ +import React from 'react'; +import FilterBuilderRowValue from './FilterBuilderRowValue'; + +const protocols = [ + { id: 'torrent', name: 'Torrent' }, + { id: 'usenet', name: 'Usenet' } +]; + +function ProtocolFilterBuilderRowValue(props) { + return ( + + ); +} + +export default ProtocolFilterBuilderRowValue; diff --git a/frontend/src/Components/Filter/Builder/QualityFilterBuilderRowValueConnector.js b/frontend/src/Components/Filter/Builder/QualityFilterBuilderRowValueConnector.js new file mode 100644 index 000000000..0290bcdcb --- /dev/null +++ b/frontend/src/Components/Filter/Builder/QualityFilterBuilderRowValueConnector.js @@ -0,0 +1,75 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import getQualities from 'Utilities/Quality/getQualities'; +import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions'; +import { tagShape } from 'Components/Form/TagInput'; +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 new file mode 100644 index 000000000..4a8b82283 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/QualityProfileFilterBuilderRowValueConnector.js @@ -0,0 +1,28 @@ +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/Filter/Builder/SeriesStatusFilterBuilderRowValue.js b/frontend/src/Components/Filter/Builder/SeriesStatusFilterBuilderRowValue.js new file mode 100644 index 000000000..50841a013 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/SeriesStatusFilterBuilderRowValue.js @@ -0,0 +1,18 @@ +import React from 'react'; +import FilterBuilderRowValue from './FilterBuilderRowValue'; + +const protocols = [ + { id: 'continuing', name: 'Continuing' }, + { id: 'ended', name: 'Ended' } +]; + +function SeriesStatusFilterBuilderRowValue(props) { + return ( + + ); +} + +export default SeriesStatusFilterBuilderRowValue; diff --git a/frontend/src/Components/Filter/Builder/TagFilterBuilderRowValueConnector.js b/frontend/src/Components/Filter/Builder/TagFilterBuilderRowValueConnector.js new file mode 100644 index 000000000..60e04c446 --- /dev/null +++ b/frontend/src/Components/Filter/Builder/TagFilterBuilderRowValueConnector.js @@ -0,0 +1,27 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createTagsSelector from 'Store/Selectors/createTagsSelector'; +import FilterBuilderRowValue from './FilterBuilderRowValue'; + +function createMapStateToProps() { + return createSelector( + createTagsSelector(), + (tagList) => { + return { + tagList: tagList.map((tag) => { + const { + id, + label: name + } = tag; + + return { + id, + name + }; + }) + }; + } + ); +} + +export default connect(createMapStateToProps)(FilterBuilderRowValue); diff --git a/frontend/src/Components/Filter/CustomFilters/CustomFilter.css b/frontend/src/Components/Filter/CustomFilters/CustomFilter.css new file mode 100644 index 000000000..7acb69dc7 --- /dev/null +++ b/frontend/src/Components/Filter/CustomFilters/CustomFilter.css @@ -0,0 +1,17 @@ +.customFilter { + display: flex; + margin-bottom: 5px; + padding: 5px; + + &:hover { + background-color: $tableRowHoverBackgroundColor; + } +} + +.label { + flex: 0 1 300px; +} + +.actions { + flex: 0 0 60px; +} diff --git a/frontend/src/Components/Filter/CustomFilters/CustomFilter.js b/frontend/src/Components/Filter/CustomFilters/CustomFilter.js new file mode 100644 index 000000000..c9c326d78 --- /dev/null +++ b/frontend/src/Components/Filter/CustomFilters/CustomFilter.js @@ -0,0 +1,114 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons } from 'Helpers/Props'; +import IconButton from 'Components/Link/IconButton'; +import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; +import styles from './CustomFilter.css'; + +class CustomFilter extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isDeleting: false + }; + } + + componentDidUpdate(prevProps) { + const { + isDeleting, + deleteError + } = this.props; + + if (prevProps.isDeleting && !isDeleting && this.state.isDeleting && deleteError) { + this.setState({ isDeleting: false }); + } + } + + componentWillUnmount() { + const { + id, + selectedFilterKey, + dispatchSetFilter + } = this.props; + + // Assume that delete and then unmounting means the delete was successful. + // Moving this check to a ancestor would be more accurate, but would have + // more boilerplate. + if (this.state.isDeleting && id === selectedFilterKey) { + dispatchSetFilter({ selectedFilterKey: 'all' }); + } + } + + // + // Listeners + + onEditPress = () => { + const { + id, + onEditPress + } = this.props; + + onEditPress(id); + } + + onRemovePress = () => { + const { + id, + dispatchDeleteCustomFilter + } = this.props; + + this.setState({ isDeleting: true }, () => { + dispatchDeleteCustomFilter({ id }); + }); + + } + + // + // Render + + render() { + const { + label + } = this.props; + + return ( +
+
+ {label} +
+ +
+ + + +
+
+ ); + } +} + +CustomFilter.propTypes = { + id: PropTypes.number.isRequired, + label: PropTypes.string.isRequired, + selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + isDeleting: PropTypes.bool.isRequired, + deleteError: PropTypes.object, + dispatchSetFilter: PropTypes.func.isRequired, + onEditPress: PropTypes.func.isRequired, + dispatchDeleteCustomFilter: PropTypes.func.isRequired +}; + +export default CustomFilter; diff --git a/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.css b/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.css new file mode 100644 index 000000000..c391764dc --- /dev/null +++ b/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.css @@ -0,0 +1,3 @@ +.addButtonContainer { + margin-top: 15px; +} diff --git a/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.js b/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.js new file mode 100644 index 000000000..1a7168fca --- /dev/null +++ b/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContent.js @@ -0,0 +1,80 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Button from 'Components/Link/Button'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import CustomFilter from './CustomFilter'; +import styles from './CustomFiltersModalContent.css'; + +function CustomFiltersModalContent(props) { + const { + selectedFilterKey, + customFilters, + isDeleting, + deleteError, + dispatchDeleteCustomFilter, + dispatchSetFilter, + onAddCustomFilter, + onEditCustomFilter, + onModalClose + } = props; + + return ( + + + Custom Filters + + + + { + customFilters.map((customFilter, index) => { + return ( + + ); + }) + } + +
+ +
+
+ + + + +
+ ); +} + +CustomFiltersModalContent.propTypes = { + selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + customFilters: PropTypes.arrayOf(PropTypes.object).isRequired, + isDeleting: PropTypes.bool.isRequired, + deleteError: PropTypes.object, + dispatchDeleteCustomFilter: PropTypes.func.isRequired, + dispatchSetFilter: PropTypes.func.isRequired, + onAddCustomFilter: PropTypes.func.isRequired, + onEditCustomFilter: PropTypes.func.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default CustomFiltersModalContent; diff --git a/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContentConnector.js b/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContentConnector.js new file mode 100644 index 000000000..32425d766 --- /dev/null +++ b/frontend/src/Components/Filter/CustomFilters/CustomFiltersModalContentConnector.js @@ -0,0 +1,23 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { deleteCustomFilter } from 'Store/Actions/customFilterActions'; +import CustomFiltersModalContent from './CustomFiltersModalContent'; + +function createMapStateToProps() { + return createSelector( + (state) => state.customFilters.isDeleting, + (state) => state.customFilters.deleteError, + (isDeleting, deleteError) => { + return { + isDeleting, + deleteError + }; + } + ); +} + +const mapDispatchToProps = { + dispatchDeleteCustomFilter: deleteCustomFilter +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(CustomFiltersModalContent); diff --git a/frontend/src/Components/Filter/FilterModal.js b/frontend/src/Components/Filter/FilterModal.js new file mode 100644 index 000000000..750d1ed48 --- /dev/null +++ b/frontend/src/Components/Filter/FilterModal.js @@ -0,0 +1,90 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Modal from 'Components/Modal/Modal'; +import FilterBuilderModalContentConnector from './Builder/FilterBuilderModalContentConnector'; +import CustomFiltersModalContentConnector from './CustomFilters/CustomFiltersModalContentConnector'; + +class FilterModal extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + filterBuilder: !props.customFilters.length, + id: null + }; + } + + // + // Listeners + + onAddCustomFilter = () => { + this.setState({ + filterBuilder: true + }); + } + + onEditCustomFilter = (id) => { + this.setState({ + filterBuilder: true, + id + }); + } + + onModalClose = () => { + this.setState({ + filterBuilder: false, + id: null + }, () => { + this.props.onModalClose(); + }); + } + + // + // Render + + render() { + const { + isOpen, + ...otherProps + } = this.props; + + const { + filterBuilder, + id + } = this.state; + + return ( + + { + filterBuilder ? + : + + } + + ); + } +} + +FilterModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + customFilters: PropTypes.arrayOf(PropTypes.object).isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default FilterModal; diff --git a/frontend/src/Components/Form/AutoCompleteInput.css b/frontend/src/Components/Form/AutoCompleteInput.css new file mode 100644 index 000000000..417a71437 --- /dev/null +++ b/frontend/src/Components/Form/AutoCompleteInput.css @@ -0,0 +1,58 @@ +.input { + composes: input from 'Components/Form/Input.css'; +} + +.hasError { + composes: hasError from 'Components/Form/Input.css'; +} + +.hasWarning { + composes: hasWarning from 'Components/Form/Input.css'; +} + +.inputWrapper { + display: flex; +} + +.inputContainer { + position: relative; + flex-grow: 1; +} + +.container { + @add-mixin scrollbar; + @add-mixin scrollbarTrack; + @add-mixin scrollbarThumb; +} + +.inputContainerOpen { + .container { + position: absolute; + z-index: 1; + overflow-y: auto; + max-height: 200px; + width: 100%; + border: 1px solid $inputBorderColor; + border-radius: 4px; + background-color: $white; + box-shadow: inset 0 1px 1px $inputBoxShadowColor; + } +} + +.list { + margin: 5px 0; + padding-left: 0; + list-style-type: none; +} + +.listItem { + padding: 0 16px; +} + +.match { + font-weight: bold; +} + +.highlighted { + background-color: $menuItemHoverBackgroundColor; +} diff --git a/frontend/src/Components/Form/AutoCompleteInput.js b/frontend/src/Components/Form/AutoCompleteInput.js new file mode 100644 index 000000000..740726b36 --- /dev/null +++ b/frontend/src/Components/Form/AutoCompleteInput.js @@ -0,0 +1,162 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Autosuggest from 'react-autosuggest'; +import classNames from 'classnames'; +import jdu from 'jdu'; +import styles from './AutoCompleteInput.css'; + +class AutoCompleteInput extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + suggestions: [] + }; + } + + // + // Control + + getSuggestionValue(item) { + return item; + } + + renderSuggestion(item) { + return item; + } + + // + // Listeners + + onInputChange = (event, { newValue }) => { + this.props.onChange({ + name: this.props.name, + value: newValue + }); + } + + onInputKeyDown = (event) => { + const { + name, + value, + onChange + } = this.props; + + const { suggestions } = this.state; + + if ( + event.key === 'Tab' && + suggestions.length && + suggestions[0] !== this.props.value + ) { + event.preventDefault(); + + if (value) { + onChange({ + name, + value: suggestions[0] + }); + } + } + } + + onInputBlur = () => { + this.setState({ suggestions: [] }); + } + + onSuggestionsFetchRequested = ({ value }) => { + const { values } = this.props; + const lowerCaseValue = jdu.replace(value).toLowerCase(); + + const filteredValues = values.filter((v) => { + return jdu.replace(v).toLowerCase().contains(lowerCaseValue); + }); + + this.setState({ suggestions: filteredValues }); + } + + onSuggestionsClearRequested = () => { + this.setState({ suggestions: [] }); + } + + // + // Render + + render() { + const { + className, + inputClassName, + name, + value, + placeholder, + hasError, + hasWarning + } = this.props; + + const { suggestions } = this.state; + + const inputProps = { + className: classNames( + inputClassName, + hasError && styles.hasError, + hasWarning && styles.hasWarning, + ), + name, + value, + placeholder, + autoComplete: 'off', + spellCheck: false, + onChange: this.onInputChange, + onKeyDown: this.onInputKeyDown, + onBlur: this.onInputBlur + }; + + const theme = { + container: styles.inputContainer, + containerOpen: styles.inputContainerOpen, + suggestionsContainer: styles.container, + suggestionsList: styles.list, + suggestion: styles.listItem, + suggestionHighlighted: styles.highlighted + }; + + return ( +
+ +
+ ); + } +} + +AutoCompleteInput.propTypes = { + className: PropTypes.string.isRequired, + inputClassName: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + value: PropTypes.string, + values: PropTypes.arrayOf(PropTypes.string).isRequired, + placeholder: PropTypes.string, + hasError: PropTypes.bool, + hasWarning: PropTypes.bool, + onChange: PropTypes.func.isRequired +}; + +AutoCompleteInput.defaultProps = { + className: styles.inputWrapper, + inputClassName: styles.input, + value: '' +}; + +export default AutoCompleteInput; diff --git a/frontend/src/Components/Form/CaptchaInput.css b/frontend/src/Components/Form/CaptchaInput.css new file mode 100644 index 000000000..e7cd1dc4e --- /dev/null +++ b/frontend/src/Components/Form/CaptchaInput.css @@ -0,0 +1,23 @@ +.captchaInputWrapper { + display: flex; +} + +.input { + composes: input from 'Components/Form/Input.css'; +} + +.hasError { + composes: hasError from 'Components/Form/Input.css'; +} + +.hasWarning { + composes: hasWarning from 'Components/Form/Input.css'; +} + +.hasButton { + composes: hasButton from 'Components/Form/Input.css'; +} + +.recaptchaWrapper { + margin-top: 10px; +} diff --git a/frontend/src/Components/Form/CaptchaInput.js b/frontend/src/Components/Form/CaptchaInput.js new file mode 100644 index 000000000..e1a5df458 --- /dev/null +++ b/frontend/src/Components/Form/CaptchaInput.js @@ -0,0 +1,84 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import ReCAPTCHA from 'react-google-recaptcha'; +import classNames from 'classnames'; +import { icons } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import FormInputButton from './FormInputButton'; +import TextInput from './TextInput'; +import styles from './CaptchaInput.css'; + +function CaptchaInput(props) { + const { + className, + name, + value, + hasError, + hasWarning, + refreshing, + siteKey, + secretToken, + onChange, + onRefreshPress, + onCaptchaChange + } = props; + + return ( +
+
+ + + + + +
+ + { + !!siteKey && !!secretToken && +
+ +
+ } +
+ ); +} + +CaptchaInput.propTypes = { + className: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + value: PropTypes.string.isRequired, + hasError: PropTypes.bool, + hasWarning: PropTypes.bool, + refreshing: PropTypes.bool.isRequired, + siteKey: PropTypes.string, + secretToken: PropTypes.string, + onChange: PropTypes.func.isRequired, + onRefreshPress: PropTypes.func.isRequired, + onCaptchaChange: PropTypes.func.isRequired +}; + +CaptchaInput.defaultProps = { + className: styles.input, + value: '' +}; + +export default CaptchaInput; diff --git a/frontend/src/Components/Form/CaptchaInputConnector.js b/frontend/src/Components/Form/CaptchaInputConnector.js new file mode 100644 index 000000000..17b875c88 --- /dev/null +++ b/frontend/src/Components/Form/CaptchaInputConnector.js @@ -0,0 +1,98 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { refreshCaptcha, getCaptchaCookie, resetCaptcha } from 'Store/Actions/captchaActions'; +import CaptchaInput from './CaptchaInput'; + +function createMapStateToProps() { + return createSelector( + (state) => state.captcha, + (captcha) => { + return captcha; + } + ); +} + +const mapDispatchToProps = { + refreshCaptcha, + getCaptchaCookie, + resetCaptcha +}; + +class CaptchaInputConnector extends Component { + + // + // Lifecycle + + componentDidUpdate(prevProps) { + const { + name, + token, + onChange + } = this.props; + + if (token && token !== prevProps.token) { + onChange({ name, value: token }); + } + } + + componentWillUnmount = () => { + this.props.resetCaptcha(); + } + + // + // Listeners + + onRefreshPress = () => { + const { + provider, + providerData + } = this.props; + + this.props.refreshCaptcha({ provider, providerData }); + } + + onCaptchaChange = (captchaResponse) => { + // If the captcha has expired `captchaResponse` will be null. + // In the event it's null don't try to get the captchaCookie. + // TODO: Should we clear the cookie? or reset the captcha? + + if (!captchaResponse) { + return; + } + + const { + provider, + providerData + } = this.props; + + this.props.getCaptchaCookie({ provider, providerData, captchaResponse }); + } + + // + // Render + + render() { + return ( + + ); + } +} + +CaptchaInputConnector.propTypes = { + provider: PropTypes.string.isRequired, + providerData: PropTypes.object.isRequired, + name: PropTypes.string.isRequired, + token: PropTypes.string, + onChange: PropTypes.func.isRequired, + refreshCaptcha: PropTypes.func.isRequired, + getCaptchaCookie: PropTypes.func.isRequired, + resetCaptcha: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(CaptchaInputConnector); diff --git a/frontend/src/Components/Form/CheckInput.css b/frontend/src/Components/Form/CheckInput.css new file mode 100644 index 000000000..5c35e5d2f --- /dev/null +++ b/frontend/src/Components/Form/CheckInput.css @@ -0,0 +1,105 @@ +.container { + position: relative; + display: flex; + flex: 1 1 65%; + user-select: none; +} + +.label { + display: flex; + margin-bottom: 0; + min-height: 21px; + font-weight: normal; + cursor: pointer; +} + +.checkbox { + position: absolute; + opacity: 0; + cursor: pointer; + pointer-events: none; + + &:global(.isDisabled) { + cursor: not-allowed; + } +} + +.input { + flex: 1 0 auto; + margin-top: 7px; + margin-right: 5px; + width: 20px; + height: 20px; + border: 1px solid #ccc; + border-radius: 2px; + background-color: $white; + color: $white; + text-align: center; + line-height: 20px; +} + +.checkbox:focus + .input { + outline: 0; + border-color: $inputFocusBorderColor; + box-shadow: inset 0 1px 1px $inputBoxShadowColor, 0 0 8px $inputFocusBoxShadowColor; +} + +.dangerIsChecked { + border-color: $dangerColor; + background-color: $dangerColor; + + &.isDisabled { + opacity: 0.7; + } +} + +.primaryIsChecked { + border-color: $primaryColor; + background-color: $primaryColor; + + &.isDisabled { + opacity: 0.7; + } +} + +.successIsChecked { + border-color: $successColor; + background-color: $successColor; + + &.isDisabled { + opacity: 0.7; + } +} + +.warningIsChecked { + border-color: $warningColor; + background-color: $warningColor; + + &.isDisabled { + opacity: 0.7; + } +} + +.isNotChecked { + &.isDisabled { + border-color: $disabledCheckInputColor; + background-color: $disabledCheckInputColor; + opacity: 0.7; + } +} + +.isIndeterminate { + border-color: $gray; + background-color: $gray; +} + +.helpText { + composes: helpText from 'Components/Form/FormInputHelpText.css'; + + margin-top: 8px; + margin-left: 5px; +} + +.isDisabled { + cursor: not-allowed; +} diff --git a/frontend/src/Components/Form/CheckInput.js b/frontend/src/Components/Form/CheckInput.js new file mode 100644 index 000000000..134290111 --- /dev/null +++ b/frontend/src/Components/Form/CheckInput.js @@ -0,0 +1,191 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { icons, kinds } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import FormInputHelpText from './FormInputHelpText'; +import styles from './CheckInput.css'; + +class CheckInput extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._checkbox = null; + } + + componentDidMount() { + this.setIndeterminate(); + } + + componentDidUpdate() { + this.setIndeterminate(); + } + + // + // Control + + setIndeterminate() { + if (!this._checkbox) { + return; + } + + const { + value, + uncheckedValue, + checkedValue + } = this.props; + + this._checkbox.indeterminate = value !== uncheckedValue && value !== checkedValue; + } + + toggleChecked = (checked, shiftKey) => { + const { + name, + value, + checkedValue, + uncheckedValue + } = this.props; + + const newValue = checked ? checkedValue : uncheckedValue; + + if (value !== newValue) { + this.props.onChange({ + name, + value: newValue, + shiftKey + }); + } + } + + // + // Listeners + + setRef = (ref) => { + this._checkbox = ref; + } + + onClick = (event) => { + if (this.props.isDisabled) { + return; + } + + const shiftKey = event.nativeEvent.shiftKey; + const checked = !this._checkbox.checked; + + event.preventDefault(); + this.toggleChecked(checked, shiftKey); + } + + onChange = (event) => { + const checked = event.target.checked; + const shiftKey = event.nativeEvent.shiftKey; + + this.toggleChecked(checked, shiftKey); + } + + // + // Render + + render() { + const { + className, + containerClassName, + name, + value, + checkedValue, + uncheckedValue, + helpText, + helpTextWarning, + isDisabled, + kind + } = this.props; + + const isChecked = value === checkedValue; + const isUnchecked = value === uncheckedValue; + const isIndeterminate = !isChecked && !isUnchecked; + const isCheckClass = `${kind}IsChecked`; + + return ( +
+ +
+ ); + } +} + +CheckInput.propTypes = { + className: PropTypes.string.isRequired, + containerClassName: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + checkedValue: PropTypes.bool, + uncheckedValue: PropTypes.bool, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), + helpText: PropTypes.string, + helpTextWarning: PropTypes.string, + isDisabled: PropTypes.bool, + kind: PropTypes.oneOf(kinds.all).isRequired, + onChange: PropTypes.func.isRequired +}; + +CheckInput.defaultProps = { + className: styles.input, + containerClassName: styles.container, + checkedValue: true, + uncheckedValue: false, + kind: kinds.PRIMARY +}; + +export default CheckInput; diff --git a/frontend/src/Components/Form/DeviceInput.css b/frontend/src/Components/Form/DeviceInput.css new file mode 100644 index 000000000..0c518e98e --- /dev/null +++ b/frontend/src/Components/Form/DeviceInput.css @@ -0,0 +1,8 @@ +.deviceInputWrapper { + display: flex; +} + +.inputContainer { + composes: inputContainer from './TagInput.css'; + composes: hasButton from 'Components/Form/Input.css'; +} diff --git a/frontend/src/Components/Form/DeviceInput.js b/frontend/src/Components/Form/DeviceInput.js new file mode 100644 index 000000000..a38648e1a --- /dev/null +++ b/frontend/src/Components/Form/DeviceInput.js @@ -0,0 +1,103 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import FormInputButton from './FormInputButton'; +import TagInput, { tagShape } from './TagInput'; +import styles from './DeviceInput.css'; + +class DeviceInput extends Component { + + onTagAdd = (device) => { + const { + name, + value, + onChange + } = this.props; + + // New tags won't have an ID, only a name. + const deviceId = device.id || device.name; + + onChange({ + name, + value: [...value, deviceId] + }); + } + + onTagDelete = ({ index }) => { + const { + name, + value, + onChange + } = this.props; + + const newValue = value.slice(); + newValue.splice(index, 1); + + onChange({ + name, + value: newValue + }); + } + + // + // Render + + render() { + const { + className, + items, + selectedDevices, + hasError, + hasWarning, + isFetching, + onRefreshPress + } = this.props; + + return ( +
+ + + + + +
+ ); + } +} + +DeviceInput.propTypes = { + className: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + value: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])).isRequired, + items: PropTypes.arrayOf(PropTypes.shape(tagShape)).isRequired, + selectedDevices: PropTypes.arrayOf(PropTypes.shape(tagShape)).isRequired, + hasError: PropTypes.bool, + hasWarning: PropTypes.bool, + isFetching: PropTypes.bool.isRequired, + isPopulated: PropTypes.bool.isRequired, + onChange: PropTypes.func.isRequired, + onRefreshPress: PropTypes.func.isRequired +}; + +DeviceInput.defaultProps = { + className: styles.deviceInputWrapper, + inputClassName: styles.input +}; + +export default DeviceInput; diff --git a/frontend/src/Components/Form/DeviceInputConnector.js b/frontend/src/Components/Form/DeviceInputConnector.js new file mode 100644 index 000000000..d53372b35 --- /dev/null +++ b/frontend/src/Components/Form/DeviceInputConnector.js @@ -0,0 +1,99 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { fetchDevices, clearDevices } from 'Store/Actions/deviceActions'; +import DeviceInput from './DeviceInput'; + +function createMapStateToProps() { + return createSelector( + (state, { value }) => value, + (state) => state.devices, + (value, devices) => { + + return { + ...devices, + selectedDevices: value.map((valueDevice) => { + // Disable equality ESLint rule so we don't need to worry about + // a type mismatch between the value items and the device ID. + // eslint-disable-next-line eqeqeq + const device = devices.items.find((d) => d.id == valueDevice); + + if (device) { + return { + id: device.id, + name: `${device.name} (${device.id})` + }; + } + + return { + id: valueDevice, + name: `Unknown (${valueDevice})` + }; + }) + }; + } + ); +} + +const mapDispatchToProps = { + dispatchFetchDevices: fetchDevices, + dispatchClearDevices: clearDevices +}; + +class DeviceInputConnector extends Component { + + // + // Lifecycle + + componentDidMount = () => { + this._populate(); + } + + componentWillUnmount = () => { + // this.props.dispatchClearDevices(); + } + + // + // Control + + _populate() { + const { + provider, + providerData, + dispatchFetchDevices + } = this.props; + + dispatchFetchDevices({ provider, providerData }); + } + + // + // Listeners + + onRefreshPress = () => { + this._populate(); + } + + // + // Render + + render() { + return ( + + ); + } +} + +DeviceInputConnector.propTypes = { + provider: PropTypes.string.isRequired, + providerData: PropTypes.object.isRequired, + name: PropTypes.string.isRequired, + onChange: PropTypes.func.isRequired, + dispatchFetchDevices: PropTypes.func.isRequired, + dispatchClearDevices: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(DeviceInputConnector); diff --git a/frontend/src/Components/Form/EnhancedSelectInput.css b/frontend/src/Components/Form/EnhancedSelectInput.css new file mode 100644 index 000000000..568e35f40 --- /dev/null +++ b/frontend/src/Components/Form/EnhancedSelectInput.css @@ -0,0 +1,79 @@ +.tether { + z-index: 2000; +} + +.enhancedSelect { + composes: input from 'Components/Form/Input.css'; + composes: link from 'Components/Link/Link.css'; + + position: relative; + display: flex; + align-items: center; + padding: 6px 16px; + width: 100%; + height: 35px; + border: 1px solid $inputBorderColor; + border-radius: 4px; + background-color: $white; + box-shadow: inset 0 1px 1px $inputBoxShadowColor; + color: $black; + cursor: default; +} + +.hasError { + composes: hasError from 'Components/Form/Input.css'; +} + +.hasWarning { + composes: hasWarning from 'Components/Form/Input.css'; +} + +.isDisabled { + opacity: 0.7; + cursor: not-allowed; +} + +.dropdownArrowContainer { + margin-left: 12px; +} + +.dropdownArrowContainerDisabled { + composes: dropdownArrowContainer; + + color: $disabledInputColor; +} + +.optionsContainer { + width: auto; +} + +.options { + border: 1px solid $inputBorderColor; + border-radius: 4px; + background-color: $white; +} + +.optionsModal { + display: flex; + justify-content: center; + max-width: 90%; + width: 350px !important; + height: auto !important; +} + +.optionsModalBody { + composes: modalBody from 'Components/Modal/ModalBody.css'; + + display: flex; + justify-content: center; + flex-direction: column; + padding: 10px 0; +} + +.optionsModalScroller { + composes: scroller from 'Components/Scroller/Scroller.css'; + + border: 1px solid $inputBorderColor; + border-radius: 4px; + background-color: $white; +} diff --git a/frontend/src/Components/Form/EnhancedSelectInput.js b/frontend/src/Components/Form/EnhancedSelectInput.js new file mode 100644 index 000000000..a127feaed --- /dev/null +++ b/frontend/src/Components/Form/EnhancedSelectInput.js @@ -0,0 +1,411 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import ReactDOM from 'react-dom'; +import TetherComponent from 'react-tether'; +import classNames from 'classnames'; +import isMobileUtil from 'Utilities/isMobile'; +import * as keyCodes from 'Utilities/Constants/keyCodes'; +import { icons, scrollDirections } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import Link from 'Components/Link/Link'; +import Measure from 'Components/Measure'; +import Modal from 'Components/Modal/Modal'; +import ModalBody from 'Components/Modal/ModalBody'; +import Scroller from 'Components/Scroller/Scroller'; +import EnhancedSelectInputSelectedValue from './EnhancedSelectInputSelectedValue'; +import EnhancedSelectInputOption from './EnhancedSelectInputOption'; +import styles from './EnhancedSelectInput.css'; + +const tetherOptions = { + skipMoveElement: true, + constraints: [ + { + to: 'window', + attachment: 'together', + pin: true + } + ], + attachment: 'top left', + targetAttachment: 'bottom left' +}; + +function isArrowKey(keyCode) { + return keyCode === keyCodes.UP_ARROW || keyCode === keyCodes.DOWN_ARROW; +} + +function getSelectedOption(selectedIndex, values) { + return values[selectedIndex]; +} + +function findIndex(startingIndex, direction, values) { + let indexToTest = startingIndex + direction; + + while (indexToTest !== startingIndex) { + if (indexToTest < 0) { + indexToTest = values.length - 1; + } else if (indexToTest >= values.length) { + indexToTest = 0; + } + + if (getSelectedOption(indexToTest, values).isDisabled) { + indexToTest = indexToTest + direction; + } else { + return indexToTest; + } + } +} + +function previousIndex(selectedIndex, values) { + return findIndex(selectedIndex, -1, values); +} + +function nextIndex(selectedIndex, values) { + return findIndex(selectedIndex, 1, values); +} + +function getSelectedIndex(props) { + const { + value, + values + } = props; + + return values.findIndex((v) => { + return v.key === value; + }); +} + +function getKey(selectedIndex, values) { + return values[selectedIndex].key; +} + +class EnhancedSelectInput extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isOpen: false, + selectedIndex: getSelectedIndex(props), + width: 0, + isMobile: isMobileUtil() + }; + } + + componentDidUpdate(prevProps) { + if (prevProps.value !== this.props.value) { + this.setState({ + selectedIndex: getSelectedIndex(this.props) + }); + } + } + + // + // Control + + _setButtonRef = (ref) => { + this._buttonRef = ref; + } + + _setOptionsRef = (ref) => { + this._optionsRef = ref; + } + + _addListener() { + window.addEventListener('click', this.onWindowClick); + } + + _removeListener() { + window.removeEventListener('click', this.onWindowClick); + } + + // + // Listeners + + onWindowClick = (event) => { + const button = ReactDOM.findDOMNode(this._buttonRef); + const options = ReactDOM.findDOMNode(this._optionsRef); + + if (!button || this.state.isMobile) { + return; + } + + if ( + !button.contains(event.target) && + options && + !options.contains(event.target) && + this.state.isOpen + ) { + this.setState({ isOpen: false }); + this._removeListener(); + } + } + + onBlur = () => { + this.setState({ + selectedIndex: getSelectedIndex(this.props) + }); + } + + onKeyDown = (event) => { + const { + values + } = this.props; + + const { + isOpen, + selectedIndex + } = this.state; + + const keyCode = event.keyCode; + const newState = {}; + + if (!isOpen) { + if (isArrowKey(keyCode)) { + event.preventDefault(); + newState.isOpen = true; + } + + if ( + selectedIndex == null || + getSelectedOption(selectedIndex, values).isDisabled + ) { + if (keyCode === keyCodes.UP_ARROW) { + newState.selectedIndex = previousIndex(0, values); + } else if (keyCode === keyCodes.DOWN_ARROW) { + newState.selectedIndex = nextIndex(values.length - 1, values); + } + } + + this.setState(newState); + return; + } + + if (keyCode === keyCodes.UP_ARROW) { + event.preventDefault(); + newState.selectedIndex = previousIndex(selectedIndex, values); + } + + if (keyCode === keyCodes.DOWN_ARROW) { + event.preventDefault(); + newState.selectedIndex = nextIndex(selectedIndex, values); + } + + if (keyCode === keyCodes.ENTER) { + event.preventDefault(); + newState.isOpen = false; + this.onSelect(getKey(selectedIndex, values)); + } + + if (keyCode === keyCodes.TAB) { + newState.isOpen = false; + this.onSelect(getKey(selectedIndex, values)); + } + + if (keyCode === keyCodes.ESCAPE) { + event.preventDefault(); + event.stopPropagation(); + newState.isOpen = false; + newState.selectedIndex = getSelectedIndex(this.props); + } + + if (!_.isEmpty(newState)) { + this.setState(newState); + } + } + + onPress = () => { + if (this.state.isOpen) { + this._removeListener(); + } else { + this._addListener(); + } + + this.setState({ isOpen: !this.state.isOpen }); + } + + onSelect = (value) => { + this.setState({ isOpen: false }); + + this.props.onChange({ + name: this.props.name, + value + }); + } + + onMeasure = ({ width }) => { + this.setState({ width }); + } + + onOptionsModalClose = () => { + this.setState({ isOpen: false }); + } + + // + // Render + + render() { + const { + className, + disabledClassName, + values, + isDisabled, + hasError, + hasWarning, + selectedValueOptions, + selectedValueComponent: SelectedValueComponent, + optionComponent: OptionComponent + } = this.props; + + const { + selectedIndex, + width, + isOpen, + isMobile + } = this.state; + + const selectedOption = getSelectedOption(selectedIndex, values); + + return ( +
+ + + + + {selectedOption ? selectedOption.value : null} + + +
+ +
+ +
+ + { + isOpen && !isMobile && +
+
+ { + values.map((v, index) => { + return ( + + {v.value} + + ); + }) + } +
+
+ } +
+ + { + isMobile && + + + + { + values.map((v, index) => { + return ( + + {v.value} + + ); + }) + } + + + + } +
+ ); + } +} + +EnhancedSelectInput.propTypes = { + className: PropTypes.string, + disabledClassName: PropTypes.string, + name: PropTypes.string.isRequired, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + values: PropTypes.arrayOf(PropTypes.object).isRequired, + isDisabled: PropTypes.bool, + hasError: PropTypes.bool, + hasWarning: PropTypes.bool, + selectedValueOptions: PropTypes.object.isRequired, + selectedValueComponent: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, + optionComponent: PropTypes.func, + onChange: PropTypes.func.isRequired +}; + +EnhancedSelectInput.defaultProps = { + className: styles.enhancedSelect, + disabledClassName: styles.isDisabled, + isDisabled: false, + selectedValueOptions: {}, + selectedValueComponent: EnhancedSelectInputSelectedValue, + optionComponent: EnhancedSelectInputOption +}; + +export default EnhancedSelectInput; diff --git a/frontend/src/Components/Form/EnhancedSelectInputOption.css b/frontend/src/Components/Form/EnhancedSelectInputOption.css new file mode 100644 index 000000000..2b96de47f --- /dev/null +++ b/frontend/src/Components/Form/EnhancedSelectInputOption.css @@ -0,0 +1,41 @@ +.option { + display: flex; + align-items: center; + justify-content: space-between; + padding: 5px 10px; + width: 100%; + cursor: default; + + &:hover { + background-color: #f9f9f9; + } +} + +.isSelected { + background-color: #e2e2e2; + + &.isMobile { + background-color: inherit; + + .iconContainer { + color: $primaryColor; + } + } +} + +.isDisabled { + background-color: #aaa; +} + +.isHidden { + display: none; +} + +.isMobile { + height: 50px; + border-bottom: 1px solid $borderColor; + + &:last-child { + border: none; + } +} diff --git a/frontend/src/Components/Form/EnhancedSelectInputOption.js b/frontend/src/Components/Form/EnhancedSelectInputOption.js new file mode 100644 index 000000000..e1b410c28 --- /dev/null +++ b/frontend/src/Components/Form/EnhancedSelectInputOption.js @@ -0,0 +1,81 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { icons } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import Link from 'Components/Link/Link'; +import styles from './EnhancedSelectInputOption.css'; + +class EnhancedSelectInputOption extends Component { + + // + // Listeners + + onPress = () => { + const { + id, + onSelect + } = this.props; + + onSelect(id); + } + + // + // Render + + render() { + const { + className, + isSelected, + isDisabled, + isHidden, + isMobile, + children + } = this.props; + + return ( + + {children} + + { + isMobile && +
+ +
+ } + + ); + } +} + +EnhancedSelectInputOption.propTypes = { + className: PropTypes.string.isRequired, + id: PropTypes.string.isRequired, + isSelected: PropTypes.bool.isRequired, + isDisabled: PropTypes.bool.isRequired, + isHidden: PropTypes.bool.isRequired, + isMobile: PropTypes.bool.isRequired, + children: PropTypes.node.isRequired, + onSelect: PropTypes.func.isRequired +}; + +EnhancedSelectInputOption.defaultProps = { + className: styles.option, + isDisabled: false, + isHidden: false +}; + +export default EnhancedSelectInputOption; diff --git a/frontend/src/Components/Form/EnhancedSelectInputSelectedValue.css b/frontend/src/Components/Form/EnhancedSelectInputSelectedValue.css new file mode 100644 index 000000000..6b8b73af9 --- /dev/null +++ b/frontend/src/Components/Form/EnhancedSelectInputSelectedValue.css @@ -0,0 +1,7 @@ +.selectedValue { + flex: 1 1 auto; +} + +.isDisabled { + color: $disabledInputColor; +} diff --git a/frontend/src/Components/Form/EnhancedSelectInputSelectedValue.js b/frontend/src/Components/Form/EnhancedSelectInputSelectedValue.js new file mode 100644 index 000000000..c40ee93c1 --- /dev/null +++ b/frontend/src/Components/Form/EnhancedSelectInputSelectedValue.js @@ -0,0 +1,35 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; +import styles from './EnhancedSelectInputSelectedValue.css'; + +function EnhancedSelectInputSelectedValue(props) { + const { + className, + children, + isDisabled + } = props; + + return ( +
+ {children} +
+ ); +} + +EnhancedSelectInputSelectedValue.propTypes = { + className: PropTypes.string.isRequired, + children: PropTypes.node, + isDisabled: PropTypes.bool.isRequired +}; + +EnhancedSelectInputSelectedValue.defaultProps = { + className: styles.selectedValue, + isDisabled: false +}; + +export default EnhancedSelectInputSelectedValue; diff --git a/frontend/src/Components/Form/Form.css b/frontend/src/Components/Form/Form.css new file mode 100644 index 000000000..52e79aec4 --- /dev/null +++ b/frontend/src/Components/Form/Form.css @@ -0,0 +1,3 @@ +.validationFailures { + margin-bottom: 20px; +} diff --git a/frontend/src/Components/Form/Form.js b/frontend/src/Components/Form/Form.js new file mode 100644 index 000000000..c2c67eddf --- /dev/null +++ b/frontend/src/Components/Form/Form.js @@ -0,0 +1,58 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { kinds } from 'Helpers/Props'; +import Alert from 'Components/Alert'; +import styles from './Form.css'; + +function Form({ children, validationErrors, validationWarnings, ...otherProps }) { + return ( +
+ { + validationErrors.length || validationWarnings.length ? +
+ { + validationErrors.map((error, index) => { + return ( + + {error.errorMessage} + + ); + }) + } + + { + validationWarnings.map((warning, index) => { + return ( + + {warning.errorMessage} + + ); + }) + } +
: + null + } + + {children} +
+ ); +} + +Form.propTypes = { + children: PropTypes.node.isRequired, + validationErrors: PropTypes.arrayOf(PropTypes.object).isRequired, + validationWarnings: PropTypes.arrayOf(PropTypes.object).isRequired +}; + +Form.defaultProps = { + validationErrors: [], + validationWarnings: [] +}; + +export default Form; diff --git a/frontend/src/Components/Form/FormGroup.css b/frontend/src/Components/Form/FormGroup.css new file mode 100644 index 000000000..ddce8863b --- /dev/null +++ b/frontend/src/Components/Form/FormGroup.css @@ -0,0 +1,28 @@ +.group { + display: flex; + margin-bottom: 20px; +} + +/* Sizes */ + +.extraSmall { + max-width: $formGroupExtraSmallWidth; +} + +.small { + max-width: $formGroupSmallWidth; +} + +.medium { + max-width: $formGroupMediumWidth; +} + +.large { + max-width: $formGroupLargeWidth; +} + +@media only screen and (max-width: $breakpointLarge) { + .group { + display: block; + } +} diff --git a/frontend/src/Components/Form/FormGroup.js b/frontend/src/Components/Form/FormGroup.js new file mode 100644 index 000000000..d2e04c350 --- /dev/null +++ b/frontend/src/Components/Form/FormGroup.js @@ -0,0 +1,56 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; +import { map } from 'Helpers/elementChildren'; +import { sizes } from 'Helpers/Props'; +import styles from './FormGroup.css'; + +function FormGroup(props) { + const { + className, + children, + size, + advancedSettings, + isAdvanced, + ...otherProps + } = props; + + if (!advancedSettings && isAdvanced) { + return null; + } + + const childProps = isAdvanced ? { isAdvanced } : {}; + + return ( +
+ { + map(children, (child) => { + return React.cloneElement(child, childProps); + }) + } +
+ ); +} + +FormGroup.propTypes = { + className: PropTypes.string.isRequired, + children: PropTypes.node.isRequired, + size: PropTypes.oneOf(sizes.all).isRequired, + advancedSettings: PropTypes.bool.isRequired, + isAdvanced: PropTypes.bool.isRequired +}; + +FormGroup.defaultProps = { + className: styles.group, + size: sizes.SMALL, + advancedSettings: false, + isAdvanced: false +}; + +export default FormGroup; diff --git a/frontend/src/Components/Form/FormInputButton.css b/frontend/src/Components/Form/FormInputButton.css new file mode 100644 index 000000000..27a1923be --- /dev/null +++ b/frontend/src/Components/Form/FormInputButton.css @@ -0,0 +1,12 @@ +.button { + composes: button from 'Components/Link/Button.css'; + + border-left: none; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.middleButton { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} diff --git a/frontend/src/Components/Form/FormInputButton.js b/frontend/src/Components/Form/FormInputButton.js new file mode 100644 index 000000000..4b6491663 --- /dev/null +++ b/frontend/src/Components/Form/FormInputButton.js @@ -0,0 +1,54 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; +import Button from 'Components/Link/Button'; +import SpinnerButton from 'Components/Link/SpinnerButton'; +import { kinds } from 'Helpers/Props'; +import styles from './FormInputButton.css'; + +function FormInputButton(props) { + const { + className, + canSpin, + isLastButton, + ...otherProps + } = props; + + if (canSpin) { + return ( + + ); + } + + return ( + + ); +} + +SpinnerButton.propTypes = { + className: PropTypes.string.isRequired, + isSpinning: PropTypes.bool.isRequired, + isDisabled: PropTypes.bool, + spinnerIcon: PropTypes.object.isRequired, + children: PropTypes.node +}; + +SpinnerButton.defaultProps = { + className: styles.button, + spinnerIcon: icons.SPINNER +}; + +export default SpinnerButton; diff --git a/frontend/src/Components/Link/SpinnerErrorButton.css b/frontend/src/Components/Link/SpinnerErrorButton.css new file mode 100644 index 000000000..5f4e68545 --- /dev/null +++ b/frontend/src/Components/Link/SpinnerErrorButton.css @@ -0,0 +1,23 @@ +.iconContainer { + composes: spinnerContainer from 'Components/Link/SpinnerButton.css'; +} + +.icon { + z-index: 1; +} + +.label { + composes: label from 'Components/Link/SpinnerButton.css'; +} + +.showIcon { + .iconContainer { + left: 50%; + visibility: visible; + } + + .label { + left: 100%; + opacity: 0; + } +} diff --git a/frontend/src/Components/Link/SpinnerErrorButton.js b/frontend/src/Components/Link/SpinnerErrorButton.js new file mode 100644 index 000000000..0575db094 --- /dev/null +++ b/frontend/src/Components/Link/SpinnerErrorButton.js @@ -0,0 +1,162 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons, kinds } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import SpinnerButton from 'Components/Link/SpinnerButton'; +import styles from './SpinnerErrorButton.css'; + +function getTestResult(error) { + if (!error) { + return { + wasSuccessful: true, + hasWarning: false, + hasError: false + }; + } + + if (error.status !== 400) { + return { + wasSuccessful: false, + hasWarning: false, + hasError: true + }; + } + + const failures = error.responseJSON; + + const hasWarning = _.some(failures, { isWarning: true }); + const hasError = _.some(failures, (failure) => !failure.isWarning); + + return { + wasSuccessful: false, + hasWarning, + hasError + }; +} + +class SpinnerErrorButton extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._testResultTimeout = null; + + this.state = { + wasSuccessful: false, + hasWarning: false, + hasError: false + }; + } + + componentDidUpdate(prevProps) { + const { + isSpinning, + error + } = this.props; + + if (prevProps.isSpinning && !isSpinning) { + const testResult = getTestResult(error); + + this.setState(testResult, () => { + const { + wasSuccessful, + hasWarning, + hasError + } = testResult; + + if (wasSuccessful || hasWarning || hasError) { + this._testResultTimeout = setTimeout(this.resetState, 3000); + } + }); + } + } + + componentWillUnmount() { + if (this._testResultTimeout) { + clearTimeout(this._testResultTimeout); + } + } + + // + // Control + + resetState = () => { + this.setState({ + wasSuccessful: false, + hasWarning: false, + hasError: false + }); + } + + // + // Render + + render() { + const { + isSpinning, + error, + children, + ...otherProps + } = this.props; + + const { + wasSuccessful, + hasWarning, + hasError + } = this.state; + + const showIcon = wasSuccessful || hasWarning || hasError; + + let iconName = icons.CHECK; + let iconKind = kinds.SUCCESS; + + if (hasWarning) { + iconName = icons.WARNING; + iconKind = kinds.WARNING; + } + + if (hasError) { + iconName = icons.DANGER; + iconKind = kinds.DANGER; + } + + return ( + + + { + showIcon && + + + + } + + { + + { + children + } + + } + + + ); + } +} + +SpinnerErrorButton.propTypes = { + isSpinning: PropTypes.bool.isRequired, + error: PropTypes.object, + children: PropTypes.node.isRequired +}; + +export default SpinnerErrorButton; diff --git a/frontend/src/Components/Link/SpinnerIconButton.js b/frontend/src/Components/Link/SpinnerIconButton.js new file mode 100644 index 000000000..a804fafc5 --- /dev/null +++ b/frontend/src/Components/Link/SpinnerIconButton.js @@ -0,0 +1,38 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons } from 'Helpers/Props'; +import IconButton from './IconButton'; + +function SpinnerIconButton(props) { + const { + name, + spinningName, + isDisabled, + isSpinning, + ...otherProps + } = props; + + return ( + + ); +} + +SpinnerIconButton.propTypes = { + name: PropTypes.object.isRequired, + spinningName: PropTypes.object.isRequired, + isDisabled: PropTypes.bool.isRequired, + isSpinning: PropTypes.bool.isRequired +}; + +SpinnerIconButton.defaultProps = { + spinningName: icons.SPINNER, + isDisabled: false, + isSpinning: false +}; + +export default SpinnerIconButton; diff --git a/frontend/src/Components/Loading/LoadingIndicator.css b/frontend/src/Components/Loading/LoadingIndicator.css new file mode 100644 index 000000000..fd224b1d6 --- /dev/null +++ b/frontend/src/Components/Loading/LoadingIndicator.css @@ -0,0 +1,49 @@ +.loading { + margin-top: 20px; + text-align: center; +} + +.rippleContainer { + position: relative; + display: inline-block; +} + +.ripple:nth-child(0) { + animation-delay: -0.8s; +} + +.ripple:nth-child(1) { + animation-delay: -0.6s; +} + +.ripple:nth-child(2) { + animation-delay: -0.4s; +} + +.ripple:nth-child(3) { + animation-delay: -0.2s; +} + +.ripple { + position: absolute; + border: 2px solid #3a3f51; + border-radius: 100%; + animation: rippleContainer 1.25s 0s infinite cubic-bezier(0.21, 0.53, 0.56, 0.8); + animation-fill-mode: both; +} + +@keyframes rippleContainer { + 0% { + opacity: 1; + transform: scale(0.1); + } + + 70% { + opacity: 0.7; + transform: scale(1); + } + + 100% { + opacity: 0; + } +} diff --git a/frontend/src/Components/Loading/LoadingIndicator.js b/frontend/src/Components/Loading/LoadingIndicator.js new file mode 100644 index 000000000..5f9a15b1a --- /dev/null +++ b/frontend/src/Components/Loading/LoadingIndicator.js @@ -0,0 +1,48 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import styles from './LoadingIndicator.css'; + +function LoadingIndicator({ className, size }) { + const sizeInPx = `${size}px`; + const width = sizeInPx; + const height = sizeInPx; + + return ( +
+
+
+ +
+ +
+
+
+ ); +} + +LoadingIndicator.propTypes = { + className: PropTypes.string, + size: PropTypes.number +}; + +LoadingIndicator.defaultProps = { + className: styles.loading, + size: 50 +}; + +export default LoadingIndicator; diff --git a/frontend/src/Components/Loading/LoadingMessage.css b/frontend/src/Components/Loading/LoadingMessage.css new file mode 100644 index 000000000..a7b39e76f --- /dev/null +++ b/frontend/src/Components/Loading/LoadingMessage.css @@ -0,0 +1,6 @@ +.loadingMessage { + margin: 50px 10px 0; + text-align: center; + font-weight: 300; + font-size: 36px; +} diff --git a/frontend/src/Components/Loading/LoadingMessage.js b/frontend/src/Components/Loading/LoadingMessage.js new file mode 100644 index 000000000..db6cb2b56 --- /dev/null +++ b/frontend/src/Components/Loading/LoadingMessage.js @@ -0,0 +1,20 @@ +import React from 'react'; +import styles from './LoadingMessage.css'; + +const messages = [ + 'Welcome to Radarr Aphrodite Preview. Enjoy' + // TODO Add some messages here +]; + +function LoadingMessage() { + const index = Math.floor(Math.random() * messages.length); + const message = messages[index]; + + return ( +
+ {message} +
+ ); +} + +export default LoadingMessage; diff --git a/frontend/src/Components/Measure.js b/frontend/src/Components/Measure.js new file mode 100644 index 000000000..a2f113de7 --- /dev/null +++ b/frontend/src/Components/Measure.js @@ -0,0 +1,38 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import ReactMeasure from 'react-measure'; + +class Measure extends Component { + + // + // Lifecycle + + componentWillUnmount() { + this.onMeasure.cancel(); + } + + // + // Listeners + + onMeasure = _.debounce((payload) => { + this.props.onMeasure(payload); + }, 250, { leading: true, trailing: false }) + + // + // Render + + render() { + return ( + + ); + } +} + +Measure.propTypes = { + onMeasure: PropTypes.func.isRequired +}; + +export default Measure; diff --git a/frontend/src/Components/Menu/FilterMenu.css b/frontend/src/Components/Menu/FilterMenu.css new file mode 100644 index 000000000..34991aed9 --- /dev/null +++ b/frontend/src/Components/Menu/FilterMenu.css @@ -0,0 +1,9 @@ +.filterMenu { + composes: menu from './Menu.css'; +} + +@media only screen and (max-width: $breakpointSmall) { + .filterMenu { + margin-right: 10px; + } +} diff --git a/frontend/src/Components/Menu/FilterMenu.js b/frontend/src/Components/Menu/FilterMenu.js new file mode 100644 index 000000000..d37876c22 --- /dev/null +++ b/frontend/src/Components/Menu/FilterMenu.js @@ -0,0 +1,110 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons } from 'Helpers/Props'; +import FilterMenuContent from './FilterMenuContent'; +import Menu from './Menu'; +import ToolbarMenuButton from './ToolbarMenuButton'; +import styles from './FilterMenu.css'; + +class FilterMenu extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isFilterModalOpen: false + }; + } + + // + // Listeners + + onCustomFiltersPress = () => { + this.setState({ isFilterModalOpen: true }); + } + + onFiltersModalClose = () => { + this.setState({ isFilterModalOpen: false }); + } + + // + // Render + + render(props) { + const { + className, + isDisabled, + selectedFilterKey, + filters, + customFilters, + buttonComponent: ButtonComponent, + filterModalConnectorComponent: FilterModalConnectorComponent, + filterModalConnectorComponentProps, + onFilterSelect, + ...otherProps + } = this.props; + + const showCustomFilters = !!FilterModalConnectorComponent; + + return ( +
+ + + + + + + + { + showCustomFilters && + + } +
+ ); + } +} + +FilterMenu.propTypes = { + className: PropTypes.string, + isDisabled: PropTypes.bool.isRequired, + selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + filters: PropTypes.arrayOf(PropTypes.object).isRequired, + customFilters: PropTypes.arrayOf(PropTypes.object).isRequired, + buttonComponent: PropTypes.func.isRequired, + filterModalConnectorComponent: PropTypes.func, + filterModalConnectorComponentProps: PropTypes.object, + onFilterSelect: PropTypes.func.isRequired +}; + +FilterMenu.defaultProps = { + className: styles.filterMenu, + isDisabled: false, + buttonComponent: ToolbarMenuButton +}; + +export default FilterMenu; diff --git a/frontend/src/Components/Menu/FilterMenuContent.js b/frontend/src/Components/Menu/FilterMenuContent.js new file mode 100644 index 000000000..7463e2c9e --- /dev/null +++ b/frontend/src/Components/Menu/FilterMenuContent.js @@ -0,0 +1,85 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import MenuContent from './MenuContent'; +import FilterMenuItem from './FilterMenuItem'; +import MenuItem from './MenuItem'; +import MenuItemSeparator from './MenuItemSeparator'; + +class FilterMenuContent extends Component { + + // + // Render + + render() { + const { + selectedFilterKey, + filters, + customFilters, + showCustomFilters, + onFilterSelect, + onCustomFiltersPress, + ...otherProps + } = this.props; + + return ( + + { + filters.map((filter) => { + return ( + + {filter.label} + + ); + }) + } + + { + customFilters.map((filter) => { + return ( + + {filter.label} + + ); + }) + } + + { + showCustomFilters && + + } + + { + showCustomFilters && + + Custom Filters + + } + + ); + } +} + +FilterMenuContent.propTypes = { + selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + filters: PropTypes.arrayOf(PropTypes.object).isRequired, + customFilters: PropTypes.arrayOf(PropTypes.object).isRequired, + showCustomFilters: PropTypes.bool.isRequired, + onFilterSelect: PropTypes.func.isRequired, + onCustomFiltersPress: PropTypes.func.isRequired +}; + +FilterMenuContent.defaultProps = { + showCustomFilters: false +}; + +export default FilterMenuContent; diff --git a/frontend/src/Components/Menu/FilterMenuItem.js b/frontend/src/Components/Menu/FilterMenuItem.js new file mode 100644 index 000000000..d2c495187 --- /dev/null +++ b/frontend/src/Components/Menu/FilterMenuItem.js @@ -0,0 +1,45 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import SelectedMenuItem from './SelectedMenuItem'; + +class FilterMenuItem extends Component { + + // + // Listeners + + onPress = () => { + const { + filterKey, + onPress + } = this.props; + + onPress(filterKey); + } + + // + // Render + + render() { + const { + filterKey, + selectedFilterKey, + ...otherProps + } = this.props; + + return ( + + ); + } +} + +FilterMenuItem.propTypes = { + filterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + onPress: PropTypes.func.isRequired +}; + +export default FilterMenuItem; diff --git a/frontend/src/Components/Menu/Menu.css b/frontend/src/Components/Menu/Menu.css new file mode 100644 index 000000000..9cce48fee --- /dev/null +++ b/frontend/src/Components/Menu/Menu.css @@ -0,0 +1,7 @@ +.tether { + z-index: 2000; +} + +.menu { + position: relative; +} diff --git a/frontend/src/Components/Menu/Menu.js b/frontend/src/Components/Menu/Menu.js new file mode 100644 index 000000000..da778bb7a --- /dev/null +++ b/frontend/src/Components/Menu/Menu.js @@ -0,0 +1,207 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import ReactDOM from 'react-dom'; +import TetherComponent from 'react-tether'; +import { align } from 'Helpers/Props'; +import styles from './Menu.css'; + +const baseTetherOptions = { + skipMoveElement: true, + constraints: [ + { + to: 'window', + attachment: 'together', + pin: true + } + ] +}; + +const tetherOptions = { + [align.RIGHT]: { + ...baseTetherOptions, + attachment: 'top right', + targetAttachment: 'bottom right' + }, + + [align.LEFT]: { + ...baseTetherOptions, + attachment: 'top left', + targetAttachment: 'bottom left' + } +}; + +class Menu extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isMenuOpen: false, + maxHeight: 0 + }; + } + + componentDidMount() { + this.setMaxHeight(); + } + + componentWillUnmount() { + this._removeListener(); + } + + // + // Control + + getMaxHeight() { + if (!this.props.enforceMaxHeight) { + return; + } + + const menu = ReactDOM.findDOMNode(this.refs.menu); + + if (!menu) { + return; + } + + const { bottom } = menu.getBoundingClientRect(); + const maxHeight = window.innerHeight - bottom; + + return maxHeight; + } + + setMaxHeight() { + this.setState({ + maxHeight: this.getMaxHeight() + }); + } + + _addListener() { + // Listen to resize events on the window and scroll events + // on all elements to ensure the menu is the best size possible. + // Listen for click events on the window to support closing the + // menu on clicks outside. + + window.addEventListener('resize', this.onWindowResize); + window.addEventListener('scroll', this.onWindowScroll, { capture: true }); + window.addEventListener('click', this.onWindowClick); + } + + _removeListener() { + window.removeEventListener('resize', this.onWindowResize); + window.removeEventListener('scroll', this.onWindowScroll, { capture: true }); + window.removeEventListener('click', this.onWindowClick); + } + + // + // Listeners + + onWindowClick = (event) => { + const menu = ReactDOM.findDOMNode(this.refs.menu); + const menuContent = ReactDOM.findDOMNode(this.refs.menuContent); + + if (!menu) { + return; + } + + if ((!menu.contains(event.target) || menuContent.contains(event.target)) && this.state.isMenuOpen) { + this.setState({ isMenuOpen: false }); + this._removeListener(); + } + } + + onWindowResize = () => { + this.setMaxHeight(); + } + + onWindowScroll = () => { + this.setMaxHeight(); + } + + onMenuButtonPress = () => { + const state = { + isMenuOpen: !this.state.isMenuOpen + }; + + if (this.state.isMenuOpen) { + this._removeListener(); + } else { + state.maxHeight = this.getMaxHeight(); + this._addListener(); + } + + this.setState(state); + } + + // + // Render + + render() { + const { + className, + children, + alignMenu + } = this.props; + + const { + maxHeight, + isMenuOpen + } = this.state; + + const childrenArray = React.Children.toArray(children); + const button = React.cloneElement( + childrenArray[0], + { + onPress: this.onMenuButtonPress + } + ); + + const content = React.cloneElement( + childrenArray[1], + { + ref: 'menuContent', + alignMenu, + maxHeight, + isOpen: isMenuOpen + } + ); + + return ( + +
+ {button} +
+ + { + isMenuOpen && + content + } +
+ ); + } +} + +Menu.propTypes = { + className: PropTypes.string, + children: PropTypes.node.isRequired, + alignMenu: PropTypes.oneOf([align.LEFT, align.RIGHT]), + enforceMaxHeight: PropTypes.bool.isRequired +}; + +Menu.defaultProps = { + className: styles.menu, + alignMenu: align.LEFT, + enforceMaxHeight: true +}; + +export default Menu; diff --git a/frontend/src/Components/Menu/MenuButton.css b/frontend/src/Components/Menu/MenuButton.css new file mode 100644 index 000000000..38812cfb7 --- /dev/null +++ b/frontend/src/Components/Menu/MenuButton.css @@ -0,0 +1,21 @@ +.menuButton { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + + &::after { + margin-left: 5px; + content: '\25BE'; + } + + &:hover { + color: $toobarButtonHoverColor; + } +} + +.isDisabled { + color: $disabledColor; + + pointer-events: none; +} diff --git a/frontend/src/Components/Menu/MenuButton.js b/frontend/src/Components/Menu/MenuButton.js new file mode 100644 index 000000000..477334a1d --- /dev/null +++ b/frontend/src/Components/Menu/MenuButton.js @@ -0,0 +1,49 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import Link from 'Components/Link/Link'; +import styles from './MenuButton.css'; + +class MenuButton extends Component { + + // + // Render + + render() { + const { + className, + children, + isDisabled, + onPress, + ...otherProps + } = this.props; + + return ( + + {children} + + ); + } +} + +MenuButton.propTypes = { + className: PropTypes.string, + children: PropTypes.node.isRequired, + isDisabled: PropTypes.bool.isRequired, + onPress: PropTypes.func +}; + +MenuButton.defaultProps = { + className: styles.menuButton, + isDisabled: false +}; + +export default MenuButton; diff --git a/frontend/src/Components/Menu/MenuContent.css b/frontend/src/Components/Menu/MenuContent.css new file mode 100644 index 000000000..0acc07390 --- /dev/null +++ b/frontend/src/Components/Menu/MenuContent.css @@ -0,0 +1,11 @@ +.menuContent { + display: flex; + flex-direction: column; + background-color: $toolbarMenuItemBackgroundColor; + line-height: 20px; +} + +.scroller { + display: flex; + flex-direction: column; +} diff --git a/frontend/src/Components/Menu/MenuContent.js b/frontend/src/Components/Menu/MenuContent.js new file mode 100644 index 000000000..1acacf80f --- /dev/null +++ b/frontend/src/Components/Menu/MenuContent.js @@ -0,0 +1,43 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Scroller from 'Components/Scroller/Scroller'; +import styles from './MenuContent.css'; + +class MenuContent extends Component { + + // + // Render + + render() { + const { + className, + children, + maxHeight + } = this.props; + + return ( +
+ + {children} + +
+ ); + } +} + +MenuContent.propTypes = { + className: PropTypes.string, + children: PropTypes.node.isRequired, + maxHeight: PropTypes.number +}; + +MenuContent.defaultProps = { + className: styles.menuContent +}; + +export default MenuContent; diff --git a/frontend/src/Components/Menu/MenuItem.css b/frontend/src/Components/Menu/MenuItem.css new file mode 100644 index 000000000..bae1a649c --- /dev/null +++ b/frontend/src/Components/Menu/MenuItem.css @@ -0,0 +1,19 @@ +.menuItem { + @add-mixin truncate; + + display: block; + flex-shrink: 0; + padding: 10px 20px; + min-width: 150px; + max-width: 250px; + background-color: $toolbarMenuItemBackgroundColor; + color: $menuItemColor; + line-height: 20px; + + &:hover, + &:focus { + background-color: $toolbarMenuItemHoverBackgroundColor; + color: $menuItemHoverColor; + text-decoration: none; + } +} diff --git a/frontend/src/Components/Menu/MenuItem.js b/frontend/src/Components/Menu/MenuItem.js new file mode 100644 index 000000000..ff083450b --- /dev/null +++ b/frontend/src/Components/Menu/MenuItem.js @@ -0,0 +1,38 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Link from 'Components/Link/Link'; +import styles from './MenuItem.css'; + +class MenuItem extends Component { + + // + // Render + + render() { + const { + className, + children, + ...otherProps + } = this.props; + + return ( + + {children} + + ); + } +} + +MenuItem.propTypes = { + className: PropTypes.string, + children: PropTypes.node.isRequired +}; + +MenuItem.defaultProps = { + className: styles.menuItem +}; + +export default MenuItem; diff --git a/frontend/src/Components/Menu/MenuItemSeparator.css b/frontend/src/Components/Menu/MenuItemSeparator.css new file mode 100644 index 000000000..a867e3153 --- /dev/null +++ b/frontend/src/Components/Menu/MenuItemSeparator.css @@ -0,0 +1,5 @@ +.separator { + overflow: hidden; + height: 1px; + background-color: $themeDarkColor; +} diff --git a/frontend/src/Components/Menu/MenuItemSeparator.js b/frontend/src/Components/Menu/MenuItemSeparator.js new file mode 100644 index 000000000..e586670c9 --- /dev/null +++ b/frontend/src/Components/Menu/MenuItemSeparator.js @@ -0,0 +1,10 @@ +import React from 'react'; +import styles from './MenuItemSeparator.css'; + +function MenuItemSeparator() { + return ( +
+ ); +} + +export default MenuItemSeparator; diff --git a/frontend/src/Components/Menu/PageMenuButton.css b/frontend/src/Components/Menu/PageMenuButton.css new file mode 100644 index 000000000..e6954f600 --- /dev/null +++ b/frontend/src/Components/Menu/PageMenuButton.css @@ -0,0 +1,11 @@ +.menuButton { + composes: menuButton from './MenuButton.css'; + + &:hover { + color: #666; + } +} + +.label { + margin-left: 5px; +} diff --git a/frontend/src/Components/Menu/PageMenuButton.js b/frontend/src/Components/Menu/PageMenuButton.js new file mode 100644 index 000000000..abbfc98f8 --- /dev/null +++ b/frontend/src/Components/Menu/PageMenuButton.js @@ -0,0 +1,36 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Icon from 'Components/Icon'; +import MenuButton from 'Components/Menu/MenuButton'; +import styles from './PageMenuButton.css'; + +function PageMenuButton(props) { + const { + iconName, + text, + ...otherProps + } = props; + + return ( + + + +
+ {text} +
+
+ ); +} + +PageMenuButton.propTypes = { + iconName: PropTypes.object.isRequired, + text: PropTypes.string +}; + +export default PageMenuButton; diff --git a/frontend/src/Components/Menu/SelectedMenuItem.css b/frontend/src/Components/Menu/SelectedMenuItem.css new file mode 100644 index 000000000..739419d69 --- /dev/null +++ b/frontend/src/Components/Menu/SelectedMenuItem.css @@ -0,0 +1,15 @@ +.item { + display: flex; + justify-content: space-between; + white-space: nowrap; +} + +.isSelected { + visibility: visible; + margin-left: 20px; +} + +.isNotSelected { + visibility: hidden; + margin-left: 20px; +} diff --git a/frontend/src/Components/Menu/SelectedMenuItem.js b/frontend/src/Components/Menu/SelectedMenuItem.js new file mode 100644 index 000000000..8b0805c57 --- /dev/null +++ b/frontend/src/Components/Menu/SelectedMenuItem.js @@ -0,0 +1,63 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import MenuItem from './MenuItem'; +import styles from './SelectedMenuItem.css'; + +class SelectedMenuItem extends Component { + + // + // Listeners + + onPress = () => { + const { + name, + onPress + } = this.props; + + onPress(name); + } + + // + // Render + + render() { + const { + children, + selectedIconName, + isSelected, + ...otherProps + } = this.props; + + return ( + +
+ {children} + + +
+
+ ); + } +} + +SelectedMenuItem.propTypes = { + name: PropTypes.string, + children: PropTypes.node.isRequired, + selectedIconName: PropTypes.object.isRequired, + isSelected: PropTypes.bool.isRequired, + onPress: PropTypes.func.isRequired +}; + +SelectedMenuItem.defaultProps = { + selectedIconName: icons.CHECK +}; + +export default SelectedMenuItem; diff --git a/frontend/src/Components/Menu/SortMenu.js b/frontend/src/Components/Menu/SortMenu.js new file mode 100644 index 000000000..a9a6a184e --- /dev/null +++ b/frontend/src/Components/Menu/SortMenu.js @@ -0,0 +1,40 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons } from 'Helpers/Props'; +import Menu from 'Components/Menu/Menu'; +import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton'; + +function SortMenu(props) { + const { + className, + children, + isDisabled, + ...otherProps + } = props; + + return ( + + + {children} + + ); +} + +SortMenu.propTypes = { + className: PropTypes.string, + children: PropTypes.node.isRequired, + isDisabled: PropTypes.bool.isRequired +}; + +SortMenu.defaultProps = { + isDisabled: false +}; + +export default SortMenu; diff --git a/frontend/src/Components/Menu/SortMenuItem.js b/frontend/src/Components/Menu/SortMenuItem.js new file mode 100644 index 000000000..e35864ae6 --- /dev/null +++ b/frontend/src/Components/Menu/SortMenuItem.js @@ -0,0 +1,37 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons, sortDirections } from 'Helpers/Props'; +import SelectedMenuItem from './SelectedMenuItem'; + +function SortMenuItem(props) { + const { + name, + sortKey, + sortDirection, + ...otherProps + } = props; + + const isSelected = name === sortKey; + + return ( + + ); +} + +SortMenuItem.propTypes = { + name: PropTypes.string, + sortKey: PropTypes.string, + sortDirection: PropTypes.oneOf(sortDirections.all), + onPress: PropTypes.func.isRequired +}; + +SortMenuItem.defaultProps = { + name: null +}; + +export default SortMenuItem; diff --git a/frontend/src/Components/Menu/ToolbarMenuButton.css b/frontend/src/Components/Menu/ToolbarMenuButton.css new file mode 100644 index 000000000..c8a905e17 --- /dev/null +++ b/frontend/src/Components/Menu/ToolbarMenuButton.css @@ -0,0 +1,11 @@ +.menuButton { + composes: menuButton from './MenuButton.css'; + + width: $toolbarButtonWidth; + height: $toolbarHeight; + text-align: center; +} + +.label { + composes: label from 'Components/Page/Toolbar/PageToolbarButton.css'; +} diff --git a/frontend/src/Components/Menu/ToolbarMenuButton.js b/frontend/src/Components/Menu/ToolbarMenuButton.js new file mode 100644 index 000000000..b80d6eaa3 --- /dev/null +++ b/frontend/src/Components/Menu/ToolbarMenuButton.js @@ -0,0 +1,38 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Icon from 'Components/Icon'; +import MenuButton from 'Components/Menu/MenuButton'; +import styles from './ToolbarMenuButton.css'; + +function ToolbarMenuButton(props) { + const { + iconName, + text, + ...otherProps + } = props; + + return ( + +
+ + +
+ {text} +
+
+
+ ); +} + +ToolbarMenuButton.propTypes = { + iconName: PropTypes.object.isRequired, + text: PropTypes.string +}; + +export default ToolbarMenuButton; diff --git a/frontend/src/Components/Menu/ViewMenu.js b/frontend/src/Components/Menu/ViewMenu.js new file mode 100644 index 000000000..60c77e003 --- /dev/null +++ b/frontend/src/Components/Menu/ViewMenu.js @@ -0,0 +1,37 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons } from 'Helpers/Props'; +import Menu from 'Components/Menu/Menu'; +import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton'; + +function ViewMenu(props) { + const { + children, + isDisabled, + ...otherProps + } = props; + + return ( + + + {children} + + ); +} + +ViewMenu.propTypes = { + children: PropTypes.node.isRequired, + isDisabled: PropTypes.bool.isRequired +}; + +ViewMenu.defaultProps = { + isDisabled: false +}; + +export default ViewMenu; diff --git a/frontend/src/Components/Menu/ViewMenuItem.js b/frontend/src/Components/Menu/ViewMenuItem.js new file mode 100644 index 000000000..d355d6e94 --- /dev/null +++ b/frontend/src/Components/Menu/ViewMenuItem.js @@ -0,0 +1,28 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import SelectedMenuItem from './SelectedMenuItem'; + +function ViewMenuItem(props) { + const { + name, + selectedView, + ...otherProps + } = props; + + const isSelected = name === selectedView; + + return ( + + ); +} + +ViewMenuItem.propTypes = { + name: PropTypes.string, + selectedView: PropTypes.string.isRequired +}; + +export default ViewMenuItem; diff --git a/frontend/src/Components/Modal/ConfirmModal.js b/frontend/src/Components/Modal/ConfirmModal.js new file mode 100644 index 000000000..5bb783d43 --- /dev/null +++ b/frontend/src/Components/Modal/ConfirmModal.js @@ -0,0 +1,88 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { kinds, sizes } from 'Helpers/Props'; +import Button from 'Components/Link/Button'; +import SpinnerButton from 'Components/Link/SpinnerButton'; +import Modal from 'Components/Modal/Modal'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; + +function ConfirmModal(props) { + const { + isOpen, + kind, + size, + title, + message, + confirmLabel, + cancelLabel, + hideCancelButton, + isSpinning, + onConfirm, + onCancel + } = props; + + return ( + + + {title} + + + {message} + + + + { + !hideCancelButton && + + } + + + {confirmLabel} + + + + + ); +} + +ConfirmModal.propTypes = { + className: PropTypes.string, + isOpen: PropTypes.bool.isRequired, + kind: PropTypes.oneOf(kinds.all), + size: PropTypes.oneOf(sizes.all), + title: PropTypes.string.isRequired, + message: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired, + confirmLabel: PropTypes.string, + cancelLabel: PropTypes.string, + hideCancelButton: PropTypes.bool, + isSpinning: PropTypes.bool.isRequired, + onConfirm: PropTypes.func.isRequired, + onCancel: PropTypes.func.isRequired +}; + +ConfirmModal.defaultProps = { + kind: kinds.PRIMARY, + size: sizes.MEDIUM, + confirmLabel: 'OK', + cancelLabel: 'Cancel', + isSpinning: false +}; + +export default ConfirmModal; diff --git a/frontend/src/Components/Modal/Modal.css b/frontend/src/Components/Modal/Modal.css new file mode 100644 index 000000000..a9b2a27ae --- /dev/null +++ b/frontend/src/Components/Modal/Modal.css @@ -0,0 +1,92 @@ +.modalContainer { + position: absolute; + top: 0; + z-index: 1000; + width: 100%; + height: 100%; +} + +.modalBackdrop { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; + background-color: $modalBackdropBackgroundColor; + opacity: 1; +} + +.modal { + position: relative; + display: flex; + max-height: 90%; + border-radius: 6px; + opacity: 1; +} + +.modalOpen { + /* Prevent the body from scrolling when the modal is open */ + overflow: hidden !important; +} + +/* + * Sizes + */ + +.small { + composes: modal; + + width: 480px; +} + +.medium { + composes: modal; + + width: 720px; +} + +.large { + composes: modal; + + width: 1080px; +} + +.extraLarge { + composes: modal; + + width: 1280px; +} + +@media only screen and (max-width: $breakpointExtraLarge) { + .modal.extraLarge { + width: 90%; + } +} + +@media only screen and (max-width: $breakpointLarge) { + .modal.large { + width: 90%; + } +} + +@media only screen and (max-width: $breakpointMedium) { + .modal.small, + .modal.medium { + width: 90%; + } +} + +@media only screen and (max-width: $breakpointSmall) { + .modalContainer { + position: fixed; + } + + .modal.small, + .modal.medium, + .modal.large, + .modal.extraLarge { + max-height: 100%; + width: 100%; + height: 100% !important; + } +} diff --git a/frontend/src/Components/Modal/Modal.js b/frontend/src/Components/Modal/Modal.js new file mode 100644 index 000000000..a9de82c6d --- /dev/null +++ b/frontend/src/Components/Modal/Modal.js @@ -0,0 +1,215 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import ReactDOM from 'react-dom'; +import classNames from 'classnames'; +import elementClass from 'element-class'; +import getUniqueElememtId from 'Utilities/getUniqueElementId'; +import * as keyCodes from 'Utilities/Constants/keyCodes'; +import { sizes } from 'Helpers/Props'; +import ErrorBoundary from 'Components/Error/ErrorBoundary'; +import ModalError from './ModalError'; +import styles from './Modal.css'; + +const openModals = []; + +function removeFromOpenModals(id) { + const index = openModals.indexOf(id); + + if (index >= 0) { + openModals.splice(index, 1); + } +} + +class Modal extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._node = document.getElementById('modal-root'); + this._backgroundRef = null; + this._modalId = getUniqueElememtId(); + } + + componentDidMount() { + if (this.props.isOpen) { + this._openModal(); + } + } + + componentDidUpdate(prevProps) { + const { + isOpen + } = this.props; + + if (!prevProps.isOpen && isOpen) { + this._openModal(); + } else if (prevProps.isOpen && !isOpen) { + this._closeModal(); + } + } + + componentWillUnmount() { + if (this.props.isOpen) { + this._closeModal(); + } + } + + // + // Control + + _setBackgroundRef = (ref) => { + this._backgroundRef = ref; + } + + _openModal() { + openModals.push(this._modalId); + window.addEventListener('keydown', this.onKeyDown); + + if (openModals.length === 1) { + elementClass(document.body).add(styles.modalOpen); + } + } + + _closeModal() { + removeFromOpenModals(this._modalId); + window.removeEventListener('keydown', this.onKeyDown); + + if (openModals.length === 0) { + elementClass(document.body).remove(styles.modalOpen); + } + } + + _isBackdropTarget(event) { + const targetElement = this._findEventTarget(event); + + if (targetElement) { + const backgroundElement = ReactDOM.findDOMNode(this._backgroundRef); + + return backgroundElement.isEqualNode(targetElement); + } + + return false; + } + + _findEventTarget(event) { + const changedTouches = event.changedTouches; + + if (!changedTouches) { + return event.target; + } + + if (changedTouches.length === 1) { + const touch = changedTouches[0]; + + return document.elementFromPoint(touch.clientX, touch.clientY); + } + } + + // + // Listeners + + onBackdropBeginPress = (event) => { + this._isBackdropPressed = this._isBackdropTarget(event); + } + + onBackdropEndPress = (event) => { + const { + closeOnBackgroundClick, + onModalClose + } = this.props; + + if ( + this._isBackdropPressed && + this._isBackdropTarget(event) && + closeOnBackgroundClick + ) { + onModalClose(); + } + + this._isBackdropPressed = false; + } + + onKeyDown = (event) => { + const keyCode = event.keyCode; + + if (keyCode === keyCodes.ESCAPE) { + if (openModals.indexOf(this._modalId) === openModals.length - 1) { + event.preventDefault(); + event.stopPropagation(); + + this.props.onModalClose(); + } + } + } + + // + // Render + + render() { + const { + className, + style, + backdropClassName, + size, + children, + isOpen, + onModalClose + } = this.props; + + if (!isOpen) { + return null; + } + + return ReactDOM.createPortal( +
+
+
+ + {children} + +
+
+
, + this._node + ); + } +} + +Modal.propTypes = { + className: PropTypes.string, + style: PropTypes.object, + backdropClassName: PropTypes.string, + size: PropTypes.oneOf(sizes.all), + children: PropTypes.node, + isOpen: PropTypes.bool.isRequired, + closeOnBackgroundClick: PropTypes.bool.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +Modal.defaultProps = { + className: styles.modal, + backdropClassName: styles.modalBackdrop, + size: sizes.LARGE, + closeOnBackgroundClick: true +}; + +export default Modal; diff --git a/frontend/src/Components/Modal/ModalBody.css b/frontend/src/Components/Modal/ModalBody.css new file mode 100644 index 000000000..ebeef29de --- /dev/null +++ b/frontend/src/Components/Modal/ModalBody.css @@ -0,0 +1,12 @@ +.modalBody { + flex: 1 0 1px; + padding: $modalBodyPadding; +} + +.modalScroller { + flex-grow: 1; +} + +.innerModalBody { + padding: $modalBodyPadding; +} diff --git a/frontend/src/Components/Modal/ModalBody.js b/frontend/src/Components/Modal/ModalBody.js new file mode 100644 index 000000000..a35f2ecf5 --- /dev/null +++ b/frontend/src/Components/Modal/ModalBody.js @@ -0,0 +1,59 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { scrollDirections } from 'Helpers/Props'; +import Scroller from 'Components/Scroller/Scroller'; +import styles from './ModalBody.css'; + +class ModalBody extends Component { + + // + // Render + + render() { + const { + innerClassName, + scrollDirection, + children, + ...otherProps + } = this.props; + + let className = this.props.className; + const hasScroller = scrollDirection !== scrollDirections.NONE; + + if (!className) { + className = hasScroller ? styles.modalScroller : styles.modalBody; + } + + return ( + + { + hasScroller ? +
+ {children} +
: + children + } +
+ ); + } + +} + +ModalBody.propTypes = { + className: PropTypes.string, + innerClassName: PropTypes.string, + children: PropTypes.node, + scrollDirection: PropTypes.oneOf([scrollDirections.NONE, scrollDirections.HORIZONTAL, scrollDirections.VERTICAL]) +}; + +ModalBody.defaultProps = { + innerClassName: styles.innerModalBody, + scrollDirection: scrollDirections.VERTICAL +}; + +export default ModalBody; diff --git a/frontend/src/Components/Modal/ModalContent.css b/frontend/src/Components/Modal/ModalContent.css new file mode 100644 index 000000000..afd798dfa --- /dev/null +++ b/frontend/src/Components/Modal/ModalContent.css @@ -0,0 +1,23 @@ +.modalContent { + position: relative; + display: flex; + flex-direction: column; + flex-grow: 1; + width: 100%; + background-color: $modalBackgroundColor; +} + +.closeButton { + position: absolute; + top: 0; + right: 0; + z-index: 1; + width: 60px; + height: 60px; + text-align: center; + line-height: 60px; + + &:hover { + color: $modalCloseButtonHoverColor; + } +} diff --git a/frontend/src/Components/Modal/ModalContent.js b/frontend/src/Components/Modal/ModalContent.js new file mode 100644 index 000000000..655046fe4 --- /dev/null +++ b/frontend/src/Components/Modal/ModalContent.js @@ -0,0 +1,52 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons } from 'Helpers/Props'; +import Link from 'Components/Link/Link'; +import Icon from 'Components/Icon'; +import styles from './ModalContent.css'; + +function ModalContent(props) { + const { + className, + children, + showCloseButton, + onModalClose, + ...otherProps + } = props; + + return ( +
+ { + showCloseButton && + + + + } + + {children} +
+ ); +} + +ModalContent.propTypes = { + className: PropTypes.string, + children: PropTypes.node, + showCloseButton: PropTypes.bool.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +ModalContent.defaultProps = { + className: styles.modalContent, + showCloseButton: true +}; + +export default ModalContent; diff --git a/frontend/src/Components/Modal/ModalError.css b/frontend/src/Components/Modal/ModalError.css new file mode 100644 index 000000000..54dbdbc63 --- /dev/null +++ b/frontend/src/Components/Modal/ModalError.css @@ -0,0 +1,15 @@ +.message { + composes: message from 'Components/Error/ErrorBoundaryError.css'; + + margin: 0; + margin-bottom: 30px; + font-weight: normal; + font-size: 26px; +} + +.details { + composes: details from 'Components/Error/ErrorBoundaryError.css'; + + margin: 0; + margin-top: 20px; +} diff --git a/frontend/src/Components/Modal/ModalError.js b/frontend/src/Components/Modal/ModalError.js new file mode 100644 index 000000000..df99a5b32 --- /dev/null +++ b/frontend/src/Components/Modal/ModalError.js @@ -0,0 +1,46 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import ErrorBoundaryError from 'Components/Error/ErrorBoundaryError'; +import Button from 'Components/Link/Button'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import styles from './ModalError.css'; + +function ModalError(props) { + const { + onModalClose, + ...otherProps + } = props; + + return ( + + + Error + + + + + + + + + + ); +} + +ModalError.propTypes = { + onModalClose: PropTypes.func.isRequired +}; + +export default ModalError; diff --git a/frontend/src/Components/Modal/ModalFooter.css b/frontend/src/Components/Modal/ModalFooter.css new file mode 100644 index 000000000..3b817d2bf --- /dev/null +++ b/frontend/src/Components/Modal/ModalFooter.css @@ -0,0 +1,23 @@ +.modalFooter { + display: flex; + align-items: center; + justify-content: flex-end; + flex-shrink: 0; + padding: 15px 30px; + border-top: 1px solid $borderColor; + + a, + button { + margin-left: 10px; + + &:first-child { + margin-left: 0; + } + } +} + +@media only screen and (max-width: $breakpointSmall) { + .modalFooter { + padding: 15px; + } +} diff --git a/frontend/src/Components/Modal/ModalFooter.js b/frontend/src/Components/Modal/ModalFooter.js new file mode 100644 index 000000000..0cf8811d3 --- /dev/null +++ b/frontend/src/Components/Modal/ModalFooter.js @@ -0,0 +1,32 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import styles from './ModalFooter.css'; + +class ModalFooter extends Component { + + // + // Render + + render() { + const { + children, + ...otherProps + } = this.props; + + return ( +
+ {children} +
+ ); + } + +} + +ModalFooter.propTypes = { + children: PropTypes.node +}; + +export default ModalFooter; diff --git a/frontend/src/Components/Modal/ModalHeader.css b/frontend/src/Components/Modal/ModalHeader.css new file mode 100644 index 000000000..eab77a9f8 --- /dev/null +++ b/frontend/src/Components/Modal/ModalHeader.css @@ -0,0 +1,8 @@ +.modalHeader { + @add-mixin truncate; + + flex-shrink: 0; + padding: 15px 50px 15px 30px; + border-bottom: 1px solid $borderColor; + font-size: 18px; +} diff --git a/frontend/src/Components/Modal/ModalHeader.js b/frontend/src/Components/Modal/ModalHeader.js new file mode 100644 index 000000000..52879b57d --- /dev/null +++ b/frontend/src/Components/Modal/ModalHeader.js @@ -0,0 +1,32 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import styles from './ModalHeader.css'; + +class ModalHeader extends Component { + + // + // Render + + render() { + const { + children, + ...otherProps + } = this.props; + + return ( +
+ {children} +
+ ); + } + +} + +ModalHeader.propTypes = { + children: PropTypes.node +}; + +export default ModalHeader; diff --git a/frontend/src/Components/MonitorToggleButton.css b/frontend/src/Components/MonitorToggleButton.css new file mode 100644 index 000000000..794af1e98 --- /dev/null +++ b/frontend/src/Components/MonitorToggleButton.css @@ -0,0 +1,11 @@ +.toggleButton { + composes: button from 'Components/Link/IconButton.css'; + + padding: 0; + font-size: inherit; +} + +.isDisabled { + color: $disabledColor; + cursor: not-allowed; +} diff --git a/frontend/src/Components/MonitorToggleButton.js b/frontend/src/Components/MonitorToggleButton.js new file mode 100644 index 000000000..15ac3d7fe --- /dev/null +++ b/frontend/src/Components/MonitorToggleButton.js @@ -0,0 +1,79 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { icons } from 'Helpers/Props'; +import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; +import styles from './MonitorToggleButton.css'; + +function getTooltip(monitored, isDisabled) { + if (isDisabled) { + return 'Cannot toogle monitored state when series is unmonitored'; + } + + if (monitored) { + return 'Monitored, click to unmonitor'; + } + + return 'Unmonitored, click to monitor'; +} + +class MonitorToggleButton extends Component { + + // + // Listeners + + onPress = (event) => { + const shiftKey = event.nativeEvent.shiftKey; + + this.props.onPress(!this.props.monitored, { shiftKey }); + } + + // + // Render + + render() { + const { + className, + monitored, + isDisabled, + isSaving, + size, + ...otherProps + } = this.props; + + const iconName = monitored ? icons.MONITORED : icons.UNMONITORED; + + return ( + + ); + } +} + +MonitorToggleButton.propTypes = { + className: PropTypes.string.isRequired, + monitored: PropTypes.bool.isRequired, + size: PropTypes.number, + isDisabled: PropTypes.bool.isRequired, + isSaving: PropTypes.bool.isRequired, + onPress: PropTypes.func.isRequired +}; + +MonitorToggleButton.defaultProps = { + className: styles.toggleButton, + isDisabled: false, + isSaving: false +}; + +export default MonitorToggleButton; diff --git a/frontend/src/Components/NotFound.css b/frontend/src/Components/NotFound.css new file mode 100644 index 000000000..9aaf1114f --- /dev/null +++ b/frontend/src/Components/NotFound.css @@ -0,0 +1,14 @@ +.container { + text-align: center; +} + +.message { + margin: 50px 0; + text-align: center; + font-weight: 300; + font-size: 36px; +} + +.image { + height: 350px; +} diff --git a/frontend/src/Components/NotFound.js b/frontend/src/Components/NotFound.js new file mode 100644 index 000000000..cdd6eda2c --- /dev/null +++ b/frontend/src/Components/NotFound.js @@ -0,0 +1,31 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import PageContent from 'Components/Page/PageContent'; +import styles from './NotFound.css'; + +function NotFound({ message }) { + return ( + +
+
+ {message} +
+ + +
+
+ ); +} + +NotFound.propTypes = { + message: PropTypes.string.isRequired +}; + +NotFound.defaultProps = { + message: 'You must be lost, nothing to see here.' +}; + +export default NotFound; diff --git a/frontend/src/Components/Page/ErrorPage.css b/frontend/src/Components/Page/ErrorPage.css new file mode 100644 index 000000000..e62a82a6b --- /dev/null +++ b/frontend/src/Components/Page/ErrorPage.css @@ -0,0 +1,12 @@ +.page { + composes: page from './Page.css'; + + margin-top: 20px; + text-align: center; + font-size: 20px; +} + +.version { + margin-top: 20px; + font-size: 16px; +} diff --git a/frontend/src/Components/Page/ErrorPage.js b/frontend/src/Components/Page/ErrorPage.js new file mode 100644 index 000000000..018e98ca1 --- /dev/null +++ b/frontend/src/Components/Page/ErrorPage.js @@ -0,0 +1,56 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import getErrorMessage from 'Utilities/Object/getErrorMessage'; +import styles from './ErrorPage.css'; + +function ErrorPage(props) { + const { + version, + isLocalStorageSupported, + moviesError, + customFiltersError, + tagsError, + qualityProfilesError, + uiSettingsError + } = props; + + let errorMessage = 'Failed to load Radarr'; + + if (!isLocalStorageSupported) { + errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.'; + } else if (moviesError) { + errorMessage = getErrorMessage(moviesError, 'Failed to load movie from API'); + } else if (customFiltersError) { + errorMessage = getErrorMessage(customFiltersError, 'Failed to load custom filters from API'); + } else if (tagsError) { + errorMessage = getErrorMessage(tagsError, 'Failed to load tags from API'); + } else if (qualityProfilesError) { + errorMessage = getErrorMessage(qualityProfilesError, 'Failed to load quality profiles from API'); + } else if (uiSettingsError) { + errorMessage = getErrorMessage(uiSettingsError, 'Failed to load UI settings from API'); + } + + return ( +
+
+ {errorMessage} +
+ +
+ Version {version} +
+
+ ); +} + +ErrorPage.propTypes = { + version: PropTypes.string.isRequired, + isLocalStorageSupported: PropTypes.bool.isRequired, + moviesError: PropTypes.object, + customFiltersError: PropTypes.object, + tagsError: PropTypes.object, + qualityProfilesError: PropTypes.object, + uiSettingsError: PropTypes.object +}; + +export default ErrorPage; diff --git a/frontend/src/Components/Page/Header/KeyboardShortcutsModal.js b/frontend/src/Components/Page/Header/KeyboardShortcutsModal.js new file mode 100644 index 000000000..a1d106b58 --- /dev/null +++ b/frontend/src/Components/Page/Header/KeyboardShortcutsModal.js @@ -0,0 +1,31 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { sizes } from 'Helpers/Props'; +import Modal from 'Components/Modal/Modal'; +import KeyboardShortcutsModalContentConnector from './KeyboardShortcutsModalContentConnector'; + +function KeyboardShortcutsModal(props) { + const { + isOpen, + onModalClose + } = props; + + return ( + + + + ); +} + +KeyboardShortcutsModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default KeyboardShortcutsModal; diff --git a/frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.css b/frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.css new file mode 100644 index 000000000..4425e0e0d --- /dev/null +++ b/frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.css @@ -0,0 +1,15 @@ +.shortcut { + display: flex; + justify-content: space-between; + padding: 5px 20px; + font-size: 18px; +} + +.key { + padding: 2px 4px; + border-radius: 3px; + background-color: $defaultColor; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); + color: $white; + font-size: 16px; +} diff --git a/frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.js b/frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.js new file mode 100644 index 000000000..9c07e047c --- /dev/null +++ b/frontend/src/Components/Page/Header/KeyboardShortcutsModalContent.js @@ -0,0 +1,90 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { shortcuts } from 'Components/keyboardShortcuts'; +import Button from 'Components/Link/Button'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import styles from './KeyboardShortcutsModalContent.css'; + +function getShortcuts() { + const allShortcuts = []; + + Object.keys(shortcuts).forEach((key) => { + allShortcuts.push(shortcuts[key]); + }); + + return allShortcuts; +} + +function getShortcutKey(combo, isOsx) { + const comboMatch = combo.match(/(.+?)\+(.)/); + + if (!comboMatch) { + return combo; + } + + const modifier = comboMatch[1]; + const key = comboMatch[2]; + let osModifier = modifier; + + if (modifier === 'mod') { + osModifier = isOsx ? 'cmd' : 'ctrl'; + } + + return `${osModifier} + ${key}`; +} + +function KeyboardShortcutsModalContent(props) { + const { + isOsx, + onModalClose + } = props; + + const allShortcuts = getShortcuts(); + + return ( + + + Keyboard Shortcuts + + + + { + allShortcuts.map((shortcut) => { + return ( +
+
+ {getShortcutKey(shortcut.key, isOsx)} +
+ +
+ {shortcut.name} +
+
+ ); + }) + } +
+ + + + +
+ ); +} + +KeyboardShortcutsModalContent.propTypes = { + isOsx: PropTypes.bool.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +export default KeyboardShortcutsModalContent; diff --git a/frontend/src/Components/Page/Header/KeyboardShortcutsModalContentConnector.js b/frontend/src/Components/Page/Header/KeyboardShortcutsModalContentConnector.js new file mode 100644 index 000000000..d80877153 --- /dev/null +++ b/frontend/src/Components/Page/Header/KeyboardShortcutsModalContentConnector.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector'; +import KeyboardShortcutsModalContent from './KeyboardShortcutsModalContent'; + +function createMapStateToProps() { + return createSelector( + createSystemStatusSelector(), + (systemStatus) => { + return { + isOsx: systemStatus.isOsx + }; + } + ); +} + +export default connect(createMapStateToProps)(KeyboardShortcutsModalContent); diff --git a/frontend/src/Components/Page/Header/MovieSearchInput.css b/frontend/src/Components/Page/Header/MovieSearchInput.css new file mode 100644 index 000000000..10eefae1e --- /dev/null +++ b/frontend/src/Components/Page/Header/MovieSearchInput.css @@ -0,0 +1,96 @@ +.wrapper { + display: flex; + align-items: center; +} + +.input { + margin-left: 8px; + width: 200px; + border: none; + border-bottom: solid 1px $white; + border-radius: 0; + background-color: transparent; + box-shadow: none; + color: $white; + transition: border 0.3s ease-out; + + &::placeholder { + color: $white; + transition: color 0.3s ease-out; + } + + &:focus { + outline: 0; + border-bottom-color: transparent; + + &::placeholder { + color: transparent; + } + } +} + +.container { + position: relative; + flex-grow: 1; +} + +.movieContainer { + @add-mixin scrollbar; + @add-mixin scrollbarTrack; + @add-mixin scrollbarThumb; +} + +.containerOpen { + .movieContainer { + position: absolute; + top: 42px; + z-index: 1; + overflow-y: auto; + min-width: 100%; + max-height: 230px; + border: 1px solid $themeDarkColor; + border-radius: 4px; + border-top-left-radius: 0; + border-top-right-radius: 0; + background-color: $themeDarkColor; + box-shadow: inset 0 1px 1px $inputBoxShadowColor; + color: $menuItemColor; + } +} + +.list { + margin: 5px 0; + padding-left: 0; + list-style-type: none; +} + +.listItem { + padding: 0 16px; + white-space: nowrap; +} + +.highlighted { + background-color: $themeLightColor; +} + +.sectionTitle { + padding: 5px 8px; + color: $disabledColor; +} + +.addNewSeriesSuggestion { + padding: 0 3px; + cursor: pointer; +} + +@media only screen and (max-width: $breakpointSmall) { + .input { + min-width: 150px; + max-width: 200px; + } + + .container { + min-width: 0; + max-width: 200px; + } +} diff --git a/frontend/src/Components/Page/Header/MovieSearchInput.js b/frontend/src/Components/Page/Header/MovieSearchInput.js new file mode 100644 index 000000000..fa49f0716 --- /dev/null +++ b/frontend/src/Components/Page/Header/MovieSearchInput.js @@ -0,0 +1,264 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Autosuggest from 'react-autosuggest'; +import jdu from 'jdu'; +import { icons } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts'; +import MovieSearchResult from './MovieSearchResult'; +import styles from './MovieSearchInput.css'; + +const ADD_NEW_TYPE = 'addNew'; + +class MovieSearchInput extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._autosuggest = null; + + this.state = { + value: '', + suggestions: [] + }; + } + + componentDidMount() { + this.props.bindShortcut(shortcuts.MOVIE_SEARCH_INPUT.key, this.focusInput); + } + + // + // Control + + setAutosuggestRef = (ref) => { + this._autosuggest = ref; + } + + focusInput = (event) => { + event.preventDefault(); + this._autosuggest.input.focus(); + } + + getSectionSuggestions(section) { + return section.suggestions; + } + + renderSectionTitle(section) { + return ( +
+ {section.title} +
+ ); + } + + getSuggestionValue({ title }) { + return title; + } + + renderSuggestion(item, { query }) { + if (item.type === ADD_NEW_TYPE) { + return ( +
+ Search for {query} +
+ ); + } + + return ( + + ); + } + + goToMovie(movie) { + this.setState({ value: '' }); + this.props.onGoToMovie(movie.titleSlug); + } + + reset() { + this.setState({ + value: '', + suggestions: [] + }); + } + + // + // Listeners + + onChange = (event, { newValue, method }) => { + if (method === 'up' || method === 'down') { + return; + } + + this.setState({ value: newValue }); + } + + onKeyDown = (event) => { + if (event.key !== 'Tab' && event.key !== 'Enter') { + return; + } + + const { + suggestions, + value + } = this.state; + + const { + highlightedSectionIndex, + highlightedSuggestionIndex + } = this._autosuggest.state; + + if (!suggestions.length || highlightedSectionIndex) { + this.props.onGoToAddNewMovie(value); + this._autosuggest.input.blur(); + this.reset(); + + return; + } + + // If an suggestion is not selected go to the first series, + // otherwise go to the selected series. + + if (highlightedSuggestionIndex == null) { + this.goToMovie(suggestions[0]); + } else { + this.goToMovie(suggestions[highlightedSuggestionIndex]); + } + + this._autosuggest.input.blur(); + this.reset(); + } + + onBlur = () => { + this.reset(); + } + + onSuggestionsFetchRequested = ({ value }) => { + const lowerCaseValue = jdu.replace(value).toLowerCase(); + + const suggestions = this.props.movie.filter((movie) => { + // Check the title first and if there isn't a match fallback to + // the alternate titles and finally the tags. + + if (value.length === 1) { + return ( + movie.cleanTitle.startsWith(lowerCaseValue) || + movie.alternateTitles.some((alternateTitle) => alternateTitle.cleanTitle.startsWith(lowerCaseValue)) || + movie.tags.some((tag) => tag.cleanLabel.startsWith(lowerCaseValue)) + ); + } + + return ( + movie.cleanTitle.contains(lowerCaseValue) || + movie.alternateTitles.some((alternateTitle) => alternateTitle.cleanTitle.contains(lowerCaseValue)) || + movie.tags.some((tag) => tag.cleanLabel.contains(lowerCaseValue)) + ); + }); + + this.setState({ suggestions }); + } + + onSuggestionsClearRequested = () => { + this.setState({ + suggestions: [] + }); + } + + onSuggestionSelected = (event, { suggestion }) => { + if (suggestion.type === ADD_NEW_TYPE) { + this.props.onGoToAddNewMovie(this.state.value); + } else { + this.goToMovie(suggestion); + } + } + + // + // Render + + render() { + const { + value, + suggestions + } = this.state; + + const suggestionGroups = []; + + if (suggestions.length) { + suggestionGroups.push({ + title: 'Existing Movie', + suggestions + }); + } + + suggestionGroups.push({ + title: 'Add New Movie', + suggestions: [ + { + type: ADD_NEW_TYPE, + title: value + } + ] + }); + + const inputProps = { + ref: this.setInputRef, + className: styles.input, + name: 'seriesSearch', + value, + placeholder: 'Search', + autoComplete: 'off', + spellCheck: false, + onChange: this.onChange, + onKeyDown: this.onKeyDown, + onBlur: this.onBlur, + onFocus: this.onFocus + }; + + const theme = { + container: styles.container, + containerOpen: styles.containerOpen, + suggestionsContainer: styles.movieContainer, + suggestionsList: styles.list, + suggestion: styles.listItem, + suggestionHighlighted: styles.highlighted + }; + + return ( +
+ + + +
+ ); + } +} + +MovieSearchInput.propTypes = { + movie: PropTypes.arrayOf(PropTypes.object).isRequired, + onGoToMovie: PropTypes.func.isRequired, + onGoToAddNewMovie: PropTypes.func.isRequired, + bindShortcut: PropTypes.func.isRequired +}; + +export default keyboardShortcuts(MovieSearchInput); diff --git a/frontend/src/Components/Page/Header/MovieSearchInputConnector.js b/frontend/src/Components/Page/Header/MovieSearchInputConnector.js new file mode 100644 index 000000000..10f3f52d7 --- /dev/null +++ b/frontend/src/Components/Page/Header/MovieSearchInputConnector.js @@ -0,0 +1,98 @@ +import { connect } from 'react-redux'; +import { push } from 'react-router-redux'; +import { createSelector } from 'reselect'; +import jdu from 'jdu'; +import createAllMoviesSelector from 'Store/Selectors/createAllMoviesSelector'; +import createTagsSelector from 'Store/Selectors/createTagsSelector'; +import MovieSearchInput from './MovieSearchInput'; + +function createCleanTagsSelector() { + return createSelector( + createTagsSelector(), + (tags) => { + return tags.map((tag) => { + const { + id, + label + } = tag; + + return { + id, + label, + cleanLabel: jdu.replace(label).toLowerCase() + }; + }); + } + ); +} + +function createCleanMovieSelector() { + return createSelector( + createAllMoviesSelector(), + createCleanTagsSelector(), + (allMovies, allTags) => { + return allMovies.map((movie) => { + const { + title, + titleSlug, + sortTitle, + images, + alternateTitles = [], + tags = [] + } = movie; + + return { + title, + titleSlug, + sortTitle, + images, + cleanTitle: jdu.replace(title).toLowerCase(), + alternateTitles: alternateTitles.map((alternateTitle) => { + return { + title: alternateTitle.title, + sortTitle: alternateTitle.sortTitle, + cleanTitle: jdu.replace(alternateTitle.title).toLowerCase() + }; + }), + tags: tags.map((id) => { + return allTags.find((tag) => tag.id === id); + }) + }; + }).sort((a, b) => { + if (a.sortTitle < b.sortTitle) { + return -1; + } + if (a.sortTitle > b.sortTitle) { + return 1; + } + + return 0; + }); + } + ); +} + +function createMapStateToProps() { + return createSelector( + createCleanMovieSelector(), + (movie) => { + return { + movie + }; + } + ); +} + +function createMapDispatchToProps(dispatch, props) { + return { + onGoToMovie(titleSlug) { + dispatch(push(`${window.Radarr.urlBase}/movie/${titleSlug}`)); + }, + + onGoToAddNewMovie(query) { + dispatch(push(`${window.Radarr.urlBase}/add/new?term=${encodeURIComponent(query)}`)); + } + }; +} + +export default connect(createMapStateToProps, createMapDispatchToProps)(MovieSearchInput); diff --git a/frontend/src/Components/Page/Header/MovieSearchResult.css b/frontend/src/Components/Page/Header/MovieSearchResult.css new file mode 100644 index 000000000..29edc382b --- /dev/null +++ b/frontend/src/Components/Page/Header/MovieSearchResult.css @@ -0,0 +1,38 @@ +.result { + display: flex; + padding: 3px; + cursor: pointer; +} + +.poster { + width: 35px; + height: 50px; +} + +.titles { + flex: 1 1 1px; +} + +.title { + flex: 1 1 1px; + margin-left: 5px; +} + +.alternateTitle { + composes: title; + + color: $disabledColor; + font-size: $smallFontSize; +} + +.tagContainer { + composes: title; +} + +@media only screen and (max-width: $breakpointSmall) { + .titles, + .title, + .alternateTitle { + @add-mixin truncate; + } +} diff --git a/frontend/src/Components/Page/Header/MovieSearchResult.js b/frontend/src/Components/Page/Header/MovieSearchResult.js new file mode 100644 index 000000000..83211a766 --- /dev/null +++ b/frontend/src/Components/Page/Header/MovieSearchResult.js @@ -0,0 +1,89 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { kinds } from 'Helpers/Props'; +import Label from 'Components/Label'; +import MoviePoster from 'Movie/MoviePoster'; +import styles from './MovieSearchResult.css'; + +function findMatchingAlternateTitle(alternateTitles, cleanQuery) { + return alternateTitles.find((alternateTitle) => { + return alternateTitle.cleanTitle.contains(cleanQuery); + }); +} + +function getMatchingTag(tags, cleanQuery) { + return tags.find((tag) => { + return tag.cleanLabel.contains(cleanQuery); + }); +} + +function MovieSearchResult(props) { + const { + cleanQuery, + title, + cleanTitle, + images, + alternateTitles, + tags + } = props; + + const titleContains = cleanTitle.contains(cleanQuery); + let alternateTitle = null; + let tag = null; + + if (!titleContains) { + alternateTitle = findMatchingAlternateTitle(alternateTitles, cleanQuery); + } + + if (!titleContains && !alternateTitle) { + tag = getMatchingTag(tags, cleanQuery); + } + + return ( +
+ + +
+
+ {title} +
+ + { + !!alternateTitle && +
+ {alternateTitle.title} +
+ } + + { + !!tag && +
+ +
+ } +
+
+ ); +} + +MovieSearchResult.propTypes = { + cleanQuery: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + cleanTitle: PropTypes.string.isRequired, + images: PropTypes.arrayOf(PropTypes.object).isRequired, + alternateTitles: PropTypes.arrayOf(PropTypes.object).isRequired, + tags: PropTypes.arrayOf(PropTypes.object).isRequired +}; + +export default MovieSearchResult; diff --git a/frontend/src/Components/Page/Header/PageHeader.css b/frontend/src/Components/Page/Header/PageHeader.css new file mode 100644 index 000000000..a3208ca66 --- /dev/null +++ b/frontend/src/Components/Page/Header/PageHeader.css @@ -0,0 +1,65 @@ +.header { + z-index: 3; + display: flex; + align-items: center; + flex: 0 0 auto; + height: $headerHeight; + background-color: #464b51; + color: $white; +} + +.logoContainer { + display: flex; + justify-content: center; + flex: 0 0 $sidebarWidth; +} + +.logoFull { + width: 144px; + height: 48px; +} + +.logo { + width: 32px; + height: 32px; +} + +.sidebarToggleContainer { + display: none; + justify-content: center; + flex: 0 0 45px; + margin-right: 14px; +} + +.right { + display: flex; + justify-content: flex-end; + flex-grow: 1; +} + +.donate { + composes: link from 'Components/Link/Link.css'; + + width: 30px; + color: $themeRed; + text-align: center; + line-height: 60px; + + &:hover { + color: #9c1f30; + } +} + +@media only screen and (max-width: $breakpointSmall) { + .logoContainer { + flex: 0 0 60px; + } + + .sidebarToggleContainer { + display: flex; + } + + .donate { + display: none; + } +} diff --git a/frontend/src/Components/Page/Header/PageHeader.js b/frontend/src/Components/Page/Header/PageHeader.js new file mode 100644 index 000000000..1847d937f --- /dev/null +++ b/frontend/src/Components/Page/Header/PageHeader.js @@ -0,0 +1,100 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons } from 'Helpers/Props'; +import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts'; +import IconButton from 'Components/Link/IconButton'; +import Link from 'Components/Link/Link'; +import MovieSearchInputConnector from './MovieSearchInputConnector'; +import PageHeaderActionsMenuConnector from './PageHeaderActionsMenuConnector'; +import KeyboardShortcutsModal from './KeyboardShortcutsModal'; +import styles from './PageHeader.css'; + +class PageHeader extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props); + + this.state = { + isKeyboardShortcutsModalOpen: false + }; + } + + componentDidMount() { + this.props.bindShortcut(shortcuts.OPEN_KEYBOARD_SHORTCUTS_MODAL.key, this.onOpenKeyboardShortcutsModal); + } + + // + // Control + + onOpenKeyboardShortcutsModal = () => { + this.setState({ isKeyboardShortcutsModalOpen: true }); + } + + // + // Listeners + + onKeyboardShortcutsModalClose = () => { + this.setState({ isKeyboardShortcutsModalOpen: false }); + } + + // + // Render + + render() { + const { + onSidebarToggle, + isSmallScreen + } = this.props; + + return ( +
+
+ + + +
+ +
+ +
+ + + +
+ + +
+ + +
+ ); + } +} + +PageHeader.propTypes = { + onSidebarToggle: PropTypes.func.isRequired, + isSmallScreen: PropTypes.bool.isRequired, + bindShortcut: PropTypes.func.isRequired +}; + +export default keyboardShortcuts(PageHeader); diff --git a/frontend/src/Components/Page/Header/PageHeaderActionsMenu.css b/frontend/src/Components/Page/Header/PageHeaderActionsMenu.css new file mode 100644 index 000000000..e27ad883e --- /dev/null +++ b/frontend/src/Components/Page/Header/PageHeaderActionsMenu.css @@ -0,0 +1,21 @@ +.menuButton { + margin-right: 15px; + width: 30px; + height: 60px; + text-align: center; + + &:hover { + color: $themeDarkColor; + } +} + +.itemIcon { + margin-right: 8px; +} + +@media only screen and (max-width: $breakpointSmall) { + .menuButton { + margin-right: 5px; + } +} + diff --git a/frontend/src/Components/Page/Header/PageHeaderActionsMenu.js b/frontend/src/Components/Page/Header/PageHeaderActionsMenu.js new file mode 100644 index 000000000..8ad7c8409 --- /dev/null +++ b/frontend/src/Components/Page/Header/PageHeaderActionsMenu.js @@ -0,0 +1,88 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { align, icons, kinds } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import Menu from 'Components/Menu/Menu'; +import MenuButton from 'Components/Menu/MenuButton'; +import MenuContent from 'Components/Menu/MenuContent'; +import MenuItem from 'Components/Menu/MenuItem'; +import MenuItemSeparator from 'Components/Menu/MenuItemSeparator'; +import styles from './PageHeaderActionsMenu.css'; + +function PageHeaderActionsMenu(props) { + const { + formsAuth, + onKeyboardShortcutsPress, + onRestartPress, + onShutdownPress + } = props; + + return ( +
+ + + + + + + + + Keyboard Shortcuts + + + + + + + Restart + + + + + Shutdown + + + { + formsAuth && +
+ } + + { + formsAuth && + + + Logout + + } + +
+
+ ); +} + +PageHeaderActionsMenu.propTypes = { + formsAuth: PropTypes.bool.isRequired, + onKeyboardShortcutsPress: PropTypes.func.isRequired, + onRestartPress: PropTypes.func.isRequired, + onShutdownPress: PropTypes.func.isRequired +}; + +export default PageHeaderActionsMenu; diff --git a/frontend/src/Components/Page/Header/PageHeaderActionsMenuConnector.js b/frontend/src/Components/Page/Header/PageHeaderActionsMenuConnector.js new file mode 100644 index 000000000..66d131521 --- /dev/null +++ b/frontend/src/Components/Page/Header/PageHeaderActionsMenuConnector.js @@ -0,0 +1,56 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { restart, shutdown } from 'Store/Actions/systemActions'; +import PageHeaderActionsMenu from './PageHeaderActionsMenu'; + +function createMapStateToProps() { + return createSelector( + (state) => state.system.status, + (status) => { + return { + formsAuth: status.item.authentication === 'forms' + }; + } + ); +} + +const mapDispatchToProps = { + restart, + shutdown +}; + +class PageHeaderActionsMenuConnector extends Component { + + // + // Listeners + + onRestartPress = () => { + this.props.restart(); + } + + onShutdownPress = () => { + this.props.shutdown(); + } + + // + // Render + + render() { + return ( + + ); + } +} + +PageHeaderActionsMenuConnector.propTypes = { + restart: PropTypes.func.isRequired, + shutdown: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(PageHeaderActionsMenuConnector); diff --git a/frontend/src/Components/Page/LoadingPage.css b/frontend/src/Components/Page/LoadingPage.css new file mode 100644 index 000000000..dd5852e61 --- /dev/null +++ b/frontend/src/Components/Page/LoadingPage.css @@ -0,0 +1,3 @@ +.page { + composes: page from './Page.css'; +} diff --git a/frontend/src/Components/Page/LoadingPage.js b/frontend/src/Components/Page/LoadingPage.js new file mode 100644 index 000000000..398b70c4b --- /dev/null +++ b/frontend/src/Components/Page/LoadingPage.js @@ -0,0 +1,15 @@ +import React from 'react'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import LoadingMessage from 'Components/Loading/LoadingMessage'; +import styles from './LoadingPage.css'; + +function LoadingPage() { + return ( +
+ + +
+ ); +} + +export default LoadingPage; diff --git a/frontend/src/Components/Page/Page.css b/frontend/src/Components/Page/Page.css new file mode 100644 index 000000000..9facbfc22 --- /dev/null +++ b/frontend/src/Components/Page/Page.css @@ -0,0 +1,18 @@ +.page { + display: flex; + flex-direction: column; + height: 100%; +} + +.main { + position: relative; /* need this to position inner content - is this really needed? */ + display: flex; + flex: 1 1 auto; +} + +@media only screen and (max-width: $breakpointSmall) { + .page { + flex-grow: 1; + height: initial; + } +} diff --git a/frontend/src/Components/Page/Page.js b/frontend/src/Components/Page/Page.js new file mode 100644 index 000000000..2bb59c532 --- /dev/null +++ b/frontend/src/Components/Page/Page.js @@ -0,0 +1,136 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import locationShape from 'Helpers/Props/Shapes/locationShape'; +import SignalRConnector from 'Components/SignalRConnector'; +import ColorImpairedContext from 'App/ColorImpairedContext'; +import ConnectionLostModalConnector from 'App/ConnectionLostModalConnector'; +import AppUpdatedModalConnector from 'App/AppUpdatedModalConnector'; +import PageHeader from './Header/PageHeader'; +import PageSidebar from './Sidebar/PageSidebar'; +import styles from './Page.css'; + +class Page extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isUpdatedModalOpen: false, + isConnectionLostModalOpen: false + }; + } + + componentDidMount() { + window.addEventListener('resize', this.onResize); + } + + componentDidUpdate(prevProps) { + const { + isDisconnected, + isUpdated + } = this.props; + + if (!prevProps.isUpdated && isUpdated) { + this.setState({ isUpdatedModalOpen: true }); + } + + if (prevProps.isDisconnected !== isDisconnected) { + this.setState({ isConnectionLostModalOpen: isDisconnected }); + } + } + + componentWillUnmount() { + window.removeEventListener('resize', this.onResize); + } + + // + // Listeners + + onResize = () => { + this.props.onResize({ + width: window.innerWidth, + height: window.innerHeight + }); + } + + onUpdatedModalClose = () => { + this.setState({ isUpdatedModalOpen: false }); + } + + onConnectionLostModalClose = () => { + this.setState({ isConnectionLostModalOpen: false }); + } + + // + // Render + + render() { + const { + className, + location, + children, + isSmallScreen, + isSidebarVisible, + enableColorImpairedMode, + onSidebarToggle, + onSidebarVisibleChange + } = this.props; + + return ( + +
+ + + + +
+ + + {children} +
+ + + + +
+
+ ); + } +} + +Page.propTypes = { + className: PropTypes.string, + location: locationShape.isRequired, + children: PropTypes.node.isRequired, + isSmallScreen: PropTypes.bool.isRequired, + isSidebarVisible: PropTypes.bool.isRequired, + isUpdated: PropTypes.bool.isRequired, + isDisconnected: PropTypes.bool.isRequired, + enableColorImpairedMode: PropTypes.bool.isRequired, + onResize: PropTypes.func.isRequired, + onSidebarToggle: PropTypes.func.isRequired, + onSidebarVisibleChange: PropTypes.func.isRequired +}; + +Page.defaultProps = { + className: styles.page +}; + +export default Page; diff --git a/frontend/src/Components/Page/PageConnector.js b/frontend/src/Components/Page/PageConnector.js new file mode 100644 index 000000000..a32bbcef7 --- /dev/null +++ b/frontend/src/Components/Page/PageConnector.js @@ -0,0 +1,197 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { withRouter } from 'react-router-dom'; +import { createSelector } from 'reselect'; +import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; +import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions'; +import { fetchCustomFilters } from 'Store/Actions/customFilterActions'; +import { fetchMovies } from 'Store/Actions/movieActions'; +import { fetchTags } from 'Store/Actions/tagActions'; +import { fetchQualityProfiles, fetchUISettings } from 'Store/Actions/settingsActions'; +import { fetchStatus } from 'Store/Actions/systemActions'; +import ErrorPage from './ErrorPage'; +import LoadingPage from './LoadingPage'; +import Page from './Page'; + +function testLocalStorage() { + const key = 'radarrTest'; + + try { + localStorage.setItem(key, key); + localStorage.removeItem(key); + + return true; + } catch (e) { + return false; + } +} + +function createMapStateToProps() { + return createSelector( + (state) => state.movies, + (state) => state.customFilters, + (state) => state.tags, + (state) => state.settings.ui, + (state) => state.settings.qualityProfiles, + (state) => state.app, + createDimensionsSelector(), + ( + movies, + customFilters, + tags, + uiSettings, + qualityProfiles, + app, + dimensions + ) => { + const isPopulated = ( + movies.isPopulated && + customFilters.isPopulated && + tags.isPopulated && + qualityProfiles.isPopulated && + uiSettings.isPopulated + ); + + const hasError = !!( + movies.error || + customFilters.error || + tags.error || + qualityProfiles.error || + uiSettings.error + ); + + return { + isPopulated, + hasError, + moviesError: movies.error, + customFiltersError: tags.error, + tagsError: tags.error, + qualityProfilesError: qualityProfiles.error, + uiSettingsError: uiSettings.error, + isSmallScreen: dimensions.isSmallScreen, + isSidebarVisible: app.isSidebarVisible, + enableColorImpairedMode: uiSettings.item.enableColorImpairedMode, + version: app.version, + isUpdated: app.isUpdated, + isDisconnected: app.isDisconnected + }; + } + ); +} + +function createMapDispatchToProps(dispatch, props) { + return { + dispatchFetchMovies() { + dispatch(fetchMovies()); + }, + dispatchFetchCustomFilters() { + dispatch(fetchCustomFilters()); + }, + dispatchFetchTags() { + dispatch(fetchTags()); + }, + dispatchFetchQualityProfiles() { + dispatch(fetchQualityProfiles()); + }, + dispatchFetchUISettings() { + dispatch(fetchUISettings()); + }, + dispatchFetchStatus() { + dispatch(fetchStatus()); + }, + onResize(dimensions) { + dispatch(saveDimensions(dimensions)); + }, + onSidebarVisibleChange(isSidebarVisible) { + dispatch(setIsSidebarVisible({ isSidebarVisible })); + } + }; +} + +class PageConnector extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isLocalStorageSupported: testLocalStorage() + }; + } + + componentDidMount() { + if (!this.props.isPopulated) { + this.props.dispatchFetchMovies(); + this.props.dispatchFetchCustomFilters(); + this.props.dispatchFetchTags(); + this.props.dispatchFetchQualityProfiles(); + this.props.dispatchFetchUISettings(); + this.props.dispatchFetchStatus(); + } + } + + // + // Listeners + + onSidebarToggle = () => { + this.props.onSidebarVisibleChange(!this.props.isSidebarVisible); + } + + // + // Render + + render() { + const { + isPopulated, + hasError, + dispatchFetchMovies, + dispatchFetchTags, + dispatchFetchQualityProfiles, + dispatchFetchUISettings, + dispatchFetchStatus, + ...otherProps + } = this.props; + + if (hasError || !this.state.isLocalStorageSupported) { + return ( + + ); + } + + if (isPopulated) { + return ( + + ); + } + + return ( + + ); + } +} + +PageConnector.propTypes = { + isPopulated: PropTypes.bool.isRequired, + hasError: PropTypes.bool.isRequired, + isSidebarVisible: PropTypes.bool.isRequired, + dispatchFetchMovies: PropTypes.func.isRequired, + dispatchFetchCustomFilters: PropTypes.func.isRequired, + dispatchFetchTags: PropTypes.func.isRequired, + dispatchFetchQualityProfiles: PropTypes.func.isRequired, + dispatchFetchUISettings: PropTypes.func.isRequired, + dispatchFetchStatus: PropTypes.func.isRequired, + onSidebarVisibleChange: PropTypes.func.isRequired +}; + +export default withRouter( + connect(createMapStateToProps, createMapDispatchToProps)(PageConnector) +); diff --git a/frontend/src/Components/Page/PageContent.css b/frontend/src/Components/Page/PageContent.css new file mode 100644 index 000000000..4580077c3 --- /dev/null +++ b/frontend/src/Components/Page/PageContent.css @@ -0,0 +1,8 @@ +.content { + position: relative; + display: flex; + flex-direction: column; + flex-grow: 1; + overflow-x: hidden; + width: 100%; +} diff --git a/frontend/src/Components/Page/PageContent.js b/frontend/src/Components/Page/PageContent.js new file mode 100644 index 000000000..62d5b5d13 --- /dev/null +++ b/frontend/src/Components/Page/PageContent.js @@ -0,0 +1,36 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import DocumentTitle from 'react-document-title'; +import ErrorBoundary from 'Components/Error/ErrorBoundary'; +import PageContentError from './PageContentError'; +import styles from './PageContent.css'; + +function PageContent(props) { + const { + className, + title, + children + } = props; + + return ( + + +
+ {children} +
+
+
+ ); +} + +PageContent.propTypes = { + className: PropTypes.string, + title: PropTypes.string, + children: PropTypes.node.isRequired +}; + +PageContent.defaultProps = { + className: styles.content +}; + +export default PageContent; diff --git a/frontend/src/Components/Page/PageContentBody.css b/frontend/src/Components/Page/PageContentBody.css new file mode 100644 index 000000000..8b41754dd --- /dev/null +++ b/frontend/src/Components/Page/PageContentBody.css @@ -0,0 +1,19 @@ +.contentBody { + /* 1px for flex-basis so the div grows correctly in Edge/Firefox */ + flex: 1 0 1px; +} + +.innerContentBody { + padding: $pageContentBodyPadding; +} + +@media only screen and (max-width: $breakpointSmall) { + .contentBody { + flex-basis: auto; + overflow-y: hidden !important; + } + + .innerContentBody { + padding: $pageContentBodyPaddingSmallScreen; + } +} diff --git a/frontend/src/Components/Page/PageContentBody.js b/frontend/src/Components/Page/PageContentBody.js new file mode 100644 index 000000000..81bd9b29b --- /dev/null +++ b/frontend/src/Components/Page/PageContentBody.js @@ -0,0 +1,52 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { scrollDirections } from 'Helpers/Props'; +import OverlayScroller from 'Components/Scroller/OverlayScroller'; +import Scroller from 'Components/Scroller/Scroller'; +import styles from './PageContentBody.css'; + +class PageContentBody extends Component { + + // + // Render + + render() { + const { + className, + innerClassName, + isSmallScreen, + children, + dispatch, + ...otherProps + } = this.props; + + const ScrollerComponent = isSmallScreen ? Scroller : OverlayScroller; + + return ( + +
+ {children} +
+
+ ); + } +} + +PageContentBody.propTypes = { + className: PropTypes.string, + innerClassName: PropTypes.string, + isSmallScreen: PropTypes.bool.isRequired, + children: PropTypes.node.isRequired, + dispatch: PropTypes.func +}; + +PageContentBody.defaultProps = { + className: styles.contentBody, + innerClassName: styles.innerContentBody +}; + +export default PageContentBody; diff --git a/frontend/src/Components/Page/PageContentBodyConnector.js b/frontend/src/Components/Page/PageContentBodyConnector.js new file mode 100644 index 000000000..b5cdfbb21 --- /dev/null +++ b/frontend/src/Components/Page/PageContentBodyConnector.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; +import PageContentBody from './PageContentBody'; + +function createMapStateToProps() { + return createSelector( + createDimensionsSelector(), + (dimensions) => { + return { + isSmallScreen: dimensions.isSmallScreen + }; + } + ); +} + +export default connect(createMapStateToProps)(PageContentBody); diff --git a/frontend/src/Components/Page/PageContentError.css b/frontend/src/Components/Page/PageContentError.css new file mode 100644 index 000000000..7b1f7a6db --- /dev/null +++ b/frontend/src/Components/Page/PageContentError.css @@ -0,0 +1,3 @@ +.content { + composes: content from './PageContent.css'; +} diff --git a/frontend/src/Components/Page/PageContentError.js b/frontend/src/Components/Page/PageContentError.js new file mode 100644 index 000000000..5ae41a936 --- /dev/null +++ b/frontend/src/Components/Page/PageContentError.js @@ -0,0 +1,19 @@ +import React from 'react'; +import ErrorBoundaryError from 'Components/Error/ErrorBoundaryError'; +import PageContentBodyConnector from './PageContentBodyConnector'; +import styles from './PageContentError.css'; + +function PageContentError(props) { + return ( +
+ + + +
+ ); +} + +export default PageContentError; diff --git a/frontend/src/Components/Page/PageContentFooter.css b/frontend/src/Components/Page/PageContentFooter.css new file mode 100644 index 000000000..74bdb3811 --- /dev/null +++ b/frontend/src/Components/Page/PageContentFooter.css @@ -0,0 +1,26 @@ +.contentFooter { + display: flex; + flex: 0 0 auto; + padding: 20px; + background-color: #f1f1f1; +} + +@media only screen and (max-width: $breakpointSmall) { + .contentFooter { + display: block; + + div { + margin-top: 10px; + + &:first-child { + margin-top: 0; + } + } + } +} + +@media only screen and (max-width: $breakpointLarge) { + .contentFooter { + flex-wrap: wrap; + } +} diff --git a/frontend/src/Components/Page/PageContentFooter.js b/frontend/src/Components/Page/PageContentFooter.js new file mode 100644 index 000000000..1f6e2d21a --- /dev/null +++ b/frontend/src/Components/Page/PageContentFooter.js @@ -0,0 +1,33 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import styles from './PageContentFooter.css'; + +class PageContentFooter extends Component { + + // + // Render + + render() { + const { + className, + children + } = this.props; + + return ( +
+ {children} +
+ ); + } +} + +PageContentFooter.propTypes = { + className: PropTypes.string, + children: PropTypes.node.isRequired +}; + +PageContentFooter.defaultProps = { + className: styles.contentFooter +}; + +export default PageContentFooter; diff --git a/frontend/src/Components/Page/PageJumpBar.css b/frontend/src/Components/Page/PageJumpBar.css new file mode 100644 index 000000000..9a116fb54 --- /dev/null +++ b/frontend/src/Components/Page/PageJumpBar.css @@ -0,0 +1,22 @@ +.jumpBar { + display: flex; + align-content: stretch; + align-items: stretch; + align-self: stretch; + justify-content: center; + flex: 0 0 30px; +} + +.jumpBarItems { + display: flex; + justify-content: space-around; + flex: 0 0 100%; + flex-direction: column; + overflow: hidden; +} + +@media only screen and (max-width: $breakpointSmall) { + .jumpBar { + display: none; + } +} diff --git a/frontend/src/Components/Page/PageJumpBar.js b/frontend/src/Components/Page/PageJumpBar.js new file mode 100644 index 000000000..f555d5426 --- /dev/null +++ b/frontend/src/Components/Page/PageJumpBar.js @@ -0,0 +1,140 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import dimensions from 'Styles/Variables/dimensions'; +import Measure from 'Components/Measure'; +import PageJumpBarItem from './PageJumpBarItem'; +import styles from './PageJumpBar.css'; + +const ITEM_HEIGHT = parseInt(dimensions.jumpBarItemHeight); + +class PageJumpBar extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + height: 0, + visibleItems: props.items + }; + } + + componentDidMount() { + this.computeVisibleItems(); + } + + shouldComponentUpdate(nextProps, nextState) { + return ( + nextProps.items !== this.props.items || + nextState.height !== this.state.height + ); + } + + componentDidUpdate(prevProps, prevState) { + if ( + prevProps.items !== this.props.items || + prevState.height !== this.state.height + ) { + this.computeVisibleItems(); + } + } + + // + // Control + + computeVisibleItems() { + const { + items, + minimumItems + } = this.props; + + const height = this.state.height; + const maximumItems = Math.floor(height / ITEM_HEIGHT); + const diff = items.length - maximumItems; + + if (diff < 0) { + this.setState({ visibleItems: items }); + return; + } + + if (items.length < minimumItems) { + this.setState({ visibleItems: items }); + return; + } + + const removeDiff = Math.ceil(items.length / maximumItems); + + const visibleItems = _.reduce(items, (acc, item, index) => { + if (index % removeDiff === 0) { + acc.push(item); + } + + return acc; + }, []); + + this.setState({ visibleItems }); + } + + // + // Listeners + + onMeasure = ({ height }) => { + this.setState({ height }); + } + + // + // Render + + render() { + const { + minimumItems, + onItemPress + } = this.props; + + const { + visibleItems + } = this.state; + + if (!visibleItems.length || visibleItems.length < minimumItems) { + return null; + } + + return ( +
+ +
+ { + visibleItems.map((item) => { + return ( + + ); + }) + } +
+
+
+ ); + } +} + +PageJumpBar.propTypes = { + items: PropTypes.arrayOf(PropTypes.string).isRequired, + minimumItems: PropTypes.number.isRequired, + onItemPress: PropTypes.func.isRequired +}; + +PageJumpBar.defaultProps = { + minimumItems: 5 +}; + +export default PageJumpBar; diff --git a/frontend/src/Components/Page/PageJumpBarItem.css b/frontend/src/Components/Page/PageJumpBarItem.css new file mode 100644 index 000000000..e829dd31a --- /dev/null +++ b/frontend/src/Components/Page/PageJumpBarItem.css @@ -0,0 +1,14 @@ +.jumpBarItem { + flex: 1 0 $jumpBarItemHeight; + border-bottom: 1px solid $borderColor; + text-align: center; + font-weight: bold; + + &:hover { + color: #777; + } + + &:last-child { + border: none; + } +} diff --git a/frontend/src/Components/Page/PageJumpBarItem.js b/frontend/src/Components/Page/PageJumpBarItem.js new file mode 100644 index 000000000..aeffe4ddd --- /dev/null +++ b/frontend/src/Components/Page/PageJumpBarItem.js @@ -0,0 +1,40 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Link from 'Components/Link/Link'; +import styles from './PageJumpBarItem.css'; + +class PageJumpBarItem extends Component { + + // + // Listeners + + onPress = () => { + const { + label, + onItemPress + } = this.props; + + onItemPress(label); + } + + // + // Render + + render() { + return ( + + {this.props.label.toUpperCase()} + + ); + } +} + +PageJumpBarItem.propTypes = { + label: PropTypes.string.isRequired, + onItemPress: PropTypes.func.isRequired +}; + +export default PageJumpBarItem; diff --git a/frontend/src/Components/Page/PageSectionContent.js b/frontend/src/Components/Page/PageSectionContent.js new file mode 100644 index 000000000..774b88669 --- /dev/null +++ b/frontend/src/Components/Page/PageSectionContent.js @@ -0,0 +1,39 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; + +function PageSectionContent(props) { + const { + isFetching, + isPopulated, + error, + errorMessage, + children + } = props; + + if (isFetching) { + return ( + + ); + } else if (!isFetching && !!error) { + return ( +
{errorMessage}
+ ); + } else if (isPopulated && !error) { + return ( +
{children}
+ ); + } + + return null; +} + +PageSectionContent.propTypes = { + isFetching: PropTypes.bool.isRequired, + isPopulated: PropTypes.bool.isRequired, + error: PropTypes.object, + errorMessage: PropTypes.string.isRequired, + children: PropTypes.node.isRequired +}; + +export default PageSectionContent; diff --git a/frontend/src/Components/Page/Sidebar/Messages/Message.css b/frontend/src/Components/Page/Sidebar/Messages/Message.css new file mode 100644 index 000000000..7d53adb69 --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/Messages/Message.css @@ -0,0 +1,42 @@ +.message { + display: flex; + border-left: 3px solid $infoColor; +} + +.iconContainer, +.text { + display: flex; + justify-content: center; + flex-direction: column; + padding: 2px 0; + color: $sidebarColor; +} + +.iconContainer { + flex: 0 0 25px; + margin-left: 24px; + padding: 10px 0; +} + +.text { + margin-right: 24px; + font-size: 13px; +} + +/* Types */ + +.error { + border-left-color: $dangerColor; +} + +.info { + border-left-color: $infoColor; +} + +.success { + border-left-color: $successColor; +} + +.warning { + border-left-color: $warningColor; +} diff --git a/frontend/src/Components/Page/Sidebar/Messages/Message.js b/frontend/src/Components/Page/Sidebar/Messages/Message.js new file mode 100644 index 000000000..a28a28019 --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/Messages/Message.js @@ -0,0 +1,70 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; +import { icons } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import styles from './Message.css'; + +function getIconName(name) { + switch (name) { + case 'ApplicationUpdate': + return icons.RESTART; + case 'Backup': + return icons.BACKUP; + case 'CheckHealth': + return icons.HEALTH; + case 'EpisodeSearch': + return icons.SEARCH; + case 'Housekeeping': + return icons.HOUSEKEEPING; + case 'RefreshMovie': + return icons.REFRESH; + case 'RssSync': + return icons.RSS; + case 'SeasonSearch': + return icons.SEARCH; + case 'MovieSearch': + return icons.SEARCH; + case 'UpdateSceneMapping': + return icons.REFRESH; + default: + return icons.SPINNER; + } +} + +function Message(props) { + const { + name, + message, + type + } = props; + + return ( +
+
+ +
+ +
+ {message} +
+
+ ); +} + +Message.propTypes = { + name: PropTypes.string.isRequired, + message: PropTypes.string.isRequired, + type: PropTypes.string.isRequired +}; + +export default Message; diff --git a/frontend/src/Components/Page/Sidebar/Messages/MessageConnector.js b/frontend/src/Components/Page/Sidebar/Messages/MessageConnector.js new file mode 100644 index 000000000..06c545c27 --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/Messages/MessageConnector.js @@ -0,0 +1,67 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { hideMessage } from 'Store/Actions/appActions'; +import Message from './Message'; + +const mapDispatchToProps = { + hideMessage +}; + +class MessageConnector extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._hideTimeoutId = null; + this.scheduleHideMessage(props.hideAfter); + } + + componentDidUpdate() { + this.scheduleHideMessage(this.props.hideAfter); + } + + // + // Control + + scheduleHideMessage = (hideAfter) => { + if (this._hideTimeoutId) { + clearTimeout(this._hideTimeoutId); + } + + if (hideAfter) { + this._hideTimeoutId = setTimeout(this.hideMessage, hideAfter * 1000); + } + } + + hideMessage = () => { + this.props.hideMessage({ id: this.props.id }); + } + + // + // Render + + render() { + return ( + + ); + } +} + +MessageConnector.propTypes = { + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + hideAfter: PropTypes.number.isRequired, + hideMessage: PropTypes.func.isRequired +}; + +MessageConnector.defaultProps = { + // Hide messages after 60 seconds if there is no activity + // hideAfter: 60 +}; + +export default connect(undefined, mapDispatchToProps)(MessageConnector); diff --git a/frontend/src/Components/Page/Sidebar/Messages/Messages.css b/frontend/src/Components/Page/Sidebar/Messages/Messages.css new file mode 100644 index 000000000..ef01ad02c --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/Messages/Messages.css @@ -0,0 +1,11 @@ +.messages { + margin-top: auto; + margin-bottom: 20px; + padding-top: 20px; +} + +@media only screen and (max-width: $breakpointSmall) { + .messages { + margin-bottom: 0; + } +} diff --git a/frontend/src/Components/Page/Sidebar/Messages/Messages.js b/frontend/src/Components/Page/Sidebar/Messages/Messages.js new file mode 100644 index 000000000..ec8876f6e --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/Messages/Messages.js @@ -0,0 +1,27 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import MessageConnector from './MessageConnector'; +import styles from './Messages.css'; + +function Messages({ messages }) { + return ( +
+ { + messages.map((message) => { + return ( + + ); + }) + } +
+ ); +} + +Messages.propTypes = { + messages: PropTypes.arrayOf(PropTypes.object).isRequired +}; + +export default Messages; diff --git a/frontend/src/Components/Page/Sidebar/Messages/MessagesConnector.js b/frontend/src/Components/Page/Sidebar/Messages/MessagesConnector.js new file mode 100644 index 000000000..5d20d9194 --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/Messages/MessagesConnector.js @@ -0,0 +1,16 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import Messages from './Messages'; + +function createMapStateToProps() { + return createSelector( + (state) => state.app.messages.items, + (messages) => { + return { + messages: messages.slice().reverse() + }; + } + ); +} + +export default connect(createMapStateToProps)(Messages); diff --git a/frontend/src/Components/Page/Sidebar/PageSidebar.css b/frontend/src/Components/Page/Sidebar/PageSidebar.css new file mode 100644 index 000000000..fdbd80320 --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/PageSidebar.css @@ -0,0 +1,34 @@ +.sidebarContainer { + flex: 0 0 $sidebarWidth; + overflow: hidden; + width: $sidebarWidth; + background-color: $sidebarBackgroundColor; + transition: transform 300ms ease-in-out; + transform: translateX(0); +} + +.sidebar { + display: flex; + flex-direction: column; + overflow: hidden; + background-color: $sidebarBackgroundColor; + color: $white; +} + +@media only screen and (max-width: $breakpointSmall) { + .sidebarContainer { + position: fixed; + top: 0; + z-index: 2; + height: 100vh; + } + + .sidebar { + position: fixed; + z-index: 2; + overflow-y: auto; + width: 100%; + height: 100%; + } +} + diff --git a/frontend/src/Components/Page/Sidebar/PageSidebar.js b/frontend/src/Components/Page/Sidebar/PageSidebar.js new file mode 100644 index 000000000..8d295be28 --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/PageSidebar.js @@ -0,0 +1,513 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import ReactDOM from 'react-dom'; +import classNames from 'classnames'; +import { icons } from 'Helpers/Props'; +import locationShape from 'Helpers/Props/Shapes/locationShape'; +import dimensions from 'Styles/Variables/dimensions'; +import OverlayScroller from 'Components/Scroller/OverlayScroller'; +import Scroller from 'Components/Scroller/Scroller'; +import QueueStatusConnector from 'Activity/Queue/Status/QueueStatusConnector'; +import HealthStatusConnector from 'System/Status/Health/HealthStatusConnector'; +import MessagesConnector from './Messages/MessagesConnector'; +import PageSidebarItem from './PageSidebarItem'; +import styles from './PageSidebar.css'; + +const HEADER_HEIGHT = parseInt(dimensions.headerHeight); +const SIDEBAR_WIDTH = parseInt(dimensions.sidebarWidth); + +const links = [ + { + iconName: icons.SERIES_CONTINUING, + title: 'Movies', + to: '/', + alias: '/movies', + children: [ + { + title: 'Add New', + to: '/add/new' + }, + { + title: 'Import', + to: '/add/import' + }, + { + title: 'Discover', + to: '/add/discover' + }, + { + title: 'Lists', + to: '/add/lists' + } + ] + }, + + { + iconName: icons.CALENDAR, + title: 'Calendar', + to: '/calendar' + }, + + { + iconName: icons.ACTIVITY, + title: 'Activity', + to: '/activity/queue', + children: [ + { + title: 'Queue', + to: '/activity/queue', + statusComponent: QueueStatusConnector + }, + { + title: 'History', + to: '/activity/history' + }, + { + title: 'Blacklist', + to: '/activity/blacklist' + } + ] + }, + + { + iconName: icons.SETTINGS, + title: 'Settings', + to: '/settings', + children: [ + { + title: 'Media Management', + to: '/settings/mediamanagement' + }, + { + title: 'Profiles', + to: '/settings/profiles' + }, + { + title: 'Quality', + to: '/settings/quality' + }, + { + title: 'Indexers', + to: '/settings/indexers' + }, + { + title: 'Download Clients', + to: '/settings/downloadclients' + }, + { + title: 'Lists', + to: '/settings/netimports' + }, + { + title: 'Connect', + to: '/settings/connect' + }, + { + title: 'Metadata', + to: '/settings/metadata' + }, + { + title: 'Tags', + to: '/settings/tags' + }, + { + title: 'General', + to: '/settings/general' + }, + { + title: 'UI', + to: '/settings/ui' + } + ] + }, + + { + iconName: icons.SYSTEM, + title: 'System', + to: '/system/status', + children: [ + { + title: 'Status', + to: '/system/status', + statusComponent: HealthStatusConnector + }, + { + title: 'Tasks', + to: '/system/tasks' + }, + { + title: 'Backup', + to: '/system/backup' + }, + { + title: 'Updates', + to: '/system/updates' + }, + { + title: 'Events', + to: '/system/events' + }, + { + title: 'Log Files', + to: '/system/logs/files' + } + ] + } +]; + +function getActiveParent(pathname) { + let activeParent = links[0].to; + + links.forEach((link) => { + if (link.to && link.to === pathname) { + activeParent = link.to; + + return false; + } + + const children = link.children; + + if (children) { + children.forEach((childLink) => { + if (pathname.startsWith(childLink.to)) { + activeParent = link.to; + + return false; + } + }); + } + + if ( + (link.to !== '/' && pathname.startsWith(link.to)) || + (link.alias && pathname.startsWith(link.alias)) + ) { + activeParent = link.to; + + return false; + } + }); + + return activeParent; +} + +function hasActiveChildLink(link, pathname) { + const children = link.children; + + if (!children || !children.length) { + return false; + } + + return _.some(children, (child) => { + return child.to === pathname; + }); +} + +function getPositioning() { + const windowScroll = window.scrollY == null ? document.documentElement.scrollTop : window.scrollY; + const top = Math.max(HEADER_HEIGHT - windowScroll, 0); + const height = window.innerHeight - top; + + return { + top: `${top}px`, + height: `${height}px` + }; +} + +class PageSidebar extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._touchStartX = null; + this._touchStartY = null; + this._sidebarRef = null; + + this.state = { + top: dimensions.headerHeight, + height: `${window.innerHeight - HEADER_HEIGHT}px`, + transition: null, + transform: props.isSidebarVisible ? 0 : SIDEBAR_WIDTH * -1 + }; + } + + componentDidMount() { + if (this.props.isSmallScreen) { + window.addEventListener('click', this.onWindowClick, { capture: true }); + window.addEventListener('scroll', this.onWindowScroll); + window.addEventListener('touchstart', this.onTouchStart); + window.addEventListener('touchmove', this.onTouchMove); + window.addEventListener('touchend', this.onTouchEnd); + window.addEventListener('touchcancel', this.onTouchCancel); + } + } + + componentDidUpdate(prevProps) { + const { + isSidebarVisible + } = this.props; + + const transform = this.state.transform; + + if (prevProps.isSidebarVisible !== isSidebarVisible) { + this._setSidebarTransform(isSidebarVisible); + } else if (transform === 0 && !isSidebarVisible) { + this.props.onSidebarVisibleChange(true); + } else if (transform === -SIDEBAR_WIDTH && isSidebarVisible) { + this.props.onSidebarVisibleChange(false); + } + } + + componentWillUnmount() { + if (this.props.isSmallScreen) { + window.removeEventListener('click', this.onWindowClick, { capture: true }); + window.removeEventListener('scroll', this.onWindowScroll); + window.removeEventListener('touchstart', this.onTouchStart); + window.removeEventListener('touchmove', this.onTouchMove); + window.removeEventListener('touchend', this.onTouchEnd); + window.removeEventListener('touchcancel', this.onTouchCancel); + } + } + + // + // Control + + _setSidebarRef = (ref) => { + this._sidebarRef = ref; + } + + _setSidebarTransform(isSidebarVisible, transition, callback) { + this.setState({ + transition, + transform: isSidebarVisible ? 0 : SIDEBAR_WIDTH * -1 + }, callback); + } + + // + // Listeners + + onWindowClick = (event) => { + const sidebar = ReactDOM.findDOMNode(this._sidebarRef); + const toggleButton = document.getElementById('sidebar-toggle-button'); + + if (!sidebar) { + return; + } + + if ( + !sidebar.contains(event.target) && + !toggleButton.contains(event.target) && + this.props.isSidebarVisible + ) { + event.preventDefault(); + event.stopPropagation(); + this.props.onSidebarVisibleChange(false); + } + } + + onWindowScroll = () => { + this.setState(getPositioning()); + } + + onTouchStart = (event) => { + const touches = event.touches; + const touchStartX = touches[0].pageX; + const touchStartY = touches[0].pageY; + const isSidebarVisible = this.props.isSidebarVisible; + + if (touches.length !== 1) { + return; + } + + if (isSidebarVisible && (touchStartX > 210 || touchStartX < 180)) { + return; + } else if (!isSidebarVisible && touchStartX > 40) { + return; + } + + this._touchStartX = touchStartX; + this._touchStartY = touchStartY; + } + + onTouchMove = (event) => { + const touches = event.touches; + const currentTouchX = touches[0].pageX; + // const currentTouchY = touches[0].pageY; + // const isSidebarVisible = this.props.isSidebarVisible; + + if (!this._touchStartX) { + return; + } + + // This is a bit funky when trying to close and you scroll + // vertical too much by mistake, commenting out for now. + // TODO: Evaluate if this should be nuked + + // if (Math.abs(this._touchStartY - currentTouchY) > 40) { + // const transform = isSidebarVisible ? 0 : SIDEBAR_WIDTH * -1; + + // this.setState({ + // transition: 'none', + // transform + // }); + + // return; + // } + + if (Math.abs(this._touchStartX - currentTouchX) < 40) { + return; + } + + const transform = Math.min(currentTouchX - SIDEBAR_WIDTH, 0); + + this.setState({ + transition: 'none', + transform + }); + } + + onTouchEnd = (event) => { + const touches = event.changedTouches; + const currentTouch = touches[0].pageX; + + if (!this._touchStartX) { + return; + } + + if (currentTouch > this._touchStartX && currentTouch > 50) { + this._setSidebarTransform(true, 'none'); + } else if (currentTouch < this._touchStartX && currentTouch < 80) { + this._setSidebarTransform(false, 'transform 50ms ease-in-out'); + } else { + this._setSidebarTransform(this.props.isSidebarVisible); + } + + this._touchStartX = null; + this._touchStartY = null; + } + + onTouchCancel = (event) => { + this._touchStartX = null; + this._touchStartY = null; + } + + onItemPress = () => { + this.props.onSidebarVisibleChange(false); + } + + // + // Render + + render() { + const { + location, + isSmallScreen + } = this.props; + + const { + top, + height, + transition, + transform + } = this.state; + + const urlBase = window.Radarr.urlBase; + const pathname = urlBase ? location.pathname.substr(urlBase.length) || '/' : location.pathname; + const activeParent = getActiveParent(pathname); + + let containerStyle = {}; + let sidebarStyle = {}; + + if (isSmallScreen) { + containerStyle = { + transition, + transform: `translateX(${transform}px)` + }; + + sidebarStyle = { + top, + height + }; + } + + const ScrollerComponent = isSmallScreen ? Scroller : OverlayScroller; + + return ( +
+ +
+ { + links.map((link) => { + const childWithStatusComponent = _.find(link.children, (child) => { + return !!child.statusComponent; + }); + + const childStatusComponent = childWithStatusComponent ? + childWithStatusComponent.statusComponent : + null; + + const isActiveParent = activeParent === link.to; + const hasActiveChild = hasActiveChildLink(link, pathname); + + return ( + + { + link.children && link.to === activeParent && + link.children.map((child) => { + return ( + + ); + }) + } + + ); + }) + } +
+ + +
+
+ ); + } +} + +PageSidebar.propTypes = { + location: locationShape.isRequired, + isSmallScreen: PropTypes.bool.isRequired, + isSidebarVisible: PropTypes.bool.isRequired, + onSidebarVisibleChange: PropTypes.func.isRequired +}; + +export default PageSidebar; diff --git a/frontend/src/Components/Page/Sidebar/PageSidebarItem.css b/frontend/src/Components/Page/Sidebar/PageSidebarItem.css new file mode 100644 index 000000000..dac40927f --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/PageSidebarItem.css @@ -0,0 +1,50 @@ +.item { + border-left: 3px solid transparent; + color: $sidebarColor; + transition: border-left 0.3s ease-in-out; +} + +.isActiveItem { + border-left: 3px solid $themeBlue; +} + +.link { + display: block; + padding: 12px 24px; + color: $sidebarColor; + + &:hover, + &:focus { + color: $themeBlue; + text-decoration: none; + } +} + +.childLink { + composes: link; + + padding: 10px 24px; +} + +.isActiveLink { + color: $themeBlue; +} + +.isActiveParentLink { + background-color: $sidebarActiveBackgroundColor; +} + +.iconContainer { + display: inline-block; + margin-right: 7px; + width: 18px; + text-align: center; +} + +.noIcon { + margin-left: 25px; +} + +.status { + float: right; +} diff --git a/frontend/src/Components/Page/Sidebar/PageSidebarItem.js b/frontend/src/Components/Page/Sidebar/PageSidebarItem.js new file mode 100644 index 000000000..d494150c0 --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/PageSidebarItem.js @@ -0,0 +1,106 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { map } from 'Helpers/elementChildren'; +import Icon from 'Components/Icon'; +import Link from 'Components/Link/Link'; +import styles from './PageSidebarItem.css'; + +class PageSidebarItem extends Component { + + // + // Listeners + + onPress = () => { + const { + isChildItem, + isParentItem, + onPress + } = this.props; + + if (isChildItem || !isParentItem) { + onPress(); + } + } + + // + // Render + + render() { + const { + iconName, + title, + to, + isActive, + isActiveParent, + isChildItem, + statusComponent: StatusComponent, + children + } = this.props; + + return ( +
+ + { + !!iconName && + + + + } + + + {title} + + + { + !!StatusComponent && + + + + } + + + { + children && + map(children, (child) => { + return React.cloneElement(child, { isChildItem: true }); + }) + } +
+ ); + } +} + +PageSidebarItem.propTypes = { + iconName: PropTypes.object, + title: PropTypes.string.isRequired, + to: PropTypes.string.isRequired, + isActive: PropTypes.bool, + isActiveParent: PropTypes.bool, + isParentItem: PropTypes.bool.isRequired, + isChildItem: PropTypes.bool.isRequired, + statusComponent: PropTypes.func, + children: PropTypes.node, + onPress: PropTypes.func +}; + +PageSidebarItem.defaultProps = { + isChildItem: false +}; + +export default PageSidebarItem; diff --git a/frontend/src/Components/Page/Sidebar/PageSidebarStatus.css b/frontend/src/Components/Page/Sidebar/PageSidebarStatus.css new file mode 100644 index 000000000..4dd0cc678 --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/PageSidebarStatus.css @@ -0,0 +1,3 @@ +.status { + composes: label from 'Components/Label.css'; +} diff --git a/frontend/src/Components/Page/Sidebar/PageSidebarStatus.js b/frontend/src/Components/Page/Sidebar/PageSidebarStatus.js new file mode 100644 index 000000000..c1ea615ed --- /dev/null +++ b/frontend/src/Components/Page/Sidebar/PageSidebarStatus.js @@ -0,0 +1,35 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { kinds, sizes } from 'Helpers/Props'; +import Label from 'Components/Label'; + +function PageSidebarStatus({ count, errors, warnings }) { + if (!count) { + return null; + } + + let kind = kinds.INFO; + + if (errors) { + kind = kinds.DANGER; + } else if (warnings) { + kind = kinds.WARNING; + } + + return ( + + ); +} + +PageSidebarStatus.propTypes = { + count: PropTypes.number, + errors: PropTypes.bool, + warnings: PropTypes.bool +}; + +export default PageSidebarStatus; diff --git a/frontend/src/Components/Page/Toolbar/PageToolbar.css b/frontend/src/Components/Page/Toolbar/PageToolbar.css new file mode 100644 index 000000000..e040bc884 --- /dev/null +++ b/frontend/src/Components/Page/Toolbar/PageToolbar.css @@ -0,0 +1,16 @@ +.toolbar { + display: flex; + justify-content: space-between; + flex: 0 0 auto; + padding: 0 20px; + height: $toolbarHeight; + background-color: $toolbarBackgroundColor; + color: $toolbarColor; + line-height: 60px; +} + +@media only screen and (max-width: $breakpointSmall) { + .toolbar { + padding: 0 10px; + } +} diff --git a/frontend/src/Components/Page/Toolbar/PageToolbar.js b/frontend/src/Components/Page/Toolbar/PageToolbar.js new file mode 100644 index 000000000..728f1b0d9 --- /dev/null +++ b/frontend/src/Components/Page/Toolbar/PageToolbar.js @@ -0,0 +1,33 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import styles from './PageToolbar.css'; + +class PageToolbar extends Component { + + // + // Render + + render() { + const { + className, + children + } = this.props; + + return ( +
+ {children} +
+ ); + } +} + +PageToolbar.propTypes = { + className: PropTypes.string, + children: PropTypes.node.isRequired +}; + +PageToolbar.defaultProps = { + className: styles.toolbar +}; + +export default PageToolbar; diff --git a/frontend/src/Components/Page/Toolbar/PageToolbarButton.css b/frontend/src/Components/Page/Toolbar/PageToolbarButton.css new file mode 100644 index 000000000..11944c1e9 --- /dev/null +++ b/frontend/src/Components/Page/Toolbar/PageToolbarButton.css @@ -0,0 +1,32 @@ +.toolbarButton { + composes: link from 'Components/Link/Link.css'; + + width: $toolbarButtonWidth; + text-align: center; + + &:hover { + color: $toobarButtonHoverColor; + } + + &.isDisabled { + color: $disabledColor; + } +} + +.isDisabled { + color: $disabledColor; +} + +.labelContainer { + display: flex; + align-items: center; + justify-content: center; + min-height: 16px; +} + +.label { + padding: 0 3px; + color: $toolbarLabelColor; + font-size: $extraSmallFontSize; + line-height: calc($extraSmallFontSize + 1px); +} diff --git a/frontend/src/Components/Page/Toolbar/PageToolbarButton.js b/frontend/src/Components/Page/Toolbar/PageToolbarButton.js new file mode 100644 index 000000000..381046bf5 --- /dev/null +++ b/frontend/src/Components/Page/Toolbar/PageToolbarButton.js @@ -0,0 +1,57 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; +import { icons } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import Link from 'Components/Link/Link'; +import styles from './PageToolbarButton.css'; + +function PageToolbarButton(props) { + const { + label, + iconName, + spinningName, + isDisabled, + isSpinning, + ...otherProps + } = props; + + return ( + + + +
+
+ {label} +
+
+ + ); +} + +PageToolbarButton.propTypes = { + label: PropTypes.string.isRequired, + iconName: PropTypes.object.isRequired, + spinningName: PropTypes.object, + isSpinning: PropTypes.bool, + isDisabled: PropTypes.bool +}; + +PageToolbarButton.defaultProps = { + spinningName: icons.SPINNER, + isDisabled: false, + isSpinning: false +}; + +export default PageToolbarButton; diff --git a/frontend/src/Components/Page/Toolbar/PageToolbarSection.css b/frontend/src/Components/Page/Toolbar/PageToolbarSection.css new file mode 100644 index 000000000..638636ffb --- /dev/null +++ b/frontend/src/Components/Page/Toolbar/PageToolbarSection.css @@ -0,0 +1,40 @@ +.sectionContainer { + display: flex; + flex: 1 1 10%; + overflow: hidden; +} + +.section { + display: flex; + align-items: center; + flex-grow: 1; +} + +.left { + justify-content: flex-start; +} + +.center { + justify-content: center; +} + +.right { + justify-content: flex-end; +} + +.overflowMenuButton { + composes: menuButton from 'Components/Menu/ToolbarMenuButton.css'; +} + +.overflowMenuItemIcon { + margin-right: 8px; +} + +@media only screen and (max-width: $breakpointSmall) { + .overflowMenuButton { + &::after { + margin-left: 0; + content: '\25BE'; + } + } +} diff --git a/frontend/src/Components/Page/Toolbar/PageToolbarSection.js b/frontend/src/Components/Page/Toolbar/PageToolbarSection.js new file mode 100644 index 000000000..35ee586ec --- /dev/null +++ b/frontend/src/Components/Page/Toolbar/PageToolbarSection.js @@ -0,0 +1,221 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { forEach } from 'Helpers/elementChildren'; +import { align, icons } from 'Helpers/Props'; +import dimensions from 'Styles/Variables/dimensions'; +import SpinnerIcon from 'Components/SpinnerIcon'; +import Measure from 'Components/Measure'; +import Menu from 'Components/Menu/Menu'; +import MenuContent from 'Components/Menu/MenuContent'; +import MenuItem from 'Components/Menu/MenuItem'; +import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton'; +import styles from './PageToolbarSection.css'; + +const BUTTON_WIDTH = parseInt(dimensions.toolbarButtonWidth); +const SEPARATOR_MARGIN = parseInt(dimensions.toolbarSeparatorMargin); +const SEPARATOR_WIDTH = 2 * SEPARATOR_MARGIN + 1; +const SEPARATOR_NAME = 'PageToolbarSeparator'; + +function calculateOverflowItems(children, isMeasured, width, collapseButtons) { + let buttonCount = 0; + let separatorCount = 0; + const validChildren = []; + + forEach(children, (child) => { + const name = child.type.name; + + if (name === SEPARATOR_NAME) { + separatorCount++; + } else { + buttonCount++; + } + + validChildren.push(child); + }); + + const buttonsWidth = buttonCount * BUTTON_WIDTH; + const separatorsWidth = separatorCount + SEPARATOR_WIDTH; + const totalWidth = buttonsWidth + separatorsWidth; + + // If the width of buttons and separators is less than + // the available width return all valid children. + + if ( + !isMeasured || + !collapseButtons || + totalWidth < width + ) { + return { + buttons: validChildren, + buttonCount, + overflowItems: [] + }; + } + + const maxButtons = Math.max(Math.floor((width - separatorsWidth) / BUTTON_WIDTH), 1); + const buttons = []; + const overflowItems = []; + let actualButtons = 0; + + // Return all buttons if only one is being pushed to the overflow menu. + if (buttonCount - 1 === maxButtons) { + return { + buttons: validChildren, + buttonCount, + overflowItems: [] + }; + } + + validChildren.forEach((child, index) => { + if (actualButtons < maxButtons) { + if (child.type.name !== SEPARATOR_NAME) { + buttons.push(child); + actualButtons++; + } + } else if (child.type.name !== SEPARATOR_NAME) { + overflowItems.push(child.props); + } + }); + + return { + buttons, + buttonCount, + overflowItems + }; +} + +class PageToolbarSection extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isMeasured: false, + width: 0, + buttons: [], + overflowItems: [] + }; + } + + // + // Listeners + + onMeasure = ({ width }) => { + this.setState({ + isMeasured: true, + width + }); + } + + // + // Render + + render() { + const { + children, + alignContent, + collapseButtons + } = this.props; + + const { + isMeasured, + width + } = this.state; + + const { + buttons, + buttonCount, + overflowItems + } = calculateOverflowItems(children, isMeasured, width, collapseButtons); + + return ( + +
+ { + isMeasured ? +
+ { + buttons.map((button) => { + return button; + }) + } + + { + !!overflowItems.length && + + + + + { + overflowItems.map((item) => { + const { + iconName, + spinningName, + label, + isDisabled, + isSpinning, + ...otherProps + } = item; + + return ( + + + {label} + + ); + }) + } + + + } +
: + null + } +
+
+ ); + } + +} + +PageToolbarSection.propTypes = { + children: PropTypes.node, + alignContent: PropTypes.oneOf([align.LEFT, align.CENTER, align.RIGHT]), + collapseButtons: PropTypes.bool.isRequired +}; + +PageToolbarSection.defaultProps = { + alignContent: align.LEFT, + collapseButtons: true +}; + +export default PageToolbarSection; diff --git a/frontend/src/Components/Page/Toolbar/PageToolbarSeparator.css b/frontend/src/Components/Page/Toolbar/PageToolbarSeparator.css new file mode 100644 index 000000000..968673593 --- /dev/null +++ b/frontend/src/Components/Page/Toolbar/PageToolbarSeparator.css @@ -0,0 +1,12 @@ +.separator { + margin: 10px $toolbarSeparatorMargin; + height: 40px; + border-right: 1px solid #e5e5e5; + opacity: 0.35; +} + +@media only screen and (max-width: $breakpointSmall) { + .separator { + margin: 10px 5px; + } +} diff --git a/frontend/src/Components/Page/Toolbar/PageToolbarSeparator.js b/frontend/src/Components/Page/Toolbar/PageToolbarSeparator.js new file mode 100644 index 000000000..754248f99 --- /dev/null +++ b/frontend/src/Components/Page/Toolbar/PageToolbarSeparator.js @@ -0,0 +1,17 @@ +import React, { Component } from 'react'; +import styles from './PageToolbarSeparator.css'; + +class PageToolbarSeparator extends Component { + + // + // Render + + render() { + return ( +
+ ); + } + +} + +export default PageToolbarSeparator; diff --git a/frontend/src/Components/ProgressBar.css b/frontend/src/Components/ProgressBar.css new file mode 100644 index 000000000..2f0019043 --- /dev/null +++ b/frontend/src/Components/ProgressBar.css @@ -0,0 +1,93 @@ +.container { + position: relative; + overflow: hidden; + width: 100%; + border-radius: 4px; + background-color: #f5f5f5; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progressBar { + position: relative; + z-index: 1; + float: left; + width: 0; + height: 100%; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + color: $white; + transition: width 0.6s ease; +} + +.frontTextContainer { + z-index: 1; + color: $white; +} + +.backTextContainer, +.frontTextContainer { + position: absolute; + overflow: hidden; + width: 0; + height: 100%; +} + +.backText, +.frontText { + display: flex; + align-items: center; + justify-content: center; + text-align: center; + font-size: 12px; + cursor: default; +} + +.primary { + background-color: $primaryColor; +} + +.danger { + background-color: $dangerColor; +} + +.success { + background-color: $successColor; +} + +.purple { + background-color: $purple; +} + +.warning { + background-color: $warningColor; +} + +.info { + background-color: $infoColor; +} + +.small { + height: $progressBarSmallHeight; + + .backText, + .frontText { + height: $progressBarSmallHeight; + } +} + +.medium { + height: $progressBarMediumHeight; + + .backText, + .frontText { + height: $progressBarMediumHeight; + } +} + +.large { + height: $progressBarLargeHeight; + + .backText, + .frontText { + height: $progressBarLargeHeight; + } +} diff --git a/frontend/src/Components/ProgressBar.js b/frontend/src/Components/ProgressBar.js new file mode 100644 index 000000000..4f457d558 --- /dev/null +++ b/frontend/src/Components/ProgressBar.js @@ -0,0 +1,100 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; +import { kinds, sizes } from 'Helpers/Props'; +import styles from './ProgressBar.css'; + +function ProgressBar(props) { + const { + className, + containerClassName, + title, + progress, + precision, + showText, + text, + kind, + size, + width + } = props; + + const progressPercent = `${progress.toFixed(precision)}%`; + const progressText = text || progressPercent; + const actualWidth = width ? `${width}px` : '100%'; + + return ( +
+ { + showText && !!width && +
+
+
+ {progressText} +
+
+
+ } + +
+ { + showText && +
+
+
+ {progressText} +
+
+
+ } +
+ ); +} + +ProgressBar.propTypes = { + className: PropTypes.string, + containerClassName: PropTypes.string, + title: PropTypes.string, + progress: PropTypes.number.isRequired, + precision: PropTypes.number.isRequired, + showText: PropTypes.bool.isRequired, + text: PropTypes.string, + kind: PropTypes.oneOf(kinds.all).isRequired, + size: PropTypes.oneOf(sizes.all).isRequired, + width: PropTypes.number +}; + +ProgressBar.defaultProps = { + className: styles.progressBar, + containerClassName: styles.container, + precision: 1, + showText: false, + kind: kinds.PRIMARY, + size: sizes.MEDIUM +}; + +export default ProgressBar; diff --git a/frontend/src/Components/Router/Switch.js b/frontend/src/Components/Router/Switch.js new file mode 100644 index 000000000..0c0004a50 --- /dev/null +++ b/frontend/src/Components/Router/Switch.js @@ -0,0 +1,44 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { Switch as RouterSwitch } from 'react-router-dom'; +import getPathWithUrlBase from 'Utilities/getPathWithUrlBase'; +import { map } from 'Helpers/elementChildren'; + +class Switch extends Component { + + // + // Render + + render() { + const { + children + } = this.props; + + return ( + + { + map(children, (child) => { + const { + path: childPath, + addUrlBase = true + } = child.props; + + if (!childPath) { + return child; + } + + const path = addUrlBase ? getPathWithUrlBase(childPath) : childPath; + + return React.cloneElement(child, { path }); + }) + } + + ); + } +} + +Switch.propTypes = { + children: PropTypes.node.isRequired +}; + +export default Switch; diff --git a/frontend/src/Components/Scroller/OverlayScroller.css b/frontend/src/Components/Scroller/OverlayScroller.css new file mode 100644 index 000000000..707a9ac6f --- /dev/null +++ b/frontend/src/Components/Scroller/OverlayScroller.css @@ -0,0 +1,15 @@ +.scroller { + /* Placeholder */ +} + +.thumb { + min-height: 50px; + border: 1px solid transparent; + border-radius: 5px; + background-color: $scrollbarBackgroundColor; + background-clip: padding-box; + + &:hover { + background-color: $scrollbarHoverBackgroundColor; + } +} diff --git a/frontend/src/Components/Scroller/OverlayScroller.js b/frontend/src/Components/Scroller/OverlayScroller.js new file mode 100644 index 000000000..23fe6058a --- /dev/null +++ b/frontend/src/Components/Scroller/OverlayScroller.js @@ -0,0 +1,127 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { Scrollbars } from 'react-custom-scrollbars'; +import { scrollDirections } from 'Helpers/Props'; +import styles from './OverlayScroller.css'; + +class OverlayScroller extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._scroller = null; + this._isScrolling = false; + } + + componentDidUpdate(prevProps) { + const { + scrollTop + } = this.props; + + if (!this._isScrolling && scrollTop != null && scrollTop !== prevProps.scrollTop) { + this._scroller.scrollTop(scrollTop); + } + } + + // + // Control + + _setScrollRef = (ref) => { + this._scroller = ref; + } + + _renderThumb = (props) => { + return ( +
+ ); + } + + _renderView = (props) => { + return ( +
+ ); + } + + // + // Listers + + onScrollStart = () => { + this._isScrolling = true; + } + + onScrollStop = () => { + this._isScrolling = false; + } + + onScroll = (event) => { + const { + scrollTop, + scrollLeft + } = event.currentTarget; + + this._isScrolling = true; + const onScroll = this.props.onScroll; + + if (onScroll) { + onScroll({ scrollTop, scrollLeft }); + } + } + + // + // Render + + render() { + const { + autoHide, + autoScroll, + children + } = this.props; + + return ( + + {children} + + ); + } + +} + +OverlayScroller.propTypes = { + className: PropTypes.string, + trackClassName: PropTypes.string, + scrollTop: PropTypes.number, + scrollDirection: PropTypes.oneOf([scrollDirections.NONE, scrollDirections.HORIZONTAL, scrollDirections.VERTICAL]).isRequired, + autoHide: PropTypes.bool.isRequired, + autoScroll: PropTypes.bool.isRequired, + children: PropTypes.node, + onScroll: PropTypes.func +}; + +OverlayScroller.defaultProps = { + className: styles.scroller, + trackClassName: styles.thumb, + scrollDirection: scrollDirections.VERTICAL, + autoHide: false, + autoScroll: true +}; + +export default OverlayScroller; diff --git a/frontend/src/Components/Scroller/Scroller.css b/frontend/src/Components/Scroller/Scroller.css new file mode 100644 index 000000000..c8783a8de --- /dev/null +++ b/frontend/src/Components/Scroller/Scroller.css @@ -0,0 +1,28 @@ +.scroller { + @add-mixin scrollbar; + @add-mixin scrollbarTrack; + @add-mixin scrollbarThumb; +} + +.none { + overflow-x: hidden; + overflow-y: hidden; +} + +.vertical { + overflow-x: hidden; + overflow-y: scroll; + + &.autoScroll { + overflow-y: auto; + } +} + +.horizontal { + overflow-x: scroll; + overflow-y: hidden; + + &.autoScroll { + overflow-x: auto; + } +} diff --git a/frontend/src/Components/Scroller/Scroller.js b/frontend/src/Components/Scroller/Scroller.js new file mode 100644 index 000000000..701ac0cf4 --- /dev/null +++ b/frontend/src/Components/Scroller/Scroller.js @@ -0,0 +1,81 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { scrollDirections } from 'Helpers/Props'; +import styles from './Scroller.css'; + +class Scroller extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this._scroller = null; + } + + componentDidMount() { + const { + scrollTop + } = this.props; + + if (this.props.scrollTop != null) { + this._scroller.scrollTop = scrollTop; + } + } + + // + // Control + + _setScrollerRef = (ref) => { + this._scroller = ref; + } + + // + // Render + + render() { + const { + className, + scrollDirection, + autoScroll, + children, + scrollTop, + onScroll, + ...otherProps + } = this.props; + + return ( +
+ {children} +
+ ); + } + +} + +Scroller.propTypes = { + className: PropTypes.string, + scrollDirection: PropTypes.oneOf([scrollDirections.NONE, scrollDirections.HORIZONTAL, scrollDirections.VERTICAL]).isRequired, + autoScroll: PropTypes.bool.isRequired, + scrollTop: PropTypes.number, + children: PropTypes.node, + onScroll: PropTypes.func +}; + +Scroller.defaultProps = { + scrollDirection: scrollDirections.VERTICAL, + autoScroll: true +}; + +export default Scroller; diff --git a/frontend/src/Components/SignalRConnector.js b/frontend/src/Components/SignalRConnector.js new file mode 100644 index 000000000..f0af952f5 --- /dev/null +++ b/frontend/src/Components/SignalRConnector.js @@ -0,0 +1,351 @@ +import $ from 'jquery'; +import 'signalr'; +import PropTypes from 'prop-types'; +import { Component } from 'react'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import { repopulatePage } from 'Utilities/pagePopulator'; +import titleCase from 'Utilities/String/titleCase'; +import { fetchCommands, updateCommand, finishCommand } from 'Store/Actions/commandActions'; +import { setAppValue, setVersion } from 'Store/Actions/appActions'; +import { update, updateItem, removeItem } from 'Store/Actions/baseActions'; +import { fetchHealth } from 'Store/Actions/systemActions'; +import { fetchQueue, fetchQueueDetails } from 'Store/Actions/queueActions'; +import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; +import { fetchTags, fetchTagDetails } from 'Store/Actions/tagActions'; + +function getState(status) { + switch (status) { + case 0: + return 'connecting'; + case 1: + return 'connected'; + case 2: + return 'reconnecting'; + case 4: + return 'disconnected'; + default: + throw new Error(`invalid status ${status}`); + } +} + +function isAppDisconnected(disconnectedTime) { + if (!disconnectedTime) { + return false; + } + + return Math.floor(new Date().getTime() / 1000) - disconnectedTime > 180; +} + +function getHandlerName(name) { + name = titleCase(name); + name = name.replace('/', ''); + + return `handle${name}`; +} + +function createMapStateToProps() { + return createSelector( + (state) => state.app.isReconnecting, + (state) => state.app.isDisconnected, + (state) => state.queue.paged.isPopulated, + (isReconnecting, isDisconnected, isQueuePopulated) => { + return { + isReconnecting, + isDisconnected, + isQueuePopulated + }; + } + ); +} + +const mapDispatchToProps = { + dispatchFetchCommands: fetchCommands, + dispatchUpdateCommand: updateCommand, + dispatchFinishCommand: finishCommand, + dispatchSetAppValue: setAppValue, + dispatchSetVersion: setVersion, + dispatchUpdate: update, + dispatchUpdateItem: updateItem, + dispatchRemoveItem: removeItem, + dispatchFetchHealth: fetchHealth, + dispatchFetchQueue: fetchQueue, + dispatchFetchQueueDetails: fetchQueueDetails, + dispatchFetchRootFolders: fetchRootFolders, + dispatchFetchTags: fetchTags, + dispatchFetchTagDetails: fetchTagDetails +}; + +class SignalRConnector extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.signalRconnectionOptions = { transport: ['webSockets', 'longPolling'] }; + this.signalRconnection = null; + this.retryInterval = 1; + this.retryTimeoutId = null; + this.disconnectedTime = null; + } + + componentDidMount() { + console.log('Starting signalR'); + + this.signalRconnection = $.connection('/signalr', { apiKey: window.Radarr.apiKey }); + + this.signalRconnection.stateChanged(this.onStateChanged); + this.signalRconnection.received(this.onReceived); + this.signalRconnection.reconnecting(this.onReconnecting); + this.signalRconnection.disconnected(this.onDisconnected); + + this.signalRconnection.start(this.signalRconnectionOptions); + } + + componentWillUnmount() { + if (this.retryTimeoutId) { + this.retryTimeoutId = clearTimeout(this.retryTimeoutId); + } + + this.signalRconnection.stop(); + this.signalRconnection = null; + } + + // + // Control + + retryConnection = () => { + if (isAppDisconnected(this.disconnectedTime)) { + this.setState({ + isDisconnected: true + }); + } + + this.retryTimeoutId = setTimeout(() => { + if (!this.signalRconnection) { + console.error('signalR: Connection was disposed'); + return; + } + + this.signalRconnection.start(this.signalRconnectionOptions); + this.retryInterval = Math.min(this.retryInterval + 1, 10); + }, this.retryInterval * 1000); + } + + handleMessage = (message) => { + const { + name, + body + } = message; + + const handler = this[getHandlerName(name)]; + + if (handler) { + handler(body); + return; + } + + 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(); + return; + } + + const resource = body.resource; + const status = resource.status; + + // Both sucessful and failed commands need to be + // completed, otherwise they spin until they timeout. + + if (status === 'completed' || status === 'failed') { + this.props.dispatchFinishCommand(resource); + } else { + this.props.dispatchUpdateCommand(resource); + } + } + + 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(); + } + + handleMovie = (body) => { + const action = body.action; + const section = 'movies'; + + if (action === 'updated') { + this.props.dispatchUpdateItem({ section, ...body.resource }); + } else if (action === 'deleted') { + this.props.dispatchRemoveItem({ section, id: body.resource.id }); + } + } + + handleQueue = () => { + if (this.props.isQueuePopulated) { + this.props.dispatchFetchQueue(); + } + } + + handleQueueDetails = () => { + this.props.dispatchFetchQueueDetails(); + } + + handleQueueStatus = (body) => { + this.props.dispatchUpdate({ section: 'queue.status', data: body.resource }); + } + + handleRootfolder = () => { + this.props.dispatchFetchRootFolders(); + } + + handleVersion = (body) => { + const version = body.Version; + + this.props.dispatchSetVersion({ version }); + } + + handleSystemTask = () => { + // No-op for now, we may want this later + } + + handleTag = (body) => { + if (body.action === 'sync') { + this.props.dispatchFetchTags(); + this.props.dispatchFetchTagDetails(); + return; + } + } + + // + // Listeners + + onStateChanged = (change) => { + const state = getState(change.newState); + console.log(`signalR: ${state}`); + + if (state === 'connected') { + // Clear disconnected time + this.disconnectedTime = null; + + const { + dispatchFetchCommands, + dispatchSetAppValue + } = this.props; + + // Repopulate the page (if a repopulator is set) to ensure things + // are in sync after reconnecting. + + if (this.props.isReconnecting || this.props.isDisconnected) { + dispatchFetchCommands(); + repopulatePage(); + } + + dispatchSetAppValue({ + isConnected: true, + isReconnecting: false, + isDisconnected: false, + isRestarting: false + }); + + this.retryInterval = 5; + + if (this.retryTimeoutId) { + clearTimeout(this.retryTimeoutId); + } + } + } + + onReceived = (message) => { + console.debug('signalR: received', message.name, message.body); + + this.handleMessage(message); + } + + onReconnecting = () => { + if (window.Radarr.unloading) { + return; + } + + if (!this.disconnectedTime) { + this.disconnectedTime = Math.floor(new Date().getTime() / 1000); + } + + this.props.dispatchSetAppValue({ + isReconnecting: true + }); + } + + onDisconnected = () => { + if (window.Radarr.unloading) { + return; + } + + if (!this.disconnectedTime) { + this.disconnectedTime = Math.floor(new Date().getTime() / 1000); + } + + this.props.dispatchSetAppValue({ + isConnected: false, + isReconnecting: true, + isDisconnected: isAppDisconnected(this.disconnectedTime) + }); + + this.retryConnection(); + } + + // + // Render + + render() { + return null; + } +} + +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, + dispatchSetAppValue: PropTypes.func.isRequired, + dispatchSetVersion: PropTypes.func.isRequired, + dispatchUpdate: PropTypes.func.isRequired, + dispatchUpdateItem: PropTypes.func.isRequired, + dispatchRemoveItem: PropTypes.func.isRequired, + dispatchFetchHealth: PropTypes.func.isRequired, + dispatchFetchQueue: PropTypes.func.isRequired, + dispatchFetchQueueDetails: PropTypes.func.isRequired, + dispatchFetchRootFolders: PropTypes.func.isRequired, + dispatchFetchTags: PropTypes.func.isRequired, + dispatchFetchTagDetails: PropTypes.func.isRequired +}; + +export default connect(createMapStateToProps, mapDispatchToProps)(SignalRConnector); diff --git a/frontend/src/Components/SpinnerIcon.js b/frontend/src/Components/SpinnerIcon.js new file mode 100644 index 000000000..d21674d9e --- /dev/null +++ b/frontend/src/Components/SpinnerIcon.js @@ -0,0 +1,33 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons } from 'Helpers/Props'; +import Icon from './Icon'; + +function SpinnerIcon(props) { + const { + name, + spinningName, + isSpinning, + ...otherProps + } = props; + + return ( + + ); +} + +SpinnerIcon.propTypes = { + name: PropTypes.object.isRequired, + spinningName: PropTypes.object.isRequired, + isSpinning: PropTypes.bool.isRequired +}; + +SpinnerIcon.defaultProps = { + spinningName: icons.SPINNER +}; + +export default SpinnerIcon; diff --git a/frontend/src/Components/Table/Cells/RelativeDateCell.css b/frontend/src/Components/Table/Cells/RelativeDateCell.css new file mode 100644 index 000000000..7be20ce5d --- /dev/null +++ b/frontend/src/Components/Table/Cells/RelativeDateCell.css @@ -0,0 +1,5 @@ +.cell { + composes: cell from './TableRowCell.css'; + + width: 180px; +} diff --git a/frontend/src/Components/Table/Cells/RelativeDateCell.js b/frontend/src/Components/Table/Cells/RelativeDateCell.js new file mode 100644 index 000000000..93004b447 --- /dev/null +++ b/frontend/src/Components/Table/Cells/RelativeDateCell.js @@ -0,0 +1,60 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import formatDateTime from 'Utilities/Date/formatDateTime'; +import getRelativeDate from 'Utilities/Date/getRelativeDate'; +import TableRowCell from './TableRowCell'; +import styles from './RelativeDateCell.css'; + +function RelativeDateCell(props) { + const { + className, + date, + includeSeconds, + showRelativeDates, + shortDateFormat, + longDateFormat, + timeFormat, + component: Component, + dispatch, + ...otherProps + } = props; + + if (!date) { + return ( + + ); + } + + return ( + + {getRelativeDate(date, shortDateFormat, showRelativeDates, { timeFormat, includeSeconds, timeForToday: true })} + + ); +} + +RelativeDateCell.propTypes = { + className: PropTypes.string.isRequired, + date: PropTypes.string, + includeSeconds: PropTypes.bool.isRequired, + showRelativeDates: PropTypes.bool.isRequired, + shortDateFormat: PropTypes.string.isRequired, + longDateFormat: PropTypes.string.isRequired, + timeFormat: PropTypes.string.isRequired, + component: PropTypes.func, + dispatch: PropTypes.func +}; + +RelativeDateCell.defaultProps = { + className: styles.cell, + includeSeconds: false, + component: TableRowCell +}; + +export default RelativeDateCell; diff --git a/frontend/src/Components/Table/Cells/RelativeDateCellConnector.js b/frontend/src/Components/Table/Cells/RelativeDateCellConnector.js new file mode 100644 index 000000000..ed996abbe --- /dev/null +++ b/frontend/src/Components/Table/Cells/RelativeDateCellConnector.js @@ -0,0 +1,21 @@ +import _ from 'lodash'; +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; +import RelativeDateCell from './RelativeDateCell'; + +function createMapStateToProps() { + return createSelector( + createUISettingsSelector(), + (uiSettings) => { + return _.pick(uiSettings, [ + 'showRelativeDates', + 'shortDateFormat', + 'longDateFormat', + 'timeFormat' + ]); + } + ); +} + +export default connect(createMapStateToProps, null)(RelativeDateCell); diff --git a/frontend/src/Components/Table/Cells/TableRowCell.css b/frontend/src/Components/Table/Cells/TableRowCell.css new file mode 100644 index 000000000..1c3e6fc5a --- /dev/null +++ b/frontend/src/Components/Table/Cells/TableRowCell.css @@ -0,0 +1,11 @@ +.cell { + padding: 8px; + border-top: 1px solid #eee; + line-height: 1.52857143; +} + +@media only screen and (max-width: $breakpointSmall) { + .cell { + white-space: nowrap; + } +} diff --git a/frontend/src/Components/Table/Cells/TableRowCell.js b/frontend/src/Components/Table/Cells/TableRowCell.js new file mode 100644 index 000000000..f66bbf3aa --- /dev/null +++ b/frontend/src/Components/Table/Cells/TableRowCell.js @@ -0,0 +1,37 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import styles from './TableRowCell.css'; + +class TableRowCell extends Component { + + // + // Render + + render() { + const { + className, + children, + ...otherProps + } = this.props; + + return ( + + {children} + + ); + } +} + +TableRowCell.propTypes = { + className: PropTypes.string.isRequired, + children: PropTypes.oneOfType([PropTypes.string, PropTypes.node]) +}; + +TableRowCell.defaultProps = { + className: styles.cell +}; + +export default TableRowCell; diff --git a/frontend/src/Components/Table/Cells/TableRowCellButton.css b/frontend/src/Components/Table/Cells/TableRowCellButton.css new file mode 100644 index 000000000..f01e7cba6 --- /dev/null +++ b/frontend/src/Components/Table/Cells/TableRowCellButton.css @@ -0,0 +1,4 @@ +.cell { + composes: cell from './TableRowCell.css'; + composes: link from 'Components/Link/Link.css'; +} diff --git a/frontend/src/Components/Table/Cells/TableRowCellButton.js b/frontend/src/Components/Table/Cells/TableRowCellButton.js new file mode 100644 index 000000000..ff50d3bc9 --- /dev/null +++ b/frontend/src/Components/Table/Cells/TableRowCellButton.js @@ -0,0 +1,25 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Link from 'Components/Link/Link'; +import TableRowCell from './TableRowCell'; +import styles from './TableRowCellButton.css'; + +function TableRowCellButton({ className, ...otherProps }) { + return ( + + ); +} + +TableRowCellButton.propTypes = { + className: PropTypes.string.isRequired +}; + +TableRowCellButton.defaultProps = { + className: styles.cell +}; + +export default TableRowCellButton; diff --git a/frontend/src/Components/Table/Cells/TableSelectCell.css b/frontend/src/Components/Table/Cells/TableSelectCell.css new file mode 100644 index 000000000..21ab944d7 --- /dev/null +++ b/frontend/src/Components/Table/Cells/TableSelectCell.css @@ -0,0 +1,11 @@ +.selectCell { + composes: cell from 'Components/Table/Cells/TableRowCell.css'; + + width: 30px; +} + +.input { + composes: input from 'Components/Form/CheckInput.css'; + + margin: 0; +} diff --git a/frontend/src/Components/Table/Cells/TableSelectCell.js b/frontend/src/Components/Table/Cells/TableSelectCell.js new file mode 100644 index 000000000..9c10f4444 --- /dev/null +++ b/frontend/src/Components/Table/Cells/TableSelectCell.js @@ -0,0 +1,80 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import CheckInput from 'Components/Form/CheckInput'; +import TableRowCell from './TableRowCell'; +import styles from './TableSelectCell.css'; + +class TableSelectCell extends Component { + + // + // Lifecycle + + componentDidMount() { + const { + id, + isSelected, + onSelectedChange + } = this.props; + + onSelectedChange({ id, value: isSelected }); + } + + componentWillUnmount() { + const { + id, + onSelectedChange + } = this.props; + + onSelectedChange({ id, value: null }); + } + + // + // Listeners + + onChange = ({ value, shiftKey }, a, b, c, d) => { + const { + id, + onSelectedChange + } = this.props; + + onSelectedChange({ id, value, shiftKey }); + } + + // + // Render + + render() { + const { + className, + id, + isSelected, + ...otherProps + } = this.props; + + return ( + + + + ); + } +} + +TableSelectCell.propTypes = { + className: PropTypes.string.isRequired, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + isSelected: PropTypes.bool.isRequired, + onSelectedChange: PropTypes.func.isRequired +}; + +TableSelectCell.defaultProps = { + className: styles.selectCell, + isSelected: false +}; + +export default TableSelectCell; diff --git a/frontend/src/Components/Table/Cells/VirtualTableRowCell.css b/frontend/src/Components/Table/Cells/VirtualTableRowCell.css new file mode 100644 index 000000000..e4cffe1c4 --- /dev/null +++ b/frontend/src/Components/Table/Cells/VirtualTableRowCell.css @@ -0,0 +1,14 @@ +.cell { + @add-mixin truncate; + composes: cell from 'Components/Table/Cells/TableRowCell.css'; + + flex-grow: 0; + flex-shrink: 1; + white-space: nowrap; +} + +@media only screen and (max-width: $breakpointSmall) { + .cell { + white-space: nowrap; + } +} diff --git a/frontend/src/Components/Table/Cells/VirtualTableRowCell.js b/frontend/src/Components/Table/Cells/VirtualTableRowCell.js new file mode 100644 index 000000000..42999216f --- /dev/null +++ b/frontend/src/Components/Table/Cells/VirtualTableRowCell.js @@ -0,0 +1,29 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import styles from './VirtualTableRowCell.css'; + +function VirtualTableRowCell(props) { + const { + className, + children + } = props; + + return ( +
+ {children} +
+ ); +} + +VirtualTableRowCell.propTypes = { + className: PropTypes.string.isRequired, + children: PropTypes.oneOfType([PropTypes.string, PropTypes.node]) +}; + +VirtualTableRowCell.defaultProps = { + className: styles.cell +}; + +export default VirtualTableRowCell; diff --git a/frontend/src/Components/Table/Cells/VirtualTableSelectCell.css b/frontend/src/Components/Table/Cells/VirtualTableSelectCell.css new file mode 100644 index 000000000..e1016aa8a --- /dev/null +++ b/frontend/src/Components/Table/Cells/VirtualTableSelectCell.css @@ -0,0 +1,11 @@ +.cell { + composes: cell from 'Components/Table/Cells/VirtualTableRowCell.css'; + + flex: 0 0 36px; +} + +.input { + composes: input from 'Components/Form/CheckInput.css'; + + margin: 0; +} diff --git a/frontend/src/Components/Table/Cells/VirtualTableSelectCell.js b/frontend/src/Components/Table/Cells/VirtualTableSelectCell.js new file mode 100644 index 000000000..a773aab58 --- /dev/null +++ b/frontend/src/Components/Table/Cells/VirtualTableSelectCell.js @@ -0,0 +1,82 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import CheckInput from 'Components/Form/CheckInput'; +import VirtualTableRowCell from './VirtualTableRowCell'; +import styles from './VirtualTableSelectCell.css'; + +export function virtualTableSelectCellRenderer(cellProps) { + const { + cellKey, + rowData, + columnData, + ...otherProps + } = cellProps; + + return ( + + ); +} + +class VirtualTableSelectCell extends Component { + + // + // Listeners + + onChange = ({ value, shiftKey }) => { + const { + id, + onSelectedChange + } = this.props; + + onSelectedChange({ id, value, shiftKey }); + } + + // + // Render + + render() { + const { + inputClassName, + id, + isSelected, + isDisabled, + ...otherProps + } = this.props; + + return ( + + + + ); + } +} + +VirtualTableSelectCell.propTypes = { + inputClassName: PropTypes.string.isRequired, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + isSelected: PropTypes.bool.isRequired, + isDisabled: PropTypes.bool.isRequired, + onSelectedChange: PropTypes.func.isRequired +}; + +VirtualTableSelectCell.defaultProps = { + inputClassName: styles.input, + isSelected: false +}; + +export default VirtualTableSelectCell; diff --git a/frontend/src/Components/Table/Table.css b/frontend/src/Components/Table/Table.css new file mode 100644 index 000000000..46d49826a --- /dev/null +++ b/frontend/src/Components/Table/Table.css @@ -0,0 +1,16 @@ +.tableContainer { + overflow-x: auto; +} + +.table { + max-width: 100%; + width: 100%; + border-collapse: collapse; +} + +@media only screen and (max-width: $breakpointSmall) { + .tableContainer { + overflow-y: hidden; + width: 100%; + } +} diff --git a/frontend/src/Components/Table/Table.js b/frontend/src/Components/Table/Table.js new file mode 100644 index 000000000..612d95b8c --- /dev/null +++ b/frontend/src/Components/Table/Table.js @@ -0,0 +1,129 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { icons, scrollDirections } from 'Helpers/Props'; +import IconButton from 'Components/Link/IconButton'; +import Scroller from 'Components/Scroller/Scroller'; +import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper'; +import TableHeader from './TableHeader'; +import TableHeaderCell from './TableHeaderCell'; +import TableSelectAllHeaderCell from './TableSelectAllHeaderCell'; +import styles from './Table.css'; + +const tableHeaderCellProps = [ + 'sortKey', + 'sortDirection' +]; + +function getTableHeaderCellProps(props) { + return _.reduce(tableHeaderCellProps, (result, key) => { + if (props.hasOwnProperty(key)) { + result[key] = props[key]; + } + + return result; + }, {}); +} + +function Table(props) { + const { + className, + selectAll, + columns, + optionsComponent, + pageSize, + canModifyColumns, + children, + onSortPress, + onTableOptionChange, + ...otherProps + } = props; + + return ( + + + + { + selectAll && + + } + + { + columns.map((column) => { + const { + name, + isVisible + } = column; + + if (!isVisible) { + return null; + } + + if ( + (name === 'actions' || name === 'details') && + onTableOptionChange + ) { + return ( + + + + + + ); + } + + return ( + + {column.label} + + ); + }) + } + + + {children} +
+
+ ); +} + +Table.propTypes = { + className: PropTypes.string, + selectAll: PropTypes.bool.isRequired, + columns: PropTypes.arrayOf(PropTypes.object).isRequired, + optionsComponent: PropTypes.func, + pageSize: PropTypes.number, + canModifyColumns: PropTypes.bool, + children: PropTypes.node, + onSortPress: PropTypes.func, + onTableOptionChange: PropTypes.func +}; + +Table.defaultProps = { + className: styles.table, + selectAll: false +}; + +export default Table; diff --git a/frontend/src/Components/Table/TableBody.js b/frontend/src/Components/Table/TableBody.js new file mode 100644 index 000000000..5cc60d6f4 --- /dev/null +++ b/frontend/src/Components/Table/TableBody.js @@ -0,0 +1,25 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; + +class TableBody extends Component { + + // + // Render + + render() { + const { + children + } = this.props; + + return ( + {children} + ); + } + +} + +TableBody.propTypes = { + children: PropTypes.node +}; + +export default TableBody; diff --git a/frontend/src/Components/Table/TableHeader.js b/frontend/src/Components/Table/TableHeader.js new file mode 100644 index 000000000..81943e919 --- /dev/null +++ b/frontend/src/Components/Table/TableHeader.js @@ -0,0 +1,28 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; + +class TableHeader extends Component { + + // + // Render + + render() { + const { + children + } = this.props; + + return ( + + + {children} + + + ); + } +} + +TableHeader.propTypes = { + children: PropTypes.node +}; + +export default TableHeader; diff --git a/frontend/src/Components/Table/TableHeaderCell.css b/frontend/src/Components/Table/TableHeaderCell.css new file mode 100644 index 000000000..c2c4f58c8 --- /dev/null +++ b/frontend/src/Components/Table/TableHeaderCell.css @@ -0,0 +1,16 @@ +.headerCell { + padding: 8px; + border: none !important; + text-align: left; + font-weight: bold; +} + +.sortIcon { + margin-left: 10px; +} + +@media only screen and (max-width: $breakpointSmall) { + .headerCell { + white-space: nowrap; + } +} diff --git a/frontend/src/Components/Table/TableHeaderCell.js b/frontend/src/Components/Table/TableHeaderCell.js new file mode 100644 index 000000000..e4739e63f --- /dev/null +++ b/frontend/src/Components/Table/TableHeaderCell.js @@ -0,0 +1,96 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons, sortDirections } from 'Helpers/Props'; +import Link from 'Components/Link/Link'; +import Icon from 'Components/Icon'; +import styles from './TableHeaderCell.css'; + +class TableHeaderCell extends Component { + + // + // Listeners + + onPress = () => { + const { + name, + fixedSortDirection + } = this.props; + + if (fixedSortDirection) { + this.props.onSortPress(name, fixedSortDirection); + } else { + this.props.onSortPress(name); + } + } + + // + // Render + + render() { + const { + className, + name, + columnLabel, + isSortable, + isVisible, + isModifiable, + sortKey, + sortDirection, + fixedSortDirection, + children, + onSortPress, + ...otherProps + } = this.props; + + const isSorting = isSortable && sortKey === name; + const sortIcon = sortDirection === sortDirections.ASCENDING ? + icons.SORT_ASCENDING : + icons.SORT_DESCENDING; + + return ( + isSortable ? + + {children} + + { + isSorting && + + } + : + + + {children} + + ); + } +} + +TableHeaderCell.propTypes = { + className: PropTypes.string, + name: PropTypes.string.isRequired, + columnLabel: PropTypes.string, + isSortable: PropTypes.bool, + isVisible: PropTypes.bool, + isModifiable: PropTypes.bool, + sortKey: PropTypes.string, + fixedSortDirection: PropTypes.string, + sortDirection: PropTypes.string, + children: PropTypes.node, + onSortPress: PropTypes.func +}; + +TableHeaderCell.defaultProps = { + className: styles.headerCell, + isSortable: false +}; + +export default TableHeaderCell; diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsColumn.css b/frontend/src/Components/Table/TableOptions/TableOptionsColumn.css new file mode 100644 index 000000000..204773c3d --- /dev/null +++ b/frontend/src/Components/Table/TableOptions/TableOptionsColumn.css @@ -0,0 +1,48 @@ +.column { + display: flex; + align-items: stretch; + width: 100%; + border: 1px solid #aaa; + border-radius: 4px; + background: #fafafa; +} + +.checkContainer { + position: relative; + margin-right: 4px; + margin-bottom: 7px; + margin-left: 8px; +} + +.label { + display: flex; + flex-grow: 1; + margin-bottom: 0; + margin-left: 2px; + font-weight: normal; + line-height: 36px; + cursor: pointer; +} + +.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; +} + +.notDragable { + padding: 4px 0; +} diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsColumn.js b/frontend/src/Components/Table/TableOptions/TableOptionsColumn.js new file mode 100644 index 000000000..a986be615 --- /dev/null +++ b/frontend/src/Components/Table/TableOptions/TableOptionsColumn.js @@ -0,0 +1,68 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; +import { icons } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import CheckInput from 'Components/Form/CheckInput'; +import styles from './TableOptionsColumn.css'; + +function TableOptionsColumn(props) { + const { + name, + label, + isVisible, + isModifiable, + isDragging, + connectDragSource, + onVisibleChange + } = props; + + return ( +
+
+ + + { + !!connectDragSource && + connectDragSource( +
+ +
+ ) + } +
+
+ ); +} + +TableOptionsColumn.propTypes = { + name: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + isVisible: PropTypes.bool.isRequired, + isModifiable: PropTypes.bool.isRequired, + index: PropTypes.number.isRequired, + isDragging: PropTypes.bool, + connectDragSource: PropTypes.func, + onVisibleChange: PropTypes.func.isRequired +}; + +export default TableOptionsColumn; diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragPreview.css b/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragPreview.css new file mode 100644 index 000000000..b927d9bce --- /dev/null +++ b/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragPreview.css @@ -0,0 +1,4 @@ +.dragPreview { + width: 380px; + opacity: 0.75; +} diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragPreview.js b/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragPreview.js new file mode 100644 index 000000000..b1d016529 --- /dev/null +++ b/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragPreview.js @@ -0,0 +1,78 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { DragLayer } from 'react-dnd'; +import dimensions from 'Styles/Variables/dimensions.js'; +import { TABLE_COLUMN } from 'Helpers/dragTypes'; +import DragPreviewLayer from 'Components/DragPreviewLayer'; +import TableOptionsColumn from './TableOptionsColumn'; +import styles from './TableOptionsColumnDragPreview.css'; + +const formGroupSmallWidth = parseInt(dimensions.formGroupSmallWidth); +const formLabelLargeWidth = parseInt(dimensions.formLabelLargeWidth); +const formLabelRightMarginWidth = parseInt(dimensions.formLabelRightMarginWidth); +const dragHandleWidth = parseInt(dimensions.dragHandleWidth); + +function collectDragLayer(monitor) { + return { + item: monitor.getItem(), + itemType: monitor.getItemType(), + currentOffset: monitor.getSourceClientOffset() + }; +} + +class TableOptionsColumnDragPreview extends Component { + + // + // Render + + render() { + const { + item, + itemType, + currentOffset + } = this.props; + + if (!currentOffset || itemType !== TABLE_COLUMN) { + 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 = formGroupSmallWidth - formLabelLargeWidth - formLabelRightMarginWidth - dragHandleWidth; + const transform = `translate3d(${x - handleOffset}px, ${y}px, 0)`; + + const style = { + position: 'absolute', + WebkitTransform: transform, + msTransform: transform, + transform + }; + + return ( + +
+ +
+
+ ); + } +} + +TableOptionsColumnDragPreview.propTypes = { + item: PropTypes.object, + itemType: PropTypes.string, + currentOffset: PropTypes.shape({ + x: PropTypes.number.isRequired, + y: PropTypes.number.isRequired + }) +}; + +export default DragLayer(collectDragLayer)(TableOptionsColumnDragPreview); diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragSource.css b/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragSource.css new file mode 100644 index 000000000..9354a35c0 --- /dev/null +++ b/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragSource.css @@ -0,0 +1,18 @@ +.columnDragSource { + padding: 4px 0; +} + +.columnPlaceholder { + width: 100%; + height: 36px; + border: 1px dotted #aaa; + border-radius: 4px; +} + +.columnPlaceholderBefore { + margin-bottom: 8px; +} + +.columnPlaceholderAfter { + margin-top: 8px; +} diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragSource.js b/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragSource.js new file mode 100644 index 000000000..80f03e430 --- /dev/null +++ b/frontend/src/Components/Table/TableOptions/TableOptionsColumnDragSource.js @@ -0,0 +1,164 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { findDOMNode } from 'react-dom'; +import { DragSource, DropTarget } from 'react-dnd'; +import classNames from 'classnames'; +import { TABLE_COLUMN } from 'Helpers/dragTypes'; +import TableOptionsColumn from './TableOptionsColumn'; +import styles from './TableOptionsColumnDragSource.css'; + +const columnDragSource = { + beginDrag(column) { + return column; + }, + + endDrag(props, monitor, component) { + props.onColumnDragEnd(monitor.getItem(), monitor.didDrop()); + } +}; + +const columnDropTarget = { + hover(props, monitor, component) { + const dragIndex = monitor.getItem().index; + const hoverIndex = props.index; + + 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. + + // Dragging downwards + if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) { + return; + } + + // Dragging upwards + if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) { + return; + } + + props.onColumnDragMove(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 TableOptionsColumnDragSource extends Component { + + // + // Render + + render() { + const { + name, + label, + isVisible, + isModifiable, + index, + isDragging, + isDraggingUp, + isDraggingDown, + isOver, + connectDragSource, + connectDropTarget, + onVisibleChange + } = this.props; + + const isBefore = !isDragging && isDraggingUp && isOver; + const isAfter = !isDragging && isDraggingDown && isOver; + + // if (isDragging && !isOver) { + // return null; + // } + + return connectDropTarget( +
+ { + isBefore && +
+ } + + + + { + isAfter && +
+ } +
+ ); + } +} + +TableOptionsColumnDragSource.propTypes = { + name: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + isVisible: PropTypes.bool.isRequired, + isModifiable: PropTypes.bool.isRequired, + index: PropTypes.number.isRequired, + isDragging: PropTypes.bool, + isDraggingUp: PropTypes.bool, + isDraggingDown: PropTypes.bool, + isOver: PropTypes.bool, + connectDragSource: PropTypes.func, + connectDropTarget: PropTypes.func, + onVisibleChange: PropTypes.func.isRequired, + onColumnDragMove: PropTypes.func.isRequired, + onColumnDragEnd: PropTypes.func.isRequired +}; + +export default DropTarget( + TABLE_COLUMN, + columnDropTarget, + collectDropTarget +)(DragSource( + TABLE_COLUMN, + columnDragSource, + collectDragSource +)(TableOptionsColumnDragSource)); diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsModal.css b/frontend/src/Components/Table/TableOptions/TableOptionsModal.css new file mode 100644 index 000000000..35544f32b --- /dev/null +++ b/frontend/src/Components/Table/TableOptions/TableOptionsModal.css @@ -0,0 +1,5 @@ +.columns { + margin-top: 10px; + width: 100%; + user-select: none; +} diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsModal.js b/frontend/src/Components/Table/TableOptions/TableOptionsModal.js new file mode 100644 index 000000000..351d827ca --- /dev/null +++ b/frontend/src/Components/Table/TableOptions/TableOptionsModal.js @@ -0,0 +1,252 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { DragDropContext } from 'react-dnd'; +import HTML5Backend from 'react-dnd-html5-backend'; +import { inputTypes } from 'Helpers/Props'; +import Button from 'Components/Link/Button'; +import Form from 'Components/Form/Form'; +import FormGroup from 'Components/Form/FormGroup'; +import FormLabel from 'Components/Form/FormLabel'; +import FormInputHelpText from 'Components/Form/FormInputHelpText'; +import FormInputGroup from 'Components/Form/FormInputGroup'; +import Modal from 'Components/Modal/Modal'; +import ModalContent from 'Components/Modal/ModalContent'; +import ModalHeader from 'Components/Modal/ModalHeader'; +import ModalBody from 'Components/Modal/ModalBody'; +import ModalFooter from 'Components/Modal/ModalFooter'; +import TableOptionsColumn from './TableOptionsColumn'; +import TableOptionsColumnDragSource from './TableOptionsColumnDragSource'; +import TableOptionsColumnDragPreview from './TableOptionsColumnDragPreview'; +import styles from './TableOptionsModal.css'; + +class TableOptionsModal extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + hasPageSize: !!props.pageSize, + pageSize: props.pageSize, + pageSizeError: null, + dragIndex: null, + dropIndex: null + }; + } + + componentDidUpdate(prevProps) { + if (prevProps.pageSize !== this.state.pageSize) { + this.setState({ pageSize: this.props.pageSize }); + } + } + + // + // Listeners + + onPageSizeChange = ({ value }) => { + let pageSizeError = null; + + if (value < 5) { + pageSizeError = 'Page size must be at least 5'; + } else if (value > 250) { + pageSizeError = 'Page size must not exceed 250'; + } else { + this.props.onTableOptionChange({ pageSize: value }); + } + + this.setState({ + pageSize: value, + pageSizeError + }); + } + + onVisibleChange = ({ name, value }) => { + const columns = _.cloneDeep(this.props.columns); + + const column = _.find(columns, { name }); + column.isVisible = value; + + this.props.onTableOptionChange({ columns }); + } + + onColumnDragMove = (dragIndex, dropIndex) => { + if (this.state.dragIndex !== dragIndex || this.state.dropIndex !== dropIndex) { + this.setState({ + dragIndex, + dropIndex + }); + } + } + + onColumnDragEnd = ({ id }, didDrop) => { + const { + dragIndex, + dropIndex + } = this.state; + + if (didDrop && dropIndex !== null) { + const columns = _.cloneDeep(this.props.columns); + const items = columns.splice(dragIndex, 1); + columns.splice(dropIndex, 0, items[0]); + + this.props.onTableOptionChange({ columns }); + } + + this.setState({ + dragIndex: null, + dropIndex: null + }); + } + + // + // Render + + render() { + const { + isOpen, + columns, + canModifyColumns, + optionsComponent: OptionsComponent, + onTableOptionChange, + onModalClose + } = this.props; + + const { + hasPageSize, + pageSize, + pageSizeError, + dragIndex, + dropIndex + } = this.state; + + const isDragging = dropIndex !== null; + const isDraggingUp = isDragging && dropIndex < dragIndex; + const isDraggingDown = isDragging && dropIndex > dragIndex; + + return ( + + + + Table Options + + + +
+ { + hasPageSize && + + Page Size + + + + } + + { + !!OptionsComponent && + + } + + { + canModifyColumns && + + Columns + +
+ + +
+ { + columns.map((column, index) => { + const { + name, + label, + columnLabel, + isVisible, + isModifiable + } = column; + + if (isModifiable !== false) { + return ( + + ); + } + + return ( + + ); + }) + } + + +
+
+
+ } + +
+ + + +
+
+ ); + } +} + +TableOptionsModal.propTypes = { + isOpen: PropTypes.bool.isRequired, + columns: PropTypes.arrayOf(PropTypes.object).isRequired, + pageSize: PropTypes.number, + canModifyColumns: PropTypes.bool.isRequired, + optionsComponent: PropTypes.func, + onTableOptionChange: PropTypes.func.isRequired, + onModalClose: PropTypes.func.isRequired +}; + +TableOptionsModal.defaultProps = { + canModifyColumns: true +}; + +export default DragDropContext(HTML5Backend)(TableOptionsModal); diff --git a/frontend/src/Components/Table/TableOptions/TableOptionsModalWrapper.js b/frontend/src/Components/Table/TableOptions/TableOptionsModalWrapper.js new file mode 100644 index 000000000..ff2b8538b --- /dev/null +++ b/frontend/src/Components/Table/TableOptions/TableOptionsModalWrapper.js @@ -0,0 +1,61 @@ +import PropTypes from 'prop-types'; +import React, { Component, Fragment } from 'react'; +import TableOptionsModal from './TableOptionsModal'; + +class TableOptionsModalWrapper extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isTableOptionsModalOpen: false + }; + } + + // + // Listeners + + onTableOptionsPress = () => { + this.setState({ isTableOptionsModalOpen: true }); + } + + onTableOptionsModalClose = () => { + this.setState({ isTableOptionsModalOpen: false }); + } + + // + // Render + + render() { + const { + columns, + children, + ...otherProps + } = this.props; + + return ( + + { + React.cloneElement(children, { onPress: this.onTableOptionsPress }) + } + + + + ); + } +} + +TableOptionsModalWrapper.propTypes = { + columns: PropTypes.arrayOf(PropTypes.object).isRequired, + children: PropTypes.node.isRequired +}; + +export default TableOptionsModalWrapper; diff --git a/frontend/src/Components/Table/TablePager.css b/frontend/src/Components/Table/TablePager.css new file mode 100644 index 000000000..17d300fb9 --- /dev/null +++ b/frontend/src/Components/Table/TablePager.css @@ -0,0 +1,77 @@ +.pager { + display: flex; + align-items: center; + justify-content: space-between; +} + +.loadingContainer, +.controlsContainer, +.recordsContainer { + flex: 0 1 33%; +} + +.controlsContainer { + display: flex; + justify-content: center; +} + +.recordsContainer { + display: flex; + justify-content: flex-end; +} + +.loading { + composes: loading from 'Components/Loading/LoadingIndicator.css'; + + margin: 0; + margin-left: 5px; + text-align: left; +} + +.controls { + display: flex; + align-items: center; + text-align: center; +} + +.pageNumber { + line-height: 30px; +} + +.pageLink { + padding: 0; + width: 30px; + height: 30px; + line-height: 30px; +} + +.records { + color: $disabledColor; +} + +.disabledPageButton { + color: $disabledColor; +} + +.pageSelect { + composes: select from 'Components/Form/SelectInput.css'; + + padding: 0 2px; + height: 25px; +} + +@media only screen and (max-width: $breakpointSmall) { + .pager { + flex-wrap: wrap; + } + + .loadingContainer, + .recordsContainer { + flex: 0 1 50%; + } + + .controlsContainer { + flex: 0 1 100%; + order: -1; + } +} diff --git a/frontend/src/Components/Table/TablePager.js b/frontend/src/Components/Table/TablePager.js new file mode 100644 index 000000000..3c7c5a8f1 --- /dev/null +++ b/frontend/src/Components/Table/TablePager.js @@ -0,0 +1,180 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { icons } from 'Helpers/Props'; +import Icon from 'Components/Icon'; +import Link from 'Components/Link/Link'; +import LoadingIndicator from 'Components/Loading/LoadingIndicator'; +import SelectInput from 'Components/Form/SelectInput'; +import styles from './TablePager.css'; + +class TablePager extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isShowingPageSelect: false + }; + } + + // + // Listeners + + onOpenPageSelectClick = () => { + this.setState({ isShowingPageSelect: true }); + } + + onPageSelect = ({ value: page }) => { + this.setState({ isShowingPageSelect: false }); + this.props.onPageSelect(parseInt(page)); + } + + onPageSelectBlur = () => { + this.setState({ isShowingPageSelect: false }); + } + + // + // Render + + render() { + const { + page, + totalPages, + totalRecords, + isFetching, + onFirstPagePress, + onPreviousPagePress, + onNextPagePress, + onLastPagePress + } = this.props; + + const isShowingPageSelect = this.state.isShowingPageSelect; + const pages = Array.from(new Array(totalPages), (x, i) => { + const pageNumber = i + 1; + + return { + key: pageNumber, + value: pageNumber + }; + }); + + if (!page) { + return null; + } + + const isFirstPage = page === 1; + const isLastPage = page === totalPages; + + return ( +
+
+ { + isFetching && + + } +
+ +
+
+ + + + + + + + +
+ { + !isShowingPageSelect && + + {page} / {totalPages} + + } + + { + isShowingPageSelect && + + } +
+ + + + + + + + +
+
+ +
+
+ Total records: {totalRecords} +
+
+
+ ); + } + +} + +TablePager.propTypes = { + page: PropTypes.number, + totalPages: PropTypes.number, + totalRecords: PropTypes.number, + isFetching: PropTypes.bool, + onFirstPagePress: PropTypes.func.isRequired, + onPreviousPagePress: PropTypes.func.isRequired, + onNextPagePress: PropTypes.func.isRequired, + onLastPagePress: PropTypes.func.isRequired, + onPageSelect: PropTypes.func.isRequired +}; + +export default TablePager; diff --git a/frontend/src/Components/Table/TableRow.css b/frontend/src/Components/Table/TableRow.css new file mode 100644 index 000000000..dcc6ad8cf --- /dev/null +++ b/frontend/src/Components/Table/TableRow.css @@ -0,0 +1,7 @@ +.row { + transition: background-color 500ms; + + &:hover { + background-color: $tableRowHoverBackgroundColor; + } +} diff --git a/frontend/src/Components/Table/TableRow.js b/frontend/src/Components/Table/TableRow.js new file mode 100644 index 000000000..c76083183 --- /dev/null +++ b/frontend/src/Components/Table/TableRow.js @@ -0,0 +1,33 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import styles from './TableRow.css'; + +function TableRow(props) { + const { + className, + children, + overlayContent, + ...otherProps + } = props; + + return ( + + {children} + + ); +} + +TableRow.propTypes = { + className: PropTypes.string.isRequired, + children: PropTypes.node, + overlayContent: PropTypes.bool +}; + +TableRow.defaultProps = { + className: styles.row +}; + +export default TableRow; diff --git a/frontend/src/Components/Table/TableRowButton.css b/frontend/src/Components/Table/TableRowButton.css new file mode 100644 index 000000000..70a2238ca --- /dev/null +++ b/frontend/src/Components/Table/TableRowButton.css @@ -0,0 +1,4 @@ +.row { + composes: link from 'Components/Link/Link.css'; + composes: row from './TableRow.css'; +} diff --git a/frontend/src/Components/Table/TableRowButton.js b/frontend/src/Components/Table/TableRowButton.js new file mode 100644 index 000000000..7ff679673 --- /dev/null +++ b/frontend/src/Components/Table/TableRowButton.js @@ -0,0 +1,16 @@ +import React from 'react'; +import Link from 'Components/Link/Link'; +import TableRow from './TableRow'; +import styles from './TableRowButton.css'; + +function TableRowButton(props) { + return ( + + ); +} + +export default TableRowButton; diff --git a/frontend/src/Components/Table/TableSelectAllHeaderCell.css b/frontend/src/Components/Table/TableSelectAllHeaderCell.css new file mode 100644 index 000000000..6090e6e9c --- /dev/null +++ b/frontend/src/Components/Table/TableSelectAllHeaderCell.css @@ -0,0 +1,11 @@ +.selectAllHeaderCell { + composes: headerCell from 'Components/Table/VirtualTableHeaderCell.css'; + + width: 30px; +} + +.input { + composes: input from 'Components/Form/CheckInput.css'; + + margin: 0; +} diff --git a/frontend/src/Components/Table/TableSelectAllHeaderCell.js b/frontend/src/Components/Table/TableSelectAllHeaderCell.js new file mode 100644 index 000000000..c889c32ae --- /dev/null +++ b/frontend/src/Components/Table/TableSelectAllHeaderCell.js @@ -0,0 +1,47 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import CheckInput from 'Components/Form/CheckInput'; +import VirtualTableHeaderCell from './TableHeaderCell'; +import styles from './TableSelectAllHeaderCell.css'; + +function getValue(allSelected, allUnselected) { + if (allSelected) { + return true; + } else if (allUnselected) { + return false; + } + + return null; +} + +function TableSelectAllHeaderCell(props) { + const { + allSelected, + allUnselected, + onSelectAllChange + } = props; + + const value = getValue(allSelected, allUnselected); + + return ( + + + + ); +} + +TableSelectAllHeaderCell.propTypes = { + allSelected: PropTypes.bool.isRequired, + allUnselected: PropTypes.bool.isRequired, + onSelectAllChange: PropTypes.func.isRequired +}; + +export default TableSelectAllHeaderCell; diff --git a/frontend/src/Components/Table/VirtualTable.css b/frontend/src/Components/Table/VirtualTable.css new file mode 100644 index 000000000..3287c5643 --- /dev/null +++ b/frontend/src/Components/Table/VirtualTable.css @@ -0,0 +1,3 @@ +.tableContainer { + width: 100%; +} diff --git a/frontend/src/Components/Table/VirtualTable.js b/frontend/src/Components/Table/VirtualTable.js new file mode 100644 index 000000000..a13807647 --- /dev/null +++ b/frontend/src/Components/Table/VirtualTable.js @@ -0,0 +1,167 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import ReactDOM from 'react-dom'; +import { WindowScroller } from 'react-virtualized'; +import { scrollDirections } from 'Helpers/Props'; +import Measure from 'Components/Measure'; +import Scroller from 'Components/Scroller/Scroller'; +import VirtualTableBody from './VirtualTableBody'; +import styles from './VirtualTable.css'; + +const ROW_HEIGHT = 38; + +function overscanIndicesGetter(options) { + const { + cellCount, + overscanCellsCount, + startIndex, + stopIndex + } = options; + + // The default getter takes the scroll direction into account, + // but that can cause issues. Ignore the scroll direction and + // always over return more items. + + const overscanStartIndex = startIndex - overscanCellsCount; + const overscanStopIndex = stopIndex + overscanCellsCount; + + return { + overscanStartIndex: Math.max(0, overscanStartIndex), + overscanStopIndex: Math.min(cellCount - 1, overscanStopIndex) + }; +} + +class VirtualTable extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + width: 0 + }; + + this._isInitialized = false; + } + + componentDidMount() { + this._contentBodyNode = ReactDOM.findDOMNode(this.props.contentBody); + } + + componentDidUpdate(prevProps, preState) { + const scrollIndex = this.props.scrollIndex; + + if (scrollIndex != null && scrollIndex !== prevProps.scrollIndex) { + const scrollTop = (scrollIndex + 1) * ROW_HEIGHT + 20; + + this.props.onScroll({ scrollTop }); + } + } + + // + // Control + + rowGetter = ({ index }) => { + return this.props.items[index]; + } + + // + // Listeners + + onMeasure = ({ width }) => { + this.setState({ + width + }); + } + + onSectionRendered = () => { + if (!this._isInitialized && this._contentBodyNode) { + this.props.onRender(); + this._isInitialized = true; + } + } + + // + // Render + + render() { + const { + className, + items, + isSmallScreen, + header, + headerHeight, + scrollTop, + rowRenderer, + onScroll, + ...otherProps + } = this.props; + + const { + width + } = this.state; + + return ( + + + {({ height, isScrolling }) => { + return ( + + {header} + + + + ); + } + } + + + ); + } +} + +VirtualTable.propTypes = { + className: PropTypes.string.isRequired, + items: PropTypes.arrayOf(PropTypes.object).isRequired, + scrollTop: PropTypes.number.isRequired, + scrollIndex: PropTypes.number, + contentBody: PropTypes.object.isRequired, + isSmallScreen: PropTypes.bool.isRequired, + header: PropTypes.node.isRequired, + headerHeight: PropTypes.number.isRequired, + rowRenderer: PropTypes.func.isRequired, + onRender: PropTypes.func.isRequired, + onScroll: PropTypes.func.isRequired +}; + +VirtualTable.defaultProps = { + className: styles.tableContainer, + headerHeight: 38, + onRender: () => {} +}; + +export default VirtualTable; diff --git a/frontend/src/Components/Table/VirtualTableBody.css b/frontend/src/Components/Table/VirtualTableBody.css new file mode 100644 index 000000000..12768646d --- /dev/null +++ b/frontend/src/Components/Table/VirtualTableBody.css @@ -0,0 +1,3 @@ +.tableBodyContainer { + position: relative; +} diff --git a/frontend/src/Components/Table/VirtualTableBody.js b/frontend/src/Components/Table/VirtualTableBody.js new file mode 100644 index 000000000..de88bd03c --- /dev/null +++ b/frontend/src/Components/Table/VirtualTableBody.js @@ -0,0 +1,40 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { Grid } from 'react-virtualized'; +import styles from './VirtualTableBody.css'; + +class VirtualTableBody extends Component { + + // + // Render + + render() { + return ( + + ); + } +} + +VirtualTableBody.propTypes = { + className: PropTypes.string.isRequired +}; + +VirtualTableBody.defaultProps = { + className: styles.tableBodyContainer +}; + +export default VirtualTableBody; diff --git a/frontend/src/Components/Table/VirtualTableHeader.css b/frontend/src/Components/Table/VirtualTableHeader.css new file mode 100644 index 000000000..4b757c1f8 --- /dev/null +++ b/frontend/src/Components/Table/VirtualTableHeader.css @@ -0,0 +1,3 @@ +.header { + display: flex; +} diff --git a/frontend/src/Components/Table/VirtualTableHeader.js b/frontend/src/Components/Table/VirtualTableHeader.js new file mode 100644 index 000000000..cf6a0f47b --- /dev/null +++ b/frontend/src/Components/Table/VirtualTableHeader.js @@ -0,0 +1,17 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import styles from './VirtualTableHeader.css'; + +function VirtualTableHeader({ children }) { + return ( +
+ {children} +
+ ); +} + +VirtualTableHeader.propTypes = { + children: PropTypes.node +}; + +export default VirtualTableHeader; diff --git a/frontend/src/Components/Table/VirtualTableHeaderCell.css b/frontend/src/Components/Table/VirtualTableHeaderCell.css new file mode 100644 index 000000000..c2c4f58c8 --- /dev/null +++ b/frontend/src/Components/Table/VirtualTableHeaderCell.css @@ -0,0 +1,16 @@ +.headerCell { + padding: 8px; + border: none !important; + text-align: left; + font-weight: bold; +} + +.sortIcon { + margin-left: 10px; +} + +@media only screen and (max-width: $breakpointSmall) { + .headerCell { + white-space: nowrap; + } +} diff --git a/frontend/src/Components/Table/VirtualTableHeaderCell.js b/frontend/src/Components/Table/VirtualTableHeaderCell.js new file mode 100644 index 000000000..bf51062e9 --- /dev/null +++ b/frontend/src/Components/Table/VirtualTableHeaderCell.js @@ -0,0 +1,107 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { icons, sortDirections } from 'Helpers/Props'; +import Link from 'Components/Link/Link'; +import Icon from 'Components/Icon'; +import styles from './VirtualTableHeaderCell.css'; + +export function headerRenderer(headerProps) { + const { + columnData = {}, + dataKey, + label + } = headerProps; + + return ( + + {label} + + ); +} + +class VirtualTableHeaderCell extends Component { + + // + // Listeners + + onPress = () => { + const { + name, + fixedSortDirection + } = this.props; + + if (fixedSortDirection) { + this.props.onSortPress(name, fixedSortDirection); + } else { + this.props.onSortPress(name); + } + } + + // + // Render + + render() { + const { + className, + name, + isSortable, + sortKey, + sortDirection, + fixedSortDirection, + children, + onSortPress, + ...otherProps + } = this.props; + + const isSorting = isSortable && sortKey === name; + const sortIcon = sortDirection === sortDirections.ASCENDING ? + icons.SORT_ASCENDING : + icons.SORT_DESCENDING; + + return ( + isSortable ? + + {children} + + { + isSorting && + + } + : + +
+ {children} +
+ ); + } +} + +VirtualTableHeaderCell.propTypes = { + className: PropTypes.string, + name: PropTypes.string.isRequired, + label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), + isSortable: PropTypes.bool, + sortKey: PropTypes.string, + fixedSortDirection: PropTypes.string, + sortDirection: PropTypes.string, + children: PropTypes.node, + onSortPress: PropTypes.func +}; + +VirtualTableHeaderCell.defaultProps = { + className: styles.headerCell, + isSortable: false +}; + +export default VirtualTableHeaderCell; diff --git a/frontend/src/Components/Table/VirtualTableRow.css b/frontend/src/Components/Table/VirtualTableRow.css new file mode 100644 index 000000000..f4c825b64 --- /dev/null +++ b/frontend/src/Components/Table/VirtualTableRow.css @@ -0,0 +1,14 @@ +.row { + display: flex; + transition: background-color 500ms; + + &:hover { + background-color: #fafbfc; + } +} + +@media only screen and (max-width: $breakpointMedium) { + .row { + overflow-x: visible !important; + } +} diff --git a/frontend/src/Components/Table/VirtualTableRow.js b/frontend/src/Components/Table/VirtualTableRow.js new file mode 100644 index 000000000..0a423902e --- /dev/null +++ b/frontend/src/Components/Table/VirtualTableRow.js @@ -0,0 +1,34 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import styles from './VirtualTableRow.css'; + +function VirtualTableRow(props) { + const { + className, + children, + style, + ...otherProps + } = props; + + return ( +
+ {children} +
+ ); +} + +VirtualTableRow.propTypes = { + className: PropTypes.string.isRequired, + style: PropTypes.object.isRequired, + children: PropTypes.node +}; + +VirtualTableRow.defaultProps = { + className: styles.row +}; + +export default VirtualTableRow; diff --git a/frontend/src/Components/Table/VirtualTableSelectAllHeaderCell.css b/frontend/src/Components/Table/VirtualTableSelectAllHeaderCell.css new file mode 100644 index 000000000..1f3f7fb30 --- /dev/null +++ b/frontend/src/Components/Table/VirtualTableSelectAllHeaderCell.css @@ -0,0 +1,11 @@ +.selectAllHeaderCell { + composes: headerCell from 'Components/Table/TableHeaderCell.css'; + + flex: 0 0 36px; +} + +.input { + composes: input from 'Components/Form/CheckInput.css'; + + margin: 0; +} diff --git a/frontend/src/Components/Table/VirtualTableSelectAllHeaderCell.js b/frontend/src/Components/Table/VirtualTableSelectAllHeaderCell.js new file mode 100644 index 000000000..58b246763 --- /dev/null +++ b/frontend/src/Components/Table/VirtualTableSelectAllHeaderCell.js @@ -0,0 +1,47 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import CheckInput from 'Components/Form/CheckInput'; +import VirtualTableHeaderCell from './VirtualTableHeaderCell'; +import styles from './VirtualTableSelectAllHeaderCell.css'; + +function getValue(allSelected, allUnselected) { + if (allSelected) { + return true; + } else if (allUnselected) { + return false; + } + + return null; +} + +function VirtualTableSelectAllHeaderCell(props) { + const { + allSelected, + allUnselected, + onSelectAllChange + } = props; + + const value = getValue(allSelected, allUnselected); + + return ( + + + + ); +} + +VirtualTableSelectAllHeaderCell.propTypes = { + allSelected: PropTypes.bool.isRequired, + allUnselected: PropTypes.bool.isRequired, + onSelectAllChange: PropTypes.func.isRequired +}; + +export default VirtualTableSelectAllHeaderCell; diff --git a/frontend/src/Components/TagList.css b/frontend/src/Components/TagList.css new file mode 100644 index 000000000..c1e5567bd --- /dev/null +++ b/frontend/src/Components/TagList.css @@ -0,0 +1,3 @@ +.tags { + flex: 1 0 auto; +} diff --git a/frontend/src/Components/TagList.js b/frontend/src/Components/TagList.js new file mode 100644 index 000000000..485651bdc --- /dev/null +++ b/frontend/src/Components/TagList.js @@ -0,0 +1,38 @@ +import _ from 'lodash'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { kinds } from 'Helpers/Props'; +import Label from './Label'; +import styles from './TagList.css'; + +function TagList({ tags, tagList }) { + return ( +
+ { + tags.map((t) => { + const tag = _.find(tagList, { id: t }); + + if (!tag) { + return null; + } + + return ( + + ); + }) + } +
+ ); +} + +TagList.propTypes = { + tags: PropTypes.arrayOf(PropTypes.number).isRequired, + tagList: PropTypes.arrayOf(PropTypes.object).isRequired +}; + +export default TagList; diff --git a/frontend/src/Components/TagListConnector.js b/frontend/src/Components/TagListConnector.js new file mode 100644 index 000000000..be7e618e3 --- /dev/null +++ b/frontend/src/Components/TagListConnector.js @@ -0,0 +1,17 @@ +import { connect } from 'react-redux'; +import { createSelector } from 'reselect'; +import createTagsSelector from 'Store/Selectors/createTagsSelector'; +import TagList from './TagList'; + +function createMapStateToProps() { + return createSelector( + createTagsSelector(), + (tagList) => { + return { + tagList + }; + } + ); +} + +export default connect(createMapStateToProps)(TagList); diff --git a/frontend/src/Components/Tooltip/Popover.css b/frontend/src/Components/Tooltip/Popover.css new file mode 100644 index 000000000..f7b87f0b9 --- /dev/null +++ b/frontend/src/Components/Tooltip/Popover.css @@ -0,0 +1,105 @@ +.tether { + z-index: 2000; +} + +.popoverContainer { + margin: 10px 15px; +} + +.popover { + position: relative; + background-color: $white; + box-shadow: 0 5px 10px $popoverShadowColor; +} + +.arrow, +.arrow::after { + position: absolute; + display: block; + width: 0; + height: 0; + border-width: 11px; + border-style: solid; + border-color: transparent; +} + +.arrow::after { + border-width: 10px; + content: ''; +} + +.top { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: $popoverArrowBorderColor; + border-bottom-width: 0; + + &::after { + bottom: 1px; + margin-left: -10px; + border-top-color: $white; + border-bottom-width: 0; + content: ' '; + } +} + +.right { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: $popoverArrowBorderColor; + border-left-width: 0; + + &::after { + bottom: -10px; + left: 1px; + border-right-color: $white; + border-left-width: 0; + content: ' '; + } +} + +.bottom { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: $popoverArrowBorderColor; + + &::after { + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: $white; + content: ' '; + } +} + +.left { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: $popoverArrowBorderColor; + + &::after { + right: 1px; + bottom: -10px; + border-right-width: 0; + border-left-color: $white; + content: ' '; + } +} + +.title { + padding: 10px 20px; + border-bottom: 1px solid $popoverTitleBorderColor; + background-color: $popoverTitleBackgroundColor; + font-size: 16px; +} + +.body { + overflow: auto; + padding: 10px; +} diff --git a/frontend/src/Components/Tooltip/Popover.js b/frontend/src/Components/Tooltip/Popover.js new file mode 100644 index 000000000..c958fce1b --- /dev/null +++ b/frontend/src/Components/Tooltip/Popover.js @@ -0,0 +1,160 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import TetherComponent from 'react-tether'; +import classNames from 'classnames'; +import isMobileUtil from 'Utilities/isMobile'; +import { tooltipPositions } from 'Helpers/Props'; +import styles from './Popover.css'; + +const baseTetherOptions = { + skipMoveElement: true, + constraints: [ + { + to: 'window', + attachment: 'together', + pin: true + } + ] +}; + +const tetherOptions = { + [tooltipPositions.TOP]: { + ...baseTetherOptions, + attachment: 'bottom center', + targetAttachment: 'top center' + }, + + [tooltipPositions.RIGHT]: { + ...baseTetherOptions, + attachment: 'middle left', + targetAttachment: 'middle right' + }, + + [tooltipPositions.BOTTOM]: { + ...baseTetherOptions, + attachment: 'top center', + targetAttachment: 'bottom center' + }, + + [tooltipPositions.LEFT]: { + ...baseTetherOptions, + attachment: 'middle right', + targetAttachment: 'middle left' + } +}; + +class Popover extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isOpen: false + }; + + this._closeTimeout = null; + } + + componentWillUnmount() { + if (this._closeTimeout) { + this._closeTimeout = clearTimeout(this._closeTimeout); + } + } + + // + // Listeners + + onClick = () => { + if (isMobileUtil()) { + this.setState({ isOpen: !this.state.isOpen }); + } + } + + onMouseEnter = () => { + if (this._closeTimeout) { + this._closeTimeout = clearTimeout(this._closeTimeout); + } + + this.setState({ isOpen: true }); + } + + onMouseLeave = () => { + this._closeTimeout = setTimeout(() => { + this.setState({ isOpen: false }); + }, 100); + } + + // + // Render + + render() { + const { + className, + anchor, + title, + body, + position + } = this.props; + + return ( + + + {anchor} + + + { + this.state.isOpen && +
+
+
+ +
+ {title} +
+ +
+ {body} +
+
+
+ } + + ); + } +} + +Popover.propTypes = { + className: PropTypes.string, + anchor: PropTypes.node.isRequired, + title: PropTypes.string.isRequired, + body: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired, + position: PropTypes.oneOf(tooltipPositions.all) +}; + +Popover.defaultProps = { + position: tooltipPositions.TOP +}; + +export default Popover; diff --git a/frontend/src/Components/Tooltip/Tooltip.css b/frontend/src/Components/Tooltip/Tooltip.css new file mode 100644 index 000000000..d1d798e0f --- /dev/null +++ b/frontend/src/Components/Tooltip/Tooltip.css @@ -0,0 +1,161 @@ +.tether { + z-index: 2000; +} + +.tooltipContainer { + margin: 10px 15px; +} + +.tooltip { + position: relative; + + &.default { + background-color: $white; + box-shadow: 0 5px 10px $popoverShadowColor; + } + + &.inverse { + background-color: $themeDarkColor; + box-shadow: 0 5px 10px $popoverShadowInverseColor; + } +} + +.arrow, +.arrow::after { + position: absolute; + display: block; + width: 0; + height: 0; + border-width: 11px; + border-style: solid; + border-color: transparent; +} + +.arrow::after { + border-width: 10px; + content: ''; +} + +.top { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + + &::after { + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + content: ' '; + + &.default { + border-top-color: $popoverArrowBorderColor; + } + + &.inverse { + border-top-color: $popoverArrowBorderInverseColor; + } + } + + &.default { + border-top-color: $popoverArrowBorderColor; + } + + &.inverse { + border-top-color: $popoverArrowBorderInverseColor; + } +} + +.right { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + + &::after { + bottom: -10px; + left: 1px; + border-left-width: 0; + content: ' '; + + &.default { + border-right-color: $popoverArrowBorderColor; + } + + &.inverse { + border-right-color: $popoverArrowBorderInverseColor; + } + } + + &.default { + border-right-color: $popoverArrowBorderColor; + } + + &.inverse { + border-right-color: $popoverArrowBorderInverseColor; + } +} + +.bottom { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + + &::after { + top: 1px; + margin-left: -10px; + border-top-width: 0; + content: ' '; + + &.default { + border-bottom-color: $popoverArrowBorderColor; + } + + &.inverse { + border-bottom-color: $popoverArrowBorderInverseColor; + } + } + + &.default { + border-bottom-color: $popoverArrowBorderColor; + } + + &.inverse { + border-bottom-color: $popoverArrowBorderInverseColor; + } +} + +.left { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + + &::after { + right: 1px; + bottom: -10px; + border-right-width: 0; + content: ' '; + + &.default { + border-left-color: $popoverArrowBorderColor; + } + + &.inverse { + border-left-color: $popoverArrowBorderInverseColor; + } + } + + &.default { + border-left-color: $popoverArrowBorderColor; + } + + &.inverse { + border-left-color: $popoverArrowBorderInverseColor; + } +} + +.body { + padding: 5px; +} diff --git a/frontend/src/Components/Tooltip/Tooltip.js b/frontend/src/Components/Tooltip/Tooltip.js new file mode 100644 index 000000000..43caf87e8 --- /dev/null +++ b/frontend/src/Components/Tooltip/Tooltip.js @@ -0,0 +1,163 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import TetherComponent from 'react-tether'; +import classNames from 'classnames'; +import isMobileUtil from 'Utilities/isMobile'; +import { kinds, tooltipPositions } from 'Helpers/Props'; +import styles from './Tooltip.css'; + +const baseTetherOptions = { + skipMoveElement: true, + constraints: [ + { + to: 'window', + attachment: 'together', + pin: true + } + ] +}; + +const tetherOptions = { + [tooltipPositions.TOP]: { + ...baseTetherOptions, + attachment: 'bottom center', + targetAttachment: 'top center' + }, + + [tooltipPositions.RIGHT]: { + ...baseTetherOptions, + attachment: 'middle left', + targetAttachment: 'middle right' + }, + + [tooltipPositions.BOTTOM]: { + ...baseTetherOptions, + attachment: 'top center', + targetAttachment: 'bottom center' + }, + + [tooltipPositions.LEFT]: { + ...baseTetherOptions, + attachment: 'middle right', + targetAttachment: 'middle left' + } +}; + +class Tooltip extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + + this.state = { + isOpen: false + }; + + this._closeTimeout = null; + } + + componentWillUnmount() { + if (this._closeTimeout) { + this._closeTimeout = clearTimeout(this._closeTimeout); + } + } + + // + // Listeners + + onClick = () => { + if (isMobileUtil()) { + this.setState({ isOpen: !this.state.isOpen }); + } + } + + onMouseEnter = () => { + if (this._closeTimeout) { + this._closeTimeout = clearTimeout(this._closeTimeout); + } + + this.setState({ isOpen: true }); + } + + onMouseLeave = () => { + this._closeTimeout = setTimeout(() => { + this.setState({ isOpen: false }); + }, 100); + } + + // + // Render + + render() { + const { + className, + anchor, + tooltip, + kind, + position + } = this.props; + + return ( + + + {anchor} + + + { + this.state.isOpen && +
+
+
+ +
+ {tooltip} +
+
+
+ } + + ); + } +} + +Tooltip.propTypes = { + className: PropTypes.string, + anchor: PropTypes.node.isRequired, + tooltip: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired, + kind: PropTypes.oneOf([kinds.DEFAULT, kinds.INVERSE]), + position: PropTypes.oneOf(tooltipPositions.all) +}; + +Tooltip.defaultProps = { + kind: kinds.DEFAULT, + position: tooltipPositions.TOP +}; + +export default Tooltip; diff --git a/frontend/src/Components/keyboardShortcuts.js b/frontend/src/Components/keyboardShortcuts.js new file mode 100644 index 000000000..109ad86e7 --- /dev/null +++ b/frontend/src/Components/keyboardShortcuts.js @@ -0,0 +1,102 @@ +import React, { Component } from 'react'; +import Mousetrap from 'mousetrap'; +import getDisplayName from 'Helpers/getDisplayName'; + +export const shortcuts = { + OPEN_KEYBOARD_SHORTCUTS_MODAL: { + key: '?', + name: 'Open This Modal' + }, + + MOVIE_SEARCH_INPUT: { + key: 's', + name: 'Focus Search Box' + }, + + SAVE_SETTINGS: { + key: 'mod+s', + name: 'Save Settings' + } +}; + +function keyboardShortcuts(WrappedComponent) { + class KeyboardShortcuts extends Component { + + // + // Lifecycle + + constructor(props, context) { + super(props, context); + this._mousetrapBindings = {}; + this._mousetrap = new Mousetrap(); + this._mousetrap.stopCallback = this.stopCallback; + } + + componentWillUnmount() { + this.unbindAllShortcuts(); + this._mousetrap = null; + } + + // + // Control + + bindShortcut = (key, callback, options = {}) => { + this._mousetrap.bind(key, callback); + this._mousetrapBindings[key] = options; + } + + unbindShortcut = (key) => { + delete this._mousetrapBindings[key]; + this._mousetrap.unbind(key); + } + + unbindAllShortcuts = () => { + const keys = Object.keys(this._mousetrapBindings); + + if (!keys.length) { + return; + } + + keys.forEach((binding) => { + this._mousetrap.unbind(binding); + }); + + this._mousetrapBindings = {}; + } + + stopCallback = (event, element, combo) => { + const binding = this._mousetrapBindings[combo]; + + if (!binding || binding.isGlobal) { + return false; + } + + return ( + element.tagName === 'INPUT' || + element.tagName === 'SELECT' || + element.tagName === 'TEXTAREA' || + (element.contentEditable && element.contentEditable === 'true') + ); + } + + // + // Render + + render() { + return ( + + ); + } + } + + KeyboardShortcuts.displayName = `KeyboardShortcut(${getDisplayName(WrappedComponent)})`; + KeyboardShortcuts.WrappedComponent = WrappedComponent; + + return KeyboardShortcuts; +} + +export default keyboardShortcuts; diff --git a/frontend/src/Components/withCurrentPage.js b/frontend/src/Components/withCurrentPage.js new file mode 100644 index 000000000..5e6d9ccf4 --- /dev/null +++ b/frontend/src/Components/withCurrentPage.js @@ -0,0 +1,25 @@ +import PropTypes from 'prop-types'; +import React from 'react'; + +function withCurrentPage(WrappedComponent) { + function CurrentPage(props) { + const { + history + } = props; + + return ( + + ); + } + + CurrentPage.propTypes = { + history: PropTypes.object.isRequired + }; + + return CurrentPage; +} + +export default withCurrentPage; diff --git a/frontend/src/Components/withScrollPosition.js b/frontend/src/Components/withScrollPosition.js new file mode 100644 index 000000000..110da9ab2 --- /dev/null +++ b/frontend/src/Components/withScrollPosition.js @@ -0,0 +1,30 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import scrollPositions from 'Store/scrollPositions'; + +function withScrollPosition(WrappedComponent, scrollPositionKey) { + function ScrollPosition(props) { + const { + history + } = props; + + const scrollTop = history.action === 'POP' ? + scrollPositions[scrollPositionKey] : + 0; + + return ( + + ); + } + + ScrollPosition.propTypes = { + history: PropTypes.object.isRequired + }; + + return ScrollPosition; +} + +export default withScrollPosition; diff --git a/frontend/src/Content/Fonts/Roboto-Light.ttf b/frontend/src/Content/Fonts/Roboto-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..94c6bcc67e09602f6d90ac10f449b5c05c2f7021 GIT binary patch literal 162420 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 z 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 literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Fonts/Roboto-Light.woff b/frontend/src/Content/Fonts/Roboto-Light.woff new file mode 100644 index 0000000000000000000000000000000000000000..ec6bf5749e52ad1cf959fc5129672b44f2f6d1ab GIT binary patch literal 89300 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 z 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%0Dh+`o+a49c{bs_0^sWpgeA?4;$ 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 MLV_d_fRm8?ABWrtUjP6A literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Fonts/Roboto-Light.woff2 b/frontend/src/Content/Fonts/Roboto-Light.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..2882017887433f9a4e4e621c60187d8a96f6d355 GIT binary patch literal 62832 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

Z=XtEWT1KTfsvcBh(5e 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 literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Fonts/Roboto-Regular.ttf b/frontend/src/Content/Fonts/Roboto-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8c082c8de090865264d37594e396c4d6c0099fe4 GIT binary patch literal 162876 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 literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Fonts/Roboto-Regular.woff b/frontend/src/Content/Fonts/Roboto-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..464d206236bfe401e3d9f5f3849c68d4e347bbbc GIT binary patch literal 89732 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

-jC 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

imCl?nAg7CQ)=23ee*SK&-grQ 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⩔(V3B$#|xuSp(J4ReX@mv(MW~Ja0|$yoE4k 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 literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Images/Icons/android-chrome-512x512.png b/frontend/src/Content/Images/Icons/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..a9a9e924df68aa21bee491d2e0a08d3929aa4bc1 GIT binary patch literal 51650 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 bS9lFNpdj+NkQPh@UICJqRgtNXhJ^kfP*X+G literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Images/Icons/browserconfig.xml b/frontend/src/Content/Images/Icons/browserconfig.xml new file mode 100644 index 000000000..993924968 --- /dev/null +++ b/frontend/src/Content/Images/Icons/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #00ccff + + + diff --git a/frontend/src/Content/Images/Icons/favicon-16x16.png b/frontend/src/Content/Images/Icons/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..40d6cc24c3b489ed2d852885d2d82d55fdb1bf2c GIT binary patch literal 1392 zcma)4dr(wm6#sZGuo230LD7X}-}mm`*FM-~Az+C`9wCxK4Kq9h29iKn6GV&f6*g+o z;FPRXmJ?w*Au~*1Gx3yQHwG26jG<8kc?cFbl8@$g*0pB(qnYlU`+fJE^E>Bv&bg-{ zJuT7OE5r*SMTRam+=Ml5k!^LWS3?OAnCLn}wG^K=zvC3W5 zawSQs^}G!NmYpcCd_xx}oXIPus<+MJQQ}Gh)nM08mqEy&aD;>`FA-N7`k8VXx^zC3;|VPy_5)Du68+ zp27&WpJE3i2`19vCDl3yMkuG*xu|EU`Wbdmr=YbsrB=`yB@^kuh%kno(fv)QVOLWz z$^h*E9SHmd2P{HPu`^LDBpHD2VxY%o6f&jOU~gQiVAzp(oYF!K&<@CO?G_5tjG+?kWXE|Z-9q=$bAo?c|05EE(0b=2V4PpBTmSsoN2JQRTWzI;mFW~=q zMAfx~Q`q3#>dk6i**(*?kteonZo^%1K-J{KuMMv6EK2>IBaXc7-#oQePg`c zE0j-DItOpLzu;%l>x52Pcwpq1lTs5nx41!W3TifIJR3}Gk})=uceNllH}m?~ z_?4pkL(cAjp*eQ;2Iz2VD`x(=RcQgJz1b(b&wc4GrIA7vp7Y+@q=1&| zi|>q1e7pD4`o7co?l&8+Tv$GGN-sa#mQY%{FduAO7t(z4)mQfaazn4X*j+ooGuA$S zBu=p~*?ULEORjQ@O@wLGqJFogbKKIka{rDpOY(z_-_cs$ez)<=iNJ2_3G49wCl~Uk z+pfK4S%3ZfmULHrPEyUEhmI~atIxK^8HT>2mUgyw`S z^Y%P*p{}5^5H3U!q!uShoT4)cm5x#CR0OQAjvyx382VoUW#!vTifaBl;N0oM$01wfvmN&aD#3$V*mR(sTxL5pWd+Tt9(d z@(2Ddetcsc)4$zC(2>cv{xtsmfNfy?0LNNq`ec&=%?GVDFUP5xfC42Yq#4i0<<|cN Dj@rlQ literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Images/Icons/favicon-32x32.png b/frontend/src/Content/Images/Icons/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..a05042842f6b5283c7f1ff323a3a00c05110c078 GIT binary patch literal 2670 zcmZ`*dpHw(8~&|fV>wr(n8Ta%VT9y3H5r*0pHRXpiI=u9$4PTe7)nm5R1QhzlafSv z(@e&Y974p>F!nk|PQCi``{TQw>wfO*x}WR5oO?m+0z)3zA!>vxqjSKQiFgo#*>FaQwJzX1V7#j?91jBJOqflVT01a%Fjy*_yW z0N=2~Si8EnR_9a5uKoMl-iEQSb~)U%Gl-_zm7NfD5Qf)3MBC)33tUgop}UnK($QDl z7%(?2ul~m2juZZ`o?b@#X$?Po=hn}r`nDczs9RgNl2 z^4>9b2yBbBxVNiUDfcO`^%Kp@{D^%A#F?GP!!nU~*KQ>Ua~*ZH?|Aq^TA%3a;mk+`YU-VVd!GOE z`uedDGxlA~w?of!^v}Ww_|TgDZjZ`gVJpQl zIhO3L@<83S0RJzJrL$?5Wzoq%7E+E6YT`83jSQO^l#&n8kRh{gE=?%Uji1}>0!tz( zC29wd!y_XU8OfzWidMbHBZ_nq;Qp!(gEJP+Mcll}XaItd4S5 z&Y9jeH_IlB$Fg*y0(f~fux#n}R9+(k-*E)Q0;$IGY8On1d^OX_^va2~b&{XeG(5#v zS`x2#0c2cHvDaYTYHsF);|K_$lR6dq@6(I2V&i7P&*YPk612t(32MIn03t=R%=O&k z=Kc2-ER(V#`hC_5RT874ONnS-##n3MHndGvk*BO%xAeXQ0A;n(cPA)u1 z^cHS`v~X5ic&pUfHxGO=gztA(P|OEPy3FbcjE}sysXgmw6(t(l{5%kbxH+GUSD+-f zqc&u7c?n165Y*X5Xr)#$&E zpQ$<8XP8XqQFCCUIFKm*%`w^Gsjb1fVeXdx550XgI$81hDZy{wl2)dj*DkKd)`_01 znal{UK%3JzTZRf*gy5i{9Sihl>5B6vvL(j~G0%?8NaZ-J0&X#aeK7m7Py*p-wtcU& zYWpiW%?p_r&PgKWl+*gv;O$2;*Up`-BzuipklV8v3N>r?xIW{fZF8>IzNv*!qW}09 zO|Xu86F0F^s0Q427JzZ#TmyJN+`NA5Oibh-+KsKGoPi{uQ2KfZQVGDXzP!t?Cwu)E{;jYbSJ_ZKgVmATS5 zCNfAu2*YBndKx;N#*j#7l;S&Zwmu$tbe?I+CS+o&Mdq+@yqj#iQC!jJDd!QV4Z8yBY3dcwy7{RO|W7ObHl%Rd4BsZaVe z6vZT=G1NRkY8Z9qmu*1{M!sQD_W4s$qO!Aq?jAFasg?RA;5EkAoyvSCU4@*1UXKWewzR+tn4Dhu5usv7kO3h-gE~B?&fM;aJ;SLB(NXu> zW4x#n96KMWE`LpzW_T=sX2ETW?xjyx)3unwN)a{Wc*)x@e~D{?**nq^EbQ%!I|H8`e#?)Uq-k=RaoK!e>yKu zGN-W7`DMtRe*Whw%h+opX&OC-qD4I$ObP5NHJ3Uf*x)=c2z7{`x$_{J+p6g)a)s|# zmZcTJ7V6yo+}%4cK*K1LF1ds)cercsJmZ+u^-X5fmOkL=#jTIkU+?Bx^ddn|f4`{2 zsx3gNCP{2tpv6)%kb4%)4S%Kox3#jE&^8~b%halId(_;l^73iZWY9=GAs2t|I1yv0 z^y5(ZPi)+Uv2+(*%~sm{IT&<(+e6U?D|Q_{Xo%AgCQ2(Rq&gE}&pQ?1dbMc;$U2Fvd?(YmZj*h4CUUv-+3X4H5cJ2IvProst9UW#}71 z7%)VGYV03MTE$jJR@8Jg&WY@k*>=KavO+8OB9w1pzLj@FG>*8~iw-wko)LX~eogzt#6nN`_ebf6nHRLnH2KII zZ}hnG<$?6hZbUGjKV#=seO1KU#22<7Mh$+8j7ML&8K&T9ah;;glBj&?x5~SN+8MPo z8C|HXA$JydV;*_+f4CURK$Dc-`?8*0VRdyC%49LCPP0w5UM(liduxn|J2_>iLSdGC zBU~LG-YY^quVD?!z3{Y-fF}Yizcc4brD4i=ja-Sf!YRFiY`{m>9I3~%>gjVNZe_T^XSAbxE zTOOMWzGkyMk+S;8HZ!B2Kf0L7I1>uMrOtclO-;ZoYT=gDNWIp14W?vHPm+m`=Rk_a zEw~HE9>c30C0HtrDqpz=HaMTrLWNK(^YJ}24>6@ZZqra?<{*NJqa53;w z^#3HEGo9dUKh;DNRpRM7~S4o O0qkrXG4vBY3I77lhudEO literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Images/Icons/favicon.ico b/frontend/src/Content/Images/Icons/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..73ba8d1baa3c082f88d87539480ae9e3412f3fd2 GIT binary patch literal 15086 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 Pz5*aGt0Ge^Wfby1(NpI> literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Images/Icons/mstile-150x150.png b/frontend/src/Content/Images/Icons/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..261955fcb3b421d97c31f237a9e6bd9f0f9ac5f5 GIT binary patch literal 9680 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 Y*(b(zKa=1|da{_jw2D-j#HYaj1E%wIL;wH) literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Images/Icons/mstile-310x150.png b/frontend/src/Content/Images/Icons/mstile-310x150.png new file mode 100644 index 0000000000000000000000000000000000000000..6d8e7afe3919ea06f500c8ebc09a382ae2f17bc6 GIT binary patch literal 10338 zcmdUVX*`r|`1S}96|y}dq_Sqop0zN^o_*g%_H`_S8I`gXkBIEq8H{9KCkfd@491Xb zF_^4_G2^}G`TyPz?}zvM`|@GN_}$li-q&@U$9Wv*ISEe;wXZN-X8?gfS9Bh0nSekS zBtRgltMnIvPmou0Lx2|=kB0^iL7=)6#xrMH;BS7{$0i0K5L6HZiirh*PJxeN{(wLb zDG+GW2?SF500MCa?}_MKA{WIF#yy3X5^%mkSVZP83TcY zsCBd+nuX78W5aSy%@_K2gC_-LvN9@%K_(@f>?|SMFN*k`Y{lA&K7V!5{Kn3>+17?c z(kBW}(9oEfX=Oj<)Y8)WCo$$=!P!fCqm_`q&h#w~B0f-J|979vDt(`jixx}6=k6(M z0C)fY=0`~Q&J+`fA6Ak+IDb+ww{Y%Mwt-=PT2%4zfnDT?`R~tq?KGH1-{SJq6A-@z z4d*YKCYN5_$%ZfwHvCL$y}{cdNcMFLTkkel;@EmUkpy$Dv(j=e(^SaP*RJNkC0ADu zzok7n@y?M`hF~Upc=yXrPpJ59C<`6bW@@`fHM)70Z)RuXIvxBoAMnpunNNk-pRek$ zgNo20sD@gzd%ey`h?@k$5fu`isV8Bh_@^sUqjE<9bjH?A zE7hVWfeUoBNR~&Nog|EZm-`9*1KlhW5(q>_7xg+?%lj|v zS!NDJdrD`-!4i--!OS77^Ewji53Aq8Y@qGnlfABe2A@ixQJ^zeof*wPKg`kC@ROr$ z<%KIWFIy{N8OyWVN1I#K)sCKo=*^^NBaaENfu3WqpvR zvg#hvS+W0`uqL|b{v5b)FJZeajIDgSIi>Q5pc2T6T6Ad zjt-Z2ByRe#gTHi^o1fq4;P0ZZ=wXhb85NHOOOB*c4f>^@5LH`UE&?;_)wq2XUVrr7 z-X0^SV4-mBHMjp z9lLX4#1s-SR>yRhkyFB}>-O@O*rO>GVh4CJFfJ$#uO?bo)1sjA&9 zErs$><#v1sq`G_?leOrF?;`blT?$z9f4`e)LLb*tS8I=%CJA+%oHi|=`yW-OthC`R zEcK&_+miCW3w!U=r4@LtDojAI9C(ju2zGP-1k+}>v*6ujYa33c<@9wVU^h3-Qtrg0 zvC06b2*HgL^RbafU1gpqRnJ1>iK{VtfbTD(eVD z_P=Ql6N?_l-Es|fc3%3!F_L4zO&T1c`3Dr(8~E%Ce-sSWI=$S=|L%vtxA9K#kssS z%y=k!zcFIymUi-dm6r|lc5SoO-JSXQ+$eg|;VPD3o8OBrji(F@dqOotKgdrRiGJIL zfagt5Ctu%)_UnWskF8^>ai3EWh{NCZ=V0AR8qLDrb8~Y$L;~N|Ox@&c9Ps87q25S+ zoK>+JWGGDmw6lDUp1>9H#3Fi;Qu>R_Ve3mtW9m3EK`6K^R0%iiaJb2?z8T=QB_*<} z9{$hOs%gaLrdShx=A>JjZ!Cgzn&a=wO;4k^M9(ikSuWMmD#}`ztxakIoiifnSk`l| zQX@HQ$ZeWprx}sMT zSM$T0sei3}eZ%O)%$s7V70lX@ZW61p6swX{Bpfuiaw*5Jg*?|ilB3Yx_UYpzZ$1knjT2P-YhkH(d|@;vBxZbPu-hT zD%g*EsTp?_tBxzq+JaO4b)?{mEmMB0$kT?c8@!t}yrx5Uv~6e=aDNSVCuz#pR^GR5 zCk38+gP!Kdt8GEceCkEG|F0Zihq|k0@6n@m6JaD&()ov*+M0mYMuPgVj2HB7A zG|1dljXYfFikdZX{Cs-pOUr+#_xV|(C-u)8#g@k+(FlYgLR3As;aAXbw)s;zQ$Ztg z5PAp8Xl~wEiI|gRq1^&FsH=Z@!^XiO@F7t~$qXB$SAb38j4l*xM}gkF9BGYtXeB=V z$HBj`tkHK;X{Y{1YTI!U;{n%Xd3D#>XFa;yxrTu&5fP)YY@a4&M@;NZgLm>(Bg@Gi z-JGocEvrTzl2*sG@DM7LY1A>*%V%@d5u7Rg+~aSO(oJTzLuZ?ObC@imh$EwBYJ?(5 zj%UCI&cF`k&?6RdkgA`Dra*l2j58Z;e)~kyww)YuL2S@stpL6R#!Mrv?b8Oks2{7n z0FJx7>Dg58cBpoTnOmdH)H`VJq~-gX$DRTA-FurCV?%wg9Zep!3&9#oPg;@QBWC81 zzV^IN2qhHIY*L> zotZ4DeM;;Ki(Rs{dDDEoH*vbuQPTd%T9{`-*4(>nV^`cssMJiO@QJf;&HCO;Iwr`@ zk2=%d8(|BLVcl>wv}6i`LVz6HXK;H_ZREF^ci$p6H0E zuiDRzzzY?{*?9X=+&HNpC!WefNQQ4)@a%`!kaiau$;U} znypsK8{ObWIeJuZWiF49!!x=(drmtQuu=Q-0g4@l=);KstGAI<%Kt-gTvGtWop(AF z7UN2>O*IbY7CD<_>UedsG}YxIMB5y@`2hSTSeOlSCn*TGf36&%>&B9EctMJ{3 zbD?0h(~6#raz}dGx4 zju;>8vDkrLDu(}k0%-_ir**X#-NX9{dZA&$@~TkO87u%+L{#(}_BLl!&mlmGN4}A4 z?Cffp`T4L13CmZ0CJMv?!lSwU=#70lp`+DlsVEHU7};~@miF7^o$C9b9*UB1uD1ru zI{r3cC`8SvpbpO*}fLZBm9#xo->&9*nm*MDJv!E_H_ci2H9SJP4W!(Q?vMLF z3VW#KedZMj?}nf%D!=mS5?N;@K?&dhs>@&9>%sSz1;C1I$u-6!VzED7F{?L-^>7K8 zMdbb6&b@PWjQ1vbeq40n)e3BLw~#5$eJpo3V%^XK8xH7J_~^i>!&CX3WvCcHq{mU@ zGPILe=?a{ok&8d&D4c4pLeWT$!a25@EgUMkz3Cnd~ zOqjl1%d_2d?^@JJ2Nxdx;YZdT(C+&ms1lGC61S>K+{U2bxn*EGO>rmroJcD3Ru%dnq-OBmU{sP-=Y&#);5P{&P ze(v;8U{0qQBNmj`YPy-3kqislEV+@e!x=MkZy9(j@j)(5u(5vY{rjHxA3Ca+N&K`f~g`oS!7Ejns;W-p%!_w~5~M z>*u3q<53DZ?tYsiKZZI;%qOTy9WS*w8iV+|C|qk*GoB~<+2(E&AeY$tepc`@YiNbj z*dpXvkgXatM_rOv$0AITJChH2!zBw*niuDzGnIn-4(?bUwft`Cd&`Yo3t5w>v$}ha zxAat}xx}o)!G9>4NI-RT_^hUPkxrWp+zLS7UQ}X$gpLtl#yjkzN3)>)!;Qil0_Q4JUyg)`m`4XFo{=2V&Y)F zH#%B zxp{TNsoGg2N%gc-oi|6VnI7I7Cs?o9`dN2xpZmm&`W+UPCqh0faD6G*0y zzRN|kI)2$1N4=)xoi$odqH8Jr^%eZ+K!OpKvPfwK0qyFx;=EeOHX$IulEIX z%zxn`i*Epn0B?C>QN^-}rHR6&sY&Bw!drH^#SS4$hed;(>v?}Kg!-f8{FWhTJGqLd z`|g&U92}z!({(X)2>Yn0CFPJE~LB0AX~O;WMkOgMLwtax-4Ms7x^ks9{4V?cM4V@ z*d@Rn$G2?-CY-$MeI~lzm&7~FQJC2EwLKa+b42i14TJmT{t-L}Hj=cjP7VMPfV{MM z@k)`TQ#r2fZ+HjR0eZsjmwwUY&3_qX5vM9~Z>)s|XB8u1(GLXY^Fhec4pIwLp=%5? zoljbSO|}+~sVu({!?AO!7qB=}wHLeIP>UuJxU)-~K7n}RfMvebl@>j7iM@vNP|VT; ztFQN82qiwEx17~)-Ah3ah{KJdsM_ml@liWjLUE0rlWmrP#^cHsRjZbCK+l1N;nf}! z-~9>cM(T?(l$d}9gwpc0rOWXHZr4V#^K2x`9+kT5o|=r0smFmUb{Jp532eqEy>6|W zW&11SuxmD7c3$j{O)lmsc}|tuOYER4jElPgW`6D%*@?tu0G$$nDNWk51xnGaKvwR0 zW^*Kmv_59hu&S}})_*(4J;iElzx}}ps;C)TMHY@~SK}ZGcHTwLFG!EmZso)F0vCnq zJ(4|Vi@*i*xw&#ES+a>Pph0`gm{|TsY6I2EWhBhozVM0g?{|kL-t;(RPfi2beoHIiw&GAQ)XoSv(7cH%g|#7tRa zbEh9w!n!Rmq<>p_RWVINSWx8dYz`P&+%16bSQzB;A2DUS zBQmMU*QMa=Nt$?0m-?d#|V*Ugz?@x^1##;@f3>jGrk&DkI*&HK@3&AQ}Q_Y8%4 zkq=*!D>X4W`RZEl+Pvbtc?o@GSw(!3KCI35 z;3P;e^3AT9iT#I(j<4Cu+B4kAY*&aGA`$CC5S@ySB8}Gb?wi|XC?fe60)fC?=yu9r z)(BV0&j5t=wpeWV)-l?{&CO?UbW~z!Y%C}9toy=WQ%b*L30ZRmf#8_(oBbfRzNvFr zq95-nvI8j(Iz9GJyJ2&>7!2>s@$X!&!z=h?NB;d$*wwF*#H_9P5n~@Yd4qKE3>~di zdgm}%R%tbT$$ZGAoU~EI~G>P|2@Fyr5k+)~x$Su}%daWX+n5L(pN?zGV>hK1UM1c#>AEW`@ zpHOyi)d`jmiqpE7W;S-+;BDO zrrVqHcQDeWS5oDCEYoKL=ctrBt%p`?(R-BeC8rg6xByIQ^Vr44Z=0nm9ytHrY$*xnOJdfTSN+>1DA^@j z1UH9_+<5-rqws|58aW2l``7Z(D*a8-G}15##!X>+{WwiCOLOf*nQV?8tp_h*9Ch1# zvl@{8TGm7`d&XAjR|jd0mHhpzi4`>z^D?Wfi#k3*=sd%=2|Duj>C>tmLU^YyAeoNI z-Xf(xAX)gs@L*bC-P@EM$jZ9vEUg{Jqf~YwBymJ^n9EuNa*1Wvk|^1UP9a)7N~&&} ze4jCPJDP9EHf^zK4Fa*VWKGo!Q`65WK*wf&j)1ga6+)37Kp-O{&mZtB zzb0H0OdD7p9w~KTbb3O8GEefG;$}@f5v^FEBo_vWZp}L1QMp;zO#g&aNd??C%OpT& zf>1Yq{;LO!g&uTub`-gMMB}`9Mj)5ewSk6q{ak4NG|<2N42ULa%7U=V62?D%TD=%r zYNO@sEn?7{Hc7RR)=)hE+oP6|pmU?j*+|vZu|5?0ekend?{`qEvS+q?az8O!Ul8bU z*Zo>}PD+DrgJQl@%E|W-H-4XFx*qE zbd?PwmzPyeE^M^?N&+)Yx7c-R7Jj;wk1xo`Xc89^igY(orsWrbxXWd5 zW&U8f>2_PamfpFEucrUqxZ9fvzn@oczB|Xl2#!16$9vz6sRzYGcj##@+^LgbB&GMd zTtZ8VbIC-mz46t-^TfncBK%7vd0Cmi96!_7kF@(~b2Ih`m*bhd*l!XPon`VBeTr9@f70Z2Na9T?2a0B(`mSr8l^f8?#H{CHPezQ^M|DFvskEL`ioLRo+F#n2 z-PzA{$^C40iIGa*mRb!9r{mA>TOT+QtwzcEo_h~~L($Kco|2B->DWhEHH62vHywQr zQ1nR(<2GRc%<0QJhnog%D@Ba?{~XOcF)~rU#P9V#=Y1Klo=;_+Z*p za8JiM)JJDkjYFg~2#tk%-gBNvk3>{?`(2^AFiO*KbJ)FpcsRsITwH`JFm&C}^tI{{ zz4piFtRPDE%;)kL+u{>30`eyp~zPt7?NTBu*wm>6z z=Pk(@jw_p_Yh=CQoPhZ97GkA9TIUb&z5`%CvrW0JnJ z^TWcS)h33UMRVM@VwnZ(qGek?Oq_kqChm?$-&M#E0cQ#U>66r>T_R52#Q8Z!olN!k zH4}kugio^jz+DrIsww>NNZw-0xX3NPu8q^Doye`!gRTqlz`#W+-p&Ilr5(Xzqw5*e zj)f3kXCl~|&hC88y{EmBuj=S|>cl@wvV0O5p4Xs;0@^Z4PY1OJ^X-OP+l&=6*V={=@?EfdQQD_)hJ6*VhT&gEJTSd z*RWhFXLx+RPFU7}_5J%k6w@c5s%9I6dk=mY92~@)J%0c=YpE=KX=O3*XlLi{?~_K} z=iTZBk$tK_FT*VC#)I7dl7DQ7=-dZRJQtxSFoqa#0xdK%^;1dcN}cm41c$=c2Tg58 zb~-rf*{6_y9{C%yflDykbbEXIf(>5dE@vOcYqw6^Mzt$6tPow_ zYzt_8!)f;jb#MA;7Ii*(m?X)`6xi-9X=W~W6XiWIG11Z5dcXd9UeMroWq*_}AbTYf z;L;bIgelMGaDCV7Q_<(o0@(%QvIb`VJgXGuxhfV$K9SsB$l4`;+}zB@z3g_f5SXj` zFya+zc%*P;6U`TBxNcZ*2KoN-`G)Dc$aL-pUjIQu@;hf)jUd-ZP$CisINb8n@mI_m zK$ki7-44)7DK7dP6a&!hhxp|YfbZSim6|wL)>FJD+YTF2dmJlr@84>*yasywpT6`6 zQ_{QZ=)f^W(#$SP7)1OWZBg0%DZ>SfZ!q3Kr(AR1kB|inVXhe;PWv@mt^mC#-%zhf zw9uRAXx#d~M|r~{$b`}-{zeN|)b7|_3un3f$f45_4KX$~O?$Ua+S)(=(2tU9o%{-R zyjqDwZUB&&d=(F$vaOoB4uJfm!TIGy$*}eY+ypFa!7vN@(an0&Od?2xQL z@pyeVC$~IJv|65mbw&2}a!;DELBWq^6_Th2!oO(qa%a@9wKpnM+tjbYYSCy5^kGZw zB|xA^%g7KoR@UEo&VKH-Eq07J;qT9(;?V@^Ct!;r$agYt0RB`<>80~M+iLk7@ixzF zrSRpEz-d}WPW!Xo%p^Vp1RZ**3L(d`T~b=wx|cgj$dUI|@!G-_PnVXK8kg~Xfm49> z&ac^DHcMY)QUKFexRL!gT;) z9s@9?KH1NU)>N3^D_1y!!8udVwr955Npkj_je$0zqGGn5P|uYL8IO@H;u8qO0RKcd zJvCl!&PTphMj_0QbXqD&=&TtV#N7a_o8&!Vm>?;d0&NW-zDcMhmm^L2_9!Q z;R8U8QLI|d;sgYEn@WZ}@d&r*1Wfj*fqUThPR+a0Lr-#3L&?hOB&Ios&|IGX zcu+?eB*f_s5G_Cfqxs7Cw+j6Rm$zrz@w*TBpE#lq3&gj|yxaalJ0O1E-+%Pi%lph6 z_cwZ@)qm|mjV5Ic62hqNrw!cZ;o`#V@9#fq_QtqxeqWNz7(3!gZQmPFI@KDI!>6DM4h(v zK7UE4TH1)a5Jc(n>fQRtNw*()ijiM3{-Cl@>M}Su;+D?*X z%%{=jCBR$f5|x(t(xG=BHL6?De%f-&HQb*tA~m-^WWHt@6Uxu#3nr@>65 z!|^lxbPe9r*f_9uY~7!CMEqx}B2xc+?j7{-5hctufR_aW!S0|l2^PDUwE6GG#oI|; zX9x_Ln(iWc8afJ$_HP1El$JhPUBBPoKBfp#b7wJT*>nw^cC;##GdFLT^3+N=ST+4_o`WTmCuSuLZaqJOvM z%N?dtXf7!C3<%)TuR@gC9CW+wu&2Xe(V-pNHR>k6EiNiduPA+EuuwA&%+EZ``1*xG zPhmjZ1F0F2e=f^1#hFJ6Yy$l4z7*i*BMeXy#D*A(?>zXbjxbeK1HsfO3qR1Uv>V^w zd`LXPpO;^^s7V}HX|}nW?IJCLKrq;&ecO<>5PPE;4;#Sy4W&woIN zmO$-5XJlr(7}jqe0$I0A%R7nBBEY@35QwrHL_#>);pD!2)l?>KI1gQ7Tnvo(TX!+M zmUg_ehf^SC56YKTCj7s29{FOLn8YO|;fls|FIBJ_< z{XxtxeqG4@w`%5&nQF1aCOax6n%mgeKwu6F?FKpWyob{*_j1_43FoP| zK^3-H~ z%D@GdP&2C#6X!7gfFOT&PoJm!ArS#j`8@+dTtT4l+~vK?^nn(_!h=Rb!#b-bAnIF; z60VG_w^;Sk*r-|gwPIv@+^BEWoAD3L{QUlH_#4kRx}liIA9W=_o182mdm3`@DZ8u# LHq=6DIKB8^oDrLJ)QI(Z-Ob1<`x&y^KBvi84VDy$qup zee}`i`?#OK;+#xivmBn;i{k_cVmu}_8K>Tn!!RJ35ga$ zLH4DV$Hc~z)jO@>k*#ev%K`6emoHJh!ZTiF&kPJS(`^g;WR~&N43Bzb{Ni8sPkxyL z*}^}$QMG$to5l7pKv)A|rxszDRoO8Xbtn8owZ&J^kg-}RbZLPCd zirmYW{z7rxF$|0}F&j8sEl-Wf)Ms9|)%E&J2!5f|Sd4Z}Qimje^No>Tb4D~DtinTK zO46I)rl!_+FFq;>BPlK2?Ca?%mp3yZywAQyJT>8w}P)Fw=rk#bQ-yLZz%MGjCQH$1yQTWdJ90ATaqRfcmq5iIhqtyHX#$kM*M#Yxu9*JP=If6euYTO0a4#8G#M6|WF z-QcSCjNpzdGI;WgsKU;|8l~{7^;Z|2klmJX_uU?8pZy#h;bY>`fVdDzzKtd73Q3`X zqGDp)aK`oZ!|lAjum_Uvn(9tYes6{yZl;8H)pd1sqYy666CbQ_x3N_gA)X7r(c~p2 z)s?UCha~A7+I14|`7A=%}uZoIGQ2cu0~D zhD(^M*?q>30X2V_1iJlwoc{2J4Bj(cTSKucIhjGJmgqo-V~^ILx^rjYdxEYbJStiT1k!lG%wCoCl<}d1=k)Y=IE3x|Cy+^Q9Z;562C zeuf#mi(d$cxp0IzF8mRba=gIo?|$>vWK}lld1k7AXCU^;Kgtmb^IvM2d_Rs+gwnNR z_Q0`mUyTxz2-fHluxtCxi*(1sYO}N3Fq*0q#>HKm$oKCvj>uNg+^QdkKF)bVnw>sv zJSKT9gER8Di%@HxJ|7cg=i!l#&t8<~NR#vQtZ#0Q#E9}p!?(gxq>rba&_A-0gi3Ln zk4e7${6ikTy*OY|-K5v(dht5PBiUw?q)s)&kjEg|r|b=C69)>lyUV^!LDlN9PM2Dm zA36D>>j?g{Y8zN2;d5oBbLeoa3+kZez+uuLh+A=ONtX?=2@UsaiVfOe! z!KQ3;(hX@=`_tV`@z`2aS|_PTT$ra!PBm=txHTZW4eL0lB3}!^7^FjuNVcHyv+q3= z**BIj0lq$mzx(^i17z@yx0TpguvjbyGxMnjeJT|*A!V4^asQ@v59b>hdwz(LPk-S2tD2UibI#BGOzvDh4!Jhfxf zVTg8f6D%Ko=`EK>$FmSRCH5R+=zIxvSel4vM@r~Yw8q^0JlE{|+1T>(zf-fb@6qlX zSOn7P)hkH|1fP3!baWHoN2rogH}i%&QYT^N-f-IJjW1tgMnek_jWCQ5wW;@FyR?WD z*$YTVivA_aBgbFa?$bWC&OIx|#SNQ^cR*A>xT`Z!Xc59A?zaAXzR(v&QDrxtIada^ z9A2%?!1x|Mk`iUv4=!F`rza&1X^4xCKJ<8Xd4AC%_Q#JORfl!oTu$~k_z4k|6f7VW z{1UtC_&FXj*G@W(x&)9jd14%Dk&C-AfnToPu&T8mTwMubYN{2GkZ7EnK2NIOz58uL z+VS1resi|h+1a`7JUl#v{u5E-Jr@xdAA`&+W`dwY^7F-xwX&0?*h^?OJ=hn{SQ~*f?rUib)a~tk z&m|9N{je|`*DOJ8HPygtXdnbRnEg#jVGo%U@js>|(e4;SJhiFHOM`94?$Zl%J!5Cz zc9DPejxQnGtthsrBh1U^V_CQN9n;@dPjjjWQpta}2-DC|1!dLxqPjYft`%20-;+0k z0zrX+PlLj3>l*EobeJTGe+F*|s1zmC>R-;+=tz-N&tlI}hE56FZQ|kUO{0u*^@{94 z|4{HS3OKg>&^7gaKiuw%4UVz>BYn2BwulaAf*&7tYU)PE#$NY$bru4^-JrkUy4qG= zt$u0s-1Ihl%ik5``po!uaofz-hI@+x*Acj0OmuScz?d-)vF;n$X!F4isW4%^AGN0e zTlyB7bOpy_qbF6ctaWw&w`j2eITE7|FBt(>^Iz`BSAht}>L_@T%b;AKz;W zE1W>JLCH50Sizlp_ukpxVQS`jl+lk-3-dii1NyL8ka+#AdBPq!N!`CW78YkEBe!aw za4E9i{O6yiDsMjS1t8~|&uWqocYBlgH%cEtC;v7XClOj(e`)ksBJQ0z|Bj5*n7(p@ z!WacR30n*g_1ZbZnR*GnWVbl|e)~oBPh+{~$~j9Rkmkg z_O5Xt&iY%J!Uu&VCFhScgA}Hel$2oK;~N8$J-?~uX)5*o{$9JVgo;W?a9bO5>Qi3- z+cX6wU?ulVy=O^Uh_B`@w^rymCuv9P4mshVhsVdcrcQEc9H@#42;M}8Qoq)#XTp@0 z=gj7mB|Elh^WcVGQS()MZCi5$&roq8`hRe&coyYrRS7Dy%B6WMuXqtfr;X z@!Q}LYSR09I90~$wRZhJa*mFU^?~;eu14ls&pC=H>yM9@K-W)KTFYYL$n~#rCMeJD znvEte^!4=Ptd48ncJ_s*k1Q>$ZZr@K1-1`LO^5;$)%NrMMx+Tt#>MtR+Lg+BC1A(( zLsffWuOaVr4Rn@Lk|VveU%v0RIH7oOZ1by)oxcM_x3J1!^2Mim6`COUw|HKC`fLt^ z`OHtEjOSc+`WpIub@#YvA|SD_vmP~0-IDtK!_FuQ+PimaY7FeZVWqnI`Y4`pb2src zr@xzFLK6NYi@`e9(M+%>a)3c;Ne|VvyuJLX)lAjOf((J#aH!W)Ur=^(aMfBEIrE0D z8O-mf#c~;IR6_eoP31%Bs(Z5&))yBS$?V;|1G^XbTrX=H88LjU(DO=DR9|CIfZ;md9)EX?b{6R_%klahp0^L`6Ds)AJO>TmtR*mR#a8x`p(z)=b}OL@Y45BqOOdJ|F_of3wQtZm2V| z`61pcGpI~;m#$&It>W?UfmZ*~*mi5pW2h0^hw6z& z=V!6GqN1@sy$?2QU2!Q;#;I~&`*YheR4()*$>jI8Yu~6IXd^=c>qMRU+xq$-wmSvX z4`6N!w3UE*?a&Q8V@Q zblW;q8<5o>J0BdAaB)dKeuR!Zc^}r!_hD$viOFqaz;k~}CO~gLjG`q+K9uw}%k$?i zlvxSQ??Mf3IG1kL+rAmWA*@vIJEKd4UDyAfXKihj3q*B(7;~~sWED#4!7UVMO4gi} z@9sjH4C`k?Yo}4l?ClIUJnjM9d%928=2kJj{(183lVFmHA^(7egk{k(TpwX$u{qL{ zB=kVs*UbFgyB8llJw20$E%{y37yzK!0?dnvOmyFfwU?GPhMvvHh}S?kN5r{F;;tLY zJ--uGVB_mwS_-A9mywmNQ<6P6J2)wQpXMu6OIR7y?_zI-)*EoqVs^&#OV2Pn$&{NdZ+kdXE%woI~yF-P?V*UgVK z5oATprUZ0l89?5-wgPz&(+yhp>ikn$XP>9^cG>9aY3*%S%(GpWCJq!0-Y{|5pD>a1 z9@_&a`4v#;jN}4{6H#f%vZx+k{qo9!%fP={Aq^OfsFJN;Kso@78|S z=s|q&^a<^jKJx8ZokJmsW9Q3R;r0hR2RmHsT=pLkC=_ zz!K4pu@mCSVtua2&d$wEUbC=tAQ=-sw3g`q*{-a4+iM_`=dQC4-E)$fV83Qc%{L1g=x{<$N^?2f%jPyXO#m>=yP0wZQ=KT7Hur zxS_+7lOUaIWXrOT3y5sBSRc*YKxMDR{n{o;Pmb-NEOgkkzMh`mDBzp!Cr{bXRFP?> zTOS=9HfPM)RF%`jAwR7sCZTGv*zHS)&GE_p%@)ORWhN%xM_(6eP2d)%G%zpY=?oas zA|oTCow;LO!f2ex!Xn6ZfHU>=Ht&y9YWAMV2!Kr1Yy><+nP1sr0(Wso+H{)ZC=}~Z zyC$jC`f)71Y3&S(o!sAx%EE5|&eF5(MAl3}e#`kDuP0?eF}xy?Iw}&mF^+`yXIrN| zV>lZ+bO0ez{PxN)2?*@=zP>U=ZUa{l1}}RcLs)&ta)5qxkoHCVFId zUtizyKF|3H1w-R3_-e+Y$DMg>O=s8}q0t)8(3iyKg#Wo0Otn}cEbJXjf88{WhuH<^ zBLyD>y{44o*53&4Tco7)q73A%ZZjpykzBEp%W0%=ZvkHRdg9N|0c^@CQZAkI;ZjEF zP@fknZNcDMP4lEH2D?m6&6KiwY@K^+N+s=guEn|G#mbE_LTTRu0&qI*HVNX%D5)1p zN@|b>tLdgrkc`N=3U%``L(p#|OI#_u#|c8WP>kHZTEBfMy?4>fIx$yv;c$DNjVVdQ zVxsZ;pFg;$$fz<<6FS*Pu6qtbE!=(0hou3a2V^g={o~O&&Iy#m@20P5oOG8>t3JS~q zp98*S=j52CMn+aH4~n{2U33bv;65c7FOcQw^S1(;!|RT8PD)t~Yf!l~Gs+{cjy#u| zvjYqh6o_5x8K<94b##h)eiZQlruwYDzM}c`0Dah&z2N^i?H>OHrJKu3W6;cm`uOE# z0vrIcT2XduaF1maDBq}nwTcJ#&(ke>i&v;2O-@^6DdKL4_b4eN-t*nBJ#V+ER&(CVV%;y*m>>_-!B^g`Un9y?V9OlpY}5%YsBIqi_E&!c-V zHB8SqIeA6|xW=ZYwHa%;wR$b#?AYm7ZJv6zdmrkt+jTOIjz0imo})jE;wCWgMCX^#Lzadsi29Nf1+E zj#iRwTiL`ri6loRCFKzuftL zcE>NIMThcsI|ftKWpJJ*WlXj?>M}07F85QzYmT+^$Txujc77#Bpro2@+C<{;_+@>X zFW)`_VE*J-wNl<_R#v7esBib3FPheZa)WAWHnr-b6`ZN1TGG+VB+kSqN6pMEG8|iR z>Gfho6qAJJ$B+5(Jxd%%r8e72O_FM|qOxr)X5BZVA|Ge5cn{N!dlU6yjy=C)XX^(^ z`=nrAn|b^u&8uCU*WFhCo+ARcwj>@4mveG(AE+oQHd(CIFg4K=)=Ba3z3qji)MUTQ zo4>&O$PHF;C_arANf}NL4;kcOj&b^E6&WA={n)GtB_gi9kd8 zgv!Mu6B7@98{&PRi}SLtbS5)&@5{BfH@&ufr<>qvfm`^pgu{gcTHUvTr=8lD)~Z5g|>KyKD^Y{VcZ zoo`;I7F*uCR&6lq_2EqE?6|_6^2mBO*1k2?x7w#=o0?4?x3IAHl#@qzGWhF7+aXrH z5IuB#TvQaFlbbu`N|d2!Cj7lZfHXDYEONZiH?*MNPUOQAxdfib{;@=0YDtZ_AJ7F*Pq3eAaQ74w z<5=|r%(OcnBTqx49zwG`z@t>L^k%b@+GGNx-C}>+cmcE9DeN&%W-`jiHP) zw0cBD0&7&~k9{6yW;wa`OE<_LG;H8Z;f5~L<&;cK`@JV*l1F%ox_cMw|I_6w?H}CX zP4>0oPdJfu(TsI=%&SH=_5zfPcPell!C8lbPO;d>a!A(v=y9d0>lBM?lDDBpGgGx1 zF&cf}eVtE#0nD@l1*MGh*|XaMHfKtzVL3W4U(V(aRaMynlBzE1k6oOLa=3QO)gwj*M0b11d!%^w>E zFJx+kw+3a<)m+68T-qJbt>znZ) zOq=Bjo1FJjL0dtZ!lZdX?*qXD5uofqC?m!-b9?lVpzojz2xF*clWu<4>rhM2;a@N* z#lg*e6H`l^G45oyM)C2h!FgdF#rMOd_?R!6P}Dt~Dept(KGdNivIl^6wVre9y zsqmi;4LLl0&IL%klV@p^f4qGwv}swJmhuSUpR(`T82y0wrcxJPMlR{ute8rfPk27H zQg79<0mp^v%DZk%dOGe}s_1_C_DxUjJM>ER1=%xT;o?G_^``kIHi6p8W9o5KT~uo~ z)zKwtbBBudo}%8zd=KrH-Ebbn_+*Zz{Mm{1Q>4Oz22)6h-MhFU)g5>ucWkI>L2I9J z318FR80|YdJ4sAcC$)PR<8uCy|F+RZO<{RCP?9X;R#7r;Bty>oD|BbcCaJUz2k*_|`adTiP&RPJ(DUU9s0 zHWJ~UvtCbNiP=+VWD|aYT=}*(Xr-EVI;(wFdT*%OC9hLmT|F;!tYve3+q(1jZ@W5g z0ybPaW%uYiP1jYxk4p(lyqmu;l8e*dvU<#GG zFdlEFd%2NT-`39lnOxb|HBnBKbeYgRJ3eS?(hNB020Eak+;@GVhLOe`3OaqBFHMycYE2n| z2NSxwJ7dHz8DksnMNkZob>hy-T@7_5k+ytA2o)IcBEFmM~RlOn(gji8g7MrtgD)`3p z5#*iqUym>1fmJmnH5Jq?JHC2?ye>P7ki6T|UamNPPVV6qVIP$?3t=TsXK(gNK||*e zE=}}wgX$u2y#)GUQ=`nm81sb!d-VPfbvRl5dZhzlxJVc3{o;jR_dlH>fp6SZRgtE? zXB%0y(?)yoFXRg(}*fMTMg-6jEu^oI(Z=OK8M=dyB%)) zNTz3|g8H_Erk-A)2N<$d6m_pe?l{+OzDc3CQlMc9kTSKR9~oqpx&gvc>9@X~m@~ji@+_`(aIgW&!isRv9ukjv!r0oUF_Y{Yl zC<=dCMj({&|MU)yU&ihX<(l=Jzv0k;=mw;o>wQWr9ih8jyTX`a_`29ym2wuZ zB9%sL@6-&M=i}q|0&^)HquTBa)&oz6VA%c?x|;FBolrr?r&w@4#X~+`;V|# z?Z0R_b|;a-m%BqhYIrjf3a3c7lIx14G-8L8cA&o86z*Puj=UoGsU#zK?T zx6X2pIvm@NKwE?l7igY9O_|bcbX(ROMHa@ksXyoSo$h&|%r9|Yy=bkNpBXh4re6Yj z%#YL6zoNqB*8KgAg+B-SzG^V{4*bimM#mhx-@Ujsh%eNnHuTuJ7Ix*>G=U$qHVLET z_nrgHEQO4gYIBa;3F#(nWFZK2*O;W7UH3BEl_Zb3IXwP@ff%9mB67J3ZZ*A5X-rFR zEH!ryxGK~b1p z@W5L_cTixzqlkymXRSI;es39T@A&Ff)*{dogeYO89)c=Sl{?P(g`uH_d^rBY-&aTv;V^=Skeb^GWI)rw~o}Kp= zK-9{!KG!w&l#2*_W>UGnR)VR)*Fo`3XN1M2ML{64Yp1p(m$+?Xkq}}i5L7KdQs|)4 zC>*)RI6h?z73u2w_!NCC$`@Ow@stJ1mngUq^?R&~LE&$D8-^?4hus`b&R5j9XHfGs zhJ1M{saxlZl05WdIWFkV>dY*JN^W5p9L$Q%I(s(6VM}>?ZvOAf|Dyrhlu=3i!CjXX zlS;%UwHFisRbQ~XB5rHRRiSTk$8d8)qY?f|F}YDTgh@Le>gsU6BA1;~K}Rvv`*@s| zHa9m{%A1dOWdh7bNpiGeCSR0*45Xovdm!SmtVnrejJLX+OsWI29E`WM`7*>A$l0Gh z`|DjN_^y4iSsVKzWk5OjK=p3-5)HT(8Lb0?ub2E%4W(`3ZYu$MJU_mzHZ@&@v#1sR z_?CDwlb+6j;Xq&*%_{UtO)8wL(RUSE5f|?fRPw7NbJfwVdWnTQMu0M|N4G1=D@3v^ z1(M=Y zIT$x>@9q{Q&i_>nxN}$M^S~`_vQ;}*XpMi0q_AR_YA9{@v77Tug%x;A^+14%ayr@f*3 zh`UVEzRpHouaAd84;Ht_ew z!Vp)ihbk^E{t473`hS8*3q>zfbW0vYJgRZB;h&7?3-i+q27;>3z|QA%ESlDVO84wY ztisOV8QXM9rmF8>b#{wCn5w>)Y1lYg)zjs(zOwoTVrWm2;2E=s$e2?>O&CWp%_E_t zk^-#x)pIhC!e|V}aPo|gu)V(>QlOa^hBc?51@XTQ;@{ihM|27UcPv?v1>rAls32Uj z!GG#7uYBeQn~XUd+t~XR?m72CO1rkdsR?s}yT~<>GU8PPkjeqTIL zX`gwugvz@MALpP=sk?LCoINH#y4jfJV*yHhk2aYkl&< zB;ZAghBHOb4-WTBaz&?MyVd)nWDQGUhjn$@O-)U-F^zRby~nAI!`J&>fSl(Up1aZg`gG%_->kl^SCZ!2J)!9Qgo59p=6BVJ-vBkf2T9f)}HrmGuICExjw zU23ad?C9rhYk|$WJi&6L_wtYLB^bEJkVCE2#srFB0>&TECeA3&qobWJddQ08of)PI zFr5A`J4l!Jq&)2VXw}InQS;9m|KkPkHJm-F798~1P9D$|sW#FAA{A#ajYaW^RY8Os zY~xfzxIZkmuef@l(e2wNFRD8zo?cw|8R=KJZ-cN@{<3C4(|h>bcJaM{rq z^I6$SHojt{8d~=bTK5hSfS)*Vy`S{$S;tjS92M|pxkFbbS3U3w~q7eUrs(M|W=8G42b2;nBAF=0IX&-OJsQl3kN` z!yfpO(Po?R%%eGY5wu@G#bz`(_FzNO0eAbsH^5lu@pw}fL%FzB@_16q?%a;W%%_w+ zN^P~Om0zIV#=sw}V7uLG#MS8CgpJT<0mHV9$%rAXG`zJ)YCepm!bFIDdG8*U|-H174tE1DzW-2&hyxXMKK{*lYbeZ_y`!T(xF_cqWcTZVU zVz@R`m&^~&%1QCv{1vKk9B%<=lMLpqMy)9&J^if6=tLf(tfM+y&d$z=&DylUoOp6X zbM4x7#!+$And!efOy4vG>E#*-Jv0@TF1r2Ag~jGUozZ@W_o*hVYjlX`w^3PzrHMk; zr^8H0cM2X(PTQktVp?-ET+zp;l@6J5ef}Mwr1Oi58wdEeib1UfE}@yu)|o~PIJM!y zv@<=$C)pc$RIq))0h=AeCtSq!*;$I*;qXx7wZ(ln+)6M(nTnFq*LCcSaCeRI@fPI2 zVCeT#Wd}rf*=Rm;%kKN(NZ4?*Vx8ELt#oXz?UTxBu7UL)b%WD{O#`1`F}x9>!m{&=cQHgTwPL$PgvXU@Il(9+Tp zs6-JB_wL+@9|c}BNw4smBD5E`%fv*0&;)6Hmf}7@a1m{NdNXAOAe3o=Pj1=>nlgL! zj+i;9(0D3=Cpew9-E96E5^J~A{c{FsY14w>xcW^C zmeO04+Jj;^4$7!-rOWh8(Sat9b2b@;tyNM@;jGpLo;41bP2xH!&$OuR!Q>*C@tj~1 z^3>4c3}HmgmC(P=n!=2Q>J549m;=VXdzlQL87_-52(4 z`Ij#<(tbBj_ghpOs1#URw_5rh>!-j^$W;clfc?AE%gtPe(9nnr_X@u+!c<(>;z<5L z%xBC2nhcxwe2!!*t4lsx+r3pC0!i5iNgg~z-=MNvX8LF+ANzAjKD8{wJ$lWmUhMt}*v5Gsbgk zXlSBnxsNM}jn_h6TYj)KF*Yz*ee8T*n+{wMV0xeXSU%j?yxIVFbbNen{)*3iXuf$x z(tYL?h)G9f)~Gt8&8b(w^)*oAwpNogQaS)hf1o?R6X*NvX9?{ay-|IGsYlk#5b!7m zR^`NjIWPi$5EC6OF$Cfg827mgIjg!CsgxWX2vF(x9}k)3_Z~3KkY5ylnVE;|?Cdmo zNIccRNvho9zkPa6M+hdRrmI4x>_1DSBJ0qE(FNaU(s!{*FtBO3bFm|?_-DYo(NFy11TID{Jo8r=1_@U^|23wpli;@H>S;DX_oxNvWsaIb>+C$wE=k6e{@ zmzMk1ShaWGMjDTvfEXty5(ezp80uI>6BCnt;Cx4iyvfD(U8) z@0!%FuR$ItDX6TOg77O_I1L9Ei0pAtRaPu~)c!8t`r;X2qr;3ZK{ncX?dvO=kz24E zHaleh_GlUN-xbA#%LPG7jHw2Eb7c>VGv)RWvFy?P}M%N(XpEh<2~PJeuftzae8_tJ6M>xCxgq* zn4noY&tXz}yBk9_bSe`>4@+mI#X3w>4qL6&Y>f6MNm_dmkv==OOinOQw8x(VnjVkkH|Gd<>`LRm#GJP`_Z|!;dwc5&{ z@BQM>VX5CVCc4W|-Y#kDnR`_%8 zot@qJ!a0xKqu_tSe=|C2H_r*17A3%3X2vfr2uvo-3VQ{M;(`&%=#9)S-)C-o?L6*< zvIqJP-SEmqotRhMP3IjDT)6afqho)ZIX|Bo^cfFN*Ui`XgO^W1@(P+t|5=k8t%7V{!obWd%<8z}_AtS7xoy@l zo=r7%#Cto^B1f{CNye%LifS}NKZ$WzLKzsQbueO7Ig zhwC(Ew9{g1ELGjE1^gaScZVi9b^@FFUdrQPA{nzX6w*RV%iHtN#ib=VqGw}09V=JN zuhv)8pt2kxuudeKVBFGrga{8ouAtcGDs}svmJx2xnyTFav)8A>&MTFSv@l0(i%FB5 z{Yem)UdT&>*TXg%$jsHOENaWg?F`)1^kiil8ylZId9v579v-gTFMhYh_`j^eN@?$1 z?iY1&ItlI`7rUGG`@>Be)Z0&nDx-7~@frB^{c8IY3KM!E`%U6TaLhbaRHV0-meygA zmi;J(G$%T8W@aV|_-bf@7W?1agdwU^i{*wr2Zt+`gDS3$?LR>Ezba(N?jJfG_j;au zWZ{=#PV~VXXPIycuWfJLJewNUKu_GzcDA=uDME`IHkS#4R0ssA%;h<3#k_)B0EawqgD_nwZP*#S<{~{T&d^eFaRRI^!^L&WzGWE=(SqCnt4_@* zg5aMCIR`T|217JoL1B@2bLP|RfFe%p)0dsCCPC17z|YUY!y`=3^`24`F+oK`6Eg{9 zGBBjH{im91%j1GG#&s{gr8ijHHVn6jv$9ScX#r-bXe#7XF8&2d=1RMXW5(kjh%>$5w%Sdzpk+ZNy4%xP z)&_3%GB0SEd<1yi$F?G}!X8NbsyR5Aq!3+E!{U{@P$6q}RHhnUciLxTu@4I?S~77C zO8g3v837?)Dhky4=^W?_;m?U?4M<&oSdUrww8^=1t0oBY=labxG2_fKZ2s3OM9}xY z_7YwfKBJ%0WybJ%aA;_&50*7m<95T9Ya2)TG>otY(`hMuPt}4}g8b`$_hh^3AnMy&@RQNrk&n(s%9)VX}{Q&!q9g zI0CJf3_`nc@;N$*7^a~JCS<_&bD9BWEn%?v;W(k8g~50E2^UYGq?`qQ7dD|J?^

;@7ltBP7}{_Gh?VR9Y5Iabg?t1}frbrXx$Uip37svs>b9_)bHx}oKOa%}{+ zh2MyBeiiMqC5{YxmR^8!BO$2A@G;6I7ucKpOI{m%^Q0UXH{a)Ki>l)Fnd$=w6>yRE zrsj(+aACjsnu#NO8i=QBqO0tY3a3=^V-M|E!#&*@_aol1A6J9d4uQyYbP@sx%R%O# zV(;a9yBo+FcA_S&zp7nw%f&=_#{9~0k$Fp|GttCB7T_*46AXG?t6l%>{F3oh)VfD&|8?{BELZ?f5g!W*d%-Z&uN=8i@#SO|v@lK? z0-)<72}OCg+R20{X4oNfZ*xC@X8h2)Fb%7xJ;i?Lxtg(I>v5;2p#KZC6S%tsmWm=4 zoIVmam*LPMfxWN<;0F?ian{y2XAJ{Y=j8_t&J$g zynHnC6;v)zoJyizE6_*Fue=Jje@ZjghDeh(&2w9WL$e!g{Pt>ltFt%u`g*2zJ3cU8 zh%t;7mi_+@vRjx=9ZhvoJ~&t(HgWrWG7VZ%fg-n+s!$(iYFsCdzgR=tfYTYVVgoiu z|GcK!#8iWeJadZg-6j|TX(~Tp2`|ALU7f(aRnTn!O)rg*=0I*&(hbG~%}gE47F+Wkh zH@O!k2O<=H6Z*}+1$Q0KT5IOhW+86Tb&UpNx#crPK!flH4A1Db@wpH6J%a~dJDam? zF0pN$4Y$e)8M$8(gsc>RzBhZuWU8fe$j*iKy&tWT%m6;uv)lbD{H(Cur^KWgTQeI|=(hg8f1a+o8 zbD2H&=d@&bTs&(0+wIhs5a|oZWumf1hT0SBbRQ3O%XE_r6%{n?wjhaaJN;i5y@Y8&pt9^43pYRx_8E*QZap?KCmQ;Z#&}&t@69>9jthQLoh_zo6O@MP#B%R2jX^kSO^GFwyKVGatBjYNL%P4udBB># zLy4fP>zpAbhK`Oz@bNnU@$$(~d*$_$Nn#w3h(Bd3A=`stV1n}`kzgZ_k+Ifc9aU(+ z?+gtc4pvE>u>FVXsrU39` z_N0h_n%S=mR48fUG?$ng%08X1>K)dij`2TG_2a}auuWa1t#z^yq6!OAoG~3d(b_;6 zpG$%oK>*O8*VFwjJh_;57+dj83UO2JRK-&Iwx zn6M(5NSFYyJ55=rvp z_5PH*VT+-*qC5`!`FSlw0)|jQtPqNT|3$`wP(n+TsLW0W zDYlX!1A##>WMN7(o}5E7Z0a<|Y7wbpP4%E@{A-gb5LfzB0#J3rFhy5qnrV!irAf{c z#Ng$nCUeL%fPdWR36_{CR--vmi9*kiTKX7I7 z3d}349fHuT3ZZTI_cBqKB2cv!#=S<}MX}|MqYZM-vM&9j8|87gTJ*x1b?CYyhs#8I z`I3fpkvt-uE~@ILmSZ z+WH&${#UT6iOW-)Od2>1(;h5E*0tR!vq5*IA4I}1^_wh+zs3skYc)s=$1ifZe3M|w z4}PDYJ(V#acY*W$anSS^iXQ;Jpc)H|RLfug+!=!l4bV)8Ab$Z(?~k9|j;^b=sAJ>X z*8D852M_d)j?xG%wFxf`GE&EY!)2r@V6sjXS7!^^a)~?Dw|HB9D`-krCiQr z8#|RvyC`bUn!$VLE918s?L1WOD&d(Mi)=FsH|ngMRW8SbX09)2Mp@bLe=14#{?$g9 zrn02ka(>NA@z}N!%~6>oov3Jkexq)x0tWt7&F^8*DgwFn=KqMLrA?C(56k0hruLSO50o^#(>liWM4{b^cYe8 zCVm6h&Erv%Ne#hvWy@$@&vkvhi!MKKHu(#$S22cB6}uq}meEYhGh#@Rci!;ZaaiiO z-q6BUcAW15_@U*q!BQWVGY>|uID2Y1B~=xLM9Qd^opre>K=x-!}R~m=3s1 z0cO^g;Ijw76X$(YNCr3vF&3=yPzsJq&Wd9NpQd8tYmQb5D{R~2ZEMqK>x2t?=0ZWP zh_urpCD9W5xf3e0D=?AbE1Ki{PcEYKv1Ru2t1qUu(6eE<_`n?KzJhr06aYI0fLSuY z&^X?FV|R`x$FXX^2iJYwO{y{U6Hw_3Gv8v(Kuh2IR^Gk9ngpnKB1BK*g1aRZTmp#S z7pQkX;;oTa?iugg6t=gsw3LMOB9~D~ZYG(RgXj1~dwWVqKl|`z@??_l%Kf5A&ffC0 z3+MTbcza!!sot$qZXYP&ilegUeN+BJuVYtDX|nyLQac+@=+_<>P5d! zAT1*rG$(m zphZ|ZEyk)yRK!Sm%U$`+5#?5PU7I3FdPoV|J!XStTW(QKMvfnq4+}B_)3)Mkv3m50 z3i9Ikk9ZRFrxMZowO@TNS6_Q9%|?IDy8%o|hPU?v`YwzQ)nzed`YSQuDgNx5%S#^c zw3X#nQKXNNPjaQLu-Ct%ssQ8h^cgocG090Ot7^VHF@@>BL!3J#ekOiOr~?3j@EKKB zv6Il(z|SFna}CJ0Bid~}(Xh6Yh{@Za-ati-#7e7{>dj*^!cc!gkM5A)d^>QKS^7C< zkc3aizS$0Ny0}_OHzKni!krqqgR2$3)KQu z!>SvlRX%o?b0Pq;@~+F-{Db|QZE(=_{?=7i77n{t=?I5%C}tXy-kR1PEj z$48qA&;1SdtIF?ZYfJIv>U8Zjrt0`dpP;gY6~q^V8So&LIUT1>T1a_BDLjgmBCX-s z&DKiy;0aYfhpg7WX1p?@zABu;c{8{g#81-aLw>QXfJ!NUotdw~7f1nSQwo7!8i9f^ z8a-rpA_$agh~7Z|Vmf^qMj`R#sd^_E^OZvYY<+n41EjZ~p0DllO`Gr^JnbsrGK|(j5aOOt&zF4%io4Oy= z#YG-65z@i95qmlEHgYiU(PgQi<84BJ@hFhMM;Nmr^WNh3ftox6@AjQhc`@+&GorKA z8zndj$mUdDn797h_nP2HRBEb?4=A*zr`y#-6mvG^ZXKT&dC^<{M0rL61kdPvKVD_J z_nZEwz!ngl1Sj_bd%H%v09>gR+2@1?S8GkPH%bDF4SkY7KH7>aO(p=Vd8oQ#dsqB< zoGLp9QpogDN2OpWJco3BAe1^TNLcX69re`W;wp@i3`+`at+ZPFT5vhaE|BF)L*;0W zc80?_gP}2$xzRL}xy}(c>rbTv(=RemK`fma}J+QhmpO~v4KrF$$mq5FdPhR z?|UBa*Jlg(wBp-1>-I`#$Ca(6h$&nDGvOr9AzW}5tNka8Ux%2&kj(4CSEyTeO29C zuHmZLzOmiGmT}OcJrng0jf()k&(=x1PGy6mR9DpoG|LjA8iA-`a5I>wakn6e$ zv;`LWeVPf6Jpt>goKMWBcZ*%pscR{ZPF-3mOKOcNFzD2+x%9)OyAGO9;&A%5nyVdAebReR7xDUX3cmill zE(U(;2gQIfs#CRhBTc{RfCsjY8lyll?%H9`hGqtVNU}e`H6DpCBk_09AbC4L^ZA&} zChZe);3|vn{S-yHfaZmDG!IzOqT8Ue(cZNU>qSj4T~QIjlCq_voDauv_qi4x0~N!+ zbR_s@t~UTS+}{D>t1oy^E(;*%96Yub-}3yFJm6ed8p4v=K1iPA!Eq&eLAkcT2(#mJ zrfPh{-vFaAnj2BlOVCo(0JsU*_H>kZ)7~|W{T<16_R*SpVy#sG2p=0yO;Hug7Vku8 zreqmh46ahyuDPn`qtpllVx6D2_=&!+ZUD%$P(77K3=#`j2TUCR6T$VWcSr#JO!tdG zJ77V;m+7#$VsLE(9qC4^0h^$tw5F8H%MAV=BtnTdeoqmXZ9edl3W0&g9q*$=kR~QO4k=I`#3=Dd5<@aLa2IKAct{ z5(A0^VdaNNlGTRq0q=?EfFBlJo?)uZf$z{j6A6fOQ~(KxqhLA;%NAH=eh8uYpC;qu ziRMrb87;KACT+e(xMXThL-;wzJT3&c(P%;BBnCz{Oy>%{L;So1WM^cCi@^2ubWOSz z=LvT5c$9NOc4kQu8~AzfwD{+aQZ4{HK*Ya0dMn7HWiNPm`x~(cT-`|5sGHW|_e*kR zdOzA{Jv^c1(k_$c@kZzWbezzqZpwB;VvaWT+$Ns*Y2BWjm{LHA{>)zp8V6Ew)JkA& zaIv`&q6E5ebxG-+UGnS)jR15?Ja{Q6@;xEBh;Sf)#&`AEQvSH9J3bEM%QYr9{75VVQsH}CMMFUg9T?aU!5riQU2`;oN z3(8N-lL*d~OVVo5V+cG6pM*{Ntp42nGEhEB%7&p~j4&*$Yl$3-VnhY$B3RT{#46{>h*{qKeT8FmL@1FWoR>d14Esu$AXMb~FTXDrSQ5Y$ zkwG!fs|iIBP{E!0%sx*)ThDs0TrbDJxUId65VJC{uK2tVF5$^u*@3~x_$fMWMNkr$ z0J|Ozx*pNS#^QaVbH={ffiPeqTTT(}&zdeLYhH<90HP@c0=+2S0yV18fBT?~vra}!qV3aObtA{eC7>};uyA01&hwIMhR$~>Uh_x{Ns6+IVex)k z5xp9e&=T``%!t{PqSRxOz3!4-=if%p<5}b$NIam_MpE)h1L@_C+w<;F=o;T;sBTu- zbjo;`q@`M&bt#Ru%rwE|rp^A7cL?B$88W!lRHai%7qS5A?L;Uq0=!7njO66-0KvP6 z)j$fNqZDWpWGEP-*P2gXq(p~5-GbK09`Kta3S8)Fa-61N_j^1>-@KIluOU>$eib~DMSb%K2 zFvJg=tSIFf9w_VU^Df@Y>}9WdUo(I3m}#Be0TA>n2$0S zfNg-I@JIA{75aq+gtux{KHex<>2rK(v?m@hgWO=qzX$Hyk^hIXug^$9~v9NxO9dNNvzV zIS~f%$q8R)G7b9>q?yey3KCJ60wsIqw2*V0{vt zb2Ub60-%HT?e@(|>8h4TBz3OoP$Mw|Me)syjGrXA z+*n7OzJ5s!4(DXI{T^dMeKU7?h$WzW^*vy3P} z(<(UV2QDIVEiU{N1b+$$Dlh7%miU`$-bRbX##TaJY?{OQf2Mglq0#%|9d70MQL59R ztSE@Lk7Bn_Ri|vT(Ct1UX^u|pJIlg|_={T8t*~VL~-eD?F`kQCFy2`UvpXcDIObR>ID`iD{3O zf{wDL27g;hicLOj&{OIk-LJcX78AdILz}J3;pCX)gL?g=ddhE&DMMGEo;d@Ud-LXF zyjGgza;9(dSaHrKTVU$*=85KPo$|b;Nbl8V`GWS_S1ouOaC1x}VX@JjUND|pfKyC0 zNV+GQz6796ELOJQl?;tcVaVX+yH9AX>rTTI)slhQ_KGB^4XWO@@{Ap`?iFRD*yuR| zP)(}-74YIqDAc^S?!;(YOkFXcS?aDxLf9wkgFV5^IAL$ipoJ^t*;f$%vhn{gG;b^t zYX`I3Gm2m`?cHF@Z;W_a@(E`vu) zC#J=P**G{BTbCwsN*@J0hjl6}@YWu#*s_a+bYf3ehi)HHF8P{Oh#x(tQV2BVlgmr< z7=~_GqSGlFCq5|!cfd+c(`(?8$Fo>O5)_hREL)!o28qwrurV}Ag32Rd)0r4tCNa+q z@0or6;bYHjs;5B}py*7W`(ttN0YL?yjUuzPBA;Mu_c^FKa_&nm4olT!s(HaP;Z6A% z^Co?ac(&6&cye>5JdHV%o<^L#9aPiL7`LHtQ{UJ3Ja;_5aK3o%d;aqDvaKlIaVN$X z_kH(Y?*A#OQ3hdehbJlR7*;txfzCeEb|%)psLDqnld|G~Uw-6B^-%m8NG635Al}5p zi|_l2`(D)iRHNeUHe6{C;q=^5JZg!gax&4f@0^@k9B*PH_R))>VP#ra~DyV%v9bh}fwC2ej`=mXk+6)kkOV zWcdT_sCc-}-~`N)by7!Iykz* zavf|o8SrT<8Z+>HjDw_N4{i0X=*#Z|H1kj6hS1RoZXju5Gt6=PcSQUJ2&cRA;1(Uj z`nf5A)HzI6AvX^+Xa#ZibNLo3Bw#jJ2FfTUaOo}m84<>gP0!O&jmF4Tv40q#zX{(0 z{&`Q!c>T2Jq=~1oBPlSyRoOBfy@3u_wpe=$L9O;yX&jNsO zcr4a&y7-N)=FO}?mUh=it!Mnw^iPW_G`3?=dt9<~^)$5FvkXMZ5V-Npxw2_YM$uTe z?z=S}3K3R3xkW7A*fSA+%-AJh{NYoKOD4U}wc?eftlw>YQJND1?|#m*27X%AM*Z2H zL9}Xh5_9TIFi=Ta2zt>5-|(U9w6J@atuKdU*XP;#rTRS~>gqZCoOlkyPD-gv!kFrR z&5e#-jDhO78ua|zLn6Zyzm)1J@rm=AniGvQoj0!`+RBs{bhk{o6QkZs)^Oh`R&~kt z6+Jy`#tH|at(;B02LfU1K$dYJ+8QieZVOf4i&O1=aql+Cg>(=3qE+>-AtxdPcB$+F zP0T6S8Hw|_V@^J zt=7w2;HM_2gn#`s*6C|XIB54msqwK+zI=Wl z$d!L8ugEBko$|V&k;*SZ0~KC|RxtUuynMJJEw$~j{qcLig|Y^OA!v>LA|B5QjZG(j zQlDhBa#~c%!!0F4W^QreI21ZO>?JN5ibx{(9&HIy1Q}Rzd!3$d@T#8DvZlnx&@vHl z3NbD|J2NH5!A?T_SmJu_%pCB7f@Tzoh5(0&G}ctRsUJGtC{zU_1~zm92G_xjTC>m0 z(WC#;0&tm4hHe$eGH&t_#|u|7k9(W+<3PopF*^QXq!476NlnUtrw%d~QV2ZqCK$E^ zMA2s_J;9KXxw zNkB;7L$_|g#)Z9%uS|3n0Gb5Be-s?BtEX?juA#TTf#{Jdpk(H@gJZz~-4<5J5a=Zv z@2~#K@vs=or0f=o7|q4TCh0Hh zpGY$9^L&$y>V8_>n@p^~`Ug4wtTDN%-2Px<{yi|r`g@D%v+Bo-n~`kZee?vBoJB7- z4}qrlQZVEpKmJbQl64MLMQfa%2+r_`k`Byp9$kZ+yd)`jfjlSd;V&*3(L!Gy3|_A} z(w3P~LT(TpNLczJJai6SQJn!5`o=G|y(1ugaZRCWpbp*fk$2*q4K^0*;wJaaxVAb> zZQW>DLBqZGQ=47wz{&F*mNdo# zoePwY1n`(b7%>OypJt%v6kw^BAcL35)Vl@7UNt`1WT|_J0M_(elUUWC(9v`HJSxQ_ z&GBmHs&~z2DzS`Rq!G(o^Uk`ju{wRTuPye1$(|&eh9FTTosSEN5M9Yo*;d1d7tbz; zdZDL~5_W}i`~peKi56tlqC>RsaXYlr%ow^0_yN%<4yOi;aMVbH zS01w25yO)|Sbrydw}HOji`1uvJ-YMv-6iSrUC)vgYuSd3zmlcHF)2+S%UM;%Xm#R2 zZS(kH0qSj0tDP&~f!*<8__Aj5L*bo4Ka(LM98 z^#xs<}#km@lo~2GuGK z(uc8u4K@+T*{59JPpeVL;mbizl7x!Q52TA+0#{CE{_*6N`Z2?N%z1Ur{{Ezi)3?*} zcVZ7ZjLlbd14m)RW$AxQpmpim=U{;#gIAVOf7dRFm#gU2Uw^P_lqdRH{sgD<*u4TH zN!WYozSLrsWY#Kfuh1yJT`6Hh)Mfh55F1M2J1hMX3QoLG9YPH0->chCe&P6?bnzN< z<0t#sHa%WbHkoJHs2@4|vw909@0*hro4>1Avo9 z*Xx!{4Fp9y@+*FIAwrKzspC$Y5G908{P+8w02cP;2)rbq+}Q}CC{D)Wx$S6>IFsVu zlRnB>X(f`krwiH9#E{%Jh3KlXF3l01(jDR|URb+BQD*V~O4v6bnZ+Zl0^3hJ3?DBn| zy-;H25pb@7eFXfJN>{RuP~!{!v`oJ%zS|;d9LZ=#QU?J zTF^va6UR_d+D1R_n_S#ZR}x2GUDV`VUx4!O1bx((iMtsb9pd7|tGCLD8}XlF1AQF# z9~NF_VY%!H3M0${vdXozK=7@Lub$6x_NV(RTowKUSNqTBhb^LnxDe@W*Lu z$u5!}sk8U^F0hfdHfJ(Hx+%rAaXHgA%DK2+>O;t_zap9ZPjiu}jj_wp2HQlN2Ya;N zJB_fv4km;Qjo>wWSuK4*eephD02>ErstTs#%7yde=>?WQY4hIc!w;FR0k>3^uS2K6 zZ)c#Dx7`n(`31-RiIdUmiLEHS=~hK)|Ml>^k+w2#CceU8bl)JOERir3q;7A3EBe|U z7n&J8<}8+=l0$uzLvDuMhU=BHb8u;_2}Mh8?;YQNmm8qEMKXJimcQ2M{w4ptk+!^O zDIxz&Cws${cujTA9-!x9+>C1g-Il<23$Y=S+rVR=1-cAMH#XZh<6wo<)4-w68=b|5 zwB-wL#9EOZzidl&^tq?7ei{0+cm8kHp!}|iYjCVMUWSax$3aWOhxtvUt3!;%RJ3x_hUhF=5TT0CsM{B3I05+g`09?uM|vGs z%!@b%+2b)I~e- zLhTGtQI6u*X0WyoeyIGXKXRY{xJknkxUnb-g^DeFZ-}HBn986nk zt(rgMn)&Q-a_k@HT87WxqrnmT5OE;G?}cPdy|Rj|Phn0lvERc#j<^qY$=#jV)ReD^ z_7Y@H&&%hXO58lqCBDai@j6_*PnLKe19bN5^;NBArdKTksq(#b8|i743&38*_S)C} z=~Rv+o7P~oe3v#IT-S}rz6xgi-FN}GHaOYq+-_t;H9*X=)a68#PW9LM=K7Mh(sIx_ zUu$5=)9T~D?A?hS@Y7Vfj8<0p?TD`4Wn+v_Ab(}qSTWikDiO`+1fB@le%KZ=g`UzF z$Jq@}Xl(1$PH+{ZUG(m&8Vagj-9gWhYAF!CjbslG59+HN*f`j=A`hob?$cCOW^>fn z%gPNsROnpqRox9?ltWc@b6c?YhwR>@)u`9wXzZw+DEg?XkJ3Y2GV>f%!o^jS%~5OH z+O;{&VWN7QyZ$*6b6Ts28w4b{Cz#ZX+h9hKBhk7$jJ-8tG=G8Poa9E#i5rlPQz!jwB3j`{J=lI1yS+SDd7<7%{L zP<~=}A21)X8YkDSh_IQ42;WMnaG zf=y$7AqMApsq(jE4iKu`d`z7QSlb^tF9ZMc&p~hlPfCkr=ub;945|7s@o-g@BTOUz zDpvU-c|wVWAC)D~$)4xp*^@Sp7Bhe#5fmpCwrP!pHRS7FY>YLJ)ik46DxfLT(xK@t z@M|+y6x&&c?wzvyem6_ zlLOFy2gV7EX7b)I4E75OZ^}_3hD>SoAnz!jX}1a9a{CcF67*H!&x!KwwA-wi5Rn-rO06-0rnpt1F2?4JQbPO2g7JG5 zV#!TWPB`dEb%hr47sX8aF(6nE?qT-^tX(r?}q<*SRc zPT$q{^nLxH_3#Y37VGhKp9lc{)~dYTBTbxr?J!=^#{;6{26M6oPwMX_@o znNxu_`F`p5OA{5eegt%Oi$HhEMlP0xR1_OL!uO56ydcK= zbLG|*Am?SVxupm3f%hoeSMX@^wfWyK^_`kEd^Sb*UI&7*4yIEf9E@NjOqygz^$6ce z5Jm0S6SX*5)CMQTPGU~b5)mwTH zuW)a+XJ-Jn=Y#098IDQ2Z8O4V{M!HHhb;(iBc#pE7iTln0&5d;Wl^xbGS?DE<9C4~ z(U3Xn(w^d0KuCK$84=rbhn()A?eIHWmIP;2sIw1Mk@%Xog%wjv1mx}6YJn#Gl_ls$ znvSt-{W7sXmPKHzMD#g74ijY5NwAe`Sr?vGrPZ>|9;u6<^EQJ;B2Gmok#vP+v4|)+ z55uq0)A36c_Tlffci{hqc1BU-ak`IF4v*LLMdZW-I3E;eVH8}iMa*^q53x;=u#O`E z2eh_pqw6|kX)ZO4)Dw-M5glB->@7I+gCih@0r)mjqf6pvb>3314l z%<82G+2S>`GeL-t7pwZ%0S0(uCHSb5pb-y|CbaDkBK2yxAY@Cpmx7Qj zo`5}Cfld+g1WkqV%B;m+JSCp%d4%r-dtVAg3!O%y;iwneGq2bl6=}1r6pPb6w5{@l zrBYVCJ%wwEGdTmdmrZLiW#cGO1fcu0%zBw} zPeS;BR7!(U6sv2>EDt%t*B^$afDy9j!D2+UgWn>I4cQU4%Ws}h@;Smb=b(Teju zh!4B}Odsu;3DTw^z_--M+M*_QMZrqL_o`%n&4#8X1`pb{dIFimuIBI_)Gq9f=Gu|?7$;u*Y6PsiuD!h`MqR~=cDn3@K3eCJiS`sVG_ zeGGdH7d2VO+q5Tdg3HAZ%L1>1?l1~smNvWcK^B3UToFx)-8yf{iTmUAZwLp_FnBpV zi)-C^zz3dMKG%bI?YnD&Xb9?{ZAbsf!E*f|?c2mqd>UC{QMP;aeN33PKF;8B-$${TqfE0L(hP?D@i~`<|H^e~=tDRrl*}4C&XfX|5Cy&jXH!Id`*sgE`fPWNoOkD8e^T%NFJ^Us7aK&`b7fY63*g_J}iZP{a(t>kT#B-HxJl`A`Y1eyL zJvX}-b(4eK>aAh-J+j!PcE+Q@={}oNQ?o6k2mcoZM^PUykaqu?1F_Ff9kayo+X;#; zRRSc0@b#{@xXBwLKKWB=@$r2-s-t9MGT@8cy4&O?e)t#5s;OC4{5ta|Pz3W=Pplf| zZV@68GW=q|b za?C!$->2!gu1dY7nLiRevJeJZ7qjtR+TObL8;b8rbMxL%k$~3|<{M^3Yd#3aX!P8H@-j3Pj?AS3# z4@+NZtxcc2WcC-(z7Z~J^))Z|Np%U--71&1@_VshW27^|c~Sq`Xy`}jfxlzhh#-&! zk3Ooo;D~R+&x2U%V`kf!ea()Yg7gUHYjMKUzMano3*mJz58hmlEOx^>F|WCPET6UG z(eNU$11fdxdlRX`_ZT}i4@miz*cf5HUjXbxS`q|ZNi|12>uf9S-pXx!?`jh%R-Nd#>v1f#A_Ou~&Bi-$X1)TkP z*n~lkBl?|;)O^p{-uvoipEI_0k@xK{clJ3OfqdTqjfK7b`)H5u-G5=(=q_@X<+w1M zu`TV)^a;csBe`b;ty)L5PFc7LKvwA^6SMP{}67T0@_Z7bZ*5dBuJe-3vM{af#M`m9ZG-nYHn*{3O{ z`Mw<*3w!FY{erXJ>}GdK_J-7ssc39Ucau{Bi^Nt4P5pKHdYV~Y98NfhyaQH8 z^!9@mtF2hK5iX1{_PmuByZ?o>Jw8M9dpV3POz~^G?mtWMO_Y)M?J1YyNCc7Z+pAHE zZ$giwd-q&$F#F+MmZKrHH)aYOr7Vj(9^NEUTfNB5t0LEJ=^jyEy%Eygt}75BGSBx- z7FTRGgkE(2W#>Z4yPF|?EAZzK{9R;Ysoo#VwL`~e zwrCa4E8mY?pyK7EBWyyo-O9q?DuYGaGE%K#r%j8jmO3-cIn+5A9hNA&%!BGn#&v!m zpj3T6P|JlDM>05VA!ygq2%p72e<&m!1G@#GL+^EBq98Du(z&piZk9#s_Iar++}u91 z$ql&kW>ZP7Sb5J*?nS+27P)Vq4HgI9zf`EDiKVG3bq zK~kwyd{#EvjU04N!XC&uv2|tLqvaVhyD5Og0Rl?284z_)(xRUsq{nve$Uy{-c%{-~ zVdAim8{wB8jufQPr;P5rV8_4->~@p3<1R$~9ArS9NRP*ao|#N-rwu^Dp_CELj)^I# z|8Oi(>d$qtGed)l_ceO8OWM2B?ZumPwNfVnAGjaKUc}0UWhxvhhoQGn6j!P-^A>^o|-ydZ5o|Vpv^G$+x*0@1KnhG zy&4JlD=w?fgQQ0{uPHg`h#QVOVbE!3opZ_cr(c6@VqrH@*i7o-k?UHJ_lR`jVv;eT zLMKjs@}TF8q_8g$<7Sd4dEQ|p`)&3aTTJ3PCON0aGfzL}pB^eATq|XpeJ6Ct#pd;^ z8?6?oRqXU_!JWhO^YmQoh@fVN24}ubM?k6mMMuyAk_z83|5a&UGhO(9UqF2N1ZIjzBb z9z~q%Gfx}KrfRe{m0#6~6TBv6qHb^w<|XHS4w`S#nvu$Xjm+*V?`TTr<6qj`ClsGl z^2h@gs-dQ($<-kHZp)Qse8Wo2Y9_r6)foFxc+gYG+=Ii(6XvZQ0N&XbW#ih7;j(_` zTz#98r*j`1jL60A3-3v~ob=H#sg<1<9D*dq|E%>ENm<%Y)rg=x=$ZCuTcq~|Pl3_V zB@~?BFd6`cHzNr`)}}#J!fs|7Ip?NSqzq5u0)lv2l6vkMc6!3nlK0I}u+ekmjB|RjKYvKA!N1))6~kpFgSrF) zp2{tw)<~!Lu@FnO^Kv0)8r@xT_QQ5c$n*wu306+=zLoC-t0*~B#x*_lIQ<{d??m^L zPd{jzKePZ2k~ZfWHIgy-1F7CYozfH!gVLo8w+=c&Djwr&#^4X|VyCuCi2PjIAf$`Y zy)t1HMfd#w1^-ZqgnFEJc>4gyjNSYJ*x7BT)Q{GKIQat#PGQzEuLNb)c_r#Y32FdJ zQw|zZu@4w}aZ+yl9Z{qc#s=w$JLkmNPybBd^qV2QYRe%}3Yg!eTLTz-{F$K)By+-6 zvy4AW{6Xvs853WpoVFRuP-dcbV&tqinn8b>YQ&mh>9_w)-v%M8p44UvnUTG%7jnt` z-c}*=Qojd6`aS*~6Vg2YHKSklB!*uq_s?91L#VoisCf|d?*spe+zRj)TC>wWVA)e> zAvYCEs+<)x+S$Off~rmj-V-p)xw%P5$F~lnR6{MnC*mxt7^YVaY6pNpS`v^F(vDun zV(ZG9XrA)8BPi`$9Vm9EsI{*?)rvJB$CMbEp^VFNg-(HUDMs_U)|o}1#f*|0=~))f zM*F1!9@z&J%b%FO59(n4r5^!CCVV8+k?|ktS0olv7DbXTzxC{UHl~tF0~sF`cA?1G zpPN{W2qcxJGN13JvW1mcty}MSY`&!j#vV&%D4jeuydi}FsM8d@gnl1;rKR8-gPveL zXdT9%!~791Q1#>`3biNyZe#N^-A+OfU*P~0P*@31MZ`Ynh54_1=UVVB!rK9@ec2un zFzFS}VaEI)es|*q1amDTlxFm^E|ouCDoDnJAl+g@p>}ct(n48~%87KXeWj2#W4PTs zF?Ec$mV3q2g*-9E`Jty+dPpM zgaRfxt0|ZHZm*QYvwd?;M9wI*CnM*-)Cy8cgU}*{EXh$^&J$^w+CDzXm(yE(!meQ& zcuvTIWCbf@LOBV%~I$7)djBsz zR3b0+3sC`!=C*e98L}}u@MDC%fB;*P;9@s{%aP9rtW{U%?0qT*DtkmVx>+-sbu9VG z+-jjCX_a=f(J9p|;M4BCu&pCBPey&?+9aV4(0OyA&U1Dv(ppDno6^j$c#nMVC}gp3&l4b>HM5dl~Iztqxfe0cTM6xte$jQ;rD)9pk&r4C29B0 z)@&B#`RM*#GboQf@{XL*RQvXfogBY8JI{H|1yPhtf5^r(* zQSMI1{JNcTD%B8a`6=bF_e}C&4bT}geTd`+@|f2eU#e>GO}*nWxlmRQ zLai;ak1Dwm=8xl;_}zaZ2l7v*>qu&fwBSe%NUUR-^RPzhN+LH>9Ibx77TSGARHT`4 zsQS(}dcJ=cYtcqz`t%rGkmkS)IyF-6kg>ClQ&-c%UQl2Tt+&!1mnM-^RHntg?i@&; zOY{r?pU)<1q*Ci_CbXftX0wZKdX8p?J$}**#st7_aQ|!#+h%B88!)zm{JG8g@oe-k z)dIaB4b6Ga8p?oKVMv$hC*gf2&MoQKrHNuaA{3yj2MMXQxcc$u5VlY^s)>|MIc3S( z9Nm`Afr}kr(uU{4)|_vlp-1!!bU1ARo5*)A?WqC|8I*R$e>v_15tUncA7D+joc+J~ zNm|_~#&k8z#PuIrp=b+^v$$3BR(j2k-(@~9Zk!SV!`=uULWDY;3Gd=yEl)If-GUFnzhDmJ3fweBS@b`v5iCXwKa=xdW`s zl?HQUCB$-7TrFb&D;~?;$k{Ami5&ZG=MbK0HO+ynAZ5XHlnf`*i^sshM6P#DQcQ`F z*VN0H5vJ4G=kygo3!M6`ReXTE9WYNSJbd%-Nq|nkw$xFlIoZ5bke5`t+ACM=>w!_Z zYX4@3ESPA1!jp3N=koWH_g^TLk4V6yErjC2w0|BV1OZYg^k_KJLoS>k@(lE5sB!xW z=4A(ZZiI-?R210{n`|_*%TQUfV1N_Q5>3jifmTccvbwSdT68t6^p#j)yd57EO(+m) zJ``q6E%IF$)@KVVFlsimoAIoY5zxsn(bxJKL~<`JG>v08y9lh#%4^V5&biy-@z%K> zKAjglKNfS-bNVtm-rxUAGNyNahaY;SSD~w6m=%wHvmGZ#Pvhb0%8GATX}wj?ZZBp> z7wF)~;+%PZ%B}4_9XRMgCV}&7I6`+oiB2V@u}wz`+@Rhy1@|1q3V?cu7bB{il_u9! z5CHAkm?G}$LJFn!CbxTO)~unfbDC$UHUQ7oFt$=k#-Xzfn9YqEb{&)wVU=){*h;b$ zn60`?ZCj88YZ$u%R8=DA=Wg@$1d?uttzHk+9@Hv(8KC!X2%f;I%U-*Abi{I3T3@mY z;Evkc)3a!x2Awuh#jkB>s7?YZB5%9wLKH)F>w-^WzbwaQ^w_a77Pu&M^qnFug9B_rKAPIYfIm7 zg&FxWF;#?boSJ&h_&~r2tkE8boCqIKgQ`RrTxh$1EoQWeaH>sK8*&=3oqT;#gk_vF z`7?eB<#~w%MEd)>T@HB4@(z5Pgs&ZEe;x4*wimY~I4Vxi^^fOz_!bXE@n>jQ3we!S zP;m(*mamJBWfUkrK^n6U$`;?0?ffx-f%&OOf>1MrYrAcL*QRV@3{HLa(dpDHN@_WJ zegG|DHgw!WG)l((?G}DrbdC5j|8c1|w%*7_8@yADH}Dp65tcGMSH{mU>PZa-HH+ku1)Z8H6x+If;O)JrsCGKG83MgpVv`t(ldPF-^`Tbusbmo|)}RCR!p$ez zIqA~FIDmW&O~f|gknu?%HRbV5AYZ7%xGEk5vn$Da;KmkxNzyhoSvX2qvOJL&i=$>? z0PR5j=Z&5BVhu%)gm~xCRpFjk|s|W=GI9HT%Pom6ZuBTyAn#NfrC=_31OkfIx z4CsO6ozKPZ^(`+8tNWB-8dqVtune*hfj+})kZZQv7`6o=ehn zYR%v~Be$I}+EL7uVi!4S$C~aosRT#hH&&;287q%DCD1ZSIw690yA!5)Txhj<)35t5 z<;msMRO8&9mu;(o?&b_u1g7yY`JgAEvs?!83>a!C4PLju6*xeOPl7KSShuuEi6`~1 zSZ_3duLn>x@1Rp5WWNab{+G^aNMNNiHn1ZEP;?=eGnaboZ~qkF}BFT(6x7PetK5aouqWOrqx-jGzys%uIW4--Zbiwaadh3PX8Xv%jK z4QJG)lY$GhTZ4}4P_#nEX(}A76gj~vW=b0-%iGD}DpvJsreXpSMH6%_cINHU0fmzB z!8O`+dCkgBU%{d?ImR^VQ{^!Uz*guA7DLSb?MMc0vt~h=y9Be|?!c_ulAAc%u15<| z2?ds6N+4}GGe;g&NnOgCa(RTWNs=0OhMvvPAq-640>e-b3u_T6I7({^Ylo#Imx&^s zA6Oc&oD7uc3Y00kJ5!eiK{)}ey@pUL3i$*BWw~G*&;`oGF3fV!?Fmh?D^O{tu>xyv zNZ2#o9LMC_EdkPL*_auLo6*)Urm2pO?aBNHCa9Wmxd`KM){=Y|>!!J}{$hn73RZUk z;h~0;QLtnYtAS-B8FUo{C*ul+7LT4w3;dO%YbIvB0lSxkz)xMvtj3euT2->Guih>& z+ziRbh5G#5k=~3r`fqhry>k!+WFSfOL!?SKXXG~wq8;Mvmkv~7FM~tu1rdOB%NPXz z-uMa&x6o$2gGl^5KW_{|HQT$CEPTc%mGc~=x8#`=CJrbLd?N6i?%2GRsl>6~ZJ9L# z^Ud|$pMtgZ+}mZW3$>6JIZ5((0k6>b-fHI$ZaHD#05vaUS!U| z%byqI89pT=1a2GgS#$r`mvVod1b1KbaCotCaf8AawHHJ3&^yHTPf9-W4T1X3Crg3; z0VrHgI;QQkv0GHclUy4cej6{~L?8thrG0GCv$Ol*a~$Y}Q1466mgL0&K;js3&F{Yt zhUCyafJI!s?-cCFIQ6Vi4EG!)5aB(-!0^RWyLQs>BDkJTT>~V->2g!*Y`M)%HufG9 zT|srh>igkna@Fyt5sV14&%b+ak>J6}#~ZBib~O+CAOAB=U=a&h!Ed=x?|3*O`7TF_ z(^L(Ho0P3kTp<@KkX#g02;>55?k1D0ThXMH-mVpMJH)O!3n&+kKPsBp9iCG@Cmjnj z$X26I=AB#zSRbR2C=6jUD!!xo7XBXp1`)h6NNaD#SQZ$aL|j-FL%N}!PQcyWkr|&< z*w;n+Z<*X(OudVyNi#_fU&er5F#RJXS%Z~Ykt+?|dFGWKouCZ9# z6%tQ1AigkR_SM_QoN>w!eSfSn!h=y(FMb-%^|??1kAb?{DfnZr5x6eka`1s9%*;t< z5ITAQPmh%6#(ntFh{+P{Fosq@0{0fTnIKyGgsOnxj-uKdyV9soCGxfY90*`i#N{P3 zXQ4^2o+ah#30|}lbtPKdXwb}E{~nOjA|P&$Y9<>hD)~yIna8%48diu_3Trq*#?Y;4 z_^TAy>lFwPrkq!Lb%&82|YLAcV?U?#6PYQ@h_-N#WfU(wq^G$77))(wa)?was?)n1qR&5U8lC zX)LN&MlWScAw3}lF*HkncT)quE>__@&)Xa1`$Y18K?oVL_`WbRAOld3tz7gf zV;spNmMUL{jvB5un-6DXUi_tdl#}hG0f&}$vnBc5ccmiK%R)5u`Y@m?dvcctrP$PU z1Ybn}N-cAx1G-$8SVFk@s)YMKh-(})t~Ks8Xi&AB*%!7&zD!h+QBWax22QqQ*3<(; zWKXdrvHK7$U{C|KjW{;R>zhDC_Q5HnGFXiJ-P}80do^nwa)m&I&s&YYWiUi3^{AL)0>+t7Zc;GI( z-~c=ENDAOkBFaa>p|^r<5YDW6-4#rYGJ)9&>8)wP zbJdl>A#uh{yo{|*LKk3i++^U8G6w<=7*~o|79-g$h~`8)D{G2b4R*YPYbW4U+)e6d z<)B*wTQcxU$;w$d;@oqLd>~we7>qn~5PH#wStje8pLcWf-^)bHs3(;}76Q)QsX7Zh zr%+t`z=P2gln#s&8~pTPtg8svLOeaBk;vxbqzuHV#JbpnOstk>t+O(3gpEA!$m+TT z@o2V-M$o=;C}k7}LB~WAUq^MWP|^Z$2V|6S;b8TJE4mzI@D8c*W5XX`^{tm`6}jk5 zN;eVjXE3fGKr%mw{#d+>^2=ghXYyNON4TG1tiXEK+fjr$!ofqtkh#RuBo^HJ;m~3u zID=Ej`?HB3am8vc#<&o>P#*|z2IS7RuB9?OPtFgK$~6z=o#&Ye1a#?e#2xfWy{*Sf zrSWcb54T?7M$c17mjUq>C$O$MF~(`4DXVD`jBQpMXnxRoD#O47UgU#Bhbd3eu(0c<5((9^lAe|_6x;5fiDoW zEV5mQb=L~(i1TIGzrrCLAh#_|nDS{(w)3MIn(O+k4EKc#q(E_2`c0|lG)m18mqQm4 zPs+U>tXEBl0^1P#!9^af>*6qixFO`!pqo7~se}nxKAh_Q=~X>qf;#cY8j!P=|NXrP zA{T|wuwip7`ef6wWA6lZQy6VqIY!q7?dU4E%B8MF0cez7wW7sE%zzUoIgAvMC{$J4Gp|EA zeZ*%sIE|eBBubJ~Oym5YYDh_Qb*{`K!&IrhGsUCE&1VEhiS@F^M+XbCCY?aqM`m`O zBmo`c_@)*5{Io@$30Lq`2nE19E4*AJzNU<@-Z-pk6ciLIz6d3>z}AybT??hqYmz}I z^st!+O2F`c^e`*~r}qdD53R%lgcBMHreZUJ({?QQ%tEWp`a}?u+T0?`YN%loiUCes zksU3k5V26Q$(cS>4ZeGFKrQa1Pndp`hPb`toGi-ZwA4AxdOkiw9;-D;k;}t$Cwh|M z#dJpJgL!HKqZp)O!ErtEMPruPjZd_N{_?dS1b*<}{5!tZQj=ss$^E=5TV;y%r@@4R zFjdEn25Dti;zGo*jA(o_qO@SLSK9fRLFdR--a8&f&~*oPyEKV0)OXZRVm1Mv#V3Z zoZYH4`p;8SA@Isa%HMQP6ry_1F`d+I7Ca_cBGE>TWU;<_s}@g-5IF3_VL|7xj9E4& zOR*a(?)^XtQ=euzPXdFzz*Ybh zL?dR+m8e}5aWe#XW_Zc);WGD-KD3C{m=v=r$LN1S_^`w|?QQYs)zH?$Pn7(tjk;*} zZDC1R;xb?phj?fOc(;Y|xiW}s_PIOQGc9|&vm0=;pU#^7u5a}AS(D`3QHHK&vZeI( zY6WS}K8JNDVe$bqSpfqhG5?FR#hr8qQ}|>RcF^|`ZV7?8o)&YpsbAj!w{MBWh1!j< zYaf-jq?ufCmTb%zP=6N^QzqFg=Zc8<6*s-|2%DWYF7pt>69hR+k4P3&^ZBsBWS<$x ztQF!Bc+->c67H+*uDz4)kDNq)t*vdd z?aplbwzVw=Ub6KO8BPqt*OD!%Dgrfgsi=U6kQoZ)`rR;G)TmE_<{BspYU`k@1gQ$8 z124_`8I?;jSqy3|(~XehX@xn!IYYp1n|AS09gSvgm9Aul2<8Zu%n~lxC!ntZj@I2HHN-}cuZTM-td)2-jUjs6ay6Rg` z;%ZI5^EDr|yJ>0fTHL<%i_Ja*kh0xx!!-|VOK`f0QYafu17>ZiwJ=3jrOj$S3(Jt@ zOqYv-<6(swUvhanYWEP)hFJH6yTc&U|61-Wu2v=oWu^8gcXfAk<&-Gjf4H5X`dSh zbjBS^>FAYoy|ySXXSRD2Uw}P0jn6SpqwUZ^L9`>;o1s;X-s_gwmR! zc4ZAJ>7f~7TtCo9Nh|tTcK(oEJRUO`5CNTRag9$ArggRfn{4F)f|pK=;pHhAALjd=};+(E>?riZiaVoJ-(kDbd#>q7m~yEdtIpK zDPLnOo+kx?2IvSgF$f+zeK{4B^1RWXLywq@c{A^^Q=Fhv3*>IGN!GAYiSVb8Fc8j? z)JY4juH1+BM$uOCdIUr%Uv``iBYkxhNndBm^0JUl%(c`{bI_+uE1P@H5pLQ01wXLB z&o1z8In9AnH>Z*=${&EsANzs8e*ELTQvB>Pz24^7uN(`u^4+*xmpS(Phv3;Wui#bL znPC3MNQfaV*^xJ7e4NwwUD8E@F2*t3*V;hYbp~8TI!7{JrZk|oXe4j2XW&xNR_stl z@Yt56orcTmGD;zS0Vjchf=*)AdRK*xT6Y*Ev6hH4rx!@BJcbzZhs8+)b+r;DqPyV_ z!V5z5Crz>_yhLf_Bj{n*q}(siv<)I*){|GusS^UO4$P(!hDoD7)`w!k_I<(&Pnxn7 z1(YS}V|k8nKn*r4flDr*DQ-A=lDSeN`nHBucrLtWKoAJ81j|(8V&q zRW1zedkbSvP2MeDGuu&(j``hbIsb^&mOwRTTtyH&GErvj@x{7wji^%y&dfz65 z@Tq4`X*f<9@rExGKymDCyVok{+ofa>qa1sbxi3~eWf&XMCh`^bU zEn2#HWSS)dg{IL%)Xr?*Ah4+l%YrO8(pqe~S(KryNyI=a!bpK&Kw^oh6zAm|vOp*R zt`Xw)r#{2s&7RcJXs$k%OjHJu1%V^?n9Z?8*tN8bgo1MF#=jOFSsB~%$j$fIR#8<( z*)2Y=7)dio%F2=^;1VP1Um5DokeFQ^rgON(Hltwq|2)u=r{&vymiOxB{k*_&uGQyw z#e0=W>acnpu>(WnuB~{1U?>akqmry}NwG^$>79cjVi2L3PII~x-gC3Yq(oDl*Mgg( zX1`!>H-%WDVc#3<5=C31bN|zB@#37+R6U+axgGtqG4q6K*DRxN$}NY#x0ueh5g#@rX+qw#Defj z*SlXMp~SPq+APGso5ueb7jBvshq8h|;X~%CQ8~iEy;mJyE(43YOt08AR{kDCs(PrE zzNL!7=5Bn1lr3PnA-sjc2?issCIUj{Srzg zx)L>BgiGh>oSnqJ>jkeJ(yy*t`sJZL8`iT4VsIbk3BqPG>B-D3t0*=*_Z- z?PA?|ax0ocrg2_>dd67b;F*QLq9GdJx4clxlq3|+sJ7a-U979_PLzUCP#3%dk#Oll zK}W?W8dOO^I@6uZmJ3Rndz2Hu!(rEvYqLRNgXa!3gT^UA5bbW2L%I=lwsoe#@f3A) z&@4C`6?*_7oOM+MAwXTc-2pvtSd4?p?To?~PDL zLA~j2`L$Xbnw@>R)lF*VX=`$gl1E6sf^hiOEm$}?v zlj$fq#hqz9Hr~FRwd~$?I4ca>K0-Vw3{;~7m{2x|`QP?drN}rx&adYde!#1cExn^z z#|7g^=2=DyurrAZR!H80AS?f)paD~SNXl|00ACXITJcF?g{j)IQKu$^ zUkNdKV^yPu*B2->szl?u`RyWSlnB1DfqPJ`sL`b_5LS9peOr9Mtk8eYh@bvlAavbo zFzny}FK+lF{*7~R8X{(3>vIAbA!=9|9Ks#C>5lpbHgva{8Oe^I>^Xv`_3Yq}IR~%B zGw{~#3HU=VK3T(`Bow{JD9$M5H>jpAGE%wmLzPlPOceCcR;ulQ_3SniWt>IpleryH z4XM6aNA^7648lN{&fGJ#IfCRReh8dA|#{}w=g^;^7LHcm-SMyf7)(oX5Mdc@@yym7(Nq5et~oG68$$|k*~)zfe=^2Fm{08J6qx_Y=-6qEd+C3t>4GfTb{;5=H78D?13pa=T|fy->MV9^C4V^r^t&V8a`tWm}HTJbyYT z_KSN|N-IA{iOfz^w!nGrc||B?;BJa-fh=qVq~|5qd9jdF`akF5nw@a)qx5aThhk{n~M}Z3Q9!?2uOtXtPww$GdWn z-XsWm6T($K5$S6vp8V!mpN+8dh3yqSy)cFDd(?^n6&?XsEy4oa3Ba|^ii4M80uFXl*nipVK|1ox&^agp>$XaDbJqty`OUMKoz7IUo-T>624upMg7@YzxPBTZWiD zCps`Vb=S^x^icRx_uiaz0V9~}pWVQ27ftQM?%ZsJ8e zpWV}n+|H1^YPR>{)6MQ&f*DN9KS%}yL&1R}~pC|OJkw|fvo z1+*X{P7DDms(I&f;QOHkbQOv}h13(NuqkQqq9Het`%f^M8*LtFq~%xX1WUdOIw+&%2lWz==!e3z|Pd{3H;0i&b{)CLTZlcp*;s|s;pHjOf}e2&c? z-xe0wt**9%^Hnl*@hE6eiDSR3S7U>(Tt6wZ3F#?>!#rqYCvPytO~`PBJ5Y}A;iffR z+o&bA9mltD=B^xH_A8HX;->JK;(6KK^5^CD%iXqx zG{GPKwi1vyWh+`LGTnYvyrmZ;J{#2dVHn;Wz8$6y8##Rg@KoLt&z@c7fyzvk{s-bT z+EM$&w?fN!dtx#Tacwg4O`zZ-{y^Lv)cR2v-5tFhrH>j_D`mu&b7oCegOsr{Xnsv( zU{+;PF)fa6NL^nU>amafzAQYAEg z607c5LM)W?S!~@kzXyGLU2U($dPoNwAoG4%)IodP{u@88!%1uZD*LUw@*PlrTyHB4 z*?ve}ow$I$LpCv8G1ZT^cWFGFg!hG*RK&u8Px`B;-WwXmRhiP;LmE7XjqJf@-1$m0 zuEU6ek9P-mWUL6y}FJH`>lNZY)|bT9t{#P67x=;q=eiq3?@8hE@bMyu10nbx86@l&5^nnas#3Q z*8$tg!MsF`n`L?Cd*~hKI>j^Ug=q_SI{ob+ z3+jeQ9@L{1o;(GDrz*if+!L@@-Y6o#*X~>jn!_NnCsAJX*aYU+g&G^92<}sY<2;bv4Z177lfeM;WH+(udbkiMjL>~l~nh%oUd zGB0$KaudyuYa$HiS$CUN8B@K$@CFmYG`+B7Qq)}MAd!FvD3^Zm3kM~Anl1V!JU?^} zREcc0ZM;+?K0}hs8X~8HLsbev=T=IKU1gjw5AP=?RQ~g%4DxQbZE2eRo~FRS0!4L- z&N@8WVnJQ?By4bf48X8a8gWsTjUZk3VgUw*=NfCbs{jMI0 z8dWNcfjAjsDk9ia@D{|Xo?0I+k0r0|$*u#xlL?19Zu?AVbxk8rc2|%`GW(3&8BxF= zAR-g&Yhr>&fSVni8G|wmEAi?1GnEQYOK!>r&KhC`Tak%Z`qfoQ%$lf&O8lG1=A{YS zxjI0vsrdb|(%Ec^x1aMLq#_4f)dCgSSQ?k1K7X4gdM0J>BoqEwR zZA)GW))-{#AcqDm#Gy)5Om~B_Skz@w?$cVCl_xUE*xu0)y&STg%WOiVfWLCTzWZ+J zW!?qa>IH-?3K>#pbt10k_||u>EelSN1Pd%N930*7F^6Xs^btESn*)n|--Cx^_!4;E z)x>PeA;!~}(LJj=7{gh`1et_of6_VhiI+7wmVz$1KcZ5UTsPyJ&fWNRtP2~}6EH(V z9IxTC5@z6Hyq$|P`D^6!yS}qit7r)u1|OmD#_F2h0Ng7lEEG)X^S0jARIH|i*3eaT z@ZHWBkDA=!pqp?$M~ONaNr9N)0k#9ISxD*>7lq*}y@85>MM<2@gn}#97EqJYie@?S z4Le!6`3inUaU&~p6Ur|>$hT9etn*3qXPlWZ^?`3M+ZwwuuERCn zU>CD#7g%`@M&rMs=z;kLoY^HSJtU77J#(&&1Y*~Py67LMFVI>&u1_4f_Kx1EPm7;+ zABfGY0Z|cXN4^&{koX@wLC`k5Hn_XUU%M|%vXI@)-eyz?mfLRZj;S2@B6^b^J`V_v zhRS*WzI;{ZR?X_vlaCIkC-uTd(K-jf=wa$Grs3DZmcn*B8#~_h>Ey ztdnsDV5O+mEb2wKNUl!!q&~0m{m{SLw?&{&o2kDD(gV6-JV)AwG<(P+%zTh1%mjHM zt?*i!J+}EtbOTlYD5jBVcW*s{h=977*mAUkK3n&h=cwn^{$8PZ;!rM?%!#<4lwi4SL zjjIY2f6ceYO5=no0RjZUOrA)j5g1Ems~d3@e4Rv{nTSroka7|b?|6Ex0fm^6Apiz~ z!{*4ZOSNtp;tcF3A+AX5GD_J$rS&e9!jEuqP*^+Ce{g)sV`bX#kLYAsMmW$#2XJZ> zwpcVU*r01$wX^`7tgw;rAb3@4J6@Ql(YEsBdax-WgAZ#qE-*1^1H1u}vF6O=0Xg9f zOo&2sj;eSNz3?AnOMcVKGD@Oe5E< z_m@_^jitO=uJ~olJb%;o%5nGdJ%rww1yv^{H;7hJ87AXHCQ;;@Oa03)V3ll&tS3xu z=a(dgC+fL;1HM_#s$U|BVfn`&sdIVE@h*Q~@Q{u#oCp`he{(_VL))pVE5#g$f<%^e zO2AJ$b4&&Tj!=0n>`&K74 zM}ei{B6uEhk)UBx5GBJ1`zTp%tj4X3BlUc%rrDF-AiGCeahI6=Jh%$TT32;yPub;z zHIkiQ&{K1vv?OC0+tcpgCLNp;x<%Bt_XN*iucSksa5B6uF0 z0yw>e^hL%;E3vkr;njF6<48Qu3?2Y{bTWr9rzQG+3JzUgXN^U*E_;%z-%3fdg&RqC zD8sK0yQ*4*Es1GHoQ}K`pDJN1P@2P5F-j{=cT9(xnzeR~t&XjW^X_C| z%QX{*OP&_e+xW3yoO)(oD)HXhVAi=C4;yZ@zUy3^lWFzLE@#Gi_}$o^{v0lQUHARKoQzlb5+#0ti*gE+g;}CUpg=we|KOC#30qXH7=CN!}{a~b*?uA z((gyPw7%Pw@5qw>6AAK%wV?D0A&XXzDRB|M_WWomN58(0LCk3Oc;ixh+UTC#IU$vs z`{p>F0*b!l_LmNZh(&B{#%B=-TFjKBX0*QRcpQ7$c_qM~JpP{~Xx~YEp9|Yko;hj} z_M#REfg-W2Ra0JyE3L{{eyb|#zNyp*=#o*+Cik3lOW5VoCQU1s9xr*ry+Gs ztn+c`+_3_1PQhkX&M=uQjWVAui3Va69%g6T6jJTvX`74%FCgZE4p1@2;%`KOj5R-E z58q#XruwAQbJcyK2$%qD-kZ?z)8jq=J06+2idaSZl>bY$_&c00mh~|l|072G?70*- z96Zze>pfmcI!2f&m0{BP**1X%2a(6yCyG85p}2((rH`E$UU)mk*z)y{n+uem6W$Uq zXeQ1R1JVL%`v{CLAyt0hzIjjb9ph`eA@c+az^d>Q=bUzPrngVrZf`l~I*Bc3d~P8g zZuDFF!CzdFm9Co)1Vi8sxe7J*v+{$+KXG{i&G1aj4h1g}&xosXQU+>`sYOBqSIu_% zffKm6H7z};!*If0$z z_@Y$Q*KT9G<*2o#k$$?sFk~8323H6qRyG}eI8anM5S=M1Oc4SwA zE!%pJpBG0WI9ih1;#jN;qCen$t9*l8`&OAguwge=awvq_kt$8Z#ANWWn1xc%ou!H< z=)^U(JYcA*JN%BfyKMu5_uGAd0&xejav{xAauUZuwh}6zPQHauVBgV$9FMeo-|wz6 z_5V}RjI#y`#7<=v-e={{tsNh-G$jyvr~E%;li#N`7^qz~lUX^Bv8+q2(JcQR8)xqi zbD|s8B^$oP`wS2G@$n2s*vf>ikmKW?^}2GaYS@6#_+9C57zvIxdu_(xXNNk#6N|s0 ziEABj$saeSmQI-(Tiq-2YXCeHBLqfq zwP`n#sY&x&d%__{w=~z8@@|7g*(I-v+-xqpAT(ZTqYWd`rp*9sjZH?QQOIH(>tkZ+ zqjZ0-l1eiWcC5C;O=No z#aIB~VE;(t&~4d>W9XBe1||-luvvC6CMmq{?h{M!tyS0%)<}(~Gk6w_8p19+x+`Q+ zBR4+33BK&(wV7rZj^2uXo8BU5z(2_TTacs(p`%2UDmOO_$cN+&i8-b5>=@ z=4bC4_*1e9(}RdDgrpCU;y2dfETl-4pQIv@s9NBefAKHe#u%2Bqaz?(1*f@XY7koYx z4bx~6^bRrq_9RW+h)2Fo1H)v&?7MBy0<^6<@o^bdhA<7LlGzWBCw~A_*NWk~Ja8n6 zYAoY)-Ls_ufQYITJ^2eRkKNxe_p3bPa(8t1WRM}L;-^;mS9W`E2BB&gr)N^pA)Z7Z z4;{MXiHt0+xV)BGJn4#iA#PEqS6pg0D7C%PGm%VeL<>k74Mi%G3!ekL-0SO%#XMX4 zni+0nBQ7E&7c9!c7^HrQV|Z&S)Muk{c&Vh~U!qJQr^FS)1bhZz*->Z@vcZ>>9+BeF z{!J=rOMyxaV_|7d4}3Mo|(%zEvm# ztiJXwy@sqyTRle~m0ce*3lyd6lIckSvs(UrUY5g%9je>*KQeM+tK76Ylm+bdWxByb z4fp52zFz`J`P$mPu|IL2U7i={rZX&3U-#a7Wv`HZ1xR`@%2WlS($;V#mWFtyf54Qa z^BDRbjw0nD(Tr7jRbQ#ttToTWgKZQ5!z|M0Sc%lHD&-45ff7Y&`NqHq{tLc6@_pt= z8{o3a4s$aBvNQm>!YXJ*0hIQ+f}+G^(%rmnRx?@F|8Tj2iY^8$khPyiBqwunLy3(W zRiN@tE$9)CxF{?B1FwO0jkbK0T14OYc2GOm`u}grug5zM?rqGkSq?)c$ciPvHQ-JW zn-Iu)_5TQcT&R|QG8rBxaB6)Hq{~`5tW_cHp5kpm)=q`TOISkseUdJcHQxZ7{+=Cv zINSe51MTt#;^@?s2S4I`)=QURQ@@HqxX zT{u{aQZk^#(+^uTBt>QhT_lu}%SavjF3^((*2Fr|BMRGwpc2yNN7Q0uLr!wrf(jBf z8zFBH2n$`vT{dTXGayXJ2L?XIfXu#0VA5PqcV9@BSxO8}B;@fRj<`f2!kl{5jmsks zXNxzQ>_Rfmsa(C2oQEzs{lL$48L0)6ddvGy>*%In$yYAfScxaxzg*1OLR(QNhDmaW|Lk5 z7((_woH` zulgTdR#0JOT_k{94A@(hYjx#4{Wx(lb%kCH?!S1*9HQJz2cC1bb)B?{qKlnviOj=r zP2^=N+_+4OdR}}ATU*bWp{7Df6dSS~009u&f`<>m25V6Yr^SoY@5(?;^`f ztq}`_;(oExDmFhaEkjFY9+{Ea-nq;IVl>w- zzvR~Rcj8i!s>+oXS)LcfwSuTtH1CY++!e5=a3zf{Es$)bU1L*3P-zj#0*S#R!+NJN zir-rB){LIXX>PI`N$*;B&B7~K8ZzTAiKC?^aW}k3E-83UBH~Paf)$VRP*zcO6^y7# z%r7TPM`cZkIL|XQLYi??^6@|5G|z~9!n(zO zThzN|VrrFhB{)rbC-qg}Rid_Y9VEp6SvbdnBbnVH)7xRZy_eiqAZ-Zjmmh;QylTSEW!qs|b&abYYLIs(gLK?VNFb_s0G(u8u$mzG7ZOM*c(a@oCQE>YcpY=yq&K1I25~DHO)~g+*phf*M1&vLnXynQ_H?ZocP z@HIGU3f+OEo|o2&@0oi?ANAafL(E&kY)>{sRtl+jB;b|51YksD;PFK2u9Y~{B9|vk zwc9Ipt*cR!B!pQ$j(`a*>Xi{6qo^?_fU{hrgfu}0M9U1o(@Cp%JRw^!{%9%Q--k!- zdTneqXGWZxp*3`CgtTgY&u4Q8)fQvBzlIq4wpO6*| z$mJN2(as{#5nA6UdUpe}`7(xu*c(F(z;IT8uQ9+#7!uE50C^ARF~IIn$65JCKJBO0 z+kd$Rm9}nw+kX9Qx0ktb)13x0K(2;)%>5YRFR&Ic(+Z6WH)g;a)Ynj7ww|D>7E-O! za9B%FeX?GFTaYwz>(lTl;!stgUFfZM4FOmW{E3X4DMNscn!Uld$b?>cdwb$_eioCH zp;IZUCqb@3Lz(-Oq^0kz^aR2l@fu zVr*i4vK~F%LE;c0hJu-Pu|&$LOGd$TW)2@BhV=pip@G*RIs4raQheSRXS-);Tt3 zwx;F^00Tl7+D?#s-RxQ3dx{+L)s0dZZ}duaH$9!3lg8+OzP9+D4!jqabsKM8-IA>f z?FEy;a0df*$DA>q*{F?+@=Cgp)Vx zKV1BEQ)0=S+GXL?XEQwX^x#e!nq-eJ@&9%^*L)I%LR zB0V&uM9ZwE*yQjtk3gkjh4K|B#bVEv-S_z{f#%VCv*l8s!RE@wA=Ax;D|O))|XxiC;R0qGh3!&@jgL`Ldd!4IOjnh@UlH}=yisITq1B`7fCE(8H`&7jvIWpsL4)Nlyuwe1J}M{rJA&&dVzMOo)cId&RItc;e40TG XLbG$9VI_3Jf0k7RS1XPO@mT->QjP?B literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Fonts/UbuntuMono-Regular.eot b/frontend/src/Content/Fonts/UbuntuMono-Regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..7a03fb5122f353d598a801d5660b51fda9cf6b4b GIT binary patch literal 23691 zcmZ^KWl$VW@a68}zAWzU?h$cXxMpmjJ;Xf?IG6Avh#h;C}zBx~sYm zH&gXy=2h2pe|`13V~qiTK_dVF^xuXD{CA=upui!5;6U&|Koamj0-&t^4g%~MQ3BNe z=k-6U5CEVA0D!tXSe%CcoA`eKAD{!U1b72n0ABwgB|rt>`rqC4zZgt_CcqkC`ycBB zumE`c#}EQ^|6@D=o&fv*9YqP?1h4}H|3d)a|NjpFAgLwyf2;XF$>9K2j{xo&fL08E zHUKhv7Bjnuy;8{N^&>{})aa zMs>i2k*_J9ra7eRK*QBd)F=fRT5f8IUAp@xl)Q9LO>oCG7wWLurtJMHu5?P){YQ;2 z?THIZ4uQXogE0#&9G<(&V^!n%u(#Is&yjFAJ4@8EM^^wc@9cD`Oc2eOh9PANOOY`v z=8zxdr=++Ta+QCNM$=2y61hq#i4}vIHPnv2-@?us+?47tL`9uC19(^MLMZV*BsZvQ z5L&EFc3%cP&%))4tQVpeS+Ttqlc9w0uRPI}WgbtZDk_x5_ljV3%1uK!HDQ`%E6{1{*pLf=|4^GYLt--Uh)UWVY1w)bWa-_bp6e zLs@h`QN$@JyWswzp*oLZVgrJbaz)|uk7y{(^;RxXQKW+hvWy`5oRUBZN{kRd)Tb*M zm>D~MGT3H5TjHZMf23CqYW0~eZWAx|NczPdrQl)p_-B4|PQ0p!wYBt45s+qg0ne!& z7AkIEK}lHkQQ1FvoJ|YHPQq=#K|Tl`1-Q?R$@wBJM1pdL!Y0<6}3=d03ku;z$ruej#>&h5eQTaA=W`!?P>DS``t^6jObwmb4&5dZ+oT@2v)8Ol?&Oaf%*l_nn4>oiZ&N@r98v)fKAdV5pWOty zB$$DcFJD6NL!JL=^ z_woBnD%*=)Ye1-dj02X0cMV4hd#1XbKe>QnA0NktqkbHl8SG(wIo_mI%hcK!4&Vw! z)&yt$Sv#9NQI3|YvTaQ<^r(_v1f;KOs?cy2xycV=Qr*P-b_?9jY!2yDWMPk`NMU8(CrB%;$VKYWE67CUCS;2$xvYl-LNPYSg&Hf|j_^1`uMT zVawCSN+UvXWS|yd#6}ijc zi-AWKiH_jnj17r01*$tg`UW|2RV!*W3~2a)28!*7*e5=}aO;WguvO+u$9M`1q zhO`k(AQCjm_9)9zyu1d9d#_QlajWB+cYmQCInEocCzf_1BB z5rQegfZBqpdA*BitED@pvKrYhCMuQZ7E zao*UBDYgjd+)Kx3nd^>6)vi0uu}8)V8puZE4AiYC<|jsHvOwJ%!eA2}itepPpdp2} zc~YmM!z`?TgU(nsb7RA;P8h>EJhVq&P(n}V1J^mTdOh`+Bd~5@os+V}vTz&oZwU`* zzHtd5YoW8DKV9r^Q?x;qbMgm9L<0q)!rscn65dpDqp%jpzMOn*G~9#j7C5ubffx*( z`}Dyv=Fij8az}!4Y#?7vQ`SFYU=}$S@391ni33S)Wx69zD3A5YGl- zMLr@PN|rBcR4~hnN3$8!aK}C_*=I<=2X1S~rxn^U3w!Vlx?6(BqUMZH8k-TtRW$`> zSK9CX>7S9QM|`~~H7=5| zgsLe`h&=Y^8&TJ7158w4tt8r%TC?d-BA8JcCTM?WdvHVC_N|*V1>amT*|fid@7s@E znN0#t;teC^z?lej1yARWSV?z%tLzWx?QN;EI0&}G;cmrqLnDITO1`tJS|JldE5eF| z*@rwR`{>D5%fE1dZU$-dqtI9p@D>J6>1{ptz#2LWDxW}k;MW6a*@m7Fqv@GwXprz1 zNpr0JK;(zMt}0F14)aJK-2iTWa<@3ZBAWoj;e89XJ0L02Sk$h+598RJI;4rZc^y*& ze)C<-wX-dGx1m>}7%t%ny+G(}G7E=W2$;m+(m-zsuv2f&i4CS~_~jcb#prcEFJjg- zZv{)jSvauG%UpQGwJFh#Bkss%^teE1{)8j@xh(TrONfupF@ZV_4$G8lPV%$^eU8$c0}>L%F{^sqjF(!+suAW z$1jq$XxtcM(v@WPR_T3X_tEE>#HtsEH@4W+_%hWY$vgkB?=Pj$js8S(-@SHb)2Z3c zToVh#K!mz@^*7sC@vewjBoMks6Kt5 z+$J=fUKj>_eu>hld(rXJI=*q5sg^<6TsTh=uOB|bQcY^Il8uq9+LQ?ze&45EEY@{H z3FRC(d>8=XKmO%)Q4XIC52~NSzkNwIk@UK{w4Fws%A70({c-$ zP>$`rg8|%?!WKG*Pws5fL9SbbJ?hEGw0)g8S*C!eDA=;dk=LMWIt(0lgZEL8k0F}? z(2k>3g4dTP!|Pi&1B~H+!%W2*ObuNIT`4xqC(pN*6)KMAT>Loj8IWJt-b9R2;+viC^i0IW8FOW)p2x(p7~KFuLxKS6?Ce~J0E#V%o9 zi?u|!K;hd*yB*V^)U-EfBA zlk$B8Z;tNwIwIJYpq0uh4RgD8k+bdhh{{_G?wYf)4|Vsr^Ct9apI&p}S=7oTYh^MQ zD}*W#>)4|1^b6Gj0icB4%AWwbTn*p-&wPb$#oi#jT2lezZ3bD%52%;hP( zgDAz~4HEyH<)wB-o^$QVz1Ys7_3N28hP44POB#&$Msr@fzJcz+9u;! zeKV&Jo-_oMN4UzS)RKUktl5Yzeta56zpEx2tpw8JN8x?Uk!W?)sfG!btE~#@18~8{ zv723CPL__koRa(dHi@GC_(BqCK;nCap@&!gPnL!2%!f4R~u-FN={^EA#HufIFCmAcL+ zl}cJlkrZFE{Q*?i8cL(em$7xX#-8t1rk-E?Xb%dgc>Mga3Q;|Jth0VTo>fcn$} z*~D6InZxbra6btAgQYAHzWk%F>Z8jn;Iit-==z;-kdF6@Hf_Fg112d|~FTwu%LA;Z%Uw3|Mn%pZR8RVQR zF(cVE+q8Z4BCVzGs(xyU$h}-oui=-v9V5)ov17f0U_BZ?`-$P0>hjEK5-u7d9tU%h zxzJ9(E3baMQZ5Hf&^In7mSA`*0Q3SiuV{{w}TG2RnW*frqD1oBDT}^NZ{1;pDx|d+ z^%jKRa_9ful(+VO*jN@g3O@B!I5t!`*UU7Nk6S~DU8OZJZ&M0gF989jS63yq9J;7p z2tJ?V5{6+OzLsYA{sy`MYpUDAM(Es?rnvwgF2e4ulqc_;sPrYC#$BLzN`aO;hRn{< zwgw!$6C*=boC-WB)#u@Pw$bxOBIFF#&yK^TjOw$!nFNa1VMe1yS&DLM($v<*f^-N+ z?J*y+LLsOz8qep#VI#5At2W$A&n^U(|~i&2y9Qfl$PX~ zLhiDyHhG{QK6x0AVD<%L6FPaV07`lG~=l)vNeHSgeEL=>jQea&aQ#Hiyl(`J|T*45#?4q zo?FpptMEC(E>}d|1;4KP2^_g15z3VVHA z6N?c18=Qr#*F8FZ$5fuu&JT%4%Bn(<^CQlFYqpnmO~C9!{T6$Jka(5ICm&iLC2Sy) zlwtm`;;&dK8ma(wFdT;|oVX#fg%KF3jZ%Ov5d0UawzFC_hHPQ8_ZBv$;@==5KqjWdib5n#5o*XX;F1B(hz;*v)DP-IXxq%Mr9w|!i@cF=AU&8|7&ACp>oi@CNscG#s?NTQyCmpv+PqT<2z-1LOp z(fyvFQWQy{G4X~Ei>X}qao~PRsUGP#vY8$x!zb%*i4>9gSnMDX$8$ym-z+bi8G6FI z6dOhvaiiB3wuk3K-R4`hq5ltM+OmNi;S|neuG(1xpUWZY@L(uRm@3244e!9!&9NC> z2rihBx#E;^`L<*6g)cYs@q%nVoXd!uPNBta#o>@X?BZDt9bysFGF%6Y0xRU5fc z_X%g6^_pIlKPg2)q5QOkQ_AYrqBGz(AIdJTo;)NHwL$x#4na#=dh}?L@5>pN|B<$8 zrw<^Ap&8vBA$2InvlkX<8!;^6qLB6?1ew-6 zBz1-ld}~5pFaa`(wEm(``HH+!55Sm+H`Hq$j9>z7g5epelu_&vN89O5kystrx*XXk zt#zOZ+8`m>F>+oW!u&5yb)ofDqDyH!q-eq2q1M-2844=`+QBDRC$dEI)u@|qVlG|D zU0GeV;mLCR@lnS&I*)L_t@Sy{%T~xb6P$H3BeT$tUq&dG(KDQ?oC)w8sYMed4hglS z9bM^)qu+U1;nd?5x+b-FHINR7#H>@(G*YP{+$(Iya@1mY+}IVbh>9FejY3D2wsg3W zp&mJFseH92PAQB!tu>5*YR|0PT@J&KCcdY*WWiL?`USOJ7|Ca)pPvj;qOpX_%v#B2wD2gbXU8D%||kV*vD%(G)NX2v;|=d*u{g3p}6%O3%~azK7Gc_2tVbJ4#> zX_I1#-oF7cX4Vt9u{~jxek zk|037g=2c+&>lC>iZ{>J1XnV+>@DQt>wFAvyTri+NmzV@O86S^NHXLf_=7)av9?ON zmPW}D1;?+fPFmY?(ka$EHoaTWjj1Pg9d;+8{=_`G-os6}bPCl($ob3*AAvt2Wsod# zHsSSH+EZ;O6y>rmpOo9(kt;6wgR$1AZwW36zGsMPvuh(};}9;#Wv=IotpZhORLhY9 z!aH1i`?FZ3Ak;>w2M&DG2<(P`mCom z$qhjhxPa8u|8k0!+@ulifTGjq(KGE>!KJfQJ((YQA@MFJ_+l4UG7I+6hUflr@=$n> zJs)!5&hq9OY??`d#8P`eCpwFdK0NWI-X~dDF0Su(6n9*AxSZY1bi_8m}RVyHY4ibec(@Mfv0BAh+ZRmEe(Q)zql5^5;txSxXE-8hc8VbIufx zOtDM*y?jja9#5({A9n(3;E`@p`@z}t+oU&lN;`YJNL;ds>f1}KdE$2}{nqfGGVG{n zWAHb<>mK#WExXzsAzJymxQZdEWdmGBRK6^Bw;$O{lplUr*z*oilxD-FgLt1?U& zEc9`!?8DQL=AQ?VNY_T$P_vibZ;ij;aqhj|`9|OZRd^_p#`kiqNPb?Q@)A=>X2HY%BuF5k6fu+${Ks;I)~9T3+ZudEi2yDVk8%D zehY42^gnWu1Rfuz_S>EnRFsz^jQr{_)fbBY<(yUgBYkR#TiwCe!SD~`i7^v=siq;m z=Z7qLKfaP@%bC5Fdz?8Ag@42E;^9mOCTigz%?ZOV{xmEMCG{6aWRp>#D9Kz`ga1j8JdDmu?)XYSV^W`|5$G7c&`j5v$4x-p$DNILda1E9#F7T(_N@J zme>>3n>YpNV%vF@Vz@dak3PU70# zV;y!k%FVGXgv{ZwRo|QMQG5{tjP!m_)-6tbGrTxp0YH*Mi}+Eaxcm2fLehWQmN>k; zK^WrGdmk&LCpRr72}e~QKS{~ZQw4`)v09ffdAC`d|FvPhY?YCJe9R>OCMQlZN*J~y z&_zu|9%)X=&254ZaK)RVHuruk=ewt^K_rsip?hJR;2Ke}^T)*yX9%(E zh=i;n_MSvAEbOQCIro0~S)EQi`nTc<=}wGHl#n)m0xU#4Kzgi&sHfoYKm5QV-X6*= z&afcG{U7jZG7f40TY2Nf`Qg&0vnX7M`$=koFi$7~)|4!YJBq)5vh*Kr$Wp z4l8sxEN?&9K1KZC{R1A!d}0A^k5I5IrGS8`!qTd3Hqnmh%wyM7s<~uC@F-gbD{2@? z@zrHzR2Z>oZ}^nk{LDrk8!z zt}xx)QSIpf7|<7XR_fXp?6z@`zTNVM+?&%ohUB@#B1t z!-GcLtRxDdIUMWQn0hxibzltL%W3$R}~>IA3n>O!Fbp4mb(dhrE$!d6%Xi44C$=3$W`*OTN={B*=zqIU9tA$n}c9s!H!jzk)cxQ43!;R@l8GZ3)x+1$(ydGG8$`&@8? zP|V4sec;cD1Sdb0Q1t?-OqC&t3ob_XTEe2!7dD4ZxC;KCGK0Z|1$#vSea?UM;o zg8lg!Zl+BHIVI~?Y`srSPOvjg<)*I2Pf5vQu{>KKx;V?CWN7N#JyQpy$^mO-gQ>N} zE?G)Nc>^4`tzuo-Fz1<(;g4Isf(fZ-*Tt2*DdV%-(%+dmjJ`>p%kO?#P#_zn4+|&} zTjYVLq_-psp##}SGIN*FUHyv__-wM_l!=k2o7FOCJBBDl?p>bi}8+1RBI}Nm_B+Gge7J}X^(g~Bo(*HT6uWXMEXYw>0ijm!hpQ1d`8mpEqZn+#U zh{Wk8%O`bf0+a_DMD;CH?46QA!new+Jia*f@~c?udYq!=O2OQi(=Pj=C5Y_&!*$URyt)C*bZBG{5L6V)X0 z?L|b#(bmrzzUy6Py9h4zvHf1+O`_8Jn;)Z94mvisr2hhKwpt>HIoY=+(WcgGaZsv; zl;=}cC1#Oy-90@7*^v15KY?0@f--vBcnpsGykZJQyVgD@)v1?|thQL)`0COybt%sC zQ>_EIUzH$ui)UKq^0qhQ8r?u#PFdPA4`5772QyppC2|x{QTL^>M;`F}$Bx)8jFz20 z2T*idQ>t;cyiv&j=ywPQ~u593b z9ote<4DoiS7SHS z=}t5KnwG>J8em;l#qbn4?C}4iyM1N-#S&B5JqJ5PDm^&69MG>GBt*(VNFJih3cuBi zF=k;WLsuUP1n`bxHxDpCp3Nj2j`XRRzNDy+Y@S&FQ|F>gOP@ix&>N1cUgZ<_>fGX;y=X|rU*kC<3ec!$K0+>w5*@VH=aD&n-T z)*F_eP>=_$AD66K=UVi;c&qe1?BvvIM+^`THR~^vM!R{05pT?o33Be9p|J8nSWnrt z$Dk?+_4YTjLmdFLAgs!A&RxT4qzGWk(bNo9XL!@~!B7^WciOiNi4ajMV=nD?r^PK# z>OEDNk?Bi@9h$@>E(mgJ^ZJ45p}?ZgG^vbtD4l%mD1-BNZ%&gX-*`(7DjjqDTK#qR z_yf-zC)F|*#$G`UiONAYoHwUc_Ia?)(9^cf_g-+cmvnjdi-glELxJM}dTl605qPk*+ zLN@A-qO~IcuKmaD7iS;NJDwjD$hz#{?%t7C z!T4CO0%U6fRM9DM#eVIk%f6|KOiRebM-eLXlq9-N z){b}MN7q)S)MDM)JE`oSkhE0{Y&8r>2DBt+9cem;N@!{~dcXSM2gtmaihOybJ&k-= z!$n?97?7QWFS;V|37gGuTZ=y!vqnFp7W}&n9c&}IKE~_lP2>18Z`~$}tap9LB{=D3 zLqKr(GbOKln7&7C@SzOp0%bM12>*s$(X}lue#17dN8XgL5F#1-ah(*r0;s+r7@dh* z-MqP(oAW>6w-HY1Rc)FrCw)NO-rE>pm(tqkd5-k{+x2`fA@@ z3@=vAbMactEoV~?rD3L}Knwc4*gIq{m_{fYR=^gQeTSyhXETDTS>tFRuRPNghur-~ zZL|x4hg{TAX&(nIHB(o*6&}zOZ!%$Kxhopye@*woVDp6#scRiHYq| zy-MLRw@>LJvE98KXW9OaSB(iho1d-~A63&5qH(_^?QH>%5x6IiXP$e+9 z`Ez~?X~Ly6uiiP4K|in|FXqevj+*vpwx0<9-tuX*PaWP#U97HBZRcU6n~LRP*QB<4zr?2nRqx{G!!OS6h#+hFn}xhSIRCby&O z`Bcl^!E))pI<=jc1Ap33Nz`7FVib__t9fE^;^*sG(iATOxY{IRE2$?FK0T{RvV*Dj z1^2rQK8cV@a@bV%*;R}psw$3*$?&f<-%~*(&7?QJaRt7ChdAOC){yjif|clZ zC~B-I2D?-)=x4+wGn#$7SRLoH!pw>E#aP@ghAR6-y?bTrW(?I`vA}s2tGG{#NYofH ztq)~qcVP=>a8o#Pl-O2G$*CFhI;3!lPbuZ^eIHlrV$IJA1F1ZXrd)#>`c#b5CQ4|j zzL3w;-mBzdosT)D6aLB?Sj&xT`&~pABb{x@8PYHgCly|M*(zZZe|0T6`R(TVmsWbw z%;Q;M6+gvG*@F-O7HB)3Cz(16O8k251r!~R zJudQ~{v=B-85@L2!ikbG!hH0?avFxzFCx^5idI9u1C%80LH<*eE6UEJQuX7&uF_KQvasnTC{uGM0dtb7JZa^*33Q0Il z)wQs(+s9$Yq1u{OMrF9P-yA95>=*4|AJ9(p#moLyB?n_`wQL!fa#{)ilFO)EcLDMn zO-<5Yyo2jFhu}omA+>M_nG3=&)s}a}h>@51dtDR&sl;@M3o?w2Qe`*}N5URp3h;o* zzq)f9p8Ex9-hGn$^mJr@Lw;H;avJ86h;84*xP8xPj%!iaV5O%^>b)cq+w^ycvPuQ2`Wwx%r1%t$_?Y z{oY;?sg`r>_m|09gsFt_312?YK?Y17{gxz7G4J`6Jg=-Oh0hnh$NbF6af}QU1!)L_ z++pz(nf5Oy{Eqy@=x!Df_cB)%8Nl9!{kSm~!YT(~Nw~u+nu(%zBvm@w{7D;?xrj-_ z1LcUwI2A)?qxg#UJxP#xv;JSr?zTCSX#Q^}p^NU;RJ+K6g^o?kokO{fOFlei;nJVy z41RuYJ=jyRp*pGG6ZmTN;P z*Hp*N*^E3yv)pV)nifX5F(b3|@W%iA)5;gmES|IHfAP`$VpT4L5ko;#Ef`$({o#KR zy_;EG?J%@lZ^AthYneq4<7(P^YzDIF;>EY)XiN>{GVX94FpllhM$Qsk@cnHXJ^wL! zwgl=m)KBSqW+sijlxdGCRH&a?6_3*9eIQ=p#6Rd%=Bmu`MAPQZ>11WEx=j|)S}G^w z(^!6*8hO!g$Z`ai@TF)4tSRhQ^l4BxD}4{ibd+PXVErVgg`Ks6<o%ZRq4NTs>qi90r$7M?t%-anc#IWSjm{2(yRt4(acfw@fv+sJ7*LnPqg zwJZ2p)V8GuJg%&-r&pc9sLM^pB+mTHUz;VwQruQg^Ft@4M{nA>_Ls+rJpwT*?dbqU z;*?j3THwo7!8u;(j9*ZpMe;8Fpb-#=k9C~GsEiO|*$1+GjPBpT>=oqlI_*zyx9B#t zKxZd7IY!%%#aErbtq|M^*618bv)kaQn9J2W|>yoSL$b zZqE5i$;<|>ahvDnqGS+fNs_TLK-zRALV{CLb7H*0JP?XPDfhsb0jO5&A+dkroD4Kj zaG5;>ib0yzW99BqK>546E8rZ$JlPuF(YRF?Uy`V_ob!NH3kYy$dqrm~_*>4*9}~V> zJ>Ft6gs?d^PQ^w%gb}Zlhm)$^g>u<=(R*&D{dp=u<)ORYzq+wbm1sOr+rvC6I#j5= zCLPuYnA$qVgzRWzqJ0pckX3Q08tsGR^F_!sb7&o7V?8*EZ*NCx7Tu%{efNi;@xD^1 zAL3|w6A#7_0$!^ioC#a3XlsD=9&tr}AD`-~NR6^*Y};B4vgZ;R)WLBwcRSHrT`YzN z>BP_b^i$`54mwi?qrqpZ+m|!5SRN@f_BhhrZYeKCJ&Z=T_A$X9@?Do`>6mwd51a)> zZ%)<}tmnhVtI(L!8+Uz8a>DGJkyC6=jjtduo3Jo99rZcUPGux!6Krp^lr=Jc{>d)L zs)s|6U;U@`x{!I(EgHf>1EqT!AatA2APvWSYOI+gdtj7GIU@@GFZHUd5Rldbu-~Cq znh_#F4dI|biCSU)hzp3FS7o)fGW;(5A%$U@Oh{GBq%c%aF%A$FjP>O&hJA0BIc z9rjpeoN=E>5d7>;wyJWH(FHX%pivQeJhY81)UxjsWtLqK|8oj`;BM|r`h~)7I8{H&7uNCzivL2@4+anh#Uj{cMuvsz zJlWIsn)Heu6ztD6C0)mI+{lEx+>o&WGAx|sn37IQH#B%_wo>L*MKzgNgB4gzz85d<`+Mj4?6e$(0LUSIADZ_2X#WI*yIv=P+&Zc$Q zj`LYpf8c!##5Sou9vL!V!?w+#TbTXkRvXJ}KFmWg9hC;0`C6%MSFQH%+wu;79blCc z4`6~neS}-;Tbg!B5D7gxQvMkCYH4+MwOBs=)r-e^)n2T?;F_&aA(q9#zvCZ_Kg82) zvjh6ux}`&{;{*J!>ruF{9sf6jF~j``{zN*;$1^s3iNC~AoNgyoP+(9vh~^NF%sc_k2vJ1v?;f6z za;c`Y31F#8eE5+Cr@v^&_4{vaGQI;8C-<*bf1MJzhMHt#4@eNcA&hGHDd$M>^LYKX zsMe{0=C0Ok?DyaKQaY_05a%I>o442tKMR!|aD|32IjCz>T-{#oAgThAINZgjAyeIq$|Mkw5+q88sv0IvTxxzttxQq%TY)~os4sY zUDmQ~XQ_Pe)H@3*)V ze~T@3ru=%%dG_$~I0@fjVxK-*01r^6HW!CCIb3{Z3rY)g>Lj1bw68OX>u(oK6>*Kf z9Is7Qu8K1|CZ)rgdWJ42c@S(U;=%dB_Ke6Wy5SNhQtR@*4AvEKvLUTTO#z7Q^u7I0 zk6{f40))LyJp_|l33bz?3M0E~uxL2JE{b?y5(zU6DhdV`e_YBaKJ#_*=@9hZ&yepr z;1ZJ%u`9=VuyR_0RslTZLE<9TL(04IDGJ4+gXlI6O<6u7n@%c~CD~+G)Y2IEqNrSz zGuAZ#vWvQ4_wfqnQrBOmx2#qTY+!5AE-qJK%dA`w0~})gGY8CRAYXeZC;kA+569!q zD}^UvWGu8Wz>O><>q^!mFib?2aMLV;j3!W4v@izSV>Hc>YH`LwcE}kcT{kI%ExPM} zxN^N!DeiH~l>Q$2fKJ6t?3C&SDkVHnXxf4?6Gf(&O&FrnMoIpxb^p&qY;sdSZXJz0 zu*1i;Jk~~*Pg=f<)m?PVo$wIAwFYzu0%^i6_JbF>X^K&n1AgLLumaJjRxvpu1~*Rs zNG}ctlX9TQI@rsn2gbzzb0*CKrZl&TNsD~nuL(XV>HvZnv3R|umQQaRX=JP%c6}jC zHG7|+X2#?z>>}9qPGQ2iT`N|cARX;qdz;R;Rf63A6nz|#_UI4yU{A>-rR(8CaX}E> zip~i@zZkF{#waTfoxk~*mZNuKId5RjrkxCx%qXk)#|F$f2WG%U1A7$)rD}rPhNBgo zMKe1QK@^s9v3!# z*X%2B$jhzNgdCHoE%L%pKL(}4za>OWYpzq(wLbPA(uKFy5mhGZjNVih&}Rn-@il{Z=g- zoq{nq=FoBq9*HnO8f1hf&#Sy zb2SR%X7qe}UT~iK)%}n79J^4X1r6)ZHS44w!$WP_O?Atzkwy)!;Prqaq|5UkTHdTU z5}WU+k8>r-Y#yc9Oa|v|A1M;h1C*$+O24nyM&Uk7N3nkq$a|l4Jd2YMs}WqQM7Ij7RFdqBbKs#H&Gvizt{P=T=HPXbiNpI3IB`;Ss_PJHtTHNCA z6V%+;Dh|t$5BZxqD;O<+P#4G{lF6(`{{Xw1xW;7#7r;${j}38*cx z&lH(v!+La6x!EvYRaKl^r}t`pGc2S@Hr$4$X- z|85u~seDr)|zu07>(I6}p4-{s*V0vYi@l_(lLMFXKYi@La0 zm4Hu@kulo8wWqiAaB|$gGe(mKp-b{%*K&;m@joREU1J zk(&-r$OhI?3)6@)%<35B6{CgRxH$0;|2Kp-C@)VX{PZcCw0DbkFLPqqEC?qQm>jKQ z{RY$f#4@-v`2%oeEN1J2R^DUYtg*PZu}0G!rEL?ZOA;D==x{j>&a zp)Gx0{my8mdzH=Hdr+V9lVv*i^V0!3r}Bt(4slskZf)de;ksGEFB2VfkK0nl=uAe$ z)0;cvWoNuz2Lf;m?YM61 zZLI8A+1X?y{0THrTUEDv=*o@$iJ>|5t zmh!MoQ?mH)6*MBN43UCYPRIbe>z&Y&5O);Eekm$fBx^bu=Nz*K6)+Z%1d(D^ILySK z%;^?+!r%=Ww00kb%`0d3{c@*d-4v_ge`_)8W5P(F6!&Hh8Gf3i%l8l2_T*7q_?;W(yNbq%pBCGnQo`E!ef8z1P309Y>?3>bN0G_WnwA(= z7gyAnAj#^hA@tD}A1wtm0q>wV^F0upO&u1fpRwq3p$rB9dA6PJU;1mzn}OAYoc63J z$#9*uUFK8_L^1AyWoD)152b<$amu&rl_gYBAn#Qy(zyh{JKz;%xgvYEoR9g-7>$=u zIrV1gKmd)Rx7FX>DxR4SJqHqLfIq-w(1)r`+qMR0mgHd&C&3O&S97SVR|w1&2UcN+hbRnmTue?G z`nIV@EZA}hlEv|OX@QOzTjMxK&!y!WX&4R5vX29?4i4zl(vXYqA>%zbl{1iR2}zxiDrJa)*$FL^}at2oykXMuJHNQ6&&+NY>VfQK*Q15AznNzT{=_jW(DMd`q-u zWCDJm@<~8OsqkxXeQtoo#PBlW*Dhum!4kh;a9Yrc@j}W@Rjq>q$u9W%76TZSg_4Gv zNpgT)l<`0ydm?I2O{gGCn_sSb~{$$-pJs?m=p_W(U@&hU_i*;!`F z_E)&;%BBoPY(O~xSmFZ2jxd#e98d%~iLxRG#$0)ah6X~o6G$@z0$L)Z4#wiSY9VED zN6aZ(aPtjV$Up!PVoRnTL%Y(!N%ZkzUp)~Qh30@=lqxB*9R+@9;(Ypvq^e5Cv9%0H zvyam@OcEo*F|+D*R0(X(%Rw{ZTzzgQ=ePL)P?_)sM>+(;s)KAmu!~QpiA?rRR zmnhE{ZnfA9r;&qQ9*9L&DWl4cbq5BtI~JibF@nfal{D5VbWfKq^@hg1bt)F ziy62d2kF*~S?LV`^gH5quC!t5%al`=oR$^*a5hER1Kw^ZH-XQFi0n)SVaOf_h`(2o zeqJA!Mtg{sy>v31Xr1+=7j}9L?Zfav*hgU{!T}!fc@c8ZPK7*JL{gBVc#H02w*V7~ zM-#+;G!>0xh=b+1W90$x9Hz9(1pyo-Lb<#0pllJx!nem2 zyo^97`}kHpM!<8$5E5HH9ueT4335(7l5tBRY`Zu)EK5N5v^-jLF#d`m`irK;VFV89 zShQR%lGOmlil7Dvh00MyC-7Um@lmv~Pf~ayLA2tPVkb&`VtaZpS90V*MUBsNY+i6# z;_h|7;UZTj4B~c1L|FO(g~gL}isD6|*Z`Ws5ugRDdAnqYoiI2<^X4(eaKMAKNJ5yE zvms1@h(Q?%R^gx=Vk82JIDscTq@?c46O2XxX-Es5MIM9wV$6cyMvX+#hcljYCrU8} z$5IfvOtBG$R8V8yaN}f5_dydva3K#Ua0dJ%6o?H25>lL__b?DqZzO5FvW*gKfF=*5 zIi1KLLyrWxTOr&9A;DUR`)pI=AU9n=!}8RuEmG#lB~U*hBod+pTW%39bBFG!SR~*D zo4olJw1<;9%;O1+MgE=e0x-GFHQD!af$o+At6n@VTjR;NiF9y534dxYelLMtMi^`5 z{%?9hWJ=ij6zNl@p%$BUVrayENv`g%xunR*)Nn=NiwlY1(B~epKi{rRVuDwf#+i=_ zk^HlhNyu9)*a)WZ`;AWuI9Xknf<+~>VH?EB^6PN6Zu)D{&g{di z;GN!0=dRqKk?Gsy!~n!jv|lgwF2ODlE)6{d9W+CJex(t((KaZOkdmkj?wfg0(2uap zjJPet0WX2Z4q6FyAE9^?XkANEGEg?k)=2E|(O31^ieupZ0cyQr?i6fN8|3GEKispp z-9n%tgx$oF07h;5Db0i}gnD7dx4qV}g|r9YfR39u2Nt!Q_mholn0%m#7U+7C1~r!P z|HEOi4H9RUZ9pjHW*4;Nv2g5tq{liFFr4%# zDTw@4Ya)QGksYx>ALL*Tp@0w$oTVXxH+oKn*_qb z(+SnFghqMJE!hSupk@FEh5)UxX=gQE9F2xYaIz=Ero`(IpgDQ>qw4@NRS}aQE@E3O zn@!D~AjD^Rk!z4bUi_6G+tk2vbw36yqE%h8Q zV^0Ba1rnxVeCC*KjN^RWdF2zn#Te+k<**?mCQ<&NT2A?Zr@gp`pql7l#lYs^`yg&u zV44%C)e`h%Po;YmCLeSMB#<10`Q)Yu$Xsh;D|Y=$J2YQBPPl+>absBq#5rZTFLB2b z(WUTR$XIEpX>zoE`^GHMBL%}Vm3s{oI|B6@Y@Yoy=0|cdWpvdOdh5=+BogR*)8&>JhsGJ64v`f6J%4`qmbV*hGV|sPj(QHlbUseSs*Rns8i?b~Y{)dvQHBVa z&FKZhoW>98G$IHNm5b(?=Lm><>wNS6nY6~!>Kgyv4o#2K{ZMX6!x!lAMzW;XC0FI0 zdM@DXSpG(zuJJl_WUV5HY;F^H70gqF<<2q6f%&^D(q4H=m2t~s#J^^|h^=W*;az86fP$)CN4Ey z^pJr38Db_FA4r8JpJ*RqC6Qn^DcIbi&008(KYM$vO1;0 z&@@B9Oe^q&q6VUmZ5*rszxR$62E-}`h+b7(T(;mzrX)*1(H3*Wi0=TbgoN~4WlhPK z2#ybBfb>_V@(?lBVPC0D%!3qzDYJrvIY-Uzh@B1~vjh)yCdKnH%8B!#v#I*F5ztFV z-5gEGEJ7iwRY8ZKaw}mC!XEG~>Vd-@2}G5l4sZo!1`vhNh_7ooj}B9F%2a61Q!^qt zDQJin8IAcSjDGFACTVj}NQf4{JI}Cko8ZZOok7vGWPmieu@e~uq2gwB;ACg;pB?OQt7W0)|1vwvs+M&{M0RHnqQUA+^YN3yKT|9wM zh_eoyV>;N&QeGOj;m}|Q-@qw24LpV0jcIjDfnv5=xiebT}OwxjMUurXw&9z`DFBKH2Rf{fRx0|xXEFk?=pcMauZGUZO>ExSMs1IzFiSm0NVFf$1tOb1^Xlafs{$}dPBEz{Zkre#udb-;D@ zl$KmTN(e|RAoLaz%aghTZ}9g z$SHGCa}3e#MS?fi#$`8VI~9~6YoJL#pdXR!Hv@(OzSbD#j|_UM4Fll*p`4zY(jY}9 z8S+U6Y+ATR2z%9fih%*L%u;^k z-y%@ep&qRpMS4E%t|ejwte?j+R}|QN^;O__txzYWy^viy_Bx)5`3UaRSNgEKqrQ5 z_$^?XKoDL2LZJ;Susu||ITyggQ~(0hz}-&k-3-3}&F{>*7ZXF(+WZN}#npMvR2JX~ zgX<|Vz6*}&DyE=9X0G6MG3Me6$Or%qnl7kB^{vnr>RbSL&xiiCb|Bu(%7LUs*dK+H z3$zeDa;QLHB6Ep;E+^>MQw72^-ksAuf+B@&<*#hAl0)u!%RX2o08$C3j-;|<8BRO# z0yX&u$ogYqaWd(I_#0?G2SnZsmM91!&_u>E796=+1F#Nu`*UK_V`ed}8DCJWwm&6I zHdiGOAy}}%qrZOZHdA&H1nQ$WsUmrMBgRRj^ZUWRu`KIBG*VMR28gNwFo=3{Xd)@J z{z(rHClz}XteS850F|D+Lfc!11k=06;Z zcuEJh7XlmJIZLqkfeV8jfs$JXMkp7YWeKX`f`WMi8n0P*V4GE)%1XBCTq-2*PMt~CvGm(lK%`H=3_8~$!3ji4xsTV-i%X6 z+1=z+6v5ep$S4ReyQ-}7xU`;>>T^%j4HzH%Urhw_{i|5#462&F-SoW&^cq8D}bpt6YacpY2=A#?of%%+1SU zY<=raCq+zkC-?c{H((O23$fbSbODf-Ydc9Um$->*AaB6pE`AYbn*=MMQ1(n+hD7?{ z3gd{m#7p>aq`bR=lJF0T!S)X_re}fIB_hmfby*%IFo&02hRAy=m{v?Mv%!9|B_QuC zaI8C83-ie)BbWml56^^nTD>)5XJ8O=&A8Aak=XQSjRBhq4N|sDUeq#nMqMq0D>ziK zrezG<=3|^tF+)X^JwVztBdNx38#K>RV^W~kP7=f*DzO$5OXzRX9QP3k!(tR!3k+2i zU4r(I3|GL`YMTdauLc%umQiyOR4Z0`jbto{cf|0(1#L3X2b$HzUGG_;mr0LKGcrtz zCoJxllA7Soa|XG%o*4=BM%O|RX&I2<;37+a4uq%Ei?D-YOE2D-1u+sfC3_uo;xy|J zH1tF#F1J9293?Pd>5mmHmYB$a#e)kPQv$XUujq|I@dFe~kRz1o*%7bAxf~I?mlStw zL`+~h6}&?o8pecbgTqI>v5zCSpYZH%+}AGyEYj8d!vv^4Y30)(2FIY8E2CJFknnJN{ya`v4g$N+1*c6-04}NF^Jv`mGwmrpsE-jYgk#XU~7+;)ZLO=&b z1)NI+`qE}k5Z$N+EGaEcJ!fWk3rVt&ROpN~xh_Hg2ORu%unL*%X0NJ@FeRQx)?lev zB>Nkhoxs*k2>qrC*6Ep}Eyu^>0Efo~zy%O!l4Vm*Z7Qxc*9w)UsKY{8$ln223vdQ0 ze&7RX?*>q~Hu%T>pwZ;{^86_CxUw=OkVJ#adDRzS0W>>I6V0xwd5h*0Cek6074bn^ zG6a_x!BZHa#b{D^BpIn|5?`p#5O6C7onuewKr~Aem;mrdBGed`cJM3TS>!k$cOM$^ z8H_QQdYp`nOJ<8ORd2D@5M`CLonr#Z-3}a@4N5?h0+J%YCL*pZ)UrN_d-=SSM>Ols^(wjgWVUDOShtImVhd_>7YPXc8+LjKZWLre*9+ zk1;STi_18!B_yQ)O*Wad>x7lOp!CrY71M~grneL=IQ?Yc)0K{9DtW|gYV1PFOE48* z`X#xke15WdSuzSa6%jQ>B^k<`QQxS8iobmz%w*@}xuq5h-(EX2y6y!K;vfVl%2IZL zHsM8f>I*^HDLcR~BEiUj1-^k45`3~jjvgFie88ojy+zq@B=^}z)Q0ErVzt#ml0 zr2hYTwBoe1{fe!^*R1Sd8-e$|Uf@t5*lB#z65 zB5NjL)EfgL9B-T6qtO=_i6DU#o+R)%)ULe&t<_bG6B`&~{pb7LS)e5Syl$6-^Jfx| zh=jHu=^w_F8b80Bs;L@uP~6~%uP+Im9w~JxE0_;Hg%3GHLpn)Nk4R`F?jCX1almq=5Np zealUAHNvs-o>EhN#Ban7%VLw$u|dq)Zm`Ms24}~GSvTstEe*86_JTY3(}}C`N1pEy}tz*GSZ9PUj4^DL>}0+3(!ID9x*_)j9q~&K_WWqIP+jlvJ^z%E#9E= z(1_U0^z=5EE05TA>nZLvI<0vq&N7(WZgzwU5j@GnO zWD#Z)$bTWxt$5j*X5eQm-{?a{4Xe246Qu*4+%si&Hhp2#@8!QeIf`5>O)Ebyj z>43_yq)MZW1RgO^1IAE!z?t=)e)Kd;Lz+-gQKi*@UP8nn`^R%^ri>Wqpr*!RBjN1L zv8ovkr$s*{6sy-N@f?$*2k(t|3Cs#FUs;mnCl>d2vnEw#6%V#-xdZ7mXt6;LtI)xO z6$If%Y9&k(C%wWgY?yS7Ny6wA^AuY(1p|y%sB86&q>r${xZ)UiFQ`XnQRWF1q#*`J zflOftgzjGhF835bf9#f=_Xs4nf=+vR!aGO1Um&Zu+&<8&nwvRcDRSJPs>FbqHiBfzPmN(4K-V}ffDi-eeun)*(=Gm%JJTSdmIv}Lka^MGs@3#WA|Fb^7pIy$@ z?YFVIlQvl<2BPN;>gF2@-rtnX5^}UFBuft-v(`U2awO0?^c4Z0W|Bm=9@t|jv`is3 zvM8CwI!FlY_>jM;0U-e%X&99NKqNOKpgI$bds#0y9Lg`90_BLg;ev>OehIVt`lN?t>wZESNY^p)soH7=SQ}Y~w4gHd=>6dGw5{r!pc4O8hQFCnU2q zAWQ+s<88Zw*{Bp#RUVFq#(X%II_&;O)=g27BCs24P5Da!0U`vO3xVP~xj;RR4woc( z+0+SK5Q4+SzR79e(r7^75mY#ZiV&B0ebeG~#(hH%I$5xil>iM$7%C>Dgr5>C zWF>wagJaq@2#Ql8+^6B708pXp1gh0AbZ85VCO9MozWsk+6rvz;QGJf(Xmt8LkQBxin)=(qB|#i8YOtLxnSFHY3q84 z=`yXgODwa;0+g>j5QPn_uxf7jdAXJd_TcUUq$kw)&|yXu@B&a%h(~RuGF{768@nv5 zlwFZaWuSctB3%4jiJpn$O&`b@P%gqPO1uD`(nugefEYBju5yS|kM3XE7001ImLiL7 zDaKx?(291jDEv4HyTvgxOj8;L29;#y&Sn^XjCa)S^2R24nFxCjvL0QJXvQeLC~MY8 zmiFc+eH?=rfHFWKvm~*ss0&yv5b%f|Y9p5PMm7;H6oy*RxCn?-gfWp^CqE=j(mpx| zb;;2MXBNFTjS(5h4K(sE0uy+Lfun?#CK^-HZt)(*xJy4VdDVGHdeFmXo-gt}rQGKp zHX~kUh#E36@@R?pg*x@%!Cd=T`I}_L+cH&Hc5v+>yhzqIf!&{AiHwg4C06&~nDUMT zght7IknjZGY*6qJU+Jp6`rqW_)cUz6vM>FlmmhbFhyWkPVEo>Ya8Y86=8l!KNSjd0 zR%4H27tJE_vHJgqa7?G-qMSa0(bV-Ry0N(U2J}=p?5xbG eF1R4jtXySYG)yFdu}phX1{a$)ONna~46A?|va6Z^ literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Fonts/UbuntuMono-Regular.ttf b/frontend/src/Content/Fonts/UbuntuMono-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fdd309d716629f4e5339d5e5508225ed857a3ede GIT binary patch literal 205748 zcmdSCdwi6|**|>Eeed~v-py_{d&+J$*(94}b0(0@IY5Ar5DX^`2#SJ=f*3RkB1l9O zRH$gFqS8t&Y7n%bw$hebYXPZ6A6i9HOIw~+lt_u<WOrjMDoEaubaE%i{AEHWcW3a;_fS#FY{}sSSAzsONj*8 zRZFhEZu!p|4-&bMzan(?+@(uWDH4%?68WjFUcBO}UAb9VMCE-X+_G)qg1PfQS7e<) zdB~s27a~AjMo;5;8lJNkUbn3GiXU~I!Si_{O>prISI$+O>CGkzRub77ubbPuM7v7; z6yEnDzW@5U*DY9AbzwCL&$-axWlL^Yx-9Xhz2``HVFOX&?j<)ZSn}Yw_zt41ok+8u zc;C>WL%05Ht^NvQ&F7>RPxFx9{`Kd-z!Q&deY$SI0%Ezp9uEfUQI z<JKC$h=<7jT z-fI4xG5obit@fgx{M!r^4S)5haSK}e&DS^FZr=9t;ctc1VjjZ3g+Sx*HydxVQF`?# z_y}B#a*1!6gWeuN5!&`$@MEO)Xl*(AYy?k8Iq;M%bP!{G8?C0F(_{1#nh(CR zj)JGlpk;Iot;A^FO}Ee*Jl!FU>cwGY;1eC$A%V2RUpsO!;yDwL{HOzeZzm&sTD*-& zeP4{8D?}N)(bg=?k1(G2HwPS({w||+C~p<&a0}gxvTwoDcZI!;+V7{grCGNDyc!*z z8B@^iO~c&#I5@Tz95`DVT|O#W)FKb%@p@P!9?C(=3_wIEZ+|1kkB?nBYFLnZ3qH<` zQSiM7DfqZmP#vCQ$k`%|2Ok9s-s{my-s3K6KzK3ceiR%x4rz|j3JTGS$iV}-#K-1J zQ2ymS$@zts@Li)>Fv_tW%)t>ZOrrD=UU7jNTZVJy@A(|(yv1|oX?VO5&L83KPDx^> zOXcq?s1sN;T7xXqopX5sdM29!Qmc3#Jbl(McslM+^I8}!=B-mpbnzV4y%92F1HSFjm&*n|TOz32Onl3cPXR)bcvho- zx%A{;3*yP7SQU83C1nB1DL_APzT)GZfv0kSr_KiDvbGBCDL{=Dq1I7I!dA3^&ksGG z)6$d6)@sCeBR9?u>GV9!7(At=j1B3FCHc-<$K|sPZY@%^plsfD-eNs^ssf?>nM<;A zq$)=*@VsOwJA%?V&lMq*$Keu_zvJL7wg>Yy zJvMyYdB1t3Ii{T*1DlX!ROSCRTW)s*T^^`_>fo=fdO z%F%CXck0EIGL?~Xr<793y!7F3>aJA(&>x5XG4#>UAMxHj+WW(!kQzwsO({|?q*kO_ zQ?01S=r{Fb>h7U;hfd?2Y$U%CH??-?v!R1SDb)9pZ|d>XnxS`w{+@ECgw*s@jnoQW zQ(hllCeNMwd8$iWSe)9Q+BtMSrA@_Bj#N+TGAZ6@OQ;2Hx$Ba)Tv9S+r@oiEZRpU@ z2PwnQzf+B=yl>@?)jaiD>O+k5e%b@9#ylR)J+&rvcd9Ej17qJq*V0{5UAY9{U##~i zdo3h<58jNX8TNr=Q&*+xF(%{j-TF;`q?V+%rLIps3U1ko^1d~K-yWI&=()7)sHJLX zb~4nOuy*k8$mbg$f5Sf`bhY&K|Aa~rCBn5-#y?mm&#O|<)-`pV3#;wdn8Td9$pPviSL!RQ zshoN#12l`=pgxKEu~L79+3HPwiCM{Mhg=P?Lk3iUVhsSTqsr7dNZ%^Z28lM(82Fp02DF*Rg0@Js zRifi*96~05eg@s67PO7(KqpCbGS#O(g?`)s+D?t2Q>h8GgPK7*B{~iB=6|rNwSrEk z@t~K{1ki4Y&Y+3#&!jfcSrVO1lT&ADjzlk~DezxG?Vvq06?86jfX<`N)F;pgIGs<^ zKo?LK=vAN})75kt=t7BJgPHR&=F`m78LS|jE~Z(a*U@ay>m_;v&4GUjT@HGqL~o)V z_?Ob$)JKraSAyOw(d9HB{#$4PXs<+9&{e5_(yeqg=xw0?fbO*r^md8fLD#^)lCA|^ zMTKYc$nNH0tD71{>>tMmiVpGg!NJN&QF6P z^nJ*|=RyBK1E9xfH|RT{@6o&T0_cCy9?;{o7xa(xBIuta`X0TM`V+lR`#?`f^aI)t z|4Dio6s-jPGrbD>A^i;WFQ9*UnTlCIspIQ=@+12>%&q2GX>r8hwThkgtCDZL5$8T}6Q932Av9Q0lKf)0cJOQPrL2>k!1 zw?Mz7->2T8ujp;iuO)hc{s8|F9Rp2C6lMy@d5%nOkAO|2PqIDmXPK-A0Uu(HC@{CV zbwdvcd2TmOto^_>272{zm^2{|f&-{$2j({CoZT1J-~e5DY{Dg@Mb1LQoMj1}#B* z&>hSQ#)7TEp5THog@v##Yzo`Lu5e~JJDeXb4cCMhhx@}1h2I=ZeRAQf@VWWC_bVZF z0ed|DQAus|({@(ED%p6}!KSeuHjnkPRqR3bkl+$B(Z))tjjyAP$I-?$Vn5n=zxaUo zl=zIeTYOVSvU#$bWb3n5Wqs-+pUda>wffqJ+jxa%Mn=Cw!m!zVKW9E`O%q zFSW5sYU48hs_$rH=WrX%Xk*4`8|VKoZEQyy9~f>UeXcmK`HD$xWT}5cV?34mOX|JU z`>7L{KZJQe;9H^@LvK@est%Gnf>pvi^d!;H!+7@)-i^T*AKpt?4{2!6&nB~Q%6s|b?V5e!>4|C>djNXJ@uPYub(=2>Q_7+{|qJvtBL-c zH<%jydhm;rFMW9O!{ev22e12Z*~w{xy@Q=ZC%2y5a`Ha7_nz!Ox%T9WlXFfspKLh! zx08Q4dHm!DC*L~x=E)-`e|7TJlP{ip97Vrr(|Tx#8fSfA{Neg>Jj(`Ax~6rq^K? zz6k5xt>Dg1@MjmB&Msr!bd5A0=dmla5bW_PiEb`M+6?qwU;eQXU| z%kF0D*bms_awhwi>CcFJ(aTG`>69WgVL7Cf z67yHh^-}1gdg!4>*i_BXJFU<+?a(uw&@VHfS9&1bxZTD_e&~)t=#1IW6(iWUMWGw! zK_}!kgF@(lMbQ09p!1bN*W>oCN@>462KwAsSVU?m3Eiz8I$I-jwPxsOt4s~fw9nb4_bLzlW7I#dsICs<~&jz5Vtdly#PpJJ_i1uNxi z;Hd-Ps)JY&e+{mB11sQf=}mC!5ju?3?f2m6cfhyrV&%FTTFC9NF|EePJ%Dxh9_TO2 zp@H1Rend~u9`+P%U{AB1kmQ@#qZq$!;y$(m+RYaB7}nlDK-1`>b?ix+&wj|h4}Ir* z(AjQ-=J6N}Kqp(lxkTa)&L?lPA7f>_m0gcDfpZBT$%W8ut_1H~3k~Im&{ci}Eo3LO zjAvjKc@CNcL9=)fdct0&!*1zjT90)Dd`b_o1#CXMf+$(r-8HSVV`}@9$&=b9P8i?X z(%jV8P+ym<9XGaSOm$UdMR{4gupmDg31^3bK9|jGGU~M&wMwaw%S3@uep9Hq$3GD1 z8IVOnt*r(8IW!jmb1w?$8So>h`O-K8ex7bFUR@G1iI`V?D`qksGdUWQnfx_WQ;_d( z3i$^PH-`NC*vzTj@ZZ-Mn&BTfBl#yuepy6%(BmNxKnj18Yhj~*fc5yB2AY>IT;J5w zSdh#fN>x0GD6)@L$ogt;B~ooUy|nGVPMtN?)0;t=6PPAWIQ%wKqB!Eu?Li~1;oUH`dmtWKGGGhUr+XU#$Ryl!O=q{1Bpuo` zU~3qlo-2n_4aA#}7A(@Vo(~MKAkQl_wR=DIhJ(9H{hmEs!pz|H7;rRTP$Et1yXRju z;Op_s2Y+7W@Ad=+k~7eKGeX@9X7Eu8nFewPQ5-%PKq(d4_N~|>kQfoT0H?UxAghH zRLPTW0P-JDjn+wqO31&dQ@Wi0wQA|uyh6GDrUi``Rq&Eb@gP-jIJfVvr@;GSxHC`% z6(7!4-iCsF0e(MTs|EzLQwrjv=<*LxyT3cMAT%Qc9!j=%^TFYLEsgKQ&d|iEGrOhH z9_Es1mprB4SB}0L_6-OPV8G^>G^l(`rRNsudGxXMTd&8Dy!NkGg(h~c=Ou@RGbI1| z@dE^wO=7xMT1wLevSvuiQ1jf7-{fyzKX+eh)x7n)lgaff9K5Z{U#!R|FrJi0;`{am=J8}07$_m z|9sv#eKQuW@0r0_n;hs!{9^+wG>!&@(74@9Q0N9Up#}8=+E6_YujS#j>2L)PSBB~b zn1dBi((w3G&p#z3f8Y)@e}6@uZ(r&_QunCN(){p>R^OJT>40gQ5%AzrtM7rOt-g(j zbw6Hiz{`8_d?(!Xcjfu+xx3ZZk9TYF?k>b#jqsIt-wU@7;m@ylZN*zF#N-NJsChZU zUWWOrfl)HpwXospuB#drbj@#=+jV6_PuIMLE4nUknA0`8VOH17h8bN0`w(pcGcLft zl?yg55Q`x2<`&KEnY(H3z}&&Pis!FjG=~+<>6x=>j@aEWz3Z}uuCC5ale#)KP3)Sw zX+l@~rtw|Pv+BE=X4PRuM0R@|OwRVPO%wNtfA5$$plY8r!1@Qmot!48&Kywm4^Y?4 zS>3xCyMM;o`|hK9@5BLbXZOH%?~I89t?(qdXB9l;-R+?I8L=3}hCfS}EycfOOGln# z4Day75Ri@pA3Xe73c&kiu1hqq|BoJoMZ*Q_VfVs^LBoedl%&&bTm?vd0ehRIUkZz0 z^)ev70Wm&hr9g(Tg!Lj+4U65E&=?8scYQjfKz`EzwlmOb=ywEtkB4_aqgx6suo>DP zA-n;$rw-_O4G7_}I;aP99YSglQZD&h;V*!15p};9uVO507zaPh z3X3Is0x8;Y*JCS@vKu&uO*Z1FRlq`E6M!9ADMQ+Flv|+!P-f*c;1p5ScCb|v8|+G=8W(V$Xly&t zIFwzBvTG41xeZJ=pQs@lUA>v8$p)MwYQ}Sm4A=_>JWezod5lN;35Y)t{)t}{+;xE}nbQ7L$+6SB> zT51DO#?ocLcHj`vGNfI0jIj9t@_}w(4KM&8&GJT~-XyRDK%INv08r-@QQ#cWZ79DF zY5VZp*ADaoI|1Z*$9$rdn}GwsX`)po0C}xi3~U7s0_TZV<9RinS0mnP#Jdae?y3Y9 z0(f5Q0#J{&h_@E`twp-E9}(UCJ_LylK-_gbzy@G1QU5NY^)jFc=mypRJnT4OLkQ#p z(*T5Tm=7!?x^FRn_T6_7I7f7UCeQ}p-Nq=|MAq7pby^kg=G_)jAKlZgK$+VPYOC2@Q(-OB*f;|0WdVK#s=UqHG&CIIjE93$GB1dwj; ztH5cZ7i~Zdumso+90ic)OO-@FN!Rc=rm*`T0Vk*HHFry#Vrg4dJh$jMv@( z-UrSS9gqPoAfM5%wpfe{U7h`zY@O@;-_9gDCUEOrpP_zJEoWzqJ#c-bM7^sP{h*?;kse{)zHF ziUN4|Q4g>TK>9QLh(1Qzk4pjWN1BgOpHEH^okhC;nN9R5>iOxbz##x>KK%&zn&>lx zf0ha412sS!FdJ9`tO2$HyMP10F#!2~hIHplKsJE7oI{**DC={CeU7?+UIZioy!#yW z{Co+p3fKf}2L^xxz)@fjI7=|*12zD8et~v;fwuk&^*Dc==-+#ZzC<0qLfWr^3#(v> zg`4UH`e8-u#aV4PF(I3nxR;pBL`)tfrsxCC5mO;t4OgoJwi46%fwRQ)uM#sLoe}9x zMZh32^D<(V0b$$9C+{CM9hUa8QX}t;m^z`=G_eJAeM!=SX-IDhFCxaAYO1b zv5<*aHphhav^Y*Sk)l0>Vp9MV_ZNZumso!AbbqMvBt8osNdKm zfI5yH08SGdhqA|Y1DlA|qTb0>z&>JicwdKn>vcdWv4&;D8n*+7fOEu}vWYe0T}vCW zR@ABW7=X5pj{@xg%9wyWu@B-IK-lF-cR9+q9QC?3w-8?oDT#QKuNZf_)Z$86vbv6aYs72@3q|LQ2vOYE*}0O5C? zBerHQv9-&H-Ho(&9{|o0TUQDo-a6E&e*>|5knWyt0RHu8@A_@T?nNKm*ADCi-Y0hd zVqzO>fb+yQAxh&^BeP@f030*Lp(KHv>v588l30Mb455wR_m0LtFN{a+LN-VOkH zeD5G|jM&32APOMf!>zbpT}14WQlJsoO6*ZQKe~a~_hrC2V%w1Z2R+2F{;|hb5!=2Q zK-d$5#Gb_ar}6>RdL;7$Ek{ zK>+c8g0g?Im)I`kv#X!jvxxH?{LkUt^P7ncpkBNCfE@tBUO=1o$N-eT2l?+o{(DjW zUexJDxG&=Q#q-2o@&m2F65uGYeMQ9fR}y;}dB3ui*sI9vXUO;G*~DIp5<39*7b;@E zL>|BDA$AaDA4Fci#=Bo{1CZzIc>WFY`YrN)b3U;{tB4(O0SJ2wX^z$q`#tjcJ>tHN z{QrQuA4Ax&0b=hU{2k=^E&=C={ntTaf1FM1PssC6i2t4nKpyYC3LGN#{z76WbiiI> zA0YfB{3rW>kBAK-pFc-|W5hm0yuZi*8?jUKiT!mkvA>-rb{g?dX98`&GGhOYwEsZd ze^vtLh<$|TGb&&^v5)fswBZxHKf9CI{|o|WiG7OnpEd%$0Kz}r2fP8GzMuJlA|MGM z|IhILv-fc&9p#=w*g1rqTLWwc4gjZ#eUAJ-M}4qPF|1GQ3#9p1KkzE>5w6+$foTBV zpU1oN$nW3C@83ya39th=M(oQdfc(EioG*_P`wDga+C}WbE@DHQ0OW;}L;-t8fu@nb zmH?|r5L`eM*bWSkAbtdVO@a)+L6EnRphyCTNKjS+tw1-fwATQqNKhl48sTb$tC3EF z^x6X?=-}$ll3-Xug7H-nOgl+1?MvKY+wWMD)12rMVUYwfV_*4chMo>JPF0w z0K$t`0eb=TQHcvcSP8;Pb^=F%uSrNmfoTB36T1Mkr4;3r<^!llDZ)z;zZCIH5x)%a z%i4inU_0;zaF&E}6ahWJCSV^hNJ6C!s08K%2(LtYDo>M8g*>WS zfnH!IaGZo{6@a+a3xQR@R^T9TmV_~A{}{v{gZ7Wv4jcl`lTZ@{x`BRRA8?w4u`VD9 zECeDq2sQ0)fz&79w;5-Sn$h)=`KzJ>}YY|?1j)Ww_lZao3cXcSU?lge- z_2|R;uSsY?zcs+$um%_a21#gC0YyMJu!@8xKd_yI=4{{qfO@o`9xX`MvI%$q5M)uSuBh2O3GZtcZl}0TSlI zojXXvJQ+|5%m+3DsMEYtBwU#ZOanFm2T7Q30u}>r0Ov_q&!BWW3_g~ss(9R-NF+>WN=iybJ$S=Rua}g>FMM#ubcDON zuRDm3NutbUI$}x(z`0#Ob1MbQ`&R&C6zl`=I&BZPYO)B;q&D2&L zHPEEkzSQZx*v_`)?MofstJY9k&c4*(9urN1dwQ?lKy8tIsk1yFh=62`ktUg=Jf7Z< zFtuMplkEBTTH*Tgfk?TG|!%#RlqmS<#SZnW5~6hBdNrUV@| z>{fxHz@A_!(+41&y%J|iii<`MQ{bs687GvL7796Fw$kznaDl_&R7N79pu%p;5}a8g zXA66%EE377a5(-uyEs$l$}P?Gl;yhHS|>ysY-W41xV*~jk9mU0BJbp>6KW@09i9nY zTD#Yr5%SnI8ds<|JK3(idcI&(HLJ|gh&|I`(dfO=%A7GBnx#twm$pgo#19K`=lV1D zq0o!DW(05L;9kou$=1QlvzbEXCxxj(p>QyIHY!AeP{oA%M6!t_iovo^G%1as88n?W z38qgRDTm;YF(xaG`HI7rW$3NSZb6(*tcz+B_#S@$Fb8Lxxaq{459S=61Kx?Ri>a5`PHs?s4< z+xQa?6&Bs!Hf2g%TYGz3L3MQjF!X^GfWYAZ%wG{V#m{4&t)LjrXX=^mr8>Xa0?y(r z#Q6*yv&SsCXZL_{3OEO;;mKF2XcGA9bke8RQ=8wVqe*^~7R1F_%k4rUcM;;4!Ihl% z;GW(Cb`|!ej`E!0N;$)om=*3>{+@9c@8N=1kxRw$XjEw`&G*Q%49hiQEGZkS*DIDP z8^taO}^D9I8y?b>4*bz^3rWm-;# zyTIZtiZYKa*O^%#Raegn`x_%6e>9YlU+s_gLcDmBG1cQ8IDAZE>p;v(tnRXTLVcrf0>kQERc zy!)MO)tq_G`1q27r8nMmQ@(I#>#H|Z&YwL!R@3$8+xtF*f^kXxEre?(M%0^EgV!ex zkCL;ff(ui*iC2gdj2M_-$pg)5wFPyvky)jl308_IvlD&fUEuRueXRco+^E-S7gU?r3kgIk?old#lhc)|9 z2?Xllk`ig?AY>06hDbStAp}D@l{t`@U`}OD1=tk+oC+txM^{<|Rye_%%;%}L$(rT% zpwSd`%A4elN>6xlNa<0ATKp>gbiK;o98$U!*^}5485KTxLXp)H2()C$OBBBH47pY( zbclwaC3|v2sff=I+vEQ%{ao;dIX;jFRTBgzHbuxjel^P7`;S+}w z>B=8IQNoph1mr)KL5TZM;m+0{|G0H0%iFiFdH;U!+m_T4+=ROqi@Gm~wSF_HRIs~R zwU5eYQ|%c@RL;Oh&Qui_Ime08987C1&}6n)LRl`Q-&^1fN1XBIqA4x!4(PUO(VV1A35NVrIv)J>(E65yLm;mQKCfFDgMEt|+ zIA^4Ie4U9e251M?fJeKSv-5{y4=)?PT*dnII^?kyH#KAQ#Y?#+zJiDOtio)9D{(Py zen`)7&n9i)W{(uj;ew=f@Tp}(guO-+wV8Mdgu*?VG~kVa$1!kjSMgWDVK+;1Pw(}3 zsSQ{B4}?;=`1NIsn)g9M#bZbw-llx>B(w^95|5lBUGUXx;9t} zf*W-CwIUO@tC?DD%-Lwa%)8Opjqa;GW3Gy0DdZv;@)r-W*qp<$IXA}sQ~I)tdimld zG7L2$6f{8SW<+H2>{UBnu7nT5e%VWw`xWp(aI#O;no z!`q&IdK*V#R%0~UI4d#i@-d$X@)G8wiRzOPfiGt)%9kNOIv2eXNG6zg~KMyPN^|gOg*eO_CQ&}Y!H!jOIxDGk`4F;6t)$aQ%W9B68&NHl7er~RU=ZyAdmvKE*S(5y(B#r1q0AX4V&}kiWaO55jL~ct^A6pEQ;`af zBiCm&dm|2aEZ|b)s{93&{<(A5VSi0^rN@|;pJ!~AYvp;Z$tsT{FR#GmiDc*uHmjmq z?RJ`Gr2AwH=EBS9lM*`jVj&+5Xtc+98{r=1i;Se<4y(M!_dwgo<~lI%ngDu3@_2{! z4Y<;J#ofIss3@7dpO6<^>4lw7C0>ZZ#pjKjPZMcnkek2)jO)q;CX{LC1Ost2nae$< z4L+Z^AzbQos@3sCP<_8f<1Q+qjd_>d;8+Pg(P7;Pdl~QGIh=s)&p=~_W{7U)D)X5V z@c+p5q7ls_?N*dXYfA|G2uX$J>Y*~H95OGhcBGdau99%Q`Ph_(%)*+0-Rp?wxN7ra zH8#J!tF*Yez>$a+HG3*9t8o_R1(YUJb4_g-pB@crXVjO7W$0^-0ayN*P;sNhFts7t zRFbLGYQ+|n1A`z?Hu&;w%nJixjN8O*>4l!DKcf27`_bVs41;_4xIAlZSbto{dE2(Ea}D27`H{>N1H5 zBz^P@+C2vxfW4-~1K$#W)=LLAJ@}Yz=#PLsWDsAz`&M^FSG6mi=f`k1B%BBO6_p zDK>JpNv|Ma8>}F6&~yJOsD`Hvmrzdd%g9VIV9khBVD2bvBMV1aX{5Y(*6I#r*=3D| zI#-pybbP+eQP^5?^;N(2mwA}hQ<$9a3Lwp#13xR_dX|9Bm7Q+T2g?xkBq%f-G_baF4u3Rl&D>%#ZO$lUd zf{$ofz>d0pU!Ggt92`2v`m>sA3l%MoZ&{h!+7w#;(9@kfZxOeo`B<&Mo;5~enE%CU z7y7Mom|5XU>Og{bsKn-RuEWNo==Eq3hAQd;3rC|EoDdgrp(4D1?vNId9-bN#B!j!$ z8o+Z+yAsRu=VSr{YUH*8qaQwvvpLV;9EWRiz^pYw-s2cqh0QzrdUZ! zzO6iT_0TV&NCbQZUPDJ~G=ET+5zX}GxV2*%BLz=P?(r4Zc*{C6imnWfE6mJ_S9!`N zIg6K?LRnb+vMp6(O^$kI)CW9Pizi^pZ813{{a?U%4#B3g0>8+~rDyrvlcpBdud|Yt z=I2VB--I#7^gGR$HfgqDns7H6MMs{UQrz3IhiF0Eax$JK*i(6m2F%T3s$g%j*P+5LPHN?Rb_jeXK-E2(v`8Gx*Y#Im zbyZmu`qYgiA8`Kq~R& z{Kgpm@jYUNTp2D4JMUv-okMr9)y~viO*>k4H1Rnt;MY}auy?u#vm1XmBxzM(&qOMj zQrwQSQ(VD7ttmcd&W(pZ_$F(t00A>l$Q~KGn&WpZOx|)y`<5iN3eFG;&Jfb_g$KCD zxeSKLJ)4Z7WqV-2GQoWX7rRZoBe+OVh$@mR#=E38&c zA_r^!X0^oH);SO^31N*x3Tz%mkl&nDy znOsO<;tA9$bex*o;1t}a;66k7Qo^5-8&{}uEDevX?$et4@|qHTqNmSK+@@U%U^%_; z!Qu3B`W@39V;mlt>U_KHn=N%HO?KXDah!Vq%x{X zt3uUzE>~hoMKq==D;U41DHyJsUebNl@8p(%S7p1D`{g5U?NL&im?79 zA`!MZ{Bia)b6#YoJc%J!FXSwSQXW5fa)<62>QxhgU_2i@V_(jQ&x@SI(IVnQ# z`-=TaxDk3^E>+U4$*H%Muxm@$ib8fR{zYz$2#bQZ1%7AiAU803(Q=b1d%3GR&$HAdXYwk$XGLC~udGj7=j+1{0QmaNl^lLLz?HT1R;Rd# zEBN1hoP6(M<~vBfqk$QRYrYB*2Lz)^Z_cO>3fv)MG#WJ;b8>S`h3#VkhKztU(X{;6 zLaxtOmG8;OE%#2V%P5Ju9NBTVJ4YoKM1@S~mMKKR6d70O$j$aB4HIi-U(O;Yn5gmO zhkSV%+D45d;`Kya8pi)}A-BIA!rb-KPxq4tT!HBY1xb=taMSy8tjW?Wggc@MOM7o= zjRtdY_osaNM(xZvJnP}U!9^Zi?CA~C7Lzj?Utf43TuIss&f)>5lTHXlFmceeToo{z zt$q3?zu(&@Hm8Lg->whu)koE!IU@`*I$NbV36tqJ)3v;U9STh;sF>53liPfGS$I;| zRbQQ3SD4``YRK^>gKnEOXUeUeQ+hk{Y)%-S>t|ObFCUj>#DN~4Yn*Qmfo}|u=1obx zOVTv0(u~vbRzQb@^#Q9TJdWj*Wn5}fGNm`8Pg7^^lc$+N;s>xpy58Kh5DMm)r9CYh z9(74XvqQ0oSJ#ZItsPf$^~BiFt1yi>7rEzNq0i8;^69-3gGQm-7;NhudRg?0nNxSi za*Q5C0e)AE3r~;-S}IR^l}b_6=;i9Agt;k@PPIZVSIbtgI`s-Z6Nh>50{G4|n%i&7Pp=9=hXpNYJ513(?DCQ6P4&}2vi80IeaOTWDS-vR52udVTWTkcXWJ#f5M^*TbO@n zP*^nd74LJHnb`NG{9{SGO0LifY^g$lWmvgFUB?tFWSmDz_@<2;o-Z6Ofq@S>4;%Ji zm9Vo=@6gYCds)2@9tyysce0uD2;W!lK)zO*kaU_PbCQO4yT;F#cn#kwadQH+N*E+8 zOGP`8)`nx6K2G_ndYZSAXeVDI9W*ytA!c=mq&BE~RiaI$5*@IE_gWoTq+st+ zxvYkzFmB?M6V{tLt3eb^<~mcON-cFVPRY48=#tK9hPU8p!;Q3NsbYM&!jgoQ2{#LJ z(ESNBETQb(;+q@&txaR?b26&ynnE2Nb+;4G&kkEi#897B8E z^lz?lN=v?^aYEmPD{XFF5aCHTw{g2vm`P3*#z&@SIvo>L9!ZX!-^FIgot zwXuxlGp55I1iMYEvuU+Dt)kq`!fvK_llwM<-exf9iL8pHg3AjX!O!y-T+lSYTFp37 zmS-BQOSvwWbh}|_7c*Ff&0}!a>5Qm0jx}wKT0Z_?vaEQX!$ zsICBOnK?16Ex@0iqc`$c_*kt8hea9&F(kskAgK&r^-QvvmF+l+5QUkovzaK0tX))T zjp{c1L7UPChmJg5e#hPG>xTZu+;#V?yQ92q`(ux`NOKVvwP2rKg#FayWRV*e=7~kr z49bsMP~%wr4ujfeP#cz-t#U5(8RWjjSSMH4DH{!Gr3a1TqlRJo;6nN+oa+I&EHTU} zU>ZJ>*92=S$}=ZU%N?62%9_}@ZuvE3Ll$At#3k3$$Y#Pu#<|*f`rv2f%Ya8A6CC z#TNM{+r3;9uq~&g*3?RVXP>dz+b74LIK)&%vtoR&{4F6FvyL7S^F^*usIXyygGraK zZ(e`()RN+k>Oi2nqqt;hwSQWDQ!_qI^{l+})+srB8ScEbJrZfZwe!~1t8WGPTo&-R zHMmT?5$lu_Wjv*)TVbGgPgjSsc1$z|s_hls*F4--Doc;b=lLXQ@L zuLAR#pM4e6@uW7Nuax~ z8Z}&LpAC0Vn&;9BfOV5PKF@l(w?Be$Twi(!V(a?*F8zR{R2x&bwEj`NS& zdRMf>omCObxN24gj%+k;TXU?S-WtevM`{Z)uDdEwT@X}f*d|vO6?t=gPK_=rS{|M{ zOQ|s^n{=*%0(Z8@p*8vQYhqI`QyUD5My;324#t1f%ML?^E3vK`nYdJejjKwKuTa); zO=m>UIdTE(D#N_Tw~QTrrsEkXsu$jaa>4T`!dM+d9vRSW^hW8jkkQ2Fo_5&U4_DGf z;o>-fzp*T}dsIv1ZmXhB--jQ9L+D5*-ETxD-v^dK`j6OVxz`|kSuv@|(P8%GXJ+R6 z%pHy*O#A9-rR;k{OXIZ>lPOXgXZH!z!+OU4GS@{K9URtt-2w`}Q8B-U@)JTAKK=~rgXeEI4ADDNj!Nzy@V?Bss@anC_+ zc96^v&SB$?%LWfOL1F_1!sWO%3htI{6lwQ#(#AKD8b8u%ppk*tK{$JZdHGEiJ{{ED zMGWpHLx`pJOZ!Sbg;*4FlW|KB@l1$k0+VNYcL9%Nbmjqk9>J9i9dO^^8DqK(@QmRe z-Q$wn?R$^`p11EoMWpv=1>8-0pjyG*$}0xBmN`$=AoC#Fzh zRw;UwDw|TJRP|Zd^|-~U*J&+UeXkDcuvVw>by#iI+q4=eS{k*lgKTu0N)4q|{R)!W z_iCBeVYAsCT5F?TS7+0x)k;O3YS_dA{R!$5#ul@4Y#cKb|0G>0mNu}&a24;JbuknD zVx1fV&ThQXWxD9OIDP*pE$byK=ZN<|+yv*31oSQZF6JR4i>f#Ir%w zHh1hp+jn+e_=>rQ{wBz$?R@;faSR4)hIxb^(tu~}uuIoj>;{$Ds5aRRIyHt*t}^RM zWm21Z%_^H&Wj5QPc9Fqu=*7)0J^m`YQ?FM$%%(bnzD})bv=293YPPg_I5MoA8xCUA z;!58@G~$!ix}d3tpq`5fXGKE9#UZvzn-$Elhnlly1iDL}n6+Z{j2%TYL!QRgR$t`< zO%tANXW3`Y44s_3bK0fz4Xm5YRcTdnZLiK~(;0QfrA#H4_sW<}#$abQTXfnwqlz)P zEWI~Q@C$kAv5B9MCLZoZUVtw>_Y(XnXaY6j*CM2to*zm%R%^F(M%OduN((mp5M z6$&Ix3>&fg1ZKl7f%u>E!WHWDRiX4vA!~w#nmd_&n()fk+mUuT(k>V&R}M=Tsb$KU zIFi7Pl*3q!(&fr=cK}j6!4~j>e^@7cz{`!Y49P~Kpt}7egVYFMLJC|56Dzqw!A}fD zZj+Yr17-a08lr+<u`F0KviH?WsWk(%6!k(Z`xGV z_G%zO;lZU3HAE>FKiPcSEz4eMD=940t@aix@1dY6D5!!#BlWwc78K<58{3E1cPN0+ zjM1Oz#T_*np8r_T(`IgN3U^q!x_pUE#F;(|Q}7ELDPOV4RFL7!4?4!?m$u|vyjPS& zS}TL0ik9r+xH=;ij3vz)^OP|%alKrjw0Io_A-3IJSf4ZWf!v_SdLOL_8nsS)j^CsMHskDuIpxU{mIE6ot1cWO4}e%4=>t$oAAxLo$d?Vb{a9@ z;-EdpTw&(++w|QPD2$I9t3vS!36HajA4L>E)}OO63ljR~xYr z6eyUH;pq2HRjYOV@{#eA45i#ukiMB!A!+Ty*Uv`|G0OQBU#@-?N1NxA1sfvPKt*PD zGM?#<*GK(hLb_0EUgeyI@ZW1^*Lc;s7M;=xn`wS+u1%?H(rbM+vru>x^?VlNVL(mi zCM_5WzHPyw09bLD^NwGoS5Q_6M@swf(lKM$;s22!O7{ zFAb!3n4|2+_yLQ=dFbd0^!UZ*I7srDhH`Hpo@Hno>x*eRJ<}>nI;#Di((&7c zzd|T&ukj#lulc=jhY7re=_V=WI8Bih3+%`wMFZ|pu4uqbk0aluj$W!kLYTg#8zXR~ z`(1FM(x4ABR?BocStuZ1ZR7o93(D^f1aO^A)o+}d*-w15)4I5{m*w^nY5O)hTfbSf z8Ghzs4@e9;GVJ_*!0@S-l8KjJHMCdWH7S3bNo$;3Tr;aCD>82KBjXa@c+e)Y_inz$ z+d9#J9~oG}$r+{NX4hoBKBmc$U5MXxO7}lL1P^#D1;N~=p_|j=+s&TE_-5gR@|XL; zy3&oNC?5=r4qRyqj_uV^e$)u}I1iV$TNr(~(sdF3jKSa%2eJ5=OGjxJ%i6QaDn1P~ z{3?Qm@7uq*98!?A(i{)3Rym!jLdaXuCkiT2EOfa%{kDn0e*Nf>Cei}<|8gPWTL&Iy z>GCMQ632y*dGv=Se5PPxR7Y}K%6#66_C!sW_qyu~#%CJc4bj$dy1eXUgEf%n@>Q5) zDvJjp*?oqCdXlOKa@;x}$g zygy8QdO#(Yt|fAJ(}s^!YG38#_|TW`=#(0 z?C1e%Oy>GrT9~1I{0@oFkIIO5sf{ajI=wTb58}RJf96!hdeW^mj>oLR5i$0-e1miZ zOW}oMX={k}qBC?epR4 zsW1D!rlG$y#W9gYwMyYCYKfzsEve~jl~hk3Rqe-rl5jeiDP1wTOBAzK8Us$J&d>Ry z1NHN*HH_A8#8QsyL74IE;>!J}(VUeI*X{%}cnZb@B9pLgjLnReUQ)NRq6TdD%*{G; z?ijXic&tCbSUYGzvRna+=bc)GO-nYd!fGO$)kb%ktTtSzFxhOlI;vesdZyAlwI;c3 zyumn0KS8d*=q50^`A^M82AB(}U#ydj?n2h7_$jcQ-wdzd<`--%Ft;nX5gmH)$DYQ9 z8p}LuWo>OnXJ^Ir`Ez3{Qns%06!J26h zSx0_#&~W#0wKdb~E#bqQ71HvtWIt^l5<~eO&G7i5KDpraqwG)MK*&Z7^fG=JC2e6* zAxSL@pi*|ZYh^|TmPCEXzcPSYkw_8?{blQb!ZomZbPEd?`j=3LQX z^5(j11@=z%E3K~Q+M%aOZpJ)G7& zkAM(DNC+@fo^8Mu$Ouao#uj)0zu=DIAx?PLPCom23c|LMmzWR_+&qMpT;eD(U?t9t zabj-BXD83*My>a+wX3RIt;Wf_57D(xo!Yf)pFOO#_8R_WUU;CxuU`N?Cw=&7!=EAg zlOb6!LskuPaAx%vE|{>x^dWDs4aA2k2pPcRM5#8&_iF}XUdVxrUTyqpq9-L%K{THT zdHAG~OPq8PGj{44LWN70Vg6xdNBwhg3YSg!lXS3tm>W%H= z*=yHMPOMooF}e1&v3*9NVC)+kyJ5Can7v_a$Nv30w(p0Tm*~ZQ@dDCp4*>HhA}A!7;KYh~q(@e1cc`Q;QBL{_w%BncF6{BV=~Q}We2WvJ z7(LgDR2i-@9a2opW(FF5()5>U(@J73?%z6{uedtW*tN;_W|F}6B(EJKf$Yb-_F2sf zKk!5o_37dW$zQIotGBZ_#&o-i=lf#k`5rL(5n2a|UB%>PX>xJep%*+wkSth1x)j=>>$R{OvS0z8a?OJ_uPiu5fdXI0MME=x|i_`T))FVn}>%Lti;|J`QK7k-%i2Ss# zfL|%ThUY`xF(YX8c_csd+H6kRA|whi?;&PLwmujWX^SHUtdO?_?ta@H`eebU52dGP z#n%fK`zD7aKpamX_shSE-^YHaC_goVc^xiQTk}=Y^yX-~IT8Rw2PL~L^Lq>>%I9f~ z^Lvac)XEo04F^i@H3zUzLaaoo)1Q~ae(HA0a5+ZJ* zn2yJxu<>}*w4w>SmP#Z|(MOc{Civ!^@^_dDPBJ*q`@eG&$HPLNzzupD(vC>a?A}pq zWCW~cWb9|(`j%5GCW-@Lw|BZeyt?E)e0aAwzwQDt7q@f0HB9X0!n%_HHWkS8^KaNM z=OK@Q$9SZ}BN>T|K_YJ)>t`jdXQkP(ki2H00~!v!8W=WoiuP#Ou?h59=0jj*%|0qhva+5pr+ z-@?k<&mw6QyZn$V&>32tu{^9!pYweVYuJHkcLY?tuM<$=bL;?6zN$nW5hc9I z>Dc6x;)K+25~p73L)I|~56Q3+QfrYNhy2B$+7jOnHU?YTmgb?-4eo5d5D1itIkz}J z_t5>n*1YMBlLLnj?=KejA3jVWpy)STf5hLS-~D3aGgVR`(DA@XVieg$IYk=fq>h(F z3@<-T2-+TB!{tB31^CNrq%g(~`Gw)dMU>WkgxC{2q}ZmzDsi+*{zI@9kn=KDlba}= z%TC*gHXkO6C1`w%l1UpKDUEHo0Shfra8yw#8j5MTlE^0BZ&AW<$H^9tmz?o%{QVYZ z*y6NUy#2mXwzQ*ku=K-{r8E%s9d~(arQ)VU9L)Q915OazES7lO=iLM|p=)!0Hp_}Q zh~@1j8|9m|0BJ7$-{*tbftIw#cS5^g@5HgdezJJt>|PzHbzHQ_;(g_$bmoTC$6~J! zLW|cMjcC4^RLQa3WOI7#{%A1ZoN@YtVV}e6w41hAyy2K9KR!NPsZ5WL=O6r+TPs_3 zADXI8jgA)z?r5^S{rhz@1Ui;y#}%77A|i`!>0po3-vig$IHTW-IBLKj;Nc zLQmIB&kHHGLb_&(rWVJX>3k^|td?}wwYh_h-#zfqeb@hHeZL+aB>L5A4~C|WPrUrp zQ-8JU#0;&&;^phbIrLu_c4Kv%Y;`eOOd8F+MwC?}S`?*2c97l%=&d}Hk$uHa+|jS& zo{v7ja(m6_$9>y48nLopF^hCoGMHFdk7%Jwi%!1u*q^)#QL+~`%IA$KkbHKuj?qqy z#KQ2QTC#tkbk0UZB(Li_LLqZ8pVjJsNU4O$VUu{a8N`<1HJVgek=2XCbbxg zdz*CSbOgg@cjUZ7W7_y({RU?;Uy1rtaEG`~-%$@#8i*gS+xJ?mwV}IycC>on@GbSm z4f_v{oc#G6)yZBIZ}Kzv0>(Rlc*tS|9-dICcgT@csVfd)C$;(`elXrg?BLeY zRf@%RnNHmpxxUihuZ?Ap25-;3?ye~)b0e`|gHSoPq6 zYf|uz7s#)+UwlFRL&QVgZUE^YvsWN7tw3U0Ax27F2km^ANuULE(40Dm4>@8W=-x~y zaeN?ZEtMK|3T5|XvT)030!jru=iCH)bG6$qUTTrEes_C<3sICEi>Kg60H>hPemJBO zsizwdU0J7F*ij860uEnsy0Pop{z4UzrN#bhb~UDpK1U!P=o2+xJnR3R(s(62S8hGF zX4d6iJ^NUzJQuEvmwv~Wjr-~OUc&R`@O*%n__})BWI_%PP?{$94Gbp)RnJS?wz0Bb z&Ijs$R*uJ6r0!$=8f#)`P&$$dy=Q$l^bYU?#33IS@U_5@WW4d<$I4N~X2Xyu0|VaP zkih?=GbAsz+e?R}#2Q9&%jF2fQ9L~ZACUF|%$YRa%(UC$vsFB|!&h29ASIuj2IQaq zGviTG{z!aJ?1Ch}{wz`)@_7oZfTE%a;0-yaSaY-!q@uJFrph}8Tw8q4P2XLg*mB2>(kha3ZW^5D;=;?fGiTv!s-k;U#V>Q1n|^!-XUptn)5cFq0J2I}D_n zyMp%}thQtRNISXKaDLbQEg_zE|F&n-RCzQK^lfR}@xOW3!U1kteDk-g}$jjJlxqFnElfL@drt|7-F5Pj=$@8!3+GZ>|{6Z-c&w^sQB8 zGx=)Mkq*MOg?NA^Mlrrx#1%iDQIv)gydzAaXLB%(rf1lg01tK{1GV*7g0GE2_i2lxS^HC_x7 z1OnJ8qhWwwvhO^_%U*G#KR@9~r*pYl>{-1?&} z@0p%{&z2vpd+s@o&suC>Q>KiR+inYKk$~cL+HCPy*cI@35qIW`I2D_jV3E$Xny-NK zb$${tQ!QMx!!TkI8UKoYwfoBj{&l;Jf1Q5+qaS@>)4Nx#diSQazegPa&bCnAr`mz7 z^<^j<_ZvwI9r8_dXfctvVj_}bK4f{PMTO-0tdWewHd@qoAQPb~3|tFC0ptYC!Y3@~ z9$8Y!5gP8h31BX?=x>N!97K&wtG3FUNAr94=G8BssBGU}fi>F!Kc9bs?;hoQ&*CKA zM)tc|<;}0Hs(M1o)(HqgXXs)Kl93Uhs}cU7GDz2@?#JLr7v#q|{umxE_?Xl${B6il z7mZu#799HU3U~kU@Vue#)DP(i(9~w3dH|EFZrlzOe*7+U& zgZ_8;O@3wG%_*{Gre>zR<)QTHQ6n$%HSP3d`9{;}9dIgfoc2<1*h>f4miE#C&`Yce zEKxrY8z9MFdilWX@PBK|t5*+n-!G93h%T_Es-t=zZnq-gLS9?p-clDpTc=*BBDD1$ zj|bkt9?!^jtrjxbW5Jv|2j`6M)B5JsjF?8C%4oJHJ~VmD zEt3o1&VKH5I%rw)@|&Q=6dO`hKKM+S&SLNbdX4Rca43iHP2w7kZEvszmo0w~T_~uE zlq@KJVf2x=Q%b+jokAfcPN0DyoXlzb77MZgj^8wolnnwBufsU>7 zlKIiQB_dsDiHWpaHg)X+8mSvPf7X|iwUlpSJRCN8B947`+;M{|`!`uRilK+`2%jG zO-ZOp_~p1Jh$F;V#>By;%&oDZsXhXK8TpA^3*Zc_gg?Z*+bN_aR*$npsn zn!f}v9EpSzT2A$sb58M-tD$f(Up4V{@n_(jA?)pj5sl}cOvxt*r(D@jSmLm0RPaOX zb6`C%KsR4}m7c~=;5%165Dp#7p775CdXkt;m-+nlGUlT`*x@#@cwcoOHNJ%ZEZ&hk z68-$IoqqNkVe~VMj$$anN+lGxd?HK30lAeKWb?&K6R$Er&{e~7HFx~gT^tnuf-Xjb zY85Q9y2v80yn`-cp6*q?h)j|HH^$QQwBq!E_h5D)hRW!sMU}TW87j21daDo$6 zT?mP(^l(MfD#Pj2FhHNGa0x?u>y)30FN+qopXX_E3+lEPg4fJCao57UXt6IQApgbB zJM~P2HAKG)?;46=5yu-z^ia1w=!LK9?NRXpBg zGUSX|Jj6L6O+$>9()0lqr@O*5*(4<5i$-$Ln0UX*7tMq`1y{oFiCJs(E-2r{t?GlW zR4f1>r-WCdD6Ku@PCLF7Dq8GPFYTCvBd7BcCgJsM3rJmC`*HJL6WP{LX&08%9q zQ7yK8QM=veLk1hT^bwt&WnM!xa^w-IFG(&1M-LXpUMC*ln5wPLt?Y?{2;HQtMCN6`qQAWG}34&;+Ng`>`tRv@S4IC47@oy{3O zmE(EgAO^k+a8XcJBCO=yME*^+u?qfae@!&?L*x4AK9~JAtu2zj{#Crny6jcRy7cR3 zk;0vwoAX3CAqVhzLu#p+j?;U?03AnoDl```{6mw*;6YLA>g>sS-8*$MsVK>{V<)|9 zvL9Hzx)_~372nx971~)n<=9oJSc_8s39w5^Vll9bG?t(jKx3D}FR=NYz!dn1+!3A0 z{DI?!tEj9Sv`rh}6w{yf}>7N)|1Mt`oE#Uu~rN~7N3VEU-|iVJQUo{YBe zBVX8Kv3jB8iF&LypY}f!;dt8TbywPrf&O*ZH|l%W_Vo`oYd^Jm9jTGNxZSIznp3(y zJCsc~rn9-3R_3o(t=m9)Fw7nM2%8d^I{+~VoANNG;zNpN_^}*9C9`{{YEJJE<^ZO! zHcZqL()BUmx;&|A$%F;is!%L|(93f>;CvwO5{<`lgXuBEn5sV?T$xTaeRn;RUX&EokZ<62BXT)>ZBL(HqStSa~1h^->Y*_gT`HB5# zP$I|!T-2U9Zpo29OtJ*STrrW*9?j%*M3kMf*x|azn4R(!TZWyXFpKRjtE4!UrLdem zzaktFB`)VsW^~KI=HzHLm>W$MXB&xIcEa}J&P?Su-}nw;9@#aSw;n&HI-Kj^8&#RD z?b%^>uXQ=qWAF6<{~TT>F>k*KLX+9$THvDFXPHy95Yo;90S?`?%~ zyp4ME6E$8BW#wkXV>mgkWsgxX$Kxi1mOyXn3I@~Og3=dEBtmdTb0PW^z^S69c)$#c1;koK~dupnUKVEOV zFRE`+y5k`gWI9wFseSeZkON9R9RXpFJ&(niFO_ z{=v@|R0>`W5>A)36r`(w#$1BKLY(O0pn_+2FNp%mvk|EyuJHZs%4&b{v5$T1JwtoT z`}M7Tl}-Bo>UBd8KJmm82WR&i+dsK!{f7+WL+iKv=5}NM>_MKRMg5vhNgHmf_?Qha zZg!m2h)s6DFnJ3AWQqb6N!_+>+gBGpZ#uN_c{G82zZQG&%ZN)ES2l|+&uq|f_L{_& zBcmTmmRsAbX@l5`i;E0)Ge|mO)I`ZO`8^0UN;V^+yhzX%O)9Yg8gw6JmA=<4vDxvS z-KHJCpViA){wjE}R|%9h|}`{t2sbFMTO0}DDfl1gQd#T1bJ zCj9|>2g8K}6ft0_?1giz+TbcFYIWHKtKo2x;%FGqp03uSqpZT(W>8>n2M>VM zc%cpeD6}4=gst3=G+MU}PUI#A;yx_}3;N#ejqR~ebh=q+4YcUCH=6V$^n=$=ZPVVL z&?CiGI)I|k1OQE7MlXb1@j|PpRdaEBu#uVB7_hIi2h*7>U^n8$p<=X>OV~rL+?ur^ zm-t4Yp49YM&}j_}q_ixMh2{FVM=gto)yG*kQaYhUp>q|E;=lvK#R$F2(kUyeW9Ad|5~p)mV31yPI$XgT%AA8d1UOI}>Pc2p;$X&3 zekggh(R+gykcl9`Oca`DBI}8%ihJa)LjfS{wgU#ZO^M;1LX~i$f9+`)(NF?s26rtn zGO1DAO0gJL=BGB)=2Oo3*80Y2&3Ah4#_H*u<@Am*F$ScYrFbN-lbWm5Tm*q#aZN49 zgS1^Kgs`UoLGzNRT4L%iaVAJo5vP;&@l0mCp5zkv5xW9Vxz*s0nW|;{g+SO9b?C`l z#-X_uep;U1UafAQDpA?DZL0KRn4M#>=7xqW*BgK;E!1PNMlou!k6KLCxLz__CZ}(l z&Sa+dPfhQi&PqSwBcco+w<9#kTnE!Qy3}=Dn8Ia?GvoDT6aN0}rpf5W(yFamwVn2)Ll%Epiwp)Gfl+ZlRrf(_ z;0*Z^nuxC*f8Jsn98XnZE>%@M$q3}Paf_X4>a4N@+1I}Wnb@UF8gZM;umjp1{{9w2 zHJ>mkE{jdzJ!>A?EF6=NoOq=L4OYVca*Hn@WU&rHzRuo1e9g|*%meK`J6j81Nq+o^ z?3ei!zej#&HSwI-kKYSCg9rq9O2RSe6*`~6izPQAp4+hSB>+8~|Ht)^4?7sK06v15 z1`!L3d#-}qr|ZPMhHIQ~lg0=p3bdSs8I)|Wpwb|RsxpJ3m1sx8>*^Q84+uO2UZP~J zq*;ZxAm+H**_5xHp|^5ZVrH@X|LWDD6;Vkas3tCJ(kndu+?77@eJ;9TG!EJhjn4spwRHKC@v} z-~3=dAbLUD`tVu5bAB)^!t2|!lVbAp;3~0dRb%vrsNg$YSikyo1DhE!?cL4%BH72A z_q=`&d9dGm>DAi3U=!cJRD1ORuD*Yu_3e9F9q7v;8E>_M*_?c=7S9c2qg%d{$Kc~f z=M6|oWLhR?2cX7u0qU;&-xAa zc@1Ko18{uU>elJi&aZr0chh?%>`eHyG|uQqtpKh<`4xz{F4r_%;aqorxKNMB>xFQ) zoGK@iW%^Sm(hWTj&>QJ)sTYen{$$@8EVuV#r~07z*W3VS14e<_28d^W!0p?A1{Ca?}%R*%|B^Xezlb;4?v&9XWGm{h2dAA=gUf7~+v0fSjc(e@k9`uRV<= zuG7}SDo4rZU6d>?p=3lmevjo$@6Whl1IER9qXO=fB0rV_s>UNjgJmAl^X&m1xg5n6qv8Mdu znWB#8VuLVgc@Vns8a*h85dg11YRDQn*zAVayY74$7ulL z_7NE=q?B!a1{&xa#}D)w_dbdIj#93UTfRp3VNfVfNjVb9`3KDoOQiEgUOsg1mDv5HG!j>*!|xAd({)~DLsboknbw_swI>e@^qIGxgh3m7zuJ#(~c`C z2OJ{ZIC&-G?oF;Op^jS`J0HO>ts92bQNNI*0)-fMLa4irX?^v8N$lCIaBFG(Ei;9k#r0~R)qH7CJnp>l#-UBExYhaZZxWuP z@(r<8>{1z>QTZ1C_NOlI1@cJ{XX;@i7BD50xGNln(_A>5w#T9GVfQ=*u^{KL2$;~o zS7M_10_Y8~atmqL;i(|!w%r;Tu0T&oUh~4AfF7}s(5fz{E9TQnHWR{$)d`C~=gy>^ zTF7Iww9S@q*rhsRv5=XAAekY!mW(a}g{>%uQjw+09M8e6Khf4JUXuNCv9tlJz17-_~53Rwo~`}%9Qmu}AX^_BC7g1+e6GN%2! zV%UlC9EG4@RESma%Q+sP?yxKsz)E0Ia1B8g3F1;$P*N}~u{eMs443%3Z;NUo8iP-v zPj~Bq;Y72UC|5lTX9~?&->Psf*r0)HwM+q%4u39h+>5MCo@yx6(i5dr%q=c=hxF2A zj3UY2z{L_j1V3{F0cA=tgzc=-0;LQ`l&vjdXc!`t9D+gb89fgde30b|ki?;0dF>4G zxjKD-8#Q8PkPyI&E)r8i$xf;$FVG~>{WBr_1btv^q*&qU*_qi-8Pj27+5pHeOu>U= zg~FJojk(9ih1q6X`7qbj*4E0tP*y7-BV>yrT} zsd~zI@`WPp@aqh)-y6b`76$4o=>(RlWUwVrvk)YamH&pEJu|H(81TLT1Y*c#SgO+QMOB2`Jm%)XtfBQ9<7 zE7X1b@}*8)5!bkGY+2pOUb}ZLLKNTel?JEiP-9Y$LM24|ClC zBk$M!Wp%JD26ghyctU?xKd)cZ-_Y&4$x+y$Iy5vP{D3MR!Z(O55Z>JDkZp3Hf1e@w z=7Mnms;I4=D!m3jop*n_T2(Wtq{Ec#L8xYv5tt|+NJPSkNYeax;xh?#N8(`Oc;d^6 zZzldZaXDd2G|dg)|52&|RW+N*n3EAlZB9w7Hkmou6X;qOR~1qsbdw0Jx+gHf1b;cM zs(=z6!Hsl!>H?~EwUD%DGCge7UP33FC?(FSzc$#0)8JUCG#2v4+s(c%+-f2j4kzjF zsi$T?`I-4u?vmC&G}Iq0yH@?iZ+~*8gTVR)4dxmAVQ;_=2R=cV6;b6bV>}d5O*T^y z<6#4&tS#vBA^yw^h!2M!NV49eEvj{R|71d}*t2lz~$uYo9I!|H0qGY`Ym8@=r9)Ux% zh_-S~T)aWrZMs2PacH;sxQCLDdpNE0`zX;sWsm zCMNiG{($u1xL~a(WU1#_(SnQf)IXFLj26NC1qMxqX(#aT#t;h<4yTI6k%@sLsd31k z<37Vaeqwld=$JOPzEr9l%XR!QVLfO?%S25Rj|_r z(yFWk+NwcDnO-i%n%&l+JyW?Aaa^O5o39dXT}h9nw)0)vt_F8qo3misf(9X|PQ1YM ziXe=LUU@--LP*VY`CpLr&7(MX3ekaDU#b4%*zru?gxTxn%AOu=k!=&rl5O7!S^q<_ z?Oz%W;M}a(Hqjzk|6#75_^Jv_fL|IOuZ}OMBDMo)jQ9nzI(k$Uxm7heV28q@3P$N&_Js3v?OI@r2F&|XB7rwJJ{G@&NHYpv@1={%mh;FrFjN8)ZVJb=R3URTOfH119zj%8gr$M7M56Ha~@ zoiLdPcBp1#`|J7;0P9EDjZCS32whs;0M&Ak8P()~dERBh>^Ix-Z?|GExA02p?%o>! zoRZNO)?m_ii(@BGwz~iCe)!?m!}9IJ;JN9`KLpm|hZJOgRqEn)&LKsFbpRCC7yxDM z8^;o=l15C1aS_~4MaNm9AkpSgH;-fHHbVIzDvB`33q~5Br$}QKqgcimS%5TJiW=D| zy6ce;zDS}*$?gd#FBqh6Hj%Xv_Di;VR;Z-kq*aV|P+lO4U;f7BZx{$9*_JlYFn;yC zk;ca<9k)_+D@DdFjer%{jtN!x^YncH+58?m4mi`9aKsU@RV!LFVvpJ%a74n6h{KUM z;%Nec@QBigMsml3>mBx*1bO@p9KXLq+k*6Ugl;S)1d3NeVplGfXqP0-?un0G5-v*# z@yTZTu9%JKDwC1E0!S^$3?&#dLllG{AwS2Pk(o@kK&YQH4Q*P_WX0_+_cwi&@cQ)& zuUlPz>?=mP7@)~|cDnDuYY7H4HJDvpJ$h~Hn(V?6kMrbv2KQveDYug_L9reglaKe$ zcxV48*b_{*FBy(>(j49?tSPxIR;u6IL&B3vaOGrg56QM^56QNBdq^nRD;n2n7stgcXF6-K0=nG_v?0am1#FRnL72Pz!aR$?nUBk9vHoLq}Bw zc!00Gj{mVTNWa!quytm-9Ra13lMID+D4!=pREdPSX?Her-?4(Re{5{`r{V?gBr+Xn z@oHPW`*zd*>sRe;M^A`vieGy4k-l6lPD(@4|NSd`;GR)t#mHG@2A#xKnV~I#rH%69 z8HzjO8#pG>4a1AxPXPOA+XMxz4$*_+0Z}5t2b-gx%&#TdaYgd^;y@|dp{yLo1v?#} zyg)!C^qyno$>c;{2Pj#sj`A0s&~fH9un$YsBrX^Y2F&N8F^3<3*WyXLfzCDUv-Wq` zP4LmHpHvLHYons*Cw+6n$CVLbA2F1A#qQJVt8}|PJ$P!>wvo;0Q^8J1Js8vkx$V(E zIqJM0fpXk#9)OY;HiRqp+v2;99=#Xi44(i%X0X|Zqo8{_3r16rkOSfgUo_?RdXm*f zHMx7QKbMXmr*t@x@%5FH)xl~qqeXJXYJYu?)<0ct7|@QEW7S;Bn25WmQrrZj?#(siG zTi8m4cB;NMt?U)*Jsyq3l&oV39o4KOB z$9wf?zcLrIwAbN>O}^J+S_ldD3Owr`w-9kRaAngpeP&4^RgEhhKL znf}DwTz<_-_*l8Nji1az!Sk$94MjJ$TKTObk5=3t*iykiW!0%fdRHLeJEiS1Z3ME; z&`?7HM3Fxufw?1&7fy`i{*Uk!oDyMZz!eTl?AwSVWEWASv)EuChu2Bhoe?x$;@m9v zcwE$wg($H#(S9(33Niwd_0k%d9~k%f`xEaIXNUXrlFJ;5r98QIC^??a4dwiS{7}xF zb{EUhe!IglGMLL{^+3go+^gX~cld&Kttftw&t&pHwFGP%w?x+ixYeSCwJ@kmGCS6% zS*%(UUQWPVrJ0qiLcUKGo_)7dy;*Hhj4Bq9JMj!!)I}bllWWgTZCapiL}m` zju=PA)1LQ11IEXrLAnai;YjTqjuQF&@I>uoV)1a)ZV#T)#eUy$tp7rgc1=v?ci z#lz8CoP-ul3hcuneMV_SNj)pdSDl4Cw*7B^3-Gr5`u?lWLK&~;{<~I!b8{o76!TQV zbNepuUC^`6-UUZhFJCqsr9w#EiPVU+jc8viuiM?fv0|Pp7CQS))}#F^+q@IZkM^an zvZTRYd$ccQy@yec_oc5miUyG+b_WE_#eFHUen4jg{EeuuuKySz9q0^TjKzh-)rx_A`KlD?=hne} zU@IZP5VXZbY!Nhr6ZueS%uubI$e1&Tevii!@TdwGPMXICPI^Z*5mWNHL_QwtI~7m@ z{(v4Z+4HeLAeJ|!GuwvX3(a~J4rK#i#p`}J)J*UTNsi!CaFCvufKMl^lH?7yoK*=9 zi6D~{8D>a!&_E7YIwbR>Hf9rxuK8TFm&6V;quJZ%DoSyJ;l}8(zqVT1_nJfy}a<@ zXwaUF-moD(+7~NLZI$bq4DMf1i8t)xwL-js*9z8kKCD=WoqW)}l?~*%Fh`NqH=VM1Oz{xzlUoI0l#+q* z#r7*NA`dwQU09ZcElPMfIioTQn^jLFb2+$-bW72{{{69HF%~bCpl2+V0HFefs)>O1 zfLHVev?N9J<a-w_QE!S>;zc&1qSgi&>qNi>=cNif~} zK9||8xILca$pF$ZD5aC;X11E?GY{lXMWF?Dc}3jpi0&FV6gd3mk2*v_Xt3ING2Vm|MNBB?-A{-C%#S z5yR#7Ms70RFH$zgGu~oka_yTo#~E)aGO@-yqwi@Glv8n{IGe>K(49g6xUr{N;eT~I z_ixWO!asMrpe@4uGM)>szw71t>#o%WqH8uJ{(~B&L#vk8?W{rJjUfvyDl$>)wMlDG zw%J*OLL`?o*sDitOV;bGEkp^#`q7~305NlPi5coMJ_YynM(*q5K3>}*T*&DW{Jzv+ zbTF$x^TLSvJ!WJJM7c2QB(P)BWArvg#EwrhgpR_1V&KG#J%o~Rxahr+!Fq_CR4N&d z{kY;3c4s+p%D>a)-saqr>!5LwUUQ4rY~UtM}iK<8tqOO#$AM4N^@6eUr59J&EW3D&)vv zoMt|87I09k=%1zan1IYa;3tD=fjox+Gf4tvCy5Sw6_e)j4231}DYAj}I}z_YZixn5 zmUVL{bFEfxt;YzhJu&sDQijFJUM?#mfTO%Zgoi-`r}OS0k<{*g_2n1N!P2+X#Wlo$ z%n1Lwa(I^d2QPJV4MDVA^oad`2&37Nhy{U};Ic+b?Iv6eO2L&Nn@5&FJBuGk$YyIK zo^yGozu@0w<9bi))M;x!zM~@Y9M8VvPI#9+$W?Dm{ zy;XU=0O^Utaeu{(Le&);EW`$~^9_Om#c<2g^r#N`|6=`o!FMl68F&a{$;k23YA5d5z zi~byRnXm*)u*Ur-5u6Jk+W8V;I9IwD&gEhWaA+&RI5RLirwVFy9XDYBAP(9Kxw;C< zc?|ffBJLW9CyJVDYA{}~?~ZM04{T_qv;m{4H{3snjr~eQ=YRX|cWK-@_67Jge*w>{ z@|oo#o|ke!zW1zB0)N4ylt_H0V>t;Ot8pX30tp9Xg(;nopI(wCp&Yka9ks&AV8288 zfEDmHnNxE>jne#@u9@uG&N9%$&6W;=^-ak7)U!okySC0xbn5nI3d)!nOCCw7hw?ikM|5U^Dk_Iig>$PeP#IFYV8)Z)xK@1B`UKUoTBy=xKd zn%B9sLlJ+e@;-Y^S!#!Zr@=BilsvN$kCA7wE{}2LuROEKc8SMuyWks3+eI=_YL^T? zwB9fuvR&dc+^)E}!@FGNVLmf<_l9hj_M2??Fl@ygyBT!5-tfxp(w>v;9`3eV>|bmb z`p5mCTS3vl^mZz9|o#O3vJ$F>I8J-i0Mke+IjGg3C(MxW~ zQ9lGb;|B?bv0?>|1iL0@EM`-4PP`D;Bsa1~!Hpt*yVru$3f(k|UTu*HMauZljNCKG zyhwYL*6cpW?>~U-JVx0$hrx5wSfh2)1J_B0s*{LZrMDFlq)358s~Y9SGvq|V;uE;k zQZb6O#jq)|Js2fxo={#eDkPbwW5K-J-8^ZU7_*%09}gRe@e`I0jEyn&cxhMbO6>6t zSCUBxAzOoi_f~m#u~W1~j^$@oW?aR=N5>YKls3w=;Yw6;XTj(35kIF99Mt>{huv@Q z;*^WotANVmf$o@s9TojfWM}I^mrrb9=yI$_xz30N%XM}TCnU)$gxk-HEYPFDa_tfg zmTT-_ca7!CyvDjTnCSXqs!X74*H{`oi?rFPlJl${F?AI`_Lc}0j2@ezq7rzz7>_v zTpAp|qAjrZ&Nw3e6tV%0jT}eVpKTaNrE8Q|+3Nfi(+qs)lFDQMA5h5~(4_#C9Ddu$ zn06={kEgo$ zid9$?4y~yMch|?X zA?NPZ>S1D|`4gt$t%qUw}iFE>$jZ!{vp4t2Tn#bQg#xm1@bQQaZ#y^42O*P@CldgRDM^Zsyt$1 zVEuEmueTTb`{JdSTXY9HfxHnum>!k=Ao*wCn%X%>|IrY#v|18Ug#l z!7AoQ)Hr1Zh;&f-ft=P!3=oOfmoTmp)UzsM%imU%E|yEzBhhX-zeJBa^Xm;SonOou z&o5#wB1+YWhIASU8i7bei`odJSUx#u8LR&;y|C;_JJ}6-Ptwb3u-NBbG6UW#ay|VP zWbUo#72&=8O#Btrj0u#hirj84C3v4Df-KBoO8pyB=LA+tM`c4AW*l`97muh8Wd5}l zx}gm~pF6gDx7fdTOJRL77ii`yed^r{#^LMY@in0&vaEiSe5YxBeoFlf{;jN1Q#Kft z^uxd)JRYd`JzOXN2-0*M>)5UgBpwR`*7cNmOZhQf$P6Tu^2}M{@U&VS01U`H0MBR_pWNZP>AF2?>nV9zcBc_7Ry?b8TqN6 zUzoVzI`!MR6lqdZxo(MJ<9+!v@mZE5h!Yb3Yjx&$HXd=oS4(uZCF)WRi4T$-Ar7D} zLDjG)(u6ufj|EvuCxVqZ6-*o$%ep4=X^AVb%fmCoi?%F ze$iQPKR=U<;H1)BZ$vAgeT2TR$FqY`w1@lw%lb%X zP3|Mt?b<8DG45tZ;6z?2M_J^Jo1{fJ@p;_bFDtRkwb{`m7bsn&fj5_4qehQ(=5&;G4%yASE`> z9Q>o6MG|Ud+dJKm9yuVPb)Ys2c6p!%3v5rD(=8l)RU zn^8&;KS=l};@;>;YW)^(IvI1UUpSvijR$-}9QtqfF6;+N+3jz;c|d&l(#O?j9PQnW zNMRO4+(Puhb;Z2e#7&nm)6&Yj5te&7x#WchNtV|B7-R*??XD|(jAq19TAI>b@gfP& zeStisb=PgGE$2g0_w=zSqn|1^5^Y;I9e5cL2z>mIasnqcqC7?f{#|OAmOS3lAkEPc zac_9cSf_8fCS?HmbBjGbRQ2diyIr&8w8+4H?|t7YO8!1{8#-)w)R(`(`HrR~8y zNk3vb^FWCWKGi$(sEWSaKbdqcFQ}x4+>N?cu1oq6)V#tLFWaQ^4!5~@-hsbLi~Xa? zAdZR0@5?qxKf-NtU2e13;x@Tvub)IyWSh6aHutFXNGart?C)HHzjN1$x1{Z!?|`@s z;yU}V6!S&4&Ep&F7|`)8Bbx9%wttN9SUirE$v&*=<^O3o2Ks~covK#rtXcF45rX1t zOuMe-@#xw>64=RgDri+I2MArAhs$hg>wMNA20f zpI(M|EV=5fXS4v?L``ZBpMH<+3fxcF75)LTD0>FIVmSI6+|TCneiHrSeu{$_2a-oU z2*$%3F5UL@R~dh>ulMZK zCh6Z~n|CUXj@;}RYjd0M*XyhW*(T}VWSbq|LVy|eahv^IlW4_W&egs_uIu{|1Mdp4e!ZDh(CB`))tGC_qco#jKC4V&N-(ZdG^Oy_ zM9BeLC@=6Dz{Pn|X8{?FD-uLBRYZA_2r-bNIlU4}R(m06>^0*yip&K}5Gm|Yr$RBI zMe++RQu2*r4EJ)R&PVzT%x;x($VG$lAUw;Xf9LgcJ7w3{g&`2FI)?&|M4a8~E;{;3>CuiUQ_Zlm;R453y+Lh7yY-d7>`d=l zJQ=nkN#oKM*^|e~<8=L18_{DcHIvT6hj%Y#sPas%bnl%nd1#k5sHm3T=7 zgK>^|32_y|?C#0IcKC}xufG_BCi89)&EHEjUwr!xK7rkwNogL*#IOdaJ*)vAa-b(I zCSkqLOOW{ffa*EwvpSBNki5`0XUD`ty+GpvTORAW&T;+&433Z?p``o9IKc9J?(;{E z?7sj0&%+G&ys_{jkv5)(-JRzUXJ*V{0ojg6G@7$0&7KX3z;cO9CL0IE&VNR!&+$O)@BeUv}FE;D0(Gj5Jb>yXzdw}-0G+UTH^B&3wn;J_x7n5Hgh*7mP1cn4+9a7yws{MF`vZ#m>nh@U=-EjuqcM{0 zkN-2ur!m>FXSpaj$)_=8H}X@FVA3o#C*ub9bLg7*O< z=|0PVULFWp=aQad@Ed_U;gk|1W{1O=d^$eMybis6&o!!al}l95-h5?JJ1e5uyVi!mnBVQzYW^#;+*zZ^ zbkEHRfgN_$ygcn4)`pIq^%BdVlf1{4*e(-Ms|SH;i)Ve#HAlKz=WE3bY4W`S%dNKh9jKdX1gJ7 zs4v?k`!cu7^{KDQ(yG07NrxiamAs?dZZOL2c7~Srn{1cPA+lYn&+T4ORVcrM=c1fC zA*FFv@j*n3kV79*Br1ribVQs^&nfFR*uG_MPB2!IgI~vKxgF@mu0xE4LsQ^)mSrRt zZ(fm&e8EQjlDZ|blha7`&S&ECU!Peuf-_3@e6||rGsvQ-$LEvoIgaWL)o?=T)~lc% zcp&N#Peprw-#Nu0jLij}+O0Q>df;EEC;920;#>x8WxSMKqEl`p{>(qSZMZ&rz=e7{YD7m3hjO185>QăESk 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 G(fmJpf?fdt literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Fonts/UbuntuMono-Regular.woff b/frontend/src/Content/Fonts/UbuntuMono-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..0289699c05a703d05e7268ffe84c7110161dfec9 GIT binary patch literal 27392 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%0D)V9?yyD2Coq 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 literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Fonts/fonts.css b/frontend/src/Content/Fonts/fonts.css new file mode 100644 index 000000000..3db8ae6b0 --- /dev/null +++ b/frontend/src/Content/Fonts/fonts.css @@ -0,0 +1,38 @@ +@font-face { + font-weight: 300; + font-style: normal; + font-family: 'Roboto'; + src: url('Roboto-Light.woff2?v=1.1.0') format('woff2'), url('Roboto-Light.woff?v=1.2.0') format('woff'), url('Roboto-Light.ttf?v=1.1.0') format('truetype'); +} + +@font-face { + font-weight: 400; + font-style: normal; + font-family: 'Roboto'; + src: url('Roboto-Regular.woff2?v=1.2.0') format('woff2'), url('Roboto-Regular.woff?v=1.2.0') format('woff'), url('Roboto-Regular.ttf?v=1.1.0') format('truetype'); +} + +@font-face { + font-weight: normal; + font-style: normal; + font-family: 'Roboto'; + src: url('Roboto-Regular.woff2?v=1.3.0') format('woff2'), url('Roboto-Regular.woff?v=1.2.0') format('woff'), url('Roboto-Regular.ttf?v=1.1.0') format('truetype'); +} + +@font-face { + font-weight: 400; + font-style: normal; + font-family: 'Ubuntu Mono'; + src: url('UbuntuMono-Regular.eot?#iefix') format('embedded-opentype'), url('UbuntuMono-Regular.woff') format('woff'), url('UbuntuMono-Regular.ttf') format('truetype'); +} + +/* + * text-security-disc + */ + +@font-face { + font-weight: normal; + font-style: normal; + font-family: 'text-security-disc'; + src: url('text-security-disc.woff') format('woff'), url('text-security-disc.ttf') format('truetype'); +} diff --git a/frontend/src/Content/Fonts/text-security-disc.ttf b/frontend/src/Content/Fonts/text-security-disc.ttf new file mode 100644 index 0000000000000000000000000000000000000000..86038dba89d7e762d5dbc458529c0d20514a3d54 GIT binary patch literal 12392 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 literal 0 HcmV?d00001 diff --git a/frontend/src/Content/Images/404.png b/frontend/src/Content/Images/404.png new file mode 100644 index 0000000000000000000000000000000000000000..deeb83f8fd8fe3b12d27cc6e821bfafb07fba27d GIT binary patch literal 103643 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