From f69f96695b1262a89ff1ea4ff2de376a55925b99 Mon Sep 17 00:00:00 2001 From: Chris Sandvik <9214195+csandman@users.noreply.github.com> Date: Sat, 20 Nov 2021 12:31:45 -0500 Subject: [PATCH] New: Add a filter bar to the "Add Indexers" modal (#607) * Add a filter bar to the "Add Indexers" modal * Fix stylelint errors * Hide AddIndexerModal alert on small screens --- .../Indexer/Add/AddIndexerModalContent.css | 45 +++++++- .../src/Indexer/Add/AddIndexerModalContent.js | 102 +++++++++++++++--- 2 files changed, 130 insertions(+), 17 deletions(-) diff --git a/frontend/src/Indexer/Add/AddIndexerModalContent.css b/frontend/src/Indexer/Add/AddIndexerModalContent.css index 9e175cacf..38c00ad82 100644 --- a/frontend/src/Indexer/Add/AddIndexerModalContent.css +++ b/frontend/src/Indexer/Add/AddIndexerModalContent.css @@ -16,7 +16,7 @@ composes: input from '~Components/Form/TextInput.css'; flex: 0 0 auto; - margin-bottom: 20px; + margin-bottom: 16px; } .alert { @@ -28,3 +28,46 @@ .scroller { flex: 1 1 auto; } + +.filterRow { + display: flex; + margin-bottom: 20px; +} + +.filterContainer { + display: flex; + align-items: stretch; + flex: 1; + flex-direction: column; + margin-right: 12px; +} + +.filterContainer:last-child { + margin-right: 0; +} + +.filterLabel { + margin-bottom: 3px; + font-weight: bold; +} + +@media only screen and (max-width: $breakpointSmall) { + .alert { + display: none; + } + + .filterRow { + flex-direction: column; + } + + .filterContainer { + margin-right: 0; + margin-bottom: 12px; + } + + .scroller { + margin-right: -30px; + margin-bottom: -30px; + margin-left: -30px; + } +} diff --git a/frontend/src/Indexer/Add/AddIndexerModalContent.js b/frontend/src/Indexer/Add/AddIndexerModalContent.js index 86f595512..1c5e0f28a 100644 --- a/frontend/src/Indexer/Add/AddIndexerModalContent.js +++ b/frontend/src/Indexer/Add/AddIndexerModalContent.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import Alert from 'Components/Alert'; +import EnhancedSelectInput from 'Components/Form/EnhancedSelectInput'; import TextInput from 'Components/Form/TextInput'; import Button from 'Components/Link/Button'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; @@ -44,6 +45,17 @@ const columns = [ } ]; +const protocols = [ + { + key: 'torrent', + value: 'torrent' + }, + { + key: 'usenet', + value: 'nzb' + } +]; + class AddIndexerModalContent extends Component { // @@ -53,7 +65,10 @@ class AddIndexerModalContent extends Component { super(props, context); this.state = { - filter: '' + filter: '', + filterProtocols: [], + filterLanguages: [], + filterPrivacyLevels: [] }; } @@ -80,8 +95,35 @@ class AddIndexerModalContent extends Component { onModalClose } = this.props; - const filter = this.state.filter; - const filterLower = filter.toLowerCase(); + const languages = Array.from(new Set(indexers.map(({ language }) => language))) + .sort((a, b) => a.localeCompare(b)) + .map((language) => ({ key: language, value: language })); + + const privacyLevels = Array.from(new Set(indexers.map(({ privacy }) => privacy))) + .sort((a, b) => a.localeCompare(b)) + .map((privacy) => ({ key: privacy, value: privacy })); + + const filteredIndexers = indexers.filter((indexer) => { + const { filter, filterProtocols, filterLanguages, filterPrivacyLevels } = this.state; + + if (!indexer.name.toLowerCase().includes(filter.toLocaleLowerCase())) { + return false; + } + + if (filterProtocols.length && !filterProtocols.includes(indexer.protocol)) { + return false; + } + + if (filterLanguages.length && !filterLanguages.includes(indexer.language)) { + return false; + } + + if (filterPrivacyLevels.length && !filterPrivacyLevels.includes(indexer.privacy)) { + return false; + } + + return true; + }); const errorMessage = getErrorMessage(error, 'Unable to load indexers'); @@ -99,11 +141,43 @@ class AddIndexerModalContent extends Component { className={styles.filterInput} placeholder={translate('FilterPlaceHolder')} name="filter" - value={filter} + value={this.state.filter} autoFocus={true} onChange={this.onFilterChange} /> +
+
+ + this.setState({ filterProtocols: value })} + /> +
+ +
+ + this.setState({ filterLanguages: value })} + /> +
+ +
+ + this.setState({ filterPrivacyLevels: value })} + /> +
+
+ { - indexers.map((indexer) => { - return indexer.name.toLowerCase().includes(filterLower) ? - ( - - ) : - null; - }) + filteredIndexers.map((indexer) => ( + + )) } :