New: Filter episodes by title or number in Manual Import

Closes #3862
This commit is contained in:
Andrew Champion 2020-07-10 11:25:24 +01:00 committed by Mark McDowall
parent a6b8a34ac9
commit 73ed5f6ee2
3 changed files with 94 additions and 45 deletions

View File

@ -52,6 +52,7 @@ function Table(props) {
scrollDirections.HORIZONTAL : scrollDirections.HORIZONTAL :
scrollDirections.NONE scrollDirections.NONE
} }
autoFocus={false}
> >
<table className={className}> <table className={className}>
<TableHeader> <TableHeader>

View File

@ -1,3 +1,22 @@
.modalBody {
composes: modalBody from '~Components/Modal/ModalBody.css';
display: flex;
flex: 1 1 auto;
flex-direction: column;
}
.filterInput {
composes: input from '~Components/Form/TextInput.css';
flex: 0 0 auto;
margin-bottom: 20px;
}
.scroller {
flex: 1 1 auto;
}
.footer { .footer {
composes: modalFooter from '~Components/Modal/ModalFooter.css'; composes: modalFooter from '~Components/Modal/ModalFooter.css';

View File

@ -4,13 +4,15 @@ import getErrorMessage from 'Utilities/Object/getErrorMessage';
import getSelectedIds from 'Utilities/Table/getSelectedIds'; import getSelectedIds from 'Utilities/Table/getSelectedIds';
import selectAll from 'Utilities/Table/selectAll'; import selectAll from 'Utilities/Table/selectAll';
import toggleSelected from 'Utilities/Table/toggleSelected'; import toggleSelected from 'Utilities/Table/toggleSelected';
import { kinds } from 'Helpers/Props'; import { kinds, scrollDirections } from 'Helpers/Props';
import TextInput from 'Components/Form/TextInput';
import Button from 'Components/Link/Button'; import Button from 'Components/Link/Button';
import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import ModalContent from 'Components/Modal/ModalContent'; import ModalContent from 'Components/Modal/ModalContent';
import ModalHeader from 'Components/Modal/ModalHeader'; import ModalHeader from 'Components/Modal/ModalHeader';
import ModalBody from 'Components/Modal/ModalBody'; import ModalBody from 'Components/Modal/ModalBody';
import ModalFooter from 'Components/Modal/ModalFooter'; import ModalFooter from 'Components/Modal/ModalFooter';
import Scroller from 'Components/Scroller/Scroller';
import Table from 'Components/Table/Table'; import Table from 'Components/Table/Table';
import TableBody from 'Components/Table/TableBody'; import TableBody from 'Components/Table/TableBody';
import SelectEpisodeRow from './SelectEpisodeRow'; import SelectEpisodeRow from './SelectEpisodeRow';
@ -46,6 +48,7 @@ class SelectEpisodeModalContent extends Component {
this.state = { this.state = {
allSelected: false, allSelected: false,
allUnselected: false, allUnselected: false,
filter: '',
lastToggled: null, lastToggled: null,
selectedState: {} selectedState: {}
}; };
@ -61,6 +64,10 @@ class SelectEpisodeModalContent extends Component {
// //
// Listeners // Listeners
onFilterChange = ({ value }) => {
this.setState({ filter: value.toLowerCase() });
}
onSelectAllChange = ({ value }) => { onSelectAllChange = ({ value }) => {
this.setState(selectAll(this.state.selectedState, value)); this.setState(selectAll(this.state.selectedState, value));
} }
@ -95,8 +102,10 @@ class SelectEpisodeModalContent extends Component {
const { const {
allSelected, allSelected,
allUnselected, allUnselected,
filter,
selectedState selectedState
} = this.state; } = this.state;
const filterEpisodeNumber = parseInt(filter);
const errorMessage = getErrorMessage(error, 'Unable to load episodes'); const errorMessage = getErrorMessage(error, 'Unable to load episodes');
@ -116,53 +125,73 @@ class SelectEpisodeModalContent extends Component {
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody
{ className={styles.modalBody}
isFetching && scrollDirection={scrollDirections.NONE}
<LoadingIndicator /> >
} <TextInput
className={styles.filterInput}
placeholder="Filter episodes by title or number"
name="filter"
value={filter}
autoFocus={true}
onChange={this.onFilterChange}
/>
{ <Scroller
error && className={styles.scroller}
<div>{errorMessage}</div> autoFocus={false}
} >
{
isFetching ? <LoadingIndicator /> : null
}
{ {
isPopulated && !!items.length && error ? <div>{errorMessage}</div> : null
<Table }
columns={columns}
selectAll={true}
allSelected={allSelected}
allUnselected={allUnselected}
sortKey={sortKey}
sortDirection={sortDirection}
onSortPress={onSortPress}
onSelectAllChange={this.onSelectAllChange}
>
<TableBody>
{
items.map((item) => {
return (
<SelectEpisodeRow
key={item.id}
id={item.id}
episodeNumber={item.episodeNumber}
title={item.title}
airDate={item.airDate}
isSelected={selectedState[item.id]}
onSelectedChange={this.onSelectedChange}
/>
);
})
}
</TableBody>
</Table>
}
{ {
isPopulated && !items.length && isPopulated && !!items.length ?
'No episodes were found for the selected season' <Table
} columns={columns}
selectAll={true}
allSelected={allSelected}
allUnselected={allUnselected}
sortKey={sortKey}
sortDirection={sortDirection}
onSortPress={onSortPress}
onSelectAllChange={this.onSelectAllChange}
>
<TableBody>
{
items.map((item) => {
return item.title.toLowerCase().includes(filter) ||
item.episodeNumber === filterEpisodeNumber ?
(
<SelectEpisodeRow
key={item.id}
id={item.id}
episodeNumber={item.episodeNumber}
title={item.title}
airDate={item.airDate}
isSelected={selectedState[item.id]}
onSelectedChange={this.onSelectedChange}
/>
) :
null;
})
}
</TableBody>
</Table> :
null
}
{
isPopulated && !items.length ?
'No episodes were found for the selected season' :
null
}
</Scroller>
</ModalBody> </ModalBody>
<ModalFooter className={styles.footer}> <ModalFooter className={styles.footer}>